[SOLVED] [LibGDX] Creating a copy of a Texture

Hi all,

I’m drawing graphics to an Image using ShapeRenderer and FrameBuffer and after I create the Image I dispose the ShapeRenderer and the FrameBuffer, but when I dispose the FrameBuffer the Image doesn’t display. It seems like the Image is referencing the Texture located inside the FrameBuffer, so is a way to make a copy of the FrameBuffer’s Texture? Then I should be able to dispose the FrameBuffer without affecting the Image.

The Texture constructor doesn’t take another Texture, but it does take a TextureData object, so I thought I could use the getTextureData() method to create new Texture, but I just got an error (see code below). I also tried making a copy of the TextureRegion, but that did nothing as I think the new TextureRegion is also referencing the same Texture.

Here is a short example code that draws a filled rectangle. I also left in my code trying to generate a new Texture with the getTextureData() method and the error I got from it.

package com.tekker.test;

import com.badlogic.gdx.ApplicationAdapter;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.scenes.scene2d.ui.Table;

public class Test extends ApplicationAdapter {
	Stage stage;	
	Table tableMain;
	TestBackground background;	
	
	@Override
	public void create () {
		stage = new Stage();
		Gdx.input.setInputProcessor(stage);
				
		tableMain = new Table();
		tableMain.setFillParent(true);
		stage.addActor(tableMain);
		
		background = new TestBackground(Gdx.graphics.getWidth(), 200);
		tableMain.add(background).size(background.getWidth(), background.getHeight());
	}
			
	@Override
	public void render () {
		Gdx.gl.glClearColor(0, 0, 0, 1);
		Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
		stage.draw();
	}
	
	@Override
	public void dispose(){
		stage.dispose();
	}
}
package com.tekker.test;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.Pixmap.Format;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.Batch;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.graphics.glutils.FrameBuffer;
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
import com.badlogic.gdx.scenes.scene2d.ui.Image;
import com.badlogic.gdx.scenes.scene2d.ui.Table;

public class TestBackground extends Table {	
	Color backgroundColor = new Color(0.5f, 0.5f, 0.5f, 1.0f);
	Image backgroundImage;
	
	public TestBackground(float width, float height){
		setSize(width, height);
		createBackground();
	}
	
	private void createBackground(){
		FrameBuffer buffer = new FrameBuffer(Format.RGBA8888, Gdx.graphics.getWidth(), Gdx.graphics.getHeight(), false);
		ShapeRenderer shapeRenderer = new ShapeRenderer();
		
		buffer.begin();
		Gdx.gl.glBlendFuncSeparate(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA, GL20.GL_ONE, GL20.GL_ONE_MINUS_SRC_ALPHA);
		Gdx.graphics.getGL20().glEnable(GL20.GL_BLEND);
		
		shapeRenderer.begin(ShapeRenderer.ShapeType.Filled);
		shapeRenderer.rect(0f, 0f, getWidth(), getHeight(), backgroundColor, backgroundColor, backgroundColor, backgroundColor);
		shapeRenderer.end();
		
		buffer.end();
		
		Texture bufferTexture = buffer.getColorBufferTexture();
		Texture newTexture = new Texture(bufferTexture.getTextureData()); // <<< ERROR >>>
		TextureRegion region = new TextureRegion(newTexture);
		region.flip(false, true);
		backgroundImage = new Image(region);
		
		shapeRenderer.dispose();
		buffer.dispose();
	}
	
	@Override
	public void draw (Batch batch, float parentAlpha) {
		applyTransform(batch, computeTransform());
		backgroundImage.draw(batch, parentAlpha);
		resetTransform(batch);
		
		super.draw(batch, parentAlpha);
	}
}

ERROR MESSAGE:

Exception in thread "LWJGL Application" com.badlogic.gdx.utils.GdxRuntimeException: Pixmap already disposed
	at com.badlogic.gdx.graphics.Pixmap.getPixels(Pixmap.java:356)
	at com.badlogic.gdx.graphics.GLTexture.uploadImageData(GLTexture.java:248)
	at com.badlogic.gdx.graphics.GLTexture.uploadImageData(GLTexture.java:212)
	at com.badlogic.gdx.graphics.Texture.load(Texture.java:133)
	at com.badlogic.gdx.graphics.Texture.<init>(Texture.java:121)
	at com.tekker.test.TestBackground.createBackground(TestBackground.java:39)
	at com.tekker.test.TestBackground.<init>(TestBackground.java:21)
	at com.tekker.test.Test.create(Test.java:34)
	at com.badlogic.gdx.backends.lwjgl.LwjglApplication.mainLoop(LwjglApplication.java:136)
	at com.badlogic.gdx.backends.lwjgl.LwjglApplication$1.run(LwjglApplication.java:114)

UPDATE: I was told on the LibGDX forum that textures are heavy weight objects and you can’t copy them.

I was advised to work with Pixmaps, and I spent some time converting my graphics from ShapeRenderer over to Pixmap and it works great. It is so much easier to work without the FrameBuffer and the Pixmap can be disposed without affecting the Image. So this is the route I’m going now. :slight_smile: