Esempio n. 1
0
        private void DrawMandelbrot(int cw, int ch)
        {
            // Get the renderer the user selected
            if (!UsePar && !UseSeq && !UseGpu)
            {
                MessageBox.Show("Select parallel or sequential.");
                return;
            }

            var render = FractalRenderer.SelectRender(AddPixel, CheckAbort, UseSeq, UsePar, UseGpu);
            // Create a stopwatch to clock the calculation speed
            Stopwatch timer = new Stopwatch();

            // Allocate a pair of render buffers that will be swapped per frame
            byte[] buffer1 = new byte[cw * ch * 4];
            byte[] buffer2 = new byte[cw * ch * 4];
            // This is the buffer selector
            bool which = false;

            // Set the two render properties
            width  = cw;
            height = ch;
            // Make sure the toImage buffer is null (no animation starting yet)
            toImage = null;

            // Start the XX FPS clock tick
            Dispatcher.InvokeAsync(renderClock.Start);
            // Start the timer
            timer.Start();
            foreach (var pt in RenderPoints)
            {
                // Select the buffer
                bytes = which ? buffer1 : buffer2;

                // Get the frame location & scale
                float scale = pt.Item3;
                float xc    = pt.Item1;
                float yc    = pt.Item2;
                XC    = xc;
                YC    = yc;
                Scale = scale;

                // Get the min/max/step values and make sure they're all sensible
                float xmin = (xc - scale / 2.0f).Clamp(-3.0f, 1f);
                float xmax = (xc + scale / 2.0f).Clamp(-3.0f, 1f);
                if (xmin > xmax)
                {
                    float t = xmin;
                    xmin = xmax;
                    xmax = t;
                }
                float ymax = (yc + scale / 2.0f).Clamp(-1.5f, 1.5f);
                float ymin = (yc - scale / 2.0f).Clamp(-1.5f, 1.5f);
                if (ymin > ymax)
                {
                    float t = ymin;
                    ymin = ymax;
                    ymax = t;
                }
                float ystep = (scale / (float)ch).Clamp(0, ymax - ymin);
                float xstep = (scale / (float)cw).Clamp(0, xmax - xmin);
                float step  = Math.Max(ystep, xstep);
                xmin = xc - (cw * step / 2);
                xmax = xc + (cw * step / 2);
                ymin = yc - (ch * step / 2);
                ymax = yc + (ch * step / 2);
                // Render this frame
                render(xmin, xmax, ymin, ymax, step);
                // Frame's complete: publish the current buffer for the
                // render thread to draw
                bytes = Interlocked.Exchange(ref toImage, bytes);
                if (bytes == null)
                {
                    // The render thread finished with the previous frame, swap it and keep going
                    which = !which;
                }
                else
                {
                    // We've finished a frame before the rendering thread had a change to
                    // render the previous frame: leave the buffer selection alone, so the
                    // frame we just calculated gets skipped.
                }
                // Update the published clock
                ElapsedTime = timer.Elapsed;
            }
            // Stop the timer
            timer.Stop();
        }
#pragma warning disable 4014
        private void DrawMandelbrot(int cw, int ch)
        {
            double range, xc, yc;

            lock (valRWLock)
            {
                RenderRange = range = Range;
                RenderXC    = xc = XC;
                RenderYC    = yc = YC;
                width       = cw;
                height      = ch;
                bytes       = new byte[width * height * 4];
            }
            lock (renderLock)
            {
                var render = FractalRenderer.SelectRender(AddPixel, CheckAbort, UseSIMD, !UseFloat, UseThreads, UseADT);
                Unsupported = render == null;
                if (render == null)
                {
                    return;
                }

                abort = false;
                done  = false;
                Dispatcher.InvokeAsync(renderClock.Start);
                double xmin = (xc - range / 2.0).Clamp(-3.0, 1);
                double xmax = (xc + range / 2.0).Clamp(-3.0, 1);
                if (xmin > xmax)
                {
                    double t = xmin;
                    xmin = xmax;
                    xmax = t;
                }
                double ymin = (yc - range / 2.0).Clamp(-1.5f, 1.5f);
                double ymax = (yc + range / 2.0).Clamp(-1.5f, 1.5f);
                if (ymin > ymax)
                {
                    double t = ymin;
                    ymin = ymax;
                    ymax = t;
                }
                double ystep = (range / (double)ch).Clamp(0, ymax - ymin);
                double xstep = (range / (double)cw).Clamp(0, xmax - xmin);
                double step  = Math.Max(ystep, xstep);
                xmin = xc - (cw * step / 2);
                xmax = xc + (cw * step / 2);
                ymin = yc - (ch * step / 2);
                ymax = yc + (ch * step / 2);

                if (xmin == xmax || ymin == ymax ||
                    xmin + xstep <= xmin || ymin + ystep <= ymin ||
                    ymax - ystep >= ymax || xmax - xstep >= xmax)
                {
                    return;
                }

                Stopwatch timer = new Stopwatch();
                timer.Start();
                render((float)xmin, (float)xmax, (float)ymin, (float)ymax, (float)step);
                ElapsedTime = timer.ElapsedMilliseconds;
                abort       = false;
                done        = true;
            }
        }