1#include "include/dvr/dvr_surface.h"
2
3#include <inttypes.h>
4
5#include <private/dvr/display_client.h>
6
7#include "dvr_internal.h"
8
9using android::dvr::display::DisplayClient;
10using android::dvr::display::Surface;
11using android::dvr::display::SurfaceAttributes;
12using android::dvr::display::SurfaceAttributeValue;
13using android::dvr::CreateDvrReadBufferFromBufferConsumer;
14using android::dvr::CreateDvrWriteBufferQueueFromProducerQueue;
15
16namespace {
17
18bool ConvertSurfaceAttributes(const DvrSurfaceAttribute* attributes,
19                              size_t attribute_count,
20                              SurfaceAttributes* surface_attributes,
21                              size_t* error_index) {
22  for (size_t i = 0; i < attribute_count; i++) {
23    SurfaceAttributeValue value;
24    switch (attributes[i].value.type) {
25      case DVR_SURFACE_ATTRIBUTE_TYPE_INT32:
26        value = attributes[i].value.int32_value;
27        break;
28      case DVR_SURFACE_ATTRIBUTE_TYPE_INT64:
29        value = attributes[i].value.int64_value;
30        break;
31      case DVR_SURFACE_ATTRIBUTE_TYPE_BOOL:
32        value = attributes[i].value.bool_value;
33        break;
34      case DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT:
35        value = attributes[i].value.float_value;
36        break;
37      case DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT2:
38        value = attributes[i].value.float2_value;
39        break;
40      case DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT3:
41        value = attributes[i].value.float3_value;
42        break;
43      case DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT4:
44        value = attributes[i].value.float4_value;
45        break;
46      case DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT8:
47        value = attributes[i].value.float8_value;
48        break;
49      case DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT16:
50        value = attributes[i].value.float16_value;
51        break;
52      default:
53        *error_index = i;
54        return false;
55    }
56
57    surface_attributes->emplace(attributes[i].key, value);
58  }
59
60  return true;
61}
62
63}  // anonymous namespace
64
65extern "C" {
66
67struct DvrSurface {
68  std::unique_ptr<Surface> surface;
69};
70
71int dvrSurfaceCreate(const DvrSurfaceAttribute* attributes,
72                     size_t attribute_count, DvrSurface** out_surface) {
73  if (out_surface == nullptr) {
74    ALOGE("dvrSurfaceCreate: Invalid inputs: out_surface=%p.", out_surface);
75    return -EINVAL;
76  }
77
78  size_t error_index;
79  SurfaceAttributes surface_attributes;
80  if (!ConvertSurfaceAttributes(attributes, attribute_count,
81                                &surface_attributes, &error_index)) {
82    ALOGE("dvrSurfaceCreate: Invalid surface attribute type: %" PRIu64,
83          attributes[error_index].value.type);
84    return -EINVAL;
85  }
86
87  auto status = Surface::CreateSurface(surface_attributes);
88  if (!status) {
89    ALOGE("dvrSurfaceCreate:: Failed to create display surface: %s",
90          status.GetErrorMessage().c_str());
91    return -status.error();
92  }
93
94  *out_surface = new DvrSurface{status.take()};
95  return 0;
96}
97
98void dvrSurfaceDestroy(DvrSurface* surface) { delete surface; }
99
100int dvrSurfaceGetId(DvrSurface* surface) {
101  return surface->surface->surface_id();
102}
103
104int dvrSurfaceSetAttributes(DvrSurface* surface,
105                            const DvrSurfaceAttribute* attributes,
106                            size_t attribute_count) {
107  if (surface == nullptr || attributes == nullptr) {
108    ALOGE(
109        "dvrSurfaceSetAttributes: Invalid inputs: surface=%p attributes=%p "
110        "attribute_count=%zu",
111        surface, attributes, attribute_count);
112    return -EINVAL;
113  }
114
115  size_t error_index;
116  SurfaceAttributes surface_attributes;
117  if (!ConvertSurfaceAttributes(attributes, attribute_count,
118                                &surface_attributes, &error_index)) {
119    ALOGE("dvrSurfaceSetAttributes: Invalid surface attribute type: %" PRIu64,
120          attributes[error_index].value.type);
121    return -EINVAL;
122  }
123
124  auto status = surface->surface->SetAttributes(surface_attributes);
125  if (!status) {
126    ALOGE("dvrSurfaceSetAttributes: Failed to set attributes: %s",
127          status.GetErrorMessage().c_str());
128    return -status.error();
129  }
130
131  return 0;
132}
133
134int dvrSurfaceCreateWriteBufferQueue(DvrSurface* surface, uint32_t width,
135                                     uint32_t height, uint32_t format,
136                                     uint32_t layer_count, uint64_t usage,
137                                     size_t capacity,
138                                     DvrWriteBufferQueue** out_writer) {
139  if (surface == nullptr || out_writer == nullptr) {
140    ALOGE(
141        "dvrSurfaceCreateWriteBufferQueue: Invalid inputs: surface=%p, "
142        "out_writer=%p.",
143        surface, out_writer);
144    return -EINVAL;
145  }
146
147  auto status = surface->surface->CreateQueue(width, height, layer_count,
148                                              format, usage, capacity);
149  if (!status) {
150    ALOGE("dvrSurfaceCreateWriteBufferQueue: Failed to create queue: %s",
151          status.GetErrorMessage().c_str());
152    return -status.error();
153  }
154
155  *out_writer = CreateDvrWriteBufferQueueFromProducerQueue(status.take());
156  return 0;
157}
158
159int dvrGetNamedBuffer(const char* name, DvrBuffer** out_buffer) {
160  auto client = DisplayClient::Create();
161  if (!client) {
162    ALOGE("dvrGetNamedBuffer: Failed to create display client!");
163    return -ECOMM;
164  }
165
166  if (out_buffer == nullptr || name == nullptr) {
167    ALOGE("dvrGetNamedBuffer: Invalid inputs: name=%p, out_buffer=%p.", name,
168          out_buffer);
169    return -EINVAL;
170  }
171
172  auto status = client->GetNamedBuffer(name);
173  if (!status) {
174    ALOGE("dvrGetNamedBuffer: Failed to find named buffer name=%s: %s", name,
175          status.GetErrorMessage().c_str());
176    return -status.error();
177  }
178  *out_buffer = CreateDvrBufferFromIonBuffer(status.take());
179  return 0;
180}
181
182}  // extern "C"
183