Clueless And Frameless

BlitzMax Forums/Brucey's Modules/Clueless And Frameless

dw817(Posted 2016) [#1]
Hi Brucey:

I'm starting to look at the modules you've done. My, haven't you been busy ! :)

Cutting to the chase, have you written a MOD and example code that will give you a frameless window while leaving the taskbar visible below - and for any setting of resolution ?

For instance, my screen is 1024x768. I'd like to create a frame in it that is 1024x728. So your MOD will not only create a frameless window but also be able to retrieve the size of the taskbar below - no matter how it is configured or sized.

I have code for this already but it uses MaxGui.Drivers which to me is a pain to use. As you stated in one of your posts, wxMax should cover what you need and - the part I like, your Max2D commands will "just work."


grable(Posted 2016) [#2]
Here you go, no need to beg brucey for this ;)



dw817(Posted 2016) [#3]
Hi Grable.

Thanks - I'm not liking the fact that my code is smaller though:



About half the size. Still, Grable - yours is not even calling a module nor do I have to twinge the system in yours to get back my favored and normal keyboard and mouse input back. I like yours better.

Now how do I set it so I have the effect of this command ?
SetGraphicsDriver GLMax2DDriver(),0 ' zero forces front buffer
So I can have my favored glflush() command back and working ?

And - is there a way to have frameless but from a set size say 640x480 and at any position on the screen ?


grable(Posted 2016) [#4]
Now how do I set it so I have the effect of this command ?
SetGraphicsDriver GLMax2DDriver(),0 ' zero forces front buffer
Like you would when you normally call Graphics. Call it first.

And - is there a way to have frameless but from a set size say 640x480 and at any position on the screen ?
If you read the code you would know how ;)
But il post it anyway.
Function WindowGraphics:TGraphics( x:Int, y:Int, w:Int, h:Int, depth:Int = 0, hz:Int = 60, flags:Int = 0)
	Local g:TGraphics = Graphics( w,h, depth, hz, flags)
	Local hwnd:Int = GetBlitzmaxWindow()
	Assert hwnd Else "unable to find BlitzMax window"

	' remove window frame
	Local wflags:Int = GetWindowLongW( hwnd, GWL_STYLE)	
	SetWindowLongW( hwnd, GWL_STYLE, wflags & WS_SIZEBOX)

	' update window
	SetWindowPos( hwnd, HWND_TOP, x,y, w, h, SWP_FRAMECHANGED | SWP_NOZORDER | SWP_HIDEWINDOW)
	ShowWindow( hwnd, 1)

	Return g
EndFunction



dw817(Posted 2016) [#5]
Hi Grable. As for the SetGraphicsDriver, I wouldn't be asking if I didn't know. If you try:
AppTitle = "Frameless"
SetGraphicsDriver GLMax2DDriver(),0 ' zero forces front buffer
WindowGraphics()
You will see this does not work. The screen locks up. If you try this:
AppTitle = "Frameless"
WindowGraphics()
SetGraphicsDriver GLMax2DDriver(),0 ' zero forces front buffer
It crashes. So no, that is why I am asking.

As for the function - thanks ! I see a bit needs to be added. if X Y W H are zero, then I can add code to instead use the standard values from rect[0 1 2 3].

Marvel of code to not use a MOD, really do appreciate it !

Still ... how difficult would it have been to ALREADY have a frameless option for graphics in default BlitzMAX ? :)


grable(Posted 2016) [#6]
It was working as expected, but the window didnt refresh properly and thus taking on whatever was behind it.
My guess is that GLGraphicsDriver doesnt refresh the window like D3D9 does before handing it over.
Function WindowGraphics:TGraphics( depth:Int = 0, hz:Int = 60, flags:Int = 0)
	Extern "Win32"
		Const SPI_GETWORKAREA:Int = $30
		
		Function SystemParametersInfoW:Int( action:Int, param1:Int, param2:Byte Ptr, winini:Int)
	EndExtern

	' get size of desktop minus taskbar/toolbars
	Local rect:Int[4]
	SystemParametersInfoW( SPI_GETWORKAREA, 0, rect, 0)
	
	Local g:TGraphics = Graphics( rect[2], rect[3], depth, hz, flags)
	Local hwnd:Int = GetBlitzmaxWindow()
	Assert hwnd Else "unable to find BlitzMax window"

	' remove window frame
	Local wflags:Int = GetWindowLongW( hwnd, GWL_STYLE)	
	SetWindowLongW( hwnd, GWL_STYLE, wflags & ~WS_CAPTION)
	SetWindowPos( hwnd, HWND_TOP, 0,0,0,0, SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE |  SWP_NOZORDER | SWP_HIDEWINDOW)

	' force window refresh
	Cls
	
	' update window
	SetWindowPos( hwnd, HWND_TOP, rect[0],rect[1], rect[2], rect[3], SWP_NOZORDER | SWP_SHOWWINDOW)
	
	Return g
EndFunction

EDIT: Btw, fixed border removal by removing the actual flags.


dw817(Posted 2016) [#7]
Wait !

Nailed it. :D I needed a Delay 1 after the Glflush. Works ! Really do appreciate it. I'll use this model for future frameless.

Here is final model:




grable(Posted 2016) [#8]
Great :)

It should even handle vertical taskbars and other toolbars as well, so you can go all in!

Though i cant for the life of me understand why you insist on using single buffering and glFlush.. Unless your running on ancient hardware and or an intel gpu. Im guessing both ;)

For comparison, with glFlush i get 490 FPS, which is fast sure. But with "Flip 0" i get 7480!
I know what im using ;) (which is "Flip 1", no need to render thousands or even hundreds of frames needlessly)


dw817(Posted 2016) [#9]
Grable, could you please post a working example of this ? The reason I'm using Glflush() is because of the following:



As you can see, Flip() flips around the images making it difficult to lock anything down.

Now with Glflush() the images stay. I want this for my work. I hate calling Flip() and finding I haven't done it right or something and it messes up on me.

Still - code that shows 490 over 7480, I'd be very interested in seeing that.


Brucey(Posted 2016) [#10]
Using Flip is not difficult :

Draw all your stuff
Flip()
Draw all your stuff
Flip()
etc.


grable(Posted 2016) [#11]
As you can see, Flip() flips around the images making it difficult to lock anything down.
Then dont do it like that. Your way of alternating drawing and flushing is an ancient way of doing things.
And is infact slower on modern hardware and operating systems.

The normal way to do things today, as Brucey pointed out. Is to draw everything each frame.

Still - code that shows 490 over 7480, I'd be very interested in seeing that.
That was using the code in this very thread. With an added function for measuring fps:
Function FPS:Int()
	Const UPDATE:Float = 0.5
	Global count:Int, lastcount:Int, lastupdate:Int
	
	If (MilliSecs() - lastupdate) > Int(UPDATE * 1000.0)
		lastcount = Float(count / UPDATE)
		count = 1
		lastupdate = MilliSecs()
	Else
		count :+ 1
	EndIf
	Return lastcount
EndFunction
So not a proper benchmark, but with a black screen and a 32x32 square it is indicative of the maximum frames your gpu is capable of pushing.

EDIT: To get a similar effect to single buffering, dont call Cls.


dw817(Posted 2016) [#12]
Brucey, that does not work if you have this command in place.
SetGraphicsDriver GLMax2DDriver() ' necessary for busy pixel reading and writing


If I DON'T use this command then while Flip() works every time I read and write pixels - things will start to slow down until it crashes. This was discovered earlier HERE:

http://www.blitzbasic.com/Community/posts.php?topic=105546

So, I need that SetGraphicsDriver command and I need a Flip() that will let me call it without swapping circles (as the example I posted above). I also do not want to use Flip() as it is inherently slower than Glflush(). Try this code:



Now you tell me what's going on here.


TomToad(Posted 2016) [#13]
Flip is deliberately slower. It is supposed to sync with your monitor rate. This is to prevent tearing. Any higher is useless as your monitor will actually only show 60 frames every second. All other frames are lost. It is best to spend that extra time updating your logic instead of drawing frames that will never be seen.

If for some reason you need to flip as fast as possible, you can use Flip 0 (or Flip false). This will prevent Flip from syncing to the refresh rate. If you change the Flip to Flip 0 in your code above, you will notice you get almost exactly the same values.


grable(Posted 2016) [#14]
If I DON'T use this command then while Flip() works every time I read and write pixels - things will start to slow down until it crashes.
I tried the example in that post and could draw with the mouse until there was nothing left, and it didnt slow down or crash.

If it does that for you, again you must have old ass hardware and drivers. As the only reason i could see that example doing that would be running out of gpu memory, and the hardware then doesnt have enough and/or the drivers are unable to free the textures fast enough.

Now you tell me what's going on here.
Well first of all, your still calling Flip 1 (1 being the default) and that V-SYNCS. so low framerates is expected. IE it will LOCK to your monitors refresh-rate, which is probably 60 if its an LCD.
So comparing it to only glFlush is wrong, for a fairer comparison you need to use Flip 0.

Here is my results for that test, with Flip 0:
Did 19357 Flip(0) in 2-seconds time.
Did 22224 Glflush() in 2-seconds time.
And with double buffering:
Did 32335 Flip(0) in 2-seconds time. -- DID display correctly
Did 3922442 Glflush() in 2-seconds time. -- did NOT display correctly
Even though this shows glFlush to be "faster" than Flip, it allso shows double buffering to be insanly "faster".
I say "faster" because at that point it doesnt really matter, all it serves to do is eat power and resources needlessly.

And btw, you do know that glFlush and Flip are not equivalent right? glFlush only flushes the command queues, but returns almost immediately. Which is why you seem to need "Delay 1" or more when the command queue takes longer to execute.
The more correct function to call would be glFinish, as that actually waits for the completion of the queued gl commands before returning.


dw817(Posted 2016) [#15]
Glfinish is it ??

*SIGH* Wow, LOL ! How many more ways are there to transfer a screen of graphics ? :D

Are you guyz okay with Glfinish over Glflush ?

There is still a problem. Let me refer to my "Nifty Scrolling Map"

http://www.blitzbasic.com/Community/post.php?topic=105731&post=1293123

Now if I replace the Glflush with Flip or Flip -1, I get very undesirable results.

Changing it to Flip 0 or Flip 1 it works. And, apparently because of the SetGraphicsDriver GLMax2DDriver(),0 Flip() is not flickering. I tested it by putting one back to back with another in the code and there is no difference.

Awright, let's recap. So I shouldn't use Glflush nor Glfinish and instead should use Flip 0 or Flip 1, yes ?

Essentially I want to create my own timer. If you try out the mapper as is, you will see I don't need Flip() at all and Glflush along with a perfect timer gives flawless pixel movement. At least it does here.

If it does that for you, again you must have old ass hardware and drivers

That's actually a good thing. That means if it runs on my system it should run on others. However =YOU= guys might be able to write code that WON'T run on my system because you're not taking into account old ass hardware and drivers. So I can test it for ya. :)

Okay, now what is the difference between Flip 0 and Flip 1 ?

I inserted this code:
  For i=0 To 77
  Flip 1
  Next
  WaitTimer timer ' defined above, wait specified time
And there is no difference then if I just used one Flip 1.


I see it described in the help file:

If sync is 0, then the flip occurs as soon as possible. If sync is 1, then the flip occurs on the next vertical blank.

As soon as possible is what I want, so I can use Flip 0 (zero) and build my own timers, like I did for the Mapper. Awright, I can adjust all my code to do that. Won't be the least bit surprised of Flip 0 does the exact same thing Glflush does and Flip 1 does the exact same thing Glfinish does. :)
. . .

:(

Actually no. I plugged in those commands, Flip 0 and Flip 1 and Glfinish in place of Glflush and so far Glflush is the fastest.

The main good news is I can use Flip() anywhere and it doesn't flicker or swap pages using SetGraphicsDriver GLMax2DDriver(),0.

And yet ... Glflush by itself with no timer is perfectly unusable. No screen can update with it until a timer is called, and even a Timer of 1 is slower than a single Flip 0.

Pondering ... Let's lay it out:

Flip -1 117 cycles
Flip 0 14911 cycles
Flip 1 14896 cycles
Glflush w NO Timer 515931 cycles (but unusable)
Glflush w Timer 1 1060 cycles
Glfinish 10448 cycles



Okay. That helps. Looks like Flip 0 is the hero after all !


grable(Posted 2016) [#16]
Okay. That helps. Looks like Flip 0 is the hero after all!
So arguing on the internet pays off in the end?
Just kidding :P im glad you figured something out atleast.
And its always nice to play well with the standard way of doing things.

No screen can update with it until a timer is called
The reason for this is that GL never gets time to update it! By the time it is finished with its queue, you are already midway in another. So the driver gets confused and tries its best keep up, but to no avail.

a Timer of 1 is slower than a single Flip 0.
And that is because of OS process scheduling, any Delay on the main thread will make the process yield its timeslice to another process, even one as low as 1ms.


dw817(Posted 2016) [#17]
I can't emphasize the importance of using these commands however, Grable.



Now if you change Flip 0 to Flip and even put a remark symbol ' in front of the WaitTimer, you will see it definitely slogs slower than before.

Now what surprises me is apparently flip all by itself is running at 60 frames-per-second where I was understanding games today were 120 frames-per-second.

It's not a problem. I can use Flip 0 and WaitTimer. The added advantage too is I can run it even faster than that by doubling the top from CreateTimer(120) to CreateTimer(240). Much better control over how fast any code I write runs.

But THIS code above should let people be aware of just how much Flip() is slowing them down and preventing them from seeing the real speed behind BlitzMAX when checked in place with an accurate timer ...


dw817(Posted 2016) [#18]
Oh, and here is the final model of Frameless Window. I'll be using this on TileMaster when I get around to finishing it.



BTW, there's an initial hiccup which can definitely be seen if you choose a window smaller than your client's, Grable. It shows the frame and then removes it. Is there a way to prevent against this so when the window is created, it's already frameless ?


grable(Posted 2016) [#19]
Now what surprises me is apparently flip all by itself is running at 60 frames-per-second where I was understanding games today were 120 frames-per-second.
As said more than once, Flip defaults to VSYNC so getting 60 is the expected behaviour IF your monitor refresh rate is 60hz, which it probably is then.
And no, games today run at whatever the hardware can manage unless VSYNC is on.

It shows the frame and then removes it. Is there a way to prevent against this so when the window is created, it's already frameless ?
Not without modifying GLGraphicsDriver, its an easy enough change though. But you would need MINGW to recompile it.


dw817(Posted 2016) [#20]
Hmm ... Dare I ask ... how EASY ?

And yes, I tried a Graphics 0,0 just to see if it would not appear, Grable. No, it does, ugly frame and all.


grable(Posted 2016) [#21]
Hmm ... Dare I ask ... how EASY ?
Adding 3 lines to the C code.
Basically adding a new flag and checking for it before window creation..

EDIT: Heres a precompiled version og BRL.GLGraphics doing just that. https://drive.google.com/open?id=0BzVLNZSckvfhT1pwOFBTOGtucTQ
usage:
Graphics 640,480, 0,0, GLGRAPHICS_FRAMELESS



dw817(Posted 2016) [#22]
wait, I think it got it. I had to MOVE the original folder out of there.

... nope, still didn't work. Shows the frame. Here's the code:
Strict
Graphics 640,480,0,0,GLGRAPHICS_FRAMELESS
WaitKey
Both debug and without. And because there is STRICT, that means GLGRAPHICS_FRAMELESS is a recognized constant.


grable(Posted 2016) [#23]
And because there is STRICT, that means GLGRAPHICS_FRAMELESS is a recognized constant.

Hmmm, it would seem to be installed correctly if so yes.

But you of course need to:
SetGraphicsDriver GLMax2DDriver()
Because the default on windows is to use D3D9.

Btw, i accidentally left in some debug prints. You should redownload the file for an updated version.


dw817(Posted 2016) [#24]
Capital ! That got it, Grable. Let me check w some other programs. Using SetGraphicsDriver GLMax2DDriver(),0

Awright ... Hmm ... Now I'm wondering why the mass of code above if all I needed to do was update my GlGraphics library.

Any other tasty libraries I should know about ? Re-downloading the link you sent as you said it was updated.

Also, perhaps a list of what has been changed or updated in GlGraphics.mod ?


grable(Posted 2016) [#25]
The only thing i added was the GLGRAPHICS_FRAMELESS and frameless window creation.
If your talking about my second update to that file, it was some debug prints i forgot to remove.

Just be warned that you can not share code using GLGRAPHICS_FRAMELESS with others without that change.


dw817(Posted 2016) [#26]
Yeah, that is the problem there. Hmm ... Is there an official rewrite of all of BlitzMAX or something that is used by most of the members I'm not aware of ?

And Frameless graphics is a visual preference of mine I just want to have - it's not required to demonstrate any visual code I might write for others.


grable(Posted 2016) [#27]
Well there is the Open Source version, and Bruceys updated ones he uses for BMX-NG.
But it seems most people stay with vanilla 1.50 still. Me included.


dw817(Posted 2016) [#28]
Let me check my version ... I have:

BCC Version: BlitzMax Release Version 1.50
BlitzMax Path: c:\David\BlitzMax-1.50
MinGW Path c:\TDM-GCC-32
FASM Version: 1.69.14
GCC Version: 5.1.0
G++ Version 5.1.0

I know it says MinGW but I never could understand it - might be installed but darned if I know how to use it or really what it's for. :)

Welp, I have the ultimate Frameless window now. Both in code and Mods. Really do appreciate you getting this set up for me.

I'm going to open a conversation regarding BlitzMAX's SeedRnd() command. I hope you'll be there !