diff --git a/jme3-core/src/main/java/com/jme3/renderer/Renderer.java b/jme3-core/src/main/java/com/jme3/renderer/Renderer.java index 608ac9d15..edfd380b4 100644 --- a/jme3-core/src/main/java/com/jme3/renderer/Renderer.java +++ b/jme3-core/src/main/java/com/jme3/renderer/Renderer.java @@ -235,7 +235,10 @@ public interface Renderer { public void setTexture(int unit, Texture tex); /** - * Modify the given Texture tex with the given Image. The image will be put at x and y into the texture. + * Modify the given Texture with the given Image. + * The image will be put at x and y into the texture. + * + * NOTE: this is only supported for uncompressed 2D images without mipmaps. * * @param tex the Texture that will be modified * @param pixels the source Image data to copy data from diff --git a/jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java b/jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java index 6a2e61204..ff957abda 100644 --- a/jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java +++ b/jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java @@ -2111,8 +2111,9 @@ public class GLRenderer implements Renderer { } public void modifyTexture(Texture tex, Image pixels, int x, int y) { -// setTexture(0, tex); -// texUtil.uploadSubTexture(caps, pixels, convertTextureType(tex.getType(), pixels.getMultiSamples(), -1), 0, x, y, linearizeSrgbImages); + setTexture(0, tex); + int target = convertTextureType(tex.getType(), pixels.getMultiSamples(), -1); + texUtil.uploadSubTexture(pixels, target, 0, x, y, linearizeSrgbImages); } public void deleteImage(Image image) { diff --git a/jme3-core/src/main/java/com/jme3/renderer/opengl/TextureUtil.java b/jme3-core/src/main/java/com/jme3/renderer/opengl/TextureUtil.java index cca0d8212..37ffe5ed3 100644 --- a/jme3-core/src/main/java/com/jme3/renderer/opengl/TextureUtil.java +++ b/jme3-core/src/main/java/com/jme3/renderer/opengl/TextureUtil.java @@ -259,108 +259,44 @@ final class TextureUtil { } } - /** - * Update the texture currently bound to target at with data from the given - * Image at position x and y. The parameter index is used as the zoffset in - * case a 3d texture or texture 2d array is being updated. - * - * @param image Image with the source data (this data will be put into the - * texture) - * @param target the target texture - * @param index the mipmap level to update - * @param x the x position where to put the image in the texture - * @param y the y position where to put the image in the texture - */ - /* - public void uploadSubTexture( - EnumSet caps, - Image image, - int target, - int index, - int x, - int y, - boolean linearizeSrgb) { - Image.Format fmt = image.getFormat(); - GLImageFormat glFmt = getImageFormatWithError(caps, fmt, image.getColorSpace() == ColorSpace.sRGB && linearizeSrgb); - - ByteBuffer data = null; - if (index >= 0 && image.getData() != null && image.getData().size() > 0) { - data = image.getData(index); - } - - int width = image.getWidth(); - int height = image.getHeight(); - int depth = image.getDepth(); - - if (data != null) { - gl.glPixelStorei(GL.GL_UNPACK_ALIGNMENT, 1); - } - - int[] mipSizes = image.getMipMapSizes(); - int pos = 0; - - // TODO: Remove unneccessary allocation - if (mipSizes == null){ - if (data != null) { - mipSizes = new int[]{ data.capacity() }; - } else { - mipSizes = new int[]{ width * height * fmt.getBitsPerPixel() / 8 }; - } - } - - int samples = image.getMultiSamples(); - - for (int i = 0; i < mipSizes.length; i++){ - int mipWidth = Math.max(1, width >> i); - int mipHeight = Math.max(1, height >> i); - int mipDepth = Math.max(1, depth >> i); - - if (data != null){ - data.position(pos); - data.limit(pos + mipSizes[i]); - } - - // to remove the cumbersome if/then/else stuff below we'll update the pos right here and use continue after each - // gl*Image call in an attempt to unclutter things a bit - pos += mipSizes[i]; - - int glFmtInternal = glFmt.internalFormat; - int glFmtFormat = glFmt.format; - int glFmtDataType = glFmt.dataType; - - if (glFmt.compressed && data != null){ - if (target == GL.GL_TEXTURE_3D){ - gl.glCompressedTexSubImage3D(target, i, x, y, index, mipWidth, mipHeight, mipDepth, glFmtInternal, data); - continue; - } - - // all other targets use 2D: array, cubemap, 2d - gl.glCompressedTexSubImage2D(target, i, x, y, mipWidth, mipHeight, glFmtInternal, data); - continue; - } - - if (target == GL.GL_TEXTURE_3D){ - gl.glTexSubImage3D(target, i, x, y, index, mipWidth, mipHeight, mipDepth, glFmtFormat, glFmtDataType, data); - continue; - } - - if (target == GLExt.GL_TEXTURE_2D_ARRAY_EXT){ - // prepare data for 2D array or upload slice - if (index == -1){ - gl.glTexSubImage3D(target, i, x, y, index, mipWidth, mipHeight, mipDepth, glFmtFormat, glFmtDataType, data); - continue; - } - - gl.glTexSubImage3D(target, i, x, y, index, width, height, 1, glFmtFormat, glFmtDataType, data); - continue; - } - - if (samples > 1){ - throw new IllegalStateException("Cannot update multisample textures"); - } + public void uploadSubTexture(Image image, int target, int index, int x, int y, boolean linearizeSrgb) { + if (target != GL.GL_TEXTURE_2D || image.getDepth() > 1) { + throw new UnsupportedOperationException("Updating non-2D texture is not supported"); + } + + if (image.getMipMapSizes() != null) { + throw new UnsupportedOperationException("Updating mip-mappped images is not supported"); + } + + if (image.getMultiSamples() > 1) { + throw new UnsupportedOperationException("Updating multisampled images is not supported"); + } + + Image.Format jmeFormat = image.getFormat(); + + if (jmeFormat.isCompressed()) { + throw new UnsupportedOperationException("Updating compressed images is not supported"); + } else if (jmeFormat.isDepthFormat()) { + throw new UnsupportedOperationException("Updating depth images is not supported"); + } + + boolean getSrgbFormat = image.getColorSpace() == ColorSpace.sRGB && linearizeSrgb; + GLImageFormat oglFormat = getImageFormatWithError(jmeFormat, getSrgbFormat); + + ByteBuffer data = null; + + if (index >= 0) { + data = image.getData(index); + } + + if (data == null) { + throw new IndexOutOfBoundsException("The image index " + index + " is not valid for the given image"); + } - gl.glTexSubImage2D(target, i, x, y, mipWidth, mipHeight, glFmtFormat, glFmtDataType, data); - } - } - */ + data.position(0); + data.limit(data.capacity()); + + gl.glTexSubImage2D(target, 0, x, y, image.getWidth(), image.getHeight(), + oglFormat.format, oglFormat.dataType, data); + } }