@@ -120,7 +120,14 @@ inline SfHwcSurface::SfHwcSurface(Surface *surface, SfHwcBackend *backend, vec2
120
120
, m_backend(backend)
121
121
, m_vsyncDelta(0 )
122
122
, m_size(size)
123
+ , m_useOverlay(false )
123
124
{
125
+ char *overlay = getenv (" RENGINE_SURFACE_USE_OVERLAY" );
126
+ if (overlay && atoi (overlay) != 0 ) {
127
+ logi << " Using HWC_OVERLAY code path in HWC" << std::endl;
128
+ m_useOverlay = true ;
129
+ }
130
+
124
131
int bufferCount = 3 ;
125
132
char *overrideBufferCount = getenv (" RENGINE_SURFACE_BUFFER_COUNT" );
126
133
if (overrideBufferCount) {
@@ -189,15 +196,34 @@ inline void SfHwcSurface::initHwc()
189
196
memset (m_hwcList, 0 , size);
190
197
191
198
m_hwcList->retireFenceFd = -1 ;
199
+ m_hwcList->outbufAcquireFenceFd = -1 ;
192
200
m_hwcList->flags = HWC_GEOMETRY_CHANGED;
193
201
m_hwcList->numHwLayers = 2 ;
194
202
195
203
sfhwc_initialize_layer (&m_hwcList->hwLayers [0 ], HWC_FRAMEBUFFER, 0 , 0 , m_size.x , m_size.y );
196
- m_hwcList->hwLayers [0 ].planeAlpha = 1 ;
204
+
205
+ // The Qualcomm HWC doesn't support planar alpha, so by setting 1 we force
206
+ // it to take the GLES composited path, in which case, the
207
+ // HWC_FRAMEBUFFER_TARGET is used for direct presentation rather than
208
+ // composition.
209
+ if (m_useOverlay)
210
+ m_hwcList->hwLayers [0 ].planeAlpha = 255 ;
211
+ else
212
+ m_hwcList->hwLayers [0 ].planeAlpha = 1 ;
197
213
198
214
sfhwc_initialize_layer (&m_hwcList->hwLayers [1 ], HWC_FRAMEBUFFER_TARGET, 0 , 0 , m_size.x , m_size.y );
199
215
sfhwc_dump_display_contents (m_hwcList);
200
216
217
+ int bufferCount = 3 ;
218
+ char *overrideBufferCount = getenv (" RENGINE_SURFACE_TARGETBUFFER_COUNT" );
219
+ if (overrideBufferCount) {
220
+ bufferCount = std::max (1 , std::min (atoi (overrideBufferCount), 10 ));
221
+ }
222
+ logi << " using " << bufferCount << " HWC_FRAMEBUFFER_TARGET buffers" ;
223
+ for (int i=0 ; i<bufferCount; ++i) {
224
+ SfHwcBuffer *buffer = new SfHwcBuffer (m_backend, 720 , 1280 , HAL_PIXEL_FORMAT_BGRA_8888, GRALLOC_USAGE_HW_COMPOSER);
225
+ m_frameBuffers.push_back (buffer);
226
+ }
201
227
}
202
228
203
229
inline void SfHwcSurface::initEgl ()
@@ -253,115 +279,104 @@ inline void SfHwcSurface::initEgl()
253
279
254
280
inline void SfHwcSurface::present (HWComposerNativeWindowBuffer *buffer)
255
281
{
256
- // logw << "buffer=" << (void *) buffer << std::endl;
257
-
258
- int status = 0 ; (void ) status;
259
-
260
- static SfHwcBuffer *staticBuffer = 0 ;
261
- if (!staticBuffer) {
262
- staticBuffer = new SfHwcBuffer (m_backend, 720 , 1280 );
263
- staticBuffer->lock ();
264
- staticBuffer->fillWithCrap ();
265
- staticBuffer->unlock ();
266
- }
282
+ static auto lastFrame = std::chrono::steady_clock::now ();
283
+ auto thisFrame = std::chrono::steady_clock::now ();
284
+ auto delta = std::chrono::duration_cast<std::chrono::milliseconds>(thisFrame - lastFrame).count ();
285
+ if (delta > 30 )
286
+ logw << " MISSED A FRAME: " << delta << std::endl;
287
+ lastFrame = thisFrame;
288
+
289
+ if (m_useOverlay)
290
+ presentAsOverlay (buffer);
291
+ else
292
+ presentAsFramebufferTarget (buffer);
293
+ }
267
294
268
- static SfHwcBuffer *staticBuffer2 = 0 ;
269
- if (!staticBuffer2) {
270
- staticBuffer2 = new SfHwcBuffer (m_backend, 720 , 1280 );
271
- staticBuffer2->lock ();
272
- staticBuffer2->fillWithCrap ();
273
- staticBuffer2->unlock ();
274
- }
295
+ inline void SfHwcSurface::presentAsOverlay (HWComposerNativeWindowBuffer *buffer)
296
+ {
297
+ logw << " buffer=" << (void *) buffer << std::endl;
275
298
276
- hwc_composer_device_1_t *hwc = m_backend-> hwcDevice ;
299
+ int status = 0 ; ( void ) status ;
277
300
278
- // static auto lastFrame = std::chrono::steady_clock::now();
279
- // auto thisFrame = std::chrono::steady_clock::now();
280
- // auto delta = std::chrono::duration_cast<std::chrono::milliseconds>(thisFrame - lastFrame).count();
281
- // if (delta > 30)
282
- // logw << "MISSED A FRAME: " << delta << std::endl;
283
- // lastFrame = thisFrame;
301
+ hwc_composer_device_1_t *hwc = m_backend->hwcDevice ;
284
302
285
303
int fd = getFenceBufferFd (buffer);
286
304
setFenceBufferFd (buffer, -1 );
287
- #if 0
288
- if (fd != -1) {
289
- auto start = std::chrono::steady_clock::now();
290
- sync_wait(fd, -1);
291
- close(fd);
292
- auto end = std::chrono::steady_clock::now();
293
- auto delta = std::chrono::duration_cast<std::chrono::microseconds>(end - start).count() / 1000.0;
294
- logw << " - sync waited on libhybris buffer: " << delta << ", buffer=" << buffer << std::endl;
295
- fd = -1;
296
- }
297
- #endif
298
305
299
- hwc_layer_1_t *fb = &m_hwcList->hwLayers [0 ];
300
- fb->handle = staticBuffer->handle ();
301
- fb->acquireFenceFd = -1 ;
302
- fb->releaseFenceFd = -1 ;
303
- fb->blending = 1 ;
304
-
305
- static int counter = 0 ;
306
- counter = counter == 1 ? 0 : 1 ;
306
+ hwc_layer_1_t *fb = &m_hwcList->hwLayers [0 ];
307
+ fb->handle = buffer->handle ;
308
+ fb->acquireFenceFd = fd;
309
+ fb->releaseFenceFd = -1 ;
307
310
308
311
hwc_layer_1_t *fbt = &m_hwcList->hwLayers [1 ];
309
- fbt->handle = buffer ->handle ;
310
- fbt->acquireFenceFd = fd ;
312
+ fbt->handle = m_frameBuffers. front () ->handle () ;
313
+ fbt->acquireFenceFd = m_frameBuffers. front ()-> fence () ;
311
314
fbt->releaseFenceFd = -1 ;
312
315
313
- // sfhwc_dump_display_contents(m_hwcList);
314
- // sfhwc_dump_hwc_device(hwc);
316
+ // advance the framebuffers..
317
+ m_frameBuffers.push_back (m_frameBuffers.front ());
318
+ m_frameBuffers.pop_front ();
319
+
320
+ status = hwc->prepare (hwc, 1 , &m_hwcList); assert (status == 0 );
321
+ status = hwc->set (hwc, 1 , &m_hwcList); assert (status == 0 );
322
+
323
+ sfhwc_dump_hwc_device (hwc);
324
+
325
+ if (fb->releaseFenceFd != -1 ) {
326
+ setFenceBufferFd (buffer, fb->releaseFenceFd );
327
+ fb->releaseFenceFd = -1 ;
328
+ }
329
+
330
+ // cycle the framebuffer target
331
+ m_frameBuffers.back ()->setFence (fbt->releaseFenceFd );
332
+
333
+ if (m_hwcList->retireFenceFd != -1 ) {
334
+ close (m_hwcList->retireFenceFd );
335
+ m_hwcList->retireFenceFd = -1 ;
336
+ }
337
+ }
315
338
316
- status = hwc->prepare (hwc, 1 , &m_hwcList);
317
- assert (status == 0 );
318
- // sfhwc_dump_display_contents(m_hwcList);
319
- // sfhwc_dump_hwc_device(hwc);
339
+ inline void SfHwcSurface::presentAsFramebufferTarget (HWComposerNativeWindowBuffer *buffer)
340
+ {
341
+ logw << " buffer=" << (void *) buffer << std::endl;
320
342
321
- // auto start = std::chrono::steady_clock::now() ;
343
+ int status = 0 ; ( void ) status ;
322
344
323
- // logi << " --> calling set" << std::endl ;
345
+ hwc_composer_device_1_t *hwc = m_backend-> hwcDevice ;
324
346
325
- status = hwc->set (hwc, 1 , &m_hwcList);
347
+ int fd = getFenceBufferFd (buffer);
348
+ setFenceBufferFd (buffer, -1 );
326
349
327
- // logi << " <-- set completed" << std::endl;
350
+ hwc_layer_1_t *fb = &m_hwcList->hwLayers [0 ];
351
+ // Just pass a dummy handle that we have, we're not using these anyway..
352
+ fb->handle = m_frameBuffers.front ()->handle ();
353
+ fb->acquireFenceFd = -1 ;
354
+ fb->releaseFenceFd = -1 ;
328
355
329
- assert (status == 0 );
330
- // sfhwc_dump_hwc_device(hwc);
356
+ hwc_layer_1_t *fbt = &m_hwcList->hwLayers [1 ];
357
+ fbt->handle = buffer->handle ;
358
+ fbt->acquireFenceFd = fd;
359
+ fbt->releaseFenceFd = -1 ;
331
360
332
- // auto end = std::chrono::steady_clock::now( );
333
- // auto delta = std::chrono::duration_cast<std::chrono::microseconds>(end - start).count() / 1000.0 ;
361
+ status = hwc-> prepare (hwc, 1 , &m_hwcList); assert (status == 0 );
362
+ status = hwc-> set (hwc, 1 , &m_hwcList); assert (status == 0 ) ;
334
363
335
- // logw << " - set completed in " << delta << std::endl;
364
+ if (fbt->releaseFenceFd != -1 ) {
365
+ setFenceBufferFd (buffer, fbt->releaseFenceFd );
366
+ fbt->releaseFenceFd = -1 ;
367
+ }
336
368
369
+ // Since we're taking the fb target code path, this buffer should be unused
370
+ // so this should in theory never happen...
337
371
if (fb->releaseFenceFd != -1 ) {
338
- #if 1
339
- setFenceBufferFd (buffer, fb->releaseFenceFd );
340
- fb->releaseFenceFd = -1 ;
341
- #else
342
- auto start = std::chrono::steady_clock::now();
343
- sync_wait(fb->releaseFenceFd, -1);
344
372
close (fb->releaseFenceFd );
345
373
fb->releaseFenceFd = -1 ;
346
- auto end = std::chrono::steady_clock::now();
347
- auto delta = std::chrono::duration_cast<std::chrono::microseconds>(end - start).count() / 1000.0;
348
- logw << " - waited for fb release fd, " << delta << std::endl;
349
- #endif
350
374
}
351
375
352
- if (fbt->releaseFenceFd != -1 ) {
353
- close (fbt->releaseFenceFd );
354
- fbt->releaseFenceFd = -1 ;
355
- // logw << " - closed fbt release fd" << std::endl;
376
+ if (m_hwcList->retireFenceFd != -1 ) {
377
+ close (m_hwcList->retireFenceFd );
378
+ m_hwcList->retireFenceFd = -1 ;
356
379
}
357
-
358
- if (m_hwcList->retireFenceFd != -1 ) {
359
- close (m_hwcList->retireFenceFd );
360
- m_hwcList->retireFenceFd = -1 ;
361
- // logw << " - closed retire fence fd.." << std::endl;
362
- }
363
-
364
- // logd << " -> frame on screen" << std::endl;
365
380
}
366
381
367
382
RENGINE_END_NAMESPACE
0 commit comments