Android系列:surface的绘制原理

2,794 阅读1分钟

1.几个问题

  • surface绘制的buffer是怎么来的
  • 绘制完的buffer是怎么提交的

2.绘制的时候怎么申请到buffer

仍然在ViewRootImpl中进行

 private void performDraw() {
     draw(fullRedrawNeeded);
 }
 
  private void draw(boolean fullRedrawNeeded) {
      drawSoftware();
  }
  
 private boolean drawSoftware(Surface surface, AttachInfo attachInfo, int xoff, int yoff,
            boolean scalingRequired, Rect dirty) {
                //获取Canvas 就是buffer
                Canvas canvas = mSurface.lockCanvas(dirty);
                mView.draw(canvas);
                //提交 buffer
                surface.unlockCanvasAndPost(canvas);
            }
            
            

[-> Surface]

在surface中去获取canvas,也就是锁定一块画布

    public Canvas lockCanvas(Rect inOutDirty)
            throws Surface.OutOfResourcesException, IllegalArgumentException {
        synchronized (mLock) {
            mLockedObject = nativeLockCanvas(mNativeObject, mCanvas, inOutDirty);
            return mCanvas;
        }
    }
static jlong nativeLockCanvas(JNIEnv* env, jclass clazz,
        jlong nativeObject, jobject canvasObj, jobject dirtyRectObj) {
        // 获取surface 其中nativeObject就是用来获取surface的变量
            sp<Surface> surface(reinterpret_cast<Surface *>(nativeObject));
            
            ANativeWindow_Buffer outBuffer;
            surface->lock(&outBuffer, dirtyRectPtr);
        }

这里有两个概念:前台buffer和后台buffer,前台buffer用于展示,后台的用于绘制

[-> Surface.cpp]

int Surface::dequeueBuffer(android_native_buffer_t** buffer, int* fenceFd) {
      
      status_t result = mGraphicBufferProducer->dequeueBuffer(&buf, &fence, reqWidth, reqHeight,
                                                            reqFormat, reqUsage, &mBufferAge,
                                                            enableFrameTimestamps ? &frameTimestamps
                                                                                  : nullptr);
    
       if ((result & IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION) || gbuf == nullptr) {
       // 使用GraphicBufferProducer创建buffer
         result = mGraphicBufferProducer->requestBuffer(buf, &gbuf);
        }
        
    }

3.buffer的提交

status_t Surface::unlockAndPost()
{

    int fd = -1;
    status_t err = mLockedBuffer->unlockAsync(&fd);

    err = queueBuffer(mLockedBuffer.get(), fd);

    return err;
}

int Surface::queueBuffer(android_native_buffer_t* buffer, int fenceFd) {
    // 
        status_t err = mGraphicBufferProducer->queueBuffer(i, input, &output);
}

总结:

==当应用需要绘制ui的时候,需要利用surface去申请buffer,这些buffer都存在BufferQueue里面,它是一个双端队列,当应用得到buffer,将ui绘制到buffer后,再将buffer提交到Queue里面去,并且通知SurfaceFlinger去从Queue中去取buffer显示到屏幕上去,SurfaceFlinger是buffer的唯一消费者。 对于suface来说,GraphicBufferProducer是它的灵魂,buffer的申请和提交都是通过它来操作的,其中BufferQueue是用来存放buffer的==