Surface

作者: 杨殿生 | 来源:发表于2020-04-30 18:22 被阅读0次

Surface创建

public class Surface implements Parcelable {
          long mNativeObject; // package scope only for SurfaceControl access
          private final Canvas mCanvas = new CompatibleCanvas();
}

他是一个parcelable类型所以可以跨进程传递、mNativeObject存储native层的Surface、mCanvas用于锁定画布提交绘制数据与底层调用skia

GraphicBufferProducer申请Buffer使用

Activity在第一次绘制时申请的时候会申请Surface

 private void performTraversals() {
         if (mFirst){
                relayoutWindow(params, viewVisibility, insetsPending);
        }  
}
 private int relayoutWindow(WindowManager.LayoutParams params, int viewVisibility,
            boolean insetsPending) throws RemoteException {
        int relayoutResult = mWindowSession.relayout(
                mWindow,····· mSurface);
    }

relayoutWindow会通过WindowSession向WMS发起调用,会把空的Surface传递给WMS,

WMS端

 public int relayout(IWindow window,···Surface outSurface) {
        int res = mService.relayoutWindow(this, window, ···outSurface);
    }
 public int relayoutWindow(){
         result = createSurfaceControl(outSurface, result, win, winAnimator);
      //最后调用
     outSurface.copyFrom(mSurfaceControl);
}

会创建SurfaceControl 7.0版本是创建了一个WindowSurfaceController包装了一个SurfaceControl,然后执行copyForm()

 /**
     * Copy another surface to this one.  This surface now holds a reference
     * to the same data as the original surface, and is -not- the owner.
     * This is for use by the window manager when returning a window surface
     * back from a client, converting it from the representation being managed
     * by the window manager to the representation the client uses to draw
     * in to it.
     * @hide
     */
    public void copyFrom(SurfaceControl other) {
        long surfaceControlPtr = other.mNativeObject;
        long newNativeObject = nativeCreateFromSurfaceControl(surfaceControlPtr);
        setNativeObjectLocked(newNativeObject);
    }

通过GraphicBufferProducer(Binder对象)生产的一个native的Surface,拷贝一个native的Surface到Java层的Surface,Java层Surface持有引用。然后传递给APP进程

Surface的本质是GraphicBufferProducer,而不是Buffer
Surface夸进程传递,本质是GraphicBufferProducer的传递

Surface绘制原理

private void performTraversals(){
    ···
    performMeasure()
    ···
    performLayout()
    ···
    performDraw()
}

performDraw()方法会调用draw

private void draw(boolean fullRedrawNeeded) {
        Surface surface = mSurface;
        drawSoftware(surface, mAttachInfo, xOffset, yOffset, scalingRequired, dirty);
    }

如果开启硬件加速会使用硬件否则是软件绘制,这里是软件绘制

 private boolean drawSoftware(Surface surface, AttachInfo attachInfo, int xoff, int yoff,
            boolean scalingRequired, Rect dirty) {
            canvas = mSurface.lockCanvas(dirty);
            mView.draw(canvas);  
            surface.unlockCanvasAndPost(canvas);
    
    }

这里为什么一定要用canvas呢,就是因为canvas会在底层调用skia库,绘制我们要绘制图像。

mSurface.lockCanvas(dirty);申请Buffer

底层会通过native的Surface,中成员变量GraphicBufferProducer的dequeueBuffer() 申请一块GraphicBuffer,这会向SurfaceFlinger申请一个空闲的buffer,Buffer的传递是传递类似句柄一样的东西,Buffer是存储在一片共享内存中

Surface 中是有两个buffer的一个是前台buffer一个是后台buffer,前台buffer用于显示,后台buffer用于绘制

unlockCanvasAndPost(canvas);提交Buffer

通过GraphicBufferProducer将buffer的句柄提交给SurfaceFlinger
后台Buffer升级为前台Buffer

Surface获取Buffer

参考
Android Surface创建
浅析 android 应用界面的展现流程(二)布局与视图的创建

相关文章

网友评论

      本文标题:Surface

      本文链接:https://www.haomeiwen.com/subject/cprtghtx.html