blob: 63c81ed46572c202404d003652b64aaec1181c7d [file] [log] [blame]
Alex Vakulenkoe4eec202017-01-27 14:41:04 -08001#include <EGL/egl.h>
2
3#include <android/native_window.h>
4#include <base/logging.h>
5#include <cutils/native_handle.h>
6#include <errno.h>
7#include <pthread.h>
8#include <semaphore.h>
9#include <stdarg.h>
10#include <string.h>
11#include <sys/timerfd.h>
12#include <system/window.h>
13#include <time.h>
14#include <ui/ANativeObjectBase.h>
15#include <utils/Errors.h>
16
17#define ATRACE_TAG ATRACE_TAG_GRAPHICS
18#include <utils/Trace.h>
19
20#include <cutils/log.h>
21
22#include <memory>
23#include <mutex>
24
25#include <dvr/graphics.h>
26#include <private/dvr/clock_ns.h>
27#include <private/dvr/display_client.h>
28#include <private/dvr/native_buffer.h>
29#include <private/dvr/native_buffer_queue.h>
30
31namespace {
32
33constexpr int kDefaultDisplaySurfaceUsage =
34 GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE;
35constexpr int kDefaultDisplaySurfaceFormat = HAL_PIXEL_FORMAT_RGBA_8888;
36constexpr int kWarpedDisplaySurfaceFlags = 0;
37constexpr int kUnwarpedDisplaySurfaceFlags =
38 DVR_DISPLAY_SURFACE_FLAGS_DISABLE_SYSTEM_EDS |
39 DVR_DISPLAY_SURFACE_FLAGS_DISABLE_SYSTEM_DISTORTION |
40 DVR_DISPLAY_SURFACE_FLAGS_DISABLE_SYSTEM_CAC;
41constexpr int kDefaultBufferCount = 4;
42
43} // anonymous namespace
44
45namespace android {
46namespace dvr {
47
48// NativeWindow is an implementation of ANativeWindow. This class interacts with
49// displayd through the DisplaySurfaceClient and NativeBufferQueue.
50class NativeWindow : public ANativeObjectBase<ANativeWindow, NativeWindow,
51 LightRefBase<NativeWindow> > {
52 public:
53 explicit NativeWindow(const std::shared_ptr<DisplaySurfaceClient>& surface);
54
55 void SetVisible(bool visible);
56 void SetZOrder(int z_order);
57 void PostEarly();
58
59 private:
60 friend class LightRefBase<NativeWindow>;
61
62 void Post(sp<NativeBufferProducer> buffer, int fence_fd);
63
64 static int SetSwapInterval(ANativeWindow* window, int interval);
65 static int DequeueBuffer(ANativeWindow* window, ANativeWindowBuffer** buffer,
66 int* fence_fd);
67 static int QueueBuffer(ANativeWindow* window, ANativeWindowBuffer* buffer,
68 int fence_fd);
69 static int CancelBuffer(ANativeWindow* window, ANativeWindowBuffer* buffer,
70 int fence_fd);
71 static int Query(const ANativeWindow* window, int what, int* value);
72 static int Perform(ANativeWindow* window, int operation, ...);
73
74 static int DequeueBuffer_DEPRECATED(ANativeWindow* window,
75 ANativeWindowBuffer** buffer);
76 static int CancelBuffer_DEPRECATED(ANativeWindow* window,
77 ANativeWindowBuffer* buffer);
78 static int QueueBuffer_DEPRECATED(ANativeWindow* window,
79 ANativeWindowBuffer* buffer);
80 static int LockBuffer_DEPRECATED(ANativeWindow* window,
81 ANativeWindowBuffer* buffer);
82
83 std::shared_ptr<DisplaySurfaceClient> surface_;
84
85 std::mutex lock_;
86 NativeBufferQueue buffer_queue_;
87 sp<NativeBufferProducer> next_post_buffer_;
88 bool next_buffer_already_posted_;
89
90 NativeWindow(const NativeWindow&) = delete;
91 void operator=(NativeWindow&) = delete;
92};
93
94NativeWindow::NativeWindow(const std::shared_ptr<DisplaySurfaceClient>& surface)
95 : surface_(surface),
96 buffer_queue_(surface, kDefaultBufferCount),
97 next_post_buffer_(nullptr),
98 next_buffer_already_posted_(false) {
99 ANativeWindow::setSwapInterval = SetSwapInterval;
100 ANativeWindow::dequeueBuffer = DequeueBuffer;
101 ANativeWindow::cancelBuffer = CancelBuffer;
102 ANativeWindow::queueBuffer = QueueBuffer;
103 ANativeWindow::query = Query;
104 ANativeWindow::perform = Perform;
105
106 ANativeWindow::dequeueBuffer_DEPRECATED = DequeueBuffer_DEPRECATED;
107 ANativeWindow::cancelBuffer_DEPRECATED = CancelBuffer_DEPRECATED;
108 ANativeWindow::lockBuffer_DEPRECATED = LockBuffer_DEPRECATED;
109 ANativeWindow::queueBuffer_DEPRECATED = QueueBuffer_DEPRECATED;
110}
111
112void NativeWindow::SetVisible(bool visible) { surface_->SetVisible(visible); }
113
114void NativeWindow::SetZOrder(int z_order) { surface_->SetZOrder(z_order); }
115
116void NativeWindow::PostEarly() {
117 ATRACE_NAME("NativeWindow::PostEarly");
118 ALOGI_IF(TRACE, "NativeWindow::PostEarly");
119
120 std::lock_guard<std::mutex> autolock(lock_);
121
122 if (!next_buffer_already_posted_) {
123 next_buffer_already_posted_ = true;
124
125 if (!next_post_buffer_.get()) {
126 next_post_buffer_ = buffer_queue_.Dequeue();
127 }
128 ATRACE_ASYNC_BEGIN("BufferPost", next_post_buffer_->buffer()->id());
129 Post(next_post_buffer_, -1);
130 }
131}
132
133void NativeWindow::Post(sp<NativeBufferProducer> buffer, int fence_fd) {
134 ATRACE_NAME(__PRETTY_FUNCTION__);
135 ALOGI_IF(TRACE, "NativeWindow::Post: buffer_id=%d, fence_fd=%d",
136 buffer->buffer()->id(), fence_fd);
137 ALOGW_IF(!surface_->visible(),
138 "NativeWindow::Post: Posting buffer on invisible surface!!!");
139 buffer->Post(fence_fd, 0);
140}
141
142int NativeWindow::SetSwapInterval(ANativeWindow* window, int interval) {
143 ALOGI_IF(TRACE, "SetSwapInterval: window=%p interval=%d", window, interval);
144 return 0;
145}
146
147int NativeWindow::DequeueBuffer(ANativeWindow* window,
148 ANativeWindowBuffer** buffer, int* fence_fd) {
149 ATRACE_NAME(__PRETTY_FUNCTION__);
150
151 NativeWindow* self = getSelf(window);
152 std::lock_guard<std::mutex> autolock(self->lock_);
153
154 if (!self->next_post_buffer_.get()) {
155 self->next_post_buffer_ = self->buffer_queue_.Dequeue();
156 }
157 ATRACE_ASYNC_BEGIN("BufferDraw", self->next_post_buffer_->buffer()->id());
158 *fence_fd = self->next_post_buffer_->ClaimReleaseFence().Release();
159 *buffer = self->next_post_buffer_.get();
160
161 ALOGI_IF(TRACE, "NativeWindow::DequeueBuffer: fence_fd=%d", *fence_fd);
162 return 0;
163}
164
165int NativeWindow::QueueBuffer(ANativeWindow* window,
166 ANativeWindowBuffer* buffer, int fence_fd) {
167 ATRACE_NAME("NativeWindow::QueueBuffer");
168 ALOGI_IF(TRACE, "NativeWindow::QueueBuffer: fence_fd=%d", fence_fd);
169
170 NativeWindow* self = getSelf(window);
171 std::lock_guard<std::mutex> autolock(self->lock_);
172
173 NativeBufferProducer* native_buffer =
174 static_cast<NativeBufferProducer*>(buffer);
175 ATRACE_ASYNC_END("BufferDraw", native_buffer->buffer()->id());
176 bool do_post = true;
177 if (self->next_buffer_already_posted_) {
178 // Check that the buffer is the one we expect, but handle it if this happens
179 // in production by allowing this buffer to post on top of the previous one.
180 DCHECK(native_buffer == self->next_post_buffer_.get());
181 if (native_buffer == self->next_post_buffer_.get()) {
182 do_post = false;
183 if (fence_fd >= 0)
184 close(fence_fd);
185 }
186 }
187 if (do_post) {
188 ATRACE_ASYNC_BEGIN("BufferPost", native_buffer->buffer()->id());
189 self->Post(native_buffer, fence_fd);
190 }
191 self->next_buffer_already_posted_ = false;
192 self->next_post_buffer_ = nullptr;
193
194 return NO_ERROR;
195}
196
197int NativeWindow::CancelBuffer(ANativeWindow* window,
198 ANativeWindowBuffer* buffer, int fence_fd) {
199 ATRACE_NAME("NativeWindow::CancelBuffer");
200 ALOGI_IF(TRACE, "NativeWindow::CancelBuffer: fence_fd: %d", fence_fd);
201
202 NativeWindow* self = getSelf(window);
203 std::lock_guard<std::mutex> autolock(self->lock_);
204
205 NativeBufferProducer* native_buffer =
206 static_cast<NativeBufferProducer*>(buffer);
207 ATRACE_ASYNC_END("BufferDraw", native_buffer->buffer()->id());
208 ATRACE_INT("CancelBuffer", native_buffer->buffer()->id());
209 bool do_enqueue = true;
210 if (self->next_buffer_already_posted_) {
211 // Check that the buffer is the one we expect, but handle it if this happens
212 // in production by returning this buffer to the buffer queue.
213 DCHECK(native_buffer == self->next_post_buffer_.get());
214 if (native_buffer == self->next_post_buffer_.get()) {
215 do_enqueue = false;
216 }
217 }
218 if (do_enqueue) {
219 self->buffer_queue_.Enqueue(native_buffer);
220 }
221 if (fence_fd >= 0)
222 close(fence_fd);
223 self->next_buffer_already_posted_ = false;
224 self->next_post_buffer_ = nullptr;
225
226 return NO_ERROR;
227}
228
229int NativeWindow::Query(const ANativeWindow* window, int what, int* value) {
230 NativeWindow* self = getSelf(const_cast<ANativeWindow*>(window));
231 std::lock_guard<std::mutex> autolock(self->lock_);
232
233 switch (what) {
234 case NATIVE_WINDOW_WIDTH:
235 *value = self->surface_->width();
236 return NO_ERROR;
237 case NATIVE_WINDOW_HEIGHT:
238 *value = self->surface_->height();
239 return NO_ERROR;
240 case NATIVE_WINDOW_FORMAT:
241 *value = self->surface_->format();
242 return NO_ERROR;
243 case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS:
244 *value = 1;
245 return NO_ERROR;
246 case NATIVE_WINDOW_CONCRETE_TYPE:
247 *value = NATIVE_WINDOW_SURFACE;
248 return NO_ERROR;
249 case NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER:
250 *value = 1;
251 return NO_ERROR;
252 case NATIVE_WINDOW_DEFAULT_WIDTH:
253 *value = self->surface_->width();
254 return NO_ERROR;
255 case NATIVE_WINDOW_DEFAULT_HEIGHT:
256 *value = self->surface_->height();
257 return NO_ERROR;
258 case NATIVE_WINDOW_TRANSFORM_HINT:
259 *value = 0;
260 return NO_ERROR;
261 }
262
263 *value = 0;
264 return BAD_VALUE;
265}
266
267int NativeWindow::Perform(ANativeWindow* window, int operation, ...) {
268 NativeWindow* self = getSelf(window);
269 std::lock_guard<std::mutex> autolock(self->lock_);
270
271 va_list args;
272 va_start(args, operation);
273
274 // TODO(eieio): The following operations are not used at this time. They are
275 // included here to help document which operations may be useful and what
276 // parameters they take.
277 switch (operation) {
278 case NATIVE_WINDOW_SET_BUFFERS_DIMENSIONS: {
279 int w = va_arg(args, int);
280 int h = va_arg(args, int);
281 ALOGD_IF(TRACE, "NATIVE_WINDOW_SET_BUFFERS_DIMENSIONS: w=%d h=%d", w, h);
282 return NO_ERROR;
283 }
284
285 case NATIVE_WINDOW_SET_BUFFERS_FORMAT: {
286 int format = va_arg(args, int);
287 ALOGD_IF(TRACE, "NATIVE_WINDOW_SET_BUFFERS_FORMAT: format=%d", format);
288 return NO_ERROR;
289 }
290
291 case NATIVE_WINDOW_SET_BUFFERS_TRANSFORM: {
292 int transform = va_arg(args, int);
293 ALOGD_IF(TRACE, "NATIVE_WINDOW_SET_BUFFERS_TRANSFORM: transform=%d",
294 transform);
295 return NO_ERROR;
296 }
297
298 case NATIVE_WINDOW_SET_USAGE: {
299 int usage = va_arg(args, int);
300 ALOGD_IF(TRACE, "NATIVE_WINDOW_SET_USAGE: usage=%d", usage);
301 return NO_ERROR;
302 }
303
304 case NATIVE_WINDOW_CONNECT:
305 case NATIVE_WINDOW_DISCONNECT:
306 case NATIVE_WINDOW_SET_BUFFERS_GEOMETRY:
307 case NATIVE_WINDOW_API_CONNECT:
308 case NATIVE_WINDOW_API_DISCONNECT:
309 // TODO(eieio): we should implement these
310 return NO_ERROR;
311
312 case NATIVE_WINDOW_SET_BUFFER_COUNT: {
313 int buffer_count = va_arg(args, int);
314 ALOGD_IF(TRACE, "NATIVE_WINDOW_SET_BUFFER_COUNT: bufferCount=%d",
315 buffer_count);
316 return NO_ERROR;
317 }
318 case NATIVE_WINDOW_SET_BUFFERS_DATASPACE: {
319 android_dataspace_t data_space =
320 static_cast<android_dataspace_t>(va_arg(args, int));
321 ALOGD_IF(TRACE, "NATIVE_WINDOW_SET_BUFFERS_DATASPACE: dataSpace=%d",
322 data_space);
323 return NO_ERROR;
324 }
325 case NATIVE_WINDOW_SET_SCALING_MODE: {
326 int mode = va_arg(args, int);
327 ALOGD_IF(TRACE, "NATIVE_WINDOW_SET_SCALING_MODE: mode=%d", mode);
328 return NO_ERROR;
329 }
330
331 case NATIVE_WINDOW_LOCK:
332 case NATIVE_WINDOW_UNLOCK_AND_POST:
333 case NATIVE_WINDOW_SET_CROP:
334 case NATIVE_WINDOW_SET_BUFFERS_TIMESTAMP:
335 return INVALID_OPERATION;
336 }
337
338 return NAME_NOT_FOUND;
339}
340
341int NativeWindow::DequeueBuffer_DEPRECATED(ANativeWindow* window,
342 ANativeWindowBuffer** buffer) {
343 int fence_fd = -1;
344 int ret = DequeueBuffer(window, buffer, &fence_fd);
345
346 // wait for fence
347 if (ret == NO_ERROR && fence_fd != -1)
348 close(fence_fd);
349
350 return ret;
351}
352
353int NativeWindow::CancelBuffer_DEPRECATED(ANativeWindow* window,
354 ANativeWindowBuffer* buffer) {
355 return CancelBuffer(window, buffer, -1);
356}
357
358int NativeWindow::QueueBuffer_DEPRECATED(ANativeWindow* window,
359 ANativeWindowBuffer* buffer) {
360 return QueueBuffer(window, buffer, -1);
361}
362
363int NativeWindow::LockBuffer_DEPRECATED(ANativeWindow* /*window*/,
364 ANativeWindowBuffer* /*buffer*/) {
365 return NO_ERROR;
366}
367
368} // namespace dvr
369} // namespace android
370
371static EGLNativeWindowType CreateDisplaySurface(int* display_width,
372 int* display_height, int format,
373 int usage, int flags) {
374 auto client = android::dvr::DisplayClient::Create();
375 if (!client) {
376 ALOGE("Failed to create display client!");
377 return nullptr;
378 }
379
380 // TODO(eieio,jbates): Consider passing flags and other parameters to get
381 // metrics based on specific surface requirements.
382 android::dvr::SystemDisplayMetrics metrics;
383 const int ret = client->GetDisplayMetrics(&metrics);
384 if (ret < 0) {
385 ALOGE("Failed to get display metrics: %s", strerror(-ret));
386 return nullptr;
387 }
388
389 int width, height;
390
391 if (flags & DVR_DISPLAY_SURFACE_FLAGS_DISABLE_SYSTEM_DISTORTION) {
392 width = metrics.display_native_width;
393 height = metrics.display_native_height;
394 } else {
395 width = metrics.distorted_width;
396 height = metrics.distorted_height;
397 }
398
399 std::shared_ptr<android::dvr::DisplaySurfaceClient> surface =
400 client->CreateDisplaySurface(width, height, format, usage, flags);
401
402 if (display_width)
403 *display_width = metrics.display_native_width;
404 if (display_height)
405 *display_height = metrics.display_native_height;
406
407 // Set the surface visible by default.
408 // TODO(eieio,jbates): Remove this from here and set visible somewhere closer
409 // to the application to account for situations where the application wants to
410 // create surfaces that will be used later or shouldn't be visible yet.
411 surface->SetVisible(true);
412
413 return new android::dvr::NativeWindow(surface);
414}
415
416std::shared_ptr<android::dvr::DisplaySurfaceClient> CreateDisplaySurfaceClient(
417 struct DvrSurfaceParameter* parameters,
418 /*out*/ android::dvr::SystemDisplayMetrics* metrics);
419
420extern "C" EGLNativeWindowType dvrCreateDisplaySurfaceExtended(
421 struct DvrSurfaceParameter* parameters) {
422 android::dvr::SystemDisplayMetrics metrics;
423 auto surface = CreateDisplaySurfaceClient(parameters, &metrics);
424 if (!surface) {
425 ALOGE("Failed to create display surface client");
426 return nullptr;
427 }
428 return new android::dvr::NativeWindow(surface);
429}
430
431extern "C" EGLNativeWindowType dvrCreateDisplaySurface() {
432 return CreateDisplaySurface(NULL, NULL, kDefaultDisplaySurfaceFormat,
433 kDefaultDisplaySurfaceUsage,
434 kUnwarpedDisplaySurfaceFlags);
435}
436
437extern "C" EGLNativeWindowType dvrCreateWarpedDisplaySurface(
438 int* display_width, int* display_height) {
439 return CreateDisplaySurface(
440 display_width, display_height, kDefaultDisplaySurfaceFormat,
441 kDefaultDisplaySurfaceUsage, kWarpedDisplaySurfaceFlags);
442}
443
444extern "C" void dvrDisplaySurfaceSetVisible(EGLNativeWindowType window,
445 int visible) {
446 auto native_window = reinterpret_cast<android::dvr::NativeWindow*>(window);
447 native_window->SetVisible(visible);
448}
449
450extern "C" void dvrDisplaySurfaceSetZOrder(EGLNativeWindowType window,
451 int z_order) {
452 auto native_window = reinterpret_cast<android::dvr::NativeWindow*>(window);
453 native_window->SetZOrder(z_order);
454}
455
456extern "C" void dvrDisplayPostEarly(EGLNativeWindowType window) {
457 auto native_window = reinterpret_cast<android::dvr::NativeWindow*>(window);
458 native_window->PostEarly();
459}