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 |