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