上一篇分析了surfaceflinger的生产-消费者模型,本文着重阐述生产者对buffer生产过程。这个过程需要弄清一下几个问题:
1、生产者是谁?
2、生产者如何从BufferQueue获取空闲buffer?
3、绘制完成后的buffer如何压入BufferQueue中,以便消费者获取?
应用获取画布surface流程已经详细地分析了APP如何通过relayout去获取画布mSurface,此处不在分析;然而APP获取的surface就是生产者。
–>ViewRootImpl.java
int relayoutResult = mWindowSession.relayout(
mWindow, mSeq, params,
(int) (mView.getMeasuredWidth() * appScale + 0.5f),
(int) (mView.getMeasuredHeight() * appScale + 0.5f),
viewVisibility, insetsPending ? WindowManagerGlobal.RELAYOUT_INSETS_PENDING : 0,
mWinFrame, mPendingOverscanInsets, mPendingContentInsets, mPendingVisibleInsets,
mPendingStableInsets, mPendingOutsets, mPendingConfiguration, mSurface);
在APP绘制过程中,会通过surface去从BufferQueue获取buffer,绘制完成后放回BufferQueue中。
–>ViewRootImpl.java
performDraw()–>draw(boolean fullRedrawNeeded)–>drawSoftware()
private boolean drawSoftware(Surface surface, AttachInfo attachInfo, int xoff, int yoff,
boolean scalingRequired, Rect dirty){
......
canvas = mSurface.lockCanvas(dirty);//见2节dequeueBuffer过程
......
surface.unlockCanvasAndPost(canvas);//见3节queueBuffer过程
......
}
–>Surface.java
public Canvas lockCanvas(Rect inOutDirty)
throws Surface.OutOfResourcesException, IllegalArgumentException {
synchronized (mLock) {
checkNotReleasedLocked();
if (mLockedObject != 0) {
// Ideally, nativeLockCanvas() would throw in this situation and prevent the
// double-lock, but that won't happen if mNativeObject was updated. We can't
// abandon the old mLockedObject because it might still be in use, so instead
// we just refuse to re-lock the Surface.
throw new IllegalArgumentException("Surface was already locked");
}
mLockedObject = nativeLockCanvas(mNativeObject, mCanvas, inOutDirty);
return mCanvas;
}
}
调用本地方法锁住资源
–>android_view_Surface.cpp
static jlong nativeLockCanvas(JNIEnv* env, jclass clazz,
jlong nativeObject, jobject canvasObj, jobject dirtyRectObj) {
sp surface(reinterpret_cast(nativeObject));
if (!isSurfaceValid(surface)) {
doThrowIAE(env);
return 0;
}
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;
}
ANativeWindow_Buffer outBuffer;
status_t err = surface->lock(&outBuffer, dirtyRectPtr);
if (err < 0) {
const char* const exception = (err == NO_MEMORY) ?
OutOfResourcesException :
"java/lang/IllegalArgumentException";
jniThrowException(env, exception, NULL);
return 0;
}
SkImageInfo info = SkImageInfo::Make(outBuffer.width, outBuffer.height,
convertPixelFormat(outBuffer.format),
kPremul_SkAlphaType);
if (outBuffer.format == PIXEL_FORMAT_RGBX_8888) {
info.fAlphaType = kOpaque_SkAlphaType;
}
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);
}
Canvas* nativeCanvas = GraphicsJNI::getNativeCanvas(env, canvasObj);
nativeCanvas->setBitmap(bitmap);
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 lockedSurface(surface);
lockedSurface->incStrong(&sRefBaseOwner);
return (jlong) lockedSurface.get();
}
–>Surface.cpp
status_t Surface::lock(
ANativeWindow_Buffer* outBuffer, ARect* inOutDirtyBounds)
{
......
ANativeWindowBuffer* out;
int fenceFd = -1;
status_t err = dequeueBuffer(&out, &fenceFd);
......
}
int Surface::dequeueBuffer(android_native_buffer_t** buffer, int* fenceFd) {
......
int buf = -1;
sp<Fence> fence;
//MonitoredProducer继承IGraphicBufferProducer,且mGraphicBufferProducer的智能指针是由MonitoredProducer向上转型
status_t result = mGraphicBufferProducer->dequeueBuffer(&buf, &fence, swapIntervalZero,
reqWidth, reqHeight, reqFormat, reqUsage);
......
}
–>MonitoredProducer.cpp
status_t MonitoredProducer::dequeueBuffer(int* slot, sp* fence,
bool async, uint32_t w, uint32_t h, PixelFormat format, uint32_t usage) {
//BufferQueueProducer继承IGraphicBufferProducer,且mProducer的智能指针是由BufferQueueProducer向上转型
return mProducer->dequeueBuffer(slot, fence, async, w, h, format, usage);
}
–>BufferQueueProducer.cpp
status_t BufferQueueProducer::dequeueBuffer(int *outSlot,
sp *outFence, bool async,
uint32_t width, uint32_t height, PixelFormat format, uint32_t usage) {
.......
}
–>Surface.java
public void unlockCanvasAndPost(Canvas canvas) {
synchronized (mLock) {
checkNotReleasedLocked();
if (mHwuiContext != null) {
mHwuiContext.unlockAndPost(canvas);
} else {
unlockSwCanvasAndPost(canvas);
}
}
}
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;
}
}
–>android_view_Surface.cpp
static void nativeUnlockCanvasAndPost(JNIEnv* env, jclass clazz,
jlong nativeObject, jobject canvasObj) {
sp surface(reinterpret_cast(nativeObject));
if (!isSurfaceValid(surface)) {
return;
}
// 将画布从surface分离
Canvas* nativeCanvas = GraphicsJNI::getNativeCanvas(env, canvasObj);
nativeCanvas->setBitmap(SkBitmap());
// 解锁surface
status_t err = surface->unlockAndPost();
if (err < 0) {
doThrowIAE(env);
}
}
–>Surface.cpp
status_t Surface::unlockAndPost()
{
if (mLockedBuffer == 0) {
ALOGE("Surface::unlockAndPost failed, no locked buffer");
return INVALID_OPERATION;
}
int fd = -1;
status_t err = mLockedBuffer->unlockAsync(&fd);
ALOGE_IF(err, "failed unlocking buffer (%p)", mLockedBuffer->handle);
err = queueBuffer(mLockedBuffer.get(), fd);
ALOGE_IF(err, "queueBuffer (handle=%p) failed (%s)",
mLockedBuffer->handle, strerror(-err));
mPostedBuffer = mLockedBuffer;
mLockedBuffer = 0;
return err;
}
int Surface::queueBuffer(android_native_buffer_t* buffer, int fenceFd) {
......
//MonitoredProducer继承IGraphicBufferProducer,且mGraphicBufferProducer的智能指针是由MonitoredProducer向上转型
status_t err = mGraphicBufferProducer->queueBuffer(i, input, &output);
......
}
–>MonitoredProducer.cpp
status_t MonitoredProducer::queueBuffer(int slot, const QueueBufferInput& input,
QueueBufferOutput* output) {
//BufferQueueProducer继承IGraphicBufferProducer,且mProducer的智能指针是由BufferQueueProducer向上转型
return mProducer->queueBuffer(slot, input, output);
}
–>BufferQueueProducer.cpp
status_t BufferQueueProducer::queueBuffer(int slot,
const QueueBufferInput &input, QueueBufferOutput *output) {
......
}
通过上述分析,开篇提到的三个问题都得到了解答。下一篇将继续分析surfaceflinger的消费过程,未完待续。。。