@ -54,6 +54,7 @@ import com.jme3.texture.Texture;
import com.jme3.texture.Texture.WrapAxis ;
import com.jme3.texture.Texture.WrapAxis ;
import com.jme3.util.BufferUtils ;
import com.jme3.util.BufferUtils ;
import com.jme3.util.ListMap ;
import com.jme3.util.ListMap ;
import com.jme3.util.MipMapGenerator ;
import com.jme3.util.NativeObjectManager ;
import com.jme3.util.NativeObjectManager ;
import java.nio.* ;
import java.nio.* ;
import java.util.Arrays ;
import java.util.Arrays ;
@ -83,21 +84,6 @@ public class GLRenderer implements Renderer {
private final EnumSet < Caps > caps = EnumSet . noneOf ( Caps . class ) ;
private final EnumSet < Caps > caps = EnumSet . noneOf ( Caps . class ) ;
private final EnumMap < Limits , Integer > limits = new EnumMap < Limits , Integer > ( Limits . class ) ;
private final EnumMap < Limits , Integer > limits = new EnumMap < Limits , Integer > ( Limits . class ) ;
// private int vertexTextureUnits;
// private int fragTextureUnits;
// private int vertexUniforms;
// private int fragUniforms;
// private int vertexAttribs;
// private int maxFBOSamples;
// private int maxFBOAttachs;
// private int maxMRTFBOAttachs;
// private int maxRBSize;
// private int maxTexSize;
// private int maxCubeTexSize;
// private int maxVertCount;
// private int maxTriCount;
// private int maxColorTexSamples;
// private int maxDepthTexSamples;
private FrameBuffer mainFbOverride = null ;
private FrameBuffer mainFbOverride = null ;
private final Statistics statistics = new Statistics ( ) ;
private final Statistics statistics = new Statistics ( ) ;
private int vpX , vpY , vpW , vpH ;
private int vpX , vpY , vpW , vpH ;
@ -120,7 +106,7 @@ public class GLRenderer implements Renderer {
this . gl4 = gl instanceof GL4 ? ( GL4 ) gl : null ;
this . gl4 = gl instanceof GL4 ? ( GL4 ) gl : null ;
this . glfbo = glfbo ;
this . glfbo = glfbo ;
this . glext = glext ;
this . glext = glext ;
this . texUtil = new TextureUtil ( gl , gl2 , glext , context ) ;
this . texUtil = new TextureUtil ( gl , gl2 , glext ) ;
}
}
@Override
@Override
@ -271,13 +257,17 @@ public class GLRenderer implements Renderer {
// gl.glGetInteger(GL.GL_MAX_FRAGMENT_UNIFORM_COMPONENTS, intBuf16);
// gl.glGetInteger(GL.GL_MAX_FRAGMENT_UNIFORM_COMPONENTS, intBuf16);
// fragUniforms = intBuf16.get(0);
// fragUniforms = intBuf16.get(0);
// logger.log(Level.FINER, "Fragment Uniforms: {0}", fragUniforms);
// logger.log(Level.FINER, "Fragment Uniforms: {0}", fragUniforms);
if ( caps . contains ( Caps . OpenGLES20 ) ) {
limits . put ( Limits . VertexUniformVectors , getInteger ( GL . GL_MAX_VERTEX_UNIFORM_VECTORS ) ) ;
} else {
limits . put ( Limits . VertexUniformVectors , getInteger ( GL . GL_MAX_VERTEX_UNIFORM_COMPONENTS ) / 4 ) ;
}
limits . put ( Limits . VertexAttributes , getInteger ( GL . GL_MAX_VERTEX_ATTRIBS ) ) ;
limits . put ( Limits . VertexAttributes , getInteger ( GL . GL_MAX_VERTEX_ATTRIBS ) ) ;
limits . put ( Limits . TextureSize , getInteger ( GL . GL_MAX_TEXTURE_SIZE ) ) ;
limits . put ( Limits . TextureSize , getInteger ( GL . GL_MAX_TEXTURE_SIZE ) ) ;
limits . put ( Limits . CubemapSize , getInteger ( GL . GL_MAX_CUBE_MAP_TEXTURE_SIZE ) ) ;
limits . put ( Limits . CubemapSize , getInteger ( GL . GL_MAX_CUBE_MAP_TEXTURE_SIZE ) ) ;
if ( hasExtension ( "GL_ARB_draw_instanced" ) & &
if ( hasExtension ( "GL_ARB_draw_instanced" ) & &
hasExtension ( "GL_ARB_instanced_arrays" ) ) {
hasExtension ( "GL_ARB_instanced_arrays" ) ) {
caps . add ( Caps . MeshInstancing ) ;
caps . add ( Caps . MeshInstancing ) ;
}
}
@ -294,11 +284,11 @@ public class GLRenderer implements Renderer {
boolean hasFloatTexture ;
boolean hasFloatTexture ;
hasFloatTexture = hasExtension ( "GL_OES_texture_half_float" ) & &
hasFloatTexture = hasExtension ( "GL_OES_texture_half_float" ) & &
hasExtension ( "GL_OES_texture_float" ) ;
hasExtension ( "GL_OES_texture_float" ) ;
if ( ! hasFloatTexture ) {
if ( ! hasFloatTexture ) {
hasFloatTexture = hasExtension ( "GL_ARB_texture_float" ) & &
hasFloatTexture = hasExtension ( "GL_ARB_texture_float" ) & &
hasExtension ( "GL_ARB_half_float_pixel" ) ;
hasExtension ( "GL_ARB_half_float_pixel" ) ;
if ( ! hasFloatTexture ) {
if ( ! hasFloatTexture ) {
hasFloatTexture = caps . contains ( Caps . OpenGL30 ) ;
hasFloatTexture = caps . contains ( Caps . OpenGL30 ) ;
@ -316,8 +306,8 @@ public class GLRenderer implements Renderer {
}
}
if ( hasExtension ( "GL_OES_rgb8_rgba8" ) | |
if ( hasExtension ( "GL_OES_rgb8_rgba8" ) | |
hasExtension ( "GL_ARM_rgba8" ) | |
hasExtension ( "GL_ARM_rgba8" ) | |
hasExtension ( "GL_EXT_texture_format_BGRA8888" ) ) {
hasExtension ( "GL_EXT_texture_format_BGRA8888" ) ) {
caps . add ( Caps . Rgba8 ) ;
caps . add ( Caps . Rgba8 ) ;
}
}
@ -326,7 +316,7 @@ public class GLRenderer implements Renderer {
}
}
if ( hasExtension ( "GL_ARB_color_buffer_float" ) & &
if ( hasExtension ( "GL_ARB_color_buffer_float" ) & &
hasExtension ( "GL_ARB_half_float_pixel" ) ) {
hasExtension ( "GL_ARB_half_float_pixel" ) ) {
// XXX: Require both 16 and 32 bit float support for FloatColorBuffer.
// XXX: Require both 16 and 32 bit float support for FloatColorBuffer.
caps . add ( Caps . FloatColorBuffer ) ;
caps . add ( Caps . FloatColorBuffer ) ;
}
}
@ -336,7 +326,7 @@ public class GLRenderer implements Renderer {
}
}
if ( ( hasExtension ( "GL_EXT_packed_float" ) & & hasFloatTexture ) | |
if ( ( hasExtension ( "GL_EXT_packed_float" ) & & hasFloatTexture ) | |
caps . contains ( Caps . OpenGL30 ) ) {
caps . contains ( Caps . OpenGL30 ) ) {
// Either OpenGL3 is available or both packed_float & half_float_pixel.
// Either OpenGL3 is available or both packed_float & half_float_pixel.
caps . add ( Caps . PackedFloatColorBuffer ) ;
caps . add ( Caps . PackedFloatColorBuffer ) ;
caps . add ( Caps . PackedFloatTexture ) ;
caps . add ( Caps . PackedFloatTexture ) ;
@ -364,14 +354,13 @@ public class GLRenderer implements Renderer {
}
}
if ( hasExtension ( "GL_ARB_texture_non_power_of_two" ) | |
if ( hasExtension ( "GL_ARB_texture_non_power_of_two" ) | |
hasExtension ( "GL_OES_texture_npot" ) | |
hasExtension ( "GL_OES_texture_npot" ) | |
hasExtension ( "GL_APPLE_texture_2D_limited_npot" ) | |
caps . contains ( Caps . OpenGL30 ) ) {
caps . contains ( Caps . OpenGL30 ) ) {
caps . add ( Caps . NonPowerOfTwoTextures ) ;
caps . add ( Caps . NonPowerOfTwoTextures ) ;
} else {
} else {
logger . log ( Level . WARNING , "Your graphics card does not "
logger . log ( Level . WARNING , "Your graphics card does not "
+ "support non-power-of-2 textures. "
+ "support non-power-of-2 textures. "
+ "Some features might not work." ) ;
+ "Some features might not work." ) ;
}
}
if ( caps . contains ( Caps . OpenGLES20 ) ) {
if ( caps . contains ( Caps . OpenGLES20 ) ) {
@ -387,7 +376,9 @@ public class GLRenderer implements Renderer {
caps . add ( Caps . TextureFilterAnisotropic ) ;
caps . add ( Caps . TextureFilterAnisotropic ) ;
}
}
if ( hasExtension ( "GL_EXT_framebuffer_object" ) | | gl3 ! = null ) {
if ( hasExtension ( "GL_EXT_framebuffer_object" )
| | gl3 ! = null
| | caps . contains ( Caps . OpenGLES20 ) ) {
caps . add ( Caps . FrameBuffer ) ;
caps . add ( Caps . FrameBuffer ) ;
limits . put ( Limits . RenderBufferSize , getInteger ( GLFbo . GL_MAX_RENDERBUFFER_SIZE_EXT ) ) ;
limits . put ( Limits . RenderBufferSize , getInteger ( GLFbo . GL_MAX_RENDERBUFFER_SIZE_EXT ) ) ;
@ -412,7 +403,7 @@ public class GLRenderer implements Renderer {
}
}
}
}
if ( hasExtension ( "GL_ARB_draw_buffers" ) ) {
if ( hasExtension ( "GL_ARB_draw_buffers" ) | | gl3 ! = null ) {
limits . put ( Limits . FrameBufferMrtAttachments , getInteger ( GLExt . GL_MAX_DRAW_BUFFERS_ARB ) ) ;
limits . put ( Limits . FrameBufferMrtAttachments , getInteger ( GLExt . GL_MAX_DRAW_BUFFERS_ARB ) ) ;
if ( limits . get ( Limits . FrameBufferMrtAttachments ) > 1 ) {
if ( limits . get ( Limits . FrameBufferMrtAttachments ) > 1 ) {
caps . add ( Caps . FrameBufferMRT ) ;
caps . add ( Caps . FrameBufferMRT ) ;
@ -437,7 +428,7 @@ public class GLRenderer implements Renderer {
// Supports sRGB pipeline.
// Supports sRGB pipeline.
if ( ( hasExtension ( "GL_ARB_framebuffer_sRGB" ) & & hasExtension ( "GL_EXT_texture_sRGB" ) )
if ( ( hasExtension ( "GL_ARB_framebuffer_sRGB" ) & & hasExtension ( "GL_EXT_texture_sRGB" ) )
| | caps . contains ( Caps . OpenGL30 ) ) {
| | caps . contains ( Caps . OpenGL30 ) ) {
caps . add ( Caps . Srgb ) ;
caps . add ( Caps . Srgb ) ;
}
}
@ -459,18 +450,18 @@ public class GLRenderer implements Renderer {
// Print context information
// Print context information
logger . log ( Level . INFO , "OpenGL Renderer Information\n" +
logger . log ( Level . INFO , "OpenGL Renderer Information\n" +
" * Vendor: {0}\n" +
" * Vendor: {0}\n" +
" * Renderer: {1}\n" +
" * Renderer: {1}\n" +
" * OpenGL Version: {2}\n" +
" * OpenGL Version: {2}\n" +
" * GLSL Version: {3}\n" +
" * GLSL Version: {3}\n" +
" * Profile: {4}" ,
" * Profile: {4}" ,
new Object [ ] {
new Object [ ] {
gl . glGetString ( GL . GL_VENDOR ) ,
gl . glGetString ( GL . GL_VENDOR ) ,
gl . glGetString ( GL . GL_RENDERER ) ,
gl . glGetString ( GL . GL_RENDERER ) ,
gl . glGetString ( GL . GL_VERSION ) ,
gl . glGetString ( GL . GL_VERSION ) ,
gl . glGetString ( GL . GL_SHADING_LANGUAGE_VERSION ) ,
gl . glGetString ( GL . GL_SHADING_LANGUAGE_VERSION ) ,
caps . contains ( Caps . CoreProfile ) ? "Core" : "Compatibility"
caps . contains ( Caps . CoreProfile ) ? "Core" : "Compatibility"
} ) ;
} ) ;
// Print capabilities (if fine logging is enabled)
// Print capabilities (if fine logging is enabled)
if ( logger . isLoggable ( Level . FINE ) ) {
if ( logger . isLoggable ( Level . FINE ) ) {
@ -551,8 +542,8 @@ public class GLRenderer implements Renderer {
}
}
/ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * \
/ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * \
| * Render State * |
| * Render State * |
\ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /
\ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /
public void setDepthRange ( float start , float end ) {
public void setDepthRange ( float start , float end ) {
gl . glDepthRange ( start , end ) ;
gl . glDepthRange ( start , end ) ;
}
}
@ -830,8 +821,8 @@ public class GLRenderer implements Renderer {
}
}
/ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * \
/ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * \
| * Camera and World transforms * |
| * Camera and World transforms * |
\ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /
\ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /
public void setViewPort ( int x , int y , int w , int h ) {
public void setViewPort ( int x , int y , int w , int h ) {
if ( x ! = vpX | | vpY ! = y | | vpW ! = w | | vpH ! = h ) {
if ( x ! = vpX | | vpY ! = y | | vpW ! = w | | vpH ! = h ) {
gl . glViewport ( x , y , w , h ) ;
gl . glViewport ( x , y , w , h ) ;
@ -874,8 +865,8 @@ public class GLRenderer implements Renderer {
}
}
/ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * \
/ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * \
| * Shaders * |
| * Shaders * |
\ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /
\ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /
protected void updateUniformLocation ( Shader shader , Uniform uniform ) {
protected void updateUniformLocation ( Shader shader , Uniform uniform ) {
int loc = gl . glGetUniformLocation ( shader . getId ( ) , uniform . getName ( ) ) ;
int loc = gl . glGetUniformLocation ( shader . getId ( ) , uniform . getName ( ) ) ;
if ( loc < 0 ) {
if ( loc < 0 ) {
@ -1058,7 +1049,7 @@ public class GLRenderer implements Renderer {
if ( gles2 & & ! language . equals ( "GLSL100" ) ) {
if ( gles2 & & ! language . equals ( "GLSL100" ) ) {
throw new RendererException ( "This shader cannot run in OpenGL ES 2. "
throw new RendererException ( "This shader cannot run in OpenGL ES 2. "
+ "Only GLSL 1.00 shaders are supported." ) ;
+ "Only GLSL 1.00 shaders are supported." ) ;
}
}
// Upload shader source.
// Upload shader source.
@ -1075,6 +1066,9 @@ public class GLRenderer implements Renderer {
stringBuf . append ( "\n" ) ;
stringBuf . append ( "\n" ) ;
} else {
} else {
if ( gles2 ) {
if ( gles2 ) {
// request GLSL ES (1.00) when compiling under GLES2.
stringBuf . append ( "#version 100\n" ) ;
if ( source . getType ( ) = = ShaderType . Fragment ) {
if ( source . getType ( ) = = ShaderType . Fragment ) {
// GLES2 requires precision qualifier.
// GLES2 requires precision qualifier.
stringBuf . append ( "precision mediump float;\n" ) ;
stringBuf . append ( "precision mediump float;\n" ) ;
@ -1091,6 +1085,7 @@ public class GLRenderer implements Renderer {
if ( linearizeSrgbImages ) {
if ( linearizeSrgbImages ) {
stringBuf . append ( "#define SRGB 1\n" ) ;
stringBuf . append ( "#define SRGB 1\n" ) ;
}
}
stringBuf . append ( "#define " ) . append ( source . getType ( ) . name ( ) . toUpperCase ( ) ) . append ( "_SHADER 1\n" ) ;
stringBuf . append ( source . getDefines ( ) ) ;
stringBuf . append ( source . getDefines ( ) ) ;
stringBuf . append ( source . getSource ( ) ) ;
stringBuf . append ( source . getSource ( ) ) ;
@ -1261,8 +1256,8 @@ public class GLRenderer implements Renderer {
}
}
/ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * \
/ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * \
| * Framebuffers * |
| * Framebuffers * |
\ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /
\ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /
public void copyFrameBuffer ( FrameBuffer src , FrameBuffer dst ) {
public void copyFrameBuffer ( FrameBuffer src , FrameBuffer dst ) {
copyFrameBuffer ( src , dst , true ) ;
copyFrameBuffer ( src , dst , true ) ;
}
}
@ -1428,7 +1423,7 @@ public class GLRenderer implements Renderer {
// Check NPOT requirements
// Check NPOT requirements
checkNonPowerOfTwo ( tex ) ;
checkNonPowerOfTwo ( tex ) ;
updateTexImageData ( image , tex . getType ( ) , 0 ) ;
updateTexImageData ( image , tex . getType ( ) , 0 , false ) ;
// NOTE: For depth textures, sets nearest/no-mips mode
// NOTE: For depth textures, sets nearest/no-mips mode
// Required to fix "framebuffer unsupported"
// Required to fix "framebuffer unsupported"
@ -1678,7 +1673,7 @@ public class GLRenderer implements Renderer {
gl . glReadPixels ( vpX , vpY , vpW , vpH , glFormat , dataType , byteBuf ) ;
gl . glReadPixels ( vpX , vpY , vpW , vpH , glFormat , dataType , byteBuf ) ;
}
}
public void readFrameBufferWithFormat ( FrameBuffer fb , ByteBuffer byteBuf , Image . Format format ) {
public void readFrameBufferWithFormat ( FrameBuffer fb , ByteBuffer byteBuf , Image . Format format ) {
GLImageFormat glFormat = texUtil . getImageFormatWithError ( format , false ) ;
GLImageFormat glFormat = texUtil . getImageFormatWithError ( format , false ) ;
readFrameBufferWithGLFormat ( fb , byteBuf , glFormat . format , glFormat . dataType ) ;
readFrameBufferWithGLFormat ( fb , byteBuf , glFormat . format , glFormat . dataType ) ;
}
}
@ -1711,12 +1706,12 @@ public class GLRenderer implements Renderer {
}
}
/ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * \
/ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * \
| * Textures * |
| * Textures * |
\ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /
\ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /
private int convertTextureType ( Texture . Type type , int samples , int face ) {
private int convertTextureType ( Texture . Type type , int samples , int face ) {
if ( samples > 1 & & ! caps . contains ( Caps . TextureMultisample ) ) {
if ( samples > 1 & & ! caps . contains ( Caps . TextureMultisample ) ) {
throw new RendererException ( "Multisample textures are not supported" +
throw new RendererException ( "Multisample textures are not supported" +
" by the video hardware." ) ;
" by the video hardware." ) ;
}
}
switch ( type ) {
switch ( type ) {
@ -1739,7 +1734,7 @@ public class GLRenderer implements Renderer {
case ThreeDimensional :
case ThreeDimensional :
if ( ! caps . contains ( Caps . OpenGL20 ) ) {
if ( ! caps . contains ( Caps . OpenGL20 ) ) {
throw new RendererException ( "3D textures are not supported" +
throw new RendererException ( "3D textures are not supported" +
" by the video hardware." ) ;
" by the video hardware." ) ;
}
}
return GL2 . GL_TEXTURE_3D ;
return GL2 . GL_TEXTURE_3D ;
case CubeMap :
case CubeMap :
@ -1858,10 +1853,6 @@ public class GLRenderer implements Renderer {
}
}
}
}
if ( context . pointSprite ) {
return ; // Attempt to fix glTexParameter crash for some ATI GPUs
}
// repeat modes
// repeat modes
switch ( tex . getType ( ) ) {
switch ( tex . getType ( ) ) {
case ThreeDimensional :
case ThreeDimensional :
@ -1897,8 +1888,8 @@ public class GLRenderer implements Renderer {
gl2 . glTexParameteri ( target , GL2 . GL_TEXTURE_COMPARE_FUNC , GL . GL_LEQUAL ) ;
gl2 . glTexParameteri ( target , GL2 . GL_TEXTURE_COMPARE_FUNC , GL . GL_LEQUAL ) ;
}
}
} else {
} else {
//restoring default value
//restoring default value
gl2 . glTexParameteri ( target , GL2 . GL_TEXTURE_COMPARE_MODE , GL . GL_NONE ) ;
gl2 . glTexParameteri ( target , GL2 . GL_TEXTURE_COMPARE_MODE , GL . GL_NONE ) ;
}
}
tex . compareModeUpdated ( ) ;
tex . compareModeUpdated ( ) ;
}
}
@ -1929,13 +1920,13 @@ public class GLRenderer implements Renderer {
if ( ! caps . contains ( Caps . PartialNonPowerOfTwoTextures ) ) {
if ( ! caps . contains ( Caps . PartialNonPowerOfTwoTextures ) ) {
// Cannot use any type of NPOT texture (uncommon)
// Cannot use any type of NPOT texture (uncommon)
throw new RendererException ( "non-power-of-2 textures are not "
throw new RendererException ( "non-power-of-2 textures are not "
+ "supported by the video hardware" ) ;
+ "supported by the video hardware" ) ;
}
}
// Partial NPOT supported..
// Partial NPOT supported..
if ( tex . getMinFilter ( ) . usesMipMapLevels ( ) ) {
if ( tex . getMinFilter ( ) . usesMipMapLevels ( ) ) {
throw new RendererException ( "non-power-of-2 textures with mip-maps "
throw new RendererException ( "non-power-of-2 textures with mip-maps "
+ "are not supported by the video hardware" ) ;
+ "are not supported by the video hardware" ) ;
}
}
switch ( tex . getType ( ) ) {
switch ( tex . getType ( ) ) {
@ -1943,7 +1934,7 @@ public class GLRenderer implements Renderer {
case ThreeDimensional :
case ThreeDimensional :
if ( tex . getWrap ( WrapAxis . R ) ! = Texture . WrapMode . EdgeClamp ) {
if ( tex . getWrap ( WrapAxis . R ) ! = Texture . WrapMode . EdgeClamp ) {
throw new RendererException ( "repeating non-power-of-2 textures "
throw new RendererException ( "repeating non-power-of-2 textures "
+ "are not supported by the video hardware" ) ;
+ "are not supported by the video hardware" ) ;
}
}
// fallthrough intentional!!!
// fallthrough intentional!!!
case TwoDimensionalArray :
case TwoDimensionalArray :
@ -1951,7 +1942,7 @@ public class GLRenderer implements Renderer {
if ( tex . getWrap ( WrapAxis . S ) ! = Texture . WrapMode . EdgeClamp
if ( tex . getWrap ( WrapAxis . S ) ! = Texture . WrapMode . EdgeClamp
| | tex . getWrap ( WrapAxis . T ) ! = Texture . WrapMode . EdgeClamp ) {
| | tex . getWrap ( WrapAxis . T ) ! = Texture . WrapMode . EdgeClamp ) {
throw new RendererException ( "repeating non-power-of-2 textures "
throw new RendererException ( "repeating non-power-of-2 textures "
+ "are not supported by the video hardware" ) ;
+ "are not supported by the video hardware" ) ;
}
}
break ;
break ;
default :
default :
@ -1965,8 +1956,10 @@ public class GLRenderer implements Renderer {
* @param img The image to upload
* @param img The image to upload
* @param type How the data in the image argument should be interpreted .
* @param type How the data in the image argument should be interpreted .
* @param unit The texture slot to be used to upload the image , not important
* @param unit The texture slot to be used to upload the image , not important
* @param scaleToPot If true , the image will be scaled to power - of - 2 dimensions
* before being uploaded .
* /
* /
public void updateTexImageData ( Image img , Texture . Type type , int unit ) {
public void updateTexImageData ( Image img , Texture . Type type , int unit , boolean scaleToPot ) {
int texId = img . getId ( ) ;
int texId = img . getId ( ) ;
if ( texId = = - 1 ) {
if ( texId = = - 1 ) {
// create texture
// create texture
@ -2050,33 +2043,39 @@ public class GLRenderer implements Renderer {
}
}
}
}
Image imageForUpload ;
if ( scaleToPot ) {
imageForUpload = MipMapGenerator . resizeToPowerOf2 ( img ) ;
} else {
imageForUpload = img ;
}
if ( target = = GL . GL_TEXTURE_CUBE_MAP ) {
if ( target = = GL . GL_TEXTURE_CUBE_MAP ) {
List < ByteBuffer > data = img . getData ( ) ;
List < ByteBuffer > data = ima geForUpload . getData ( ) ;
if ( data . size ( ) ! = 6 ) {
if ( data . size ( ) ! = 6 ) {
logger . log ( Level . WARNING , "Invalid texture: {0}\n"
logger . log ( Level . WARNING , "Invalid texture: {0}\n"
+ "Cubemap textures must contain 6 data units." , img ) ;
+ "Cubemap textures must contain 6 data units." , img ) ;
return ;
return ;
}
}
for ( int i = 0 ; i < 6 ; i + + ) {
for ( int i = 0 ; i < 6 ; i + + ) {
texUtil . uploadTexture ( img , GL . GL_TEXTURE_CUBE_MAP_POSITIVE_X + i , i , linearizeSrgbImages ) ;
texUtil . uploadTexture ( ima geForUpload , GL . GL_TEXTURE_CUBE_MAP_POSITIVE_X + i , i , linearizeSrgbImages ) ;
}
}
} else if ( target = = GLExt . GL_TEXTURE_2D_ARRAY_EXT ) {
} else if ( target = = GLExt . GL_TEXTURE_2D_ARRAY_EXT ) {
if ( ! caps . contains ( Caps . TextureArray ) ) {
if ( ! caps . contains ( Caps . TextureArray ) ) {
throw new RendererException ( "Texture arrays not supported by graphics hardware" ) ;
throw new RendererException ( "Texture arrays not supported by graphics hardware" ) ;
}
}
List < ByteBuffer > data = img . getData ( ) ;
List < ByteBuffer > data = ima geForUpload . getData ( ) ;
// -1 index specifies prepare data for 2D Array
// -1 index specifies prepare data for 2D Array
texUtil . uploadTexture ( img , target , - 1 , linearizeSrgbImages ) ;
texUtil . uploadTexture ( ima geForUpload , target , - 1 , linearizeSrgbImages ) ;
for ( int i = 0 ; i < data . size ( ) ; i + + ) {
for ( int i = 0 ; i < data . size ( ) ; i + + ) {
// upload each slice of 2D array in turn
// upload each slice of 2D array in turn
// this time with the appropriate index
// this time with the appropriate index
texUtil . uploadTexture ( img , target , i , linearizeSrgbImages ) ;
texUtil . uploadTexture ( ima geForUpload , target , i , linearizeSrgbImages ) ;
}
}
} else {
} else {
texUtil . uploadTexture ( img , target , 0 , linearizeSrgbImages ) ;
texUtil . uploadTexture ( ima geForUpload , target , 0 , linearizeSrgbImages ) ;
}
}
if ( img . getMultiSamples ( ) ! = imageSamples ) {
if ( img . getMultiSamples ( ) ! = imageSamples ) {
@ -2097,9 +2096,23 @@ public class GLRenderer implements Renderer {
Image image = tex . getImage ( ) ;
Image image = tex . getImage ( ) ;
if ( image . isUpdateNeeded ( ) | | ( image . isGeneratedMipmapsRequired ( ) & & ! image . isMipmapsGenerated ( ) ) ) {
if ( image . isUpdateNeeded ( ) | | ( image . isGeneratedMipmapsRequired ( ) & & ! image . isMipmapsGenerated ( ) ) ) {
// Check NPOT requirements
// Check NPOT requirements
checkNonPowerOfTwo ( tex ) ;
boolean scaleToPot = false ;
try {
checkNonPowerOfTwo ( tex ) ;
} catch ( RendererException ex ) {
if ( logger . isLoggable ( Level . WARNING ) ) {
int nextWidth = FastMath . nearestPowerOfTwo ( tex . getImage ( ) . getWidth ( ) ) ;
int nextHeight = FastMath . nearestPowerOfTwo ( tex . getImage ( ) . getHeight ( ) ) ;
logger . log ( Level . WARNING ,
"Non-power-of-2 textures are not supported! Scaling texture '" + tex . getName ( ) +
"' of size " + tex . getImage ( ) . getWidth ( ) + "x" + tex . getImage ( ) . getHeight ( ) +
" to " + nextWidth + "x" + nextHeight ) ;
}
scaleToPot = true ;
}
updateTexImageData ( image , tex . getType ( ) , unit ) ;
updateTexImageData ( image , tex . getType ( ) , unit , scaleToPot ) ;
}
}
int texId = image . getId ( ) ;
int texId = image . getId ( ) ;
@ -2144,8 +2157,8 @@ public class GLRenderer implements Renderer {
}
}
/ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * \
/ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * \
| * Vertex Buffers and Attributes * |
| * Vertex Buffers and Attributes * |
\ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /
\ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /
private int convertUsage ( Usage usage ) {
private int convertUsage ( Usage usage ) {
switch ( usage ) {
switch ( usage ) {
case Static :
case Static :
@ -2484,8 +2497,8 @@ public class GLRenderer implements Renderer {
}
}
/ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * \
/ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * \
| * Render Calls * |
| * Render Calls * |
\ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /
\ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /
public int convertElementMode ( Mesh . Mode mode ) {
public int convertElementMode ( Mesh . Mode mode ) {
switch ( mode ) {
switch ( mode ) {
case Points :
case Points :
@ -2648,10 +2661,10 @@ public class GLRenderer implements Renderer {
public void setMainFrameBufferSrgb ( boolean enableSrgb ) {
public void setMainFrameBufferSrgb ( boolean enableSrgb ) {
// Gamma correction
// Gamma correction
if ( ! caps . contains ( Caps . Srgb ) ) {
if ( ! caps . contains ( Caps . Srgb ) & & enableSrgb ) {
// Not supported, sorry.
// Not supported, sorry.
logger . warning ( "sRGB framebuffer is not supported " +
logger . warning ( "sRGB framebuffer is not supported " +
"by video hardware, but was requested." ) ;
"by video hardware, but was requested." ) ;
return ;
return ;
}
}