4 * This file is part of OpenTTD.
5 * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
6 * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
7 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
10 /** @file 32bpp_sse2.cpp Implementation of the SSE2 32 bpp blitter. */
14 #include "../stdafx.h"
15 #include "../zoom_func.h"
16 #include "../settings_type.h"
17 #include "32bpp_sse2.hpp"
18 #include "32bpp_sse_func.hpp"
20 #include "../safeguards.h"
22 /** Instantiation of the SSE2 32bpp blitter factory. */
23 static FBlitter_32bppSSE2 iFBlitter_32bppSSE2
;
25 Sprite
*Blitter_32bppSSE_Base::Encode(const SpriteLoader::Sprite
*sprite
, AllocatorProc
*allocator
)
27 /* First uint32 of a line = the number of transparent pixels from the left.
28 * Second uint32 of a line = the number of transparent pixels from the right.
29 * Then all RGBA then all MV.
31 ZoomLevel zoom_min
= ZOOM_LVL_NORMAL
;
32 ZoomLevel zoom_max
= ZOOM_LVL_NORMAL
;
33 if (sprite
->type
!= ST_FONT
) {
34 zoom_min
= _settings_client
.gui
.zoom_min
;
35 zoom_max
= _settings_client
.gui
.zoom_max
;
36 if (zoom_max
== zoom_min
) zoom_max
= ZOOM_LVL_MAX
;
39 /* Calculate sizes and allocate. */
41 memset(&sd
, 0, sizeof(sd
));
42 uint all_sprites_size
= 0;
43 for (ZoomLevel z
= zoom_min
; z
<= zoom_max
; z
++) {
44 const SpriteLoader::Sprite
*src_sprite
= &sprite
[z
];
45 sd
.infos
[z
].sprite_width
= src_sprite
->width
;
46 sd
.infos
[z
].sprite_offset
= all_sprites_size
;
47 sd
.infos
[z
].sprite_line_size
= sizeof(Colour
) * src_sprite
->width
+ sizeof(uint32
) * META_LENGTH
;
49 const uint rgba_size
= sd
.infos
[z
].sprite_line_size
* src_sprite
->height
;
50 sd
.infos
[z
].mv_offset
= all_sprites_size
+ rgba_size
;
52 const uint mv_size
= sizeof(MapValue
) * src_sprite
->width
* src_sprite
->height
;
53 all_sprites_size
+= rgba_size
+ mv_size
;
56 Sprite
*dst_sprite
= (Sprite
*) allocator(sizeof(Sprite
) + sizeof(SpriteData
) + all_sprites_size
);
57 dst_sprite
->height
= sprite
->height
;
58 dst_sprite
->width
= sprite
->width
;
59 dst_sprite
->x_offs
= sprite
->x_offs
;
60 dst_sprite
->y_offs
= sprite
->y_offs
;
61 memcpy(dst_sprite
->data
, &sd
, sizeof(SpriteData
));
63 /* Copy colours and determine flags. */
64 bool has_remap
= false;
65 bool has_anim
= false;
66 bool has_translucency
= false;
67 for (ZoomLevel z
= zoom_min
; z
<= zoom_max
; z
++) {
68 const SpriteLoader::Sprite
*src_sprite
= &sprite
[z
];
69 const SpriteLoader::CommonPixel
*src
= (const SpriteLoader::CommonPixel
*) src_sprite
->data
;
70 Colour
*dst_rgba_line
= (Colour
*) &dst_sprite
->data
[sizeof(SpriteData
) + sd
.infos
[z
].sprite_offset
];
71 MapValue
*dst_mv
= (MapValue
*) &dst_sprite
->data
[sizeof(SpriteData
) + sd
.infos
[z
].mv_offset
];
72 for (uint y
= src_sprite
->height
; y
!= 0; y
--) {
73 Colour
*dst_rgba
= dst_rgba_line
+ META_LENGTH
;
74 for (uint x
= src_sprite
->width
; x
!= 0; x
--) {
77 if (src
->a
!= 0 && src
->a
!= 255) has_translucency
= true;
80 /* Do some accounting for flags. */
82 if (src
->m
>= PALETTE_ANIM_START
) has_anim
= true;
84 /* Get brightest value (or default brightness if it's a black pixel). */
85 const uint8 rgb_max
= max(src
->r
, max(src
->g
, src
->b
));
86 dst_mv
->v
= (rgb_max
== 0) ? Blitter_32bppBase::DEFAULT_BRIGHTNESS
: rgb_max
;
88 /* Pre-convert the mapping channel to a RGB value. */
89 const Colour colour
= AdjustBrightneSSE(Blitter_32bppBase::LookupColourInPalette(src
->m
), dst_mv
->v
);
90 dst_rgba
->r
= colour
.r
;
91 dst_rgba
->g
= colour
.g
;
92 dst_rgba
->b
= colour
.b
;
97 dst_mv
->v
= Blitter_32bppBase::DEFAULT_BRIGHTNESS
;
101 *(uint16
*) dst_mv
= 0;
108 /* Count the number of transparent pixels from the left. */
109 dst_rgba
= dst_rgba_line
+ META_LENGTH
;
110 uint32 nb_pix_transp
= 0;
111 for (uint x
= src_sprite
->width
; x
!= 0; x
--) {
112 if (dst_rgba
->a
== 0) nb_pix_transp
++;
116 (*dst_rgba_line
).data
= nb_pix_transp
;
118 Colour
*nb_right
= dst_rgba_line
+ 1;
119 dst_rgba_line
= (Colour
*) ((byte
*) dst_rgba_line
+ sd
.infos
[z
].sprite_line_size
);
121 /* Count the number of transparent pixels from the right. */
122 dst_rgba
= dst_rgba_line
- 1;
124 for (uint x
= src_sprite
->width
; x
!= 0; x
--) {
125 if (dst_rgba
->a
== 0) nb_pix_transp
++;
129 (*nb_right
).data
= nb_pix_transp
;
133 /* Store sprite flags. */
135 if (has_translucency
) sd
.flags
|= SF_TRANSLUCENT
;
136 if (!has_remap
) sd
.flags
|= SF_NO_REMAP
;
137 if (!has_anim
) sd
.flags
|= SF_NO_ANIM
;
138 memcpy(dst_sprite
->data
, &sd
, sizeof(SpriteData
));
143 #endif /* WITH_SSE */