Android 源码 图形系统之 Surface 初始化

在 《Android 源码 图形系统之 relayoutWindow》 一节中,outSurface 初始化(调用其 copyFrom(…) 方法,入参是 SurfaceControl 对象)没有继续分析了。现在详细来分析一下后续流程。

copyFrom(…) 方法将另一个 Surface 复制到此 Surface。现在,此 Surface 拥有对与原始 Surface 相同数据的引用,并且不是所有者。这是供窗口管理器从客户端返回窗口 Surface 时使用的,将其从窗口管理器管理的表示形式转换为客户端用来向其绘制的表示形式。

surfaceControlPtr 指针指向 Native SurfaceControl 对象,接着调用 nativeCreateFromSurfaceControl(…) jni 方法获取 Native Surface 指针,最后将指针强转为 jlong 赋值给成员变量 mNativeObject。

frameworks/base/core/java/android/view/Surface.java

public class Surface implements Parcelable {
    ......
    public void copyFrom(SurfaceControl other) {
        if (other == null) {
            throw new IllegalArgumentException("other must not be null");
        }

        long surfaceControlPtr = other.mNativeObject;
        if (surfaceControlPtr == 0) {
            throw new NullPointerException(
                    "SurfaceControl native object is null. Are you using a released SurfaceControl?");
        }
        long newNativeObject = nativeCreateFromSurfaceControl(surfaceControlPtr);

        synchronized (mLock) {
            if (mNativeObject != 0) {
                nativeRelease(mNativeObject);
            }
            setNativeObjectLocked(newNativeObject);
        }
    }    
    ......
}

构造 Surface 之后,WindowManagerService 会使用此方法,这对于将 Surface 引用返回给调用方是必需的。在这一点上,我们应该只有一个 SurfaceControl。

frameworks/base/core/jni/android_view_Surface.cpp

static jlong nativeCreateFromSurfaceControl(JNIEnv* env, jclass clazz,
        jlong surfaceControlNativeObj) {
    sp<SurfaceControl> ctrl(reinterpret_cast<SurfaceControl *>(surfaceControlNativeObj));
    sp<Surface> surface(ctrl->getSurface());
    if (surface != NULL) {
        surface->incStrong(&sRefBaseOwner);
    }
    return reinterpret_cast<jlong>(surface.get());
}

getSurface() 中终于创建了 Surface 对象。

frameworks/native/libs/gui/SurfaceControl.cpp

sp<Surface> SurfaceControl::getSurface() const
{
    Mutex::Autolock _l(mLock);
    if (mSurfaceData == 0) {
        // SurfaceFlinger 始终消耗此 Surface,因此 controlledByApp 值无关紧要,使用 false。
        mSurfaceData = new Surface(mGraphicBufferProducer, false);
    }
    return mSurfaceData;
}

ANativeWindow 的实现,可将图形缓冲区输入 BufferQueue。

这些程序通常用于希望通过某种方式(例如 OpenGL,软件渲染器或硬件解码器)渲染帧并将其创建的帧转发到 SurfaceFlinger 进行合成。例如,视频解码器可以渲染帧并调用 eglSwapBuffers(),后者调用由 Surface 定义的 ANativeWindow 回调。然后,Surface 通过 Binder IPC 将缓冲区转发到 BufferQueue 的生产者接口,从而将新帧提供给诸如 GLConsumer 之类的消费者。

根据给定的 IGraphicBufferProducer 创建一个 Surface(具体实现是 BufferQueue)。

在断开连接时,Surface 主要是无状态的,可以将其视为美化的 IGraphicBufferProducer 持有者。因此,从同一 IGraphicBufferProducer 创建其他 Surface 是安全的。但是,一旦连接了 Surface,它将防止其他引用同一个 IGraphicBufferProducer 的 Surface 连接起来,从而防止将它们用作缓冲区的实际生成器。

controlledByApp 标志指示此 Surface(生产者)由应用程序控制。此标志在连接时使用。

frameworks/native/libs/gui/Surface.cpp


Surface::Surface(
        const sp<IGraphicBufferProducer>& bufferProducer,
        bool controlledByApp)
    : mGraphicBufferProducer(bufferProducer),
      mGenerationNumber(0)
{
    // 初始化 ANativeWindow 函数指针。
    ANativeWindow::setSwapInterval  = hook_setSwapInterval;
    ANativeWindow::dequeueBuffer    = hook_dequeueBuffer;
    ANativeWindow::cancelBuffer     = hook_cancelBuffer;
    ANativeWindow::queueBuffer      = hook_queueBuffer;
    ANativeWindow::query            = hook_query;
    ANativeWindow::perform          = hook_perform;

    ANativeWindow::dequeueBuffer_DEPRECATED = hook_dequeueBuffer_DEPRECATED;
    ANativeWindow::cancelBuffer_DEPRECATED  = hook_cancelBuffer_DEPRECATED;
    ANativeWindow::lockBuffer_DEPRECATED    = hook_lockBuffer_DEPRECATED;
    ANativeWindow::queueBuffer_DEPRECATED   = hook_queueBuffer_DEPRECATED;

    const_cast<int&>(ANativeWindow::minSwapInterval) = 0;
    const_cast<int&>(ANativeWindow::maxSwapInterval) = 1;

    mReqWidth = 0;
    mReqHeight = 0;
    mReqFormat = 0;
    mReqUsage = 0;
    mTimestamp = NATIVE_WINDOW_TIMESTAMP_AUTO;
    mDataSpace = HAL_DATASPACE_UNKNOWN;
    mCrop.clear();
    mScalingMode = NATIVE_WINDOW_SCALING_MODE_FREEZE;
    mTransform = 0;
    mStickyTransform = 0;
    mDefaultWidth = 0;
    mDefaultHeight = 0;
    mUserWidth = 0;
    mUserHeight = 0;
    mTransformHint = 0;
    mConsumerRunningBehind = false;
    mConnectedToCpu = false;
    mProducerControlledByApp = controlledByApp;
    mSwapIntervalZero = false;
}

现在开始分析 Surface 分配缓冲区都做了什么?这是调用 Surface 类 allocateBuffers() 实现的。

mGraphicBufferProducer 是在 Surface 构造器中初始化的。它实际指向一个 BpGraphicBufferProducer 对象。Surface::allocateBuffers() 方法中实际调用了 BpGraphicBufferProducer 类 allocateBuffers(…) 方法。

frameworks/native/libs/gui/Surface.cpp

void Surface::allocateBuffers() {
    uint32_t reqWidth = mReqWidth ? mReqWidth : mUserWidth;
    uint32_t reqHeight = mReqHeight ? mReqHeight : mUserHeight;
    mGraphicBufferProducer->allocateBuffers(mSwapIntervalZero, reqWidth,
            reqHeight, mReqFormat, mReqUsage);
}

调用了 BpGraphicBufferProducer 类 allocateBuffers(…) 方法,最终会调用到 Bn 端对应实现(BufferQueueProducer)。

  1. 查找空闲 Slot
  2. 获取可用 Slot 数量(newBufferCount)
  3. 创建 GraphicBuffer
  4. 关联 GraphicBuffer 到对应槽位

frameworks/native/libs/gui/BufferQueueProducer.cpp

void BufferQueueProducer::allocateBuffers(bool async, uint32_t width,
        uint32_t height, PixelFormat format, uint32_t usage) {
    ATRACE_CALL();
    while (true) {
        Vector<int> freeSlots;
        size_t newBufferCount = 0;
        uint32_t allocWidth = 0;
        uint32_t allocHeight = 0;
        PixelFormat allocFormat = PIXEL_FORMAT_UNKNOWN;
        uint32_t allocUsage = 0;
        { // Autolock scope
            Mutex::Autolock lock(mCore->mMutex);
            mCore->waitWhileAllocatingLocked();

            if (!mCore->mAllowAllocation) {
                BQ_LOGE("allocateBuffers: allocation is not allowed for this "
                        "BufferQueue");
                return;
            }

            int currentBufferCount = 0;
            for (int slot = 0; slot < BufferQueueDefs::NUM_BUFFER_SLOTS; ++slot) {
                if (mSlots[slot].mGraphicBuffer != NULL) {
                    ++currentBufferCount;
                } else {
                    if (mSlots[slot].mBufferState != BufferSlot::FREE) {
                        BQ_LOGE("allocateBuffers: slot %d without buffer is not FREE",
                                slot);
                        continue;
                    }

                    freeSlots.push_back(slot);
                }
            }

            int maxBufferCount = mCore->getMaxBufferCountLocked(async);
            BQ_LOGV("allocateBuffers: allocating from %d buffers up to %d buffers",
                    currentBufferCount, maxBufferCount);
            if (maxBufferCount <= currentBufferCount)
                return;
            newBufferCount =
                    static_cast<size_t>(maxBufferCount - currentBufferCount);
            if (freeSlots.size() < newBufferCount) {
                BQ_LOGE("allocateBuffers: ran out of free slots");
                return;
            }
            allocWidth = width > 0 ? width : mCore->mDefaultWidth;
            allocHeight = height > 0 ? height : mCore->mDefaultHeight;
            allocFormat = format != 0 ? format : mCore->mDefaultBufferFormat;
            allocUsage = usage | mCore->mConsumerUsageBits;

            mCore->mIsAllocating = true;
        } // Autolock scope

        Vector<sp<GraphicBuffer>> buffers;
        for (size_t i = 0; i <  newBufferCount; ++i) {
            status_t result = NO_ERROR;
            sp<GraphicBuffer> graphicBuffer(mCore->mAllocator->createGraphicBuffer(
                    allocWidth, allocHeight, allocFormat, allocUsage, &result));
            if (result != NO_ERROR) {
                BQ_LOGE("allocateBuffers: failed to allocate buffer (%u x %u, format"
                        " %u, usage %u)", width, height, format, usage);
                Mutex::Autolock lock(mCore->mMutex);
                mCore->mIsAllocating = false;
                mCore->mIsAllocatingCondition.broadcast();
                return;
            }
            buffers.push_back(graphicBuffer);
        }

        { // Autolock scope
            Mutex::Autolock lock(mCore->mMutex);
            uint32_t checkWidth = width > 0 ? width : mCore->mDefaultWidth;
            uint32_t checkHeight = height > 0 ? height : mCore->mDefaultHeight;
            PixelFormat checkFormat = format != 0 ?
                    format : mCore->mDefaultBufferFormat;
            uint32_t checkUsage = usage | mCore->mConsumerUsageBits;
            if (checkWidth != allocWidth || checkHeight != allocHeight ||
                checkFormat != allocFormat || checkUsage != allocUsage) {
                // 当我们释放锁时,有些东西改变了。重试。
                BQ_LOGV("allocateBuffers: size/format/usage changed while allocating. Retrying.");
                mCore->mIsAllocating = false;
                mCore->mIsAllocatingCondition.broadcast();
                continue;
            }

            for (size_t i = 0; i < newBufferCount; ++i) {
                int slot = freeSlots[i];
                if (mSlots[slot].mBufferState != BufferSlot::FREE) {
                    // 消费者使用 attachBuffer 分配空闲槽。丢弃我们分配的缓冲区。
                    BQ_LOGV("allocateBuffers: slot %d was acquired while allocating. "
                            "Dropping allocated buffer.", slot);
                    continue;
                }
                mCore->freeBufferLocked(slot); // 先把槽清理干净
                mSlots[slot].mGraphicBuffer = buffers[i];
                mSlots[slot].mFence = Fence::NO_FENCE;

                // freeBufferLocked 将此槽放入空闲槽列表。
                // 由于我们随后 attach 了缓冲区,因此将槽移至空闲缓冲区列表。
                mCore->mFreeSlots.erase(slot);
                mCore->mFreeBuffers.push_front(slot);

                BQ_LOGV("allocateBuffers: allocated a new buffer in slot %d", slot);
            }

            mCore->mIsAllocating = false;
            mCore->mIsAllocatingCondition.broadcast();
            mCore->validateConsistencyLocked();
        } // Autolock scope
    }
}
  1. new 一个 GraphicBuffer 对象
  2. 调用 GraphicBuffer 类 initCheck(),检查其返回值

frameworks/native/libs/gui/GraphicBufferAlloc.cpp

sp<GraphicBuffer> GraphicBufferAlloc::createGraphicBuffer(uint32_t width,
        uint32_t height, PixelFormat format, uint32_t usage, status_t* error) {
    sp<GraphicBuffer> graphicBuffer(
            new GraphicBuffer(width, height, format, usage));
    status_t err = graphicBuffer->initCheck();
    *error = err;
    if (err != 0 || graphicBuffer->handle == 0) {
        if (err == NO_MEMORY) {
            GraphicBuffer::dumpAllocationsToSystemLog();
        }
        ALOGE("GraphicBufferAlloc::createGraphicBuffer(w=%d, h=%d) "
             "failed (%s), handle=%p",
                width, height, strerror(-err), graphicBuffer->handle);
        return 0;
    }
    return graphicBuffer;
}

GraphicBuffer 构造函数中初始化了成员变量 mBufferMapper,获取 GraphicBufferMapper 单例进行了初始化。接着调用了 initSize(…) 开始实际分配工作。

frameworks/native/libs/ui/GraphicBuffer.cpp

GraphicBuffer::GraphicBuffer(uint32_t inWidth, uint32_t inHeight,
        PixelFormat inFormat, uint32_t inUsage)
    : BASE(), mOwner(ownData), mBufferMapper(GraphicBufferMapper::get()),
      mInitCheck(NO_ERROR), mId(getUniqueId())
{
    width  =
    height =
    stride =
    format =
    usage  = 0;
    handle = NULL;
    mInitCheck = initSize(inWidth, inHeight, inFormat, inUsage);
}

GraphicBufferMapper 类构造器中加载了 HAL 模块 gralloc。

frameworks/native/libs/ui/GraphicBufferMapper.cpp

ANDROID_SINGLETON_STATIC_INSTANCE( GraphicBufferMapper )

GraphicBufferMapper::GraphicBufferMapper()
    : mAllocMod(0)
{
    hw_module_t const* module;
    int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
    ALOGE_IF(err, "FATAL: can't find the %s module", GRALLOC_HARDWARE_MODULE_ID);
    if (err == 0) {
        mAllocMod = reinterpret_cast<gralloc_module_t const *>(module);
    }
}
  1. 获取 GraphicBufferAllocator 对象
  2. 调用 GraphicBufferAllocator 类 alloc(…) 方法进行内存分配

frameworks/native/libs/ui/GraphicBuffer.cpp

status_t GraphicBuffer::initSize(uint32_t inWidth, uint32_t inHeight,
        PixelFormat inFormat, uint32_t inUsage)
{
    GraphicBufferAllocator& allocator = GraphicBufferAllocator::get();
    uint32_t outStride = 0;
    status_t err = allocator.alloc(inWidth, inHeight, inFormat, inUsage,
            &handle, &outStride);
    if (err == NO_ERROR) {
        width = static_cast<int>(inWidth);
        height = static_cast<int>(inHeight);
        format = inFormat;
        usage = static_cast<int>(inUsage);
        stride = static_cast<int>(outStride);
    }
    return err;
}

initCheck() 方法仅仅返回成员变量 mInitCheck 的值。

frameworks/native/libs/ui/GraphicBuffer.cpp

status_t GraphicBuffer::initCheck() const {
    return static_cast<status_t>(mInitCheck);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

TYYJ-洪伟

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值