2 * Copyright (c) 2003-2009 jMonkeyEngine
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
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.
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.
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.
33 package com.jmex.awt.swingui;
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;
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;
47 import com.jme.image.Texture;
48 import com.jme.system.DisplaySystem;
52 * LWJGL implementation of {@link ImageGraphics}.
54 class LWJGLImageGraphics extends ImageGraphicsBaseImpl {
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 );
65 protected LWJGLImageGraphics( int width, int height, int paintedMipMapCount ) {
66 this( width, height, paintedMipMapCount, 0, 1 );
69 private LWJGLImageGraphics( int width, int height, int paintedMipMapCount, int mipMapLevel, float scale ) {
70 super( width, height, paintedMipMapCount, mipMapLevel, scale );
72 if ( paintedMipMapCount > 0 && ( width > 1 || height > 1 ) ) {
79 mipMapChild = new LWJGLImageGraphics( width / 2, height / 2, paintedMipMapCount, mipMapLevel + 1, scale * 0.5f );
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
89 Rectangle2D.intersect( dirty, getImageBounds(), dirty );
91 if ( !this.dirty.isEmpty() ) {
93 //debug: check if we already have an error from previous operations
96 } catch ( OpenGLException e ) {
97 throw new RuntimeException("OpenGLException caused before any GL commands by LWJGLImageGraphics!", e );
100 boolean hasMipMaps = texture.getMinificationFilter().usesMipMapLevels();
103 if ( !glTexSubImage2DSupported || ( hasMipMaps && paintedMipMapCount == 0 ) ) {
106 DisplaySystem.getDisplaySystem().getRenderer()
107 .updateTextureSubImage(texture, 0, 0, image, 0,
108 0, image.getWidth(), image.getHeight());
111 // Remember what was previously bound.
113 GL11.glGetInteger(GL11.GL_TEXTURE_BINDING_2D, idBuff);
114 int oldTex = idBuff.get();
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 );
120 ByteBuffer data = image.getData(0);
123 GLU.gluBuild2DMipmaps( GL11.GL_TEXTURE_2D,
125 .getWidth(), image.getHeight(),
127 GL11.GL_UNSIGNED_BYTE, data );
129 // Rebind previous texture.
130 GL11.glBindTexture(GL11.GL_TEXTURE_2D, oldTex);
132 //debug: check if texture operations caused an error
136 DisplaySystem.getDisplaySystem().getRenderer()
137 .updateTextureSubImage(texture, dirty.x, dirty.y,
138 image, dirty.x, dirty.y, dirty.width,
141 //debug: check if texture operations caused an error to print more info
143 } catch ( OpenGLException e ) {
144 logger.warning("Error updating dirty region: " + dirty
146 + "falling back to updating whole image!");
147 glTexSubImage2DSupported = false;
148 update( texture, clean );
150 updateChildren = mipMapChild != null;
154 if ( updateChildren ) {
155 // delete lowest order bit to make position dividable by two
158 // make size dividable by two
159 if ( ( dirty.width & 1 ) != 0 ) {
162 if ( ( dirty.height & 1 ) != 0 ) {
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 );
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 );
179 mipMapChild.update( texture, clean );
182 this.dirty.width = 0;
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 );