SimpleJavaEngine/src/main/java/speiger/src/coreengine/rendering/textures/custom/DynamicTexture.java

141 lines
3.9 KiB
Java

package speiger.src.coreengine.rendering.textures.custom;
import org.lwjgl.opengl.GL45;
import org.lwjgl.system.MemoryUtil;
import speiger.src.collections.ints.collections.IntIterator;
import speiger.src.collections.ints.sets.IntLinkedOpenHashSet;
import speiger.src.collections.ints.sets.IntSet;
import speiger.src.coreengine.assets.base.IAssetProvider;
import speiger.src.coreengine.math.BitUtil;
import speiger.src.coreengine.rendering.textures.base.BaseTexture;
import speiger.src.coreengine.rendering.textures.base.TextureMetadata;
import speiger.src.coreengine.rendering.utils.values.GLDataType;
import speiger.src.coreengine.rendering.utils.values.textures.GLTextureFormat;
public class DynamicTexture extends BaseTexture implements IDynamicTexture {
IntSet dirtySections = new IntLinkedOpenHashSet();
TextureMetadata metadata;
int width;
int height;
long data;
public DynamicTexture(int width, int height, TextureMetadata metadata) {
this.metadata = metadata;
this.width = width;
this.height = height;
data = MemoryUtil.nmemAllocChecked(4L * width * height);
}
@Override
public void load(IAssetProvider provider) {
createTexture();
metadata.applyArguments(id);
GL45.glTextureStorage2D(id, 1, GLTextureFormat.RGBA.glValue(), width, height);
GL45.nglTextureSubImage2D(id, 0, 0, 0, width, height, GLTextureFormat.RGBA.glValue(), GLDataType.UNSIGNED_BYTE.glValue(), data);
dirtySections.clear();
}
@Override
public void delete(boolean untrack) {
super.delete(untrack);
if(untrack && data != 0L) {
MemoryUtil.nmemFree(data);
data = 0L;
}
}
@Override
public int width() { return width; }
@Override
public int height() { return height; }
@Override
public boolean isDirty() { return !dirtySections.isEmpty(); }
@Override
public void process(boolean full) {
if(full) {
GL45.nglTextureSubImage2D(id, 0, 0, 0, width, height, GLTextureFormat.RGBA.glValue(), GLDataType.UNSIGNED_BYTE.glValue(), data);
dirtySections.clear();
return;
}
Thread thread = Thread.currentThread();
long tempBuffer = MemoryUtil.nmemAllocChecked(1024);
for(IntIterator iter = dirtySections.iterator();iter.hasNext() && !thread.isInterrupted();iter.remove()) {
int key = iter.nextInt();
int x = BitUtil.toFirstShort(key) * 16;
int y = BitUtil.toSecondShort(key) * 16;
for(int i = 0;i<16;i++) {
MemoryUtil.memCopy(data + offset(x, y+i), tempBuffer+i*64, 64);//TODO implement a better solution here, i don't like it
}
GL45.nglTextureSubImage2D(id, 0, x, y, 16, 16, GLTextureFormat.RGBA.glValue(), GLDataType.UNSIGNED_BYTE.glValue(), tempBuffer);
}
MemoryUtil.nmemFree(tempBuffer);
}
protected long offset(int x, int y) {
return ((y * width()) + x) * 4L;
}
@Override
public void dirty(int x, int y) {
if(id() == 0) return;
dirtySections.add(BitUtil.toInt(x >> 4, y >> 4));
}
@Override
public void set(int index, int data) {
MemoryUtil.memPutInt(index * 4L, Integer.rotateLeft(data, 8));
dirty(index);
}
@Override
public void setR(int index, int red) {
MemoryUtil.memPutByte(index * 4L, (byte)(red & 0xFF));
dirty(index);
}
@Override
public void setG(int index, int green) {
MemoryUtil.memPutByte(index * 4L + 1L, (byte)(green & 0xFF));
dirty(index);
}
@Override
public void setB(int index, int blue) {
MemoryUtil.memPutByte(index * 4L + 2L, (byte)(blue & 0xFF));
dirty(index);
}
@Override
public void setA(int index, int alpha) {
MemoryUtil.memPutByte(index * 4L + 3L, (byte)(alpha & 0xFF));
dirty(index);
}
@Override
public int get(int index) {
return Integer.rotateRight(MemoryUtil.memGetInt(index * 4L), 8);
}
@Override
public int getR(int index) {
return MemoryUtil.memGetByte(index * 4L);
}
@Override
public int getG(int index) {
return MemoryUtil.memGetByte(index * 4L + 1L);
}
@Override
public int getB(int index) {
return MemoryUtil.memGetByte(index * 4L + 2L);
}
@Override
public int getA(int index) {
return MemoryUtil.memGetByte(index * 4L + 3L);
}
}