Initial integration, lots of broken stuff
[supertux.git] / src / unison / src / video / sdl / Blitters.cpp
1 //          Copyright Timothy Goya 2007.
2 // Distributed under the Boost Software License, Version 1.0.
3 //    (See accompanying file LICENSE_1_0.txt or copy at
4 //          http://www.boost.org/LICENSE_1_0.txt)
5
6 #include <unison/video/sdl/Blitters.hpp>
7 #include <unison/video/Surface.hpp>
8
9 #include <assert.h>
10
11 #include "SDL.h"
12
13 namespace
14 {
15    unsigned char add_saturate(unsigned char lhs, int rhs)
16    {
17       if(lhs + rhs < 0x00)
18       {
19          return 0x00;
20       }
21       if(lhs + rhs > 0xff)
22       {
23          return 0xff;
24       }
25       return lhs + rhs;
26    }
27 }
28
29
30 namespace Unison
31 {
32    namespace Video
33    {
34       namespace SDL
35       {
36          /*SDL_Surface *Blitters::optimize(const Surface &src)
37          {
38             bool colors[(1 << 12)];
39             memset(colors, 0, (1 << 12) * sizeof(bool));
40
41             Surface dst(src);
42             Color *iter = dst.get_pixels();
43             for(unsigned int y = 0;y < dst.get_size().y;y++)
44             {
45                for(unsigned int x = 0;x < dst.get_size().x;x++, iter++)
46                {
47                   unsigned char oldalpha = iter->alpha;
48                   unsigned char newalpha = oldalpha & 0x80 ? 0xff : 0x00;
49                   iter->alpha = newalpha;
50                   int error = oldalpha - newalpha;
51                   if(x != dst.get_size().x - 1)
52                   {
53                      (iter + 1)->alpha = add_saturate((iter + 1)->alpha, error * 7 / 16);
54                   }
55                   if(y != dst.get_size().y - 1)
56                   {
57                      if(x != 0)
58                      {
59                         (iter + dst.get_size().x - 1)->alpha = add_saturate((iter + dst.get_size().x - 1)->alpha, error * 3 / 16);
60                      }
61                      (iter + dst.get_size().x)->alpha = add_saturate((iter + dst.get_size().x)->alpha, error * 5 / 16);
62                      if(x != dst.get_size().x - 1)
63                      {
64                         (iter + dst.get_size().x + 1)->alpha = add_saturate((iter + dst.get_size().x + 1)->alpha, error * 1 / 16);
65                      }
66                   }
67                   if(newalpha != 0)
68                   {
69                      colors[((iter->red & 0xf0) << 4) | (iter->green & 0xf0) | ((iter->blue & 0xf0) >> 4)] = true;
70                   }
71                }
72             }
73
74             int keycolor = -1;
75             for(int i = 0;i < (1 << 12);i++)
76             {
77                if(!colors[i])
78                {
79                   keycolor = i;
80                   break;
81                }
82             }
83             if(keycolor == -1)
84             {
85                SDL_Surface *converted = create_sdl_surface_from(src);
86                SDL_Surface *optimized = SDL_DisplayFormatAlpha(converted);
87                SDL_FreeSurface(converted);
88                return optimized;
89             }
90
91             Color key(((keycolor & 0xf00) >> 4) | 0xf, (keycolor & 0x0f0) | 0xf, ((keycolor & 0x00f) << 4) | 0xf);
92
93             Color *end = dst.get_pixels() + dst.get_size().x * dst.get_size().y;
94             for(iter = dst.get_pixels();iter != end;++iter)
95             {
96                if(iter->alpha == 0x00)
97                {
98                   *iter = key;
99                }
100             }
101
102             SDL_Surface *converted = create_sdl_surface_from(dst);
103             SDL_SetColorKey(converted, SDL_SRCCOLORKEY | SDL_RLEACCEL, SDL_MapRGB(converted->format, key.red, key.green, key.blue));
104             SDL_Surface *optimized = SDL_DisplayFormat(converted);
105             SDL_FreeSurface(converted);
106             return optimized;
107          }*/
108          SDL_Surface *Blitters::optimize(const Surface &src)
109          {
110             unsigned int transparent = 0;
111             unsigned int opaque = 0;
112             unsigned int semitransparent = 0;
113             unsigned int alphasum = 0;
114             unsigned int squaredalphasum = 0;
115             bool colors[(1 << 12)];
116             memset(colors, 0, (1 << 12) * sizeof(bool));
117
118             const Color *src_end = src.get_pixels() + src.get_size().x * src.get_size().y;
119             for(const Color *iter = src.get_pixels();iter != src_end;++iter)
120             {
121                if(iter->alpha < 16)
122                {
123                   transparent++;
124                }
125                else if(iter->alpha > 240)
126                {
127                   opaque++;
128                   alphasum += iter->alpha;
129                   squaredalphasum += iter->alpha * iter->alpha;
130                }
131                else
132                {
133                   semitransparent++;
134                   squaredalphasum += iter->alpha * iter->alpha;
135                }
136                if(iter->alpha != 0)
137                {
138                   colors[((iter->red & 0xf0) << 4) | (iter->green & 0xf0) | ((iter->blue & 0xf0) >> 4)] = true;
139                }
140             }
141
142             unsigned int avgalpha = (opaque + semitransparent) ? alphasum / (opaque + semitransparent) : 0;
143             unsigned int avgsquaredalpha = (opaque + semitransparent) ? squaredalphasum / (opaque + semitransparent) : 0;
144             unsigned int alphavariance = avgsquaredalpha - avgalpha * avgalpha;
145             if(semitransparent > ((transparent + opaque + semitransparent) / 8) && alphavariance > 16)
146             {
147                SDL_Surface *converted = create_sdl_surface_from(src);
148                SDL_Surface *optimized = SDL_DisplayFormatAlpha(converted);
149                SDL_FreeSurface(converted);
150                return optimized;
151             }
152
153             int keycolor = -1;
154             for(int i = 0;i < (1 << 12);i++)
155             {
156                if(!colors[i])
157                {
158                   keycolor = i;
159                   break;
160                }
161             }
162             if(keycolor == -1)
163             {
164                SDL_Surface *converted = create_sdl_surface_from(src);
165                SDL_Surface *optimized = SDL_DisplayFormatAlpha(converted);
166                SDL_FreeSurface(converted);
167                return optimized;
168             }
169
170             Color key(((keycolor & 0xf00) >> 4) | 0xf, (keycolor & 0x0f0) | 0xf, ((keycolor & 0x00f) << 4) | 0xf);
171             Surface dst(src.get_size());
172             Color *dst_end = dst.get_pixels() + dst.get_size().x * dst.get_size().y;
173             const Color *src_iter = src.get_pixels();
174             Color *dst_iter = dst.get_pixels();
175             for(;dst_iter != dst_end;++dst_iter, ++src_iter)
176             {
177                *dst_iter = (src_iter->alpha < avgalpha / 4) ? key : *src_iter;
178             }
179
180             SDL_Surface *converted = create_sdl_surface_from(dst);
181             if(avgalpha < 240)
182             {
183                SDL_SetAlpha(converted, SDL_SRCALPHA | SDL_RLEACCEL, avgalpha);
184             }
185             SDL_SetColorKey(converted, SDL_SRCCOLORKEY | SDL_RLEACCEL, SDL_MapRGB(converted->format, key.red, key.green, key.blue));
186             SDL_Surface *optimized = SDL_DisplayFormat(converted);
187             SDL_FreeSurface(converted);
188             return optimized;
189          }
190
191          void Blitters::blit_upper(SDL_Surface *src, Rect src_rect, SDL_Surface *dst, Point dst_pos, void (*blit_lower)(SDL_Surface *, const Rect &, SDL_Surface *, const Point &))
192          {
193             assert(src);
194             assert(dst);
195             assert(blit_lower);
196             if(src_rect == Rect())
197             {
198                src_rect.size.x = src->w;
199                src_rect.size.y = src->h;
200             }
201             if(dst_pos.x < 0)
202             {
203                if(src_rect.size.x < (unsigned int) -dst_pos.x)
204                {
205                   return;
206                }
207                src_rect.pos.x += -dst_pos.x;
208                src_rect.size.x += dst_pos.x;
209                dst_pos.x = 0;
210             }
211             if(dst_pos.y < 0)
212             {
213                if(src_rect.size.y < (unsigned int) -dst_pos.y)
214                {
215                   return;
216                }
217                src_rect.pos.y += -dst_pos.y;
218                src_rect.size.y += dst_pos.y;
219                dst_pos.y = 0;
220             }
221             if(src_rect.pos.x < 0)
222             {
223                if(src_rect.size.x < (unsigned int) -src_rect.pos.x)
224                {
225                   return;
226                }
227                src_rect.size.x += src_rect.pos.x;
228                src_rect.pos.x = 0;
229             }
230             if(src_rect.pos.y < 0)
231             {
232                if(src_rect.size.y < (unsigned int) -src_rect.pos.y)
233                {
234                   return;
235                }
236                src_rect.size.y += src_rect.pos.y;
237                src_rect.pos.y = 0;
238             }
239             if(src_rect.get_right() > src->w)
240             {
241                src_rect.size.x = src->w - src_rect.pos.x;
242             }
243             if(src_rect.get_bottom() > src->h)
244             {
245                src_rect.size.y = src->h - src_rect.pos.y;
246             }
247             if(int(dst_pos.x + src_rect.size.x) > dst->w)
248             {
249                src_rect.size.x = dst->w - dst_pos.x;
250             }
251             if(int(dst_pos.y + src_rect.size.y) > dst->h)
252             {
253                src_rect.size.y = dst->h - dst_pos.y;
254             }
255             blit_lower(src, src_rect, dst, dst_pos);
256          }
257
258          void Blitters::blit_lower_none(SDL_Surface *src, const Rect &src_rect, SDL_Surface *dst, const Point &dst_pos)
259          {
260             SDL_Rect sdl_src_rect = {src_rect.pos.x, src_rect.pos.y, src_rect.size.x, src_rect.size.y};
261             SDL_Rect sdl_dst_rect = {dst_pos.x, dst_pos.y, 0, 0};
262
263             Uint8 alpha = src->format->alpha;
264             SDL_SetAlpha(src, 0, 0);
265             SDL_BlitSurface(src, &sdl_src_rect, dst, &sdl_dst_rect);
266             SDL_SetAlpha(src, SDL_SRCALPHA | SDL_RLEACCEL, alpha);
267          }
268
269          void Blitters::blit_lower_mask(SDL_Surface *src, const Rect &src_rect, SDL_Surface *dst, const Point &dst_pos)
270          {
271             if(SDL_MUSTLOCK(src))
272             {
273                SDL_LockSurface(src);
274             }
275             if(SDL_MUSTLOCK(dst))
276             {
277                SDL_LockSurface(dst);
278             }
279             int src_bpp = src->format->BytesPerPixel;
280             int dst_bpp = dst->format->BytesPerPixel;
281             Uint8 *src_pixel = (Uint8 *)src->pixels + src_rect.pos.y * src->pitch + src_rect.pos.x * src_bpp;
282             Uint8 *dst_pixel = (Uint8 *)dst->pixels + dst_pos.y * dst->pitch + dst_pos.x * dst_bpp;
283             for(unsigned int y = 0;y < src_rect.size.y;y++)
284             {
285                for(unsigned int x = 0;x < src_rect.size.x;x++)
286                {
287                   Uint32 src_mapped = 0;
288                   switch(src_bpp) {
289                      case 1:
290                         src_mapped = *src_pixel;
291                         break;
292                      case 2:
293                         src_mapped = *(Uint16 *)src_pixel;
294                         break;
295                      case 3:
296 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
297                         src_mapped |= src_pixel[0] << 16;
298                         src_mapped |= src_pixel[1] << 8;
299                         src_mapped |= src_pixel[2] << 0;
300 #else
301                         src_mapped |= src_pixel[0] << 0;
302                         src_mapped |= src_pixel[1] << 8;
303                         src_mapped |= src_pixel[2] << 16;
304 #endif
305                         break;
306                      case 4:
307                         src_mapped = *(Uint32 *)src_pixel;
308                         break;
309                   }
310                   Uint8 src_red, src_green, src_blue, src_alpha;
311                   SDL_GetRGBA(src_mapped, src->format, &src_red, &src_green, &src_blue, &src_alpha);
312                   if(src_alpha)
313                   {
314                      Uint32 blend_mapped = SDL_MapRGBA(dst->format, src_red, src_green, src_blue, src_alpha);
315                      switch(dst_bpp) {
316                         case 1:
317                            *dst_pixel = blend_mapped;
318                            break;
319                         case 2:
320                            *(Uint16 *)dst_pixel = blend_mapped;
321                            break;
322                         case 3:
323 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
324                            dst_pixel[0] = (blend_mapped >> 16) & 0xff;
325                            dst_pixel[1] = (blend_mapped >> 8) & 0xff;
326                            dst_pixel[2] = (blend_mapped >> 0) & 0xff;
327 #else
328                            dst_pixel[0] = (blend_mapped >> 0) & 0xff;
329                            dst_pixel[1] = (blend_mapped >> 8) & 0xff;
330                            dst_pixel[2] = (blend_mapped >> 16) & 0xff;
331 #endif
332                            break;
333                         case 4:
334                            *(Uint32 *)dst_pixel = blend_mapped;
335                            break;
336                      }
337                   }
338                   src_pixel += src_bpp;
339                   dst_pixel += dst_bpp;
340                }
341                src_pixel += src->pitch - src_rect.size.x * src_bpp;
342                dst_pixel += dst->pitch - src_rect.size.x * dst_bpp;
343             }
344             if(SDL_MUSTLOCK(dst))
345             {
346                SDL_UnlockSurface(dst);
347             }
348             if(SDL_MUSTLOCK(src))
349             {
350                SDL_UnlockSurface(src);
351             }
352          }
353
354          void Blitters::blit_lower_alpha(SDL_Surface *src, const Rect &src_rect, SDL_Surface *dst, const Point &dst_pos)
355          {
356             SDL_Rect sdl_src_rect = {src_rect.pos.x, src_rect.pos.y, src_rect.size.x, src_rect.size.y};
357             SDL_Rect sdl_dst_rect = {dst_pos.x, dst_pos.y, 0, 0};
358
359             SDL_BlitSurface(src, &sdl_src_rect, dst, &sdl_dst_rect);
360          }
361
362          void Blitters::blit_lower_add(SDL_Surface *src, const Rect &src_rect, SDL_Surface *dst, const Point &dst_pos)
363          {
364             if(SDL_MUSTLOCK(src))
365             {
366                SDL_LockSurface(src);
367             }
368             if(SDL_MUSTLOCK(dst))
369             {
370                SDL_LockSurface(dst);
371             }
372             int src_bpp = src->format->BytesPerPixel;
373             int dst_bpp = dst->format->BytesPerPixel;
374             Uint8 *src_pixel = (Uint8 *)src->pixels + src_rect.pos.y * src->pitch + src_rect.pos.x * src_bpp;
375             Uint8 *dst_pixel = (Uint8 *)dst->pixels + dst_pos.y * dst->pitch + dst_pos.x * dst_bpp;
376             for(unsigned int y = 0;y < src_rect.size.y;y++)
377             {
378                for(unsigned int x = 0;x < src_rect.size.x;x++)
379                {
380                   Uint32 src_mapped = 0;
381                   switch(src_bpp) {
382                      case 1:
383                         src_mapped = *src_pixel;
384                         break;
385                      case 2:
386                         src_mapped = *(Uint16 *)src_pixel;
387                         break;
388                      case 3:
389 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
390                         src_mapped |= src_pixel[0] << 16;
391                         src_mapped |= src_pixel[1] << 8;
392                         src_mapped |= src_pixel[2] << 0;
393 #else
394                         src_mapped |= src_pixel[0] << 0;
395                         src_mapped |= src_pixel[1] << 8;
396                         src_mapped |= src_pixel[2] << 16;
397 #endif
398                         break;
399                      case 4:
400                         src_mapped = *(Uint32 *)src_pixel;
401                         break;
402                   }
403                   Uint8 src_red, src_green, src_blue, src_alpha;
404                   SDL_GetRGBA(src_mapped, src->format, &src_red, &src_green, &src_blue, &src_alpha);
405                   Uint32 dst_mapped = 0;
406                   switch(dst_bpp) {
407                      case 1:
408                         dst_mapped = *dst_pixel;
409                         break;
410                      case 2:
411                         dst_mapped = *(Uint16 *)dst_pixel;
412                         break;
413                      case 3:
414 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
415                         dst_mapped |= dst_pixel[0] << 16;
416                         dst_mapped |= dst_pixel[1] << 8;
417                         dst_mapped |= dst_pixel[2] << 0;
418 #else
419                         dst_mapped |= dst_pixel[0] << 0;
420                         dst_mapped |= dst_pixel[1] << 8;
421                         dst_mapped |= dst_pixel[2] << 16;
422 #endif
423                         break;
424                      case 4:
425                         dst_mapped = *(Uint32 *)dst_pixel;
426                         break;
427                   }
428                   Uint8 dst_red, dst_green, dst_blue, dst_alpha;
429                   SDL_GetRGBA(dst_mapped, dst->format, &dst_red, &dst_green, &dst_blue, &dst_alpha);
430                   Uint8 blend_red = src_red, blend_green = src_green, blend_blue = src_blue, blend_alpha = src_alpha;
431                   if(src_red != 0 && dst_red != 0xff)
432                   {
433                      int redsum = dst_red + src_red * src_alpha / 0xff;
434                      blend_red = redsum & ~0xff ? 0xff : redsum;
435                   }
436                   else
437                   {
438                   }
439                   if(src_green != 0 && dst_green != 0xff)
440                   {
441                      int greensum = dst_green + src_green * src_alpha / 0xff;
442                      blend_green = greensum & ~0xff ? 0xff : greensum;
443                   }
444                   if(src_blue != 0 && dst_blue != 0xff)
445                   {
446                      int bluesum = dst_blue + src_blue * src_alpha / 0xff;
447                      blend_blue = bluesum & ~0xff ? 0xff : bluesum;
448                   }
449                   if(src_red != blend_red || src_green != blend_green || src_blue != blend_blue || src_alpha != blend_alpha)
450                   {
451                      Uint32 blend_mapped = SDL_MapRGBA(dst->format, blend_red, blend_green, blend_blue, blend_alpha);
452                      switch(dst_bpp) {
453                         case 1:
454                            *dst_pixel = blend_mapped;
455                            break;
456                         case 2:
457                            *(Uint16 *)dst_pixel = blend_mapped;
458                            break;
459                         case 3:
460 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
461                            dst_pixel[0] = (blend_mapped >> 16) & 0xff;
462                            dst_pixel[1] = (blend_mapped >> 8) & 0xff;
463                            dst_pixel[2] = (blend_mapped >> 0) & 0xff;
464 #else
465                            dst_pixel[0] = (blend_mapped >> 0) & 0xff;
466                            dst_pixel[1] = (blend_mapped >> 8) & 0xff;
467                            dst_pixel[2] = (blend_mapped >> 16) & 0xff;
468 #endif
469                            break;
470                         case 4:
471                            *(Uint32 *)dst_pixel = blend_mapped;
472                            break;
473                      }
474                   }
475                   src_pixel += src_bpp;
476                   dst_pixel += dst_bpp;
477                }
478                src_pixel += src->pitch - src_rect.size.x * src_bpp;
479                dst_pixel += dst->pitch - src_rect.size.x * dst_bpp;
480             }
481             if(SDL_MUSTLOCK(dst))
482             {
483                SDL_UnlockSurface(dst);
484             }
485             if(SDL_MUSTLOCK(src))
486             {
487                SDL_UnlockSurface(src);
488             }
489          }
490
491          void Blitters::blit_lower_mod(SDL_Surface *src, const Rect &src_rect, SDL_Surface *dst, const Point &dst_pos)
492          {
493             if(SDL_MUSTLOCK(src))
494             {
495                SDL_LockSurface(src);
496             }
497             if(SDL_MUSTLOCK(dst))
498             {
499                SDL_LockSurface(dst);
500             }
501             int src_bpp = src->format->BytesPerPixel;
502             int dst_bpp = dst->format->BytesPerPixel;
503             Uint8 *src_pixel = (Uint8 *)src->pixels + src_rect.pos.y * src->pitch + src_rect.pos.x * src_bpp;
504             Uint8 *dst_pixel = (Uint8 *)dst->pixels + dst_pos.y * dst->pitch + dst_pos.x * dst_bpp;
505             for(unsigned int y = 0;y < src_rect.size.y;y++)
506             {
507                for(unsigned int x = 0;x < src_rect.size.x;x++)
508                {
509                   Uint32 src_mapped = 0;
510                   switch(src_bpp) {
511                      case 1:
512                         src_mapped = *src_pixel;
513                         break;
514                      case 2:
515                         src_mapped = *(Uint16 *)src_pixel;
516                         break;
517                      case 3:
518 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
519                         src_mapped |= src_pixel[0] << 16;
520                         src_mapped |= src_pixel[1] << 8;
521                         src_mapped |= src_pixel[2] << 0;
522 #else
523                         src_mapped |= src_pixel[0] << 0;
524                         src_mapped |= src_pixel[1] << 8;
525                         src_mapped |= src_pixel[2] << 16;
526 #endif
527                         break;
528                      case 4:
529                         src_mapped = *(Uint32 *)src_pixel;
530                         break;
531                   }
532                   Uint8 src_red, src_green, src_blue, src_alpha;
533                   SDL_GetRGBA(src_mapped, src->format, &src_red, &src_green, &src_blue, &src_alpha);
534                   Uint32 dst_mapped = 0;
535                   switch(dst_bpp) {
536                      case 1:
537                         dst_mapped = *dst_pixel;
538                         break;
539                      case 2:
540                         dst_mapped = *(Uint16 *)dst_pixel;
541                         break;
542                      case 3:
543 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
544                         dst_mapped |= dst_pixel[0] << 16;
545                         dst_mapped |= dst_pixel[1] << 8;
546                         dst_mapped |= dst_pixel[2] << 0;
547 #else
548                         dst_mapped |= dst_pixel[0] << 0;
549                         dst_mapped |= dst_pixel[1] << 8;
550                         dst_mapped |= dst_pixel[2] << 16;
551 #endif
552                         break;
553                      case 4:
554                         dst_mapped = *(Uint32 *)dst_pixel;
555                         break;
556                   }
557                   Uint8 dst_red, dst_green, dst_blue, dst_alpha;
558                   SDL_GetRGBA(dst_mapped, dst->format, &dst_red, &dst_green, &dst_blue, &dst_alpha);
559                   Uint8 blend_red, blend_green, blend_blue, blend_alpha;
560                   blend_red = dst_red * src_red / 0xff;
561                   blend_green = dst_green * src_green / 0xff;
562                   blend_blue = dst_blue * src_blue / 0xff;
563                   blend_alpha = dst_alpha * src_alpha / 0xff;
564                   if(src_red != blend_red || src_green != blend_green || src_blue != blend_blue || src_alpha != blend_alpha)
565                   {
566                      Uint32 blend_mapped = SDL_MapRGBA(dst->format, blend_red, blend_green, blend_blue, blend_alpha);
567                      switch(dst_bpp) {
568                         case 1:
569                            *dst_pixel = blend_mapped;
570                            break;
571                         case 2:
572                            *(Uint16 *)dst_pixel = blend_mapped;
573                            break;
574                         case 3:
575 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
576                            dst_pixel[0] = (blend_mapped >> 16) & 0xff;
577                            dst_pixel[1] = (blend_mapped >> 8) & 0xff;
578                            dst_pixel[2] = (blend_mapped >> 0) & 0xff;
579 #else
580                            dst_pixel[0] = (blend_mapped >> 0) & 0xff;
581                            dst_pixel[1] = (blend_mapped >> 8) & 0xff;
582                            dst_pixel[2] = (blend_mapped >> 16) & 0xff;
583 #endif
584                            break;
585                         case 4:
586                            *(Uint32 *)dst_pixel = blend_mapped;
587                            break;
588                      }
589                   }
590                   src_pixel += src_bpp;
591                   dst_pixel += dst_bpp;
592                }
593                src_pixel += src->pitch - src_rect.size.x * src_bpp;
594                dst_pixel += dst->pitch - src_rect.size.x * dst_bpp;
595             }
596             if(SDL_MUSTLOCK(dst))
597             {
598                SDL_UnlockSurface(dst);
599             }
600             if(SDL_MUSTLOCK(src))
601             {
602                SDL_UnlockSurface(src);
603             }
604          }
605       }
606    }
607 }