屏幕撕裂和fps在一个屏幕上下降,但在另一个屏幕没有



我正在尝试用java编程一个游戏,它基本上构成了在屏幕上绘制大量图像资产。

这在基础上工作得很好,我的主屏幕上每秒有70帧。问题是,当我把游戏窗口拖到另一个屏幕上时,它突然出现屏幕撕裂和严重的帧速率问题,每秒只显示15-25帧。

我已经使用正确配置的sun.java2d.d3d.D3DGraphicsConfig将其缩小到1个屏幕(三星电视(,而另一个屏幕(笔记本电脑屏幕https://www.acer.com/ac/de/DE/content/series/nitro5)默认为sun.awt.Win32GraphicsConfig.

在java中加载图像后,我尝试了Java2D性能问题和FPS下降的解决方案,并用以下代码将所有图像更改为正确配置的图像:

final BufferedImage image = ImageIO.read(file);
if(usedConfig != null) {
final BufferedImage compatibleImage = usedConfig.createCompatibleImage(image.getWidth(), image.getHeight(), image.getTransparency());
final Graphics2D g = compatibleImage.createGraphics();
g.drawImage(image, 0, 0, null);
}
currentImages.put(pathname+file.getName(), image);

我正在调整我的配置每帧:

GraphicsConfiguration currentConfig = null;
if(Game.jpanel != null) {
currentConfig = Game.board.getGraphicsConfiguration();
}
if(usedConfig != currentConfig) {
System.out.println("config mismatch");
if(usedConfig != null) {
System.out.println(usedConfig.getClass().getName());
}
System.out.println(currentConfig.getClass().getName());
usedConfig = currentConfig;
firstCall = true;
}
if(firstCall != true) {
return;
}
firstCall = false;
...//load and transform each image

问题是,无论我做什么,在慢屏幕上似乎没有什么真正的帮助,我只能坚持每秒25帧。

当你读到这篇文章时,我仍在处理这个问题,所以如果我找到答案,我会发布一个答案。

要模拟这些问题,您可以使用以下代码尝试VM选项-Dsun.java2d.d3d=false:

import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.awt.image.ImageObserver;
import java.io.File;
import java.io.IOException;
import java.util.Timer;
import java.util.TimerTask;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class SmallestReproducableExample {
public static int frames = 0;
public static int fps = 0;
public static void main(final String[] args) throws IOException {
final String pathname = "./image.png";
final File file = new File(pathname);
final BufferedImage image = ImageIO.read(file);
final JFrame frame = new JFrame("SmallestReproducableExample");
frame.setDefaultCloseOperation
(JFrame.EXIT_ON_CLOSE);
final TimerTask fpsCounterTask = new TimerTask() {
@Override
public void run() {
fps = frames;
frames = 0;
}
};
final Timer fpsCounter = new Timer();
final Timer paintThread = new Timer();
fpsCounter.schedule(fpsCounterTask, 1000, 1000);
final JPanel board = new JPanel() {
@Override
public void paint(final Graphics g) {
g.clearRect(-45, -45, 2041, 1041);
for(int x = -40; x <= 2000; x+=40) {
for(int y = -40; y <= 1000; y+=40) {
g.drawImage(image, x, y, 40, 40, (ImageObserver)null);
}
}
for(int x = -41; x <= 2000; x+=40) {
for(int y = -41; y <= 1000; y+=40) {
g.drawImage(image, x, y, 40, 40, (ImageObserver)null);
}
}
for(int x = -42; x <= 2000; x+=40) {
for(int y = -42; y <= 1000; y+=40) {
g.drawImage(image, x, y, 40, 40, (ImageObserver)null);
}
}
frame.setTitle("SmallestReproducableExample fps: "+fps);
final TimerTask repaintTask = new TimerTask() { //Task must be new otherwise it throws java.lang.IllegalStateException: Task already scheduled or cancelled
@Override
public void run() {
repaint();
}
};
++frames;
paintThread.schedule(repaintTask, 1);
}
};
board.setSize((1900),(1070));
board.setDoubleBuffered(true);
frame.add(board);
frame.setSize((1900),(1070));
frame.setVisible(true);
frame.setExtendedState(frame.getExtendedState() | JFrame.MAXIMIZED_BOTH);
}
}

很明显,您需要自己的带有透明内容的测试映像,因为由于许可证的原因,我无法提供。

好的,更新到这个问题,如果我启用虚拟机选项-Dsun.java2d.nopeng=true并插入我的另一个屏幕,那么在慢速屏幕上启用了opengl管道,导致60-70帧/秒的高速度,这在以前是不可能的。

但现在切换屏幕时,另一个屏幕的速度很慢。

我还需要一种方法来以编程的方式启用opengl管道,以完全解决这个问题。

最新更新