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

Commit 822b710a authored by Okan Arikan's avatar Okan Arikan
Browse files

Adopt the use of shared buffers.

Bug: 37001948
Test: Make system image
Change-Id: I032574f250e0f0fe7768af649730406e24d853db
parent f2dcd371
Loading
Loading
Loading
Loading
+28 −7
Original line number Diff line number Diff line
@@ -174,8 +174,6 @@ class BroadcastRing {
  //
  // There must be at least |MemorySize(record_count)| bytes of space already
  // allocated at |mmap|. The ring does not take ownership.
  //
  // Use this function for dynamically sized rings.
  static BroadcastRing Create(void* mmap, size_t mmap_size,
                              uint32_t record_count) {
    BroadcastRing ring(mmap);
@@ -188,12 +186,11 @@ class BroadcastRing {
  //
  // There must be at least |MemorySize()| bytes of space already allocated at
  // |mmap|. The ring does not take ownership.
  //
  // Use this function for statically sized rings.
  static BroadcastRing Create(void* mmap, size_t mmap_size) {
    static_assert(Traits::kUseStaticRecordCount,
                  "Wrong Create() function called for dynamic record count");
    return Create(mmap, mmap_size, Traits::kStaticRecordCount);
    return Create(mmap, mmap_size,
                  Traits::kUseStaticRecordCount
                      ? Traits::kStaticRecordCount
                      : BroadcastRing::GetRecordCount(mmap_size));
  }

  // Imports an existing ring at |mmap|.
@@ -233,6 +230,30 @@ class BroadcastRing {
    return MemorySize(Traits::kStaticRecordCount);
  }

  static uint32_t NextPowerOf2(uint32_t n) {
    if (n == 0)
      return 0;
    n -= 1;
    n |= n >> 16;
    n |= n >> 8;
    n |= n >> 4;
    n |= n >> 2;
    n |= n >> 1;
    return n + 1;
  }

  // Gets the biggest power of 2 record count that can fit into this mmap.
  //
  // The header size has been taken into account.
  static uint32_t GetRecordCount(size_t mmap_size) {
    if (mmap_size <= sizeof(Header)) {
      return 0;
    }
    uint32_t count =
        static_cast<uint32_t>((mmap_size - sizeof(Header)) / sizeof(Record));
    return IsPowerOfTwo(count) ? count : (NextPowerOf2(count) / 2);
  }

  // Writes a record to the ring.
  //
  // The oldest record is overwritten unless the ring is not already full.
+2 −1
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@ sourceFiles = [
    "display_manager_client.cpp",
    "display_protocol.cpp",
    "vsync_client.cpp",
    "shared_buffer_helpers.cpp",
]

localIncludeFiles = [
@@ -39,7 +40,7 @@ staticLibraries = [
    "libdvrcommon",
    "libbufferhubqueue",
    "libbufferhub",
    "libvrsensor",
    "libbroadcastring",
    "libpdx_default_transport",
]

+138 −0
Original line number Diff line number Diff line
#ifndef ANDROID_DVR_SHARED_BUFFER_HELPERS_H_
#define ANDROID_DVR_SHARED_BUFFER_HELPERS_H_

#include <assert.h>
#include <tuple>

#include <libbroadcastring/broadcast_ring.h>
#include <private/dvr/display_client.h>

namespace android {
namespace dvr {

// The buffer usage type for mapped shared buffers.
enum class CPUUsageMode { READ_OFTEN, READ_RARELY, WRITE_OFTEN, WRITE_RARELY };

// Holds the memory for the mapped shared buffer. Unlocks and releases the
// underlying IonBuffer in destructor.
class CPUMappedBuffer {
 public:
  // This constructor will create a display client and get the buffer from it.
  CPUMappedBuffer(DvrGlobalBufferKey key, CPUUsageMode mode);

  // If you already have the IonBuffer, use this. It will take ownership.
  CPUMappedBuffer(std::unique_ptr<IonBuffer> buffer, CPUUsageMode mode);

  // Use this if you do not want to take ownership.
  CPUMappedBuffer(IonBuffer* buffer, CPUUsageMode mode);

  ~CPUMappedBuffer();

  // Getters.
  size_t Size() const { return size_; }
  void* Address() const { return address_; }
  bool IsMapped() const { return Address() != nullptr; }

  // Attempt mapping this buffer to the CPU addressable space.
  // This will create a display client and see if the buffer exists.
  // If the buffer has not been setup yet, you will need to try again later.
  void TryMapping();

 protected:
  // The memory area if we managed to map it.
  size_t size_ = 0;
  void* address_ = nullptr;

  // If we are polling the display client, the buffer key here.
  DvrGlobalBufferKey buffer_key_;

  // If we just own the IonBuffer outright, it's here.
  std::unique_ptr<IonBuffer> owned_buffer_ = nullptr;

  // If we do not own the IonBuffer, it's here
  IonBuffer* buffer_ = nullptr;

  // The usage mode.
  CPUUsageMode usage_mode_ = CPUUsageMode::READ_OFTEN;
};

// Represents a broadcast ring inside a mapped shared memory buffer.
// If has the same set of constructors as CPUMappedBuffer.
// The template argument is the concrete BroadcastRing class that this buffer
// holds.
template <class RingType>
class CPUMappedBroadcastRing : public CPUMappedBuffer {
 public:
  CPUMappedBroadcastRing(DvrGlobalBufferKey key, CPUUsageMode mode)
      : CPUMappedBuffer(key, mode) {}

  CPUMappedBroadcastRing(std::unique_ptr<IonBuffer> buffer, CPUUsageMode mode)
      : CPUMappedBuffer(std::move(buffer), mode) {}

  CPUMappedBroadcastRing(IonBuffer* buffer, CPUUsageMode mode)
      : CPUMappedBuffer(buffer, mode) {}

  // Helper function for publishing records in the ring.
  void Publish(const typename RingType::Record& record) {
    assert((usage_mode_ == CPUUsageMode::WRITE_OFTEN) ||
           (usage_mode_ == CPUUsageMode::WRITE_RARELY));

    auto ring = Ring();
    if (ring) {
      ring->Put(record);
    }
  }

  // Helper function for getting records from the ring.
  // Returns true if we were able to retrieve the latest.
  bool GetNewest(typename RingType::Record* record) {
    assert((usage_mode_ == CPUUsageMode::READ_OFTEN) ||
           (usage_mode_ == CPUUsageMode::READ_RARELY));

    auto ring = Ring();
    if (ring) {
      return ring->GetNewest(&sequence_, record);
    }

    return false;
  }

  // Try obtaining the ring. If the named buffer has not been created yet, it
  // will return nullptr.
  RingType* Ring() {
    if (IsMapped() == false) {
      TryMapping();

      if (IsMapped()) {
        switch (usage_mode_) {
          case CPUUsageMode::READ_OFTEN:
          case CPUUsageMode::READ_RARELY: {
            RingType ring;
            bool import_ok;
            std::tie(ring, import_ok) = RingType::Import(address_, size_);
            if (import_ok) {
              ring_ = std::make_unique<RingType>(ring);
            }
          } break;
          case CPUUsageMode::WRITE_OFTEN:
          case CPUUsageMode::WRITE_RARELY:
            ring_ =
                std::make_unique<RingType>(RingType::Create(address_, size_));
            break;
        }
      }
    }

    return ring_.get();
  }

 protected:
  std::unique_ptr<RingType> ring_ = nullptr;

  uint32_t sequence_ = 0;
};

}  // namespace dvr
}  // namespace android

#endif  // ANDROID_DVR_SHARED_BUFFER_HELPERS_H_
+84 −0
Original line number Diff line number Diff line
#include <private/dvr/shared_buffer_helpers.h>

namespace android {
namespace dvr {

CPUMappedBuffer::CPUMappedBuffer(DvrGlobalBufferKey key, CPUUsageMode mode)
    : buffer_key_(key), usage_mode_(mode) {
  TryMapping();
}

CPUMappedBuffer::CPUMappedBuffer(std::unique_ptr<IonBuffer> buffer,
                                 CPUUsageMode mode)
    : owned_buffer_(std::move(buffer)),
      buffer_(owned_buffer_.get()),
      usage_mode_(mode) {
  TryMapping();
}

CPUMappedBuffer::CPUMappedBuffer(IonBuffer* buffer, CPUUsageMode mode)
    : buffer_(buffer), usage_mode_(mode) {
  TryMapping();
}

CPUMappedBuffer::~CPUMappedBuffer() {
  if (IsMapped()) {
    buffer_->Unlock();
  }
}

void CPUMappedBuffer::TryMapping() {
  // Do we have an IonBuffer for this shared memory object?
  if (buffer_ == nullptr) {
    // Create a display client and get the buffer.
    // TODO(okana): We might want to throttle this.
    auto display_client = display::DisplayClient::Create();
    if (display_client) {
      auto get_result = display_client->GetGlobalBuffer(buffer_key_);
      if (get_result.ok()) {
        owned_buffer_ = get_result.take();
        buffer_ = owned_buffer_.get();
      } else {
        ALOGW("Could not get named buffer from pose service : %s(%d)",
              get_result.GetErrorMessage().c_str(), get_result.error());
      }
    } else {
      ALOGE("Unable to create display client for shared buffer access");
    }
  }

  if (buffer_) {
    auto usage = buffer_->usage() & ~GRALLOC_USAGE_SW_READ_MASK &
                 ~GRALLOC_USAGE_SW_WRITE_MASK;

    // Figure out the usage bits.
    switch (usage_mode_) {
      case CPUUsageMode::READ_OFTEN:
        usage |= GRALLOC_USAGE_SW_READ_OFTEN;
        break;
      case CPUUsageMode::READ_RARELY:
        usage |= GRALLOC_USAGE_SW_READ_RARELY;
        break;
      case CPUUsageMode::WRITE_OFTEN:
        usage |= GRALLOC_USAGE_SW_WRITE_OFTEN;
        break;
      case CPUUsageMode::WRITE_RARELY:
        usage |= GRALLOC_USAGE_SW_WRITE_RARELY;
        break;
    }

    int width = static_cast<int>(buffer_->width());
    int height = 1;
    const auto ret = buffer_->Lock(usage, 0, 0, width, height, &address_);

    if (ret < 0 || !address_) {
      ALOGE("Pose failed to map ring buffer: ret:%d, addr:%p", ret, address_);
      buffer_->Unlock();
    } else {
      size_ = width;
    }
  }
}

}  // namespace dvr
}  // namespace android
+2 −1
Original line number Diff line number Diff line
@@ -34,10 +34,11 @@ srcs = [
]

static_libs = [
    "libbroadcastring",
    "libbufferhub",
    "libbufferhubqueue",
    "libdisplay",
    "libvrsensor",
    "libdisplay",
    "libvirtualtouchpadclient",
    "libvr_hwc-impl",
    "libvr_hwc-binder",
Loading