maxGUI game without tearing possible?
BlitzMax Forums/MaxGUI Module/maxGUI game without tearing possible?
| ||
Is it possible to have a maxGUI game in a window, not using flip(1) without any tearing? Or should I just not bother using maxGUI for games? I can get smooth animation with no tearing using flip(1) but then it hogs all the cpu cycles. If I use flip(0) or flip(-1) then the cpu cycles are minimal but I get tearing. I'm making a small cross platform windowed toy to have on the desktop so it can't be taking up all the cpu cycles as it's for people to have open and play with while they are doing other things as well. The tearing is especially noticeable when the mouse pointer goes over the canvas. The pointer turns into an image and if you move it around just even moderately fast it tears like crazy. I'm at work so I don't have code to post, but if anybody would explain to me a opengl setup that won't tear and won't hog the cpu that would be great. I searched through the forums but couldn't find anything that worked. Otherwise I will have to live without some of the things I would like to use maxGUI for. Thank you, James |
| ||
A few guesses without much real knowledge to back them: - Call flip 1 less often via an anim timer? So you only ever Flip when something changes - Somehow set the Canvas Graphics hz to a multiple of your screen hz and use Flip -1 in the attempt to skip refreshes. I'm not sure how you would do that or if it would work though! Failing that I think Flip 1 is going direct to the gl graphics driver, which by my guess would make it more a gl issue than a max gui one. - David |
| ||
Try Flip -1 (the default) Flip 1 forces processor busy wait I think. My nvidia card under xp seems to flip -1 without tearing and no 100 cpu % for both dx and gl. I think there is a GL extension at work for the swapinterval so may not be supported on all cards, hence your problems. The following has been tested with gl canvas and seems to work, call before Flip 0. Import PUB.DirectX Function WaitVB() Global _ddraw7:IDirectDraw7 If Not _ddraw7 DirectDrawCreateEx( Null,Varptr _ddraw7,IID_IDirectDraw7,Null ) EndIf If _ddraw7 GrabPixmap(0,0,1,1) ' flush drawing buffer _ddraw7.WaitForVerticalBlank(DDWAITVB_BLOCKBEGIN,0) EndIf End Function |
| ||
Thanks for the suggestions. I'll give them a try when I get home. skidracer, is theresomething equivalent to what you posted for opengl? What you posted won't work for linux or osx right? I'll give it a try on my windows machine though to see if it works. Thanks, James |
| ||
flip -1 should be working fine and tear free on all platforms including win32, if not let me know and I will look into it further. |
| ||
The "only draw when something changes" or "when you get a Paint event" is a good idea for an app that you expect to run all the time on the desktop. That way you return a LOT more CPU cycles to the PC. |
| ||
The grabpixmap trick effectively flushes the graphics pipeline which by logic seems like a good state to be in before asking for a synchronized flip. The directdraw interface dates back to 95 and is still supported by directx9 (possibly a lot more reliably than it ever was we trust). If you using pure max2d i'd recomend testing out the dx9 libs for your windows users, Doug seems very wise in his approach to such things. |
| ||
Well, I'm basing my code on the example hook rendering code in the docs. All I did was to turn the mouse pointer into an image when it's over the canvas. Just edit the mousePointer field to load whatever image you want, run it and move the mouse around. It tears pretty bad on my desktop and laptop. Skidracer, the waitVB code you posted got rid of the tearing but it pegged the cpu just like flip(1). I also tried using directx but I got the same results.' rendering a canvas using an EventHook based Applet Type Strict Type TApplet Field window:TGadget Field canvas:TGadget Field timer:TTimer Field mousePointer:TImage = LoadImage("./Assets/Textures/blob.png") Field mDraw:Int Field mX:Short Field mY:Short Method Render() Local x,y,width,height,t,i width=GraphicsWidth() height=GraphicsHeight() SetViewport 0,0,width,height SetClsColor 0,0,0 Cls ' draw blobs SetBlend LIGHTBLEND If mDraw = True Then DrawImage(mousePointer,mX,mY) End If SetBlend SOLIDBLEND End Method Method OnEvent(event:TEvent) Select event.id Case EVENT_WINDOWCLOSE End Case EVENT_TIMERTICK RedrawGadget canvas Case EVENT_GADGETPAINT SetGraphics CanvasGraphics(canvas) Render Flip Case EVENT_MOUSEMOVE mX = event.x my = event.y Case EVENT_MOUSEENTER HideMouse mDraw = True Case EVENT_MOUSELEAVE ShowMouse mDraw = False End Select End Method Function eventhook:Object(id,data:Object,context:Object) Local event:TEvent Local app:TApplet event=TEvent(data) app=TApplet(context) app.OnEvent event End Function Method Create:TApplet(name$) Local a:TApplet Local w,h window=CreateWindow(name,20,20,512,512) w=ClientWidth(window) h=ClientHeight(window) canvas=CreateCanvas(0,0,w,h,window) canvas.SetLayout 1,1,1,1 timer=CreateTimer(60) AddHook EmitEventHook,eventhook,Self Return Self End Method End Type AutoMidHandle True Local applet:TApplet applet=New TApplet.Create("Render Applet") While True WaitEvent Wend |
| ||
Well, I haven't been able to get smooth non tearing graphics in a maxGUI window without maxing out the cpu utilization whether I use directx or opengl. So I'm going to have to move on and do this without maxGUI. Thanks for the help everybody. James |
| ||
Okay, I came up with an acceptable solution to my dilema which I'm sure people already use. I basically switch flip(1) to flip() or pause the rendering when the app is suspended to kick the cpu usage down. That way, if the user needs to stop and do something else the cpu is freed but when the user goes back to the game, flip(1) get's used and I get no tearing :) I'm using flip() while the app is suspended because I want some little animations to run in the background but otherwise I would just pause it. Flip() works alright as long as nothing is moving too fast. James |