Using Vertex Buffer Object method to speed up the rendering

This commit is contained in:
Andrea Cavalli 2017-09-23 23:23:26 +02:00
parent 30512b143d
commit 209109d75c
12 changed files with 230 additions and 116 deletions

View File

@ -58,15 +58,15 @@ public class Main {
if (arg.contains("headless")) { if (arg.contains("headless")) {
Utils.headlessOverride = true; Utils.headlessOverride = true;
} }
if (arg.contains("console-8")) { if (arg.contains("headless-8")) {
Utils.headlessOverride = true; Utils.headlessOverride = true;
Utils.forceEngine = "console-8"; Utils.forceEngine = "console-8";
} }
if (arg.contains("console-256")) { if (arg.contains("headless-256")) {
Utils.headlessOverride = true; Utils.headlessOverride = true;
Utils.forceEngine = "console-256"; Utils.forceEngine = "console-256";
} }
if (arg.contains("console-24bit")) { if (arg.contains("headless-24bit")) {
Utils.headlessOverride = true; Utils.headlessOverride = true;
Utils.forceEngine = "console-24bit"; Utils.forceEngine = "console-24bit";
} }
@ -81,7 +81,8 @@ public class Main {
Utils.msDosMode = true; Utils.msDosMode = true;
} }
} }
DisplayManager.setBrightness(0.5f); DisplayManager.preInitialization();
DisplayManager.setBrightness(0.2f);
Keyboard.startKeyboard(); Keyboard.startKeyboard();
} }

View File

@ -1,6 +1,9 @@
package org.warp.picalculator.gui; package org.warp.picalculator.gui;
import java.io.IOException; import java.io.IOException;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;
import java.util.concurrent.Semaphore; import java.util.concurrent.Semaphore;
import org.warp.picalculator.Main; import org.warp.picalculator.Main;
@ -26,21 +29,33 @@ public final class DisplayManager implements RenderingLoop {
public static DisplayManager INSTANCE; public static DisplayManager INSTANCE;
private static float brightness; private static float brightness;
public static final GraphicEngine engine = chooseGraphicEngine(); public static final GraphicEngine engine;
public static final boolean supportsPauses = engine.doesRefreshPauses(); public static final boolean supportsPauses;
public static Renderer renderer; public static Renderer renderer;
public static Skin guiSkin; public static Skin guiSkin;
public static BinaryFont[] fonts; public static BinaryFont[] fonts;
public static String error = null; public static String error;
public String[] errorStackTrace = null; public String[] errorStackTrace;
public final static int[] glyphsHeight = new int[] { 9, 6, 12, 9 }; public final static int[] glyphsHeight;
public static Screen screen; public static Screen screen;
public static String displayDebugString = ""; public static String displayDebugString;
public static ObjectArrayList<GUIErrorMessage> errorMessages = new ObjectArrayList<>(); public static ObjectArrayList<GUIErrorMessage> errorMessages;
static {
engine = chooseGraphicEngine();
supportsPauses = engine.doesRefreshPauses();
glyphsHeight = new int[] { 9, 6, 12, 9 };
displayDebugString = "";
errorMessages = new ObjectArrayList<>();
}
public static void preInitialization() {
//Nothing. When called for the first time the static methods will be loaded
}
public DisplayManager(Screen screen) { public DisplayManager(Screen screen) {
setScreen(screen); setScreen(screen);
INSTANCE = this; INSTANCE = this;
@ -236,7 +251,8 @@ public final class DisplayManager implements RenderingLoop {
private void draw_init() { private void draw_init() {
if (engine.supportsFontRegistering()) { if (engine.supportsFontRegistering()) {
for (BinaryFont f : engine.getRegisteredFonts()) { List<BinaryFont> fontsIterator = engine.getRegisteredFonts();
for (BinaryFont f : fontsIterator) {
if (!f.isInitialized()) { if (!f.isInitialized()) {
f.initialize(engine); f.initialize(engine);
} }

View File

@ -28,7 +28,7 @@ public class GraphicUtils {
RAD = (float) Math.PI / 180.0f; RAD = (float) Math.PI / 180.0f;
DEG = 180.0f / (float) Math.PI; DEG = 180.0f / (float) Math.PI;
SIN_BITS = 12; SIN_BITS = 8;
SIN_MASK = ~(-1 << SIN_BITS); SIN_MASK = ~(-1 << SIN_BITS);
SIN_COUNT = SIN_MASK + 1; SIN_COUNT = SIN_MASK + 1;

View File

@ -1,7 +1,8 @@
package org.warp.picalculator.gui.graphicengine; package org.warp.picalculator.gui.graphicengine;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.List;
import java.util.Vector;
public interface GraphicEngine { public interface GraphicEngine {
@ -43,7 +44,11 @@ public interface GraphicEngine {
public boolean doesRefreshPauses(); public boolean doesRefreshPauses();
public boolean supportsFontRegistering(); public default boolean supportsFontRegistering() {
return false;
}
public ArrayList<BinaryFont> getRegisteredFonts(); public default List<BinaryFont> getRegisteredFonts() {
return null;
}
} }

View File

@ -193,16 +193,4 @@ public class CPUEngine implements GraphicEngine {
public boolean doesRefreshPauses() { public boolean doesRefreshPauses() {
return true; return true;
} }
@Override
public boolean supportsFontRegistering() {
// TODO Auto-generated method stub
return false;
}
@Override
public ArrayList<BinaryFont> getRegisteredFonts() {
// TODO Auto-generated method stub
return null;
}
} }

View File

@ -2,6 +2,10 @@ package org.warp.picalculator.gui.graphicengine.gpu;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Vector;
import java.util.concurrent.CopyOnWriteArrayList;
import org.warp.picalculator.Main; import org.warp.picalculator.Main;
import org.warp.picalculator.Utils; import org.warp.picalculator.Utils;
@ -12,7 +16,7 @@ import org.warp.picalculator.gui.graphicengine.Skin;
import com.jogamp.opengl.GLProfile; import com.jogamp.opengl.GLProfile;
public class GPUEngine implements org.warp.picalculator.gui.graphicengine.GraphicEngine { public class GPUEngine implements GraphicEngine {
private volatile boolean initialized = false; private volatile boolean initialized = false;
private volatile boolean created = false; private volatile boolean created = false;
@ -20,7 +24,7 @@ public class GPUEngine implements org.warp.picalculator.gui.graphicengine.Graphi
private RenderingLoop d; private RenderingLoop d;
private GPURenderer r; private GPURenderer r;
int[] size = new int[] { Main.screenSize[0], Main.screenSize[1] }; int[] size = new int[] { Main.screenSize[0], Main.screenSize[1] };
private final ArrayList<BinaryFont> registeredFonts = new ArrayList<BinaryFont>(); private final CopyOnWriteArrayList<BinaryFont> registeredFonts = new CopyOnWriteArrayList<BinaryFont>();
@Override @Override
public int[] getSize() { public int[] getSize() {
@ -165,7 +169,7 @@ public class GPUEngine implements org.warp.picalculator.gui.graphicengine.Graphi
} }
@Override @Override
public ArrayList<BinaryFont> getRegisteredFonts() { public CopyOnWriteArrayList<BinaryFont> getRegisteredFonts() {
return registeredFonts; return registeredFonts;
} }

View File

@ -27,13 +27,16 @@ public class GPURenderer implements Renderer {
public static GL2ES1 gl; public static GL2ES1 gl;
private static final int ELEMENT_VERTICES_COUNT = 6;
private static final int ELEMENTS_MAX_COUNT_PER_BUFFER = 128;
private final DeallocationHelper deallocationHelper = new DeallocationHelper(); private final DeallocationHelper deallocationHelper = new DeallocationHelper();
FloatBuffer fbVertices; FloatBuffer fbVertices;
FloatBuffer txVertices; FloatBuffer txVertices;
FloatBuffer colVertices; FloatBuffer colVertices;
int fbElements; int fbElements;
float[] currentColor = new float[16]; float[] currentColor = new float[24];
float[] currentClearColorARGBf = new float[] { 1f, 197f / 255f, 194f / 255f, 175f / 255f }; float[] currentClearColorARGBf = new float[] { 1f, 197f / 255f, 194f / 255f, 175f / 255f };
boolean currentTexEnabled; boolean currentTexEnabled;
Texture currentTex; Texture currentTex;
@ -47,17 +50,42 @@ public class GPURenderer implements Renderer {
final float red = (r) / 255f; final float red = (r) / 255f;
final float gre = (gg) / 255f; final float gre = (gg) / 255f;
final float blu = (b) / 255f; final float blu = (b) / 255f;
currentColor = new float[] { red, gre, blu, 1.0f, red, gre, blu, 1.0f, red, gre, blu, 1.0f, red, gre, blu, 1.0f, }; //currentColor = new float[] { red, gre, blu, 1.0f, red, gre, blu, 1.0f, red, gre, blu, 1.0f, red, gre, blu, 1.0f, };
currentColor = new float[] {
red, gre, blu, 1.0f,
red, gre, blu, 1.0f,
red, gre, blu, 1.0f,
red, gre, blu, 1.0f,
red, gre, blu, 1.0f,
red, gre, blu, 1.0f,
}; //OK
} }
@Override @Override
public void glColor3f(float red, float gre, float blu) { public void glColor3f(float red, float gre, float blu) {
currentColor = new float[] { red, gre, blu, 1.0f, red, gre, blu, 1.0f, red, gre, blu, 1.0f, red, gre, blu, 1.0f, }; // currentColor = new float[] { red, gre, blu, 1.0f, red, gre, blu, 1.0f, red, gre, blu, 1.0f, red, gre, blu, 1.0f, };
currentColor = new float[] {
red, gre, blu, 1.0f,
red, gre, blu, 1.0f,
red, gre, blu, 1.0f,
red, gre, blu, 1.0f,
red, gre, blu, 1.0f,
red, gre, blu, 1.0f,
};//OK
} }
@Override @Override
public void glColor4f(float red, float gre, float blu, float alp) { public void glColor4f(float red, float gre, float blu, float alp) {
currentColor = new float[] { red, gre, blu, alp, red, gre, blu, alp, red, gre, blu, alp, red, gre, blu, alp, }; // currentColor = new float[] { red, gre, blu, alp, red, gre, blu, alp, red, gre, blu, alp, red, gre, blu, alp, };
currentColor = new float[] {
red, gre, blu, alp,
red, gre, blu, alp,
red, gre, blu, alp,
red, gre, blu, alp,
red, gre, blu, alp,
red, gre, blu, alp,
};//ok
} }
@Override @Override
@ -89,7 +117,15 @@ public class GPURenderer implements Renderer {
final float gre = (g) / 255f; final float gre = (g) / 255f;
final float blu = (b) / 255f; final float blu = (b) / 255f;
final float alp = (a) / 255f; final float alp = (a) / 255f;
currentColor = new float[] { red, gre, blu, alp, red, gre, blu, alp, red, gre, blu, alp, red, gre, blu, alp, }; //currentColor = new float[] { red, gre, blu, alp, red, gre, blu, alp, red, gre, blu, alp, red, gre, blu, alp, };
currentColor = new float[] {
red, gre, blu, alp,
red, gre, blu, alp,
red, gre, blu, alp,
red, gre, blu, alp,
red, gre, blu, alp,
red, gre, blu, alp,
};//OK
} }
@Override @Override
@ -125,8 +161,37 @@ public class GPURenderer implements Renderer {
uvX /= currentTexWidth; uvX /= currentTexWidth;
uvHeight /= currentTexHeight; uvHeight /= currentTexHeight;
uvY = 1 - uvY / currentTexHeight - uvHeight; uvY = 1 - uvY / currentTexHeight - uvHeight;
final float[] vertices = { x, y, 0.0f, x, y + height, 0.0f, x + width, y, 0.0f, x + width, y + height, 0.0f, }; // final float[] vertices = { x, y, 0.0f, x, y + height, 0.0f, x + width, y, 0.0f, x + width, y + height, 0.0f, };
final float[] tex_vertices = { uvX, uvY + uvHeight, uvX, uvY, uvX + uvWidth, uvY + uvHeight, uvX + uvWidth, uvY, }; // final float[] tex_vertices = { uvX, uvY + uvHeight, uvX, uvY, uvX + uvWidth, uvY + uvHeight, uvX + uvWidth, uvY, };
//V0 x, y, 0.0f
//V1 x, y + height, 0.0f
//V2 x + width, y, 0.0f
//V3 x + width, y + height, 0.0f
//NV0 = V1
//NV1 = V3
//NV2 = V0
//NV3 = V0
//NV4 = V3
//NV5 = V2
final float[] vertices = {
x, y + height, 0.0f,
x + width, y + height, 0.0f,
x, y, 0.0f,
x, y, 0.0f,
x + width, y + height, 0.0f,
x + width, y, 0.0f
};
final float[] tex_vertices = {
uvX, uvY,
uvX + uvWidth, uvY,
uvX, uvY + uvHeight,
uvX, uvY + uvHeight,
uvX + uvWidth, uvY,
uvX + uvWidth, uvY + uvHeight
};
fbElements++; fbElements++;
fbVertices.put(vertices); fbVertices.put(vertices);
txVertices.put(tex_vertices); txVertices.put(tex_vertices);
@ -136,8 +201,37 @@ public class GPURenderer implements Renderer {
@Override @Override
public void glFillColor(float x0, float y0, float w1, float h1) { public void glFillColor(float x0, float y0, float w1, float h1) {
disableTexture(); disableTexture();
final float[] vertices = { x0, y0, 0.0f, x0, y0 + h1, 0.0f, x0 + w1, y0, 0.0f, x0 + w1, y0 + h1, 0.0f, }; // final float[] vertices = { x0, y0, 0.0f, x0, y0 + h1, 0.0f, x0 + w1, y0, 0.0f, x0 + w1, y0 + h1, 0.0f, };
final float[] tex_vertices = { 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, }; // final float[] tex_vertices = { 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, };
//V0 x0, y0, 0.0f
//V1 x0, y0 + h1, 0.0f
//V2 x0 + w1, y0, 0.0f
//V3 x0 + w1, y0 + h1, 0.0f
//NV0 = V1
//NV1 = V3
//NV2 = V0
//NV3 = V0
//NV4 = V3
//NV5 = V2
final float[] vertices = {
x0, y0 + h1, 0.0f,
x0 + w1, y0 + h1, 0.0f,
x0, y0, 0.0f,
x0, y0, 0.0f,
x0 + w1, y0 + h1, 0.0f,
x0 + w1, y0, 0.0f,
};
final float[] tex_vertices = {
0.0f, 0.0f,
1.0f, 0.0f,
0.0f, 1.0f,
0.0f, 1.0f,
1.0f, 0.0f,
1.0f, 1.0f,
};
fbElements++; fbElements++;
fbVertices.put(vertices); fbVertices.put(vertices);
txVertices.put(tex_vertices); txVertices.put(tex_vertices);
@ -215,37 +309,39 @@ public class GPURenderer implements Renderer {
return tex; return tex;
} }
@Override public void startDrawCycle(boolean first) {
public void glClearSkin() {
if (currentTex != null) {
currentTex = null;
endDrawCycle();
startDrawCycle();
}
}
public void startDrawCycle() {
if (fbVertices == null) { if (fbVertices == null) {
fbVertices = Buffers.newDirectFloatBuffer(3 * 4); fbVertices = Buffers.newDirectFloatBuffer(3 * ELEMENT_VERTICES_COUNT * ELEMENTS_MAX_COUNT_PER_BUFFER);
txVertices = Buffers.newDirectFloatBuffer(2 * 4); txVertices = Buffers.newDirectFloatBuffer(2 * ELEMENT_VERTICES_COUNT * ELEMENTS_MAX_COUNT_PER_BUFFER);
colVertices = Buffers.newDirectFloatBuffer(4 * 4); colVertices = Buffers.newDirectFloatBuffer(4 * ELEMENT_VERTICES_COUNT * ELEMENTS_MAX_COUNT_PER_BUFFER);
} }
fbElements = 0; if (first || fbVertices == null || cycleEnded) {
fbElements = 0;
}
cycleEnded = false;
} }
private boolean precTexEnabled; private boolean precTexEnabled;
private Texture precTex; private Texture precTex;
private boolean cycleEnded = true;
public void endDrawCycle() { public void updateDrawCycle() {
fbVertices.rewind(); updateDrawCycle(false, false);
txVertices.rewind(); }
colVertices.rewind();
public void updateDrawCycle(boolean first, boolean last) {
gl.glColorPointer(4, GL.GL_FLOAT, 0, colVertices); final boolean textureChange = precTexEnabled != currentTexEnabled || precTex != currentTex;
gl.glTexCoordPointer(2, GL.GL_FLOAT, 0, txVertices); final boolean changeRequired = last || fbElements >= ELEMENTS_MAX_COUNT_PER_BUFFER;
gl.glVertexPointer(3, GL.GL_FLOAT, 0, fbVertices); if (first) {
startDrawCycle(true);
if (precTexEnabled != currentTexEnabled | precTex != currentTex) { }
if (textureChange) {
if (!first && fbElements > 0) {
endDrawCycle();
if (!last) {
startDrawCycle(true);
}
}
precTexEnabled = currentTexEnabled; precTexEnabled = currentTexEnabled;
precTex = currentTex; precTex = currentTex;
if (currentTexEnabled) { if (currentTexEnabled) {
@ -254,9 +350,34 @@ public class GPURenderer implements Renderer {
} else { } else {
gl.glDisable(GL.GL_TEXTURE_2D); gl.glDisable(GL.GL_TEXTURE_2D);
} }
} else if (!first) {
if (fbElements > 0 && changeRequired) {
endDrawCycle();
if (!last) {
startDrawCycle(false);
}
}
} }
}
public void endDrawCycle() {
fbVertices.limit(fbVertices.position());
txVertices.limit(txVertices.position());
colVertices.limit(colVertices.position());
fbVertices.rewind();
txVertices.rewind();
colVertices.rewind();
gl.glDrawArrays(GL.GL_TRIANGLE_STRIP, 0, fbElements * 4); gl.glVertexPointer(3, GL.GL_FLOAT, 0, fbVertices);
gl.glTexCoordPointer(2, GL.GL_FLOAT, 0, txVertices);
gl.glColorPointer(4, GL.GL_FLOAT, 0, colVertices);
fbVertices.limit(fbVertices.capacity());
txVertices.limit(txVertices.capacity());
colVertices.limit(colVertices.capacity());
gl.glDrawArrays(GL.GL_TRIANGLES, 0, fbElements * ELEMENT_VERTICES_COUNT);
//gl.glDrawArrays(GL.GL_TRIANGLE_STRIP, 0, fbElements * ELEMENT_VERTICES_COUNT);
cycleEnded = true;
// deleteBuffer(fbVertices); // deleteBuffer(fbVertices);
// deleteBuffer(txVertices); // deleteBuffer(txVertices);
@ -272,22 +393,28 @@ public class GPURenderer implements Renderer {
} }
} }
@Override
public void glClearSkin() {
if (currentTex != null) {
currentTex = null;
updateDrawCycle();
}
}
void disableTexture() { void disableTexture() {
endDrawCycle();
startDrawCycle();
currentTexEnabled = false; currentTexEnabled = false;
updateDrawCycle();
} }
void enableTexture() { void enableTexture() {
endDrawCycle();
startDrawCycle();
currentTexEnabled = true; currentTexEnabled = true;
updateDrawCycle();
} }
void useTexture(Texture t, float w, float h) { void useTexture(Texture t, float w, float h) {
enableTexture();
currentTex = t; currentTex = t;
currentTexWidth = w; currentTexWidth = w;
currentTexHeight = h; currentTexHeight = h;
enableTexture();
} }
} }

View File

@ -342,11 +342,11 @@ class NEWTWindow implements GLEventListener {
gl.glEnableClientState(GLPointerFunc.GL_VERTEX_ARRAY); gl.glEnableClientState(GLPointerFunc.GL_VERTEX_ARRAY);
gl.glEnableClientState(GLPointerFunc.GL_TEXTURE_COORD_ARRAY); gl.glEnableClientState(GLPointerFunc.GL_TEXTURE_COORD_ARRAY);
renderer.startDrawCycle(); renderer.updateDrawCycle(true, false);
disp.repaint(); disp.repaint();
renderer.endDrawCycle(); renderer.updateDrawCycle(false, true);
GPURenderer.gl = null; GPURenderer.gl = null;

View File

@ -330,14 +330,4 @@ public class Headless24bitEngine implements org.warp.picalculator.gui.graphiceng
public boolean doesRefreshPauses() { public boolean doesRefreshPauses() {
return true; return true;
} }
@Override
public boolean supportsFontRegistering() {
return false;
}
@Override
public ArrayList<BinaryFont> getRegisteredFonts() {
return null;
}
} }

View File

@ -280,16 +280,4 @@ public class Headless256Engine implements org.warp.picalculator.gui.graphicengin
public boolean doesRefreshPauses() { public boolean doesRefreshPauses() {
return true; return true;
} }
@Override
public boolean supportsFontRegistering() {
// TODO Auto-generated method stub
return false;
}
@Override
public ArrayList<BinaryFont> getRegisteredFonts() {
// TODO Auto-generated method stub
return null;
}
} }

View File

@ -281,16 +281,4 @@ public class Headless8Engine implements org.warp.picalculator.gui.graphicengine.
public boolean doesRefreshPauses() { public boolean doesRefreshPauses() {
return true; return true;
} }
@Override
public boolean supportsFontRegistering() {
// TODO Auto-generated method stub
return false;
}
@Override
public ArrayList<BinaryFont> getRegisteredFonts() {
// TODO Auto-generated method stub
return null;
}
} }

View File

@ -82,14 +82,18 @@ public class MathParser {
boolean lastLoopDidSomething; boolean lastLoopDidSomething;
Function lastElement; Function lastElement;
Utils.out.print(Utils.OUTPUTLEVEL_DEBUG_MAX, "\tStatus: "); if (Utils.debugOn) {
for (Function f : functionsList) { Utils.out.print(Utils.OUTPUTLEVEL_DEBUG_MAX, "\tStatus: ");
Utils.out.print(Utils.OUTPUTLEVEL_DEBUG_MAX, f.toString()); for (Function f : functionsList) {
Utils.out.print(Utils.OUTPUTLEVEL_DEBUG_MAX, f.toString());
}
Utils.out.println(Utils.OUTPUTLEVEL_DEBUG_MAX);
} }
Utils.out.println(Utils.OUTPUTLEVEL_DEBUG_MAX);
for (MathParserStep step : steps) { for (MathParserStep step : steps) {
Utils.out.println(2, "Stack fixing step \""+step.getStepName()+"\""); if (Utils.debugOn) {
Utils.out.println(2, "Stack fixing step \""+step.getStepName()+"\"");
}
int stepQty = step.requiresReversedIteration()?-1:1, initialIndex = step.requiresReversedIteration()?functionsList.size()-1:0; int stepQty = step.requiresReversedIteration()?-1:1, initialIndex = step.requiresReversedIteration()?functionsList.size()-1:0;
do { do {
lastLoopDidSomething = false; lastLoopDidSomething = false;
@ -107,11 +111,14 @@ public class MathParser {
curIndex.i += stepQty; curIndex.i += stepQty;
} }
} while (lastLoopDidSomething); } while (lastLoopDidSomething);
Utils.out.print(Utils.OUTPUTLEVEL_DEBUG_MAX, "\tStatus: ");
for (Function f : functionsList) { if (Utils.debugOn) {
Utils.out.print(Utils.OUTPUTLEVEL_DEBUG_MAX, f.toString()); Utils.out.print(Utils.OUTPUTLEVEL_DEBUG_MAX, "\tStatus: ");
for (Function f : functionsList) {
Utils.out.print(Utils.OUTPUTLEVEL_DEBUG_MAX, f.toString());
}
Utils.out.println(Utils.OUTPUTLEVEL_DEBUG_MAX);
} }
Utils.out.println(Utils.OUTPUTLEVEL_DEBUG_MAX);
} }
// //Phase 4 // //Phase 4