LWJGL3 - Displays and Windows (Few questions)

Started by abcdef, November 26, 2014, 19:08:04

Previous topic - Next topic

abcdef

Hi

Firstly the new site looks great and I am looking forward to using LWJGL3. I have just kicked things off in migrating my project, it should be fairly simple but i have some questions / points

1) Can you update the javadoc for

public static java.nio.ByteBuffer glfwGetVideoModes(long monitor,
                                    java.nio.ByteBuffer count)

Its missing the information on Count which is referenced

http://www.glfw.org/docs/latest/group__monitor.html#ga820b0ce9a5237d645ea7cbb4bd383458

2) In this function I get a ByteBuffer back (which is a pretty weird design...but I'll go with it as I know you want to stick the api's religously), but there is no javadoc documentation on how I can interpret what is in this byte buffer. You have to go to the GLFW site to find out more. When digging a bit further on the GLFW site I realise I need to use the below, details of this would be useful in the javadoc.

http://www.glfw.org/docs/latest/structGLFWvidmode.html#details

I saw that there is a helper function for the singlular "getVideoMode" result ByteBuffer but I have no clue how to use this with multiple video modes being returned (an array of VideoModes is meant to be returned). Should I create my own helper class for this?

To me this is quite a complicated way to just get a list of video modes!

3) Am I correct in saying that when you create a window it can be any size? It doesn't have to match the window size of a valid video mode resolution?

4) How do I set the color depth of the window I am creating? If my desktop is 24 bit but I want to create a 16 bit window how to I go about doing this?

5) I noticed animated cursors are not in the glfw api (My favourite :)), can I take it support for these will be dependant on if GLFW supports them in the future?

Thanks

abcdef



spasi

Quote from: abcdef on November 26, 2014, 19:08:041) Can you update the javadoc for

public static java.nio.ByteBuffer glfwGetVideoModes(long monitor,
                                    java.nio.ByteBuffer count)

Its missing the information on Count which is referenced

http://www.glfw.org/docs/latest/group__monitor.html#ga820b0ce9a5237d645ea7cbb4bd383458

Thanks, this is a bug and will be fixed.

Quote from: abcdef on November 26, 2014, 19:08:042) In this function I get a ByteBuffer back (which is a pretty weird design...but I'll go with it as I know you want to stick the api's religously), but there is no javadoc documentation on how I can interpret what is in this byte buffer. You have to go to the GLFW site to find out more. When digging a bit further on the GLFW site I realise I need to use the below, details of this would be useful in the javadoc.

http://www.glfw.org/docs/latest/structGLFWvidmode.html#details

I saw that there is a helper function for the singlular "getVideoMode" result ByteBuffer but I have no clue how to use this with multiple video modes being returned (an array of VideoModes is meant to be returned). Should I create my own helper class for this?

To me this is quite a complicated way to just get a list of video modes!

This has been asked before, the reply is here.

You have a good point about documentation, it is not immediately obvious how to use functions that accept or return structs. I will try to improve the JavaDoc of such functions with LWJGL-specific information. For now, just remember that for any native struct you see in an API, there's a corresponding (auto-generated) Java class with helper methods (org.lwjgl.system.glfw.GLFWvidmode in this case).

Quote from: abcdef on November 26, 2014, 19:08:043) Am I correct in saying that when you create a window it can be any size? It doesn't have to match the window size of a valid video mode resolution?

Yes, if it's a desktop-mode window (NULL monitor in glfwCreateWindow). For fullscreen (non-NULL monitor), I'm sure you have to match a valid vidmode, but I haven't tried what happens if you don't.

Quote from: abcdef on November 26, 2014, 19:08:044) How do I set the color depth of the window I am creating? If my desktop is 24 bit but I want to create a 16 bit window how to I go about doing this?

See the documentation for glfwWindowHint, you need to use the <channel>_BITS hints.

Quote from: abcdef on November 26, 2014, 19:08:045) I noticed animated cursors are not in the glfw api (My favourite :)), can I take it support for these will be dependant on if GLFW supports them in the future?

There won't be an API for this, because the current API already supports cursor animation. Just create a GLFWcursor for every frame of the animation and use glfwSetCursor to switch frames in your render loop. See here for an example.

abcdef

Thanks Spasi

Is the wiki editable in github by anyone? It might be useful to add info on all the questions people are raising there

spasi

Yes, the wiki is editable by anyone.

Sorry that I haven't been able to work on the wiki and site in the last couple of weeks, but I'm 100% occupied with development. I've been working with users to reproduce and resolve issues, while also doing heavy work on new features.

After the alpha is out I'll hopefully be able to relax and focus on documentation. I will also compile a list of FAQ that will be published on the site.

jmguillemette

im hoping you can elaborate on GLFW.glfwGetVideoModes

im lost on how we are to translate the resulting buffer to GLFWVidmode.. is there a order to the values and we just populate them in? or is there a helper method to take in a buffer and self populate?

thanks
j.

jmguillemette

nevermind i figured it out.
takes a bit to wrap your head around the new approach but its workable :)

here is a sample for anyone else who gets caught on this.


public static void getDisplayModes(long window){
      PointerBuffer monitorBuf = GLFW.glfwGetMonitors();
      for(int x=0;x<monitorBuf.limit();x++){
         IntBuffer buf = BufferUtils.createIntBuffer(1);
         buf.put(10);
         buf.flip();
         ByteBuffer modes = GLFW.glfwGetVideoModes(monitorBuf.get(x), buf);
         
         for(int i=0;i<modes.limit();){
            ByteBuffer vidMode = BufferUtils.createByteBuffer(GLFWvidmode.SIZEOF);
            byte[] vidModeData = new byte[GLFWvidmode.SIZEOF];
            modes.get(vidModeData);
            vidMode.put(vidModeData);      
            vidMode.flip();
            int width = GLFWvidmode.width(vidMode);
            int height = GLFWvidmode.height(vidMode);
            System.out.println(width+","+height);
            i =i+GLFWvidmode.SIZEOF;
         }
      }

jmguillemette

Quote from: spasi on November 27, 2014, 11:09:42
Yes, the wiki is editable by anyone.

Sorry that I haven't been able to work on the wiki and site in the last couple of weeks, but I'm 100% occupied with development. I've been working with users to reproduce and resolve issues, while also doing heavy work on new features.

After the alpha is out I'll hopefully be able to relax and focus on documentation. I will also compile a list of FAQ that will be published on the site.

As i write my engine if i make snippets like this one i will gladly put them int he wiki.
you may need to give me access to do so.

BrickFarmer

Quote from: jmguillemette on November 28, 2014, 06:05:54
nevermind i figured it out.
takes a bit to wrap your head around the new approach but its workable :)

Thanks for that!  I hope this is on topic still, but I tried the code.  So I have two monitors atttached, and both get listed.  They only give "Generic PnP Monitor" as their names, but I can identify the monitor I want using the width and height.  However, when creating the window, it still uses the primary monitor for full screen.  I'm trying to get the second monitor fullscreen...

window = glfwCreateWindow(1920, 1200, "Hello World!", secondMonitorId, NULL);


Also I've set the following hint, but not sure it is even required for fullscreen.

glfwWindowHint(GLFW_DECORATED, GL_FALSE);


Is this the correct approach for fullscreen on second monitor?

using: LWJGL 3.0.0a
Oculus Rift CV1, MBP 2016 - 2.9 i7 - Radeon Pro 460  OSX 10.12.4,  Win7 - i5 4670K - GTX1070.
Oculus Rift VR Experiments: https://github.com/WhiteHexagon

spasi

Fullscreen on secondary monitor works fine for me (Windows 8.1). What is your operating system? Could you post the complete code you're using for selecting the monitor?


BrickFarmer

Quote from: spasi on December 02, 2014, 21:24:33
Fullscreen on secondary monitor works fine for me (Windows 8.1). What is your operating system? Could you post the complete code you're using for selecting the monitor?

Windows 7

import org.lwjgl.BufferUtils;
import org.lwjgl.PointerBuffer;
import org.lwjgl.Sys;
import org.lwjgl.opengl.*;
import org.lwjgl.system.glfw.*;

import java.nio.ByteBuffer;
import java.nio.IntBuffer;

import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.system.MemoryUtil.*;
import static org.lwjgl.system.glfw.GLFW.*;

public class TriangleMain {
    private long window;
    private long riftMonitorId;
    private final int riftWidth = 1920;
    private final int riftHeight = 1080;

    public boolean findRift() {
        PointerBuffer monitorBuf = GLFW.glfwGetMonitors();
        for (int x = 0; x < monitorBuf.limit(); x++) {
            IntBuffer buf = BufferUtils.createIntBuffer(1);
            buf.put(10);
            buf.flip();
            long monitorId = monitorBuf.get(x);
            ByteBuffer modes = GLFW.glfwGetVideoModes(monitorId, buf);
            System.out.println(glfwGetMonitorName(monitorId));              // EDID not exposed?
            for (int i = 0; i < modes.limit();) {
                ByteBuffer vidMode = BufferUtils.createByteBuffer(GLFWvidmode.SIZEOF);
                byte[] vidModeData = new byte[GLFWvidmode.SIZEOF];
                modes.get(vidModeData);
                vidMode.put(vidModeData);
                vidMode.flip();
                int width = GLFWvidmode.width(vidMode);
                int height = GLFWvidmode.height(vidMode);
                if (width == riftWidth && height == riftHeight) {
                    System.out.println(width + "," + height + "," + monitorId);
                    riftMonitorId = monitorId;
                    return true;
                }
                i =i+GLFWvidmode.SIZEOF;
            }
            System.out.println("-----------------");
        }
        return false;
    }

    public void execute() {
        System.out.println("Hello LWJGL " + Sys.getVersion() + "!");
        try {
            init();
            loop();
            glfwDestroyWindow(window);
        } finally {
            glfwTerminate();
        }
    }

    private void init() {
        glfwSetErrorCallback(ErrorCallback.Util.getDefault());
        if (glfwInit() != GL11.GL_TRUE) {
            throw new IllegalStateException("Unable to initialize GLFW");
        }
        glfwDefaultWindowHints();
        // glfwWindowHint(GLFW_VISIBLE, GL_FALSE);
        // glfwWindowHint(GLFW_RESIZABLE, GL_TRUE);
        // glfwWindowHint(GLFW_DECORATED, GL_FALSE);        // not required for fullscreen?

        if (findRift()) {
            window = glfwCreateWindow(riftWidth, riftHeight, "Hello World!", riftMonitorId, NULL);
            System.out.println("found rift and using it " + riftMonitorId);
        } else {
            window = glfwCreateWindow(riftWidth, riftHeight, "Hello World!", NULL, NULL);
            System.out.println("use rift debug mode");
        }
        if (window == NULL) {
            throw new RuntimeException("Failed to create the GLFW window");
        }
        WindowCallback.set(window, new WindowCallbackAdapter() {
            @Override
            public void key(long window, int key, int scancode, int action, int mods) {
                if (key == GLFW_KEY_ESCAPE && action == GLFW_RELEASE)
                    glfwSetWindowShouldClose(window, GL_TRUE);
            }
        });
        // not relevant to fullscreen mode
        // ByteBuffer vidmode = glfwGetVideoMode(glfwGetPrimaryMonitor());
        // glfwSetWindowPos(
        // window,
        // (GLFWvidmode.width(vidmode) - WIDTH) / 2,
        // (GLFWvidmode.height(vidmode) - HEIGHT) / 2
        // );
        glfwMakeContextCurrent(window);
        glfwSwapInterval(1);
        glfwShowWindow(window);
    }

    private void loop() {
        GLContext.createFromCurrent();
        glClearColor(1.0f, 0.0f, 0.0f, 0.0f);
        while (glfwWindowShouldClose(window) == GL_FALSE) {
            glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
            glfwSwapBuffers(window);
            glfwPollEvents();
        }
    }

    public static void main(String[] args) {
        new TriangleMain().execute();
    }
}
Oculus Rift CV1, MBP 2016 - 2.9 i7 - Radeon Pro 460  OSX 10.12.4,  Win7 - i5 4670K - GTX1070.
Oculus Rift VR Experiments: https://github.com/WhiteHexagon

BrickFarmer

The good news is that I have just tested this on OSX 10.8.5 and it works as expected :)
Oculus Rift CV1, MBP 2016 - 2.9 i7 - Radeon Pro 460  OSX 10.12.4,  Win7 - i5 4670K - GTX1070.
Oculus Rift VR Experiments: https://github.com/WhiteHexagon

spasi

First of all, your monitor/vidmode iteration code is unnecessarily complicated and wrong. This is the correct way:

PointerBuffer monitors = glfwGetMonitors();
IntBuffer modeCount = BufferUtils.createIntBuffer(1);
for ( int i = 0; i < monitors.limit(); i++ ) {
	long monitor = monitors.get(i);
	
	ByteBuffer modes = glfwGetVideoModes(monitor, modeCount);
	for ( int j = 0; j < modeCount.get(0); j++ ) {
		modes.position(j * GLFWvidmode.SIZEOF);
		
		int width = GLFWvidmode.width(modes);
		int height = GLFWvidmode.height(modes);
		// ...
	}
}

Since you're trying to identify a Rift, I don't think this can reliably be done using only the video modes (more than one monitor may support 1920x1080). Please see this issue. It has not been resolved yet, but some functionality is already supported. You can use GLFWWin32.glfwGetWin32Monitor(), see if that provides enough information.

BrickFarmer

Thanks! silly me, that mode was supported by both. 

Quote from: spasi on December 03, 2014, 10:18:12
You can use GLFWWin32.glfwGetWin32Monitor(), see if that provides enough information.

That call only gives me DISPLAY1 DISPLAY2.  The equivalent call on OSX just seems to return the cgDirectDisplayID?  I think what I probably need to access is the manufacturer, but it looks like EDID has been replaced by a new standard anyway, displayID.  So I guess I'm going to need a popup for now for selection. No problem.

The good news is that fullscreen is working for me now on both platforms :)
Oculus Rift CV1, MBP 2016 - 2.9 i7 - Radeon Pro 460  OSX 10.12.4,  Win7 - i5 4670K - GTX1070.
Oculus Rift VR Experiments: https://github.com/WhiteHexagon

BrickFarmer

Is it expected that activating full screen on my second monitor would trigger the mouse being moved onto that screen?
Oculus Rift CV1, MBP 2016 - 2.9 i7 - Radeon Pro 460  OSX 10.12.4,  Win7 - i5 4670K - GTX1070.
Oculus Rift VR Experiments: https://github.com/WhiteHexagon