diff --git a/Makefile.am b/Makefile.am index aa70ded..642ec60 100644 --- a/Makefile.am +++ b/Makefile.am @@ -21,7 +21,9 @@ i3lock_CFLAGS = \ $(XCB_UTIL_CFLAGS) \ $(XKBCOMMON_CFLAGS) \ $(CAIRO_CFLAGS) \ - $(CODE_COVERAGE_CFLAGS) + $(CODE_COVERAGE_CFLAGS) \ + $(X11_CFLAGS) \ + $(SIMD_CFLAGS) i3lock_CPPFLAGS = \ $(AM_CPPFLAGS) \ @@ -33,7 +35,8 @@ i3lock_LDADD = \ $(XCB_UTIL_LIBS) \ $(XKBCOMMON_LIBS) \ $(CAIRO_LIBS) \ - $(CODE_COVERAGE_LDFLAGS) + $(CODE_COVERAGE_LDFLAGS) \ + $(X11_LIBS) i3lock_SOURCES = \ cursors.h \ @@ -44,7 +47,13 @@ i3lock_SOURCES = \ unlock_indicator.c \ unlock_indicator.h \ xcb.c \ - xcb.h + xcb.h \ + tinyexpr.c \ + tinyexpr.h \ + blur_simd.c \ + blur.c \ + blur.h + EXTRA_DIST = \ $(pamd_files) \ diff --git a/blur.c b/blur.c index 1838df4..a63751e 100644 --- a/blur.c +++ b/blur.c @@ -65,7 +65,7 @@ blur_image_surface (cairo_surface_t *surface, int sigma) // according to a paper by Peter Kovesi [1], box filter of width w, equals to Gaussian blur of following sigma: // σ_av = sqrt((w*w-1)/12) - // for our 7x7 filter we have σ_av = 2.0. + // for our 8x8 filter we have σ_av = 2.0. // applying the same Gaussian filter n times results in σ_n = sqrt(n*σ_av*σ_av) [2] // after some trivial math, we arrive at n = ((σ_d)/(σ_av))^2 // since it's a box blur filter, n >= 3 diff --git a/blur.h b/blur.h index dfc1c3d..2c42fd5 100644 --- a/blur.h +++ b/blur.h @@ -4,7 +4,7 @@ #include #include -#define KERNEL_SIZE 7 +#define KERNEL_SIZE 8 #define SIGMA_AV 2 #define HALF_KERNEL KERNEL_SIZE / 2 diff --git a/blur_simd.c b/blur_simd.c index b654e98..48c3fba 100644 --- a/blur_simd.c +++ b/blur_simd.c @@ -10,24 +10,30 @@ #include "blur.h" #include +#include + // number of xmm registers needed to store input pixels for given kernel size #define REGISTERS_CNT (KERNEL_SIZE + 4/2) / 4 void blur_impl_horizontal_pass_sse2(uint32_t *src, uint32_t *dst, int width, int height) { + printf("height %d by width %d\n", height, width); for (int row = 0; row < height; row++) { + printf("row %d\n", row); for (int column = 0; column < width; column++, src++) { + printf("\tcol %d\n", column); __m128i rgbaIn[REGISTERS_CNT]; // handle borders int leftBorder = column < HALF_KERNEL; - int rightBorder = column > width - HALF_KERNEL; + int rightBorder = column > (width - HALF_KERNEL); + // +1 to make memory checkers not complain uint32_t _rgbaIn[KERNEL_SIZE] __attribute__((aligned(16))); int i = 0; if (leftBorder) { - // for kernel size 7x7 and column == 0, we have: - // x x x P0 P1 P2 P3 - // first loop mirrors P{0..3} to fill x's, - // second one loads P{0..3} + // for kernel size 8x8 and column == 0, we have: + // x x x x P0 P1 P2 P3 + // first loop mirrors P{0..4} to fill x's, + // second one loads P{0..4} for (; i < HALF_KERNEL - column; i++) _rgbaIn[i] = *(src + (HALF_KERNEL - i)); for (; i < KERNEL_SIZE; i++) @@ -44,8 +50,10 @@ void blur_impl_horizontal_pass_sse2(uint32_t *src, uint32_t *dst, int width, int for (int k = 0; k < REGISTERS_CNT; k++) rgbaIn[k] = _mm_load_si128((__m128i*)(_rgbaIn + 4*k)); } else { - for (int k = 0; k < REGISTERS_CNT; k++) - rgbaIn[k] = _mm_loadu_si128((__m128i*)(src + 4*k - HALF_KERNEL)); + for (int k = 0; k < REGISTERS_CNT; k++) { + printf("\t\tk: %d\n", k); + rgbaIn[k] = _mm_load_si128((__m128i*)(src + 4*k - HALF_KERNEL)); + } } __m128i zero = _mm_setzero_si128(); @@ -57,10 +65,12 @@ void blur_impl_horizontal_pass_sse2(uint32_t *src, uint32_t *dst, int width, int // kernel size equals to 7, but we can only load multiples of 4 pixels // we have to set 8th pixel to zero +/* acc = _mm_add_epi16(acc, _mm_andnot_si128(_mm_set_epi32(0xFFFFFFFF, 0xFFFFFFFF, 0, 0), _mm_unpackhi_epi8(rgbaIn[1], zero))); acc = _mm_add_epi32(_mm_unpacklo_epi16(acc, zero), _mm_unpackhi_epi16(acc, zero)); +*/ // multiplication is significantly faster than division acc = _mm_cvtps_epi32(_mm_mul_ps(_mm_cvtepi32_ps(acc), diff --git a/configure.ac b/configure.ac index d4bceb0..687c3a5 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ # Run autoreconf -fi to generate a configure script from this file. AC_PREREQ([2.69]) -AC_INIT([i3lock], [2.10], [https://github.com/i3/i3lock/issues]) +AC_INIT([i3lock-color], [2.10], [https://github.com/chrjguill/i3lock-color/issues]) # For AX_EXTEND_SRCDIR AX_ENABLE_BUILDDIR AM_INIT_AUTOMAKE([foreign subdir-objects -Wall no-dist-gzip dist-bzip2]) @@ -34,7 +34,7 @@ AS_IF([test -d ${srcdir}/.git], VERSION="$(git -C ${srcdir} describe --tags --abbrev=0)" I3LOCK_VERSION="$(git -C ${srcdir} describe --tags --always) ($(git -C ${srcdir} log --pretty=format:%cd --date=short -n1), branch \\\"$(git -C ${srcdir} describe --tags --always --all | sed s:heads/::)\\\")" # Mirrors what libi3/is_debug_build.c does: - is_release=$(test $(echo "${I3LOCK_VERSION}" | cut -d '(' -f 1 | wc -m) -lt 10 && echo yes || echo no) + is_release=$(test $(echo "${I3LOCK_VERSION}" | cut -d '(' -f 1 | wc -m) -lt 11 && echo yes || echo no) ], [ VERSION="$(cut -d '-' -f 1 ${srcdir}/I3LOCK_VERSION | cut -d ' ' -f 1)" @@ -82,11 +82,14 @@ AC_SEARCH_LIBS([iconv_open], [iconv], , [AC_MSG_FAILURE([cannot find the require dnl Each prefix corresponds to a source tarball which users might have dnl downloaded in a newer version and would like to overwrite. -PKG_CHECK_MODULES([XCB], [xcb xcb-xkb xcb-xinerama xcb-randr]) +PKG_CHECK_MODULES([XCB], [xcb xcb-xkb xcb-xinerama xcb-randr xcb-composite]) PKG_CHECK_MODULES([XCB_IMAGE], [xcb-image]) PKG_CHECK_MODULES([XCB_UTIL], [xcb-event xcb-util xcb-atom]) PKG_CHECK_MODULES([XKBCOMMON], [xkbcommon xkbcommon-x11]) PKG_CHECK_MODULES([CAIRO], [cairo]) +PKG_CHECK_MODULES([X11], [x11]) + +SIMD_CFLAGS=" -funroll-loops -msse2 -std=c99 -pipe -O2" # Checks for programs. AC_PROG_AWK diff --git a/unlock_indicator.c b/unlock_indicator.c index fd8be65..ef37936 100644 --- a/unlock_indicator.c +++ b/unlock_indicator.c @@ -145,22 +145,22 @@ unlock_state_t unlock_state; auth_state_t auth_state; // color arrays -rgba_t insidever16[4]; -rgba_t insidewrong16[4]; -rgba_t inside16[4]; -rgba_t ringver16[4]; -rgba_t ringwrong16[4]; -rgba_t ring16[4]; -rgba_t line16[4]; -rgba_t text16[4]; -rgba_t layout16[4]; -rgba_t time16[4]; -rgba_t date16[4]; -rgba_t keyhl16[4]; -rgba_t bshl16[4]; -rgba_t sep16[4]; +rgba_t insidever16; +rgba_t insidewrong16; +rgba_t inside16; +rgba_t ringver16; +rgba_t ringwrong16; +rgba_t ring16; +rgba_t line16; +rgba_t text16; +rgba_t layout16; +rgba_t time16; +rgba_t date16; +rgba_t keyhl16; +rgba_t bshl16; +rgba_t sep16; // just rgb -rgb_t rgb16[3]; +rgb_t rgb16; /* * Initialize all the color arrays once. @@ -182,32 +182,32 @@ rgb_t rgb16[3]; (strtol(colorstring_tmparr[3], NULL, 16))}; */ -inline void set_color(char* dest, const char* src, int offset) { +void set_color(char* dest, const char* src, int offset) { dest[0] = src[offset]; dest[1] = src[offset + 1]; dest[2] = '\0'; } -inline void colorgen(rgba_str_t* tmp, const char* src, rgba_t* dest) { +void colorgen(rgba_str_t* tmp, const char* src, rgba_t* dest) { set_color(tmp->red, src, 0); set_color(tmp->green, src, 2); set_color(tmp->blue, src, 4); set_color(tmp->alpha, src, 6); - dest->red = strtol(tmp->red, NULL, 16); - dest->green = strtol(tmp->green, NULL, 16); - dest->blue = strtol(tmp->blue, NULL, 16); - dest->alpha = strtol(tmp->alpha, NULL, 16); + dest->red = strtol(tmp->red, NULL, 16) / 255.0; + dest->green = strtol(tmp->green, NULL, 16) / 255.0; + dest->blue = strtol(tmp->blue, NULL, 16) / 255.0; + dest->alpha = strtol(tmp->alpha, NULL, 16) / 255.0; } -inline void colorgen_rgb(rgb_str_t* tmp, const char* src, rgb_t* dest) { +void colorgen_rgb(rgb_str_t* tmp, const char* src, rgb_t* dest) { set_color(tmp->red, src, 0); set_color(tmp->green, src, 2); set_color(tmp->blue, src, 4); - dest->red = strtol(tmp->red, NULL, 16); - dest->green = strtol(tmp->green, NULL, 16); - dest->blue = strtol(tmp->blue, NULL, 16); + dest->red = strtol(tmp->red, NULL, 16) / 255.0; + dest->green = strtol(tmp->green, NULL, 16) / 255.0; + dest->blue = strtol(tmp->blue, NULL, 16) / 255.0; } void init_colors_once(void) { @@ -215,21 +215,21 @@ void init_colors_once(void) { rgb_str_t tmp_rgb; /* build indicator color arrays */ - colorgen(&tmp, insidevercolor, insidever16); - colorgen(&tmp, insidewrongcolor, insidewrong16); - colorgen(&tmp, insidecolor, inside16); - colorgen(&tmp, ringvercolor, ringver16); - colorgen(&tmp, ringwrongcolor, ringwrong16); - colorgen(&tmp, ringcolor, ring16); - colorgen(&tmp, linecolor, line16); - colorgen(&tmp, textcolor, text16); - colorgen(&tmp, layoutcolor, layout16); - colorgen(&tmp, timecolor, time16); - colorgen(&tmp, datecolor, date16); - colorgen(&tmp, keyhlcolor, keyhl16); - colorgen(&tmp, bshlcolor, bshl16); - colorgen(&tmp, separatorcolor, sep16); - colorgen_rgb(&tmp_rgb, color, rgb16); + colorgen(&tmp, insidevercolor, &insidever16); + colorgen(&tmp, insidewrongcolor, &insidewrong16); + colorgen(&tmp, insidecolor, &inside16); + colorgen(&tmp, ringvercolor, &ringver16); + colorgen(&tmp, ringwrongcolor, &ringwrong16); + colorgen(&tmp, ringcolor, &ring16); + colorgen(&tmp, linecolor, &line16); + colorgen(&tmp, textcolor, &text16); + colorgen(&tmp, layoutcolor, &layout16); + colorgen(&tmp, timecolor, &time16); + colorgen(&tmp, datecolor, &date16); + colorgen(&tmp, keyhlcolor, &keyhl16); + colorgen(&tmp, bshlcolor, &bshl16); + colorgen(&tmp, separatorcolor, &sep16); + colorgen_rgb(&tmp_rgb, color, &rgb16); } /* @@ -238,8 +238,8 @@ void init_colors_once(void) { * */ static double scaling_factor(void) { - const int dpi = (double)screen->height_in_pixels * 25.4 / - (double)screen->height_in_millimeters; + const int dpi = (double) screen->height_in_pixels * 25.4 / + (double) screen->height_in_millimeters; return (dpi / 96.0); } @@ -301,7 +301,7 @@ xcb_pixmap_t draw_image(uint32_t *resolution) { } } } else { - cairo_set_source_rgb(xcb_ctx, rgb16->red / 255.0, rgb16->green / 255.0, rgb16->blue / 255.0); + cairo_set_source_rgb(xcb_ctx, rgb16.red, rgb16.green, rgb16.blue); cairo_rectangle(xcb_ctx, 0, 0, resolution[0], resolution[1]); cairo_fill(xcb_ctx); } @@ -331,14 +331,14 @@ xcb_pixmap_t draw_image(uint32_t *resolution) { switch (auth_state) { case STATE_AUTH_VERIFY: case STATE_AUTH_LOCK: - cairo_set_source_rgba(ctx, (double)insidever16->red/255, (double)insidever16->green/255, (double)insidever16->blue/255, (double)insidever16->alpha/255); + cairo_set_source_rgba(ctx, insidever16.red, insidever16.green, insidever16.blue, insidever16.alpha); break; case STATE_AUTH_WRONG: case STATE_I3LOCK_LOCK_FAILED: - cairo_set_source_rgba(ctx, (double)insidewrong16->red/255, (double)insidewrong16->green/255, (double)insidewrong16->blue/255, (double)insidewrong16->alpha/255); + cairo_set_source_rgba(ctx, insidewrong16.red, insidewrong16.green, insidewrong16.blue, insidewrong16.alpha); break; default: - cairo_set_source_rgba(ctx, (double)inside16->red/255, (double)inside16->green/255, (double)inside16->blue/255, (double)inside16->alpha/255); + cairo_set_source_rgba(ctx, inside16.red, inside16.green, inside16.blue, inside16.alpha); break; } cairo_fill_preserve(ctx); @@ -346,31 +346,31 @@ xcb_pixmap_t draw_image(uint32_t *resolution) { switch (auth_state) { case STATE_AUTH_VERIFY: case STATE_AUTH_LOCK: - cairo_set_source_rgba(ctx, (double)ringver16->red/255, (double)ringver16->green/255, (double)ringver16->blue/255, (double)ringver16->alpha/255); + cairo_set_source_rgba(ctx, ringver16.red, ringver16.green, ringver16.blue, ringver16.alpha); if (internal_line_source == 1) { - line16->red = ringver16->red; - line16->green = ringver16->green; - line16->blue = ringver16->blue; - line16->alpha = ringver16->alpha; + line16.red = ringver16.red; + line16.green = ringver16.green; + line16.blue = ringver16.blue; + line16.alpha = ringver16.alpha; } break; case STATE_AUTH_WRONG: case STATE_I3LOCK_LOCK_FAILED: - cairo_set_source_rgba(ctx, (double)ringwrong16->red/255, (double)ringwrong16->green/255, (double)ringwrong16->blue/255, (double)ringwrong16->alpha/255); + cairo_set_source_rgba(ctx, ringwrong16.red, ringwrong16.green, ringwrong16.blue, ringwrong16.alpha); if (internal_line_source == 1) { - line16->red = ringwrong16->red; - line16->green = ringwrong16->green; - line16->blue = ringwrong16->blue; - line16->alpha = ringwrong16->alpha; + line16.red = ringwrong16.red; + line16.green = ringwrong16.green; + line16.blue = ringwrong16.blue; + line16.alpha = ringwrong16.alpha; } break; case STATE_AUTH_IDLE: - cairo_set_source_rgba(ctx, (double)ring16->red/255, (double)ring16->green/255, (double)ring16->blue/255, (double)ring16->alpha/255); + cairo_set_source_rgba(ctx, ring16.red, ring16.green, ring16.blue, ring16.alpha); if (internal_line_source == 1) { - line16->red = ring16->red; - line16->green = ring16->green; - line16->blue = ring16->blue; - line16->alpha = ring16->alpha; + line16.red = ring16.red; + line16.green = ring16.green; + line16.blue = ring16.blue; + line16.alpha = ring16.alpha; } break; } @@ -378,7 +378,7 @@ xcb_pixmap_t draw_image(uint32_t *resolution) { /* Draw an inner separator line. */ if (internal_line_source != 2) { //pretty sure this only needs drawn if it's being drawn over the inside? - cairo_set_source_rgba(ctx, (double)line16->red/255, (double)line16->green/255, (double)line16->blue/255, (double)line16->alpha/255); + cairo_set_source_rgba(ctx, line16.red, line16.green, line16.blue, line16.alpha); cairo_set_line_width(ctx, 2.0); cairo_arc(ctx, BUTTON_CENTER /* x */, @@ -397,7 +397,7 @@ xcb_pixmap_t draw_image(uint32_t *resolution) { /* We don't want to show more than a 3-digit number. */ char buf[4]; - cairo_set_source_rgba(ctx, (double)text16->red/255, (double)text16->green/255, (double)text16->blue/255, (double)text16->alpha/255); + cairo_set_source_rgba(ctx, text16.red, text16.green, text16.blue, text16.alpha); cairo_select_font_face(ctx, status_font, CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL); cairo_set_font_size(ctx, text_size); @@ -472,17 +472,17 @@ xcb_pixmap_t draw_image(uint32_t *resolution) { highlight_start + (M_PI / 3.0)); if (unlock_state == STATE_KEY_ACTIVE) { /* For normal keys, we use a lighter green. */ //lol no - cairo_set_source_rgba(ctx, (double)keyhl16->red/255, (double)keyhl16->green/255, (double)keyhl16->blue/255, (double)keyhl16->alpha/255); + cairo_set_source_rgba(ctx, keyhl16.red, keyhl16.green, keyhl16.blue, keyhl16.alpha); } else { /* For backspace, we use red. */ //lol no - cairo_set_source_rgba(ctx, (double)bshl16->red/255, (double)bshl16->green/255, (double)bshl16->blue/255, (double)bshl16->alpha/255); + cairo_set_source_rgba(ctx, bshl16.red, bshl16.green, bshl16.blue, bshl16.alpha); } cairo_stroke(ctx); /* Draw two little separators for the highlighted part of the * unlock indicator. */ - cairo_set_source_rgba(ctx, (double)sep16->red/255, (double)sep16->green/255, (double)sep16->blue/255, (double)sep16->alpha/255); + cairo_set_source_rgba(ctx, sep16.red, sep16.green, sep16.blue, sep16.alpha); cairo_arc(ctx, BUTTON_CENTER /* x */, BUTTON_CENTER /* y */, @@ -517,7 +517,7 @@ xcb_pixmap_t draw_image(uint32_t *resolution) { if (text) { cairo_set_font_size(time_ctx, time_size); cairo_select_font_face(time_ctx, time_font, CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL); - cairo_set_source_rgba(time_ctx, (double)time16->red/255, (double)time16->green/255, (double)time16->blue/255, (double)time16->alpha/255); + cairo_set_source_rgba(time_ctx, time16.red, time16.green, time16.blue, time16.alpha); cairo_text_extents(time_ctx, text, &extents); switch(time_align) { @@ -542,7 +542,7 @@ xcb_pixmap_t draw_image(uint32_t *resolution) { if (date) { cairo_select_font_face(date_ctx, date_font, CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL); - cairo_set_source_rgba(date_ctx, (double)date16->red/255, (double)date16->green/255, (double)date16->blue/255, (double)date16->alpha/255); + cairo_set_source_rgba(date_ctx, date16.red, date16.green, date16.blue, date16.alpha); cairo_set_font_size(date_ctx, date_size); cairo_text_extents(date_ctx, date, &extents); @@ -568,7 +568,7 @@ xcb_pixmap_t draw_image(uint32_t *resolution) { } if (layout_text) { cairo_select_font_face(layout_ctx, layout_font, CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL); - cairo_set_source_rgba(layout_ctx, (double)layout16->red/255, (double)layout16->green/255, (double)layout16->blue/255, (double)layout16->alpha/255); + cairo_set_source_rgba(layout_ctx, layout16.red, layout16.green, layout16.blue, layout16.alpha); cairo_set_font_size(layout_ctx, layout_size); cairo_text_extents(layout_ctx, layout_text, &extents); @@ -763,6 +763,15 @@ xcb_pixmap_t draw_image(uint32_t *resolution) { cairo_fill(xcb_ctx); } } + + te_free(te_ind_x_expr); + te_free(te_ind_y_expr); + te_free(te_time_x_expr); + te_free(te_time_y_expr); + te_free(te_date_x_expr); + te_free(te_date_y_expr); + te_free(te_layout_x_expr); + te_free(te_layout_y_expr); cairo_surface_destroy(xcb_output); cairo_surface_destroy(time_output); diff --git a/unlock_indicator.h b/unlock_indicator.h index 7947c3d..b26e4bd 100644 --- a/unlock_indicator.h +++ b/unlock_indicator.h @@ -4,9 +4,9 @@ #include typedef struct rgb { - uint32_t red; - uint32_t green; - uint32_t blue; + double red; + double green; + double blue; } rgb_t; typedef struct rgb_str { @@ -16,10 +16,10 @@ typedef struct rgb_str { } rgb_str_t; typedef struct rgba { - uint32_t red; - uint32_t green; - uint32_t blue; - uint32_t alpha; + double red; + double green; + double blue; + double alpha; } rgba_t; typedef struct rgba_str {