Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make DynamicFormat and Bitmap formats_map constexpr #1960

Merged
merged 2 commits into from Dec 13, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
103 changes: 51 additions & 52 deletions src/bitmap.cpp
Expand Up @@ -386,42 +386,41 @@ Rect Bitmap::TransformRectangle(const Transform& xform, const Rect& rect) {
return Rect(bounds.x1, bounds.y1, bounds.x2 - bounds.x1, bounds.y2 - bounds.y1);
}

static constexpr std::array<std::pair<int,pixman_format_code_t>, 27> formats_map = {{
{ DynamicFormat(32,8,24,8,16,8,8,8,0,PF::Alpha).code_alpha(), PIXMAN_r8g8b8a8 },
{ DynamicFormat(32,8,24,8,16,8,8,8,0,PF::NoAlpha).code_alpha(), PIXMAN_r8g8b8x8 },

{ DynamicFormat(32,8,16,8,8,8,0,8,24,PF::Alpha).code_alpha(), PIXMAN_a8r8g8b8 },
{ DynamicFormat(32,8,16,8,8,8,0,0,0,PF::NoAlpha).code_alpha(), PIXMAN_x8r8g8b8 },
{ DynamicFormat(32,8,0,8,8,8,16,8,24,PF::Alpha).code_alpha(), PIXMAN_a8b8g8r8 },
{ DynamicFormat(32,8,0,8,8,8,16,0,0,PF::NoAlpha).code_alpha(), PIXMAN_x8b8g8r8 },
{ DynamicFormat(32,8,8,8,16,8,24,8,0,PF::Alpha).code_alpha(), PIXMAN_b8g8r8a8 },
{ DynamicFormat(32,8,8,8,16,8,24,0,0,PF::NoAlpha).code_alpha(), PIXMAN_b8g8r8x8 },

{ DynamicFormat(32,6,12,6,6,6,0,0,0,PF::NoAlpha).code_alpha(), PIXMAN_x14r6g6b6 },
{ DynamicFormat(32,10,20,10,10,10,0,0,0,PF::NoAlpha).code_alpha(), PIXMAN_x2r10g10b10 },
{ DynamicFormat(32,10,20,10,10,10,0,2,30,PF::Alpha).code_alpha(), PIXMAN_a2r10g10b10 },
{ DynamicFormat(32,10,0,10,10,10,20,0,0,PF::NoAlpha).code_alpha(), PIXMAN_x2b10g10r10 },
{ DynamicFormat(32,10,0,10,10,10,20,2,30,PF::Alpha).code_alpha(), PIXMAN_a2b10g10r10 },

{ DynamicFormat(24,8,16,8,8,8,0,0,0,PF::NoAlpha).code_alpha(), PIXMAN_r8g8b8 },
{ DynamicFormat(24,8,0,8,8,8,16,0,0,PF::NoAlpha).code_alpha(), PIXMAN_b8g8r8 },

{ DynamicFormat(16,5,11,6,5,5,0,0,0,PF::NoAlpha).code_alpha(), PIXMAN_r5g6b5 },
{ DynamicFormat(16,5,0,6,5,5,11,0,0,PF::NoAlpha).code_alpha(), PIXMAN_b5g6r5 },
{ DynamicFormat(16,5,10,5,5,5,0,1,15,PF::Alpha).code_alpha(), PIXMAN_a1r5g5b5 },
{ DynamicFormat(16,5,10,5,5,5,0,0,0,PF::NoAlpha).code_alpha(), PIXMAN_x1r5g5b5 },
{ DynamicFormat(16,5,0,5,5,5,10,1,15,PF::Alpha).code_alpha(), PIXMAN_a1b5g5r5 },
{ DynamicFormat(16,5,0,5,5,5,10,0,0,PF::NoAlpha).code_alpha(), PIXMAN_x1b5g5r5 },
{ DynamicFormat(16,4,8,4,4,4,0,4,12,PF::Alpha).code_alpha(), PIXMAN_a4r4g4b4 },
{ DynamicFormat(16,4,8,4,4,4,0,0,0,PF::NoAlpha).code_alpha(), PIXMAN_x4r4g4b4 },
{ DynamicFormat(16,4,0,4,4,4,8,4,12,PF::Alpha).code_alpha(), PIXMAN_a4b4g4r4 },
{ DynamicFormat(16,4,0,4,4,4,8,0,0,PF::NoAlpha).code_alpha(), PIXMAN_x4b4g4r4 },
{ DynamicFormat(8,8,0,8,0,8,0,8,0,PF::Alpha).code_alpha(), PIXMAN_g8 },
{ DynamicFormat(8,8,0,8,0,8,0,0,0,PF::NoAlpha).code_alpha(), PIXMAN_g8 }
}};

pixman_format_code_t Bitmap::find_format(const DynamicFormat& format) {
static std::array<std::pair<int,pixman_format_code_t>, 27> formats_map = {{
{ DynamicFormat(32,8,24,8,16,8,8,8,0,PF::Alpha).code_alpha(), PIXMAN_r8g8b8a8 },
{ DynamicFormat(32,8,24,8,16,8,8,8,0,PF::NoAlpha).code_alpha(), PIXMAN_r8g8b8x8 },

{ DynamicFormat(32,8,16,8,8,8,0,8,24,PF::Alpha).code_alpha(), PIXMAN_a8r8g8b8 },
{ DynamicFormat(32,8,16,8,8,8,0,0,0,PF::NoAlpha).code_alpha(), PIXMAN_x8r8g8b8 },
{ DynamicFormat(32,8,0,8,8,8,16,8,24,PF::Alpha).code_alpha(), PIXMAN_a8b8g8r8 },
{ DynamicFormat(32,8,0,8,8,8,16,0,0,PF::NoAlpha).code_alpha(), PIXMAN_x8b8g8r8 },
{ DynamicFormat(32,8,8,8,16,8,24,8,0,PF::Alpha).code_alpha(), PIXMAN_b8g8r8a8 },
{ DynamicFormat(32,8,8,8,16,8,24,0,0,PF::NoAlpha).code_alpha(), PIXMAN_b8g8r8x8 },

{ DynamicFormat(32,6,12,6,6,6,0,0,0,PF::NoAlpha).code_alpha(), PIXMAN_x14r6g6b6 },
{ DynamicFormat(32,10,20,10,10,10,0,0,0,PF::NoAlpha).code_alpha(), PIXMAN_x2r10g10b10 },
{ DynamicFormat(32,10,20,10,10,10,0,2,30,PF::Alpha).code_alpha(), PIXMAN_a2r10g10b10 },
{ DynamicFormat(32,10,0,10,10,10,20,0,0,PF::NoAlpha).code_alpha(), PIXMAN_x2b10g10r10 },
{ DynamicFormat(32,10,0,10,10,10,20,2,30,PF::Alpha).code_alpha(), PIXMAN_a2b10g10r10 },

{ DynamicFormat(24,8,16,8,8,8,0,0,0,PF::NoAlpha).code_alpha(), PIXMAN_r8g8b8 },
{ DynamicFormat(24,8,0,8,8,8,16,0,0,PF::NoAlpha).code_alpha(), PIXMAN_b8g8r8 },

{ DynamicFormat(16,5,11,6,5,5,0,0,0,PF::NoAlpha).code_alpha(), PIXMAN_r5g6b5 },
{ DynamicFormat(16,5,0,6,5,5,11,0,0,PF::NoAlpha).code_alpha(), PIXMAN_b5g6r5 },
{ DynamicFormat(16,5,10,5,5,5,0,1,15,PF::Alpha).code_alpha(), PIXMAN_a1r5g5b5 },
{ DynamicFormat(16,5,10,5,5,5,0,0,0,PF::NoAlpha).code_alpha(), PIXMAN_x1r5g5b5 },
{ DynamicFormat(16,5,0,5,5,5,10,1,15,PF::Alpha).code_alpha(), PIXMAN_a1b5g5r5 },
{ DynamicFormat(16,5,0,5,5,5,10,0,0,PF::NoAlpha).code_alpha(), PIXMAN_x1b5g5r5 },
{ DynamicFormat(16,4,8,4,4,4,0,4,12,PF::Alpha).code_alpha(), PIXMAN_a4r4g4b4 },
{ DynamicFormat(16,4,8,4,4,4,0,0,0,PF::NoAlpha).code_alpha(), PIXMAN_x4r4g4b4 },
{ DynamicFormat(16,4,0,4,4,4,8,4,12,PF::Alpha).code_alpha(), PIXMAN_a4b4g4r4 },
{ DynamicFormat(16,4,0,4,4,4,8,0,0,PF::NoAlpha).code_alpha(), PIXMAN_x4b4g4r4 },
{ DynamicFormat(8,8,0,8,0,8,0,8,0,PF::Alpha).code_alpha(), PIXMAN_g8 },
{ DynamicFormat(8,8,0,8,0,8,0,0,0,PF::NoAlpha).code_alpha(), PIXMAN_g8 }
}};

auto dcode = format.code_alpha();
auto iter = std::find_if(formats_map.begin(), formats_map.end(), [dcode](const auto& p) { return p.first == dcode; });
if (iter == formats_map.end()) {
Expand Down Expand Up @@ -804,21 +803,28 @@ void Bitmap::ClearRect(Rect const& dst_rect) {
}

// Hard light lookup table mapping source color to destination color
static uint8_t hard_light_lookup[256][256];
// FIXME: Replace this with std::array<std::array<uint8_t,256>,256> when we have C++17
struct HardLightTable {
uint8_t table[256][256] = {};
};

static void make_hard_light_lookup() {
static constexpr HardLightTable make_hard_light_lookup() {
HardLightTable hl;
for (int i = 0; i < 256; ++i) {
for (int j = 0; j < 256; ++j) {
int res = 0;
if (i <= 128)
res = (2 * i * j) / 255;
else
res = 255 - 2 * (255 - i) * (255 - j) / 255;
hard_light_lookup[i][j] = res > 255 ? 255 : res < 0 ? 0 : res;
hl.table[i][j] = res > 255 ? 255 : res < 0 ? 0 : res;
}
}
return hl;
}

constexpr auto hard_light = make_hard_light_lookup();

// Saturation Tone Inline: Changes a pixel saturation
static inline void saturation_tone(uint32_t &src_pixel, int saturation, int rs, int gs, int bs, int as) {
// Algorithm from OpenPDN (MIT license)
Expand All @@ -843,10 +849,10 @@ static inline void saturation_tone(uint32_t &src_pixel, int saturation, int rs,
}

// Color Tone Inline: Changes color of a pixel by hard light table
static inline void color_tone(uint32_t &src_pixel, Tone tone, uint8_t hard_light_lookup[256][256], int rs, int gs, int bs, int as) {
src_pixel = ((uint32_t)hard_light_lookup[tone.red][(src_pixel >> rs) & 0xFF] << rs)
| ((uint32_t)hard_light_lookup[tone.green][(src_pixel >> gs) & 0xFF] << gs)
| ((uint32_t)hard_light_lookup[tone.blue][(src_pixel >> bs) & 0xFF] << bs)
static inline void color_tone(uint32_t &src_pixel, Tone tone, int rs, int gs, int bs, int as) {
src_pixel = ((uint32_t)hard_light.table[tone.red][(src_pixel >> rs) & 0xFF] << rs)
| ((uint32_t)hard_light.table[tone.green][(src_pixel >> gs) & 0xFF] << gs)
| ((uint32_t)hard_light.table[tone.blue][(src_pixel >> bs) & 0xFF] << bs)
| ((uint32_t)((src_pixel >> as) & 0xFF) << as);
}

Expand All @@ -871,13 +877,6 @@ void Bitmap::ToneBlit(int x, int y, Bitmap const& src, Rect const& src_rect, con
x, y,
src_rect.width, src_rect.height);

// To implement Saturation and Color:
static bool index_made = false;
if (!index_made) {
make_hard_light_lookup();
index_made = true;
}

int as = pixel_format.a.shift;
int rs = pixel_format.r.shift;
int gs = pixel_format.g.shift;
Expand All @@ -901,7 +900,7 @@ void Bitmap::ToneBlit(int x, int y, Bitmap const& src, Rect const& src_rect, con
continue;

saturation_tone(pixels[j], sat, rs, gs, bs, as);
color_tone(pixels[j], tone, hard_light_lookup, rs, gs, bs, as);
color_tone(pixels[j], tone, rs, gs, bs, as);
}
}
}
Expand All @@ -910,7 +909,7 @@ void Bitmap::ToneBlit(int x, int y, Bitmap const& src, Rect const& src_rect, con
pixels += next_row;
for (uint16_t j = 0; j < limit_width; ++j) {
saturation_tone(pixels[j], sat, rs, gs, bs, as);
color_tone(pixels[j], tone, hard_light_lookup, rs, gs, bs, as);
color_tone(pixels[j], tone, rs, gs, bs, as);
}
}
}
Expand Down Expand Up @@ -950,15 +949,15 @@ void Bitmap::ToneBlit(int x, int y, Bitmap const& src, Rect const& src_rect, con
if ((uint8_t)((pixels[j] >> as) & 0xFF) == 0)
continue;

color_tone(pixels[j], tone, hard_light_lookup, rs, gs, bs, as);
color_tone(pixels[j], tone, rs, gs, bs, as);
}
}
}
else {
for (uint16_t i = 0; i < limit_height; ++i) {
pixels += next_row;
for (uint16_t j = 0; j < limit_width; ++j) {
color_tone(pixels[j], tone, hard_light_lookup, rs, gs, bs, as);
color_tone(pixels[j], tone, rs, gs, bs, as);
}
}
}
Expand Down
56 changes: 28 additions & 28 deletions src/pixel_format.h
Expand Up @@ -37,12 +37,12 @@ namespace PF {

/** Component struct */
struct Component {
uint8_t bits;
uint8_t shift;
uint8_t byte;
uint32_t mask;
uint8_t bits = 0;
uint8_t shift = 0;
uint8_t byte = 0;
uint32_t mask = 0;

static inline int count_bits(uint32_t mask) {
static constexpr int count_bits(uint32_t mask) {
int count = 0;
if ((mask & 0xFFFF0000) != 0)
count += 16, mask >>= 16;
Expand All @@ -59,7 +59,7 @@ struct Component {
return count;
}

inline void convert_mask() {
constexpr void convert_mask() {
int bit_count = count_bits(mask);
uint32_t mask_ex = (~0U >> (32 - bit_count));
uint32_t mask_lo = mask_ex - mask;
Expand All @@ -68,31 +68,31 @@ struct Component {
byte = shift / 8;
}

inline bool operator==(const Component& c) {
constexpr bool operator==(const Component& c) {
return mask == c.mask;
}

inline bool operator!=(const Component& c) {
constexpr bool operator!=(const Component& c) {
return mask != c.mask;
}

inline uint8_t unpack(uint32_t pix) const {
constexpr uint8_t unpack(uint32_t pix) const {
return (uint8_t)(((pix >> shift) & ((1 << bits) - 1)) << (8 - bits));
}

inline uint32_t pack(const uint8_t& x) const {
constexpr uint32_t pack(const uint8_t& x) const {
return (((uint32_t)x >> (8 - bits)) << shift);
}

Component() {}
constexpr Component() {}

Component(unsigned int bits, unsigned int shift) :
constexpr Component(unsigned int bits, unsigned int shift) :
bits((uint8_t)bits),
shift((uint8_t)shift),
byte((uint8_t)(shift / 8)),
mask(((1 << bits)-1) << shift) {}

Component(uint32_t mask) :
constexpr Component(uint32_t mask) :
mask(mask) { convert_mask(); }
};

Expand All @@ -101,14 +101,14 @@ struct Component {
*/
class DynamicFormat {
public:
int bits;
int bytes;
int bits = 0;
int bytes = 0;
Component r, g, b, a;
PF::AlphaType alpha_type;
PF::AlphaType alpha_type = PF::NoAlpha;

DynamicFormat() {}
constexpr DynamicFormat() {}

DynamicFormat(int bits,
constexpr DynamicFormat(int bits,
int rb, int rs,
int gb, int gs,
int bb, int bs,
Expand All @@ -118,7 +118,7 @@ class DynamicFormat {
r(rb, rs), g(gb, gs), b(bb, bs), a(ab, as),
alpha_type(alpha_type) {}

DynamicFormat(int bits,
constexpr DynamicFormat(int bits,
uint32_t rmask,
uint32_t gmask,
uint32_t bmask,
Expand All @@ -128,12 +128,12 @@ class DynamicFormat {
r(rmask), g(gmask), b(bmask), a(amask),
alpha_type(alpha_type) {}

DynamicFormat(const DynamicFormat& ref) :
constexpr DynamicFormat(const DynamicFormat& ref) :
bits(ref.bits), bytes((bits + 7) / 8),
r(ref.r), g(ref.g), b(ref.b), a(ref.a),
alpha_type(ref.alpha_type) {}

void Set(int _bits,
constexpr void Set(int _bits,
int rb, int rs,
int gb, int gs,
int bb, int bs,
Expand All @@ -148,7 +148,7 @@ class DynamicFormat {
alpha_type = _alpha_type;
}

void Set(int _bits,
constexpr void Set(int _bits,
uint32_t rmask,
uint32_t gmask,
uint32_t bmask,
Expand All @@ -163,7 +163,7 @@ class DynamicFormat {
alpha_type = _alpha_type;
}

inline int code(bool shifts) const {
constexpr int code(bool shifts) const {
int x = (int) alpha_type | ((bits - 1) << 2);
if (!shifts)
return x;
Expand All @@ -173,7 +173,7 @@ class DynamicFormat {
(b.shift << 17);
}

inline int code_alpha() const {
constexpr int code_alpha() const {
int x = (int) (alpha_type == PF::Alpha ? PF::Alpha : PF::NoAlpha) | ((bits - 1) << 2);
return x |
(r.shift << 7) |
Expand All @@ -182,22 +182,22 @@ class DynamicFormat {
(alpha_type == PF::Alpha ? (a.shift << 22) : 0);
}

inline void uint32_to_rgba(uint32_t pix, uint8_t& _r, uint8_t& _g, uint8_t& _b, uint8_t& _a) const {
constexpr void uint32_to_rgba(uint32_t pix, uint8_t& _r, uint8_t& _g, uint8_t& _b, uint8_t& _a) const {
_r = r.unpack(pix);
_g = g.unpack(pix);
_b = b.unpack(pix);
_a = a.unpack(pix);
}

inline uint32_t rgba_to_uint32_t(const uint8_t& _r, const uint8_t& _g, const uint8_t& _b, const uint8_t& _a) const {
constexpr uint32_t rgba_to_uint32_t(const uint8_t& _r, const uint8_t& _g, const uint8_t& _b, const uint8_t& _a) const {
return r.pack(_r) | g.pack(_g) | b.pack(_b) | a.pack(_a);
}

inline bool operator==(const DynamicFormat& f) {
constexpr bool operator==(const DynamicFormat& f) {
return r == f.r && g == f.g && b == f.b && a == f.a && alpha_type == f.alpha_type;
}

inline bool operator!=(const DynamicFormat& f) {
constexpr bool operator!=(const DynamicFormat& f) {
return r != f.r || g != f.g || b != f.b || a != f.a || alpha_type != f.alpha_type;
}
};
Expand Down