drawbuf pixel storage optimizations - don't use GC: #499

This commit is contained in:
Vadim Lopatin 2017-10-19 14:21:25 +03:00
parent 513a98a332
commit 62ceed2870
2 changed files with 86 additions and 13 deletions

View File

@ -643,3 +643,76 @@ dstring normalizeEndOfLineCharacters(dstring s) {
} }
return cast(dstring)res; return cast(dstring)res;
} }
/// C malloc allocated array wrapper
struct MallocBuf(T) {
import core.stdc.stdlib : realloc, free;
private T * _allocated;
private uint _allocatedSize;
private uint _length;
/// get pointer
@property T * ptr() { return _allocated; }
/// get length
@property uint length() { return _length; }
/// set new length
@property void length(uint len) {
if (len > _allocatedSize) {
reserve(_allocatedSize ? len * 2 : len);
}
_length = len;
}
/// const array[index];
T opIndex(uint index) const {
assert(index < _length);
return _allocated[index];
}
/// ref array[index];
ref T opIndex(uint index) {
assert(index < _length);
return _allocated[index];
}
/// array[index] = value;
void opIndexAssign(uint index, T value) {
assert(index < _length);
_allocated[index] = value;
}
/// array[index] = value;
void opIndexAssign(uint index, T[] values) {
assert(index + values.length < _length);
_allocated[index .. index + values.length] = values[];
}
/// array[a..b]
T[] opSlice(uint a, uint b) {
assert(a <= b && b <= _length);
return _allocated[a .. b];
}
/// array[]
T[] opSlice() {
return _allocated ? _allocated[0 .. _length] : null;
}
/// array[$]
uint opDollar() { return _length; }
~this() {
clear();
}
/// free allocated memory, set length to 0
void clear() {
if (_allocated)
free(_allocated);
_allocatedSize = 0;
_length = 0;
}
/// make sure buffer capacity is at least (size) items
void reserve(uint size) {
if (_allocatedSize < size) {
_allocated = cast(T*)realloc(_allocated, T.sizeof * size);
_allocatedSize = size;
}
}
/// fill buffer with specified value
void fill(T value) {
if (_length) {
_allocated[0 .. _length] = value;
}
}
}

View File

@ -1233,14 +1233,15 @@ class ColorDrawBufBase : DrawBuf {
} }
class GrayDrawBuf : DrawBuf { class GrayDrawBuf : DrawBuf {
int _dx; protected int _dx;
int _dy; protected int _dy;
/// returns buffer bits per pixel /// returns buffer bits per pixel
override @property int bpp() { return 8; } override @property int bpp() { return 8; }
@property override int width() { return _dx; } @property override int width() { return _dx; }
@property override int height() { return _dy; } @property override int height() { return _dy; }
ubyte[] _buf; protected MallocBuf!ubyte _buf;
this(int width, int height) { this(int width, int height) {
resize(width, height); resize(width, height);
} }
@ -1473,7 +1474,7 @@ class GrayDrawBuf : DrawBuf {
} }
class ColorDrawBuf : ColorDrawBufBase { class ColorDrawBuf : ColorDrawBufBase {
uint[] _buf; protected MallocBuf!uint _buf;
/// create ARGB8888 draw buf of specified width and height /// create ARGB8888 draw buf of specified width and height
this(int width, int height) { this(int width, int height) {
@ -1482,9 +1483,8 @@ class ColorDrawBuf : ColorDrawBufBase {
/// create copy of ColorDrawBuf /// create copy of ColorDrawBuf
this(ColorDrawBuf v) { this(ColorDrawBuf v) {
this(v.width, v.height); this(v.width, v.height);
//_buf.length = v._buf.length; if (auto len = _buf.length)
foreach(i; 0 .. _buf.length) _buf.ptr[0 .. len] = v._buf.ptr[0 .. len];
_buf[i] = v._buf[i];
} }
/// create resized copy of ColorDrawBuf /// create resized copy of ColorDrawBuf
this(ColorDrawBuf v, int dx, int dy) { this(ColorDrawBuf v, int dx, int dy) {
@ -1494,7 +1494,7 @@ class ColorDrawBuf : ColorDrawBufBase {
} }
void invertAndPreMultiplyAlpha() { void invertAndPreMultiplyAlpha() {
foreach(ref pixel; _buf) { foreach(ref pixel; _buf[]) {
uint a = (pixel >> 24) & 0xFF; uint a = (pixel >> 24) & 0xFF;
uint r = (pixel >> 16) & 0xFF; uint r = (pixel >> 16) & 0xFF;
uint g = (pixel >> 8) & 0xFF; uint g = (pixel >> 8) & 0xFF;
@ -1510,12 +1510,12 @@ class ColorDrawBuf : ColorDrawBufBase {
} }
void invertAlpha() { void invertAlpha() {
foreach(ref pixel; _buf) foreach(ref pixel; _buf[])
pixel ^= 0xFF000000; pixel ^= 0xFF000000;
} }
void invertByteOrder() { void invertByteOrder() {
foreach(ref pixel; _buf) { foreach(ref pixel; _buf[]) {
pixel = (pixel & 0xFF00FF00) | pixel = (pixel & 0xFF00FF00) |
((pixel & 0xFF0000) >> 16) | ((pixel & 0xFF0000) >> 16) |
((pixel & 0xFF) << 16); ((pixel & 0xFF) << 16);
@ -1524,7 +1524,7 @@ class ColorDrawBuf : ColorDrawBufBase {
// for passing of image to OpenGL texture // for passing of image to OpenGL texture
void invertAlphaAndByteOrder() { void invertAlphaAndByteOrder() {
foreach(ref pixel; _buf) { foreach(ref pixel; _buf[]) {
pixel = ((pixel & 0xFF00FF00) | pixel = ((pixel & 0xFF00FF00) |
((pixel & 0xFF0000) >> 16) | ((pixel & 0xFF0000) >> 16) |
((pixel & 0xFF) << 16)); ((pixel & 0xFF) << 16));
@ -1643,9 +1643,9 @@ class ColorDrawBuf : ColorDrawBufBase {
uint[] tmpbuf; uint[] tmpbuf;
tmpbuf.length = _buf.length; tmpbuf.length = _buf.length;
// do horizontal blur // do horizontal blur
blurOneDimension(_buf, tmpbuf, blurSize, true); blurOneDimension(_buf[], tmpbuf, blurSize, true);
// then do vertical blur // then do vertical blur
blurOneDimension(tmpbuf, _buf, blurSize, false); blurOneDimension(tmpbuf, _buf[], blurSize, false);
} }
} }