does the order matter druing a g.dispose() strat.show()

Does it matter at all what comes first? Is there a difference between:

g.dispose();
strategy.show();

and

strategy.show();
g.dispose();

It doesn’t matter. We recommend disposing of Graphics context as soon as you’re done
rendering to the surface (which means the first case).

As a matter of fact, we’ve recently updated the sample code in the javadoc for BufferStrategy class.
Check it out:
http://download.java.net/jdk6/docs/api/java/awt/image/BufferStrategy.html

Thanks,
Dmitri

When I had this conversation about the example code with campbell he stopped responding to the thread.
I figured it had fallen through the cracks. Thanks for making some changes to it. :slight_smile:

// Repeat the rendering if the drawing buffer was lost
} while (strategy.contentsLost());

under what circumstances can that occur?

Many circumstances like resolution changes, no free vram and a hand of other events.
Its just not guaranteed that contents are always restored thats why the programmer needs to take care of.

lg Clemens

If you have a non-fullscreen frame with BufferStrategy and the frame was resized,
for example.

Dmitri

Not sure I see the need for the outer contentsLost() loop.

It doesn’t protect you from potencially displaying a lost buffer, if the buffer is lost between :-

         } while (strategy.contentsRestored());

and…

         // Display the buffer
         strategy.show();

And in a vsync’ed configuration, it will result in the paint loop blocking for a 2nd frame, when it could have been doing a game update.

It’s a good point, but the lost buffer won’t be shown - the buffer swap operation (or a blit) will fail.

I’m actually thinking about modifying the code such that we don’t even attempt
to show a lost buffer, and make show() a no-op in this case so you don’t need to do
stuff like this:


  ...
  if (!strategy.contentsLost()) {
    strategy.show();
  }
} while (strategy.contentsLost())

The goal of the sample was to show how make sure that a frame was rendered fully and correctly.
For example, Swing uses BufferStrategy and they have to do this, since there may not be
another repaint event for a while, and the user must see a consistent gui in the meantime.

Dmitri

ah, that little nugget of info. makes the example loop make alot more sense.
(though that info. realy should be covered in the javadoc)

However, even with this implicit behaviour there is still a limitation that will require either an API change, or a further addition to the underlying functionality.

If the surface is lost between this :-


    strategy.show();

And this :-

} while (strategy.contentsLost());

You will end up rendering the same frame twice, even though it wasn’t necessary.

I can see 2 ways to fix this.

  1. Change show() so it returns a boolean indicating success.
    The outside loop can then be replaced with
} while(!strategy.show());
  1. Change the implementation of contentsLost, so it doesn’t return true if the buffer has been lost after a successful show().
    A successful call to show() would freeze contentsLost() to always return false until the next call to getDrawGraphics().

The 2nd change is obviously easier but in my opinion is a nasty hack.
However I can see that changing just the return type of a method, and maintaining backward compatability would be a nightmare.
(requiring deprecation of “void show()”, and a new method adding - something like “boolean showBuffer()”.

How about 2 examples, one that works with Passive rendering and another for Active. Most people who are making games should be using Active rendering. If a window is resized, dropping a frame redraw probably isnt a big deal, so keeping the timing on track may be more important, so getting to the next update phase is good. Although if your timing code is written properly it wont matter either way :slight_smile:

I still think having at least a commented out section of code that recreates the BufferStrategy for pre Java6 compatibility would be a good thing.

In that case you get the javadoc for the version you are targetting :wink:

Well yeah I guess :slight_smile:

Unfortunately the other examples were never very good.

loop part of Javadoc for 5

// Render loop
while (!done) {
Graphics g = strategy.getDrawGraphics();
// Draw to graphics

strategy.show();
}

Remember to optimize for the most often used path. In this case it’s “nothing failed, everything is OK”.
But in case of an error (which is rare) do everything you can to show the correct stuff,
even if costs a bit (like rendering the same frame one extra time) . Errors are rare, we don’t
need optimizing this path.

With this philosophy in mind I think the suggested sample code fits fine, for both
active and passive cases.

Thanks,
Dmitri

yeah, brush the API flaw under the carpet.
Who cares about doing things the right way!

Just don’t be suprised when a bug is reported against it, as I’m sure someone will find a situation where this bug will cause a problem.

A situation I can think of right away, is where an application has a rendering cycle that takes a loooong time.
Performing an excessive rerender of an entire frame, when it wasn’t absolutely necessary could be extrememly annoying - and with the current API implementation is unavoidable.

tbh, I don’t see why BufferStrategy exposes the contentsLost and contentsRestored methods.
All an application cares about is whether show() was successful or not.

In my mind a far better implementation would have been to throw a RuntimeException of some kind at the first render operation attempt onto a surface that had lost its contents.
Afterall loss of the rendering surface is an exceptional circumstance.

A typical rendering loop would then look like :-



while(running) {

   boolean renderingFailed = false;
   do {
      Graphics g = strategy.getDrawGraphics();
      try {
         try {
            // misc rendering operations onto Graphics g.


         }
         finally {
            g.dispose(); // should always be done in a finally (incase of an unexpected Exception)
         }
         strategy.show();
      }
      catch(ContentsLostException e) {
         renderingFailed = true;
      }
   }
   while(renderingFailed);
}

There is a big difference between wasting time optimizing stuff that rarely happens, and “brushing the API flaw under the carpet”

[quote]A situation I can think of right away, is where an application has a rendering cycle that takes a loooong time.
Performing an excessive rerender of an entire frame, when it wasn’t absolutely necessary could be extrememly annoying - and with the current API implementation is unavoidable.
[/quote]
You left out “would almost never happen”, but I get the point… if the change to the API is trivial why not just do it?

You do-while loop is broken ‘renderingFailed’ is out of scope in the ‘while’ part. That example won’t compile, but again I get the point. It doesn’t seem unreasonable.

ta, fixed.
Too busy fixing the tab alignment ::slight_smile:

I myself don’t think the BufferStrategy stuff is a well-designed api, but we have to work with what we’ve
got because of the backward compatibility. So whatever we do, we would still have to support
contentsLost() and contentsRestored().

Anyway, handling a contents lost situation with an exception would be inconsistent with
the rest of the apis dealing with VolatileImages - so that stuff would also need to be changed.

Another thing is that you want to validate your graphics before rendering to it - this is
currently done in getDrawGraphics(), so it should be done inside the loop.

What do you think about show() returning a status? So it’d look something like this:


do {
    Graphics g = strategy.getDrawGraphics();
    // render to g
    g.dispose();
} while (strategy.show() != SUCCESS)

You can have the try/finally for the disposal of the graphics there as well.

Dmitri

Unless a liberal sprinkling of @deprecated was applied :slight_smile:

Though I agree, for such a minor change it isn’t worth it.

[quote]Anyway, handling a contents lost situation with an exception would be inconsistent with
the rest of the apis dealing with VolatileImages - so that stuff would also need to be changed.
[/quote]
yeah, blitting to a VolatileImage would have to behave in the same fashion as BufferStrategy.

When blitting from a VolatileImage, a Listener pattern would be realy nice.

Each time the VolatileImage was used for a blitting operation (where pixel reading from the Image was necessary),
a check to contentsLost() would be done ‘under the hood’.
If the contents was found to be lost, a reconstruction method (implemented in user code) would be invoked in the VolatileImages listener.

This would give VolatileImages the same usability as managed Images, without any of the nasty complication that the current API involves.

[quote]Another thing is that you want to validate your graphics before rendering to it - this is
currently done in getDrawGraphics(), so it should be done inside the loop.
[/quote]
ah yes, another silly mistake in my example. Fixed.

[quote]What do you think about show() returning a status? So it’d look something like this:


do {
    Graphics g = strategy.getDrawGraphics();
    // render to g
    g.dispose();
} while (strategy.show() != SUCCESS)

You can have the try/finally for the disposal of the graphics there as well.

Dmitri
[/quote]
Yeah, I suggested something earlier.
While such a solution would not break any existing source code, it would break backward bytecode compatibility.(i think?)
Also, you cant have 2 methods with the same signature, so you couldn’t simply add a new variant of show() that had a return type.

You would end up having to deprecate “void show()”, and add a new method “boolean/int showBuffer()” or something.

[quote]Also, you cant have 2 methods with the same signature, so you couldn’t simply add a new variant of show() that had a return type.
[/quote]
I realize that, I’m just speculating…

Dmitri