Can I "keep" images on the backbuffer?

BlitzMax Forums/BlitzMax Programming/Can I "keep" images on the backbuffer?

Abomination(Posted 2006) [#1]
XLSIOR stated somewhere on these forums: "you can't actually *count* on the backbuffer not getting cleared by the driver."
Does this mean I can't "savely" keep images on the backbuffer while it's beeing flipped?
eg. Ik draw something_1 to the backbuffer, flip, draw something_2,flip.
Can i be sure that something_1 is now visable?
Or is there a chance it's cleared somehow?
I want to know, because if have a large area of my screen that is mainly static and only needs to be refreshed if something moves over it.
I thought of just leaving it there and only redraw it when it changes.
But is this save under al circumstances?


H&K(Posted 2006) [#2]
NO
You cannot garentee that the backbuffer will still be in the same place next cycle. (Its often the same place, but thats just lucky)

What you need to do is draw the static stuff to a third buffer that you keep yourself, (Just a pixmap really), then blitz that to the back buffer, then draw the dynamic stuff, then filp
(Well you could just draw straight to the frount buffer, but..... well you know)

Edit. HAHA, ok somtimes you want to blitz the static background stuff, then draw the dynamic mainground stuff, then blitz the foreground static stuff (eg HUD), then the dynamic foregroud stuff, then flip


Abomination(Posted 2006) [#3]
hehe... problem is that the static BG is not THAT static.
And IF it changes, I would need to grab the backbuffer. And I REALY don't wan't to need to do that.
I thought of using "render2texture" by indiepath, but I could't get it to work the way I wanted.
Other sugestions?


H&K(Posted 2006) [#4]
Not Really. I just keep all the cell plains in pixmaps, manipulate them, then blitz


ImaginaryHuman(Posted 2006) [#5]
You can keep the backbuffer so long as you do your own `flip` routine, which would have to do a copy of the backbuffer to the front buffer. see glCopyPixels() etc


H&K(Posted 2006) [#6]
Really?

Thats good to know.
Can I do it with Max2d, or would I have to drop into opengl?


Grey Alien(Posted 2006) [#7]
My whole Xmas and Easter Bonus graphics engine was dirty rects-based and thus kept stuff on the backbuffer. But it was in BPlus...


Abomination(Posted 2006) [#8]
If I understand this correctly the backbuffer is not "cleared" sometimes, but replaced by an other one, somewhere else in VRam.
And this occurs the moment you do a flip.
So:after a flip: the backbuffer will always become the frontbuffer, but you can't be sure if the frontbuffer will be the backbuffer.
is this correct?

Now, "using glCopyPixels()" could I: copy the "Static" area from the frontbuffer to the backbuffer, draw the things that change, do a flip. [edit] how fast would this be?[/edit]
That way the static part should always be kept savely in VRam??
I don't know the first thing about GL, so could someone give me a push in the wright direction?


ImaginaryHuman(Posted 2006) [#9]
You would not need to copy the static area to the backbuffer. If you are keeping the backbuffer then presumably you are also then storing destroyed areas into some kind of safe buffer which you then replace inbetween frames before drawing the next set of animations. If you are going to be copying from the front buffer to the backbuffer you might as well just use double buffering and redraw your whole display each frame.
I've no idea on the speed, try it. Yes you can't do it in Max2D, you have to use a custom copy routine such as glCopyPixels(), or glReadBuffer(GL_BACK), glDrawBuffer(GL_FRONT), glCopyTexSubImage2D(), glBegin GL_QUADS, glVertex, etc...


Dreamora(Posted 2006) [#10]
What was the actual problem with Indiepaths render2texture?
I ask because its most likely the only performant way of doing what you want to achieve as it draws the rendertexture to backbuffer with no measurable time lose (which all other approaches don't offer)


Abomination(Posted 2006) [#11]
erm... no. I can't keep the backbuffer, because the "normal" drawing-commands draw on the backbuffer, so it needs to be flipped.
I want to keep an area of the frontbuffer so i don't have to grab a piece of the backbuffer.
If I can copy the BG-part from front- to back-buffer i can draw on it directly.
Do a flip and Voila!
[edit]
example:
you have a tiled background of three layers 1 player and on enemy.
[start loop]
you then have to draw the three layers then the player and the enemy. do a flip and start all over.[end loop]

I want to:
one time (at gamestart): draw the three layers to the backgound.
[start of loop]
then: save the parts where player and enemy will be and then draw player and enemy. do a flip.
Save the font to the back, repair th positions of player and enemy and start all over[end loop]


SculptureOfSoul(Posted 2006) [#12]
I'm just speculating, and I'm sure AngelDaniel (the man when it comes to OpenGL :) could probably clarify if this is plausible or not, but would it be possible to utilize a stencil buffer for something like this?

Is it possible to somehow utilize the stencil buffer as a mask that protects the static images from being overdrawn?


Dreamora(Posted 2006) [#13]
Abomination: And what was the actual problem with the r2t module? There you would draw your static stuff to the texture you specify and then draw that one first to the backbuffer and then the "dynamic part".
If the background (pseudo static) changes, you redraw the background texture, thats it.

I've been doing similar things to your problem with my entity module and indiepaths r2t module before I decided that it needs a major redesign.

btw: If the background changes every or every second frame, then the whole talk we are doing here is quite pointless


TartanTangerine (was Indiepath)(Posted 2006) [#14]
Ever tried not calling "Cls"? (problem with this in Fullscreen since you flip between surfaces).

You could always try my software render module for BMAX - it's on here somewhere and will so all of this for you.


Abomination(Posted 2006) [#15]
@dreamora Didn't see you up there:)

I can't predict how big the "static" parts will be, so any routine would have to take in account various sizes.
the texture to render to, has to have fixed sizes 128, 256 etc.
If I had to use more textures i had to find a way to draw over the "edge" of one and continue over the "edge" of an other.
Plus ( but this I didn't quite get) rendering to the texture was as if rendered to the screen. so if the grahics was 800 600, the result would distort by those proportions.
I couldn't see how to avoid difficult calculations to overcome these things.

@Exigo I will look in to it
Perhaps the probs I had with your mod have to do with me, not understanding how it works


Dreamora(Posted 2006) [#16]
??
You would create a single texture for your whole backbuffer, not "small blocks" you draw to.
That way at least the first half is easy to overcome.

And the second half theoretically as well: Create a texture large enough for your desired resolution. 1024x1024 shouldn't be a problem and it is enough for 1024x768 to work as "fake backbuffer"

What you are looking for isn't a background you can keep alive, but a "keep this block alive" functionality ... At least thats how your last discription looks like. *because a background has no edge or border where it ends. Its everything rendered until a given item thats static and everything afterwards would be the changing part*


Abomination(Posted 2006) [#17]
well; we are strolling away from the front-to-back-question,but hee.
You would create a single texture for your whole backbuffer, not "small blocks" you draw to.
That way at least the first half is easy to overcome
I want to use as less as VRam as possible, but yes this IS easier than multiple blocks.
1024x1024 shouldn't be a problem and it is enough for 1024x768 to work as "fake backbuffer"
but if I draw a square image to this this texture, it will look "flattened", so i need to do a drawimagerect to counter that, but that will blur the image. (unless I'm totaly wrong?)(I could be...)
"keep this block alive" functionality
Yes, it could even be part of the foreground, as long as it doesn't change for a longer amount of time.

Wel at least I have learned a couple of things
1.) The Backbuffer will flip to become the frontbuffer, but the frontbuffer will not always become the backbuffer.
2.) It is possible to use OpenGL to copy things from the front to the back. (thanks AngelDaniel)
3.) I still have no idea how to do that.(Guess I have to study OpenGL )


Dreamora(Posted 2006) [#18]
1024x1024 is 4MB of VRAM, 1024x768 is a little less VRAM, thats correct, but still you would need to maintain a full backbuffer for your copy, not only parts of it ... so the different is 1024x256 so 1MB VRAM, nothing to break the world :-)

I don't understand what you mean by flattened.
BM uses similar technique for all non power of 2 images: 200x200 becomes 256x256 with black outline you never see ... But that would need testing.
Draw image rect would cause problems, there you are right.
For that reason I would simply draw that 1024x1024 with drawimage to 0,0. The rest at the right would just be dropped.

That with part of the foreground is no problem, unless you plan to draw something in between. In that case there wouldn't be any possibility at all (without playing around with manually setting the zbuffer to force the background behind and foreground in front of everything you draw the next call)

Reason I would not suggest using OpenGL and tried to find a solution with indiepaths r2t: Are you planning that only ATI Radeon and NVIDIA GeForce users are able to use your app? Because OpenGL will enforce that. All Intel Users will most likely be out (more than 50% of all users and especially the sector of users that buy / use indie games)


Abomination(Posted 2006) [#19]
I don't understand what you mean by flattened
Example:
Strict

Import Indiepath.Render2Texture

HideMouse()
SetGraphicsDriver GLMax2DDriver()
Graphics 1024,768,32

tRender.Initialise()

Local logo:Timage = LoadImage("gfx/bmax160_2.png",0)
Local myImage:TImage = tRender.Create(1024,1024,0)

tRender.TextureRender_Begin(myImage)
   Cls
tRender.TextureRender_End()

SetBlend(ALPHABLEND)


While Not KeyHit(KEY_ESCAPE)
   
   SetBlend(ALPHABLEND)
   SetAlpha(1)
   tRender.TextureRender_Begin(myImage)
   Cls   
      DrawImage logo,20,20
   tRender.TextureRender_End()


   tRender.BackBufferRender_Begin()
   Cls
      SetBlend(ALPHABLEND)
      DrawImage myImage,0,0',256,256
      DrawImageRect myImage,600,0,1024,768
   tRender.BackBufferRender_End()
      DrawImage logo,320,20
   
   Flip
   
Wend
So I can get the proportions of the original (the right one) but only if I use DrawImageRect( the middle one)


Dreamora(Posted 2006) [#20]
If you create the render image as 1024,768 it will retain its proportions as the UVs are correct. it will be resized internally to 1024x1024, but to you it will remain correct.

But that showed a different strange thing, which when I'm not wrong is known:
If you create 256x256 and draw that it has a scaling issue.




Abomination(Posted 2006) [#21]
If I run your example with the setscale-line commented out it looks fine to me.
but is this meant to work without SetGraphicsDriver GLMax2DDriver()? Because it was so in the examples I have seen. Though that was the reason I couldn't get it to work the way it does without it.


Dreamora(Posted 2006) [#22]
Yes, the indiepath modules work with DX and OpenGL
If only OpenGL would work it would be pointless again for your problem as this would reduce the users of your app to NVidia GeForce and ATI Radeon owners which is undesirable.

Are you running BlitzMax 1.20 with latest sync mods? If so I have to find out whats going wrong with my module build.
As without the setscale, its broken on 256x256 rendertexture (it's totally underscaled)


tonyg(Posted 2006) [#23]
<edit as irrelevant>
That reduction in size is the same issue I'm having with my RT code. I can't find a way around it unless I do lots of odd things (drawtext, drawoval 0,0,0,0 etc).
Might not be the same issue but, imo, the RTT capability is tricky to say the least.


Abomination(Posted 2006) [#24]
erm, I import it like so:Import "Render2Texture.bmx".
Because I had no idea were to find indiepath! hehe.

and yes 1.20 and sync mods.
No underscaling here...
with setscale it tolaly overscales