LwjglRenderer - Preparing for abstraction layer shift

* All GL calls are done via static imports
 * Once again remove dependency on GL21 / GL30 - with the generator it will be possible to choose whether to target GL2+extensions or GL3 core
 * ContextCapabilities is field in Renderer, not allowed to use GLContext to retrieve it anymore
 * Assume depth textures are always supported (they should be since GL1.4)
experimental
shadowislord 11 years ago
parent 2e796444a5
commit 03f8df05b6
  1. 17
      jme3-lwjgl/src/main/java/com/jme3/renderer/lwjgl/LwjglGL1Renderer.java
  2. 141
      jme3-lwjgl/src/main/java/com/jme3/renderer/lwjgl/LwjglRenderer.java
  3. 320
      jme3-lwjgl/src/main/java/com/jme3/renderer/lwjgl/TextureUtil.java

@ -47,6 +47,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.NativeObjectManager; import com.jme3.util.NativeObjectManager;
import org.lwjgl.opengl.ContextCapabilities;
public class LwjglGL1Renderer implements GL1Renderer { public class LwjglGL1Renderer implements GL1Renderer {
@ -76,6 +77,8 @@ public class LwjglGL1Renderer implements GL1Renderer {
private ArrayList<Light> lightList = new ArrayList<Light>(8); private ArrayList<Light> lightList = new ArrayList<Light>(8);
private ColorRGBA materialAmbientColor = new ColorRGBA(); private ColorRGBA materialAmbientColor = new ColorRGBA();
private Vector3f tempVec = new Vector3f(); private Vector3f tempVec = new Vector3f();
private ContextCapabilities ctxCaps;
protected void updateNameBuffer() { protected void updateNameBuffer() {
int len = stringBuf.length(); int len = stringBuf.length();
@ -98,7 +101,9 @@ public class LwjglGL1Renderer implements GL1Renderer {
} }
public void initialize() { public void initialize() {
if (GLContext.getCapabilities().OpenGL12){ ctxCaps = GLContext.getCapabilities();
if (ctxCaps.OpenGL12){
gl12 = true; gl12 = true;
} }
@ -119,7 +124,7 @@ public class LwjglGL1Renderer implements GL1Renderer {
glEnable(GL_NORMALIZE); glEnable(GL_NORMALIZE);
} }
if (GLContext.getCapabilities().GL_ARB_texture_non_power_of_two) { if (ctxCaps.GL_ARB_texture_non_power_of_two) {
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 "
@ -753,7 +758,7 @@ public class LwjglGL1Renderer implements GL1Renderer {
} }
// Check sizes if graphics card doesn't support NPOT // Check sizes if graphics card doesn't support NPOT
if (!GLContext.getCapabilities().GL_ARB_texture_non_power_of_two && img.isNPOT()) { if (!ctxCaps.GL_ARB_texture_non_power_of_two && img.isNPOT()) {
// Resize texture to Power-of-2 size // Resize texture to Power-of-2 size
MipMapGenerator.resizeToPowerOf2(img); MipMapGenerator.resizeToPowerOf2(img);
} }
@ -763,7 +768,7 @@ public class LwjglGL1Renderer implements GL1Renderer {
// generate from base level if required // generate from base level if required
// Check if hardware mips are supported // Check if hardware mips are supported
if (GLContext.getCapabilities().OpenGL14) { if (ctxCaps.OpenGL14) {
glTexParameteri(target, GL14.GL_GENERATE_MIPMAP, GL_TRUE); glTexParameteri(target, GL14.GL_GENERATE_MIPMAP, GL_TRUE);
} else { } else {
MipMapGenerator.generateMipMaps(img); MipMapGenerator.generateMipMaps(img);
@ -797,7 +802,7 @@ public class LwjglGL1Renderer implements GL1Renderer {
TextureUtil.uploadTexture(img, target, i, 0, tdc); TextureUtil.uploadTexture(img, target, i, 0, tdc);
} }
} else {*/ } else {*/
TextureUtil.uploadTexture(img, target, 0, 0, false); TextureUtil.uploadTexture(ctxCaps, img, target, 0, 0, false);
//} //}
img.clearUpdateNeeded(); img.clearUpdateNeeded();
@ -848,7 +853,7 @@ public class LwjglGL1Renderer implements GL1Renderer {
public void modifyTexture(Texture tex, Image pixels, int x, int y) { public void modifyTexture(Texture tex, Image pixels, int x, int y) {
setTexture(0, tex); setTexture(0, tex);
TextureUtil.uploadSubTexture(pixels, convertTextureType(tex.getType()), 0, x, y, false); TextureUtil.uploadSubTexture(ctxCaps, pixels, convertTextureType(tex.getType()), 0, x, y, false);
} }
private void clearTextureUnits() { private void clearTextureUnits() {

@ -63,18 +63,30 @@ import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
import jme3tools.converters.MipMapGenerator; import jme3tools.converters.MipMapGenerator;
import jme3tools.shader.ShaderDebug; import jme3tools.shader.ShaderDebug;
import static org.lwjgl.opengl.ARBDrawInstanced.*;
import static org.lwjgl.opengl.ARBInstancedArrays.*;
import static org.lwjgl.opengl.ARBMultisample.*;
import static org.lwjgl.opengl.ARBTextureMultisample.*; import static org.lwjgl.opengl.ARBTextureMultisample.*;
import static org.lwjgl.opengl.ARBVertexArrayObject.*;
import org.lwjgl.opengl.ContextCapabilities;
import static org.lwjgl.opengl.EXTFramebufferBlit.*; import static org.lwjgl.opengl.EXTFramebufferBlit.*;
import static org.lwjgl.opengl.EXTFramebufferMultisample.*; import static org.lwjgl.opengl.EXTFramebufferMultisample.*;
import static org.lwjgl.opengl.EXTFramebufferObject.*; import static org.lwjgl.opengl.EXTFramebufferObject.*;
import static org.lwjgl.opengl.EXTFramebufferSRGB.*;
import static org.lwjgl.opengl.EXTGpuShader4.*;
import static org.lwjgl.opengl.EXTTextureArray.*;
import static org.lwjgl.opengl.EXTTextureFilterAnisotropic.*;
import static org.lwjgl.opengl.GL11.*; import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.opengl.GL12.*; import static org.lwjgl.opengl.GL12.*;
import static org.lwjgl.opengl.GL13.*; import static org.lwjgl.opengl.GL13.*;
import static org.lwjgl.opengl.GL14.*; import static org.lwjgl.opengl.GL14.*;
import static org.lwjgl.opengl.GL15.*; import static org.lwjgl.opengl.GL15.*;
import static org.lwjgl.opengl.GL20.*; import static org.lwjgl.opengl.GL20.*;
import org.lwjgl.opengl.*; import org.lwjgl.opengl.GLContext;
//import static org.lwjgl.opengl.ARBDrawInstanced.*; //import static org.lwjgl.opengl.GL21.*;
//import static org.lwjgl.opengl.GL30.*;
public class LwjglRenderer implements Renderer { public class LwjglRenderer implements Renderer {
@ -113,6 +125,7 @@ public class LwjglRenderer implements Renderer {
private int vpX, vpY, vpW, vpH; private int vpX, vpY, vpW, vpH;
private int clipX, clipY, clipW, clipH; private int clipX, clipY, clipW, clipH;
private boolean linearizeSrgbImages; private boolean linearizeSrgbImages;
private ContextCapabilities ctxCaps;
public LwjglRenderer() { public LwjglRenderer() {
} }
@ -141,7 +154,7 @@ public class LwjglRenderer implements Renderer {
@SuppressWarnings("fallthrough") @SuppressWarnings("fallthrough")
public void initialize() { public void initialize() {
ContextCapabilities ctxCaps = GLContext.getCapabilities(); ctxCaps = GLContext.getCapabilities();
if (ctxCaps.OpenGL20) { if (ctxCaps.OpenGL20) {
caps.add(Caps.OpenGL20); caps.add(Caps.OpenGL20);
if (ctxCaps.OpenGL21) { if (ctxCaps.OpenGL21) {
@ -371,24 +384,17 @@ public class LwjglRenderer implements Renderer {
caps.add(Caps.FrameBufferMRT); caps.add(Caps.FrameBufferMRT);
logger.log(Level.FINER, "FBO Max MRT renderbuffers: {0}", maxMRTFBOAttachs); logger.log(Level.FINER, "FBO Max MRT renderbuffers: {0}", maxMRTFBOAttachs);
} }
// if (ctxCaps.GL_ARB_draw_buffers) {
// caps.add(Caps.FrameBufferMRT);
// glGetInteger(ARBDrawBuffers.GL_MAX_DRAW_BUFFERS_ARB, intBuf16);
// maxMRTFBOAttachs = intBuf16.get(0);
// logger.log(Level.FINER, "FBO Max MRT renderbuffers: {0}", maxMRTFBOAttachs);
//}
} }
if (ctxCaps.GL_ARB_multisample) { if (ctxCaps.GL_ARB_multisample) {
glGetInteger(ARBMultisample.GL_SAMPLE_BUFFERS_ARB, intBuf16); glGetInteger(GL_SAMPLE_BUFFERS_ARB, intBuf16);
boolean available = intBuf16.get(0) != 0; boolean available = intBuf16.get(0) != 0;
glGetInteger(ARBMultisample.GL_SAMPLES_ARB, intBuf16); glGetInteger(GL_SAMPLES_ARB, intBuf16);
int samples = intBuf16.get(0); int samples = intBuf16.get(0);
logger.log(Level.FINER, "Samples: {0}", samples); logger.log(Level.FINER, "Samples: {0}", samples);
boolean enabled = glIsEnabled(ARBMultisample.GL_MULTISAMPLE_ARB); boolean enabled = glIsEnabled(GL_MULTISAMPLE_ARB);
if (samples > 0 && available && !enabled) { if (samples > 0 && available && !enabled) {
glEnable(ARBMultisample.GL_MULTISAMPLE_ARB); glEnable(GL_MULTISAMPLE_ARB);
} }
caps.add(Caps.Multisample); caps.add(Caps.Multisample);
} }
@ -472,11 +478,11 @@ public class LwjglRenderer implements Renderer {
} }
public void setAlphaToCoverage(boolean value) { public void setAlphaToCoverage(boolean value) {
if (caps.contains(Caps.Multisample)) { if (ctxCaps.GL_ARB_multisample) {
if (value) { if (value) {
glEnable(ARBMultisample.GL_SAMPLE_ALPHA_TO_COVERAGE_ARB); glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE_ARB);
} else { } else {
glDisable(ARBMultisample.GL_SAMPLE_ALPHA_TO_COVERAGE_ARB); glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE_ARB);
} }
} }
} }
@ -1068,12 +1074,12 @@ public class LwjglRenderer implements Renderer {
glAttachShader(id, source.getId()); glAttachShader(id, source.getId());
} }
if (caps.contains(Caps.OpenGL30)) { if (ctxCaps.GL_EXT_gpu_shader4) {
// Check if GLSL version is 1.5 for shader // Check if GLSL version is 1.5 for shader
GL30.glBindFragDataLocation(id, 0, "outFragColor"); glBindFragDataLocationEXT(id, 0, "outFragColor");
// For MRT // For MRT
for (int i = 0; i < maxMRTFBOAttachs; i++) { for (int i = 0; i < maxMRTFBOAttachs; i++) {
GL30.glBindFragDataLocation(id, i, "outFragData[" + i + "]"); glBindFragDataLocationEXT(id, i, "outFragData[" + i + "]");
} }
} }
@ -1178,7 +1184,7 @@ public class LwjglRenderer implements Renderer {
} }
public void copyFrameBuffer(FrameBuffer src, FrameBuffer dst, boolean copyDepth) { public void copyFrameBuffer(FrameBuffer src, FrameBuffer dst, boolean copyDepth) {
if (GLContext.getCapabilities().GL_EXT_framebuffer_blit) { if (ctxCaps.GL_EXT_framebuffer_blit) {
int srcX0 = 0; int srcX0 = 0;
int srcY0 = 0; int srcY0 = 0;
int srcX1; int srcX1;
@ -1310,8 +1316,8 @@ public class LwjglRenderer implements Renderer {
String readBuf = getTargetBufferName(glGetInteger(GL_READ_BUFFER)); String readBuf = getTargetBufferName(glGetInteger(GL_READ_BUFFER));
int fbId = fb.getId(); int fbId = fb.getId();
int curDrawBinding = glGetInteger(ARBFramebufferObject.GL_DRAW_FRAMEBUFFER_BINDING); int curDrawBinding = glGetInteger(GL_DRAW_FRAMEBUFFER_BINDING_EXT);
int curReadBinding = glGetInteger(ARBFramebufferObject.GL_READ_FRAMEBUFFER_BINDING); int curReadBinding = glGetInteger(GL_READ_FRAMEBUFFER_BINDING_EXT);
System.out.println("=== OpenGL FBO State ==="); System.out.println("=== OpenGL FBO State ===");
System.out.println("Context doublebuffered? " + doubleBuffer); System.out.println("Context doublebuffered? " + doubleBuffer);
@ -1384,9 +1390,9 @@ public class LwjglRenderer implements Renderer {
+ ":" + fb.getHeight() + " is not supported."); + ":" + fb.getHeight() + " is not supported.");
} }
TextureUtil.GLImageFormat glFmt = TextureUtil.getImageFormatWithError(rb.getFormat(), fb.isSrgb()); TextureUtil.GLImageFormat glFmt = TextureUtil.getImageFormatWithError(ctxCaps, rb.getFormat(), fb.isSrgb());
if (fb.getSamples() > 1 && GLContext.getCapabilities().GL_EXT_framebuffer_multisample) { if (fb.getSamples() > 1 && ctxCaps.GL_EXT_framebuffer_multisample) {
int samples = fb.getSamples(); int samples = fb.getSamples();
if (maxFBOSamples < samples) { if (maxFBOSamples < samples) {
samples = maxFBOSamples; samples = maxFBOSamples;
@ -1488,6 +1494,9 @@ public class LwjglRenderer implements Renderer {
if (fb.getSamples() <= 1) { if (fb.getSamples() <= 1) {
throw new IllegalArgumentException("Framebuffer must be multisampled"); throw new IllegalArgumentException("Framebuffer must be multisampled");
} }
if (!ctxCaps.GL_ARB_texture_multisample) {
throw new RendererException("Multisampled textures are not supported");
}
setFrameBuffer(fb); setFrameBuffer(fb);
@ -1507,6 +1516,11 @@ public class LwjglRenderer implements Renderer {
} }
public void setFrameBuffer(FrameBuffer fb) { public void setFrameBuffer(FrameBuffer fb) {
if (!ctxCaps.GL_EXT_framebuffer_object) {
throw new RendererException("Framebuffer objects are not supported" +
" by the video hardware");
}
if (fb == null && mainFbOverride != null) { if (fb == null && mainFbOverride != null) {
fb = mainFbOverride; fb = mainFbOverride;
} }
@ -1684,18 +1698,23 @@ public class LwjglRenderer 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 && !ctxCaps.GL_ARB_texture_multisample) {
throw new RendererException("Multisample textures are not supported" +
" by the video hardware.");
}
switch (type) { switch (type) {
case TwoDimensional: case TwoDimensional:
if (samples > 1) { if (samples > 1) {
return ARBTextureMultisample.GL_TEXTURE_2D_MULTISAMPLE; return GL_TEXTURE_2D_MULTISAMPLE;
} else { } else {
return GL_TEXTURE_2D; return GL_TEXTURE_2D;
} }
case TwoDimensionalArray: case TwoDimensionalArray:
if (samples > 1) { if (samples > 1) {
return ARBTextureMultisample.GL_TEXTURE_2D_MULTISAMPLE_ARRAY; return GL_TEXTURE_2D_MULTISAMPLE_ARRAY;
} else { } else {
return EXTTextureArray.GL_TEXTURE_2D_ARRAY_EXT; return GL_TEXTURE_2D_ARRAY_EXT;
} }
case ThreeDimensional: case ThreeDimensional:
return GL_TEXTURE_3D; return GL_TEXTURE_3D;
@ -1771,9 +1790,9 @@ public class LwjglRenderer implements Renderer {
glTexParameteri(target, GL_TEXTURE_MAG_FILTER, magFilter); glTexParameteri(target, GL_TEXTURE_MAG_FILTER, magFilter);
if (tex.getAnisotropicFilter() > 1) { if (tex.getAnisotropicFilter() > 1) {
if (GLContext.getCapabilities().GL_EXT_texture_filter_anisotropic) { if (ctxCaps.GL_EXT_texture_filter_anisotropic) {
glTexParameterf(target, glTexParameterf(target,
EXTTextureFilterAnisotropic.GL_TEXTURE_MAX_ANISOTROPY_EXT, GL_TEXTURE_MAX_ANISOTROPY_EXT,
tex.getAnisotropicFilter()); tex.getAnisotropicFilter());
} }
} }
@ -1853,7 +1872,7 @@ public class LwjglRenderer implements Renderer {
// Image does not have mipmaps, but they are required. // Image does not have mipmaps, but they are required.
// Generate from base level. // Generate from base level.
if (!GLContext.getCapabilities().OpenGL30) { if (!ctxCaps.OpenGL30) {
glTexParameteri(target, GL_GENERATE_MIPMAP, GL_TRUE); glTexParameteri(target, GL_GENERATE_MIPMAP, GL_TRUE);
img.setMipmapsGenerated(true); img.setMipmapsGenerated(true);
} else { } else {
@ -1880,7 +1899,7 @@ public class LwjglRenderer implements Renderer {
} }
// Yes, some OpenGL2 cards (GeForce 5) still dont support NPOT. // Yes, some OpenGL2 cards (GeForce 5) still dont support NPOT.
if (!GLContext.getCapabilities().GL_ARB_texture_non_power_of_two && img.isNPOT()) { if (!ctxCaps.GL_ARB_texture_non_power_of_two && img.isNPOT()) {
if (img.getData(0) == null) { if (img.getData(0) == null) {
throw new RendererException("non-power-of-2 framebuffer textures are not supported by the video hardware"); throw new RendererException("non-power-of-2 framebuffer textures are not supported by the video hardware");
} else { } else {
@ -1889,7 +1908,7 @@ public class LwjglRenderer implements Renderer {
} }
// Check if graphics card doesn't support multisample textures // Check if graphics card doesn't support multisample textures
if (!GLContext.getCapabilities().GL_ARB_texture_multisample) { if (!ctxCaps.GL_ARB_texture_multisample) {
if (img.getMultiSamples() > 1) { if (img.getMultiSamples() > 1) {
throw new RendererException("Multisample textures not supported by graphics hardware"); throw new RendererException("Multisample textures not supported by graphics hardware");
} }
@ -1914,9 +1933,9 @@ public class LwjglRenderer implements Renderer {
return; return;
} }
for (int i = 0; i < 6; i++) { for (int i = 0; i < 6; i++) {
TextureUtil.uploadTexture(img, GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, i, 0, linearizeSrgbImages); TextureUtil.uploadTexture(ctxCaps, img, GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, i, 0, linearizeSrgbImages);
} }
} else if (target == EXTTextureArray.GL_TEXTURE_2D_ARRAY_EXT) { } else if (target == 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");
} }
@ -1924,22 +1943,22 @@ public class LwjglRenderer implements Renderer {
List<ByteBuffer> data = img.getData(); List<ByteBuffer> data = img.getData();
// -1 index specifies prepare data for 2D Array // -1 index specifies prepare data for 2D Array
TextureUtil.uploadTexture(img, target, -1, 0, linearizeSrgbImages); TextureUtil.uploadTexture(ctxCaps, img, target, -1, 0, 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
TextureUtil.uploadTexture(img, target, i, 0, linearizeSrgbImages); TextureUtil.uploadTexture(ctxCaps, img, target, i, 0, linearizeSrgbImages);
} }
} else { } else {
TextureUtil.uploadTexture(img, target, 0, 0, linearizeSrgbImages); TextureUtil.uploadTexture(ctxCaps, img, target, 0, 0, linearizeSrgbImages);
} }
if (img.getMultiSamples() != imageSamples) { if (img.getMultiSamples() != imageSamples) {
img.setMultiSamples(imageSamples); img.setMultiSamples(imageSamples);
} }
if (GLContext.getCapabilities().OpenGL30) { if (ctxCaps.OpenGL30) {
if (!img.hasMipmaps() && img.isGeneratedMipmapsRequired() && img.getData() != null) { if (!img.hasMipmaps() && img.isGeneratedMipmapsRequired() && img.getData() != null) {
// XXX: Required for ATI // XXX: Required for ATI
glEnable(target); glEnable(target);
@ -1990,7 +2009,7 @@ public class LwjglRenderer implements Renderer {
public void modifyTexture(Texture tex, Image pixels, int x, int y) { public void modifyTexture(Texture tex, Image pixels, int x, int y) {
setTexture(0, tex); setTexture(0, tex);
TextureUtil.uploadSubTexture(pixels, convertTextureType(tex.getType(), pixels.getMultiSamples(), -1), 0, x, y, linearizeSrgbImages); TextureUtil.uploadSubTexture(ctxCaps, pixels, convertTextureType(tex.getType(), pixels.getMultiSamples(), -1), 0, x, y, linearizeSrgbImages);
} }
public void clearTextureUnits() { public void clearTextureUnits() {
@ -2050,9 +2069,6 @@ public class LwjglRenderer implements Renderer {
return GL_INT; return GL_INT;
case UnsignedInt: case UnsignedInt:
return GL_UNSIGNED_INT; return GL_UNSIGNED_INT;
// case Half:
// return NVHalfFloat.GL_HALF_FLOAT_NV;
// return ARBHalfFloatVertex.GL_HALF_FLOAT;
case Float: case Float:
return GL_FLOAT; return GL_FLOAT;
case Double: case Double:
@ -2175,7 +2191,7 @@ public class LwjglRenderer implements Renderer {
int idx = attribList.oldList[i]; int idx = attribList.oldList[i];
glDisableVertexAttribArray(idx); glDisableVertexAttribArray(idx);
if (context.boundAttribs[idx].isInstanced()) { if (context.boundAttribs[idx].isInstanced()) {
ARBInstancedArrays.glVertexAttribDivisorARB(idx, 0); glVertexAttribDivisorARB(idx, 0);
} }
context.boundAttribs[idx] = null; context.boundAttribs[idx] = null;
} }
@ -2212,8 +2228,8 @@ public class LwjglRenderer implements Renderer {
int slotsRequired = 1; int slotsRequired = 1;
if (vb.isInstanced()) { if (vb.isInstanced()) {
if (!GLContext.getCapabilities().GL_ARB_instanced_arrays if (!ctxCaps.GL_ARB_instanced_arrays
|| !GLContext.getCapabilities().GL_ARB_draw_instanced) { || !ctxCaps.GL_ARB_draw_instanced) {
throw new RendererException("Instancing is required, " throw new RendererException("Instancing is required, "
+ "but not supported by the " + "but not supported by the "
+ "graphics hardware"); + "graphics hardware");
@ -2278,10 +2294,10 @@ public class LwjglRenderer implements Renderer {
int slot = loc + i; int slot = loc + i;
if (vb.isInstanced() && (attribs[slot] == null || !attribs[slot].isInstanced())) { if (vb.isInstanced() && (attribs[slot] == null || !attribs[slot].isInstanced())) {
// non-instanced -> instanced // non-instanced -> instanced
ARBInstancedArrays.glVertexAttribDivisorARB(slot, 1); glVertexAttribDivisorARB(slot, 1);
} else if (!vb.isInstanced() && attribs[slot] != null && attribs[slot].isInstanced()) { } else if (!vb.isInstanced() && attribs[slot] != null && attribs[slot].isInstanced()) {
// instanced -> non-instanced // instanced -> non-instanced
ARBInstancedArrays.glVertexAttribDivisorARB(slot, 0); glVertexAttribDivisorARB(slot, 0);
} }
attribs[slot] = vb; attribs[slot] = vb;
} }
@ -2298,7 +2314,7 @@ public class LwjglRenderer implements Renderer {
public void drawTriangleArray(Mesh.Mode mode, int count, int vertCount) { public void drawTriangleArray(Mesh.Mode mode, int count, int vertCount) {
boolean useInstancing = count > 1 && caps.contains(Caps.MeshInstancing); boolean useInstancing = count > 1 && caps.contains(Caps.MeshInstancing);
if (useInstancing) { if (useInstancing) {
ARBDrawInstanced.glDrawArraysInstancedARB(convertElementMode(mode), 0, glDrawArraysInstancedARB(convertElementMode(mode), 0,
vertCount, count); vertCount, count);
} else { } else {
glDrawArrays(convertElementMode(mode), 0, vertCount); glDrawArrays(convertElementMode(mode), 0, vertCount);
@ -2348,7 +2364,7 @@ public class LwjglRenderer implements Renderer {
int elementLength = elementLengths[i]; int elementLength = elementLengths[i];
if (useInstancing) { if (useInstancing) {
ARBDrawInstanced.glDrawElementsInstancedARB(elMode, glDrawElementsInstancedARB(elMode,
elementLength, elementLength,
fmt, fmt,
curOffset, curOffset,
@ -2366,7 +2382,7 @@ public class LwjglRenderer implements Renderer {
} }
} else { } else {
if (useInstancing) { if (useInstancing) {
ARBDrawInstanced.glDrawElementsInstancedARB(convertElementMode(mesh.getMode()), glDrawElementsInstancedARB(convertElementMode(mesh.getMode()),
indexBuf.getData().limit(), indexBuf.getData().limit(),
convertFormat(indexBuf.getFormat()), convertFormat(indexBuf.getFormat()),
0, 0,
@ -2410,13 +2426,13 @@ public class LwjglRenderer implements Renderer {
int id = mesh.getId(); int id = mesh.getId();
if (id == -1) { if (id == -1) {
IntBuffer temp = intBuf1; IntBuffer temp = intBuf1;
ARBVertexArrayObject.glGenVertexArrays(temp); glGenVertexArrays(temp);
id = temp.get(0); id = temp.get(0);
mesh.setId(id); mesh.setId(id);
} }
if (context.boundVertexArray != id) { if (context.boundVertexArray != id) {
ARBVertexArrayObject.glBindVertexArray(id); glBindVertexArray(id);
context.boundVertexArray = id; context.boundVertexArray = id;
} }
@ -2454,7 +2470,7 @@ public class LwjglRenderer implements Renderer {
} }
if (context.boundVertexArray != mesh.getId()) { if (context.boundVertexArray != mesh.getId()) {
ARBVertexArrayObject.glBindVertexArray(mesh.getId()); glBindVertexArray(mesh.getId());
context.boundVertexArray = mesh.getId(); context.boundVertexArray = mesh.getId();
} }
@ -2546,7 +2562,7 @@ public class LwjglRenderer implements Renderer {
} }
statistics.onMeshDrawn(mesh, lod, count); statistics.onMeshDrawn(mesh, lod, count);
// if (GLContext.getCapabilities().GL_ARB_vertex_array_object){ // if (ctxCaps.GL_ARB_vertex_array_object){
// renderMeshVertexArray(mesh, lod, count); // renderMeshVertexArray(mesh, lod, count);
// }else{ // }else{
renderMeshDefault(mesh, lod, count, instanceData); renderMeshDefault(mesh, lod, count, instanceData);
@ -2568,25 +2584,18 @@ public class LwjglRenderer implements Renderer {
setFrameBuffer(null); setFrameBuffer(null);
if (enableSrgb) { if (enableSrgb) {
if (!glGetBoolean(GL30.GL_FRAMEBUFFER_SRGB_CAPABLE)) { if (!glGetBoolean(GL_FRAMEBUFFER_SRGB_CAPABLE_EXT)) {
logger.warning("Driver claims that default framebuffer " logger.warning("Driver claims that default framebuffer "
+ "is not sRGB capable. Enabling anyway."); + "is not sRGB capable. Enabling anyway.");
} }
int encoding = GL30.glGetFramebufferAttachmentParameteri(GL30.GL_DRAW_FRAMEBUFFER,
GL_FRONT_LEFT,
GL30.GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING);
if (encoding != GL21.GL_SRGB) {
logger.warning("Driver claims that default framebuffer "
+ "is not using sRGB color encoding. Enabling anyway.");
}
glEnable(GL30.GL_FRAMEBUFFER_SRGB); glEnable(GL_FRAMEBUFFER_SRGB_EXT);
logger.log(Level.FINER, "SRGB FrameBuffer enabled (Gamma Correction)"); logger.log(Level.FINER, "SRGB FrameBuffer enabled (Gamma Correction)");
} else { } else {
glDisable(GL30.GL_FRAMEBUFFER_SRGB); glDisable(GL_FRAMEBUFFER_SRGB_EXT);
} }
} }

@ -39,20 +39,23 @@ import com.jme3.texture.image.ColorSpace;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
import org.lwjgl.opengl.ARBTextureFloat; import static org.lwjgl.opengl.ARBDepthBufferFloat.*;
import org.lwjgl.opengl.ARBTextureMultisample; import static org.lwjgl.opengl.ARBHalfFloatPixel.*;
import static org.lwjgl.opengl.ARBTextureFloat.*;
import static org.lwjgl.opengl.ARBTextureMultisample.*;
import org.lwjgl.opengl.ContextCapabilities; import org.lwjgl.opengl.ContextCapabilities;
import org.lwjgl.opengl.EXTTextureArray; import static org.lwjgl.opengl.EXTPackedDepthStencil.*;
import org.lwjgl.opengl.EXTTextureCompressionLATC; import static org.lwjgl.opengl.EXTPackedFloat.*;
import org.lwjgl.opengl.EXTTextureCompressionS3TC; import static org.lwjgl.opengl.EXTTextureArray.*;
import org.lwjgl.opengl.EXTTextureSRGB; import static org.lwjgl.opengl.EXTTextureCompressionLATC.*;
import org.lwjgl.opengl.GL11; import static org.lwjgl.opengl.EXTTextureCompressionS3TC.*;
import org.lwjgl.opengl.GL12; import static org.lwjgl.opengl.EXTTextureSRGB.*;
import org.lwjgl.opengl.GL13; import static org.lwjgl.opengl.EXTTextureSharedExponent.*;
import org.lwjgl.opengl.GL14; import static org.lwjgl.opengl.GL11.*;
import org.lwjgl.opengl.GL21; import static org.lwjgl.opengl.GL12.*;
import org.lwjgl.opengl.GL30; import static org.lwjgl.opengl.GL13.*;
import org.lwjgl.opengl.GLContext; import static org.lwjgl.opengl.GL14.*;
import static org.lwjgl.opengl.GL20.*;
class TextureUtil { class TextureUtil {
@ -79,80 +82,80 @@ class TextureUtil {
static { static {
// Alpha formats // Alpha formats
setFormat(Format.Alpha8, GL11.GL_ALPHA8, GL11.GL_ALPHA, GL11.GL_UNSIGNED_BYTE, false); setFormat(Format.Alpha8, GL_ALPHA8, GL_ALPHA, GL_UNSIGNED_BYTE, false);
setFormat(Format.Alpha16, GL11.GL_ALPHA16, GL11.GL_ALPHA, GL11.GL_UNSIGNED_SHORT, false); setFormat(Format.Alpha16, GL_ALPHA16, GL_ALPHA, GL_UNSIGNED_SHORT, false);
// Luminance formats // Luminance formats
setFormat(Format.Luminance8, GL11.GL_LUMINANCE8, GL11.GL_LUMINANCE, GL11.GL_UNSIGNED_BYTE, false); setFormat(Format.Luminance8, GL_LUMINANCE8, GL_LUMINANCE, GL_UNSIGNED_BYTE, false);
setFormat(Format.Luminance16, GL11.GL_LUMINANCE16, GL11.GL_LUMINANCE, GL11.GL_UNSIGNED_SHORT, false); setFormat(Format.Luminance16, GL_LUMINANCE16, GL_LUMINANCE, GL_UNSIGNED_SHORT, false);
setFormat(Format.Luminance16F, ARBTextureFloat.GL_LUMINANCE16F_ARB, GL11.GL_LUMINANCE, GL30.GL_HALF_FLOAT, false); setFormat(Format.Luminance16F, GL_LUMINANCE16F_ARB, GL_LUMINANCE, GL_HALF_FLOAT_ARB, false);
setFormat(Format.Luminance32F, ARBTextureFloat.GL_LUMINANCE32F_ARB, GL11.GL_LUMINANCE, GL11.GL_FLOAT, false); setFormat(Format.Luminance32F, GL_LUMINANCE32F_ARB, GL_LUMINANCE, GL_FLOAT, false);
// Luminance alpha formats // Luminance alpha formats
setFormat(Format.Luminance8Alpha8, GL11.GL_LUMINANCE8_ALPHA8, GL11.GL_LUMINANCE_ALPHA, GL11.GL_UNSIGNED_BYTE, false); setFormat(Format.Luminance8Alpha8, GL_LUMINANCE8_ALPHA8, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, false);
setFormat(Format.Luminance16Alpha16, GL11.GL_LUMINANCE16_ALPHA16, GL11.GL_LUMINANCE_ALPHA, GL11.GL_UNSIGNED_SHORT, false); setFormat(Format.Luminance16Alpha16, GL_LUMINANCE16_ALPHA16, GL_LUMINANCE_ALPHA, GL_UNSIGNED_SHORT, false);
setFormat(Format.Luminance16FAlpha16F, ARBTextureFloat.GL_LUMINANCE_ALPHA16F_ARB, GL11.GL_LUMINANCE_ALPHA, GL30.GL_HALF_FLOAT, false); setFormat(Format.Luminance16FAlpha16F, GL_LUMINANCE_ALPHA16F_ARB, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT_ARB, false);
// Depth formats // Depth formats
setFormat(Format.Depth, GL11.GL_DEPTH_COMPONENT, GL11.GL_DEPTH_COMPONENT, GL11.GL_UNSIGNED_BYTE, false); setFormat(Format.Depth, GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, false);
setFormat(Format.Depth16, GL14.GL_DEPTH_COMPONENT16, GL11.GL_DEPTH_COMPONENT, GL11.GL_UNSIGNED_SHORT, false); setFormat(Format.Depth16, GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, false);
setFormat(Format.Depth24, GL14.GL_DEPTH_COMPONENT24, GL11.GL_DEPTH_COMPONENT, GL11.GL_UNSIGNED_INT, false); setFormat(Format.Depth24, GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, false);
setFormat(Format.Depth32, GL14.GL_DEPTH_COMPONENT32, GL11.GL_DEPTH_COMPONENT, GL11.GL_UNSIGNED_INT, false); setFormat(Format.Depth32, GL_DEPTH_COMPONENT32, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, false);
setFormat(Format.Depth32F, GL30.GL_DEPTH_COMPONENT32F, GL11.GL_DEPTH_COMPONENT, GL11.GL_FLOAT, false); setFormat(Format.Depth32F, GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, GL_FLOAT, false);
// Depth stencil formats // Depth stencil formats
setFormat(Format.Depth24Stencil8, GL30.GL_DEPTH24_STENCIL8, GL30.GL_DEPTH_STENCIL, GL30.GL_UNSIGNED_INT_24_8, false); setFormat(Format.Depth24Stencil8, GL_DEPTH24_STENCIL8_EXT, GL_DEPTH_STENCIL_EXT, GL_UNSIGNED_INT_24_8_EXT, false);
// RGB formats // RGB formats
setFormat(Format.BGR8, GL11.GL_RGB8, GL12.GL_BGR, GL11.GL_UNSIGNED_BYTE, false); setFormat(Format.BGR8, GL_RGB8, GL_BGR, GL_UNSIGNED_BYTE, false);
setFormat(Format.ARGB8, GL11.GL_RGBA8, GL12.GL_BGRA, GL12.GL_UNSIGNED_INT_8_8_8_8, false); setFormat(Format.ARGB8, GL_RGBA8, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8, false);
setFormat(Format.BGRA8, GL11.GL_RGBA8, GL12.GL_BGRA, GL11.GL_UNSIGNED_BYTE, false); setFormat(Format.BGRA8, GL_RGBA8, GL_BGRA, GL_UNSIGNED_BYTE, false);
setFormat(Format.RGB8, GL11.GL_RGB8, GL11.GL_RGB, GL11.GL_UNSIGNED_BYTE, false); setFormat(Format.RGB8, GL_RGB8, GL_RGB, GL_UNSIGNED_BYTE, false);
// setFormat(Format.RGB10, GL11.GL_RGB10, GL11.GL_RGB, GL12.GL_UNSIGNED_INT_10_10_10_2, false); // setFormat(Format.RGB10, GL_RGB10, GL_RGB, GL_UNSIGNED_INT_10_10_10_2, false);
setFormat(Format.RGB16, GL11.GL_RGB16, GL11.GL_RGB, GL11.GL_UNSIGNED_SHORT, false); setFormat(Format.RGB16, GL_RGB16, GL_RGB, GL_UNSIGNED_SHORT, false);
setFormat(Format.RGB16F, GL30.GL_RGB16F, GL11.GL_RGB, GL30.GL_HALF_FLOAT, false); setFormat(Format.RGB16F, GL_RGB16F_ARB, GL_RGB, GL_HALF_FLOAT_ARB, false);
setFormat(Format.RGB32F, GL30.GL_RGB32F, GL11.GL_RGB, GL11.GL_FLOAT, false); setFormat(Format.RGB32F, GL_RGB32F_ARB, GL_RGB, GL_FLOAT, false);
// Special RGB formats // Special RGB formats
setFormat(Format.RGB111110F, GL30.GL_R11F_G11F_B10F, GL11.GL_RGB, GL30.GL_UNSIGNED_INT_10F_11F_11F_REV, false); setFormat(Format.RGB111110F, GL_R11F_G11F_B10F_EXT, GL_RGB, GL_UNSIGNED_INT_10F_11F_11F_REV_EXT, false);
setFormat(Format.RGB9E5, GL30.GL_RGB9_E5, GL11.GL_RGB, GL30.GL_UNSIGNED_INT_5_9_9_9_REV, false); setFormat(Format.RGB9E5, GL_RGB9_E5_EXT, GL_RGB, GL_UNSIGNED_INT_5_9_9_9_REV_EXT, false);
setFormat(Format.RGB16F_to_RGB111110F, GL30.GL_R11F_G11F_B10F, GL11.GL_RGB, GL30.GL_HALF_FLOAT, false); setFormat(Format.RGB16F_to_RGB111110F, GL_R11F_G11F_B10F_EXT, GL_RGB, GL_HALF_FLOAT_ARB, false);
setFormat(Format.RGB16F_to_RGB9E5, GL30.GL_RGB9_E5, GL11.GL_RGB, GL30.GL_HALF_FLOAT, false); setFormat(Format.RGB16F_to_RGB9E5, GL_RGB9_E5_EXT, GL_RGB, GL_HALF_FLOAT_ARB, false);
setFormat(Format.RGB10_A2, GL11.GL_RGB10_A2, GL11.GL_RGBA, GL12.GL_UNSIGNED_INT_10_10_10_2, false); setFormat(Format.RGB10_A2, GL_RGB10_A2, GL_RGBA, GL_UNSIGNED_INT_10_10_10_2, false);
// RGBA formats // RGBA formats
setFormat(Format.ABGR8, GL11.GL_RGBA8, GL11.GL_RGBA, GL12.GL_UNSIGNED_INT_8_8_8_8, false); setFormat(Format.ABGR8, GL_RGBA8, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, false);
setFormat(Format.RGB5A1, GL11.GL_RGB5_A1, GL11.GL_RGBA, GL12.GL_UNSIGNED_SHORT_5_5_5_1, false); setFormat(Format.RGB5A1, GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, false);
setFormat(Format.ARGB4444,GL11.GL_RGBA4, GL11.GL_RGBA, GL12.GL_UNSIGNED_SHORT_4_4_4_4_REV, false); setFormat(Format.ARGB4444,GL_RGBA4, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4_REV, false);
setFormat(Format.RGBA8, GL11.GL_RGBA8, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, false); setFormat(Format.RGBA8, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, false);
setFormat(Format.RGBA16, GL11.GL_RGBA16, GL11.GL_RGBA, GL11.GL_UNSIGNED_SHORT, false); // might be incorrect setFormat(Format.RGBA16, GL_RGBA16, GL_RGBA, GL_UNSIGNED_SHORT, false); // might be incorrect
setFormat(Format.RGBA16F, GL30.GL_RGBA16F, GL11.GL_RGBA, GL30.GL_HALF_FLOAT, false); setFormat(Format.RGBA16F, GL_RGBA16F_ARB, GL_RGBA, GL_HALF_FLOAT_ARB, false);
setFormat(Format.RGBA32F, GL30.GL_RGBA32F, GL11.GL_RGBA, GL11.GL_FLOAT, false); setFormat(Format.RGBA32F, GL_RGBA32F_ARB, GL_RGBA, GL_FLOAT, false);
// DXT formats // DXT formats
setFormat(Format.DXT1, EXTTextureCompressionS3TC.GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL11.GL_RGB, GL11.GL_UNSIGNED_BYTE, true); setFormat(Format.DXT1, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_RGB, GL_UNSIGNED_BYTE, true);
setFormat(Format.DXT1A, EXTTextureCompressionS3TC.GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, true); setFormat(Format.DXT1A, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_RGBA, GL_UNSIGNED_BYTE, true);
setFormat(Format.DXT3, EXTTextureCompressionS3TC.GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, true); setFormat(Format.DXT3, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, GL_RGBA, GL_UNSIGNED_BYTE, true);
setFormat(Format.DXT5, EXTTextureCompressionS3TC.GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, true); setFormat(Format.DXT5, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, GL_RGBA, GL_UNSIGNED_BYTE, true);
// LTC/LATC/3Dc formats // LTC/LATC/3Dc formats
setFormat(Format.LTC, EXTTextureCompressionLATC.GL_COMPRESSED_LUMINANCE_LATC1_EXT, GL11.GL_LUMINANCE, GL11.GL_UNSIGNED_BYTE, true); setFormat(Format.LTC, GL_COMPRESSED_LUMINANCE_LATC1_EXT, GL_LUMINANCE, GL_UNSIGNED_BYTE, true);
setFormat(Format.LATC, EXTTextureCompressionLATC.GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT, GL11.GL_LUMINANCE_ALPHA, GL11.GL_UNSIGNED_BYTE, true); setFormat(Format.LATC, GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, true);
} }
//sRGB formats //sRGB formats
private static final GLImageFormat sRGB_RGB8 = new GLImageFormat(GL21.GL_SRGB8, GL11.GL_RGB, GL11.GL_UNSIGNED_BYTE, false); private static final GLImageFormat sRGB_RGB8 = new GLImageFormat(GL_SRGB8_EXT, GL_RGB, GL_UNSIGNED_BYTE, false);
private static final GLImageFormat sRGB_RGBA8 = new GLImageFormat(GL21.GL_SRGB8_ALPHA8, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, false); private static final GLImageFormat sRGB_RGBA8 = new GLImageFormat(GL_SRGB8_ALPHA8_EXT, GL_RGBA, GL_UNSIGNED_BYTE, false);
private static final GLImageFormat sRGB_Luminance8 = new GLImageFormat(GL21.GL_SLUMINANCE8, GL11.GL_LUMINANCE, GL11.GL_UNSIGNED_BYTE, false); private static final GLImageFormat sRGB_Luminance8 = new GLImageFormat(GL_SLUMINANCE8_EXT, GL_LUMINANCE, GL_UNSIGNED_BYTE, false);
private static final GLImageFormat sRGB_LuminanceAlpha8 = new GLImageFormat(GL21.GL_SLUMINANCE8_ALPHA8, GL11.GL_LUMINANCE_ALPHA, GL11.GL_UNSIGNED_BYTE, false); private static final GLImageFormat sRGB_LuminanceAlpha8 = new GLImageFormat(GL_SLUMINANCE8_ALPHA8_EXT, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, false);
private static final GLImageFormat sRGB_BGR8 = new GLImageFormat(GL21.GL_SRGB8, GL12.GL_BGR, GL11.GL_UNSIGNED_BYTE, false); private static final GLImageFormat sRGB_BGR8 = new GLImageFormat(GL_SRGB8_EXT, GL_BGR, GL_UNSIGNED_BYTE, false);
private static final GLImageFormat sRGB_ABGR8 = new GLImageFormat(GL21.GL_SRGB8_ALPHA8, GL11.GL_RGBA, GL12.GL_UNSIGNED_INT_8_8_8_8, false); private static final GLImageFormat sRGB_ABGR8 = new GLImageFormat(GL_SRGB8_ALPHA8_EXT, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, false);
private static final GLImageFormat sRGB_ARGB8 = new GLImageFormat(GL21.GL_SRGB8_ALPHA8, GL12.GL_BGRA, GL12.GL_UNSIGNED_INT_8_8_8_8, false); private static final GLImageFormat sRGB_ARGB8 = new GLImageFormat(GL_SRGB8_ALPHA8_EXT, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8, false);
private static final GLImageFormat sRGB_BGRA8 = new GLImageFormat(GL21.GL_SRGB8_ALPHA8, GL12.GL_BGRA, GL11.GL_UNSIGNED_BYTE, false); private static final GLImageFormat sRGB_BGRA8 = new GLImageFormat(GL_SRGB8_ALPHA8_EXT, GL_BGRA, GL_UNSIGNED_BYTE, false);
private static final GLImageFormat sRGB_DXT1 = new GLImageFormat(EXTTextureSRGB.GL_COMPRESSED_SRGB_S3TC_DXT1_EXT,GL11.GL_RGB, GL11.GL_UNSIGNED_BYTE, true); private static final GLImageFormat sRGB_DXT1 = new GLImageFormat(GL_COMPRESSED_SRGB_S3TC_DXT1_EXT,GL_RGB, GL_UNSIGNED_BYTE, true);
private static final GLImageFormat sRGB_DXT1A = new GLImageFormat(EXTTextureSRGB.GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, true); private static final GLImageFormat sRGB_DXT1A = new GLImageFormat(GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT, GL_RGBA, GL_UNSIGNED_BYTE, true);
private static final GLImageFormat sRGB_DXT3 = new GLImageFormat(EXTTextureSRGB.GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, true); private static final GLImageFormat sRGB_DXT3 = new GLImageFormat(GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT, GL_RGBA, GL_UNSIGNED_BYTE, true);
private static final GLImageFormat sRGB_DXT5 = new GLImageFormat(EXTTextureSRGB.GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, true); private static final GLImageFormat sRGB_DXT5 = new GLImageFormat(GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, GL_RGBA, GL_UNSIGNED_BYTE, true);
public static GLImageFormat getImageFormat(ContextCapabilities caps, Format fmt, boolean isSrgb){ public static GLImageFormat getImageFormat(ContextCapabilities caps, Format fmt, boolean isSrgb){
switch (fmt){ switch (fmt){
@ -164,14 +167,6 @@ class TextureUtil {
return null; return null;
} }
break; break;
case Depth:
case Depth16:
case Depth24:
case Depth32:
if (!caps.OpenGL14 && !caps.GL_ARB_depth_texture){
return null;
}
break;
case Depth24Stencil8: case Depth24Stencil8:
if (!caps.OpenGL30 && !caps.GL_EXT_packed_depth_stencil){ if (!caps.OpenGL30 && !caps.GL_EXT_packed_depth_stencil){
return null; return null;
@ -219,8 +214,8 @@ class TextureUtil {
} }
} }
public static GLImageFormat getImageFormatWithError(Format fmt, boolean isSrgb) { public static GLImageFormat getImageFormatWithError(ContextCapabilities caps, Format fmt, boolean isSrgb) {
GLImageFormat glFmt = getImageFormat(GLContext.getCapabilities(), fmt, isSrgb); GLImageFormat glFmt = getImageFormat(caps, fmt, isSrgb);
if (glFmt == null) { if (glFmt == null) {
throw new RendererException("Image format '" + fmt + "' is unsupported by the video hardware."); throw new RendererException("Image format '" + fmt + "' is unsupported by the video hardware.");
} }
@ -259,14 +254,15 @@ class TextureUtil {
} }
} }
public static void uploadTexture(Image image, public static void uploadTexture(ContextCapabilities caps,
Image image,
int target, int target,
int index, int index,
int border, int border,
boolean linearizeSrgb){ boolean linearizeSrgb){
Image.Format fmt = image.getFormat(); Image.Format fmt = image.getFormat();
GLImageFormat glFmt = getImageFormatWithError(fmt, image.getColorSpace() == ColorSpace.sRGB && linearizeSrgb); GLImageFormat glFmt = getImageFormatWithError(caps, fmt, image.getColorSpace() == ColorSpace.sRGB && linearizeSrgb);
ByteBuffer data; ByteBuffer data;
if (index >= 0 && image.getData() != null && image.getData().size() > 0){ if (index >= 0 && image.getData() != null && image.getData().size() > 0){
@ -280,7 +276,7 @@ class TextureUtil {
int depth = image.getDepth(); int depth = image.getDepth();
if (data != null) { if (data != null) {
GL11.glPixelStorei(GL11.GL_UNPACK_ALIGNMENT, 1); glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
} }
int[] mipSizes = image.getMipMapSizes(); int[] mipSizes = image.getMipMapSizes();
@ -307,63 +303,63 @@ class TextureUtil {
} }
if (glFmt.compressed && data != null){ if (glFmt.compressed && data != null){
if (target == GL12.GL_TEXTURE_3D){ if (target == GL_TEXTURE_3D){
GL13.glCompressedTexImage3D(target, glCompressedTexImage3D(target,
i, i,
glFmt.internalFormat, glFmt.internalFormat,
mipWidth, mipWidth,
mipHeight, mipHeight,
mipDepth, mipDepth,
border, border,
data); data);
}else{ }else{
//all other targets use 2D: array, cubemap, 2d //all other targets use 2D: array, cubemap, 2d
GL13.glCompressedTexImage2D(target, glCompressedTexImage2D(target,
i, i,
glFmt.internalFormat, glFmt.internalFormat,
mipWidth, mipWidth,
mipHeight, mipHeight,
border, border,
data); data);
} }
}else{ }else{
if (target == GL12.GL_TEXTURE_3D){ if (target == GL_TEXTURE_3D){
GL12.glTexImage3D(target, glTexImage3D(target,
i, i,
glFmt.internalFormat, glFmt.internalFormat,
mipWidth, mipWidth,
mipHeight, mipHeight,
mipDepth, mipDepth,
border, border,
glFmt.format, glFmt.format,
glFmt.dataType, glFmt.dataType,
data); data);
}else if (target == EXTTextureArray.GL_TEXTURE_2D_ARRAY_EXT){ }else if (target == GL_TEXTURE_2D_ARRAY_EXT){
// prepare data for 2D array // prepare data for 2D array
// or upload slice // or upload slice
if (index == -1){ if (index == -1){
GL12.glTexImage3D(target, glTexImage3D(target,
i, i,
glFmt.internalFormat, glFmt.internalFormat,
mipWidth, mipWidth,
mipHeight, mipHeight,
image.getData().size(), //# of slices image.getData().size(), //# of slices
border, border,
glFmt.format, glFmt.format,
glFmt.dataType, glFmt.dataType,
data); data);
}else{ }else{
GL12.glTexSubImage3D(target, glTexSubImage3D(target,
i, // level i, // level
0, // xoffset 0, // xoffset
0, // yoffset 0, // yoffset
index, // zoffset index, // zoffset
width, // width width, // width
height, // height height, // height
1, // depth 1, // depth
glFmt.format, glFmt.format,
glFmt.dataType, glFmt.dataType,
data); data);
} }
}else{ }else{
if (subtex){ if (subtex){
@ -371,31 +367,31 @@ class TextureUtil {
throw new IllegalStateException("Cannot update multisample textures"); throw new IllegalStateException("Cannot update multisample textures");
} }
GL11.glTexSubImage2D(target, glTexSubImage2D(target,
i, i,
0, 0, 0, 0,
mipWidth, mipHeight, mipWidth, mipHeight,
glFmt.format, glFmt.format,
glFmt.dataType, glFmt.dataType,
data); data);
}else{ }else{
if (samples > 1){ if (samples > 1){
ARBTextureMultisample.glTexImage2DMultisample(target, glTexImage2DMultisample(target,
samples, samples,
glFmt.internalFormat, glFmt.internalFormat,
mipWidth, mipWidth,
mipHeight, mipHeight,
true); true);
}else{ }else{
GL11.glTexImage2D(target, glTexImage2D(target,
i, i,
glFmt.internalFormat, glFmt.internalFormat,
mipWidth, mipWidth,
mipHeight, mipHeight,
border, border,
glFmt.format, glFmt.format,
glFmt.dataType, glFmt.dataType,
data); data);
} }
} }
} }
@ -416,6 +412,7 @@ class TextureUtil {
* @param y the y position where to put the image in the texture * @param y the y position where to put the image in the texture
*/ */
public static void uploadSubTexture( public static void uploadSubTexture(
ContextCapabilities caps,
Image image, Image image,
int target, int target,
int index, int index,
@ -423,7 +420,7 @@ class TextureUtil {
int y, int y,
boolean linearizeSrgb) { boolean linearizeSrgb) {
Image.Format fmt = image.getFormat(); Image.Format fmt = image.getFormat();
GLImageFormat glFmt = getImageFormatWithError(fmt, image.getColorSpace() == ColorSpace.sRGB && linearizeSrgb); GLImageFormat glFmt = getImageFormatWithError(caps, fmt, image.getColorSpace() == ColorSpace.sRGB && linearizeSrgb);
ByteBuffer data = null; ByteBuffer data = null;
if (index >= 0 && image.getData() != null && image.getData().size() > 0) { if (index >= 0 && image.getData() != null && image.getData().size() > 0) {
@ -435,7 +432,7 @@ class TextureUtil {
int depth = image.getDepth(); int depth = image.getDepth();
if (data != null) { if (data != null) {
GL11.glPixelStorei(GL11.GL_UNPACK_ALIGNMENT, 1); glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
} }
int[] mipSizes = image.getMipMapSizes(); int[] mipSizes = image.getMipMapSizes();
@ -471,29 +468,29 @@ class TextureUtil {
int glFmtDataType = glFmt.dataType; int glFmtDataType = glFmt.dataType;
if (glFmt.compressed && data != null){ if (glFmt.compressed && data != null){
if (target == GL12.GL_TEXTURE_3D){ if (target == GL_TEXTURE_3D){
GL13.glCompressedTexSubImage3D(target, i, x, y, index, mipWidth, mipHeight, mipDepth, glFmtInternal, data); glCompressedTexSubImage3D(target, i, x, y, index, mipWidth, mipHeight, mipDepth, glFmtInternal, data);
continue; continue;
} }
// all other targets use 2D: array, cubemap, 2d // all other targets use 2D: array, cubemap, 2d
GL13.glCompressedTexSubImage2D(target, i, x, y, mipWidth, mipHeight, glFmtInternal, data); glCompressedTexSubImage2D(target, i, x, y, mipWidth, mipHeight, glFmtInternal, data);
continue; continue;
} }
if (target == GL12.GL_TEXTURE_3D){ if (target == GL_TEXTURE_3D){
GL12.glTexSubImage3D(target, i, x, y, index, mipWidth, mipHeight, mipDepth, glFmtFormat, glFmtDataType, data); glTexSubImage3D(target, i, x, y, index, mipWidth, mipHeight, mipDepth, glFmtFormat, glFmtDataType, data);
continue; continue;
} }
if (target == EXTTextureArray.GL_TEXTURE_2D_ARRAY_EXT){ if (target == GL_TEXTURE_2D_ARRAY_EXT){
// prepare data for 2D array or upload slice // prepare data for 2D array or upload slice
if (index == -1){ if (index == -1){
GL12.glTexSubImage3D(target, i, x, y, index, mipWidth, mipHeight, mipDepth, glFmtFormat, glFmtDataType, data); glTexSubImage3D(target, i, x, y, index, mipWidth, mipHeight, mipDepth, glFmtFormat, glFmtDataType, data);
continue; continue;
} }
GL12.glTexSubImage3D(target, i, x, y, index, width, height, 1, glFmtFormat, glFmtDataType, data); glTexSubImage3D(target, i, x, y, index, width, height, 1, glFmtFormat, glFmtDataType, data);
continue; continue;
} }
@ -501,8 +498,7 @@ class TextureUtil {
throw new IllegalStateException("Cannot update multisample textures"); throw new IllegalStateException("Cannot update multisample textures");
} }
GL11.glTexSubImage2D(target, i, x, y, mipWidth, mipHeight, glFmtFormat, glFmtDataType, data); glTexSubImage2D(target, i, x, y, mipWidth, mipHeight, glFmtFormat, glFmtDataType, data);
continue;
} }
} }
} }

Loading…
Cancel
Save