/* * Copyright (c) 2009-2012 jMonkeyEngine * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * * Neither the name of 'jMonkeyEngine' nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package com.jme3.renderer; import com.jme3.shader.Shader; import com.jme3.shader.Shader.ShaderSource; import com.jme3.texture.FrameBuffer; import com.jme3.texture.FrameBuffer.RenderBuffer; import com.jme3.texture.Image; import com.jme3.texture.Image.Format; import com.jme3.texture.Texture; import java.util.Collection; /** * <code>Caps</code> is an enum specifying a capability that the {@link Renderer} * supports. * * @author Kirill Vainer */ public enum Caps { /** * Supports {@link FrameBuffer FrameBuffers}. * <p> * OpenGL: Renderer exposes the GL_EXT_framebuffer_object extension.<br> * OpenGL ES: Renderer supports OpenGL ES 2.0. *//** * Supports {@link FrameBuffer FrameBuffers}. * <p> * OpenGL: Renderer exposes the GL_EXT_framebuffer_object extension.<br> * OpenGL ES: Renderer supports OpenGL ES 2.0. *//** * Supports {@link FrameBuffer FrameBuffers}. * <p> * OpenGL: Renderer exposes the GL_EXT_framebuffer_object extension.<br> * OpenGL ES: Renderer supports OpenGL ES 2.0. *//** * Supports {@link FrameBuffer FrameBuffers}. * <p> * OpenGL: Renderer exposes the GL_EXT_framebuffer_object extension.<br> * OpenGL ES: Renderer supports OpenGL ES 2.0. */ FrameBuffer, /** * Supports framebuffer Multiple Render Targets (MRT) * <p> * OpenGL: Renderer exposes the GL_ARB_draw_buffers extension */ FrameBufferMRT, /** * Supports framebuffer multi-sampling * <p> * OpenGL: Renderer exposes the GL EXT framebuffer multisample extension<br> * OpenGL ES: Renderer exposes GL_APPLE_framebuffer_multisample or * GL_ANGLE_framebuffer_multisample. */ FrameBufferMultisample, /** * Supports texture multi-sampling * <p> * OpenGL: Renderer exposes the GL_ARB_texture_multisample extension<br> * OpenGL ES: Renderer exposes the GL_IMG_multisampled_render_to_texture * extension. */ TextureMultisample, /** * Supports OpenGL 2.0 or OpenGL ES 2.0. */ OpenGL20, /** * Supports OpenGL 2.1 */ OpenGL21, /** * Supports OpenGL 3.0 */ OpenGL30, /** * Supports OpenGL 3.1 */ OpenGL31, /** * Supports OpenGL 3.2 */ OpenGL32, /** * Supports OpenGL 3.3 */ OpenGL33, /** * Supports OpenGL 4.0 */ OpenGL40, /** * Do not use. * * @deprecated do not use. */ @Deprecated Reserved0, /** * Supports GLSL 1.0 */ GLSL100, /** * Supports GLSL 1.1 */ GLSL110, /** * Supports GLSL 1.2 */ GLSL120, /** * Supports GLSL 1.3 */ GLSL130, /** * Supports GLSL 1.4 */ GLSL140, /** * Supports GLSL 1.5 */ GLSL150, /** * Supports GLSL 3.3 */ GLSL330, /** * Supports GLSL 4.0 */ GLSL400, /** * Supports reading from textures inside the vertex shader. */ VertexTextureFetch, /** * Supports geometry shader. */ GeometryShader, /** * Supports Tesselation shader */ TesselationShader, /** * Supports texture arrays */ TextureArray, /** * Supports texture buffers */ TextureBuffer, /** * Supports floating point & half textures (Format.RGB16F) */ FloatTexture, /** * Supports integer textures */ IntegerTexture, /** * Supports floating point FBO color buffers (Format.RGB16F) */ FloatColorBuffer, /** * Supports floating point depth buffer */ FloatDepthBuffer, /** * Supports Format.RGB111110F for textures */ PackedFloatTexture, /** * Supports Format.RGB9E5 for textures */ SharedExponentTexture, /** * Supports Format.RGB111110F for FBO color buffers */ PackedFloatColorBuffer, /** * Supports Format.RGB9E5 for FBO color buffers */ SharedExponentColorBuffer, /** * Do not use. * * @deprecated do not use. */ @Deprecated Reserved1, /** * Supports Non-Power-Of-Two (NPOT) textures and framebuffers */ NonPowerOfTwoTextures, /** * Supports geometry instancing. */ MeshInstancing, /** * Supports VAO, or vertex buffer arrays */ VertexBufferArray, /** * Supports multisampling on the screen */ Multisample, /** * Supports FBO with Depth24Stencil8 image format */ PackedDepthStencilBuffer, /** * Supports sRGB framebuffers and sRGB texture format */ Srgb, /** * Supports blitting framebuffers. */ FrameBufferBlit, /** * Supports {@link Format#DXT1} and sister formats. */ TextureCompressionS3TC, /** * Supports anisotropic texture filtering. */ TextureFilterAnisotropic, /** * Supports {@link Format#ETC1} texture compression. */ TextureCompressionETC1, /** * Supports {@link Format#ETC1} texture compression by uploading * the texture as ETC2 (they are backwards compatible). */ TextureCompressionETC2, /** * Supports OpenGL ES 2 */ OpenGLES20, /** * Supports RGB8 / RGBA8 textures */ Rgba8, /** * Supports depth textures. */ DepthTexture, /** * Supports 32-bit index buffers. */ IntegerIndexBuffer, /** * Partial support for non-power-of-2 textures, typically found * on OpenGL ES 2 devices. * <p> * Use of NPOT textures is allowed iff: * <ul> * <li>The {@link Texture.WrapMode} is set to * {@link Texture.WrapMode#EdgeClamp}.</li> * <li>Mip-mapping is not used, meaning {@link Texture.MinFilter} is set to * {@link Texture.MinFilter#BilinearNoMipMaps} or * {@link Texture.MinFilter#NearestNoMipMaps}</li> * </ul> */ PartialNonPowerOfTwoTextures, /** * When sampling cubemap edges, interpolate between the adjecent faces * instead of just sampling one face. * <p> * Improves the quality of environment mapping. */ SeamlessCubemap, /** * Running with OpenGL 3.2+ core profile. * * Compatibility features will not be available. */ CoreProfile, /** * GPU can provide and accept binary shaders. */ BinaryShader; /** * Returns true if given the renderer capabilities, the texture * can be supported by the renderer. * <p> * This only checks the format of the texture, non-power-of-2 * textures are scaled automatically inside the renderer * if are not supported natively. * * @param caps The collection of renderer capabilities {@link Renderer#getCaps() }. * @param tex The texture to check * @return True if it is supported, false otherwise. */ public static boolean supports(Collection<Caps> caps, Texture tex){ if (tex.getType() == Texture.Type.TwoDimensionalArray && !caps.contains(Caps.TextureArray)) return false; Image img = tex.getImage(); if (img == null) return true; Format fmt = img.getFormat(); switch (fmt){ case Depth24Stencil8: return caps.contains(Caps.PackedDepthStencilBuffer); case Depth32F: return caps.contains(Caps.FloatDepthBuffer); case RGB16F_to_RGB111110F: case RGB111110F: return caps.contains(Caps.PackedFloatTexture); case RGB16F_to_RGB9E5: case RGB9E5: return caps.contains(Caps.SharedExponentTexture); default: if (fmt.isFloatingPont()) return caps.contains(Caps.FloatTexture); return true; } } private static boolean supportsColorBuffer(Collection<Caps> caps, RenderBuffer colorBuf){ Format colorFmt = colorBuf.getFormat(); if (colorFmt.isDepthFormat()) return false; if (colorFmt.isCompressed()) return false; switch (colorFmt){ case RGB111110F: return caps.contains(Caps.PackedFloatColorBuffer); case RGB16F_to_RGB111110F: case RGB16F_to_RGB9E5: case RGB9E5: return false; default: if (colorFmt.isFloatingPont()) return caps.contains(Caps.FloatColorBuffer); return true; } } /** * Returns true if given the renderer capabilities, the framebuffer * can be supported by the renderer. * * @param caps The collection of renderer capabilities {@link Renderer#getCaps() }. * @param fb The framebuffer to check * @return True if it is supported, false otherwise. */ public static boolean supports(Collection<Caps> caps, FrameBuffer fb){ if (!caps.contains(Caps.FrameBuffer)) return false; if (fb.getSamples() > 1 && !caps.contains(Caps.FrameBufferMultisample)) return false; RenderBuffer depthBuf = fb.getDepthBuffer(); if (depthBuf != null){ Format depthFmt = depthBuf.getFormat(); if (!depthFmt.isDepthFormat()){ return false; }else{ if (depthFmt == Format.Depth32F && !caps.contains(Caps.FloatDepthBuffer)) return false; if (depthFmt == Format.Depth24Stencil8 && !caps.contains(Caps.PackedDepthStencilBuffer)) return false; } } for (int i = 0; i < fb.getNumColorBuffers(); i++){ if (!supportsColorBuffer(caps, fb.getColorBuffer(i))){ return false; } } return true; } /** * Returns true if given the renderer capabilities, the shader * can be supported by the renderer. * * @param caps The collection of renderer capabilities {@link Renderer#getCaps() }. * @param shader The shader to check * @return True if it is supported, false otherwise. */ public static boolean supports(Collection<Caps> caps, Shader shader){ for (ShaderSource source : shader.getSources()) { if (source.getLanguage().startsWith("GLSL")) { int ver = Integer.parseInt(source.getLanguage().substring(4)); switch (ver) { case 100: if (!caps.contains(Caps.GLSL100)) return false; case 110: if (!caps.contains(Caps.GLSL110)) return false; case 120: if (!caps.contains(Caps.GLSL120)) return false; case 130: if (!caps.contains(Caps.GLSL130)) return false; case 140: if (!caps.contains(Caps.GLSL140)) return false; case 150: if (!caps.contains(Caps.GLSL150)) return false; case 330: if (!caps.contains(Caps.GLSL330)) return false; default: return false; } } } return true; } }