Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve item and texture bindings #43

Open
thecodewarrior opened this issue Jul 12, 2019 · 7 comments
Open

Improve item and texture bindings #43

thecodewarrior opened this issue Jul 12, 2019 · 7 comments
Labels
good first issue Good for newcomers question Further information is requested

Comments

@thecodewarrior
Copy link

I'm working on porting an app from the (frankly shoddy) Kotlin ImGui port, and while overall the change has been a positive one (if painful), I've run into a couple issues with binding support.

The first thing I noticed not being bound was the JImGui.listBox function, along with the itemSize and itemAdd functions. The listBox was trivial to reimplement, and I figured out that the JImGui.rect method creates an item, so I'm using that temporarily.

I'm also using a lot of custom BufferedImage textures (I'm using it to render reference glyphs to an image to draw in imgui), but the texture support in jimgui doesn't quite support this. Firstly, in order to export a BufferedImage to ImGui I would have to write it to a byte array as a .png for ImGui to read, which seems far from ideal. Secondly, I update these textures relatively frequently, so the fact that there isn't a method to replace or release a texture after it's created means old textures would just end up piling up.

This isn't really hampering development much however, since at the moment I've got workarounds for the missing JImGui bindings and I'm not working on the section that uses the textures at the moment.

@ice1000
Copy link
Owner

ice1000 commented Jul 12, 2019

The signature of listBox is ListBox(const char* label, int* current_item, bool (*items_getter)(void* data, int idx, const char** out_text), void* data, int items_count, int height_in_items = -1); or ListBox(const char* label, int* current_item, const char* const items[], int items_count, int height_in_items = -1);, which includes either a string array or a callback function. I haven't decide on how can I design such JVM API yet, because passing a Java array to C++ through JNI is expensive (so does converting string and pass it through C++).

@ice1000
Copy link
Owner

ice1000 commented Jul 12, 2019

I'm also using a lot of custom BufferedImage textures (I'm using it to render reference glyphs to an image to draw in imgui), but the texture support in jimgui doesn't quite support this.

Yes, because imgui accepts textures supported natively by the GL backend you're using.
If I want to support BufferedImage, I can't do more than just converting your BufferedImage into byte[] and pass it into existing APIs.

@ice1000
Copy link
Owner

ice1000 commented Jul 12, 2019

Most of your questions are related to the design of the original imgui implementation. I'll recommend you to take a look at some FAQs provided by https://github.com/ocornut/imgui and see how things are going.

Like, loading image needs to be completely implemented by yourself (using DirectX API or OpenGL API, for example). I'm already doing this for you -- on Linux/macOS it's:

JNIEXPORT auto JNICALL
Java_org_ice1000_jimgui_JImTextureID_createTextureFromFile(Ptr<JNIEnv> env,
jclass,
jbyteArray _fileName) -> jlongArray {
__JNI__FUNCTION__INIT__
__get(Byte, fileName)
GLuint texture = 0;
int width, height, channels;
int forceChannels = 4;
auto *imageData = stbi_load(STR_J2C(fileName), &width, &height, &channels, forceChannels);
__release(Byte, fileName)
__JNI__FUNCTION__CLEAN__
if (!imageData) texture = 0;
else initTexture(imageData, &texture, width, height);
stbi_image_free(imageData);
#define RET_LEN 3
auto ret = new jlong[RET_LEN];
ret[0] = static_cast<jlong> (texture);
ret[1] = static_cast<jlong> (width);
ret[2] = static_cast<jlong> (height);
__init(Long, ret, RET_LEN);
#undef RET_LEN
delete[] ret;
return _ret;
}
JNIEXPORT auto JNICALL
Java_org_ice1000_jimgui_JImTextureID_createTextureFromBytes(Ptr<JNIEnv> env,
jclass,
jbyteArray _rawData,
jint size) -> jlongArray {
__JNI__FUNCTION__INIT__
__get(Byte, rawData)
GLuint texture = 0;
int width, height, channels;
int forceChannels = 4;
auto *imageData = stbi_load_from_memory(PTR_J2C(stbi_uc, rawData), size, &width, &height, &channels, forceChannels);
__release(Byte, rawData)
__JNI__FUNCTION__CLEAN__
if (!imageData) texture = 0;
else initTexture(imageData, &texture, width, height);
stbi_image_free(imageData);
#define RET_LEN 3
auto ret = new jlong[RET_LEN];
ret[0] = static_cast<jlong> (texture);
ret[1] = static_cast<jlong> (width);
ret[2] = static_cast<jlong> (height);
__init(Long, ret, RET_LEN);
#undef RET_LEN
delete[] ret;
return _ret;
}

void initTexture(Ptr<void> imageData, Ptr<GLuint> tex, int x, int y) {
// NPOT check
// if ((x & (x - 1)) != 0 || (y & (y - 1)) != 0)
// fprintf(stderr, "WARNING: texture %s is not power-of-2 dimensions\n", fileName);
glGenTextures(1, tex);
glBindTexture(GL_TEXTURE_2D, *tex);
// glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, x, y, 0, GL_RGBA, GL_UNSIGNED_BYTE, imageData);
glGenerateMipmap(GL_TEXTURE_2D);
// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
}

For Windows it's:

auto loadTexture(Ptr<const char> fileName, LPDIRECT3DTEXTURE9 &texture) -> bool {
return SUCCEEDED(D3DXCreateTextureFromFile(g_pd3dDevice, fileName, &texture));
}
auto loadTextureInMemory(Ptr<void> rawData, size_t size, LPDIRECT3DTEXTURE9 &texture) -> bool {
return SUCCEEDED(D3DXCreateTextureFromFileInMemory(g_pd3dDevice, rawData, size, &texture));
}
JNIEXPORT auto JNICALL
Java_org_ice1000_jimgui_JImTextureID_createTextureFromFile(Ptr<JNIEnv> env,
jclass,
jbyteArray _fileName) -> jlongArray {
__JNI__FUNCTION__INIT__
__get(Byte, fileName)
LPDIRECT3DTEXTURE9 texture;
auto success = loadTexture(STR_J2C(fileName), texture);
__release(Byte, fileName)
__JNI__FUNCTION__CLEAN__
if (!success) return nullptr;
D3DSURFACE_DESC desc;
texture->GetLevelDesc(0, &desc);
int width = static_cast<jint>(desc.Width);
int height = static_cast<jint>(desc.Height);
#define RET_LEN 3
auto ret = new jlong[RET_LEN];
ret[0] = PTR_C2J(texture);
ret[1] = static_cast<jlong> (width);
ret[2] = static_cast<jlong> (height);
__init(Long, ret, RET_LEN);
#undef RET_LEN
delete[] ret;
return _ret;
}
JNIEXPORT auto JNICALL
Java_org_ice1000_jimgui_JImTextureID_createTextureFromBytes(Ptr<JNIEnv> env,
jclass,
jbyteArray _rawData,
jint size) -> jlongArray {
__JNI__FUNCTION__INIT__
__get(Byte, rawData)
LPDIRECT3DTEXTURE9 texture;
auto success = loadTextureInMemory(PTR_J2C(void, rawData), size, texture);
__release(Byte, rawData)
__JNI__FUNCTION__CLEAN__
if (!success) return nullptr;
D3DSURFACE_DESC desc;
texture->GetLevelDesc(0, &desc);
int width = static_cast<jint>(desc.Width);
int height = static_cast<jint>(desc.Height);
#define RET_LEN 3
auto ret = new jlong[RET_LEN];
ret[0] = PTR_C2J(texture);
ret[1] = static_cast<jlong> (width);
ret[2] = static_cast<jlong> (height);
__init(Long, ret, RET_LEN);
#undef RET_LEN
delete[] ret;
return _ret;
}

I assume you're not asking for JImTexture(long nativePointer) -- which might be useful for you.

@ice1000
Copy link
Owner

ice1000 commented Jul 12, 2019

So the problem is jimgui uses DirectX (9, if you're asking for the version. But 11 is planned) on Windows, while the reimplementation from kotlin-graphics is completely based on some OpenGL thing (thus rendering details can be customized as well).

@ice1000 ice1000 added good first issue Good for newcomers question Further information is requested labels Jul 12, 2019
@ice1000
Copy link
Owner

ice1000 commented Jul 12, 2019

For the listBox thing, if you have an idea in mind, don't hesitate to tell me (or pull me).

@ice1000
Copy link
Owner

ice1000 commented Jul 12, 2019

I update these textures relatively frequently, so the fact that there isn't a method to replace or release a texture after it's created means old textures would just end up piling up

This sounds like you're asking for an API to release textures. Contribution is also welcomed.

@ice1000
Copy link
Owner

ice1000 commented Jul 12, 2019

/cc #11

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
good first issue Good for newcomers question Further information is requested
Projects
None yet
Development

No branches or pull requests

2 participants