不带全屏窗口的Java VSync

问题描述 投票:0回答:1

我正在尝试使窗口应用程序VSync与监视器一起刷新。此代码与“ fullscreen = true”(报告75FPS,监视器的刷新率)一起正常工作,但是在窗口模式下,它仅报告32FPS。有人知道我在这里做错了吗?感谢您的帮助!

import java.awt.BufferCapabilities;
import java.awt.GraphicsEnvironment;
import java.awt.ImageCapabilities;
import java.awt.image.BufferStrategy;
import java.util.concurrent.TimeUnit;
import javax.swing.JFrame;
import sun.java2d.pipe.hw.ExtendedBufferCapabilities;

public class VSyncTest {

    public static void main(String args[]) {
        final boolean fullscreen = true;
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                JFrame v = new JFrame();
                if (fullscreen) {
                    GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().setFullScreenWindow(v);
                    v.createBufferStrategy(2);
                } else {
                    v.setVisible(true);
                    ExtendedBufferCapabilities b = new ExtendedBufferCapabilities(new BufferCapabilities(new ImageCapabilities(true), new ImageCapabilities(true), BufferCapabilities.FlipContents.PRIOR), ExtendedBufferCapabilities.VSyncType.VSYNC_ON);
                    try {
                        v.createBufferStrategy(2, b);
                    } catch (Exception e) {
                        e.printStackTrace();
                        throw new RuntimeException(e);
                    }
                }
                new Thread() {
                    @Override
                    public void run() {
                        BufferStrategy bs = v.getBufferStrategy();
                        long start = System.nanoTime(), frames = 0;
                        do {
                            bs.getDrawGraphics();
                            bs.show();
                            frames++;
                            long elapsed = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - start);
                            long framesPerS = (long) (frames / (elapsed / 1000D));
                            if (frames % 60 == 0) {
                                System.out.println("Frames/s: " + framesPerS + ", Elapsed: " + elapsed / 1000);
                            }

                        } while (true);
                    }
                }.start();
            }
        });
    }
}

编辑:[凹凸] [凹凸]

java swing jframe fullscreen vsync
1个回答
0
投票

我将尝试回答一个问题,尽管该问题本身似乎不是Java问题,但似乎是图形问题。因此,首先,此答案基于我正在测试的配置,Windows 10,带有Intel显卡的DELL笔记本电脑,2560x1440显示器。

第二次为您的代码添加注释,以下设置在我的配置中严重失败:

ExtendedBufferCapabilities b = new ExtendedBufferCapabilities(
    new BufferCapabilities(new ImageCapabilities(true), new ImageCapabilities(true), BufferCapabilities.FlipContents.PRIOR),
ExtendedBufferCapabilities.VSyncType.VSYNC_ON);

引起闪烁,并且镜框计数器发疯。如果查看createBufferStrategy(2)使用的代码-没有功能的过载-它使用FlipContents.UNDEFINED而不是FlipContents.PRIOR。无论如何,我建议您使用

GraphicsEnvironment.getLocalGraphicsEnvironment()
          .getDefaultScreenDevice()
          .getDefaultConfiguration()
          .getBufferCapabilities()

为了获得适当的设备功能。这样就停止了闪烁,并将刷新率仪固定为60 fps,与我全屏运行时的刷新率仪相同。

另一件事是,我试图为框架设置实际尺寸并移除装饰。调用setUndecorated(true)似乎没有什么区别,尽管建议您在进入全屏显示之前先调用它。最后,如果您调整窗口大小,计数器将再次关闭,以便查看是否可以使用frame.setResizable( false );生存,并且如果将帧移至另一台监视器,则vsync丢失-您实际上可以看到帧计数器再次发疯。不幸的是,我不是图形专家来解释这些问题,尽管如果我没记错的话,缓冲区会在设备上分配,并且在调整大小时需要使缓冲区无效-这就是为什么全屏毕竟有意义。我不记得我在哪里读过这篇文章。

© www.soinside.com 2019 - 2024. All rights reserved.