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