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

流媒体/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_surface.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_cursor_c.h"
  29. #include "SDL_blit.h"
  30. #include "SDL_RLEaccel_c.h"
  31. #include "SDL_pixels_c.h"
  32. #include "SDL_memops.h"
  33. #include "SDL_leaks.h"
  34. /* Public routines */
  35. /*
  36.  * Create an empty RGB surface of the appropriate depth
  37.  */
  38. SDL_Surface * SDL_CreateRGBSurface (Uint32 flags,
  39. int width, int height, int depth,
  40. Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask)
  41. {
  42. SDL_VideoDevice *video = current_video;
  43. SDL_VideoDevice *this  = current_video;
  44. SDL_Surface *screen;
  45. SDL_Surface *surface;
  46. /* Check to see if we desire the surface in video memory */
  47. if ( video ) {
  48. screen = SDL_PublicSurface;
  49. } else {
  50. screen = NULL;
  51. }
  52. if ( screen && ((screen->flags&SDL_HWSURFACE) == SDL_HWSURFACE) ) {
  53. if ( (flags&(SDL_SRCCOLORKEY|SDL_SRCALPHA)) != 0 ) {
  54. flags |= SDL_HWSURFACE;
  55. }
  56. if ( (flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY ) {
  57. if ( ! current_video->info.blit_hw_CC ) {
  58. flags &= ~SDL_HWSURFACE;
  59. }
  60. }
  61. if ( (flags & SDL_SRCALPHA) == SDL_SRCALPHA ) {
  62. if ( ! current_video->info.blit_hw_A ) {
  63. flags &= ~SDL_HWSURFACE;
  64. }
  65. }
  66. } else {
  67. flags &= ~SDL_HWSURFACE;
  68. }
  69. /* Allocate the surface */
  70. surface = (SDL_Surface *)malloc(sizeof(*surface));
  71. if ( surface == NULL ) {
  72. SDL_OutOfMemory();
  73. return(NULL);
  74. }
  75. surface->flags = SDL_SWSURFACE;
  76. if ( (flags & SDL_HWSURFACE) == SDL_HWSURFACE ) {
  77. depth = screen->format->BitsPerPixel;
  78. Rmask = screen->format->Rmask;
  79. Gmask = screen->format->Gmask;
  80. Bmask = screen->format->Bmask;
  81. Amask = screen->format->Amask;
  82. }
  83. surface->format = SDL_AllocFormat(depth, Rmask, Gmask, Bmask, Amask);
  84. if ( surface->format == NULL ) {
  85. free(surface);
  86. return(NULL);
  87. }
  88. if ( Amask ) {
  89. surface->flags |= SDL_SRCALPHA;
  90. }
  91. surface->w = width;
  92. surface->h = height;
  93. surface->pitch = SDL_CalculatePitch(surface);
  94. surface->pixels = NULL;
  95. surface->offset = 0;
  96. surface->hwdata = NULL;
  97. surface->locked = 0;
  98. surface->map = NULL;
  99. surface->format_version = 0;
  100. SDL_SetClipRect(surface, NULL);
  101. /* Get the pixels */
  102. if ( ((flags&SDL_HWSURFACE) == SDL_SWSURFACE) || 
  103. (video->AllocHWSurface(this, surface) < 0) ) {
  104. if ( surface->w && surface->h ) {
  105. surface->pixels = malloc(surface->h*surface->pitch);
  106. if ( surface->pixels == NULL ) {
  107. SDL_FreeSurface(surface);
  108. SDL_OutOfMemory();
  109. return(NULL);
  110. }
  111. /* This is important for bitmaps */
  112. memset(surface->pixels, 0, surface->h*surface->pitch);
  113. }
  114. }
  115. /* Allocate an empty mapping */
  116. surface->map = SDL_AllocBlitMap();
  117. if ( surface->map == NULL ) {
  118. SDL_FreeSurface(surface);
  119. return(NULL);
  120. }
  121. /* The surface is ready to go */
  122. surface->refcount = 1;
  123. #ifdef CHECK_LEAKS
  124. ++surfaces_allocated;
  125. #endif
  126. return(surface);
  127. }
  128. /*
  129.  * Create an RGB surface from an existing memory buffer
  130.  */
  131. SDL_Surface * SDL_CreateRGBSurfaceFrom (void *pixels,
  132. int width, int height, int depth, int pitch,
  133. Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask)
  134. {
  135. SDL_Surface *surface;
  136. surface = SDL_CreateRGBSurface(SDL_SWSURFACE, 0, 0, depth,
  137.                                Rmask, Gmask, Bmask, Amask);
  138. if ( surface != NULL ) {
  139. surface->flags |= SDL_PREALLOC;
  140. surface->pixels = pixels;
  141. surface->w = width;
  142. surface->h = height;
  143. surface->pitch = pitch;
  144. SDL_SetClipRect(surface, NULL);
  145. }
  146. return(surface);
  147. }
  148. /*
  149.  * Set the color key in a blittable surface
  150.  */
  151. int SDL_SetColorKey (SDL_Surface *surface, Uint32 flag, Uint32 key)
  152. {
  153. /* Sanity check the flag as it gets passed in */
  154. if ( flag & SDL_SRCCOLORKEY ) {
  155. if ( flag & (SDL_RLEACCEL|SDL_RLEACCELOK) ) {
  156. flag = (SDL_SRCCOLORKEY | SDL_RLEACCELOK);
  157. } else {
  158. flag = SDL_SRCCOLORKEY;
  159. }
  160. } else {
  161. flag = 0;
  162. }
  163. /* Optimize away operations that don't change anything */
  164. if ( (flag == (surface->flags & (SDL_SRCCOLORKEY|SDL_RLEACCELOK))) &&
  165.      (key == surface->format->colorkey) ) {
  166. return(0);
  167. }
  168. /* UnRLE surfaces before we change the colorkey */
  169. if ( surface->flags & SDL_RLEACCEL ) {
  170.         SDL_UnRLESurface(surface, 1);
  171. }
  172. if ( flag ) {
  173. SDL_VideoDevice *video = current_video;
  174. SDL_VideoDevice *this  = current_video;
  175. surface->flags |= SDL_SRCCOLORKEY;
  176. surface->format->colorkey = key;
  177. if ( (surface->flags & SDL_HWACCEL) == SDL_HWACCEL ) {
  178. if ( (video->SetHWColorKey == NULL) ||
  179.      (video->SetHWColorKey(this, surface, key) < 0) ) {
  180. surface->flags &= ~SDL_HWACCEL;
  181. }
  182. }
  183. if ( flag & SDL_RLEACCELOK ) {
  184. surface->flags |= SDL_RLEACCELOK;
  185. } else {
  186. surface->flags &= ~SDL_RLEACCELOK;
  187. }
  188. } else {
  189. surface->flags &= ~(SDL_SRCCOLORKEY|SDL_RLEACCELOK);
  190. surface->format->colorkey = 0;
  191. }
  192. SDL_InvalidateMap(surface->map);
  193. return(0);
  194. }
  195. int SDL_SetAlpha (SDL_Surface *surface, Uint32 flag, Uint8 value)
  196. {
  197. Uint32 oldflags = surface->flags;
  198. Uint32 oldalpha = surface->format->alpha;
  199. /* Sanity check the flag as it gets passed in */
  200. if ( flag & SDL_SRCALPHA ) {
  201. if ( flag & (SDL_RLEACCEL|SDL_RLEACCELOK) ) {
  202. flag = (SDL_SRCALPHA | SDL_RLEACCELOK);
  203. } else {
  204. flag = SDL_SRCALPHA;
  205. }
  206. } else {
  207. flag = 0;
  208. }
  209. /* Optimize away operations that don't change anything */
  210. if ( (flag == (surface->flags & (SDL_SRCALPHA|SDL_RLEACCELOK))) &&
  211.      (!flag || value == oldalpha) ) {
  212. return(0);
  213. }
  214. if(!(flag & SDL_RLEACCELOK) && (surface->flags & SDL_RLEACCEL))
  215. SDL_UnRLESurface(surface, 1);
  216. if ( flag ) {
  217. SDL_VideoDevice *video = current_video;
  218. SDL_VideoDevice *this  = current_video;
  219. surface->flags |= SDL_SRCALPHA;
  220. surface->format->alpha = value;
  221. if ( (surface->flags & SDL_HWACCEL) == SDL_HWACCEL ) {
  222. if ( (video->SetHWAlpha == NULL) ||
  223.      (video->SetHWAlpha(this, surface, value) < 0) ) {
  224. surface->flags &= ~SDL_HWACCEL;
  225. }
  226. }
  227. if ( flag & SDL_RLEACCELOK ) {
  228.         surface->flags |= SDL_RLEACCELOK;
  229. } else {
  230.         surface->flags &= ~SDL_RLEACCELOK;
  231. }
  232. } else {
  233. surface->flags &= ~SDL_SRCALPHA;
  234. surface->format->alpha = SDL_ALPHA_OPAQUE;
  235. }
  236. /*
  237.  * The representation for software surfaces is independent of
  238.  * per-surface alpha, so no need to invalidate the blit mapping
  239.  * if just the alpha value was changed. (If either is 255, we still
  240.  * need to invalidate.)
  241.  */
  242. if((surface->flags & SDL_HWACCEL) == SDL_HWACCEL
  243.    || oldflags != surface->flags
  244.    || (((oldalpha + 1) ^ (value + 1)) & 0x100))
  245. SDL_InvalidateMap(surface->map);
  246. return(0);
  247. }
  248. /*
  249.  * A function to calculate the intersection of two rectangles:
  250.  * return true if the rectangles intersect, false otherwise
  251.  */
  252. static __inline__
  253. SDL_bool SDL_IntersectRect(const SDL_Rect *A, const SDL_Rect *B, SDL_Rect *intersection)
  254. {
  255. int Amin, Amax, Bmin, Bmax;
  256. /* Horizontal intersection */
  257. Amin = A->x;
  258. Amax = Amin + A->w;
  259. Bmin = B->x;
  260. Bmax = Bmin + B->w;
  261. if(Bmin > Amin)
  262.         Amin = Bmin;
  263. intersection->x = Amin;
  264. if(Bmax < Amax)
  265.         Amax = Bmax;
  266. intersection->w = Amax - Amin > 0 ? Amax - Amin : 0;
  267. /* Vertical intersection */
  268. Amin = A->y;
  269. Amax = Amin + A->h;
  270. Bmin = B->y;
  271. Bmax = Bmin + B->h;
  272. if(Bmin > Amin)
  273.         Amin = Bmin;
  274. intersection->y = Amin;
  275. if(Bmax < Amax)
  276.         Amax = Bmax;
  277. intersection->h = Amax - Amin > 0 ? Amax - Amin : 0;
  278. return (intersection->w && intersection->h);
  279. }
  280. /*
  281.  * Set the clipping rectangle for a blittable surface
  282.  */
  283. SDL_bool SDL_SetClipRect(SDL_Surface *surface, const SDL_Rect *rect)
  284. {
  285. SDL_Rect full_rect;
  286. /* Don't do anything if there's no surface to act on */
  287. if ( ! surface ) {
  288. return SDL_FALSE;
  289. }
  290. /* Set up the full surface rectangle */
  291. full_rect.x = 0;
  292. full_rect.y = 0;
  293. full_rect.w = surface->w;
  294. full_rect.h = surface->h;
  295. /* Set the clipping rectangle */
  296. if ( ! rect ) {
  297. surface->clip_rect = full_rect;
  298. return 1;
  299. }
  300. return SDL_IntersectRect(rect, &full_rect, &surface->clip_rect);
  301. }
  302. void SDL_GetClipRect(SDL_Surface *surface, SDL_Rect *rect)
  303. {
  304. if ( surface && rect ) {
  305. *rect = surface->clip_rect;
  306. }
  307. }
  308. /* 
  309.  * Set up a blit between two surfaces -- split into three parts:
  310.  * The upper part, SDL_UpperBlit(), performs clipping and rectangle 
  311.  * verification.  The lower part is a pointer to a low level
  312.  * accelerated blitting function.
  313.  *
  314.  * These parts are separated out and each used internally by this 
  315.  * library in the optimimum places.  They are exported so that if
  316.  * you know exactly what you are doing, you can optimize your code
  317.  * by calling the one(s) you need.
  318.  */
  319. int SDL_LowerBlit (SDL_Surface *src, SDL_Rect *srcrect,
  320. SDL_Surface *dst, SDL_Rect *dstrect)
  321. {
  322. SDL_blit do_blit;
  323. /* Check to make sure the blit mapping is valid */
  324. if ( (src->map->dst != dst) ||
  325.              (src->map->dst->format_version != src->map->format_version) ) {
  326. if ( SDL_MapSurface(src, dst) < 0 ) {
  327. return(-1);
  328. }
  329. }
  330. /* Figure out which blitter to use */
  331. if ( (src->flags & SDL_HWACCEL) == SDL_HWACCEL ) {
  332. do_blit = src->map->hw_blit;
  333. } else {
  334. do_blit = src->map->sw_blit;
  335. }
  336. return(do_blit(src, srcrect, dst, dstrect));
  337. }
  338. int SDL_UpperBlit (SDL_Surface *src, SDL_Rect *srcrect,
  339.    SDL_Surface *dst, SDL_Rect *dstrect)
  340. {
  341.         SDL_Rect fulldst;
  342. int srcx, srcy, w, h;
  343. /* Make sure the surfaces aren't locked */
  344. if ( ! src || ! dst ) {
  345. SDL_SetError("SDL_UpperBlit: passed a NULL surface");
  346. return(-1);
  347. }
  348. if ( src->locked || dst->locked ) {
  349. SDL_SetError("Surfaces must not be locked during blit");
  350. return(-1);
  351. }
  352. /* If the destination rectangle is NULL, use the entire dest surface */
  353. if ( dstrect == NULL ) {
  354.         fulldst.x = fulldst.y = 0;
  355. dstrect = &fulldst;
  356. }
  357. /* clip the source rectangle to the source surface */
  358. if(srcrect) {
  359.         int maxw, maxh;
  360. srcx = srcrect->x;
  361. w = srcrect->w;
  362. if(srcx < 0) {
  363.         w += srcx;
  364. dstrect->x -= srcx;
  365. srcx = 0;
  366. }
  367. maxw = src->w - srcx;
  368. if(maxw < w)
  369. w = maxw;
  370. srcy = srcrect->y;
  371. h = srcrect->h;
  372. if(srcy < 0) {
  373.         h += srcy;
  374. dstrect->y -= srcy;
  375. srcy = 0;
  376. }
  377. maxh = src->h - srcy;
  378. if(maxh < h)
  379. h = maxh;
  380.     
  381. } else {
  382.         srcx = srcy = 0;
  383. w = src->w;
  384. h = src->h;
  385. }
  386. /* clip the destination rectangle against the clip rectangle */
  387. {
  388.         SDL_Rect *clip = &dst->clip_rect;
  389. int dx, dy;
  390. dx = clip->x - dstrect->x;
  391. if(dx > 0) {
  392. w -= dx;
  393. dstrect->x += dx;
  394. srcx += dx;
  395. }
  396. dx = dstrect->x + w - clip->x - clip->w;
  397. if(dx > 0)
  398. w -= dx;
  399. dy = clip->y - dstrect->y;
  400. if(dy > 0) {
  401. h -= dy;
  402. dstrect->y += dy;
  403. srcy += dy;
  404. }
  405. dy = dstrect->y + h - clip->y - clip->h;
  406. if(dy > 0)
  407. h -= dy;
  408. }
  409. if(w > 0 && h > 0) {
  410.         SDL_Rect sr;
  411.         sr.x = srcx;
  412. sr.y = srcy;
  413. sr.w = dstrect->w = w;
  414. sr.h = dstrect->h = h;
  415. return SDL_LowerBlit(src, &sr, dst, dstrect);
  416. }
  417. dstrect->w = dstrect->h = 0;
  418. return 0;
  419. }
  420. /* 
  421.  * This function performs a fast fill of the given rectangle with 'color'
  422.  */
  423. int SDL_FillRect(SDL_Surface *dst, SDL_Rect *dstrect, Uint32 color)
  424. {
  425. SDL_VideoDevice *video = current_video;
  426. SDL_VideoDevice *this  = current_video;
  427. int x, y;
  428. Uint8 *row;
  429. /* If 'dstrect' == NULL, then fill the whole surface */
  430. if ( dstrect ) {
  431. /* Perform clipping */
  432. if ( !SDL_IntersectRect(dstrect, &dst->clip_rect, dstrect) ) {
  433. return(0);
  434. }
  435. } else {
  436. dstrect = &dst->clip_rect;
  437. }
  438. /* Check for hardware acceleration */
  439. if ( ((dst->flags & SDL_HWSURFACE) == SDL_HWSURFACE) &&
  440. video->info.blit_fill ) {
  441. return(video->FillHWRect(this, dst, dstrect, color));
  442. }
  443. /* Perform software fill */
  444. if ( SDL_LockSurface(dst) != 0 ) {
  445. return(-1);
  446. }
  447. row = (Uint8 *)dst->pixels+dstrect->y*dst->pitch+
  448. dstrect->x*dst->format->BytesPerPixel;
  449. if ( dst->format->palette || (color == 0) ) {
  450. x = dstrect->w*dst->format->BytesPerPixel;
  451. if ( !color && !((long)row&3) && !(x&3) && !(dst->pitch&3) ) {
  452. int n = x >> 2;
  453. for ( y=dstrect->h; y; --y ) {
  454. SDL_memset4(row, 0, n);
  455. row += dst->pitch;
  456. }
  457. } else {
  458. #ifdef __powerpc__
  459. /*
  460.  * memset() on PPC (both glibc and codewarrior) uses
  461.  * the dcbz (Data Cache Block Zero) instruction, which
  462.  * causes an alignment exception if the destination is
  463.  * uncachable, so only use it on software surfaces
  464.  */
  465. if((dst->flags & SDL_HWSURFACE) == SDL_HWSURFACE) {
  466. if(dstrect->w >= 8) {
  467. /*
  468.  * 64-bit stores are probably most
  469.  * efficient to uncached video memory
  470.  */
  471. double fill;
  472. memset(&fill, color, (sizeof fill));
  473. for(y = dstrect->h; y; y--) {
  474. Uint8 *d = row;
  475. unsigned n = x;
  476. unsigned nn;
  477. Uint8 c = color;
  478. double f = fill;
  479. while((unsigned long)d
  480.       & (sizeof(double) - 1)) {
  481. *d++ = c;
  482. n--;
  483. }
  484. nn = n / (sizeof(double) * 4);
  485. while(nn) {
  486. ((double *)d)[0] = f;
  487. ((double *)d)[1] = f;
  488. ((double *)d)[2] = f;
  489. ((double *)d)[3] = f;
  490. d += 4*sizeof(double);
  491. nn--;
  492. }
  493. n &= ~(sizeof(double) * 4 - 1);
  494. nn = n / sizeof(double);
  495. while(nn) {
  496. *(double *)d = f;
  497. d += sizeof(double);
  498. nn--;
  499. }
  500. n &= ~(sizeof(double) - 1);
  501. while(n) {
  502. *d++ = c;
  503. n--;
  504. }
  505. row += dst->pitch;
  506. }
  507. } else {
  508. /* narrow boxes */
  509. for(y = dstrect->h; y; y--) {
  510. Uint8 *d = row;
  511. Uint8 c = color;
  512. int n = x;
  513. while(n) {
  514. *d++ = c;
  515. n--;
  516. }
  517. row += dst->pitch;
  518. }
  519. }
  520. } else
  521. #endif /* __powerpc__ */
  522. {
  523. for(y = dstrect->h; y; y--) {
  524. memset(row, color, x);
  525. row += dst->pitch;
  526. }
  527. }
  528. }
  529. } else {
  530. switch (dst->format->BytesPerPixel) {
  531.     case 2:
  532. for ( y=dstrect->h; y; --y ) {
  533. Uint16 *pixels = (Uint16 *)row;
  534. Uint16 c = color;
  535. Uint32 cc = (Uint32)c << 16 | c;
  536. int n = dstrect->w;
  537. if((unsigned long)pixels & 3) {
  538. *pixels++ = c;
  539. n--;
  540. }
  541. if(n >> 1)
  542. SDL_memset4(pixels, cc, n >> 1);
  543. if(n & 1)
  544. pixels[n - 1] = c;
  545. row += dst->pitch;
  546. }
  547. break;
  548.     case 3:
  549. if(SDL_BYTEORDER == SDL_BIG_ENDIAN)
  550. color <<= 8;
  551. for ( y=dstrect->h; y; --y ) {
  552. Uint8 *pixels = row;
  553. for ( x=dstrect->w; x; --x ) {
  554. memcpy(pixels, &color, 3);
  555. pixels += 3;
  556. }
  557. row += dst->pitch;
  558. }
  559. break;
  560.     case 4:
  561. for(y = dstrect->h; y; --y) {
  562. SDL_memset4(row, color, dstrect->w);
  563. row += dst->pitch;
  564. }
  565. break;
  566. }
  567. }
  568. SDL_UnlockSurface(dst);
  569. /* We're done! */
  570. return(0);
  571. }
  572. /*
  573.  * Lock a surface to directly access the pixels
  574.  * -- Do not call this from any blit function, as SDL_DrawCursor() may recurse
  575.  *    Instead, use:
  576.  *    if ( (surface->flags & SDL_HWSURFACE) == SDL_HWSURFACE )
  577.  *               video->LockHWSurface(video, surface);
  578.  */
  579. int SDL_LockSurface (SDL_Surface *surface)
  580. {
  581. if ( ! surface->locked ) {
  582. /* Perform the lock */
  583. if ( surface->flags & (SDL_HWSURFACE|SDL_ASYNCBLIT) ) {
  584. SDL_VideoDevice *video = current_video;
  585. SDL_VideoDevice *this  = current_video;
  586. if ( video->LockHWSurface(this, surface) < 0 ) {
  587. return(-1);
  588. }
  589. }
  590. if ( surface->flags & SDL_RLEACCEL ) {
  591. SDL_UnRLESurface(surface, 1);
  592. surface->flags |= SDL_RLEACCEL; /* save accel'd state */
  593. }
  594. /* This needs to be done here in case pixels changes value */
  595. surface->pixels = (Uint8 *)surface->pixels + surface->offset;
  596. }
  597. /* Increment the surface lock count, for recursive locks */
  598. ++surface->locked;
  599. /* Ready to go.. */
  600. return(0);
  601. }
  602. /*
  603.  * Unlock a previously locked surface
  604.  * -- Do not call this from any blit function, as SDL_DrawCursor() may recurse
  605.  *    Instead, use:
  606.  *    if ( (surface->flags & SDL_HWSURFACE) == SDL_HWSURFACE )
  607.  *               video->UnlockHWSurface(video, surface);
  608.  */
  609. void SDL_UnlockSurface (SDL_Surface *surface)
  610. {
  611. /* Only perform an unlock if we are locked */
  612. if ( ! surface->locked || (--surface->locked > 0) ) {
  613. return;
  614. }
  615. /* Perform the unlock */
  616. surface->pixels = (Uint8 *)surface->pixels - surface->offset;
  617. /* Unlock hardware or accelerated surfaces */
  618. if ( surface->flags & (SDL_HWSURFACE|SDL_ASYNCBLIT) ) {
  619. SDL_VideoDevice *video = current_video;
  620. SDL_VideoDevice *this  = current_video;
  621. video->UnlockHWSurface(this, surface);
  622. } else {
  623. /* Update RLE encoded surface with new data */
  624. if ( (surface->flags & SDL_RLEACCEL) == SDL_RLEACCEL ) {
  625.         surface->flags &= ~SDL_RLEACCEL; /* stop lying */
  626. SDL_RLESurface(surface);
  627. }
  628. }
  629. }
  630. /* 
  631.  * Convert a surface into the specified pixel format.
  632.  */
  633. SDL_Surface * SDL_ConvertSurface (SDL_Surface *surface,
  634. SDL_PixelFormat *format, Uint32 flags)
  635. {
  636. SDL_Surface *convert;
  637. Uint32 colorkey = 0;
  638. Uint8 alpha = 0;
  639. Uint32 surface_flags;
  640. SDL_Rect bounds;
  641. /* Check for empty destination palette! (results in empty image) */
  642. if ( format->palette != NULL ) {
  643. int i;
  644. for ( i=0; i<format->palette->ncolors; ++i ) {
  645. if ( (format->palette->colors[i].r != 0) ||
  646.      (format->palette->colors[i].g != 0) ||
  647.      (format->palette->colors[i].b != 0) )
  648. break;
  649. }
  650. if ( i == format->palette->ncolors ) {
  651. SDL_SetError("Empty destination palette");
  652. return(NULL);
  653. }
  654. }
  655. /* Only create hw surfaces with alpha channel if hw alpha blits
  656.    are supported */
  657. if(format->Amask != 0 && (flags & SDL_HWSURFACE)) {
  658. const SDL_VideoInfo *vi = SDL_GetVideoInfo();
  659. if(!vi || !vi->blit_hw_A)
  660. flags &= ~SDL_HWSURFACE;
  661. }
  662. /* Create a new surface with the desired format */
  663. convert = SDL_CreateRGBSurface(flags,
  664. surface->w, surface->h, format->BitsPerPixel,
  665. format->Rmask, format->Gmask, format->Bmask, format->Amask);
  666. if ( convert == NULL ) {
  667. return(NULL);
  668. }
  669. /* Copy the palette if any */
  670. if ( format->palette && convert->format->palette ) {
  671. memcpy(convert->format->palette->colors,
  672. format->palette->colors,
  673. format->palette->ncolors*sizeof(SDL_Color));
  674. convert->format->palette->ncolors = format->palette->ncolors;
  675. }
  676. /* Save the original surface color key and alpha */
  677. surface_flags = surface->flags;
  678. if ( (surface_flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY ) {
  679. /* Convert colourkeyed surfaces to RGBA if requested */
  680. if((flags & SDL_SRCCOLORKEY) != SDL_SRCCOLORKEY
  681.    && format->Amask) {
  682. surface_flags &= ~SDL_SRCCOLORKEY;
  683. } else {
  684. colorkey = surface->format->colorkey;
  685. SDL_SetColorKey(surface, 0, 0);
  686. }
  687. }
  688. if ( (surface_flags & SDL_SRCALPHA) == SDL_SRCALPHA ) {
  689. alpha = surface->format->alpha;
  690. SDL_SetAlpha(surface, 0, 0);
  691. }
  692. /* Copy over the image data */
  693. bounds.x = 0;
  694. bounds.y = 0;
  695. bounds.w = surface->w;
  696. bounds.h = surface->h;
  697. SDL_LowerBlit(surface, &bounds, convert, &bounds);
  698. /* Clean up the original surface, and update converted surface */
  699. if ( convert != NULL ) {
  700. SDL_SetClipRect(convert, &surface->clip_rect);
  701. }
  702. if ( (surface_flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY ) {
  703. Uint32 cflags = surface_flags&(SDL_SRCCOLORKEY|SDL_RLEACCELOK);
  704. if ( convert != NULL ) {
  705. Uint8 keyR, keyG, keyB;
  706. SDL_GetRGB(colorkey,surface->format,&keyR,&keyG,&keyB);
  707. SDL_SetColorKey(convert, cflags|(flags&SDL_RLEACCELOK),
  708. SDL_MapRGB(convert->format, keyR, keyG, keyB));
  709. }
  710. SDL_SetColorKey(surface, cflags, colorkey);
  711. }
  712. if ( (surface_flags & SDL_SRCALPHA) == SDL_SRCALPHA ) {
  713. Uint32 aflags = surface_flags&(SDL_SRCALPHA|SDL_RLEACCELOK);
  714. if ( convert != NULL ) {
  715.         SDL_SetAlpha(convert, aflags|(flags&SDL_RLEACCELOK),
  716. alpha);
  717. }
  718. SDL_SetAlpha(surface, aflags, alpha);
  719. }
  720. /* We're ready to go! */
  721. return(convert);
  722. }
  723. /*
  724.  * Free a surface created by the above function.
  725.  */
  726. void SDL_FreeSurface (SDL_Surface *surface)
  727. {
  728. /* Free anything that's not NULL, and not the screen surface */
  729. if ((surface == NULL) ||
  730.     (current_video &&
  731.     ((surface == SDL_ShadowSurface)||(surface == SDL_VideoSurface)))) {
  732. return;
  733. }
  734. if ( --surface->refcount > 0 ) {
  735. return;
  736. }
  737. if ( (surface->flags & SDL_RLEACCEL) == SDL_RLEACCEL ) {
  738.         SDL_UnRLESurface(surface, 0);
  739. }
  740. if ( surface->format ) {
  741. SDL_FreeFormat(surface->format);
  742. surface->format = NULL;
  743. }
  744. if ( surface->map != NULL ) {
  745. SDL_FreeBlitMap(surface->map);
  746. surface->map = NULL;
  747. }
  748. if ( (surface->flags & SDL_HWSURFACE) == SDL_HWSURFACE ) {
  749. SDL_VideoDevice *video = current_video;
  750. SDL_VideoDevice *this  = current_video;
  751. video->FreeHWSurface(this, surface);
  752. }
  753. if ( surface->pixels &&
  754.      ((surface->flags & SDL_PREALLOC) != SDL_PREALLOC) ) {
  755. free(surface->pixels);
  756. }
  757. free(surface);
  758. #ifdef CHECK_LEAKS
  759. --surfaces_allocated;
  760. #endif
  761. }