Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f96cea4a authored by Lajos Molnar's avatar Lajos Molnar
Browse files

Codec2: make C2Allocation API independent from android limitations

- use C2Fence everywhere
- use crop region and address in unmap

Bug: 64121714
Test: unit tests
Change-Id: Ifd0cadfa347194ea390edd204cfc243bdfcbb950
parent 6662be7e
Loading
Loading
Loading
Loading
+49 −36
Original line number Diff line number Diff line
@@ -746,8 +746,8 @@ public:
    /**
     * Maps a portion of an allocation starting from |offset| with |size| into local process memory.
     * Stores the starting address into |addr|, or NULL if the operation was unsuccessful.
     * |fenceFd| is a file descriptor referring to an acquire sync fence object. If it is already
     * safe to access the buffer contents, then -1.
     * |fence| will contain an acquire sync fence object. If it is already
     * safe to access the buffer contents, then it will contain an empty (already fired) fence.
     *
     * \param offset        starting position of the portion to be mapped (this does not have to
     *                      be page aligned)
@@ -755,9 +755,9 @@ public:
     *                      aligned)
     * \param usage         the desired usage. \todo this must be kSoftwareRead and/or
     *                      kSoftwareWrite.
     * \param fenceFd         a pointer to a file descriptor if an async mapping is requested. If
     *                      not-null, and acquire fence FD will be stored here on success, or -1
     *                      on failure. If null, the mapping will be synchronous.
     * \param fence         a pointer to a fence object if an async mapping is requested. If
     *                      not-null, and acquire fence will be stored here on success, or empty
     *                      fence on failure. If null, the mapping will be synchronous.
     * \param addr          a pointer to where the starting address of the mapped portion will be
     *                      stored. On failure, nullptr will be stored here.
     *
@@ -775,19 +775,19 @@ public:
     * \retval C2_CORRUPTED some unknown error prevented the operation from completing (unexpected)
     */
    virtual c2_status_t map(
            size_t offset, size_t size, C2MemoryUsage usage, int *fenceFd /* nullable */,
            size_t offset, size_t size, C2MemoryUsage usage, C2Fence *fence /* nullable */,
            void **addr /* nonnull */) = 0;

    /**
     * Unmaps a portion of an allocation at |addr| with |size|. These must be parameters previously
     * passed to |map|; otherwise, this operation is a no-op.
     * passed to and returned by |map|; otherwise, this operation is a no-op.
     *
     * \param addr          starting address of the mapped region
     * \param size          size of the mapped region
     * \param fenceFd         a pointer to a file descriptor if an async unmapping is requested. If
     *                      not-null, a release fence FD will be stored here on success, or -1
     * \param fence         a pointer to a fence object if an async unmapping is requested. If
     *                      not-null, a release fence will be stored here on success, or empty fence
     *                      on failure. This fence signals when the original allocation contains
     *                      any changes that happened to the mapped region. If null, the unmapping
     *                      all changes that happened to the mapped region. If null, the unmapping
     *                      will be synchronous.
     *
     * \retval C2_OK        the operation was successful
@@ -798,7 +798,7 @@ public:
     * \retval C2_CORRUPTED some unknown error prevented the operation from completing (unexpected)
     * \retval C2_REFUSED   no permission to unmap the portion (unexpected - system)
     */
    virtual c2_status_t unmap(void *addr, size_t size, int *fenceFd /* nullable */) = 0;
    virtual c2_status_t unmap(void *addr, size_t size, C2Fence *fence /* nullable */) = 0;

    /**
     * Returns the allocator ID for this allocation. This is useful to put the handle into context.
@@ -1510,6 +1510,15 @@ struct C2PlaneInfo {
        BIG_END,    // BIG_ENDIAN is a reserved macro
    } endianness; ///< endianness of the samples

    /**
     * The following two fields define the relation between multiple planes. If multiple planes are
     * interleaved, they share a root plane (whichever plane's start address is the lowest), and
     * |offset| is the offset of this plane inside the root plane (in bytes). |rootIx| is the index
     * of the root plane. If a plane is independent, rootIx is its index and offset is 0.
     */
    uint32_t rootIx; ///< index of the root plane
    uint32_t offset; ///< offset of this plane inside of the root plane

    inline constexpr ssize_t minOffset(uint32_t width, uint32_t height) const {
        ssize_t offs = 0;
        if (width > 0 && colInc < 0) {
@@ -1544,7 +1553,8 @@ struct C2PlanarLayout {
    };

    type_t type;                    // image type
    uint32_t numPlanes;             // number of planes
    uint32_t numPlanes;             // number of component planes
    uint32_t rootPlanes;            // number of layout planes (root planes)

    enum plane_index_t : uint32_t {
        PLANE_Y = 0,
@@ -1696,22 +1706,19 @@ public:
     * Maps a rectangular section (as defined by |rect|) of a 2D allocation into local process
     * memory for flexible access. On success, it fills out |layout| with the plane specifications
     * and fills the |addr| array with pointers to the first byte of the top-left pixel of each
     * plane used. Otherwise, it leaves |layout| and |addr| untouched. |fenceFd| is a file
     * descriptor referring to an acquire sync fence object. If it is already safe to access the
     * buffer contents, then -1.
     * plane used. Otherwise, it leaves |layout| and |addr| untouched. |fence| will contain
     * an acquire sync fence object. If it is already safe to access the
     * buffer contents, then it will be an empty (already fired) fence.
     *
     * Safe regions for the pointer addresses returned can be gotten via C2LayoutInfo.minOffse()/
     * Safe regions for the pointer addresses returned can be gotten via C2LayoutInfo.minOffset()/
     * maxOffset().
     *
     * \note Only one portion of the graphic allocation can be mapped at the same time. (This is
     * from gralloc1 limitation.)
     *
     * \param rect          section to be mapped (this does not have to be aligned)
     * \param usage         the desired usage. \todo this must be kSoftwareRead and/or
     *                      kSoftwareWrite.
     * \param fenceFd       a pointer to a file descriptor if an async mapping is requested. If
     *                      not-null, and acquire fence FD will be stored here on success, or -1
     *                      on failure. If null, the mapping will be synchronous.
     * \param fence         a pointer to a fence object if an async mapping is requested. If
     *                      not-null, and acquire fence will be stored here on success, or empty
     *                      fence on failure. If null, the mapping will be synchronous.
     * \param layout        a pointer to where the mapped planes' descriptors will be
     *                      stored. On failure, nullptr will be stored here.
     * \param addr          pointer to an array with at least C2PlanarLayout::MAX_NUM_PLANES
@@ -1719,7 +1726,8 @@ public:
     *
     * \retval C2_OK        the operation was successful
     * \retval C2_REFUSED   no permission to map the section
     * \retval C2_DUPLICATE there is already a mapped region (caller error)
     * \retval C2_DUPLICATE there is already a mapped region and this allocation cannot support
     *                      multi-mapping (caller error)
     * \retval C2_TIMED_OUT the operation timed out
     * \retval C2_NO_MEMORY not enough memory to complete the operation
     * \retval C2_BAD_VALUE the parameters (rect) are invalid or outside the allocation, or the
@@ -1728,25 +1736,30 @@ public:

     */
    virtual c2_status_t map(
            C2Rect rect, C2MemoryUsage usage, int *fenceFd,
            C2Rect rect, C2MemoryUsage usage, C2Fence *fence,
            C2PlanarLayout *layout /* nonnull */, uint8_t **addr /* nonnull */) = 0;

    /**
     * Unmaps the last mapped rectangular section.
     * Unmaps a section of an allocation at |addr| with |rect|. These must be parameters previously
     * passed to and returned by |map|; otherwise, this operation is a no-op.
     *
     * \param fenceFd         a pointer to a file descriptor if an async unmapping is requested. If
     *                      not-null, a release fence FD will be stored here on success, or -1
     * \param addr          pointer to an array with at least C2PlanarLayout::MAX_NUM_PLANES
     *                      elements containing the starting addresses of the mapped layers
     * \param rect          boundaries of the mapped section
     * \param fence         a pointer to a fence object if an async unmapping is requested. If
     *                      not-null, a release fence will be stored here on success, or empty fence
     *                      on failure. This fence signals when the original allocation contains
     *                      any changes that happened to the mapped section. If null, the unmapping
     *                      all changes that happened to the mapped section. If null, the unmapping
     *                      will be synchronous.
     *
     * \retval C2_OK        the operation was successful
     * \retval C2_TIMED_OUT the operation timed out
     * \retval C2_NOT_FOUND there is no mapped region (caller error)
     * \retval C2_NOT_FOUND there is no such mapped region (caller error)
     * \retval C2_CORRUPTED some unknown error prevented the operation from completing (unexpected)
     * \retval C2_REFUSED   no permission to unmap the section (unexpected - system)
     */
    virtual c2_status_t unmap(C2Fence *fenceFd /* nullable */) = 0;
    virtual c2_status_t unmap(
            uint8_t **addr /* nonnull */, C2Rect rect, C2Fence *fence /* nullable */) = 0;

    /**
     * Returns the allocator ID for this allocation. This is useful to put the handle into context.
+5 −1
Original line number Diff line number Diff line
@@ -312,13 +312,15 @@ public:
            addr[C2PlanarLayout::PLANE_V] = nullptr;
            FAIL() << "C2GraphicAllocation::map() failed: " << err;
        }
        mMappedRect = rect;
        memcpy(mAddrGraphic, addr, sizeof(uint8_t*) * C2PlanarLayout::MAX_NUM_PLANES);
    }

    void unmapGraphic() {
        ASSERT_TRUE(mGraphicAllocation);

        // TODO: fence
        ASSERT_EQ(C2_OK, mGraphicAllocation->unmap(nullptr));
        ASSERT_EQ(C2_OK, mGraphicAllocation->unmap(mAddrGraphic, mMappedRect, nullptr));
    }

    std::shared_ptr<C2BlockPool> makeGraphicBlockPool() {
@@ -330,6 +332,8 @@ private:
    std::shared_ptr<C2LinearAllocation> mLinearAllocation;
    size_t mSize;
    void *mAddr;
    C2Rect mMappedRect;
    uint8_t* mAddrGraphic[C2PlanarLayout::MAX_NUM_PLANES];

    std::shared_ptr<C2Allocator> mGraphicAllocator;
    std::shared_ptr<C2GraphicAllocation> mGraphicAllocation;
+40 −9
Original line number Diff line number Diff line
@@ -213,9 +213,10 @@ public:
    virtual ~C2AllocationGralloc() override;

    virtual c2_status_t map(
            C2Rect rect, C2MemoryUsage usage, int *fenceFd,
            C2Rect rect, C2MemoryUsage usage, C2Fence *fence,
            C2PlanarLayout *layout /* nonnull */, uint8_t **addr /* nonnull */) override;
    virtual c2_status_t unmap(C2Fence *fenceFd /* nullable */) override;
    virtual c2_status_t unmap(
            uint8_t **addr /* nonnull */, C2Rect rect, C2Fence *fence /* nullable */) override;
    virtual C2Allocator::id_t getAllocatorId() const override { return mAllocatorId; }
    virtual const C2Handle *handle() const override { return mLockedHandle ? : mHandle; }
    virtual bool equals(const std::shared_ptr<const C2GraphicAllocation> &other) const override;
@@ -263,16 +264,18 @@ C2AllocationGralloc::~C2AllocationGralloc() {
        return;
    }
    if (mLocked) {
        unmap(nullptr);
        // implementation ignores addresss and rect
        uint8_t* addr[C2PlanarLayout::MAX_NUM_PLANES] = {};
        unmap(addr, C2Rect(), nullptr);
    }
    mMapper->freeBuffer(const_cast<native_handle_t *>(mBuffer));
}

c2_status_t C2AllocationGralloc::map(
        C2Rect rect, C2MemoryUsage usage, int *fenceFd,
        C2Rect rect, C2MemoryUsage usage, C2Fence *fence,
        C2PlanarLayout *layout /* nonnull */, uint8_t **addr /* nonnull */) {
    // TODO
    (void) fenceFd;
    (void) fence;
    (void) usage;

    if (mBuffer && mLocked) {
@@ -326,6 +329,7 @@ c2_status_t C2AllocationGralloc::map(
            addr[C2PlanarLayout::PLANE_V] = (uint8_t *)ycbcrLayout.cr;
            layout->type = C2PlanarLayout::TYPE_YUV;
            layout->numPlanes = 3;
            layout->rootPlanes = 3;
            layout->planes[C2PlanarLayout::PLANE_Y] = {
                C2PlaneInfo::CHANNEL_Y,         // channel
                1,                              // colInc
@@ -336,6 +340,8 @@ c2_status_t C2AllocationGralloc::map(
                8,                              // bitDepth
                0,                              // rightShift
                C2PlaneInfo::NATIVE,            // endianness
                C2PlanarLayout::PLANE_Y,        // rootIx
                0,                              // offset
            };
            layout->planes[C2PlanarLayout::PLANE_U] = {
                C2PlaneInfo::CHANNEL_CB,          // channel
@@ -347,6 +353,8 @@ c2_status_t C2AllocationGralloc::map(
                8,                                // bitDepth
                0,                                // rightShift
                C2PlaneInfo::NATIVE,              // endianness
                C2PlanarLayout::PLANE_U,          // rootIx
                0,                                // offset
            };
            layout->planes[C2PlanarLayout::PLANE_V] = {
                C2PlaneInfo::CHANNEL_CR,          // channel
@@ -358,7 +366,20 @@ c2_status_t C2AllocationGralloc::map(
                8,                                // bitDepth
                0,                                // rightShift
                C2PlaneInfo::NATIVE,              // endianness
                C2PlanarLayout::PLANE_V,          // rootIx
                0,                                // offset
            };
            // handle interleaved formats
            intptr_t uvOffset = addr[C2PlanarLayout::PLANE_V] - addr[C2PlanarLayout::PLANE_U];
            if (uvOffset > 0 && uvOffset < (intptr_t)ycbcrLayout.chromaStep) {
                layout->rootPlanes = 2;
                layout->planes[C2PlanarLayout::PLANE_V].rootIx = C2PlanarLayout::PLANE_U;
                layout->planes[C2PlanarLayout::PLANE_V].offset = uvOffset;
            } else if (uvOffset < 0 && uvOffset > -(intptr_t)ycbcrLayout.chromaStep) {
                layout->rootPlanes = 2;
                layout->planes[C2PlanarLayout::PLANE_U].rootIx = C2PlanarLayout::PLANE_V;
                layout->planes[C2PlanarLayout::PLANE_U].offset = -uvOffset;
            }
            break;
        }

@@ -387,6 +408,7 @@ c2_status_t C2AllocationGralloc::map(
            addr[C2PlanarLayout::PLANE_B] = (uint8_t *)pointer + 2;
            layout->type = C2PlanarLayout::TYPE_RGB;
            layout->numPlanes = 3;
            layout->rootPlanes = 1;
            layout->planes[C2PlanarLayout::PLANE_R] = {
                C2PlaneInfo::CHANNEL_R,         // channel
                4,                              // colInc
@@ -397,6 +419,8 @@ c2_status_t C2AllocationGralloc::map(
                8,                              // bitDepth
                0,                              // rightShift
                C2PlaneInfo::NATIVE,            // endianness
                C2PlanarLayout::PLANE_R,        // rootIx
                0,                              // offset
            };
            layout->planes[C2PlanarLayout::PLANE_G] = {
                C2PlaneInfo::CHANNEL_G,         // channel
@@ -408,6 +432,8 @@ c2_status_t C2AllocationGralloc::map(
                8,                              // bitDepth
                0,                              // rightShift
                C2PlaneInfo::NATIVE,            // endianness
                C2PlanarLayout::PLANE_R,        // rootIx
                1,                              // offset
            };
            layout->planes[C2PlanarLayout::PLANE_B] = {
                C2PlaneInfo::CHANNEL_B,         // channel
@@ -419,6 +445,8 @@ c2_status_t C2AllocationGralloc::map(
                8,                              // bitDepth
                0,                              // rightShift
                C2PlaneInfo::NATIVE,            // endianness
                C2PlanarLayout::PLANE_R,        // rootIx
                2,                              // offset
            };
            break;
        }
@@ -431,14 +459,17 @@ c2_status_t C2AllocationGralloc::map(
    return C2_OK;
}

c2_status_t C2AllocationGralloc::unmap(C2Fence *fenceFd /* nullable */) {
    // TODO: fence
c2_status_t C2AllocationGralloc::unmap(
        uint8_t **addr, C2Rect rect, C2Fence *fence /* nullable */) {
    // TODO: check addr and size, use fence
    (void)addr;
    (void)rect;
    c2_status_t err = C2_OK;
    mMapper->unlock(
            const_cast<native_handle_t *>(mBuffer),
            [&err, &fenceFd](const auto &maperr, const auto &releaseFence) {
            [&err, &fence](const auto &maperr, const auto &releaseFence) {
                // TODO
                (void) fenceFd;
                (void) fence;
                (void) releaseFence;
                err = maperr2error(maperr);
                if (err == C2_OK) {
+11 −11
Original line number Diff line number Diff line
@@ -117,9 +117,9 @@ class C2AllocationIon : public C2LinearAllocation {
public:
    /* Interface methods */
    virtual c2_status_t map(
        size_t offset, size_t size, C2MemoryUsage usage, int *fence,
        size_t offset, size_t size, C2MemoryUsage usage, C2Fence *fence,
        void **addr /* nonnull */) override;
    virtual c2_status_t unmap(void *addr, size_t size, int *fenceFd) override;
    virtual c2_status_t unmap(void *addr, size_t size, C2Fence *fenceFd) override;
    virtual ~C2AllocationIon() override;
    virtual const C2Handle *handle() const override;
    virtual id_t getAllocatorId() const override;
@@ -218,8 +218,8 @@ public:
        return new Impl(ionFd, size, bufferFd, buffer, id, ret);
    }

    c2_status_t map(size_t offset, size_t size, C2MemoryUsage usage, int *fenceFd, void **addr) {
        (void)fenceFd; // TODO: wait for fence
    c2_status_t map(size_t offset, size_t size, C2MemoryUsage usage, C2Fence *fence, void **addr) {
        (void)fence; // TODO: wait for fence
        *addr = nullptr;
        if (mMapSize > 0) {
            // TODO: technically we should return DUPLICATE here, but our block views don't
@@ -272,7 +272,7 @@ public:
        return err;
    }

    c2_status_t unmap(void *addr, size_t size, int *fenceFd) {
    c2_status_t unmap(void *addr, size_t size, C2Fence *fence) {
        if (mMapFd < 0 || mMapSize == 0) {
            return C2_NOT_FOUND;
        }
@@ -284,8 +284,8 @@ public:
        if (err != 0) {
            return c2_map_errno<EINVAL>(errno);
        }
        if (fenceFd) {
            *fenceFd = -1; // not using fences
        if (fence) {
            *fence = C2Fence(); // not using fences
        }
        mMapSize = 0;
        return C2_OK;
@@ -334,12 +334,12 @@ private:
};

c2_status_t C2AllocationIon::map(
    size_t offset, size_t size, C2MemoryUsage usage, int *fenceFd, void **addr) {
    return mImpl->map(offset, size, usage, fenceFd, addr);
    size_t offset, size_t size, C2MemoryUsage usage, C2Fence *fence, void **addr) {
    return mImpl->map(offset, size, usage, fence, addr);
}

c2_status_t C2AllocationIon::unmap(void *addr, size_t size, int *fenceFd) {
    return mImpl->unmap(addr, size, fenceFd);
c2_status_t C2AllocationIon::unmap(void *addr, size_t size, C2Fence *fence) {
    return mImpl->unmap(addr, size, fence);
}

c2_status_t C2AllocationIon::status() const {
+10 −5
Original line number Diff line number Diff line
@@ -414,6 +414,7 @@ public:
            if (mError != C2_OK) {
                memset(&mLayout, 0, sizeof(mLayout));
                memset(mData, 0, sizeof(mData));
                memset(mOffsetData, 0, sizeof(mData));
            } else {
                // TODO: validate plane layout and
                // adjust data pointers to the crop region's top left corner.
@@ -424,13 +425,15 @@ public:
                    if (crop.left % colSampling || crop.right() % colSampling
                            || crop.top % rowSampling || crop.bottom() % rowSampling) {
                        // cannot calculate data pointer
                        mImpl->getAllocation()->unmap(nullptr);
                        mImpl->getAllocation()->unmap(mData, crop, nullptr);
                        memset(&mLayout, 0, sizeof(mLayout));
                        memset(mData, 0, sizeof(mData));
                        memset(mOffsetData, 0, sizeof(mData));
                        mError = C2_BAD_VALUE;
                        return;
                    }
                    mData[planeIx] += (ssize_t)crop.left * mLayout.planes[planeIx].colInc
                    mOffsetData[planeIx] =
                        mData[planeIx] + (ssize_t)crop.left * mLayout.planes[planeIx].colInc
                                + (ssize_t)crop.top * mLayout.planes[planeIx].rowInc;
                }
            }
@@ -441,12 +444,13 @@ public:
            // CHECK(error != C2_OK);
            memset(&mLayout, 0, sizeof(mLayout));
            memset(mData, 0, sizeof(mData));
            memset(mOffsetData, 0, sizeof(mData));
        }

    public:
        ~Mapped() {
            if (mData[0] != nullptr) {
                mImpl->getAllocation()->unmap(nullptr);
                mImpl->getAllocation()->unmap(mData, mImpl->crop(), nullptr);
            }
        }

@@ -454,7 +458,7 @@ public:
        c2_status_t error() const { return mError; }

        /** returns data pointer */
        uint8_t *const *data() const { return mData; }
        uint8_t *const *data() const { return mOffsetData; }

        /** returns the plane layout */
        C2PlanarLayout layout() const { return mLayout; }
@@ -467,6 +471,7 @@ public:
        bool mWritable;
        c2_status_t mError;
        uint8_t *mData[C2PlanarLayout::MAX_NUM_PLANES];
        uint8_t *mOffsetData[C2PlanarLayout::MAX_NUM_PLANES];
        C2PlanarLayout mLayout;
    };