Why is lockCanvas () slow?

I am implementing a SurfaceView subclass where I run a separate thread to draw on SurfaceHolders canvas. I measure the time before and after the lockCanvas() call, and I get from about 70 ms to 100 ms. Can anyone tell me why I get such high timings? Here's the relevant piece of code:

 public class TestView extends SurfaceView implements SurfaceHolder.Callback { .... boolean created; public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { mThread = new DrawingThread(mHolder, true); mThread.onWindowResize(width, height); mThread.start(); } public void surfaceCreated(SurfaceHolder holder) { created = true; } public void surfaceDestroyed(SurfaceHolder holder) { created = false; } class DrawingThread extends Thread { public void run() { while(created) { Canvas canvas = null; try { long t0 = System.currentTimeMillis(); canvas = holder.lockCanvas(null); long t1 = System.currentTimeMillis(); Log.i(TAG, "Timing: " + ( t1 - t0) ); } finally { holder.unlockCanvasAndPost(canvas); } } 
+6
source share
3 answers

You create a stream every time the surface changes. You must start your thread in surfaceCreated and kill it in surfaceDestroyed . surfaceChanged used to resize your surface.

From SurfaceView. surfaceCreated docs:

This is called immediately after the surface is first created. Implementations of this should run any desired rendering code . Please note that only one stream can be drawn on the surface , so you should not paint in Surface here if your regular rendering is in another stream.

Multiple threads are likely to make you strangle. From SurfaceHolder. lockCanvas docs:

If you call this repeatedly when the surface is not ready (before Callback.surfaceCreated or after Callback.surfaceDestroyed), your calls will be throttled at a slow speed to avoid CPU consumption.

However, I am not sure if this is the only problem. Is surfaceChanged called multiple times?

+4
source

This is due to how lockCanvas actually implemented in the Android graphics environment.

You probably already know that lockCanvas will return to you the free portion of memory that you will be using. For free , this means that this memory is not used for composition, not for display. Internally, simply put, SurfaceView is backed by a double buffer, one for drawing, one for composition / display. This double buffer is managed by BufferQueque. If composition / rendering is slower than drawing, we need to wait until we have a free buffer.

+1
source

Source: https://habr.com/ru/post/888181/


All Articles