State of Accelerated OpenGL

Ok to understand a bit better could you give a small overview again of how things are done now in your application? Given that you changed things a number of times across the postings, it’s a bit confusing as to what exactly you’re using now (i.e. what does the application thread do, which window and view classes are you inheriting from, how do you want to route the events…) :slight_smile:

Also, have you already looked into some of the sample code? There’s e.g. the well-known GL teapot: http://cgit.haiku-os.org/haiku/tree/src/apps/glteapot
From what I understand, it should do roughly what you’re looking for: it uses BDirectWindow (class TeapotWindow) with a BGLView (class ObjectView). ObjectView receives and processes, among other things, mouse events, so you can spin the teapot around by dragging it. The actual drawing is done in a separate thread (“simonThread”, spawned from ObjectView), which calls ObjectView::DrawFrame() in an endless loop (until quitting).

Can do.

If I try running the teapot demo I get a turning teapot (lines up with my engine successfully rendering into the window) but mouse and keyboard input are not working (i can click and drag but teapot keeps spinning the same. lines up with my problem). Menu does work and resizing does work (this does not work in my case but could be a problem with BGLView not doing resizing properly). So there seems to be something broken with BGLView since I get the same behavior on the teapot demo.

Just to fully answer the question how things are set up here now (pseudo-code):

main:
  new deBeApp();
  be_app->Run();
  delete be_app;

deBeApp -> BApplication:
  virtual ReadToRun:
    spawn_thread(ThreadHandler...)
  virtual MessageReceived:
    gameEngine.addMessage(new BMessage(message)) // uses own BMessageQueue instance
    -> addMessage:
        queue.Lock
        queue.AddMessage
        queue.Unlock
  ThreadHandler:
    launch engine // does engine run loop
    -> engine runLoop
      for each message in own message queue:
        process message

cDirectWindow -> BDirectWindow
  constructor:
    BDirectWindow(frame, title, B_DOCUMENT_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, 0, B_CURRENT_WORKSPACE)
    AddChild(new cGLView())
    glView.MakeFocus()
  virtual MessageReceived:
    gameEngine.addMessage(new BMessage(message))
  virtual DirectConnected:
    glView.DirectConnected(info)

cGLView -> BGLView:
  constructor:
    BGLView(frame, name, B_FOLLOW_ALL, B_WILL_DRAW, BGL_RGB | BGL_DOUBLE | BGL_DEPTH | BGL_STENCIL)
  virtual MessageReceived:
    gameEngine.addMessage(new BMessage(message))

RenderThread
  window.LockGL
  render
  window.UnlockGL
  window.glView.SwapBuffers

That’s the basic working in a nutshell for better overview. Seems similar to teapot example in my opinion.

Well, indeed something seems broken regarding BGLView events handling when in BDirectWindow, as I experience the same lack of mouse selecting reaction in GLTeapot too. That’s a regression.

Did you try to use Debugger to track down each thread state?

I tried but I could not get much information out of it since mostly all threads are named “pthread func”. I guess these are the threads of my parallel processing code. But in general none of the displayed threads shows anything unusual so far

EDIT:
I ran both my application and the teapot one with the debugger again. In the debugger I see nothing special but I noticed now in both applications I see in the console messages like “Failed to run thread XYZ: Bad port ID”. Could this be a message handling thread going haywire?

1 Like

Some of what is described here is being tracked in this trac ticket:
https://dev.haiku-os.org/ticket/13585

That’s unrelated. The drawing artifacts are a known problem because of the way BDirectWindow works and the lack of hardware mouse pointer support in most of our video drivers. It is unrelated to the application getting input events from the window.

So yes, it looks like a bug in Mesa 17. I think glteapot on x86_gcc2 still works?

@dragon: on Haiku you can rename threads using rename_thread (http://cgit.haiku-os.org/haiku/tree/headers/os/kernel/OS.h#n337) and get_pthread_thread_id(http://cgit.haiku-os.org/haiku/tree/headers/os/kernel/OS.h#n367). This could make debugging a lot easier indeed.

1 Like

Maybe we will implement pthread_set_name_np() one day.

Thanks for responses ! :sunglasses:

Ok, thanks for the overview.

Is it right that your class cGLView does not override the BView hook functions, such as MouseDown() and MouseMoved()? In that case, it’s not a bug, it’s expected.

Certain system-sent messages – such as the mouse move events – are handled specially in BWindow and will not result in a call to the Window’s or View’s MessageReceived(). Instead, the appropriate hook method is called on the BView. So if you want mouse move events, you need to implement the virtual method cGLView::MouseMoved().

For more information, see “From Looper To Handler” in the BeBook Messaging documentation:
https://www.haiku-os.org/legacy-docs/bebook/TheApplicationKit_Messaging.html#TheApplicationKit_Messaging_FromLooperToHandler

Especially the part titled “Finding a Function” is relevant here, although the entire document is very much worth a read if you want to know more about how the messaging really works in Haiku.

For an overview of overridable event hook methods offered by BView, see:
https://www.haiku-os.org/legacy-docs/bebook/BView.html#BView_Hook

Oh, and about the GLTeapot… I looked into it, and yes, moving it around with the mouse is currently broken with the Mesa on Haiku x86_64 (works fine on x86_gcc2 and x86_gcc5, which both have older Mesa versions). However, this is unrelated to event handling… the mouse events arrive in its ObjectView::MouseMoved() just fine, it’s the hit-testing done then which is broken. GLTeapot does it by drawing the various teapots (you can have more than one) in a number of colours using flat shading and no lighting, then it reads the pixel at the mouse cursor using glReadPixels() and finds out which teapot (if any) was clicked, based on the pixel’s colour value. However, in x86_64 Haiku, the glReadPixels() always returns colour (0, 0, 0) for some reason. Maybe something broken in our Mesa-Renderer add-on, or maybe it’s its OpenGL code (GLTeapot is based on BeOS sample code written in 1999, although with newer parts too) which isn’t quite compatible with the latest version… I don’t know. Unfortunately I currently know way too little about OpenGL to find out what’s wrong there.

I see. From the documentation I got it that MessageReceived will be always called and that the BWindow::MessageReceived just calls the hooks. So I understood by doing the MessageReceived yourself you skip the hook calling but instead doing the legwork yourself (and in my case that’s simpler than trying to re-create the message from the hook since in the hook the BMessage is gone). I’ll have to see how this works out.

Rather than recreating the BMessage, you can get the message currently being processed by using CurrentMessage() on the BLooper that is processing the message. Should be possible to call it from within a hook function, in case the hook doesn’t pass in all the event data you need from the original BMessage. See https://www.haiku-os.org/legacy-docs/bebook/BLooper.html

That seems to work. I get now the input messages and can process them. The mouse pointer though is a huge problem. I can’t track the position outside the window (no message send anymore) an I can’t seem to find a way to change the mouse position (center on BView for example).

This went lost in the discussion, it seems:

For grabbing input outside your window you need to use SetEventMask or SetMouseEventMask with B_POINTER_EVENTS.

Yup, what PulkoMandy said.

Another note on the messaging: you could also go another approach, and override BWindow::DispatchMessage() in your window class. It’s the low-level method that receives any message for the window, and by default will hand them off to the view’s MessageReceived(), or to hooks like MouseDown(). So if you only want to forward the message anyway, overriding the dispatch might be simpler than implementing all the hooks. Remember to pass any messages you don’t handle yourself on to the base class’s DispatchMessage(). And there’s also a downside: certain functionality like drag&drop relies on things in the default implementation of BWindow::DispatchMessage() to work correctly. So if you override it, you’re on your own, and certain window/view functionality might be limited.

I had MessageReceived overriden in BWindow already but it didn’t work. In the linked documentation it is stated that BWindow does something with PreferredHandler mapping to CurrentView or something like this. Looks like dealing with that would be required too and as you mentioned sounds like a tricky move. I only need to subclass keyboard/mouse/resize/activate type events and that’s fine so far.

I set already the mouse mask but it is not working. Am I missing something?
SetMouseEventMask(B_POINTER_EVENTS | B_KEYBOARD_EVENTS | B_NO_POINTER_HISTORY | B_LOCK_WINDOW_FOCUS);

And about set_mouse_position I’ll see if it works. I didn’t find that method in the documentation.

You misread, I meant DispatchMessage() now, not MessageReceived(). (The relationship between the two can be found in the Messaging system overview docs I linked in an earlier post.)

BView::SetMouseEventMask() is probably not what you want, it’s only for usage inside BView::MouseDown(), and only stays active until the mouse button is lifted again. To always receive the mouse move events, use BView::SetEventMask(). For details see:
https://www.haiku-os.org/legacy-docs/bebook/BView.html#BView_SetEventMask

The documentation for set_mouse_position() is here:
https://www.haiku-os.org/legacy-docs/bebook/TheGameKit_Functions.html

You can disregard the note about having to use BWindowScreen there. On Haiku, set_mouse_position() will always work, regardless of the window type.

I got it now. SetEventMask does get me the events now also outside the window but I can’t “grab” the input as in other OS. This leads to the problem that somebody can still manage to somehow click outside the window and break out. But something like grabbing the input I could also not find in the documentation. Click and drag, yes, but not grabbing input generally.

I also experimented with set_mouse_position and it is not working as advertised. When called the mouse cursor does jump to the center of the window but when I move the mouse again it snaps back to where it had been before. So set_mouse_position only “visually” moves the cursors to the new location but logically it is still at the old position. Obviously this is not working at all. set_mouse_position should also change the logical mouse position not just the current visual rendering of it.

EDIT: Also MouseDown, MouseUp and MouseMoved hooks are working. KeyDown and KeyUp are not working. They are never called. Do I need to enable them somehow?

Not receiving key events is most probably due to the view not having the keyboard focus. Try calling BView::MakeFocus() on the view. If that’s not enough, you can add B_KEYBOARD_EVENTS to your mask for SetEventMask(), then it will get the events even when not focused.

The problem with set_mouse_position() sounds a bit weird, because it’s working just fine here. With a very simple test program:

#include <WindowScreen.h> int main() { set_mouse_position(100, 100); return 0; }

it makes the cursor jump to (100, 100). It’s not just drawn there, the mouse continues moving from there. So I’m not sure what’s going on in your case…
Maybe you’re calling it at some place in the system event loop where the new mouse position is not yet set, so your change is immediately overwritten by the previous position again?

I’m using MakeFocus and B_KEYBOARD_EVENTS already but it’s not working.

I’m calling it somewhere outside any hook methods or event processing. Actually it runs if BApplication looper has no more messages to process. See my flow outline above. It’s called in the engine loop before all messages are processed (these are copies so at that time these messages have been already processed by the respective hook adding the copy).

Can I shomehow ensure the loopers have all messages processed? Or do I need to somehow drain the BDirectWindow looper before calling this? I’ve got access to the window in that situation, just from a different thread.

No answer so I will try to rephrase the question: Is there a way to make all messages in a BLooper (in this case BWindow) to be fully processed before I update the mouse position?