Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Design issues with setActive  (Read 2035 times)

0 Members and 1 Guest are viewing this topic.

wintertime

  • Sr. Member
  • ****
  • Posts: 255
    • View Profile
Design issues with setActive
« on: November 12, 2013, 10:55:36 pm »
I am writing a GUI library that should draw some things on the current active context, but for doing this it has to sometimes create a texture first using a RenderTexture. The problem is the current context gets deactivated and I found no good way in SFML to reactivate the previous context.

I see a few possible solutions:
- Ideally I would be able to retrieve a reference to a sf::Context for the current active context inside the library from some static method and then later call setActive on it, but I see no way in SFML for doing this. (I think the static ensureGLContext method would just use some hidden context and that would not help me as it would be the wrong one.)
- Next best alternative would be giving the library function a parameter with a reference to an object of a SFML class with the setActive function. The problem there is the inheritance hierarchy in SFML does not allow for casting to a common base class with a virtual setActive function, because its missing in GlResource/RenderTarget and RenderTarget does not even derive from GlResource. That makes it not possible to transparently handle Context, Window, RenderWindow and RenderTexture, because they all freshly declare a new version of the identically named function.
- Another alternative would be if all of Window, RenderWindow and RenderTexture had a function to get a reference to their Context, but there is also no such methods.
- The awkward, last-I-can-think-of and only-one-I-can-implement-myself-without-changing-SFML alternative would be I create a function object class with a pure virtual operator(), then derive a template function-object class from it that gets a reference to one of those SFML objects in the constructor, saves it in a member variable of the templates parameter-type and overrides the operator() to call setActive on the member. Then I would have the library user need to create a function object from the derived template and give the library a casted-to-the-base-class reference or smart pointer to it and the library could then somehow get it into the resource creation function to use it at the appropriate moment, but that function would be needed to be changed into a function object too and then the resource cache using that function as a template parameter would hopefully still work with this after some change to it.

Now I dont really think or know if it was feasible to change SFML for my singular case, though maybe someone got another idea how I could design my library in any other way around this?
« Last Edit: November 12, 2013, 10:58:04 pm by wintertime »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: Design issues with setActive
« Reply #1 on: November 13, 2013, 07:57:43 am »
Probably not the best solution for you, but it's simple and doesn't require to change SFML: write a generic getCurrentContext/setCurrentContext pair using the low-level functions of WGL, GLX and AGL.
Laurent Gomila - SFML developer

wintertime

  • Sr. Member
  • ****
  • Posts: 255
    • View Profile
Re: Design issues with setActive
« Reply #2 on: November 13, 2013, 10:02:44 am »
Thanks for the answer, but I had kind of discarded that solution immediately, because I thought that could mess up some of that internal SFML state where it remembers which context was active, if I first let it change the context to the RenderTexture's and then behind its back switch it myself without informing SFML of it. Or would that be some lucky case where it accidently works/appears to work?
Additionally I would prefer using a cross-platform way, where I dont write one(maybe 2) of the 3(or later 4/5) and have the other versions of the code possibly or really broken.


I thought of even another solution, but that would open a possibly even larger can of worms. I could avoid deactivating the context in the first place by adding threads to the mix, because contexts are local to a thread in OpenGL and I think SFML uses shared contexts where one can access all objects from another context? If I'm lucky its even faster to create a thread compared to changing the contexts of one thread.

That would give only a localized implementation where I create a thread, let it do the work of creating and using the RenderTexture and copying things into a Image/Texture, then wait for it to finish.

Though I then would maybe need to also write a complicated version for another version of the renderer; with a permanent background thread, two queues with mutexes (or maybe a lockfree ring buffer) for communicating and two events (for waking up the thread and declaring the work finished); to actually gain some more performance from the thread by avoiding to block the main thread until its really needed.
There I imagine could be problems with sometimes starving one of the threads or OpenGL/WGL quirks (where it slows down or worse) when rendering from more than one thread at same time onto shared contexts?

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: Design issues with setActive
« Reply #3 on: November 13, 2013, 12:56:13 pm »
That could work, I think it's worth trying ;)
Laurent Gomila - SFML developer

wintertime

  • Sr. Member
  • ****
  • Posts: 255
    • View Profile
Re: Design issues with setActive
« Reply #4 on: November 13, 2013, 03:34:59 pm »
I put in the simple version of the last solution, with creating a new sf::Thread and sf::String, Text, RenderTexture and new copied to Texture inside every time, and it works.
It feels like its a fraction of a second slower when testing it, but there are opportunities to optimize that later. I think its worth it as I can now clean up my code and remove the hacked in update function and setActive in the main loop, which only worked cause of the current version of the renderer caching draw calls already. :)