Turns out fullscreen mode is important - if I go into windowed mode, it takes about 2ms just like nearest neighbour. Still pluggin away.
Are you able to reproduce the problem in fullscreen mode BurntPizza? Scouring this forum it sounds like there is a fair amount of knowledge on here about hardware accelerated images, and this feels like a pretty common situation when making a 2D game run fullscreen… surely someone has run into this before!
Oddly enough it goes down to 30 fps in fullscreen mode, scaling or not.
The display mode has a 60 hz refresh rate even.
import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;
import javax.swing.JFrame;
import javax.swing.JPanel;
@SuppressWarnings("serial")
public class Scaling extends JPanel {
private BufferedImage buffer = new BufferedImage(1280, 720, BufferedImage.TYPE_INT_RGB);
private long lastSec = System.nanoTime();
private int fps = 0;
private int fpsDisplay = 0;
public static void main(String[] a) {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new Scaling());
frame.setUndecorated(true);
GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().setFullScreenWindow(frame);
frame.setVisible(true);
frame.addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_ESCAPE)
System.exit(0);
}
});
System.out.println(GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDisplayMode().getRefreshRate());
while (true) {
frame.repaint();
}
}
@Override
public void paint(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR);
g2d.drawImage(buffer, 0, 0, 1920, 1200, null);
g2d.setColor(Color.white);
g2d.drawString("FPS: " + fpsDisplay, 50, 50);
if (System.nanoTime() - lastSec > 1000000000) {
lastSec = System.nanoTime();
fpsDisplay = fps;
fps = 0;
}
fps++;
}
}
Goes back up to 250 though in a “simulated fullscreen:”
@@ frame.setUndecorated(true);
- GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().setFullScreenWindow(frame);
+ frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
Could be just vSync or something that’s dropping you down to 30fps (though that still performs better than mine).
Yeah basically my solution is to do a ‘simulated fullscreen’ by creating an undecorated window that fills the entirety of the screen. Seems to work okay, I guess I’ll go ahead with this unless someone has some magic to get fullscreen exclusive mode to work.
Try to render the BufferedImage on a VolatileImage, as rendering to VolatileImages is (almost) guaranteed to be optimal in regards of hardware acceleration.
Yeah, try that, I get another 100 FPS on the blank screen test, and bicubic is just as fast as the others, as opposed to toaster speed.
Unfortunately, no luck. Just as slow in FSEM. In the pseudo-fullscreen mode it is slightly slower that way (likely due to the buffer copy).
Weirdly, my BICUBIC interpolation now crashes with an NPE in J2D.
java.lang.NullPointerException
at sun.java2d.pipe.DrawImage.renderImageXform(DrawImage.java:515)
at sun.java2d.d3d.D3DDrawImage.renderImageXform(D3DDrawImage.java:77)
at sun.java2d.pipe.DrawImage.transformImage(DrawImage.java:268)
at sun.java2d.pipe.DrawImage.scaleImage(DrawImage.java:128)
at sun.java2d.pipe.DrawImage.scaleImage(DrawImage.java:1047)
at sun.java2d.pipe.ValidatePipe.scaleImage(ValidatePipe.java:207)
at sun.java2d.SunGraphics2D.drawImage(SunGraphics2D.java:3047)
at sun.java2d.SunGraphics2D.drawImage(SunGraphics2D.java:2996)
Try using BufferStrategy.
Also stick some delays around switching into FSEM, as its interaction with the rest of the J2D API is prone to race conditions. (Even when it’s all executing on the EDT)
It’s a terribly unstable and unreliable API.
Also, spinning on Component.repaint() is terribly wasteful(flooding the EDT’s EventQueue with repaint events) and is not guaranteed to achieve what you want it to.
Hi Abuse,
Sorry it’s been a while since I checked the thread. I tried buffer strategy but it did not fix the issue. It basically just created a volatile image behind the scenes anyways which I had already tried.
I actually did have delays after switching to FSEM - it was necessary for me to wait until FSEM was fully instantiated before the canvas.getWidth() and Height returned valid properties. Unfortunately that didn’t fix the performance issue.
Regarding repaint - you are confusing BurntPizza’s test code with mine. My code doesn’t spin on repaint().