1 /**********************************************************************
2  Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold
3    This program is free software; you can redistribute it and/or modify
4    it under the terms of the GNU General Public License as published by
5    the Free Software Foundation; either version 2, or (at your option)
6    any later version.
7 
8    This program 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
11    GNU General Public License for more details.
12 ***********************************************************************/
13 
14 /**********************************************************************
15                           graphics.c  -  description
16                              -------------------
17     begin                : Mon Jul 1 2002
18     copyright            : (C) 2000 by Michael Speck
19 			 : (C) 2002 by Rafał Bursig
20     email                : Michael Speck <kulkanie@gmx.net>
21 			 : Rafał Bursig <bursig@poczta.fm>
22  **********************************************************************/
23 
24 #ifdef HAVE_CONFIG_H
25 #include <fc_config.h>
26 #endif
27 
28 /* SDL */
29 #include <SDL/SDL_image.h>
30 #include <SDL/SDL_syswm.h>
31 #include <SDL/SDL_ttf.h>
32 
33 /* utility */
34 #include "fcintl.h"
35 #include "log.h"
36 
37 /* client */
38 #include "tilespec.h"
39 
40 /* gui-sdl */
41 #include "gui_tilespec.h"
42 #include "mapview.h"
43 #include "themebackgrounds.h"
44 #include "themespec.h"
45 
46 #include "graphics.h"
47 
48 #ifdef HAVE_MMX1
49 #include "mmx.h"
50 #endif
51 
52 /* ------------------------------ */
53 
54 struct main Main;
55 
56 /**************************************************************************
57   Allocate new gui_layer.
58 **************************************************************************/
gui_layer_new(int x,int y,SDL_Surface * surface)59 struct gui_layer *gui_layer_new(int x, int y, SDL_Surface *surface)
60 {
61   struct gui_layer *result;
62 
63   result = fc_calloc(1, sizeof(struct gui_layer));
64 
65   result->dest_rect = (SDL_Rect){x, y, 0, 0};
66   result->surface = surface;
67 
68   return result;
69 }
70 
71 /**************************************************************************
72   Free resources associated with gui_layer.
73 **************************************************************************/
gui_layer_destroy(struct gui_layer ** gui_layer)74 void gui_layer_destroy(struct gui_layer **gui_layer)
75 {
76   FREESURFACE((*gui_layer)->surface);
77   FC_FREE(*gui_layer);
78 }
79 
80 /**************************************************************************
81   Get surface gui_layer.
82 **************************************************************************/
get_gui_layer(SDL_Surface * surface)83 struct gui_layer *get_gui_layer(SDL_Surface *surface)
84 {
85   int i = 0;
86 
87   while ((i < Main.guis_count) && Main.guis[i]) {
88     if(Main.guis[i]->surface == surface) {
89       return Main.guis[i];
90     }
91     i++;
92   }
93 
94   return NULL;
95 }
96 
97 /**************************************************************************
98   Buffer allocation function.
99   This function is call by "create_window(...)" function and allocate
100   buffer layer for this function.
101 
102   Pointer for this buffer is put in buffer array on last position that
103   flush functions will draw this layer last.
104 **************************************************************************/
add_gui_layer(int width,int height)105 struct gui_layer *add_gui_layer(int width, int height)
106 {
107   struct gui_layer *gui_layer = NULL;
108   SDL_Surface *pBuffer;
109 
110   pBuffer = create_surf_alpha(/*Main.screen->w*/width, /*Main.screen->h*/height, SDL_SWSURFACE);
111   gui_layer = gui_layer_new(0, 0, pBuffer);
112 
113   /* add to buffers array */
114   if (Main.guis) {
115     int i;
116     /* find NULL element */
117     for(i = 0; i < Main.guis_count; i++) {
118       if(!Main.guis[i]) {
119         Main.guis[i] = gui_layer;
120 	return gui_layer;
121       }
122     }
123     Main.guis_count++;
124     Main.guis = fc_realloc(Main.guis, Main.guis_count * sizeof(struct gui_layer *));
125     Main.guis[Main.guis_count - 1] = gui_layer;
126   } else {
127     Main.guis = fc_calloc(1, sizeof(struct gui_layer *));
128     Main.guis[0] = gui_layer;
129     Main.guis_count = 1;
130   }
131 
132   return gui_layer;
133 }
134 
135 /**************************************************************************
136   Free buffer layer ( call by popdown_window_group_dialog(...) funct )
137   Funct. free buffer layer and cleare buffer array entry.
138 **************************************************************************/
remove_gui_layer(struct gui_layer * gui_layer)139 void remove_gui_layer(struct gui_layer *gui_layer)
140 {
141   int i;
142 
143   for(i = 0; i < Main.guis_count - 1; i++) {
144     if(Main.guis[i] && (Main.guis[i]== gui_layer)) {
145       gui_layer_destroy(&Main.guis[i]);
146       Main.guis[i] = Main.guis[i + 1];
147       Main.guis[i + 1] = NULL;
148     } else {
149       if(!Main.guis[i]) {
150 	Main.guis[i] = Main.guis[i + 1];
151         Main.guis[i + 1] = NULL;
152       }
153     }
154   }
155 
156   if (Main.guis[Main.guis_count - 1]) {
157     gui_layer_destroy(&Main.guis[Main.guis_count - 1]);
158   }
159 }
160 
161 /**********************************************************************//**
162   Translate dest_rect from global screen to gui_layer's coordinates.
163 **************************************************************************/
screen_rect_to_layer_rect(struct gui_layer * gui_layer,SDL_Rect * dest_rect)164 void screen_rect_to_layer_rect(struct gui_layer *gui_layer, SDL_Rect *dest_rect)
165 {
166   if (gui_layer) {
167     dest_rect->x = dest_rect->x - gui_layer->dest_rect.x;
168     dest_rect->y = dest_rect->y - gui_layer->dest_rect.y;
169   }
170 }
171 
172 /**********************************************************************//**
173   Translate dest_rect from gui_layer's to global screen coordinates.
174 **************************************************************************/
layer_rect_to_screen_rect(struct gui_layer * gui_layer,SDL_Rect * dest_rect)175 void layer_rect_to_screen_rect(struct gui_layer *gui_layer, SDL_Rect *dest_rect)
176 {
177   if (gui_layer) {
178     dest_rect->x = dest_rect->x + gui_layer->dest_rect.x;
179     dest_rect->y = dest_rect->y + gui_layer->dest_rect.y;
180   }
181 }
182 
183 /* ============ Freeciv sdl graphics function =========== */
184 
185 /**************************************************************************
186   Execute alphablit.
187 **************************************************************************/
alphablit(SDL_Surface * src,SDL_Rect * srcrect,SDL_Surface * dst,SDL_Rect * dstrect)188 int alphablit(SDL_Surface *src, SDL_Rect *srcrect,
189               SDL_Surface *dst, SDL_Rect *dstrect) {
190 
191   if (!(src && dst)) {
192     return 0;
193   }
194 
195   /* use for RGBA->RGBA blits only */
196   if (src->format->Amask && dst->format->Amask) {
197     return pygame_AlphaBlit(src, srcrect, dst, dstrect);
198   } else {
199     return SDL_BlitSurface(src, srcrect, dst, dstrect);
200   }
201 }
202 
203 /**************************************************************************
204   Create new surface (pRect->w x pRect->h size) and copy pRect area of
205   pSource.
206   if pRect == NULL then create copy of entire pSource.
207 **************************************************************************/
crop_rect_from_surface(SDL_Surface * pSource,SDL_Rect * pRect)208 SDL_Surface * crop_rect_from_surface(SDL_Surface *pSource,
209 				    SDL_Rect *pRect)
210 {
211   SDL_Surface *pNew = create_surf_with_format(pSource->format,
212 					      pRect ? pRect->w : pSource->w,
213 					      pRect ? pRect->h : pSource->h,
214 					      SDL_SWSURFACE);
215   if (alphablit(pSource, pRect, pNew, NULL) != 0) {
216     FREESURFACE(pNew);
217   }
218 
219   return pNew;
220 }
221 
222 /**************************************************************************
223   Reduce the alpha of the final surface proportional to the alpha of the mask.
224   Thus if the mask has 50% alpha the final image will be reduced by 50% alpha.
225 
226   mask_offset_x, mask_offset_y is the offset of the mask relative to the
227   origin of the source image.  The pixel at (mask_offset_x,mask_offset_y)
228   in the mask image will be used to clip pixel (0,0) in the source image
229   which is pixel (-x,-y) in the new image.
230 **************************************************************************/
mask_surface(SDL_Surface * pSrc,SDL_Surface * pMask,int mask_offset_x,int mask_offset_y)231 SDL_Surface *mask_surface(SDL_Surface * pSrc, SDL_Surface * pMask,
232                           int mask_offset_x, int mask_offset_y)
233 {
234   SDL_Surface *pDest = NULL;
235 
236   int row, col;
237   bool free_pMask = FALSE;
238   Uint32 *pSrc_Pixel = NULL;
239   Uint32 *pDest_Pixel = NULL;
240   Uint32 *pMask_Pixel = NULL;
241   unsigned char src_alpha, mask_alpha;
242 
243   if (!pMask->format->Amask) {
244     pMask = SDL_DisplayFormatAlpha(pMask);
245     free_pMask = TRUE;
246   }
247 
248   pSrc = SDL_DisplayFormatAlpha(pSrc);
249   pDest = SDL_DisplayFormatAlpha(pSrc);
250 
251   lock_surf(pSrc);
252   lock_surf(pMask);
253   lock_surf(pDest);
254 
255   pSrc_Pixel = (Uint32 *)pSrc->pixels;
256   pDest_Pixel = (Uint32 *)pDest->pixels;
257 
258   for (row = 0; row < pSrc->h; row++) {
259 
260     pMask_Pixel = (Uint32 *)pMask->pixels
261                   + pMask->w * (row + mask_offset_y)
262                   + mask_offset_x;
263 
264     for (col = 0; col < pSrc->w; col++) {
265       src_alpha = (*pSrc_Pixel & pSrc->format->Amask) >> pSrc->format->Ashift;
266       mask_alpha = (*pMask_Pixel & pMask->format->Amask) >> pMask->format->Ashift;
267 
268       *pDest_Pixel = (*pSrc_Pixel & ~pSrc->format->Amask)
269                    | (((src_alpha * mask_alpha) / 255) << pDest->format->Ashift);
270 
271       pSrc_Pixel++; pDest_Pixel++; pMask_Pixel++;
272     }
273   }
274 
275   unlock_surf(pDest);
276   unlock_surf(pMask);
277   unlock_surf(pSrc);
278 
279   if (free_pMask) {
280     FREESURFACE(pMask);
281   }
282 
283   FREESURFACE(pSrc); /* result of SDL_DisplayFormatAlpha() */
284 
285   return pDest;
286 }
287 
288 /**************************************************************************
289   Create new surface by blending source.
290 **************************************************************************/
blend_surface(SDL_Surface * pSrc,unsigned char alpha)291 SDL_Surface *blend_surface(SDL_Surface *pSrc, unsigned char alpha)
292 {
293   SDL_Surface *ret;
294 
295   SDL_Surface *pMask = SDL_DisplayFormatAlpha(pSrc);
296   SDL_Color c = {255, 255, 255, alpha};
297   SDL_FillRect(pMask, NULL, map_rgba(pMask->format, c));
298 
299   ret = mask_surface(pSrc, pMask, 0, 0);
300 
301   FREESURFACE(pMask);
302 
303   return ret;
304 }
305 
306 /**************************************************************************
307   Load a surface from file putting it in software mem.
308 **************************************************************************/
load_surf(const char * pFname)309 SDL_Surface *load_surf(const char *pFname)
310 {
311   SDL_Surface *pBuf;
312 
313   if(!pFname) {
314     return NULL;
315   }
316 
317   if ((pBuf = IMG_Load(pFname)) == NULL) {
318     log_error(_("load_surf: Failed to load graphic file %s!"), pFname);
319     return NULL;
320   }
321 
322   if(Main.screen) {
323     SDL_Surface *pNew_sur;
324     if ((pNew_sur = SDL_DisplayFormatAlpha(pBuf)) == NULL) {
325       log_error(_("load_surf: Unable to convert file %s "
326                   "into screen's format!"), pFname);
327     } else {
328       FREESURFACE(pBuf);
329       return pNew_sur;
330     }
331   }
332 
333   return pBuf;
334 }
335 
336 /**************************************************************************
337   Load a surface from file putting it in soft or hardware mem
338   Warning: pFname must have full path to file
339 **************************************************************************/
load_surf_with_flags(const char * pFname,int iFlags)340 SDL_Surface *load_surf_with_flags(const char *pFname, int iFlags)
341 {
342   SDL_Surface *pBuf = NULL;
343   SDL_Surface *pNew_sur = NULL;
344   SDL_PixelFormat *pSpf = SDL_GetVideoSurface()->format;
345 
346   if ((pBuf = IMG_Load(pFname)) == NULL) {
347     log_error(_("load_surf_with_flags: Unable to load file %s."), pFname);
348     return NULL;
349   }
350 
351   if ((pNew_sur = SDL_ConvertSurface(pBuf, pSpf, iFlags)) == NULL) {
352     log_error(_("Unable to convert image from file %s into format %d."),
353               pFname, iFlags);
354     return pBuf;
355   }
356 
357   FREESURFACE(pBuf);
358 
359   return pNew_sur;
360 }
361 
362 /**************************************************************************
363    create an surface with format
364    MUST NOT BE USED IF NO SDLSCREEN IS SET
365 **************************************************************************/
create_surf_with_format(SDL_PixelFormat * pSpf,int iWidth,int iHeight,Uint32 iFlags)366 SDL_Surface *create_surf_with_format(SDL_PixelFormat * pSpf,
367 				     int iWidth, int iHeight,
368 				     Uint32 iFlags)
369 {
370   SDL_Surface *pSurf = SDL_CreateRGBSurface(iFlags, iWidth, iHeight,
371 					    pSpf->BitsPerPixel,
372 					    pSpf->Rmask,
373 					    pSpf->Gmask,
374 					    pSpf->Bmask, pSpf->Amask);
375 
376   if (!pSurf) {
377     log_error(_("Unable to create Sprite (Surface) of size "
378                 "%d x %d %d Bits in format %d"),
379               iWidth, iHeight, pSpf->BitsPerPixel, iFlags);
380     return NULL;
381   }
382 
383   return pSurf;
384 }
385 
386 /**************************************************************************
387   create a surface with alpha channel
388 **************************************************************************/
create_surf_alpha(int iWidth,int iHeight,Uint32 iFlags)389 SDL_Surface *create_surf_alpha(int iWidth, int iHeight, Uint32 iFlags) {
390   SDL_Surface *pTmp = create_surf(iWidth, iHeight, iFlags);
391   SDL_Surface *pNew = SDL_DisplayFormatAlpha(pTmp);
392   FREESURFACE(pTmp);
393   clear_surface(pNew, NULL);
394 
395   return pNew;
396 }
397 
398 /**************************************************************************
399   create an surface with screen format and fill with color.
400   if pColor == NULL surface is filled with transparent white A = 128
401   MUST NOT BE USED IF NO SDLSCREEN IS SET
402 **************************************************************************/
create_filled_surface(Uint16 w,Uint16 h,Uint32 iFlags,SDL_Color * pColor,bool add_alpha)403 SDL_Surface *create_filled_surface(Uint16 w, Uint16 h, Uint32 iFlags,
404 				   SDL_Color * pColor, bool add_alpha)
405 {
406   SDL_Surface *pNew;
407   SDL_Color color = {255, 255, 255, 128};
408 
409   if (add_alpha) {
410     pNew = create_surf_alpha(w, h, iFlags);
411   } else {
412     pNew = create_surf(w, h, iFlags);
413   }
414 
415   if (!pNew) {
416     return NULL;
417   }
418 
419   if (!pColor) {
420     /* pColor->unused == ALPHA */
421     pColor = &color;
422   }
423 
424   SDL_FillRect(pNew, NULL,
425 	       SDL_MapRGBA(pNew->format, pColor->r, pColor->g, pColor->b,
426 			   pColor->unused));
427 
428   if (pColor->unused != 255) {
429     SDL_SetAlpha(pNew, SDL_SRCALPHA, pColor->unused);
430   }
431 
432   return pNew;
433 }
434 
435 /**************************************************************************
436   fill surface with (0, 0, 0, 0), so the next blitting operation can set
437   the per pixel alpha
438 **************************************************************************/
clear_surface(SDL_Surface * pSurf,SDL_Rect * dstrect)439 int clear_surface(SDL_Surface *pSurf, SDL_Rect *dstrect) {
440   /* SDL_FillRect might change the rectangle, so we create a copy */
441   if (dstrect) {
442     SDL_Rect _dstrect = *dstrect;
443     return SDL_FillRect(pSurf, &_dstrect, SDL_MapRGBA(pSurf->format, 0, 0, 0, 0));
444   } else {
445     return SDL_FillRect(pSurf, NULL, SDL_MapRGBA(pSurf->format, 0, 0, 0, 0));
446   }
447 }
448 
449 /**************************************************************************
450   blit entire src [SOURCE] surface to destination [DEST] surface
451   on position : [iDest_x],[iDest_y] using it's actual alpha and
452   color key settings.
453 **************************************************************************/
blit_entire_src(SDL_Surface * pSrc,SDL_Surface * pDest,Sint16 iDest_x,Sint16 iDest_y)454 int blit_entire_src(SDL_Surface * pSrc, SDL_Surface * pDest,
455 		    Sint16 iDest_x, Sint16 iDest_y)
456 {
457   SDL_Rect dest_rect = { iDest_x, iDest_y, 0, 0 };
458   return alphablit(pSrc, NULL, pDest, &dest_rect);
459 }
460 
461 
462 /*
463  * this is center main application window function
464  * currently it work only for X but problem is that such
465  * functions will be needed by others enviroments.
466  * ( for X it's make by settings "SDL_VIDEO_CENTERED" enviroment )
467  */
center_main_window_on_screen(void)468 int center_main_window_on_screen(void)
469 {
470   SDL_SysWMinfo myinfo;
471   SDL_VERSION(&myinfo.version);
472   if (SDL_GetWMInfo(&myinfo) > 0)
473   {
474 #ifdef WIN32_NATIVE
475 
476     /* Port ME - Write center window code with WinAPI instructions */
477 
478     return 0;
479 #else /* WIN32_NATIVE */
480 
481 #if 0
482     /* this code is for X and is only example what should be write to other
483        eviroments */
484     Screen *defscr;
485     Display *d = myinfo.info.x11.display;
486     myinfo.info.x11.lock_func();
487     defscr = DefaultScreenOfDisplay(d);
488     XMoveWindow(d, myinfo.info.x11.wmwindow,
489                (defscr->width - Main.screen->w) / 2,
490                (defscr->height - Main.screen->h) / 2);
491     myinfo.info.x11.unlock_func();
492 #endif /* 0 */
493     return 0;
494 #endif /* WIN32_NATIVE */
495   }
496   return -1;
497 }
498 
499 /**************************************************************************
500   get pixel
501   Return the pixel value at (x, y)
502   NOTE: The surface must be locked before calling this!
503 **************************************************************************/
getpixel(SDL_Surface * pSurface,Sint16 x,Sint16 y)504 Uint32 getpixel(SDL_Surface * pSurface, Sint16 x, Sint16 y)
505 {
506   if (!pSurface) return 0x0;
507   switch (pSurface->format->BytesPerPixel) {
508   case 1:
509     return *(Uint8 *) ((Uint8 *) pSurface->pixels + y * pSurface->pitch + x);
510 
511   case 2:
512     return *((Uint16 *)pSurface->pixels + y * pSurface->pitch / sizeof(Uint16) + x);
513 
514   case 3:
515     {
516       /* Here ptr is the address to the pixel we want to retrieve */
517       Uint8 *ptr =
518 	  (Uint8 *) pSurface->pixels + y * pSurface->pitch + x * 3;
519       if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
520 	return ptr[0] << 16 | ptr[1] << 8 | ptr[2];
521       } else {
522 	return ptr[0] | ptr[1] << 8 | ptr[2] << 16;
523       }
524     }
525   case 4:
526     return *((Uint32 *)pSurface->pixels + y * pSurface->pitch / sizeof(Uint32) + x);
527 
528   default:
529     return 0;			/* shouldn't happen, but avoids warnings */
530   }
531 }
532 
533 /**************************************************************************
534   get first pixel
535   Return the pixel value at (0, 0)
536   NOTE: The surface must be locked before calling this!
537 **************************************************************************/
get_first_pixel(SDL_Surface * pSurface)538 Uint32 get_first_pixel(SDL_Surface *pSurface)
539 {
540   if (!pSurface) return 0;
541   switch (pSurface->format->BytesPerPixel) {
542   case 1:
543     return *((Uint8 *)pSurface->pixels);
544 
545   case 2:
546     return *((Uint16 *)pSurface->pixels);
547 
548   case 3:
549     {
550       if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
551 	return (((Uint8 *)pSurface->pixels)[0] << 16)|
552 		(((Uint8 *)pSurface->pixels)[1] << 8)|
553 			((Uint8 *)pSurface->pixels)[2];
554       } else {
555 	return ((Uint8 *)pSurface->pixels)[0]|
556 		(((Uint8 *)pSurface->pixels)[1] << 8)|
557 			(((Uint8 *)pSurface->pixels)[2] << 16);
558       }
559     }
560   case 4:
561     return *((Uint32 *)pSurface->pixels);
562 
563   default:
564     return 0;			/* shouldn't happen, but avoids warnings */
565   }
566 }
567 
568 /* ===================================================================== */
569 
570 /**************************************************************************
571   initialize sdl with Flags
572 **************************************************************************/
init_sdl(int iFlags)573 void init_sdl(int iFlags)
574 {
575   bool error;
576   Main.screen = NULL;
577   Main.guis = NULL;
578   Main.gui = NULL;
579   Main.map = NULL;
580   Main.dummy = NULL; /* can't create yet -- hope we don't need it */
581   Main.rects_count = 0;
582   Main.guis_count = 0;
583 
584   if (SDL_WasInit(SDL_INIT_AUDIO)) {
585     error = (SDL_InitSubSystem(iFlags) < 0);
586   } else {
587     error = (SDL_Init(iFlags) < 0);
588   }
589   if (error) {
590     log_fatal(_("Unable to initialize SDL library: %s"), SDL_GetError());
591     exit(1);
592   }
593 
594   atexit(SDL_Quit);
595 
596   /* Initialize the TTF library */
597   if (TTF_Init() < 0) {
598     log_fatal(_("Unable to initialize SDL_ttf library: %s"), SDL_GetError());
599     exit(2);
600   }
601 
602   atexit(TTF_Quit);
603 }
604 
605 /**************************************************************************
606   Free screen buffers
607 **************************************************************************/
quit_sdl(void)608 void quit_sdl(void)
609 {
610   FC_FREE(Main.guis);
611   gui_layer_destroy(&Main.gui);
612   FREESURFACE(Main.map);
613   FREESURFACE(Main.dummy);
614 }
615 
616 /**************************************************************************
617   Switch to passed video mode.
618 **************************************************************************/
set_video_mode(int iWidth,int iHeight,int iFlags)619 int set_video_mode(int iWidth, int iHeight, int iFlags)
620 {
621   /* find best bpp */
622   int iDepth = SDL_GetVideoInfo()->vfmt->BitsPerPixel;
623 
624   /*  if screen does exist check if this is mayby
625      exactly the same resolution then return 1 */
626   if (Main.screen) {
627     if (Main.screen->w == iWidth && Main.screen->h == iHeight)
628       if ((Main.screen->flags & SDL_FULLSCREEN)
629 	  && (iFlags & SDL_FULLSCREEN))
630 	return 1;
631   }
632 
633   /* Check to see if a particular video mode is supported */
634   if ((iDepth = SDL_VideoModeOK(iWidth, iHeight, iDepth, iFlags)) == 0) {
635     log_error(_("No available mode for this resolution : %d x %d %d bpp"),
636               iWidth, iHeight, iDepth);
637 
638     log_debug(_("Setting default resolution to : 640 x 480 16 bpp SW"));
639 
640     Main.screen = SDL_SetVideoMode(640, 480, 16, SDL_SWSURFACE);
641   } else { /* set video mode */
642     if ((Main.screen = SDL_SetVideoMode(iWidth, iHeight,
643                                         iDepth, iFlags)) == NULL) {
644     log_error(_("Unable to set this resolution: %d x %d %d bpp %s"),
645               iWidth, iHeight, iDepth, SDL_GetError());
646 
647     exit(-30);
648   }
649 
650   log_debug(_("Setting resolution to: %d x %d %d bpp"),
651             iWidth, iHeight, iDepth);
652   }
653 
654   /* Create a dummy surface to be used when sprites are missing, etc.
655    * Various things (such as zoomSurfaceRGBA() don't cope well with a
656    * zero-sized surface, so we use a transparent 1x1 surface. */
657   FREESURFACE(Main.dummy);
658   Main.dummy = create_surf_alpha(1, 1, SDL_SWSURFACE);
659 
660   FREESURFACE(Main.map);
661   Main.map = SDL_DisplayFormat(Main.screen);
662 
663   if (Main.gui) {
664     FREESURFACE(Main.gui->surface);
665     Main.gui->surface = create_surf_alpha(Main.screen->w, Main.screen->h, SDL_SWSURFACE);
666   } else {
667     Main.gui = add_gui_layer(Main.screen->w, Main.screen->h);
668   }
669 
670   clear_surface(Main.gui->surface, NULL);
671 
672   return 0;
673 }
674 
675 /**************************************************************************
676                            Fill Rect with RGBA color
677 **************************************************************************/
678 #define MASK565	0xf7de
679 #define MASK555	0xfbde
680 
681 /* 50% alpha (128) */
682 #define BLEND16_50( d, s , mask )	\
683 	(((( s & mask ) + ( d & mask )) >> 1) + ( s & d & ( ~mask & 0xffff)))
684 
685 #define BLEND2x16_50( d, s , mask )	\
686 	(((( s & (mask | mask << 16)) + ( d & ( mask | mask << 16 ))) >> 1) + \
687 	( s & d & ( ~(mask | mask << 16))))
688 
689 #ifdef HAVE_MMX1
690 
691 /**************************************************************************
692   Fill rectangle for "555" format surface
693 **************************************************************************/
__FillRectAlpha555(SDL_Surface * pSurface,SDL_Rect * pRect,SDL_Color * pColor)694 static int __FillRectAlpha555(SDL_Surface * pSurface, SDL_Rect * pRect,
695 			      SDL_Color * pColor)
696 {
697   register Uint32 D, S =
698       SDL_MapRGB(pSurface->format, pColor->r, pColor->g, pColor->b);
699   register Uint32 A = pColor->unused >> 3;
700   Uint8 load[8];
701   Uint32 y, end;
702   Uint16 *start, *pixel;
703 
704   S &= 0xFFFF;
705 
706   *(Uint64 *)load = pColor->unused;
707   movq_m2r(*load, mm0); /* alpha -> mm0 */
708   punpcklwd_r2r(mm0, mm0); /* 00000A0A -> mm0 */
709   punpckldq_r2r(mm0, mm0); /* 0A0A0A0A -> mm0 */
710 
711   *(Uint64 *)load = S;
712   movq_m2r(*load, mm2); /* src(000000CL) -> mm2 */
713   punpcklwd_r2r(mm2, mm2); /* 0000CLCL -> mm2 */
714   punpckldq_r2r(mm2, mm2); /* CLCLCLCL -> mm2 */
715 
716   /* Setup the color channel masks */
717   *(Uint64 *)load = 0x7C007C007C007C00;
718   movq_m2r(*load, mm1); /* MASKRED -> mm1 */
719   *(Uint64 *)load = 0x03E003E003E003E0;
720   movq_m2r(*load, mm4); /* MASKGREEN -> mm4 */
721   *(Uint64 *)load = 0x001F001F001F001F;
722   movq_m2r(*load, mm7); /* MASKBLUE -> mm7 */
723 
724   lock_surf(pSurface);
725 
726   if (pRect == NULL) {
727     end = pSurface->w * pSurface->h;
728     pixel = (Uint16 *) pSurface->pixels;
729     if (A == 16) {		/* A == 128 >> 3 */
730       S = S | S << 16;
731       *(Uint64 *)load = MASK555;
732       movq_m2r(*load, mm0); /* mask(000000MS) -> mm0 */
733       punpcklwd_r2r(mm0, mm0); /* 0000MSMS -> mm0 */
734       punpcklwd_r2r(mm0, mm0); /* MSMSMSMS -> mm0 */
735       movq_r2r(mm0, mm1); /* mask -> mm1 */
736       *(Uint64 *)load = 0xFFFFFFFFFFFFFFFF;
737       movq_m2r(*load, mm7);
738       pxor_r2r(mm7, mm1); /* !mask -> mm1 */
739       DUFFS_LOOP_QUATRO2(
740       {
741 	D = *pixel;
742 	*pixel++ = BLEND16_50(D, (S & 0xFFFF), MASK555);
743       },{
744 	D = *(Uint32 *) pixel;
745 	*(Uint32 *) pixel = BLEND2x16_50(D, S, MASK555);
746 	pixel += 2;
747       },{
748 	movq_m2r((*pixel), mm3);/* load 4 dst pixels -> mm2 */
749 	movq_r2r(mm3, mm5); /* dst -> mm5 */
750 	movq_r2r(mm2, mm4); /* src -> mm4 */
751 
752 	pand_r2r(mm0, mm5); /* dst & mask -> mm1 */
753 	pand_r2r(mm0, mm4); /* src & mask -> mm4 */
754 	paddw_r2r(mm5, mm4); /* mm5 + mm4 -> mm4 */
755 	psrlq_i2r(1, mm4); /* mm4 >> 1 -> mm4 */
756 
757 	pand_r2r(mm2, mm3); /* src & dst -> mm3 */
758 	pand_r2r(mm1, mm3); /* mm3 & !mask -> mm3 */
759 	paddw_r2r(mm4, mm3); /* mm3 + mm4 -> mm4 */
760 	movq_r2m(mm3, (*pixel));/* mm3 -> 4 dst pixels */
761 	pixel += 4;
762       }, end);
763       emms();
764     } else {
765       S = (S | S << 16) & 0x03e07c1f;
766       DUFFS_LOOP_QUATRO2(
767       {
768 	D = *pixel;
769 	D = (D | D << 16) & 0x03e07c1f;
770 	D += (S - D) * A >> 5;
771 	D &= 0x03e07c1f;
772 	*pixel++ = (D | (D >> 16)) & 0xFFFF;
773       },{
774 	D = *pixel;
775 	D = (D | D << 16) & 0x03e07c1f;
776 	D += (S - D) * A >> 5;
777 	D &= 0x03e07c1f;
778 	*pixel++ = (D | (D >> 16)) & 0xFFFF;
779 	D = *pixel;
780 	D = (D | D << 16) & 0x03e07c1f;
781 	D += (S - D) * A >> 5;
782 	D &= 0x03e07c1f;
783 	*pixel++ = (D | (D >> 16)) & 0xFFFF;
784       },{
785 	movq_m2r((*pixel), mm3);/* load 4 dst pixels -> mm2 */
786 
787 	/* RED */
788 	movq_r2r(mm2, mm5); /* src -> mm5 */
789 	pand_r2r(mm1 , mm5); /* src & MASKRED -> mm5 */
790 	psrlq_i2r(10, mm5); /* mm5 >> 10 -> mm5 [000r 000r 000r 000r] */
791 
792 	movq_r2r(mm3, mm6); /* dst -> mm6 */
793 	pand_r2r(mm1 , mm6); /* dst & MASKRED -> mm6 */
794 	psrlq_i2r(10, mm6); /* mm6 >> 10 -> mm6 [000r 000r 000r 000r] */
795 
796 	/* blend */
797 	psubw_r2r(mm6, mm5);/* src - dst -> mm5 */
798 	pmullw_r2r(mm0, mm5); /* mm5 * alpha -> mm5 */
799 	psrlw_i2r(8, mm5); /* mm5 >> 8 -> mm5 */
800 	paddw_r2r(mm5, mm6); /* mm1 + mm2(dst) -> mm2 */
801 	psllq_i2r(10, mm6); /* mm6 << 10 -> mm6 */
802 	pand_r2r(mm1, mm6); /* mm6 & MASKRED -> mm6 */
803 
804 	movq_r2r(mm4, mm5); /* MASKGREEN -> mm5 */
805 	por_r2r(mm7, mm5);  /* MASKBLUE | mm5 -> mm5 */
806 	pand_r2r(mm5, mm3); /* mm3 & mm5(!MASKRED) -> mm3 */
807 	por_r2r(mm6, mm3);  /* save new reds in dsts */
808 
809 	/* green */
810 	movq_r2r(mm2, mm5); /* src -> mm5 */
811 	pand_r2r(mm4 , mm5); /* src & MASKGREEN -> mm5 */
812 	psrlq_i2r(5, mm5); /* mm5 >> 5 -> mm5 [000g 000g 000g 000g] */
813 
814 	movq_r2r(mm3, mm6); /* dst -> mm6 */
815 	pand_r2r(mm4 , mm6); /* dst & MASKGREEN -> mm6 */
816 	psrlq_i2r(5, mm6); /* mm6 >> 5 -> mm6 [000g 000g 000g 000g] */
817 
818 	/* blend */
819 	psubw_r2r(mm6, mm5);/* src - dst -> mm5 */
820 	pmullw_r2r(mm0, mm5); /* mm5 * alpha -> mm5 */
821 	psrlw_i2r(8, mm5); /* mm5 >> 8 -> mm5 */
822 	paddw_r2r(mm5, mm6); /* mm1 + mm2(dst) -> mm2 */
823 	psllq_i2r(5, mm6); /* mm6 << 5 -> mm6 */
824 	pand_r2r(mm4, mm6); /* mm6 & MASKGREEN -> mm6 */
825 
826 	movq_r2r(mm1, mm5); /* MASKRED -> mm5 */
827 	por_r2r(mm7, mm5);  /* MASKBLUE | mm5 -> mm5 */
828 	pand_r2r(mm5, mm3); /* mm3 & mm5(!MASKGREEN) -> mm3 */
829 	por_r2r(mm6, mm3); /* save new greens in dsts */
830 
831 	/* blue */
832 	movq_r2r(mm2, mm5); /* src -> mm5 */
833 	pand_r2r(mm7 , mm5); /* src & MASKRED -> mm5[000b 000b 000b 000b] */
834 
835 	movq_r2r(mm3, mm6); /* dst -> mm6 */
836 	pand_r2r(mm7 , mm6); /* dst & MASKBLUE -> mm6[000b 000b 000b 000b] */
837 
838 	/* blend */
839 	psubw_r2r(mm6, mm5);/* src - dst -> mm5 */
840 	pmullw_r2r(mm0, mm5); /* mm5 * alpha -> mm5 */
841 	psrlw_i2r(8, mm5); /* mm5 >> 8 -> mm5 */
842 	paddw_r2r(mm5, mm6); /* mm1 + mm2(dst) -> mm2 */
843 	pand_r2r(mm7, mm6); /* mm6 & MASKBLUE -> mm6 */
844 
845 	movq_r2r(mm1, mm5); /* MASKRED -> mm5 */
846 	por_r2r(mm4, mm5);  /* MASKGREEN | mm5 -> mm5 */
847 	pand_r2r(mm5, mm3); /* mm3 & mm5(!MASKBLUE) -> mm3 */
848 	por_r2r(mm6, mm3); /* save new blues in dsts */
849 
850 	movq_r2m(mm3, *pixel);/* mm2 -> 4 dst pixels */
851 
852 	pixel += 4;
853 
854       }, end);
855       emms();
856     }
857   } else {
858     /* correct pRect size */
859     if (pRect->x < 0) {
860       pRect->w += pRect->x;
861       pRect->x = 0;
862     } else {
863       if (pRect->x >= pSurface->w - pRect->w) {
864 	pRect->w = pSurface->w - pRect->x;
865       }
866     }
867 
868     if (pRect->y < 0) {
869       pRect->h += pRect->y;
870       pRect->y = 0;
871     } else {
872       if (pRect->y >= pSurface->h - pRect->h) {
873 	pRect->h = pSurface->h - pRect->y;
874       }
875     }
876 
877     start = pixel = (Uint16 *) pSurface->pixels +
878 	(pRect->y * (pSurface->pitch >> 1)) + pRect->x;
879 
880     if (A == 16) {		/* A == 128 >> 3 */
881       S = S | S << 16;
882       y = pRect->h;
883       end = pRect->w;
884       *(Uint64 *)load = MASK555;
885       movq_m2r(*load, mm0); /* mask(000000MS) -> mm0 */
886       punpcklwd_r2r(mm0, mm0); /* 0000MSMS -> mm0 */
887       punpcklwd_r2r(mm0, mm0); /* MSMSMSMS -> mm0 */
888       movq_r2r(mm0, mm1); /* mask -> mm1 */
889       pandn_r2r(mm1, mm1); /* !mask -> mm1 */
890       while(y--) {
891         DUFFS_LOOP_QUATRO2(
892         {
893 	  D = *pixel;
894  	  *pixel++ = BLEND16_50(D, (S & 0xFFFF), MASK555);
895         },{
896 	  D = *(Uint32 *) pixel;
897 	  *(Uint32 *) pixel = BLEND2x16_50(D, S, MASK555);
898 	  pixel += 2;
899         },{
900 	  movq_m2r((*pixel), mm3);/* load 4 dst pixels -> mm2 */
901 	  movq_r2r(mm3, mm5); /* dst -> mm5 */
902 	  movq_r2r(mm2, mm4); /* src -> mm4 */
903 
904 	  pand_r2r(mm0, mm5); /* dst & mask -> mm1 */
905 	  pand_r2r(mm0, mm4); /* src & mask -> mm4 */
906 	  paddd_r2r(mm5, mm4); /* mm5 + mm4 -> mm4 */ /*w*/
907 	  psrld_i2r(1, mm4); /* mm4 >> 1 -> mm4 */ /*q*/
908 
909 	  pand_r2r(mm2, mm3); /* src & dst -> mm3 */
910 	  pand_r2r(mm1, mm3); /* mm3 & !mask -> mm3 */
911 	  paddd_r2r(mm4, mm3); /* mm3 + mm4 -> mm4 */ /*w*/
912 	  movq_r2m(mm3, (*pixel));/* mm3 -> 4 dst pixels */
913 	  pixel += 4;
914         }, end);
915 	pixel = start + (pSurface->pitch >> 1);
916 	start = pixel;
917       }/* while */
918       emms();
919     } else {
920       S = (S | S << 16) & 0x03e07c1f;
921       y = pRect->h;
922       end = pRect->w;
923 
924       while (y--) {
925 	DUFFS_LOOP_QUATRO2(
926         {
927 	  D = *pixel;
928 	  D = (D | D << 16) & 0x03e07c1f;
929 	  D += (S - D) * A >> 5;
930 	  D &= 0x03e07c1f;
931 	  *pixel++ = (D | (D >> 16)) & 0xFFFF;
932         },{
933 	  D = *pixel;
934 	  D = (D | D << 16) & 0x03e07c1f;
935 	  D += (S - D) * A >> 5;
936 	  D &= 0x03e07c1f;
937 	  *pixel++ = (D | (D >> 16)) & 0xFFFF;
938 	  D = *pixel;
939 	  D = (D | D << 16) & 0x03e07c1f;
940 	  D += (S - D) * A >> 5;
941 	  D &= 0x03e07c1f;
942 	  *pixel++ = (D | (D >> 16)) & 0xFFFF;
943         },{
944 	  movq_m2r((*pixel), mm3);/* load 4 dst pixels -> mm2 */
945 
946 	  /* RED */
947 	  movq_r2r(mm2, mm5); /* src -> mm5 */
948 	  pand_r2r(mm1 , mm5); /* src & MASKRED -> mm5 */
949 	  psrlq_i2r(10, mm5); /* mm5 >> 10 -> mm5 [000r 000r 000r 000r] */
950 
951 	  movq_r2r(mm3, mm6); /* dst -> mm6 */
952 	  pand_r2r(mm1 , mm6); /* dst & MASKRED -> mm6 */
953 	  psrlq_i2r(10, mm6); /* mm6 >> 10 -> mm6 [000r 000r 000r 000r] */
954 
955 	  /* blend */
956 	  psubw_r2r(mm6, mm5);/* src - dst -> mm5 */
957 	  pmullw_r2r(mm0, mm5); /* mm5 * alpha -> mm5 */
958 	  psrlw_i2r(8, mm5); /* mm5 >> 8 -> mm5 */
959 	  paddw_r2r(mm5, mm6); /* mm1 + mm2(dst) -> mm2 */
960 	  psllq_i2r(10, mm6); /* mm6 << 10 -> mm6 */
961 	  pand_r2r(mm1, mm6); /* mm6 & MASKRED -> mm6 */
962 
963 	  movq_r2r(mm4, mm5); /* MASKGREEN -> mm5 */
964 	  por_r2r(mm7, mm5);  /* MASKBLUE | mm5 -> mm5 */
965 	  pand_r2r(mm5, mm3); /* mm3 & mm5(!MASKRED) -> mm3 */
966 	  por_r2r(mm6, mm3);  /* save new reds in dsts */
967 
968 	  /* green */
969 	  movq_r2r(mm2, mm5); /* src -> mm5 */
970 	  pand_r2r(mm4 , mm5); /* src & MASKGREEN -> mm5 */
971 	  psrlq_i2r(5, mm5); /* mm5 >> 5 -> mm5 [000g 000g 000g 000g] */
972 
973 	  movq_r2r(mm3, mm6); /* dst -> mm6 */
974 	  pand_r2r(mm4 , mm6); /* dst & MASKGREEN -> mm6 */
975 	  psrlq_i2r(5, mm6); /* mm6 >> 5 -> mm6 [000g 000g 000g 000g] */
976 
977 	  /* blend */
978 	  psubw_r2r(mm6, mm5);/* src - dst -> mm5 */
979 	  pmullw_r2r(mm0, mm5); /* mm5 * alpha -> mm5 */
980 	  psrlw_i2r(8, mm5); /* mm5 >> 8 -> mm5 */
981 	  paddw_r2r(mm5, mm6); /* mm1 + mm2(dst) -> mm2 */
982 	  psllq_i2r(5, mm6); /* mm6 << 5 -> mm6 */
983 	  pand_r2r(mm4, mm6); /* mm6 & MASKGREEN -> mm6 */
984 
985 	  movq_r2r(mm1, mm5); /* MASKRED -> mm5 */
986 	  por_r2r(mm7, mm5);  /* MASKBLUE | mm5 -> mm5 */
987 	  pand_r2r(mm5, mm3); /* mm3 & mm5(!MASKGREEN) -> mm3 */
988 	  por_r2r(mm6, mm3); /* save new greens in dsts */
989 
990 	  /* blue */
991 	  movq_r2r(mm2, mm5); /* src -> mm5 */
992 	  pand_r2r(mm7 , mm5); /* src & MASKRED -> mm5[000b 000b 000b 000b] */
993 
994 	  movq_r2r(mm3, mm6); /* dst -> mm6 */
995 	  pand_r2r(mm7 , mm6); /* dst & MASKBLUE -> mm6[000b 000b 000b 000b] */
996 
997 	  /* blend */
998 	  psubw_r2r(mm6, mm5);/* src - dst -> mm5 */
999 	  pmullw_r2r(mm0, mm5); /* mm5 * alpha -> mm5 */
1000 	  psrlw_i2r(8, mm5); /* mm5 >> 8 -> mm5 */
1001 	  paddw_r2r(mm5, mm6); /* mm1 + mm2(dst) -> mm2 */
1002 	  pand_r2r(mm7, mm6); /* mm6 & MASKBLUE -> mm6 */
1003 
1004 	  movq_r2r(mm1, mm5); /* MASKRED -> mm5 */
1005 	  por_r2r(mm4, mm5);  /* MASKGREEN | mm5 -> mm5 */
1006 	  pand_r2r(mm5, mm3); /* mm3 & mm5(!MASKBLUE) -> mm3 */
1007 	  por_r2r(mm6, mm3); /* save new blues in dsts */
1008 
1009 	  movq_r2m(mm3, *pixel);/* mm2 -> 4 dst pixels */
1010 
1011 	  pixel += 4;
1012 
1013         }, end);
1014 
1015         pixel = start + (pSurface->pitch >> 1);
1016         start = pixel;
1017       } /* while */
1018       emms();
1019     }
1020 
1021   }
1022 
1023   unlock_surf(pSurface);
1024   return 0;
1025 }
1026 
1027 /**************************************************************************
1028   Fill rectangle for "565" format surface
1029 **************************************************************************/
__FillRectAlpha565(SDL_Surface * pSurface,SDL_Rect * pRect,SDL_Color * pColor)1030 static int __FillRectAlpha565(SDL_Surface * pSurface, SDL_Rect * pRect,
1031 			      SDL_Color * pColor)
1032 {
1033   register Uint32 D, S =
1034       SDL_MapRGB(pSurface->format, pColor->r, pColor->g, pColor->b);
1035   register Uint32 A = pColor->unused >> 3;
1036   Uint8 load[8];
1037   Uint32 y, end;
1038   Uint16 *start, *pixel;
1039 
1040   S &= 0xFFFF;
1041 
1042   *(Uint64 *)load = pColor->unused;
1043   movq_m2r(*load, mm0); /* alpha -> mm0 */
1044   punpcklwd_r2r(mm0, mm0); /* 00000A0A -> mm0 */
1045   punpckldq_r2r(mm0, mm0); /* 0A0A0A0A -> mm0 */
1046 
1047   *(Uint64 *)load = S;
1048   movq_m2r(*load, mm2); /* src(000000CL) -> mm2 */
1049   punpcklwd_r2r(mm2, mm2); /* 0000CLCL -> mm2 */
1050   punpckldq_r2r(mm2, mm2); /* CLCLCLCL -> mm2 */
1051 
1052   /* Setup the color channel masks */
1053   *(Uint64 *)load = 0xF800F800F800F800;
1054   movq_m2r(*load, mm1); /* MASKRED -> mm1 */
1055   *(Uint64 *)load = 0x07E007E007E007E0;
1056   movq_m2r(*load, mm4); /* MASKGREEN -> mm4 */
1057   *(Uint64 *)load = 0x001F001F001F001F;
1058   movq_m2r(*load, mm7); /* MASKBLUE -> mm7 */
1059 
1060   lock_surf(pSurface);
1061 
1062   if (pRect == NULL) {
1063     end = pSurface->w * pSurface->h;
1064     pixel = (Uint16 *) pSurface->pixels;
1065     if (A == 16) {		/* A == 128 >> 3 */
1066       S = S | S << 16;
1067       *(Uint64 *)load = MASK565;
1068       movq_m2r(*load, mm0); /* mask(000000MS) -> mm0 */
1069       punpcklwd_r2r(mm0, mm0); /* 0000MSMS -> mm0 */
1070       punpcklwd_r2r(mm0, mm0); /* MSMSMSMS -> mm0 */
1071       movq_r2r(mm0, mm1); /* mask -> mm1 */
1072       *(Uint64 *)load = 0xFFFFFFFFFFFFFFFF;
1073       movq_m2r(*load, mm7);
1074       pxor_r2r(mm7, mm1); /* !mask -> mm1 */
1075       DUFFS_LOOP_QUATRO2(
1076       {
1077 	D = *pixel;
1078 	*pixel++ = BLEND16_50(D, (S & 0xFFFF), MASK565);
1079       },{
1080 	D = *(Uint32 *) pixel;
1081 	*(Uint32 *) pixel = BLEND2x16_50(D, S, MASK565);
1082 	pixel += 2;
1083       },{
1084 	movq_m2r((*pixel), mm3);/* load 4 dst pixels -> mm2 */
1085 	movq_r2r(mm3, mm5); /* dst -> mm5 */
1086 	movq_r2r(mm2, mm4); /* src -> mm4 */
1087 
1088 	pand_r2r(mm0, mm5); /* dst & mask -> mm1 */
1089 	pand_r2r(mm0, mm4); /* src & mask -> mm4 */
1090 	paddw_r2r(mm5, mm4); /* mm5 + mm4 -> mm4 */
1091 	psrlq_i2r(1, mm4); /* mm4 >> 1 -> mm4 */
1092 
1093 	pand_r2r(mm2, mm3); /* src & dst -> mm3 */
1094 	pand_r2r(mm1, mm3); /* mm3 & !mask -> mm3 */
1095 	paddw_r2r(mm4, mm3); /* mm3 + mm4 -> mm4 */
1096 	movq_r2m(mm3, (*pixel));/* mm3 -> 4 dst pixels */
1097 	pixel += 4;
1098       }, end);
1099       emms();
1100     } else {
1101       S = (S | S << 16) & 0x07e0f81f;
1102       DUFFS_LOOP_QUATRO2(
1103       {
1104 	D = *pixel;
1105 	D = (D | D << 16) & 0x07e0f81f;
1106 	D += (S - D) * A >> 5;
1107 	D &= 0x07e0f81f;
1108 	*pixel++ = (D | (D >> 16)) & 0xFFFF;
1109       },{
1110 	D = *pixel;
1111 	D = (D | D << 16) & 0x07e0f81f;
1112 	D += (S - D) * A >> 5;
1113 	D &= 0x07e0f81f;
1114 	*pixel++ = (D | (D >> 16)) & 0xFFFF;
1115 	D = *pixel;
1116 	D = (D | D << 16) & 0x07e0f81f;
1117 	D += (S - D) * A >> 5;
1118 	D &= 0x07e0f81f;
1119 	*pixel++ = (D | (D >> 16)) & 0xFFFF;
1120       },{
1121 	movq_m2r((*pixel), mm3);/* load 4 dst pixels -> mm2 */
1122 
1123 	/* RED */
1124 	movq_r2r(mm2, mm5); /* src -> mm5 */
1125 	pand_r2r(mm1 , mm5); /* src & MASKRED -> mm5 */
1126 	psrlq_i2r(11, mm5); /* mm5 >> 11 -> mm5 [000r 000r 000r 000r] */
1127 
1128 	movq_r2r(mm3, mm6); /* dst -> mm6 */
1129 	pand_r2r(mm1 , mm6); /* dst & MASKRED -> mm6 */
1130 	psrlq_i2r(11, mm6); /* mm6 >> 11 -> mm6 [000r 000r 000r 000r] */
1131 
1132 	/* blend */
1133 	psubw_r2r(mm6, mm5);/* src - dst -> mm5 */
1134 	pmullw_r2r(mm0, mm5); /* mm5 * alpha -> mm5 */
1135 	psrlw_i2r(8, mm5); /* mm5 >> 8 -> mm5 */
1136 	paddw_r2r(mm5, mm6); /* mm1 + mm2(dst) -> mm2 */
1137 	psllq_i2r(11, mm6); /* mm6 << 11 -> mm6 */
1138 	pand_r2r(mm1, mm6); /* mm6 & MASKRED -> mm6 */
1139 
1140 	movq_r2r(mm4, mm5); /* MASKGREEN -> mm5 */
1141 	por_r2r(mm7, mm5);  /* MASKBLUE | mm5 -> mm5 */
1142 	pand_r2r(mm5, mm3); /* mm3 & mm5(!MASKRED) -> mm3 */
1143 	por_r2r(mm6, mm3);  /* save new reds in dsts */
1144 
1145 	/* green */
1146 	movq_r2r(mm2, mm5); /* src -> mm5 */
1147 	pand_r2r(mm4 , mm5); /* src & MASKGREEN -> mm5 */
1148 	psrlq_i2r(5, mm5); /* mm5 >> 5 -> mm5 [000g 000g 000g 000g] */
1149 
1150 	movq_r2r(mm3, mm6); /* dst -> mm6 */
1151 	pand_r2r(mm4 , mm6); /* dst & MASKGREEN -> mm6 */
1152 	psrlq_i2r(5, mm6); /* mm6 >> 5 -> mm6 [000g 000g 000g 000g] */
1153 
1154 	/* blend */
1155 	psubw_r2r(mm6, mm5);/* src - dst -> mm5 */
1156 	pmullw_r2r(mm0, mm5); /* mm5 * alpha -> mm5 */
1157 	psrlw_i2r(8, mm5); /* mm5 >> 8 -> mm5 */
1158 	paddw_r2r(mm5, mm6); /* mm1 + mm2(dst) -> mm2 */
1159 	psllq_i2r(5, mm6); /* mm6 << 5 -> mm6 */
1160 	pand_r2r(mm4, mm6); /* mm6 & MASKGREEN -> mm6 */
1161 
1162 	movq_r2r(mm1, mm5); /* MASKRED -> mm5 */
1163 	por_r2r(mm7, mm5);  /* MASKBLUE | mm5 -> mm5 */
1164 	pand_r2r(mm5, mm3); /* mm3 & mm5(!MASKGREEN) -> mm3 */
1165 	por_r2r(mm6, mm3); /* save new greens in dsts */
1166 
1167 	/* blue */
1168 	movq_r2r(mm2, mm5); /* src -> mm5 */
1169 	pand_r2r(mm7 , mm5); /* src & MASKRED -> mm5[000b 000b 000b 000b] */
1170 
1171 	movq_r2r(mm3, mm6); /* dst -> mm6 */
1172 	pand_r2r(mm7 , mm6); /* dst & MASKBLUE -> mm6[000b 000b 000b 000b] */
1173 
1174 	/* blend */
1175 	psubw_r2r(mm6, mm5);/* src - dst -> mm5 */
1176 	pmullw_r2r(mm0, mm5); /* mm5 * alpha -> mm5 */
1177 	psrlw_i2r(8, mm5); /* mm5 >> 8 -> mm5 */
1178 	paddw_r2r(mm5, mm6); /* mm1 + mm2(dst) -> mm2 */
1179 	pand_r2r(mm7, mm6); /* mm6 & MASKBLUE -> mm6 */
1180 
1181 	movq_r2r(mm1, mm5); /* MASKRED -> mm5 */
1182 	por_r2r(mm4, mm5);  /* MASKGREEN | mm5 -> mm5 */
1183 	pand_r2r(mm5, mm3); /* mm3 & mm5(!MASKBLUE) -> mm3 */
1184 	por_r2r(mm6, mm3); /* save new blues in dsts */
1185 
1186 	movq_r2m(mm3, *pixel);/* mm2 -> 4 dst pixels */
1187 
1188 	pixel += 4;
1189 
1190       }, end);
1191       emms();
1192     }
1193   } else {
1194     /* correct pRect size */
1195     if (pRect->x < 0) {
1196       pRect->w += pRect->x;
1197       pRect->x = 0;
1198     } else {
1199       if (pRect->x >= pSurface->w - pRect->w) {
1200 	pRect->w = pSurface->w - pRect->x;
1201       }
1202     }
1203 
1204     if (pRect->y < 0) {
1205       pRect->h += pRect->y;
1206       pRect->y = 0;
1207     } else {
1208       if (pRect->y >= pSurface->h - pRect->h) {
1209 	pRect->h = pSurface->h - pRect->y;
1210       }
1211     }
1212 
1213     start = pixel = (Uint16 *) pSurface->pixels +
1214 	(pRect->y * (pSurface->pitch >> 1)) + pRect->x;
1215 
1216     if (A == 16) {		/* A == 128 >> 3 */
1217       S = S | S << 16;
1218       y = pRect->h;
1219       end = pRect->w;
1220       *(Uint64 *)load = MASK565;
1221       movq_m2r(*load, mm0); /* mask(000000MS) -> mm0 */
1222       punpcklwd_r2r(mm0, mm0); /* 0000MSMS -> mm0 */
1223       punpcklwd_r2r(mm0, mm0); /* MSMSMSMS -> mm0 */
1224       movq_r2r(mm0, mm1); /* mask -> mm1 */
1225       pandn_r2r(mm1, mm1); /* !mask -> mm1 */
1226       while(y--) {
1227         DUFFS_LOOP_QUATRO2(
1228         {
1229 	  D = *pixel;
1230  	  *pixel++ = BLEND16_50(D, (S & 0xFFFF), MASK565);
1231         },{
1232 	  D = *(Uint32 *) pixel;
1233 	  *(Uint32 *) pixel = BLEND2x16_50(D, S, MASK565);
1234 	  pixel += 2;
1235         },{
1236 	  movq_m2r((*pixel), mm3);/* load 4 dst pixels -> mm2 */
1237 	  movq_r2r(mm3, mm5); /* dst -> mm5 */
1238 	  movq_r2r(mm2, mm4); /* src -> mm4 */
1239 
1240 	  pand_r2r(mm0, mm5); /* dst & mask -> mm1 */
1241 	  pand_r2r(mm0, mm4); /* src & mask -> mm4 */
1242 	  paddd_r2r(mm5, mm4); /* mm5 + mm4 -> mm4 */ /*w*/
1243 	  psrld_i2r(1, mm4); /* mm4 >> 1 -> mm4 */ /*q*/
1244 
1245 	  pand_r2r(mm2, mm3); /* src & dst -> mm3 */
1246 	  pand_r2r(mm1, mm3); /* mm3 & !mask -> mm3 */
1247 	  paddd_r2r(mm4, mm3); /* mm3 + mm4 -> mm4 */ /*w*/
1248 	  movq_r2m(mm3, (*pixel));/* mm3 -> 4 dst pixels */
1249 	  pixel += 4;
1250         }, end);
1251 	pixel = start + (pSurface->pitch >> 1);
1252 	start = pixel;
1253       }/* while */
1254       emms();
1255     } else {
1256       S = (S | S << 16) & 0x07e0f81f;
1257       y = pRect->h;
1258       end = pRect->w;
1259 
1260       while(y--) {
1261 	DUFFS_LOOP_QUATRO2(
1262         {
1263 	  D = *pixel;
1264 	  D = (D | D << 16) & 0x07e0f81f;
1265 	  D += (S - D) * A >> 5;
1266 	  D &= 0x07e0f81f;
1267 	  *pixel++ = (D | (D >> 16)) & 0xFFFF;
1268         },{
1269 	  D = *pixel;
1270 	  D = (D | D << 16) & 0x07e0f81f;
1271 	  D += (S - D) * A >> 5;
1272 	  D &= 0x07e0f81f;
1273 	  *pixel++ = (D | (D >> 16)) & 0xFFFF;
1274 	  D = *pixel;
1275 	  D = (D | D << 16) & 0x07e0f81f;
1276 	  D += (S - D) * A >> 5;
1277 	  D &= 0x07e0f81f;
1278 	  *pixel++ = (D | (D >> 16)) & 0xFFFF;
1279         },{
1280 	  movq_m2r((*pixel), mm3);/* load 4 dst pixels -> mm2 */
1281 
1282 	  /* RED */
1283 	  movq_r2r(mm2, mm5); /* src -> mm5 */
1284 	  pand_r2r(mm1 , mm5); /* src & MASKRED -> mm5 */
1285 	  psrlq_i2r(11, mm5); /* mm5 >> 11 -> mm5 [000r 000r 000r 000r] */
1286 
1287 	  movq_r2r(mm3, mm6); /* dst -> mm6 */
1288 	  pand_r2r(mm1 , mm6); /* dst & MASKRED -> mm6 */
1289 	  psrlq_i2r(11, mm6); /* mm6 >> 11 -> mm6 [000r 000r 000r 000r] */
1290 
1291 	  /* blend */
1292 	  psubw_r2r(mm6, mm5);/* src - dst -> mm5 */
1293 	  pmullw_r2r(mm0, mm5); /* mm5 * alpha -> mm5 */
1294 	  psrlw_i2r(8, mm5); /* mm5 >> 8 -> mm5 */
1295 	  paddw_r2r(mm5, mm6); /* mm1 + mm2(dst) -> mm2 */
1296 	  psllq_i2r(11, mm6); /* mm6 << 11 -> mm6 */
1297 	  pand_r2r(mm1, mm6); /* mm6 & MASKRED -> mm6 */
1298 
1299 	  movq_r2r(mm4, mm5); /* MASKGREEN -> mm5 */
1300 	  por_r2r(mm7, mm5);  /* MASKBLUE | mm5 -> mm5 */
1301 	  pand_r2r(mm5, mm3); /* mm3 & mm5(!MASKRED) -> mm3 */
1302 	  por_r2r(mm6, mm3);  /* save new reds in dsts */
1303 
1304 	  /* green */
1305 	  movq_r2r(mm2, mm5); /* src -> mm5 */
1306 	  pand_r2r(mm4 , mm5); /* src & MASKGREEN -> mm5 */
1307 	  psrlq_i2r(5, mm5); /* mm5 >> 11 -> mm5 [000g 000g 000g 000g] */
1308 
1309 	  movq_r2r(mm3, mm6); /* dst -> mm6 */
1310 	  pand_r2r(mm4 , mm6); /* dst & MASKGREEN -> mm6 */
1311 	  psrlq_i2r(5, mm6); /* mm6 >> 11 -> mm6 [000g 000g 000g 000g] */
1312 
1313 	  /* blend */
1314 	  psubw_r2r(mm6, mm5);/* src - dst -> mm5 */
1315 	  pmullw_r2r(mm0, mm5); /* mm5 * alpha -> mm5 */
1316 	  psrlw_i2r(8, mm5); /* mm5 >> 8 -> mm5 */
1317 	  paddw_r2r(mm5, mm6); /* mm1 + mm2(dst) -> mm2 */
1318 	  psllq_i2r(5, mm6); /* mm6 << 5 -> mm6 */
1319 	  pand_r2r(mm4, mm6); /* mm6 & MASKGREEN -> mm6 */
1320 
1321 	  movq_r2r(mm1, mm5); /* MASKRED -> mm5 */
1322 	  por_r2r(mm7, mm5);  /* MASKBLUE | mm5 -> mm5 */
1323 	  pand_r2r(mm5, mm3); /* mm3 & mm5(!MASKGREEN) -> mm3 */
1324 	  por_r2r(mm6, mm3); /* save new greens in dsts */
1325 
1326 	  /* blue */
1327 	  movq_r2r(mm2, mm5); /* src -> mm5 */
1328 	  pand_r2r(mm7 , mm5); /* src & MASKRED -> mm5[000b 000b 000b 000b] */
1329 
1330 	  movq_r2r(mm3, mm6); /* dst -> mm6 */
1331 	  pand_r2r(mm7 , mm6); /* dst & MASKBLUE -> mm6[000b 000b 000b 000b] */
1332 
1333 	  /* blend */
1334 	  psubw_r2r(mm6, mm5);/* src - dst -> mm5 */
1335 	  pmullw_r2r(mm0, mm5); /* mm5 * alpha -> mm5 */
1336 	  psrlw_i2r(8, mm5); /* mm5 >> 8 -> mm5 */
1337 	  paddw_r2r(mm5, mm6); /* mm1 + mm2(dst) -> mm2 */
1338 	  pand_r2r(mm7, mm6); /* mm6 & MASKBLUE -> mm6 */
1339 
1340 	  movq_r2r(mm1, mm5); /* MASKRED -> mm5 */
1341 	  por_r2r(mm4, mm5);  /* MASKGREEN | mm5 -> mm5 */
1342 	  pand_r2r(mm5, mm3); /* mm3 & mm5(!MASKBLUE) -> mm3 */
1343 	  por_r2r(mm6, mm3); /* save new blues in dsts */
1344 
1345 	  movq_r2m(mm3, *pixel);/* mm2 -> 4 dst pixels */
1346 
1347 	  pixel += 4;
1348 
1349         }, end);
1350 
1351         pixel = start + (pSurface->pitch >> 1);
1352         start = pixel;
1353       } /* while */
1354       emms();
1355     }
1356 
1357   }
1358 
1359   unlock_surf(pSurface);
1360   return 0;
1361 }
1362 
1363 /**************************************************************************
1364   Fill rectangle for 32bit "888" format surface
1365 **************************************************************************/
__FillRectAlpha888_32bit(SDL_Surface * pSurface,SDL_Rect * pRect,SDL_Color * pColor)1366 static int __FillRectAlpha888_32bit(SDL_Surface * pSurface, SDL_Rect * pRect,
1367 			       SDL_Color * pColor)
1368 {
1369   Uint8 load[8] = {pColor->unused, pColor->unused,
1370 		    pColor->unused, pColor->unused,
1371     			pColor->unused, pColor->unused,
1372 			pColor->unused, pColor->unused};
1373   Uint32 A = pColor->unused;
1374   register Uint32 sSIMD2 = SDL_MapRGB(pSurface->format,
1375 					    pColor->r, pColor->g,
1376 					    pColor->b);
1377   Uint32 y, end;
1378   Uint32 *start, *pixel;
1379 
1380 
1381   movq_m2r(*load, mm4); /* alpha -> mm4 */
1382 
1383   *(Uint64 *)load = 0x00FF00FF00FF00FF;
1384   movq_m2r(*load, mm3); /* mask -> mm2 */
1385 
1386   pand_r2r(mm3, mm4); /* mm4 & mask -> 0A0A0A0A -> mm4 */
1387 
1388   *(Uint64 *)load = sSIMD2;
1389   movq_m2r(*load, mm5); /* src(0000ARGB) -> mm5 */
1390   movq_r2r(mm5, mm1); /* src(0000ARGB) -> mm1 (fot alpha 128 blits) */
1391   punpcklbw_r2r(mm5, mm5); /* AARRGGBB -> mm5 */
1392   pand_r2r(mm3, mm5); /* 0A0R0G0B -> mm5 */
1393 
1394   *(Uint64 *)load = 0xFF000000FF000000;/* dst alpha mask */
1395   movq_m2r(*load, mm7); /* dst alpha mask -> mm7 */
1396 
1397   lock_surf(pSurface);
1398 
1399   if (pRect == NULL) {
1400     end = pSurface->w * pSurface->h;
1401     pixel = (Uint32 *) pSurface->pixels;
1402     if (A == 128) {		/* 50% A */
1403       *(Uint64 *)load = 0x00fefefe00fefefe;/* alpha128 mask */
1404       movq_m2r(*load, mm4); /* alpha128 mask -> mm4 */
1405       *(Uint64 *)load = 0x0001010100010101;/* alpha128 mask */
1406       movq_m2r(*load, mm3); /* !alpha128 mask -> mm3 */
1407       punpckldq_r2r(mm1, mm1); /* mm1(0000ARGB) -> mm1(ARGBARGB) */
1408       DUFFS_LOOP_DOUBLE2(
1409       {
1410 	A = *pixel;
1411 	*pixel++ = ((((sSIMD2 & 0x00fefefe) + (A & 0x00fefefe)) >> 1)
1412 		    + (sSIMD2 & A & 0x00010101)) | 0xFF000000;
1413       },{
1414 	movq_m2r((*pixel), mm2);/* dst(ARGBARGB) -> mm2 */
1415 	movq_r2r(mm2, mm6); /* dst(ARGBARGB) -> mm6 */
1416 	movq_r2r(mm1, mm5); /* src(ARGBARGB) -> mm5 */
1417 
1418 	pand_r2r(mm4, mm6); /* dst & mask -> mm1 */
1419 	pand_r2r(mm4, mm5); /* src & mask -> mm4 */
1420 	paddw_r2r(mm6, mm5); /* mm5 + mm4 -> mm4 */
1421 	psrlq_i2r(1, mm5); /* mm4 >> 1 -> mm4 */
1422 
1423 	pand_r2r(mm1, mm2); /* src & dst -> mm2 */
1424 	pand_r2r(mm3, mm2); /* mm2 & !mask -> mm2 */
1425 	paddw_r2r(mm5, mm2); /* mm5 + mm2 -> mm2 */
1426 	por_r2r(mm7, mm2); /* mm7(dst alpha mask) | mm2 -> mm2 */
1427 	movq_r2m(mm2, (*pixel));/* mm2 -> 2 dst pixels */
1428 	pixel += 2;
1429 
1430       }, end);
1431       emms();
1432     } else {
1433       DUFFS_LOOP_DOUBLE2(
1434       {
1435 	movq_r2r(mm5, mm1); /* src(0A0R0G0B) -> mm1 */
1436 
1437 	movd_m2r((*pixel), mm2);/* dst(ARGB) -> mm2 (0000ARGB)*/
1438         punpcklbw_r2r(mm2, mm2); /* AARRGGBB -> mm2 */
1439         pand_r2r(mm3, mm2); /* 0A0R0G0B -> mm2 */
1440 
1441         psubw_r2r(mm2, mm1);/* src - dst -> mm1 */
1442 	pmullw_r2r(mm4, mm1); /* mm1 * alpha -> mm1 */
1443 	psrlw_i2r(8, mm1); /* mm1 >> 8 -> mm1 */
1444 	paddw_r2r(mm1, mm2); /* mm1 + mm2(dst) -> mm2 */
1445 	pand_r2r(mm3, mm2); /* 0A0R0G0B -> mm2 */
1446 	packuswb_r2r(mm2, mm2);  /* ARGBARGB -> mm2 */
1447         por_r2r(mm7, mm2); /* mm7(dst alpha mask) | mm2 -> mm2 */
1448 	movd_r2m(mm2, *pixel);/* mm2 -> pixel */
1449 	pixel++;
1450       }, {
1451 	movq_r2r(mm5, mm1); /* src(0A0R0G0B) -> mm1 */
1452 	movq_r2r(mm5, mm0); /* src(0A0R0G0B) -> mm0 */
1453 
1454 	movq_m2r((*pixel), mm2);/* dst(ARGBARGB) -> mm2 */
1455 	movq_r2r(mm2, mm6); /* dst(ARGBARGB) -> mm1 */
1456         punpcklbw_r2r(mm2, mm2); /* low - AARRGGBB -> mm2 */
1457 	punpckhbw_r2r(mm6, mm6); /* high - AARRGGBB -> mm6 */
1458         pand_r2r(mm3, mm2); /* 0A0R0G0B -> mm2 */
1459 	pand_r2r(mm3, mm6); /* 0A0R0G0B -> mm6 */
1460 
1461         psubw_r2r(mm2, mm1);/* src - dst1 -> mm1 */
1462 	psubw_r2r(mm6, mm0);/* src - dst2 -> mm0 */
1463 
1464 	pmullw_r2r(mm4, mm1); /* mm1 * alpha -> mm1 */
1465 	pmullw_r2r(mm4, mm0); /* mm0 * alpha -> mm0 */
1466 	psrlw_i2r(8, mm1); /* mm1 >> 8 -> mm1 */
1467 	psrlw_i2r(8, mm0); /* mm0 >> 8 -> mm0 */
1468 	paddw_r2r(mm1, mm2); /* mm1 + mm2(dst) -> mm2 */
1469 	paddw_r2r(mm0, mm6); /* mm0 + mm6(dst) -> mm6 */
1470 	pand_r2r(mm3, mm2); /* 0A0R0G0B -> mm2 */
1471 	pand_r2r(mm3, mm6); /* 0A0R0G0B -> mm6 */
1472 	packuswb_r2r(mm2, mm2);  /* ARGBARGB -> mm2 */
1473 	packuswb_r2r(mm6, mm6);  /* ARGBARGB -> mm6 */
1474 	psrlq_i2r(32, mm2); /* mm2 >> 32 -> mm2 */
1475 	psllq_i2r(32, mm6); /* mm6 << 32 -> mm6 */
1476 	por_r2r(mm6, mm2); /* mm6 | mm2 -> mm2 */
1477 	por_r2r(mm7, mm2); /* mm7(dst alpha mask) | mm2 -> mm2 */
1478         movq_r2m(mm2, *pixel);/* mm2 -> pixel */
1479 	pixel += 2;
1480       },end);
1481       emms();
1482     } /* A != 128 */
1483   } else {
1484     /* correct pRect size */
1485     if (pRect->x < 0) {
1486       pRect->w += pRect->x;
1487       pRect->x = 0;
1488     } else {
1489       if (pRect->x >= pSurface->w - pRect->w) {
1490 	pRect->w = pSurface->w - pRect->x;
1491       }
1492     }
1493 
1494     if (pRect->y < 0) {
1495       pRect->h += pRect->y;
1496       pRect->y = 0;
1497     } else {
1498       if (pRect->y >= pSurface->h - pRect->h) {
1499 	pRect->h = pSurface->h - pRect->y;
1500       }
1501     }
1502 
1503     start = pixel = (Uint32 *) pSurface->pixels +
1504 	(pRect->y * (pSurface->pitch >> 2)) + pRect->x;
1505 
1506     if (A == 128) {		/* 50% A */
1507       *(Uint64 *)load = 0x00fefefe00fefefe;/* alpha128 mask */
1508       movq_m2r(*load, mm4); /* alpha128 mask -> mm4 */
1509       *(Uint64 *)load = 0x0001010100010101;/* alpha128 mask */
1510       movq_m2r(*load, mm3); /* !alpha128 mask -> mm3 */
1511       punpckldq_r2r(mm1, mm1); /* mm1(0000ARGB) -> mm1(ARGBARGB) */
1512       y = pRect->h;
1513       end = pRect->w;
1514       while(y--) {
1515         DUFFS_LOOP_DOUBLE2(
1516         {
1517 	  A = *pixel;
1518 	  *pixel++ = ((((sSIMD2 & 0x00fefefe) + (A & 0x00fefefe)) >> 1)
1519 		    + (sSIMD2 & A & 0x00010101)) | 0xFF000000;
1520         },{
1521 	  movq_m2r((*pixel), mm2);/* dst(ARGBARGB) -> mm2 */
1522 	  movq_r2r(mm2, mm6); /* dst(ARGBARGB) -> mm6 */
1523 	  movq_r2r(mm1, mm5); /* src(ARGBARGB) -> mm5 */
1524 
1525 	  pand_r2r(mm4, mm6); /* dst & mask -> mm1 */
1526 	  pand_r2r(mm4, mm5); /* src & mask -> mm4 */
1527 	  paddd_r2r(mm6, mm5); /* mm5 + mm4 -> mm4 */
1528 	  psrld_i2r(1, mm5); /* mm4 >> 1 -> mm4 */
1529 
1530 	  pand_r2r(mm1, mm2); /* src & dst -> mm2 */
1531 	  pand_r2r(mm3, mm2); /* mm2 & !mask -> mm2 */
1532 	  paddd_r2r(mm5, mm2); /* mm5 + mm2 -> mm2 */
1533 	  por_r2r(mm7, mm2); /* mm7(dst alpha mask) | mm2 -> mm2 */
1534 	  movq_r2m(mm2, (*pixel));/* mm2 -> 2 dst pixels */
1535 	  pixel += 2;
1536 
1537         }, end);
1538 	pixel = start + (pSurface->pitch >> 2);
1539 	start = pixel;
1540       }/* while */
1541       emms();
1542 
1543     } else {
1544       y = pRect->h;
1545       end = pRect->w;
1546 
1547       while(y--) {
1548 	DUFFS_LOOP_DOUBLE2(
1549         {
1550           movq_r2r(mm5, mm1); /* src(0A0R0G0B) -> mm1 */
1551 
1552 	  movd_m2r((*pixel), mm2);/* dst(ARGB) -> mm2 (0000ARGB)*/
1553           punpcklbw_r2r(mm2, mm2); /* AARRGGBB -> mm2 */
1554           pand_r2r(mm3, mm2); /* 0A0R0G0B -> mm2 */
1555 
1556           psubw_r2r(mm2, mm1);/* src - dst -> mm1 */
1557 	  pmullw_r2r(mm4, mm1); /* mm1 * alpha -> mm1 */
1558 	  psrlw_i2r(8, mm1); /* mm1 >> 8 -> mm1 */
1559 	  paddw_r2r(mm1, mm2); /* mm1 + mm2(dst) -> mm2 */
1560 	  pand_r2r(mm3, mm2); /* 0A0R0G0B -> mm2 */
1561 	  packuswb_r2r(mm2, mm2);  /* ARGBARGB -> mm2 */
1562 	  por_r2r(mm7, mm2); /* mm7(dst alpha mask) | mm2 -> mm2 */
1563 	  movd_r2m(mm2, *pixel);/* mm2 -> pixel */
1564 	  pixel++;
1565         }, {
1566 	  movq_r2r(mm5, mm1); /* src(0A0R0G0B) -> mm1 */
1567 	  movq_r2r(mm5, mm0); /* src(0A0R0G0B) -> mm0 */
1568 
1569 	  movq_m2r((*pixel), mm2);/* dst(ARGBARGB) -> mm2 */
1570 	  movq_r2r(mm2, mm6); /* dst(ARGBARGB) -> mm1 */
1571           punpcklbw_r2r(mm2, mm2); /* low - AARRGGBB -> mm2 */
1572 	  punpckhbw_r2r(mm6, mm6); /* high - AARRGGBB -> mm6 */
1573           pand_r2r(mm3, mm2); /* 0A0R0G0B -> mm2 */
1574 	  pand_r2r(mm3, mm6); /* 0A0R0G0B -> mm6 */
1575 
1576           psubw_r2r(mm2, mm1);/* src - dst1 -> mm1 */
1577 	  psubw_r2r(mm6, mm0);/* src - dst2 -> mm0 */
1578 
1579 	  pmullw_r2r(mm4, mm1); /* mm1 * alpha -> mm1 */
1580 	  pmullw_r2r(mm4, mm0); /* mm0 * alpha -> mm0 */
1581 	  psrlw_i2r(8, mm1); /* mm1 >> 8 -> mm1 */
1582 	  psrlw_i2r(8, mm0); /* mm0 >> 8 -> mm0 */
1583 	  paddw_r2r(mm1, mm2); /* mm1 + mm2(dst) -> mm2 */
1584 	  paddw_r2r(mm0, mm6); /* mm0 + mm6(dst) -> mm6 */
1585 	  pand_r2r(mm3, mm2); /* 0A0R0G0B -> mm2 */
1586 	  pand_r2r(mm3, mm6); /* 0A0R0G0B -> mm6 */
1587 	  packuswb_r2r(mm2, mm2);  /* ARGBARGB -> mm2 */
1588 	  packuswb_r2r(mm6, mm6);  /* ARGBARGB -> mm6 */
1589 	  psrlq_i2r(32, mm2); /* mm2 >> 32 -> mm2 */
1590 	  psllq_i2r(32, mm6); /* mm6 << 32 -> mm6 */
1591 	  por_r2r(mm6, mm2); /* mm6 | mm2 -> mm2 */
1592 	  por_r2r(mm7, mm2); /* mm7(dst alpha mask) | mm2 -> mm2 */
1593           movq_r2m(mm2, *pixel);/* mm2 -> pixel */
1594 	  pixel += 2;
1595 	}, end);
1596 
1597 	pixel = start + (pSurface->pitch >> 2);
1598 	start = pixel;
1599       } /* while */
1600       emms();
1601     }
1602   }
1603 
1604   unlock_surf(pSurface);
1605   return 0;
1606 }
1607 
1608 /**************************************************************************
1609   Fill rectangle for 32bit "8888" format surface
1610 **************************************************************************/
__FillRectAlpha8888_32bit(SDL_Surface * pSurface,SDL_Rect * pRect,SDL_Color * pColor)1611 static int __FillRectAlpha8888_32bit(SDL_Surface * pSurface, SDL_Rect * pRect,
1612 			       SDL_Color * pColor)
1613 {
1614   Uint8 load[8] = {pColor->unused, pColor->unused,
1615 		    pColor->unused, pColor->unused,
1616     			pColor->unused, pColor->unused,
1617 			pColor->unused, pColor->unused};
1618   Uint32 A = pColor->unused;
1619   Uint32 sSIMD2 = SDL_MapRGB(pSurface->format,
1620 					    pColor->r, pColor->g,
1621 					    pColor->b);
1622   Uint32 y, end, A_Dst, A_Mask = pSurface->format->Amask;
1623   Uint32 *start, *pixel;
1624 
1625   lock_surf(pSurface);
1626 
1627   movq_m2r(*load, mm4); /* alpha -> mm4 */
1628 
1629   *(Uint64 *)load = 0x00FF00FF00FF00FF;
1630   movq_m2r(*load, mm3); /* mask -> mm2 */
1631 
1632   pand_r2r(mm3, mm4); /* mm4 & mask -> 0A0A0A0A -> mm4 */
1633 
1634   *(Uint64 *)load = sSIMD2;
1635   movq_m2r(*load, mm5); /* src(0000ARGB) -> mm5 */
1636   movq_r2r(mm5, mm1); /* src(0000ARGB) -> mm1 (fot alpha 128 blits) */
1637   punpcklbw_r2r(mm5, mm5); /* AARRGGBB -> mm5 */
1638   pand_r2r(mm3, mm5); /* 0A0R0G0B -> mm5 */
1639 
1640   *(Uint64 *)load = 0xFF000000FF000000;/* dst alpha mask */
1641   movq_m2r(*load, mm7); /* dst alpha mask -> mm7 */
1642 
1643 
1644   if (pRect == NULL) {
1645     end = pSurface->w * pSurface->h;
1646     pixel = (Uint32 *) pSurface->pixels;
1647     if (A == 128) {		/* 50% A */
1648       *(Uint64 *)load = 0x00fefefe00fefefe;/* alpha128 mask */
1649       movq_m2r(*load, mm4); /* alpha128 mask -> mm4 */
1650       *(Uint64 *)load = 0x0001010100010101;/* alpha128 mask */
1651       movq_m2r(*load, mm3); /* !alpha128 mask -> mm3 */
1652       punpckldq_r2r(mm1, mm1); /* mm1(0000ARGB) -> mm1(ARGBARGB) */
1653       DUFFS_LOOP_DOUBLE2(
1654       {
1655 	A = *pixel;
1656 	A_Dst = A & A_Mask;
1657 	*pixel++ = ((((sSIMD2 & 0x00fefefe) + (A & 0x00fefefe)) >> 1)
1658 		    + (sSIMD2 & A & 0x00010101)) | A_Dst;
1659       },{
1660 	movq_m2r((*pixel), mm2);/* dst(ARGBARGB) -> mm2 */
1661 	movq_r2r(mm2, mm6); /* dst(ARGBARGB) -> mm6 */
1662 	movq_r2r(mm2, mm0); /* dst(ARGBARGB) -> mm0 */
1663 	pand_r2r(mm7, mm0); /* dst & alpha mask -> mm0 */
1664 	movq_r2r(mm1, mm5); /* src(ARGBARGB) -> mm5 */
1665 
1666 	pand_r2r(mm4, mm6); /* dst & mask -> mm1 */
1667 	pand_r2r(mm4, mm5); /* src & mask -> mm4 */
1668 	paddw_r2r(mm6, mm5); /* mm5 + mm4 -> mm4 */
1669 	psrlq_i2r(1, mm5); /* mm4 >> 1 -> mm4 */
1670 
1671 	pand_r2r(mm1, mm2); /* src & dst -> mm2 */
1672 	pand_r2r(mm3, mm2); /* mm2 & !mask -> mm2 */
1673 	paddw_r2r(mm5, mm2); /* mm5 + mm2 -> mm2 */
1674 
1675 	por_r2r(mm0, mm2); /* mm0(dst alpha) | mm2 -> mm2 */
1676 
1677 	movq_r2m(mm2, (*pixel));/* mm2 -> 2 dst pixels */
1678 	pixel += 2;
1679 
1680       }, end);
1681       emms();
1682     } else {
1683       DUFFS_LOOP_DOUBLE2(
1684       {
1685 	movq_r2r(mm5, mm1); /* src(0A0R0G0B) -> mm1 */
1686 
1687 	movd_m2r((*pixel), mm2);/* dst(ARGB) -> mm2 (0000ARGB)*/
1688 	movq_r2r(mm2, mm6);/* dst(ARGB) -> mm6 (0000ARGB)*/
1689         punpcklbw_r2r(mm2, mm2); /* AARRGGBB -> mm2 */
1690         pand_r2r(mm3, mm2); /* 0A0R0G0B -> mm2 */
1691 	pand_r2r(mm7, mm6); /* 0000A000 -> mm6 */
1692         psubw_r2r(mm2, mm1);/* src - dst -> mm1 */
1693 	pmullw_r2r(mm4, mm1); /* mm1 * alpha -> mm1 */
1694 	psrlw_i2r(8, mm1); /* mm1 >> 8 -> mm1 */
1695 	paddw_r2r(mm1, mm2); /* mm1 + mm2(dst) -> mm2 */
1696 	pand_r2r(mm3, mm2); /* 0A0R0G0B -> mm2 */
1697 	packuswb_r2r(mm2, mm2);  /* ARGBARGB -> mm2 */
1698 	pcmpeqd_r2r(mm5,mm5); /* set mm5 high "1" */
1699 	pxor_r2r(mm7, mm5); /* make clear alpha mask */
1700 	pand_r2r(mm5, mm2); /* 0RGB0RGB -> mm2 */
1701 	por_r2r(mm6, mm2); /* mm6(dst alpha) | mm2 -> mm2 */
1702 	movd_r2m(mm2, *pixel);/* mm2 -> pixel */
1703 	pixel++;
1704       }, {
1705 	movq_r2r(mm5, mm1); /* src(0A0R0G0B) -> mm1 */
1706 	movq_r2r(mm5, mm0); /* src(0A0R0G0B) -> mm0 */
1707 
1708 	movq_m2r((*pixel), mm2);/* 2 x dst -> mm2(ARGBARGB) */
1709 	movq_r2r(mm2, mm6); /* 2 x dst -> mm1(ARGBARGB) */
1710 	movq_r2r(mm2, mm5); /* 2 x dst -> mm1(ARGBARGB) */
1711 	pand_r2r(mm7, mm5); /* save dst alpha -> mm5(A000A000) */
1712         punpcklbw_r2r(mm2, mm2); /* low - AARRGGBB -> mm2 */
1713 	punpckhbw_r2r(mm6, mm6); /* high - AARRGGBB -> mm6 */
1714         pand_r2r(mm3, mm2); /* 0A0R0G0B -> mm2 */
1715 	pand_r2r(mm3, mm6); /* 0A0R0G0B -> mm6 */
1716 
1717         psubw_r2r(mm2, mm1);/* src - dst1 -> mm1 */
1718 	psubw_r2r(mm6, mm0);/* src - dst2 -> mm0 */
1719 
1720 	pmullw_r2r(mm4, mm1); /* mm1 * alpha -> mm1 */
1721 	pmullw_r2r(mm4, mm0); /* mm0 * alpha -> mm0 */
1722 	psrlw_i2r(8, mm1); /* mm1 >> 8 -> mm1 */
1723 	psrlw_i2r(8, mm0); /* mm0 >> 8 -> mm0 */
1724 	paddw_r2r(mm1, mm2); /* mm1 + mm2(dst) -> mm2 */
1725 	paddw_r2r(mm0, mm6); /* mm0 + mm6(dst) -> mm6 */
1726 	pand_r2r(mm3, mm2); /* 0A0R0G0B -> mm2 */
1727 	pand_r2r(mm3, mm6); /* 0A0R0G0B -> mm6 */
1728 	packuswb_r2r(mm2, mm2);  /* ARGBARGB -> mm2 */
1729 	packuswb_r2r(mm6, mm6);  /* ARGBARGB -> mm6 */
1730 	psrlq_i2r(32, mm2); /* mm2 >> 32 -> mm2 */
1731 	psllq_i2r(32, mm6); /* mm6 << 32 -> mm6 */
1732 	por_r2r(mm6, mm2); /* mm6 | mm2 -> mm2 */
1733 	pcmpeqd_r2r(mm1,mm1); /* set mm1 to "1" */
1734 	pxor_r2r(mm7, mm1); /* make clear alpha mask */
1735 	pand_r2r(mm1, mm2); /* 0RGB0RGB -> mm2 */
1736 	por_r2r(mm5, mm2); /* mm5(dst alpha) | mm2 -> mm2 */
1737         movq_r2m(mm2, *pixel);/* mm2 -> pixel */
1738 	pixel += 2;
1739       },end);
1740       emms();
1741     } /* A != 128 */
1742   } else {
1743     /* correct pRect size */
1744     if (pRect->x < 0) {
1745       pRect->w += pRect->x;
1746       pRect->x = 0;
1747     } else {
1748       if (pRect->x >= pSurface->w - pRect->w) {
1749 	pRect->w = pSurface->w - pRect->x;
1750       }
1751     }
1752 
1753     if (pRect->y < 0) {
1754       pRect->h += pRect->y;
1755       pRect->y = 0;
1756     } else {
1757       if (pRect->y >= pSurface->h - pRect->h) {
1758 	pRect->h = pSurface->h - pRect->y;
1759       }
1760     }
1761 
1762     start = pixel = (Uint32 *) pSurface->pixels +
1763 	(pRect->y * (pSurface->pitch >> 2)) + pRect->x;
1764 
1765     if (A == 128) {		/* 50% A */
1766       *(Uint64 *)load = 0x00fefefe00fefefe;/* alpha128 mask */
1767       movq_m2r(*load, mm4); /* alpha128 mask -> mm4 */
1768       *(Uint64 *)load = 0x0001010100010101;/* alpha128 mask */
1769       movq_m2r(*load, mm3); /* !alpha128 mask -> mm3 */
1770       punpckldq_r2r(mm1, mm1); /* mm1(0000ARGB) -> mm1(ARGBARGB) */
1771       y = pRect->h;
1772       end = pRect->w;
1773       while(y--) {
1774         DUFFS_LOOP_DOUBLE2(
1775         {
1776 	  A = *pixel;
1777 	  A_Dst = A & A_Mask;
1778 	  *pixel++ = ((((sSIMD2 & 0x00fefefe) + (A & 0x00fefefe)) >> 1)
1779 		    + (sSIMD2 & A & 0x00010101)) | A_Dst;
1780         },{
1781 	  movq_m2r((*pixel), mm2);/* dst(ARGBARGB) -> mm2 */
1782 	  movq_r2r(mm2, mm6); /* dst(ARGBARGB) -> mm6 */
1783 	  movq_r2r(mm2, mm0); /* dst(ARGBARGB) -> mm0 */
1784 	  pand_r2r(mm7, mm0); /* dst & alpha mask -> mm0(A000A000) */
1785 	  movq_r2r(mm1, mm5); /* src(ARGBARGB) -> mm5 */
1786 
1787 	  pand_r2r(mm4, mm6); /* dst & mask -> mm1 */
1788 	  pand_r2r(mm4, mm5); /* src & mask -> mm4 */
1789 	  paddd_r2r(mm6, mm5); /* mm5 + mm4 -> mm4 */
1790 	  psrld_i2r(1, mm5); /* mm4 >> 1 -> mm4 */
1791 
1792 	  pand_r2r(mm1, mm2); /* src & dst -> mm2 */
1793 	  pand_r2r(mm3, mm2); /* mm2 & !mask -> mm2 */
1794 	  paddd_r2r(mm5, mm2); /* mm5 + mm2 -> mm2 */
1795 	  por_r2r(mm0, mm2); /* mm0(dst alpha) | mm2 -> mm2 */
1796 	  movq_r2m(mm2, (*pixel));/* mm2 -> 2 dst pixels */
1797 	  pixel += 2;
1798 
1799         }, end);
1800 	pixel = start + (pSurface->pitch >> 2);
1801 	start = pixel;
1802       }/* while */
1803       emms();
1804 
1805     } else {
1806       y = pRect->h;
1807       end = pRect->w;
1808 
1809       while(y--) {
1810 	DUFFS_LOOP_DOUBLE2(
1811         {
1812           movq_r2r(mm5, mm1); /* src(0A0R0G0B) -> mm1 */
1813 
1814 	  movd_m2r((*pixel), mm2);/* dst(ARGB) -> mm2 (0000ARGB)*/
1815 	  movq_r2r(mm2, mm6);/* dst(ARGB) -> mm6 (0000ARGB)*/
1816           punpcklbw_r2r(mm2, mm2); /* AARRGGBB -> mm2 */
1817           pand_r2r(mm3, mm2); /* 0A0R0G0B -> mm2 */
1818 	  pand_r2r(mm7, mm6); /* 0000A000 -> mm6 */
1819           psubw_r2r(mm2, mm1);/* src - dst -> mm1 */
1820 	  pmullw_r2r(mm4, mm1); /* mm1 * alpha -> mm1 */
1821 	  psrlw_i2r(8, mm1); /* mm1 >> 8 -> mm1 */
1822 	  paddw_r2r(mm1, mm2); /* mm1 + mm2(dst) -> mm2 */
1823 	  pand_r2r(mm3, mm2); /* 0A0R0G0B -> mm2 */
1824 	  packuswb_r2r(mm2, mm2);  /* ARGBARGB -> mm2 */
1825 	  pcmpeqd_r2r(mm5,mm5); /* set mm5 high "1" */
1826 	  pxor_r2r(mm7, mm5); /* make clear alpha mask */
1827 	  pand_r2r(mm5, mm2); /* 0RGB0RGB -> mm2 */
1828 	  por_r2r(mm6, mm2); /* mm6(dst alpha) | mm2 -> mm2 */
1829 	  movd_r2m(mm2, *pixel);/* mm2 -> pixel */
1830 	  pixel++;
1831         }, {
1832 	  movq_r2r(mm5, mm1); /* src(0A0R0G0B) -> mm1 */
1833 	  movq_r2r(mm5, mm0); /* src(0A0R0G0B) -> mm0 */
1834 
1835 	  movq_m2r((*pixel), mm2);/* dst(ARGBARGB) -> mm2 */
1836 	  movq_r2r(mm2, mm6); /* dst(ARGBARGB) -> mm1 */
1837 	  punpckhbw_r2r(mm6, mm6); /* high - AARRGGBB -> mm6 */
1838 	  pand_r2r(mm3, mm6); /* 0A0R0G0B -> mm6 */
1839 
1840 	  psubw_r2r(mm6, mm0);/* src - dst2 -> mm0 */
1841 	  pmullw_r2r(mm4, mm0); /* mm0 * alpha -> mm0 */
1842 	  psrlw_i2r(8, mm0); /* mm0 >> 8 -> mm0 */
1843 	  paddw_r2r(mm0, mm6); /* mm0 + mm6(dst) -> mm6 */
1844 	  packuswb_r2r(mm6, mm6);  /* ARGBARGB -> mm6 */
1845 
1846 	  movq_r2r(mm2, mm0); /* 2 x dst -> mm0(ARGBARGB) */
1847 	  pand_r2r(mm7, mm0); /* save dst alpha -> mm0(A000A000) */
1848           punpcklbw_r2r(mm2, mm2); /* low - AARRGGBB -> mm2 */
1849 	  pand_r2r(mm3, mm2); /* 0A0R0G0B -> mm2 */
1850 
1851           psubw_r2r(mm2, mm1);/* src - dst1 -> mm1 */
1852 	  pmullw_r2r(mm4, mm1); /* mm1 * alpha -> mm1 */
1853 
1854 	  psrlw_i2r(8, mm1); /* mm1 >> 8 -> mm1 */
1855 	  paddw_r2r(mm1, mm2); /* mm1 + mm2(dst) -> mm2 */
1856 
1857 	  pand_r2r(mm3, mm2); /* 0A0R0G0B -> mm2 */
1858 	  packuswb_r2r(mm2, mm2);  /* ARGBARGB -> mm2 */
1859 
1860 	  psrlq_i2r(32, mm2); /* mm2 >> 32 -> mm2 */
1861 	  pcmpeqd_r2r(mm1,mm1); /* set mm1 to "1" */
1862 	  psllq_i2r(32, mm6); /* mm6 << 32 -> mm6 */
1863 	  por_r2r(mm6, mm2); /* mm6 | mm2 -> mm2 */
1864 	  pxor_r2r(mm7, mm1); /* make clear alpha mask */
1865 	  pand_r2r(mm1, mm2); /* 0RGB0RGB -> mm2 */
1866 	  por_r2r(mm0, mm2); /* mm5(dst alpha) | mm2 -> mm2 */
1867           movq_r2m(mm2, *pixel);/* mm2 -> pixel */
1868 	  pixel += 2;
1869 	}, end);
1870 
1871 	pixel = start + (pSurface->pitch >> 2);
1872 	start = pixel;
1873       } /* while */
1874       emms();
1875     }
1876   }
1877 
1878   unlock_surf(pSurface);
1879   return 0;
1880 }
1881 
1882 /**************************************************************************
1883   Fill rectangle for 24bit "888" format surface
1884 **************************************************************************/
__FillRectAlpha888_24bit(SDL_Surface * pSurface,SDL_Rect * pRect,SDL_Color * pColor)1885 static int __FillRectAlpha888_24bit(SDL_Surface * pSurface, SDL_Rect * pRect,
1886 			       SDL_Color * pColor)
1887 {
1888   Uint8 load[8] = {pColor->unused, pColor->unused,
1889 		    pColor->unused, pColor->unused,
1890     			pColor->unused, pColor->unused,
1891 			pColor->unused, pColor->unused};
1892   Uint32 A = pColor->unused;
1893   register Uint32 sSIMD2 = SDL_MapRGB(pSurface->format,
1894 					    pColor->r, pColor->g,
1895 					    pColor->b);
1896   Uint32 y, end;
1897   Uint8 *start, *pixel;
1898 
1899   movq_m2r(*load, mm4); /* alpha -> mm4 */
1900 
1901   *(Uint64 *)load = 0x00FF00FF00FF00FF;
1902   movq_m2r(*load, mm3); /* mask -> mm2 */
1903 
1904   pand_r2r(mm3, mm4); /* mm4 & mask -> 0A0A0A0A -> mm4 */
1905 
1906   *(Uint64 *)load = sSIMD2;
1907   movq_m2r(*load, mm5); /* src(0000ARGB) -> mm5 */
1908   movq_r2r(mm5, mm1); /* src(0000ARGB) -> mm1 (fot alpha 128 blits) */
1909   punpcklbw_r2r(mm5, mm5); /* AARRGGBB -> mm5 */
1910   pand_r2r(mm3, mm5); /* 0A0R0G0B -> mm5 */
1911 
1912   lock_surf(pSurface);
1913 
1914   if (pRect == NULL) {
1915     end = pSurface->w * pSurface->h;
1916     pixel = (Uint8 *) pSurface->pixels;
1917     if (A == 128) {		/* 50% A */
1918       *(Uint64 *)load = 0x0000fefefefefefe;/* alpha128 mask */
1919       movq_m2r(*load, mm4); /* alpha128 mask -> mm4 */
1920       *(Uint64 *)load = 0x0000010101010101;/* alpha128 mask */
1921       movq_m2r(*load, mm3); /* !alpha128 mask -> mm3 */
1922       movq_r2r(mm1, mm7); /* color -> mm7 */
1923       psllq_i2r(24, mm7); /* mm7 << 24 -> mm7 */
1924       por_r2r(mm7, mm1); /* (00RGBRGB) -> mm1 */
1925       DUFFS_LOOP_DOUBLE2(
1926       {
1927 	A = *pixel;
1928 	A = ((((sSIMD2 & 0x00fefefe) + (A & 0x00fefefe)) >> 1)
1929 		    + (sSIMD2 & A & 0x00010101));
1930 	pixel[0] = A & 0xff;
1931         pixel[1] = (A >> 8) & 0xff;
1932         pixel[2] = (A >> 16) & 0xff;
1933 	pixel += 3;
1934       },{
1935 	movq_m2r((*pixel), mm2);/* dst(gbRGBRGB) -> mm2 */
1936 	movq_r2r(mm2, mm6); /* dst(gbRGBRGB) -> mm6 */
1937 	movq_r2r(mm1, mm5); /* src(00RGBRGB) -> mm5 */
1938 
1939 	pand_r2r(mm4, mm6); /* dst & mask -> mm1 */
1940 	pand_r2r(mm4, mm5); /* src & mask -> mm4 */
1941 	paddw_r2r(mm6, mm5); /* mm5 + mm4 -> mm4 */
1942 	psrlq_i2r(1, mm5); /* mm4 >> 1 -> mm4 */
1943 
1944 	pand_r2r(mm1, mm2); /* src & dst -> mm2 */
1945 	pand_r2r(mm3, mm2); /* mm2 & !mask -> mm2 */
1946 	paddw_r2r(mm5, mm2); /* mm5 + mm2 -> mm2 */
1947 	movq_r2m(mm2, *load);/* mm2 -> 2 dst pixels */
1948 	pixel[0] = load[0];
1949 	pixel[1] = load[1];
1950 	pixel[2] = load[2];
1951 	pixel[3] = load[3];
1952 	pixel[4] = load[4];
1953 	pixel[5] = load[5];
1954 	pixel += 6;
1955       }, end);
1956       emms();
1957     } else {
1958       DUFFS_LOOP_DOUBLE2(
1959       {
1960 	movq_r2r(mm5, mm1); /* src(0A0R0G0B) -> mm1 */
1961 
1962 	movd_m2r((*pixel), mm2);/* dst(ARGB) -> mm2 (0000bRGB)*/
1963         punpcklbw_r2r(mm2, mm2); /* bbRRGGBB -> mm2 */
1964         pand_r2r(mm3, mm2); /* 0b0R0G0B -> mm2 */
1965 
1966         psubw_r2r(mm2, mm1);/* src - dst -> mm1 */
1967 	pmullw_r2r(mm4, mm1); /* mm1 * alpha -> mm1 */
1968 	psrlw_i2r(8, mm1); /* mm1 >> 8 -> mm1 */
1969 	paddw_r2r(mm1, mm2); /* mm1 + mm2(dst) -> mm2 */
1970 	pand_r2r(mm3, mm2); /* 0b0R0G0B -> mm2 */
1971 	packuswb_r2r(mm2, mm2);  /* bRGBbRGB -> mm2 */
1972 	movd_r2m(mm2, *load);/* mm2 -> pixel */
1973 	pixel[0] = load[0];
1974 	pixel[1] = load[1];
1975 	pixel[2] = load[2];
1976 	pixel += 3;
1977       }, {
1978 	movq_r2r(mm5, mm1); /* src(0A0R0G0B) -> mm1 */
1979 	movq_r2r(mm5, mm0); /* src(0A0R0G0B) -> mm0 */
1980 
1981 	movq_m2r((*pixel), mm2);/* dst(gbRGBRGB) -> mm2 */
1982 	movq_r2r(mm2, mm6); /* dst(gbRGBRGB) -> mm6 */
1983 	psllq_i2r(8, mm6); /* mm6 << 8 -> mm6(bRGBRGB0) */
1984         punpcklbw_r2r(mm2, mm2); /* low - BBRRGGBB -> mm2 */
1985 	punpckhbw_r2r(mm6, mm6); /* high - bbRRGGBB -> mm6 */
1986         pand_r2r(mm3, mm2); /* 0b0R0G0B -> mm2 */
1987 	pand_r2r(mm3, mm6); /* 0b0R0G0B -> mm6 */
1988 
1989         psubw_r2r(mm2, mm1);/* src - dst1 -> mm1 */
1990 	psubw_r2r(mm6, mm0);/* src - dst2 -> mm0 */
1991 	pmullw_r2r(mm4, mm1); /* mm1 * alpha -> mm1 */
1992 	pmullw_r2r(mm4, mm0); /* mm0 * alpha -> mm0 */
1993 	psrlw_i2r(8, mm1); /* mm1 >> 8 -> mm1 */
1994 	psrlw_i2r(8, mm0); /* mm0 >> 8 -> mm0 */
1995 	paddw_r2r(mm1, mm2); /* mm1 + mm2(dst) -> mm2 */
1996 	paddw_r2r(mm0, mm6); /* mm0 + mm6(dst) -> mm6 */
1997 	pand_r2r(mm3, mm2); /* 0A0R0G0B -> mm2 */
1998 	pand_r2r(mm3, mm6); /* 0A0R0G0B -> mm6 */
1999 	packuswb_r2r(mm2, mm2);  /* ARGBARGB -> mm2 */
2000 	packuswb_r2r(mm6, mm6);  /* ARGBARGB -> mm6 */
2001 	psrlq_i2r(32, mm2); /* mm2 >> 32 -> mm2 */
2002 	psllq_i2r(32, mm6); /* mm6 << 32 -> mm6 */
2003 	por_r2r(mm6, mm2); /* mm6 | mm2 -> mm2 */
2004         movq_r2m(mm2, *load);/* mm2 -> pixel */
2005 	pixel[0] = load[0];
2006 	pixel[1] = load[1];
2007 	pixel[2] = load[2];
2008 	pixel[4] = load[4];
2009 	pixel[5] = load[5];
2010 	pixel[6] = load[6];
2011 	pixel += 6;
2012       },end);
2013       emms();
2014     } /* A != 128 */
2015   } else {
2016     /* correct pRect size */
2017     if (pRect->x < 0) {
2018       pRect->w += pRect->x;
2019       pRect->x = 0;
2020     } else {
2021       if (pRect->x >= pSurface->w - pRect->w) {
2022 	pRect->w = pSurface->w - pRect->x;
2023       }
2024     }
2025 
2026     if (pRect->y < 0) {
2027       pRect->h += pRect->y;
2028       pRect->y = 0;
2029     } else {
2030       if (pRect->y >= pSurface->h - pRect->h) {
2031 	pRect->h = pSurface->h - pRect->y;
2032       }
2033     }
2034 
2035     start = pixel = (Uint8 *) pSurface->pixels +
2036       (pRect->y * pSurface->pitch ) + pRect->x * 3;
2037 
2038     if (A == 128) {		/* 50% A */
2039       *(Uint64 *)load = 0x0000fefefefefefe;/* alpha128 mask */
2040       movq_m2r(*load, mm4); /* alpha128 mask -> mm4 */
2041       *(Uint64 *)load = 0x0000010101010101;/* alpha128 mask */
2042       movq_m2r(*load, mm3); /* !alpha128 mask -> mm3 */
2043       movq_r2r(mm1, mm7); /* color -> mm7 */
2044       psllq_i2r(24, mm7); /* mm7 << 24 -> mm7 */
2045       por_r2r(mm7, mm1);
2046       y = pRect->h;
2047       end = pRect->w;
2048       while(y--) {
2049         DUFFS_LOOP_DOUBLE2(
2050         {
2051 	  A = *pixel;
2052 	  A = ((((sSIMD2 & 0x00fefefe) + (A & 0x00fefefe)) >> 1)
2053 		    + (sSIMD2 & A & 0x00010101));
2054 	  pixel[0] = A & 0xff;
2055           pixel[1] = (A >> 8) & 0xff;
2056           pixel[2] = (A >> 16) & 0xff;
2057 	  pixel += 3;
2058         },{
2059 	  movq_m2r((*pixel), mm2);/* dst(gbRGBRGB) -> mm2 */
2060 	  movq_r2r(mm2, mm6); /* dst(gbRGBRGB) -> mm6 */
2061 	  movq_r2r(mm1, mm5); /* src(ARGBARGB) -> mm5 */
2062 
2063 	  pand_r2r(mm4, mm6); /* dst & mask -> mm1 */
2064 	  pand_r2r(mm4, mm5); /* src & mask -> mm4 */
2065 	  paddd_r2r(mm6, mm5); /* mm5 + mm4 -> mm4 */
2066 	  psrld_i2r(1, mm5); /* mm4 >> 1 -> mm4 */
2067 
2068 	  pand_r2r(mm1, mm2); /* src & dst -> mm2 */
2069 	  pand_r2r(mm3, mm2); /* mm2 & !mask -> mm2 */
2070 	  paddd_r2r(mm5, mm2); /* mm5 + mm2 -> mm2 */
2071 	  por_r2r(mm7, mm2); /* mm7(dst alpha mask) | mm2 -> mm2 */
2072 	  movq_r2m(mm2, *load);/* mm2 -> 2 dst pixels */
2073 	  pixel[0] = load[0];
2074 	  pixel[1] = load[1];
2075 	  pixel[2] = load[2];
2076 	  pixel[3] = load[3];
2077 	  pixel[4] = load[4];
2078 	  pixel[5] = load[5];
2079 	  pixel += 6;
2080         }, end);
2081 
2082         pixel = start + pSurface->pitch;
2083         start = pixel;
2084       }/* while */
2085       emms();
2086 
2087     } else {
2088       y = pRect->h;
2089       end = pRect->w;
2090 
2091       while(y--) {
2092 	DUFFS_LOOP_DOUBLE2(
2093         {
2094           movq_r2r(mm5, mm1); /* src(0A0R0G0B) -> mm1 */
2095 
2096 	  movd_m2r((*pixel), mm2);/* dst(bRGB) -> mm2 (0000bRGB)*/
2097           punpcklbw_r2r(mm2, mm2); /* bbRRGGBB -> mm2 */
2098           pand_r2r(mm3, mm2); /* 0b0R0G0B -> mm2 */
2099 
2100           psubw_r2r(mm2, mm1);/* src - dst -> mm1 */
2101 	  pmullw_r2r(mm4, mm1); /* mm1 * alpha -> mm1 */
2102 	  psrlw_i2r(8, mm1); /* mm1 >> 8 -> mm1 */
2103 	  paddw_r2r(mm1, mm2); /* mm1 + mm2(dst) -> mm2 */
2104 	  pand_r2r(mm3, mm2); /* 0A0R0G0B -> mm2 */
2105 	  packuswb_r2r(mm2, mm2);  /* ARGBARGB -> mm2 */
2106 	  por_r2r(mm7, mm2); /* mm7(dst alpha mask) | mm2 -> mm2 */
2107 	  movd_r2m(mm2, *load);/* mm2 -> pixel */
2108 	  pixel[0] = load[0];
2109 	  pixel[1] = load[1];
2110 	  pixel[2] = load[2];
2111 
2112 	  pixel += 3;
2113         }, {
2114 	  movq_r2r(mm5, mm1); /* src(0A0R0G0B) -> mm1 */
2115 	  movq_r2r(mm5, mm0); /* src(0A0R0G0B) -> mm0 */
2116 
2117 	  movq_m2r((*pixel), mm2);/* dst(gbRGBRGB) -> mm2 */
2118 	  movq_r2r(mm2, mm6); /* dst(gbRGBRGB) -> mm1 */
2119 	  psllq_i2r(8, mm6); /* mm6 << 8 -> mm6(bRGBRGB0) */
2120           punpcklbw_r2r(mm2, mm2); /* low - BBRRGGBB -> mm2 */
2121 	  punpckhbw_r2r(mm6, mm6); /* high - bbRRGGBB -> mm6 */
2122           pand_r2r(mm3, mm2); /* 0B0R0G0B -> mm2 */
2123 	  pand_r2r(mm3, mm6); /* 0b0R0G0B -> mm6 */
2124 
2125           psubw_r2r(mm2, mm1);/* src - dst1 -> mm1 */
2126 	  psubw_r2r(mm6, mm0);/* src - dst2 -> mm0 */
2127 
2128 	  pmullw_r2r(mm4, mm1); /* mm1 * alpha -> mm1 */
2129 	  pmullw_r2r(mm4, mm0); /* mm0 * alpha -> mm0 */
2130 	  psrlw_i2r(8, mm1); /* mm1 >> 8 -> mm1 */
2131 	  psrlw_i2r(8, mm0); /* mm0 >> 8 -> mm0 */
2132 	  paddw_r2r(mm1, mm2); /* mm1 + mm2(dst) -> mm2 */
2133 	  paddw_r2r(mm0, mm6); /* mm0 + mm6(dst) -> mm6 */
2134 	  pand_r2r(mm3, mm2); /* 0A0R0G0B -> mm2 */
2135 	  pand_r2r(mm3, mm6); /* 0A0R0G0B -> mm6 */
2136 	  packuswb_r2r(mm2, mm2);  /* ARGBARGB -> mm2 */
2137 	  packuswb_r2r(mm6, mm6);  /* ARGBARGB -> mm6 */
2138 	  psrlq_i2r(32, mm2); /* mm2 >> 32 -> mm2 */
2139 	  psllq_i2r(32, mm6); /* mm6 << 32 -> mm6 */
2140 	  por_r2r(mm6, mm2); /* mm6 | mm2 -> mm2 */
2141 	  por_r2r(mm7, mm2); /* mm7(dst alpha mask) | mm2 -> mm2 */
2142           movq_r2m(mm2, *load);/* mm2 -> pixel */
2143 	  pixel[0] = load[0];
2144 	  pixel[1] = load[1];
2145 	  pixel[2] = load[2];
2146 	  pixel[3] = load[4];
2147 	  pixel[4] = load[5];
2148 	  pixel[5] = load[6];
2149 	  pixel += 6;
2150 	}, end);
2151 
2152         pixel = start + pSurface->pitch;
2153         start = pixel;
2154       } /* while */
2155       emms();
2156     }
2157   }
2158 
2159   unlock_surf(pSurface);
2160   return 0;
2161 }
2162 
2163 
2164 #else  /* HAVE_MMX1 */
2165 /**************************************************************************
2166   Fill rectangle for "565" format surface
2167 **************************************************************************/
__FillRectAlpha565(SDL_Surface * pSurface,SDL_Rect * pRect,SDL_Color * pColor)2168 static int __FillRectAlpha565(SDL_Surface *pSurface, SDL_Rect *pRect,
2169                               SDL_Color *pColor)
2170 {
2171   Uint32 y, end;
2172 
2173   Uint32 *start;
2174   Uint32 *pixel;
2175 
2176   register Uint32 D, S =
2177       SDL_MapRGB(pSurface->format, pColor->r, pColor->g, pColor->b);
2178   register Uint32 A = pColor->unused >> 3;
2179 
2180   S &= 0xFFFF;
2181 
2182   lock_surf(pSurface);
2183   if (pRect == NULL) {
2184     end = pSurface->w * pSurface->h;
2185     pixel = pSurface->pixels;
2186     if (A == 16) {		/* A == 128 >> 3 */
2187       /* this code don't work (A == 128) */
2188       if (end & 0x1) {		/* end % 2 */
2189 	D = *pixel;
2190 	*pixel++ = BLEND16_50(D, S, MASK565);
2191 	end--;
2192       }
2193 
2194       S = S | S << 16;
2195       for (y = 0; y < end; y += 2) {
2196 	D = *(Uint32 *) pixel;
2197 	*(Uint32 *) pixel = BLEND2x16_50(D, S, MASK565);
2198 	pixel += 2;
2199       }
2200     } else {
2201       S = (S | S << 16) & 0x07e0f81f;
2202       DUFFS_LOOP8(
2203       {
2204 	D = *pixel;
2205 	D = (D | D << 16) & 0x07e0f81f;
2206 	D += (S - D) * A >> 5;
2207 	D &= 0x07e0f81f;
2208 	*pixel++ = (D | (D >> 16)) & 0xFFFF;
2209       }, end);
2210     }
2211   } else {
2212     /* correct pRect size */
2213     if (pRect->x < 0) {
2214       pRect->w += pRect->x;
2215       pRect->x = 0;
2216     } else {
2217       if (pRect->x >= pSurface->w - pRect->w) {
2218 	pRect->w = pSurface->w - pRect->x;
2219       }
2220     }
2221 
2222     if (pRect->y < 0) {
2223       pRect->h += pRect->y;
2224       pRect->y = 0;
2225     } else {
2226       if (pRect->y >= pSurface->h - pRect->h) {
2227 	pRect->h = pSurface->h - pRect->y;
2228       }
2229     }
2230 
2231     start = pixel = (Uint32 *) pSurface->pixels +
2232       (pRect->y * pSurface->pitch) + pRect->x / 2;
2233 
2234     if (A == 16) {		/* A == 128 >> 3 */
2235       /* this code don't work (A == 128) */
2236       S = S | S << 16;
2237       for (y = 0; y < pRect->h; y++) {
2238 	end = 0;
2239 
2240 	if (pRect->w & 0x1) {
2241 	  D = *pixel;
2242 	  *pixel++ = BLEND16_50(D, (S & 0xFFFF), MASK565);
2243 	  end++;
2244 	}
2245 
2246 	for (; end < pRect->w; end += 2) {
2247 	  D = *(Uint32 *) pixel;
2248 	  *(Uint32 *) pixel = BLEND2x16_50(D, S, MASK565);
2249 	  pixel += 2;
2250 	}
2251 
2252         pixel = start + pSurface->pitch;
2253         start = pixel;
2254       }
2255     } else {
2256       y = 0;
2257       S = (S | S << 16) & 0x07e0f81f;
2258       y = pRect->h;
2259       end = pRect->w;
2260 
2261       while(y--) {
2262 	DUFFS_LOOP8(
2263         {
2264           D = *pixel;
2265 	  D = (D | D << 16) & 0x07e0f81f;
2266 	  D += (S - D) * A >> 5;
2267 	  D &= 0x07e0f81f;
2268 	  *pixel++ = (D | (D >> 16)) & 0xFFFF;
2269         }, end);
2270 
2271         pixel = start + pSurface->pitch;
2272         start = pixel;
2273       } /* while */
2274     }
2275 
2276   }
2277 
2278   unlock_surf(pSurface);
2279   return 0;
2280 }
2281 
2282 /**************************************************************************
2283   Fill rectangle for "555" format surface
2284 **************************************************************************/
__FillRectAlpha555(SDL_Surface * pSurface,SDL_Rect * pRect,SDL_Color * pColor)2285 static int __FillRectAlpha555(SDL_Surface * pSurface, SDL_Rect * pRect,
2286 			      SDL_Color * pColor)
2287 {
2288   Uint32 y, end;
2289 
2290   Uint32 *start, *pixel;
2291 
2292   register Uint32 D, S =
2293       SDL_MapRGB(pSurface->format, pColor->r, pColor->g, pColor->b);
2294   register Uint32 A = pColor->unused >> 3;
2295 
2296   S &= 0xFFFF;
2297 
2298   lock_surf(pSurface);
2299 
2300   if (pRect == NULL) {
2301     end = pSurface->w * pSurface->h;
2302     pixel = pSurface->pixels;
2303     if (A == 16) {		/* A == 128 >> 3 */
2304       if (end & 0x1) {
2305 	D = *pixel;
2306 	*pixel++ = BLEND16_50(D, S, MASK555);
2307 	end--;
2308       }
2309 
2310       S = S | S << 16;
2311       for (y = 0; y < end; y += 2) {
2312 	D = *pixel;
2313 	*pixel = BLEND2x16_50(D, S, MASK555);
2314 	pixel += 2;
2315       }
2316     } else {
2317       S = (S | S << 16) & 0x03e07c1f;
2318       DUFFS_LOOP8(
2319       {
2320 	D = *pixel;
2321 	D = (D | D << 16) & 0x03e07c1f;
2322 	D += (S - D) * A >> 5;
2323 	D &= 0x03e07c1f;
2324 	*pixel++ = (D | (D >> 16)) & 0xFFFF;
2325       }, end);
2326     }
2327   } else {
2328     /* correct pRect size */
2329     if (pRect->x < 0) {
2330       pRect->w += pRect->x;
2331       pRect->x = 0;
2332     } else {
2333       if (pRect->x >= pSurface->w - pRect->w) {
2334 	pRect->w = pSurface->w - pRect->x;
2335       }
2336     }
2337 
2338     if (pRect->y < 0) {
2339       pRect->h += pRect->y;
2340       pRect->y = 0;
2341     } else {
2342       if (pRect->y >= pSurface->h - pRect->h) {
2343 	pRect->h = pSurface->h - pRect->y;
2344       }
2345     }
2346 
2347     start = pixel = (Uint32 *) pSurface->pixels +
2348       (pRect->y * pSurface->pitch) + pRect->x / 2;
2349 
2350     if (A == 16) {		/* A == 128 >> 3 */
2351       S = S | S << 16;
2352       for (y = 0; y < pRect->h; y++) {
2353 	end = 0;
2354 
2355 	if (pRect->w & 0x1) {
2356 	  D = *pixel;
2357 	  *pixel++ = BLEND16_50(D, (S & 0xFFFF), MASK555);
2358 	  end++;
2359 	}
2360 
2361 	for (; end < pRect->w; end += 2) {
2362 	  D = *(Uint32 *) pixel;
2363 	  *(Uint32 *) pixel = BLEND2x16_50(D, S, MASK555);
2364 	  pixel += 2;
2365 	}
2366 
2367         pixel = start + pSurface->pitch;
2368         start = pixel;
2369       }
2370     } else {
2371 
2372       S = (S | S << 16) & 0x03e07c1f;
2373       y = pRect->h;
2374       end = pRect->w;
2375 
2376       while(y--) {
2377 	DUFFS_LOOP8(
2378         {
2379           D = *pixel;
2380 	  D = (D | D << 16) & 0x03e07c1f;
2381 	  D += (S - D) * A >> 5;
2382 	  D &= 0x03e07c1f;
2383 	  *pixel++ = (D | (D >> 16)) & 0xFFFF;
2384         }, end);
2385 
2386         pixel = start + pSurface->pitch;
2387         start = pixel;
2388       } /* while */
2389     }
2390   }
2391 
2392   unlock_surf(pSurface);
2393   return 0;
2394 }
2395 
2396 /**************************************************************************
2397   Fill rectangle for 32bit "8888" format surface
2398 **************************************************************************/
__FillRectAlpha8888_32bit(SDL_Surface * pSurface,SDL_Rect * pRect,SDL_Color * pColor)2399 static int __FillRectAlpha8888_32bit(SDL_Surface * pSurface, SDL_Rect * pRect,
2400 			       SDL_Color * pColor)
2401 {
2402   register Uint32 A = pColor->unused;
2403   register Uint32 dSIMD1, dSIMD2;
2404   register Uint32 sSIMD1, sSIMD2 = SDL_MapRGB(pSurface->format,
2405 					    pColor->r, pColor->g,
2406 					    pColor->b);
2407   Uint32 y, end, A_Dst, A_Mask = pSurface->format->Amask;
2408   Uint32 *start, *pixel;
2409 
2410   sSIMD1 = sSIMD2 & 0x00FF00FF;
2411 
2412   lock_surf(pSurface);
2413 
2414   if (pRect == NULL) {
2415     end = pSurface->w * pSurface->h;
2416     pixel = (Uint32 *) pSurface->pixels;
2417     if (A == 128) {		/* 50% A */
2418       DUFFS_LOOP8(
2419       {
2420 	dSIMD2 = *pixel;
2421 	A_Dst = dSIMD2 & A_Mask;
2422 	*pixel++ = ((((sSIMD2 & 0x00fefefe) + (dSIMD2 & 0x00fefefe)) >> 1)
2423 		      + (sSIMD2 & dSIMD2 & 0x00010101)) | A_Dst;
2424       }, end);
2425     } else {
2426       sSIMD2 &= 0xFF00;
2427       sSIMD2 = sSIMD2 >> 8 | sSIMD2 << 8;
2428       DUFFS_LOOP_DOUBLE2(
2429         {
2430 	  dSIMD2 = *pixel;
2431 	  A_Dst = dSIMD2 & A_Mask;
2432 	  dSIMD1 = dSIMD2 & 0x00FF00FF;
2433 	  dSIMD1 += (sSIMD1 - dSIMD1) * A >> 8;
2434 	  dSIMD1 &= 0x00FF00FF;
2435 	  dSIMD2 &= 0xFF00;
2436 	  dSIMD2 += (((sSIMD2 << 8) & 0xFF00) - dSIMD2) * A >> 8;
2437 	  dSIMD2 &= 0xFF00;
2438 	  *pixel++ = dSIMD1 | dSIMD2 | A_Dst;
2439       },{
2440 	  dSIMD1 = *pixel;
2441 	  A_Dst = dSIMD1 & A_Mask;
2442 	  dSIMD1 &= 0x00FF00FF;
2443 	  dSIMD1 += (sSIMD1 - dSIMD1) * A >> 8;
2444 	  dSIMD1 &= 0x00FF00FF;
2445 
2446 	  dSIMD2 = ((*pixel & 0xFF00) >> 8)| ((pixel[1] & 0xFF00) << 8);
2447 	  dSIMD2 += (sSIMD2 - dSIMD2) * A >> 8;
2448 	  dSIMD2 &= 0x00FF00FF;
2449 
2450 	  *pixel++ = dSIMD1 | ((dSIMD2 << 8) & 0xFF00) | A_Dst;
2451 
2452 	  dSIMD1 = *pixel;
2453 	  A_Dst = dSIMD1 & A_Mask;
2454 	  dSIMD1 &= 0x00FF00FF;
2455 	  dSIMD1 += (sSIMD1 - dSIMD1) * A >> 8;
2456 	  dSIMD1 &= 0x00FF00FF;
2457 
2458 	  *pixel++ = dSIMD1 | ((dSIMD2 >> 8) & 0xFF00) | A_Dst;
2459       }, end);
2460     }
2461   } else {
2462     /* correct pRect size */
2463     if (pRect->x < 0) {
2464       pRect->w += pRect->x;
2465       pRect->x = 0;
2466     } else {
2467       if (pRect->x >= pSurface->w - pRect->w) {
2468 	pRect->w = pSurface->w - pRect->x;
2469       }
2470     }
2471 
2472     if (pRect->y < 0) {
2473       pRect->h += pRect->y;
2474       pRect->y = 0;
2475     } else {
2476       if (pRect->y >= pSurface->h - pRect->h) {
2477 	pRect->h = pSurface->h - pRect->y;
2478       }
2479     }
2480 
2481     start = pixel = (Uint32 *) pSurface->pixels +
2482 	(pRect->y * (pSurface->pitch >> 2)) + pRect->x;
2483 
2484     if (A == 128) {		/* 50% A */
2485       y = pRect->h;
2486       end = pRect->w;
2487       while(y--) {
2488         DUFFS_LOOP4(
2489 	{
2490 	  dSIMD2 = *pixel;
2491 	  A_Dst = dSIMD2 & A_Mask;
2492 	  *pixel++ = ((((sSIMD2 & 0x00fefefe) + (dSIMD2 & 0x00fefefe)) >> 1)
2493 		      + (sSIMD2 & dSIMD2 & 0x00010101)) | A_Dst;
2494 	}, end);
2495 	pixel = start + (pSurface->pitch >> 2);
2496 	start = pixel;
2497       }
2498     } else {
2499       y = pRect->h;
2500       end = pRect->w;
2501 
2502       sSIMD2 &= 0xFF00;
2503       sSIMD2 = sSIMD2 >> 8 | sSIMD2 << 8;
2504 
2505       while(y--) {
2506 	DUFFS_LOOP_DOUBLE2(
2507         {
2508 	  dSIMD2 = *pixel;
2509 	  A_Dst = dSIMD2 & A_Mask;
2510 	  dSIMD1 = dSIMD2 & 0x00FF00FF;
2511 	  dSIMD1 += (sSIMD1 - dSIMD1) * A >> 8;
2512 	  dSIMD1 &= 0x00FF00FF;
2513 	  dSIMD2 &= 0xFF00;
2514 	  dSIMD2 += (((sSIMD2 << 8) & 0xFF00) - dSIMD2) * A >> 8;
2515 	  dSIMD2 &= 0xFF00;
2516 	  *pixel++ = dSIMD1 | dSIMD2 | A_Dst;
2517         },{
2518 	  dSIMD1 = *pixel;
2519 	  A_Dst = dSIMD1 & A_Mask;
2520 	  dSIMD1 &= 0x00FF00FF;
2521 	  dSIMD1 += (sSIMD1 - dSIMD1) * A >> 8;
2522 	  dSIMD1 &= 0x00FF00FF;
2523 
2524 	  dSIMD2 = ((*pixel & 0xFF00) >> 8)| ((pixel[1] & 0xFF00) << 8);
2525 	  dSIMD2 += (sSIMD2 - dSIMD2) * A >> 8;
2526 	  dSIMD2 &= 0x00FF00FF;
2527 
2528 	  *pixel++ = dSIMD1 | ((dSIMD2 << 8) & 0xFF00) | A_Dst;
2529 
2530 	  dSIMD1 = *pixel;
2531 	  A_Dst = dSIMD1 & A_Mask;
2532 	  dSIMD1 &= 0x00FF00FF;
2533 	  dSIMD1 += (sSIMD1 - dSIMD1) * A >> 8;
2534 	  dSIMD1 &= 0x00FF00FF;
2535 
2536 	  *pixel++ = dSIMD1 | ((dSIMD2 >> 8) & 0xFF00) | A_Dst;
2537         }, end);
2538 
2539 	pixel = start + (pSurface->pitch >> 2);
2540 	start = pixel;
2541 
2542       } /* while */
2543     }
2544   }
2545 
2546   unlock_surf(pSurface);
2547   return 0;
2548 }
2549 
2550 /**************************************************************************
2551   Fill rectangle for 32bit "888" format surface
2552 **************************************************************************/
__FillRectAlpha888_32bit(SDL_Surface * pSurface,SDL_Rect * pRect,SDL_Color * pColor)2553 static int __FillRectAlpha888_32bit(SDL_Surface * pSurface, SDL_Rect * pRect,
2554 			       SDL_Color * pColor)
2555 {
2556   register Uint32 A = pColor->unused;
2557   register Uint32 dSIMD1, dSIMD2;
2558   register Uint32 sSIMD1, sSIMD2 = SDL_MapRGB(pSurface->format,
2559 					    pColor->r, pColor->g,
2560 					    pColor->b);
2561   Uint32 y, end;
2562   Uint32 *start, *pixel;
2563 
2564   sSIMD1 = sSIMD2 & 0x00FF00FF;
2565 
2566   lock_surf(pSurface);
2567 
2568   if (pRect == NULL) {
2569     end = pSurface->w * pSurface->h;
2570     pixel = (Uint32 *) pSurface->pixels;
2571     if (A == 128) {		/* 50% A */
2572       for (y = 0; y < end; y++) {
2573 	dSIMD2 = *pixel;
2574 	*pixel++ = ((((sSIMD2 & 0x00fefefe) + (dSIMD2 & 0x00fefefe)) >> 1)
2575 		    + (sSIMD2 & dSIMD2 & 0x00010101)) | 0xFF000000;
2576       }
2577     } else {
2578       sSIMD2 &= 0xFF00;
2579       sSIMD2 = sSIMD2 >> 8 | sSIMD2 << 8;
2580       DUFFS_LOOP_DOUBLE2(
2581         {
2582 	  dSIMD2 = *pixel;
2583 	  dSIMD1 = dSIMD2 & 0x00FF00FF;
2584 	  dSIMD1 += (sSIMD1 - dSIMD1) * A >> 8;
2585 	  dSIMD1 &= 0x00FF00FF;
2586 	  dSIMD2 &= 0xFF00;
2587 	  dSIMD2 += (((sSIMD2 << 8) & 0xFF00) - dSIMD2) * A >> 8;
2588 	  dSIMD2 &= 0xFF00;
2589 	  *pixel++ = dSIMD1 | dSIMD2 | 0xFF000000;
2590       },{
2591 	  dSIMD1 = *pixel & 0x00FF00FF;
2592 	  dSIMD1 += (sSIMD1 - dSIMD1) * A >> 8;
2593 	  dSIMD1 &= 0x00FF00FF;
2594 
2595 	  dSIMD2 = ((*pixel & 0xFF00) >> 8)| ((pixel[1] & 0xFF00) << 8);
2596 	  dSIMD2 += (sSIMD2 - dSIMD2) * A >> 8;
2597 	  dSIMD2 &= 0x00FF00FF;
2598 
2599 	  *pixel++ = dSIMD1 | ((dSIMD2 << 8) & 0xFF00) | 0xFF000000;
2600 
2601 	  dSIMD1 = *pixel & 0x00FF00FF;
2602 	  dSIMD1 += (sSIMD1 - dSIMD1) * A >> 8;
2603 	  dSIMD1 &= 0x00FF00FF;
2604 
2605 	  *pixel++ = dSIMD1 | ((dSIMD2 >> 8) & 0xFF00) | 0xFF000000;
2606       }, end);
2607     }
2608   } else {
2609     /* correct pRect size */
2610     if (pRect->x < 0) {
2611       pRect->w += pRect->x;
2612       pRect->x = 0;
2613     } else {
2614       if (pRect->x >= pSurface->w - pRect->w) {
2615 	pRect->w = pSurface->w - pRect->x;
2616       }
2617     }
2618 
2619     if (pRect->y < 0) {
2620       pRect->h += pRect->y;
2621       pRect->y = 0;
2622     } else {
2623       if (pRect->y >= pSurface->h - pRect->h) {
2624 	pRect->h = pSurface->h - pRect->y;
2625       }
2626     }
2627 
2628     start = pixel = (Uint32 *) pSurface->pixels +
2629 	(pRect->y * (pSurface->pitch >> 2)) + pRect->x;
2630 
2631     if (A == 128) {		/* 50% A */
2632 
2633       for (y = 0; y < pRect->h; y++) {
2634 
2635 	for (end = 0; end < pRect->w; end++) {
2636 	  dSIMD2 = *pixel;
2637 	  *pixel++ = ((((sSIMD2 & 0x00fefefe) + (dSIMD2 & 0x00fefefe)) >> 1)
2638 		      + (sSIMD2 & dSIMD2 & 0x00010101)) | 0xFF000000;
2639 	}
2640 
2641 	pixel = start + (pSurface->pitch >> 2);
2642 	start = pixel;
2643       }
2644     } else {
2645       y = pRect->h;
2646       end = pRect->w;
2647 
2648       sSIMD2 &= 0xFF00;
2649       sSIMD2 = sSIMD2 >> 8 | sSIMD2 << 8;
2650 
2651       while(y--) {
2652 	DUFFS_LOOP_DOUBLE2(
2653         {
2654 	  dSIMD2 = *pixel;
2655 	  dSIMD1 = dSIMD2 & 0x00FF00FF;
2656 	  dSIMD1 += (sSIMD1 - dSIMD1) * A >> 8;
2657 	  dSIMD1 &= 0x00FF00FF;
2658 	  dSIMD2 &= 0xFF00;
2659 	  dSIMD2 += (((sSIMD2 << 8) & 0xFF00) - dSIMD2) * A >> 8;
2660 	  dSIMD2 &= 0xFF00;
2661 	  *pixel++ = dSIMD1 | dSIMD2 | 0xFF000000;
2662         },{
2663 	  dSIMD1 = *pixel & 0x00FF00FF;
2664 	  dSIMD1 += (sSIMD1 - dSIMD1) * A >> 8;
2665 	  dSIMD1 &= 0x00FF00FF;
2666 
2667 	  dSIMD2 = ((*pixel & 0xFF00) >> 8)| ((pixel[1] & 0xFF00) << 8);
2668 	  dSIMD2 += (sSIMD2 - dSIMD2) * A >> 8;
2669 	  dSIMD2 &= 0x00FF00FF;
2670 
2671 	  *pixel++ = dSIMD1 | ((dSIMD2 << 8) & 0xFF00) | 0xFF000000;
2672 
2673 	  dSIMD1 = *pixel & 0x00FF00FF;
2674 	  dSIMD1 += (sSIMD1 - dSIMD1) * A >> 8;
2675 	  dSIMD1 &= 0x00FF00FF;
2676 
2677 	  *pixel++ = dSIMD1 | ((dSIMD2 >> 8) & 0xFF00) | 0xFF000000;
2678         }, end);
2679 
2680 	pixel = start + (pSurface->pitch >> 2);
2681 	start = pixel;
2682 
2683       } /* while */
2684     }
2685   }
2686 
2687   unlock_surf(pSurface);
2688   return 0;
2689 }
2690 
2691 
2692 /**************************************************************************
2693   Fill rectangle for 24bit "888" format surface
2694 **************************************************************************/
__FillRectAlpha888_24bit(SDL_Surface * pSurface,SDL_Rect * pRect,SDL_Color * pColor)2695 static int __FillRectAlpha888_24bit(SDL_Surface * pSurface, SDL_Rect * pRect,
2696 			      SDL_Color * pColor)
2697 {
2698   Uint32 y, end;
2699 
2700   Uint8 *start, *pixel;
2701 
2702   register Uint32 P, D, S1, S2 = SDL_MapRGB(pSurface->format,
2703 					    pColor->r, pColor->g,
2704 					    pColor->b);
2705 
2706   register Uint32 A = pColor->unused;
2707 
2708   S1 = S2 & 0x00FF00FF;
2709 
2710   S2 &= 0xFF00;
2711 
2712   lock_surf(pSurface);
2713 
2714   if (pRect == NULL) {
2715     end = pSurface->w * pSurface->h;
2716     pixel = (Uint8 *) pSurface->pixels;
2717 
2718     for (y = 0; y < end; y++) {
2719       D = (pixel[0] << 16) + (pixel[1] << 8) + pixel[2];
2720 
2721       P = D & 0x00FF00FF;
2722       P += (S1 - P) * A >> 8;
2723       P &= 0x00ff00ff;
2724 
2725       D = (D & 0xFF00);
2726       D += (S2 - D) * A >> 8;
2727       D &= 0xFF00;
2728 
2729       P = P | D;
2730 
2731       /* Fix me to little - big EDIAN */
2732 
2733       pixel[0] = P & 0xff;
2734       pixel[1] = (P >> 8) & 0xff;
2735       pixel[2] = (P >> 16) & 0xff;
2736 
2737       pixel += 3;
2738     }
2739 
2740   } else {
2741     /* correct pRect size */
2742     if (pRect->x < 0) {
2743       pRect->w += pRect->x;
2744       pRect->x = 0;
2745     } else {
2746       if (pRect->x >= pSurface->w - pRect->w) {
2747 	pRect->w = pSurface->w - pRect->x;
2748       }
2749     }
2750 
2751     if (pRect->y < 0) {
2752       pRect->h += pRect->y;
2753       pRect->y = 0;
2754     } else {
2755       if (pRect->y >= pSurface->h - pRect->h) {
2756 	pRect->h = pSurface->h - pRect->y;
2757       }
2758     }
2759 
2760     end = pRect->w * pRect->h;
2761     start = pixel = (Uint8 *) pSurface->pixels +
2762 	(pRect->y * pSurface->pitch) + pRect->x * 3;
2763 
2764     y = 0;
2765     while (y != pRect->h) {
2766       D = (pixel[0] << 16) + (pixel[1] << 8) + pixel[2];
2767 
2768       P = D & 0x00FF00FF;
2769       P += (S1 - P) * A >> 8;
2770       P &= 0x00ff00ff;
2771 
2772       D = (D & 0xFF00);
2773       D += (S2 - D) * A >> 8;
2774       D &= 0xFF00;
2775 
2776       P = P | D;
2777 
2778       /* Fix me to little - big EDIAN */
2779 
2780       pixel[0] = P & 0xff;
2781       pixel[1] = (P >> 8) & 0xff;
2782       pixel[2] = (P >> 16) & 0xff;
2783 
2784       if ((pixel - start) == (pRect->w * 3)) {
2785 	pixel = start + pSurface->pitch;
2786 	start = pixel;
2787 	y++;
2788       } else {
2789 	pixel += 3;
2790       }
2791 
2792     }
2793 
2794   }
2795 
2796   unlock_surf(pSurface);
2797   return 0;
2798 }
2799 #endif /* HAVE_MMX1 */
2800 
2801 /**************************************************************************
2802   Fill rectangle with color with alpha channel.
2803 **************************************************************************/
SDL_FillRectAlpha(SDL_Surface * pSurface,SDL_Rect * pRect,SDL_Color * pColor)2804 int SDL_FillRectAlpha(SDL_Surface * pSurface, SDL_Rect * pRect,
2805 		      SDL_Color * pColor)
2806 {
2807   if (pRect && ( pRect->x < - pRect->w || pRect->x >= pSurface->w ||
2808 	         pRect->y < - pRect->h || pRect->y >= pSurface->h ))
2809   {
2810      return -2;
2811   }
2812 
2813   if (pColor->unused == 255 )
2814   {
2815     return SDL_FillRect(pSurface, pRect,
2816 	SDL_MapRGB(pSurface->format, pColor->r, pColor->g, pColor->b));
2817   }
2818 
2819   if (!pColor->unused)
2820   {
2821     return -3;
2822   }
2823 
2824   switch (pSurface->format->BytesPerPixel) {
2825   case 1:
2826     /* PORT ME */
2827     return -1;
2828 
2829   case 2:
2830     if (pSurface->format->Gmask == 0x7E0) {
2831       return __FillRectAlpha565(pSurface, pRect, pColor);
2832     } else {
2833       if (pSurface->format->Gmask == 0x3E0) {
2834 	return __FillRectAlpha555(pSurface, pRect, pColor);
2835       } else {
2836 	return -1;
2837       }
2838     }
2839     break;
2840 
2841   case 3:
2842     return __FillRectAlpha888_24bit(pSurface, pRect, pColor);
2843 
2844   case 4:
2845     if (pSurface->format->Amask) {
2846       return __FillRectAlpha8888_32bit(pSurface, pRect, pColor);
2847     } else {
2848       return __FillRectAlpha888_32bit(pSurface, pRect, pColor);
2849     }
2850   }
2851 
2852   return -1;
2853 }
2854 
2855 /**************************************************************************
2856   Make rectangle region sane. Return TRUE if result is sane.
2857 **************************************************************************/
correct_rect_region(SDL_Rect * pRect)2858 bool correct_rect_region(SDL_Rect * pRect)
2859 {
2860   int ww = pRect->w, hh = pRect->h;
2861 
2862   if (pRect->x < 0) {
2863     ww += pRect->x;
2864     pRect->x = 0;
2865   }
2866 
2867   if (pRect->y < 0) {
2868     hh += pRect->y;
2869     pRect->y = 0;
2870   }
2871 
2872   if (pRect->x + ww > Main.screen->w) {
2873     ww = Main.screen->w - pRect->x;
2874   }
2875 
2876   if (pRect->y + hh > Main.screen->h) {
2877     hh = Main.screen->h - pRect->y;
2878   }
2879 
2880   /* End Correction */
2881 
2882   if (ww <= 0 || hh <= 0) {
2883     return FALSE;			/* suprise :) */
2884   } else {
2885     pRect->w = ww;
2886     pRect->h = hh;
2887   }
2888 
2889   return TRUE;
2890 }
2891 
2892 /**************************************************************************
2893   Return whether coordinates are in rectangle.
2894 **************************************************************************/
is_in_rect_area(int x,int y,SDL_Rect rect)2895 bool is_in_rect_area(int x, int y, SDL_Rect rect)
2896 {
2897   return ((x >= rect.x) && (x < rect.x + rect.w)
2898 	  && (y >= rect.y) && (y < rect.y + rect.h));
2899 }
2900 
2901 /**************************************************************************
2902   Most black color is coded like {0,0,0,255} but in sdl if alpha is turned
2903   off and colorkey is set to 0 this black color is trasparent.
2904   To fix this we change all black {0, 0, 0, 255} to newblack {4, 4, 4, 255}
2905   (first collor != 0 in 16 bit coding).
2906 **************************************************************************/
correct_black(SDL_Surface * pSrc)2907 bool correct_black(SDL_Surface * pSrc)
2908 {
2909   bool ret = 0;
2910   register int x;
2911   if (pSrc->format->BitsPerPixel == 32 && pSrc->format->Amask) {
2912 
2913     register Uint32 alpha, *pPixels = (Uint32 *) pSrc->pixels;
2914     Uint32 Amask = pSrc->format->Amask;
2915 
2916     Uint32 black = SDL_MapRGBA(pSrc->format, 0, 0, 0, 255);
2917     Uint32 new_black = SDL_MapRGBA(pSrc->format, 4, 4, 4, 255);
2918 
2919     int end = pSrc->w * pSrc->h;
2920 
2921     /* for 32 bit color coding */
2922 
2923     lock_surf(pSrc);
2924 
2925     for (x = 0; x < end; x++, pPixels++) {
2926       if (*pPixels == black) {
2927 	*pPixels = new_black;
2928       } else {
2929 	if (!ret) {
2930 	  alpha = *pPixels & Amask;
2931 	  if (alpha && (alpha != Amask)) {
2932 	    ret = 1;
2933 	  }
2934 	}
2935       }
2936     }
2937 
2938     unlock_surf(pSrc);
2939   } else {
2940     if (pSrc->format->BitsPerPixel == 8 && pSrc->format->palette) {
2941       for(x = 0; x < pSrc->format->palette->ncolors; x++) {
2942 	if (x != pSrc->format->colorkey &&
2943 	  pSrc->format->palette->colors[x].r < 4 &&
2944 	  pSrc->format->palette->colors[x].g < 4 &&
2945 	  pSrc->format->palette->colors[x].b < 4) {
2946 	    pSrc->format->palette->colors[x].r = 4;
2947 	    pSrc->format->palette->colors[x].g = 4;
2948 	    pSrc->format->palette->colors[x].b = 4;
2949 	  }
2950       }
2951     }
2952   }
2953 
2954   return ret;
2955 }
2956 
2957 /* ===================================================================== */
2958 
2959 /**************************************************************************
2960   Get visible rectangle from surface.
2961 **************************************************************************/
get_smaller_surface_rect(SDL_Surface * pSurface)2962 SDL_Rect get_smaller_surface_rect(SDL_Surface * pSurface)
2963 {
2964   int w, h, x, y;
2965   Uint16 minX, maxX, minY, maxY;
2966   Uint32 colorkey;
2967   SDL_Rect src;
2968   fc_assert(pSurface != NULL);
2969 
2970   minX = pSurface->w;
2971   maxX = 0;
2972   minY = pSurface->h;
2973   maxY = 0;
2974   colorkey = pSurface->format->colorkey;
2975 
2976   lock_surf(pSurface);
2977 
2978   switch(pSurface->format->BytesPerPixel) {
2979     case 1:
2980     {
2981       Uint8 *pixel = (Uint8 *)pSurface->pixels;
2982       Uint8 *start = pixel;
2983       x = 0;
2984       y = 0;
2985       w = pSurface->w;
2986       h = pSurface->h;
2987       while(h--) {
2988         do {
2989 	  if(*pixel != colorkey) {
2990 	    if (minY > y) {
2991 	      minY = y;
2992 	    }
2993 
2994 	    if (minX > x) {
2995 	      minX = x;
2996 	    }
2997             break;
2998 	  }
2999 	  pixel++;
3000 	  x++;
3001         } while( --w > 0 );
3002 	w = pSurface->w;
3003 	x = 0;
3004 	y++;
3005 	pixel = start + pSurface->pitch;
3006 	start = pixel;
3007       }
3008 
3009       w = pSurface->w;
3010       h = pSurface->h;
3011       x = w - 1;
3012       y = h - 1;
3013       pixel = (Uint8 *)((Uint8 *)pSurface->pixels + (y * pSurface->pitch) + x);
3014       start = pixel;
3015       while(h--) {
3016         do {
3017 	  if(*pixel != colorkey) {
3018 	    if (maxY < y) {
3019 	      maxY = y;
3020 	    }
3021 
3022 	    if (maxX < x) {
3023 	      maxX = x;
3024 	    }
3025             break;
3026 	  }
3027 	  pixel--;
3028 	  x--;
3029         } while( --w > 0 );
3030 	w = pSurface->w;
3031 	x = w - 1;
3032 	y--;
3033 	pixel = start - pSurface->pitch;
3034 	start = pixel;
3035       }
3036     }
3037     break;
3038     case 2:
3039     {
3040       Uint16 *pixel = (Uint16 *)pSurface->pixels;
3041       Uint16 *start = pixel;
3042       x = 0;
3043       y = 0;
3044       w = pSurface->w;
3045       h = pSurface->h;
3046       while(h--) {
3047         do {
3048 	  if(*pixel != colorkey) {
3049 	    if (minY > y) {
3050 	      minY = y;
3051 	    }
3052 
3053 	    if (minX > x) {
3054 	      minX = x;
3055 	    }
3056             break;
3057 	  }
3058 	  pixel++;
3059 	  x++;
3060         } while( --w > 0 );
3061 	w = pSurface->w;
3062 	x = 0;
3063 	y++;
3064 	pixel = start + pSurface->pitch / 2;
3065 	start = pixel;
3066       }
3067 
3068       w = pSurface->w;
3069       h = pSurface->h;
3070       x = w - 1;
3071       y = h - 1;
3072       pixel = ((Uint16 *)pSurface->pixels + (y * pSurface->pitch / 2) + x);
3073       start = pixel;
3074       while(h--) {
3075         do {
3076 	  if(*pixel != colorkey) {
3077 	    if (maxY < y) {
3078 	      maxY = y;
3079 	    }
3080 
3081 	    if (maxX < x) {
3082 	      maxX = x;
3083 	    }
3084             break;
3085 	  }
3086 	  pixel--;
3087 	  x--;
3088         } while( --w > 0 );
3089 	w = pSurface->w;
3090 	x = w - 1;
3091 	y--;
3092 	pixel = start - pSurface->pitch / 2;
3093 	start = pixel;
3094       }
3095     }
3096     break;
3097     case 3:
3098     {
3099       Uint8 *pixel = (Uint8 *)pSurface->pixels;
3100       Uint8 *start = pixel;
3101       Uint32 color;
3102       x = 0;
3103       y = 0;
3104       w = pSurface->w;
3105       h = pSurface->h;
3106       while(h--) {
3107         do {
3108 	  if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
3109 	    color = (pixel[0] << 16 | pixel[1] << 8 | pixel[2]);
3110           } else {
3111 	    color = (pixel[0] | pixel[1] << 8 | pixel[2] << 16);
3112           }
3113 	  if(color != colorkey) {
3114 	    if (minY > y) {
3115 	      minY = y;
3116 	    }
3117 
3118 	    if (minX > x) {
3119 	      minX = x;
3120 	    }
3121             break;
3122 	  }
3123 	  pixel += 3;
3124 	  x++;
3125         } while( --w > 0 );
3126 	w = pSurface->w;
3127 	x = 0;
3128 	y++;
3129 	pixel = start + pSurface->pitch / 3;
3130 	start = pixel;
3131       }
3132 
3133       w = pSurface->w;
3134       h = pSurface->h;
3135       x = w - 1;
3136       y = h - 1;
3137       pixel = (Uint8 *)((Uint8 *)pSurface->pixels + (y * pSurface->pitch) + x * 3);
3138       start = pixel;
3139       while(h--) {
3140         do {
3141 	  if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
3142 	    color = (pixel[0] << 16 | pixel[1] << 8 | pixel[2]);
3143           } else {
3144 	    color = (pixel[0] | pixel[1] << 8 | pixel[2] << 16);
3145           }
3146 	  if(color != colorkey) {
3147 	    if (maxY < y) {
3148 	      maxY = y;
3149 	    }
3150 
3151 	    if (maxX < x) {
3152 	      maxX = x;
3153 	    }
3154             break;
3155 	  }
3156 	  pixel -= 3;
3157 	  x--;
3158         } while( --w > 0 );
3159 	w = pSurface->w;
3160 	x = w - 1;
3161 	y--;
3162 	pixel = start - pSurface->pitch / 3;
3163 	start = pixel;
3164       }
3165     }
3166     break;
3167     case 4:
3168     {
3169       Uint32 *pixel = (Uint32 *)pSurface->pixels;
3170       Uint32 *start = pixel;
3171       x = 0;
3172       y = 0;
3173       w = pSurface->w;
3174       h = pSurface->h;
3175       while(h--) {
3176         do {
3177 	  if(*pixel != colorkey) {
3178 	    if (minY > y) {
3179 	      minY = y;
3180 	    }
3181 
3182 	    if (minX > x) {
3183 	      minX = x;
3184 	    }
3185             break;
3186 	  }
3187 	  pixel++;
3188 	  x++;
3189         } while( --w > 0 );
3190 	w = pSurface->w;
3191 	x = 0;
3192 	y++;
3193 	pixel = start + pSurface->pitch / 4;
3194 	start = pixel;
3195       }
3196 
3197       w = pSurface->w;
3198       h = pSurface->h;
3199       x = w - 1;
3200       y = h - 1;
3201       pixel = ((Uint32 *)pSurface->pixels + (y * pSurface->pitch / 4) + x);
3202       start = pixel;
3203       while(h--) {
3204         do {
3205 	  if(*pixel != colorkey) {
3206 	    if (maxY < y) {
3207 	      maxY = y;
3208 	    }
3209 
3210 	    if (maxX < x) {
3211 	      maxX = x;
3212 	    }
3213             break;
3214 	  }
3215 	  pixel--;
3216 	  x--;
3217         } while( --w > 0 );
3218 	w = pSurface->w;
3219 	x = w - 1;
3220 	y--;
3221 	pixel = start - pSurface->pitch / 4;
3222 	start = pixel;
3223       }
3224     }
3225     break;
3226   }
3227 
3228   unlock_surf(pSurface);
3229   src.x = minX;
3230   src.y = minY;
3231   src.w = maxX - minX + 1;
3232   src.h = maxY - minY + 1;
3233 
3234   return src;
3235 }
3236 
3237 /**************************************************************************
3238   Create new surface that is just visible part of source surface.
3239 **************************************************************************/
crop_visible_part_from_surface(SDL_Surface * pSrc)3240 SDL_Surface *crop_visible_part_from_surface(SDL_Surface * pSrc)
3241 {
3242   SDL_Rect src = get_smaller_surface_rect(pSrc);
3243   return crop_rect_from_surface(pSrc, &src);
3244 }
3245 
3246 /**************************************************************************
3247   Scale surface.
3248 **************************************************************************/
ResizeSurface(const SDL_Surface * pSrc,Uint16 new_width,Uint16 new_height,int smooth)3249 SDL_Surface *ResizeSurface(const SDL_Surface * pSrc, Uint16 new_width,
3250 			   Uint16 new_height, int smooth)
3251 {
3252   if (pSrc == NULL) {
3253     return NULL;
3254   }
3255 
3256   return zoomSurface((SDL_Surface*)pSrc,
3257                      (double)new_width / pSrc->w,
3258                      (double)new_height / pSrc->h,
3259                      smooth);
3260 }
3261 
3262 /**************************************************************************
3263   Resize a surface to fit into a box with the dimensions 'new_width' and a
3264   'new_height'. If 'scale_up' is FALSE, a surface that already fits into
3265   the box will not be scaled up to the boundaries of the box.
3266   If 'absolute_dimensions' is TRUE, the function returns a surface with the
3267   dimensions of the box and the scaled/original surface centered in it.
3268 **************************************************************************/
ResizeSurfaceBox(const SDL_Surface * pSrc,Uint16 new_width,Uint16 new_height,int smooth,bool scale_up,bool absolute_dimensions)3269 SDL_Surface *ResizeSurfaceBox(const SDL_Surface * pSrc,
3270                               Uint16 new_width, Uint16 new_height, int smooth,
3271                               bool scale_up, bool absolute_dimensions)
3272 {
3273   SDL_Surface *tmpSurface, *result;
3274 
3275   if (pSrc == NULL) {
3276     return NULL;
3277   }
3278 
3279   if (!((scale_up == FALSE) && ((new_width >= pSrc->w) && (new_height >= pSrc->h)))) {
3280     if ((new_width - pSrc->w) <= (new_height - pSrc->h)) {
3281       /* horizontal limit */
3282       tmpSurface = zoomSurface((SDL_Surface*)pSrc,
3283                                (double)new_width / pSrc->w,
3284                                (double)new_width / pSrc->w,
3285                                smooth);
3286     } else {
3287       /* vertical limit */
3288       tmpSurface = zoomSurface((SDL_Surface*)pSrc,
3289                                (double)new_height / pSrc->h,
3290                                (double)new_height / pSrc->h,
3291                                smooth);
3292     }
3293   } else {
3294     tmpSurface = zoomSurface((SDL_Surface*)pSrc,
3295                              1.0,
3296                              1.0,
3297                              smooth);
3298   }
3299 
3300   if (absolute_dimensions) {
3301     SDL_Rect area = {
3302       (new_width - tmpSurface->w) / 2,
3303       (new_height - tmpSurface->h) / 2,
3304       0, 0
3305     };
3306     result = create_surf_alpha(new_width, new_height, SDL_SWSURFACE);
3307     alphablit(tmpSurface, NULL, result, &area);
3308     FREESURFACE(tmpSurface);
3309   } else {
3310     result = tmpSurface;
3311   }
3312 
3313   return result;
3314 }
3315 
3316 /* ============ Freeciv game graphics function =========== */
3317 
3318 /**************************************************************************
3319   Return whether the client supports given view type
3320 **************************************************************************/
is_view_supported(enum ts_type type)3321 bool is_view_supported(enum ts_type type)
3322 {
3323   switch (type) {
3324   case TS_ISOMETRIC:
3325   case TS_OVERHEAD:
3326     return TRUE;
3327   }
3328 
3329   return FALSE;
3330 }
3331 
3332 /**************************************************************************
3333   Load intro sprites. Not used in SDL-client.
3334 **************************************************************************/
load_intro_gfx(void)3335 void load_intro_gfx(void)
3336 {
3337   /* nothing */
3338 }
3339 
3340 /**************************************************************************
3341   Frees the introductory sprites.
3342 **************************************************************************/
free_intro_radar_sprites(void)3343 void free_intro_radar_sprites(void)
3344 {
3345   /* nothing */
3346 }
3347