OpenTTD
32bpp_anim_sse2.cpp
1 /* $Id$ */
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 "../video/video_driver.hpp"
16 #include "32bpp_anim_sse2.hpp"
17 #include "32bpp_sse_func.hpp"
18 
19 #include "../safeguards.h"
20 
22 static FBlitter_32bppSSE2_Anim iFBlitter_32bppSSE2_Anim;
23 
24 void Blitter_32bppSSE2_Anim::PaletteAnimate(const Palette &palette)
25 {
26  assert(!_screen_disable_anim);
27 
28  this->palette = palette;
29  /* If first_dirty is 0, it is for 8bpp indication to send the new
30  * palette. However, only the animation colours might possibly change.
31  * Especially when going between toyland and non-toyland. */
32  assert(this->palette.first_dirty == PALETTE_ANIM_START || this->palette.first_dirty == 0);
33 
34  const uint16 *anim = this->anim_buf;
35  Colour *dst = (Colour *)_screen.dst_ptr;
36 
37  bool screen_dirty = false;
38 
39  /* Let's walk the anim buffer and try to find the pixels */
40  const int width = this->anim_buf_width;
41  const int screen_pitch = _screen.pitch;
42  const int anim_pitch = this->anim_buf_pitch;
43  __m128i anim_cmp = _mm_set1_epi16(PALETTE_ANIM_START - 1);
44  __m128i brightness_cmp = _mm_set1_epi16(Blitter_32bppBase::DEFAULT_BRIGHTNESS);
45  __m128i colour_mask = _mm_set1_epi16(0xFF);
46  for (int y = this->anim_buf_height; y != 0 ; y--) {
47  Colour *next_dst_ln = dst + screen_pitch;
48  const uint16 *next_anim_ln = anim + anim_pitch;
49  int x = width;
50  while (x > 0) {
51  __m128i data = _mm_load_si128((const __m128i *) anim);
52 
53  /* low bytes only, shifted into high positions */
54  __m128i colour_data = _mm_and_si128(data, colour_mask);
55 
56  /* test if any colour >= PALETTE_ANIM_START */
57  int colour_cmp_result = _mm_movemask_epi8(_mm_cmpgt_epi16(colour_data, anim_cmp));
58  if (colour_cmp_result) {
59  /* test if any brightness is unexpected */
60  if (x < 8 || colour_cmp_result != 0xFFFF ||
61  _mm_movemask_epi8(_mm_cmpeq_epi16(_mm_srli_epi16(data, 8), brightness_cmp)) != 0xFFFF) {
62  /* slow path: < 8 pixels left or unexpected brightnesses */
63  for (int z = min<int>(x, 8); z != 0 ; z--) {
64  int value = _mm_extract_epi16(data, 0);
65  uint8 colour = GB(value, 0, 8);
66  if (colour >= PALETTE_ANIM_START) {
67  /* Update this pixel */
68  *dst = AdjustBrightneSSE(LookupColourInPalette(colour), GB(value, 8, 8));
69  screen_dirty = true;
70  }
71  data = _mm_srli_si128(data, 2);
72  dst++;
73  }
74  } else {
75  /* medium path: 8 pixels to animate all of expected brightnesses */
76  for (int z = 0; z < 8; z++) {
77  *dst = LookupColourInPalette(_mm_extract_epi16(colour_data, 0));
78  colour_data = _mm_srli_si128(colour_data, 2);
79  dst++;
80  }
81  screen_dirty = true;
82  }
83  } else {
84  /* fast path, no animation */
85  dst += 8;
86  }
87  anim += 8;
88  x -= 8;
89  }
90  dst = next_dst_ln;
91  anim = next_anim_ln;
92  }
93 
94  if (screen_dirty) {
95  /* Make sure the backend redraws the whole screen */
96  VideoDriver::GetInstance()->MakeDirty(0, 0, _screen.width, _screen.height);
97  }
98 }
99 
100 #endif /* WITH_SSE */
virtual void MakeDirty(int left, int top, int width, int height)=0
Mark a particular area dirty.
Information about the currently used palette.
Definition: gfx_type.h:309
bool _screen_disable_anim
Disable palette animation (important for 32bpp-anim blitter during giant screenshot) ...
Definition: gfx.cpp:44
int first_dirty
The first dirty element.
Definition: gfx_type.h:311
static VideoDriver * GetInstance()
Get the currently active instance of the video driver.
static uint GB(const T x, const uint8 s, const uint8 n)
Fetch n bits from x, started at bit s.
Functions related to SSE 32 bpp blitter.
Structure to access the alpha, red, green, and blue channels from a 32 bit number.
Definition: gfx_type.h:164
Index in the _palettes array from which all animations are taking places (table/palettes.h)
Definition: gfx_type.h:278