Skip to content

Commit 98037bc

Browse files
committed
Fix of surface copy constructor
After coppy new surface should be aligmet like orginal one. If orginal surface dont have palette, you can still copy it.
1 parent a10d5af commit 98037bc

2 files changed

Lines changed: 106 additions & 47 deletions

File tree

‎src/Engine/Surface.cpp‎

Lines changed: 105 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -35,62 +35,107 @@
3535
#define _aligned_free __mingw_aligned_free
3636
#endif //MINGW
3737
#include "Language.h"
38+
#ifdef __MORPHOS__
39+
#include <ppcinline/exec.h>
40+
#endif
3841

3942
namespace OpenXcom
4043
{
4144

45+
46+
namespace
47+
{
48+
4249
/**
43-
* Sets up a blank 8bpp surface with the specified size and position,
44-
* with pure black as the transparent color.
45-
* @note Surfaces don't have to fill the whole size since their
46-
* background is transparent, specially subclasses with their own
47-
* drawing logic, so it just covers the maximum drawing area.
48-
* @param width Width in pixels.
49-
* @param height Height in pixels.
50-
* @param x X position in pixels.
51-
* @param y Y position in pixels.
52-
* @param bpp Bits-per-pixel depth.
50+
* Helper function counting pitch with 16byte align
51+
* @param bpp bytes per pixel
52+
* @param width number of pixel in row
53+
* @return pitch in bytes
5354
*/
55+
inline int GetPitch(int bpp, int width)
56+
{
57+
return (bpp/8) * ((width+15)& ~0xF);
58+
}
5459

55-
#ifdef __MORPHOS__
56-
#include <ppcinline/exec.h>
57-
#endif
58-
59-
Surface::Surface(int width, int height, int x, int y, int bpp) : _x(x), _y(y), _visible(true), _hidden(false), _redraw(false), _originalColors(0), _misalignedPixelBuffer(0), _alignedBuffer(0)
60+
/**
61+
* Helper function creating aligned buffer
62+
* @param bpp bytes per pixel
63+
* @param width number of pixel in row
64+
* @param height number of rows
65+
* @return pointer to memory
66+
*/
67+
inline void* NewAligned(int bpp, int width, int height)
6068
{
61-
//_surface = SDL_CreateRGBSurface(SDL_SWSURFACE, width, height, 8, 0, 0, 0, 0);
62-
int pitch = (bpp/8) * ((width+15)& ~0xF);
69+
int pitch = GetPitch(bpp, width);
70+
void* buffer = 0;
6371

6472
#ifndef _WIN32
6573

6674
#ifdef __MORPHOS__
6775

68-
_alignedBuffer = calloc( pitch * height * (bpp/8), 1 );
69-
if (!_alignedBuffer)
76+
buffer = calloc( pitch * height * (bpp/8), 1 );
77+
if (!buffer)
7078
{
7179
throw Exception("Where's the memory, Lebowski?");
7280
}
7381

7482
#else
7583
int rc;
76-
if ((rc = posix_memalign(&_alignedBuffer, 16, pitch * height * (bpp/8))))
84+
if ((rc = posix_memalign(&buffer, 16, pitch * height * (bpp/8))))
7785
{
7886
throw Exception(strerror(rc));
7987
}
8088
#endif
81-
89+
8290
#else
91+
8392
// of course Windows has to be difficult about this!
84-
_alignedBuffer = _aligned_malloc(pitch*height*(bpp/8), 16);
85-
if (!_alignedBuffer)
93+
buffer = _aligned_malloc(pitch*height*(bpp/8), 16);
94+
if (!buffer)
8695
{
8796
throw Exception("Where's the memory, Lebowski?");
8897
}
98+
8999
#endif
90-
91-
memset(_alignedBuffer, 0, pitch * height * (bpp/8));
92-
93-
_surface = SDL_CreateRGBSurfaceFrom(_alignedBuffer,width, height, bpp, pitch, 0, 0, 0, 0);
100+
101+
memset(buffer, 0, pitch * height * (bpp/8));
102+
return buffer;
103+
}
104+
105+
/**
106+
* Helper function release aligned memory
107+
* @param buffer buffer to delete
108+
*/
109+
inline void DeleteAligned(void* buffer)
110+
{
111+
if (buffer)
112+
{
113+
#ifdef _WIN32
114+
_aligned_free(buffer);
115+
#else
116+
free(buffer);
117+
#endif
118+
}
119+
}
120+
121+
} //namespace
122+
123+
/**
124+
* Sets up a blank 8bpp surface with the specified size and position,
125+
* with pure black as the transparent color.
126+
* @note Surfaces don't have to fill the whole size since their
127+
* background is transparent, specially subclasses with their own
128+
* drawing logic, so it just covers the maximum drawing area.
129+
* @param width Width in pixels.
130+
* @param height Height in pixels.
131+
* @param x X position in pixels.
132+
* @param y Y position in pixels.
133+
* @param bpp Bits-per-pixel depth.
134+
*/
135+
Surface::Surface(int width, int height, int x, int y, int bpp) : _x(x), _y(y), _visible(true), _hidden(false), _redraw(false), _originalColors(0), _alignedBuffer(0)
136+
{
137+
_alignedBuffer = NewAligned(bpp, width, height);
138+
_surface = SDL_CreateRGBSurfaceFrom(_alignedBuffer, width, height, bpp, GetPitch(bpp, width), 0, 0, 0, 0);
94139

95140
if (_surface == 0)
96141
{
@@ -113,7 +158,31 @@ Surface::Surface(int width, int height, int x, int y, int bpp) : _x(x), _y(y), _
113158
*/
114159
Surface::Surface(const Surface& other)
115160
{
116-
_surface = SDL_ConvertSurface(other._surface, other._surface->format, other._surface->flags);
161+
//if is native OpenXcom aligned surface
162+
if(other._alignedBuffer)
163+
{
164+
Uint8 bpp = other._surface->format->BitsPerPixel;
165+
int width = other.getWidth();
166+
int height = other.getHeight();
167+
int pitch = GetPitch(bpp, width);
168+
_alignedBuffer = NewAligned(bpp, width, height);
169+
_surface = SDL_CreateRGBSurfaceFrom(_alignedBuffer, width, height, bpp, pitch, 0, 0, 0, 0);
170+
SDL_SetColorKey(_surface, SDL_SRCCOLORKEY, 0);
171+
//cant call `SetPalette` because its vitual function and it dont work correctly in constructor
172+
//additionally it use original colors, not temporarily ones.
173+
SDL_SetColors(_surface, other._originalColors ? other._originalColors : other.getPalette(), 0, 255);
174+
memcpy(_alignedBuffer, other._alignedBuffer, height*pitch);
175+
}
176+
else
177+
{
178+
_surface = SDL_ConvertSurface(other._surface, other._surface->format, other._surface->flags);
179+
_alignedBuffer = 0;
180+
}
181+
182+
if (_surface == 0)
183+
{
184+
throw Exception(SDL_GetError());
185+
}
117186
_x = other._x;
118187
_y = other._y;
119188
_crop.w = other._crop.w;
@@ -123,22 +192,17 @@ Surface::Surface(const Surface& other)
123192
_visible = other._visible;
124193
_hidden = other._hidden;
125194
_redraw = other._redraw;
126-
_originalColors = other._originalColors;
127-
_misalignedPixelBuffer = 0;
128-
_alignedBuffer = 0;
195+
_originalColors = 0;
196+
_dx = other._dx;
197+
_dy = other._dy;
129198
}
130199

131200
/**
132201
* Deletes the surface from memory.
133202
*/
134203
Surface::~Surface()
135204
{
136-
//if (_misalignedPixelBuffer) _surface->pixels = _misalignedPixelBuffer;
137-
#ifdef _WIN32
138-
if (_alignedBuffer) _aligned_free(_alignedBuffer);
139-
#else
140-
if (_alignedBuffer) free(_alignedBuffer);
141-
#endif
205+
DeleteAligned(_alignedBuffer);
142206
SDL_FreeSurface(_surface);
143207
}
144208

@@ -188,21 +252,16 @@ void Surface::loadScr(const std::string &filename)
188252
void Surface::loadImage(const std::string &filename)
189253
{
190254
// Destroy current surface (will be replaced)
191-
#ifdef _WIN32
192-
if (_alignedBuffer) _aligned_free(_alignedBuffer);
193-
#else
194-
if (_alignedBuffer) free(_alignedBuffer);
195-
#endif
196-
_alignedBuffer = 0;
255+
DeleteAligned(_alignedBuffer);
197256
SDL_FreeSurface(_surface);
257+
_alignedBuffer = 0;
198258
_surface = 0;
199-
_misalignedPixelBuffer = 0;
200-
259+
201260
// SDL only takes UTF-8 filenames
202261
// so here's an ugly hack to match this ugly reasoning
203262
std::wstring wstr = Language::cpToWstr(filename);
204263
std::string utf8 = Language::wstrToUtf8(wstr);
205-
264+
206265
// Load file
207266
_surface = IMG_Load(utf8.c_str());
208267
if (!_surface)

‎src/Engine/Surface.h‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ class Surface
4343
SDL_Rect _crop;
4444
bool _visible, _hidden, _redraw;
4545
SDL_Color *_originalColors;
46-
void *_misalignedPixelBuffer, *_alignedBuffer;
46+
void *_alignedBuffer;
4747
int _dx, _dy;
4848
std::string _tooltip;
4949
public:

0 commit comments

Comments
 (0)