OSDN Git Service

Set optimal mime types and executable settings.
[mikumikustudio/MikuMikuStudio.git] / src / com / jmex / awt / swingui / LWJGLImageGraphics.java
1 /*
2  * Copyright (c) 2003-2009 jMonkeyEngine
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met:
8  *
9  * * Redistributions of source code must retain the above copyright
10  *   notice, this list of conditions and the following disclaimer.
11  *
12  * * Redistributions in binary form must reproduce the above copyright
13  *   notice, this list of conditions and the following disclaimer in the
14  *   documentation and/or other materials provided with the distribution.
15  *
16  * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
17  *   may be used to endorse or promote products derived from this software
18  *   without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32
33 package com.jmex.awt.swingui;
34
35 import java.awt.Graphics;
36 import java.awt.Graphics2D;
37 import java.awt.Rectangle;
38 import java.awt.geom.Rectangle2D;
39 import java.awt.image.BufferedImage;
40 import java.nio.ByteBuffer;
41
42 import org.lwjgl.opengl.GL11;
43 import org.lwjgl.opengl.OpenGLException;
44 import org.lwjgl.opengl.Util;
45 import org.lwjgl.util.glu.GLU;
46
47 import com.jme.image.Texture;
48 import com.jme.system.DisplaySystem;
49
50
51 /**
52  * LWJGL implementation of {@link ImageGraphics}.
53  */
54 class LWJGLImageGraphics extends ImageGraphicsBaseImpl {
55
56     private LWJGLImageGraphics( BufferedImage awtImage, byte[] data, Graphics2D delegate,
57                                 com.jme.image.Image image, Rectangle dirty,
58                                 int translationX, int translationY,
59                                 float scaleX, float scaleY, int mipMapCount,
60                                 ImageGraphicsBaseImpl mipMapChild, int mipMapLevel ) {
61         super( awtImage, data, delegate, image, dirty, translationX, translationY, scaleX, scaleY,
62                 mipMapCount, mipMapChild, mipMapLevel );
63     }
64
65     protected LWJGLImageGraphics( int width, int height, int paintedMipMapCount ) {
66         this( width, height, paintedMipMapCount, 0, 1 );
67     }
68
69     private LWJGLImageGraphics( int width, int height, int paintedMipMapCount, int mipMapLevel, float scale ) {
70         super( width, height, paintedMipMapCount, mipMapLevel, scale );
71
72         if ( paintedMipMapCount > 0 && ( width > 1 || height > 1 ) ) {
73             if ( width < 2 ) {
74                 width = 2;
75             }
76             if ( height < 2 ) {
77                 height = 2;
78             }
79             mipMapChild = new LWJGLImageGraphics( width / 2, height / 2, paintedMipMapCount, mipMapLevel + 1, scale * 0.5f );
80         }
81     }
82
83     public void update( Texture texture, boolean clean ) {
84         boolean updateChildren = false;
85         synchronized ( dirty ) {
86             if ( !dirty.isEmpty() ) {
87                 dirty.grow( 2, 2 ); // to prevent antialiasing problems
88             }
89             Rectangle2D.intersect( dirty, getImageBounds(), dirty );
90
91             if ( !this.dirty.isEmpty() ) {
92
93                 //debug: check if we already have an error from previous operations
94                 try {
95                     Util.checkGLError();
96                 } catch ( OpenGLException e ) {
97                     throw new RuntimeException("OpenGLException caused before any GL commands by LWJGLImageGraphics!", e );
98                 }
99
100                 boolean hasMipMaps = texture.getMinificationFilter().usesMipMapLevels();
101
102                 update();
103                 if ( !glTexSubImage2DSupported || ( hasMipMaps && paintedMipMapCount == 0 ) ) {
104
105                     if ( !hasMipMaps ) {
106                         DisplaySystem.getDisplaySystem().getRenderer()
107                                 .updateTextureSubImage(texture, 0, 0, image, 0,
108                                         0, image.getWidth(), image.getHeight());
109                     }
110                     else {
111                         // Remember what was previously bound.
112                         idBuff.clear();
113                         GL11.glGetInteger(GL11.GL_TEXTURE_BINDING_2D, idBuff);
114                         int oldTex = idBuff.get();
115
116                         GL11.glBindTexture( GL11.GL_TEXTURE_2D, texture.getTextureId() );
117                         //set alignment to support images with  width % 4 != 0, as images are not aligned
118                         GL11.glPixelStorei( GL11.GL_UNPACK_ALIGNMENT, 1 );
119
120                         ByteBuffer data = image.getData(0);
121                         data.rewind();
122                         
123                         GLU.gluBuild2DMipmaps( GL11.GL_TEXTURE_2D,
124                                 GL11.GL_RGBA8, image
125                                 .getWidth(), image.getHeight(),
126                                 GL11.GL_RGBA,
127                                 GL11.GL_UNSIGNED_BYTE, data );
128                         
129                       // Rebind previous texture.
130                       GL11.glBindTexture(GL11.GL_TEXTURE_2D, oldTex);
131                     }
132                     //debug: check if texture operations caused an error
133                     Util.checkGLError();
134                 }
135                 else {
136                     DisplaySystem.getDisplaySystem().getRenderer()
137                             .updateTextureSubImage(texture, dirty.x, dirty.y,
138                                     image, dirty.x, dirty.y, dirty.width,
139                                     dirty.height);
140                     try {
141                         //debug: check if texture operations caused an error to print more info
142                         Util.checkGLError();
143                     } catch ( OpenGLException e ) {
144                         logger.warning("Error updating dirty region: " + dirty
145                                 + " - "
146                                 + "falling back to updating whole image!");
147                         glTexSubImage2DSupported = false;
148                         update( texture, clean );
149                     }
150                     updateChildren = mipMapChild != null;
151                 }
152             }
153         }
154         if ( updateChildren ) {
155             // delete lowest order bit to make position dividable by two
156             dirty.x &= ~1;
157             dirty.y &= ~1;
158             // make size dividable by two
159             if ( ( dirty.width & 1 ) != 0 ) {
160                 dirty.width++;
161             }
162             if ( ( dirty.height & 1 ) != 0 ) {
163                 dirty.height++;
164             }
165
166             int dx1 = (int) ( ( dirty.x - translation.x ) / scaleX );
167             int dy1 = (int) ( ( dirty.y - translation.y ) / scaleY );
168             int dx2 = (int) ( ( dirty.x + dirty.width - translation.x ) / scaleX );
169             int dy2 = (int) ( ( dirty.y + dirty.height - translation.y ) / scaleY );
170             int dw = dx2 - dx1;
171             int dh = dy2 - dy1;
172             mipMapChild.setClip( dx1, dy1, dw, dh );
173             // draw image on the mip map child image but don't let them draw it on their children
174             mipMapChild.delegate.clearRect( dx1, dy1, dw, dh );
175             mipMapChild.delegate.drawImage( awtImage, dx1, dy1, dx2, dy2,
176                     dirty.x, dirty.y, dirty.x + dirty.width, dirty.y + dirty.height, null );
177             mipMapChild.makeDirty( dx1, dy1, dw, dh );
178
179             mipMapChild.update( texture, clean );
180         }
181         if ( clean ) {
182             this.dirty.width = 0;
183         }
184     }
185
186     public Graphics create() {
187         return new LWJGLImageGraphics( awtImage, data, (Graphics2D) delegate.create(), image, dirty,
188                 translation.x, translation.y, scaleX, scaleY, paintedMipMapCount,
189                 mipMapChild != null && mipMapLevel < paintedMipMapCount - 1
190                         ? (ImageGraphicsBaseImpl) mipMapChild.create() : null, mipMapLevel );
191     }
192 }