I am trying to use a single thread to display three separate TextureViews from a UI thread using canvas lock / unlock. The observed problem is the constant flickering of each of the presented Texture views, with a flicker consisting of a DIFFERENT TextureView frame. So, for example, I draw frames A, B, and C in that order. Frame C will appear accurate, however frames A and B will flicker with random instances of frame C, and frame A will sometimes flicker with instances of frame B.
I read the documentation describing Android Core Graphics, and I have a pretty good idea of how the android buffering system works. In short, my suspicion is that I am making the lockCanvas / unlockCanvasAndPost call too quickly in a row and that the framebuffer cannot fulfill my request and just draws the previous (wrong) frame.
I tried several things to solve this problem. Trying to use the choreographer to wait for VSYNC to continue calling the canvas helped, but was expected to reduce the frame rate, but the problem was still there. I also tried an alternative rendering cycle without a sleep command, without distinguishing the observed phenomenon.
In fact, I do not know how to solve this problem, and was hoping to get some external input from it. Thanks in advance, the code snippet below:
The main rendering cycle:
while (running) { long now = System.nanoTime(); long updateLength = now - lastLoopTime; lastLoopTime = now; float delta = updateLength / ((float)OPTIMAL_TIME.get()); lastFpsTime += updateLength; fps++; if (lastFpsTime >= 1000000000) { Log.e(TAG, "(FPS Target: " + TARGET_FPS+ " ,FPS Actual: " + fps + ")"); lastFpsTime = 0; fps = 0; } for (MyTextureView mtv : mItemList){ if (!mtv.isLocked()) { mtv.doUpdate(delta); mtv.doRender(); } } long sleepTime = (lastLoopTime-System.nanoTime() + OPTIMAL_TIME.get())/1000000; sleepTime = sleepTime < 0 ? 0 : sleepTime; try{ Thread.sleep( sleepTime ); } catch (InterruptedException e) { e.printStackTrace(); } }
MyTextureView doRender () method:
public void doRender() { doubleBufferCanvas.drawPaint(Colors.BLACK); doDraw(doubleBufferCanvas);