Clueless And Frameless
BlitzMax Forums/Brucey's Modules/Clueless And Frameless
| ||
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." |
| ||
Here you go, no need to beg brucey for this ;) |
| ||
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 bufferSo 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 ? |
| ||
Now how do I set it so I have the effect of this command ? Like you would when you normally call Graphics. Call it first.SetGraphicsDriver GLMax2DDriver(),0 ' zero forces front buffer 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 |
| ||
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 bufferIt 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 ? :) |
| ||
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. |
| ||
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: |
| ||
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) |
| ||
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. |
| ||
Using Flip is not difficult : Draw all your stuff Flip() Draw all your stuff Flip() etc. |
| ||
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 EndFunctionSo 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. |
| ||
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. |
| ||
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. |
| ||
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 correctlyEven 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. |
| ||
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. :) I inserted this code: For i=0 To 77 Flip 1 Next WaitTimer timer ' defined above, wait specified timeAnd 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 ! |
| ||
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. |
| ||
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 ... |
| ||
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 ? |
| ||
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. |
| ||
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. |
| ||
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 |
| ||
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 WaitKeyBoth debug and without. And because there is STRICT, that means GLGRAPHICS_FRAMELESS is a recognized constant. |
| ||
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. |
| ||
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 ? |
| ||
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. |
| ||
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. |
| ||
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. |
| ||
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 ! |