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

Commit 2251d822 authored by Corey Tabaka's avatar Corey Tabaka
Browse files

Remove the VR compositor from the framework.

Remove the VR compositor framework and enable out-of-process VR composition
in VrCore.

This CL seems large due to the ripple effect of changing the VrFlinger
API and protocol types. There are three major modules that require
concurrent changes:
  1. Protocol definitions and low-level VrFlinger API in libdisplay.
     * Additional changes needed to keep old interfaces working for
       a short time while replacing the dependent code (dvrGraphics*).
  2. VrFlinger service implementation changes to support VrCore compositor
     and the removal of the internal compositor.
  3. Changes to libdvr platform library API due to changes in #1 and #2.

Because of the nature of the interdependence of types and other defs it is
difficult to break this CL into smaller chunks. However, review of the three
major modules (libdisplay, libdvr, and libvrflinger) may be done separately
to ease the mental burden on reviewers.

Change Summary:
- Remove obsolete screenshot service. VR screenshots will be implemented
  by VrCore.
- Update display protocol definitions for changes in VrFlinger service
  requirements. The majority of the changes in libdisplay are a
  consequence of these protocol and service changes.
- Update VrFlinger to support two kinds of surfaces:
    1. Application - use by VR apps.
    2. Direct - used by VrCore (protected by permission check).
- Remove VrFlinger internal compositor and GL context.
- Remove obsolete debug console.
- Update VrFlinger hardware composer interface to handle direct
  surfaces only, removing the concept of GPU (compositor) layers.
- Update display manager to expose access to application surface info
  to VrCore (protected by permission check).
- Update libdvr platform library interfaces for changes to VrFlinger
  API / protocol.
- Clean up libdvr API struct setup using a common include.
- Add C++ header-only helpers for DVR platform library opaque types.

Bug: 36401174
Test: Build; run VrFlinger display test tool.
Change-Id: I15abfde5f72dbb3725a3f58621486afba6b64902
parent 3f82d313
Loading
Loading
Loading
Loading

cmds/vr/vrscreencap/Android.mk

deleted100644 → 0
+0 −25
Original line number Diff line number Diff line
LOCAL_PATH:= $(call my-dir)

include $(CLEAR_VARS)

LOCAL_SRC_FILES := \
	vrscreencap.cpp

LOCAL_STATIC_LIBRARIES := \
	libbufferhub \
	libdisplay \
	libimageio \
	libpdx_default_transport \

LOCAL_SHARED_LIBRARIES := \
	libcutils \
	liblog \
	libpng \
	libsync \
	libui \

LOCAL_MODULE := vrscreencap

LOCAL_MODULE_TAGS := optional

include $(BUILD_EXECUTABLE)
+0 −74
Original line number Diff line number Diff line
// screencap is a tool for taking screenshots using the screenshot service.

#include <fstream>
#include <iostream>
#include <string>
#include <vector>

#include <private/dvr/image_io.h>
#include <private/dvr/screenshot_client.h>

namespace {

// Attempt to take a screenshot and save it to |filename|.
// Returns zero on success, or a non-zero exit code otherwise.
int TakeScreenshot(const std::string& app_name, const std::string& filename,
                   int index) {
  auto error_out = [app_name]() -> std::ostream& {
    return std::cerr << app_name << ": ";
  };

  auto info_out = [app_name]() -> std::ostream& {
    return std::cout << app_name << ": ";
  };

  auto client = android::dvr::ScreenshotClient::Create();

  if (client->format() != HAL_PIXEL_FORMAT_RGB_888) {
    error_out() << "The screenshot format for this device is not supported."
                << std::endl;
    return 1;
  }

  std::vector<uint8_t> image;
  int width = 0;
  int height = 0;
  if (client->Take(&image, index, &width, &height) != 0) {
    error_out() << "Failed to take screenshot." << std::endl;
    return 1;
  }

  info_out() << "Got " << width << "x" << height << " screenshot." << std::endl;

  if (!image_io_write_rgb888(filename.c_str(), width, height, image.data())) {
    error_out() << "Failed to write image to output file " << filename
                << std::endl;
    return 1;
  }

  return 0;
}

}  // namespace

int main(int argc, char** argv) {
  // Parse arguments
  if (argc != 2 && argc != 3) {
    std::cerr
        << "Usage: " << argv[0]
        << " filename.[" DVR_IMAGE_IO_SUPPORTED_WRITE
           "] [INDEX]\n"
           "INDEX: specify 1..n to grab hw_composer layers by index.\n"
           "       specify -n to grab pre-warp layers (-1 is base layer).\n"
           "       the default is 1 (the base hw_composer layer).\n"
           "       an invalid index will result in an error.\n";
    return 1;
  }
  const std::string filename(argv[1]);
  int index = 1;
  if (argc > 2)
    index = atoi(argv[2]);

  // Perform the actual screenshot.
  return TakeScreenshot(argv[0], filename, index);
}
+0 −19
Original line number Diff line number Diff line
@@ -453,23 +453,4 @@ class ConsumerQueue : public BufferHubQueue {
}  // namespace dvr
}  // namespace android

// Concrete C type definition for DVR API.

#ifdef __cplusplus
extern "C" {
#endif

struct DvrWriteBufferQueue {
  std::shared_ptr<android::dvr::ProducerQueue> producer_queue_;
  ANativeWindow* native_window_{nullptr};
};

struct DvrReadBufferQueue {
  std::shared_ptr<android::dvr::ConsumerQueue> consumer_queue_;
};

#ifdef __cplusplus
}  // extern "C"
#endif

#endif  // ANDROID_DVR_BUFFER_HUB_QUEUE_CLIENT_H_
+1 −1
Original line number Diff line number Diff line
@@ -18,11 +18,11 @@ sourceFiles = [
    "display_manager_client.cpp",
    "display_protocol.cpp",
    "dummy_native_window.cpp",
    "frame_history.cpp",
    "gl_fenced_flush.cpp",
    "graphics.cpp",
    "late_latch.cpp",
    "vsync_client.cpp",
    "frame_history.cpp",
]

localIncludeFiles = [
+115 −181
Original line number Diff line number Diff line
@@ -12,6 +12,7 @@
#include <private/dvr/late_latch.h>
#include <private/dvr/native_buffer.h>

using android::pdx::ErrorStatus;
using android::pdx::LocalHandle;
using android::pdx::LocalChannelHandle;
using android::pdx::Status;
@@ -20,99 +21,61 @@ using android::pdx::rpc::IfAnyOf;

namespace android {
namespace dvr {
namespace display {

SurfaceClient::SurfaceClient(LocalChannelHandle channel_handle,
                             SurfaceType type)
    : Client{pdx::default_transport::ClientChannel::Create(
          std::move(channel_handle))},
      type_(type) {}

SurfaceClient::SurfaceClient(const std::string& endpoint_path, SurfaceType type)
    : Client{pdx::default_transport::ClientChannelFactory::Create(
                 endpoint_path),
             kInfiniteTimeout},
      type_(type) {}

int SurfaceClient::GetMetadataBufferFd(LocalHandle* out_fd) {
  auto buffer_producer = GetMetadataBuffer();
  if (!buffer_producer)
    return -ENOMEM;

  *out_fd = buffer_producer->GetBlobFd();
  return 0;
}

std::shared_ptr<BufferProducer> SurfaceClient::GetMetadataBuffer() {
  if (!metadata_buffer_) {
    auto status = InvokeRemoteMethod<DisplayRPC::GetMetadataBuffer>();
Surface::Surface(LocalChannelHandle channel_handle, int* error)
    : BASE{pdx::default_transport::ClientChannel::Create(
          std::move(channel_handle))} {
  auto status = InvokeRemoteMethod<DisplayProtocol::GetSurfaceInfo>();
  if (!status) {
      ALOGE(
          "SurfaceClient::AllocateMetadataBuffer: Failed to allocate buffer: "
          "%s",
    ALOGE("Surface::Surface: Failed to get surface info: %s",
          status.GetErrorMessage().c_str());
      return nullptr;
    }

    metadata_buffer_ = BufferProducer::Import(status.take());
    Close(status.error());
    if (error)
      *error = status.error();
  }

  return metadata_buffer_;
  surface_id_ = status.get().surface_id;
  z_order_ = status.get().z_order;
  visible_ = status.get().visible;
}

DisplaySurfaceClient::DisplaySurfaceClient(int width, int height, int format,
                                           int usage, int flags)
    : BASE(DisplayRPC::kClientPath, SurfaceTypeEnum::Normal),
      width_(width),
      height_(height),
      format_(format),
      usage_(usage),
      flags_(flags),
      z_order_(0),
      visible_(true),
      exclude_from_blur_(false),
      blur_behind_(true),
      mapped_metadata_buffer_(nullptr) {
  auto status = InvokeRemoteMethod<DisplayRPC::CreateSurface>(
      width, height, format, usage, flags);
Surface::Surface(const SurfaceAttributes& attributes, int* error)
    : BASE{pdx::default_transport::ClientChannelFactory::Create(
               DisplayProtocol::kClientPath),
           kInfiniteTimeout} {
  auto status = InvokeRemoteMethod<DisplayProtocol::CreateSurface>(attributes);
  if (!status) {
    ALOGE(
        "DisplaySurfaceClient::DisplaySurfaceClient: Failed to create display "
        "surface: %s",
    ALOGE("Surface::Surface: Failed to create display surface: %s",
          status.GetErrorMessage().c_str());
    Close(status.error());
  }
}

void DisplaySurfaceClient::SetVisible(bool visible) {
  SetAttributes({{DisplaySurfaceAttributeEnum::Visible,
                  DisplaySurfaceAttributeValue{visible}}});
    if (error)
      *error = status.error();
  }

void DisplaySurfaceClient::SetZOrder(int z_order) {
  SetAttributes({{DisplaySurfaceAttributeEnum::ZOrder,
                  DisplaySurfaceAttributeValue{z_order}}});
  surface_id_ = status.get().surface_id;
  z_order_ = status.get().z_order;
  visible_ = status.get().visible;
}

void DisplaySurfaceClient::SetExcludeFromBlur(bool exclude_from_blur) {
  SetAttributes({{DisplaySurfaceAttributeEnum::ExcludeFromBlur,
                  DisplaySurfaceAttributeValue{exclude_from_blur}}});
Status<void> Surface::SetVisible(bool visible) {
  return SetAttributes(
      {{SurfaceAttribute::Visible, SurfaceAttributeValue{visible}}});
}

void DisplaySurfaceClient::SetBlurBehind(bool blur_behind) {
  SetAttributes({{DisplaySurfaceAttributeEnum::BlurBehind,
                  DisplaySurfaceAttributeValue{blur_behind}}});
Status<void> Surface::SetZOrder(int z_order) {
  return SetAttributes(
      {{SurfaceAttribute::ZOrder, SurfaceAttributeValue{z_order}}});
}

void DisplaySurfaceClient::SetAttributes(
    const DisplaySurfaceAttributes& attributes) {
  Status<int> status =
      InvokeRemoteMethod<DisplayRPC::SetAttributes>(attributes);
Status<void> Surface::SetAttributes(const SurfaceAttributes& attributes) {
  auto status = InvokeRemoteMethod<DisplayProtocol::SetAttributes>(attributes);
  if (!status) {
    ALOGE(
        "DisplaySurfaceClient::SetAttributes: Failed to set display surface "
        "Surface::SetAttributes: Failed to set display surface "
        "attributes: %s",
        status.GetErrorMessage().c_str());
    return;
    return status.error_status();
  }

  // Set the local cached copies of the attributes we care about from the full
@@ -122,159 +85,130 @@ void DisplaySurfaceClient::SetAttributes(
    const auto* variant = &attribute.second;
    bool invalid_value = false;
    switch (key) {
      case DisplaySurfaceAttributeEnum::Visible:
      case SurfaceAttribute::Visible:
        invalid_value =
            !IfAnyOf<int32_t, int64_t, bool>::Get(variant, &visible_);
        break;
      case DisplaySurfaceAttributeEnum::ZOrder:
      case SurfaceAttribute::ZOrder:
        invalid_value = !IfAnyOf<int32_t>::Get(variant, &z_order_);
        break;
      case DisplaySurfaceAttributeEnum::ExcludeFromBlur:
        invalid_value =
            !IfAnyOf<int32_t, int64_t, bool>::Get(variant, &exclude_from_blur_);
        break;
      case DisplaySurfaceAttributeEnum::BlurBehind:
        invalid_value =
            !IfAnyOf<int32_t, int64_t, bool>::Get(variant, &blur_behind_);
        break;
    }

    if (invalid_value) {
      ALOGW(
          "DisplaySurfaceClient::SetAttributes: Failed to set display "
          "surface attribute '%s' because of incompatible type: %d",
          DisplaySurfaceAttributeEnum::ToString(key).c_str(), variant->index());
          "Surface::SetAttributes: Failed to set display surface "
          "attribute %d because of incompatible type: %d",
          key, variant->index());
    }
  }

  return {};
}

std::shared_ptr<ProducerQueue> DisplaySurfaceClient::GetProducerQueue() {
  if (producer_queue_ == nullptr) {
    // Create producer queue through DisplayRPC
    auto status = InvokeRemoteMethod<DisplayRPC::CreateBufferQueue>();
Status<std::unique_ptr<ProducerQueue>> Surface::CreateQueue() {
  ALOGD_IF(TRACE, "Surface::CreateQueue: Creating empty queue.");
  auto status = InvokeRemoteMethod<DisplayProtocol::CreateQueue>(0);
  if (!status) {
      ALOGE(
          "DisplaySurfaceClient::GetProducerQueue: failed to create producer "
          "queue: %s",
    ALOGE("Surface::CreateQueue: Failed to create queue: %s",
          status.GetErrorMessage().c_str());
      return nullptr;
    return status.error_status();
  }

    producer_queue_ = ProducerQueue::Import(status.take());
  auto producer_queue = ProducerQueue::Import(status.take());
  if (!producer_queue) {
    ALOGE("Surface::CreateQueue: Failed to import producer queue!");
    return ErrorStatus(ENOMEM);
  }
  return producer_queue_;

  return {std::move(producer_queue)};
}

volatile DisplaySurfaceMetadata* DisplaySurfaceClient::GetMetadataBufferPtr() {
  if (!mapped_metadata_buffer_) {
    if (auto buffer_producer = GetMetadataBuffer()) {
      void* addr = nullptr;
      const int ret = buffer_producer->GetBlobReadWritePointer(
          sizeof(DisplaySurfaceMetadata), &addr);
Status<std::unique_ptr<ProducerQueue>> Surface::CreateQueue(uint32_t width,
                                                            uint32_t height,
                                                            uint32_t format,
                                                            uint64_t usage,
                                                            size_t capacity) {
  ALOGD_IF(TRACE,
           "Surface::CreateQueue: width=%u height=%u format=%u usage=%" PRIx64
           " capacity=%zu",
           width, height, format, usage, capacity);
  auto status = CreateQueue();
  if (!status)
    return status.error_status();

  auto producer_queue = status.take();

  ALOGD_IF(TRACE, "Surface::CreateQueue: Allocating %zu buffers...", capacity);
  for (size_t i = 0; i < capacity; i++) {
    size_t slot;
    const size_t kSliceCount = 1;
    const int ret = producer_queue->AllocateBuffer(width, height, format, usage,
                                                   kSliceCount, &slot);
    if (ret < 0) {
      ALOGE(
            "DisplaySurfaceClient::GetMetadataBufferPtr: Failed to map surface "
            "metadata: %s",
            strerror(-ret));
        return nullptr;
          "Surface::CreateQueue: Failed to allocate buffer on queue_id=%d: %s",
          producer_queue->id(), strerror(-ret));
      return ErrorStatus(ENOMEM);
    }
      mapped_metadata_buffer_ = static_cast<DisplaySurfaceMetadata*>(addr);
    }
  }

  return mapped_metadata_buffer_;
    ALOGD_IF(
        TRACE,
        "Surface::CreateQueue: Allocated buffer at slot=%zu of capacity=%zu",
        slot, capacity);
  }

LocalChannelHandle DisplaySurfaceClient::CreateVideoMeshSurface() {
  auto status = InvokeRemoteMethod<DisplayRPC::CreateVideoMeshSurface>();
  if (!status) {
    ALOGE(
        "DisplaySurfaceClient::CreateVideoMeshSurface: Failed to create "
        "video mesh surface: %s",
        status.GetErrorMessage().c_str());
  }
  return status.take();
  return {std::move(producer_queue)};
}

DisplayClient::DisplayClient(int* error)
    : BASE(pdx::default_transport::ClientChannelFactory::Create(
               DisplayRPC::kClientPath),
               DisplayProtocol::kClientPath),
           kInfiniteTimeout) {
  if (error)
    *error = Client::error();
}

int DisplayClient::GetDisplayMetrics(SystemDisplayMetrics* metrics) {
  auto status = InvokeRemoteMethod<DisplayRPC::GetMetrics>();
  if (!status) {
    ALOGE("DisplayClient::GetDisplayMetrics: Failed to get metrics: %s",
          status.GetErrorMessage().c_str());
    return -status.error();
  }

  *metrics = status.get();
  return 0;
}

pdx::Status<void> DisplayClient::SetViewerParams(
    const ViewerParams& viewer_params) {
  auto status = InvokeRemoteMethod<DisplayRPC::SetViewerParams>(viewer_params);
  if (!status) {
    ALOGE("DisplayClient::SetViewerParams: Failed to set viewer params: %s",
          status.GetErrorMessage().c_str());
  }
  return status;
}

int DisplayClient::GetLastFrameEdsTransform(LateLatchOutput* ll_out) {
  auto status = InvokeRemoteMethod<DisplayRPC::GetEdsCapture>();
  if (!status) {
    ALOGE(
        "DisplayClient::GetLastFrameLateLatch: Failed to get most recent late"
        " latch: %s",
        status.GetErrorMessage().c_str());
    return -status.error();
  }

  if (status.get().size() != sizeof(LateLatchOutput)) {
    ALOGE(
        "DisplayClient::GetLastFrameLateLatch: Error expected to receive %zu "
        "bytes but received %zu",
        sizeof(LateLatchOutput), status.get().size());
    return -EIO;
  }

  *ll_out = *reinterpret_cast<const LateLatchOutput*>(status.get().data());
  return 0;
Status<Metrics> DisplayClient::GetDisplayMetrics() {
  return InvokeRemoteMethod<DisplayProtocol::GetMetrics>();
}

std::unique_ptr<DisplaySurfaceClient> DisplayClient::CreateDisplaySurface(
    int width, int height, int format, int usage, int flags) {
  return DisplaySurfaceClient::Create(width, height, format, usage, flags);
Status<std::unique_ptr<Surface>> DisplayClient::CreateSurface(
    const SurfaceAttributes& attributes) {
  int error;
  if (auto client = Surface::Create(attributes, &error))
    return {std::move(client)};
  else
    return ErrorStatus(error);
}

std::unique_ptr<IonBuffer> DisplayClient::GetNamedBuffer(
Status<std::unique_ptr<IonBuffer>> DisplayClient::GetNamedBuffer(
    const std::string& name) {
  auto status = InvokeRemoteMethod<DisplayRPC::GetNamedBuffer>(name);
  auto status = InvokeRemoteMethod<DisplayProtocol::GetNamedBuffer>(name);
  if (!status) {
    ALOGE(
        "DisplayClient::GetNamedBuffer: Failed to get pose buffer. name=%s, "
        "DisplayClient::GetNamedBuffer: Failed to get named buffer: name=%s; "
        "error=%s",
        name.c_str(), status.GetErrorMessage().c_str());
    return nullptr;
    return status.error_status();
  }

  auto ion_buffer = std::make_unique<IonBuffer>();
  status.take().Import(ion_buffer.get());
  return ion_buffer;
  auto native_buffer_handle = status.take();
  const int ret = native_buffer_handle.Import(ion_buffer.get());
  if (ret < 0) {
    ALOGE(
        "DisplayClient::GetNamedBuffer: Failed to import named buffer: "
        "name=%s; error=%s",
        name.c_str(), strerror(-ret));
    return ErrorStatus(-ret);
  }

bool DisplayClient::IsVrAppRunning() {
  auto status = InvokeRemoteMethod<DisplayRPC::IsVrAppRunning>();
  if (!status)
    return 0;
  return static_cast<bool>(status.get());
  return {std::move(ion_buffer)};
}

Status<bool> DisplayClient::IsVrAppRunning() {
  return InvokeRemoteMethod<DisplayProtocol::IsVrAppRunning>();
}

}  // namespace display
}  // namespace dvr
}  // namespace android
Loading