Android6.0ディスプレイシステム(2)Surface Flinger Surface作成
7781 ワード
前のブログでは、SurfaceComposerClientでcreateSurface関数を呼び出すと、SurfaceFlingerのClientのcreateSurface関数に最後に呼び出されると分析しています.
この関数を見てみると,handleとgbpはいずれもBinderオブジェクトであり,gbpは画像バッファオブジェクトである.このhandleオブジェクトの役割は、前に説明したActivityのtokenと同様であり、Binderの一意性を利用してSurfaceに一意の識別子を生成することでもある.
この関数ではメッセージクラスMessageCreateLayerを定義し、そのオブジェクトをpostMessageSyncメソッドで送信します.このメッセージは同期的に送信されるので、関数が終了したら直接結果を返すことができます.そこでhandler関数に直接アクセスし,この関数ではSurfaceFlingerのcreateLayer関数を呼び出した.
この関数は、転送されたflagsに基づいて、通常のLayerかぼやけたLayerかを作成します.
次にhandleの取得を見てみましょう.Handleを新規作成するだけです.このHandleはBinderの実装にすぎません.Surfaceのグローバル一意性を識別し、実際の内容はありません.
ではgbpの取得を見てみましょう.それはLayerのmProducerメンバー変数です.
一方、mProducerはLayerのonFirstRefに付与されており、MonitoredProducerコンストラクション関数のパラメータproducerに注目しています.実際にはMonitoredProducerはエージェントクラスにすぎず、このproducerパラメータで実装されています.BufferQueue::createBufferQueueで作成されました.
このproducerがBufferQueueProducerオブジェクトです.
この関数を見てみると,handleとgbpはいずれもBinderオブジェクトであり,gbpは画像バッファオブジェクトである.このhandleオブジェクトの役割は、前に説明したActivityのtokenと同様であり、Binderの一意性を利用してSurfaceに一意の識別子を生成することでもある.
status_t Client::createSurface(
const String8& name,
uint32_t w, uint32_t h, PixelFormat format, uint32_t flags,
sp* handle,
sp* gbp)
{
/*
* createSurface must be called from the GL thread so that it can
* have access to the GL context.
*/
class MessageCreateLayer : public MessageBase {
SurfaceFlinger* flinger;
Client* client;
sp* handle;
sp* gbp;
status_t result;
const String8& name;
uint32_t w, h;
PixelFormat format;
uint32_t flags;
public:
MessageCreateLayer(SurfaceFlinger* flinger,
const String8& name, Client* client,
uint32_t w, uint32_t h, PixelFormat format, uint32_t flags,
sp* handle,
sp* gbp)
: flinger(flinger), client(client),
handle(handle), gbp(gbp),
name(name), w(w), h(h), format(format), flags(flags) {
}
status_t getResult() const { return result; }
virtual bool handler() {
result = flinger->createLayer(name, client, w, h, format, flags,
handle, gbp);
return true;
}
};
sp msg = new MessageCreateLayer(mFlinger.get(),
name, this, w, h, format, flags, handle, gbp);
mFlinger->postMessageSync(msg);
return static_cast( msg.get() )->getResult();
}
この関数ではメッセージクラスMessageCreateLayerを定義し、そのオブジェクトをpostMessageSyncメソッドで送信します.このメッセージは同期的に送信されるので、関数が終了したら直接結果を返すことができます.そこでhandler関数に直接アクセスし,この関数ではSurfaceFlingerのcreateLayer関数を呼び出した.
一、Layerの作成
この関数は、転送されたflagsに基づいて、通常のLayerかぼやけたLayerかを作成します.
status_t SurfaceFlinger::createLayer(
const String8& name,
const sp& client,
uint32_t w, uint32_t h, PixelFormat format, uint32_t flags,
sp* handle, sp* gbp)
{
if (int32_t(w|h) < 0) {
ALOGE("createLayer() failed, w or h is negative (w=%d, h=%d)",
int(w), int(h));
return BAD_VALUE;
}
status_t result = NO_ERROR;
sp layer;
switch (flags & ISurfaceComposerClient::eFXSurfaceMask) {
case ISurfaceComposerClient::eFXSurfaceNormal:
result = createNormalLayer(client,//
name, w, h, flags, format,
handle, gbp, &layer);
break;
case ISurfaceComposerClient::eFXSurfaceDim://
result = createDimLayer(client,
name, w, h, flags,
handle, gbp, &layer);
break;
default:
result = BAD_VALUE;
break;
}
if (result != NO_ERROR) {
return result;
}
result = addClientLayer(client, *handle, *gbp, layer);
if (result != NO_ERROR) {
return result;
}
setTransactionFlags(eTransactionNeeded);
return result;
}
まず、一般的なLayerの作成を見てみましょう.入力されたformatパラメータに基づいて、異なるフォーマットを選択します.次に、Layerを作成します.具体的なLayerについては、後述します.次にhandleとgbpを取得します.status_t SurfaceFlinger::createNormalLayer(const sp& client,
const String8& name, uint32_t w, uint32_t h, uint32_t flags, PixelFormat& format,
sp* handle, sp* gbp, sp* outLayer)
{
// initialize the surfaces
switch (format) {
case PIXEL_FORMAT_TRANSPARENT:
case PIXEL_FORMAT_TRANSLUCENT:
format = PIXEL_FORMAT_RGBA_8888;//
break;
case PIXEL_FORMAT_OPAQUE:
format = PIXEL_FORMAT_RGBX_8888;//
break;
}
*outLayer = new Layer(this, client, name, w, h, flags);// Layer
status_t err = (*outLayer)->setBuffers(w, h, format, flags);
if (err == NO_ERROR) {
*handle = (*outLayer)->getHandle();
*gbp = (*outLayer)->getProducer();
}
ALOGE_IF(err, "createNormalLayer() failed (%s)", strerror(-err));
return err;
}
では、あいまいなLayerを見てみましょう.これは簡単で、layerDimを直接新規作成し、handleとgbpを取得します.status_t SurfaceFlinger::createDimLayer(const sp& client,
const String8& name, uint32_t w, uint32_t h, uint32_t flags,
sp* handle, sp* gbp, sp* outLayer)
{
*outLayer = new LayerDim(this, client, name, w, h, flags);
*handle = (*outLayer)->getHandle();
*gbp = (*outLayer)->getProducer();
return NO_ERROR;
}
二、handleを取得する
次にhandleの取得を見てみましょう.Handleを新規作成するだけです.このHandleはBinderの実装にすぎません.Surfaceのグローバル一意性を識別し、実際の内容はありません.
sp Layer::getHandle() {
Mutex::Autolock _l(mLock);
LOG_ALWAYS_FATAL_IF(mHasSurface,
"Layer::getHandle() has already been called");
mHasSurface = true;
/*
* The layer handle is just a BBinder object passed to the client
* (remote process) -- we don't keep any reference on our side such that
* the dtor is called when the remote side let go of its reference.
*
* LayerCleaner ensures that mFlinger->onLayerDestroyed() is called for
* this layer when the handle is destroyed.
*/
class Handle : public BBinder, public LayerCleaner {
wp mOwner;
public:
Handle(const sp& flinger, const sp& layer)
: LayerCleaner(flinger, layer), mOwner(layer) {
}
};
return new Handle(mFlinger, this);
}
三、gbp画像バッファ
ではgbpの取得を見てみましょう.それはLayerのmProducerメンバー変数です.
sp Layer::getProducer() const {
return mProducer;
}
一方、mProducerはLayerのonFirstRefに付与されており、MonitoredProducerコンストラクション関数のパラメータproducerに注目しています.実際にはMonitoredProducerはエージェントクラスにすぎず、このproducerパラメータで実装されています.BufferQueue::createBufferQueueで作成されました.
void Layer::onFirstRef() {
// Creates a custom BufferQueue for SurfaceFlingerConsumer to use
sp producer;
sp consumer;
BufferQueue::createBufferQueue(&producer, &consumer);
mProducer = new MonitoredProducer(producer, mFlinger);
......
このproducerがBufferQueueProducerオブジェクトです.
void BufferQueue::createBufferQueue(sp* outProducer,
sp* outConsumer,
const sp& allocator) {
sp core(new BufferQueueCore(allocator));
sp producer(new BufferQueueProducer(core));
sp consumer(new BufferQueueConsumer(core));
*outProducer = producer;
*outConsumer = consumer;
}
次のブログでは、これを分析します.