Java-Gaming.org Hi !
Featured games (83)
games approved by the League of Dukes
Games in Showcase (541)
Games in Android Showcase (133)
games submitted by our members
Games in WIP (603)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1] 2
  ignore  |  Print  
  getGraphics()  (Read 10917 times)
0 Members and 1 Guest are viewing this topic.
Online zeroone
« Posted 2006-10-16 13:32:39 »

If I invoke getGraphics() on a panel or a frame from a worker thread (as opposed to the swing/awt event-dispatching thread) and use the returned Graphics object for drawing, how often do I need to dispose it and grab a new one?  Will it occationally become invalid and if so, how do you detect when it can no longer be used for drawing?
Offline Abuse

JGO Knight


Medals: 15


falling into the abyss of reality


« Reply #1 - Posted 2006-10-16 13:37:12 »

Why not just grab a new one every game loop?
It doesn't effect performance, and will give u smaller bytecode.

Make Elite IV:Dangerous happen! Pledge your backing at KICKSTARTER here! https://dl.dropbox.com/u/54785909/EliteIVsmaller.png
Online zeroone
« Reply #2 - Posted 2006-10-16 13:51:49 »

Are you sure it does not affect performance if I obtain a new one per loop iteration and dispose the old one?  What's the basis of that?  And, why would that compile to a smaller class file?
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline Abuse

JGO Knight


Medals: 15


falling into the abyss of reality


« Reply #3 - Posted 2006-10-16 13:54:14 »

Are you sure it does not affect performance if I obtain a new one per loop iteration and dispose the old one?  What's the basis of that?  And, why would that compile to a smaller class file?

I wouldn't bother disposing of it - that will definitely save you space.

Make Elite IV:Dangerous happen! Pledge your backing at KICKSTARTER here! https://dl.dropbox.com/u/54785909/EliteIVsmaller.png
Offline woogley
« Reply #4 - Posted 2006-10-16 14:12:04 »

you should -always- dispose() after each frame, otherwise on some platforms the game will not be displayed correctly.

at least, that is what kevin glass told me (I asked him why he didn't get rid of dispose() in his Goop 4K game)
Offline Son Of Cain

Junior Devvie





« Reply #5 - Posted 2006-10-16 14:26:17 »

I do it like this:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
 // Loop
        while ( running ) {
           
            long elapsedTime = System.nanoTime() - current;
            current += elapsedTime;
           
            // Graphics and Graphics2D
            // game is a JPanel, instance of my main and only class
            Graphics g = game.getGraphics();
            Image screen = game.createImage(800, 600);
            Graphics2D g2d = (Graphics2D) screen.getGraphics();

            // draw with g2d
            // ...

           // in the end
           g.drawImage(screen, 0, 0, game);
           g2d.dispose();


I only dispose of the graphics instance of the BufferedImage, which is the "screen" where I render all my stuff. Didn't notice anything unusual up to now.

Rodrigo
Online zeroone
« Reply #6 - Posted 2006-10-16 14:44:12 »

In that loop, you not only create and dispose new Graphics objects, you create a new image.  Why not create an image once and use it throughout?  Does anyone have documentation about when Graphics objects need to be disposed?
Offline woogley
« Reply #7 - Posted 2006-10-16 15:39:04 »

wow, Son of Cain. for one, you're using Image, not BufferedImage. secondly, you should not create a new image for each frame, that's a huge performance killer.

if you used an actual BufferedImage instance, you wouldn't need to cast (Graphics2D) either, as BufferedImage's createGraphics() method returns a Graphics2D object.

zeroone, from the JavaDoc,
Quote
For efficiency, programmers should call dispose when finished using a Graphics object only if it was created directly from a component or another Graphics object.

thus, you should dispose() the Graphics object you receive from getGraphics(). This is an example of when you do not need to dispose it:

1  
2  
3  
4  
5  
public void paint(Graphics g) {
  // drawing stuff here
  // ..
  // we do not need to call g.dispose() here, because the class that called this method will do it automatically
}
Online zeroone
« Reply #8 - Posted 2006-10-16 15:54:19 »

I agree the Javadoc says that you should dispose it, but when should you do it?  Once per game loop iteration or once per application execution?  Can I safely hold onto a Graphics handle for the full program run or is there a chance it will become invalid?
Offline woogley
« Reply #9 - Posted 2006-10-16 15:59:14 »

since the doc says that several Graphics objects can be created in a short time frame, I would say it's best to dispose() of the Graphics object per frame. I've heard some people say (on the Sun forums I believe) that the Graphics context can change at any time, so if you're going to bother grabbing getGraphics() every frame, you might as well dispose() of it also.
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Online zeroone
« Reply #10 - Posted 2006-10-16 16:02:16 »

I've heard similar things, but where's the proof?  Does this only apply to Graphics objects that point to panels/frames/components?  How about Graphics objects that point to BufferedImages?
Offline woogley
« Reply #11 - Posted 2006-10-16 16:08:05 »

proof is this: you call getGraphics() every frame, yeah? why in the hell wouldn't you dispose of the old one, since you're never going to use it again?

solid proof isnt available to me, I've only heard about Graphcis glitches from those who use macs and some versions of linux. (I'm stuck on windows)

the Graphics from BufferedImages fall under the same rule. the only Graphics objects that aren't affected by the rule are the ones passed through the paint method, because the object that called paint will dispose of the Graphics automatically. (of course, if you called paint yourself, then you'd have to dispose of the Graphics yourself)

in the end, every Graphics object is supposed to be disposed, the real question is "who" does it. If you don't call paint, then you don't have to dispose of the Graphics object that comes with the parameter. if you acquire a Graphics object in any other way, through getGraphics() on an image or component or wherever, you're supposed to dispose of it yourself.
Online zeroone
« Reply #12 - Posted 2006-10-16 16:12:00 »

I agree that it makes sense to dispose of the Graphics object once per frame if it were obtained with getGraphics() once per frame.  However, is there really anything wrong with calling getGraphics() once and only once at the start of the program since this is not full screen exclusive mode.
Offline woogley
« Reply #13 - Posted 2006-10-16 16:16:29 »

I can't say for sure, some people say there's no problem with it (I've never had a glitch on my windows box), others on non-windows boxes have experienced some graphical glitches.

I would play it safe and dispose every frame, because due to java's cross-platform compatibility, you can't be 100% confident in the underlying rendering system. maybe windows doesn't experience glitches because of the DirectDraw that java uses? well linux and mac dont have DirectDraw, which could be why not disposing on certain versions of mac/linux produce errors.

it would be really nice if Dmitri could enlighten us on this. (he's pointed out some very interesting things about java2d)
Offline oNyx

JGO Coder


Medals: 2


pixels! :x


« Reply #14 - Posted 2006-10-16 16:18:37 »

>Can I safely hold onto a Graphics handle for the full program run[...]

No. Your program might consume all ram and then hang. One of my first games did that on Macs, because I initially recycled the Graphics object.

So dont do that. Its glitchy and not any faster.

Get, draw, dispose... each frame. (I think its about the 5th time I wrote that.)

弾幕 ☆ @mahonnaiseblog
Online zeroone
« Reply #15 - Posted 2006-10-16 16:35:49 »

oNyx,

Does that apply only to the Graphics object that points to visible components (i.e. frames or panels)?  Can I safely hold onto a Graphics object to a BufferedImage for the duration of the program run?

Any idea why it consumes resources to hold onto the Graphics object for a long period of time?
Online zeroone
« Reply #16 - Posted 2006-10-16 17:14:54 »

From http://fivedots.coe.psu.ac.th/~ad/jg/ch1/ch1.pdf:

Quote
The panel's graphics context may be changed by the JVM, typically when the canvas
is resized or when it becomes the front window after being behind others. Also, the
context may disappear if the application or applet exits while the animation thread is
running.

For these reasons, the graphics context must be freshly obtained each time it is needed
(by calling getGraphics()). Also, its use must be surrounded by a try-catch block to
capture any failure due to its disappearance.

In practice, if the program has a fixed window size, then the most likely time for an
exception is when a game applet is terminated by the user closing its surrounding
Web page.

This suggests that holding onto a Graphics object will not slowly eat up system resources; however, it does mean that the object may eventually become unusable.  What's worse is that getGraphics() may return null; so, we need to check for that.  Also, when the Graphics object becomes unuseable, it may throw an exception when you invoke one of its methods; so, we need to catch that exception.

It's still unclear if this applies to Graphics objects that point to BufferedImages.

Is anyone really going to do for a 4K game.  Seems like a lot of code to prepare for an extremely unlikely event.  I've never had getGraphics() return null and I've never had a Graphics object throw an exception.
Offline oNyx

JGO Coder


Medals: 2


pixels! :x


« Reply #17 - Posted 2006-10-16 17:20:23 »

>Can I safely hold onto a Graphics object to a BufferedImage for the duration of the program run?

Like manual double buffering? No.

>Any idea why it consumes resources to hold onto the Graphics object for a long period of time?

Dunno. Guess the mac implementation stored the things you did in some list for some reason (the mem consumption was rather slow... after 15minutes it ate 300mb iirc).

edit: null... never seen that, never wrote a check for that.

弾幕 ☆ @mahonnaiseblog
Offline woogley
« Reply #18 - Posted 2006-10-16 17:22:48 »

Graphics are Graphics. whether they come from JFrame, or BufferedImage, or Image. the only time you're not supposed to dispose() it is when you're using a Graphics object passed through a method, because the method caller will dispose it automatically.

and this is not hard in a 4K game, you do not need to check for exceptions if you "get, draw, dispose"

example ..
1  
2  
3  
4  
5  
6  
7  
8  
9  
Graphics gfx = buffer.createGraphics(); // the buffer graphics
// draw stuff
// ..

// now render buffer to screen
Graphics g = getGraphics();
if (g != null) g.drawImage(buffer,0,0,null);
g.dispose();
gfx.dispose();
Online zeroone
« Reply #19 - Posted 2006-10-16 17:32:42 »

Quote
you do not need to check for exceptions if you "get, draw, dispose"

Apparently, "draw" can throw an exception if the Graphics object becomes invalid between "get" and "draw".  If you don't bother to catch the exception, there is no point in refreshing the Graphics object with "get" in the first place.  Your program will crash in that rare event.
Offline woogley
« Reply #20 - Posted 2006-10-16 17:34:53 »

an exception will not be thrown unless you're doing something out of the ordinary. e.g. drawing to an Image that was created with createImage(width,height) using a Window that was invisible.

and if its so rare, you do not need to bother checking for it, especially in 4K (exception catching is nearly nonexistant in 4K..)

but that doesn't even matter, the only 100% away to avoid such an exception is not to draw at all Wink
Online zeroone
« Reply #21 - Posted 2006-10-16 17:47:51 »

If you bother to check if the Graphics object is null, then you might as well check for the exception.  Both appear to indicate the same issue; it's just a matter of where you are in the game loop when it occurs.  If you detect for the null condition to prevent the game from crashing, then you should catch the exception.  Doing one without the other doesn't make a lot of sense.  Either accept that the thread can die in the unlikely event that the Graphics object becomes invalid or completely cover your bases to let the program carry on. 

I suspect that getGraphics() will only return null or an exception will be thrown during "draw" is when the frame/panel cannot be drawn to prior to being displayed or during shutdown of the application.

I still don't understand why the Graphics object for a BufferedImage ever needs to be disposed.  What could render it invalid?
Offline woogley
« Reply #22 - Posted 2006-10-16 17:56:36 »

...

the exception and null value can be completely different issues. you should check for null because the Window can return null when the Window is minimized or otherwise unfocused/invisible/nondisplayable.

this does not mean you need to check for an extremely rare exception (I've never heard of it myself), that's a waste of space. The doc does not say Graphics will throw an exception, but the doc for getGraphics() does mention it can return null. that's why you should check for null, and shouldn't be worried about the Exception ,that's more on the VM level than anything  (probably not something you can control - especially since it will crash your game whether you catch it or not)

I still don't understand why the Graphics object for a BufferedImage ever needs to be disposed.  What could render it invalid?

can't say for sure, probably something to do with the underlying buffers. as oNyx mentioned, for reasons unknown, holding any Graphics object in memory will consume ram. so if you're grabbing a new Graphics object each frame, it's only logical to dispose of it at the end of each frame
Offline g666

Junior Devvie





« Reply #23 - Posted 2006-10-16 17:58:44 »


>Can I safely hold onto a Graphics object to a BufferedImage for the duration of the program run?

Like manual double buffering? No.


ive done that for my 4k stuff last year and some stuff ive started this year, ive never had any problems.

desperately seeking sanity
Offline woogley
« Reply #24 - Posted 2006-10-16 17:59:46 »

ive done that for my 4k stuff last year and some stuff ive started this year, ive never had any problems.

were you on Mac? as stated earlier, different Graphics problems stretch across the different platforms
Offline Son Of Cain

Junior Devvie





« Reply #25 - Posted 2006-10-16 19:50:52 »

wow, Son of Cain. for one, you're using Image, not BufferedImage. secondly, you should not create a new image for each frame, that's a huge performance killer.

if you used an actual BufferedImage instance, you wouldn't need to cast (Graphics2D) either, as BufferedImage's createGraphics() method returns a Graphics2D object.

Thanks, dude Wink My first time on 4K Cheesy

The creteGraphics(int, int) returns an Image, which I assumed to be of subtype BufferedImage. Am I wrong? Having the reference declared as a super class changes nothing right, since the methods will be called on the correct subclass (BufferedImage, in this case, if I'm not wrong).

The image creation within the loop was dumb, I acknowledge that. Thanks for the tip, now it's fixed  Roll Eyes
Offline woogley
« Reply #26 - Posted 2006-10-16 19:56:51 »

Thanks, dude Wink My first time on 4K Cheesy

awesome. welcome Smiley

The creteGraphics(int, int) returns an Image, which I assumed to be of subtype BufferedImage. Am I wrong?

actually, BufferedImage is a sublcass of Image. Image has been around since java 1.0, BufferedImage wasn't on the scene until Java 1.3 I believe. Also note that creating a BufferedImage does not rely on your Window to be visible (like createImage(int,int) does).
Offline Son Of Cain

Junior Devvie





« Reply #27 - Posted 2006-10-16 20:31:30 »

Yes, I meant that, the other way around :p
As you see, i'm not a native english speaker :p
Offline Markus_Persson

JGO Wizard


Medals: 16
Projects: 19


Mojang Specifications


« Reply #28 - Posted 2006-10-17 13:39:49 »

I still don't understand why the Graphics object for a BufferedImage ever needs to be disposed.  What could render it invalid?

can't say for sure, probably something to do with the underlying buffers. as oNyx mentioned, for reasons unknown, holding any Graphics object in memory will consume ram. so if you're grabbing a new Graphics object each frame, it's only logical to dispose of it at the end of each frame

I've never seen this happen, and I can find no mention at all of Graphics objects to be disposed because "they're no longer valid" in the javadocs.

Source?

Play Minecraft!
Offline woogley
« Reply #29 - Posted 2006-10-17 14:03:20 »

"no longer invalid" is zeroone's words, not mine. what you quoted is my best guess, after my recent buffer revelation Tongue

I quote the javadoc as saying:
Quote
"When a Java program runs, a large number of Graphics  objects can be created within a short time frame."

it goes onto say how the Graphics in paint(Graphics) and update(Graphics) are disposed of automatically, but then says otherwise-acquired Graphics objects should be disposed of manually:

Quote
"Graphics objects which are provided as arguments to the paint and update methods of components are automatically released by the system when those methods return. For efficiency, programmers should call dispose when finished using a Graphics object only if it was created directly from a component or another Graphics object."
(source: http://java.sun.com/j2se/1.4.2/docs/api/java/awt/Graphics.html#dispose())

as far as solid proof goes, you'd need that program oNyx was talking about and a Mac platform to test it on. I'm stuck on Windows, and Windows doesn't seem to be affected by dispose() (or lack thereof).

I've also heard from Kevin Glass (when I was asking him why he didn't remove dispose() in his Goop4K game to save space) that dispose needs to be called to avoid graphical glitches on different platforms.

when you read the javadoc quoted above, the major unclarity is when you're considered to be "done" with a Graphics object - in oNyx's case, he wasn't done until the program closed, which resulted in (according to him) RAM consumption.

being on windows, the whole issue is somewhat confusing to me. up until now, I have never used dispose() (just check out the Goomba4K source), but maybe those random glitches (see the Goomba4K thread) were caused by the lack of dipose(). if kevglass isn't going to take the risk, I'm certainly not either o_O
Pages: [1] 2
  ignore  |  Print  
 
 
You cannot reply to this message, because it is very, very old.

 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

Mr.CodeIt (24 views)
2014-12-23 03:34:11

rwatson462 (55 views)
2014-12-15 09:26:44

Mr.CodeIt (46 views)
2014-12-14 19:50:38

BurntPizza (91 views)
2014-12-09 22:41:13

BurntPizza (113 views)
2014-12-08 04:46:31

JscottyBieshaar (83 views)
2014-12-05 12:39:02

SHC (92 views)
2014-12-03 16:27:13

CopyableCougar4 (102 views)
2014-11-29 21:32:03

toopeicgaming1999 (161 views)
2014-11-26 15:22:04

toopeicgaming1999 (164 views)
2014-11-26 15:20:36
Resources for WIP games
by kpars
2014-12-18 10:26:14

Understanding relations between setOrigin, setScale and setPosition in libGdx
by mbabuskov
2014-10-09 22:35:00

Definite guide to supporting multiple device resolutions on Android (2014)
by mbabuskov
2014-10-02 22:36:02

List of Learning Resources
by Longor1996
2014-08-16 10:40:00

List of Learning Resources
by SilverTiger
2014-08-05 19:33:27

Resources for WIP games
by CogWheelz
2014-08-01 16:20:17

Resources for WIP games
by CogWheelz
2014-08-01 16:19:50

List of Learning Resources
by SilverTiger
2014-07-31 16:29:50
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!