OpenTTD
32bpp_sse2.cpp
Go to the documentation of this file.
1 /* $Id: 32bpp_sse2.cpp 26482 2014-04-23 20:13:33Z rubidium $ */
2 
3 /*
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/>.
8  */
9 
12 #ifdef WITH_SSE
13 
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"
19 
20 #include "../safeguards.h"
21 
23 static FBlitter_32bppSSE2 iFBlitter_32bppSSE2;
24 
25 Sprite *Blitter_32bppSSE_Base::Encode(const SpriteLoader::Sprite *sprite, AllocatorProc *allocator)
26 {
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.
30  */
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;
37  }
38 
39  /* Calculate sizes and allocate. */
40  SpriteData sd;
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;
48 
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;
51 
52  const uint mv_size = sizeof(MapValue) * src_sprite->width * src_sprite->height;
53  all_sprites_size += rgba_size + mv_size;
54  }
55 
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));
62 
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--) {
75  if (src->a != 0) {
76  dst_rgba->a = src->a;
77  if (src->a != 0 && src->a != 255) has_translucency = true;
78  dst_mv->m = src->m;
79  if (src->m != 0) {
80  /* Do some accounting for flags. */
81  has_remap = true;
82  if (src->m >= PALETTE_ANIM_START) has_anim = true;
83 
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;
87 
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;
93  } else {
94  dst_rgba->r = src->r;
95  dst_rgba->g = src->g;
96  dst_rgba->b = src->b;
97  dst_mv->v = Blitter_32bppBase::DEFAULT_BRIGHTNESS;
98  }
99  } else {
100  dst_rgba->data = 0;
101  *(uint16*) dst_mv = 0;
102  }
103  dst_rgba++;
104  dst_mv++;
105  src++;
106  }
107 
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++;
113  else break;
114  dst_rgba++;
115  }
116  (*dst_rgba_line).data = nb_pix_transp;
117 
118  Colour *nb_right = dst_rgba_line + 1;
119  dst_rgba_line = (Colour*) ((byte*) dst_rgba_line + sd.infos[z].sprite_line_size);
120 
121  /* Count the number of transparent pixels from the right. */
122  dst_rgba = dst_rgba_line - 1;
123  nb_pix_transp = 0;
124  for (uint x = src_sprite->width; x != 0; x--) {
125  if (dst_rgba->a == 0) nb_pix_transp++;
126  else break;
127  dst_rgba--;
128  }
129  (*nb_right).data = nb_pix_transp;
130  }
131  }
132 
133  /* Store sprite flags. */
134  sd.flags = SF_NONE;
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));
139 
140  return dst_sprite;
141 }
142 
143 #endif /* WITH_SSE */