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