Java-Gaming.org    
Featured games (79)
games approved by the League of Dukes
Games in Showcase (476)
Games in Android Showcase (106)
games submitted by our members
Games in WIP (532)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  Graphics2D.drawImage() is my bottleneck  (Read 4561 times)
0 Members and 1 Guest are viewing this topic.
Offline Malohkan

Senior Member




while (true) System.out.println("WOO!!!!");


« Posted 2004-07-08 18:21:16 »

My latest game is nearing completion and I'm trying to fine tune the works of it.  I had it written for phone/pda sizes in an Applet and I have another guy working on converting my code to J2ME code.  So now what I'm doing is making it scale up for play at 800x600 and higher for a PC version, but now I'm hitting some performance problems.

I'm using the GAGETimer to keep my framerate at 50fps and I've modified the sleepUntil() to return the number of times it it yielded, which I then print on my screen each frame.  When I play the game the low-res way at 300x300 I get 6000-12000 yields every frame, I'm happy with that.  When I play the high-res way at 800x600 (with different art to match the resolution) the yields are ALWAYS 0.  That tells me I need to do a bit of optimizing :)

So profiling has revealed where the biggest bottlenecks are.  I tried bringing up the biggest one a couple of weeks ago on the Java Gaming Forums at Sun, but I didn't really get much of a response so hopefully you guys can help me tune this up.  So here's the biggest one, aparantly taking 20% of my processing time each loop.  It's where I draw the background tiles of the game.  And that's when there's like 15 other ships firing their weapons at me on the screen.  Without that it's over 35%

1  
2  
3  
for (int i = bgStartX-Constants.SYSTEM_TILE_WIDTH; i < Constants.GAME_WIDTH; i += Constants.SYSTEM_TILE_WIDTH)
      for (int j = bgStartY-Constants.SYSTEM_TILE_HEIGHT; j < Constants.GAME_HEIGHT; j += Constants.SYSTEM_TILE_HEIGHT)
            g2d.drawImage(back, i, j, null);
bgStartX is a number%Constants.SYSTEM_TILE_WIDTH which goes in so I can set the BufferedImage "back" just far enough behind the screen to start to satisfy the scrolling effect.

back is created with:
1  
GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration().createCompatibleImage(width, height, Transparency.OPAQUE)
I look forward to any advice I can get.  Thanks in advance!

Admin and Game Developer at
GameLizard.com
Play Rimscape!    |    Play Conquer!
Offline jbanes

JGO Coder


Projects: 1


"Java Games? Incredible! Mr. Incredible, that is!"


« Reply #1 - Posted 2004-07-08 18:32:18 »

I'm sure you've probably heard this, but make sure you copy your images to "Automatic" or "Volatile" images. This speeds up blits by buffering the image inside the card. Other than that, tile drawing is just plain slow. Try to use larger tiles for one thing. (e.g. 64x64) Another optimization is to only redraw what you need to. If you use a backbuffer for the Map, you may not need to redraw it every frame. This is particularly effective for Parallax scrolling. I use this method in GAGE2D and it does help.

IIRC, I also tried the "copy the unchanged portion over a bit, then redraw the 'dirty' tiles" method. Unfortunately, it didn't provide any speed boosts in my testing. Memory bandwidth was probably the limiting factor.

Java Game Console Project
Last Journal Entry: 12/17/04
Offline Malohkan

Senior Member




while (true) System.out.println("WOO!!!!");


« Reply #2 - Posted 2004-07-08 18:57:39 »

the dimensions of my tiles are 512x512.  I'm putting them on the BufferedImage created as I described, and Abuse has instructed that that will keep the image in vram, but is that image too big?  Also, since the tiles have no Alpha value, I guess I could use Volatile Images, but would the speed be much different?

I'm going to look into the parallax scrolling to see what I can learn from it.  Thanks!

Admin and Game Developer at
GameLizard.com
Play Rimscape!    |    Play Conquer!
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline jbanes

JGO Coder


Projects: 1


"Java Games? Incredible! Mr. Incredible, that is!"


« Reply #3 - Posted 2004-07-08 19:16:01 »

Quote
the dimensions of my tiles are 512x512.  I'm putting them on the BufferedImage created as I described, and Abuse has instructed that that will keep the image in vram, but is that image too big?


OUCH. Yeah, 512x512 is probably too big. At 32 bit color, you're using about a megabyte of video RAM for each tile. Remember, if you use powers of two for tile sizes, the memory requirements go up exponentially. Allow me to demonstrate:

8x8 = 256 bytes
16x16 = 1 KB
32x32 = 4 KB
64x64 = 16 KB
128x128 = 64 KB
256x256 = 256 KB
512x512 = 1 MB
1024x1024 = 4 MB

Quote
Also, since the tiles have no Alpha value, I guess I could use Volatile Images, but would the speed be much different?


As long as you're copying your images to "Automatic" (I forget, didn't we change the name to "Managed"?) images, there should be no difference using Volatile images. "Automatic" images use the best backing store available. With any luck, that should be a Volatile Image.

Java Game Console Project
Last Journal Entry: 12/17/04
Offline Malohkan

Senior Member




while (true) System.out.println("WOO!!!!");


« Reply #4 - Posted 2004-07-08 19:51:16 »

I tried this:
1  
2  
3  
4  
BufferedImage tile = Rimscape.getMediaItem(Constants.TILES, systems[currentSystem].getBackgroundTile());
back = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration().createCompatibleVolatileImage(tile.getWidth(), tile.getHeight());
Graphics g = back.getGraphics();
g.drawImage(tile, 0, 0, null);
then drawing "back" like I did before and the costs almost tripled.... so I think I was better off with BufferedImage.  Before I was just using
1  
back = Rimscape.getMediaItem(Constants.TILES, systems[currentSystem].getBackgroundTile());

Admin and Game Developer at
GameLizard.com
Play Rimscape!    |    Play Conquer!
Offline Malohkan

Senior Member




while (true) System.out.println("WOO!!!!");


« Reply #5 - Posted 2004-07-08 20:32:56 »

Hey I just managed to cut the load by 1/3.  I figured since my tiles are friggin huge that drawing before and beyond the borders of the screen might be a problem, so after scratching my head for a few minutes I wrote some code to keep my game from drawing anything outside the bounds of the screen.  Here's what I came up with instead of my previous draw method:
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
for (i = bgStartX-tW; i < w; i += tW)
      for (j = bgStartY-tH; j < h; j += tH) {
           
            startX = Math.max(0, i);      startY = Math.max(0, j);
            if ((width = Math.min(tW - (startX - i), w - startX)) > 0) {
                 
                  if ((height = Math.min(tH - (startY - j), h - startY)) > 0) {
                 
                        sourceX = (startX == 0 ? 0 - i : 0);
                        sourceY = (startY == 0 ? 0 - j : 0);
                       
                        g2d.drawImage(back,
                              //dest rect
                             startX, startY, startX + width, startY + height,
                              //source rect
                             sourceX, sourceY, sourceX + width, sourceY + height,
                              null
                        );
                  }
            }
      }

Admin and Game Developer at
GameLizard.com
Play Rimscape!    |    Play Conquer!
Offline oNyx

JGO Coder


Medals: 1


pixels! :x


« Reply #6 - Posted 2004-07-10 12:37:16 »

trembovetski said:
Quote
This one is easy: we have this limit (which we often forget about ourselves) for bitmask images on windows, the size (w * h) must be less than 65536 in order for image to get accelerated. This is because of the way we accelerate bitmask images with DirectX pipeline.

See here:
http://www.java-gaming.org/cgi-bin/JGNetForums/YaBB.cgi?board=2D;action=display;num=1083335469;start=15

So 256x256 is the maximum (square) tile size you should use.

弾幕 ☆ @mahonnaiseblog
Offline Malohkan

Senior Member




while (true) System.out.println("WOO!!!!");


« Reply #7 - Posted 2004-07-10 16:38:06 »

I tried splitting those into 256x256, 128x128, and 64x64 pixel tiles, but each time I went lower, performance decreased.  I was creating the BufferedImages in the same way I described above, which I have come to understand puts them in video memory.  Am I wrong?  Or is there something else I'm missing?  So far though, my best performance has been with the images being at 512x512

Admin and Game Developer at
GameLizard.com
Play Rimscape!    |    Play Conquer!
Offline crystalsquid

Junior Member




... Boing ...


« Reply #8 - Posted 2004-07-11 19:19:57 »

We found the 2D performance was a bit pants in general - especially with transparencies so we rolled our own software version.

There are some references in this forum, basically you make a new ImageProducer/ImageConsumer and use an int array for the screen. then some nice for loops for copying the sprite data to the image, and a single drawImage call at the end to render the screen. the VM seems to do a great job with optimising these loops Smiley

It can be a bit complicated, but I used various references such as:
Quote
Take a glance at TinyPTC http://www.gaffer.org/tinyptc/ which has a correct ImageProducer/ImageConsumer model, although  I have not used it plenty of people like it.

and:
Quote
JEF stands for Java Emulation Frame Work and is a Source Forge project which can be located here:
https://sourceforge.net/projects/jef/

These helped me on my way and now we have nice fast 2D rendering with alpha blending and other cool features (like z-buffering so sprites can move behind background features)

Be warned though - it's not a job for the faint hearted!

- Dom
Offline Malohkan

Senior Member




while (true) System.out.println("WOO!!!!");


« Reply #9 - Posted 2004-07-13 05:09:43 »

Well I've spent the last two days reading through most all of the classes for those two projects and browsing most of their pages and surprisingly I found nothing to help me.  I'm afraid I don't understand what it is you're saying I should be looking for.  You say you should be "copying pixels" but when you use sprites with alpha components you have to combine pixels, not just copy them over.... so I don't understand what you mean I think.  Could you elaborate more for me?

Admin and Game Developer at
GameLizard.com
Play Rimscape!    |    Play Conquer!
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline crystalsquid

Junior Member




... Boing ...


« Reply #10 - Posted 2004-07-13 08:33:23 »

You need the ImageConsumer and ImageProducer bits from those libs to draw the screen from an array of ints.

From our derived applet class:
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
      public synchronized boolean render()
      {
            if ( copy11 )
            {
                  // get our graphics buffer (640x480 int array)
                 int pixels[] = myGraphics.dest;

                  // check consumer
                 if (_consumer!=null)
                  {
                        // copy integer pixel data to image consumer
                       _consumer.setPixels(0,0,_width,_height,_model,pixels,0,_width);
                       
                        // notify image consumer that the frame is done
                       _consumer.imageComplete(ImageConsumer.SINGLEFRAMEDONE);
                  }
                  // draw image to graphics context
                 _graphics.drawImage(_image, 0, 0, _width, _height, null);
            }
            else
            {
                  // draw image to graphics context
                 _graphics.drawImage(_image2, 0, 0, _width, _height, null);
            }
            return true;
      }

You should be able to find this bit of code in those libs (plus the rest of the class) as that is where we got it from Smiley

We use a derived Sprite class too, which after loading the original image as normal uses a PixelGrabber to get the sprite data into an array of ints.


Non-transparent sprites are draw just by copying the ints:
From our derived 'Graphics' object:
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
            int w = s.width;
            int h = s.height;
            int start = y*width + x;
            int start_end = start + width*h;
            int sp = 0;
            int src[] = s.pixels;
            for(; start < start_end; start+=width)
            {
                  int end = start + w;
                  for( int curr=start; curr<end; curr++, sp++ )
                  {
                        dest[curr] = src[sp];
                  }
            }



To do transparency, you do a similar same thing but blend using the the algorithm here:
http://www.java-gaming.org/cgi-bin/JGNetForums/YaBB.cgi?board=cluebies;action=display;num=1086024248

We have about 16 different sprite draw functions, to do transparency, render a sub-rectangle, scaling, etc.

As I said, its quite a bit of work to get up and running, but afterwards you have your own 2D lib that is pretty fast for rendering Smiley

Hope this helps,

- Dom
Offline Abuse

JGO Coder


Medals: 11


falling into the abyss of reality


« Reply #11 - Posted 2004-07-13 17:44:20 »

Quote

We found the 2D performance was a bit pants in general - especially with transparencies so we rolled our own software version.


Transparency is fine, its translucency that will cause Java2D to crawl (unless you are using the experimental transaccel flag)

Malohkan, a couple of questions :-

1) How much space do the images for your background (and indeed your entire game) take up?

If you have more images than can fit in your available vram, you are going to have problems.
At the moment there is no way to control what (if anything) gets shunted out of vram. (it works on a first come first served basis)
If this is your problem, there isn't much you can do.
Load in the images that are most expensive to render 1st.
(i.e. the images that are drawn most often)

2) How are you creating your images?

I would recommend loading your images through ImageIO.read(), and then copy them onto a BufferedImage obtained from GraphicsConfiguration.createCompatibleImage(int,int,int)

This will definitly give you a managed image.

3) As Onyx said, the size of the images matter.

Although i seem to remember it is large ( >256x256)
BITMASK images that will not be cached in vram.
OPAQUE images always are, regardless of size (note this maybe wrong)

4) What platorm are you using?

Everything I have said above is applicable to Windows only.

Make Elite IV:Dangerous happen! Pledge your backing at KICKSTARTER here! https://dl.dropbox.com/u/54785909/EliteIVsmaller.png
Offline Malohkan

Senior Member




while (true) System.out.println("WOO!!!!");


« Reply #12 - Posted 2004-07-13 18:45:09 »

The images take up about 4mb.  The class files are about 150k.  I've tried playing the game while printing out GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getAvailableAcceleratedMemory() and it always shows a heck of a lot.

I load in my images using Toolkit and MediaTracker because I've never gotten ImageIO to work even when using code you've shared on the forums.  I then draw that image onto a BufferedImage using the method I described in my initial post up top, using GraphicsConfiguration.

I don't load very many of my BufferedImages with Transparency.OPAQUE.  Most are TRANSLUCENT and none are BITMASK.

I'm using Windows XP.

crystalsquid, I'm working on creating some of the tools you've described.  I have the basics down, but my drawing of images onto others still isn't working.  I double checked the math and I can't find anything wrong, but the image is being drawn broken.  The funny thing is that it's drawing in the correct placement, but it's like it's grabbing the wrong pixels from the source.  I'm sure I just need to tinker more and figure out where I messed up.

Admin and Game Developer at
GameLizard.com
Play Rimscape!    |    Play Conquer!
Offline Malohkan

Senior Member




while (true) System.out.println("WOO!!!!");


« Reply #13 - Posted 2004-07-13 21:24:36 »

Well so far my progress has actually degraded Wink  I made a drawImage for a custom class I made using all this, and then it seems like my coordinate system went retarded.  Some things are flipped over y=x, and some things are rotated.  I also haven't gotten alpha to work, but I have managed to make the screen look like it does when your monitor is dying and all the colors go nuts.  Soo.... yeah this isn't going well Wink  I think I'm going to have to scratch this project unless maybe you might know where I've screwed up.  Thanks though!

Admin and Game Developer at
GameLizard.com
Play Rimscape!    |    Play Conquer!
Offline tom
« Reply #14 - Posted 2004-07-13 22:31:09 »

Quote
You need the ImageConsumer and ImageProducer bits from those libs to draw the screen from an array of ints.

But will it be fast enough to sustain 800x600 at 50 fps? Sounds too much even if you don't touch the int array.

With Java2D you can't use TRANSLUCENT if you wan't descent speed. I think the background is read from the card (very slow), blended, then written back.

You might consider using OpenGL. It is fast even with blending. A lot of work ofcource, and you'll have to deploy some extra dlls.

Offline Malohkan

Senior Member




while (true) System.out.println("WOO!!!!");


« Reply #15 - Posted 2004-07-13 22:51:19 »

yeah good question.  When I made my attempt, although it wasn't working right, it was stilly only drawing like half of the stuff (because I hadn't made a drawImage method to take AffineTransform objects) and working with 0 alpha and I was getting fps's of like 20.  So that wasn't very encouraging

Admin and Game Developer at
GameLizard.com
Play Rimscape!    |    Play Conquer!
Offline Abuse

JGO Coder


Medals: 11


falling into the abyss of reality


« Reply #16 - Posted 2004-07-14 03:15:17 »

Quote

Most are TRANSLUCENT


Then thats your problem.

Unless you have the 'transaccel' flag set, and have a graphics card with the necessary support, translucent images will be very slow.

:edit:

just for a quick metric on that.

Balls.jar with rendering TRANSLUCENT 32x32 images onto a BufferStrategy backBuffer (or VolatileImage) on my machine gets :-

with 'transaccel'    :     ~3000 @ 30fps
without 'transaccel' :     ~30 @ 30fps

:edit:

hmm, i've just discovered something very strange with regard to different resolutions, and TRANSLUCENT rendering (with and without acceleration)
I'm gonna post a new thread on it.

Make Elite IV:Dangerous happen! Pledge your backing at KICKSTARTER here! https://dl.dropbox.com/u/54785909/EliteIVsmaller.png
Offline Malohkan

Senior Member




while (true) System.out.println("WOO!!!!");


« Reply #17 - Posted 2004-07-14 06:12:12 »

Yeah that's very helpful on my standalone version, but I still want to have it run the best it can in an Applet.

Admin and Game Developer at
GameLizard.com
Play Rimscape!    |    Play Conquer!
Offline Abuse

JGO Coder


Medals: 11


falling into the abyss of reality


« Reply #18 - Posted 2004-07-14 08:34:51 »

Quote
Yeah that's very helpful on my standalone version, but I still want to have it run the best it can in an Applet.


a 4mb Applet?! =/

I doubt many ppl will have the patience to wait that long for an applet to load.
If you are not limiting yourself to Java1.1 only capable machines, i see little reason to use Applets.

Use webstart!

Make Elite IV:Dangerous happen! Pledge your backing at KICKSTARTER here! https://dl.dropbox.com/u/54785909/EliteIVsmaller.png
Offline Malohkan

Senior Member




while (true) System.out.println("WOO!!!!");


« Reply #19 - Posted 2004-07-14 20:28:55 »

I have a low-res set of art that's only about 350k.  But I'd hate to have to have two sets of code and every time I want to make a change I'd have to go through both sets and make simultaneous changes.  The 350k version is plenty small for the Applet and will be condensed further.

Anyway, loading the full one as an Applet is faster than loading many of the Flash games at MiniClip.com and plenty of people play those Smiley

So, more questions.  Abuse, I saw you made a post today about using VolatileImages.  I tried it for my tiling background, since there's no transparency.  The tiles are broken into pieces so that they'll be sure to be cached in vram.  Even without checking whether contents have been lost an all that, when I used VolatileImages I got fps's of around 15fps.  When I used BufferedImage, I got 70+ fps.  Do VolatileImages choke when the drawImage(image, destRect, sourceRect, null) method is called?

I'm creating them all through the GraphicsConfiguration blah blah so that they'll be cached in vram.  I tried breaking them into 256x256, 128x128, and 64x64.  Performance got worse as I went to smaller sizes.  With BufferedImage though I never dropped my framerate.

Why do VolatileImages always perform so slowly for me?  I know they should be faster, so what am I missing?


Oh, and I won't be using WebStart because web start forces you to jump out of the browser.  That means you can't see the ad's on the page, which means bye bye to my only source of revenue for my free games site.  That's not gonna happen Wink

Admin and Game Developer at
GameLizard.com
Play Rimscape!    |    Play Conquer!
Offline Abuse

JGO Coder


Medals: 11


falling into the abyss of reality


« Reply #20 - Posted 2004-07-14 20:57:45 »

Quote

drawImage(image, destRect, sourceRect, null)


do you mean :-

drawImage(Image img, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1, int sx2, int sy2, ImageObserver observer) ?

I havn't ever needed to use that.
However, the symptoms you state do fit the possibility that your 2 rectangles are different dimensions from 1 another.

This would result in your image drawing being scaled.
As scaling isn't currently HW accelerated, this would force the JVM to use the software rendering loops.

Using BufferedImages, it would simply be slow, because of no HW acceleration.
Using VolatileImages it would be *very* *very* *very* slow, as each image would have to be read back from vram, scaled, and then blitted to the destination Image (which is probably back in vram)

So yes, using that drawImage is probably the cause of your problems.

p.s.

There is a flag to enable HW accelerated scaling.
something.something.ddscale=true I believe.

Make Elite IV:Dangerous happen! Pledge your backing at KICKSTARTER here! https://dl.dropbox.com/u/54785909/EliteIVsmaller.png
Offline Malohkan

Senior Member




while (true) System.out.println("WOO!!!!");


« Reply #21 - Posted 2004-07-14 21:18:43 »

yep that's the one.  Thanks for the explanation, it makes sense why VolatileImages would be slow in that case, thanks!

sun.java2d.ddscale = true has been set!  Thanks for that tip Smiley

I was hoping it would help speed up my AffineTransform translations, but unfortunately it hasn't.  I'm pretty much doing everything horribly bad I could do in one fell swoop on this one particular effect.  I'm rotating a highly translucent image and scaling it differently every frame for my Trekky jump effect Smiley

The ddscale doesn't seem to help that at all.  I still go from a steady 60fps (on the standalone version the fps is VERY constant) to 5 fps when the jump flash occurs.


Oh, one thing I did do good.  One source of translucency problems was in my stars being drawn on the background.  However, since they never move, I was able to simulate the background being in the correct place and drawing it onto an OPAQUE image the size of the star, and then drawing the star on top of that.  Now my planets/stars use OPAQUE BufferedImages instead of Translucent ones.  That's helped a lot!

Admin and Game Developer at
GameLizard.com
Play Rimscape!    |    Play Conquer!
Offline Malohkan

Senior Member




while (true) System.out.println("WOO!!!!");


« Reply #22 - Posted 2004-07-18 00:30:35 »

Well I decided to try using VolatileImages without scaling them to see if that would make a difference, and as it turns out, VolatileImages show themselves to get slower every time they're drawn.  Something HAS to be wrong here.

Here are benchmarks of calling my draw method 1000 times with OPAQUE BufferedImages:
1  
2  
3  
4  
5  
6  
7  
8  
6x6      8x8      4x4      2x2      1x1
6547      7281      5984      5234      4844
6719      7781      6391      5234      4766
6875      7594      6531      5406      4875
6813      7594      6234      5344      4844
7000      8000      6218      5453      4813
7313      7594      6203      5203      4875
              7688      6344      5516      4906

As you can see, my efforts to help them cache in vram by chopping them into smaller images actually made things slower.  To clarify, Number x Number is the array size of my image.  So 1x1 means 1 512x512 image.  8x8 means a whole lot of 64x64 images.

Here's how things turned out with VolatileImages:
1  
2  
3  
4  
1x1      4x4      8x8
 4859       5469      8500
56500      74297
73937

In this case every time I called the method things got amazingly slower, from the first call being normal (under 1 second), to the next call being about a minute long.  I'm not modifying the images between calls in any way.  The only access done to the images are a getWidth(), getHeight() and then drawImage(image, x, y, null);  As you can imagine with the first result being 8500ms, I wasn't about to see how that time multiplied on the next call.

There's no scaling, no alpha, just straight drawing.  Why would VolatileImage not only be slower than BufferedImage, but actually get worse as time progresses?  More importantly, how do I fix this?

Admin and Game Developer at
GameLizard.com
Play Rimscape!    |    Play Conquer!
Offline Abuse

JGO Coder


Medals: 11


falling into the abyss of reality


« Reply #23 - Posted 2004-07-18 22:15:20 »

what are you drawing onto? a Graphics context obtained from the current BufferStrategy?

Make Elite IV:Dangerous happen! Pledge your backing at KICKSTARTER here! https://dl.dropbox.com/u/54785909/EliteIVsmaller.png
Offline Malohkan

Senior Member




while (true) System.out.println("WOO!!!!");


« Reply #24 - Posted 2004-07-18 22:51:55 »

I'm drawing onto a Graphics2D object obtained from a VolatileImage obtained from the GraphicsEnvironment...createCompatibleVolatileImage method.  Ultimately that image gets drawn onto the Graphics from the Applet.getGraphics() call.  Both of these facts are true for all of the benchmark results I posted.

Admin and Game Developer at
GameLizard.com
Play Rimscape!    |    Play Conquer!
Offline Abuse

JGO Coder


Medals: 11


falling into the abyss of reality


« Reply #25 - Posted 2004-07-18 23:21:57 »

hmm, without seeing the code - Im not sure I can see where the problem is occuring.

However, 1 thing you should try.

Add a canvas to the Applet, and on the Canvas, use createBufferStrategy(2).

Then try blitting onto the graphics context obtained from getBufferStrategy().getDrawGraphics().

That may give different results.
If it does, it means something is going pear-shaped when trying to blit onto VolatileImages.

Also, make sure you are performing no transforms of any kind, and that the source image does not have any kind of an alpha channel. (though BITMASK should be ok)

p.s. what acceleration flags do you have set?
In 1.4.2 some of them have undesirable side effects (that maybe the cause of Volatile->Volatile blits losing acceleration)

p.s. what is your gfx card? does it fully support DirectX?
That could be another problem (though rather unlikely)

What sort of performance do you get with Balls.jar?

Make Elite IV:Dangerous happen! Pledge your backing at KICKSTARTER here! https://dl.dropbox.com/u/54785909/EliteIVsmaller.png
Offline Malohkan

Senior Member




while (true) System.out.println("WOO!!!!");


« Reply #26 - Posted 2004-07-19 00:17:11 »

I tried your suggestion with the canvas, but it didn't change the benchmarks for BufferedImage or VolatileImage at all.

I have the flags: "sun.java2d.translaccel" and "sun.java2d.ddscale" and I tried turning them both on and off, but neither case made any difference either.

The surface I'm drawing onto was a VolatileImage, so no alpha there.  Then when on the canvas it was going onto the BufferStrategy.  My source image drawing onto it has no alpha, it's coming from an OPAQUE BufferedImage, and I'm using the drawImage(image, x, y, null); method.  I draw onto it once, and never again.

My graphics card is an Intel 82852/82855 GM/GME Graphics Controller on a Toshiba laptop.  It's got 64 megs of graphics memory.  It has full OpenGL support but I'm not sure about DirectX.  All the DX diagnostic tests run successfully though.

Balls could keep at 50fps with about 2100 balls with VolatileImages, but only about 1500 balls with Managed Images on 800x600 32bit.  With ImageIO about 700, Unaccelerated about 800, and Masked Managed about 1800.

Admin and Game Developer at
GameLizard.com
Play Rimscape!    |    Play Conquer!
Offline Abuse

JGO Coder


Medals: 11


falling into the abyss of reality


« Reply #27 - Posted 2004-07-20 12:57:36 »

ok, well most of the code for Balls is included in the jar (though I missed out a few of the utility classes unfortunetly)

You need to have a look what your program is doing differently to mine.

Make Elite IV:Dangerous happen! Pledge your backing at KICKSTARTER here! https://dl.dropbox.com/u/54785909/EliteIVsmaller.png
Offline Malohkan

Senior Member




while (true) System.out.println("WOO!!!!");


« Reply #28 - Posted 2004-07-20 15:21:28 »

Unless your GameFrame class is doing something different, I can find no differences.  I took everything from Balls I could make use of, anything that ever did anything to the Graphics2D Object I did the same to.  I even set the AlphaComposite.SrcOver in that you had where you had it.

I try printing out the capabilities after I create my images and I get that isAccelerated = true and isTrueVolatile = true on every frame of animation.  What else can I try?  VolatileImage is still very slow and BufferedImage is fast but just not fast enough.  I even tried setting extra RenderingHints for speed but found no change.

Here's from creation to usage of my VolatileImages:
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
48  
49  
50  
51  
back = new VolatileImage[1][1];
for (int i = 0; i < back.length; i++) {
      for (int j = 0; j < back.length; j++) {
            back[i][j] = GLUIUtil.createVI(Constants.SYSTEM_TILE_WIDTH/back.length,
                        Constants.SYSTEM_TILE_HEIGHT/back.length);
      }
}
public VolatileImage GLUIUtil.createVI(int width, int height) {
      return GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration().createCompatibleVolatileImage(width, height);
}
//In drawing, which only ever happens once:
Graphics2D g2d = back[i][j].createGraphics();
g2d.setComposite(AlphaComposite.Src);
g2d.drawImage(tile, i*back[0][0].getWidth()/back.length, j*back[0][0].getHeight()/back[0].length, null);

g2d.dispose();

ImageCapabilities ic = back[i][j].getCapabilities();
System.out.println("isAccelerated = " + ic.isAccelerated() + "\n" +
      "isTrueVolatile

//Then finally when I use them:
int i, j, frameX = 0, frameY = 0;
int w = Constants.GAME_WIDTH;
int h = Constants.GAME_HEIGHT;
int tW = back[0][0].getWidth();
int tH = back[0][0].getHeight();

g2d.setComposite(AlphaComposite.SrcOver);

int startX, startY, width, height, sourceX, sourceY;

for (i = bgStartX-Constants.SYSTEM_TILE_WIDTH; i < w; i += tW) {
      for (j = bgStartY-Constants.SYSTEM_TILE_HEIGHT; j < h; j += tH) {
           
            startX = Math.max(0, i);
            if ((width = Math.min(tW - (startX - i), w - startX)) > 0) {
                 
                  startY = Math.max(0, j);
                  if ((height = Math.min(tH - (startY - j), h - startY)) > 0) {
                       
                        g2d.drawImage(back[frameX][frameY], i, j, null);
                  }
            }
           
            frameY = (frameY + 1)%back.length;
      }
      frameY = 0;
     
      frameX = (frameX + 1)%back.length;
}
And that's all that ever touches them.

Admin and Game Developer at
GameLizard.com
Play Rimscape!    |    Play Conquer!
Pages: [1]
  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.

pw (17 views)
2014-07-24 01:59:36

Riven (17 views)
2014-07-23 21:16:32

Riven (14 views)
2014-07-23 21:07:15

Riven (17 views)
2014-07-23 20:56:16

ctomni231 (45 views)
2014-07-18 06:55:21

Zero Volt (40 views)
2014-07-17 23:47:54

danieldean (32 views)
2014-07-17 23:41:23

MustardPeter (36 views)
2014-07-16 23:30:00

Cero (51 views)
2014-07-16 00:42:17

Riven (50 views)
2014-07-14 18:02:53
HotSpot Options
by dleskov
2014-07-08 03:59:08

Java and Game Development Tutorials
by SwordsMiner
2014-06-14 00:58:24

Java and Game Development Tutorials
by SwordsMiner
2014-06-14 00:47:22

How do I start Java Game Development?
by ra4king
2014-05-17 11:13:37

HotSpot Options
by Roquen
2014-05-15 09:59:54

HotSpot Options
by Roquen
2014-05-06 15:03:10

Escape Analysis
by Roquen
2014-04-29 22:16:43

Experimental Toys
by Roquen
2014-04-28 13:24:22
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!