settra
Posts: 4
Joined: Sun Mar 26, 2017 6:00 pm

java graphics stater on rasbian

Fri Apr 07, 2017 8:09 am

Hello forum. on raspi 3 (with rasbian, biut maybe later on arch ) , i am running a java application . the app has a simple gui, which i do not think is heavy to draw.

A timer calls the paint function every 16ms . The paint takes ~3mS to complete ( i have measured it) , on a Desktop PC.
on raspberry it takes 50ms, but if i run the app with -Dsun.java2d.opengl=true. it takes ~5ms , which sould be enough!

But never the less the gui seems to be laging. i have a counter, that is incremeanted in every paint, and i can clearly see that in 1 second, less paints have been made than in a Desktop PC. IF i decrease the size of the window, then this counter seems to be speeding up...

any ideas?? thanks!

P.S on archlinux , on a desktop PC, it runs just fine !

settra
Posts: 4
Joined: Sun Mar 26, 2017 6:00 pm

Re: java graphics stater on rasbian

Sat Apr 08, 2017 5:11 pm

ok, after searching some more, i found the following :
- In java, all .repaint() calls are gathered, and executed when the event stack pops the paint event.
- Once the paint has started, it takes only 4mS for my app to paint
- but apparantly, even though i call .repaint() every 10mS, it seems to paint every ~ 100mS ...

any ideas?

knute
Posts: 279
Joined: Thu Oct 23, 2014 12:14 am

Re: java graphics stater on rasbian

Sat Apr 08, 2017 5:59 pm

Don't call repaint() because it queues the painting calls. Are you drawing on a Swing component? You can try calling paintImmediately() but that method must be called from the event dispatch thread.

I haven't been able to increase the speed of drawing by using the open gl pipeline with Java on the Pi. Do you use the new video driver?

Here is an example of fast drawing on a Swing component:

Code: Select all

package com.knutejohnson.cookbook;

import java.awt.*;
import java.awt.event.*;
import java.lang.reflect.*;
import javax.swing.*;

/**
 * Demonstrates a method to do fast and smooth drawing for animation.
 *
 * The component drawing is done on the Event Dispatch Thread by wrapping the
 * call to JComponent#paintImmediately in EventQueue#invokeAndWait.  This
 * technique is very smooth but not nearly as fast as using a VolatileImage
 * or a BufferStrategy to do the drawing with.
 * <p>
 * Try commenting out the EventQueue#invokeAndWait and replacing it with the
 * Component#repaint method.  Component#repaint schedules repainting on the
 * Event Dispatch Thread but will also allow write combining.  At some point
 * as the display rate is increased the drawing will start to jerk or shake as
 * the Component#repaint method discards some of the earlier drawing calls for
 * the most recent one.
 * <p>
 * There are two timing gate methods, smoothGate and lowResourceGate.
 * Both are used to control the drawing rate by adding a delay to the
 * animation thread.  Try running this example with and without a timing gate.
 * <p>
 * The smoothGate method loops as fast as the processor will allow until the
 * time delay for the desired frame rate has elapsed.  On a modern computer
 * with many processors and cores there is still adequate processor power
 * available to run other programs even if one of the cores is saturated.
 * <p>
 * The lowResourceGate method loops around a Thread#sleep call and as a
 * result uses considerably less processor power than the smoothGate method.
 * The trade off is that the lowResourceGate method is not a consistent as
 * the smoothGate method and requires some tweaking to get the frame rates
 * accurate.  This is caused by the unpredictability of Thread#sleep.
 *
 * @author  Knute Johnson
 *
 * @see DrawVolatile
 * @see DrawStrategy
 */
public class DrawFast extends JComponent implements Runnable {
    /** Display increment angle in radians */
    private static final double ANGLE_INCREMENT = 0.0005;

    /** Animation thread */
    private final Thread thread;

    /**
     * Animation thread control flag.
     *
     * This variable is volatile because it is written to by one thread and
     * read by another.
     */
    private volatile boolean runFlag;

    /** Timer for rate display */
    private final java.util.Timer timer;

    /** TimerTask for rate display */
    private final java.util.TimerTask timerTask;

    /**
     * Current drawing angle in radians
     *
     * This variable is thread constrained to the animation thread.
     */
    private double radians;

    /**
     * Frame count for rate display.
     *
     * This variable is volatile because it is written to by one thread and
     * read by another.
     */
    private volatile long frameCount;

    /**
     * Frame rate for rate display.
     *
     * This variable is volatile because it is written to by one thread and
     * read by another.
     */
    private volatile double frameRate;

    /**
     * Constructs the component, sets its preferred size, creates the animation
     * thread, creates a Timer and TimerTask to update the frame rate display.
     */
    public DrawFast() {
        // give the component a starting size
        setPreferredSize(new Dimension(400,300));

        // create the animation thread
        thread = new Thread(this,"Animation Thread");

        // create the animation timer as daemon so we don't have to explicitly
        // stop it when the program ends
        timer = new java.util.Timer("Rate Display Timer",true);

        // updates the variable frameRate for the rate display
        timerTask = new java.util.TimerTask() {
            // time of last frame rate update
            long then = 0;
            // frame count of last frame rate update
            long lastCount = 0;

            @Override public void run() {
                long now = System.nanoTime();
                long frames = frameCount - lastCount;
                double duration = (now - then) / 1000000000.0;
                then = now;
                lastCount = frameCount;
                frameRate = frames / duration;
            }
        };
    }

    /**
     * Starts the animation thread and the rate display timer
     */
    public void start() {
        runFlag = true;
        thread.start();
        timer.scheduleAtFixedRate(timerTask,0,1000);
    }

    /**
     * The animation thread adjusts animation values, and calls
     * JComponent#paintImmediately to draw the updated image.
     */
    public void run() {
        // the last time the gate was opened
        long then = 0;

        while (runFlag) {
            // adjust display values
            radians += ANGLE_INCREMENT;
            ++frameCount;

            // delay get to control frame rate
//            then = smoothGate(then,200);
//            then = lowResourceGate(then,200);

            // move the contained code to the Event Dispatch Thread and wait
            // for it to complete
            try {
                EventQueue.invokeAndWait(new Runnable() {
                    public void run() {
                        // draw the component now
                        paintImmediately(getBounds());
                    }
                });
            } catch (InterruptedException ie) {
                ie.printStackTrace();
            } catch (InvocationTargetException ite) {
                ite.printStackTrace();
            }
            
            // try commenting out the EventQueue#invokeAndWait code above and
            // replacing it with Component#repaint.  See the class notes above
            // for a discussion of this topic.

//            repaint();
        }
    }

    /**
     * Stops the animation thread
     */
    public void stop() {
        runFlag = false;
    }

    /**
     * All drawing is done here.
     *
     * @param   g2D     the Graphics object
     */
    @Override public void paintComponent(Graphics g2D) {
        int w = getWidth();
        int h = getHeight();

        // the passed in Graphics is actually a Graphics2D
        Graphics2D g = (Graphics2D)g2D;

        // turn on anti-aliasiang to get smooth drawing edges and text
        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
         RenderingHints.VALUE_ANTIALIAS_ON);

        // fill the background with white
        g.setColor(Color.WHITE);
        g.fillRect(0,0,w,h);

        // draw the frame rate in the upper left corner of component
        g.setColor(Color.RED);
        g.drawString(String.format("%.0f fps",frameRate),5,15);

        // draw the rotating blue square
        g.setColor(Color.BLUE);
        g.rotate(radians,w/2,h/2);
        g.fillRect(w/2 - 100,h/2 - 100,200,200);
    }

    /**
     * Delay method to control the frame rate of the display.
     *
     * This method uses large amounts of processor resources but is very
     * smooth and will allow very fast frame rates to be used.
     *
     * @param   then    the time the gate was last entered, from the return
     *                  value of the previous call to this method
     * @param   fps     the desired frame rate in frames per second
     *
     * @return          the time the gate was exited, used as input to the next
     *                  call to this method
     */
    public long smoothGate(long then, long fps) {
        long now;
        while ((now = System.nanoTime()) - then < (1000000000L / fps))
            ;

        return now;
    }

    /**
     * Delay method to control the frame rate of the display.
     *
     * This method uses very little processor resources but is not very smooth
     * or very accurate in its timing.
     *
     * @param   then    the time the gate was last entered, from the return
     *                  value of the previous call to this method
     * @param   fps     the desired frame rate in frames per second
     *
     * @return          the time the gate was exited, used as input to the next
     *                  call to this method
     */
    public long lowResourceGate(long then, long fps) {
        long now;
        while ((now = System.nanoTime()) - then < (1000000000L / fps))
            try {
                Thread.sleep(0L,10000);
            } catch (InterruptedException ie) { }

        // tuned for 200 fps
        return now - 600000;
    }

    /**
     * Create the GUI and use a WindowListener to start and stop the animation
     * thread.
     *
     * @param   args    command line arguments (not used)
     */
    public static void main(String... args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                final DrawFast dF = new DrawFast();
                final JFrame frame = new JFrame("DrawFast");
                frame.addWindowListener(new WindowAdapter() {
                    // start the animation once the GUI is created
                    public void windowOpened(WindowEvent we) {
                        dF.start();
                    }
                    // stop the animation and dispose the GUI window
                    public void windowClosing(WindowEvent we) {
                        dF.stop();
                        frame.dispose();
                    }
                });
                frame.add(dF,BorderLayout.CENTER);
                frame.pack();
                frame.setVisible(true);
            }
        });
    }
}

Return to “Java”

Who is online

Users browsing this forum: No registered users and 3 guests