| @@ -104,9 +104,9 @@ public: | |||
| { | |||
| double f = (double)i / PALETTE_STEP; | |||
| double r = 0.5 * sin(f * 0.27 - 2.5) + 0.5; | |||
| double g = 0.5 * sin(f * 0.13 + 1.1) + 0.5; | |||
| double b = 0.5 * sin(f * 0.21 + 0.4) + 0.5; | |||
| double r = 0.5 * sin(f * 0.27 + 2.0) + 0.5; | |||
| double g = 0.5 * sin(f * 0.17 - 1.8) + 0.5; | |||
| double b = 0.5 * sin(f * 0.21 - 2.6) + 0.5; | |||
| if (f < 7.0) | |||
| { | |||
| @@ -146,10 +146,20 @@ public: | |||
| bbox[0] = position; | |||
| bbox[1] = ivec3(m_window_size, 0); | |||
| Input::TrackMouse(this); | |||
| /* Spawn worker threads and wait for their readiness. */ | |||
| for (int i = 0; i < MAX_THREADS; i++) | |||
| m_threads[i] = new Thread(DoWorkHelper, this); | |||
| for (int i = 0; i < MAX_THREADS; i++) | |||
| m_spawnqueue.Pop(); | |||
| } | |||
| ~Fractal() | |||
| { | |||
| /* Signal worker threads for completion. */ | |||
| for (int i = 0; i < MAX_THREADS; i++) | |||
| m_jobqueue.Push(-1); | |||
| Input::UntrackMouse(this); | |||
| #if !defined __native_client__ | |||
| Ticker::Unref(m_centertext); | |||
| @@ -307,49 +317,39 @@ public: | |||
| { | |||
| m_dirty[m_frame]--; | |||
| /* FIXME: this is the ugliest, most pathetic excuse for a | |||
| * threading system that I have seen in a while. */ | |||
| DoWorkHelper helpers[m_slices]; | |||
| for (int slice = 0; slice < m_slices; slice++) | |||
| { | |||
| helpers[slice].fractal = this; | |||
| helpers[slice].slice = slice; | |||
| // helpers[slice].thread = new Thread(DoWorkHelper::Help, | |||
| // &helpers[slice]); | |||
| DoWork(slice); | |||
| } | |||
| for (int slice = 0; slice < m_slices; slice++) | |||
| { | |||
| // delete helpers[slice].thread; | |||
| } | |||
| for (int i = 0; i < m_size.y; i += MAX_LINES * 2) | |||
| m_jobqueue.Push(i); | |||
| } | |||
| } | |||
| struct DoWorkHelper | |||
| static void *DoWorkHelper(void *data) | |||
| { | |||
| Fractal *fractal; | |||
| Thread *thread; | |||
| int slice; | |||
| static void *Help(void *data) | |||
| Fractal *that = (Fractal *)data; | |||
| that->m_spawnqueue.Push(0); | |||
| for ( ; ; ) | |||
| { | |||
| DoWorkHelper *helper = (DoWorkHelper *)data; | |||
| helper->fractal->DoWork(helper->slice); | |||
| return NULL; | |||
| int line = that->m_jobqueue.Pop(); | |||
| if (line == -1) | |||
| break; | |||
| that->DoWork(line); | |||
| that->m_donequeue.Push(0); | |||
| } | |||
| return NULL; | |||
| }; | |||
| void DoWork(int slice) | |||
| void DoWork(int line) | |||
| { | |||
| double const maxsqlen = 1024; | |||
| double const k1 = 1.0 / (1 << 10) / log2(maxsqlen); | |||
| int jmin = m_size.y * slice / m_slices; | |||
| int jmax = m_size.y * (slice + 1) / m_slices; | |||
| int jmin = ((m_frame + 1) % 4) / 2 + line; | |||
| int jmax = jmin + MAX_LINES * 2; | |||
| if (jmax > m_size.y) | |||
| jmax = m_size.y; | |||
| u8vec4 *m_pixelstart = m_pixels | |||
| + m_size.x * (m_size.y / 4 * m_frame + jmin / 4); | |||
| + m_size.x * (m_size.y / 4 * m_frame + line / 4); | |||
| for (int j = ((m_frame + 1) % 4) / 2 + jmin; j < jmax; j += 2) | |||
| for (int j = jmin; j < jmax; j += 2) | |||
| for (int i = m_frame % 2; i < m_size.x; i += 2) | |||
| { | |||
| f64cmplx z0 = m_center + TexelToWorldOffset(ivec2(i, j)); | |||
| @@ -659,6 +659,9 @@ DoWork(slice); | |||
| if (m_dirty[m_frame]) | |||
| { | |||
| for (int i = 0; i < m_size.y; i += MAX_LINES * 2) | |||
| m_donequeue.Pop(); | |||
| m_dirty[m_frame]--; | |||
| #ifdef __CELLOS_LV2__ | |||
| @@ -718,8 +721,10 @@ DoWork(slice); | |||
| } | |||
| private: | |||
| static int const MAX_ITERATIONS = 170; | |||
| static int const MAX_ITERATIONS = 340; | |||
| static int const PALETTE_STEP = 32; | |||
| static int const MAX_THREADS = 8; | |||
| static int const MAX_LINES = 8; | |||
| ivec2 m_size, m_window_size, m_oldmouse; | |||
| double m_window2world; | |||
| @@ -745,6 +750,10 @@ private: | |||
| f64cmplx m_deltashift[4]; | |||
| double m_deltascale[4]; | |||
| /* Worker threads */ | |||
| Thread *m_threads[MAX_THREADS]; | |||
| Queue m_spawnqueue, m_jobqueue, m_donequeue; | |||
| /* Debug information */ | |||
| #if !defined __native_client__ | |||
| Text *m_centertext, *m_mousetext, *m_zoomtext; | |||