Android 中有多个窗口,每个窗口都是一个 Renderer,每个窗口渲染后把 buffer 传递给 Composer。由 Composer 来合成每个窗口的 buffer,最后发送给显示器显示。
Graphic data flow through Android
Renderer 和 Composer 通过 BufferQueue 交互,它是一个生产者消费者模式。生产者和消费者之间传递的是 GraphicBuffer。
该文档会介绍 GraphicBuffer 的组成和跨进程传递的原理。
/**
* Simple wrapper for the native GraphicBuffer class.
* @hide
*/
public class GraphicBuffer implements Parcelable {
...
private final int mWidth;
private final int mHeight;
private final int mFormat;
private final int mUsage;
// Note: do not rename, this field is used by native code
private final long mNativeObject;
// These two fields are only used by lock/unlockCanvas()
private Canvas mCanvas;
private int mSaveCount;
...
}
GraphicBuffer 实现了 Parcelable,所以它可以通过 binder 传递。它有 4 个成员描述 buffer 的属性:宽、高、像素格式 和 usage。
mNativeObject
指向的是 GraphicBufferWrapper,它包装了 GraphicBuffer native 指针。
class GraphicBufferWrapper {
public:
explicit GraphicBufferWrapper(const sp<GraphicBuffer>& buffer): buffer(buffer) {
LOG_ALWAYS_FATAL_IF(buffer == nullptr, "creating a null GraphicBuffer");
}
const sp<GraphicBuffer>& get() const {
return buffer;
}
private:
sp<GraphicBuffer> const buffer;
};
mCanvas
是在 lockCanvas()
创建的。
/**
* Creates new <code>GraphicBuffer</code> instance. This method will return null
* if the buffer cannot be created.
*
* @param width The width in pixels of the buffer
* @param height The height in pixels of the buffer
* @param format The format of each pixel as specified in {@link PixelFormat}
* @param usage Hint indicating how the buffer will be used
*
* @return A <code>GraphicBuffer</code> instance or null
*/
public static GraphicBuffer create(int width, int height, int format, int usage) {
long nativeObject = nCreateGraphicBuffer(width, height, format, usage);
if (nativeObject != 0) {
return new GraphicBuffer(width, height, format, usage, nativeObject);
}
return null;
}
静态方法 GraphicBuffer.create() 中先调用 nCreateGraphicBuffer()
方法创建 GraphicBuffer native,然后创建一个 GraphicBuffer 对象返回。
static jlong android_graphics_GraphicBuffer_create(JNIEnv* env, jobject clazz,
jint width, jint height, jint format, jint usage) {
sp<GraphicBuffer> buffer = new GraphicBuffer(
uint32_t(width), uint32_t(height), PixelFormat(format), uint32_t(usage),
std::string("android_graphics_GraphicBuffer_create pid [") +
std::to_string(getpid()) +"]");
status_t error = buffer->initCheck();
if (error < 0) {
ALOGW_IF(kDebugGraphicBuffer, "createGraphicBuffer() failed in GraphicBuffer.create()");
return NULL;
}
GraphicBufferWrapper* wrapper = new GraphicBufferWrapper(buffer);
return reinterpret_cast<jlong>(wrapper);
}