Commit | Line | Data |
---|---|---|
d42e7319 JB |
1 | /* |
2 | * Copyright (C) 2013 libhybris | |
3 | * | |
4 | * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | * you may not use this file except in compliance with the License. | |
6 | * You may obtain a copy of the License at | |
7 | * | |
8 | * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | * | |
10 | * Unless required by applicable law or agreed to in writing, software | |
11 | * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | * See the License for the specific language governing permissions and | |
14 | * limitations under the License. | |
15 | */ | |
16 | ||
17 | #include "hwcomposer_window.h" | |
18 | #include "logging.h" | |
19 | ||
20 | #include <errno.h> | |
21 | #include <assert.h> | |
22 | #include <pthread.h> | |
23 | #include <stdio.h> | |
24 | #include <unistd.h> | |
25 | ||
26 | #include <android/android-version.h> | |
27 | ||
28 | extern "C" { | |
29 | #include <android/sync/sync.h> | |
30 | }; | |
31 | ||
32 | static pthread_cond_t _cond = PTHREAD_COND_INITIALIZER; | |
33 | static pthread_mutex_t _mutex = PTHREAD_MUTEX_INITIALIZER; | |
34 | ||
35 | ||
36 | HWComposerNativeWindowBuffer::HWComposerNativeWindowBuffer(alloc_device_t* alloc_device, | |
37 | unsigned int width, | |
38 | unsigned int height, | |
39 | unsigned int format, | |
40 | unsigned int usage) | |
41 | { | |
42 | ANativeWindowBuffer::width = width; | |
43 | ANativeWindowBuffer::height = height; | |
44 | ANativeWindowBuffer::format = format; | |
45 | ANativeWindowBuffer::usage = usage; | |
46 | fenceFd = -1; | |
47 | busy = 0; | |
48 | status = 0; | |
49 | m_alloc = alloc_device; | |
50 | ||
51 | if (m_alloc) { | |
52 | status = m_alloc->alloc(m_alloc, | |
53 | width, height, format, usage, | |
54 | &handle, &stride); | |
55 | } | |
56 | ||
57 | TRACE("width=%d height=%d stride=%d format=x%x usage=x%x status=%s this=%p", | |
58 | width, height, stride, format, usage, strerror(-status), this); | |
59 | } | |
60 | ||
61 | ||
62 | ||
63 | HWComposerNativeWindowBuffer::~HWComposerNativeWindowBuffer() | |
64 | { | |
65 | TRACE("%p", this); | |
66 | if (m_alloc && handle) | |
67 | m_alloc->free(m_alloc, handle); | |
68 | ||
69 | } | |
70 | ||
71 | ||
72 | //////////////////////////////////////////////////////////////////////////////// | |
73 | HWComposerNativeWindow::HWComposerNativeWindow(unsigned int width, unsigned int height, unsigned int format) | |
74 | { | |
75 | m_alloc = NULL; | |
76 | m_width = width; | |
77 | m_height = height; | |
78 | m_bufFormat = format; | |
79 | m_usage = GRALLOC_USAGE_HW_COMPOSER; | |
80 | m_frontBuf = NULL; | |
81 | } | |
82 | ||
83 | void HWComposerNativeWindow::setup(gralloc_module_t* gralloc, alloc_device_t* alloc) | |
84 | { | |
85 | m_alloc = alloc; | |
86 | setBufferCount(2); | |
87 | } | |
88 | ||
89 | HWComposerNativeWindow::~HWComposerNativeWindow() | |
90 | { | |
91 | destroyBuffers(); | |
92 | } | |
93 | ||
94 | ||
95 | ||
96 | void HWComposerNativeWindow::destroyBuffers() | |
97 | { | |
98 | TRACE(""); | |
99 | ||
100 | std::list<HWComposerNativeWindowBuffer*>::iterator it = m_bufList.begin(); | |
101 | for (; it!=m_bufList.end(); ++it) | |
102 | { | |
103 | HWComposerNativeWindowBuffer* fbnb = *it; | |
104 | fbnb->common.decRef(&fbnb->common); | |
105 | } | |
106 | m_bufList.clear(); | |
107 | m_freeBufs = 0; | |
108 | m_frontBuf = NULL; | |
109 | } | |
110 | ||
111 | ||
112 | ||
113 | ||
114 | /* | |
115 | * Set the swap interval for this surface. | |
116 | * | |
117 | * Returns 0 on success or -errno on error. | |
118 | */ | |
119 | int HWComposerNativeWindow::setSwapInterval(int interval) | |
120 | { | |
121 | TRACE("interval=%i WARN STUB", interval); | |
122 | return 0; | |
123 | } | |
124 | ||
125 | ||
126 | /* | |
127 | * Hook called by EGL to acquire a buffer. This call may block if no | |
128 | * buffers are available. | |
129 | * | |
130 | * The window holds a reference to the buffer between dequeueBuffer and | |
131 | * either queueBuffer or cancelBuffer, so clients only need their own | |
132 | * reference if they might use the buffer after queueing or canceling it. | |
133 | * Holding a reference to a buffer after queueing or canceling it is only | |
134 | * allowed if a specific buffer count has been set. | |
135 | * | |
136 | * The libsync fence file descriptor returned in the int pointed to by the | |
137 | * fenceFd argument will refer to the fence that must signal before the | |
138 | * dequeued buffer may be written to. A value of -1 indicates that the | |
139 | * caller may access the buffer immediately without waiting on a fence. If | |
140 | * a valid file descriptor is returned (i.e. any value except -1) then the | |
141 | * caller is responsible for closing the file descriptor. | |
142 | * | |
143 | * Returns 0 on success or -errno on error. | |
144 | */ | |
145 | int HWComposerNativeWindow::dequeueBuffer(BaseNativeWindowBuffer** buffer, int *fenceFd) | |
146 | { | |
147 | HYBRIS_TRACE_BEGIN("hwcomposer-platform", "dequeueBuffer", ""); | |
148 | ||
149 | HWComposerNativeWindowBuffer* fbnb=NULL; | |
150 | ||
151 | pthread_mutex_lock(&_mutex); | |
152 | ||
153 | HYBRIS_TRACE_BEGIN("hwcomposer-platform", "dequeueBuffer-wait", ""); | |
154 | #if defined(DEBUG) | |
155 | ||
156 | if (m_frontBuf) | |
157 | TRACE("Status: Has front buf %p", m_frontBuf); | |
158 | ||
159 | std::list<HWComposerNativeWindowBuffer*>::iterator cit = m_bufList.begin(); | |
160 | for (; cit != m_bufList.end(); ++cit) | |
161 | { | |
162 | TRACE("Status: Buffer %p with busy %i\n", (*cit), (*cit)->busy); | |
163 | } | |
164 | #endif | |
165 | ||
166 | ||
167 | while (m_freeBufs==0) | |
168 | { | |
169 | pthread_cond_wait(&_cond, &_mutex); | |
170 | } | |
171 | ||
172 | while (1) | |
173 | { | |
174 | std::list<HWComposerNativeWindowBuffer*>::iterator it = m_bufList.begin(); | |
175 | for (; it != m_bufList.end(); ++it) | |
176 | { | |
177 | if (*it==m_frontBuf) | |
178 | continue; | |
179 | if ((*it)->busy==0) | |
180 | { | |
181 | TRACE("Found a free non-front buffer"); | |
182 | break; | |
183 | } | |
184 | } | |
185 | if (it == m_bufList.end()) | |
186 | { | |
187 | // have to wait once again | |
188 | pthread_cond_wait(&_cond, &_mutex); | |
189 | continue; | |
190 | } | |
191 | ||
192 | fbnb = *it; | |
193 | break; | |
194 | } | |
195 | HYBRIS_TRACE_END("hwcomposer-platform", "dequeueBuffer-wait", ""); | |
196 | ||
197 | assert(fbnb!=NULL); | |
198 | fbnb->busy = 1; | |
199 | m_freeBufs--; | |
200 | ||
201 | *buffer = fbnb; | |
202 | *fenceFd = -1; | |
203 | ||
204 | TRACE("%lu DONE --> %p", pthread_self(), fbnb); | |
205 | pthread_mutex_unlock(&_mutex); | |
206 | HYBRIS_TRACE_END("hwcomposer-platform", "dequeueBuffer", ""); | |
207 | ||
208 | return 0; | |
209 | } | |
210 | ||
211 | /* | |
212 | * Hook called by EGL when modifications to the render buffer are done. | |
213 | * This unlocks and post the buffer. | |
214 | * | |
215 | * The window holds a reference to the buffer between dequeueBuffer and | |
216 | * either queueBuffer or cancelBuffer, so clients only need their own | |
217 | * reference if they might use the buffer after queueing or canceling it. | |
218 | * Holding a reference to a buffer after queueing or canceling it is only | |
219 | * allowed if a specific buffer count has been set. | |
220 | * | |
221 | * The fenceFd argument specifies a libsync fence file descriptor for a | |
222 | * fence that must signal before the buffer can be accessed. If the buffer | |
223 | * can be accessed immediately then a value of -1 should be used. The | |
224 | * caller must not use the file descriptor after it is passed to | |
225 | * queueBuffer, and the ANativeWindow implementation is responsible for | |
226 | * closing it. | |
227 | * | |
228 | * Returns 0 on success or -errno on error. | |
229 | */ | |
230 | int HWComposerNativeWindow::queueBuffer(BaseNativeWindowBuffer* buffer, int fenceFd) | |
231 | { | |
232 | TRACE("%lu %d", pthread_self(), fenceFd); | |
233 | HWComposerNativeWindowBuffer* fbnb = (HWComposerNativeWindowBuffer*) buffer; | |
234 | ||
235 | HYBRIS_TRACE_BEGIN("hwcomposer-platform", "queueBuffer", "-%p", fbnb); | |
236 | fbnb->fenceFd = fenceFd; | |
237 | ||
238 | pthread_mutex_lock(&_mutex); | |
239 | ||
240 | /* Front buffer hasn't yet been picked up for posting */ | |
241 | while (m_frontBuf && m_frontBuf->busy >= 2) | |
242 | { | |
243 | pthread_cond_wait(&_cond, &_mutex); | |
244 | } | |
245 | ||
246 | assert(fbnb->busy==1); | |
247 | fbnb->busy = 2; | |
248 | m_frontBuf = fbnb; | |
249 | m_freeBufs++; | |
250 | ||
251 | sync_wait(fenceFd, -1); | |
252 | ::close(fenceFd); | |
253 | ||
254 | pthread_cond_signal(&_cond); | |
255 | ||
256 | TRACE("%lu %p %p",pthread_self(), m_frontBuf, fbnb); | |
257 | pthread_mutex_unlock(&_mutex); | |
258 | HYBRIS_TRACE_END("hwcomposer-platform", "queueBuffer", "-%p", fbnb); | |
259 | ||
260 | return 0; | |
261 | } | |
262 | ||
263 | void HWComposerNativeWindow::lockFrontBuffer(HWComposerNativeWindowBuffer **buffer) | |
264 | { | |
265 | TRACE(""); | |
266 | HWComposerNativeWindowBuffer *buf; | |
267 | pthread_mutex_lock(&_mutex); | |
268 | ||
269 | while (!m_frontBuf) | |
270 | { | |
271 | pthread_cond_wait(&_cond, &_mutex); | |
272 | } | |
273 | ||
274 | assert(m_frontBuf->busy == 2); | |
275 | ||
276 | m_frontBuf->busy = 3; | |
277 | buf = m_frontBuf; | |
278 | pthread_mutex_unlock(&_mutex); | |
279 | ||
280 | *buffer = buf; | |
281 | return; | |
282 | ||
283 | } | |
284 | ||
285 | void HWComposerNativeWindow::unlockFrontBuffer(HWComposerNativeWindowBuffer *buffer) | |
286 | { | |
287 | TRACE(""); | |
288 | pthread_mutex_lock(&_mutex); | |
289 | ||
290 | assert(buffer == m_frontBuf); | |
291 | m_frontBuf->busy = 0; | |
292 | ||
293 | pthread_cond_signal(&_cond); | |
294 | pthread_mutex_unlock(&_mutex); | |
295 | ||
296 | return; | |
297 | } | |
298 | ||
299 | /* | |
300 | * Hook used to cancel a buffer that has been dequeued. | |
301 | * No synchronization is performed between dequeue() and cancel(), so | |
302 | * either external synchronization is needed, or these functions must be | |
303 | * called from the same thread. | |
304 | * | |
305 | * The window holds a reference to the buffer between dequeueBuffer and | |
306 | * either queueBuffer or cancelBuffer, so clients only need their own | |
307 | * reference if they might use the buffer after queueing or canceling it. | |
308 | * Holding a reference to a buffer after queueing or canceling it is only | |
309 | * allowed if a specific buffer count has been set. | |
310 | * | |
311 | * The fenceFd argument specifies a libsync fence file decsriptor for a | |
312 | * fence that must signal before the buffer can be accessed. If the buffer | |
313 | * can be accessed immediately then a value of -1 should be used. | |
314 | * | |
315 | * Note that if the client has not waited on the fence that was returned | |
316 | * from dequeueBuffer, that same fence should be passed to cancelBuffer to | |
317 | * ensure that future uses of the buffer are preceded by a wait on that | |
318 | * fence. The caller must not use the file descriptor after it is passed | |
319 | * to cancelBuffer, and the ANativeWindow implementation is responsible for | |
320 | * closing it. | |
321 | * | |
322 | * Returns 0 on success or -errno on error. | |
323 | */ | |
324 | int HWComposerNativeWindow::cancelBuffer(BaseNativeWindowBuffer* buffer, int fenceFd) | |
325 | { | |
326 | TRACE(""); | |
327 | HWComposerNativeWindowBuffer* fbnb = (HWComposerNativeWindowBuffer*)buffer; | |
328 | ||
329 | pthread_mutex_lock(&_mutex); | |
330 | ||
331 | fbnb->busy=0; | |
332 | ||
333 | m_freeBufs++; | |
334 | ||
335 | pthread_cond_signal(&_cond); | |
336 | pthread_mutex_unlock(&_mutex); | |
337 | ||
338 | return 0; | |
339 | } | |
340 | ||
341 | ||
342 | ||
343 | int HWComposerNativeWindow::lockBuffer(BaseNativeWindowBuffer* buffer) | |
344 | { | |
345 | TRACE("%lu STUB", pthread_self()); | |
346 | return NO_ERROR; | |
347 | } | |
348 | ||
349 | ||
350 | /* | |
351 | * see NATIVE_WINDOW_FORMAT | |
352 | */ | |
353 | unsigned int HWComposerNativeWindow::width() const | |
354 | { | |
355 | unsigned int rv = m_width; | |
356 | TRACE("width=%i", rv); | |
357 | return rv; | |
358 | } | |
359 | ||
360 | ||
361 | /* | |
362 | * see NATIVE_WINDOW_HEIGHT | |
363 | */ | |
364 | unsigned int HWComposerNativeWindow::height() const | |
365 | { | |
366 | unsigned int rv = m_height; | |
367 | TRACE("height=%i", rv); | |
368 | return rv; | |
369 | } | |
370 | ||
371 | ||
372 | /* | |
373 | * see NATIVE_WINDOW_FORMAT | |
374 | */ | |
375 | unsigned int HWComposerNativeWindow::format() const | |
376 | { | |
377 | unsigned int rv = m_bufFormat; | |
378 | TRACE("format=x%x", rv); | |
379 | return rv; | |
380 | } | |
381 | ||
382 | ||
383 | /* | |
384 | * Default width and height of ANativeWindow buffers, these are the | |
385 | * dimensions of the window buffers irrespective of the | |
386 | * NATIVE_WINDOW_SET_BUFFERS_DIMENSIONS call and match the native window | |
387 | * size unless overridden by NATIVE_WINDOW_SET_BUFFERS_USER_DIMENSIONS. | |
388 | */ | |
389 | /* | |
390 | * see NATIVE_WINDOW_DEFAULT_HEIGHT | |
391 | */ | |
392 | unsigned int HWComposerNativeWindow::defaultHeight() const | |
393 | { | |
394 | unsigned int rv = m_height; | |
395 | TRACE("height=%i", rv); | |
396 | return rv; | |
397 | } | |
398 | ||
399 | ||
400 | /* | |
401 | * see BaseNativeWindow::_query(NATIVE_WINDOW_DEFAULT_WIDTH) | |
402 | */ | |
403 | unsigned int HWComposerNativeWindow::defaultWidth() const | |
404 | { | |
405 | unsigned int rv = m_width; | |
406 | TRACE("width=%i", rv); | |
407 | return rv; | |
408 | } | |
409 | ||
410 | ||
411 | /* | |
412 | * see NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER | |
413 | */ | |
414 | unsigned int HWComposerNativeWindow::queueLength() const | |
415 | { | |
416 | TRACE(""); | |
417 | return 0; | |
418 | } | |
419 | ||
420 | ||
421 | /* | |
422 | * see NATIVE_WINDOW_CONCRETE_TYPE | |
423 | */ | |
424 | unsigned int HWComposerNativeWindow::type() const | |
425 | { | |
426 | TRACE(""); | |
427 | return NATIVE_WINDOW_FRAMEBUFFER; | |
428 | } | |
429 | ||
430 | ||
431 | /* | |
432 | * see NATIVE_WINDOW_TRANSFORM_HINT | |
433 | */ | |
434 | unsigned int HWComposerNativeWindow::transformHint() const | |
435 | { | |
436 | TRACE(""); | |
437 | return 0; | |
438 | } | |
439 | ||
440 | ||
441 | ||
442 | /* | |
443 | * native_window_set_usage(..., usage) | |
444 | * Sets the intended usage flags for the next buffers | |
445 | * acquired with (*lockBuffer)() and on. | |
446 | * By default (if this function is never called), a usage of | |
447 | * GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE | |
448 | * is assumed. | |
449 | * Calling this function will usually cause following buffers to be | |
450 | * reallocated. | |
451 | */ | |
452 | int HWComposerNativeWindow::setUsage(int usage) | |
453 | { | |
454 | int need_realloc = (m_usage != usage); | |
455 | TRACE("usage=x%x realloc=%d", usage, need_realloc); | |
456 | m_usage = usage; | |
457 | if (need_realloc) | |
458 | this->setBufferCount(m_bufList.size()); | |
459 | ||
460 | return NO_ERROR; | |
461 | } | |
462 | ||
463 | ||
464 | /* | |
465 | * native_window_set_buffers_format(..., int format) | |
466 | * All buffers dequeued after this call will have the format specified. | |
467 | * | |
468 | * If the specified format is 0, the default buffer format will be used. | |
469 | */ | |
470 | int HWComposerNativeWindow::setBuffersFormat(int format) | |
471 | { | |
472 | int need_realloc = (format != m_bufFormat); | |
473 | TRACE("format=x%x realloc=%d", format, need_realloc); | |
474 | m_bufFormat = format; | |
475 | if (need_realloc) | |
476 | this->setBufferCount(m_bufList.size()); | |
477 | return NO_ERROR; | |
478 | } | |
479 | ||
480 | ||
481 | /* | |
482 | * native_window_set_buffer_count(..., count) | |
483 | * Sets the number of buffers associated with this native window. | |
484 | */ | |
485 | int HWComposerNativeWindow::setBufferCount(int cnt) | |
486 | { | |
487 | TRACE("cnt=%d", cnt); | |
488 | int err=NO_ERROR; | |
489 | pthread_mutex_lock(&_mutex); | |
490 | ||
491 | destroyBuffers(); | |
492 | ||
493 | for(unsigned int i = 0; i < cnt; i++) | |
494 | { | |
495 | HWComposerNativeWindowBuffer *fbnb = new HWComposerNativeWindowBuffer(m_alloc, | |
496 | m_width, m_height, m_bufFormat, | |
497 | m_usage|GRALLOC_USAGE_HW_COMPOSER); | |
498 | ||
499 | fbnb->common.incRef(&fbnb->common); | |
500 | ||
501 | TRACE("buffer %i is at %p (native %p),err=%s, handle=%p stride=%i", | |
502 | i, fbnb, (ANativeWindowBuffer*)fbnb, | |
503 | strerror(-fbnb->status), fbnb->handle, fbnb->stride); | |
504 | ||
505 | if (fbnb->status) | |
506 | { | |
507 | fbnb->common.decRef(&fbnb->common); | |
508 | fprintf(stderr,"WARNING: %s: allocated only %d buffers out of %d\n", __PRETTY_FUNCTION__, m_freeBufs, cnt); | |
509 | break; | |
510 | } | |
511 | ||
512 | m_freeBufs++; | |
513 | m_bufList.push_back(fbnb); | |
514 | } | |
515 | pthread_mutex_unlock(&_mutex); | |
516 | ||
517 | return err; | |
518 | } | |
519 | ||
520 | /* | |
521 | * native_window_set_buffers_dimensions(..., int w, int h) | |
522 | * All buffers dequeued after this call will have the dimensions specified. | |
523 | * In particular, all buffers will have a fixed-size, independent from the | |
524 | * native-window size. They will be scaled according to the scaling mode | |
525 | * (see native_window_set_scaling_mode) upon window composition. | |
526 | * | |
527 | * If w and h are 0, the normal behavior is restored. That is, dequeued buffers | |
528 | * following this call will be sized to match the window's size. | |
529 | * | |
530 | * Calling this function will reset the window crop to a NULL value, which | |
531 | * disables cropping of the buffers. | |
532 | */ | |
533 | int HWComposerNativeWindow::setBuffersDimensions(int width, int height) | |
534 | { | |
535 | TRACE("WARN: stub. size=%ix%i", width, height); | |
536 | return NO_ERROR; | |
537 | } | |
538 | // vim: noai:ts=4:sw=4:ss=4:expandtab |