Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2.     SDL - Simple DirectMedia Layer
  3.     Copyright (C) 1997, 1998, 1999, 2000, 2001  Sam Lantinga
  4.  
  5.     This library is free software; you can redistribute it and/or
  6.     modify it under the terms of the GNU Library General Public
  7.     License as published by the Free Software Foundation; either
  8.     version 2 of the License, or (at your option) any later version.
  9.  
  10.     This library is distributed in the hope that it will be useful,
  11.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13.     Library General Public License for more details.
  14.  
  15.     You should have received a copy of the GNU Library General Public
  16.     License along with this library; if not, write to the Free
  17.     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  18.  
  19.     Sam Lantinga
  20.     slouken@devolution.com
  21. */
  22.  
  23. #include <stdio.h>
  24. #include <stdlib.h>
  25. #include <string.h>
  26.  
  27. #include "SDL_error.h"
  28. #include "SDL_video.h"
  29. #include "SDL_sysvideo.h"
  30. #include "SDL_blit.h"
  31. #include "SDL_RLEaccel_c.h"
  32. #include "SDL_pixels_c.h"
  33. #include "SDL_memops.h"
  34.  
  35. /* The general purpose software blit routine */
  36. static int SDL_SoftBlit(SDL_Surface *src, SDL_Rect *srcrect,
  37.                         SDL_Surface *dst, SDL_Rect *dstrect)
  38. {
  39.         int okay;
  40.         int src_locked;
  41.         int dst_locked;
  42.  
  43.         /* Everything is okay at the beginning...  */
  44.         okay = 1;
  45.  
  46.         /* Lock the destination if it's in hardware */
  47.         dst_locked = 0;
  48.         if ( dst->flags & (SDL_HWSURFACE|SDL_ASYNCBLIT) ) {
  49.                 SDL_VideoDevice *video = current_video;
  50.                 SDL_VideoDevice *this  = current_video;
  51.                 if ( video->LockHWSurface(this, dst) < 0 ) {
  52.                         okay = 0;
  53.                 } else {
  54.                         dst_locked = 1;
  55.                 }
  56.         }
  57.         /* Lock the source if it's in hardware */
  58.         src_locked = 0;
  59.         if ( src->flags & (SDL_HWSURFACE|SDL_ASYNCBLIT) ) {
  60.                 SDL_VideoDevice *video = current_video;
  61.                 SDL_VideoDevice *this  = current_video;
  62.                 if ( video->LockHWSurface(this, src) < 0 ) {
  63.                         okay = 0;
  64.                 } else {
  65.                         src_locked = 1;
  66.                 }
  67.         }
  68.  
  69.         /* Unencode the destination if it's RLE encoded */
  70.         if ( dst->flags & SDL_RLEACCEL ) {
  71.                 SDL_UnRLESurface(dst, 1);
  72.                 dst->flags |= SDL_RLEACCEL;     /* save accel'd state */
  73.         }
  74.  
  75.         /* Set up source and destination buffer pointers, and BLIT! */
  76.         if ( okay  && srcrect->w && srcrect->h ) {
  77.                 SDL_BlitInfo info;
  78.                 SDL_loblit RunBlit;
  79.  
  80.                 /* Set up the blit information */
  81.                 info.s_pixels = (Uint8 *)src->pixels + src->offset +
  82.                                 (Uint16)srcrect->y*src->pitch +
  83.                                 (Uint16)srcrect->x*src->format->BytesPerPixel;
  84.                 info.s_width = srcrect->w;
  85.                 info.s_height = srcrect->h;
  86.                 info.s_skip=src->pitch-info.s_width*src->format->BytesPerPixel;
  87.                 info.d_pixels = (Uint8 *)dst->pixels + dst->offset +
  88.                                 (Uint16)dstrect->y*dst->pitch +
  89.                                 (Uint16)dstrect->x*dst->format->BytesPerPixel;
  90.                 info.d_width = dstrect->w;
  91.                 info.d_height = dstrect->h;
  92.                 info.d_skip=dst->pitch-info.d_width*dst->format->BytesPerPixel;
  93.                 info.aux_data = src->map->sw_data->aux_data;
  94.                 info.src = src->format;
  95.                 info.table = src->map->table;
  96.                 info.dst = dst->format;
  97.                 RunBlit = src->map->sw_data->blit;
  98.  
  99.                 /* Run the actual software blit */
  100.                 RunBlit(&info);
  101.         }
  102.  
  103.         /* Re-encode the destination if it's RLE encoded */
  104.         if ( dst->flags & SDL_RLEACCEL ) {
  105.                 dst->flags &= ~SDL_RLEACCEL; /* stop lying */
  106.                 SDL_RLESurface(dst);
  107.         }
  108.  
  109.         /* We need to unlock the surfaces if they're locked */
  110.         if ( dst_locked ) {
  111.                 SDL_VideoDevice *video = current_video;
  112.                 SDL_VideoDevice *this  = current_video;
  113.                 video->UnlockHWSurface(this, dst);
  114.         } else
  115.         if ( src_locked ) {
  116.                 SDL_VideoDevice *video = current_video;
  117.                 SDL_VideoDevice *this  = current_video;
  118.                 video->UnlockHWSurface(this, src);
  119.         }
  120.         /* Blit is done! */
  121.         return(okay ? 0 : -1);
  122. }
  123.  
  124. static void SDL_BlitCopy(SDL_BlitInfo *info)
  125. {
  126.         Uint8 *src, *dst;
  127.         int w, h;
  128.         int srcskip, dstskip;
  129.  
  130.         w = info->d_width*info->dst->BytesPerPixel;
  131.         h = info->d_height;
  132.         src = info->s_pixels;
  133.         dst = info->d_pixels;
  134.         srcskip = w+info->s_skip;
  135.         dstskip = w+info->d_skip;
  136.         while ( h-- ) {
  137.                 SDL_memcpy(dst, src, w);
  138.                 src += srcskip;
  139.                 dst += dstskip;
  140.         }
  141. }
  142.  
  143. static void SDL_BlitCopyOverlap(SDL_BlitInfo *info)
  144. {
  145.         Uint8 *src, *dst;
  146.         int w, h;
  147.         int srcskip, dstskip;
  148.  
  149.         w = info->d_width*info->dst->BytesPerPixel;
  150.         h = info->d_height;
  151.         src = info->s_pixels;
  152.         dst = info->d_pixels;
  153.         srcskip = w+info->s_skip;
  154.         dstskip = w+info->d_skip;
  155.         if ( dst < src ) {
  156.                 while ( h-- ) {
  157.                         SDL_memcpy(dst, src, w);
  158.                         src += srcskip;
  159.                         dst += dstskip;
  160.                 }
  161.         } else {
  162.                 src += ((h-1) * srcskip);
  163.                 dst += ((h-1) * dstskip);
  164.                 while ( h-- ) {
  165.                         SDL_revcpy(dst, src, w);
  166.                         src -= srcskip;
  167.                         dst -= dstskip;
  168.                 }
  169.         }
  170. }
  171.  
  172. /* Figure out which of many blit routines to set up on a surface */
  173. int SDL_CalculateBlit(SDL_Surface *surface)
  174. {
  175.         int blit_index;
  176.  
  177.         /* Clean everything out to start */
  178.         if ( (surface->flags & SDL_RLEACCEL) == SDL_RLEACCEL ) {
  179.                 SDL_UnRLESurface(surface, 1);
  180.         }
  181.         surface->map->sw_blit = NULL;
  182.  
  183.         /* Figure out if an accelerated hardware blit is possible */
  184.         surface->flags &= ~SDL_HWACCEL;
  185.         if ( surface->map->identity ) {
  186.                 int hw_blit_ok;
  187.  
  188.                 if ( (surface->flags & SDL_HWSURFACE) == SDL_HWSURFACE ) {
  189.                         /* We only support accelerated blitting to hardware */
  190.                         if ( surface->map->dst->flags & SDL_HWSURFACE ) {
  191.                                 hw_blit_ok = current_video->info.blit_hw;
  192.                         } else {
  193.                                 hw_blit_ok = 0;
  194.                         }
  195.                         if (hw_blit_ok && (surface->flags & SDL_SRCCOLORKEY)) {
  196.                                 hw_blit_ok = current_video->info.blit_hw_CC;
  197.                         }
  198.                         if ( hw_blit_ok && (surface->flags & SDL_SRCALPHA) ) {
  199.                                 hw_blit_ok = current_video->info.blit_hw_A;
  200.                         }
  201.                 } else {
  202.                         /* We only support accelerated blitting to hardware */
  203.                         if ( surface->map->dst->flags & SDL_HWSURFACE ) {
  204.                                 hw_blit_ok = current_video->info.blit_sw;
  205.                         } else {
  206.                                 hw_blit_ok = 0;
  207.                         }
  208.                         if (hw_blit_ok && (surface->flags & SDL_SRCCOLORKEY)) {
  209.                                 hw_blit_ok = current_video->info.blit_sw_CC;
  210.                         }
  211.                         if ( hw_blit_ok && (surface->flags & SDL_SRCALPHA) ) {
  212.                                 hw_blit_ok = current_video->info.blit_sw_A;
  213.                         }
  214.                 }
  215.                 if ( hw_blit_ok ) {
  216.                         SDL_VideoDevice *video = current_video;
  217.                         SDL_VideoDevice *this  = current_video;
  218.                         video->CheckHWBlit(this, surface, surface->map->dst);
  219.                 }
  220.         }
  221.  
  222.         /* Get the blit function index, based on surface mode */
  223.         /* { 0 = nothing, 1 = colorkey, 2 = alpha, 3 = colorkey+alpha } */
  224.         blit_index = 0;
  225.         blit_index |= (!!(surface->flags & SDL_SRCCOLORKEY))      << 0;
  226.         if ( surface->flags & SDL_SRCALPHA
  227.              && (surface->format->alpha != SDL_ALPHA_OPAQUE
  228.                  || surface->format->Amask) ) {
  229.                 blit_index |= 2;
  230.         }
  231.  
  232.         /* Check for special "identity" case -- copy blit */
  233.         if ( surface->map->identity && blit_index == 0 ) {
  234.                 surface->map->sw_data->blit = SDL_BlitCopy;
  235.  
  236.                 /* Handle overlapping blits on the same surface */
  237.                 if ( surface == surface->map->dst ) {
  238.                         surface->map->sw_data->blit = SDL_BlitCopyOverlap;
  239.                 }
  240.         } else {
  241.                 if ( surface->format->BitsPerPixel < 8 ) {
  242.                         surface->map->sw_data->blit =
  243.                             SDL_CalculateBlit0(surface, blit_index);
  244.                 } else {
  245.                         switch ( surface->format->BytesPerPixel ) {
  246.                             case 1:
  247.                                 surface->map->sw_data->blit =
  248.                                     SDL_CalculateBlit1(surface, blit_index);
  249.                                 break;
  250.                             case 2:
  251.                             case 3:
  252.                             case 4:
  253.                                 surface->map->sw_data->blit =
  254.                                     SDL_CalculateBlitN(surface, blit_index);
  255.                                 break;
  256.                             default:
  257.                                 surface->map->sw_data->blit = NULL;
  258.                                 break;
  259.                         }
  260.                 }
  261.         }
  262.         /* Make sure we have a blit function */
  263.         if ( surface->map->sw_data->blit == NULL ) {
  264.                 SDL_InvalidateMap(surface->map);
  265.                 SDL_SetError("Blit combination not supported");
  266.                 return(-1);
  267.         }
  268.  
  269.         /* Choose software blitting function */
  270.         if(surface->flags & SDL_RLEACCELOK
  271.            && (surface->flags & SDL_HWACCEL) != SDL_HWACCEL) {
  272.  
  273.                 if(surface->map->identity
  274.                    && (blit_index == 1
  275.                        || (blit_index == 3 && !surface->format->Amask))) {
  276.                         if ( SDL_RLESurface(surface) == 0 )
  277.                                 surface->map->sw_blit = SDL_RLEBlit;
  278.                 } else if(blit_index == 2 && surface->format->Amask) {
  279.                         if ( SDL_RLESurface(surface) == 0 )
  280.                                 surface->map->sw_blit = SDL_RLEAlphaBlit;
  281.                 }
  282.         }
  283.        
  284.         if ( surface->map->sw_blit == NULL ) {
  285.                 surface->map->sw_blit = SDL_SoftBlit;
  286.         }
  287.         return(0);
  288. }
  289.  
  290.