TextureData and null Buffer parameter

Hi all!

I’m trying to use the new TextureData/Texture classes, instead of using the glTexImage calls and stuff. However, I stumbled upon a problem. I created a new TextureData object using a null Buffer parameter. Then I created a new Texture :


        TextureData textureData = new TextureData(GL.GL_RGB,
                                                  128, 
                                                  128,
                                                  0,
                                                  GL.GL_BGRA,
                                                  GL.GL_UNSIGNED_BYTE,
                                                  false,
                                                  false,
                                                  false,
                                                  null, // BufferUtil.newByteBuffer(4*Terrain.IMAGE_TEXTURE_SIZE*Terrain.IMAGE_TEXTURE_SIZE),
                                                  null); 
        
        texture = TextureIO.newTexture(textureData);

The equivelant using the old way is :


        int[] texs = new int[1];
        gl.glGenTextures(1, texs,0);
        textureID = texs[0];

        gl.glBindTexture(GL.GL_TEXTURE_2D, textureID);
        long l = System.nanoTime();
        gl.glTexImage2D(GL.GL_TEXTURE_2D, 
                0, 
                GL.GL_RGB,
                128, 
                128,
                0,
                GL.GL_BGRA, 
                GL.GL_UNSIGNED_BYTE, 
                null);

By using the old way, texture space could be allocated directly to the GPU without transferring data to it. Texture data could be provided later by glCopTexImage calls. However, when I tried to do the same using the new code, the VM crashed. It crashes at the Texture creation, and not at the TextureData constructor call.

Is this a bug, or am I doing something wrong here? I think that a Texture should be created using TextureData with null texels (since texture dimensions and format have already been specified). I’m using the lastest nightly build.

TIA
N

To do what you want you should simply wait to instantiate the Texture object until the first time you have some data to put into it. You can update the image with glTexSubImage2D by calling Texture.updateData() after the Texture has been instantiated.

Hmmm… I must be missing something here…Let’s say that I want to create a 10x10 Texture, and I instantiate it when some data are available for it (e.g. the 5x5 pixel top-left area). Available data can be sent to the gpu with glTexSubImage (using Texture.updateData()), but how is the Texture object instantiated without previously sending the 10x10 pixels? By using the glTexImage2D call, a texture could be allocated in the gpu without actually sending any data, but I can’t find a way to do the same using Texture class objects.

Have I misunderstood Texture object use? :-[

If you want to download sub-portions of the texture you first have to initialize the texture data to something. According to the spec for glTexImage2D you can not use NULL as the texture data to perform the allocation, update only a sub-portion of the texture, and then expect to display it. Because of this there would basically be no point in our adding support for null Buffers in the TextureData. You should allocate a zero-filled Buffer and pass it to the TextureData constructotr in order to get the background of your texture cleared.

I’m almost certain that null can be passed as an argument to glTexImage2D so as to allocate space to the gpu for an empty texture, whose parts can later be updated by glTexSubImage2D. I have used this trick many times to avoid clearing/initalizing a texture by sending data to the gpu. Look also here:

http://groups.google.gr/group/comp.graphics.api.opengl/browse_thread/thread/821e537274c593d2/3d7d244f18ade423?lnk=st&q=empty+texture+opengl&rnum=2&hl=en#3d7d244f18ade423

I have also measured times (using null data with glTexImage to instantiate a texture, and passing a zero-filled Buffer to TextureData as you suggested). Time in the first case is about 0.01ms, where in the second case is 2ms or more.

Hi Ken,

Actually, you can pass NULL to glTexImage2D() as of OpenGL 1.1:
http://www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/teximage2d.html

We used to pass a dummy array to glTexImage2D() in the Java2D OGL pipeline, but once I discovered that NULL was a valid parameter, I started using that and it definitely simplifies the code. I think null should be allowed in TextureData for the use case mantesat describes; we do essentially the same thing in our OGL pipeline.

Thanks,
Chris

Look further down in that paragraph: “The image is undefined if the user tries to apply an uninitialized portion of the texture image to a primitive.” That implies to me that you have to download sub-images covering the entire texture image in order for it to be valid, so if you want to upload just a 5x5 upper rectangle and draw the rest then you need to initialize the whole 10x10 texture to black anyway.

I guess it depends on mantesat’s use case. I assumed that the uninitialized region would not be mapped (i.e. only the 5x5 region would be mapped at any time). But I agree that you can’t rely on the contents of the uninitialized area to be filled with black by default. In the OGL pipeline we create pow2 textures (via glTexImage2D, NULL param) to hold non-pow2 image data (uploaded later via glTexSubImage2D), but we never map the uninitalized region, so this scenario works well for us.

Perhaps mantesat could clarify the intended usage…

Thanks,
Chris

Yes, my intended use is the exact one described by campbell. I know that when passing null as an argument for glTexImage2D, produces undefined results (as Ken pointed out), but in this case I use only the part of the texture whose data have been set by glTexSubImage2D. That behavior is useful for non-power of two textures, as campbell also suggested.

OK, I see. I’ve checked in support for the case where a TextureData has a null buffer. It should show up in the nightly builds dated 3/4 or later. Please post if there are problems with it.