1 #include <stddef.h> 2 #include <stdio.h> 3 #include <stdlib.h> 4 #include <stdint.h> 5 6 /* Set to 1 to enable debug log traces. */ 7 #define DEBUG 0 8 9 /* Set to 1 to optimize memory stores when generating plasma. */ 10 #define OPTIMIZE_WRITES 1 11 12 /* We're going to perform computations for every pixel of the target 13 * bitmap. floating-point operations are very slow on ARMv5, and not 14 * too bad on ARMv7 with the exception of trigonometric functions. 15 * 16 * For better performance on all platforms, we're going to use fixed-point 17 * arithmetic and all kinds of tricks 18 */ 19 20 typedef int32_t Fixed; 21 22 #define FIXED_BITS 16 23 #define FIXED_ONE (1 << FIXED_BITS) 24 #define FIXED_AVERAGE(x,y) (((x) + (y)) >> 1) 25 26 #define FIXED_FROM_INT(x) ((x) << FIXED_BITS) 27 #define FIXED_TO_INT(x) ((x) >> FIXED_BITS) 28 29 #define FIXED_FROM_FLOAT(x) ((Fixed)((x)*FIXED_ONE)) 30 #define FIXED_TO_FLOAT(x) ((x)/(1.*FIXED_ONE)) 31 32 #define FIXED_MUL(x,y) (((int64_t)(x) * (y)) >> FIXED_BITS) 33 #define FIXED_DIV(x,y) (((int64_t)(x) * FIXED_ONE) / (y)) 34 35 #define FIXED_DIV2(x) ((x) >> 1) 36 #define FIXED_AVERAGE(x,y) (((x) + (y)) >> 1) 37 38 #define FIXED_FRAC(x) ((x) & ((1 << FIXED_BITS)-1)) 39 #define FIXED_TRUNC(x) ((x) & ~((1 << FIXED_BITS)-1)) 40 41 #define FIXED_FROM_INT_FLOAT(x,f) (Fixed)((x)*(FIXED_ONE*(f))) 42 43 typedef int32_t Angle; 44 45 #define ANGLE_BITS 9 46 47 #if ANGLE_BITS < 8 48 # error ANGLE_BITS must be at least 8 49 #endif 50 51 #define ANGLE_2PI (1 << ANGLE_BITS) 52 #define ANGLE_PI (1 << (ANGLE_BITS-1)) 53 #define ANGLE_PI2 (1 << (ANGLE_BITS-2)) 54 #define ANGLE_PI4 (1 << (ANGLE_BITS-3)) 55 56 #define ANGLE_FROM_FLOAT(x) (Angle)((x)*ANGLE_PI/M_PI) 57 #define ANGLE_TO_FLOAT(x) ((x)*M_PI/ANGLE_PI) 58 59 #if ANGLE_BITS <= FIXED_BITS 60 # define ANGLE_FROM_FIXED(x) (Angle)((x) >> (FIXED_BITS - ANGLE_BITS)) 61 # define ANGLE_TO_FIXED(x) (Fixed)((x) << (FIXED_BITS - ANGLE_BITS)) 62 #else 63 # define ANGLE_FROM_FIXED(x) (Angle)((x) << (ANGLE_BITS - FIXED_BITS)) 64 # define ANGLE_TO_FIXED(x) (Fixed)((x) >> (ANGLE_BITS - FIXED_BITS)) 65 #endif 66 67 static Fixed *angle_sin_tab; 68 //static Fixed angle_sin_tab[ANGLE_2PI+1]; 69 70 static __inline__ Fixed angle_sin( Angle a ) 71 { 72 return angle_sin_tab[(uint32_t)a & (ANGLE_2PI-1)]; 73 } 74 75 static __inline__ Fixed angle_cos( Angle a ) 76 { 77 return angle_sin(a + ANGLE_PI2); 78 } 79 80 static __inline__ Fixed fixed_sin( Fixed f ) 81 { 82 return angle_sin(ANGLE_FROM_FIXED(f)); 83 } 84 85 static __inline__ Fixed fixed_cos( Fixed f ) 86 { 87 return angle_cos(ANGLE_FROM_FIXED(f)); 88 } 89 90 /* Color palette used for rendering the plasma */ 91 #define PALETTE_BITS 8 92 #define PALETTE_SIZE (1 << PALETTE_BITS) 93 94 #if PALETTE_BITS > FIXED_BITS 95 # error PALETTE_BITS must be smaller than FIXED_BITS 96 #endif 97 98 #if 0 99 static uint16_t make565(int red, int green, int blue) 100 { 101 return (uint16_t)( ((red << 8) & 0xf800) | 102 ((green << 2) & 0x03e0) | 103 ((blue >> 3) & 0x001f) ); 104 } 105 106 static void init_palette(uint16_t *palette) 107 { 108 int nn, mm = 0; 109 /* fun with colors */ 110 for (nn = 0; nn < PALETTE_SIZE/4; nn++) { 111 int jj = (nn-mm)*4*255/PALETTE_SIZE; 112 palette[nn] = make565(255, jj, 255-jj); 113 } 114 115 for ( mm = nn; nn < PALETTE_SIZE/2; nn++ ) { 116 int jj = (nn-mm)*4*255/PALETTE_SIZE; 117 palette[nn] = make565(255-jj, 255, jj); 118 } 119 120 for ( mm = nn; nn < PALETTE_SIZE*3/4; nn++ ) { 121 int jj = (nn-mm)*4*255/PALETTE_SIZE; 122 palette[nn] = make565(0, 255-jj, 255); 123 } 124 125 for ( mm = nn; nn < PALETTE_SIZE; nn++ ) { 126 int jj = (nn-mm)*4*255/PALETTE_SIZE; 127 palette[nn] = make565(jj, 0, 255); 128 } 129 } 130 #endif 131 static __inline__ uint16_t palette_from_fixed(uint16_t* palette, Fixed x ) 132 { 133 if (x < 0) x = -x; 134 if (x >= FIXED_ONE) x = FIXED_ONE-1; 135 int idx = FIXED_FRAC(x) >> (FIXED_BITS - PALETTE_BITS); 136 return palette[idx & (PALETTE_SIZE-1)]; 137 } 138 139 140 extern void root(uint32_t width, uint32_t height, uint32_t stride, double t, uint16_t* palette, void* pixels, void *_angle_sin_tab) 141 { 142 angle_sin_tab = _angle_sin_tab; 143 Fixed ft = FIXED_FROM_FLOAT(t/1000.); 144 Fixed yt1 = FIXED_FROM_FLOAT(t/1230.); 145 Fixed yt2 = yt1; 146 Fixed xt10 = FIXED_FROM_FLOAT(t/3000.); 147 Fixed xt20 = xt10; 148 149 #define YT1_INCR FIXED_FROM_FLOAT(1/100.) 150 #define YT2_INCR FIXED_FROM_FLOAT(1/163.) 151 152 int yy; 153 for (yy = 0; yy < height; yy++) { 154 uint16_t* line = (uint16_t*)pixels; 155 Fixed base = fixed_sin(yt1) + fixed_sin(yt2); 156 Fixed xt1 = xt10; 157 Fixed xt2 = xt20; 158 159 yt1 += YT1_INCR; 160 yt2 += YT2_INCR; 161 162 #define XT1_INCR FIXED_FROM_FLOAT(1/173.) 163 #define XT2_INCR FIXED_FROM_FLOAT(1/242.) 164 165 uint16_t* line_end = line + width; 166 167 if (line < line_end) { 168 if (((uint32_t)line & 3) != 0) { 169 Fixed ii = base + fixed_sin(xt1) + fixed_sin(xt2); 170 171 xt1 += XT1_INCR; 172 xt2 += XT2_INCR; 173 174 line[0] = palette_from_fixed(palette, ii >> 2); 175 line++; 176 } 177 178 while (line + 2 <= line_end) { 179 Fixed i1 = base + fixed_sin(xt1) + fixed_sin(xt2); 180 xt1 += XT1_INCR; 181 xt2 += XT2_INCR; 182 183 Fixed i2 = base + fixed_sin(xt1) + fixed_sin(xt2); 184 xt1 += XT1_INCR; 185 xt2 += XT2_INCR; 186 187 uint32_t pixel = ((uint32_t)palette_from_fixed(palette, i1 >> 2) << 16) | 188 (uint32_t)palette_from_fixed(palette, i2 >> 2); 189 190 ((uint32_t*)line)[0] = pixel; 191 line += 2; 192 } 193 194 if (line < line_end) { 195 Fixed ii = base + fixed_sin(xt1) + fixed_sin(xt2); 196 line[0] = palette_from_fixed(palette, ii >> 2); 197 line++; 198 } 199 } 200 201 // go to next line 202 pixels = (char*)pixels + stride; 203 } 204 } 205 206 /* simple stats management */ 207 typedef struct { 208 double renderTime; 209 double frameTime; 210 } FrameStats; 211 212 #define MAX_FRAME_STATS 200 213 #define MAX_PERIOD_MS 1500 214 215 typedef struct { 216 double firstTime; 217 double lastTime; 218 double frameTime; 219 220 int firstFrame; 221 int numFrames; 222 FrameStats frames[ MAX_FRAME_STATS ]; 223 } Stats; 224 225