Skip to content

Commit 283e780

Browse files
committed
Simplify, improve and optimize the rendering for LWJGL3
1 parent ed7bf36 commit 283e780

File tree

6 files changed

+263
-230
lines changed

6 files changed

+263
-230
lines changed

config/checkstyle/checkstyle.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@
121121
<!-- Checks for imports -->
122122
<!-- See https://checkstyle.org/config_import.html -->
123123
<module name="AvoidStarImport">
124-
<property name="excludes" value="org.lwjgl.opengl.GL30,org.lwjgl.glfw.GLFW"/>
124+
<property name="excludes" value="org.lwjgl.opengl.GL32,org.lwjgl.glfw.GLFW"/>
125125
</module>
126126
<module name="IllegalImport"/> <!-- defaults to sun.* packages -->
127127
<module name="RedundantImport"/>
Lines changed: 187 additions & 126 deletions
Original file line numberDiff line numberDiff line change
@@ -1,173 +1,234 @@
11
package imgui;
22

3-
import java.nio.Buffer;
43
import java.nio.ByteBuffer;
54
import java.nio.ByteOrder;
65

76
/**
8-
* All draw data to render a Dear ImGui frame.
7+
* All draw data to render Dear ImGui frame
8+
* (NB: the style and the naming convention here is a little inconsistent, we currently preserve them for backward compatibility purpose,
9+
* as this is one of the oldest structure exposed by the library! Basically, ImDrawList == CmdList)
910
* <p>
10-
* BINDING NOTICE: DO NOT TRY TO MODIFY FIELDS OF THIS CLASS MANUALLY! You should only access their values after {@link ImGui#render()} call.
11+
* BINDING NOTICE: Since it's impossible to do a 1:1 mapping with JNI, current class provides "getCmdList*()" methods.
12+
* Those are used to get the data needed to do a rendering.
1113
*/
12-
public final class ImDrawData {
13-
public static final int V_BUFFER_SIZE = (4 + 1) * 4;
14-
public static final int I_BUFFER_SIZE = 2;
15-
public static final int CMD_BUFFER_SIZE = (1 + 4 + 1) * 4;
16-
17-
public ByteBuffer vByteBuffer;
18-
public ByteBuffer iByteBuffer;
19-
public ByteBuffer cmdByteBuffer;
20-
21-
public int totalIdxCount; // For convenience, sum of all ImDrawList's IdxBuffer.Size
22-
public int totalVtxCount; // For convenience, sum of all ImDrawList's VtxBuffer.Size
23-
public int cmdListsCount; // Number of ImDrawList* to render
24-
25-
// Upper-left position of the viewport to render (== upper-left of the orthogonal projection matrix to use)
26-
//
27-
public float displayPosX;
28-
public float displayPosY;
29-
30-
// Size of the viewport to render (== io.DisplaySize for the main viewport)
31-
// (DisplayPos+DisplaySize == lower-right of the orthogonal projection matrix to use)
32-
//
33-
public float displaySizeX;
34-
public float displaySizeY;
35-
36-
// Amount of pixels for each unit of DisplaySize. Based on io.DisplayFramebufferScale. Generally (1,1) on normal display, (2,2) on OSX with Retina display.
37-
//
38-
public float framebufferScaleX;
39-
public float framebufferScaleY;
40-
41-
ImDrawData(final int maxVertices, final int maxIndices, final int maxCmd) {
42-
vByteBuffer = ByteBuffer.allocateDirect(maxVertices * V_BUFFER_SIZE).order(ByteOrder.nativeOrder());
43-
iByteBuffer = ByteBuffer.allocateDirect(maxIndices * I_BUFFER_SIZE).order(ByteOrder.nativeOrder());
44-
cmdByteBuffer = ByteBuffer.allocateDirect(maxCmd * CMD_BUFFER_SIZE).order(ByteOrder.nativeOrder());
14+
public final class ImDrawData implements ImDestroyable {
15+
public static final int SIZEOF_IM_DRAW_IDX = 2;
16+
public static final int SIZEOF_IM_DRAW_VERT = (4 + 1) * 4;
17+
18+
private static final int COUNT_FACTOR = 5_000;
19+
20+
final long ptr;
21+
22+
private ByteBuffer idxBuffer = ByteBuffer.allocateDirect(SIZEOF_IM_DRAW_IDX * COUNT_FACTOR).order(ByteOrder.nativeOrder());
23+
private ByteBuffer vtxBuffer = ByteBuffer.allocateDirect(SIZEOF_IM_DRAW_VERT * COUNT_FACTOR).order(ByteOrder.nativeOrder());
24+
25+
/**
26+
* This class will create a native structure.
27+
* Call {@link #destroy()} method to manually free used memory.
28+
*/
29+
public ImDrawData() {
30+
ImGui.touch();
31+
ptr = nCreate();
32+
}
33+
34+
ImDrawData(final long ptr) {
35+
this.ptr = ptr;
36+
}
37+
38+
@Override
39+
public void destroy() {
40+
nDestroy(ptr);
4541
}
4642

4743
/*JNI
4844
#include <stdint.h>
4945
#include <imgui.h>
46+
#include "jni_common.h"
47+
48+
jfieldID imDrawDataPtrID;
5049
51-
jfieldID totalVtxCountID;
52-
jfieldID totalIdxCountID;
53-
jfieldID CmdListsCountID;
54-
jfieldID displayPosXID;
55-
jfieldID displayPosYID;
56-
jfieldID displaySizeXID;
57-
jfieldID displaySizeYID;
58-
jfieldID framebufferScaleXID;
59-
jfieldID framebufferScaleYID;
50+
#define IM_DRAW_DATA ((ImDrawData*)env->GetLongField(object, imDrawDataPtrID))
6051
*/
6152

6253
static native void nInit(); /*
63-
jclass jDrawDataClass = env->FindClass("imgui/ImDrawData");
54+
jclass jImDrawDataClass = env->FindClass("imgui/ImDrawData");
55+
imDrawDataPtrID = env->GetFieldID(jImDrawDataClass, "ptr", "J");
56+
*/
6457

65-
totalVtxCountID = env->GetFieldID(jDrawDataClass, "totalVtxCount", "I");
66-
totalIdxCountID = env->GetFieldID(jDrawDataClass, "totalIdxCount", "I");
67-
CmdListsCountID = env->GetFieldID(jDrawDataClass, "cmdListsCount", "I");
68-
displayPosXID = env->GetFieldID(jDrawDataClass, "displayPosX", "F");
69-
displayPosYID = env->GetFieldID(jDrawDataClass, "displayPosY", "F");
70-
displaySizeXID = env->GetFieldID(jDrawDataClass, "displaySizeX", "F");
71-
displaySizeYID = env->GetFieldID(jDrawDataClass, "displaySizeY", "F");
72-
framebufferScaleXID = env->GetFieldID(jDrawDataClass, "framebufferScaleX", "F");
73-
framebufferScaleYID = env->GetFieldID(jDrawDataClass, "framebufferScaleY", "F");
58+
private native long nCreate(); /*
59+
ImDrawData* imDrawData = new ImDrawData();
60+
return (intptr_t)imDrawData;
7461
*/
7562

76-
native void nFillDrawData(Buffer indexBuffer, Buffer vertexBuffer, Buffer cmdBuffer); /*
77-
ImDrawData* drawData = ImGui::GetDrawData();
63+
private native void nDestroy(long ptr); /*
64+
delete (ImDrawData*)ptr;
65+
*/
7866

79-
if (drawData == NULL) {
80-
return;
81-
}
67+
///////// Start of Render Methods | Binding
8268

83-
int cmdListsCount = drawData->CmdListsCount;
69+
/**
70+
* Draw commands. Typically 1 command = 1 GPU draw call, unless the command is a callback.
71+
*/
72+
public native int getCmdListCmdBufferSize(int cmdListIdx); /*
73+
return IM_DRAW_DATA->CmdLists[cmdListIdx]->CmdBuffer.Size;
74+
*/
75+
76+
/**
77+
* Number of indices (multiple of 3) to be rendered as triangles.
78+
* Vertices are stored in the callee ImDrawList's vtx_buffer[] array, indices in idx_buffer[].
79+
*/
80+
public native int getCmdListCmdBufferElemCount(int cmdListIdx, int cmdBufferIdx); /*
81+
return IM_DRAW_DATA->CmdLists[cmdListIdx]->CmdBuffer[cmdBufferIdx].ElemCount;
82+
*/
83+
84+
/**
85+
* Clipping rectangle (x1, y1, x2, y2). Subtract ImDrawData->DisplayPos to get clipping rectangle in "viewport" coordinates
86+
*/
87+
public native void getCmdListCmdBufferClipRect(int cmdListIdx, int cmdBufferIdx, ImVec4 dstImVec4); /*
88+
Jni::ImVec4Cpy(env, &IM_DRAW_DATA->CmdLists[cmdListIdx]->CmdBuffer[cmdBufferIdx].ClipRect, dstImVec4);
89+
*/
90+
91+
/**
92+
* User-provided texture ID. Set by user in ImfontAtlas::SetTexID() for fonts or passed to Image*() functions.
93+
* Ignore if never using images or multiple fonts atlas.
94+
*/
95+
public native int getCmdListCmdBufferTextureId(int cmdListIdx, int cmdBufferIdx); /*
96+
return (intptr_t)IM_DRAW_DATA->CmdLists[cmdListIdx]->CmdBuffer[cmdBufferIdx].TextureId;
97+
*/
98+
99+
/**
100+
* Start offset in vertex buffer. Pre-1.71 or without ImGuiBackendFlags_RendererHasVtxOffset: always 0.
101+
* With ImGuiBackendFlags_RendererHasVtxOffset: may be >0 to support meshes larger than 64K vertices with 16-bit indices.
102+
*/
103+
public native int getCmdListCmdBufferVtxOffset(int cmdListIdx, int cmdBufferIdx); /*
104+
return IM_DRAW_DATA->CmdLists[cmdListIdx]->CmdBuffer[cmdBufferIdx].VtxOffset;
105+
*/
106+
107+
/**
108+
* Start offset in index buffer. Always equal to sum of ElemCount drawn so far.
109+
*/
110+
public native int getCmdListCmdBufferIdxOffset(int cmdListIdx, int cmdBufferIdx); /*
111+
return IM_DRAW_DATA->CmdLists[cmdListIdx]->CmdBuffer[cmdBufferIdx].IdxOffset;
112+
*/
84113

85-
// Set values
86-
env->SetIntField(object, totalVtxCountID, drawData->TotalVtxCount);
87-
env->SetIntField(object, totalIdxCountID, drawData->TotalIdxCount);
88-
env->SetIntField(object, CmdListsCountID, cmdListsCount);
114+
/**
115+
* Index buffer. Each command consume ImDrawCmd::ElemCount of those
116+
*/
117+
public native int getCmdListIdxBufferSize(int cmdListIdx); /*
118+
return IM_DRAW_DATA->CmdLists[cmdListIdx]->IdxBuffer.Size;
119+
*/
89120

90-
env->SetFloatField(object, displayPosXID, drawData->DisplayPos.x);
91-
env->SetFloatField(object, displayPosYID, drawData->DisplayPos.y);
121+
public ByteBuffer getCmdListIdxBufferData(final int cmdListIdx) {
122+
final int idxBufferCapacity = getCmdListIdxBufferSize(cmdListIdx) * SIZEOF_IM_DRAW_IDX;
123+
if (idxBuffer.capacity() < idxBufferCapacity) {
124+
idxBuffer = ByteBuffer.allocateDirect(idxBufferCapacity + COUNT_FACTOR).order(ByteOrder.nativeOrder());
125+
}
92126

93-
env->SetFloatField(object, displaySizeXID, drawData->DisplaySize.x);
94-
env->SetFloatField(object, displaySizeYID, drawData->DisplaySize.y);
127+
nGetCmdListIdxBufferData(cmdListIdx, idxBuffer, idxBufferCapacity);
95128

96-
env->SetFloatField(object, framebufferScaleXID, drawData->FramebufferScale.x);
97-
env->SetFloatField(object, framebufferScaleYID, drawData->FramebufferScale.y);
129+
idxBuffer.position(0);
130+
idxBuffer.limit(idxBufferCapacity);
98131

99-
ImDrawList** drawLists = drawData->CmdLists;
132+
return idxBuffer;
133+
}
100134

101-
int verticesOffset = 0;
102-
int indicesOffset = 0;
103-
int cmdOffset = 0;
135+
private native void nGetCmdListIdxBufferData(int cmdListIdx, ByteBuffer idxBuffer, int idxBufferCapacity); /*
136+
memcpy(idxBuffer, IM_DRAW_DATA->CmdLists[cmdListIdx]->IdxBuffer.Data, idxBufferCapacity);
137+
*/
104138

105-
for(int i = 0; i < cmdListsCount; i++) {
106-
ImDrawList& drawList = *drawLists[i];
107-
ImVector<ImDrawCmd>& imDrawCmdList = drawList.CmdBuffer;
108-
ImVector<ImDrawIdx>& idxBuffer = drawList.IdxBuffer;
109-
ImVector<ImDrawVert>& vtxBuffer = drawList.VtxBuffer;
139+
/**
140+
* Vertex buffer.
141+
*/
142+
public native int getCmdListVtxBufferSize(int cmdListIdx); /*
143+
return IM_DRAW_DATA->CmdLists[cmdListIdx]->VtxBuffer.Size;
144+
*/
110145

111-
float* vertexArrayDest = (float*)vertexBuffer;
112-
short* indexArrayDest = (short*)indexBuffer;
146+
public ByteBuffer getCmdListVtxBufferData(final int cmdListIdx) {
147+
final int vtxBufferCapacity = getCmdListVtxBufferSize(cmdListIdx) * SIZEOF_IM_DRAW_VERT;
148+
if (vtxBuffer.capacity() < vtxBufferCapacity) {
149+
vtxBuffer = ByteBuffer.allocateDirect(vtxBufferCapacity + COUNT_FACTOR).order(ByteOrder.nativeOrder());
150+
}
113151

114-
int colorSize = 1;
115-
int verticesItemSize = (4 + colorSize);
152+
nGetCmdListVtxBufferData(cmdListIdx, vtxBuffer, vtxBufferCapacity);
116153

117-
vertexArrayDest[verticesOffset++] = vtxBuffer.Size;
154+
vtxBuffer.position(0);
155+
vtxBuffer.limit(vtxBufferCapacity);
118156

119-
// copy vertices to Destination buffer
120-
for(int j = 0; j < vtxBuffer.Size; j++) {
121-
ImDrawVert v = vtxBuffer[j];
122-
float posX = v.pos.x;
123-
float posY = v.pos.y;
124-
float uvX = v.uv.x;
125-
float uvY = v.uv.y;
157+
return vtxBuffer;
158+
}
126159

127-
int byteIndex = (j * verticesItemSize) + verticesOffset;
160+
private native void nGetCmdListVtxBufferData(int cmdListIdx, ByteBuffer vtxBuffer, int vtxBufferCapacity); /*
161+
memcpy(vtxBuffer, IM_DRAW_DATA->CmdLists[cmdListIdx]->VtxBuffer.Data, vtxBufferCapacity);
162+
*/
128163

129-
float color = 0;
130-
memcpy(&color, &v.col, 4); // move unsigned int color to float
164+
///////// End of Render Methods
131165

132-
vertexArrayDest[byteIndex + 0] = posX;
133-
vertexArrayDest[byteIndex + 1] = posY;
134-
vertexArrayDest[byteIndex + 2] = uvX;
135-
vertexArrayDest[byteIndex + 3] = uvY;
136-
vertexArrayDest[byteIndex + 4] = color;
137-
}
138-
verticesOffset += vtxBuffer.Size * verticesItemSize;
166+
/**
167+
* Only valid after Render() is called and before the next NewFrame() is called.
168+
*/
169+
public native boolean getValid(); /*
170+
return IM_DRAW_DATA->Valid;
171+
*/
139172

140-
// copy index to destination buffer
141-
indexArrayDest[indicesOffset++] = idxBuffer.Size;
173+
/**
174+
* Number of ImDrawList* to render
175+
*/
176+
public native int getCmdListsCount(); /*
177+
return IM_DRAW_DATA->CmdListsCount;
178+
*/
142179

143-
for(int j = 0; j < idxBuffer.Size; j++) {
144-
indexArrayDest[j + indicesOffset] = idxBuffer[j];
145-
}
180+
/**
181+
* For convenience, sum of all ImDrawList's IdxBuffer.Size
182+
*/
183+
public native int getTotalIdxCount(); /*
184+
return IM_DRAW_DATA->TotalIdxCount;
185+
*/
146186

147-
indicesOffset += idxBuffer.Size;
187+
/**
188+
* For convenience, sum of all ImDrawList's VtxBuffer.Size
189+
*/
190+
public native int getTotalVtxCount(); /*
191+
return IM_DRAW_DATA->TotalVtxCount;
192+
*/
148193

149-
float* cmdArrayDest = (float*)cmdBuffer;
194+
/**
195+
* Upper-left position of the viewport to render (== upper-left of the orthogonal projection matrix to use)
196+
*/
197+
public native void getDisplayPos(ImVec2 dstImVec2); /*
198+
Jni::ImVec2Cpy(env, &IM_DRAW_DATA->DisplayPos, dstImVec2);
199+
*/
150200

151-
cmdArrayDest[cmdOffset++] = imDrawCmdList.Size;
152-
int bytesOffset = 0;
153-
int imDrawCmdSize = 1 + 4 + 1;
201+
/**
202+
* Size of the viewport to render (== io.DisplaySize for the main viewport)
203+
* (DisplayPos + DisplaySize == lower-right of the orthogonal projection matrix to use)
204+
*/
205+
public native void getDisplaySize(ImVec2 dstImVec2); /*
206+
Jni::ImVec2Cpy(env, &IM_DRAW_DATA->DisplaySize, dstImVec2);
207+
*/
154208

155-
for (int cmd_i = 0; cmd_i < imDrawCmdList.Size; cmd_i++) {
156-
const ImDrawCmd* pcmd = &imDrawCmdList[cmd_i];
209+
/**
210+
* Amount of pixels for each unit of DisplaySize. Based on io.DisplayFramebufferScale. Generally (1,1) on normal display, (2,2) on OSX with Retina display.
211+
*/
212+
public native void getFramebufferScale(ImVec2 dstImVec2); /*
213+
Jni::ImVec2Cpy(env, &IM_DRAW_DATA->FramebufferScale, dstImVec2);
214+
*/
157215

158-
float textureID = (float)(intptr_t)pcmd->TextureId;
159-
float tempArray [6] = {
160-
(float)pcmd->ElemCount,
161-
pcmd->ClipRect.x, pcmd->ClipRect.y,
162-
pcmd->ClipRect.z, pcmd->ClipRect.w,
163-
textureID
164-
};
216+
// Functions
165217

166-
memcpy((cmdArrayDest + (cmd_i * imDrawCmdSize) + cmdOffset), tempArray, imDrawCmdSize * 4);
167-
bytesOffset = bytesOffset + imDrawCmdSize;
168-
}
218+
/**
219+
* Helper to convert all buffers from indexed to non-indexed, in case you cannot render indexed. Note: this is slow and most likely a waste of resources.
220+
* Always prefer indexed rendering!
221+
*/
222+
public native void deIndexAllBuffers(); /*
223+
IM_DRAW_DATA->DeIndexAllBuffers();
224+
*/
169225

170-
cmdOffset += imDrawCmdList.Size * imDrawCmdSize;
171-
}
226+
/**
227+
* Helper to scale the ClipRect field of each ImDrawCmd. Use if your final output buffer is at a different scale than Dear ImGui expects,
228+
* or if there is a difference between your window resolution and framebuffer resolution.
229+
*/
230+
public native void scaleClipRects(float fbScaleX, float fbScaleY); /*
231+
const ImVec2 fbScale = ImVec2(fbScaleX, fbScaleY);
232+
IM_DRAW_DATA->ScaleClipRects(fbScale);
172233
*/
173234
}

imgui-binding/src/main/java/imgui/ImDrawList.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,11 +55,16 @@ public final class ImDrawList {
5555
drawListTypeID = env->GetFieldID(jImDrawListClass, "drawListType", "I");
5656
*/
5757

58-
// Flags, you may poke into these to adjust anti-aliasing settings per-primitive.
58+
/**
59+
* Flags, you may poke into these to adjust anti-aliasing settings per-primitive.
60+
*/
5961
public native int getImDrawListFlags(); /*
6062
return IM_DRAW_LIST->Flags;
6163
*/
6264

65+
/**
66+
* Flags, you may poke into these to adjust anti-aliasing settings per-primitive.
67+
*/
6368
public native void setImDrawListFlags(int imDrawListFlags); /*
6469
IM_DRAW_LIST->Flags = imDrawListFlags;
6570
*/

0 commit comments

Comments
 (0)