Java-Gaming.org    
Featured games (81)
games approved by the League of Dukes
Games in Showcase (498)
Games in Android Showcase (115)
games submitted by our members
Games in WIP (562)
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  
  Software rendering  (Read 4059 times)
0 Members and 1 Guest are viewing this topic.
Offline Martin Strand

Junior Member





« Posted 2006-02-12 23:23:25 »

Hello, I'm new here.
I've put together a game which uses software rendering, something like this:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
// Create image
Component target = ...; // A JPanel inside a JFrame's contentPane()
BufferedImage image = (BufferedImage) target.createImage(width, height);
int[] buffer = ((DataBufferInt) image.getRaster().getDataBuffer()).getData();

// Software rendering
for (...)
{
    buffer[i] = ...;
}

// Blit it to screen
target.getGraphics().drawImage(image, 0, 0, target.getWidth(), target.getHeight(), null);


This works ok, but I noticed a significant frame rate drop when the window gets bigger.

Back in the days when I used DirectDraw, I usually just did something like this this:
1. ddsSecondary->Lock()
2. Copied the pixels
3. ddsSecondary->Unlock()
4. ddsPrimary->Blt(...)
and that always worked fine, regardless of the window size.

I assume the difference is that in my Java code, the surface remains locked. What can I do to improve performance?

Thanks,
Martin
Offline jbanes

JGO Coder


Projects: 1


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


« Reply #1 - Posted 2006-02-13 05:10:20 »

Go read up on <a href="http://java.sun.com/docs/books/tutorial/extra/fullscreen/index.html">BufferStrategy</a>. It handles the page flipping automatically. i.e. You don't need to lock and unlock surfaces. Smiley

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

Junior Member





« Reply #2 - Posted 2006-02-13 22:40:43 »

Thanks for your help, I did some reading and added BufferStrategies to my app. But it appears the problem is related to the scaling inside drawImage(...). Here's a test app: (assumes your desktop is 32 bpp)

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  
import java.awt.Canvas;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.image.BufferStrategy;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferInt;

import javax.swing.JFrame;

public class Test
{
   public static void main(String[] args)
      throws Exception
   {
      /* Window */
      JFrame window = new JFrame();
      window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      Rectangle bounds = new Rectangle(10, 10, 0x300, 0x300);
      window.setBounds(bounds);
      window.setVisible(true);

      /* Canvas, strategy */
      Canvas canvas = new Canvas();
      window.getContentPane().add(canvas);
      canvas.createBufferStrategy(3);
      BufferStrategy bufferStrategy = canvas.getBufferStrategy();

      /* Image, buffer */
      BufferedImage image = (BufferedImage) canvas.createImage(window.getWidth(), window.getHeight());
      int[] buffer = ((DataBufferInt) image.getRaster().getDataBuffer()).getData();

      int color = 0;
      while (true)
      {
         /* Pixels */
         for (int i = 0; i < buffer.length; i++, color++)
         {
            buffer[i] = color | 0xff000000;
         }

         /* Blit to screen */
         Graphics g = bufferStrategy.getDrawGraphics();
         g.drawImage(image, 0, 0, window.getWidth(), window.getHeight(), null);
         bufferStrategy.show();
         g.dispose();
      }
   }
}


Note how everything slows down as the window gets bigger. I guess this is because the dd surface for that BufferedImage must remain locked at all times since Java allows me to access its pixels directly at any time.

Is there a better way to use a BufferStrategy and still get direct access to the pixels?
Or is there a way to "unlock" the BufferedImage so that drawImage(...) can be hardware accelerated?
Or did I just misunderstand everything and now I'm looking like an idiot? Smiley

/Martin
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 2006-02-13 23:00:02 »

You don't manipulate pixels in Java. Doing so is going to get you all the performance of glDrawPixles. i.e. Absolutely horrible performance.

What you want is to blit your images directly (as if they were polygon surfaces), then apply transformations for scaling, rotation, and special effects. This will then get shunted down the Direct3D/OpenGL pipeline to be rendered directly onto the backbuffer in Video RAM.

For maximum performance, make sure you acquire an image that matches the depth and memory organization of the backbuffer before rendering. Otherwise Java will convert the image to the native format every time you need to render the image. As you can imagine, this is EXTREMELY slow. As a result, you'll usually want to create a loader that automatically copies the image data into new images of the proper format. Such a loader is available here:

http://wiki.java.net/bin/view/Games/LoadingSpritesWithImageIO

You may also find that perusing this tutorial may help answer some of your questions:

http://www.cokeandcode.com/info/tut2d.html

And stop worrying about surface locking. It's got nothing to do with anything. Smiley

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

Junior Member





« Reply #4 - Posted 2006-02-13 23:36:17 »

You don't manipulate pixels in Java.
That's the whole point - I do need to manipulate pixels directly, hence the topic "Software rendering". I know this is not normal but in this case I really need to do it. I've got all the pixels ready and I just need to blit them to the primary surface as fast as possible. Smiley

WIth DirectDraw, I just did the regular [lock, copy pixels, unlock] thing and that way I could use hardware accelerated blits for that surface but still access its pixels directly for a limited time (during the lock). Is there absolutely no way to do this with Java?
I assume calling "((DataBufferInt) image.getRaster().getDataBuffer()).getData();" results in hardware acccelerated blits being disabled since from that point on I can access the pixels directly at any time, so the surface is most likely moved out of VRAM. What I want is to tell Java "Ok, I don't need direct access to the pixels anymore" so that I can have hardware acceleration enabled again for that surface. How can I do that?

/Martin
Offline Jeff

JGO Coder




Got any cats?


« Reply #5 - Posted 2006-02-14 00:22:40 »

You might want to ask this over in the 2D section. Normally we discourage cross posting but I dont know if the Java2D guys read this and i know they DO read the 2D topic.

Got a question about Java and game programming?  Just new to the Java Game Development Community?  Try my FAQ.  Its likely you'll learn something!

http://wiki.java.net/bin/view/Games/JeffFAQ
Offline jbanes

JGO Coder


Projects: 1


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


« Reply #6 - Posted 2006-02-14 02:00:42 »

It's inefficient to access the Video RAM pixel by pixel. The result would be tons of unnecessary bandwidth on the line. Thus Java copies the entire buffer when it's done. What you're doing is pretty close to the fastest thing available . A few helpful hints:

  • Create a Graphics Configuration compatible image for your backbuffer the same way I pointed to above.(i.e. BufferedImage buffer = gc.createCompatibleImage(width, height); ) This will prevent Java from having to convert the image data.
  • Set the BufferCapabilities to BufferCapabilities.FlipContents.PRIOR to save time during flips.

That's about as fast as you're going to get. You should be able to get 60 or so FPS, though.

Keep in mind that this is all going through a 3D API, so pixel level performance is not intended to be fast.

Perhaps if you could tell us more about why you specifically *need* pixel level rendering, we could offer more suggestions? Quite a few new Java Game programmers don't realize the things that can be done without access to the pixel level.

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

Junior Member





« Reply #7 - Posted 2006-02-14 11:32:09 »


Perhaps if you could tell us more about why you specifically *need* pixel level rendering, we could offer more suggestions? Quite a few new Java Game programmers don't realize the things that can be done without access to the pixel level.

I am guessing for software 3d.

use:

int[] imgData = (int[]) ((DataBufferInt) img.getRaster().getDataBuffer()).getData();

to get the array of pixels that make up a buffered image, (the type of databuffer / array will vary depending on which type of image it is, the above works the BufferedImage.TYPE_INT_RGB at least.

Performance is not too bad using this method, i am able to get ~300fps with a 512*384 img just clearing it and drawing it to the screen every frame.

desperately seeking sanity
Offline Martin Strand

Junior Member





« Reply #8 - Posted 2006-02-14 16:43:57 »

I appreciate your help, guys.

Perhaps if you could tell us more about why you specifically *need* pixel level rendering, we could offer more suggestions? Quite a few new Java Game programmers don't realize the things that can be done without access to the pixel level.

I'm writing a console emulator (NES/Famicom). All pixels are generated by the GPU emulator, I'm afraid there's no way to use hardware acceleration in this case. On each frame, the GPU emits a 256x240 image. I need to use hardware acceleration when blitting that image to screen.

Quote
Performance is not too bad using this method, i am able to get ~300fps with a 512*384 img just clearing it and drawing it to the screen every frame.
It works, but for a big window this method is several times slower than using hardware accleration for that blit. That's why I'm looking for alternatives...  Undecided

/Martin
Offline jbanes

JGO Coder


Projects: 1


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


« Reply #9 - Posted 2006-02-14 16:59:14 »

Quote
I'm writing a console emulator (NES/Famicom). All pixels are generated by the GPU emulator, I'm afraid there's no way to use hardware acceleration in this case.

That's not actually true. The NES/Famicom contained sprite hardware. By rendering the sprite slivers to correctly sized buffered images, you could potentially accelerate the process. Especially if you cached sprite/tile values. It's a lot more complicated method than a straightup NTSC GPU emulator, though. Sad

Quote
On each frame, the GPU emits a 256x240 image. I need to use hardware acceleration when blitting that image to screen. It works, but for a big window this method is several times slower than using hardware accleration for that blit.

Are you  resizing the image before or during the render? Because I guarantee that the fastest method is to render to a 256x256 buffered image (just ignore the extra area) then scale it with the g.drawImage(image, x, y, width, height, null) method. That will transfer less data over the bus, and force the hardware to do the hard work for you. Smiley

Java Game Console Project
Last Journal Entry: 12/17/04
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline Martin Strand

Junior Member





« Reply #10 - Posted 2006-02-14 21:23:30 »

Quote
I'm writing a console emulator (NES/Famicom). All pixels are generated by the GPU emulator, I'm afraid there's no way to use hardware acceleration in this case.

That's not actually true. The NES/Famicom contained sprite hardware. By rendering the sprite slivers to correctly sized buffered images, you could potentially accelerate the process. Especially if you cached sprite/tile values. It's a lot more complicated method than a straightup NTSC GPU emulator, though. Sad

Yeah, I've thought about that too. I know it all may seem simple until you look closer into the tech details. But believe me, hardware rendering is not a good (or even fast) solution here. I'm 100% sure on this one.

Quote
Quote
On each frame, the GPU emits a 256x240 image. I need to use hardware acceleration when blitting that image to screen. It works, but for a big window this method is several times slower than using hardware accleration for that blit.

Are you  resizing the image before or during the render? Because I guarantee that the fastest method is to render to a 256x256 buffered image (just ignore the extra area) then scale it with the g.drawImage(image, x, y, width, height, null) method. That will transfer less data over the bus, and force the hardware to do the hard work for you. Smiley

Yeah, that's exactly what I want to do - I want drawImage to be hw accelerated after I've set the pixels manually. Do you have any working example code? Could you modify this example so that it forces the hardware to do the hard work for me?

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  
import java.awt.Canvas;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.image.BufferStrategy;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferInt;
import javax.swing.JFrame;

public class Test
{
   public static void main(String[] args)
      throws Exception
   {
      /* Window */
      JFrame window = new JFrame();
      window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      Rectangle bounds = new Rectangle(10, 10, 0x200, 0x200);
      window.setBounds(bounds);
      window.setVisible(true);

      /* Canvas, strategy */
      Canvas canvas = new Canvas();
      window.getContentPane().add(canvas);
      canvas.createBufferStrategy(2);
      BufferStrategy bufferStrategy = canvas.getBufferStrategy();

      /* Image, buffer */
      BufferedImage image = (BufferedImage) canvas.createImage(0x100, 0x100);
      int[] buffer = ((DataBufferInt) image.getRaster().getDataBuffer()).getData();
      int color = 0;

      while (true)
      {
         /* Pixels */
         for (int i = 0; i < buffer.length; i++, color++)
         {
            buffer[i] = color | 0xff000000;
         }

         /* Blit to screen */
         Graphics g = bufferStrategy.getDrawGraphics();
         g.drawImage(image, 0, 0, window.getWidth(), window.getHeight(), null);
         g.dispose();
         bufferStrategy.show();
      }
   }
}
Offline jbanes

JGO Coder


Projects: 1


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


« Reply #11 - Posted 2006-02-14 21:56:15 »

Doh! I didn't think to look at the code that you posted to see if it was already doing the resize. It looks fine by me. Here's a version with a frame counter added in:

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  
52  
53  
54  
55  
56  
57  
58  
59  
60  
61  
62  
63  
64  
65  
66  
67  
68  
69  
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.image.BufferStrategy;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferInt;
import javax.swing.JFrame;

public class Test
{
    public static void main(String[] args)
    throws Exception
    {
        /* Window */
        JFrame window = new JFrame();
        window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        Rectangle bounds = new Rectangle(10, 10, 0x200, 0x200);
        window.setBounds(bounds);
        window.setVisible(true);

        /* Canvas, strategy */
        Canvas canvas = new Canvas();
        window.getContentPane().add(canvas);
        window.invalidate();
        window.validate();
        canvas.createBufferStrategy(2);
        BufferStrategy bufferStrategy = canvas.getBufferStrategy();

        /* Image, buffer */
        BufferedImage image = (BufferedImage) canvas.createImage(0x100, 0x100);
        int[] buffer = ((DataBufferInt) image.getRaster().getDataBuffer()).getData();
        int color = 0;

        long time = 0;
        long delta = 0;
        int counter = 0;
        long fps = 0;

        while (true)
        {
            /* Pixels */
            for (int i = 0; i < buffer.length; i++, color++)
            {
                buffer[i] = color | 0xff000000;
            }

            /* Blit to screen */
            Graphics g = bufferStrategy.getDrawGraphics();
            g.drawImage(image, 0, 0, window.getWidth(), window.getHeight(), null);
            g.setColor(Color.white);
            g.drawString(String.valueOf((int)fps), 10, 10);
            g.dispose();
            bufferStrategy.show();

            delta += System.currentTimeMillis() - time;
            time = System.currentTimeMillis();
            counter++;

            if(counter >= 100)
            {
                fps = 100000/delta;

                delta = 0;
                counter = 0;
            }
        }
    }
}


I get about 400 frames per second on my machine.  I actually added "try {Thread.sleep( 8 );} catch(Exception e) {}" right after "bufferStrategy.show();" to lock it at 100FPS so I could appreciate the effect. (Ahh, lovely. Smiley) Unless you're on a Mac, I wouldn't be surprised if you're seeing similar results.

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

Junior Member





« Reply #12 - Posted 2006-02-14 22:51:51 »

Yeah, I get about 400fps too, but it's still not hw accelerated - it's using my precious cpu time to scale that image.
If I resize the window to its smallest size, I get 1700 fps.
If I maximize the window, the frame rate drops to 120fps.
With hw acceleration, I believe we would see >1700fps no matter what the window size.

In my real app - which is somewhat more complex Smiley - these numbers are 250fps/90fps. This suggests that if I could have drawImage(...) hw accelerated, I could triple my app's performance.
Offline Anon666

Junior Member




aka Abuse/AbU5e/TehJumpingJawa


« Reply #13 - Posted 2006-02-15 20:12:30 »

1) set one of the system properties - sun.java2d.opengl=true, or sun.java2d.ddscale=true.
2) perform all your per pixel operations to a BufferedImage compatible with the screen pixel format (obtained from createCompatibleImage)
3) copy the image to a VolatileImage.
4) blit the VolatileImage with a scaling transform, onto your BufferStrategy.

This *should* result in the scale being performed in hardware, not software.

Though tbh, this shouldn't be necessary - the scale *should* be getting done in hardware anyway.
If scaling an unaccelerated BufferedImage, onto an accelerated surface means the scale is done in software, not hardware - I would consider it a bug in the java2d implementation.
Offline Anon666

Junior Member




aka Abuse/AbU5e/TehJumpingJawa


« Reply #14 - Posted 2006-02-15 20:34:41 »

Depressingly enough, I'm right - you have to copy it to a VolatileImage, before performing the scale - otherwise the scale won't be hardware accelerated.

Also, rather depressingly - it appears drawImage(img, x,y,width,height,imgObs) isn't accelerated by ddscale.
You have to use an AffineTransform.

Heres the code, minor adapation from above.

I get a solid 1050fps when windowed, 950 when the window is maximised.

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  
52  
53  
54  
55  
56  
57  
58  
59  
60  
61  
62  
63  
64  
65  
66  
67  
68  
69  
70  
71  
72  
73  
74  
75  
76  
77  
78  
79  
80  
81  
82  
83  
84  
85  
86  
87  
88  
89  
90  
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.Rectangle;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferStrategy;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferInt;
import java.awt.image.VolatileImage;

import javax.swing.JFrame;

public class Test
{
    public static void main(String[] args)
    throws Exception
    {
       System.setProperty("sun.java2d.ddscale","true");
       //System.setProperty("sun.java2d.opengl","true");
//        opengl pipeline doesn't work properly for me at all,
//       renders vsync'ed in a window, doesn't resize the BufferStrategy when the canvas is rescaled,
//       and causes a VM crash when I close the application down :S
     
        /* Window */
        JFrame window = new JFrame();
        window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        Rectangle bounds = new Rectangle(10, 10, 0x200, 0x200);
        window.setBounds(bounds);
        window.setVisible(true);

        /* Canvas, strategy */
        Canvas canvas = new Canvas();
        window.getContentPane().add(canvas);
        window.invalidate();
        window.validate();
        canvas.createBufferStrategy(2);
        BufferStrategy bufferStrategy = canvas.getBufferStrategy();

        GraphicsConfiguration gc = canvas.getGraphicsConfiguration();
       
        /* Image, buffer */
        VolatileImage vi = gc.createCompatibleVolatileImage(0x100,0x100);
       
        BufferedImage image = gc.createCompatibleImage(0x100, 0x100);
        int[] buffer = ((DataBufferInt) image.getRaster().getDataBuffer()).getData();
        int color = 0;

        long time = 0;
        long delta = 0;
        int counter = 0;
        long fps = 0;

        while (true)
        {
            /* Pixels */
            for (int i = 0; i < buffer.length; i++, color++)
            {
                buffer[i] = color | 0xff000000;
            }

            /* Blit to screen */
            Graphics2D g = (Graphics2D)bufferStrategy.getDrawGraphics();
            vi.getGraphics().drawImage(image,0,0,null);
           
            AffineTransform at = g.getTransform();
            g.setTransform(AffineTransform.getScaleInstance(canvas.getWidth()/(double)vi.getWidth(), canvas.getHeight()/(double)vi.getHeight()));
           
            g.drawImage(vi, 0, 0, null);
           
            g.setTransform(at);
            g.setColor(Color.white);
            g.drawString(String.valueOf((int)fps), 10, 10);
            g.dispose();
            bufferStrategy.show();

            delta += System.currentTimeMillis() - time;
            time = System.currentTimeMillis();
            counter++;

            if(counter >= 100)
            {
                fps = 100000/delta;

                delta = 0;
                counter = 0;
            }
        }
    }
}
Offline Martin Strand

Junior Member





« Reply #15 - Posted 2006-02-17 00:16:41 »

Anon666, your code did the trick and everything works great now - I went from 90fps to 240fps in my app!!. Smiley
Below is some more test code, you can try different stretch strategies by clicking the canvas.

I got the same fps without AffineTransform as I got with it. I have no idea why you didn't, it seems reasonable for drawImage to be hw accelerated for VolatileImages.  Undecided

Thanks everyone for your help.

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  
52  
53  
54  
55  
56  
57  
58  
59  
60  
61  
62  
63  
64  
65  
66  
67  
68  
69  
70  
71  
72  
73  
74  
75  
76  
77  
78  
79  
80  
81  
82  
83  
84  
85  
86  
87  
88  
89  
90  
91  
92  
93  
94  
95  
96  
97  
98  
99  
100  
101  
102  
103  
104  
105  
106  
107  
108  
109  
110  
111  
112  
113  
114  
115  
116  
117  
118  
119  
120  
121  
122  
123  
124  
125  
126  
127  
128  
129  
130  
131  
132  
133  
134  
135  
136  
137  
138  
139  
140  
141  
142  
143  
144  
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferStrategy;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferInt;
import java.awt.image.VolatileImage;
import javax.swing.JFrame;

public class Test
{
   private static int stretchStrategy;

   public static void main(String[] args)
      throws Exception
   {
      System.setProperty("sun.java2d.ddscale", "true");

      /* Window */
      JFrame window = new JFrame();
      window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      Rectangle bounds = new Rectangle(10, 10, 0x200, 0x200);
      window.setBounds(bounds);
      window.setVisible(true);

      /* Canvas, strategy */
      Canvas canvas = new Canvas();
      window.getContentPane().add(canvas);
      window.invalidate();
      window.validate();
      canvas.createBufferStrategy(2);
      BufferStrategy bufferStrategy = canvas.getBufferStrategy();
      GraphicsConfiguration gc = canvas.getGraphicsConfiguration();
      canvas.addMouseListener(new MouseListener()
      {
         public void mouseClicked(MouseEvent e)
         {
            stretchStrategy++;
            stretchStrategy %= 3;
         }

         public void mousePressed(MouseEvent e)
         {

         }

         public void mouseReleased(MouseEvent e)
         {

         }

         public void mouseEntered(MouseEvent e)
         {

         }

         public void mouseExited(MouseEvent e)
         {

         }
      });

      /* Image, buffer */
      VolatileImage vi = gc.createCompatibleVolatileImage(0x100, 0x100);
      BufferedImage bi = gc.createCompatibleImage(0x100, 0x100);
      int[] buffer = ((DataBufferInt) bi.getRaster().getDataBuffer()).getData();

      int color = 0;
      long time = 0;
      long delta = 0;
      int counter = 0;
      long fps = 0;

      while (true)
      {
         /* Pixels */
         for (int i = 0; i < buffer.length; i++, color++)
         {
            buffer[i] = color | 0xff000000;
         }

         /* Blit to screen */
         Graphics2D g = (Graphics2D) bufferStrategy.getDrawGraphics();

         switch (stretchStrategy)
         {
         case 0:
         {
            /*
             * Copy the BufferedImage to a VolatileImage, then stretch the
             * VolatileImage to screen with an AffineTransform
             */

            vi.getGraphics().drawImage(bi, 0, 0, null);
            double width = canvas.getWidth() / (double) vi.getWidth();
            double height = canvas.getHeight() / (double) vi.getHeight();
            AffineTransform at = g.getTransform();
            g.setTransform(AffineTransform.getScaleInstance(width, height));
            g.drawImage(vi, 0, 0, null);
            g.setTransform(at);
            break;
         }
         case 1:
         {
            /*
             * Copy the BufferedImage over to a VolatileImage and then stretch the
             * VolatileImage to screen.
             */

            vi.getGraphics().drawImage(bi, 0, 0, null);
            g.drawImage(vi, 0, 0, canvas.getWidth(), canvas.getHeight(), null);
            break;
         }
         case 2:
         {
            /*
             * Stretch the BufferedImage directly to screen
             */

            g.drawImage(bi, 0, 0, canvas.getWidth(), canvas.getHeight(), null);
            break;
         }
         }

         g.dispose();
         bufferStrategy.show();

         /* FPS counter */
         delta += System.currentTimeMillis() - time;
         time = System.currentTimeMillis();
         counter++;
         if (counter >= 100)
         {
            fps = 100000 / delta;
            String title = "Stretch strategy: " + stretchStrategy + ", FPS: " + String.valueOf((int) fps);
            window.setTitle(title);
            delta = 0;
            counter = 0;
         }
      }
   }
}

Offline trembovetski

Senior Member




If only I knew what I'm talking about!


« Reply #16 - Posted 2006-02-17 01:33:48 »

Since you're all big boys and girls and understand that flags aren't guaranteed to be supported forever,
 I'll post another version with some flags which have been there for a while.
If you're curious what those flags mean, feel free to browse the jdk source code =)

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  
52  
53  
54  
55  
56  
57  
58  
59  
60  
61  
62  
63  
64  
65  
66  
67  
68  
69  
70  
71  
72  
73  
74  
75  
76  
77  
78  
79  
80  
81  
82  
83  
84  
85  
86  
87  
88  
89  
90  
91  
92  
93  
94  
95  
96  
97  
98  
99  
100  
101  
102  
103  
104  
105  
106  
107  
108  
109  
110  
111  
112  
113  
114  
115  
116  
117  
118  
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferStrategy;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferInt;
import java.awt.image.VolatileImage;

import javax.swing.JFrame;

public class Test
{
    public static void main(String[] args)
    throws Exception
    {
        boolean useVI = false;
        for (String s : args) {
            if (s.equals("-usevi")) {
                useVI = true;
            } else if (s.equals("-usebi")) {
                useVI = false;
            }
        }
        System.setProperty("sun.java2d.ddscale", "true");
        if (!useVI) {
            // this should work with opengl pipeline as well
//            System.setProperty("sun.java2d.opengl", "true");
           
            // d3d is only accelerated in mustang
//            System.setProperty("sun.java2d.d3d", "true");

            // magic passes
           System.setProperty("sun.java2d.accthreshold", "0");
            System.setProperty("sun.java2d.allowrastersteal", "true");
        }
        /* Window */
        JFrame window = new JFrame();
        window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        Rectangle bounds = new Rectangle(10, 10, 0x200, 0x200);
        window.setBounds(bounds);
        window.setVisible(true);

        /* Canvas, strategy */
        Canvas canvas = new Canvas();
        window.getContentPane().add(canvas);
        window.invalidate();
        window.validate();
        canvas.createBufferStrategy(2);
        BufferStrategy bufferStrategy = canvas.getBufferStrategy();

        /* Image, buffer */
        BufferedImage image = (BufferedImage) new BufferedImage(0x100, 0x100, BufferedImage.TYPE_INT_RGB);
        int[] buffer = ((DataBufferInt) image.getRaster().getDataBuffer()).getData();
        int color = 0;
        Color translucentColor = new Color(0.0f, 0.0f, 0.0f, 0.0f);
       
        long time = 0;
        long delta = 0;
        int counter = 0;
        long fps = 0;

        VolatileImage vi =
            useVI ? canvas.createVolatileImage(0x100, 0x100) : null;
       
        while (true)
        {
            /* Pixels */
            for (int i = 0; i < buffer.length; i++, color++)
            {
                buffer[i] = color | 0xff000000;
            }

            /* Blit to screen */
            Graphics2D g = (Graphics2D)bufferStrategy.getDrawGraphics();
            if (useVI) {
                vi.validate(canvas.getGraphicsConfiguration());
                vi.getGraphics().drawImage(image, 0, 0, null);
                g.drawImage(vi, 0, 0,
                            window.getWidth(), window.getHeight(), null);
               
            } else {
                // mark the image dirty so the accelerated copy is updated
               Graphics gg = image.getGraphics();
                gg.setColor(translucentColor);
                gg.fillRect(0, 0, 1, 1);
               
                AffineTransform at = g.getTransform();
                g.setTransform(
                    AffineTransform.getScaleInstance(
                        canvas.getWidth()/(double)image.getWidth(),
                        canvas.getHeight()/(double)image.getHeight()));
           
                g.drawImage(image, 0, 0, null);
           
                g.setTransform(at);
            }
            g.setColor(Color.white);
            g.drawString(String.valueOf((int)fps), 10, 10);
            g.dispose();
            bufferStrategy.show();

            delta += System.currentTimeMillis() - time;
            time = System.currentTimeMillis();
            counter++;

            if(counter >= 100)
            {
                fps = 100000/delta;

                delta = 0;
                counter = 0;
            }
        }
    }
}
Offline Anon666

Junior Member




aka Abuse/AbU5e/TehJumpingJawa


« Reply #17 - Posted 2006-02-19 05:06:09 »

Quote
Anon666, your code did the trick and everything works great now - I went from 90fps to 240fps in my app!!. Smiley
Below is some more test code, you can try different stretch strategies by clicking the canvas.

I got the same fps without AffineTransform as I got with it. I have no idea why you didn't, it seems reasonable for drawImage to be hw accelerated for VolatileImages.  Undecided

Thanks everyone for your help.

yeah, I am now too =)

I guess I was just mistaken Wink
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.

radar3301 (9 views)
2014-09-21 23:33:17

BurntPizza (28 views)
2014-09-21 02:42:18

BurntPizza (18 views)
2014-09-21 01:30:30

moogie (20 views)
2014-09-21 00:26:15

UprightPath (27 views)
2014-09-20 20:14:06

BurntPizza (29 views)
2014-09-19 03:14:18

Dwinin (46 views)
2014-09-12 09:08:26

Norakomi (74 views)
2014-09-10 13:57:51

TehJavaDev (102 views)
2014-09-10 06:39:09

Tekkerue (50 views)
2014-09-09 02:24:56
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

List of Learning Resources
by SilverTiger
2014-07-31 16:26:06

List of Learning Resources
by SilverTiger
2014-07-31 11:54:12

HotSpot Options
by dleskov
2014-07-08 01:59:08
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!