Loading...
avatar

Android系统_Surface渲染过程分析(软件绘制)

基于API 23

前篇:Android系统_Surface创建流程分析

申请Buffer

ViewRootImpl.draw

执行遍历 > 执行Draw > draw方法 > 软件绘制流程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

private void performTraversals() {
...
relayoutWindow(params, viewVisibility, insetsPending);
...
performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);
...
performLayout(lp, mWidth, mHeight);
...
performDraw();
...
}

private void performDraw() {
draw(fullRedrawNeeded);
}

private void draw(boolean fullRedrawNeeded) {
if (!dirty.isEmpty() || mIsAnimating || accessibilityFocusDirty) {
// 硬件加速 ,绘制绘制流程
if (mAttachInfo.mHardwareRenderer != null && mAttachInfo.mHardwareRenderer.isEnabled()) {
...
mAttachInfo.mHardwareRenderer.draw(mView, mAttachInfo, this);
} else {
...
// 软件绘制 流程
if (!drawSoftware(surface, mAttachInfo, xOffset, yOffset, scalingRequired, dirty)) {
return;
}
}
}

ViewRootImpl.drawSoftware

主要三个步骤 申请Buffer、绘制、绘制完成

1
2
3
4
5
6
7
8
9
10
private boolean drawSoftware(Surface surface, AttachInfo attachInfo,...) {
// Draw with software renderer.
final Canvas canvas;
...
canvas = mSurface.lockCanvas(dirty); //申请Buffer
...
mView.draw(canvas); //绘制
...
mSurface.unlockCanvasAndPost(canvas); //绘制完成
}

Surface.lockCanvas

执行JNI层的nativeLockCanvas,mNativeObject就是native层Surface指针

1
2
3
4
5
6
7
8
9
public Canvas lockCanvas(Rect inOutDirty)
throws Surface.OutOfResourcesException, IllegalArgumentException {
synchronized (mLock) {
checkNotReleasedLocked();

mLockedObject = nativeLockCanvas(mNativeObject, mCanvas, inOutDirty);
return mCanvas;
}
}

android_view_Surface.cpp

创建一个Rect对象,确定要重绘制的区域,执行Surface的lock方法来申请bugger,然后新建了一个SKBitmap,设置了内存地址,并把这个bitmap放入了Canvas中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
static jlong nativeLockCanvas(JNIEnv* env, jclass clazz,jlong nativeObject, jobject canvasObj, jobject dirtyRectObj) {
sp<Surface> surface(reinterpret_cast<Surface *>(nativeObject)); //转换指针
...
Rect dirtyRect;
Rect* dirtyRectPtr = NULL;

if (dirtyRectObj) {
dirtyRect.left = env->GetIntField(dirtyRectObj, gRectClassInfo.left);
dirtyRect.top = env->GetIntField(dirtyRectObj, gRectClassInfo.top);
dirtyRect.right = env->GetIntField(dirtyRectObj, gRectClassInfo.right);
dirtyRect.bottom = env->GetIntField(dirtyRectObj, gRectClassInfo.bottom);
dirtyRectPtr = &dirtyRect;
}

// 申请内存Buffer
ANativeWindow_Buffer outBuffer;
status_t err = surface->lock(&outBuffer, dirtyRectPtr);

...
SkImageInfo info = SkImageInfo::Make(outBuffer.width, outBuffer.height,
convertPixelFormat(outBuffer.format),
kPremul_SkAlphaType);

// 新建一个SkBitmap 并进行一系列设置
SkBitmap bitmap;
ssize_t bpr = outBuffer.stride * bytesPerPixel(outBuffer.format);
bitmap.setInfo(info, bpr);
if (outBuffer.width > 0 && outBuffer.height > 0) {
bitmap.setPixels(outBuffer.bits);
} else {
// be safe with an empty bitmap.
bitmap.setPixels(NULL);
}
// 把创建的bitmap 设置到Canvas中
Canvas* nativeCanvas = GraphicsJNI::getNativeCanvas(env, canvasObj);
nativeCanvas->setBitmap(bitma
if (dirtyRectPtr) {
nativeCanvas->clipRect(dirtyRect.left, dirtyRect.top,
dirtyRect.right, dirtyRect.bottom);

if (dirtyRectObj) {
env->SetIntField(dirtyRectObj, gRectClassInfo.left, dirtyRect.left);
env->SetIntField(dirtyRectObj, gRectClassInfo.top, dirtyRect.top);
env->SetIntField(dirtyRectObj, gRectClassInfo.right, dirtyRect.right);
env->SetIntField(dirtyRectObj, gRectClassInfo.bottom, dirtyRect.bottom);

// Create another reference to the surface and return it. This reference
// should be passed to nativeUnlockCanvasAndPost in place of mNativeObject,
// because the latter could be replaced while the surface is locked.
sp<Surface> lockedSurface(surface);
lockedSurface->incStrong(&sRefBaseOwner);
return (jlong) lockedSurface.get();
}

Surface.cpp

通过dequeueBuffer获取一个ANativeWindowBuffer,之后构造一个GraphicBuffer,这个bugger用来传递绘制的元数据
BufferQueueProducer中dequeueBuffer,将分配的内存放到mSlots中,outSlot就是给应用进程mSlots的序号
BufferQueueProducer中requestBuffer,根据序号,从mSlots拿到buffer

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
status_t Surface::lock(ANativeWindow_Buffer* outBuffer, ARect* inOutDirtyBounds){

ANativeWindowBuffer* out; int fenceFd = -1;
status_t err = dequeueBuffer(&out, &fenceFd); //从 GraphicBufferProduce 中 拿出来一个 buffer

if (err == NO_ERROR) {
sp<GraphicBuffer> backBuffer(GraphicBuffer::getSelf(out));//放到backBuffer中
const Rect bounds(backBuffer->width, backBuffer->height);

.......

void* vaddr;
status_t res = backBuffer->lockAsync(//把buffer的handle中的地址传到vaddr中
GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN,
newDirtyRegion.bounds(), &vaddr, fenceFd);

if (res != 0) {
err = INVALID_OPERATION;
} else {
mLockedBuffer = backBuffer;
outBuffer->width = backBuffer->width;
outBuffer->height = backBuffer->height;
outBuffer->stride = backBuffer->stride;
outBuffer->format = backBuffer->format;
outBuffer->bits = vaddr;//buffer地址
}


return err // 返回GraphicBuffer
}

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 == 0) {
result = mGraphicBufferProducer->requestBuffer(buf, &gbuf);//根据需要拿到buffer
}

sp<GraphicBuffer>& gbuf(mSlots[buf].buffer);
*buffer = gbuf.get();

return OK;

}

View绘制

View.draw

执行View的绘制流程
下面看常见的 canvas.drawRect

1
2
3
public void drawRect(float left, float top, float right, float bottom, @NonNull Paint paint) {
native_drawRect(mNativeCanvasWrapper, left, top, right, bottom, paint.getNativeInstance());
}

android_graphics_Canvas.cpp

1
2
3
4
5
6
7

static void drawRect(JNIEnv* env, jobject, jlong canvasHandle, jfloat left, jfloat top,
jfloat right, jfloat bottom, jlong paintHandle) {
const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
get_canvas(canvasHandle)->drawRect(left, top, right, bottom, *paint);

}

SkiaCanvas.drawRect

执行Skia库的绘制方法

1
2
3
4
5
void SkiaCanvas::drawRect(float left, float top, float right, float bottom,
const SkPaint& paint) {
mCanvas->drawRectCoords(left, top, right, bottom, paint);

}

SkCanvas.drawRectCoords

执行 到SkBitmap写入Buffer数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

void SkCanvas::drawRectCoords(SkScalar left, SkScalar top,
SkScalar right, SkScalar bottom,
const SkPaint& paint) {
TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawRectCoords()");
SkRect r;

r.set(left, top, right, bottom);
this->drawRect(r, paint);

}


void SkCanvas::DrawRect(const SkDraw& draw, const SkPaint& paint,
const SkRect& r, SkScalar textSize) {
if (paint.getStyle() == SkPaint::kFill_Style) {
// fDevice 即SKBitmap ,从而实现将数据写入buffer
draw.fDevice->drawRect(draw, r, paint);
} else {
SkPaint p(paint);
p.setStrokeWidth(SkScalarMul(textSize, paint.getStrokeWidth()));
draw.fDevice->drawRect(draw, r, p);
}

}

View绘制完成后通知刷新

Surface.unlockCanvasAndPost(canvas)

1
2
3
4
5
6
7
8
9
10
11
12
public void unlockCanvasAndPost(Canvas canvas) {
synchronized (mLock) {
checkNotReleasedLocked();

if (mHwuiContext != null) {
mHwuiContext.unlockAndPost(canvas);
} else {
// 走软件绘制流程
unlockSwCanvasAndPost(canvas);
}
}
}

android_view.Surface.nativeUnlockCanvasAndPost

设置一个空的SkBitmap
然后执行Surface的unlockANdPost函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
private void unlockSwCanvasAndPost(Canvas canvas) {
if (canvas != mCanvas) {
throw new IllegalArgumentException("canvas object must be the same instance that "
+ "was previously returned by lockCanvas");
}
if (mNativeObject != mLockedObject) {
Log.w(TAG, "WARNING: Surface's mNativeObject (0x" +
Long.toHexString(mNativeObject) + ") != mLockedObject (0x" +
Long.toHexString(mLockedObject) +")");
}
if (mLockedObject == 0) {
throw new IllegalStateException("Surface was not locked");
}
try {
nativeUnlockCanvasAndPost(mLockedObject, canvas);
} finally {
nativeRelease(mLockedObject);
mLockedObject = 0;
}
}

Surface.cpp.unlockAndPost

解除buffer锁定,执行queueBuffer最后执行到GraphicBufferProducer的queueBuffer函数,将buffer清除

1
2
3
4
5
6
7
8
9
10
11
12
13
14
status_t Surface::unlockAndPost()

{

int fd = -1;
status_t err = mLockedBuffer->unlockAsync(&fd);//通过Gralloc模块,最后是操作的ioctl

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

mPostedBuffer = mLockedBuffer;
mLockedBuffer = 0;
return err;

}

Surface.queueBuffer

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
int Surface::queueBuffer(android_native_buffer_t* buffer, int fenceFd) {
...
// 获取Slot数组保存的buffer
int i = getSlotFromBufferLocked(buffer);
..
IGraphicBufferProducer::QueueBufferOutput output;
IGraphicBufferProducer::QueueBufferInput input(timestamp, isAutoTimestamp,
static_cast<android_dataspace>(mDataSpace), crop, mScalingMode,
mTransform ^ mStickyTransform, fence, mStickyTransform,
mEnableFrameTimestamps);
...
// 插入buffer
status_t err = mGraphicBufferProducer->queueBuffer(i, input, &output);
...
// 通知
mQueueBufferCondition.broadcast();
return err;
}

// mSlog集合为按照顺序保存GraphicBuffer的数组
int Surface::getSlotFromBufferLocked(android_native_buffer_t* buffer) const {
for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
if (mSlots[i].buffer != NULL && mSlots[i].buffer->handle == buffer->handle) {
return i;
}
}
return BAD_VALUE;
}

BufferQueueProducer.cpp.queueBuffer

根据输入参数完善一个BufferItem,然后通知frameAvailabel

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
status_t BufferQueueProducer::queueBuffer(int slot, const QueueBufferInput &input, QueueBufferOutput *output) { 

//从input中获取一些列参数
input.deflate(&requestedPresentTimestamp, &isAutoTimestamp, &dataSpace,
&crop, &scalingMode, &transform, &acquireFence, &stickyTransform,
&getFrameTimestamps);


sp<IConsumerListener> frameAvailableListener;
sp<IConsumerListener> frameReplacedListener;
BufferItem item; //一个待渲染的帧

...
//item的一系列赋值操作

item.mAcquireCalled = mSlots[slot].mAcquireCalled;
item.mGraphicBuffer = mSlots[slot].mGraphicBuffer; //根据slot获取GraphicBuffer。
item.mCrop = crop;
item.mTransform = transform &
~static_cast<uint32_t>(NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY);
item.mTransformToDisplayInverse =
(transform & NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY) != 0;
item.mScalingMode = static_cast<uint32_t>(scalingMode);
item.mTimestamp = requestedPresentTimestamp;
item.mIsAutoTimestamp = isAutoTimestamp;

...

if (frameAvailableListener != NULL) {
frameAvailableListener->onFrameAvailable(item); //item是一个frame,准备完毕,要通知外界
} else if (frameReplacedListener != NULL) {
frameReplacedListener->onFrameReplaced(item);
}

addAndGetFrameTimestamps(&newFrameEventsEntry,etFrameTimestamps ? &output->frameTimestamps : nullptr);

return NO_ERROR;
}

BufferLayer.cpp

1
2
3
4
void BufferLayer::onFrameAvailable(const BufferItem& item) {
...
mFlinger->signalLayerUpdate();
}

SurfaceFlinger.cpp

执行SurfaceFlinger的invalidate方法

1
2
3
void SurfaceFlinger::signalLayerUpdate() {
mEventQueue->invalidate();
}

————————————————————————————————————
推荐阅读图形系统总结

Author: Afree
Link: https://afree8909.github.io/blog/2019/12/08/Android%E7%B3%BB%E7%BB%9F_Surface%E6%B8%B2%E6%9F%93%E8%BF%87%E7%A8%8B%E5%88%86%E6%9E%90%EF%BC%88%E8%BD%AF%E4%BB%B6%E7%BB%98%E5%88%B6%EF%BC%89/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.

Comment