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

Commit 442b6de7 authored by Okan Arikan's avatar Okan Arikan Committed by Android (Google) Code Review
Browse files

Merge "Adopt the use of shared buffers."

parents de370e5e 822b710a
Loading
Loading
Loading
Loading
+28 −7
Original line number Original line Diff line number Diff line
@@ -174,8 +174,6 @@ class BroadcastRing {
  //
  //
  // There must be at least |MemorySize(record_count)| bytes of space already
  // There must be at least |MemorySize(record_count)| bytes of space already
  // allocated at |mmap|. The ring does not take ownership.
  // 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,
  static BroadcastRing Create(void* mmap, size_t mmap_size,
                              uint32_t record_count) {
                              uint32_t record_count) {
    BroadcastRing ring(mmap);
    BroadcastRing ring(mmap);
@@ -188,12 +186,11 @@ class BroadcastRing {
  //
  //
  // There must be at least |MemorySize()| bytes of space already allocated at
  // There must be at least |MemorySize()| bytes of space already allocated at
  // |mmap|. The ring does not take ownership.
  // |mmap|. The ring does not take ownership.
  //
  // Use this function for statically sized rings.
  static BroadcastRing Create(void* mmap, size_t mmap_size) {
  static BroadcastRing Create(void* mmap, size_t mmap_size) {
    static_assert(Traits::kUseStaticRecordCount,
    return Create(mmap, mmap_size,
                  "Wrong Create() function called for dynamic record count");
                  Traits::kUseStaticRecordCount
    return Create(mmap, mmap_size, Traits::kStaticRecordCount);
                      ? Traits::kStaticRecordCount
                      : BroadcastRing::GetRecordCount(mmap_size));
  }
  }


  // Imports an existing ring at |mmap|.
  // Imports an existing ring at |mmap|.
@@ -233,6 +230,30 @@ class BroadcastRing {
    return MemorySize(Traits::kStaticRecordCount);
    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.
  // Writes a record to the ring.
  //
  //
  // The oldest record is overwritten unless the ring is not already full.
  // The oldest record is overwritten unless the ring is not already full.
+2 −1
Original line number Original line Diff line number Diff line
@@ -17,6 +17,7 @@ sourceFiles = [
    "display_manager_client.cpp",
    "display_manager_client.cpp",
    "display_protocol.cpp",
    "display_protocol.cpp",
    "vsync_client.cpp",
    "vsync_client.cpp",
    "shared_buffer_helpers.cpp",
]
]


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


+138 −0
Original line number Original line 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 Original line 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 Original line Diff line number Diff line
@@ -34,10 +34,11 @@ srcs = [
]
]


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