parent
5c55f3131c
commit
9b693085f7
@ -0,0 +1,93 @@ |
|||||||
|
--- |
||||||
|
Surface 的绘制原理 |
||||||
|
--- |
||||||
|
|
||||||
|
1. Surface 绘制的 buffer 是怎么来的? |
||||||
|
2. buffer 绘制完了又是怎么提交的? |
||||||
|
|
||||||
|
```java |
||||||
|
private void performTraversals(){ |
||||||
|
performMeasure(); |
||||||
|
performLayout(); |
||||||
|
performDraw(); |
||||||
|
} |
||||||
|
private void draw(boolean fullRedrawNeeded){ |
||||||
|
Surface surface = mSurface; |
||||||
|
drawSoftware(surface, mAttachInfo, ..., dirty); |
||||||
|
} |
||||||
|
private boolean drawSoftware(Surface surface, ...){ |
||||||
|
final Canvas canvas; |
||||||
|
canvas = mSurface.lockCanvas(dirty); |
||||||
|
mView.draw(canvas); |
||||||
|
surface.unlockCanvasAndPost(canvas); |
||||||
|
} |
||||||
|
static jlong nativeLockCanvas(JNIEnv* env, jclass clazz, jlong nativeObject, jobject canvasObj, jobject dirtyRectObj){ |
||||||
|
sp<Surface> surface(reinterpert_cast<Surface *>(nativeObject)); |
||||||
|
ANativeWindow_Buffer outBuffer; |
||||||
|
surface->lock(&outBuffer, dirtyRectPtr); |
||||||
|
SkBitmap bitmap; |
||||||
|
bitmap.setPixels(outBuffer.bits); |
||||||
|
Canvas* nativeCanvas = GraphicsJNI::getNativeCanvas(env, canvasObj); |
||||||
|
nativeCanvas->setBitmap(bitmap); |
||||||
|
sp<Surface> lockedSurface(surface); |
||||||
|
return (jlong)lockedSurface.get(); |
||||||
|
} |
||||||
|
``` |
||||||
|
|
||||||
|
每次绘制都要重新申请一块 buffer,它是怎么申请的? |
||||||
|
|
||||||
|
```c++ |
||||||
|
status_t Surface::lock(ANativeWindow_Buffer* outBuffer, ...){ |
||||||
|
ANativeWindowBuffer* out; |
||||||
|
dequeueBuffer(&out, &fenceFd); |
||||||
|
sp<GraphicBuffer> backBuffer(GraphicBuffer::getSelf(out)); |
||||||
|
void* vaddr; |
||||||
|
status_t res = backBuffer->lockAsync(..., &vaddr, fenceFd); |
||||||
|
mLockedBuffer = backBuffer; |
||||||
|
outBuffer->bits = vaddr; |
||||||
|
} |
||||||
|
int Surface::dequeueBuffer(android_native_buffer_t** buffer, ...){ |
||||||
|
int buf = -1; |
||||||
|
status_t result = mGraphicBufferProduct->dequeueBuffer(&buf, ...); |
||||||
|
sp<GraphicBuffer>& gbuf(mSlot[buf].buffer); |
||||||
|
if((result&IGraphicBufferProduct::BUFFER_NEEDS_REALLOCATION)||gbuf == 0){ |
||||||
|
result = mGraphicBufferProduct->requestBuffer(buf, &gbuf); |
||||||
|
} |
||||||
|
*buffer = gbuf.get(); |
||||||
|
return OK; |
||||||
|
} |
||||||
|
``` |
||||||
|
|
||||||
|
Buffer 是怎么提交的? |
||||||
|
|
||||||
|
```c++ |
||||||
|
public void unlockCanvasAndPost(Canvas canvas){ |
||||||
|
synchronized(mLock){ |
||||||
|
unlockSwCanvasAndPost(canvas); |
||||||
|
} |
||||||
|
} |
||||||
|
private void unlockSwCanvasAndPost(Canvas canvas){ |
||||||
|
nativeUnlockCanvasAndPost(mLockedObject, canvas); |
||||||
|
nativeRelease(mLockedObject); |
||||||
|
mLockedObject = 0; |
||||||
|
} |
||||||
|
static void nativeUnlockCanvasAndPost(JNIEnv* env, jclass clazz, jlong nativeObject, jobject canvasObj) { |
||||||
|
sp<Surface> surface(reinterpret_cast<Surface *>(nativeObject)); |
||||||
|
Canvas* nativeCanvas = GraphicsJNI::getNativeCanvas(env, canvasObj); |
||||||
|
nativeCanvas->setBitmap(SkBitmap()); |
||||||
|
surface->unlockAndPost(); |
||||||
|
} |
||||||
|
status_t Surface::unlockAndPost(){ |
||||||
|
mLockedBuffer->unlockAsync(...); |
||||||
|
queueBuffer(mLockedBuffer.get(), ...); |
||||||
|
mPostedBuffer = mLockedBuffer; |
||||||
|
mLockedBuffer = 0; |
||||||
|
return err; |
||||||
|
} |
||||||
|
int Surface::queueBuffer(android_native_buffer_t* buffer, ...){ |
||||||
|
int i = getSlotFromBufferLocked(buffer); |
||||||
|
mGraphicBufferProducer->queueBuffer(i, ...); |
||||||
|
} |
||||||
|
``` |
||||||
|
|
||||||
|
![](https://i.loli.net/2020/03/26/l1QyIsgBtPSvLpF.png) |
After Width: | Height: | Size: 154 KiB |
Loading…
Reference in new issue