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

Commit 434bc98a authored by John Reck's avatar John Reck
Browse files

Move PlaneLayout lookup to GraphicBuffer

This keeps GraphicBufferMapper's lock closer to a raw
lock avoiding the PlaneLayout query if nobody is asking for it,
reduces code duplication between Gralloc 4 & 5, and enables
caching of the PlaneLayout to minimize queries

Partial step towards an extended lock buffer API

Also begin modernizing the API surface using a proper
Result<T> along with an error enum class

Test: make && atest
Bug: 288142323
Change-Id: Ib4590b7a3b839a993f6c747c5f09a6312f7ab329
parent 19db87d0
Loading
Loading
Loading
Loading
+2 −31
Original line number Diff line number Diff line
@@ -262,37 +262,8 @@ void Gralloc4Mapper::getTransportSize(buffer_handle_t bufferHandle, uint32_t* ou
status_t Gralloc4Mapper::lock(buffer_handle_t bufferHandle, uint64_t usage, const Rect& bounds,
                              int acquireFence, void** outData, int32_t* outBytesPerPixel,
                              int32_t* outBytesPerStride) const {
    std::vector<ui::PlaneLayout> planeLayouts;
    status_t err = getPlaneLayouts(bufferHandle, &planeLayouts);

    if (err == NO_ERROR && !planeLayouts.empty()) {
        if (outBytesPerPixel) {
            int32_t bitsPerPixel = planeLayouts.front().sampleIncrementInBits;
            for (const auto& planeLayout : planeLayouts) {
                if (bitsPerPixel != planeLayout.sampleIncrementInBits) {
                    bitsPerPixel = -1;
                }
            }
            if (bitsPerPixel >= 0 && bitsPerPixel % 8 == 0) {
                *outBytesPerPixel = bitsPerPixel / 8;
            } else {
                *outBytesPerPixel = -1;
            }
        }
        if (outBytesPerStride) {
            int32_t bytesPerStride = planeLayouts.front().strideInBytes;
            for (const auto& planeLayout : planeLayouts) {
                if (bytesPerStride != planeLayout.strideInBytes) {
                    bytesPerStride = -1;
                }
            }
            if (bytesPerStride >= 0) {
                *outBytesPerStride = bytesPerStride;
            } else {
                *outBytesPerStride = -1;
            }
        }
    }
    if (outBytesPerPixel) *outBytesPerPixel = -1;
    if (outBytesPerStride) *outBytesPerStride = -1;

    auto buffer = const_cast<native_handle_t*>(bufferHandle);

+2 −31
Original line number Diff line number Diff line
@@ -589,37 +589,8 @@ void Gralloc5Mapper::getTransportSize(buffer_handle_t bufferHandle, uint32_t *ou
status_t Gralloc5Mapper::lock(buffer_handle_t bufferHandle, uint64_t usage, const Rect &bounds,
                              int acquireFence, void **outData, int32_t *outBytesPerPixel,
                              int32_t *outBytesPerStride) const {
    std::vector<ui::PlaneLayout> planeLayouts;
    status_t err = getPlaneLayouts(bufferHandle, &planeLayouts);

    if (err == NO_ERROR && !planeLayouts.empty()) {
        if (outBytesPerPixel) {
            int32_t bitsPerPixel = planeLayouts.front().sampleIncrementInBits;
            for (const auto &planeLayout : planeLayouts) {
                if (bitsPerPixel != planeLayout.sampleIncrementInBits) {
                    bitsPerPixel = -1;
                }
            }
            if (bitsPerPixel >= 0 && bitsPerPixel % 8 == 0) {
                *outBytesPerPixel = bitsPerPixel / 8;
            } else {
                *outBytesPerPixel = -1;
            }
        }
        if (outBytesPerStride) {
            int32_t bytesPerStride = planeLayouts.front().strideInBytes;
            for (const auto &planeLayout : planeLayouts) {
                if (bytesPerStride != planeLayout.strideInBytes) {
                    bytesPerStride = -1;
                }
            }
            if (bytesPerStride >= 0) {
                *outBytesPerStride = bytesPerStride;
            } else {
                *outBytesPerStride = -1;
            }
        }
    }
    if (outBytesPerPixel) *outBytesPerPixel = -1;
    if (outBytesPerStride) *outBytesPerStride = -1;

    auto status = mMapper->v5.lock(bufferHandle, usage, bounds, acquireFence, outData);

+86 −16
Original line number Diff line number Diff line
@@ -22,7 +22,7 @@
#include <cutils/atomic.h>

#include <grallocusage/GrallocUsageConversion.h>

#include <sync/sync.h>
#include <ui/GraphicBufferAllocator.h>
#include <ui/GraphicBufferMapper.h>
#include <utils/Trace.h>
@@ -40,6 +40,38 @@ static uint64_t getUniqueId() {
    return id;
}

static void resolveLegacyByteLayoutFromPlaneLayout(const std::vector<ui::PlaneLayout>& planeLayouts,
                                                   int32_t* outBytesPerPixel,
                                                   int32_t* outBytesPerStride) {
    if (planeLayouts.empty()) return;
    if (outBytesPerPixel) {
        int32_t bitsPerPixel = planeLayouts.front().sampleIncrementInBits;
        for (const auto& planeLayout : planeLayouts) {
            if (bitsPerPixel != planeLayout.sampleIncrementInBits) {
                bitsPerPixel = -1;
            }
        }
        if (bitsPerPixel >= 0 && bitsPerPixel % 8 == 0) {
            *outBytesPerPixel = bitsPerPixel / 8;
        } else {
            *outBytesPerPixel = -1;
        }
    }
    if (outBytesPerStride) {
        int32_t bytesPerStride = planeLayouts.front().strideInBytes;
        for (const auto& planeLayout : planeLayouts) {
            if (bytesPerStride != planeLayout.strideInBytes) {
                bytesPerStride = -1;
            }
        }
        if (bytesPerStride >= 0) {
            *outBytesPerStride = bytesPerStride;
        } else {
            *outBytesPerStride = -1;
        }
    }
}

sp<GraphicBuffer> GraphicBuffer::from(ANativeWindowBuffer* anwb) {
    return static_cast<GraphicBuffer *>(anwb);
}
@@ -279,10 +311,7 @@ status_t GraphicBuffer::lock(uint32_t inUsage, const Rect& rect, void** vaddr,
        return BAD_VALUE;
    }

    status_t res = getBufferMapper().lock(handle, inUsage, rect, vaddr, outBytesPerPixel,
                                          outBytesPerStride);

    return res;
    return lockAsync(inUsage, rect, vaddr, -1, outBytesPerPixel, outBytesPerStride);
}

status_t GraphicBuffer::lockYCbCr(uint32_t inUsage, android_ycbcr* ycbcr)
@@ -302,14 +331,12 @@ status_t GraphicBuffer::lockYCbCr(uint32_t inUsage, const Rect& rect,
                width, height);
        return BAD_VALUE;
    }
    status_t res = getBufferMapper().lockYCbCr(handle, inUsage, rect, ycbcr);
    return res;
    return lockAsyncYCbCr(inUsage, rect, ycbcr, -1);
}

status_t GraphicBuffer::unlock()
{
    status_t res = getBufferMapper().unlock(handle);
    return res;
    return unlockAsync(nullptr);
}

status_t GraphicBuffer::lockAsync(uint32_t inUsage, void** vaddr, int fenceFd,
@@ -336,10 +363,49 @@ status_t GraphicBuffer::lockAsync(uint64_t inProducerUsage, uint64_t inConsumerU
        return BAD_VALUE;
    }

    status_t res = getBufferMapper().lockAsync(handle, inProducerUsage, inConsumerUsage, rect,
                                               vaddr, fenceFd, outBytesPerPixel, outBytesPerStride);
    // Resolve the bpp & bps before doing a lock in case this fails we don't have to worry about
    // doing an unlock
    int32_t legacyBpp = -1, legacyBps = -1;
    if (outBytesPerPixel || outBytesPerStride) {
        const auto mapperVersion = getBufferMapperVersion();
        // For gralloc2 we need to guess at the bpp & bps
        // For gralloc3 the lock() call will return it
        // For gralloc4 & later the PlaneLayout metadata query is vastly superior and we
        // resolve bpp & bps just for compatibility

        // TODO: See if we can't just remove gralloc2 support.
        if (mapperVersion == GraphicBufferMapper::GRALLOC_2) {
            legacyBpp = bytesPerPixel(format);
            if (legacyBpp > 0) {
                legacyBps = stride * legacyBpp;
            } else {
                legacyBpp = -1;
            }
        } else if (mapperVersion >= GraphicBufferMapper::GRALLOC_4) {
            auto planeLayout = getBufferMapper().getPlaneLayouts(handle);
            if (!planeLayout.has_value()) return planeLayout.asStatus();
            resolveLegacyByteLayoutFromPlaneLayout(planeLayout.value(), &legacyBpp, &legacyBps);
        }
    }

    const uint64_t usage = static_cast<uint64_t>(
            android_convertGralloc1To0Usage(inProducerUsage, inConsumerUsage));

    return res;
    auto result = getBufferMapper().lock(handle, usage, rect, base::unique_fd{fenceFd});

    if (!result.has_value()) {
        return result.error().asStatus();
    }
    auto value = result.value();
    *vaddr = value.address;

    if (outBytesPerPixel) {
        *outBytesPerPixel = legacyBpp != -1 ? legacyBpp : value.bytesPerPixel;
    }
    if (outBytesPerStride) {
        *outBytesPerStride = legacyBps != -1 ? legacyBps : value.bytesPerStride;
    }
    return OK;
}

status_t GraphicBuffer::lockAsyncYCbCr(uint32_t inUsage, android_ycbcr* ycbcr,
@@ -360,14 +426,18 @@ status_t GraphicBuffer::lockAsyncYCbCr(uint32_t inUsage, const Rect& rect,
                width, height);
        return BAD_VALUE;
    }
    status_t res = getBufferMapper().lockAsyncYCbCr(handle, inUsage, rect, ycbcr, fenceFd);
    return res;
    auto result = getBufferMapper().lockYCbCr(handle, static_cast<int64_t>(inUsage), rect,
                                              base::unique_fd{fenceFd});
    if (!result.has_value()) {
        return result.error().asStatus();
    }
    *ycbcr = result.value();
    return OK;
}

status_t GraphicBuffer::unlockAsync(int *fenceFd)
{
    status_t res = getBufferMapper().unlockAsync(handle, fenceFd);
    return res;
    return getBufferMapper().unlockAsync(handle, fenceFd);
}

status_t GraphicBuffer::isSupported(uint32_t inWidth, uint32_t inHeight, PixelFormat inFormat,
+81 −43
Original line number Diff line number Diff line
@@ -41,9 +41,13 @@

#include <system/graphics.h>

using unique_fd = ::android::base::unique_fd;

namespace android {
// ---------------------------------------------------------------------------

using LockResult = GraphicBufferMapper::LockResult;

ANDROID_SINGLETON_STATIC_INSTANCE( GraphicBufferMapper )

void GraphicBufferMapper::preloadHal() {
@@ -135,63 +139,86 @@ status_t GraphicBufferMapper::freeBuffer(buffer_handle_t handle)
    return NO_ERROR;
}

status_t GraphicBufferMapper::lock(buffer_handle_t handle, uint32_t usage, const Rect& bounds,
                                   void** vaddr, int32_t* outBytesPerPixel,
                                   int32_t* outBytesPerStride) {
    return lockAsync(handle, usage, bounds, vaddr, -1, outBytesPerPixel, outBytesPerStride);
}
ui::Result<LockResult> GraphicBufferMapper::lock(buffer_handle_t handle, int64_t usage,
                                                 const Rect& bounds, unique_fd&& acquireFence) {
    ATRACE_CALL();

status_t GraphicBufferMapper::lockYCbCr(buffer_handle_t handle, uint32_t usage,
        const Rect& bounds, android_ycbcr *ycbcr)
{
    return lockAsyncYCbCr(handle, usage, bounds, ycbcr, -1);
    LockResult result;
    status_t status = mMapper->lock(handle, usage, bounds, acquireFence.release(), &result.address,
                                    &result.bytesPerPixel, &result.bytesPerStride);
    if (status != OK) {
        return base::unexpected(ui::Error::statusToCode(status));
    } else {
        return result;
    }

status_t GraphicBufferMapper::unlock(buffer_handle_t handle)
{
    int32_t fenceFd = -1;
    status_t error = unlockAsync(handle, &fenceFd);
    if (error == NO_ERROR && fenceFd >= 0) {
        sync_wait(fenceFd, -1);
        close(fenceFd);
    }
    return error;
}

status_t GraphicBufferMapper::lockAsync(buffer_handle_t handle, uint32_t usage, const Rect& bounds,
                                        void** vaddr, int fenceFd, int32_t* outBytesPerPixel,
                                        int32_t* outBytesPerStride) {
    return lockAsync(handle, usage, usage, bounds, vaddr, fenceFd, outBytesPerPixel,
                     outBytesPerStride);
}

status_t GraphicBufferMapper::lockAsync(buffer_handle_t handle, uint64_t producerUsage,
                                        uint64_t consumerUsage, const Rect& bounds, void** vaddr,
                                        int fenceFd, int32_t* outBytesPerPixel,
                                        int32_t* outBytesPerStride) {
ui::Result<android_ycbcr> GraphicBufferMapper::lockYCbCr(buffer_handle_t handle, int64_t usage,
                                                         const Rect& bounds,
                                                         base::unique_fd&& acquireFence) {
    ATRACE_CALL();

    const uint64_t usage = static_cast<uint64_t>(
            android_convertGralloc1To0Usage(producerUsage, consumerUsage));
    return mMapper->lock(handle, usage, bounds, fenceFd, vaddr, outBytesPerPixel,
                         outBytesPerStride);
    android_ycbcr result = {};
    status_t status = mMapper->lock(handle, usage, bounds, acquireFence.release(), &result);
    if (status != OK) {
        return base::unexpected(ui::Error::statusToCode(status));
    } else {
        return result;
    }
}

status_t GraphicBufferMapper::lockAsyncYCbCr(buffer_handle_t handle,
        uint32_t usage, const Rect& bounds, android_ycbcr *ycbcr, int fenceFd)
{
status_t GraphicBufferMapper::unlock(buffer_handle_t handle, base::unique_fd* outFence) {
    ATRACE_CALL();
    int fence = mMapper->unlock(handle);
    if (outFence) {
        *outFence = unique_fd{fence};
    } else {
        sync_wait(fence, -1);
        close(fence);
    }
    return OK;
}

    return mMapper->lock(handle, usage, bounds, fenceFd, ycbcr);
status_t GraphicBufferMapper::lock(buffer_handle_t handle, uint32_t usage, const Rect& bounds,
                                   void** vaddr) {
    auto result = lock(handle, static_cast<int64_t>(usage), bounds);
    if (!result.has_value()) return result.asStatus();
    auto val = result.value();
    *vaddr = val.address;
    return OK;
}

status_t GraphicBufferMapper::unlockAsync(buffer_handle_t handle, int *fenceFd)
{
    ATRACE_CALL();
status_t GraphicBufferMapper::lockYCbCr(buffer_handle_t handle, uint32_t usage, const Rect& bounds,
                                        android_ycbcr* ycbcr) {
    auto result = lockYCbCr(handle, static_cast<int64_t>(usage), bounds);
    if (!result.has_value()) return result.asStatus();
    *ycbcr = result.value();
    return OK;
}

status_t GraphicBufferMapper::lockAsync(buffer_handle_t handle, uint32_t usage, const Rect& bounds,
                                        void** vaddr, int fenceFd) {
    auto result = lock(handle, static_cast<int64_t>(usage), bounds, unique_fd{fenceFd});
    if (!result.has_value()) return result.asStatus();
    auto val = result.value();
    *vaddr = val.address;
    return OK;
}

    *fenceFd = mMapper->unlock(handle);
status_t GraphicBufferMapper::lockAsync(buffer_handle_t handle, uint64_t producerUsage,
                                        uint64_t consumerUsage, const Rect& bounds, void** vaddr,
                                        int fenceFd) {
    return lockAsync(handle, android_convertGralloc1To0Usage(producerUsage, consumerUsage), bounds,
                     vaddr, fenceFd);
}

    return NO_ERROR;
status_t GraphicBufferMapper::lockAsyncYCbCr(buffer_handle_t handle, uint32_t usage,
                                             const Rect& bounds, android_ycbcr* ycbcr,
                                             int fenceFd) {
    auto result = lockYCbCr(handle, static_cast<int64_t>(usage), bounds, unique_fd{fenceFd});
    if (!result.has_value()) return result.asStatus();
    *ycbcr = result.value();
    return OK;
}

status_t GraphicBufferMapper::isSupported(uint32_t width, uint32_t height,
@@ -287,6 +314,17 @@ status_t GraphicBufferMapper::getPlaneLayouts(buffer_handle_t bufferHandle,
    return mMapper->getPlaneLayouts(bufferHandle, outPlaneLayouts);
}

ui::Result<std::vector<ui::PlaneLayout>> GraphicBufferMapper::getPlaneLayouts(
        buffer_handle_t bufferHandle) {
    std::vector<ui::PlaneLayout> temp;
    status_t status = mMapper->getPlaneLayouts(bufferHandle, &temp);
    if (status == OK) {
        return std::move(temp);
    } else {
        return base::unexpected(ui::Error::statusToCode(status));
    }
}

status_t GraphicBufferMapper::getDataspace(buffer_handle_t bufferHandle,
                                           ui::Dataspace* outDataspace) {
    return mMapper->getDataspace(bufferHandle, outDataspace);
+41 −9
Original line number Diff line number Diff line
@@ -22,9 +22,11 @@

#include <memory>

#include <android-base/unique_fd.h>
#include <ui/GraphicTypes.h>
#include <ui/PixelFormat.h>
#include <ui/Rect.h>
#include <ui/Result.h>
#include <utils/Singleton.h>

// Needed by code that still uses the GRALLOC_USAGE_* constants.
@@ -38,6 +40,12 @@ namespace android {

class GrallocMapper;

/**
 * This class is a thin wrapper over the various gralloc HALs. It is a "raw" wrapper, having
 * version-specific behaviors & features. It is not recommend for general use. It is instead
 * strongly recommended to use AHardwareBuffer or ui::GraphicBuffer which will provide stronger
 * API compatibility & consistency behaviors.
 */
class GraphicBufferMapper : public Singleton<GraphicBufferMapper>
{
public:
@@ -66,27 +74,50 @@ public:
    void getTransportSize(buffer_handle_t handle,
            uint32_t* outTransportNumFds, uint32_t* outTransportNumInts);

    status_t lock(buffer_handle_t handle, uint32_t usage, const Rect& bounds, void** vaddr,
                  int32_t* outBytesPerPixel = nullptr, int32_t* outBytesPerStride = nullptr);
    struct LockResult {
        void* address = nullptr;
        /**
         * Note: bytesPerPixel is only populated if version is gralloc 3
         * Gralloc 4 & later should use instead getPlaneLayout()
         */
        int32_t bytesPerPixel = -1;
        /**
         * Note: bytesPerPixel is only populated if version is gralloc 3
         * Gralloc 4 & later should use instead getPlaneLayout()
         */
        int32_t bytesPerStride = -1;
    };

    ui::Result<LockResult> lock(buffer_handle_t handle, int64_t usage, const Rect& bounds,
                                base::unique_fd&& acquireFence = {});

    ui::Result<android_ycbcr> lockYCbCr(buffer_handle_t handle, int64_t usage, const Rect& bounds,
                                        base::unique_fd&& acquireFence = {});

    status_t lock(buffer_handle_t handle, uint32_t usage, const Rect& bounds, void** vaddr);

    status_t lockYCbCr(buffer_handle_t handle,
            uint32_t usage, const Rect& bounds, android_ycbcr *ycbcr);

    status_t unlock(buffer_handle_t handle);

    status_t lockAsync(buffer_handle_t handle, uint32_t usage, const Rect& bounds, void** vaddr,
                       int fenceFd, int32_t* outBytesPerPixel = nullptr,
                       int32_t* outBytesPerStride = nullptr);
                       int fenceFd);

    status_t lockAsync(buffer_handle_t handle, uint64_t producerUsage, uint64_t consumerUsage,
                       const Rect& bounds, void** vaddr, int fenceFd,
                       int32_t* outBytesPerPixel = nullptr, int32_t* outBytesPerStride = nullptr);
                       const Rect& bounds, void** vaddr, int fenceFd);

    status_t lockAsyncYCbCr(buffer_handle_t handle,
            uint32_t usage, const Rect& bounds, android_ycbcr *ycbcr,
            int fenceFd);

    status_t unlockAsync(buffer_handle_t handle, int *fenceFd);
    status_t unlock(buffer_handle_t handle, base::unique_fd* outFence = nullptr);
    status_t unlockAsync(buffer_handle_t handle, int* fenceFd) {
        base::unique_fd temp;
        status_t result = unlock(handle, fenceFd ? &temp : nullptr);
        if (fenceFd) {
            *fenceFd = temp.release();
        }
        return result;
    }

    status_t isSupported(uint32_t width, uint32_t height, android::PixelFormat format,
                         uint32_t layerCount, uint64_t usage, bool* outSupported);
@@ -122,6 +153,7 @@ public:
    status_t getChromaSiting(buffer_handle_t bufferHandle, ui::ChromaSiting* outChromaSiting);
    status_t getPlaneLayouts(buffer_handle_t bufferHandle,
                             std::vector<ui::PlaneLayout>* outPlaneLayouts);
    ui::Result<std::vector<ui::PlaneLayout>> getPlaneLayouts(buffer_handle_t bufferHandle);
    status_t getDataspace(buffer_handle_t bufferHandle, ui::Dataspace* outDataspace);
    status_t setDataspace(buffer_handle_t bufferHandle, ui::Dataspace dataspace);
    status_t getBlendMode(buffer_handle_t bufferHandle, ui::BlendMode* outBlendMode);
Loading