a small optimization for the vertical gradients, and use the same log(n) strategy to use less memcpy's for filling out the horizontal gradients
This commit is contained in:
parent
3611c8210c
commit
9c72998684
2 changed files with 73 additions and 20 deletions
|
@ -218,8 +218,8 @@ static inline void repeat_pixel(RrPixel32 *start, gint w)
|
||||||
|
|
||||||
/* for >= 8, then use O(log n) memcpy's... */
|
/* for >= 8, then use O(log n) memcpy's... */
|
||||||
else {
|
else {
|
||||||
gint len = 4;
|
gchar *cdest;
|
||||||
gint lenbytes = 4 * sizeof(RrPixel32);
|
gint lenbytes;
|
||||||
|
|
||||||
/* copy the first 3 * 32 bits (3 words) ourselves - then we have
|
/* copy the first 3 * 32 bits (3 words) ourselves - then we have
|
||||||
3 + the original 1 = 4 words to make copies of at a time
|
3 + the original 1 = 4 words to make copies of at a time
|
||||||
|
@ -229,16 +229,38 @@ static inline void repeat_pixel(RrPixel32 *start, gint w)
|
||||||
for (x = 3; x > 0; --x)
|
for (x = 3; x > 0; --x)
|
||||||
*(dest++) = *start;
|
*(dest++) = *start;
|
||||||
|
|
||||||
for (x = w - 4; x > 0;) {
|
/* cdest is a pointer to the pixel data that is typed char* so that
|
||||||
memcpy(dest, start, lenbytes);
|
adding 1 to its position moves it only one byte
|
||||||
x -= len;
|
|
||||||
dest += len;
|
lenbytes is the amount of bytes that we will be copying each
|
||||||
len <<= 1;
|
iteration. this doubles each time through the loop.
|
||||||
|
|
||||||
|
x is the number of bytes left to copy into. lenbytes will alwaysa
|
||||||
|
be bounded by x
|
||||||
|
|
||||||
|
this loop will run O(log n) times (n is the number of bytes we
|
||||||
|
need to copy into), since the size of the copy is doubled each
|
||||||
|
iteration. it seems that gcc does some nice optimizations to make
|
||||||
|
this memcpy very fast on hardware with support for vector operations
|
||||||
|
such as mmx or see. here is an idea of the kind of speed up we are
|
||||||
|
getting by doing this (splitvertical3 switches from doing
|
||||||
|
"*(data++) = color" n times to doing this memcpy thing log n times:
|
||||||
|
|
||||||
|
% cumulative self self total
|
||||||
|
time seconds seconds calls ms/call ms/call name
|
||||||
|
49.44 0.88 0.88 1063 0.83 0.83 splitvertical1
|
||||||
|
47.19 1.72 0.84 1063 0.79 0.79 splitvertical2
|
||||||
|
2.81 1.77 0.05 1063 0.05 0.05 splitvertical3
|
||||||
|
*/
|
||||||
|
cdest = (gchar*)dest;
|
||||||
|
lenbytes = 4 * sizeof(RrPixel32);
|
||||||
|
for (x = (w - 4) * sizeof(RrPixel32); x > 0;) {
|
||||||
|
memcpy(cdest, start, lenbytes);
|
||||||
|
x -= lenbytes;
|
||||||
|
cdest += lenbytes;
|
||||||
lenbytes <<= 1;
|
lenbytes <<= 1;
|
||||||
if (len > x) {
|
if (lenbytes > x)
|
||||||
len = x;
|
lenbytes = x;
|
||||||
lenbytes = x * sizeof(RrPixel32);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -534,12 +556,14 @@ static void gradient_splitvertical(RrAppearance *a, gint w, gint h)
|
||||||
|
|
||||||
static void gradient_horizontal(RrSurface *sf, gint w, gint h)
|
static void gradient_horizontal(RrSurface *sf, gint w, gint h)
|
||||||
{
|
{
|
||||||
gint x, y;
|
gint x, y, cpbytes;
|
||||||
RrPixel32 *data = sf->pixel_data, *datav;
|
RrPixel32 *data = sf->pixel_data, *datav;
|
||||||
|
gchar *datac;
|
||||||
|
|
||||||
VARS(x);
|
VARS(x);
|
||||||
SETUP(x, sf->primary, sf->secondary, w);
|
SETUP(x, sf->primary, sf->secondary, w);
|
||||||
|
|
||||||
|
/* set the color values for the first row */
|
||||||
datav = data;
|
datav = data;
|
||||||
for (x = w - 1; x > 0; --x) { /* 0 -> w - 1 */
|
for (x = w - 1; x > 0; --x) { /* 0 -> w - 1 */
|
||||||
*datav = COLOR(x);
|
*datav = COLOR(x);
|
||||||
|
@ -549,22 +573,32 @@ static void gradient_horizontal(RrSurface *sf, gint w, gint h)
|
||||||
*datav = COLOR(x);
|
*datav = COLOR(x);
|
||||||
++datav;
|
++datav;
|
||||||
|
|
||||||
for (y = h - 1; y > 0; --y) { /* 1 -> h */
|
/* copy the first row to the rest in O(logn) copies */
|
||||||
memcpy(datav, data, w * sizeof(RrPixel32));
|
datac = (gchar*)datav;
|
||||||
datav += w;
|
cpbytes = 1 * w * sizeof(RrPixel32);
|
||||||
|
for (y = (h - 1) * w * sizeof(RrPixel32); y > 0;) {
|
||||||
|
memcpy(datac, data, cpbytes);
|
||||||
|
y -= cpbytes;
|
||||||
|
datac += cpbytes;
|
||||||
|
cpbytes <<= 1;
|
||||||
|
if (cpbytes > y)
|
||||||
|
cpbytes = y;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gradient_mirrorhorizontal(RrSurface *sf, gint w, gint h)
|
static void gradient_mirrorhorizontal(RrSurface *sf, gint w, gint h)
|
||||||
{
|
{
|
||||||
gint x, y, half1, half2;
|
gint x, y, half1, half2, cpbytes;
|
||||||
RrPixel32 *data = sf->pixel_data, *datav;
|
RrPixel32 *data = sf->pixel_data, *datav;
|
||||||
|
gchar *datac;
|
||||||
|
|
||||||
VARS(x);
|
VARS(x);
|
||||||
|
|
||||||
half1 = (w + 1) / 2;
|
half1 = (w + 1) / 2;
|
||||||
half2 = w / 2;
|
half2 = w / 2;
|
||||||
|
|
||||||
|
/* set the color values for the first row */
|
||||||
|
|
||||||
SETUP(x, sf->primary, sf->secondary, half1);
|
SETUP(x, sf->primary, sf->secondary, half1);
|
||||||
datav = data;
|
datav = data;
|
||||||
for (x = half1 - 1; x > 0; --x) { /* 0 -> half1 - 1 */
|
for (x = half1 - 1; x > 0; --x) { /* 0 -> half1 - 1 */
|
||||||
|
@ -586,9 +620,16 @@ static void gradient_mirrorhorizontal(RrSurface *sf, gint w, gint h)
|
||||||
++datav;
|
++datav;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (y = h - 1; y > 0; --y) { /* 1 -> h */
|
/* copy the first row to the rest in O(logn) copies */
|
||||||
memcpy(datav, data, w * sizeof(RrPixel32));
|
datac = (gchar*)datav;
|
||||||
datav += w;
|
cpbytes = 1 * w * sizeof(RrPixel32);
|
||||||
|
for (y = (h - 1) * w * sizeof(RrPixel32); y > 0;) {
|
||||||
|
memcpy(datac, data, cpbytes);
|
||||||
|
y -= cpbytes;
|
||||||
|
datac += cpbytes;
|
||||||
|
cpbytes <<= 1;
|
||||||
|
if (cpbytes > y)
|
||||||
|
cpbytes = y;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -68,7 +68,7 @@ gint main()
|
||||||
inst = RrInstanceNew(ob_display, ob_screen);
|
inst = RrInstanceNew(ob_display, ob_screen);
|
||||||
|
|
||||||
look = RrAppearanceNew(inst, 0);
|
look = RrAppearanceNew(inst, 0);
|
||||||
look->surface.grad = RR_SURFACE_SPLIT_VERTICAL;
|
look->surface.grad = RR_SURFACE_MIRROR_HORIZONTAL;
|
||||||
look->surface.secondary = RrColorParse(inst, "Yellow");
|
look->surface.secondary = RrColorParse(inst, "Yellow");
|
||||||
look->surface.split_secondary = RrColorParse(inst, "Red");
|
look->surface.split_secondary = RrColorParse(inst, "Red");
|
||||||
look->surface.split_primary = RrColorParse(inst, "Green");
|
look->surface.split_primary = RrColorParse(inst, "Green");
|
||||||
|
@ -79,6 +79,18 @@ gint main()
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if BIGTEST
|
||||||
|
int i;
|
||||||
|
look->surface.pixel_data = g_new(RrPixel32, w*h);
|
||||||
|
for (i = 0; i < 10000; ++i) {
|
||||||
|
printf("\r%d", i);
|
||||||
|
fflush(stdout);
|
||||||
|
RrRender(look, w, h);
|
||||||
|
}
|
||||||
|
exit (0);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
RrPaint(look, win, w, h);
|
RrPaint(look, win, w, h);
|
||||||
done = 0;
|
done = 0;
|
||||||
while (!done) {
|
while (!done) {
|
||||||
|
|
Loading…
Reference in a new issue