Skip to content

Commit

Permalink
Improve PixmapEmu and Gdx2DPixmapEmu
Browse files Browse the repository at this point in the history
  • Loading branch information
xpenatan committed Jan 6, 2025
1 parent c030cbf commit bfca256
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 44 deletions.
27 changes: 15 additions & 12 deletions backends/backend-teavm/emu/com/badlogic/gdx/graphics/PixmapEmu.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
import com.github.xpenatan.gdx.backends.teavm.dom.typedarray.TypedArrays;
import com.github.xpenatan.gdx.backends.teavm.dom.typedarray.Uint8ArrayWrapper;
import com.github.xpenatan.gdx.backends.teavm.gen.Emulate;
import com.github.xpenatan.gdx.backends.teavm.assetloader.AssetDownloader;
import com.github.xpenatan.gdx.backends.teavm.assetloader.AssetType;
import com.github.xpenatan.gdx.backends.teavm.assetloader.Blob;
import java.nio.ByteBuffer;
Expand All @@ -26,8 +25,9 @@ public class PixmapEmu implements Disposable {
public static PixmapEmu createFromFrameBuffer(int x, int y, int w, int h) {
Gdx.gl.glPixelStorei(GL20.GL_PACK_ALIGNMENT, 1);
final PixmapEmu pixmap = new PixmapEmu(w, h, FormatEmu.RGBA8888);
ByteBuffer pixels = pixmap.getPixels();
ByteBuffer pixels = BufferUtils.newByteBuffer(h * w * 4);
Gdx.gl.glReadPixels(x, y, w, h, GL20.GL_RGBA, GL20.GL_UNSIGNED_BYTE, pixels);
pixmap.setPixels(pixels);
return pixmap;
}

Expand Down Expand Up @@ -64,8 +64,7 @@ public static int toGlType (FormatEmu format) {
return Gdx2DPixmapEmu.toGlType(toGdx2DPixmapFormat(format));
}
}
Uint8ArrayWrapper nativePixels;
ByteBuffer buffer;

BlendingEmu blending = PixmapEmu.BlendingEmu.SourceOver;
FilterEmu filter = PixmapEmu.FilterEmu.BiLinear;

Expand Down Expand Up @@ -103,12 +102,10 @@ public PixmapEmu(FileHandle file) {
}
byte[] bytes = file.readBytes();
nativePixmap = new Gdx2DPixmapEmu(bytes, 0, bytes.length, 0);
initPixmapEmu();
}

public PixmapEmu(byte[] encodedData, int offset, int len) {
nativePixmap = new Gdx2DPixmapEmu(encodedData, offset, len, 0);
initPixmapEmu();
}

public PixmapEmu(ByteBuffer encodedData, int offset, int len) {
Expand All @@ -126,14 +123,13 @@ public PixmapEmu(int width, int height, FormatEmu format) {
nativePixmap = new Gdx2DPixmapEmu(width, height, PixmapEmu.FormatEmu.toGdx2DPixmapFormat(format));
setColor(0, 0, 0, 0);
fill();
initPixmapEmu();
}

private void initPixmapEmu() {
private ByteBuffer getNewBuffer() {
if(nativePixmap != null) {
nativePixels = nativePixmap.getPixels();
Uint8ArrayWrapper nativePixels = nativePixmap.getPixels(true);
byte[] byteArray = TypedArrays.toByteArray(nativePixels);
buffer = ByteBuffer.wrap(byteArray);
return ByteBuffer.wrap(byteArray);
}
else {
throw new GdxRuntimeException("NOT SUPPORTED PIXMAP");
Expand Down Expand Up @@ -224,13 +220,20 @@ public int getGLType () {
}

public ByteBuffer getPixels() {
return buffer;
ByteBuffer newBuffer = getNewBuffer();
return newBuffer;
}

public void setPixels(ByteBuffer pixels) {
if (!pixels.isDirect())
throw new GdxRuntimeException("Couldn't setPixels from non-direct ByteBuffer");
BufferUtils.copy(pixels, buffer, buffer.limit());
// Return the heap array so we can update the values directly
Uint8ArrayWrapper nativePixels = nativePixmap.getPixels(false);
int length = nativePixels.getLength();
for(int i = 0; i < length; i++) {
byte b = pixels.get(i);
nativePixels.set(i, b);
}
}

public int getPixel(int x, int y) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.utils.Disposable;
import com.badlogic.gdx.utils.GdxRuntimeException;
import com.github.xpenatan.gdx.backends.teavm.dom.typedarray.Int32ArrayWrapper;
import com.github.xpenatan.gdx.backends.teavm.dom.typedarray.Uint8ArrayWrapper;
import com.github.xpenatan.gdx.backends.teavm.gen.Emulate;
import java.io.InputStream;
import org.teavm.jso.JSBody;
import org.teavm.jso.JSByRef;

@Emulate(Gdx2DPixmap.class)
public class Gdx2DPixmapEmu implements Disposable {
Expand Down Expand Up @@ -61,16 +61,15 @@ public static int toGlType(int format) {
int width;
int height;
int format;
int[] nativeData = new int[4];
int heapStartIndex;
int heapEndIndex;

Uint8ArrayWrapper pixelPtr;
Int32ArrayWrapper nativeData;

public Gdx2DPixmapEmu(byte[] encodedData, int offset, int len, int requestedFormat) {
pixelPtr = load(nativeData, encodedData, offset, len);
basePtr = nativeData[0];
width = nativeData[1];
height = nativeData[2];
format = nativeData[3];
nativeData = loadNative(encodedData, offset, len);
updateNativeData();

if(requestedFormat != 0 && requestedFormat != format) {
convert(requestedFormat);
}
Expand All @@ -80,11 +79,17 @@ public Gdx2DPixmapEmu(byte[] encodedData, int offset, int len, int requestedForm
* @throws GdxRuntimeException if allocation failed.
*/
public Gdx2DPixmapEmu(int width, int height, int format) throws GdxRuntimeException {
pixelPtr = newPixmap(nativeData, width, height, format);
this.basePtr = nativeData[0];
this.width = nativeData[1];
this.height = nativeData[2];
this.format = nativeData[3];
nativeData = newPixmapNative(width, height, format);
updateNativeData();
}

private void updateNativeData() {
this.basePtr = nativeData.get(0);
this.width = nativeData.get(1);
this.height = nativeData.get(2);
this.format = nativeData.get(3);
this.heapStartIndex = nativeData.get(4);
this.heapEndIndex = nativeData.get(5);
}

// public Gdx2DPixmapEmu(ByteBuffer encodedData, int offset, int len, int requestedFormat) throws IOException {
Expand Down Expand Up @@ -144,7 +149,8 @@ private void convert(int requestedFormat) {
this.width = pixmap.width;
this.height = pixmap.height;
this.nativeData = pixmap.nativeData;
this.pixelPtr = pixmap.pixelPtr;
this.heapStartIndex = pixmap.heapStartIndex;
this.heapEndIndex = pixmap.heapEndIndex;
}

@Override
Expand Down Expand Up @@ -221,8 +227,8 @@ public static Gdx2DPixmapEmu newPixmap(int width, int height, int format) {
}
}

public Uint8ArrayWrapper getPixels() {
return pixelPtr;
public Uint8ArrayWrapper getPixels(boolean shouldCopy) {
return getHeapData(shouldCopy);
}

public int getHeight() {
Expand Down Expand Up @@ -253,6 +259,13 @@ public String getFormatString() {
return getFormatString(format);
}

public Uint8ArrayWrapper getHeapData(boolean shouldCopy) {
if(heapStartIndex == 0 && heapEndIndex == 0) {
return null;
}
return getHeapDataNative(shouldCopy, heapStartIndex, heapEndIndex);
}

static private String getFormatString(int format) {
switch(format) {
case GDX2D_FORMAT_ALPHA:
Expand All @@ -272,13 +285,23 @@ static private String getFormatString(int format) {
}
}

@JSBody(params = {"shouldCopy", "heapStartIndex", "heapEndIndex"}, script = "" +
"var heapArray = Gdx.HEAPU8.subarray(heapStartIndex, heapEndIndex);" +
"if(shouldCopy) {" +
" var newArray = new Uint8Array(heapArray);" +
" return newArray;" +
"}" +
"return heapArray;"
)
private static native Uint8ArrayWrapper getHeapDataNative(boolean shouldCopy, int heapStartIndex, int heapEndIndex);

// @off
/*JNI
#include <gdx2d/gdx2d.h>
#include <stdlib.h>
*/

@JSBody(params = {"nativeData", "buffer", "offset", "len"}, script = "" +
@JSBody(params = {"buffer", "offset", "len"}, script = "" +
"var cBufferSize = buffer.length * Uint8Array.BYTES_PER_ELEMENT;" +
"var cBuffer = Gdx._malloc(cBufferSize);" +
"Gdx.writeArrayToMemory(buffer, cBuffer);" +
Expand All @@ -289,18 +312,20 @@ static private String getFormatString(int format) {
"var format = pixmap.get_format();" +
"var width = pixmap.get_width();" +
"var height = pixmap.get_height();" +
"nativeData[0] = pixmapAddr;" +
"nativeData[1] = width;" +
"nativeData[2] = height;" +
"nativeData[3] = format;" +
"var bytesPerPixel = Gdx.Gdx.prototype.g2d_bytes_per_pixel(format);" +
"var bytesSize = width * height * bytesPerPixel;" +
"var startIndex = pixels;" +
"var endIndex = startIndex + bytesSize;" +
"var heapArray = Gdx.HEAPU8.subarray(startIndex, endIndex);" +
"return heapArray;"
"var nativeData = new Int32Array(6);" +
"nativeData[0] = pixmapAddr;" +
"nativeData[1] = width;" +
"nativeData[2] = height;" +
"nativeData[3] = format;" +
"nativeData[4] = startIndex;" +
"nativeData[5] = endIndex;" +
"return nativeData;"
)
private static native Uint8ArrayWrapper load(@JSByRef() int[] nativeData, @JSByRef() byte[] buffer, int offset, int len); /*MANUAL
private static native Int32ArrayWrapper loadNative(byte[] buffer, int offset, int len); /*MANUAL
const unsigned char* p_buffer = (const unsigned char*)env->GetPrimitiveArrayCritical(buffer, 0);
gdx2d_pixmap* pixmap = gdx2d_load(p_buffer + offset, len);
env->ReleasePrimitiveArrayCritical(buffer, (char*)p_buffer, 0);
Expand All @@ -319,25 +344,27 @@ static private String getFormatString(int format) {
return pixel_buffer;
*/

@JSBody(params = {"nativeData", "width", "height", "format"}, script = "" +
@JSBody(params = {"width", "height", "format"}, script = "" +
"var pixmap = Gdx.Gdx.prototype.g2d_new(width, height, format);" +
"var pixels = Gdx.Gdx.prototype.g2d_get_pixels(pixmap);" +
"var pixmapAddr = Gdx.getPointer(pixmap);" +
"var format = pixmap.get_format();" +
"var width = pixmap.get_width();" +
"var height = pixmap.get_height();" +
"nativeData[0] = pixmapAddr;" +
"nativeData[1] = width;" +
"nativeData[2] = height;" +
"nativeData[3] = format;" +
"var bytesPerPixel = Gdx.Gdx.prototype.g2d_bytes_per_pixel(format);" +
"var bytesSize = width * height * bytesPerPixel;" +
"var startIndex = pixels;" +
"var endIndex = startIndex + bytesSize;" +
"var newArray = Gdx.HEAPU8.subarray(startIndex, endIndex);" +
"return newArray;"
"var nativeData = new Int32Array(6);" +
"nativeData[0] = pixmapAddr;" +
"nativeData[1] = width;" +
"nativeData[2] = height;" +
"nativeData[3] = format;" +
"nativeData[4] = startIndex;" +
"nativeData[5] = endIndex;" +
"return nativeData;"
)
private static native Uint8ArrayWrapper newPixmap(@JSByRef() int[] nativeData, int width, int height, int format); /*MANUAL
private static native Int32ArrayWrapper newPixmapNative(int width, int height, int format); /*MANUAL
gdx2d_pixmap* pixmap = gdx2d_new(width, height, format);
if(pixmap==0)
return 0;
Expand Down

0 comments on commit bfca256

Please sign in to comment.