how can reduce the time taken to draw all my components?
as, specifically, PGraphics.beginDraw()
and PGraphics.endDraw()
calls are expensive if there are a lot of them in a single call
as if i do 400 by 400
i get 60 fps
if i do fullscreen i get half that
however if i do not add any applications then i get 60fps in fullscreen
with 0 applications i get 60
with 1 i get 54.9
with 2 i get 43
with 3 i get 36
with 4 i get 31
with 5 i get 26
and so on
how can i avoid this while still retaining the ability to off-screen render?
the following is a complete minimal example of this
Compositor compositor;
void settings() {
fullScreen(P3D); // 31 fps
//size(400, 400, P3D); // 60 fps
}
class Applications_Cube extends Window {
@Override
void draw() {
graphics.lights();
graphics.background(0);
graphics.noStroke();
graphics.translate(width/2, height/2);
graphics.rotateX(frameCount/100.0);
graphics.rotateY(frameCount/200.0);
graphics.box(40);
}
}
void addApplications() {
compositor.add(new Applications_Cube(), 200, 200);
compositor.setLocation(0, 0);
compositor.add(new Applications_Cube(), 200, 200);
compositor.setLocation(0, 200);
compositor.add(new Applications_Cube(), 200, 200);
compositor.setLocation(200, 0);
compositor.add(new Applications_Cube(), 200, 200);
compositor.setLocation(200, 200);
}
void setup() {
compositor = new Compositor(width, height);
compositor.displayFPS = true;
addApplications();
compositor.setup();
}
void draw() {
compositor.draw();
}
// TODO: rename to Window manager and split to WindowManager and Compositor
// for now, assume that the compositor draws what the window manager renders
// however this may be incorrect, so avoid doing this for the time being
// untill more information is available on the difference between a
// compositor and a window manager
// from https://github.com/mgood7123/AndroidCompositor/blob/5232f327e22df10368c780287822bc2320b22f06/app/src/main/jni/compositor.cpp#L17
// my current understanding of all this is that a compositor will render each
// application's frame buffer, and a window manager such as KDE or GNOME or I3,
// will work WITH the compositor retrieving information about windows and their
// position, then draw boarders around those windows and implement either stacking
// or tiling like functionality depending on the windowing system type and assumably
// send information back to the compositor such as updates on window changes.
// for example if the window is minimized or its position changes, the compositor
// will then redraw itself as it sees fit according to the received information
// end from https://github.com/mgood7123/AndroidCompositor/blob/5232f327e22df10368c780287822bc2320b22f06/app/src/main/jni/compositor.cpp#L17
// TODO: optimize focus algorithm
class Compositor {
public PGraphics graphics;
ArrayList<WindowObject> windows = new ArrayList<WindowObject>();
WindowObject w;
int windowFocus = -1;
int lastWindowFocus = -1;
boolean displayFPS = false;
Compositor(int width, int height) {
graphics = createGraphics(width, height, P3D);
}
void add(Window window, int width, int height) {
w = new WindowObject(width, height);
windows.add(w);
w.attach(window);
}
void setLocation(int x, int y) {
w.x = x;
w.y = y;
}
void drawGraphics() {
if (displayFPS) {
graphics.beginDraw();
int oldColor = graphics.fillColor;
graphics.fill(255);
graphics.textSize(16);
graphics.text("FPS: " + frameRate, 10, 20);
graphics.fill(oldColor);
graphics.endDraw();
}
image(graphics, 0, 0);
}
void drawGraphics(WindowObject window) {
graphics.image(
window.graphics,
window.x,
window.y,
window.width,
window.height
);
}
void setup() {
graphics.beginDraw();
for (WindowObject window : windows) {
window.setup();
drawGraphics(window);
}
graphics.endDraw();
drawGraphics();
}
void draw() {
graphics.beginDraw();
graphics.background(0);
for (WindowObject window : windows) {
window.draw();
drawGraphics(window);
}
graphics.endDraw();
drawGraphics();
}
}
class Window {
public PGraphics graphics = null;
int height;
int width;
int x, y;
int mouseX, mouseY;
Window() {
} // implicit super constructor required
void onBeforeResize() {
}
String onRequestType() {
return P3D;
}
void onAfterResize() {
}
void setup() {
graphics.background(0);
}
void draw() {
graphics.background(0);
}
}
class WindowObject {
public PGraphics graphics;
Window window;
int height;
int width;
int x;
int y;
int borderTop = 20;
int borderLeft = 3;
int borderBottom = 3;
int borderRight = 3;
WindowObject() {
} // implicit super constructor required
WindowObject(int width, int height) {
this.width = width;
this.height = height;
graphics = createGraphics(width, height, P3D);
}
void attach(Window window) {
this.window = window;
this.window.x = borderLeft;
this.window.width = width-borderLeft-borderRight;
this.window.y = borderTop;
this.window.height = height-borderTop-borderBottom;
}
void clearScreen() {
graphics.background(0);
}
void drawBordersWithFill(int fill__) {
graphics.rectMode(CORNER);
graphics.stroke(0);
graphics.fill(fill__);
graphics.rect(0, 0, width, height, 10);
}
void drawBorders() {
drawBordersWithFill(87);
}
void drawGraphics() {
graphics.endDraw();
window.graphics.beginDraw();
// draw fps
window.graphics.endDraw();
graphics.beginDraw();
graphics.image(window.graphics, window.x, window.y, window.width, window.height);
}
void drawWindow() {
graphics.beginDraw();
clearScreen();
drawBorders();
drawGraphics();
graphics.endDraw();
}
void resizeWindow() {
String type = window.onRequestType();
window.onBeforeResize();
window.graphics = createGraphics(window.width, window.height, type);
window.onAfterResize();
}
void setup() {
resizeWindow();
window.graphics.beginDraw();
window.setup();
window.graphics.endDraw();
drawWindow();
}
void draw() {
window.graphics.beginDraw();
window.draw();
window.graphics.endDraw();
drawWindow();
}
}