summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Fennema <fennema@google.com>2018-05-08 13:50:32 -0700
committerBen Fennema <fennema@google.com>2018-05-08 14:36:40 -0700
commitd39a514dd0540cf47e121775a77e9ac1b578bdb1 (patch)
tree77c1c6c4ab08abbdcc067f2f05cf8a7cb50696a1
parent3a26d0f124f7d89c4e01078dd44e6ed656e5ccaf (diff)
downloaddisplay-d39a514dd0540cf47e121775a77e9ac1b578bdb1.tar.gz
display: msm8909w caf release LW.BR.4.0-00800-8x09w.0 for SD2100.
MSM8909W display HAL code copied from CAF release LW.BR.4.0-00800-8x09w.0. Bug: 79356346 Test: build Change-Id: Ie801976595c8ed9164b0d91737f5daf40764d8a6 Signed-off-by: Ben Fennema <fennema@google.com>
-rw-r--r--msm8909/.clang-format13
-rw-r--r--msm8909/.gitignore4
-rw-r--r--msm8909/Android.bp42
-rw-r--r--msm8909/Android.mk13
-rw-r--r--msm8909/common.mk94
-rw-r--r--msm8909/gpu_tonemapper/Android.mk27
-rw-r--r--msm8909/gpu_tonemapper/EGLImageBuffer.cpp161
-rw-r--r--msm8909/gpu_tonemapper/EGLImageBuffer.h50
-rw-r--r--msm8909/gpu_tonemapper/EGLImageWrapper.cpp154
-rw-r--r--msm8909/gpu_tonemapper/EGLImageWrapper.h47
-rw-r--r--msm8909/gpu_tonemapper/TonemapFactory.cpp34
-rw-r--r--msm8909/gpu_tonemapper/TonemapFactory.h37
-rw-r--r--msm8909/gpu_tonemapper/Tonemapper.cpp153
-rw-r--r--msm8909/gpu_tonemapper/Tonemapper.h47
-rw-r--r--msm8909/gpu_tonemapper/engine.h43
-rw-r--r--msm8909/gpu_tonemapper/forward_tonemap.inl55
-rw-r--r--msm8909/gpu_tonemapper/fullscreen_vertex_shader.inl37
-rw-r--r--msm8909/gpu_tonemapper/glengine.cpp415
-rw-r--r--msm8909/gpu_tonemapper/glengine.h47
-rw-r--r--msm8909/gpu_tonemapper/rgba_inverse_tonemap.inl60
-rw-r--r--msm8909/gralloc/Android.mk38
-rw-r--r--msm8909/gralloc/gr_adreno_info.cpp214
-rw-r--r--msm8909/gralloc/gr_adreno_info.h148
-rw-r--r--msm8909/gralloc/gr_allocator.cpp312
-rw-r--r--msm8909/gralloc/gr_allocator.h75
-rw-r--r--msm8909/gralloc/gr_buf_descriptor.h96
-rw-r--r--msm8909/gralloc/gr_buf_mgr.cpp929
-rw-r--r--msm8909/gralloc/gr_buf_mgr.h135
-rw-r--r--msm8909/gralloc/gr_device_impl.cpp530
-rw-r--r--msm8909/gralloc/gr_device_impl.h133
-rw-r--r--msm8909/gralloc/gr_ion_alloc.cpp204
-rw-r--r--msm8909/gralloc/gr_ion_alloc.h (renamed from msm8909/libhdmi/hdmi_stub.cpp)91
-rw-r--r--msm8909/gralloc/gr_priv_handle.h200
-rw-r--r--msm8909/gralloc/gr_utils.cpp854
-rw-r--r--msm8909/gralloc/gr_utils.h96
-rw-r--r--msm8909/gralloc/gralloc_priv.h209
-rw-r--r--msm8909/hdmi_cec/Android.mk18
-rw-r--r--msm8909/hdmi_cec/qhdmi_cec.cpp721
-rw-r--r--msm8909/hdmi_cec/qhdmi_cec.h91
-rw-r--r--msm8909/include/Android.mk20
-rw-r--r--msm8909/include/color_metadata.h189
-rw-r--r--msm8909/include/display_properties.h101
-rw-r--r--msm8909/libcopybit/Android.mk11
-rw-r--r--msm8909/libcopybit/c2d2.h4
-rw-r--r--msm8909/libcopybit/copybit.cpp31
-rw-r--r--msm8909/libcopybit/copybit.h15
-rw-r--r--msm8909/libcopybit/copybit_c2d.cpp46
-rw-r--r--msm8909/libcopybit/software_converter.cpp3
-rw-r--r--msm8909/libcopybit/software_converter.h3
-rw-r--r--msm8909/libdisplayconfig/Android.mk13
-rw-r--r--msm8909/libdisplayconfig/DisplayConfig.cpp363
-rw-r--r--msm8909/libdisplayconfig/DisplayConfig.h110
-rw-r--r--msm8909/libdrmutils/Android.mk17
-rw-r--r--msm8909/libdrmutils/drm_interface.h449
-rw-r--r--msm8909/libdrmutils/drm_lib_loader.cpp92
-rw-r--r--msm8909/libdrmutils/drm_lib_loader.h64
-rw-r--r--msm8909/libdrmutils/drm_logger.h69
-rw-r--r--msm8909/libdrmutils/drm_master.cpp149
-rw-r--r--msm8909/libdrmutils/drm_master.h95
-rw-r--r--msm8909/libdrmutils/drm_res_mgr.cpp151
-rw-r--r--msm8909/libdrmutils/drm_res_mgr.h72
-rw-r--r--msm8909/libgralloc/Android.mk19
-rw-r--r--msm8909/libgralloc/Makefile.am42
-rw-r--r--msm8909/libgralloc/adreno_utils.h59
-rw-r--r--msm8909/libgralloc/alloc_controller.cpp950
-rw-r--r--msm8909/libgralloc/alloc_controller.h18
-rw-r--r--msm8909/libgralloc/framebuffer.cpp8
-rw-r--r--msm8909/libgralloc/gpu.cpp147
-rw-r--r--msm8909/libgralloc/gpu.h2
-rw-r--r--msm8909/libgralloc/gr.h95
-rw-r--r--msm8909/libgralloc/gralloc.cpp2
-rw-r--r--msm8909/libgralloc/gralloc_priv.h299
-rw-r--r--msm8909/libgralloc/ionalloc.cpp12
-rw-r--r--msm8909/libgralloc/mapper.cpp299
-rw-r--r--msm8909/libgralloc/memalloc.h1
-rw-r--r--msm8909/libhdmi/Android.mk18
-rw-r--r--msm8909/libhdmi/hdmi.cpp699
-rw-r--r--msm8909/libhdmi/hdmi.h110
-rw-r--r--msm8909/libhwcomposer/Android.mk71
-rw-r--r--msm8909/libhwcomposer/hwc.cpp977
-rw-r--r--msm8909/libhwcomposer/hwc_ad.cpp278
-rw-r--r--msm8909/libhwcomposer/hwc_copybit.cpp1382
-rw-r--r--msm8909/libhwcomposer/hwc_copybit.h149
-rw-r--r--msm8909/libhwcomposer/hwc_dump_layers.cpp454
-rw-r--r--msm8909/libhwcomposer/hwc_dump_layers.h136
-rw-r--r--msm8909/libhwcomposer/hwc_fbupdate.cpp565
-rw-r--r--msm8909/libhwcomposer/hwc_fbupdate.h111
-rw-r--r--msm8909/libhwcomposer/hwc_mdpcomp.cpp2827
-rw-r--r--msm8909/libhwcomposer/hwc_mdpcomp.h371
-rw-r--r--msm8909/libhwcomposer/hwc_qclient.cpp401
-rw-r--r--msm8909/libhwcomposer/hwc_qdcm.cpp292
-rw-r--r--msm8909/libhwcomposer/hwc_qdcm.h94
-rw-r--r--msm8909/libhwcomposer/hwc_uevents.cpp243
-rw-r--r--msm8909/libhwcomposer/hwc_utils.cpp2907
-rw-r--r--msm8909/libhwcomposer/hwc_utils.h718
-rw-r--r--msm8909/libhwcomposer/hwc_virtual.cpp236
-rw-r--r--msm8909/libhwcomposer/hwc_virtual.h64
-rw-r--r--msm8909/libhwcomposer/hwc_vsync.cpp239
-rw-r--r--msm8909/liblight/Android.mk14
-rw-r--r--msm8909/liblight/lights.c122
-rw-r--r--msm8909/liblight/lights_prv.cpp (renamed from msm8909/libhwcomposer/hwc_qclient.h)55
-rw-r--r--msm8909/liblight/lights_prv.h (renamed from msm8909/libhwcomposer/hwc_qdcm_legacy.cpp)58
-rw-r--r--msm8909/libmemtrack/Android.mk4
-rw-r--r--msm8909/libmemtrack/kgsl.c13
-rw-r--r--msm8909/liboverlay/Android.mk23
-rw-r--r--msm8909/liboverlay/mdpWrapper.h388
-rw-r--r--msm8909/liboverlay/overlay.cpp582
-rw-r--r--msm8909/liboverlay/overlay.h428
-rw-r--r--msm8909/liboverlay/overlayCtrlData.h249
-rw-r--r--msm8909/liboverlay/overlayMdp.cpp393
-rw-r--r--msm8909/liboverlay/overlayMdp.h321
-rwxr-xr-xmsm8909/liboverlay/overlayMdpRot.cpp322
-rw-r--r--msm8909/liboverlay/overlayMdssRot.cpp430
-rw-r--r--msm8909/liboverlay/overlayMem.h222
-rw-r--r--msm8909/liboverlay/overlayRotator.cpp242
-rw-r--r--msm8909/liboverlay/overlayRotator.h322
-rw-r--r--msm8909/liboverlay/overlayUtils.cpp399
-rw-r--r--msm8909/liboverlay/overlayUtils.h683
-rw-r--r--msm8909/liboverlay/overlayWriteback.cpp280
-rw-r--r--msm8909/liboverlay/overlayWriteback.h122
-rw-r--r--msm8909/liboverlay/pipes/overlayGenPipe.cpp124
-rw-r--r--msm8909/liboverlay/pipes/overlayGenPipe.h86
-rw-r--r--msm8909/libqdutils/Android.bp42
-rw-r--r--msm8909/libqdutils/Android.mk40
-rw-r--r--msm8909/libqdutils/Makefile.am32
-rw-r--r--msm8909/libqdutils/cb_swap_rect.cpp46
-rw-r--r--msm8909/libqdutils/cb_utils.cpp134
-rw-r--r--msm8909/libqdutils/comptype.cpp33
-rw-r--r--msm8909/libqdutils/comptype.h82
-rw-r--r--msm8909/libqdutils/display_config.cpp201
-rw-r--r--msm8909/libqdutils/display_config.h94
-rw-r--r--msm8909/libqdutils/idle_invalidator.cpp149
-rw-r--r--msm8909/libqdutils/idle_invalidator.h59
-rw-r--r--msm8909/libqdutils/mdp_version.cpp489
-rw-r--r--msm8909/libqdutils/mdp_version.h182
-rw-r--r--msm8909/libqdutils/profiler.cpp1
-rw-r--r--msm8909/libqdutils/profiler.h2
-rw-r--r--msm8909/libqdutils/qdMetaData.cpp286
-rw-r--r--msm8909/libqdutils/qdMetaData.h153
-rw-r--r--msm8909/libqdutils/qd_utils.cpp329
-rw-r--r--msm8909/libqdutils/qd_utils.h29
-rw-r--r--msm8909/libqservice/Android.bp16
-rw-r--r--msm8909/libqservice/Android.mk21
-rw-r--r--msm8909/libqservice/IQHDMIClient.cpp103
-rw-r--r--msm8909/libqservice/IQHDMIClient.h (renamed from msm8909/libhwcomposer/hwc_ad.h)53
-rw-r--r--msm8909/libqservice/IQService.cpp67
-rw-r--r--msm8909/libqservice/IQService.h70
-rw-r--r--msm8909/libqservice/Makefile.am18
-rw-r--r--msm8909/libqservice/QService.cpp34
-rw-r--r--msm8909/libqservice/QService.h8
-rw-r--r--msm8909/libqservice/QServiceUtils.h36
-rw-r--r--msm8909/sdm/include/core/buffer_allocator.h159
-rw-r--r--msm8909/sdm/include/core/buffer_sync_handler.h99
-rw-r--r--msm8909/sdm/include/core/core_interface.h240
-rw-r--r--msm8909/sdm/include/core/debug_interface.h165
-rw-r--r--msm8909/sdm/include/core/display_interface.h694
-rw-r--r--msm8909/sdm/include/core/layer_buffer.h283
-rw-r--r--msm8909/sdm/include/core/layer_stack.h392
-rw-r--r--msm8909/sdm/include/core/sdm_types.h75
-rw-r--r--msm8909/sdm/include/core/socket_handler.h75
-rw-r--r--msm8909/sdm/include/private/color_interface.h88
-rw-r--r--msm8909/sdm/include/private/color_params.h636
-rw-r--r--msm8909/sdm/include/private/dpps_control_interface.h40
-rw-r--r--msm8909/sdm/include/private/extension_interface.h87
-rw-r--r--msm8909/sdm/include/private/hw_info_types.h561
-rw-r--r--msm8909/sdm/include/private/partial_update_interface.h55
-rw-r--r--msm8909/sdm/include/private/resource_interface.h77
-rw-r--r--msm8909/sdm/include/private/strategy_interface.h65
-rw-r--r--msm8909/sdm/include/utils/constants.h84
-rw-r--r--msm8909/sdm/include/utils/debug.h121
-rw-r--r--msm8909/sdm/include/utils/factory.h63
-rw-r--r--msm8909/sdm/include/utils/formats.h (renamed from msm8909/libqdutils/cb_swap_rect.h)44
-rw-r--r--msm8909/sdm/include/utils/locker.h166
-rw-r--r--msm8909/sdm/include/utils/rect.h67
-rw-r--r--msm8909/sdm/include/utils/sync_task.h143
-rw-r--r--msm8909/sdm/include/utils/sys.h101
-rw-r--r--msm8909/sdm/include/utils/utils.h (renamed from msm8909/libqdutils/cb_utils.h)40
-rw-r--r--msm8909/sdm/libs/core/Android.mk82
-rw-r--r--msm8909/sdm/libs/core/Makefile.am47
-rw-r--r--msm8909/sdm/libs/core/color_manager.cpp243
-rw-r--r--msm8909/sdm/libs/core/color_manager.h98
-rw-r--r--msm8909/sdm/libs/core/comp_manager.cpp605
-rw-r--r--msm8909/sdm/libs/core/comp_manager.h123
-rw-r--r--msm8909/sdm/libs/core/core_impl.cpp188
-rw-r--r--msm8909/sdm/libs/core/core_impl.h80
-rw-r--r--msm8909/sdm/libs/core/core_interface.cpp133
-rw-r--r--msm8909/sdm/libs/core/display_base.cpp1536
-rw-r--r--msm8909/sdm/libs/core/display_base.h184
-rw-r--r--msm8909/sdm/libs/core/display_hdmi.cpp303
-rw-r--r--msm8909/sdm/libs/core/display_hdmi.h71
-rw-r--r--msm8909/sdm/libs/core/display_primary.cpp338
-rw-r--r--msm8909/sdm/libs/core/display_primary.h75
-rw-r--r--msm8909/sdm/libs/core/display_virtual.cpp141
-rw-r--r--msm8909/sdm/libs/core/display_virtual.h74
-rw-r--r--msm8909/sdm/libs/core/drm/hw_color_manager_drm.cpp294
-rw-r--r--msm8909/sdm/libs/core/drm/hw_color_manager_drm.h64
-rw-r--r--msm8909/sdm/libs/core/drm/hw_device_drm.cpp1061
-rw-r--r--msm8909/sdm/libs/core/drm/hw_device_drm.h168
-rw-r--r--msm8909/sdm/libs/core/drm/hw_events_drm.cpp298
-rw-r--r--msm8909/sdm/libs/core/drm/hw_events_drm.h90
-rw-r--r--msm8909/sdm/libs/core/drm/hw_info_drm.cpp594
-rw-r--r--msm8909/sdm/libs/core/drm/hw_info_drm.h82
-rw-r--r--msm8909/sdm/libs/core/drm/hw_scale_drm.cpp157
-rw-r--r--msm8909/sdm/libs/core/drm/hw_scale_drm.h63
-rw-r--r--msm8909/sdm/libs/core/fb/hw_color_manager.cpp188
-rw-r--r--msm8909/sdm/libs/core/fb/hw_color_manager.h60
-rw-r--r--msm8909/sdm/libs/core/fb/hw_device.cpp1368
-rw-r--r--msm8909/sdm/libs/core/fb/hw_device.h167
-rw-r--r--msm8909/sdm/libs/core/fb/hw_events.cpp237
-rw-r--r--msm8909/sdm/libs/core/fb/hw_events.h86
-rw-r--r--msm8909/sdm/libs/core/fb/hw_hdmi.cpp1129
-rw-r--r--msm8909/sdm/libs/core/fb/hw_hdmi.h130
-rw-r--r--msm8909/sdm/libs/core/fb/hw_info.cpp565
-rw-r--r--msm8909/sdm/libs/core/fb/hw_info.h81
-rw-r--r--msm8909/sdm/libs/core/fb/hw_primary.cpp687
-rw-r--r--msm8909/sdm/libs/core/fb/hw_primary.h96
-rw-r--r--msm8909/sdm/libs/core/fb/hw_scale.cpp314
-rw-r--r--msm8909/sdm/libs/core/fb/hw_scale.h85
-rw-r--r--msm8909/sdm/libs/core/fb/hw_virtual.cpp86
-rw-r--r--msm8909/sdm/libs/core/fb/hw_virtual.h52
-rw-r--r--msm8909/sdm/libs/core/hw_events_interface.cpp75
-rw-r--r--msm8909/sdm/libs/core/hw_events_interface.h63
-rw-r--r--msm8909/sdm/libs/core/hw_info_interface.cpp62
-rw-r--r--msm8909/sdm/libs/core/hw_info_interface.h48
-rw-r--r--msm8909/sdm/libs/core/hw_interface.cpp102
-rw-r--r--msm8909/sdm/libs/core/hw_interface.h120
-rw-r--r--msm8909/sdm/libs/core/resource_default.cpp950
-rw-r--r--msm8909/sdm/libs/core/resource_default.h150
-rw-r--r--msm8909/sdm/libs/core/strategy.cpp265
-rw-r--r--msm8909/sdm/libs/core/strategy.h79
-rw-r--r--msm8909/sdm/libs/hwc/Android.mk39
-rw-r--r--msm8909/sdm/libs/hwc/blit_engine.h66
-rw-r--r--msm8909/sdm/libs/hwc/blit_engine_c2d.cpp608
-rw-r--r--msm8909/sdm/libs/hwc/blit_engine_c2d.h121
-rw-r--r--msm8909/sdm/libs/hwc/cpuhint.cpp108
-rw-r--r--msm8909/sdm/libs/hwc/cpuhint.h61
-rw-r--r--msm8909/sdm/libs/hwc/hwc_buffer_allocator.cpp330
-rw-r--r--msm8909/sdm/libs/hwc/hwc_buffer_allocator.h70
-rw-r--r--msm8909/sdm/libs/hwc/hwc_buffer_sync_handler.cpp92
-rw-r--r--msm8909/sdm/libs/hwc/hwc_buffer_sync_handler.h53
-rw-r--r--msm8909/sdm/libs/hwc/hwc_color_manager.cpp651
-rw-r--r--msm8909/sdm/libs/hwc/hwc_color_manager.h149
-rw-r--r--msm8909/sdm/libs/hwc/hwc_debugger.cpp232
-rw-r--r--msm8909/sdm/libs/hwc/hwc_debugger.h81
-rw-r--r--msm8909/sdm/libs/hwc/hwc_display.cpp1536
-rw-r--r--msm8909/sdm/libs/hwc/hwc_display.h266
-rw-r--r--msm8909/sdm/libs/hwc/hwc_display_external.cpp336
-rw-r--r--msm8909/sdm/libs/hwc/hwc_display_external.h64
-rw-r--r--msm8909/sdm/libs/hwc/hwc_display_external_test.cpp764
-rw-r--r--msm8909/sdm/libs/hwc/hwc_display_external_test.h102
-rw-r--r--msm8909/sdm/libs/hwc/hwc_display_null.cpp120
-rw-r--r--msm8909/sdm/libs/hwc/hwc_display_null.h106
-rw-r--r--msm8909/sdm/libs/hwc/hwc_display_primary.cpp574
-rw-r--r--msm8909/sdm/libs/hwc/hwc_display_primary.h91
-rw-r--r--msm8909/sdm/libs/hwc/hwc_display_virtual.cpp334
-rw-r--r--msm8909/sdm/libs/hwc/hwc_display_virtual.h64
-rw-r--r--msm8909/sdm/libs/hwc/hwc_session.cpp1734
-rw-r--r--msm8909/sdm/libs/hwc/hwc_session.h162
-rw-r--r--msm8909/sdm/libs/hwc/hwc_socket_handler.cpp48
-rw-r--r--msm8909/sdm/libs/hwc/hwc_socket_handler.h47
-rw-r--r--msm8909/sdm/libs/hwc/hwc_tonemapper.cpp341
-rw-r--r--msm8909/sdm/libs/hwc/hwc_tonemapper.h101
-rw-r--r--msm8909/sdm/libs/hwc2/Android.mk67
-rw-r--r--msm8909/sdm/libs/hwc2/display_null.cpp68
-rw-r--r--msm8909/sdm/libs/hwc2/display_null.h110
-rw-r--r--msm8909/sdm/libs/hwc2/hwc_buffer_allocator.cpp409
-rw-r--r--msm8909/sdm/libs/hwc2/hwc_buffer_allocator.h80
-rw-r--r--msm8909/sdm/libs/hwc2/hwc_callbacks.cpp82
-rw-r--r--msm8909/sdm/libs/hwc2/hwc_callbacks.h63
-rw-r--r--msm8909/sdm/libs/hwc2/hwc_color_manager.cpp461
-rw-r--r--msm8909/sdm/libs/hwc2/hwc_color_manager.h143
-rw-r--r--msm8909/sdm/libs/hwc2/hwc_display.cpp2049
-rw-r--r--msm8909/sdm/libs/hwc2/hwc_display.h317
-rw-r--r--msm8909/sdm/libs/hwc2/hwc_display_external.cpp280
-rw-r--r--msm8909/sdm/libs/hwc2/hwc_display_external.h68
-rw-r--r--msm8909/sdm/libs/hwc2/hwc_display_external_test.cpp750
-rw-r--r--msm8909/sdm/libs/hwc2/hwc_display_external_test.h102
-rw-r--r--msm8909/sdm/libs/hwc2/hwc_display_primary.cpp620
-rw-r--r--msm8909/sdm/libs/hwc2/hwc_display_primary.h110
-rw-r--r--msm8909/sdm/libs/hwc2/hwc_display_virtual.cpp263
-rw-r--r--msm8909/sdm/libs/hwc2/hwc_display_virtual.h64
-rw-r--r--msm8909/sdm/libs/hwc2/hwc_layers.cpp827
-rw-r--r--msm8909/sdm/libs/hwc2/hwc_layers.h132
-rw-r--r--msm8909/sdm/libs/hwc2/hwc_session.cpp1631
-rw-r--r--msm8909/sdm/libs/hwc2/hwc_session.h264
-rw-r--r--msm8909/sdm/libs/hwc2/hwc_session_services.cpp494
-rw-r--r--msm8909/sdm/libs/hwc2/hwc_tonemapper.cpp386
-rw-r--r--msm8909/sdm/libs/hwc2/hwc_tonemapper.h125
-rw-r--r--msm8909/sdm/libs/utils/Android.mk32
-rw-r--r--msm8909/sdm/libs/utils/Makefile.am12
-rw-r--r--msm8909/sdm/libs/utils/debug.cpp216
-rw-r--r--msm8909/sdm/libs/utils/formats.cpp131
-rw-r--r--msm8909/sdm/libs/utils/rect.cpp270
-rw-r--r--msm8909/sdm/libs/utils/sys.cpp95
-rw-r--r--msm8909/sdm/libs/utils/utils.cpp71
295 files changed, 50516 insertions, 21464 deletions
diff --git a/msm8909/.clang-format b/msm8909/.clang-format
new file mode 100644
index 00000000..9082c400
--- /dev/null
+++ b/msm8909/.clang-format
@@ -0,0 +1,13 @@
+---
+Language: Cpp
+BasedOnStyle: Google
+AllowShortIfStatementsOnASingleLine: false
+AllowShortLoopsOnASingleLine: false
+AllowShortFunctionsOnASingleLine: Inline
+AllowShortBlocksOnASingleLine: false
+ColumnLimit: 100
+ConstructorInitializerAllOnOneLineOrOnePerLine: true
+ConstructorInitializerIndentWidth: 4
+DerivePointerAlignment: false
+PointerAlignment: Right
+#ReflowComments: false
diff --git a/msm8909/.gitignore b/msm8909/.gitignore
new file mode 100644
index 00000000..ad71dd6c
--- /dev/null
+++ b/msm8909/.gitignore
@@ -0,0 +1,4 @@
+CMakeLists.txt
+.idea/
+.editorconfig
+.clang-complete
diff --git a/msm8909/Android.bp b/msm8909/Android.bp
new file mode 100644
index 00000000..ea40594f
--- /dev/null
+++ b/msm8909/Android.bp
@@ -0,0 +1,42 @@
+soong_namespace {
+}
+
+cc_defaults {
+ name: "display_defaults",
+ cflags: [
+ "-Wno-missing-field-initializers",
+ "-Wconversion",
+ "-Wall",
+ "-Werror",
+ "-std=c++14",
+ ],
+ shared_libs: [
+ "liblog",
+ "libcutils",
+ "libutils",
+ ],
+ header_libs: ["display_headers"],
+ clang: true,
+}
+
+cc_library_headers {
+ name: "display_headers",
+ vendor_available: true,
+ export_include_dirs: [
+ "include",
+ "libcopybit",
+ "libdrmutils",
+ "libqdutils",
+ "libqservice",
+ "gpu_tonemapper",
+ "sdm/include",
+ "gralloc",
+ ],
+ header_libs: ["libhardware_headers"],
+ export_header_lib_headers: ["libhardware_headers"],
+}
+
+subdirs = [
+ "libqservice",
+ "libqdutils",
+]
diff --git a/msm8909/Android.mk b/msm8909/Android.mk
index d8b168d2..f354caf5 100644
--- a/msm8909/Android.mk
+++ b/msm8909/Android.mk
@@ -1,6 +1,13 @@
-display-hals := libgralloc libgenlock libcopybit liblight
-display-hals += libhwcomposer liboverlay libqdutils libhdmi libqservice
-display-hals += libmemtrack
+sdm-libs := sdm/libs
+display-hals := include $(sdm-libs)/utils $(sdm-libs)/core
+
+ifneq ($(TARGET_IS_HEADLESS), true)
+ display-hals += libcopybit liblight libmemtrack hdmi_cec \
+ $(sdm-libs)/hwc $(sdm-libs)/hwc2 gpu_tonemapper libdrmutils libdisplayconfig
+endif
+
+display-hals += gralloc
+
ifeq ($(call is-vendor-board-platform,QCOM),true)
include $(call all-named-subdir-makefiles,$(display-hals))
else
diff --git a/msm8909/common.mk b/msm8909/common.mk
index 2465cc86..f8fe936e 100644
--- a/msm8909/common.mk
+++ b/msm8909/common.mk
@@ -1,69 +1,81 @@
#Common headers
-common_includes := $(LOCAL_PATH)/../libgralloc
-common_includes += $(LOCAL_PATH)/../liboverlay
-common_includes += $(LOCAL_PATH)/../libcopybit
-common_includes += $(LOCAL_PATH)/../libqdutils
-common_includes += $(LOCAL_PATH)/../libhwcomposer
-common_includes += $(LOCAL_PATH)/../libhdmi
-common_includes += $(LOCAL_PATH)/../libqservice
+display_top := $(call my-dir)
+display_config_version := $(shell \
+ if [ -d "$(TOP)/vendor/qcom/codeaurora/interfaces/vendor/display/config/1.1" ];\
+ then echo DISPLAY_CONFIG_1_1; fi)
-ifeq ($(TARGET_USES_POST_PROCESSING),true)
- common_flags += -DUSES_POST_PROCESSING
- common_includes += $(TARGET_OUT_HEADERS)/pp/inc
+#Common C flags
+common_flags := -DDEBUG_CALC_FPS -Wno-missing-field-initializers
+common_flags += -Wconversion -Wall -Werror -std=c++14
+ifeq ($(TARGET_IS_HEADLESS), true)
+ common_flags += -DTARGET_HEADLESS
+ LOCAL_CLANG := false
endif
-common_header_export_path := qcom/display
+ifeq ($(display_config_version), DISPLAY_CONFIG_1_1)
+ common_flags += -DDISPLAY_CONFIG_1_1
+endif
-#Common libraries external to display HAL
-common_libs := liblog libutils libcutils libhardware
+ifeq ($(TARGET_USES_COLOR_METADATA), true)
+ common_flags += -DUSE_COLOR_METADATA
+endif
-#Common C flags
-common_flags := -DDEBUG_CALC_FPS -Wno-missing-field-initializers
-common_flags += -Wconversion -Wall -Werror -Wno-sign-conversion
+ifeq ($(TARGET_USES_QCOM_BSP),true)
+ common_flags += -DQTI_BSP
+endif
ifeq ($(ARCH_ARM_HAVE_NEON),true)
common_flags += -D__ARM_HAVE_NEON
endif
-ifeq ($(call is-board-platform-in-list, $(MSM_VIDC_TARGET_LIST)), true)
- common_flags += -DVENUS_COLOR_FORMAT
+ifeq ($(call is-board-platform-in-list, $(MASTER_SIDE_CP_TARGET_LIST)), true)
+ common_flags += -DMASTER_SIDE_CP
endif
-ifeq ($(call is-board-platform-in-list, msm8974 msm8226 msm8610 apq8084 \
- mpq8092 msm_bronze msm8916 msm8994), true)
- common_flags += -DMDSS_TARGET
+use_hwc2 := false
+ifeq ($(TARGET_USES_HWC2), true)
+ use_hwc2 := true
+ common_flags += -DVIDEO_MODE_DEFER_RETIRE_FENCE
endif
-ifeq ($(call is-board-platform-in-list, msm8909), true)
- common_flags += -DVENUS_COLOR_FORMAT
- common_flags += -DMDSS_TARGET
+
+ifeq ($(TARGET_USES_GRALLOC1), true)
+ common_flags += -DUSE_GRALLOC1
endif
-ifeq ($(DISPLAY_DEBUG_SWAPINTERVAL),true)
- common_flags += -DDEBUG_SWAPINTERVAL
+common_includes := system/core/base/include
+CHECK_VERSION_LE = $(shell if [ $(1) -le $(2) ] ; then echo true ; else echo false ; fi)
+PLATFORM_SDK_NOUGAT = 25
+ifeq "REL" "$(PLATFORM_VERSION_CODENAME)"
+ifeq ($(call CHECK_VERSION_LE, $(PLATFORM_SDK_VERSION), $(PLATFORM_SDK_NOUGAT)), true)
+version_flag := -D__NOUGAT__
+
+# These include paths are deprecated post N
+common_includes += $(display_top)/libqdutils
+common_includes += $(display_top)/libqservice
+common_includes += $(display_top)/gpu_tonemapper
+ifneq ($(TARGET_IS_HEADLESS), true)
+ common_includes += $(display_top)/libcopybit
+endif
+
+common_includes += $(display_top)/include
+common_includes += $(display_top)/sdm/include
+common_flags += -isystem $(TARGET_OUT_HEADERS)/qcom/display
+endif
endif
-common_flags += -D__STDC_FORMAT_MACROS
+common_header_export_path := qcom/display
+#Common libraries external to display HAL
+common_libs := liblog libutils libcutils libhardware
common_deps :=
kernel_includes :=
-# Executed only on QCOM BSPs
-ifeq ($(TARGET_USES_QCOM_BSP),true)
-# Enable QCOM Display features
- common_flags += -DQTI_BSP
- common_includes += $(BOARD_OPENSOURCE_DIR)/display-frameworks/include
-endif
-ifneq ($(call is-platform-sdk-version-at-least,18),true)
- common_flags += -DANDROID_JELLYBEAN_MR1=1
-endif
-ifeq ($(call is-vendor-board-platform,QCOM),true)
+ifeq ($(TARGET_COMPILE_WITH_MSM_KERNEL),true)
# This check is to pick the kernel headers from the right location.
# If the macro above is defined, we make the assumption that we have the kernel
# available in the build tree.
# If the macro is not present, the headers are picked from hardware/qcom/msmXXXX
# failing which, they are picked from bionic.
- common_deps += $(BOARD_KERNEL_HEADER_DEPENDENCIES)
- kernel_includes += $(BOARD_KERNEL_HEADER_DIR)
+ common_deps += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr
+ kernel_includes += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include
endif
-
-common_clang_flags := true
diff --git a/msm8909/gpu_tonemapper/Android.mk b/msm8909/gpu_tonemapper/Android.mk
new file mode 100644
index 00000000..77ecc4a3
--- /dev/null
+++ b/msm8909/gpu_tonemapper/Android.mk
@@ -0,0 +1,27 @@
+LOCAL_PATH := $(call my-dir)
+include $(LOCAL_PATH)/../common.mk
+
+include $(CLEAR_VARS)
+LOCAL_COPY_HEADERS_TO := $(common_header_export_path)
+LOCAL_COPY_HEADERS := TonemapFactory.h Tonemapper.h
+include $(BUILD_COPY_HEADERS)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := libgpu_tonemapper
+LOCAL_VENDOR_MODULE := true
+LOCAL_MODULE_TAGS := optional
+LOCAL_C_INCLUDES := $(TARGET_OUT_HEADERS)/qcom/display/
+LOCAL_C_INCLUDES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include
+LOCAL_SHARED_LIBRARIES := libEGL libGLESv2 libGLESv3 libui libutils liblog
+LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps) $(kernel_deps)
+
+LOCAL_CFLAGS := $(version_flag) -Wno-missing-field-initializers -Wall \
+ -Wno-unused-parameter -std=c++11 -DLOG_TAG=\"GPU_TONEMAPPER\"
+
+LOCAL_SRC_FILES := TonemapFactory.cpp \
+ glengine.cpp \
+ EGLImageBuffer.cpp \
+ EGLImageWrapper.cpp \
+ Tonemapper.cpp
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/msm8909/gpu_tonemapper/EGLImageBuffer.cpp b/msm8909/gpu_tonemapper/EGLImageBuffer.cpp
new file mode 100644
index 00000000..eeb02733
--- /dev/null
+++ b/msm8909/gpu_tonemapper/EGLImageBuffer.cpp
@@ -0,0 +1,161 @@
+/*
+ * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+ * Not a Contribution.
+ *
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "EGLImageBuffer.h"
+#include <cutils/native_handle.h>
+#include <gralloc_priv.h>
+#include <ui/GraphicBuffer.h>
+#include <map>
+#include "EGLImageWrapper.h"
+#include "glengine.h"
+
+//-----------------------------------------------------------------------------
+EGLImageKHR create_eglImage(android::sp<android::GraphicBuffer> graphicBuffer)
+//-----------------------------------------------------------------------------
+{
+ bool isProtected = (graphicBuffer->getUsage() & GRALLOC_USAGE_PROTECTED);
+ EGLint attrs[] = {EGL_IMAGE_PRESERVED_KHR, EGL_TRUE,
+ isProtected ? EGL_PROTECTED_CONTENT_EXT : EGL_NONE,
+ isProtected ? EGL_TRUE : EGL_NONE, EGL_NONE};
+
+ EGLImageKHR eglImage = eglCreateImageKHR(
+ eglGetCurrentDisplay(), (EGLContext)EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID,
+ (EGLClientBuffer)(graphicBuffer->getNativeBuffer()), attrs);
+
+ return eglImage;
+}
+
+//-----------------------------------------------------------------------------
+EGLImageBuffer::EGLImageBuffer(android::sp<android::GraphicBuffer> graphicBuffer)
+//-----------------------------------------------------------------------------
+{
+ // this->graphicBuffer = graphicBuffer;
+ this->eglImageID = create_eglImage(graphicBuffer);
+ this->width = graphicBuffer->getWidth();
+ this->height = graphicBuffer->getHeight();
+
+ textureID = 0;
+ renderbufferID = 0;
+ framebufferID = 0;
+}
+
+//-----------------------------------------------------------------------------
+EGLImageBuffer::~EGLImageBuffer()
+//-----------------------------------------------------------------------------
+{
+ if (textureID != 0) {
+ GL(glDeleteTextures(1, &textureID));
+ textureID = 0;
+ }
+
+ if (renderbufferID != 0) {
+ GL(glDeleteRenderbuffers(1, &renderbufferID));
+ renderbufferID = 0;
+ }
+
+ if (framebufferID != 0) {
+ GL(glDeleteFramebuffers(1, &framebufferID));
+ framebufferID = 0;
+ }
+
+ // Delete the eglImage
+ if (eglImageID != 0)
+ {
+ eglDestroyImageKHR(eglGetCurrentDisplay(), eglImageID);
+ eglImageID = 0;
+ }
+}
+
+//-----------------------------------------------------------------------------
+int EGLImageBuffer::getWidth()
+//-----------------------------------------------------------------------------
+{
+ return width;
+}
+
+//-----------------------------------------------------------------------------
+int EGLImageBuffer::getHeight()
+//-----------------------------------------------------------------------------
+{
+ return height;
+}
+
+//-----------------------------------------------------------------------------
+unsigned int EGLImageBuffer::getTexture()
+//-----------------------------------------------------------------------------
+{
+ if (textureID == 0) {
+ bindAsTexture();
+ }
+
+ return textureID;
+}
+
+//-----------------------------------------------------------------------------
+unsigned int EGLImageBuffer::getFramebuffer()
+//-----------------------------------------------------------------------------
+{
+ if (framebufferID == 0) {
+ bindAsFramebuffer();
+ }
+
+ return framebufferID;
+}
+
+//-----------------------------------------------------------------------------
+void EGLImageBuffer::bindAsTexture()
+//-----------------------------------------------------------------------------
+{
+ if (textureID == 0) {
+ GL(glGenTextures(1, &textureID));
+ int target = 0x8D65;
+ GL(glBindTexture(target, textureID));
+ GL(glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
+ GL(glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
+ GL(glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
+ GL(glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
+
+ GL(glEGLImageTargetTexture2DOES(0x8D65, eglImageID));
+ }
+
+ GL(glBindTexture(0x8D65, textureID));
+}
+
+//-----------------------------------------------------------------------------
+void EGLImageBuffer::bindAsFramebuffer()
+//-----------------------------------------------------------------------------
+{
+ if (renderbufferID == 0) {
+ GL(glGenFramebuffers(1, &framebufferID));
+ GL(glGenRenderbuffers(1, &renderbufferID));
+
+ GL(glBindRenderbuffer(GL_RENDERBUFFER, renderbufferID));
+ GL(glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER, eglImageID));
+
+ GL(glBindFramebuffer(GL_FRAMEBUFFER, framebufferID));
+ GL(glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
+ renderbufferID));
+ GLenum result = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+ if (result != GL_FRAMEBUFFER_COMPLETE) {
+ ALOGI("%s Framebuffer Invalid***************", __FUNCTION__);
+ }
+ }
+
+ GL(glBindFramebuffer(GL_FRAMEBUFFER, framebufferID));
+}
diff --git a/msm8909/gpu_tonemapper/EGLImageBuffer.h b/msm8909/gpu_tonemapper/EGLImageBuffer.h
new file mode 100644
index 00000000..23af5732
--- /dev/null
+++ b/msm8909/gpu_tonemapper/EGLImageBuffer.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ * Not a Contribution.
+ *
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __EGLIMAGE_BUFFER_H__
+#define __EGLIMAGE_BUFFER_H__
+
+#include <cutils/native_handle.h>
+#include <gralloc_priv.h>
+#include <ui/GraphicBuffer.h>
+#include "engine.h"
+
+class EGLImageBuffer {
+ // android::sp<android::GraphicBuffer> graphicBuffer;
+ void *eglImageID;
+ int width;
+ int height;
+ uint textureID;
+ uint renderbufferID;
+ uint framebufferID;
+
+ public:
+ int getWidth();
+ int getHeight();
+ EGLImageBuffer(android::sp<android::GraphicBuffer>);
+ unsigned int getTexture();
+ unsigned int getFramebuffer();
+ void bindAsTexture();
+ void bindAsFramebuffer();
+ ~EGLImageBuffer();
+ static EGLImageBuffer *from(const private_handle_t *src);
+ static void clear();
+};
+
+#endif //__EGLIMAGE_BUFFER_H__ \ No newline at end of file
diff --git a/msm8909/gpu_tonemapper/EGLImageWrapper.cpp b/msm8909/gpu_tonemapper/EGLImageWrapper.cpp
new file mode 100644
index 00000000..dfc16d84
--- /dev/null
+++ b/msm8909/gpu_tonemapper/EGLImageWrapper.cpp
@@ -0,0 +1,154 @@
+/*
+ * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+ * Not a Contribution.
+ *
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "EGLImageWrapper.h"
+#include <cutils/native_handle.h>
+#include <gralloc_priv.h>
+#include <ui/GraphicBuffer.h>
+#include <fcntl.h>
+#include <linux/msm_ion.h>
+
+//-----------------------------------------------------------------------------
+void free_ion_cookie(int ion_fd, int cookie)
+//-----------------------------------------------------------------------------
+{
+ if (ion_fd && !ioctl(ion_fd, ION_IOC_FREE, &cookie)) {
+ } else {
+ ALOGE("ION_IOC_FREE failed: ion_fd = %d, cookie = %d", ion_fd, cookie);
+ }
+}
+
+//-----------------------------------------------------------------------------
+int get_ion_cookie(int ion_fd, int fd)
+//-----------------------------------------------------------------------------
+{
+ int cookie = fd;
+
+ struct ion_fd_data fdData;
+ memset(&fdData, 0, sizeof(fdData));
+ fdData.fd = fd;
+
+ if (ion_fd && !ioctl(ion_fd, ION_IOC_IMPORT, &fdData)) {
+ cookie = fdData.handle;
+ } else {
+ ALOGE("ION_IOC_IMPORT failed: ion_fd = %d, fd = %d", ion_fd, fd);
+ }
+
+ return cookie;
+}
+
+//-----------------------------------------------------------------------------
+EGLImageWrapper::DeleteEGLImageCallback::DeleteEGLImageCallback(int fd)
+//-----------------------------------------------------------------------------
+{
+ ion_fd = fd;
+}
+
+//-----------------------------------------------------------------------------
+void EGLImageWrapper::DeleteEGLImageCallback::operator()(int& k, EGLImageBuffer*& eglImage)
+//-----------------------------------------------------------------------------
+{
+ free_ion_cookie(ion_fd, k);
+ if( eglImage != 0 )
+ {
+ delete eglImage;
+ }
+}
+
+//-----------------------------------------------------------------------------
+EGLImageWrapper::EGLImageWrapper()
+//-----------------------------------------------------------------------------
+{
+ eglImageBufferMap = new android::LruCache<int, EGLImageBuffer*>(32);
+ ion_fd = open("/dev/ion", O_RDONLY);
+ callback = new DeleteEGLImageCallback(ion_fd);
+ eglImageBufferMap->setOnEntryRemovedListener(callback);
+}
+
+//-----------------------------------------------------------------------------
+EGLImageWrapper::~EGLImageWrapper()
+//-----------------------------------------------------------------------------
+{
+ if( eglImageBufferMap != 0 )
+ {
+ eglImageBufferMap->clear();
+ delete eglImageBufferMap;
+ eglImageBufferMap = 0;
+ }
+
+ if( callback != 0 )
+ {
+ delete callback;
+ callback = 0;
+ }
+
+ if( ion_fd > 0 )
+ {
+ close(ion_fd);
+ }
+ ion_fd = -1;
+}
+//-----------------------------------------------------------------------------
+static EGLImageBuffer* L_wrap(const private_handle_t *src)
+//-----------------------------------------------------------------------------
+{
+ EGLImageBuffer* result = 0;
+
+ native_handle_t *native_handle = const_cast<private_handle_t *>(src);
+
+ int flags = android::GraphicBuffer::USAGE_HW_TEXTURE |
+ android::GraphicBuffer::USAGE_SW_READ_NEVER |
+ android::GraphicBuffer::USAGE_SW_WRITE_NEVER;
+
+ if (src->flags & private_handle_t::PRIV_FLAGS_SECURE_BUFFER) {
+ flags |= android::GraphicBuffer::USAGE_PROTECTED;
+ }
+
+ android::sp<android::GraphicBuffer> graphicBuffer =
+ new android::GraphicBuffer(src->unaligned_width, src->unaligned_height, src->format,
+#ifndef __NOUGAT__
+ 1, // Layer count
+#endif
+ flags, src->width /*src->stride*/,
+ native_handle, false);
+
+ result = new EGLImageBuffer(graphicBuffer);
+
+ return result;
+}
+
+//-----------------------------------------------------------------------------
+EGLImageBuffer *EGLImageWrapper::wrap(const void *pvt_handle)
+//-----------------------------------------------------------------------------
+{
+ const private_handle_t *src = static_cast<const private_handle_t *>(pvt_handle);
+
+ int ion_cookie = get_ion_cookie(ion_fd, src->fd);
+ EGLImageBuffer* eglImage = eglImageBufferMap->get(ion_cookie);
+ if( eglImage == 0 )
+ {
+ eglImage = L_wrap(src);
+ eglImageBufferMap->put(ion_cookie, eglImage);
+ }
+ else {
+ free_ion_cookie(ion_fd, ion_cookie);
+ }
+
+ return eglImage;
+}
diff --git a/msm8909/gpu_tonemapper/EGLImageWrapper.h b/msm8909/gpu_tonemapper/EGLImageWrapper.h
new file mode 100644
index 00000000..e9a4d68f
--- /dev/null
+++ b/msm8909/gpu_tonemapper/EGLImageWrapper.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+ * Not a Contribution.
+ *
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __TONEMAPPER_EGLIMAGEWRAPPER_H__
+#define __TONEMAPPER_EGLIMAGEWRAPPER_H__
+
+#include <utils/LruCache.h>
+#include "EGLImageBuffer.h"
+
+class EGLImageWrapper {
+ private:
+ class DeleteEGLImageCallback : public android::OnEntryRemoved<int, EGLImageBuffer*>
+ {
+ private:
+ int ion_fd;
+ public:
+ DeleteEGLImageCallback(int ion_fd);
+ void operator()(int& ion_cookie, EGLImageBuffer*& eglImage);
+ };
+
+ android::LruCache<int, EGLImageBuffer *>* eglImageBufferMap;
+ DeleteEGLImageCallback* callback;
+ int ion_fd;
+
+ public:
+ EGLImageWrapper();
+ ~EGLImageWrapper();
+ EGLImageBuffer* wrap(const void *pvt_handle);
+};
+
+#endif //__TONEMAPPER_EGLIMAGEWRAPPER_H__
diff --git a/msm8909/gpu_tonemapper/TonemapFactory.cpp b/msm8909/gpu_tonemapper/TonemapFactory.cpp
new file mode 100644
index 00000000..db4b8be6
--- /dev/null
+++ b/msm8909/gpu_tonemapper/TonemapFactory.cpp
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+ * Not a Contribution.
+ *
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "TonemapFactory.h"
+#include <log/log.h>
+#include "Tonemapper.h"
+#include "engine.h"
+
+//----------------------------------------------------------------------------------------------------------------------------------------------------------
+Tonemapper *TonemapperFactory_GetInstance(int type, void *colorMap, int colorMapSize,
+ void *lutXform, int lutXformSize, bool isSecure)
+//----------------------------------------------------------------------------------------------------------------------------------------------------------
+{
+ // build the tonemapper
+ Tonemapper *tonemapper = Tonemapper::build(type, colorMap, colorMapSize, lutXform, lutXformSize, isSecure);
+
+ return tonemapper;
+}
diff --git a/msm8909/gpu_tonemapper/TonemapFactory.h b/msm8909/gpu_tonemapper/TonemapFactory.h
new file mode 100644
index 00000000..17cad400
--- /dev/null
+++ b/msm8909/gpu_tonemapper/TonemapFactory.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ * Not a Contribution.
+ *
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __TONEMAPPER_TONEMAPPERFACTORY_H__
+#define __TONEMAPPER_TONEMAPPERFACTORY_H__
+
+#include "Tonemapper.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// returns an instance of Tonemapper
+Tonemapper *TonemapperFactory_GetInstance(int type, void *colorMap, int colorMapSize,
+ void *lutXform, int lutXformSize, bool isSecure);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //__TONEMAPPER_TONEMAPPERFACTORY_H__
diff --git a/msm8909/gpu_tonemapper/Tonemapper.cpp b/msm8909/gpu_tonemapper/Tonemapper.cpp
new file mode 100644
index 00000000..811e091a
--- /dev/null
+++ b/msm8909/gpu_tonemapper/Tonemapper.cpp
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+ * Not a Contribution.
+ *
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <utils/Log.h>
+
+#include "EGLImageWrapper.h"
+#include "Tonemapper.h"
+#include "engine.h"
+#include "forward_tonemap.inl"
+#include "fullscreen_vertex_shader.inl"
+#include "rgba_inverse_tonemap.inl"
+
+//-----------------------------------------------------------------------------
+Tonemapper::Tonemapper()
+//-----------------------------------------------------------------------------
+{
+ tonemapTexture = 0;
+ lutXformTexture = 0;
+ programID = 0;
+ eglImageWrapper = new EGLImageWrapper();
+
+ lutXformScaleOffset[0] = 1.0f;
+ lutXformScaleOffset[1] = 0.0f;
+
+ tonemapScaleOffset[0] = 1.0f;
+ tonemapScaleOffset[1] = 0.0f;
+}
+
+//-----------------------------------------------------------------------------
+Tonemapper::~Tonemapper()
+//-----------------------------------------------------------------------------
+{
+ engine_bind(engineContext);
+ engine_deleteInputBuffer(tonemapTexture);
+ engine_deleteInputBuffer(lutXformTexture);
+ engine_deleteProgram(programID);
+
+ // clear EGLImage mappings
+ if (eglImageWrapper != 0) {
+ delete eglImageWrapper;
+ eglImageWrapper = 0;
+ }
+
+ engine_shutdown(engineContext);
+}
+
+//-----------------------------------------------------------------------------
+Tonemapper *Tonemapper::build(int type, void *colorMap, int colorMapSize, void *lutXform,
+ int lutXformSize, bool isSecure)
+//-----------------------------------------------------------------------------
+{
+ if (colorMapSize <= 0) {
+ ALOGE("Invalid Color Map size = %d", colorMapSize);
+ return NULL;
+ }
+
+ // build new tonemapper
+ Tonemapper *tonemapper = new Tonemapper();
+
+ tonemapper->engineContext = engine_initialize(isSecure);
+
+ engine_bind(tonemapper->engineContext);
+
+ // load the 3d lut
+ tonemapper->tonemapTexture = engine_load3DTexture(colorMap, colorMapSize, 0);
+ tonemapper->tonemapScaleOffset[0] = ((float)(colorMapSize-1))/((float)(colorMapSize));
+ tonemapper->tonemapScaleOffset[1] = 1.0f/(2.0f*colorMapSize);
+
+ // load the non-uniform xform
+ tonemapper->lutXformTexture = engine_load1DTexture(lutXform, lutXformSize, 0);
+ bool bUseXform = (tonemapper->lutXformTexture != 0) && (lutXformSize != 0);
+ if( bUseXform )
+ {
+ tonemapper->lutXformScaleOffset[0] = ((float)(lutXformSize-1))/((float)(lutXformSize));
+ tonemapper->lutXformScaleOffset[1] = 1.0f/(2.0f*lutXformSize);
+ }
+
+ // create the program
+ const char *fragmentShaders[3];
+ int fragmentShaderCount = 0;
+ const char *version = "#version 300 es\n";
+ const char *define = "#define USE_NONUNIFORM_SAMPLING\n";
+
+ fragmentShaders[fragmentShaderCount++] = version;
+
+ // non-uniform sampling
+ if (bUseXform) {
+ fragmentShaders[fragmentShaderCount++] = define;
+ }
+
+ if (type == TONEMAP_INVERSE) { // inverse tonemapping
+ fragmentShaders[fragmentShaderCount++] = rgba_inverse_tonemap_shader;
+ } else { // forward tonemapping
+ fragmentShaders[fragmentShaderCount++] = forward_tonemap_shader;
+ }
+
+ tonemapper->programID =
+ engine_loadProgram(1, &fullscreen_vertex_shader, fragmentShaderCount, fragmentShaders);
+
+ return tonemapper;
+}
+
+//-----------------------------------------------------------------------------
+int Tonemapper::blit(const void *dst, const void *src, int srcFenceFd)
+//-----------------------------------------------------------------------------
+{
+ // make current
+ engine_bind(engineContext);
+
+ // create eglimages if required
+ EGLImageBuffer *dst_buffer = eglImageWrapper->wrap(dst);
+ EGLImageBuffer *src_buffer = eglImageWrapper->wrap(src);
+
+ // bind the program
+ engine_setProgram(programID);
+
+ engine_setData2f(3, tonemapScaleOffset);
+ bool bUseXform = (lutXformTexture != 0);
+ if( bUseXform )
+ {
+ engine_setData2f(4, lutXformScaleOffset);
+ }
+
+ // set destination
+ engine_setDestination(dst_buffer->getFramebuffer(), 0, 0, dst_buffer->getWidth(),
+ dst_buffer->getHeight());
+ // set source
+ engine_setExternalInputBuffer(0, src_buffer->getTexture());
+ // set 3d lut
+ engine_set3DInputBuffer(1, tonemapTexture);
+ // set non-uniform xform
+ engine_set2DInputBuffer(2, lutXformTexture);
+
+ // perform
+ int fenceFD = engine_blit(srcFenceFd);
+
+ return fenceFD;
+}
diff --git a/msm8909/gpu_tonemapper/Tonemapper.h b/msm8909/gpu_tonemapper/Tonemapper.h
new file mode 100644
index 00000000..707cdfe6
--- /dev/null
+++ b/msm8909/gpu_tonemapper/Tonemapper.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+ * Not a Contribution.
+ *
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __TONEMAPPER_TONEMAP_H__
+#define __TONEMAPPER_TONEMAP_H__
+
+#define TONEMAP_FORWARD 0
+#define TONEMAP_INVERSE 1
+
+#include "EGLImageWrapper.h"
+#include "engine.h"
+
+class Tonemapper {
+ private:
+ void* engineContext;
+ unsigned int tonemapTexture;
+ unsigned int lutXformTexture;
+ unsigned int programID;
+ float lutXformScaleOffset[2];
+ float tonemapScaleOffset[2];
+ EGLImageWrapper* eglImageWrapper;
+ Tonemapper();
+
+ public:
+ ~Tonemapper();
+ static Tonemapper *build(int type, void *colorMap, int colorMapSize, void *lutXform,
+ int lutXformSize, bool isSecure);
+ int blit(const void *dst, const void *src, int srcFenceFd);
+};
+
+#endif //__TONEMAPPER_TONEMAP_H__
diff --git a/msm8909/gpu_tonemapper/engine.h b/msm8909/gpu_tonemapper/engine.h
new file mode 100644
index 00000000..8fb9452f
--- /dev/null
+++ b/msm8909/gpu_tonemapper/engine.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+ * Not a Contribution.
+ *
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __TONEMAPPER_ENGINE_H__
+#define __TONEMAPPER_ENGINE_H__
+
+void* engine_initialize(bool isSecure);
+void engine_bind(void*);
+void engine_shutdown(void*);
+
+unsigned int engine_loadProgram(int, const char **, int, const char **);
+void engine_setProgram(int);
+void engine_deleteProgram(unsigned int);
+
+unsigned int engine_load3DTexture(void *data, int sz, int format);
+unsigned int engine_load1DTexture(void *xform, int xformSize, int format);
+void engine_deleteInputBuffer(unsigned int);
+
+void engine_set2DInputBuffer(int binding, unsigned int textureID);
+void engine_set3DInputBuffer(int binding, unsigned int textureID);
+void engine_setExternalInputBuffer(int binding, unsigned int textureID);
+void engine_setDestination(int id, int x, int y, int w, int h);
+void engine_setData2f(int loc, float* data);
+
+int engine_blit(int);
+
+#endif //__TONEMAPPER_ENGINE_H__
diff --git a/msm8909/gpu_tonemapper/forward_tonemap.inl b/msm8909/gpu_tonemapper/forward_tonemap.inl
new file mode 100644
index 00000000..0d89a9ea
--- /dev/null
+++ b/msm8909/gpu_tonemapper/forward_tonemap.inl
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+ * Not a Contribution.
+ *
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+const char* forward_tonemap_shader = ""
+ "#extension GL_OES_EGL_image_external_essl3 : require \n"
+ "precision highp float; \n"
+ "precision highp sampler2D; \n"
+ "layout(binding = 0) uniform samplerExternalOES externalTexture; \n"
+ "layout(binding = 1) uniform sampler3D tonemapper; \n"
+ "layout(binding = 2) uniform sampler2D xform; \n"
+ "layout(location = 3) uniform vec2 tSO; \n"
+ "#ifdef USE_NONUNIFORM_SAMPLING \n"
+ "layout(location = 4) uniform vec2 xSO; \n"
+ "#endif \n"
+ "in vec2 uv; \n"
+ "out vec4 fs_color; \n"
+ " \n"
+ "vec3 ScaleOffset(in vec3 samplePt, in vec2 so) \n"
+ "{ \n"
+ " vec3 adjPt = so.x * samplePt + so.y; \n"
+ " return adjPt; \n"
+ "} \n"
+ " \n"
+ "void main() \n"
+ "{ \n"
+ "vec2 flipped = vec2(uv.x, 1.0f - uv.y); \n"
+ "vec4 rgb = texture(externalTexture, flipped); \n"
+ "#ifdef USE_NONUNIFORM_SAMPLING \n"
+ "vec3 adj = ScaleOffset(rgb.xyz, xSO); \n"
+ "float r = texture(xform, vec2(adj.r, 0.5f)).r; \n"
+ "float g = texture(xform, vec2(adj.g, 0.5f)).g; \n"
+ "float b = texture(xform, vec2(adj.b, 0.5f)).b; \n"
+ "#else \n"
+ "float r = rgb.r; \n"
+ "float g = rgb.g; \n"
+ "float b = rgb.b; \n"
+ "#endif \n"
+ "fs_color.rgb = texture(tonemapper, ScaleOffset(vec3(r, g, b), tSO)).rgb; \n"
+ "} \n";
diff --git a/msm8909/gpu_tonemapper/fullscreen_vertex_shader.inl b/msm8909/gpu_tonemapper/fullscreen_vertex_shader.inl
new file mode 100644
index 00000000..9a70c2b3
--- /dev/null
+++ b/msm8909/gpu_tonemapper/fullscreen_vertex_shader.inl
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ * Not a Contribution.
+ *
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+const char* fullscreen_vertex_shader = " "
+"#version 300 es \n"
+"precision highp float; \n"
+"layout(location = 0) in vec2 iUV; \n"
+"out vec2 uv; \n"
+"void main() \n"
+"{ \n"
+" vec2 positions[3]; \n"
+" positions[0] = vec2(-1.0f, 3.0f); \n"
+" positions[1] = vec2(-1.0f, -1.0f); \n"
+" positions[2] = vec2(3.0f, -1.0f); \n"
+" vec2 uvs[3]; \n"
+" uvs[0] = vec2(0.0f, -1.0f); \n"
+" uvs[1] = vec2(0.0f, 1.0f); \n"
+" uvs[2] = vec2(2.0f, 1.0f); \n"
+" gl_Position = vec4(positions[gl_VertexID], -1.0f, 1.0f); \n"
+" uv = uvs[gl_VertexID]; \n"
+"} \n";
diff --git a/msm8909/gpu_tonemapper/glengine.cpp b/msm8909/gpu_tonemapper/glengine.cpp
new file mode 100644
index 00000000..35e1932c
--- /dev/null
+++ b/msm8909/gpu_tonemapper/glengine.cpp
@@ -0,0 +1,415 @@
+/*
+ * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+ * Not a Contribution.
+ *
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "glengine.h"
+#include <log/log.h>
+#include "engine.h"
+
+void checkGlError(const char *, int);
+void checkEglError(const char *, int);
+
+class EngineContext {
+ public:
+ EGLDisplay eglDisplay;
+ EGLContext eglContext;
+ EGLSurface eglSurface;
+ EngineContext()
+ {
+ eglDisplay = EGL_NO_DISPLAY;
+ eglContext = EGL_NO_CONTEXT;
+ eglSurface = EGL_NO_SURFACE;
+ }
+};
+
+//-----------------------------------------------------------------------------
+// Make Current
+void engine_bind(void* context)
+//-----------------------------------------------------------------------------
+{
+ EngineContext* engineContext = (EngineContext*)(context);
+ EGL(eglMakeCurrent(engineContext->eglDisplay, engineContext->eglSurface, engineContext->eglSurface, engineContext->eglContext));
+}
+
+//-----------------------------------------------------------------------------
+// initialize GL
+//
+void* engine_initialize(bool isSecure)
+//-----------------------------------------------------------------------------
+{
+ EngineContext* engineContext = new EngineContext();
+
+ // display
+ engineContext->eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+ EGL(eglBindAPI(EGL_OPENGL_ES_API));
+
+ // initialize
+ EGL(eglInitialize(engineContext->eglDisplay, 0, 0));
+
+ // config
+ EGLConfig eglConfig;
+ EGLint eglConfigAttribList[] = {EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
+ EGL_RED_SIZE, 8,
+ EGL_GREEN_SIZE, 8,
+ EGL_BLUE_SIZE, 8,
+ EGL_ALPHA_SIZE, 8,
+ EGL_NONE};
+ int numConfig = 0;
+ EGL(eglChooseConfig(engineContext->eglDisplay, eglConfigAttribList, &eglConfig, 1, &numConfig));
+
+ // context
+ EGLint eglContextAttribList[] = {EGL_CONTEXT_CLIENT_VERSION, 3,
+ isSecure ? EGL_PROTECTED_CONTENT_EXT : EGL_NONE,
+ isSecure ? EGL_TRUE : EGL_NONE,
+ EGL_NONE};
+ engineContext->eglContext = eglCreateContext(engineContext->eglDisplay, eglConfig, NULL, eglContextAttribList);
+
+ // surface
+ EGLint eglSurfaceAttribList[] = {EGL_WIDTH, 1,
+ EGL_HEIGHT, 1,
+ isSecure ? EGL_PROTECTED_CONTENT_EXT : EGL_NONE,
+ isSecure ? EGL_TRUE : EGL_NONE,
+ EGL_NONE};
+ engineContext->eglSurface = eglCreatePbufferSurface(engineContext->eglDisplay, eglConfig, eglSurfaceAttribList);
+
+ eglMakeCurrent(engineContext->eglDisplay, engineContext->eglSurface, engineContext->eglSurface, engineContext->eglContext);
+
+ ALOGI("In %s context = %p", __FUNCTION__, (void *)(engineContext->eglContext));
+
+ return (void*)(engineContext);
+}
+
+//-----------------------------------------------------------------------------
+// Shutdown.
+void engine_shutdown(void* context)
+//-----------------------------------------------------------------------------
+{
+ EngineContext* engineContext = (EngineContext*)context;
+ EGL(eglMakeCurrent(engineContext->eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));
+ EGL(eglDestroySurface(engineContext->eglDisplay, engineContext->eglSurface));
+ EGL(eglDestroyContext(engineContext->eglDisplay, engineContext->eglContext));
+ EGL(eglTerminate(engineContext->eglDisplay));
+ engineContext->eglDisplay = EGL_NO_DISPLAY;
+ engineContext->eglContext = EGL_NO_CONTEXT;
+ engineContext->eglSurface = EGL_NO_SURFACE;
+}
+
+//-----------------------------------------------------------------------------
+void engine_deleteInputBuffer(unsigned int id)
+//-----------------------------------------------------------------------------
+{
+ if (id != 0) {
+ GL(glDeleteTextures(1, &id));
+ }
+}
+
+//-----------------------------------------------------------------------------
+void engine_deleteProgram(unsigned int id)
+//-----------------------------------------------------------------------------
+{
+ if (id != 0) {
+ GL(glDeleteProgram(id));
+ }
+}
+
+//-----------------------------------------------------------------------------
+void engine_setData2f(int location, float* data)
+//-----------------------------------------------------------------------------
+{
+ GL(glUniform2f(location, data[0], data[1]));
+}
+
+//-----------------------------------------------------------------------------
+unsigned int engine_load3DTexture(void *colorMapData, int sz, int format)
+//-----------------------------------------------------------------------------
+{
+ GLuint texture = 0;
+ GL(glGenTextures(1, &texture));
+ GL(glBindTexture(GL_TEXTURE_3D, texture));
+ GL(glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
+ GL(glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
+ GL(glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE));
+ GL(glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
+ GL(glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
+
+ GL(glTexImage3D(GL_TEXTURE_3D, 0, GL_RGB10_A2, sz, sz, sz, 0, GL_RGBA,
+ GL_UNSIGNED_INT_2_10_10_10_REV, colorMapData));
+
+ return texture;
+}
+//-----------------------------------------------------------------------------
+unsigned int engine_load1DTexture(void *data, int sz, int format)
+//-----------------------------------------------------------------------------
+{
+ GLuint texture = 0;
+ if ((data != 0) && (sz != 0)) {
+ GL(glGenTextures(1, &texture));
+ GL(glBindTexture(GL_TEXTURE_2D, texture));
+ GL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
+ GL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
+ GL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
+ GL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
+
+ GL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB10_A2, sz, 1, 0, GL_RGBA,
+ GL_UNSIGNED_INT_2_10_10_10_REV, data));
+ }
+ return texture;
+}
+
+//-----------------------------------------------------------------------------
+void dumpShaderLog(int shader)
+//-----------------------------------------------------------------------------
+{
+ int success = 0;
+ GLchar infoLog[512];
+ GL(glGetShaderiv(shader, GL_COMPILE_STATUS, &success));
+ if (!success) {
+ glGetShaderInfoLog(shader, 512, NULL, infoLog);
+ ALOGI("Shader Failed to compile: %s\n", infoLog);
+ }
+}
+
+//-----------------------------------------------------------------------------
+GLuint engine_loadProgram(int vertexEntries, const char **vertex, int fragmentEntries,
+ const char **fragment)
+//-----------------------------------------------------------------------------
+{
+ GLuint progId = glCreateProgram();
+
+ int vertId = glCreateShader(GL_VERTEX_SHADER);
+ int fragId = glCreateShader(GL_FRAGMENT_SHADER);
+
+ GL(glShaderSource(vertId, vertexEntries, vertex, 0));
+ GL(glCompileShader(vertId));
+ dumpShaderLog(vertId);
+
+ GL(glShaderSource(fragId, fragmentEntries, fragment, 0));
+ GL(glCompileShader(fragId));
+ dumpShaderLog(fragId);
+
+ GL(glAttachShader(progId, vertId));
+ GL(glAttachShader(progId, fragId));
+
+ GL(glLinkProgram(progId));
+
+ GL(glDetachShader(progId, vertId));
+ GL(glDetachShader(progId, fragId));
+
+ GL(glDeleteShader(vertId));
+ GL(glDeleteShader(fragId));
+
+ return progId;
+}
+
+//-----------------------------------------------------------------------------
+void WaitOnNativeFence(int fd)
+//-----------------------------------------------------------------------------
+{
+ if (fd != -1) {
+ EGLint attribs[] = {EGL_SYNC_NATIVE_FENCE_FD_ANDROID, fd, EGL_NONE};
+
+ EGLSyncKHR sync = eglCreateSyncKHR(eglGetCurrentDisplay(), EGL_SYNC_NATIVE_FENCE_ANDROID, attribs);
+
+ if (sync == EGL_NO_SYNC_KHR) {
+ ALOGE("%s - Failed to Create sync from source fd", __FUNCTION__);
+ } else {
+ // the gpu will wait for this sync - not this cpu thread.
+ EGL(eglWaitSyncKHR(eglGetCurrentDisplay(), sync, 0));
+ EGL(eglDestroySyncKHR(eglGetCurrentDisplay(), sync));
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+int CreateNativeFence()
+//-----------------------------------------------------------------------------
+{
+ int fd = -1;
+
+ EGLSyncKHR sync = eglCreateSyncKHR(eglGetCurrentDisplay(), EGL_SYNC_NATIVE_FENCE_ANDROID, NULL);
+ GL(glFlush());
+ if (sync == EGL_NO_SYNC_KHR) {
+ ALOGE("%s - Failed to Create Native Fence sync", __FUNCTION__);
+ } else {
+ fd = eglDupNativeFenceFDANDROID(eglGetCurrentDisplay(), sync);
+ if (fd == EGL_NO_NATIVE_FENCE_FD_ANDROID) {
+ ALOGE("%s - Failed to dup sync", __FUNCTION__);
+ }
+ EGL(eglDestroySyncKHR(eglGetCurrentDisplay(), sync));
+ }
+
+ return fd;
+}
+
+//-----------------------------------------------------------------------------
+void engine_setDestination(int id, int x, int y, int w, int h)
+//-----------------------------------------------------------------------------
+{
+ GL(glBindFramebuffer(GL_FRAMEBUFFER, id));
+ GL(glViewport(x, y, w, h));
+}
+
+//-----------------------------------------------------------------------------
+void engine_setProgram(int id)
+//-----------------------------------------------------------------------------
+{
+ GL(glUseProgram(id));
+}
+
+//-----------------------------------------------------------------------------
+void engine_set2DInputBuffer(int binding, unsigned int id)
+//-----------------------------------------------------------------------------
+{
+ GL(glActiveTexture(GL_TEXTURE0 + binding));
+ GL(glBindTexture(GL_TEXTURE_2D, id));
+}
+
+//-----------------------------------------------------------------------------
+void engine_set3DInputBuffer(int binding, unsigned int id)
+//-----------------------------------------------------------------------------
+{
+ GL(glActiveTexture(GL_TEXTURE0 + binding));
+ GL(glBindTexture(GL_TEXTURE_3D, id));
+}
+
+//-----------------------------------------------------------------------------
+void engine_setExternalInputBuffer(int binding, unsigned int id)
+//-----------------------------------------------------------------------------
+{
+ GL(glActiveTexture(GL_TEXTURE0 + binding));
+ GL(glBindTexture(0x8D65, id));
+}
+
+//-----------------------------------------------------------------------------
+int engine_blit(int srcFenceFd)
+//-----------------------------------------------------------------------------
+{
+ int fd = -1;
+ WaitOnNativeFence(srcFenceFd);
+ float fullscreen_vertices[]{0.0f, 2.0f, 0.0f, 0.0f, 2.0f, 0.0f};
+ GL(glEnableVertexAttribArray(0));
+ GL(glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, fullscreen_vertices));
+ GL(glDrawArrays(GL_TRIANGLES, 0, 3));
+ fd = CreateNativeFence();
+ GL(glFlush());
+ return fd;
+}
+
+//-----------------------------------------------------------------------------
+void checkGlError(const char *file, int line)
+//-----------------------------------------------------------------------------
+{
+ for (GLint error = glGetError(); error; error = glGetError()) {
+ char *pError;
+ switch (error) {
+ case GL_NO_ERROR:
+ pError = (char *)"GL_NO_ERROR";
+ break;
+ case GL_INVALID_ENUM:
+ pError = (char *)"GL_INVALID_ENUM";
+ break;
+ case GL_INVALID_VALUE:
+ pError = (char *)"GL_INVALID_VALUE";
+ break;
+ case GL_INVALID_OPERATION:
+ pError = (char *)"GL_INVALID_OPERATION";
+ break;
+ case GL_OUT_OF_MEMORY:
+ pError = (char *)"GL_OUT_OF_MEMORY";
+ break;
+ case GL_INVALID_FRAMEBUFFER_OPERATION:
+ pError = (char *)"GL_INVALID_FRAMEBUFFER_OPERATION";
+ break;
+
+ default:
+ ALOGE("glError (0x%x) %s:%d\n", error, file, line);
+ return;
+ }
+
+ ALOGE("glError (%s) %s:%d\n", pError, file, line);
+ return;
+ }
+ return;
+}
+
+//-----------------------------------------------------------------------------
+void checkEglError(const char *file, int line)
+//-----------------------------------------------------------------------------
+{
+ for (int i = 0; i < 5; i++) {
+ const EGLint error = eglGetError();
+ if (error == EGL_SUCCESS) {
+ break;
+ }
+
+ char *pError;
+ switch (error) {
+ case EGL_SUCCESS:
+ pError = (char *)"EGL_SUCCESS";
+ break;
+ case EGL_NOT_INITIALIZED:
+ pError = (char *)"EGL_NOT_INITIALIZED";
+ break;
+ case EGL_BAD_ACCESS:
+ pError = (char *)"EGL_BAD_ACCESS";
+ break;
+ case EGL_BAD_ALLOC:
+ pError = (char *)"EGL_BAD_ALLOC";
+ break;
+ case EGL_BAD_ATTRIBUTE:
+ pError = (char *)"EGL_BAD_ATTRIBUTE";
+ break;
+ case EGL_BAD_CONTEXT:
+ pError = (char *)"EGL_BAD_CONTEXT";
+ break;
+ case EGL_BAD_CONFIG:
+ pError = (char *)"EGL_BAD_CONFIG";
+ break;
+ case EGL_BAD_CURRENT_SURFACE:
+ pError = (char *)"EGL_BAD_CURRENT_SURFACE";
+ break;
+ case EGL_BAD_DISPLAY:
+ pError = (char *)"EGL_BAD_DISPLAY";
+ break;
+ case EGL_BAD_SURFACE:
+ pError = (char *)"EGL_BAD_SURFACE";
+ break;
+ case EGL_BAD_MATCH:
+ pError = (char *)"EGL_BAD_MATCH";
+ break;
+ case EGL_BAD_PARAMETER:
+ pError = (char *)"EGL_BAD_PARAMETER";
+ break;
+ case EGL_BAD_NATIVE_PIXMAP:
+ pError = (char *)"EGL_BAD_NATIVE_PIXMAP";
+ break;
+ case EGL_BAD_NATIVE_WINDOW:
+ pError = (char *)"EGL_BAD_NATIVE_WINDOW";
+ break;
+ case EGL_CONTEXT_LOST:
+ pError = (char *)"EGL_CONTEXT_LOST";
+ break;
+ default:
+ ALOGE("eglError (0x%x) %s:%d\n", error, file, line);
+ return;
+ }
+ ALOGE("eglError (%s) %s:%d\n", pError, file, line);
+ return;
+ }
+ return;
+}
diff --git a/msm8909/gpu_tonemapper/glengine.h b/msm8909/gpu_tonemapper/glengine.h
new file mode 100644
index 00000000..f6aeec84
--- /dev/null
+++ b/msm8909/gpu_tonemapper/glengine.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ * Not a Contribution.
+ *
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __TONEMAPPER_GLENGINE_H__
+#define __TONEMAPPER_GLENGINE_H__
+#include <EGL/egl.h>
+#define EGL_EGLEXT_PROTOTYPES
+#include <EGL/eglext.h>
+#include <GLES3/gl31.h>
+#define GL_GLEXT_PROTOTYPES
+#include <GLES2/gl2ext.h>
+#include <GLES3/gl3ext.h>
+
+#if defined(CHECK_GL_ERRORS)
+#define GL(func) func;
+#define EGL(func) func;
+#else
+#define GL(func) \
+ func; \
+ checkGlError(__FILE__, __LINE__);
+#define EGL(func) \
+ func; \
+ checkEglError(__FILE__, __LINE__);
+#endif
+
+#define EGL_PROTECTED_CONTENT_EXT 0x32C0
+
+void checkGlError(const char *file, int line);
+void checkEglError(const char *file, int line);
+
+#endif //__TONEMAPPER_GLENGINE_H__
diff --git a/msm8909/gpu_tonemapper/rgba_inverse_tonemap.inl b/msm8909/gpu_tonemapper/rgba_inverse_tonemap.inl
new file mode 100644
index 00000000..2865fbe0
--- /dev/null
+++ b/msm8909/gpu_tonemapper/rgba_inverse_tonemap.inl
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+ * Not a Contribution.
+ *
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+const char* rgba_inverse_tonemap_shader = ""
+ "#extension GL_OES_EGL_image_external_essl3 : require \n"
+ "precision highp float; \n"
+ "precision highp sampler2D; \n"
+ "layout(binding = 0) uniform samplerExternalOES externalTexture; \n"
+ "layout(binding = 1) uniform sampler3D tonemapper; \n"
+ "layout(binding = 2) uniform sampler2D xform; \n"
+ "layout(location = 3) uniform vec2 tSO; \n"
+ "#if defined(USE_NONUNIFORM_SAMPLING) \n"
+ "layout(location = 4) uniform vec2 xSO; \n"
+ "#endif \n"
+ "in vec2 uv; \n"
+ "out vec4 fs_color; \n"
+ " \n"
+ "vec3 ScaleOffset(in vec3 samplePt, in vec2 so) \n"
+ "{ \n"
+ " vec3 adjPt = so.x * samplePt + so.y; \n"
+ " return adjPt; \n"
+ "} \n"
+ " \n"
+ "void main() \n"
+ "{ \n"
+ "vec2 flipped = vec2(uv.x, 1.0f - uv.y); \n"
+ "vec4 rgb_premulalpha = texture(externalTexture, flipped); \n"
+ "fs_color = rgb_premulalpha; \n"
+ "if( rgb_premulalpha.a > 0.0 ) { \n"
+ "vec3 rgb = rgb_premulalpha.rgb/rgb_premulalpha.a; \n"
+ "#if defined(USE_NONUNIFORM_SAMPLING) \n"
+ "vec3 adj = ScaleOffset(rgb.xyz, xSO); \n"
+ "float r = texture(xform, vec2(adj.r, 0.5f)).r; \n"
+ "float g = texture(xform, vec2(adj.g, 0.5f)).g; \n"
+ "float b = texture(xform, vec2(adj.b, 0.5f)).b; \n"
+ "#else \n"
+ "float r = rgb.r; \n"
+ "float g = rgb.g; \n"
+ "float b = rgb.b; \n"
+ "#endif \n"
+ "fs_color.rgb = texture(tonemapper, ScaleOffset(vec3(r, g, b), tSO)).rgb * rgb_premulalpha.a; \n"
+ "fs_color.a = rgb_premulalpha.a; \n"
+ "} \n"
+ "} \n";
diff --git a/msm8909/gralloc/Android.mk b/msm8909/gralloc/Android.mk
new file mode 100644
index 00000000..cdb651cf
--- /dev/null
+++ b/msm8909/gralloc/Android.mk
@@ -0,0 +1,38 @@
+# Gralloc module
+LOCAL_PATH := $(call my-dir)
+include $(LOCAL_PATH)/../common.mk
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := gralloc.$(TARGET_BOARD_PLATFORM)
+LOCAL_VENDOR_MODULE := true
+LOCAL_MODULE_RELATIVE_PATH := hw
+LOCAL_MODULE_TAGS := optional
+LOCAL_C_INCLUDES := $(common_includes) \
+ external/libcxx/include/
+
+LOCAL_HEADER_LIBRARIES := display_headers
+LOCAL_SHARED_LIBRARIES := $(common_libs) libqdMetaData libsync libgrallocutils
+LOCAL_CFLAGS := $(common_flags) -DLOG_TAG=\"qdgralloc\" -Wall -std=c++11 -Werror
+LOCAL_CFLAGS += -isystem $(kernel_includes)
+LOCAL_CLANG := true
+LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps) $(kernel_deps)
+LOCAL_SRC_FILES := gr_ion_alloc.cpp \
+ gr_allocator.cpp \
+ gr_buf_mgr.cpp \
+ gr_device_impl.cpp
+LOCAL_COPY_HEADERS_TO := $(common_header_export_path)
+LOCAL_COPY_HEADERS := gr_device_impl.h gralloc_priv.h gr_priv_handle.h
+include $(BUILD_SHARED_LIBRARY)
+
+#libgrallocutils
+include $(CLEAR_VARS)
+LOCAL_MODULE := libgrallocutils
+LOCAL_VENDOR_MODULE := true
+LOCAL_MODULE_TAGS := optional
+LOCAL_C_INCLUDES := $(common_includes) $(kernel_includes)
+LOCAL_HEADER_LIBRARIES := display_headers
+LOCAL_SHARED_LIBRARIES := $(common_libs) libqdMetaData libdl
+LOCAL_CFLAGS := $(common_flags) -DLOG_TAG=\"grallocutils\" -Wno-sign-conversion
+LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps) $(kernel_deps)
+LOCAL_SRC_FILES := gr_utils.cpp gr_adreno_info.cpp
+include $(BUILD_SHARED_LIBRARY)
diff --git a/msm8909/gralloc/gr_adreno_info.cpp b/msm8909/gralloc/gr_adreno_info.cpp
new file mode 100644
index 00000000..c681daaf
--- /dev/null
+++ b/msm8909/gralloc/gr_adreno_info.cpp
@@ -0,0 +1,214 @@
+/*
+ * Copyright (c) 2011-2018, The Linux Foundation. All rights reserved.
+
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <log/log.h>
+#include <cutils/properties.h>
+#include <dlfcn.h>
+#include <mutex>
+
+#include "gralloc_priv.h"
+#include "gr_adreno_info.h"
+#include "gr_utils.h"
+
+using std::lock_guard;
+using std::mutex;
+
+namespace gralloc1 {
+
+AdrenoMemInfo *AdrenoMemInfo::s_instance = nullptr;
+
+AdrenoMemInfo *AdrenoMemInfo::GetInstance() {
+ static mutex s_lock;
+ lock_guard<mutex> obj(s_lock);
+ if (!s_instance) {
+ s_instance = new AdrenoMemInfo();
+ }
+
+ return s_instance;
+}
+
+AdrenoMemInfo::AdrenoMemInfo() {
+ libadreno_utils_ = ::dlopen("libadreno_utils.so", RTLD_NOW);
+ if (libadreno_utils_) {
+ *reinterpret_cast<void **>(&LINK_adreno_compute_aligned_width_and_height) =
+ ::dlsym(libadreno_utils_, "compute_aligned_width_and_height");
+ *reinterpret_cast<void **>(&LINK_adreno_compute_padding) =
+ ::dlsym(libadreno_utils_, "compute_surface_padding");
+ *reinterpret_cast<void **>(&LINK_adreno_compute_compressedfmt_aligned_width_and_height) =
+ ::dlsym(libadreno_utils_, "compute_compressedfmt_aligned_width_and_height");
+ *reinterpret_cast<void **>(&LINK_adreno_isUBWCSupportedByGpu) =
+ ::dlsym(libadreno_utils_, "isUBWCSupportedByGpu");
+ *reinterpret_cast<void **>(&LINK_adreno_get_gpu_pixel_alignment) =
+ ::dlsym(libadreno_utils_, "get_gpu_pixel_alignment");
+ } else {
+ ALOGE(" Failed to load libadreno_utils.so");
+ }
+
+ // Check if the overriding property debug.gralloc.gfx_ubwc_disable
+ // that disables UBWC allocations for the graphics stack is set
+ char property[PROPERTY_VALUE_MAX];
+ property_get(DISABLE_UBWC_PROP, property, "0");
+ if (!(strncmp(property, "1", PROPERTY_VALUE_MAX)) ||
+ !(strncmp(property, "true", PROPERTY_VALUE_MAX))) {
+ gfx_ubwc_disable_ = true;
+ }
+
+ if ((property_get(MAP_FB_MEMORY_PROP, property, NULL) > 0) &&
+ (!strncmp(property, "1", PROPERTY_VALUE_MAX) ||
+ (!strncasecmp(property, "true", PROPERTY_VALUE_MAX)))) {
+ map_fb_ = true;
+ }
+}
+
+AdrenoMemInfo::~AdrenoMemInfo() {
+ if (libadreno_utils_) {
+ ::dlclose(libadreno_utils_);
+ }
+}
+
+void AdrenoMemInfo::AlignUnCompressedRGB(int width, int height, int format, int tile_enabled,
+ unsigned int *aligned_w, unsigned int *aligned_h) {
+ *aligned_w = (unsigned int)ALIGN(width, 32);
+ *aligned_h = (unsigned int)ALIGN(height, 32);
+
+ // Don't add any additional padding if debug.gralloc.map_fb_memory
+ // is enabled
+ if (map_fb_) {
+ return;
+ }
+
+ int bpp = 4;
+ switch (format) {
+ case HAL_PIXEL_FORMAT_RGB_888:
+ case HAL_PIXEL_FORMAT_BGR_888:
+ bpp = 3;
+ break;
+ case HAL_PIXEL_FORMAT_RGB_565:
+ case HAL_PIXEL_FORMAT_BGR_565:
+ case HAL_PIXEL_FORMAT_RGBA_5551:
+ case HAL_PIXEL_FORMAT_RGBA_4444:
+ bpp = 2;
+ break;
+ default:
+ break;
+ }
+
+ int raster_mode = 0; // Adreno unknown raster mode.
+ int padding_threshold = 512; // Threshold for padding surfaces.
+ // the function below computes aligned width and aligned height
+ // based on linear or macro tile mode selected.
+ if (LINK_adreno_compute_aligned_width_and_height) {
+ LINK_adreno_compute_aligned_width_and_height(
+ width, height, bpp, tile_enabled, raster_mode, padding_threshold,
+ reinterpret_cast<int *>(aligned_w), reinterpret_cast<int *>(aligned_h));
+ } else if (LINK_adreno_compute_padding) {
+ int surface_tile_height = 1; // Linear surface
+ *aligned_w = UINT(LINK_adreno_compute_padding(width, bpp, surface_tile_height, raster_mode,
+ padding_threshold));
+ ALOGW("%s: Warning!! Old GFX API is used to calculate stride", __FUNCTION__);
+ } else {
+ ALOGW(
+ "%s: Warning!! Symbols compute_surface_padding and "
+ "compute_aligned_width_and_height not found",
+ __FUNCTION__);
+ }
+}
+
+void AdrenoMemInfo::AlignCompressedRGB(int width, int height, int format, unsigned int *aligned_w,
+ unsigned int *aligned_h) {
+ if (LINK_adreno_compute_compressedfmt_aligned_width_and_height) {
+ int bytesPerPixel = 0;
+ int raster_mode = 0; // Adreno unknown raster mode.
+ int padding_threshold = 512; // Threshold for padding
+ // surfaces.
+
+ LINK_adreno_compute_compressedfmt_aligned_width_and_height(
+ width, height, format, 0, raster_mode, padding_threshold,
+ reinterpret_cast<int *>(aligned_w), reinterpret_cast<int *>(aligned_h), &bytesPerPixel);
+ } else {
+ *aligned_w = (unsigned int)ALIGN(width, 32);
+ *aligned_h = (unsigned int)ALIGN(height, 32);
+ ALOGW("%s: Warning!! compute_compressedfmt_aligned_width_and_height not found", __FUNCTION__);
+ }
+}
+
+bool AdrenoMemInfo::IsUBWCSupportedByGPU(int format) {
+ if (!gfx_ubwc_disable_ && LINK_adreno_isUBWCSupportedByGpu) {
+ ADRENOPIXELFORMAT gpu_format = GetGpuPixelFormat(format);
+ return LINK_adreno_isUBWCSupportedByGpu(gpu_format);
+ }
+
+ return false;
+}
+
+uint32_t AdrenoMemInfo::GetGpuPixelAlignment() {
+ if (LINK_adreno_get_gpu_pixel_alignment) {
+ return LINK_adreno_get_gpu_pixel_alignment();
+ }
+
+ return 1;
+}
+
+ADRENOPIXELFORMAT AdrenoMemInfo::GetGpuPixelFormat(int hal_format) {
+ switch (hal_format) {
+ case HAL_PIXEL_FORMAT_RGBA_8888:
+ return ADRENO_PIXELFORMAT_R8G8B8A8;
+ case HAL_PIXEL_FORMAT_RGBX_8888:
+ return ADRENO_PIXELFORMAT_R8G8B8X8;
+ case HAL_PIXEL_FORMAT_RGB_565:
+ return ADRENO_PIXELFORMAT_B5G6R5;
+ case HAL_PIXEL_FORMAT_BGR_565:
+ return ADRENO_PIXELFORMAT_R5G6B5;
+ case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
+ return ADRENO_PIXELFORMAT_NV12;
+ case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
+ case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC:
+ return ADRENO_PIXELFORMAT_NV12_EXT;
+ case HAL_PIXEL_FORMAT_YCbCr_420_TP10_UBWC:
+ return ADRENO_PIXELFORMAT_TP10;
+ case HAL_PIXEL_FORMAT_YCbCr_420_P010:
+ case HAL_PIXEL_FORMAT_YCbCr_420_P010_UBWC:
+ return ADRENO_PIXELFORMAT_P010;
+ case HAL_PIXEL_FORMAT_RGBA_1010102:
+ return ADRENO_PIXELFORMAT_R10G10B10A2_UNORM;
+ case HAL_PIXEL_FORMAT_RGBX_1010102:
+ return ADRENO_PIXELFORMAT_R10G10B10X2_UNORM;
+ case HAL_PIXEL_FORMAT_ABGR_2101010:
+ return ADRENO_PIXELFORMAT_A2B10G10R10_UNORM;
+ case HAL_PIXEL_FORMAT_RGB_888:
+ return ADRENO_PIXELFORMAT_R8G8B8;
+ default:
+ ALOGE("%s: No map for format: 0x%x", __FUNCTION__, hal_format);
+ break;
+ }
+
+ return ADRENO_PIXELFORMAT_UNKNOWN;
+}
+
+} // namespace gralloc1
diff --git a/msm8909/gralloc/gr_adreno_info.h b/msm8909/gralloc/gr_adreno_info.h
new file mode 100644
index 00000000..478b5270
--- /dev/null
+++ b/msm8909/gralloc/gr_adreno_info.h
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2011-2017, The Linux Foundation. All rights reserved.
+
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __GR_ADRENO_INFO_H__
+#define __GR_ADRENO_INFO_H__
+
+#include <media/msm_media_info.h>
+
+namespace gralloc1 {
+
+// Adreno Pixel Formats
+typedef enum {
+ ADRENO_PIXELFORMAT_UNKNOWN = 0,
+ ADRENO_PIXELFORMAT_R10G10B10A2_UNORM = 24, // Vertex, Normalized GL_UNSIGNED_INT_10_10_10_2_OES
+ ADRENO_PIXELFORMAT_R8G8B8A8 = 28,
+ ADRENO_PIXELFORMAT_R8G8B8A8_SRGB = 29,
+ ADRENO_PIXELFORMAT_B5G6R5 = 85,
+ ADRENO_PIXELFORMAT_B5G5R5A1 = 86,
+ ADRENO_PIXELFORMAT_B8G8R8A8 = 90,
+ ADRENO_PIXELFORMAT_B8G8R8A8_SRGB = 91,
+ ADRENO_PIXELFORMAT_B8G8R8X8_SRGB = 93,
+ ADRENO_PIXELFORMAT_NV12 = 103,
+ ADRENO_PIXELFORMAT_P010 = 104,
+ ADRENO_PIXELFORMAT_YUY2 = 107,
+ ADRENO_PIXELFORMAT_B4G4R4A4 = 115,
+ ADRENO_PIXELFORMAT_NV12_EXT = 506, // NV12 with non-std alignment and offsets
+ ADRENO_PIXELFORMAT_R8G8B8X8 = 507, // GL_RGB8 (Internal)
+ ADRENO_PIXELFORMAT_R8G8B8 = 508, // GL_RGB8
+ ADRENO_PIXELFORMAT_A1B5G5R5 = 519, // GL_RGB5_A1
+ ADRENO_PIXELFORMAT_R8G8B8X8_SRGB = 520, // GL_SRGB8
+ ADRENO_PIXELFORMAT_R8G8B8_SRGB = 521, // GL_SRGB8
+ ADRENO_PIXELFORMAT_A2B10G10R10_UNORM = 532,
+ // Vertex, Normalized GL_UNSIGNED_INT_10_10_10_2_OES
+ ADRENO_PIXELFORMAT_R10G10B10X2_UNORM = 537,
+ // Vertex, Normalized GL_UNSIGNED_INT_10_10_10_2_OES
+ ADRENO_PIXELFORMAT_R5G6B5 = 610, // RGBA version of B5G6R5
+ ADRENO_PIXELFORMAT_R5G5B5A1 = 611, // RGBA version of B5G5R5A1
+ ADRENO_PIXELFORMAT_R4G4B4A4 = 612, // RGBA version of B4G4R4A4
+ ADRENO_PIXELFORMAT_UYVY = 614, // YUV 4:2:2 packed progressive (1 plane)
+ ADRENO_PIXELFORMAT_NV21 = 619,
+ ADRENO_PIXELFORMAT_Y8U8V8A8 = 620, // YUV 4:4:4 packed (1 plane)
+ ADRENO_PIXELFORMAT_Y8 = 625, // Single 8-bit luma only channel YUV format
+ ADRENO_PIXELFORMAT_TP10 = 648, // YUV 4:2:0 planar 10 bits/comp (2 planes)
+} ADRENOPIXELFORMAT;
+
+class AdrenoMemInfo {
+ public:
+ /*
+ * Function to compute aligned width and aligned height based on
+ * width, height, format and usage flags.
+ *
+ * @return aligned width, aligned height
+ */
+ void GetAlignedWidthAndHeight(int width, int height, int format, int usage,
+ unsigned int *aligned_w, unsigned int *aligned_h, bool ubwc_enabled,
+ bool tile_enabled);
+
+ /*
+ * Function to compute the adreno aligned width and aligned height
+ * based on the width and format.
+ *
+ * @return aligned width, aligned height
+ */
+ void AlignUnCompressedRGB(int width, int height, int format, int tileEnabled,
+ unsigned int *aligned_w, unsigned int *aligned_h);
+
+ /*
+ * Function to compute the adreno aligned width and aligned height
+ * based on the width and format.
+ *
+ * @return aligned width, aligned height
+ */
+ void AlignCompressedRGB(int width, int height, int format, unsigned int *aligned_w,
+ unsigned int *aligned_h);
+
+ /*
+ * Function to compute the pixel alignment requirement.
+ *
+ * @return alignment
+ */
+ uint32_t GetGpuPixelAlignment();
+
+ /*
+ * Function to query whether GPU supports UBWC for given HAL format
+ * @return > 0 : supported
+ * 0 : not supported
+ */
+ bool IsUBWCSupportedByGPU(int format);
+
+ /*
+ * Function to get the corresponding Adreno format for given HAL format
+ */
+ ADRENOPIXELFORMAT GetGpuPixelFormat(int hal_format);
+
+ static AdrenoMemInfo *GetInstance();
+
+ private:
+ AdrenoMemInfo();
+ ~AdrenoMemInfo();
+ // link(s)to adreno surface padding library.
+ int (*LINK_adreno_compute_padding)(int width, int bpp, int surface_tile_height,
+ int screen_tile_height, int padding_threshold) = NULL;
+ void (*LINK_adreno_compute_aligned_width_and_height)(int width, int height, int bpp,
+ int tile_mode, int raster_mode,
+ int padding_threshold, int *aligned_w,
+ int *aligned_h) = NULL;
+ void (*LINK_adreno_compute_compressedfmt_aligned_width_and_height)(
+ int width, int height, int format, int tile_mode, int raster_mode, int padding_threshold,
+ int *aligned_w, int *aligned_h, int *bpp) = NULL;
+ int (*LINK_adreno_isUBWCSupportedByGpu)(ADRENOPIXELFORMAT format) = NULL;
+ unsigned int (*LINK_adreno_get_gpu_pixel_alignment)() = NULL;
+
+ bool gfx_ubwc_disable_ = false;
+ bool map_fb_ = false;
+ void *libadreno_utils_ = NULL;
+
+ static AdrenoMemInfo *s_instance;
+};
+
+} // namespace gralloc1
+
+#endif // __GR_ADRENO_INFO_H__
diff --git a/msm8909/gralloc/gr_allocator.cpp b/msm8909/gralloc/gr_allocator.cpp
new file mode 100644
index 00000000..330da182
--- /dev/null
+++ b/msm8909/gralloc/gr_allocator.cpp
@@ -0,0 +1,312 @@
+/*
+ * Copyright (c) 2011-2017, The Linux Foundation. All rights reserved.
+
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <log/log.h>
+#include <algorithm>
+#include <vector>
+
+#include "gr_utils.h"
+#include "gr_allocator.h"
+#include "gralloc_priv.h"
+
+#include "qd_utils.h"
+
+#ifndef ION_FLAG_CP_PIXEL
+#define ION_FLAG_CP_PIXEL 0
+#endif
+
+#ifndef ION_FLAG_ALLOW_NON_CONTIG
+#define ION_FLAG_ALLOW_NON_CONTIG 0
+#endif
+
+#ifndef ION_FLAG_CP_CAMERA_PREVIEW
+#define ION_FLAG_CP_CAMERA_PREVIEW 0
+#endif
+
+#ifdef MASTER_SIDE_CP
+#define CP_HEAP_ID ION_SECURE_HEAP_ID
+#define SD_HEAP_ID ION_SECURE_DISPLAY_HEAP_ID
+#define ION_CP_FLAGS (ION_SECURE | ION_FLAG_CP_PIXEL)
+#define ION_SD_FLAGS (ION_SECURE | ION_FLAG_CP_SEC_DISPLAY)
+#define ION_SC_FLAGS (ION_SECURE | ION_FLAG_CP_CAMERA)
+#define ION_SC_PREVIEW_FLAGS (ION_SECURE | ION_FLAG_CP_CAMERA_PREVIEW)
+#else // SLAVE_SIDE_CP
+#define CP_HEAP_ID ION_CP_MM_HEAP_ID
+#define SD_HEAP_ID CP_HEAP_ID
+#define ION_CP_FLAGS (ION_SECURE | ION_FLAG_ALLOW_NON_CONTIG)
+#define ION_SD_FLAGS ION_SECURE
+#define ION_SC_FLAGS ION_SECURE
+#define ION_SC_PREVIEW_FLAGS ION_SECURE
+#endif
+
+using std::vector;
+using std::shared_ptr;
+
+namespace gralloc1 {
+
+static BufferInfo GetBufferInfo(const BufferDescriptor &descriptor) {
+ return BufferInfo(descriptor.GetWidth(), descriptor.GetHeight(), descriptor.GetFormat(),
+ descriptor.GetProducerUsage(), descriptor.GetConsumerUsage());
+}
+
+Allocator::Allocator() : ion_allocator_(NULL) {
+}
+
+bool Allocator::Init() {
+ ion_allocator_ = new IonAlloc();
+ if (!ion_allocator_->Init()) {
+ return false;
+ }
+
+ return true;
+}
+
+Allocator::~Allocator() {
+ if (ion_allocator_) {
+ delete ion_allocator_;
+ }
+}
+
+int Allocator::AllocateMem(AllocData *alloc_data, gralloc1_producer_usage_t prod_usage,
+ gralloc1_consumer_usage_t cons_usage) {
+ int ret;
+ alloc_data->uncached = UseUncached(prod_usage, cons_usage);
+
+ // After this point we should have the right heap set, there is no fallback
+ GetIonHeapInfo(prod_usage, cons_usage, &alloc_data->heap_id, &alloc_data->alloc_type,
+ &alloc_data->flags);
+
+ ret = ion_allocator_->AllocBuffer(alloc_data);
+ if (ret >= 0) {
+ alloc_data->alloc_type |= private_handle_t::PRIV_FLAGS_USES_ION;
+ } else {
+ ALOGE("%s: Failed to allocate buffer - heap: 0x%x flags: 0x%x", __FUNCTION__,
+ alloc_data->heap_id, alloc_data->flags);
+ }
+
+ return ret;
+}
+
+int Allocator::MapBuffer(void **base, unsigned int size, unsigned int offset, int fd) {
+ if (ion_allocator_) {
+ return ion_allocator_->MapBuffer(base, size, offset, fd);
+ }
+
+ return -EINVAL;
+}
+
+int Allocator::ImportBuffer(int fd) {
+ if (ion_allocator_) {
+ return ion_allocator_->ImportBuffer(fd);
+ }
+ return -EINVAL;
+}
+
+int Allocator::FreeBuffer(void *base, unsigned int size, unsigned int offset, int fd,
+ int handle) {
+ if (ion_allocator_) {
+ return ion_allocator_->FreeBuffer(base, size, offset, fd, handle);
+ }
+
+ return -EINVAL;
+}
+
+int Allocator::CleanBuffer(void *base, unsigned int size, unsigned int offset, int handle, int op) {
+ if (ion_allocator_) {
+ return ion_allocator_->CleanBuffer(base, size, offset, handle, op);
+ }
+
+ return -EINVAL;
+}
+
+bool Allocator::CheckForBufferSharing(uint32_t num_descriptors,
+ const vector<shared_ptr<BufferDescriptor>>& descriptors,
+ ssize_t *max_index) {
+ unsigned int cur_heap_id = 0, prev_heap_id = 0;
+ unsigned int cur_alloc_type = 0, prev_alloc_type = 0;
+ unsigned int cur_ion_flags = 0, prev_ion_flags = 0;
+ bool cur_uncached = false, prev_uncached = false;
+ unsigned int alignedw, alignedh;
+ unsigned int max_size = 0;
+
+ *max_index = -1;
+ for (uint32_t i = 0; i < num_descriptors; i++) {
+ // Check Cached vs non-cached and all the ION flags
+ cur_uncached = UseUncached(descriptors[i]->GetProducerUsage(),
+ descriptors[i]->GetConsumerUsage());
+ GetIonHeapInfo(descriptors[i]->GetProducerUsage(), descriptors[i]->GetConsumerUsage(),
+ &cur_heap_id, &cur_alloc_type, &cur_ion_flags);
+
+ if (i > 0 && (cur_heap_id != prev_heap_id || cur_alloc_type != prev_alloc_type ||
+ cur_ion_flags != prev_ion_flags)) {
+ return false;
+ }
+
+ // For same format type, find the descriptor with bigger size
+ GetAlignedWidthAndHeight(GetBufferInfo(*descriptors[i]), &alignedw, &alignedh);
+ unsigned int size = GetSize(GetBufferInfo(*descriptors[i]), alignedw, alignedh);
+ if (max_size < size) {
+ *max_index = INT(i);
+ max_size = size;
+ }
+
+ prev_heap_id = cur_heap_id;
+ prev_uncached = cur_uncached;
+ prev_ion_flags = cur_ion_flags;
+ prev_alloc_type = cur_alloc_type;
+ }
+
+ return true;
+}
+
+int Allocator::GetImplDefinedFormat(gralloc1_producer_usage_t prod_usage,
+ gralloc1_consumer_usage_t cons_usage, int format) {
+ int gr_format = format;
+
+ // If input format is HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED then based on
+ // the usage bits, gralloc assigns a format.
+ if (format == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED ||
+ format == HAL_PIXEL_FORMAT_YCbCr_420_888) {
+ if (prod_usage & GRALLOC1_PRODUCER_USAGE_PRIVATE_ALLOC_UBWC) {
+ gr_format = HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC;
+ } else if (cons_usage & GRALLOC1_CONSUMER_USAGE_VIDEO_ENCODER) {
+ gr_format = HAL_PIXEL_FORMAT_NV12_ENCODEABLE; // NV12
+ } else if (cons_usage & GRALLOC1_CONSUMER_USAGE_CAMERA) {
+ if (prod_usage & GRALLOC1_PRODUCER_USAGE_CAMERA) {
+ // Assumed ZSL if both producer and consumer camera flags set
+ gr_format = HAL_PIXEL_FORMAT_NV21_ZSL; // NV21
+ } else {
+ gr_format = HAL_PIXEL_FORMAT_YCrCb_420_SP; // NV21
+ }
+ } else if (prod_usage & GRALLOC1_PRODUCER_USAGE_CAMERA) {
+ if (format == HAL_PIXEL_FORMAT_YCbCr_420_888) {
+ gr_format = HAL_PIXEL_FORMAT_NV21_ZSL; // NV21
+ } else {
+ gr_format = HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS; // NV12 preview
+ }
+ } else if (cons_usage & GRALLOC1_CONSUMER_USAGE_HWCOMPOSER) {
+ // XXX: If we still haven't set a format, default to RGBA8888
+ gr_format = HAL_PIXEL_FORMAT_RGBA_8888;
+ } else if (format == HAL_PIXEL_FORMAT_YCbCr_420_888) {
+ // If no other usage flags are detected, default the
+ // flexible YUV format to NV21_ZSL
+ gr_format = HAL_PIXEL_FORMAT_NV21_ZSL;
+ }
+ }
+
+ return gr_format;
+}
+
+/* The default policy is to return cached buffers unless the client explicity
+ * sets the PRIVATE_UNCACHED flag or indicates that the buffer will be rarely
+ * read or written in software. */
+bool Allocator::UseUncached(gralloc1_producer_usage_t prod_usage,
+ gralloc1_consumer_usage_t cons_usage) {
+ if ((prod_usage & GRALLOC1_PRODUCER_USAGE_PRIVATE_UNCACHED) ||
+ (prod_usage & GRALLOC1_PRODUCER_USAGE_PROTECTED)) {
+ return true;
+ }
+
+ // CPU read rarely
+ if ((prod_usage & GRALLOC1_PRODUCER_USAGE_CPU_READ) &&
+ !(prod_usage & GRALLOC1_PRODUCER_USAGE_CPU_READ_OFTEN)) {
+ return true;
+ }
+
+ // CPU write rarely
+ if ((prod_usage & GRALLOC1_PRODUCER_USAGE_CPU_WRITE) &&
+ !(prod_usage & GRALLOC1_PRODUCER_USAGE_CPU_WRITE_OFTEN)) {
+ return true;
+ }
+
+ if ((prod_usage & GRALLOC1_PRODUCER_USAGE_SENSOR_DIRECT_DATA) ||
+ (cons_usage & GRALLOC1_CONSUMER_USAGE_GPU_DATA_BUFFER)) {
+ return true;
+ }
+
+ return false;
+}
+
+void Allocator::GetIonHeapInfo(gralloc1_producer_usage_t prod_usage,
+ gralloc1_consumer_usage_t cons_usage, unsigned int *ion_heap_id,
+ unsigned int *alloc_type, unsigned int *ion_flags) {
+ unsigned int heap_id = 0;
+ unsigned int type = 0;
+ uint32_t flags = 0;
+ if (prod_usage & GRALLOC1_PRODUCER_USAGE_PROTECTED) {
+ if (cons_usage & GRALLOC1_CONSUMER_USAGE_PRIVATE_SECURE_DISPLAY) {
+ heap_id = ION_HEAP(SD_HEAP_ID);
+ /*
+ * There is currently no flag in ION for Secure Display
+ * VM. Please add it to the define once available.
+ */
+ flags |= UINT(ION_SD_FLAGS);
+ } else if (prod_usage & GRALLOC1_PRODUCER_USAGE_CAMERA) {
+ heap_id = ION_HEAP(SD_HEAP_ID);
+ if (cons_usage & GRALLOC1_CONSUMER_USAGE_HWCOMPOSER) {
+ flags |= UINT(ION_SC_PREVIEW_FLAGS);
+ } else {
+ flags |= UINT(ION_SC_FLAGS);
+ }
+ } else {
+ heap_id = ION_HEAP(CP_HEAP_ID);
+ flags |= UINT(ION_CP_FLAGS);
+ }
+ } else if (prod_usage & GRALLOC1_PRODUCER_USAGE_PRIVATE_MM_HEAP) {
+ // MM Heap is exclusively a secure heap.
+ // If it is used for non secure cases, fallback to IOMMU heap
+ ALOGW("MM_HEAP cannot be used as an insecure heap. Using system heap instead!!");
+ heap_id |= ION_HEAP(ION_SYSTEM_HEAP_ID);
+ }
+
+ if (prod_usage & GRALLOC1_PRODUCER_USAGE_PRIVATE_CAMERA_HEAP) {
+ heap_id |= ION_HEAP(ION_CAMERA_HEAP_ID);
+ }
+
+ if (prod_usage & GRALLOC1_PRODUCER_USAGE_PRIVATE_ADSP_HEAP ||
+ prod_usage & GRALLOC1_PRODUCER_USAGE_SENSOR_DIRECT_DATA) {
+ heap_id |= ION_HEAP(ION_ADSP_HEAP_ID);
+ }
+
+ if (flags & UINT(ION_SECURE)) {
+ type |= private_handle_t::PRIV_FLAGS_SECURE_BUFFER;
+ }
+
+ // if no ion heap flags are set, default to system heap
+ if (!heap_id) {
+ heap_id = ION_HEAP(ION_SYSTEM_HEAP_ID);
+ }
+
+ *alloc_type = type;
+ *ion_flags = flags;
+ *ion_heap_id = heap_id;
+
+ return;
+}
+} // namespace gralloc1
diff --git a/msm8909/gralloc/gr_allocator.h b/msm8909/gralloc/gr_allocator.h
new file mode 100644
index 00000000..d57f50e6
--- /dev/null
+++ b/msm8909/gralloc/gr_allocator.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2011-2017, The Linux Foundation. All rights reserved.
+
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __GR_ALLOCATOR_H__
+#define __GR_ALLOCATOR_H__
+
+#ifdef MASTER_SIDE_CP
+#define SECURE_ALIGN SZ_4K
+#else
+#define SECURE_ALIGN SZ_1M
+#endif
+
+#include <vector>
+
+#include "gralloc_priv.h"
+#include "gr_buf_descriptor.h"
+#include "gr_ion_alloc.h"
+
+namespace gralloc1 {
+
+class Allocator {
+ public:
+ Allocator();
+ ~Allocator();
+ bool Init();
+ int MapBuffer(void **base, unsigned int size, unsigned int offset, int fd);
+ int ImportBuffer(int fd);
+ int FreeBuffer(void *base, unsigned int size, unsigned int offset, int fd, int handle);
+ int CleanBuffer(void *base, unsigned int size, unsigned int offset, int handle, int op);
+ int AllocateMem(AllocData *data, gralloc1_producer_usage_t prod_usage,
+ gralloc1_consumer_usage_t cons_usage);
+ // @return : index of the descriptor with maximum buffer size req
+ bool CheckForBufferSharing(uint32_t num_descriptors,
+ const std::vector<std::shared_ptr<BufferDescriptor>>& descriptors,
+ ssize_t *max_index);
+ int GetImplDefinedFormat(gralloc1_producer_usage_t prod_usage,
+ gralloc1_consumer_usage_t cons_usage, int format);
+ bool UseUncached(gralloc1_producer_usage_t prod_usage, gralloc1_consumer_usage_t cons_usage);
+
+ private:
+ void GetIonHeapInfo(gralloc1_producer_usage_t prod_usage, gralloc1_consumer_usage_t cons_usage,
+ unsigned int *ion_heap_id, unsigned int *alloc_type, unsigned int *ion_flags);
+
+ IonAlloc *ion_allocator_ = NULL;
+};
+
+} // namespace gralloc1
+
+#endif // __GR_ALLOCATOR_H__
diff --git a/msm8909/gralloc/gr_buf_descriptor.h b/msm8909/gralloc/gr_buf_descriptor.h
new file mode 100644
index 00000000..c909fa46
--- /dev/null
+++ b/msm8909/gralloc/gr_buf_descriptor.h
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __GR_BUF_DESCRIPTOR_H__
+#define __GR_BUF_DESCRIPTOR_H__
+
+#include <hardware/gralloc1.h>
+#include <atomic>
+
+namespace gralloc1 {
+class BufferDescriptor {
+ public:
+ BufferDescriptor() : id_(next_id_++) {}
+
+ BufferDescriptor(int w, int h, int f)
+ : width_(w),
+ height_(h),
+ format_(f),
+ producer_usage_(GRALLOC1_PRODUCER_USAGE_NONE),
+ consumer_usage_(GRALLOC1_CONSUMER_USAGE_NONE),
+ id_(next_id_++) {}
+
+ BufferDescriptor(int w, int h, int f, gralloc1_producer_usage_t prod_usage,
+ gralloc1_consumer_usage_t cons_usage)
+ : width_(w),
+ height_(h),
+ format_(f),
+ producer_usage_(prod_usage),
+ consumer_usage_(cons_usage),
+ id_(next_id_++) {}
+
+ void SetConsumerUsage(gralloc1_consumer_usage_t usage) { consumer_usage_ = usage; }
+
+ void SetProducerUsage(gralloc1_producer_usage_t usage) { producer_usage_ = usage; }
+
+ void SetDimensions(int w, int h) {
+ width_ = w;
+ height_ = h;
+ }
+
+ void SetColorFormat(int format) { format_ = format; }
+
+ void SetLayerCount(uint32_t layer_count) { layer_count_ = layer_count; }
+
+ gralloc1_consumer_usage_t GetConsumerUsage() const { return consumer_usage_; }
+
+ gralloc1_producer_usage_t GetProducerUsage() const { return producer_usage_; }
+
+ int GetWidth() const { return width_; }
+
+ int GetHeight() const { return height_; }
+
+ int GetFormat() const { return format_; }
+
+ uint32_t GetLayerCount() const { return layer_count_; }
+
+ gralloc1_buffer_descriptor_t GetId() const { return id_; }
+
+ private:
+ int width_ = -1;
+ int height_ = -1;
+ int format_ = -1;
+ uint32_t layer_count_ = 1;
+ gralloc1_producer_usage_t producer_usage_ = GRALLOC1_PRODUCER_USAGE_NONE;
+ gralloc1_consumer_usage_t consumer_usage_ = GRALLOC1_CONSUMER_USAGE_NONE;
+ const gralloc1_buffer_descriptor_t id_;
+ static std::atomic<gralloc1_buffer_descriptor_t> next_id_;
+};
+}; // namespace gralloc1
+#endif // __GR_BUF_DESCRIPTOR_H__
diff --git a/msm8909/gralloc/gr_buf_mgr.cpp b/msm8909/gralloc/gr_buf_mgr.cpp
new file mode 100644
index 00000000..23bed236
--- /dev/null
+++ b/msm8909/gralloc/gr_buf_mgr.cpp
@@ -0,0 +1,929 @@
+/*
+ * Copyright (c) 2011-2018 The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ *
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define DEBUG 0
+
+#include <iomanip>
+#include <utility>
+#include <vector>
+#include <sstream>
+
+#include "qd_utils.h"
+#include "gr_priv_handle.h"
+#include "gr_buf_descriptor.h"
+#include "gr_utils.h"
+#include "gr_buf_mgr.h"
+#include "qdMetaData.h"
+
+namespace gralloc1 {
+std::atomic<gralloc1_buffer_descriptor_t> BufferDescriptor::next_id_(1);
+
+static BufferInfo GetBufferInfo(const BufferDescriptor &descriptor) {
+ return BufferInfo(descriptor.GetWidth(), descriptor.GetHeight(), descriptor.GetFormat(),
+ descriptor.GetProducerUsage(), descriptor.GetConsumerUsage());
+}
+
+BufferManager::BufferManager() : next_id_(0) {
+ char property[PROPERTY_VALUE_MAX];
+
+ // Map framebuffer memory
+ if ((property_get(MAP_FB_MEMORY_PROP, property, NULL) > 0) &&
+ (!strncmp(property, "1", PROPERTY_VALUE_MAX) ||
+ (!strncasecmp(property, "true", PROPERTY_VALUE_MAX)))) {
+ map_fb_mem_ = true;
+ }
+
+ handles_map_.clear();
+ allocator_ = new Allocator();
+ allocator_->Init();
+}
+
+
+gralloc1_error_t BufferManager::CreateBufferDescriptor(
+ gralloc1_buffer_descriptor_t *descriptor_id) {
+ std::lock_guard<std::mutex> lock(descriptor_lock_);
+ auto descriptor = std::make_shared<BufferDescriptor>();
+ descriptors_map_.emplace(descriptor->GetId(), descriptor);
+ *descriptor_id = descriptor->GetId();
+ return GRALLOC1_ERROR_NONE;
+}
+
+gralloc1_error_t BufferManager::DestroyBufferDescriptor(
+ gralloc1_buffer_descriptor_t descriptor_id) {
+ std::lock_guard<std::mutex> lock(descriptor_lock_);
+ const auto descriptor = descriptors_map_.find(descriptor_id);
+ if (descriptor == descriptors_map_.end()) {
+ return GRALLOC1_ERROR_BAD_DESCRIPTOR;
+ }
+ descriptors_map_.erase(descriptor);
+ return GRALLOC1_ERROR_NONE;
+}
+
+BufferManager::~BufferManager() {
+ if (allocator_) {
+ delete allocator_;
+ }
+}
+
+gralloc1_error_t BufferManager::AllocateBuffers(uint32_t num_descriptors,
+ const gralloc1_buffer_descriptor_t *descriptor_ids,
+ buffer_handle_t *out_buffers) {
+ bool shared = true;
+ gralloc1_error_t status = GRALLOC1_ERROR_NONE;
+
+ // since GRALLOC1_CAPABILITY_TEST_ALLOCATE capability is supported
+ // client can ask to test the allocation by passing NULL out_buffers
+ bool test_allocate = !out_buffers;
+
+ // Validate descriptors
+ std::lock_guard<std::mutex> descriptor_lock(descriptor_lock_);
+ std::vector<std::shared_ptr<BufferDescriptor>> descriptors;
+ for (uint32_t i = 0; i < num_descriptors; i++) {
+ const auto map_descriptor = descriptors_map_.find(descriptor_ids[i]);
+ if (map_descriptor == descriptors_map_.end()) {
+ return GRALLOC1_ERROR_BAD_DESCRIPTOR;
+ } else {
+ descriptors.push_back(map_descriptor->second);
+ }
+ }
+
+ // Resolve implementation defined formats
+ for (auto &descriptor : descriptors) {
+ descriptor->SetColorFormat(allocator_->GetImplDefinedFormat(descriptor->GetProducerUsage(),
+ descriptor->GetConsumerUsage(),
+ descriptor->GetFormat()));
+ }
+
+ // Check if input descriptors can be supported AND
+ // Find out if a single buffer can be shared for all the given input descriptors
+ uint32_t i = 0;
+ ssize_t max_buf_index = -1;
+ shared = allocator_->CheckForBufferSharing(num_descriptors, descriptors, &max_buf_index);
+
+ if (test_allocate) {
+ status = shared ? GRALLOC1_ERROR_NOT_SHARED : status;
+ return status;
+ }
+
+ std::lock_guard<std::mutex> buffer_lock(buffer_lock_);
+ if (shared && (max_buf_index >= 0)) {
+ // Allocate one and duplicate/copy the handles for each descriptor
+ if (AllocateBuffer(*descriptors[UINT(max_buf_index)], &out_buffers[max_buf_index])) {
+ return GRALLOC1_ERROR_NO_RESOURCES;
+ }
+
+ for (i = 0; i < num_descriptors; i++) {
+ // Create new handle for a given descriptor.
+ // Current assumption is even MetaData memory would be same
+ // Need to revisit if there is a need for own metadata memory
+ if (i != UINT(max_buf_index)) {
+ CreateSharedHandle(out_buffers[max_buf_index], *descriptors[i], &out_buffers[i]);
+ }
+ }
+ } else {
+ // Buffer sharing is not feasible.
+ // Allocate separate buffer for each descriptor
+ for (i = 0; i < num_descriptors; i++) {
+ if (AllocateBuffer(*descriptors[i], &out_buffers[i])) {
+ return GRALLOC1_ERROR_NO_RESOURCES;
+ }
+ }
+ }
+
+ // Allocation is successful. If backstore is not shared inform the client.
+ if (!shared) {
+ return GRALLOC1_ERROR_NOT_SHARED;
+ }
+
+ return status;
+}
+
+void BufferManager::CreateSharedHandle(buffer_handle_t inbuffer, const BufferDescriptor &descriptor,
+ buffer_handle_t *outbuffer) {
+ // TODO(user): This path is not verified
+ private_handle_t const *input = reinterpret_cast<private_handle_t const *>(inbuffer);
+
+ // Get Buffer attributes or dimension
+ unsigned int alignedw = 0, alignedh = 0;
+ BufferInfo info = GetBufferInfo(descriptor);
+
+ GetAlignedWidthAndHeight(info, &alignedw, &alignedh);
+
+ // create new handle from input reference handle and given descriptor
+ int flags = GetHandleFlags(descriptor.GetFormat(), descriptor.GetProducerUsage(),
+ descriptor.GetConsumerUsage());
+ int buffer_type = GetBufferType(descriptor.GetFormat());
+
+ // Duplicate the fds
+ // TODO(user): Not sure what to do for fb_id. Use duped fd and new dimensions?
+ private_handle_t *out_hnd = new private_handle_t(dup(input->fd),
+ dup(input->fd_metadata),
+ flags,
+ INT(alignedw),
+ INT(alignedh),
+ descriptor.GetWidth(),
+ descriptor.GetHeight(),
+ descriptor.GetFormat(),
+ buffer_type,
+ input->size,
+ descriptor.GetProducerUsage(),
+ descriptor.GetConsumerUsage());
+ out_hnd->id = ++next_id_;
+ // TODO(user): Base address of shared handle and ion handles
+ RegisterHandleLocked(out_hnd, -1, -1);
+ *outbuffer = out_hnd;
+}
+
+gralloc1_error_t BufferManager::FreeBuffer(std::shared_ptr<Buffer> buf) {
+ auto hnd = buf->handle;
+ ALOGD_IF(DEBUG, "FreeBuffer handle:%p", hnd);
+
+ if (private_handle_t::validate(hnd) != 0) {
+ ALOGE("FreeBuffer: Invalid handle: %p", hnd);
+ return GRALLOC1_ERROR_BAD_HANDLE;
+ }
+
+ if (allocator_->FreeBuffer(reinterpret_cast<void *>(hnd->base), hnd->size, hnd->offset,
+ hnd->fd, buf->ion_handle_main) != 0) {
+ return GRALLOC1_ERROR_BAD_HANDLE;
+ }
+
+ unsigned int meta_size = ALIGN((unsigned int)sizeof(MetaData_t), PAGE_SIZE);
+ if (allocator_->FreeBuffer(reinterpret_cast<void *>(hnd->base_metadata), meta_size,
+ hnd->offset_metadata, hnd->fd_metadata, buf->ion_handle_meta) != 0) {
+ return GRALLOC1_ERROR_BAD_HANDLE;
+ }
+
+ private_handle_t * handle = const_cast<private_handle_t *>(hnd);
+ handle->fd = -1;
+ handle->fd_metadata = -1;
+ if (!(handle->flags & private_handle_t::PRIV_FLAGS_CLIENT_ALLOCATED)) {
+ delete handle;
+ }
+ return GRALLOC1_ERROR_NONE;
+}
+
+void BufferManager::RegisterHandleLocked(const private_handle_t *hnd,
+ int ion_handle,
+ int ion_handle_meta) {
+ auto buffer = std::make_shared<Buffer>(hnd, ion_handle, ion_handle_meta);
+ handles_map_.emplace(std::make_pair(hnd, buffer));
+}
+
+gralloc1_error_t BufferManager::ImportHandleLocked(private_handle_t *hnd) {
+ ALOGD_IF(DEBUG, "Importing handle:%p id: %" PRIu64, hnd, hnd->id);
+ int ion_handle = allocator_->ImportBuffer(hnd->fd);
+ if (ion_handle < 0) {
+ ALOGE("Failed to import ion buffer: hnd: %p, fd:%d, id:%" PRIu64, hnd, hnd->fd, hnd->id);
+ return GRALLOC1_ERROR_BAD_HANDLE;
+ }
+ int ion_handle_meta = allocator_->ImportBuffer(hnd->fd_metadata);
+ if (ion_handle_meta < 0) {
+ ALOGE("Failed to import ion metadata buffer: hnd: %p, fd:%d, id:%" PRIu64, hnd,
+ hnd->fd, hnd->id);
+ return GRALLOC1_ERROR_BAD_HANDLE;
+ }
+ // Set base pointers to NULL since the data here was received over binder
+ hnd->base = 0;
+ hnd->base_metadata = 0;
+ RegisterHandleLocked(hnd, ion_handle, ion_handle_meta);
+ return GRALLOC1_ERROR_NONE;
+}
+
+std::shared_ptr<BufferManager::Buffer>
+BufferManager::GetBufferFromHandleLocked(const private_handle_t *hnd) {
+ auto it = handles_map_.find(hnd);
+ if (it != handles_map_.end()) {
+ return it->second;
+ } else {
+ return nullptr;
+ }
+}
+
+gralloc1_error_t BufferManager::MapBuffer(private_handle_t const *handle) {
+ private_handle_t *hnd = const_cast<private_handle_t *>(handle);
+ ALOGD_IF(DEBUG, "Map buffer handle:%p id: %" PRIu64, hnd, hnd->id);
+
+ hnd->base = 0;
+ if (allocator_->MapBuffer(reinterpret_cast<void **>(&hnd->base), hnd->size, hnd->offset,
+ hnd->fd) != 0) {
+ return GRALLOC1_ERROR_BAD_HANDLE;
+ }
+ return GRALLOC1_ERROR_NONE;
+}
+
+gralloc1_error_t BufferManager::RetainBuffer(private_handle_t const *hnd) {
+ ALOGD_IF(DEBUG, "Retain buffer handle:%p id: %" PRIu64, hnd, hnd->id);
+ gralloc1_error_t err = GRALLOC1_ERROR_NONE;
+ std::lock_guard<std::mutex> lock(buffer_lock_);
+ auto buf = GetBufferFromHandleLocked(hnd);
+ if (buf != nullptr) {
+ buf->IncRef();
+ } else {
+ private_handle_t *handle = const_cast<private_handle_t *>(hnd);
+ err = ImportHandleLocked(handle);
+ }
+ return err;
+}
+
+gralloc1_error_t BufferManager::ReleaseBuffer(private_handle_t const *hnd) {
+ ALOGD_IF(DEBUG, "Release buffer handle:%p", hnd);
+ std::lock_guard<std::mutex> lock(buffer_lock_);
+ auto buf = GetBufferFromHandleLocked(hnd);
+ if (buf == nullptr) {
+ ALOGE("Could not find handle: %p id: %" PRIu64, hnd, hnd->id);
+ return GRALLOC1_ERROR_BAD_HANDLE;
+ } else {
+ if (buf->DecRef()) {
+ handles_map_.erase(hnd);
+ // Unmap, close ion handle and close fd
+ FreeBuffer(buf);
+ }
+ }
+ return GRALLOC1_ERROR_NONE;
+}
+
+gralloc1_error_t BufferManager::LockBuffer(const private_handle_t *hnd,
+ gralloc1_producer_usage_t prod_usage,
+ gralloc1_consumer_usage_t cons_usage) {
+ std::lock_guard<std::mutex> lock(buffer_lock_);
+ gralloc1_error_t err = GRALLOC1_ERROR_NONE;
+ ALOGD_IF(DEBUG, "LockBuffer buffer handle:%p id: %" PRIu64, hnd, hnd->id);
+
+ // If buffer is not meant for CPU return err
+ if (!CpuCanAccess(prod_usage, cons_usage)) {
+ return GRALLOC1_ERROR_BAD_VALUE;
+ }
+
+ auto buf = GetBufferFromHandleLocked(hnd);
+ if (buf == nullptr) {
+ return GRALLOC1_ERROR_BAD_HANDLE;
+ }
+
+ if (hnd->base == 0) {
+ // we need to map for real
+ err = MapBuffer(hnd);
+ }
+
+ // todo use handle here
+ if (!err && (hnd->flags & private_handle_t::PRIV_FLAGS_USES_ION) &&
+ (hnd->flags & private_handle_t::PRIV_FLAGS_CACHED)) {
+
+ // Invalidate if CPU reads in software and there are non-CPU
+ // writers. No need to do this for the metadata buffer as it is
+ // only read/written in software.
+ if ((cons_usage & (GRALLOC1_CONSUMER_USAGE_CPU_READ | GRALLOC1_CONSUMER_USAGE_CPU_READ_OFTEN))
+ && (hnd->flags & private_handle_t::PRIV_FLAGS_NON_CPU_WRITER)) {
+ if (allocator_->CleanBuffer(reinterpret_cast<void *>(hnd->base), hnd->size, hnd->offset,
+ buf->ion_handle_main, CACHE_INVALIDATE)) {
+
+ return GRALLOC1_ERROR_BAD_HANDLE;
+ }
+ }
+ }
+
+ // Mark the buffer to be flushed after CPU write.
+ if (!err && CpuCanWrite(prod_usage)) {
+ private_handle_t *handle = const_cast<private_handle_t *>(hnd);
+ handle->flags |= private_handle_t::PRIV_FLAGS_NEEDS_FLUSH;
+ }
+
+ return err;
+}
+
+gralloc1_error_t BufferManager::UnlockBuffer(const private_handle_t *handle) {
+ std::lock_guard<std::mutex> lock(buffer_lock_);
+ gralloc1_error_t status = GRALLOC1_ERROR_NONE;
+
+ private_handle_t *hnd = const_cast<private_handle_t *>(handle);
+ auto buf = GetBufferFromHandleLocked(hnd);
+ if (buf == nullptr) {
+ return GRALLOC1_ERROR_BAD_HANDLE;
+ }
+
+ if (hnd->flags & private_handle_t::PRIV_FLAGS_NEEDS_FLUSH) {
+ if (allocator_->CleanBuffer(reinterpret_cast<void *>(hnd->base), hnd->size, hnd->offset,
+ buf->ion_handle_main, CACHE_CLEAN) != 0) {
+ status = GRALLOC1_ERROR_BAD_HANDLE;
+ }
+ hnd->flags &= ~private_handle_t::PRIV_FLAGS_NEEDS_FLUSH;
+ }
+
+ return status;
+}
+
+uint32_t BufferManager::GetDataAlignment(int format, gralloc1_producer_usage_t prod_usage,
+ gralloc1_consumer_usage_t cons_usage) {
+ uint32_t align = UINT(getpagesize());
+ if (format == HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED) {
+ align = 8192;
+ }
+
+ if (prod_usage & GRALLOC1_PRODUCER_USAGE_PROTECTED) {
+ if ((prod_usage & GRALLOC1_PRODUCER_USAGE_CAMERA) ||
+ (cons_usage & GRALLOC1_CONSUMER_USAGE_PRIVATE_SECURE_DISPLAY)) {
+ // The alignment here reflects qsee mmu V7L/V8L requirement
+ align = SZ_2M;
+ } else {
+ align = SECURE_ALIGN;
+ }
+ }
+
+ return align;
+}
+
+int BufferManager::GetHandleFlags(int format, gralloc1_producer_usage_t prod_usage,
+ gralloc1_consumer_usage_t cons_usage) {
+ int flags = 0;
+ if (cons_usage & GRALLOC1_CONSUMER_USAGE_PRIVATE_EXTERNAL_ONLY) {
+ flags |= private_handle_t::PRIV_FLAGS_EXTERNAL_ONLY;
+ }
+
+ if (cons_usage & GRALLOC1_CONSUMER_USAGE_PRIVATE_INTERNAL_ONLY) {
+ flags |= private_handle_t::PRIV_FLAGS_INTERNAL_ONLY;
+ }
+
+ if (cons_usage & GRALLOC1_CONSUMER_USAGE_VIDEO_ENCODER) {
+ flags |= private_handle_t::PRIV_FLAGS_VIDEO_ENCODER;
+ }
+
+ if (prod_usage & GRALLOC1_PRODUCER_USAGE_CAMERA) {
+ flags |= private_handle_t::PRIV_FLAGS_CAMERA_WRITE;
+ }
+
+ if (prod_usage & GRALLOC1_CONSUMER_USAGE_CAMERA) {
+ flags |= private_handle_t::PRIV_FLAGS_CAMERA_READ;
+ }
+
+ if (cons_usage & GRALLOC1_CONSUMER_USAGE_HWCOMPOSER) {
+ flags |= private_handle_t::PRIV_FLAGS_HW_COMPOSER;
+ }
+
+ if (prod_usage & GRALLOC1_CONSUMER_USAGE_GPU_TEXTURE) {
+ flags |= private_handle_t::PRIV_FLAGS_HW_TEXTURE;
+ }
+
+ if (cons_usage & GRALLOC1_CONSUMER_USAGE_PRIVATE_SECURE_DISPLAY) {
+ flags |= private_handle_t::PRIV_FLAGS_SECURE_DISPLAY;
+ }
+
+ if (IsUBwcEnabled(format, prod_usage, cons_usage)) {
+ flags |= private_handle_t::PRIV_FLAGS_UBWC_ALIGNED;
+ }
+
+ if (prod_usage & (GRALLOC1_PRODUCER_USAGE_CPU_READ | GRALLOC1_PRODUCER_USAGE_CPU_WRITE)) {
+ flags |= private_handle_t::PRIV_FLAGS_CPU_RENDERED;
+ }
+
+ // TODO(user): is this correct???
+ if ((cons_usage &
+ (GRALLOC1_CONSUMER_USAGE_VIDEO_ENCODER | GRALLOC1_CONSUMER_USAGE_CLIENT_TARGET)) ||
+ (prod_usage & (GRALLOC1_PRODUCER_USAGE_CAMERA | GRALLOC1_PRODUCER_USAGE_GPU_RENDER_TARGET))) {
+ flags |= private_handle_t::PRIV_FLAGS_NON_CPU_WRITER;
+ }
+
+ if (cons_usage & GRALLOC1_CONSUMER_USAGE_HWCOMPOSER) {
+ flags |= private_handle_t::PRIV_FLAGS_DISP_CONSUMER;
+ }
+
+ if (!allocator_->UseUncached(prod_usage, cons_usage)) {
+ flags |= private_handle_t::PRIV_FLAGS_CACHED;
+ }
+
+ return flags;
+}
+
+int BufferManager::GetBufferType(int inputFormat) {
+ int buffer_type = BUFFER_TYPE_VIDEO;
+ if (IsUncompressedRGBFormat(inputFormat)) {
+ // RGB formats
+ buffer_type = BUFFER_TYPE_UI;
+ }
+
+ return buffer_type;
+}
+
+int BufferManager::AllocateBuffer(const BufferDescriptor &descriptor, buffer_handle_t *handle,
+ unsigned int bufferSize) {
+ if (!handle)
+ return -EINVAL;
+
+ int format = descriptor.GetFormat();
+ gralloc1_producer_usage_t prod_usage = descriptor.GetProducerUsage();
+ gralloc1_consumer_usage_t cons_usage = descriptor.GetConsumerUsage();
+ uint32_t layer_count = descriptor.GetLayerCount();
+
+ // Get implementation defined format
+ int gralloc_format = allocator_->GetImplDefinedFormat(prod_usage, cons_usage, format);
+
+ unsigned int size;
+ unsigned int alignedw, alignedh;
+ int buffer_type = GetBufferType(gralloc_format);
+ BufferInfo info = GetBufferInfo(descriptor);
+ GetBufferSizeAndDimensions(info, &size, &alignedw, &alignedh);
+ size = (bufferSize >= size) ? bufferSize : size;
+
+ int err = 0;
+ int flags = 0;
+ auto page_size = UINT(getpagesize());
+ AllocData data;
+ data.align = GetDataAlignment(format, prod_usage, cons_usage);
+ size = ALIGN(size, data.align) * layer_count;
+ data.size = size;
+ data.handle = (uintptr_t) handle;
+ data.uncached = allocator_->UseUncached(prod_usage, cons_usage);
+
+ // Allocate buffer memory
+ err = allocator_->AllocateMem(&data, prod_usage, cons_usage);
+ if (err) {
+ ALOGE("gralloc failed to allocate err=%s", strerror(-err));
+ return err;
+ }
+
+ // Allocate memory for MetaData
+ AllocData e_data;
+ e_data.size = ALIGN(UINT(sizeof(MetaData_t)), page_size);
+ e_data.handle = data.handle;
+ e_data.align = page_size;
+
+ err =
+ allocator_->AllocateMem(&e_data, GRALLOC1_PRODUCER_USAGE_NONE, GRALLOC1_CONSUMER_USAGE_NONE);
+ if (err) {
+ ALOGE("gralloc failed to allocate metadata error=%s", strerror(-err));
+ return err;
+ }
+
+ flags = GetHandleFlags(format, prod_usage, cons_usage);
+ flags |= data.alloc_type;
+
+ // Create handle
+ private_handle_t *hnd = new private_handle_t(data.fd,
+ e_data.fd,
+ flags,
+ INT(alignedw),
+ INT(alignedh),
+ descriptor.GetWidth(),
+ descriptor.GetHeight(),
+ format,
+ buffer_type,
+ data.size,
+ prod_usage,
+ cons_usage);
+
+ hnd->id = ++next_id_;
+ hnd->base = 0;
+ hnd->base_metadata = 0;
+ hnd->layer_count = layer_count;
+
+ ColorSpace_t colorSpace = ITU_R_601;
+ setMetaData(hnd, UPDATE_COLOR_SPACE, reinterpret_cast<void *>(&colorSpace));
+ *handle = hnd;
+ RegisterHandleLocked(hnd, data.ion_handle, e_data.ion_handle);
+ ALOGD_IF(DEBUG, "Allocated buffer handle: %p id: %" PRIu64, hnd, hnd->id);
+ if (DEBUG) {
+ private_handle_t::Dump(hnd);
+ }
+ return err;
+}
+
+gralloc1_error_t BufferManager::Perform(int operation, va_list args) {
+ switch (operation) {
+ case GRALLOC_MODULE_PERFORM_CREATE_HANDLE_FROM_BUFFER: {
+ int fd = va_arg(args, int);
+ unsigned int size = va_arg(args, unsigned int);
+ unsigned int offset = va_arg(args, unsigned int);
+ void *base = va_arg(args, void *);
+ int width = va_arg(args, int);
+ int height = va_arg(args, int);
+ int format = va_arg(args, int);
+
+ native_handle_t **handle = va_arg(args, native_handle_t **);
+ if (!handle) {
+ return GRALLOC1_ERROR_BAD_HANDLE;
+ }
+
+ private_handle_t *hnd = reinterpret_cast<private_handle_t *>(
+ native_handle_create(private_handle_t::kNumFds, private_handle_t::NumInts()));
+ if (hnd) {
+ unsigned int alignedw = 0, alignedh = 0;
+ hnd->magic = private_handle_t::kMagic;
+ hnd->fd = fd;
+ hnd->flags = private_handle_t::PRIV_FLAGS_USES_ION;
+ hnd->size = size;
+ hnd->offset = offset;
+ hnd->base = uint64_t(base);
+ hnd->gpuaddr = 0;
+ BufferInfo info(width, height, format);
+ GetAlignedWidthAndHeight(info, &alignedw, &alignedh);
+ hnd->unaligned_width = width;
+ hnd->unaligned_height = height;
+ hnd->width = INT(alignedw);
+ hnd->height = INT(alignedh);
+ hnd->format = format;
+ *handle = reinterpret_cast<native_handle_t *>(hnd);
+ }
+ } break;
+
+ case GRALLOC_MODULE_PERFORM_GET_STRIDE: {
+ int width = va_arg(args, int);
+ int format = va_arg(args, int);
+ int *stride = va_arg(args, int *);
+ unsigned int alignedw = 0, alignedh = 0;
+
+ if (!stride) {
+ return GRALLOC1_ERROR_BAD_VALUE;
+ }
+
+ BufferInfo info(width, width, format);
+ GetAlignedWidthAndHeight(info, &alignedw, &alignedh);
+ *stride = INT(alignedw);
+ } break;
+
+ case GRALLOC_MODULE_PERFORM_GET_CUSTOM_STRIDE_FROM_HANDLE: {
+ private_handle_t *hnd = va_arg(args, private_handle_t *);
+ int *stride = va_arg(args, int *);
+ if (private_handle_t::validate(hnd) != 0) {
+ return GRALLOC1_ERROR_BAD_HANDLE;
+ }
+
+ if (!stride) {
+ return GRALLOC1_ERROR_BAD_VALUE;
+ }
+
+ BufferDim_t buffer_dim;
+ if (getMetaData(hnd, GET_BUFFER_GEOMETRY, &buffer_dim) == 0) {
+ *stride = buffer_dim.sliceWidth;
+ } else {
+ *stride = hnd->width;
+ }
+ } break;
+
+ // TODO(user) : this alone should be sufficient, ask gfx to get rid of above
+ case GRALLOC_MODULE_PERFORM_GET_CUSTOM_STRIDE_AND_HEIGHT_FROM_HANDLE: {
+ private_handle_t *hnd = va_arg(args, private_handle_t *);
+ int *stride = va_arg(args, int *);
+ int *height = va_arg(args, int *);
+ if (private_handle_t::validate(hnd) != 0) {
+ return GRALLOC1_ERROR_BAD_HANDLE;
+ }
+
+ if (!stride || !height) {
+ return GRALLOC1_ERROR_BAD_VALUE;
+ }
+
+ BufferDim_t buffer_dim;
+ if (getMetaData(hnd, GET_BUFFER_GEOMETRY, &buffer_dim) == 0) {
+ *stride = buffer_dim.sliceWidth;
+ *height = buffer_dim.sliceHeight;
+ } else {
+ *stride = hnd->width;
+ *height = hnd->height;
+ }
+ } break;
+
+ case GRALLOC_MODULE_PERFORM_GET_ATTRIBUTES: {
+ // TODO(user): Usage is split now. take care of it from Gfx client.
+ // see if we can directly expect descriptor from gfx client.
+ int width = va_arg(args, int);
+ int height = va_arg(args, int);
+ int format = va_arg(args, int);
+ uint64_t producer_usage = va_arg(args, uint64_t);
+ uint64_t consumer_usage = va_arg(args, uint64_t);
+ gralloc1_producer_usage_t prod_usage = static_cast<gralloc1_producer_usage_t>(producer_usage);
+ gralloc1_consumer_usage_t cons_usage = static_cast<gralloc1_consumer_usage_t>(consumer_usage);
+
+ int *aligned_width = va_arg(args, int *);
+ int *aligned_height = va_arg(args, int *);
+ int *tile_enabled = va_arg(args, int *);
+ if (!aligned_width || !aligned_height || !tile_enabled) {
+ return GRALLOC1_ERROR_BAD_VALUE;
+ }
+
+ unsigned int alignedw, alignedh;
+ BufferInfo info(width, height, format, prod_usage, cons_usage);
+ *tile_enabled = IsUBwcEnabled(format, prod_usage, cons_usage);
+ GetAlignedWidthAndHeight(info, &alignedw, &alignedh);
+ *aligned_width = INT(alignedw);
+ *aligned_height = INT(alignedh);
+ } break;
+
+ case GRALLOC_MODULE_PERFORM_GET_COLOR_SPACE_FROM_HANDLE: {
+ private_handle_t *hnd = va_arg(args, private_handle_t *);
+ int *color_space = va_arg(args, int *);
+
+ if (private_handle_t::validate(hnd) != 0) {
+ return GRALLOC1_ERROR_BAD_HANDLE;
+ }
+
+ if (!color_space) {
+ return GRALLOC1_ERROR_BAD_VALUE;
+ }
+
+ *color_space = 0;
+ ColorMetaData color_metadata;
+ if (getMetaData(hnd, GET_COLOR_METADATA, &color_metadata) == 0) {
+ switch (color_metadata.colorPrimaries) {
+ case ColorPrimaries_BT709_5:
+ *color_space = HAL_CSC_ITU_R_709;
+ break;
+ case ColorPrimaries_BT601_6_525:
+ *color_space = ((color_metadata.range) ? HAL_CSC_ITU_R_601_FR : HAL_CSC_ITU_R_601);
+ break;
+ case ColorPrimaries_BT2020:
+ *color_space = (color_metadata.range) ? HAL_CSC_ITU_R_2020_FR : HAL_CSC_ITU_R_2020;
+ break;
+ default:
+ ALOGE("Unknown Color Space = %d", color_metadata.colorPrimaries);
+ break;
+ }
+ break;
+ } else if (getMetaData(hnd, GET_COLOR_SPACE, color_space) != 0) {
+ *color_space = 0;
+ }
+ } break;
+ case GRALLOC_MODULE_PERFORM_GET_YUV_PLANE_INFO: {
+ private_handle_t *hnd = va_arg(args, private_handle_t *);
+ android_ycbcr *ycbcr = va_arg(args, struct android_ycbcr *);
+ if (private_handle_t::validate(hnd) != 0) {
+ return GRALLOC1_ERROR_BAD_HANDLE;
+ }
+
+ if (!ycbcr) {
+ return GRALLOC1_ERROR_BAD_VALUE;
+ }
+
+ if (GetYUVPlaneInfo(hnd, ycbcr)) {
+ return GRALLOC1_ERROR_UNDEFINED;
+ }
+ } break;
+
+ case GRALLOC_MODULE_PERFORM_GET_MAP_SECURE_BUFFER_INFO: {
+ private_handle_t *hnd = va_arg(args, private_handle_t *);
+ int *map_secure_buffer = va_arg(args, int *);
+
+ if (private_handle_t::validate(hnd) != 0) {
+ return GRALLOC1_ERROR_BAD_HANDLE;
+ }
+
+ if (!map_secure_buffer) {
+ return GRALLOC1_ERROR_BAD_VALUE;
+ }
+
+ if (getMetaData(hnd, GET_MAP_SECURE_BUFFER, map_secure_buffer) == 0) {
+ *map_secure_buffer = 0;
+ }
+ } break;
+
+ case GRALLOC_MODULE_PERFORM_GET_UBWC_FLAG: {
+ private_handle_t *hnd = va_arg(args, private_handle_t *);
+ int *flag = va_arg(args, int *);
+
+ if (private_handle_t::validate(hnd) != 0) {
+ return GRALLOC1_ERROR_BAD_HANDLE;
+ }
+
+ if (!flag) {
+ return GRALLOC1_ERROR_BAD_VALUE;
+ }
+
+ *flag = hnd->flags &private_handle_t::PRIV_FLAGS_UBWC_ALIGNED;
+ int linear_format = 0;
+ if (getMetaData(hnd, GET_LINEAR_FORMAT, &linear_format) == 0) {
+ if (linear_format) {
+ *flag = 0;
+ }
+ }
+ } break;
+
+ case GRALLOC_MODULE_PERFORM_GET_RGB_DATA_ADDRESS: {
+ private_handle_t *hnd = va_arg(args, private_handle_t *);
+ void **rgb_data = va_arg(args, void **);
+
+ if (private_handle_t::validate(hnd) != 0) {
+ return GRALLOC1_ERROR_BAD_HANDLE;
+ }
+
+ if (!rgb_data) {
+ return GRALLOC1_ERROR_BAD_VALUE;
+ }
+
+ if (GetRgbDataAddress(hnd, rgb_data)) {
+ return GRALLOC1_ERROR_UNDEFINED;
+ }
+ } break;
+
+ case GRALLOC1_MODULE_PERFORM_GET_BUFFER_SIZE_AND_DIMENSIONS: {
+ int width = va_arg(args, int);
+ int height = va_arg(args, int);
+ int format = va_arg(args, int);
+ uint64_t p_usage = va_arg(args, uint64_t);
+ uint64_t c_usage = va_arg(args, uint64_t);
+ gralloc1_producer_usage_t producer_usage = static_cast<gralloc1_producer_usage_t>(p_usage);
+ gralloc1_consumer_usage_t consumer_usage = static_cast<gralloc1_consumer_usage_t>(c_usage);
+ uint32_t *aligned_width = va_arg(args, uint32_t *);
+ uint32_t *aligned_height = va_arg(args, uint32_t *);
+ uint32_t *size = va_arg(args, uint32_t *);
+
+ if (!aligned_width || !aligned_height || !size) {
+ return GRALLOC1_ERROR_BAD_VALUE;
+ }
+
+ auto info = BufferInfo(width, height, format, producer_usage, consumer_usage);
+ GetBufferSizeAndDimensions(info, size, aligned_width, aligned_height);
+ // Align size
+ auto align = GetDataAlignment(format, producer_usage, consumer_usage);
+ *size = ALIGN(*size, align);
+ } break;
+
+ case GRALLOC1_MODULE_PERFORM_ALLOCATE_BUFFER: {
+ std::lock_guard<std::mutex> lock(buffer_lock_);
+ int width = va_arg(args, int);
+ int height = va_arg(args, int);
+ int format = va_arg(args, int);
+ uint64_t p_usage = va_arg(args, uint64_t);
+ uint64_t c_usage = va_arg(args, uint64_t);
+ buffer_handle_t *hnd = va_arg(args, buffer_handle_t*);
+ gralloc1_producer_usage_t producer_usage = static_cast<gralloc1_producer_usage_t>(p_usage);
+ gralloc1_consumer_usage_t consumer_usage = static_cast<gralloc1_consumer_usage_t>(c_usage);
+ BufferDescriptor descriptor(width, height, format, producer_usage, consumer_usage);
+ unsigned int size;
+ unsigned int alignedw, alignedh;
+ GetBufferSizeAndDimensions(GetBufferInfo(descriptor), &size, &alignedw, &alignedh);
+ AllocateBuffer(descriptor, hnd, size);
+ } break;
+
+ case GRALLOC1_MODULE_PERFORM_GET_INTERLACE_FLAG: {
+ private_handle_t *hnd = va_arg(args, private_handle_t *);
+ int *flag = va_arg(args, int *);
+
+ if (private_handle_t::validate(hnd) != 0) {
+ return GRALLOC1_ERROR_BAD_HANDLE;
+ }
+
+ if (!flag) {
+ return GRALLOC1_ERROR_BAD_VALUE;
+ }
+
+ if (getMetaData(hnd, GET_PP_PARAM_INTERLACED, flag) != 0) {
+ *flag = 0;
+ }
+ } break;
+
+ default:
+ break;
+ }
+ return GRALLOC1_ERROR_NONE;
+}
+
+static bool IsYuvFormat(const private_handle_t *hnd) {
+ switch (hnd->format) {
+ case HAL_PIXEL_FORMAT_YCbCr_420_SP:
+ case HAL_PIXEL_FORMAT_YCbCr_422_SP:
+ case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
+ case HAL_PIXEL_FORMAT_NV12_ENCODEABLE: // Same as YCbCr_420_SP_VENUS
+ case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC:
+ case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+ case HAL_PIXEL_FORMAT_YCrCb_422_SP:
+ case HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO:
+ case HAL_PIXEL_FORMAT_NV21_ZSL:
+ case HAL_PIXEL_FORMAT_RAW16:
+ case HAL_PIXEL_FORMAT_Y16:
+ case HAL_PIXEL_FORMAT_RAW12:
+ case HAL_PIXEL_FORMAT_RAW10:
+ case HAL_PIXEL_FORMAT_YV12:
+ case HAL_PIXEL_FORMAT_Y8:
+ return true;
+ default:
+ return false;
+ }
+}
+
+gralloc1_error_t BufferManager::GetNumFlexPlanes(const private_handle_t *hnd,
+ uint32_t *out_num_planes) {
+ if (!IsYuvFormat(hnd)) {
+ return GRALLOC1_ERROR_UNSUPPORTED;
+ } else {
+ *out_num_planes = 3;
+ }
+ return GRALLOC1_ERROR_NONE;
+}
+
+gralloc1_error_t BufferManager::GetFlexLayout(const private_handle_t *hnd,
+ struct android_flex_layout *layout) {
+ if (!IsYuvFormat(hnd)) {
+ return GRALLOC1_ERROR_UNSUPPORTED;
+ }
+
+ android_ycbcr ycbcr;
+ int err = GetYUVPlaneInfo(hnd, &ycbcr);
+
+ if (err != 0) {
+ return GRALLOC1_ERROR_BAD_HANDLE;
+ }
+
+ layout->format = FLEX_FORMAT_YCbCr;
+ layout->num_planes = 3;
+
+ for (uint32_t i = 0; i < layout->num_planes; i++) {
+ layout->planes[i].bits_per_component = 8;
+ layout->planes[i].bits_used = 8;
+ layout->planes[i].h_increment = 1;
+ layout->planes[i].v_increment = 1;
+ layout->planes[i].h_subsampling = 2;
+ layout->planes[i].v_subsampling = 2;
+ }
+
+ layout->planes[0].top_left = static_cast<uint8_t *>(ycbcr.y);
+ layout->planes[0].component = FLEX_COMPONENT_Y;
+ layout->planes[0].v_increment = static_cast<int32_t>(ycbcr.ystride);
+
+ layout->planes[1].top_left = static_cast<uint8_t *>(ycbcr.cb);
+ layout->planes[1].component = FLEX_COMPONENT_Cb;
+ layout->planes[1].h_increment = static_cast<int32_t>(ycbcr.chroma_step);
+ layout->planes[1].v_increment = static_cast<int32_t>(ycbcr.cstride);
+
+ layout->planes[2].top_left = static_cast<uint8_t *>(ycbcr.cr);
+ layout->planes[2].component = FLEX_COMPONENT_Cr;
+ layout->planes[2].h_increment = static_cast<int32_t>(ycbcr.chroma_step);
+ layout->planes[2].v_increment = static_cast<int32_t>(ycbcr.cstride);
+ return GRALLOC1_ERROR_NONE;
+}
+
+gralloc1_error_t BufferManager::Dump(std::ostringstream *os) {
+ for (auto it : handles_map_) {
+ auto buf = it.second;
+ auto hnd = buf->handle;
+ *os << "handle id: " << std::setw(4) << hnd->id;
+ *os << " fd: " << std::setw(3) << hnd->fd;
+ *os << " fd_meta: " << std::setw(3) << hnd->fd_metadata;
+ *os << " wxh: " << std::setw(4) << hnd->width <<" x " << std::setw(4) << hnd->height;
+ *os << " uwxuh: " << std::setw(4) << hnd->unaligned_width << " x ";
+ *os << std::setw(4) << hnd->unaligned_height;
+ *os << " size: " << std::setw(9) << hnd->size;
+ *os << std::hex << std::setfill('0');
+ *os << " priv_flags: " << "0x" << std::setw(8) << hnd->flags;
+ *os << " prod_usage: " << "0x" << std::setw(8) << hnd->producer_usage;
+ *os << " cons_usage: " << "0x" << std::setw(8) << hnd->consumer_usage;
+ // TODO(user): get format string from qdutils
+ *os << " format: " << "0x" << std::setw(8) << hnd->format;
+ *os << std::dec << std::setfill(' ') << std::endl;
+ }
+ return GRALLOC1_ERROR_NONE;
+}
+} // namespace gralloc1
diff --git a/msm8909/gralloc/gr_buf_mgr.h b/msm8909/gralloc/gr_buf_mgr.h
new file mode 100644
index 00000000..861a7a7b
--- /dev/null
+++ b/msm8909/gralloc/gr_buf_mgr.h
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 2011-2017, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ *
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __GR_BUF_MGR_H__
+#define __GR_BUF_MGR_H__
+
+#include <pthread.h>
+#include <unordered_map>
+#include <unordered_set>
+#include <utility>
+#include <mutex>
+
+#include "gralloc_priv.h"
+#include "gr_allocator.h"
+#include "gr_buf_descriptor.h"
+
+namespace gralloc1 {
+
+class BufferManager {
+ public:
+ ~BufferManager();
+ gralloc1_error_t CreateBufferDescriptor(gralloc1_buffer_descriptor_t *descriptor_id);
+ gralloc1_error_t DestroyBufferDescriptor(gralloc1_buffer_descriptor_t descriptor_id);
+ gralloc1_error_t AllocateBuffers(uint32_t num_descriptors,
+ const gralloc1_buffer_descriptor_t *descriptor_ids,
+ buffer_handle_t *out_buffers);
+ gralloc1_error_t RetainBuffer(private_handle_t const *hnd);
+ gralloc1_error_t ReleaseBuffer(private_handle_t const *hnd);
+ gralloc1_error_t LockBuffer(const private_handle_t *hnd, gralloc1_producer_usage_t prod_usage,
+ gralloc1_consumer_usage_t cons_usage);
+ gralloc1_error_t UnlockBuffer(const private_handle_t *hnd);
+ gralloc1_error_t Perform(int operation, va_list args);
+ gralloc1_error_t GetFlexLayout(const private_handle_t *hnd, struct android_flex_layout *layout);
+ gralloc1_error_t GetNumFlexPlanes(const private_handle_t *hnd, uint32_t *out_num_planes);
+ gralloc1_error_t Dump(std::ostringstream *os);
+
+ template <typename... Args>
+ gralloc1_error_t CallBufferDescriptorFunction(gralloc1_buffer_descriptor_t descriptor_id,
+ void (BufferDescriptor::*member)(Args...),
+ Args... args) {
+ std::lock_guard<std::mutex> lock(descriptor_lock_);
+ const auto map_descriptor = descriptors_map_.find(descriptor_id);
+ if (map_descriptor == descriptors_map_.end()) {
+ return GRALLOC1_ERROR_BAD_DESCRIPTOR;
+ }
+ const auto descriptor = map_descriptor->second;
+ (descriptor.get()->*member)(std::forward<Args>(args)...);
+ return GRALLOC1_ERROR_NONE;
+ }
+
+ static BufferManager* GetInstance() {
+ static BufferManager *instance = new BufferManager();
+ return instance;
+ }
+
+ private:
+ BufferManager();
+ gralloc1_error_t MapBuffer(private_handle_t const *hnd);
+ int GetBufferType(int format);
+ int AllocateBuffer(const BufferDescriptor &descriptor, buffer_handle_t *handle,
+ unsigned int bufferSize = 0);
+ uint32_t GetDataAlignment(int format, gralloc1_producer_usage_t prod_usage,
+ gralloc1_consumer_usage_t cons_usage);
+ int GetHandleFlags(int format, gralloc1_producer_usage_t prod_usage,
+ gralloc1_consumer_usage_t cons_usage);
+ void CreateSharedHandle(buffer_handle_t inbuffer, const BufferDescriptor &descriptor,
+ buffer_handle_t *out_buffer);
+
+ // Imports the ion fds into the current process. Returns an error for invalid handles
+ gralloc1_error_t ImportHandleLocked(private_handle_t *hnd);
+
+ // Creates a Buffer from the valid private handle and adds it to the map
+ void RegisterHandleLocked(const private_handle_t *hnd, int ion_handle, int ion_handle_meta);
+
+ // Wrapper structure over private handle
+ // Values associated with the private handle
+ // that do not need to go over IPC can be placed here
+ // This structure is also not expected to be ABI stable
+ // unlike private_handle_t
+ struct Buffer {
+ const private_handle_t *handle = nullptr;
+ int ref_count = 1;
+ // Hold the main and metadata ion handles
+ // Freed from the allocator process
+ // and unused in the mapping process
+ int ion_handle_main = -1;
+ int ion_handle_meta = -1;
+
+ Buffer() = delete;
+ explicit Buffer(const private_handle_t* h, int ih_main = -1, int ih_meta = -1):
+ handle(h),
+ ion_handle_main(ih_main),
+ ion_handle_meta(ih_meta) {
+ }
+ void IncRef() { ++ref_count; }
+ bool DecRef() { return --ref_count == 0; }
+ };
+
+ gralloc1_error_t FreeBuffer(std::shared_ptr<Buffer> buf);
+
+ // Get the wrapper Buffer object from the handle, returns nullptr if handle is not found
+ std::shared_ptr<Buffer> GetBufferFromHandleLocked(const private_handle_t *hnd);
+
+ bool map_fb_mem_ = false;
+ Allocator *allocator_ = NULL;
+ std::mutex buffer_lock_;
+ std::mutex descriptor_lock_;
+ // TODO(user): The private_handle_t is used as a key because the unique ID generated
+ // from next_id_ is not unique across processes. The correct way to resolve this would
+ // be to use the allocator over hwbinder
+ std::unordered_map<const private_handle_t*, std::shared_ptr<Buffer>> handles_map_ = {};
+ std::unordered_map<gralloc1_buffer_descriptor_t,
+ std::shared_ptr<BufferDescriptor>> descriptors_map_ = {};
+ std::atomic<uint64_t> next_id_;
+};
+
+} // namespace gralloc1
+
+#endif // __GR_BUF_MGR_H__
diff --git a/msm8909/gralloc/gr_device_impl.cpp b/msm8909/gralloc/gr_device_impl.cpp
new file mode 100644
index 00000000..7a3c16db
--- /dev/null
+++ b/msm8909/gralloc/gr_device_impl.cpp
@@ -0,0 +1,530 @@
+/*
+ * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <log/log.h>
+#include <sync/sync.h>
+#include <algorithm>
+#include <sstream>
+#include <string>
+
+#include "gr_device_impl.h"
+#include "gr_buf_descriptor.h"
+#include "gralloc_priv.h"
+#include "qd_utils.h"
+#include "qdMetaData.h"
+#include "gr_utils.h"
+
+int gralloc_device_open(const struct hw_module_t *module, const char *name, hw_device_t **device);
+
+int gralloc_device_close(struct hw_device_t *device);
+
+static struct hw_module_methods_t gralloc_module_methods = {.open = gralloc_device_open};
+
+struct gralloc_module_t HAL_MODULE_INFO_SYM = {
+ .common = {
+ .tag = HARDWARE_MODULE_TAG,
+ .module_api_version = GRALLOC_MODULE_API_VERSION_1_0,
+ .hal_api_version = HARDWARE_HAL_API_VERSION,
+ .id = GRALLOC_HARDWARE_MODULE_ID,
+ .name = "Graphics Memory Module",
+ .author = "Code Aurora Forum",
+ .methods = &gralloc_module_methods,
+ .dso = 0,
+ .reserved = {0},
+ },
+};
+
+int gralloc_device_open(const struct hw_module_t *module, const char *name, hw_device_t **device) {
+ int status = -EINVAL;
+ if (!strcmp(name, GRALLOC_HARDWARE_MODULE_ID)) {
+ gralloc1::GrallocImpl * /*gralloc1_device_t*/ dev = gralloc1::GrallocImpl::GetInstance(module);
+ *device = reinterpret_cast<hw_device_t *>(dev);
+ if (dev) {
+ status = 0;
+ } else {
+ ALOGE("Fatal error opening gralloc1 device");
+ }
+ }
+ return status;
+}
+
+namespace gralloc1 {
+
+GrallocImpl::GrallocImpl(const hw_module_t *module) {
+ common.tag = HARDWARE_DEVICE_TAG;
+ common.version = GRALLOC_MODULE_API_VERSION_1_0;
+ common.module = const_cast<hw_module_t *>(module);
+ common.close = CloseDevice;
+ getFunction = GetFunction;
+ getCapabilities = GetCapabilities;
+
+ initalized_ = Init();
+}
+
+bool GrallocImpl::Init() {
+ buf_mgr_ = BufferManager::GetInstance();
+ return buf_mgr_ != nullptr;
+}
+
+GrallocImpl::~GrallocImpl() {
+}
+
+int GrallocImpl::CloseDevice(hw_device_t *device __unused) {
+ // No-op since the gralloc device is a singleton
+ return 0;
+}
+
+void GrallocImpl::GetCapabilities(struct gralloc1_device *device, uint32_t *out_count,
+ int32_t /*gralloc1_capability_t*/ *out_capabilities) {
+ if (device != nullptr) {
+ if (out_capabilities != nullptr && *out_count >= 3) {
+ out_capabilities[0] = GRALLOC1_CAPABILITY_TEST_ALLOCATE;
+ out_capabilities[1] = GRALLOC1_CAPABILITY_LAYERED_BUFFERS;
+ out_capabilities[2] = GRALLOC1_CAPABILITY_RELEASE_IMPLY_DELETE;
+ }
+ *out_count = 3;
+ }
+ return;
+}
+
+gralloc1_function_pointer_t GrallocImpl::GetFunction(gralloc1_device_t *device, int32_t function) {
+ if (!device) {
+ return NULL;
+ }
+
+ switch (function) {
+ case GRALLOC1_FUNCTION_DUMP:
+ return reinterpret_cast<gralloc1_function_pointer_t>(Dump);
+ case GRALLOC1_FUNCTION_CREATE_DESCRIPTOR:
+ return reinterpret_cast<gralloc1_function_pointer_t>(CreateBufferDescriptor);
+ case GRALLOC1_FUNCTION_DESTROY_DESCRIPTOR:
+ return reinterpret_cast<gralloc1_function_pointer_t>(DestroyBufferDescriptor);
+ case GRALLOC1_FUNCTION_SET_CONSUMER_USAGE:
+ return reinterpret_cast<gralloc1_function_pointer_t>(SetConsumerUsage);
+ case GRALLOC1_FUNCTION_SET_DIMENSIONS:
+ return reinterpret_cast<gralloc1_function_pointer_t>(SetBufferDimensions);
+ case GRALLOC1_FUNCTION_SET_FORMAT:
+ return reinterpret_cast<gralloc1_function_pointer_t>(SetColorFormat);
+ case GRALLOC1_FUNCTION_SET_LAYER_COUNT:
+ return reinterpret_cast<gralloc1_function_pointer_t>(SetLayerCount);
+ case GRALLOC1_FUNCTION_SET_PRODUCER_USAGE:
+ return reinterpret_cast<gralloc1_function_pointer_t>(SetProducerUsage);
+ case GRALLOC1_FUNCTION_GET_BACKING_STORE:
+ return reinterpret_cast<gralloc1_function_pointer_t>(GetBackingStore);
+ case GRALLOC1_FUNCTION_GET_CONSUMER_USAGE:
+ return reinterpret_cast<gralloc1_function_pointer_t>(GetConsumerUsage);
+ case GRALLOC1_FUNCTION_GET_DIMENSIONS:
+ return reinterpret_cast<gralloc1_function_pointer_t>(GetBufferDimensions);
+ case GRALLOC1_FUNCTION_GET_FORMAT:
+ return reinterpret_cast<gralloc1_function_pointer_t>(GetColorFormat);
+ case GRALLOC1_FUNCTION_GET_LAYER_COUNT:
+ return reinterpret_cast<gralloc1_function_pointer_t>(GetLayerCount);
+ case GRALLOC1_FUNCTION_GET_PRODUCER_USAGE:
+ return reinterpret_cast<gralloc1_function_pointer_t>(GetProducerUsage);
+ case GRALLOC1_FUNCTION_GET_STRIDE:
+ return reinterpret_cast<gralloc1_function_pointer_t>(GetBufferStride);
+ case GRALLOC1_FUNCTION_ALLOCATE:
+ return reinterpret_cast<gralloc1_function_pointer_t>(AllocateBuffers);
+ case GRALLOC1_FUNCTION_RETAIN:
+ return reinterpret_cast<gralloc1_function_pointer_t>(RetainBuffer);
+ case GRALLOC1_FUNCTION_RELEASE:
+ return reinterpret_cast<gralloc1_function_pointer_t>(ReleaseBuffer);
+ case GRALLOC1_FUNCTION_GET_NUM_FLEX_PLANES:
+ return reinterpret_cast<gralloc1_function_pointer_t>(GetNumFlexPlanes);
+ case GRALLOC1_FUNCTION_LOCK:
+ return reinterpret_cast<gralloc1_function_pointer_t>(LockBuffer);
+ case GRALLOC1_FUNCTION_LOCK_FLEX:
+ return reinterpret_cast<gralloc1_function_pointer_t>(LockFlex);
+ case GRALLOC1_FUNCTION_UNLOCK:
+ return reinterpret_cast<gralloc1_function_pointer_t>(UnlockBuffer);
+ case GRALLOC1_FUNCTION_PERFORM:
+ return reinterpret_cast<gralloc1_function_pointer_t>(Gralloc1Perform);
+ default:
+ ALOGE("%s:Gralloc Error. Client Requested for unsupported function", __FUNCTION__);
+ return NULL;
+ }
+
+ return NULL;
+}
+
+gralloc1_error_t GrallocImpl::Dump(gralloc1_device_t *device, uint32_t *out_size,
+ char *out_buffer) {
+ if (!device) {
+ ALOGE("Gralloc Error : device=%p", (void *)device);
+ return GRALLOC1_ERROR_BAD_DESCRIPTOR;
+ }
+ const size_t max_dump_size = 8192;
+ if (out_buffer == nullptr) {
+ *out_size = max_dump_size;
+ } else {
+ std::ostringstream os;
+ os << "-------------------------------" << std::endl;
+ os << "QTI gralloc dump:" << std::endl;
+ os << "-------------------------------" << std::endl;
+ GrallocImpl const *dev = GRALLOC_IMPL(device);
+ dev->buf_mgr_->Dump(&os);
+ os << "-------------------------------" << std::endl;
+ auto copied = os.str().copy(out_buffer, std::min(os.str().size(), max_dump_size), 0);
+ *out_size = UINT(copied);
+ }
+
+ return GRALLOC1_ERROR_NONE;
+}
+
+gralloc1_error_t GrallocImpl::CheckDeviceAndHandle(gralloc1_device_t *device,
+ buffer_handle_t buffer) {
+ const private_handle_t *hnd = PRIV_HANDLE_CONST(buffer);
+ if (!device || (private_handle_t::validate(hnd) != 0)) {
+ ALOGE("Gralloc Error : device= %p, buffer-handle=%p", (void *)device, (void *)buffer);
+ return GRALLOC1_ERROR_BAD_HANDLE;
+ }
+
+ return GRALLOC1_ERROR_NONE;
+}
+
+gralloc1_error_t GrallocImpl::CreateBufferDescriptor(gralloc1_device_t *device,
+ gralloc1_buffer_descriptor_t *out_descriptor) {
+ if (!device) {
+ return GRALLOC1_ERROR_BAD_DESCRIPTOR;
+ }
+ GrallocImpl const *dev = GRALLOC_IMPL(device);
+ return dev->buf_mgr_->CreateBufferDescriptor(out_descriptor);
+}
+
+gralloc1_error_t GrallocImpl::DestroyBufferDescriptor(gralloc1_device_t *device,
+ gralloc1_buffer_descriptor_t descriptor) {
+ if (!device) {
+ return GRALLOC1_ERROR_BAD_DESCRIPTOR;
+ }
+ GrallocImpl const *dev = GRALLOC_IMPL(device);
+ return dev->buf_mgr_->DestroyBufferDescriptor(descriptor);
+}
+
+gralloc1_error_t GrallocImpl::SetConsumerUsage(gralloc1_device_t *device,
+ gralloc1_buffer_descriptor_t descriptor,
+ gralloc1_consumer_usage_t usage) {
+ if (!device) {
+ return GRALLOC1_ERROR_BAD_DESCRIPTOR;
+ } else {
+ GrallocImpl const *dev = GRALLOC_IMPL(device);
+ return dev->buf_mgr_->CallBufferDescriptorFunction(descriptor,
+ &BufferDescriptor::SetConsumerUsage, usage);
+ }
+}
+
+gralloc1_error_t GrallocImpl::SetBufferDimensions(gralloc1_device_t *device,
+ gralloc1_buffer_descriptor_t descriptor,
+ uint32_t width, uint32_t height) {
+ if (!device) {
+ return GRALLOC1_ERROR_BAD_DESCRIPTOR;
+ } else {
+ GrallocImpl const *dev = GRALLOC_IMPL(device);
+ return dev->buf_mgr_->CallBufferDescriptorFunction(descriptor,
+ &BufferDescriptor::SetDimensions,
+ INT(width), INT(height));
+ }
+}
+
+gralloc1_error_t GrallocImpl::SetColorFormat(gralloc1_device_t *device,
+ gralloc1_buffer_descriptor_t descriptor,
+ int32_t format) {
+ if (!device) {
+ return GRALLOC1_ERROR_BAD_DESCRIPTOR;
+ } else {
+ GrallocImpl const *dev = GRALLOC_IMPL(device);
+ return dev->buf_mgr_->CallBufferDescriptorFunction(descriptor,
+ &BufferDescriptor::SetColorFormat, format);
+ }
+}
+
+gralloc1_error_t GrallocImpl::SetLayerCount(gralloc1_device_t *device,
+ gralloc1_buffer_descriptor_t descriptor,
+ uint32_t layer_count) {
+ if (!device) {
+ return GRALLOC1_ERROR_BAD_DESCRIPTOR;
+ } else {
+ GrallocImpl const *dev = GRALLOC_IMPL(device);
+ return dev->buf_mgr_->CallBufferDescriptorFunction(descriptor,
+ &BufferDescriptor::SetLayerCount,
+ layer_count);
+ }
+}
+
+gralloc1_error_t GrallocImpl::SetProducerUsage(gralloc1_device_t *device,
+ gralloc1_buffer_descriptor_t descriptor,
+ gralloc1_producer_usage_t usage) {
+ if (!device) {
+ return GRALLOC1_ERROR_BAD_DESCRIPTOR;
+ } else {
+ GrallocImpl const *dev = GRALLOC_IMPL(device);
+ return dev->buf_mgr_->CallBufferDescriptorFunction(descriptor,
+ &BufferDescriptor::SetProducerUsage, usage);
+ }
+}
+
+gralloc1_error_t GrallocImpl::GetBackingStore(gralloc1_device_t *device, buffer_handle_t buffer,
+ gralloc1_backing_store_t *out_backstore) {
+ if (!device || !buffer) {
+ return GRALLOC1_ERROR_BAD_HANDLE;
+ }
+
+ *out_backstore =
+ static_cast<gralloc1_backing_store_t>(PRIV_HANDLE_CONST(buffer)->GetBackingstore());
+
+ return GRALLOC1_ERROR_NONE;
+}
+
+gralloc1_error_t GrallocImpl::GetConsumerUsage(gralloc1_device_t *device, buffer_handle_t buffer,
+ gralloc1_consumer_usage_t *outUsage) {
+ gralloc1_error_t status = CheckDeviceAndHandle(device, buffer);
+ if (status == GRALLOC1_ERROR_NONE) {
+ *outUsage = PRIV_HANDLE_CONST(buffer)->GetConsumerUsage();
+ }
+
+ return status;
+}
+
+gralloc1_error_t GrallocImpl::GetBufferDimensions(gralloc1_device_t *device, buffer_handle_t buffer,
+ uint32_t *outWidth, uint32_t *outHeight) {
+ gralloc1_error_t status = CheckDeviceAndHandle(device, buffer);
+ if (status == GRALLOC1_ERROR_NONE) {
+ const private_handle_t *hnd = PRIV_HANDLE_CONST(buffer);
+ *outWidth = UINT(hnd->GetUnalignedWidth());
+ *outHeight = UINT(hnd->GetUnalignedHeight());
+ }
+
+ return status;
+}
+
+gralloc1_error_t GrallocImpl::GetColorFormat(gralloc1_device_t *device, buffer_handle_t buffer,
+ int32_t *outFormat) {
+ gralloc1_error_t status = CheckDeviceAndHandle(device, buffer);
+ if (status == GRALLOC1_ERROR_NONE) {
+ *outFormat = PRIV_HANDLE_CONST(buffer)->GetColorFormat();
+ }
+
+ return status;
+}
+
+gralloc1_error_t GrallocImpl::GetLayerCount(gralloc1_device_t *device, buffer_handle_t buffer,
+ uint32_t *outLayerCount) {
+ gralloc1_error_t status = CheckDeviceAndHandle(device, buffer);
+ if (status == GRALLOC1_ERROR_NONE) {
+ *outLayerCount = PRIV_HANDLE_CONST(buffer)->GetLayerCount();
+ }
+
+ return status;
+}
+
+gralloc1_error_t GrallocImpl::GetProducerUsage(gralloc1_device_t *device, buffer_handle_t buffer,
+ gralloc1_producer_usage_t *outUsage) {
+ if (!outUsage) {
+ return GRALLOC1_ERROR_BAD_VALUE;
+ }
+
+ gralloc1_error_t status = CheckDeviceAndHandle(device, buffer);
+ if (status == GRALLOC1_ERROR_NONE) {
+ const private_handle_t *hnd = PRIV_HANDLE_CONST(buffer);
+ *outUsage = hnd->GetProducerUsage();
+ }
+
+ return status;
+}
+
+gralloc1_error_t GrallocImpl::GetBufferStride(gralloc1_device_t *device, buffer_handle_t buffer,
+ uint32_t *outStride) {
+ if (!outStride) {
+ return GRALLOC1_ERROR_BAD_VALUE;
+ }
+
+ gralloc1_error_t status = CheckDeviceAndHandle(device, buffer);
+ if (status == GRALLOC1_ERROR_NONE) {
+ *outStride = UINT(PRIV_HANDLE_CONST(buffer)->GetStride());
+ }
+
+ return status;
+}
+
+gralloc1_error_t GrallocImpl::AllocateBuffers(gralloc1_device_t *device, uint32_t num_descriptors,
+ const gralloc1_buffer_descriptor_t *descriptors,
+ buffer_handle_t *out_buffers) {
+ if (!num_descriptors || !descriptors) {
+ return GRALLOC1_ERROR_BAD_DESCRIPTOR;
+ }
+
+ if (!device) {
+ return GRALLOC1_ERROR_BAD_VALUE;
+ }
+
+ GrallocImpl const *dev = GRALLOC_IMPL(device);
+ gralloc1_error_t status = dev->buf_mgr_->AllocateBuffers(num_descriptors, descriptors,
+ out_buffers);
+
+ return status;
+}
+
+gralloc1_error_t GrallocImpl::RetainBuffer(gralloc1_device_t *device, buffer_handle_t buffer) {
+ gralloc1_error_t status = CheckDeviceAndHandle(device, buffer);
+ if (status == GRALLOC1_ERROR_NONE) {
+ const private_handle_t *hnd = PRIV_HANDLE_CONST(buffer);
+ GrallocImpl const *dev = GRALLOC_IMPL(device);
+ status = dev->buf_mgr_->RetainBuffer(hnd);
+ }
+
+ return status;
+}
+
+gralloc1_error_t GrallocImpl::ReleaseBuffer(gralloc1_device_t *device, buffer_handle_t buffer) {
+ if (!device || !buffer) {
+ return GRALLOC1_ERROR_BAD_DESCRIPTOR;
+ }
+
+ const private_handle_t *hnd = PRIV_HANDLE_CONST(buffer);
+ GrallocImpl const *dev = GRALLOC_IMPL(device);
+ return dev->buf_mgr_->ReleaseBuffer(hnd);
+}
+
+gralloc1_error_t GrallocImpl::GetNumFlexPlanes(gralloc1_device_t *device, buffer_handle_t buffer,
+ uint32_t *out_num_planes) {
+ if (!out_num_planes) {
+ return GRALLOC1_ERROR_BAD_VALUE;
+ }
+
+ gralloc1_error_t status = CheckDeviceAndHandle(device, buffer);
+ if (status == GRALLOC1_ERROR_NONE) {
+ GrallocImpl const *dev = GRALLOC_IMPL(device);
+ const private_handle_t *hnd = PRIV_HANDLE_CONST(buffer);
+ status = dev->buf_mgr_->GetNumFlexPlanes(hnd, out_num_planes);
+ }
+ return status;
+}
+
+static inline void CloseFdIfValid(int fd) {
+ if (fd > 0) {
+ close(fd);
+ }
+}
+
+gralloc1_error_t GrallocImpl::LockBuffer(gralloc1_device_t *device, buffer_handle_t buffer,
+ gralloc1_producer_usage_t prod_usage,
+ gralloc1_consumer_usage_t cons_usage,
+ const gralloc1_rect_t *region, void **out_data,
+ int32_t acquire_fence) {
+ gralloc1_error_t status = CheckDeviceAndHandle(device, buffer);
+ if (status != GRALLOC1_ERROR_NONE || !out_data ||
+ !region) { // currently we ignore the region/rect client wants to lock
+ CloseFdIfValid(acquire_fence);
+ return status;
+ }
+
+ if (acquire_fence > 0) {
+ int error = sync_wait(acquire_fence, 1000);
+ CloseFdIfValid(acquire_fence);
+ if (error < 0) {
+ ALOGE("%s: sync_wait timedout! error = %s", __FUNCTION__, strerror(errno));
+ return GRALLOC1_ERROR_UNDEFINED;
+ }
+ }
+
+ const private_handle_t *hnd = PRIV_HANDLE_CONST(buffer);
+ GrallocImpl const *dev = GRALLOC_IMPL(device);
+
+ // Either producer usage or consumer usage must be *_USAGE_NONE
+ if ((prod_usage != GRALLOC1_PRODUCER_USAGE_NONE) &&
+ (cons_usage != GRALLOC1_CONSUMER_USAGE_NONE)) {
+ // Current gralloc1 clients do not satisfy this restriction.
+ // See b/33588773 for details
+ // return GRALLOC1_ERROR_BAD_VALUE;
+ }
+
+ // TODO(user): Need to check if buffer was allocated with the same flags
+ status = dev->buf_mgr_->LockBuffer(hnd, prod_usage, cons_usage);
+ *out_data = reinterpret_cast<void *>(hnd->base);
+
+ return status;
+}
+
+gralloc1_error_t GrallocImpl::LockFlex(gralloc1_device_t *device, buffer_handle_t buffer,
+ gralloc1_producer_usage_t prod_usage,
+ gralloc1_consumer_usage_t cons_usage,
+ const gralloc1_rect_t *region,
+ struct android_flex_layout *out_flex_layout,
+ int32_t acquire_fence) {
+ if (!out_flex_layout) {
+ CloseFdIfValid(acquire_fence);
+ return GRALLOC1_ERROR_BAD_VALUE;
+ }
+
+ void *out_data {};
+ gralloc1_error_t status = GrallocImpl::LockBuffer(device, buffer, prod_usage, cons_usage, region,
+ &out_data, acquire_fence);
+ if (status != GRALLOC1_ERROR_NONE) {
+ return status;
+ }
+
+ GrallocImpl const *dev = GRALLOC_IMPL(device);
+ const private_handle_t *hnd = PRIV_HANDLE_CONST(buffer);
+ dev->buf_mgr_->GetFlexLayout(hnd, out_flex_layout);
+ return status;
+}
+
+gralloc1_error_t GrallocImpl::UnlockBuffer(gralloc1_device_t *device, buffer_handle_t buffer,
+ int32_t *release_fence) {
+ gralloc1_error_t status = CheckDeviceAndHandle(device, buffer);
+ if (status != GRALLOC1_ERROR_NONE) {
+ return status;
+ }
+
+ if (!release_fence) {
+ return GRALLOC1_ERROR_BAD_VALUE;
+ }
+
+ const private_handle_t *hnd = PRIV_HANDLE_CONST(buffer);
+ GrallocImpl const *dev = GRALLOC_IMPL(device);
+
+ *release_fence = -1;
+
+ return dev->buf_mgr_->UnlockBuffer(hnd);
+}
+
+gralloc1_error_t GrallocImpl::Gralloc1Perform(gralloc1_device_t *device, int operation, ...) {
+ if (!device) {
+ return GRALLOC1_ERROR_BAD_VALUE;
+ }
+
+ va_list args;
+ va_start(args, operation);
+ GrallocImpl const *dev = GRALLOC_IMPL(device);
+ gralloc1_error_t err = dev->buf_mgr_->Perform(operation, args);
+ va_end(args);
+
+ return err;
+}
+
+} // namespace gralloc1
diff --git a/msm8909/gralloc/gr_device_impl.h b/msm8909/gralloc/gr_device_impl.h
new file mode 100644
index 00000000..55ce44b3
--- /dev/null
+++ b/msm8909/gralloc/gr_device_impl.h
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __GR_DEVICE_IMPL_H__
+#define __GR_DEVICE_IMPL_H__
+
+#include <hardware/hardware.h>
+#include <hardware/gralloc1.h>
+#include "gr_buf_mgr.h"
+
+struct private_module_t {
+ hw_module_t base;
+};
+
+#define GRALLOC_IMPL(exp) reinterpret_cast<GrallocImpl const *>(exp)
+
+namespace gralloc1 {
+
+class GrallocImpl : public gralloc1_device_t {
+ public:
+ static int CloseDevice(hw_device_t *device);
+ static void GetCapabilities(struct gralloc1_device *device, uint32_t *out_count,
+ int32_t * /*gralloc1_capability_t*/ out_capabilities);
+ static gralloc1_function_pointer_t GetFunction(
+ struct gralloc1_device *device, int32_t /*gralloc1_function_descriptor_t*/ descriptor);
+
+ static GrallocImpl* GetInstance(const struct hw_module_t *module) {
+ static GrallocImpl *instance = new GrallocImpl(module);
+ if (instance->IsInitialized()) {
+ return instance;
+ } else {
+ return nullptr;
+ }
+ }
+
+ private:
+ static inline gralloc1_error_t Dump(gralloc1_device_t *device, uint32_t *out_size,
+ char *out_buffer);
+ static inline gralloc1_error_t CheckDeviceAndHandle(gralloc1_device_t *device,
+ buffer_handle_t buffer);
+ static gralloc1_error_t CreateBufferDescriptor(gralloc1_device_t *device,
+ gralloc1_buffer_descriptor_t *out_descriptor);
+ static gralloc1_error_t DestroyBufferDescriptor(gralloc1_device_t *device,
+ gralloc1_buffer_descriptor_t descriptor);
+ static gralloc1_error_t SetConsumerUsage(gralloc1_device_t *device,
+ gralloc1_buffer_descriptor_t descriptor,
+ gralloc1_consumer_usage_t usage);
+ static gralloc1_error_t SetBufferDimensions(gralloc1_device_t *device,
+ gralloc1_buffer_descriptor_t descriptor,
+ uint32_t width, uint32_t height);
+ static gralloc1_error_t SetColorFormat(gralloc1_device_t *device,
+ gralloc1_buffer_descriptor_t descriptor, int32_t format);
+ static gralloc1_error_t SetLayerCount(gralloc1_device_t *device,
+ gralloc1_buffer_descriptor_t descriptor,
+ uint32_t layer_count);
+ static gralloc1_error_t SetProducerUsage(gralloc1_device_t *device,
+ gralloc1_buffer_descriptor_t descriptor,
+ gralloc1_producer_usage_t usage);
+ static gralloc1_error_t GetBackingStore(gralloc1_device_t *device, buffer_handle_t buffer,
+ gralloc1_backing_store_t *out_store);
+ static gralloc1_error_t GetConsumerUsage(gralloc1_device_t *device, buffer_handle_t buffer,
+ gralloc1_consumer_usage_t *out_usage);
+ static gralloc1_error_t GetBufferDimensions(gralloc1_device_t *device, buffer_handle_t buffer,
+ uint32_t *out_width, uint32_t *out_height);
+ static gralloc1_error_t GetColorFormat(gralloc1_device_t *device, buffer_handle_t descriptor,
+ int32_t *outFormat);
+ static gralloc1_error_t GetLayerCount(gralloc1_device_t *device, buffer_handle_t buffer,
+ uint32_t *out_layer_count);
+ static gralloc1_error_t GetProducerUsage(gralloc1_device_t *device, buffer_handle_t buffer,
+ gralloc1_producer_usage_t *out_usage);
+ static gralloc1_error_t GetBufferStride(gralloc1_device_t *device, buffer_handle_t buffer,
+ uint32_t *out_stride);
+ static gralloc1_error_t AllocateBuffers(gralloc1_device_t *device, uint32_t num_dptors,
+ const gralloc1_buffer_descriptor_t *descriptors,
+ buffer_handle_t *out_buffers);
+ static gralloc1_error_t RetainBuffer(gralloc1_device_t *device, buffer_handle_t buffer);
+ static gralloc1_error_t ReleaseBuffer(gralloc1_device_t *device, buffer_handle_t buffer);
+ static gralloc1_error_t GetNumFlexPlanes(gralloc1_device_t *device, buffer_handle_t buffer,
+ uint32_t *out_num_planes);
+ static gralloc1_error_t LockBuffer(gralloc1_device_t *device, buffer_handle_t buffer,
+ gralloc1_producer_usage_t prod_usage,
+ gralloc1_consumer_usage_t cons_usage,
+ const gralloc1_rect_t *region, void **out_data,
+ int32_t acquire_fence);
+ static gralloc1_error_t LockFlex(gralloc1_device_t *device, buffer_handle_t buffer,
+ gralloc1_producer_usage_t prod_usage,
+ gralloc1_consumer_usage_t cons_usage,
+ const gralloc1_rect_t *region,
+ struct android_flex_layout *out_flex_layout,
+ int32_t acquire_fence);
+
+ static gralloc1_error_t UnlockBuffer(gralloc1_device_t *device, buffer_handle_t buffer,
+ int32_t *release_fence);
+ static gralloc1_error_t Gralloc1Perform(gralloc1_device_t *device, int operation, ...);
+
+ explicit GrallocImpl(const hw_module_t *module);
+ ~GrallocImpl();
+ bool Init();
+ bool IsInitialized() const { return initalized_; }
+
+ BufferManager *buf_mgr_ = NULL;
+ bool initalized_ = false;
+};
+
+} // namespace gralloc1
+
+#endif // __GR_DEVICE_IMPL_H__
diff --git a/msm8909/gralloc/gr_ion_alloc.cpp b/msm8909/gralloc/gr_ion_alloc.cpp
new file mode 100644
index 00000000..680a516a
--- /dev/null
+++ b/msm8909/gralloc/gr_ion_alloc.cpp
@@ -0,0 +1,204 @@
+/*
+ * Copyright (c) 2011-2017, The Linux Foundation. All rights reserved.
+
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#define DEBUG 0
+#define ATRACE_TAG (ATRACE_TAG_GRAPHICS | ATRACE_TAG_HAL)
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <log/log.h>
+#include <errno.h>
+#include <utils/Trace.h>
+
+#include "gralloc_priv.h"
+#include "gr_utils.h"
+#include "gr_ion_alloc.h"
+
+namespace gralloc1 {
+
+bool IonAlloc::Init() {
+ if (ion_dev_fd_ == FD_INIT) {
+ ion_dev_fd_ = open(kIonDevice, O_RDONLY);
+ }
+
+ if (ion_dev_fd_ < 0) {
+ ALOGE("%s: Failed to open ion device - %s", __FUNCTION__, strerror(errno));
+ ion_dev_fd_ = FD_INIT;
+ return false;
+ }
+
+ return true;
+}
+
+void IonAlloc::CloseIonDevice() {
+ if (ion_dev_fd_ > FD_INIT) {
+ close(ion_dev_fd_);
+ }
+
+ ion_dev_fd_ = FD_INIT;
+}
+
+int IonAlloc::AllocBuffer(AllocData *data) {
+ ATRACE_CALL();
+ int err = 0;
+ struct ion_handle_data handle_data;
+ struct ion_fd_data fd_data;
+ struct ion_allocation_data ion_alloc_data;
+
+ ion_alloc_data.len = data->size;
+ ion_alloc_data.align = data->align;
+ ion_alloc_data.heap_id_mask = data->heap_id;
+ ion_alloc_data.flags = data->flags;
+ ion_alloc_data.flags |= data->uncached ? 0 : ION_FLAG_CACHED;
+
+ if (ioctl(ion_dev_fd_, INT(ION_IOC_ALLOC), &ion_alloc_data)) {
+ err = -errno;
+ ALOGE("ION_IOC_ALLOC failed with error - %s", strerror(errno));
+ return err;
+ }
+
+ fd_data.handle = ion_alloc_data.handle;
+ handle_data.handle = ion_alloc_data.handle;
+ if (ioctl(ion_dev_fd_, INT(ION_IOC_MAP), &fd_data)) {
+ err = -errno;
+ ALOGE("%s: ION_IOC_MAP failed with error - %s", __FUNCTION__, strerror(errno));
+ ioctl(ion_dev_fd_, INT(ION_IOC_FREE), &handle_data);
+ return err;
+ }
+
+ data->fd = fd_data.fd;
+ data->ion_handle = handle_data.handle;
+ ALOGD_IF(DEBUG, "ion: Allocated buffer size:%zu fd:%d handle:0x%x",
+ ion_alloc_data.len, data->fd, data->ion_handle);
+
+ return 0;
+}
+
+int IonAlloc::FreeBuffer(void *base, unsigned int size, unsigned int offset, int fd,
+ int ion_handle) {
+ ATRACE_CALL();
+ int err = 0;
+ ALOGD_IF(DEBUG, "ion: Freeing buffer base:%p size:%u fd:%d handle:0x%x", base, size, fd,
+ ion_handle);
+
+ if (base) {
+ err = UnmapBuffer(base, size, offset);
+ }
+
+ if (ion_handle > 0) {
+ struct ion_handle_data handle_data;
+ handle_data.handle = ion_handle;
+ ioctl(ion_dev_fd_, INT(ION_IOC_FREE), &handle_data);
+ }
+ close(fd);
+ return err;
+}
+
+int IonAlloc::MapBuffer(void **base, unsigned int size, unsigned int offset, int fd) {
+ ATRACE_CALL();
+ int err = 0;
+ void *addr = 0;
+
+ // It is a (quirky) requirement of ION to have opened the
+ // ion fd in the process that is doing the mapping
+ addr = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+ *base = addr;
+ if (addr == MAP_FAILED) {
+ err = -errno;
+ ALOGE("ion: Failed to map memory in the client: %s", strerror(errno));
+ } else {
+ ALOGD_IF(DEBUG, "ion: Mapped buffer base:%p size:%u offset:%u fd:%d", addr, size, offset, fd);
+ }
+
+ return err;
+}
+
+int IonAlloc::ImportBuffer(int fd) {
+ struct ion_fd_data fd_data;
+ int err = 0;
+ fd_data.fd = fd;
+ if (ioctl(ion_dev_fd_, INT(ION_IOC_IMPORT), &fd_data)) {
+ err = -errno;
+ ALOGE("%s: ION_IOC_IMPORT failed with error - %s", __FUNCTION__, strerror(errno));
+ return err;
+ }
+ return fd_data.handle;
+}
+
+int IonAlloc::UnmapBuffer(void *base, unsigned int size, unsigned int /*offset*/) {
+ ATRACE_CALL();
+ ALOGD_IF(DEBUG, "ion: Unmapping buffer base:%p size:%u", base, size);
+
+ int err = 0;
+ if (munmap(base, size)) {
+ err = -errno;
+ ALOGE("ion: Failed to unmap memory at %p : %s", base, strerror(errno));
+ }
+
+ return err;
+}
+
+int IonAlloc::CleanBuffer(void *base, unsigned int size, unsigned int offset, int handle, int op) {
+ ATRACE_CALL();
+ ATRACE_INT("operation id", op);
+ struct ion_flush_data flush_data;
+ int err = 0;
+
+ flush_data.handle = handle;
+ flush_data.vaddr = base;
+ // offset and length are unsigned int
+ flush_data.offset = offset;
+ flush_data.length = size;
+
+ struct ion_custom_data d;
+ switch (op) {
+ case CACHE_CLEAN:
+ d.cmd = ION_IOC_CLEAN_CACHES;
+ break;
+ case CACHE_INVALIDATE:
+ d.cmd = ION_IOC_INV_CACHES;
+ break;
+ case CACHE_CLEAN_AND_INVALIDATE:
+ default:
+ d.cmd = ION_IOC_CLEAN_INV_CACHES;
+ }
+
+ d.arg = (unsigned long)(&flush_data); // NOLINT
+ if (ioctl(ion_dev_fd_, INT(ION_IOC_CUSTOM), &d)) {
+ err = -errno;
+ ALOGE("%s: ION_IOC_CLEAN_INV_CACHES failed with error - %s", __FUNCTION__, strerror(errno));
+ return err;
+ }
+
+ return 0;
+}
+
+} // namespace gralloc1
diff --git a/msm8909/libhdmi/hdmi_stub.cpp b/msm8909/gralloc/gr_ion_alloc.h
index 9ba9b602..b25f509b 100644
--- a/msm8909/libhdmi/hdmi_stub.cpp
+++ b/msm8909/gralloc/gr_ion_alloc.h
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 2016, The Linux Foundation. All rights reserved.
- *
+ * Copyright (c) 2011-2017, The Linux Foundation. All rights reserved.
+
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
@@ -27,59 +27,58 @@
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include "hwc_utils.h"
-#include "hdmi.h"
+#ifndef __GR_ION_ALLOC_H__
+#define __GR_ION_ALLOC_H__
-namespace qhwc {
+#include <linux/msm_ion.h>
-HDMIDisplay::HDMIDisplay() : mFd(-1), mCurrentMode(-1), mModeCount(0),
- mPrimaryWidth(0), mPrimaryHeight(0), mUnderscanSupported(false) {
- ALOGV("%s stub", __FUNCTION__);
-}
+#define FD_INIT -1
-HDMIDisplay::~HDMIDisplay() {
- ALOGV("%s stub", __FUNCTION__);
-}
+namespace gralloc1 {
-void HDMIDisplay::setHPD(uint32_t value) {
- ALOGV("%s stub", __FUNCTION__);
- (void) value;
-}
-
-bool HDMIDisplay::isHDMIPrimaryDisplay() {
- ALOGV("%s stub", __FUNCTION__);
- return false;
-}
+enum {
+ CACHE_CLEAN = 0x1,
+ CACHE_INVALIDATE,
+ CACHE_CLEAN_AND_INVALIDATE,
+};
-int HDMIDisplay::getConnectedState() {
- ALOGV("%s stub", __FUNCTION__);
- return -1;
-}
+struct AllocData {
+ void *base = NULL;
+ int fd = -1;
+ int ion_handle = -1;
+ unsigned int offset = 0;
+ unsigned int size = 0;
+ unsigned int align = 1;
+ uintptr_t handle = 0;
+ bool uncached = false;
+ unsigned int flags = 0x0;
+ unsigned int heap_id = 0x0;
+ unsigned int alloc_type = 0x0;
+};
-void HDMIDisplay::activateDisplay() {
- ALOGV("%s stub", __FUNCTION__);
-}
+class IonAlloc {
+ public:
+ IonAlloc() { ion_dev_fd_ = FD_INIT; }
-void HDMIDisplay::getAttributes(uint32_t& width, uint32_t& height) {
- ALOGV("%s stub", __FUNCTION__);
- width = height = 0;
-}
+ ~IonAlloc() { CloseIonDevice(); }
-int HDMIDisplay::configure() {
- ALOGV("%s stub", __FUNCTION__);
- return -1;
-}
+ bool Init();
+ int AllocBuffer(AllocData *data);
+ int FreeBuffer(void *base, unsigned int size, unsigned int offset, int fd, int ion_handle);
+ int MapBuffer(void **base, unsigned int size, unsigned int offset, int fd);
+ int ImportBuffer(int fd);
+ int UnmapBuffer(void *base, unsigned int size, unsigned int offset);
+ int CleanBuffer(void *base, unsigned int size, unsigned int offset, int handle, int op);
-int HDMIDisplay::teardown() {
- ALOGV("%s stub", __FUNCTION__);
- return 0;
-}
+ private:
+ const char *kIonDevice = "/dev/ion";
-void HDMIDisplay::setPrimaryAttributes(uint32_t primaryWidth,
- uint32_t primaryHeight) {
- ALOGV("%s stub", __FUNCTION__);
- (void) primaryWidth;
- (void) primaryHeight;
-}
+ int OpenIonDevice();
+ void CloseIonDevice();
+ int ion_dev_fd_;
};
+
+} // namespace gralloc1
+
+#endif // __GR_ION_ALLOC_H__
diff --git a/msm8909/gralloc/gr_priv_handle.h b/msm8909/gralloc/gr_priv_handle.h
new file mode 100644
index 00000000..8c4797a1
--- /dev/null
+++ b/msm8909/gralloc/gr_priv_handle.h
@@ -0,0 +1,200 @@
+/*
+ * Copyright (c) 2011-2017, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ *
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __GR_PRIV_HANDLE_H__
+#define __GR_PRIV_HANDLE_H__
+
+#include <errno.h>
+#include <log/log.h>
+#include <hardware/gralloc1.h>
+#include <hardware/gralloc.h>
+#ifdef __cplusplus
+#include <cinttypes>
+#endif
+
+#define GRALLOC1_FUNCTION_PERFORM 0x00001000
+
+#define DBG_HANDLE false
+
+typedef gralloc1_error_t (*GRALLOC1_PFN_PERFORM)(gralloc1_device_t *device, int operation, ...);
+
+#define PRIV_HANDLE_CONST(exp) static_cast<const private_handle_t *>(exp)
+
+#ifdef __cplusplus
+struct private_handle_t : public native_handle_t {
+#else
+struct private_handle_t {
+ native_handle_t nativeHandle;
+#endif
+ enum {
+ PRIV_FLAGS_FRAMEBUFFER = 0x00000001,
+ PRIV_FLAGS_USES_ION = 0x00000008,
+ PRIV_FLAGS_NEEDS_FLUSH = 0x00000020,
+ PRIV_FLAGS_INTERNAL_ONLY = 0x00000040,
+ PRIV_FLAGS_NON_CPU_WRITER = 0x00000080,
+ PRIV_FLAGS_CACHED = 0x00000200,
+ PRIV_FLAGS_SECURE_BUFFER = 0x00000400,
+ PRIV_FLAGS_EXTERNAL_ONLY = 0x00002000,
+ PRIV_FLAGS_PROTECTED_BUFFER = 0x00004000,
+ PRIV_FLAGS_VIDEO_ENCODER = 0x00010000,
+ PRIV_FLAGS_CAMERA_WRITE = 0x00020000,
+ PRIV_FLAGS_CAMERA_READ = 0x00040000,
+ PRIV_FLAGS_HW_COMPOSER = 0x00080000,
+ PRIV_FLAGS_HW_TEXTURE = 0x00100000,
+ PRIV_FLAGS_ITU_R_601 = 0x00200000, // Unused from display
+ PRIV_FLAGS_ITU_R_601_FR = 0x00400000, // Unused from display
+ PRIV_FLAGS_ITU_R_709 = 0x00800000, // Unused from display
+ PRIV_FLAGS_SECURE_DISPLAY = 0x01000000,
+ PRIV_FLAGS_TILE_RENDERED = 0x02000000,
+ PRIV_FLAGS_CPU_RENDERED = 0x04000000,
+ PRIV_FLAGS_UBWC_ALIGNED = 0x08000000,
+ PRIV_FLAGS_DISP_CONSUMER = 0x10000000,
+ PRIV_FLAGS_CLIENT_ALLOCATED = 0x20000000, // Ion buffer allocated outside of gralloc
+ };
+
+ // file-descriptors dup'd over IPC
+ int fd;
+ int fd_metadata;
+
+ // values sent over IPC
+ int magic;
+ int flags;
+ int width; // holds width of the actual buffer allocated
+ int height; // holds height of the actual buffer allocated
+ int unaligned_width; // holds width client asked to allocate
+ int unaligned_height; // holds height client asked to allocate
+ int format;
+ int buffer_type;
+ unsigned int size;
+ unsigned int offset;
+ unsigned int offset_metadata;
+ uint64_t base __attribute__((aligned(8)));
+ uint64_t base_metadata __attribute__((aligned(8)));
+ uint64_t gpuaddr __attribute__((aligned(8)));
+ uint64_t id __attribute__((aligned(8)));
+ gralloc1_producer_usage_t producer_usage __attribute__((aligned(8)));
+ gralloc1_consumer_usage_t consumer_usage __attribute__((aligned(8)));
+ unsigned int layer_count;
+#ifdef __cplusplus
+ static const int kNumFds = 2;
+ static const int kMagic = 'gmsm';
+
+ static inline int NumInts() {
+ return ((sizeof(private_handle_t) - sizeof(native_handle_t)) / sizeof(int))
+ - kNumFds;
+ }
+
+ private_handle_t(int fd,
+ int meta_fd,
+ int flags,
+ int width,
+ int height,
+ int uw,
+ int uh,
+ int format,
+ int buf_type,
+ unsigned int size,
+ gralloc1_producer_usage_t prod_usage = GRALLOC1_PRODUCER_USAGE_NONE,
+ gralloc1_consumer_usage_t cons_usage = GRALLOC1_CONSUMER_USAGE_NONE)
+ : fd(fd),
+ fd_metadata(meta_fd),
+ magic(kMagic),
+ flags(flags),
+ width(width),
+ height(height),
+ unaligned_width(uw),
+ unaligned_height(uh),
+ format(format),
+ buffer_type(buf_type),
+ size(size),
+ offset(0),
+ offset_metadata(0),
+ base(0),
+ base_metadata(0),
+ gpuaddr(0),
+ id(0),
+ producer_usage(prod_usage),
+ consumer_usage(cons_usage),
+ layer_count(1) {
+ version = static_cast<int>(sizeof(native_handle));
+ numInts = NumInts();
+ numFds = kNumFds;
+ }
+
+// Legacy constructor used by some clients
+ private_handle_t(int fd, unsigned int size, int usage, int buf_type, int format, int w, int h)
+ : private_handle_t(fd, -1, PRIV_FLAGS_CLIENT_ALLOCATED, w, h, 0, 0, format, buf_type, size,
+ static_cast<gralloc1_producer_usage_t>(usage),
+ static_cast<gralloc1_consumer_usage_t>(usage)) {
+ }
+
+ ~private_handle_t() {
+ magic = 0;
+ ALOGE_IF(DBG_HANDLE, "Deleting buffer handle %p", this);
+ }
+
+ static int validate(const native_handle *h) {
+ const private_handle_t *hnd = (const private_handle_t *)h;
+ if (!h || h->version != sizeof(native_handle) || h->numInts != NumInts() ||
+ h->numFds != kNumFds || hnd->magic != kMagic) {
+ ALOGE(
+ "Invalid gralloc handle (at %p): ver(%d/%zu) ints(%d/%d) fds(%d/%d) "
+ "magic(%c%c%c%c/%c%c%c%c)",
+ h, h ? h->version : -1, sizeof(native_handle), h ? h->numInts : -1, NumInts(),
+ h ? h->numFds : -1, kNumFds,
+ hnd ? (((hnd->magic >> 24) & 0xFF) ? ((hnd->magic >> 24) & 0xFF) : '-') : '?',
+ hnd ? (((hnd->magic >> 16) & 0xFF) ? ((hnd->magic >> 16) & 0xFF) : '-') : '?',
+ hnd ? (((hnd->magic >> 8) & 0xFF) ? ((hnd->magic >> 8) & 0xFF) : '-') : '?',
+ hnd ? (((hnd->magic >> 0) & 0xFF) ? ((hnd->magic >> 0) & 0xFF) : '-') : '?',
+ (kMagic >> 24) & 0xFF, (kMagic >> 16) & 0xFF, (kMagic >> 8) & 0xFF, (kMagic >> 0) & 0xFF);
+ return -EINVAL;
+ }
+
+ return 0;
+ }
+ static void Dump(const private_handle_t *hnd) {
+ ALOGD("handle id:%" PRIu64 " wxh:%dx%d uwxuh:%dx%d size: %d fd:%d fd_meta:%d flags:0x%x "
+ "prod_usage:0x%" PRIx64" cons_usage:0x%" PRIx64 " format:0x%x layer_count: %d",
+ hnd->id, hnd->width, hnd->height, hnd->unaligned_width, hnd->unaligned_height, hnd->size,
+ hnd->fd, hnd->fd_metadata, hnd->flags, hnd->producer_usage, hnd->consumer_usage,
+ hnd->format, hnd->layer_count);
+ }
+
+ int GetUnalignedWidth() const { return unaligned_width; }
+
+ int GetUnalignedHeight() const { return unaligned_height; }
+
+ int GetColorFormat() const { return format; }
+
+ unsigned int GetLayerCount() const { return layer_count; }
+
+ int GetStride() const {
+ // In handle we currently store aligned width after allocation.
+ return width;
+ }
+
+ gralloc1_consumer_usage_t GetConsumerUsage() const { return consumer_usage; }
+
+ gralloc1_producer_usage_t GetProducerUsage() const { return producer_usage; }
+
+ uint64_t GetBackingstore() const { return id; }
+#endif
+};
+
+#endif // __GR_PRIV_HANDLE_H__
diff --git a/msm8909/gralloc/gr_utils.cpp b/msm8909/gralloc/gr_utils.cpp
new file mode 100644
index 00000000..d89b8fe1
--- /dev/null
+++ b/msm8909/gralloc/gr_utils.cpp
@@ -0,0 +1,854 @@
+/*
+ * Copyright (c) 2011-2017, The Linux Foundation. All rights reserved.
+
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <media/msm_media_info.h>
+#include <algorithm>
+
+#include "gr_utils.h"
+#include "gr_adreno_info.h"
+#include "qdMetaData.h"
+
+#define ASTC_BLOCK_SIZE 16
+
+#ifndef COLOR_FMT_P010_UBWC
+#define COLOR_FMT_P010_UBWC 9
+#endif
+
+namespace gralloc1 {
+
+bool IsUncompressedRGBFormat(int format) {
+ switch (format) {
+ case HAL_PIXEL_FORMAT_RGBA_8888:
+ case HAL_PIXEL_FORMAT_RGBX_8888:
+ case HAL_PIXEL_FORMAT_RGB_888:
+ case HAL_PIXEL_FORMAT_RGB_565:
+ case HAL_PIXEL_FORMAT_BGR_565:
+ case HAL_PIXEL_FORMAT_BGRA_8888:
+ case HAL_PIXEL_FORMAT_RGBA_5551:
+ case HAL_PIXEL_FORMAT_RGBA_4444:
+ case HAL_PIXEL_FORMAT_R_8:
+ case HAL_PIXEL_FORMAT_RG_88:
+ case HAL_PIXEL_FORMAT_BGRX_8888:
+ case HAL_PIXEL_FORMAT_RGBA_1010102:
+ case HAL_PIXEL_FORMAT_ARGB_2101010:
+ case HAL_PIXEL_FORMAT_RGBX_1010102:
+ case HAL_PIXEL_FORMAT_XRGB_2101010:
+ case HAL_PIXEL_FORMAT_BGRA_1010102:
+ case HAL_PIXEL_FORMAT_ABGR_2101010:
+ case HAL_PIXEL_FORMAT_BGRX_1010102:
+ case HAL_PIXEL_FORMAT_XBGR_2101010:
+ case HAL_PIXEL_FORMAT_RGBA_FP16:
+ case HAL_PIXEL_FORMAT_BGR_888:
+ return true;
+ default:
+ break;
+ }
+
+ return false;
+}
+
+bool IsCompressedRGBFormat(int format) {
+ switch (format) {
+ case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_4x4_KHR:
+ case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR:
+ case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_5x4_KHR:
+ case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR:
+ case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_5x5_KHR:
+ case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR:
+ case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_6x5_KHR:
+ case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR:
+ case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_6x6_KHR:
+ case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR:
+ case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_8x5_KHR:
+ case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR:
+ case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_8x6_KHR:
+ case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR:
+ case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_8x8_KHR:
+ case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR:
+ case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_10x5_KHR:
+ case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR:
+ case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_10x6_KHR:
+ case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR:
+ case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_10x8_KHR:
+ case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR:
+ case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_10x10_KHR:
+ case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR:
+ case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_12x10_KHR:
+ case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR:
+ case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_12x12_KHR:
+ case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR:
+ return true;
+ default:
+ break;
+ }
+
+ return false;
+}
+
+uint32_t GetBppForUncompressedRGB(int format) {
+ uint32_t bpp = 0;
+ switch (format) {
+ case HAL_PIXEL_FORMAT_RGBA_FP16:
+ bpp = 8;
+ break;
+ case HAL_PIXEL_FORMAT_RGBA_8888:
+ case HAL_PIXEL_FORMAT_RGBX_8888:
+ case HAL_PIXEL_FORMAT_BGRA_8888:
+ case HAL_PIXEL_FORMAT_BGRX_8888:
+ case HAL_PIXEL_FORMAT_RGBA_1010102:
+ case HAL_PIXEL_FORMAT_ARGB_2101010:
+ case HAL_PIXEL_FORMAT_RGBX_1010102:
+ case HAL_PIXEL_FORMAT_XRGB_2101010:
+ case HAL_PIXEL_FORMAT_BGRA_1010102:
+ case HAL_PIXEL_FORMAT_ABGR_2101010:
+ case HAL_PIXEL_FORMAT_BGRX_1010102:
+ case HAL_PIXEL_FORMAT_XBGR_2101010:
+ bpp = 4;
+ break;
+ case HAL_PIXEL_FORMAT_RGB_888:
+ case HAL_PIXEL_FORMAT_BGR_888:
+ bpp = 3;
+ break;
+ case HAL_PIXEL_FORMAT_RGB_565:
+ case HAL_PIXEL_FORMAT_BGR_565:
+ case HAL_PIXEL_FORMAT_RGBA_5551:
+ case HAL_PIXEL_FORMAT_RGBA_4444:
+ bpp = 2;
+ break;
+ default:
+ ALOGE("Error : %s New format request = 0x%x", __FUNCTION__, format);
+ break;
+ }
+
+ return bpp;
+}
+
+bool CpuCanAccess(gralloc1_producer_usage_t prod_usage, gralloc1_consumer_usage_t cons_usage) {
+ return CpuCanRead(prod_usage, cons_usage) || CpuCanWrite(prod_usage);
+}
+
+bool CpuCanRead(gralloc1_producer_usage_t prod_usage, gralloc1_consumer_usage_t cons_usage) {
+ if (prod_usage & GRALLOC1_PRODUCER_USAGE_CPU_READ) {
+ return true;
+ }
+
+ if (cons_usage & GRALLOC1_CONSUMER_USAGE_CPU_READ) {
+ return true;
+ }
+
+ return false;
+}
+
+bool CpuCanWrite(gralloc1_producer_usage_t prod_usage) {
+ if (prod_usage & GRALLOC1_PRODUCER_USAGE_CPU_WRITE) {
+ // Application intends to use CPU for rendering
+ return true;
+ }
+
+ return false;
+}
+
+unsigned int GetSize(const BufferInfo &info, unsigned int alignedw,
+ unsigned int alignedh) {
+ unsigned int size = 0;
+ int format = info.format;
+ int width = info.width;
+ int height = info.height;
+ gralloc1_producer_usage_t prod_usage = info.prod_usage;
+ gralloc1_consumer_usage_t cons_usage = info.cons_usage;
+
+ if (IsUBwcEnabled(format, prod_usage, cons_usage)) {
+ return GetUBwcSize(width, height, format, alignedw, alignedh);
+ }
+
+ if (IsUncompressedRGBFormat(format)) {
+ uint32_t bpp = GetBppForUncompressedRGB(format);
+ size = alignedw * alignedh * bpp;
+ return size;
+ }
+
+ if (IsCompressedRGBFormat(format)) {
+ size = alignedw * alignedh * ASTC_BLOCK_SIZE;
+ return size;
+ }
+
+ // Below switch should be for only YUV/custom formats
+ switch (format) {
+ case HAL_PIXEL_FORMAT_RAW16:
+ case HAL_PIXEL_FORMAT_Y16:
+ size = alignedw * alignedh * 2;
+ break;
+ case HAL_PIXEL_FORMAT_RAW10:
+ case HAL_PIXEL_FORMAT_RAW12:
+ size = ALIGN(alignedw * alignedh, SIZE_4K);
+ break;
+ case HAL_PIXEL_FORMAT_RAW8:
+ case HAL_PIXEL_FORMAT_Y8:
+ size = alignedw * alignedh * 1;
+ break;
+
+ // adreno formats
+ case HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO: // NV21
+ size = ALIGN(alignedw * alignedh, SIZE_4K);
+ size += (unsigned int)ALIGN(2 * ALIGN(width / 2, 32) * ALIGN(height / 2, 32), SIZE_4K);
+ break;
+ case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED: // NV12
+ // The chroma plane is subsampled,
+ // but the pitch in bytes is unchanged
+ // The GPU needs 4K alignment, but the video decoder needs 8K
+ size = ALIGN(alignedw * alignedh, SIZE_8K);
+ size += ALIGN(alignedw * (unsigned int)ALIGN(height / 2, 32), SIZE_8K);
+ break;
+ case HAL_PIXEL_FORMAT_YV12:
+ if ((format == HAL_PIXEL_FORMAT_YV12) && ((width & 1) || (height & 1))) {
+ ALOGE("w or h is odd for the YV12 format");
+ return 0;
+ }
+ size = alignedw * alignedh + (ALIGN(alignedw / 2, 16) * (alignedh / 2)) * 2;
+ size = ALIGN(size, (unsigned int)SIZE_4K);
+ break;
+ case HAL_PIXEL_FORMAT_YCbCr_420_SP:
+ case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+ size = ALIGN((alignedw * alignedh) + (alignedw * alignedh) / 2 + 1, SIZE_4K);
+ break;
+ case HAL_PIXEL_FORMAT_YCbCr_420_P010:
+ size = ALIGN((alignedw * alignedh * 2) + (alignedw * alignedh) + 1, SIZE_4K);
+ break;
+ case HAL_PIXEL_FORMAT_YCbCr_422_SP:
+ case HAL_PIXEL_FORMAT_YCrCb_422_SP:
+ case HAL_PIXEL_FORMAT_YCbCr_422_I:
+ case HAL_PIXEL_FORMAT_YCrCb_422_I:
+ case HAL_PIXEL_FORMAT_CbYCrY_422_I:
+ if (width & 1) {
+ ALOGE("width is odd for the YUV422_SP format");
+ return 0;
+ }
+ size = ALIGN(alignedw * alignedh * 2, SIZE_4K);
+ break;
+ case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
+ case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
+ size = VENUS_BUFFER_SIZE(COLOR_FMT_NV12, width, height);
+ break;
+ case HAL_PIXEL_FORMAT_YCrCb_420_SP_VENUS:
+ size = VENUS_BUFFER_SIZE(COLOR_FMT_NV21, width, height);
+ break;
+ case HAL_PIXEL_FORMAT_BLOB:
+ case HAL_PIXEL_FORMAT_RAW_OPAQUE:
+ if (height != 1) {
+ ALOGE("%s: Buffers with HAL_PIXEL_FORMAT_BLOB must have height 1 ", __FUNCTION__);
+ return 0;
+ }
+ size = (unsigned int)width;
+ break;
+ case HAL_PIXEL_FORMAT_NV21_ZSL:
+ size = ALIGN((alignedw * alignedh) + (alignedw * alignedh) / 2, SIZE_4K);
+ break;
+ default:
+ ALOGE("%s: Unrecognized pixel format: 0x%x", __FUNCTION__, format);
+ return 0;
+ }
+
+ return size;
+}
+
+void GetBufferSizeAndDimensions(const BufferInfo &info, unsigned int *size,
+ unsigned int *alignedw, unsigned int *alignedh) {
+ GetAlignedWidthAndHeight(info, alignedw, alignedh);
+ *size = GetSize(info, *alignedw, *alignedh);
+}
+
+void GetYuvUbwcSPPlaneInfo(uint64_t base, uint32_t width, uint32_t height,
+ int color_format, struct android_ycbcr *ycbcr) {
+ // UBWC buffer has these 4 planes in the following sequence:
+ // Y_Meta_Plane, Y_Plane, UV_Meta_Plane, UV_Plane
+ unsigned int y_meta_stride, y_meta_height, y_meta_size;
+ unsigned int y_stride, y_height, y_size;
+ unsigned int c_meta_stride, c_meta_height, c_meta_size;
+ unsigned int alignment = 4096;
+
+ y_meta_stride = VENUS_Y_META_STRIDE(color_format, INT(width));
+ y_meta_height = VENUS_Y_META_SCANLINES(color_format, INT(height));
+ y_meta_size = ALIGN((y_meta_stride * y_meta_height), alignment);
+
+ y_stride = VENUS_Y_STRIDE(color_format, INT(width));
+ y_height = VENUS_Y_SCANLINES(color_format, INT(height));
+ y_size = ALIGN((y_stride * y_height), alignment);
+
+ c_meta_stride = VENUS_UV_META_STRIDE(color_format, INT(width));
+ c_meta_height = VENUS_UV_META_SCANLINES(color_format, INT(height));
+ c_meta_size = ALIGN((c_meta_stride * c_meta_height), alignment);
+
+ ycbcr->y = reinterpret_cast<void *>(base + y_meta_size);
+ ycbcr->cb = reinterpret_cast<void *>(base + y_meta_size + y_size + c_meta_size);
+ ycbcr->cr = reinterpret_cast<void *>(base + y_meta_size + y_size + c_meta_size + 1);
+ ycbcr->ystride = y_stride;
+ ycbcr->cstride = VENUS_UV_STRIDE(color_format, INT(width));
+}
+
+void GetYuvUbwcInterlacedSPPlaneInfo(uint64_t base, uint32_t width, uint32_t height,
+ int color_format, struct android_ycbcr *ycbcr) {
+ unsigned int uv_stride, uv_height, uv_size;
+ unsigned int alignment = 4096;
+ uint64_t field_base;
+
+ // UBWC interlaced has top-bottom field layout with each field as
+ // 4-plane NV12_UBWC with width = image_width & height = image_height / 2.
+ // Client passed ycbcr argument is ptr to struct android_ycbcr[2].
+ // Plane info to be filled for each field separately.
+ height = (height + 1) >> 1;
+ uv_stride = VENUS_UV_STRIDE(color_format, INT(width));
+ uv_height = VENUS_UV_SCANLINES(color_format, INT(height));
+ uv_size = ALIGN((uv_stride * uv_height), alignment);
+
+ field_base = base;
+ GetYuvUbwcSPPlaneInfo(field_base, width, height, COLOR_FMT_NV12_UBWC, &ycbcr[0]);
+
+ field_base = reinterpret_cast<uint64_t>(ycbcr[0].cb) + uv_size;
+ GetYuvUbwcSPPlaneInfo(field_base, width, height, COLOR_FMT_NV12_UBWC, &ycbcr[1]);
+}
+
+void GetYuvSPPlaneInfo(uint64_t base, uint32_t width, uint32_t height, uint32_t bpp,
+ struct android_ycbcr *ycbcr) {
+ unsigned int ystride, cstride;
+
+ ystride = cstride = UINT(width) * bpp;
+ ycbcr->y = reinterpret_cast<void *>(base);
+ ycbcr->cb = reinterpret_cast<void *>(base + ystride * UINT(height));
+ ycbcr->cr = reinterpret_cast<void *>(base + ystride * UINT(height) + 1);
+ ycbcr->ystride = ystride;
+ ycbcr->cstride = cstride;
+ ycbcr->chroma_step = 2 * bpp;
+}
+
+int GetYUVPlaneInfo(const private_handle_t *hnd, struct android_ycbcr *ycbcr) {
+ int err = 0;
+ uint32_t width = UINT(hnd->width);
+ uint32_t height = UINT(hnd->height);
+ int format = hnd->format;
+ gralloc1_producer_usage_t prod_usage = hnd->GetProducerUsage();
+ gralloc1_consumer_usage_t cons_usage = hnd->GetConsumerUsage();
+ unsigned int ystride, cstride;
+ bool interlaced = false;
+
+ memset(ycbcr->reserved, 0, sizeof(ycbcr->reserved));
+
+ // Check if UBWC buffer has been rendered in linear format.
+ int linear_format = 0;
+ if (getMetaData(const_cast<private_handle_t *>(hnd),
+ GET_LINEAR_FORMAT, &linear_format) == 0) {
+ format = INT(linear_format);
+ }
+
+ // Check metadata if the geometry has been updated.
+ BufferDim_t buffer_dim;
+ if (getMetaData(const_cast<private_handle_t *>(hnd),
+ GET_BUFFER_GEOMETRY, &buffer_dim) == 0) {
+ int usage = 0;
+ if (hnd->flags & private_handle_t::PRIV_FLAGS_UBWC_ALIGNED) {
+ usage = GRALLOC1_PRODUCER_USAGE_PRIVATE_ALLOC_UBWC;
+ }
+
+ BufferInfo info(buffer_dim.sliceWidth, buffer_dim.sliceHeight, format,
+ prod_usage, cons_usage);
+ GetAlignedWidthAndHeight(info, &width, &height);
+ }
+
+ // Check metadata for interlaced content.
+ int interlace_flag = 0;
+ if (getMetaData(const_cast<private_handle_t *>(hnd),
+ GET_PP_PARAM_INTERLACED, &interlace_flag) != 0) {
+ interlaced = interlace_flag;
+ }
+
+ // Get the chroma offsets from the handle width/height. We take advantage
+ // of the fact the width _is_ the stride
+ switch (format) {
+ // Semiplanar
+ case HAL_PIXEL_FORMAT_YCbCr_420_SP:
+ case HAL_PIXEL_FORMAT_YCbCr_422_SP:
+ case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
+ case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
+ // Same as YCbCr_420_SP_VENUS
+ GetYuvSPPlaneInfo(hnd->base, width, height, 1, ycbcr);
+ break;
+
+ case HAL_PIXEL_FORMAT_YCbCr_420_P010:
+ GetYuvSPPlaneInfo(hnd->base, width, height, 2, ycbcr);
+ break;
+
+ case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC:
+ if (!interlaced) {
+ GetYuvUbwcSPPlaneInfo(hnd->base, width, height, COLOR_FMT_NV12_UBWC, ycbcr);
+ } else {
+ GetYuvUbwcInterlacedSPPlaneInfo(hnd->base, width, height, COLOR_FMT_NV12_UBWC, ycbcr);
+ }
+ ycbcr->chroma_step = 2;
+ break;
+
+ case HAL_PIXEL_FORMAT_YCbCr_420_TP10_UBWC:
+ GetYuvUbwcSPPlaneInfo(hnd->base, width, height, COLOR_FMT_NV12_BPP10_UBWC, ycbcr);
+ ycbcr->chroma_step = 3;
+ break;
+
+ case HAL_PIXEL_FORMAT_YCbCr_420_P010_UBWC:
+ GetYuvUbwcSPPlaneInfo(hnd->base, width, height, COLOR_FMT_P010_UBWC, ycbcr);
+ ycbcr->chroma_step = 4;
+ break;
+
+ case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+ case HAL_PIXEL_FORMAT_YCrCb_422_SP:
+ case HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO:
+ case HAL_PIXEL_FORMAT_YCrCb_420_SP_VENUS:
+ case HAL_PIXEL_FORMAT_NV21_ZSL:
+ case HAL_PIXEL_FORMAT_RAW16:
+ case HAL_PIXEL_FORMAT_Y16:
+ case HAL_PIXEL_FORMAT_RAW10:
+ case HAL_PIXEL_FORMAT_RAW8:
+ case HAL_PIXEL_FORMAT_Y8:
+ GetYuvSPPlaneInfo(hnd->base, width, height, 1, ycbcr);
+ std::swap(ycbcr->cb, ycbcr->cr);
+ break;
+
+ // Planar
+ case HAL_PIXEL_FORMAT_YV12:
+ ystride = width;
+ cstride = ALIGN(width / 2, 16);
+ ycbcr->y = reinterpret_cast<void *>(hnd->base);
+ ycbcr->cr = reinterpret_cast<void *>(hnd->base + ystride * height);
+ ycbcr->cb = reinterpret_cast<void *>(hnd->base + ystride * height + cstride * height / 2);
+ ycbcr->ystride = ystride;
+ ycbcr->cstride = cstride;
+ ycbcr->chroma_step = 1;
+ break;
+ case HAL_PIXEL_FORMAT_CbYCrY_422_I:
+ ystride = width * 2;
+ cstride = 0;
+ ycbcr->y = reinterpret_cast<void *>(hnd->base);
+ ycbcr->cr = NULL;
+ ycbcr->cb = NULL;
+ ycbcr->ystride = ystride;
+ ycbcr->cstride = 0;
+ ycbcr->chroma_step = 0;
+ break;
+ // Unsupported formats
+ case HAL_PIXEL_FORMAT_YCbCr_422_I:
+ case HAL_PIXEL_FORMAT_YCrCb_422_I:
+ case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED:
+ default:
+ ALOGD("%s: Invalid format passed: 0x%x", __FUNCTION__, format);
+ err = -EINVAL;
+ }
+
+ return err;
+}
+
+// Explicitly defined UBWC formats
+bool IsUBwcFormat(int format) {
+ switch (format) {
+ case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC:
+ case HAL_PIXEL_FORMAT_YCbCr_420_TP10_UBWC:
+ case HAL_PIXEL_FORMAT_YCbCr_420_P010_UBWC:
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool IsUBwcSupported(int format) {
+ // Existing HAL formats with UBWC support
+ switch (format) {
+ case HAL_PIXEL_FORMAT_BGR_565:
+ case HAL_PIXEL_FORMAT_RGBA_8888:
+ case HAL_PIXEL_FORMAT_RGBX_8888:
+ case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
+ case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
+ case HAL_PIXEL_FORMAT_RGBA_1010102:
+ case HAL_PIXEL_FORMAT_RGBX_1010102:
+ return true;
+ default:
+ break;
+ }
+
+ return false;
+}
+
+bool IsUBwcEnabled(int format, gralloc1_producer_usage_t prod_usage,
+ gralloc1_consumer_usage_t cons_usage) {
+ // Allow UBWC, if client is using an explicitly defined UBWC pixel format.
+ if (IsUBwcFormat(format)) {
+ return true;
+ }
+
+ // Allow UBWC, if an OpenGL client sets UBWC usage flag and GPU plus MDP
+ // support the format. OR if a non-OpenGL client like Rotator, sets UBWC
+ // usage flag and MDP supports the format.
+ if ((prod_usage & GRALLOC1_PRODUCER_USAGE_PRIVATE_ALLOC_UBWC) && IsUBwcSupported(format)) {
+ bool enable = true;
+ // Query GPU for UBWC only if buffer is intended to be used by GPU.
+ if ((cons_usage & GRALLOC1_CONSUMER_USAGE_GPU_TEXTURE) ||
+ (prod_usage & GRALLOC1_PRODUCER_USAGE_GPU_RENDER_TARGET)) {
+ if (AdrenoMemInfo::GetInstance()) {
+ enable = AdrenoMemInfo::GetInstance()->IsUBWCSupportedByGPU(format);
+ }
+ }
+
+ // Allow UBWC, only if CPU usage flags are not set
+ if (enable && !(CpuCanAccess(prod_usage, cons_usage))) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void GetYuvUBwcWidthAndHeight(int width, int height, int format, unsigned int *aligned_w,
+ unsigned int *aligned_h) {
+ switch (format) {
+ case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
+ case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
+ case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC:
+ *aligned_w = VENUS_Y_STRIDE(COLOR_FMT_NV12_UBWC, width);
+ *aligned_h = VENUS_Y_SCANLINES(COLOR_FMT_NV12_UBWC, height);
+ break;
+ case HAL_PIXEL_FORMAT_YCbCr_420_TP10_UBWC:
+ // The macro returns the stride which is 4/3 times the width, hence * 3/4
+ *aligned_w = (VENUS_Y_STRIDE(COLOR_FMT_NV12_BPP10_UBWC, width) * 3) / 4;
+ *aligned_h = VENUS_Y_SCANLINES(COLOR_FMT_NV12_BPP10_UBWC, height);
+ break;
+ case HAL_PIXEL_FORMAT_YCbCr_420_P010_UBWC:
+ // The macro returns the stride which is 2 times the width, hence / 2
+ *aligned_w = (VENUS_Y_STRIDE(COLOR_FMT_P010_UBWC, width) / 2);
+ *aligned_h = VENUS_Y_SCANLINES(COLOR_FMT_P010_UBWC, height);
+ break;
+ default:
+ ALOGE("%s: Unsupported pixel format: 0x%x", __FUNCTION__, format);
+ *aligned_w = 0;
+ *aligned_h = 0;
+ break;
+ }
+}
+
+void GetRgbUBwcBlockSize(uint32_t bpp, int *block_width, int *block_height) {
+ *block_width = 0;
+ *block_height = 0;
+
+ switch (bpp) {
+ case 2:
+ case 4:
+ *block_width = 16;
+ *block_height = 4;
+ break;
+ case 8:
+ *block_width = 8;
+ *block_height = 4;
+ break;
+ case 16:
+ *block_width = 4;
+ *block_height = 4;
+ break;
+ default:
+ ALOGE("%s: Unsupported bpp: %d", __FUNCTION__, bpp);
+ break;
+ }
+}
+
+unsigned int GetRgbUBwcMetaBufferSize(int width, int height, uint32_t bpp) {
+ unsigned int size = 0;
+ int meta_width, meta_height;
+ int block_width, block_height;
+
+ GetRgbUBwcBlockSize(bpp, &block_width, &block_height);
+ if (!block_width || !block_height) {
+ ALOGE("%s: Unsupported bpp: %d", __FUNCTION__, bpp);
+ return size;
+ }
+
+ // Align meta buffer height to 16 blocks
+ meta_height = ALIGN(((height + block_height - 1) / block_height), 16);
+
+ // Align meta buffer width to 64 blocks
+ meta_width = ALIGN(((width + block_width - 1) / block_width), 64);
+
+ // Align meta buffer size to 4K
+ size = (unsigned int)ALIGN((meta_width * meta_height), 4096);
+
+ return size;
+}
+
+unsigned int GetUBwcSize(int width, int height, int format, unsigned int alignedw,
+ unsigned int alignedh) {
+ unsigned int size = 0;
+ uint32_t bpp = 0;
+ switch (format) {
+ case HAL_PIXEL_FORMAT_BGR_565:
+ case HAL_PIXEL_FORMAT_RGBA_8888:
+ case HAL_PIXEL_FORMAT_RGBX_8888:
+ case HAL_PIXEL_FORMAT_RGBA_1010102:
+ case HAL_PIXEL_FORMAT_RGBX_1010102:
+ bpp = GetBppForUncompressedRGB(format);
+ size = alignedw * alignedh * bpp;
+ size += GetRgbUBwcMetaBufferSize(width, height, bpp);
+ break;
+ case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
+ case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
+ case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC:
+ size = VENUS_BUFFER_SIZE(COLOR_FMT_NV12_UBWC, width, height);
+ break;
+ case HAL_PIXEL_FORMAT_YCbCr_420_TP10_UBWC:
+ size = VENUS_BUFFER_SIZE(COLOR_FMT_NV12_BPP10_UBWC, width, height);
+ break;
+ case HAL_PIXEL_FORMAT_YCbCr_420_P010_UBWC:
+ size = VENUS_BUFFER_SIZE(COLOR_FMT_P010_UBWC, width, height);
+ break;
+ default:
+ ALOGE("%s: Unsupported pixel format: 0x%x", __FUNCTION__, format);
+ break;
+ }
+
+ return size;
+}
+
+int GetRgbDataAddress(private_handle_t *hnd, void **rgb_data) {
+ int err = 0;
+
+ // This api is for RGB* formats
+ if (!gralloc1::IsUncompressedRGBFormat(hnd->format)) {
+ return -EINVAL;
+ }
+
+ // linear buffer, nothing to do further
+ if (!(hnd->flags & private_handle_t::PRIV_FLAGS_UBWC_ALIGNED)) {
+ *rgb_data = reinterpret_cast<void *>(hnd->base);
+ return err;
+ }
+
+ unsigned int meta_size = 0;
+ uint32_t bpp = GetBppForUncompressedRGB(hnd->format);
+ switch (hnd->format) {
+ case HAL_PIXEL_FORMAT_BGR_565:
+ case HAL_PIXEL_FORMAT_RGBA_8888:
+ case HAL_PIXEL_FORMAT_RGBX_8888:
+ case HAL_PIXEL_FORMAT_RGBA_1010102:
+ case HAL_PIXEL_FORMAT_RGBX_1010102:
+ meta_size = GetRgbUBwcMetaBufferSize(hnd->width, hnd->height, bpp);
+ break;
+ default:
+ ALOGE("%s:Unsupported RGB format: 0x%x", __FUNCTION__, hnd->format);
+ err = -EINVAL;
+ break;
+ }
+ *rgb_data = reinterpret_cast<void *>(hnd->base + meta_size);
+
+ return err;
+}
+
+void GetAlignedWidthAndHeight(const BufferInfo &info, unsigned int *alignedw,
+ unsigned int *alignedh) {
+ int width = info.width;
+ int height = info.height;
+ int format = info.format;
+ gralloc1_producer_usage_t prod_usage = info.prod_usage;
+ gralloc1_consumer_usage_t cons_usage = info.cons_usage;
+
+ // Currently surface padding is only computed for RGB* surfaces.
+ bool ubwc_enabled = IsUBwcEnabled(format, prod_usage, cons_usage);
+ int tile = ubwc_enabled;
+
+ if (IsUncompressedRGBFormat(format)) {
+ if (AdrenoMemInfo::GetInstance()) {
+ AdrenoMemInfo::GetInstance()->AlignUnCompressedRGB(width, height, format, tile, alignedw,
+ alignedh);
+ }
+ return;
+ }
+
+ if (ubwc_enabled) {
+ GetYuvUBwcWidthAndHeight(width, height, format, alignedw, alignedh);
+ return;
+ }
+
+ if (IsCompressedRGBFormat(format)) {
+ if (AdrenoMemInfo::GetInstance()) {
+ AdrenoMemInfo::GetInstance()->AlignCompressedRGB(width, height, format, alignedw, alignedh);
+ }
+ return;
+ }
+
+ int aligned_w = width;
+ int aligned_h = height;
+ unsigned int alignment = 32;
+
+ // Below should be only YUV family
+ switch (format) {
+ case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+ case HAL_PIXEL_FORMAT_YCbCr_420_SP:
+ if (AdrenoMemInfo::GetInstance() == nullptr) {
+ return;
+ }
+ alignment = AdrenoMemInfo::GetInstance()->GetGpuPixelAlignment();
+ aligned_w = ALIGN(width, alignment);
+ break;
+ case HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO:
+ aligned_w = ALIGN(width, alignment);
+ break;
+ case HAL_PIXEL_FORMAT_RAW16:
+ case HAL_PIXEL_FORMAT_Y16:
+ case HAL_PIXEL_FORMAT_Y8:
+ aligned_w = ALIGN(width, 16);
+ break;
+ case HAL_PIXEL_FORMAT_RAW12:
+ aligned_w = ALIGN(width * 12 / 8, 8);
+ break;
+ case HAL_PIXEL_FORMAT_RAW10:
+ aligned_w = ALIGN(width * 10 / 8, 8);
+ break;
+ case HAL_PIXEL_FORMAT_RAW8:
+ aligned_w = ALIGN(width, 8);
+ break;
+ case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED:
+ aligned_w = ALIGN(width, 128);
+ break;
+ case HAL_PIXEL_FORMAT_YV12:
+ case HAL_PIXEL_FORMAT_YCbCr_422_SP:
+ case HAL_PIXEL_FORMAT_YCrCb_422_SP:
+ case HAL_PIXEL_FORMAT_YCbCr_422_I:
+ case HAL_PIXEL_FORMAT_YCrCb_422_I:
+ case HAL_PIXEL_FORMAT_YCbCr_420_P010:
+ aligned_w = ALIGN(width, 16);
+ break;
+ case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
+ case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
+ aligned_w = INT(VENUS_Y_STRIDE(COLOR_FMT_NV12, width));
+ aligned_h = INT(VENUS_Y_SCANLINES(COLOR_FMT_NV12, height));
+ break;
+ case HAL_PIXEL_FORMAT_YCrCb_420_SP_VENUS:
+ aligned_w = INT(VENUS_Y_STRIDE(COLOR_FMT_NV21, width));
+ aligned_h = INT(VENUS_Y_SCANLINES(COLOR_FMT_NV21, height));
+ break;
+ case HAL_PIXEL_FORMAT_BLOB:
+ case HAL_PIXEL_FORMAT_RAW_OPAQUE:
+ break;
+ case HAL_PIXEL_FORMAT_NV21_ZSL:
+ aligned_w = ALIGN(width, 64);
+ aligned_h = ALIGN(height, 64);
+ break;
+ default:
+ break;
+ }
+
+ *alignedw = (unsigned int)aligned_w;
+ *alignedh = (unsigned int)aligned_h;
+}
+
+int GetBufferLayout(private_handle_t *hnd, uint32_t stride[4],
+ uint32_t offset[4], uint32_t *num_planes) {
+ if (!hnd || !stride || !offset || !num_planes) {
+ return -EINVAL;
+ }
+
+ struct android_ycbcr yuvInfo = {};
+ *num_planes = 1;
+ stride[0] = 0;
+
+ switch (hnd->format) {
+ case HAL_PIXEL_FORMAT_RGB_565:
+ case HAL_PIXEL_FORMAT_BGR_565:
+ case HAL_PIXEL_FORMAT_RGBA_5551:
+ case HAL_PIXEL_FORMAT_RGBA_4444:
+ stride[0] = static_cast<uint32_t>(hnd->width * 2);
+ break;
+ case HAL_PIXEL_FORMAT_RGB_888:
+ stride[0] = static_cast<uint32_t>(hnd->width * 3);
+ break;
+ case HAL_PIXEL_FORMAT_RGBA_8888:
+ case HAL_PIXEL_FORMAT_BGRA_8888:
+ case HAL_PIXEL_FORMAT_RGBX_8888:
+ case HAL_PIXEL_FORMAT_BGRX_8888:
+ case HAL_PIXEL_FORMAT_RGBA_1010102:
+ case HAL_PIXEL_FORMAT_ARGB_2101010:
+ case HAL_PIXEL_FORMAT_RGBX_1010102:
+ case HAL_PIXEL_FORMAT_XRGB_2101010:
+ case HAL_PIXEL_FORMAT_BGRA_1010102:
+ case HAL_PIXEL_FORMAT_ABGR_2101010:
+ case HAL_PIXEL_FORMAT_BGRX_1010102:
+ case HAL_PIXEL_FORMAT_XBGR_2101010:
+ stride[0] = static_cast<uint32_t>(hnd->width * 4);
+ break;
+ }
+
+ // Format is RGB
+ if (stride[0]) {
+ return 0;
+ }
+
+ (*num_planes)++;
+ int ret = GetYUVPlaneInfo(hnd, &yuvInfo);
+ if (ret < 0) {
+ ALOGE("%s failed", __FUNCTION__);
+ return ret;
+ }
+
+ stride[0] = static_cast<uint32_t>(yuvInfo.ystride);
+ offset[0] = static_cast<uint32_t>(reinterpret_cast<uint64_t>(yuvInfo.y) - hnd->base);
+ stride[1] = static_cast<uint32_t>(yuvInfo.cstride);
+ switch (hnd->format) {
+ case HAL_PIXEL_FORMAT_YCbCr_420_SP:
+ case HAL_PIXEL_FORMAT_YCbCr_422_SP:
+ case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
+ case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
+ case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC:
+ case HAL_PIXEL_FORMAT_YCbCr_420_P010:
+ case HAL_PIXEL_FORMAT_YCbCr_420_TP10_UBWC:
+ case HAL_PIXEL_FORMAT_YCbCr_420_P010_UBWC:
+ offset[1] = static_cast<uint32_t>(reinterpret_cast<uint64_t>(yuvInfo.cb) - hnd->base);
+ break;
+ case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+ case HAL_PIXEL_FORMAT_YCrCb_420_SP_VENUS:
+ case HAL_PIXEL_FORMAT_YCrCb_422_SP:
+ offset[1] = static_cast<uint32_t>(reinterpret_cast<uint64_t>(yuvInfo.cr) - hnd->base);
+ break;
+ case HAL_PIXEL_FORMAT_YV12:
+ offset[1] = static_cast<uint32_t>(reinterpret_cast<uint64_t>(yuvInfo.cr) - hnd->base);
+ stride[2] = static_cast<uint32_t>(yuvInfo.cstride);
+ offset[2] = static_cast<uint32_t>(reinterpret_cast<uint64_t>(yuvInfo.cb) - hnd->base);
+ (*num_planes)++;
+ break;
+ default:
+ ALOGW("%s: Unsupported format", __FUNCTION__);
+ ret = -EINVAL;
+ }
+
+ if (hnd->flags & private_handle_t::PRIV_FLAGS_UBWC_ALIGNED) {
+ std::fill(offset, offset + 4, 0);
+ }
+
+ return 0;
+}
+
+} // namespace gralloc1
diff --git a/msm8909/gralloc/gr_utils.h b/msm8909/gralloc/gr_utils.h
new file mode 100644
index 00000000..2a085392
--- /dev/null
+++ b/msm8909/gralloc/gr_utils.h
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2011-2016, The Linux Foundation. All rights reserved.
+
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __GR_UTILS_H__
+#define __GR_UTILS_H__
+
+#include "gralloc_priv.h"
+
+#define SZ_2M 0x200000
+#define SZ_1M 0x100000
+#define SZ_4K 0x1000
+
+#define SIZE_4K 4096
+#define SIZE_8K 4096
+
+#define INT(exp) static_cast<int>(exp)
+#define UINT(exp) static_cast<unsigned int>(exp)
+
+namespace gralloc1 {
+
+struct BufferInfo {
+ BufferInfo(int w, int h, int f, gralloc1_producer_usage_t prod = GRALLOC1_PRODUCER_USAGE_NONE,
+ gralloc1_consumer_usage_t cons = GRALLOC1_CONSUMER_USAGE_NONE) : width(w), height(h),
+ format(f), prod_usage(prod), cons_usage(cons) {}
+ int width;
+ int height;
+ int format;
+ gralloc1_producer_usage_t prod_usage;
+ gralloc1_consumer_usage_t cons_usage;
+};
+
+template <class Type1, class Type2>
+inline Type1 ALIGN(Type1 x, Type2 align) {
+ return (Type1)((x + (Type1)align - 1) & ~((Type1)align - 1));
+}
+
+bool IsCompressedRGBFormat(int format);
+bool IsUncompressedRGBFormat(int format);
+uint32_t GetBppForUncompressedRGB(int format);
+bool CpuCanAccess(gralloc1_producer_usage_t prod_usage, gralloc1_consumer_usage_t cons_usage);
+bool CpuCanRead(gralloc1_producer_usage_t prod_usage, gralloc1_consumer_usage_t cons_usage);
+bool CpuCanWrite(gralloc1_producer_usage_t prod_usage);
+unsigned int GetSize(const BufferInfo &d, unsigned int alignedw, unsigned int alignedh);
+void GetBufferSizeAndDimensions(const BufferInfo &d, unsigned int *size,
+ unsigned int *alignedw, unsigned int *alignedh);
+void GetAlignedWidthAndHeight(const BufferInfo &d, unsigned int *aligned_w,
+ unsigned int *aligned_h);
+int GetYUVPlaneInfo(const private_handle_t *hnd, struct android_ycbcr *ycbcr);
+int GetRgbDataAddress(private_handle_t *hnd, void **rgb_data);
+bool IsUBwcFormat(int format);
+bool IsUBwcSupported(int format);
+bool IsUBwcEnabled(int format, gralloc1_producer_usage_t prod_usage,
+ gralloc1_consumer_usage_t cons_usage);
+void GetYuvUBwcWidthAndHeight(int width, int height, int format, unsigned int *aligned_w,
+ unsigned int *aligned_h);
+void GetYuvSPPlaneInfo(uint64_t base, uint32_t width, uint32_t height, uint32_t bpp,
+ struct android_ycbcr *ycbcr);
+void GetYuvUbwcSPPlaneInfo(uint64_t base, uint32_t width, uint32_t height, int color_format,
+ struct android_ycbcr *ycbcr);
+void GetYuvUbwcInterlacedSPPlaneInfo(uint64_t base, uint32_t width, uint32_t height,
+ int color_format, struct android_ycbcr *ycbcr);
+void GetRgbUBwcBlockSize(uint32_t bpp, int *block_width, int *block_height);
+unsigned int GetRgbUBwcMetaBufferSize(int width, int height, uint32_t bpp);
+unsigned int GetUBwcSize(int width, int height, int format, unsigned int alignedw,
+ unsigned int alignedh);
+int GetBufferLayout(private_handle_t *hnd, uint32_t stride[4],
+ uint32_t offset[4], uint32_t *num_planes);
+} // namespace gralloc1
+
+#endif // __GR_UTILS_H__
diff --git a/msm8909/gralloc/gralloc_priv.h b/msm8909/gralloc/gralloc_priv.h
new file mode 100644
index 00000000..5e619eb0
--- /dev/null
+++ b/msm8909/gralloc/gralloc_priv.h
@@ -0,0 +1,209 @@
+/*
+ * Copyright (c) 2011-2018, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ *
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __GRALLOC_PRIV_H__
+#define __GRALLOC_PRIV_H__
+
+#include <unistd.h>
+#include "gr_priv_handle.h"
+
+#define GRALLOC_PROP_PREFIX "vendor.gralloc."
+#define GRALLOC_PROP(prop_name) GRALLOC_PROP_PREFIX prop_name
+
+#define DISABLE_UBWC_PROP GRALLOC_PROP("disable_ubwc")
+#define ENABLE_FB_UBWC_PROP GRALLOC_PROP("enable_fb_ubwc")
+#define MAP_FB_MEMORY_PROP GRALLOC_PROP("map_fb_memory")
+
+#define ROUND_UP_PAGESIZE(x) roundUpToPageSize(x)
+inline int roundUpToPageSize(int x) {
+ return (x + (getpagesize()-1)) & ~(getpagesize()-1);
+}
+
+/* Gralloc usage bits indicating the type of allocation that should be used */
+/* Refer gralloc1_producer_usage_t & gralloc1_consumer_usage-t in gralloc1.h */
+
+/* Producer flags */
+/* Non linear, Universal Bandwidth Compression */
+#define GRALLOC1_PRODUCER_USAGE_PRIVATE_ALLOC_UBWC GRALLOC1_PRODUCER_USAGE_PRIVATE_0
+
+/* Set this for allocating uncached memory (using O_DSYNC),
+ * cannot be used with noncontiguous heaps */
+#define GRALLOC1_PRODUCER_USAGE_PRIVATE_UNCACHED GRALLOC1_PRODUCER_USAGE_PRIVATE_1
+
+/* CAMERA heap is a carveout heap for camera, is not secured */
+#define GRALLOC1_PRODUCER_USAGE_PRIVATE_CAMERA_HEAP GRALLOC1_PRODUCER_USAGE_PRIVATE_2
+
+/* ADSP heap is a carveout heap, is not secured */
+#define GRALLOC1_PRODUCER_USAGE_PRIVATE_ADSP_HEAP GRALLOC1_PRODUCER_USAGE_PRIVATE_3
+
+/* IOMMU heap comes from manually allocated pages, can be cached/uncached, is not secured */
+#define GRALLOC1_PRODUCER_USAGE_PRIVATE_IOMMU_HEAP GRALLOC1_PRODUCER_USAGE_PRIVATE_4
+
+/* MM heap is a carveout heap for video, can be secured */
+#define GRALLOC1_PRODUCER_USAGE_PRIVATE_MM_HEAP GRALLOC1_PRODUCER_USAGE_PRIVATE_5
+
+/* Use legacy ZSL definition until we know the correct usage on gralloc1 */
+#define GRALLOC1_PRODUCER_USAGE_PRIVATE_CAMERA_ZSL GRALLOC_USAGE_HW_CAMERA_ZSL
+
+
+/* Consumer flags */
+/* TODO(user): Fix when producer and consumer flags are actually separated */
+/* This flag is set for WFD usecase */
+#define GRALLOC1_CONSUMER_USAGE_PRIVATE_WFD 0x00200000
+
+/* This flag is used for SECURE display usecase */
+#define GRALLOC1_CONSUMER_USAGE_PRIVATE_SECURE_DISPLAY 0x02000000
+
+/* Buffer content should be displayed on a primary display only */
+#define GRALLOC1_CONSUMER_USAGE_PRIVATE_INTERNAL_ONLY 0x04000000
+
+/* Buffer content should be displayed on an external display only */
+#define GRALLOC1_CONSUMER_USAGE_PRIVATE_EXTERNAL_ONLY 0x08000000
+
+
+/* Legacy gralloc0.x definitions */
+/* Some clients may still be using the old flags */
+#define GRALLOC_USAGE_PRIVATE_ALLOC_UBWC GRALLOC1_PRODUCER_USAGE_PRIVATE_ALLOC_UBWC
+#define GRALLOC_USAGE_PRIVATE_UNCACHED GRALLOC1_PRODUCER_USAGE_PRIVATE_UNCACHED
+#define GRALLOC_USAGE_PRIVATE_IOMMU_HEAP GRALLOC1_PRODUCER_USAGE_PRIVATE_IOMMU_HEAP
+#define GRALLOC_USAGE_PRIVATE_WFD GRALLOC1_CONSUMER_USAGE_PRIVATE_WFD
+#define GRALLOC_USAGE_PRIVATE_CAMERA_HEAP GRALLOC1_PRODUCER_USAGE_PRIVATE_CAMERA_HEAP
+#define GRALLOC_USAGE_PRIVATE_SECURE_DISPLAY GRALLOC1_CONSUMER_USAGE_PRIVATE_SECURE_DISPLAY
+#define GRALLOC_USAGE_PRIVATE_MM_HEAP 0x0
+
+
+
+// for PERFORM API :
+#define GRALLOC_MODULE_PERFORM_CREATE_HANDLE_FROM_BUFFER 1
+#define GRALLOC_MODULE_PERFORM_GET_STRIDE 2
+#define GRALLOC_MODULE_PERFORM_GET_CUSTOM_STRIDE_FROM_HANDLE 3
+#define GRALLOC_MODULE_PERFORM_GET_CUSTOM_STRIDE_AND_HEIGHT_FROM_HANDLE 4
+#define GRALLOC_MODULE_PERFORM_GET_ATTRIBUTES 5
+#define GRALLOC_MODULE_PERFORM_GET_COLOR_SPACE_FROM_HANDLE 6
+#define GRALLOC_MODULE_PERFORM_GET_YUV_PLANE_INFO 7
+#define GRALLOC_MODULE_PERFORM_GET_MAP_SECURE_BUFFER_INFO 8
+#define GRALLOC_MODULE_PERFORM_GET_UBWC_FLAG 9
+#define GRALLOC_MODULE_PERFORM_GET_RGB_DATA_ADDRESS 10
+#define GRALLOC_MODULE_PERFORM_GET_IGC 11
+#define GRALLOC_MODULE_PERFORM_SET_IGC 12
+#define GRALLOC_MODULE_PERFORM_SET_SINGLE_BUFFER_MODE 13
+#define GRALLOC1_MODULE_PERFORM_GET_BUFFER_SIZE_AND_DIMENSIONS 14
+#define GRALLOC1_MODULE_PERFORM_ALLOCATE_BUFFER 15
+#define GRALLOC1_MODULE_PERFORM_GET_INTERLACE_FLAG 16
+
+// OEM specific HAL formats
+#define HAL_PIXEL_FORMAT_RGBA_5551 6
+#define HAL_PIXEL_FORMAT_RGBA_4444 7
+#define HAL_PIXEL_FORMAT_NV12_ENCODEABLE 0x102
+#define HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS 0x7FA30C04
+#define HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED 0x7FA30C03
+#define HAL_PIXEL_FORMAT_YCbCr_420_SP 0x109
+#define HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO 0x7FA30C01
+#define HAL_PIXEL_FORMAT_YCrCb_422_SP 0x10B
+#define HAL_PIXEL_FORMAT_R_8 0x10D
+#define HAL_PIXEL_FORMAT_RG_88 0x10E
+#define HAL_PIXEL_FORMAT_YCbCr_444_SP 0x10F
+#define HAL_PIXEL_FORMAT_YCrCb_444_SP 0x110
+#define HAL_PIXEL_FORMAT_YCrCb_422_I 0x111
+#define HAL_PIXEL_FORMAT_BGRX_8888 0x112
+#define HAL_PIXEL_FORMAT_NV21_ZSL 0x113
+#define HAL_PIXEL_FORMAT_YCrCb_420_SP_VENUS 0x114
+#define HAL_PIXEL_FORMAT_BGR_565 0x115
+#define HAL_PIXEL_FORMAT_RAW8 0x123
+
+// 10 bit
+#define HAL_PIXEL_FORMAT_ARGB_2101010 0x117
+#define HAL_PIXEL_FORMAT_RGBX_1010102 0x118
+#define HAL_PIXEL_FORMAT_XRGB_2101010 0x119
+#define HAL_PIXEL_FORMAT_BGRA_1010102 0x11A
+#define HAL_PIXEL_FORMAT_ABGR_2101010 0x11B
+#define HAL_PIXEL_FORMAT_BGRX_1010102 0x11C
+#define HAL_PIXEL_FORMAT_XBGR_2101010 0x11D
+#define HAL_PIXEL_FORMAT_YCbCr_420_P010 0x11F
+#define HAL_PIXEL_FORMAT_YCbCr_420_P010_UBWC 0x124
+
+#define HAL_PIXEL_FORMAT_CbYCrY_422_I 0x120
+#define HAL_PIXEL_FORMAT_BGR_888 0x121
+
+#define HAL_PIXEL_FORMAT_INTERLACE 0x180
+
+// v4l2_fourcc('Y', 'U', 'Y', 'L'). 24 bpp YUYV 4:2:2 10 bit per component
+#define HAL_PIXEL_FORMAT_YCbCr_422_I_10BIT 0x4C595559
+
+// v4l2_fourcc('Y', 'B', 'W', 'C'). 10 bit per component. This compressed
+// format reduces the memory access bandwidth
+#define HAL_PIXEL_FORMAT_YCbCr_422_I_10BIT_COMPRESSED 0x43574259
+
+// UBWC aligned Venus format
+#define HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC 0x7FA30C06
+#define HAL_PIXEL_FORMAT_YCbCr_420_TP10_UBWC 0x7FA30C09
+
+// Khronos ASTC formats
+#define HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_4x4_KHR 0x93B0
+#define HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_5x4_KHR 0x93B1
+#define HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_5x5_KHR 0x93B2
+#define HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_6x5_KHR 0x93B3
+#define HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_6x6_KHR 0x93B4
+#define HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_8x5_KHR 0x93B5
+#define HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_8x6_KHR 0x93B6
+#define HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_8x8_KHR 0x93B7
+#define HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_10x5_KHR 0x93B8
+#define HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_10x6_KHR 0x93B9
+#define HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_10x8_KHR 0x93BA
+#define HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_10x10_KHR 0x93BB
+#define HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_12x10_KHR 0x93BC
+#define HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_12x12_KHR 0x93BD
+#define HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR 0x93D0
+#define HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR 0x93D1
+#define HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR 0x93D2
+#define HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR 0x93D3
+#define HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR 0x93D4
+#define HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR 0x93D5
+#define HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR 0x93D6
+#define HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR 0x93D7
+#define HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR 0x93D8
+#define HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR 0x93D9
+#define HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR 0x93DA
+#define HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR 0x93DB
+#define HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR 0x93DC
+#define HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR 0x93DD
+
+/* possible values for inverse gamma correction */
+#define HAL_IGC_NOT_SPECIFIED 0
+#define HAL_IGC_s_RGB 1
+
+/* Color Space: Values maps to ColorSpace_t in qdMetadata.h */
+#define HAL_CSC_ITU_R_601 0
+#define HAL_CSC_ITU_R_601_FR 1
+#define HAL_CSC_ITU_R_709 2
+#define HAL_CSC_ITU_R_2020 3
+#define HAL_CSC_ITU_R_2020_FR 4
+
+/* possible formats for 3D content*/
+enum {
+ HAL_NO_3D = 0x0,
+ HAL_3D_SIDE_BY_SIDE_L_R = 0x1,
+ HAL_3D_SIDE_BY_SIDE_R_L = 0x2,
+ HAL_3D_TOP_BOTTOM = 0x4,
+ HAL_3D_IN_SIDE_BY_SIDE_L_R = 0x10000, // unused legacy format
+};
+
+enum { BUFFER_TYPE_UI = 0, BUFFER_TYPE_VIDEO };
+
+#endif // __GRALLOC_PRIV_H__
diff --git a/msm8909/hdmi_cec/Android.mk b/msm8909/hdmi_cec/Android.mk
new file mode 100644
index 00000000..4fed1f03
--- /dev/null
+++ b/msm8909/hdmi_cec/Android.mk
@@ -0,0 +1,18 @@
+LOCAL_PATH := $(call my-dir)
+include $(LOCAL_PATH)/../common.mk
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := hdmi_cec.$(TARGET_BOARD_PLATFORM)
+LOCAL_VENDOR_MODULE := true
+LOCAL_MODULE_RELATIVE_PATH := hw
+LOCAL_MODULE_TAGS := optional
+LOCAL_C_INCLUDES := $(common_includes)
+LOCAL_HEADER_LIBRARIES := display_headers
+LOCAL_SHARED_LIBRARIES := $(common_libs)
+
+LOCAL_CFLAGS := $(common_flags) -DLOG_TAG=\"qdhdmi_cec\" -Wno-sign-conversion
+LOCAL_CLANG := true
+LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps)
+LOCAL_SRC_FILES := qhdmi_cec.cpp
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/msm8909/hdmi_cec/qhdmi_cec.cpp b/msm8909/hdmi_cec/qhdmi_cec.cpp
new file mode 100644
index 00000000..be3ff992
--- /dev/null
+++ b/msm8909/hdmi_cec/qhdmi_cec.cpp
@@ -0,0 +1,721 @@
+/*
+* Copyright (c) 2014, 2016-2017, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation. nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#define DEBUG 0
+#define ATRACE_TAG (ATRACE_TAG_GRAPHICS | ATRACE_TAG_HAL)
+#include <log/log.h>
+#include <errno.h>
+#include <hardware/hdmi_cec.h>
+#include <utils/Trace.h>
+#include <utils/debug.h>
+#include <utils/sys.h>
+#include <vector>
+#include "qhdmi_cec.h"
+
+namespace qhdmicec {
+
+const int NUM_HDMI_PORTS = 1;
+const int MAX_SYSFS_DATA = 128;
+const int MAX_CEC_FRAME_SIZE = 20;
+const int MAX_SEND_MESSAGE_RETRIES = 1;
+
+const char* SYSFS_BASE = "/sys/devices/virtual/graphics/fb";
+const char* UEVENT_SWITCH_HDMI = "change@/devices/virtual/switch/hdmi";
+const char* FB_PATH = "/sys/devices/virtual/graphics/fb";
+
+enum {
+ LOGICAL_ADDRESS_SET = 1,
+ LOGICAL_ADDRESS_UNSET = -1,
+};
+
+// Offsets of members of struct hdmi_cec_msg
+// drivers/video/msm/mdss/mdss_hdmi_cec.c
+// XXX: Get this from a driver header
+enum {
+ CEC_OFFSET_SENDER_ID,
+ CEC_OFFSET_RECEIVER_ID,
+ CEC_OFFSET_OPCODE,
+ CEC_OFFSET_OPERAND,
+ CEC_OFFSET_FRAME_LENGTH = 17,
+ CEC_OFFSET_RETRANSMIT,
+};
+
+//Forward declarations
+static void cec_close_context(cec_context_t* ctx __unused);
+static int cec_enable(cec_context_t *ctx, int enable);
+static int cec_is_connected(const struct hdmi_cec_device* dev, int port_id);
+static void cec_monitor_deinit(cec_context_t* ctx);
+static void handle_cec_msg_event(cec_context_t* ctx, uint32_t node_event);
+
+void event_monitor(cec_context_t* ctx); // hdmi event monitor function
+static int get_event_value(const char *uevent_data, int length, const char *event_info);
+static int uevent_init(int *uevent_fd);
+static void handle_hdmihotplug_event(cec_context_t* ctx, uint32_t node_event);
+
+static int populate_event_data(cec_context_t* ctx, std::vector<eventData> *event_data_list);
+static int set_event_params(cec_context_t* ctx, uint32_t node_event, eventData *event_data);
+static void handle_exit_event(cec_context_t* ctx, uint32_t node_event);
+
+static ssize_t read_node(const char *path, char *data)
+{
+ ssize_t err = 0;
+ FILE *fp = NULL;
+ err = access(path, R_OK);
+ if (!err) {
+ fp = fopen(path, "r");
+ if (fp) {
+ err = fread(data, sizeof(char), MAX_SYSFS_DATA ,fp);
+ fclose(fp);
+ }
+ }
+ return err;
+}
+
+static ssize_t write_node(const char *path, const char *data, size_t len)
+{
+ ssize_t err = 0;
+ int fd = -1;
+ err = access(path, W_OK);
+ if (!err) {
+ fd = open(path, O_WRONLY);
+ errno = 0;
+ err = write(fd, data, len);
+ if (err < 0) {
+ err = -errno;
+ }
+ close(fd);
+ } else {
+ ALOGE("%s: Failed to access path: %s error: %s",
+ __FUNCTION__, path, strerror(errno));
+ err = -errno;
+ }
+ return err;
+}
+
+// Helper function to write integer values to the full sysfs path
+static ssize_t write_int_to_node(cec_context_t *ctx,
+ const char *path_postfix,
+ const int value)
+{
+ std::string sysfs_full_path;
+ char sysfs_data[MAX_SYSFS_DATA];
+ snprintf(sysfs_data, sizeof(sysfs_data), "%d",value);
+ sysfs_full_path = ctx->fb_sysfs_path + "/";
+ sysfs_full_path.append(path_postfix);
+ ssize_t err = write_node(sysfs_full_path.c_str(), sysfs_data, strlen(sysfs_data));
+ return err;
+}
+
+static void hex_to_string(const char *msg, ssize_t len, char *str)
+{
+ //Functions assumes sufficient memory in str
+ char *ptr = str;
+ for(int i=0; i < len ; i++) {
+ ptr += snprintf(ptr, 3, "%02X", msg[i]);
+ // Overwrite null termination of snprintf in all except the last byte
+ if (i < len - 1)
+ *ptr = ':';
+ ptr++;
+ }
+}
+
+static ssize_t cec_get_fb_node_number(cec_context_t *ctx)
+{
+ //XXX: Do this from a common utility library across the display HALs
+ const int MAX_FB_DEVICES = 2;
+ ssize_t len = 0;
+ std::string fb_type_path;
+ char fb_type[MAX_SYSFS_DATA];
+ const char *dtv_panel_str = "dtv panel";
+
+ for(int num = 0; num < MAX_FB_DEVICES; num++) {
+ fb_type_path = SYSFS_BASE + std::to_string(ctx->fb_num) + "/msm_fb_type";
+ len = read_node(fb_type_path.c_str(), fb_type);
+ ALOGD_IF(DEBUG, "%s: fb_type:%s", __FUNCTION__, fb_type);
+ if(len > 0 && (strncmp(fb_type, dtv_panel_str, strlen(dtv_panel_str)) == 0)){
+ ALOGD_IF(DEBUG, "%s: Found DTV panel at fb%d", __FUNCTION__, num);
+ ctx->fb_num = num;
+ ctx->fb_sysfs_path = SYSFS_BASE + std::to_string(ctx->fb_num);
+ break;
+ }
+ }
+ if (len < 0)
+ return len;
+ else
+ return 0;
+}
+
+static int cec_add_logical_address(const struct hdmi_cec_device* dev,
+ cec_logical_address_t addr)
+{
+ if (addr < CEC_ADDR_TV || addr > CEC_ADDR_BROADCAST) {
+ ALOGE("%s: Received invalid address: %d ", __FUNCTION__, addr);
+ return -EINVAL;
+ }
+ cec_context_t* ctx = (cec_context_t*)(dev);
+ ctx->logical_address[addr] = LOGICAL_ADDRESS_SET;
+
+ //XXX: We can get multiple logical addresses here but we can only send one
+ //to the driver. Store locally for now
+ ssize_t err = write_int_to_node(ctx, "cec/logical_addr", addr);
+ ALOGI("%s: Allocated logical address: %d ", __FUNCTION__, addr);
+ return (int) err;
+}
+
+static void cec_clear_logical_address(const struct hdmi_cec_device* dev)
+{
+ cec_context_t* ctx = (cec_context_t*)(dev);
+ memset(ctx->logical_address, LOGICAL_ADDRESS_UNSET,
+ sizeof(ctx->logical_address));
+ //XXX: Find logical_addr that needs to be reset
+ write_int_to_node(ctx, "cec/logical_addr", 15);
+ ALOGD_IF(DEBUG, "%s: Cleared logical addresses", __FUNCTION__);
+}
+
+static int cec_get_physical_address(const struct hdmi_cec_device* dev,
+ uint16_t* addr)
+{
+ cec_context_t* ctx = (cec_context_t*)(dev);
+ std::string pa_path;
+ char pa_data[MAX_SYSFS_DATA];
+ pa_path = ctx->fb_sysfs_path;
+ pa_path.append("/pa");
+ int err = (int) read_node(pa_path.c_str(), pa_data);
+ *addr = (uint16_t) atoi(pa_data);
+ ALOGD_IF(DEBUG, "%s: Physical Address: 0x%x", __FUNCTION__, *addr);
+ if (err < 0)
+ return err;
+ else
+ return 0;
+}
+
+static int cec_send_message(const struct hdmi_cec_device* dev,
+ const cec_message_t* msg)
+{
+ ATRACE_CALL();
+ if(cec_is_connected(dev, 0) <= 0)
+ return HDMI_RESULT_FAIL;
+
+ cec_context_t* ctx = (cec_context_t*)(dev);
+ ALOGD_IF(DEBUG, "%s: initiator: %d destination: %d length: %u",
+ __FUNCTION__, msg->initiator, msg->destination,
+ (uint32_t) msg->length);
+
+ // Dump message received from framework
+ char dump[128];
+ if(msg->length > 0) {
+ hex_to_string((char*)msg->body, msg->length, dump);
+ ALOGD_IF(DEBUG, "%s: message from framework: %s", __FUNCTION__, dump);
+ }
+
+ std::string write_msg_path;
+ char write_msg[MAX_CEC_FRAME_SIZE];
+ memset(write_msg, 0, sizeof(write_msg));
+ // See definition of struct hdmi_cec_msg in driver code
+ // drivers/video/msm/mdss/mdss_hdmi_cec.c
+ // Write header block
+ // XXX: Include this from header in kernel
+ write_msg[CEC_OFFSET_SENDER_ID] = msg->initiator;
+ write_msg[CEC_OFFSET_RECEIVER_ID] = msg->destination;
+ //Kernel splits opcode/operand, but Android sends it in one byte array
+ write_msg[CEC_OFFSET_OPCODE] = msg->body[0];
+ if(msg->length > 1) {
+ memcpy(&write_msg[CEC_OFFSET_OPERAND], &msg->body[1],
+ sizeof(char)*(msg->length - 1));
+ }
+ //msg length + initiator + destination
+ write_msg[CEC_OFFSET_FRAME_LENGTH] = (unsigned char) (msg->length + 1);
+ hex_to_string(write_msg, sizeof(write_msg), dump);
+ write_msg_path = ctx->fb_sysfs_path;
+ write_msg_path.append("/cec/wr_msg");
+ int retry_count = 0;
+ ssize_t err = 0;
+ //HAL spec requires us to retry at least once.
+ while (true) {
+ err = write_node(write_msg_path.c_str(), write_msg, sizeof(write_msg));
+ retry_count++;
+ if (err == -EAGAIN && retry_count <= MAX_SEND_MESSAGE_RETRIES) {
+ ALOGE("%s: CEC line busy, retrying", __FUNCTION__);
+ } else {
+ break;
+ }
+ }
+
+ if (err < 0) {
+ if (err == -ENXIO) {
+ ALOGI("%s: No device exists with the destination address",
+ __FUNCTION__);
+ return HDMI_RESULT_NACK;
+ } else if (err == -EAGAIN) {
+ ALOGE("%s: CEC line is busy, max retry count exceeded",
+ __FUNCTION__);
+ return HDMI_RESULT_BUSY;
+ } else {
+ return HDMI_RESULT_FAIL;
+ ALOGE("%s: Failed to send CEC message err: %zd - %s",
+ __FUNCTION__, err, strerror(int(-err)));
+ }
+ } else {
+ ALOGD_IF(DEBUG, "%s: Sent CEC message - %zd bytes written",
+ __FUNCTION__, err);
+ return HDMI_RESULT_SUCCESS;
+ }
+}
+
+void cec_receive_message(cec_context_t *ctx, char *msg, ssize_t len)
+{
+ if(!ctx->system_control)
+ return;
+
+ char dump[128];
+ if(len > 0) {
+ hex_to_string(msg, len, dump);
+ ALOGD_IF(DEBUG, "%s: Message from driver: %s", __FUNCTION__, dump);
+ }
+
+ hdmi_event_t event;
+ event.type = HDMI_EVENT_CEC_MESSAGE;
+ event.dev = (hdmi_cec_device *) ctx;
+ // Remove initiator/destination from this calculation
+ event.cec.length = msg[CEC_OFFSET_FRAME_LENGTH] - 1;
+ event.cec.initiator = (cec_logical_address_t) msg[CEC_OFFSET_SENDER_ID];
+ event.cec.destination = (cec_logical_address_t) msg[CEC_OFFSET_RECEIVER_ID];
+ //Copy opcode and operand
+ size_t copy_size = event.cec.length > sizeof(event.cec.body) ?
+ sizeof(event.cec.body) : event.cec.length;
+ memcpy(event.cec.body, &msg[CEC_OFFSET_OPCODE],copy_size);
+ hex_to_string((char *) event.cec.body, copy_size, dump);
+ ALOGD_IF(DEBUG, "%s: Message to framework: %s", __FUNCTION__, dump);
+ ctx->callback.callback_func(&event, ctx->callback.callback_arg);
+}
+
+void cec_hdmi_hotplug(cec_context_t *ctx, int connected)
+{
+ //Ignore unplug events when system control is disabled
+ if(!ctx->system_control && connected == 0)
+ return;
+ hdmi_event_t event;
+ event.type = HDMI_EVENT_HOT_PLUG;
+ event.dev = (hdmi_cec_device *) ctx;
+ event.hotplug.connected = connected ? HDMI_CONNECTED : HDMI_NOT_CONNECTED;
+ ctx->callback.callback_func(&event, ctx->callback.callback_arg);
+}
+
+static void cec_register_event_callback(const struct hdmi_cec_device* dev,
+ event_callback_t callback, void* arg)
+{
+ ALOGD_IF(DEBUG, "%s: Registering callback", __FUNCTION__);
+ cec_context_t* ctx = (cec_context_t*)(dev);
+ ctx->callback.callback_func = callback;
+ ctx->callback.callback_arg = arg;
+}
+
+static void cec_get_version(const struct hdmi_cec_device* dev, int* version)
+{
+ cec_context_t* ctx = (cec_context_t*)(dev);
+ *version = ctx->version;
+ ALOGD_IF(DEBUG, "%s: version: %d", __FUNCTION__, *version);
+}
+
+static void cec_get_vendor_id(const struct hdmi_cec_device* dev,
+ uint32_t* vendor_id)
+{
+ cec_context_t* ctx = (cec_context_t*)(dev);
+ *vendor_id = ctx->vendor_id;
+ ALOGD_IF(DEBUG, "%s: vendor id: %u", __FUNCTION__, *vendor_id);
+}
+
+static void cec_get_port_info(const struct hdmi_cec_device* dev,
+ struct hdmi_port_info* list[], int* total)
+{
+ ALOGD_IF(DEBUG, "%s: Get port info", __FUNCTION__);
+ cec_context_t* ctx = (cec_context_t*)(dev);
+ *total = NUM_HDMI_PORTS;
+ *list = ctx->port_info;
+}
+
+static void cec_set_option(const struct hdmi_cec_device* dev, int flag,
+ int value)
+{
+ cec_context_t* ctx = (cec_context_t*)(dev);
+ switch (flag) {
+ case HDMI_OPTION_WAKEUP:
+ ALOGD_IF(DEBUG, "%s: Wakeup: value: %d", __FUNCTION__, value);
+ //XXX
+ break;
+ case HDMI_OPTION_ENABLE_CEC:
+ ALOGD_IF(DEBUG, "%s: Enable CEC: value: %d", __FUNCTION__, value);
+ cec_enable(ctx, value? 1 : 0);
+ break;
+ case HDMI_OPTION_SYSTEM_CEC_CONTROL:
+ ALOGD_IF(DEBUG, "%s: system_control: value: %d",
+ __FUNCTION__, value);
+ ctx->system_control = !!value;
+ break;
+ }
+}
+
+static void cec_set_audio_return_channel(const struct hdmi_cec_device* dev,
+ int port, int flag)
+{
+ cec_context_t* ctx = (cec_context_t*)(dev);
+ ctx->arc_enabled = flag ? true : false;
+ ALOGD_IF(DEBUG, "%s: ARC flag: %d port: %d", __FUNCTION__, flag, port);
+}
+
+static int cec_is_connected(const struct hdmi_cec_device* dev, int port_id)
+{
+ // Ignore port_id since we have only one port
+ int connected = 0;
+ cec_context_t* ctx = (cec_context_t*)(dev);
+ std::string connected_path;
+ char connected_data[MAX_SYSFS_DATA];
+ connected_path = ctx->fb_sysfs_path;
+ connected_path.append("/connected");
+ ssize_t err = read_node(connected_path.c_str(), connected_data);
+ connected = atoi(connected_data);
+
+ ALOGD_IF(DEBUG, "%s: HDMI at port %d is - %s", __FUNCTION__, port_id,
+ connected ? "connected":"disconnected");
+ if (err < 0)
+ return (int) err;
+ else
+ return connected;
+}
+
+static int cec_device_close(struct hw_device_t *dev)
+{
+ ALOGD_IF(DEBUG, "%s: Close CEC HAL ", __FUNCTION__);
+ if (!dev) {
+ ALOGE("%s: NULL device pointer", __FUNCTION__);
+ return -EINVAL;
+ }
+ cec_context_t* ctx = (cec_context_t*)(dev);
+ cec_close_context(ctx);
+ free(dev);
+ return 0;
+}
+
+static int cec_enable(cec_context_t *ctx, int enable)
+{
+ ssize_t err;
+ // Enable CEC
+ int value = enable ? 0x3 : 0x0;
+ err = write_int_to_node(ctx, "cec/enable", value);
+ if(err < 0) {
+ ALOGE("%s: Failed to toggle CEC: enable: %d",
+ __FUNCTION__, enable);
+ return (int) err;
+ }
+ ctx->enabled = enable;
+ return 0;
+}
+
+static void cec_init_context(cec_context_t *ctx)
+{
+ ALOGD_IF(DEBUG, "%s: Initializing context", __FUNCTION__);
+ int err = -EINVAL;
+ cec_get_fb_node_number(ctx);
+
+ //Initialize ports - We support only one output port
+ ctx->port_info = new hdmi_port_info[NUM_HDMI_PORTS];
+ ctx->port_info[0].type = HDMI_OUTPUT;
+ ctx->port_info[0].port_id = 1;
+ ctx->port_info[0].cec_supported = 1;
+ //XXX: Enable ARC if supported
+ ctx->port_info[0].arc_supported = 0;
+ cec_get_physical_address((hdmi_cec_device *) ctx,
+ &ctx->port_info[0].physical_address );
+
+ ctx->version = 0x4;
+ ctx->vendor_id = 0xA47733;
+ cec_clear_logical_address((hdmi_cec_device_t*)ctx);
+
+ //Enable CEC - framework expects it to be enabled by default
+ cec_enable(ctx, true);
+
+ ALOGD("%s: CEC enabled", __FUNCTION__);
+
+ ctx->node_list.push_back("cec_msg_event");
+ ctx->node_list.push_back("hotplug_event");
+ ctx->node_list.push_back("exit_event");
+
+ err = populate_event_data(ctx, &ctx->event_data_list);
+ if (err < 0) {
+ ALOGE("Failed to populate poll parameters for monitoring HDMI CEC events. Exiting.");
+ cec_enable(ctx, false);
+ return;
+ }
+
+ ctx->hdmi_cec_monitor = std::thread(event_monitor, ctx);
+
+}
+
+static void cec_close_context(cec_context_t* ctx __unused)
+{
+ ALOGD("%s: Closing context", __FUNCTION__);
+
+ uint64_t exit_value = 1;
+ long int write_size = write(ctx->exit_fd, &exit_value, sizeof(uint64_t));
+
+ if (write_size != sizeof(uint64_t)) {
+ ALOGE("Error triggering exit_fd (%d). write size = %ld, error = %s",
+ ctx->exit_fd, write_size, strerror(errno));
+ return;
+ }
+
+ if (ctx->hdmi_cec_monitor.joinable()) {
+ ctx->hdmi_cec_monitor.join();
+ }
+}
+
+static int cec_device_open(const struct hw_module_t* module,
+ const char* name,
+ struct hw_device_t** device)
+{
+ ALOGD_IF(DEBUG, "%s: name: %s", __FUNCTION__, name);
+ int status = -EINVAL;
+ if (!strcmp(name, HDMI_CEC_HARDWARE_INTERFACE )) {
+ struct cec_context_t *dev;
+ dev = (cec_context_t *) calloc (1, sizeof(*dev));
+ if (dev) {
+ cec_init_context(dev);
+ //Setup CEC methods
+ dev->device.common.tag = HARDWARE_DEVICE_TAG;
+ dev->device.common.version = HDMI_CEC_DEVICE_API_VERSION_1_0;
+ dev->device.common.module = const_cast<hw_module_t* >(module);
+ dev->device.common.close = cec_device_close;
+ dev->device.add_logical_address = cec_add_logical_address;
+ dev->device.clear_logical_address = cec_clear_logical_address;
+ dev->device.get_physical_address = cec_get_physical_address;
+ dev->device.send_message = cec_send_message;
+ dev->device.register_event_callback = cec_register_event_callback;
+ dev->device.get_version = cec_get_version;
+ dev->device.get_vendor_id = cec_get_vendor_id;
+ dev->device.get_port_info = cec_get_port_info;
+ dev->device.set_option = cec_set_option;
+ dev->device.set_audio_return_channel = cec_set_audio_return_channel;
+ dev->device.is_connected = cec_is_connected;
+
+ *device = &dev->device.common;
+ status = 0;
+ } else {
+ status = -EINVAL;
+ }
+ }
+ return status;
+}
+
+void event_monitor(cec_context_t* ctx) {
+ ALOGD("%s IN", __FUNCTION__);
+ int err = -EINVAL;
+
+ prctl(PR_SET_NAME, "cec_monitor", 0, 0, 0);
+ setpriority(PRIO_PROCESS, 0, HAL_PRIORITY_URGENT_DISPLAY);
+
+ while (!ctx->cec_exit_thread) {
+ err = poll(ctx->poll_fds.data(), (nfds_t)ctx->event_data_list.size(), -1);
+ if ( err <= 0 ) {
+ ALOGI("Failed to poll, Error %s", strerror(errno));
+ continue;
+ }
+
+ for (uint32_t event = 0; event < ctx->event_data_list.size(); event++) {
+ pollfd &poll_fd = ctx->poll_fds[event];
+
+ if (poll_fd.revents & POLLIN || poll_fd.revents & POLLPRI) {
+ ctx->event_data_list[event].event_parser(ctx, event);
+ }
+ }
+ }
+
+ cec_monitor_deinit(ctx);
+ ALOGD("%s OUT", __FUNCTION__);
+ return;
+}
+
+static int populate_event_data(cec_context_t* ctx, std::vector<eventData> *event_data_list) {
+ int err = -EINVAL;
+ ctx->poll_fds.resize(ctx->node_list.size());
+
+ for (uint32_t event = 0; event < ctx->node_list.size(); event++) {
+ const char *event_name = ctx->node_list.at(event).c_str();
+ eventData event_data;
+ event_data.event_name = event_name;
+ err = set_event_params(ctx, event, &event_data);
+ if (err < 0) {
+ ALOGE("Failed to set poll event parameters");
+ return err;
+ }
+
+ event_data_list->push_back(event_data);
+ }
+
+ return 0;
+}
+
+static int set_event_params(cec_context_t* ctx, uint32_t node_event, eventData *event_data) {
+ pollfd poll_fd;
+ poll_fd.fd = -EINVAL;
+
+ if (!strncmp(event_data->event_name, "cec_msg_event", strlen("cec_msg_event"))) {
+ char node_path[MAX_STRING_LENGTH] = {0};
+
+ snprintf(node_path, sizeof(node_path), "%s%d/%s", FB_PATH, ctx->fb_num, "cec/rd_msg");
+ poll_fd.fd = open(node_path, O_RDONLY);
+ if (poll_fd.fd < 0) {
+ ALOGE("Node open failed for display %d event %s error %s",
+ ctx->fb_num, "cec/rd_msg", strerror(errno));
+ return poll_fd.fd;
+ }
+
+ poll_fd.events |= POLLPRI | POLLERR;
+ // Read once on fd to clear the data
+ pread(poll_fd.fd, ctx->data, MAX_STRING_LENGTH, 0);
+ event_data->event_parser = &handle_cec_msg_event;
+ } else if (!strncmp(event_data->event_name, "hotplug_event", strlen("hotplug_event"))) {
+ if (!uevent_init(&poll_fd.fd)) {
+ ALOGE("Failed to register uevent for hotplug detection");
+ return -1;
+ }
+
+ poll_fd.events |= POLLIN | POLLERR;
+ event_data->event_parser = &handle_hdmihotplug_event;
+ } else if (!strncmp(event_data->event_name, "exit_event", strlen("exit_event"))) {
+ poll_fd.fd = eventfd(0, 0);
+ poll_fd.events |= POLLIN;
+ event_data->event_parser = &handle_exit_event;
+ ctx->exit_fd = poll_fd.fd;
+ }
+
+ ctx->poll_fds[node_event] = poll_fd;
+ return 0;
+}
+
+static void handle_cec_msg_event(cec_context_t* ctx, uint32_t node_event) {
+ if ((ctx->poll_fds[node_event].revents & POLLPRI) &&
+ (pread(ctx->poll_fds[node_event].fd, ctx->data, MAX_STRING_LENGTH, 0) > 0)) {
+ ALOGD_IF(DEBUG, "Handling CEC message %s", __FUNCTION__);
+ cec_receive_message(ctx, ctx->data, 0);
+ }
+
+ return;
+}
+
+static void handle_hdmihotplug_event(cec_context_t* ctx, uint32_t node_event) {
+ char uevent_data[PAGE_SIZE];
+ int count = 0;
+
+ if (ctx->poll_fds[node_event].revents & POLLIN) {
+ count = static_cast<int> (recv(ctx->poll_fds[node_event].fd, uevent_data,
+ (INT32(sizeof(uevent_data))) - 2, 0));
+
+ if ((count > 0) && (strcasestr(UEVENT_SWITCH_HDMI, uevent_data))) {
+ int connected = get_event_value(uevent_data, count, "SWITCH_STATE=");
+ ALOGD("HDMI CEC is %s", connected ? "connected" : "disconnected");
+ cec_hdmi_hotplug(ctx, connected);
+ }
+ }
+
+ return;
+}
+
+static void handle_exit_event(cec_context_t* ctx, uint32_t node_event) {
+ ALOGD_IF(DEBUG, "Enter %s", __FUNCTION__);
+
+ if (ctx->poll_fds[node_event].revents & POLLIN) {
+ ctx->cec_exit_thread = true;
+ }
+
+ return;
+}
+
+static void cec_monitor_deinit(cec_context_t* ctx) {
+ for (uint32_t event = 0; event < ctx->poll_fds.size(); event++) {
+ close(ctx->poll_fds[event].fd);
+ ctx->poll_fds[event].fd = -1;
+ }
+}
+
+static int get_event_value(const char *uevent_data, int length, const char *event_info) {
+ const char *iterator_str = uevent_data;
+ while (((iterator_str - uevent_data) <= length) && (*iterator_str)) {
+ const char *pstr = strstr(iterator_str, event_info);
+ if (pstr != NULL) {
+ return (atoi(iterator_str + strlen(event_info)));
+ }
+ iterator_str += strlen(iterator_str) + 1;
+ }
+ return -1;
+}
+
+/* Returns 0 on failure, 1 on success */
+static int uevent_init(int *uevent_fd) {
+ struct sockaddr_nl addr;
+ int sz = 64*1024;
+ int s;
+
+ memset(&addr, 0, sizeof(addr));
+ addr.nl_family = AF_NETLINK;
+ addr.nl_pid = getpid();
+ addr.nl_groups = 0xffffffff;
+
+ s = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT);
+ if (s < 0)
+ return 0;
+
+ setsockopt(s, SOL_SOCKET, SO_RCVBUFFORCE, &sz, sizeof(sz));
+
+ if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+ close(s);
+ return 0;
+ }
+
+ *uevent_fd = s;
+ return (*uevent_fd > 0);
+}
+
+}; //namespace qhdmicec
+
+// Standard HAL module, should be outside qhdmicec namespace
+static struct hw_module_methods_t cec_module_methods = {
+ .open = qhdmicec::cec_device_open
+};
+
+hdmi_module_t HAL_MODULE_INFO_SYM = {
+ .common = {
+ .tag = HARDWARE_MODULE_TAG,
+ .version_major = 1,
+ .version_minor = 0,
+ .id = HDMI_CEC_HARDWARE_MODULE_ID,
+ .name = "QTI HDMI CEC module",
+ .author = "The Linux Foundation",
+ .methods = &cec_module_methods,
+ }
+};
diff --git a/msm8909/hdmi_cec/qhdmi_cec.h b/msm8909/hdmi_cec/qhdmi_cec.h
new file mode 100644
index 00000000..e2c97552
--- /dev/null
+++ b/msm8909/hdmi_cec/qhdmi_cec.h
@@ -0,0 +1,91 @@
+/*
+* Copyright (c) 2017 The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation. nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+#ifndef QHDMI_CEC_H
+#define QHDMI_CEC_H
+
+#include <hardware/hdmi_cec.h>
+#include <sys/poll.h>
+#include <sys/prctl.h>
+#include <sys/socket.h>
+#include <sys/resource.h>
+#include <linux/netlink.h>
+#include <thread>
+#include <vector>
+
+namespace qhdmicec {
+
+static const int MAX_STRING_LENGTH = 1024;
+
+struct cec_callback_t {
+ // Function in HDMI service to call back on CEC messages
+ event_callback_t callback_func;
+ // This stores the object to pass back to the framework
+ void* callback_arg;
+
+};
+
+struct eventData;
+
+struct cec_context_t {
+ hdmi_cec_device_t device; // Device for HW module
+ cec_callback_t callback; // Struct storing callback object
+ bool enabled;
+ bool arc_enabled;
+ bool system_control; // If true, HAL/driver handle CEC messages
+ int fb_num; // Framebuffer node for HDMI
+ std::string fb_sysfs_path;
+ hdmi_port_info *port_info; // HDMI port info
+
+ // Logical address is stored in an array, the index of the array is the
+ // logical address and the value in the index shows whether it is set or not
+ int logical_address[CEC_ADDR_BROADCAST];
+ int version;
+ uint32_t vendor_id;
+
+ std::vector<pollfd> poll_fds; // poll fds for cec message monitor and exit signal
+ // on cec message monitor thread
+ int exit_fd = -1;
+ bool cec_exit_thread = false;
+ std::thread hdmi_cec_monitor; // hdmi plugin monitor thread variable
+ char data[MAX_STRING_LENGTH] = {0};
+
+ std::vector<std::string> node_list = {};
+ std::vector<eventData> event_data_list = {};
+};
+
+struct eventData {
+ const char* event_name = NULL;
+ void (*event_parser)(cec_context_t* ctx, uint32_t node_event) = NULL;
+};
+
+void cec_receive_message(cec_context_t *ctx, char *msg, ssize_t len);
+void cec_hdmi_hotplug(cec_context_t *ctx, int connected);
+
+}; //namespace
+#endif /* end of include guard: QHDMI_CEC_H */
diff --git a/msm8909/include/Android.mk b/msm8909/include/Android.mk
new file mode 100644
index 00000000..74c37afe
--- /dev/null
+++ b/msm8909/include/Android.mk
@@ -0,0 +1,20 @@
+LOCAL_PATH:= $(call my-dir)
+include $(LOCAL_PATH)/../common.mk
+include $(CLEAR_VARS)
+
+# Legacy header copy. This is deprecated.
+# Modules using these headers should shift to using
+# LOCAL_HEADER_LIBRARIES := display_headers
+LOCAL_VENDOR_MODULE := true
+LOCAL_COPY_HEADERS_TO := $(common_header_export_path)
+LOCAL_COPY_HEADERS := color_metadata.h \
+ display_properties.h \
+ ../libqdutils/qd_utils.h \
+ ../libqdutils/qdMetaData.h \
+ ../libqdutils/display_config.h \
+ ../libqservice/QServiceUtils.h \
+ ../libqservice/IQService.h \
+ ../libqservice/IQHDMIClient.h \
+ ../libqservice/IQClient.h
+
+include $(BUILD_COPY_HEADERS)
diff --git a/msm8909/include/color_metadata.h b/msm8909/include/color_metadata.h
new file mode 100644
index 00000000..aff6fc93
--- /dev/null
+++ b/msm8909/include/color_metadata.h
@@ -0,0 +1,189 @@
+/*
+* Copyright (c) 2016, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without modification, are permitted
+* provided that the following conditions are met:
+* * Redistributions of source code must retain the above copyright notice, this list of
+* conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright notice, this list of
+* conditions and the following disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its contributors may be used to
+* endorse or promote products derived from this software without specific prior written
+* permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __COLOR_METADATA_H__
+#define __COLOR_METADATA_H__
+
+#ifdef __cplusplus
+extern "C" {
+#else
+#include <stdbool.h>
+#endif
+
+typedef enum ColorRange {
+ Range_Limited = 0,
+ Range_Full = 1,
+ Range_Max = 0xff,
+} ColorRange;
+
+// The following values matches the HEVC spec
+typedef enum ColorPrimaries {
+ // Unused = 0;
+ ColorPrimaries_BT709_5 = 1, // ITU-R BT.709-5 or equivalent
+ /* Unspecified = 2, Reserved = 3*/
+ ColorPrimaries_BT470_6M = 4, // ITU-R BT.470-6 System M or equivalent
+ ColorPrimaries_BT601_6_625 = 5, // ITU-R BT.601-6 625 or equivalent
+ ColorPrimaries_BT601_6_525 = 6, // ITU-R BT.601-6 525 or equivalent
+ ColorPrimaries_SMPTE_240M = 7, // SMPTE_240M
+ ColorPrimaries_GenericFilm = 8, // Generic Film
+ ColorPrimaries_BT2020 = 9, // ITU-R BT.2020 or equivalent
+ ColorPrimaries_SMPTE_ST428 = 10, // SMPTE_240M
+ ColorPrimaries_AdobeRGB = 11,
+ ColorPrimaries_DCIP3 = 12,
+ ColorPrimaries_EBU3213 = 22,
+ ColorPrimaries_Max = 0xff,
+} ColorPrimaries;
+
+typedef enum GammaTransfer {
+ // Unused = 0;
+ Transfer_sRGB = 1, // ITR-BT.709-5
+ /* Unspecified = 2, Reserved = 3 */
+ Transfer_Gamma2_2 = 4,
+ Transfer_Gamma2_8 = 5,
+ Transfer_SMPTE_170M = 6, // BT.601-6 525 or 625
+ Transfer_SMPTE_240M = 7, // SMPTE_240M
+ Transfer_Linear = 8,
+ Transfer_Log = 9,
+ Transfer_Log_Sqrt = 10,
+ Transfer_XvYCC = 11, // IEC 61966-2-4
+ Transfer_BT1361 = 12, // Rec.ITU-R BT.1361 extended gamut
+ Transfer_sYCC = 13, // IEC 61966-2-1 sRGB or sYCC
+ Transfer_BT2020_2_1 = 14, // Rec. ITU-R BT.2020-2 (same as the values 1, 6, and 15)
+ Transfer_BT2020_2_2 = 15, // Rec. ITU-R BT.2020-2 (same as the values 1, 6, and 14)
+ Transfer_SMPTE_ST2084 = 16, // 2084
+ // transfers unlikely to be required by Android
+ Transfer_ST_428 = 17, // SMPTE ST 428-1
+ Transfer_HLG = 18, // ARIB STD-B67
+ Transfer_Max = 0xff,
+} GammaTransfer;
+
+typedef enum MatrixCoEfficients {
+ MatrixCoEff_Identity = 0,
+ MatrixCoEff_BT709_5 = 1,
+ /* Unspecified = 2, Reserved = 3 */
+ MatrixCoeff_FCC_73_682 = 4,
+ MatrixCoEff_BT601_6_625 = 5,
+ MatrixCoEff_BT601_6_525 = 6,
+ MatrixCoEff_SMPTE240M = 7, // used with 601_525_Unadjusted
+ MatrixCoEff_YCgCo = 8,
+ MatrixCoEff_BT2020 = 9,
+ MatrixCoEff_BT2020Constant = 10,
+ MatrixCoEff_BT601_6_Unadjusted = 11, // Used with BT601_625(KR=0.222, KB=0.071)
+ MatrixCoEff_DCIP3 = 12,
+ MatrixCoEff_Chroma_NonConstant = 13,
+ MatrixCoEff_Max = 0xff,
+} MatrixCoEfficients;
+
+typedef struct Primaries {
+ uint32_t rgbPrimaries[3][2]; // unit 1/50000;
+ uint32_t whitePoint[2]; // unit 1/50000;
+} Primaries;
+
+typedef struct MasteringDisplay {
+ bool colorVolumeSEIEnabled;
+ Primaries primaries;
+ uint32_t maxDisplayLuminance; // unit: cd/m^2.
+ uint32_t minDisplayLuminance; // unit: 1/10000 cd/m^2.
+} MasteringDisplay;
+
+typedef struct ContentLightLevel {
+ bool lightLevelSEIEnabled;
+ uint32_t maxContentLightLevel; // unit: cd/m^2.
+ uint32_t minPicAverageLightLevel; // unit: 1/10000 cd/m^2.
+} ContentLightLevel;
+
+typedef struct ColorRemappingInfo {
+ bool criEnabled;
+ uint32_t crId;
+ uint32_t crCancelFlag;
+ uint32_t crPersistenceFlag;
+ uint32_t crVideoSignalInfoPresentFlag;
+ uint32_t crRange;
+ ColorPrimaries crPrimaries;
+ GammaTransfer crTransferFunction;
+ MatrixCoEfficients crMatrixCoefficients;
+ uint32_t crInputBitDepth;
+ uint32_t crOutputBitDepth;
+ uint32_t crPreLutNumValMinusOne[3];
+ uint32_t crPreLutCodedValue[3*33];
+ uint32_t crPreLutTargetValue[3*33];
+ uint32_t crMatrixPresentFlag;
+ uint32_t crLog2MatrixDenom;
+ int32_t crCoefficients[3*3];
+ uint32_t crPostLutNumValMinusOne[3];
+ uint32_t crPostLutCodedValue[3*33];
+ uint32_t crPostLutTargetValue[3*33];
+} ColorRemappingInfo;
+
+typedef struct ColorMetaData {
+ // Default values based on sRGB, needs to be overridden in gralloc
+ // based on the format and size.
+ ColorPrimaries colorPrimaries;
+ ColorRange range;
+ GammaTransfer transfer;
+ MatrixCoEfficients matrixCoefficients;
+
+ MasteringDisplay masteringDisplayInfo;
+ ContentLightLevel contentLightLevel;
+ ColorRemappingInfo cRI;
+} ColorMetaData;
+
+typedef struct Color10Bit {
+ uint32_t R: 10;
+ uint32_t G: 10;
+ uint32_t B: 10;
+ uint32_t A: 2;
+} Color10Bit;
+
+typedef struct Lut3d {
+ uint16_t dim; // dimension of each side of LUT cube (ex: 13, 17)in lutEntries
+ uint16_t gridSize; // number of elements in the gridEntries
+ /* Matrix ordering convension
+ for (b = 0; b < dim; b++) {
+ for (g = 0; g < dim; g++) {
+ for (r = 0; r < dim; r++) {
+ read/write [mR mG mB] associated w/ 3DLUT[r][g][b] to/from file
+ }
+ }
+ } */
+ Color10Bit *lutEntries;
+ bool validLutEntries; // Indicates if entries are valid and can be used.
+ /*
+ The grid is a 1D LUT for each of the R,G,B channels that can be
+ used to apply an independent nonlinear transformation to each
+ channel before it is used as a coordinate for addressing
+ the uniform 3D LUT. This effectively creates a non-uniformly
+ sampled 3D LUT. This is useful for having independent control
+ of the sampling grid density along each dimension for greater
+ precision in spite of having a relatively small number of samples.i
+ */
+ Color10Bit *gridEntries;
+ bool validGridEntries; // Indicates if entries are valid and can be used.
+} Lut3d;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // __COLOR_METADATA_H__
diff --git a/msm8909/include/display_properties.h b/msm8909/include/display_properties.h
new file mode 100644
index 00000000..b9c8971a
--- /dev/null
+++ b/msm8909/include/display_properties.h
@@ -0,0 +1,101 @@
+/*
+* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __DISPLAY_PROPERTIES_H__
+#define __DISPLAY_PROPERTIES_H__
+
+#define DISP_PROP_PREFIX "vendor.display."
+#define GRALLOC_PROP_PREFIX "vendor.gralloc."
+#define RO_DISP_PROP_PREFIX "ro.vendor.display."
+#define PERSIST_DISP_PROP_PREFIX "persist.vendor.display."
+
+#define DISPLAY_PROP(prop_name) DISP_PROP_PREFIX prop_name
+#define GRALLOC_PROP(prop_name) GRALLOC_PROP_PREFIX prop_name
+#define RO_DISPLAY_PROP(prop_name) RO_DISP_PROP_PREFIX prop_name
+#define PERSIST_DISPLAY_PROP(prop_name) PERSIST_DISP_PROP_PREFIX prop_name
+
+#define COMPOSITION_MASK_PROP DISPLAY_PROP("comp_mask")
+#define HDMI_CONFIG_INDEX_PROP DISPLAY_PROP("hdmi_cfg_idx")
+#define IDLE_TIME_PROP DISPLAY_PROP("idle_time")
+#define IDLE_TIME_INACTIVE_PROP DISPLAY_PROP("idle_time_inactive")
+#define BOOT_ANIMATION_LAYER_COUNT_PROP DISPLAY_PROP("boot_anim_layer_count")
+#define DISABLE_ROTATOR_DOWNSCALE_PROP DISPLAY_PROP("disable_rotator_downscale")
+#define DISABLE_DECIMATION_PROP DISPLAY_PROP("disable_decimation")
+#define PRIMARY_MIXER_STAGES_PROP DISPLAY_PROP("primary_mixer_stages")
+#define EXTERNAL_MIXER_STAGES_PROP DISPLAY_PROP("external_mixer_stages")
+#define VIRTUAL_MIXER_STAGES_PROP DISPLAY_PROP("virtual_mixer_stages")
+#define MAX_UPSCALE_PROP DISPLAY_PROP("max_upscale")
+#define VIDEO_MODE_PANEL_PROP DISPLAY_PROP("video_mode_panel")
+#define DISABLE_ROTATOR_UBWC_PROP DISPLAY_PROP("disable_rotator_ubwc")
+#define DISABLE_ROTATOR_SPLIT_PROP DISPLAY_PROP("disable_rotator_split")
+#define DISABLE_SCALER_PROP DISPLAY_PROP("disable_scaler")
+#define DISABLE_AVR_PROP DISPLAY_PROP("disable_avr")
+#define DISABLE_EXTERNAL_ANIMATION_PROP DISPLAY_PROP("disable_ext_anim")
+#define DISABLE_PARTIAL_SPLIT_PROP DISPLAY_PROP("disable_partial_split")
+#define PREFER_SOURCE_SPLIT_PROP DISPLAY_PROP("prefer_source_split")
+#define MIXER_RESOLUTION_PROP DISPLAY_PROP("mixer_resolution")
+#define SIMULATED_CONFIG_PROP DISPLAY_PROP("simulated_config")
+#define MAX_EXTERNAL_LAYERS_PROP DISPLAY_PROP("max_external_layers")
+#define PERF_HINT_WINDOW_PROP DISPLAY_PROP("perf_hint_window")
+#define ENABLE_EXTERNAL_DOWNSCALE_PROP DISPLAY_PROP("enable_external_downscale")
+#define EXTERNAL_ACTION_SAFE_WIDTH_PROP DISPLAY_PROP("external_action_safe_width")
+#define EXTERNAL_ACTION_SAFE_HEIGHT_PROP DISPLAY_PROP("external_action_safe_height")
+#define FB_WIDTH_PROP DISPLAY_PROP("fb_width")
+#define FB_HEIGHT_PROP DISPLAY_PROP("fb_height")
+#define DISABLE_METADATA_DYNAMIC_FPS_PROP DISPLAY_PROP("disable_metadata_dynamic_fps")
+#define DISABLE_BLIT_COMPOSITION_PROP DISPLAY_PROP("disable_blit_comp")
+#define DISABLE_SKIP_VALIDATE_PROP DISPLAY_PROP("disable_skip_validate")
+#define HDMI_S3D_MODE_PROP DISPLAY_PROP("hdmi_s3d_mode")
+#define DISABLE_DESTINATION_SCALER_PROP DISPLAY_PROP("disable_dest_scaler")
+#define ENABLE_PARTIAL_UPDATE_PROP DISPLAY_PROP("enable_partial_update")
+#define ENABLE_ROTATOR_SYNC_ALLOC DISPLAY_PROP("rotator_sync_alloc")
+#define WRITEBACK_SUPPORTED DISPLAY_PROP("support_writeback")
+#define DISABLE_UBWC_PROP GRALLOC_PROP("disable_ubwc")
+#define ENABLE_FB_UBWC_PROP GRALLOC_PROP("enable_fb_ubwc")
+#define MAP_FB_MEMORY_PROP GRALLOC_PROP("map_fb_memory")
+
+#define MAX_BLIT_FACTOR_PROP DISPLAY_PROP("max_blit_factor")
+#define DISABLE_SECURE_INLINE_ROTATOR_PROP DISPLAY_PROP("disable_secure_inline_rotator")
+#define DISABLE_MULTIRECT_PROP DISPLAY_PROP("disable_multirect")
+#define DISABLE_UBWC_FF_VOTING_PROP DISPLAY_PROP("disable_ubwc_ff_voting")
+#define DISABLE_INLINE_ROTATOR_PROP DISPLAY_PROP("disable_inline_rotator")
+#define DISABLE_FB_CROPPING_PROP DISPLAY_PROP("disable_fb_cropping")
+#define PRIORITIZE_CACHE_COMPOSITION_PROP DISPLAY_PROP("prioritize_cache_comp")
+
+#define DISABLE_HDR_LUT_GEN DISPLAY_PROP("disable_hdr_lut_gen")
+#define ENABLE_DEFAULT_COLOR_MODE DISPLAY_PROP("enable_default_color_mode")
+#define DISABLE_HDR DISPLAY_PROP("disable_hdr")
+
+#define HDR_CONFIG_PROP RO_DISPLAY_PROP("hdr.config")
+#define QDCM_PCC_TRANS_PROP DISPLAY_PROP("qdcm.pcc_for_trans")
+#define QDCM_DIAGONAL_MATRIXMODE_PROP DISPLAY_PROP("qdcm.diagonal_matrix_mode")
+#define QDCM_DISABLE_TIMEOUT_PROP PERSIST_DISPLAY_PROP("qdcm.disable_timeout")
+
+
+#endif // __DISPLAY_PROPERTIES_H__
diff --git a/msm8909/libcopybit/Android.mk b/msm8909/libcopybit/Android.mk
index f2c78b21..6e906c36 100644
--- a/msm8909/libcopybit/Android.mk
+++ b/msm8909/libcopybit/Android.mk
@@ -14,22 +14,24 @@
LOCAL_PATH:= $(call my-dir)
include $(LOCAL_PATH)/../common.mk
-
include $(CLEAR_VARS)
+
LOCAL_COPY_HEADERS_TO := $(common_header_export_path)
LOCAL_COPY_HEADERS := copybit.h copybit_priv.h c2d2.h
+#Copy the headers regardless of whether copybit is built
include $(BUILD_COPY_HEADERS)
include $(CLEAR_VARS)
+ifneq ($(TARGET_USES_GRALLOC1), true)
LOCAL_MODULE := copybit.$(TARGET_BOARD_PLATFORM)
+LOCAL_VENDOR_MODULE := true
LOCAL_MODULE_RELATIVE_PATH := hw
-LOCAL_PROPRIETARY_MODULE := true
LOCAL_MODULE_TAGS := optional
LOCAL_C_INCLUDES := $(common_includes) $(kernel_includes)
LOCAL_SHARED_LIBRARIES := $(common_libs) libdl libmemalloc
-LOCAL_CFLAGS := $(common_flags) -DLOG_TAG=\"qdcopybit\"
+LOCAL_CFLAGS := $(common_flags) -DLOG_TAG=\"qdcopybit\" -Wno-sign-conversion
LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps)
-LOCAL_CLANG := $(common_clang_flags)
+LOCAL_CLANG := true
ifeq ($(TARGET_USES_C2D_COMPOSITION),true)
LOCAL_CFLAGS += -DCOPYBIT_Z180=1 -DC2D_SUPPORT_DISPLAY=1
@@ -48,3 +50,4 @@ else
endif
endif
endif
+endif
diff --git a/msm8909/libcopybit/c2d2.h b/msm8909/libcopybit/c2d2.h
index 886f38a2..315a3ba5 100644
--- a/msm8909/libcopybit/c2d2.h
+++ b/msm8909/libcopybit/c2d2.h
@@ -72,6 +72,7 @@ typedef enum {
C2D_FORMAT_MACROTILED = (1 << 16), /* tiled in macro level */
C2D_FORMAT_TILED_4x4 = (1 << 17), /* 4x4 tiled format */
C2D_FORMAT_SWAP_RB = (1 << 18), /* Swap R & B color components */
+ C2D_FORMAT_UBWC_COMPRESSED = (1 << 23), /* UBWC compressed format */
} C2D_FORMAT_MODE;
/* Definitions of supported RGB formats, used in C2D_RGB_SURFACE_DEF.
@@ -408,7 +409,8 @@ typedef enum {
C2D_DRIVER_SUPPORTS_TARGET_RECT_OP = (1 << 15),
C2D_DRIVER_SUPPORTS_ROTATE_OP = (1 << 16), /* all rotations */
C2D_DRIVER_SUPPORTS_FLUSH_WITH_FENCE_FD_OP = (1 << 17), /* all rotations */
- C2D_DRIVER_SUPPORTS_ALL_CAPABILITIES_OP = ((0xFFFFFFFF) >> (31 - 17)) /* mask for all capabilities supported */
+ C2D_DRIVER_SUPPORTS_UBWC_COMPRESSED_OP = (1 << 18), /* UBWC Compression */
+ C2D_DRIVER_SUPPORTS_ALL_CAPABILITIES_OP = ((0xFFFFFFFF) >> (31 - 18)) /* mask for all capabilities supported */
} C2D_DRIVER_CAPABILITIES;
/* 2D driver workaround bits used by the 2D applications */
diff --git a/msm8909/libcopybit/copybit.cpp b/msm8909/libcopybit/copybit.cpp
index c2790f8d..bd49edc2 100644
--- a/msm8909/libcopybit/copybit.cpp
+++ b/msm8909/libcopybit/copybit.cpp
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2008 The Android Open Source Project
- * Copyright (c) 2010 - 2014,2016 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2010 - 2014, The Linux Foundation. All rights reserved.
*
* Not a Contribution, Apache license notifications and license are retained
* for attribution purposes only.
@@ -18,7 +18,7 @@
* limitations under the License.
*/
-#include <cutils/log.h>
+#include <log/log.h>
#include <linux/msm_mdp.h>
#include <linux/fb.h>
@@ -75,22 +75,22 @@ static int open_copybit(const struct hw_module_t* module, const char* name,
struct hw_device_t** device);
static struct hw_module_methods_t copybit_module_methods = {
- .open = open_copybit
+open: open_copybit
};
/*
* The COPYBIT Module
*/
struct copybit_module_t HAL_MODULE_INFO_SYM = {
- .common = {
- .tag = HARDWARE_MODULE_TAG,
- .version_major = 1,
- .version_minor = 0,
- .id = COPYBIT_HARDWARE_MODULE_ID,
- .name = "QCT MSM7K COPYBIT Module",
- .author = "Google, Inc.",
- .methods = &copybit_module_methods
- }
+common: {
+tag: HARDWARE_MODULE_TAG,
+ version_major: 1,
+ version_minor: 0,
+ id: COPYBIT_HARDWARE_MODULE_ID,
+ name: "QCT MSM7K COPYBIT Module",
+ author: "Google, Inc.",
+ methods: &copybit_module_methods
+ }
};
/******************************************************************************/
@@ -131,6 +131,8 @@ static bool validateCopybitRect(struct copybit_rect_t *rect) {
static int get_format(int format) {
switch (format) {
case HAL_PIXEL_FORMAT_RGB_565: return MDP_RGB_565;
+ case HAL_PIXEL_FORMAT_RGBA_5551: return MDP_RGBA_5551;
+ case HAL_PIXEL_FORMAT_RGBA_4444: return MDP_RGBA_4444;
case HAL_PIXEL_FORMAT_RGBX_8888: return MDP_RGBX_8888;
case HAL_PIXEL_FORMAT_BGRX_8888: return MDP_BGRX_8888;
case HAL_PIXEL_FORMAT_RGB_888: return MDP_RGB_888;
@@ -144,7 +146,10 @@ static int get_format(int format) {
case HAL_PIXEL_FORMAT_YCbCr_420_SP: return MDP_Y_CBCR_H2V2;
case HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO: return MDP_Y_CBCR_H2V2_ADRENO;
case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS: return MDP_Y_CBCR_H2V2_VENUS;
+ case HAL_PIXEL_FORMAT_YCrCb_420_SP_VENUS: return MDP_Y_CRCB_H2V2_VENUS;
case HAL_PIXEL_FORMAT_NV12_ENCODEABLE: return MDP_Y_CBCR_H2V2;
+ case HAL_PIXEL_FORMAT_CbYCrY_422_I: return MDP_CBYCRY_H2V1;
+ case HAL_PIXEL_FORMAT_BGR_888: return MDP_BGR_888;
}
return -1;
}
@@ -454,6 +459,8 @@ static int stretch_copybit(
// we don't support plane alpha with RGBA formats
case HAL_PIXEL_FORMAT_RGBA_8888:
case HAL_PIXEL_FORMAT_BGRA_8888:
+ case HAL_PIXEL_FORMAT_RGBA_5551:
+ case HAL_PIXEL_FORMAT_RGBA_4444:
ALOGE ("%s : Unsupported Pixel format %d", __FUNCTION__,
src->format);
return -EINVAL;
diff --git a/msm8909/libcopybit/copybit.h b/msm8909/libcopybit/copybit.h
index b4af0214..de585ee3 100644
--- a/msm8909/libcopybit/copybit.h
+++ b/msm8909/libcopybit/copybit.h
@@ -49,6 +49,8 @@ enum {
COPYBIT_FORMAT_RGB_888 = HAL_PIXEL_FORMAT_RGB_888,
COPYBIT_FORMAT_RGB_565 = HAL_PIXEL_FORMAT_RGB_565,
COPYBIT_FORMAT_BGRA_8888 = HAL_PIXEL_FORMAT_BGRA_8888,
+ COPYBIT_FORMAT_RGBA_5551 = HAL_PIXEL_FORMAT_RGBA_5551,
+ COPYBIT_FORMAT_RGBA_4444 = HAL_PIXEL_FORMAT_RGBA_4444,
COPYBIT_FORMAT_YCbCr_422_SP = 0x10,
COPYBIT_FORMAT_YCrCb_420_SP = 0x11,
};
@@ -78,6 +80,10 @@ enum {
COPYBIT_FRAMEBUFFER_HEIGHT = 8,
COPYBIT_FG_LAYER = 9,
COPYBIT_DYNAMIC_FPS = 10,
+ /* Source Format Mode */
+ COPYBIT_SRC_FORMAT_MODE = 11,
+ /* Destination Format Mode */
+ COPYBIT_DST_FORMAT_MODE = 12,
};
/* values for copybit_set_parameter(COPYBIT_TRANSFORM) */
@@ -114,6 +120,13 @@ enum {
COPYBIT_BLENDING_COVERAGE = 0x0405
};
+enum {
+ /* Linear format mode*/
+ COPYBIT_LINEAR = 0x0000,
+ /* UBWC format mode*/
+ COPYBIT_UBWC_COMPRESSED = 0x0001,
+};
+
/* use get_static_info() to query static informations about the hardware */
enum {
/* Maximum amount of minification supported by the hardware*/
@@ -124,6 +137,8 @@ enum {
COPYBIT_SCALING_FRAC_BITS = 3,
/* Supported rotation step in degres. */
COPYBIT_ROTATION_STEP_DEG = 4,
+ /* UBWC support*/
+ COPYBIT_UBWC_SUPPORT = 5,
};
/* Image structure */
diff --git a/msm8909/libcopybit/copybit_c2d.cpp b/msm8909/libcopybit/copybit_c2d.cpp
index 43408555..63c13790 100644
--- a/msm8909/libcopybit/copybit_c2d.cpp
+++ b/msm8909/libcopybit/copybit_c2d.cpp
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2008 The Android Open Source Project
- * Copyright (c) 2010-2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2010-2015, The Linux Foundation. All rights reserved.
*
* Not a Contribution, Apache license notifications and license are retained
* for attribution purposes only.
@@ -17,7 +17,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-#include <cutils/log.h>
+#include <log/log.h>
#include <sys/resource.h>
#include <sys/prctl.h>
@@ -124,7 +124,8 @@ enum eConversionType {
enum eC2DFlags {
FLAGS_PREMULTIPLIED_ALPHA = 1<<0,
FLAGS_YUV_DESTINATION = 1<<1,
- FLAGS_TEMP_SRC_DST = 1<<2
+ FLAGS_TEMP_SRC_DST = 1<<2,
+ FLAGS_UBWC_FORMAT_MODE = 1<<3
};
static gralloc::IAllocController* sAlloc = 0;
@@ -159,6 +160,8 @@ struct copybit_context_t {
void* time_stamp;
bool dst_surface_mapped; // Set when dst surface is mapped to GPU addr
void* dst_surface_base; // Stores the dst surface addr
+ bool is_src_ubwc_format;
+ bool is_dst_ubwc_format;
// used for signaling the wait thread
bool wait_timestamp;
@@ -264,6 +267,8 @@ static int get_format(int format) {
case HAL_PIXEL_FORMAT_RGBA_8888: return C2D_COLOR_FORMAT_8888_ARGB |
C2D_FORMAT_SWAP_RB;
case HAL_PIXEL_FORMAT_BGRA_8888: return C2D_COLOR_FORMAT_8888_ARGB;
+ case HAL_PIXEL_FORMAT_RGBA_5551: return C2D_COLOR_FORMAT_5551_RGBA;
+ case HAL_PIXEL_FORMAT_RGBA_4444: return C2D_COLOR_FORMAT_4444_RGBA;
case HAL_PIXEL_FORMAT_YCbCr_420_SP: return C2D_COLOR_FORMAT_420_NV12;
case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:return C2D_COLOR_FORMAT_420_NV12;
case HAL_PIXEL_FORMAT_YCrCb_420_SP: return C2D_COLOR_FORMAT_420_NV21;
@@ -348,12 +353,7 @@ static size_t c2d_get_gpuaddr(copybit_context_t* ctx,
if(!handle)
return 0;
- if (handle->flags & (private_handle_t::PRIV_FLAGS_USES_PMEM |
- private_handle_t::PRIV_FLAGS_USES_PMEM_ADSP))
- memtype = KGSL_USER_MEM_TYPE_PMEM;
- else if (handle->flags & private_handle_t::PRIV_FLAGS_USES_ASHMEM)
- memtype = KGSL_USER_MEM_TYPE_ASHMEM;
- else if (handle->flags & private_handle_t::PRIV_FLAGS_USES_ION)
+ if (handle->flags & private_handle_t::PRIV_FLAGS_USES_ION)
memtype = KGSL_USER_MEM_TYPE_ION;
else {
ALOGE("Invalid handle flags: 0x%x", handle->flags);
@@ -402,7 +402,9 @@ static int is_supported_rgb_format(int format)
case HAL_PIXEL_FORMAT_RGBX_8888:
case HAL_PIXEL_FORMAT_RGB_888:
case HAL_PIXEL_FORMAT_RGB_565:
- case HAL_PIXEL_FORMAT_BGRA_8888: {
+ case HAL_PIXEL_FORMAT_BGRA_8888:
+ case HAL_PIXEL_FORMAT_RGBA_5551:
+ case HAL_PIXEL_FORMAT_RGBA_4444: {
return COPYBIT_SUCCESS;
}
default:
@@ -544,6 +546,10 @@ static int set_image(copybit_context_t* ctx, uint32 surfaceId,
surfaceDef.format = c2d_format |
((flags & FLAGS_PREMULTIPLIED_ALPHA) ? C2D_FORMAT_PREMULTIPLIED : 0);
+
+ surfaceDef.format = surfaceDef.format |
+ ((flags & FLAGS_UBWC_FORMAT_MODE) ? C2D_FORMAT_UBWC_COMPRESSED : 0);
+
surfaceDef.width = rhs->w;
surfaceDef.height = rhs->h;
int aligned_width = ALIGN((int)surfaceDef.width,32);
@@ -700,6 +706,8 @@ static int clear_copybit(struct copybit_device_t *dev,
int flags = FLAGS_PREMULTIPLIED_ALPHA;
int mapped_dst_idx = -1;
struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
+ if (ctx->is_dst_ubwc_format)
+ flags |= FLAGS_UBWC_FORMAT_MODE;
C2D_RECT c2drect = {rect->l, rect->t, rect->r - rect->l, rect->b - rect->t};
pthread_mutex_lock(&ctx->wait_cleanup_lock);
if(!ctx->dst_surface_mapped) {
@@ -865,6 +873,12 @@ static int set_parameter_copybit(
case COPYBIT_BLIT_TO_FRAMEBUFFER:
// Do nothing
break;
+ case COPYBIT_SRC_FORMAT_MODE:
+ ctx->is_src_ubwc_format = (value == COPYBIT_UBWC_COMPRESSED);
+ break;
+ case COPYBIT_DST_FORMAT_MODE:
+ ctx->is_dst_ubwc_format = (value == COPYBIT_UBWC_COMPRESSED);
+ break;
default:
ALOGE("%s: default case param=0x%x", __FUNCTION__, name);
status = -EINVAL;
@@ -898,6 +912,12 @@ static int get(struct copybit_device_t *dev, int name)
case COPYBIT_ROTATION_STEP_DEG:
value = 1;
break;
+ case COPYBIT_UBWC_SUPPORT:
+ value = 0;
+ if (ctx->c2d_driver_info.capabilities_mask & C2D_DRIVER_SUPPORTS_UBWC_COMPRESSED_OP) {
+ value = 1;
+ }
+ break;
default:
ALOGE("%s: default case param=0x%x", __FUNCTION__, name);
value = -EINVAL;
@@ -980,7 +1000,7 @@ static int get_temp_buffer(const bufferInfo& info, alloc_data& data)
data.size = get_size(info);
data.align = getpagesize();
data.uncached = true;
- int allocFlags = GRALLOC_USAGE_PRIVATE_SYSTEM_HEAP;
+ int allocFlags = 0;
if (sAlloc == 0) {
sAlloc = gralloc::IAllocController::getInstance();
@@ -1103,6 +1123,9 @@ static int stretch_copybit_internal(
}
int dst_surface_type;
+ if (ctx->is_dst_ubwc_format)
+ flags |= FLAGS_UBWC_FORMAT_MODE;
+
if (is_supported_rgb_format(dst->format) == COPYBIT_SUCCESS) {
dst_surface_type = RGB_SURFACE;
flags |= FLAGS_PREMULTIPLIED_ALPHA;
@@ -1285,6 +1308,7 @@ static int stretch_copybit_internal(
flags |= (ctx->is_premultiplied_alpha) ? FLAGS_PREMULTIPLIED_ALPHA : 0;
flags |= (ctx->dst_surface_type != RGB_SURFACE) ? FLAGS_YUV_DESTINATION : 0;
+ flags |= (ctx->is_src_ubwc_format) ? FLAGS_UBWC_FORMAT_MODE : 0;
status = set_image(ctx, src_surface.surface_id, &src_image,
(eC2DFlags)flags, mapped_src_idx);
if(status) {
diff --git a/msm8909/libcopybit/software_converter.cpp b/msm8909/libcopybit/software_converter.cpp
index 5b41d41a..1aa3ce60 100644
--- a/msm8909/libcopybit/software_converter.cpp
+++ b/msm8909/libcopybit/software_converter.cpp
@@ -27,8 +27,7 @@
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include <cutils/log.h>
-#include <string.h>
+#include <log/log.h>
#include <stdlib.h>
#include <errno.h>
#include "software_converter.h"
diff --git a/msm8909/libcopybit/software_converter.h b/msm8909/libcopybit/software_converter.h
index 6e53e164..cc6ae342 100644
--- a/msm8909/libcopybit/software_converter.h
+++ b/msm8909/libcopybit/software_converter.h
@@ -31,11 +31,12 @@
#include <copybit.h>
#include "gralloc_priv.h"
-#include "gr.h"
#define COPYBIT_SUCCESS 0
#define COPYBIT_FAILURE -1
+#define ALIGN(x, y) (((x) + y - 1) & (~(y - 1)))
+
int convertYV12toYCrCb420SP(const copybit_image_t *src,private_handle_t *yv12_handle);
/*
diff --git a/msm8909/libdisplayconfig/Android.mk b/msm8909/libdisplayconfig/Android.mk
new file mode 100644
index 00000000..3d44444c
--- /dev/null
+++ b/msm8909/libdisplayconfig/Android.mk
@@ -0,0 +1,13 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := libdisplayconfig
+LOCAL_MODULE_TAGS := optional
+LOCAL_C_INCLUDES := $(common_includes)
+LOCAL_HEADER_LIBRARIES := display_headers
+LOCAL_SRC_FILES := DisplayConfig.cpp
+LOCAL_SHARED_LIBRARIES := libhidlbase libhidltransport libutils \
+ vendor.display.config@1.0
+LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/msm8909/libdisplayconfig/DisplayConfig.cpp b/msm8909/libdisplayconfig/DisplayConfig.cpp
new file mode 100644
index 00000000..29fcc940
--- /dev/null
+++ b/msm8909/libdisplayconfig/DisplayConfig.cpp
@@ -0,0 +1,363 @@
+/*
+* Copyright (c) 2017 The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation. nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <vendor/display/config/1.0/IDisplayConfig.h>
+
+#include "DisplayConfig.h"
+
+namespace display {
+
+using vendor::display::config::V1_0::IDisplayConfig;
+
+//=============================================================================
+// The functions below run in the client process and wherever necessary
+// do a binder call to HWC to get/set data.
+
+IDisplayConfig::DisplayType MapDisplayType(int dpy) {
+ switch (dpy) {
+ case DISPLAY_PRIMARY:
+ return IDisplayConfig::DisplayType::DISPLAY_PRIMARY;
+
+ case DISPLAY_EXTERNAL:
+ return IDisplayConfig::DisplayType::DISPLAY_EXTERNAL;
+
+ case DISPLAY_VIRTUAL:
+ return IDisplayConfig::DisplayType::DISPLAY_VIRTUAL;
+
+ default:
+ break;
+ }
+
+ return IDisplayConfig::DisplayType::INVALID;
+}
+
+IDisplayConfig::DisplayExternalStatus MapExternalStatus(uint32_t status) {
+ switch (status) {
+ case EXTERNAL_OFFLINE:
+ return IDisplayConfig::DisplayExternalStatus::EXTERNAL_OFFLINE;
+
+ case EXTERNAL_ONLINE:
+ return IDisplayConfig::DisplayExternalStatus::EXTERNAL_ONLINE;
+
+ case EXTERNAL_PAUSE:
+ return IDisplayConfig::DisplayExternalStatus::EXTERNAL_PAUSE;
+
+ case EXTERNAL_RESUME:
+ return IDisplayConfig::DisplayExternalStatus::EXTERNAL_RESUME;
+
+ default:
+ break;
+ }
+
+ return IDisplayConfig::DisplayExternalStatus::INVALID;
+}
+
+IDisplayConfig::DisplayDynRefreshRateOp MapDynRefreshRateOp(uint32_t op) {
+ switch (op) {
+ case DISABLE_METADATA_DYN_REFRESH_RATE:
+ return IDisplayConfig::DisplayDynRefreshRateOp::DISABLE_METADATA_DYN_REFRESH_RATE;
+
+ case ENABLE_METADATA_DYN_REFRESH_RATE:
+ return IDisplayConfig::DisplayDynRefreshRateOp::ENABLE_METADATA_DYN_REFRESH_RATE;
+
+ case SET_BINDER_DYN_REFRESH_RATE:
+ return IDisplayConfig::DisplayDynRefreshRateOp::SET_BINDER_DYN_REFRESH_RATE;
+
+ default:
+ break;
+ }
+
+ return IDisplayConfig::DisplayDynRefreshRateOp::INVALID;
+}
+
+int MapDisplayPortType(IDisplayConfig::DisplayPortType panelType) {
+ switch (panelType) {
+ case IDisplayConfig::DisplayPortType::DISPLAY_PORT_DEFAULT:
+ return DISPLAY_PORT_DEFAULT;
+
+ case IDisplayConfig::DisplayPortType::DISPLAY_PORT_DSI:
+ return DISPLAY_PORT_DSI;
+
+ case IDisplayConfig::DisplayPortType::DISPLAY_PORT_DTV:
+ return DISPLAY_PORT_DTV;
+
+ case IDisplayConfig::DisplayPortType::DISPLAY_PORT_WRITEBACK:
+ return DISPLAY_PORT_WRITEBACK;
+
+ case IDisplayConfig::DisplayPortType::DISPLAY_PORT_LVDS:
+ return DISPLAY_PORT_LVDS;
+
+ case IDisplayConfig::DisplayPortType::DISPLAY_PORT_EDP:
+ return DISPLAY_PORT_EDP;
+
+ case IDisplayConfig::DisplayPortType::DISPLAY_PORT_DP:
+ return DISPLAY_PORT_DP;
+
+ default:
+ break;
+ }
+
+ return -1;
+}
+
+int isExternalConnected() {
+ android::sp<IDisplayConfig> intf = IDisplayConfig::getService();
+ if (intf == NULL) {
+ return 0;
+ }
+
+ int connected = 0;
+ intf->isDisplayConnected(IDisplayConfig::DisplayType::DISPLAY_EXTERNAL,
+ [&](const auto &tmpError, const auto &tmpStatus) {
+ if (tmpError) {
+ return;
+ }
+
+ connected = tmpStatus;
+ });
+
+ return connected;
+}
+
+int setSecondayDisplayStatus(int dpy, uint32_t status) {
+ android::sp<IDisplayConfig> intf = IDisplayConfig::getService();
+ if (intf == NULL) {
+ return -1;
+ }
+
+ return intf->setSecondayDisplayStatus(MapDisplayType(dpy), MapExternalStatus(status));
+}
+
+int configureDynRefeshRate(uint32_t op, uint32_t refreshRate) {
+ android::sp<IDisplayConfig> intf = IDisplayConfig::getService();
+ if (intf == NULL) {
+ return -1;
+ }
+
+ return intf->configureDynRefeshRate(MapDynRefreshRateOp(op), refreshRate);
+}
+
+int getConfigCount(int dpy) {
+ android::sp<IDisplayConfig> intf = IDisplayConfig::getService();
+ if (intf == NULL) {
+ return -1;
+ }
+
+ int count = 0;
+ intf->getConfigCount(MapDisplayType(dpy),
+ [&](const auto &tmpError, const auto &tmpCount) {
+ if (tmpError) {
+ return;
+ }
+
+ count = tmpCount;
+ });
+
+ return count;
+}
+
+int getActiveConfig(int dpy) {
+ android::sp<IDisplayConfig> intf = IDisplayConfig::getService();
+ if (intf == NULL) {
+ return -1;
+ }
+
+ int config = 0;
+ intf->getActiveConfig(MapDisplayType(dpy),
+ [&](const auto &tmpError, const auto &tmpConfig) {
+ if (tmpError) {
+ return;
+ }
+
+ config = tmpConfig;
+ });
+
+ return config;
+}
+
+int setActiveConfig(int dpy, uint32_t config) {
+ android::sp<IDisplayConfig> intf = IDisplayConfig::getService();
+ if (intf == NULL) {
+ return -1;
+ }
+
+ return intf->setActiveConfig(MapDisplayType(dpy), config);
+}
+
+DisplayAttributes getDisplayAttributes(uint32_t configIndex, int dpy) {
+ DisplayAttributes attributes;
+
+ android::sp<IDisplayConfig> intf = IDisplayConfig::getService();
+ if (intf == NULL) {
+ return attributes;
+ }
+
+ intf->getDisplayAttributes(configIndex, MapDisplayType(dpy),
+ [&](const auto &tmpError, const auto &tmpAttributes) {
+ if (tmpError) {
+ return;
+ }
+
+ attributes.vsync_period = tmpAttributes.vsyncPeriod;
+ attributes.xres = tmpAttributes.xRes;
+ attributes.yres = tmpAttributes.yRes;
+ attributes.xdpi = tmpAttributes.xDpi;
+ attributes.ydpi = tmpAttributes.yDpi;
+ attributes.panel_type = MapDisplayPortType(tmpAttributes.panelType);
+ attributes.is_yuv = tmpAttributes.isYuv;
+ });
+
+ return attributes;
+}
+
+int setPanelBrightness(uint32_t level) {
+ android::sp<IDisplayConfig> intf = IDisplayConfig::getService();
+ if (intf == NULL) {
+ return -1;
+ }
+
+ return intf->setPanelBrightness(level);
+}
+
+uint32_t getPanelBrightness() {
+ android::sp<IDisplayConfig> intf = IDisplayConfig::getService();
+ if (intf == NULL) {
+ return 0;
+ }
+
+ int level = 0;
+ intf->getPanelBrightness(
+ [&](const auto &tmpError, const auto &tmpLevel) {
+ if (tmpError) {
+ return;
+ }
+
+ level = tmpLevel;
+ });
+
+ return level;
+}
+
+int minHdcpEncryptionLevelChanged(int dpy, uint32_t min_enc_level) {
+ android::sp<IDisplayConfig> intf = IDisplayConfig::getService();
+ if (intf == NULL) {
+ return -1;
+ }
+
+ return intf->minHdcpEncryptionLevelChanged(MapDisplayType(dpy), min_enc_level);
+}
+
+int refreshScreen() {
+ android::sp<IDisplayConfig> intf = IDisplayConfig::getService();
+ if (intf == NULL) {
+ return -1;
+ }
+
+ return intf->refreshScreen();
+}
+
+int controlPartialUpdate(int dpy, bool enable) {
+ android::sp<IDisplayConfig> intf = IDisplayConfig::getService();
+ if (intf == NULL) {
+ return -1;
+ }
+
+ return intf->controlPartialUpdate(MapDisplayType(dpy), enable);
+}
+
+int toggleScreenUpdate(uint32_t on) {
+ android::sp<IDisplayConfig> intf = IDisplayConfig::getService();
+ if (intf == NULL) {
+ return -1;
+ }
+
+ return intf->toggleScreenUpdate(on == 1);
+}
+
+int setIdleTimeout(uint32_t value) {
+ android::sp<IDisplayConfig> intf = IDisplayConfig::getService();
+ if (intf == NULL) {
+ return -1;
+ }
+
+ return intf->setIdleTimeout(value);
+}
+
+int getHDRCapabilities(int dpy, DisplayHDRCapabilities *caps) {
+ android::sp<IDisplayConfig> intf = IDisplayConfig::getService();
+ if (intf == NULL || caps == NULL) {
+ return -1;
+ }
+
+ int error = -1;
+ intf->getHDRCapabilities(MapDisplayType(dpy),
+ [&](const auto &tmpError, const auto &tmpCaps) {
+ error = tmpError;
+ if (error) {
+ return;
+ }
+
+ caps->supported_hdr_types = tmpCaps.supportedHdrTypes;
+ caps->max_luminance = tmpCaps.maxLuminance;
+ caps->max_avg_luminance = tmpCaps.maxAvgLuminance;
+ caps->min_luminance = tmpCaps.minLuminance;
+ });
+
+ return error;
+}
+
+int setCameraLaunchStatus(uint32_t on) {
+ android::sp<IDisplayConfig> intf = IDisplayConfig::getService();
+ if (intf == NULL) {
+ return -1;
+ }
+
+ return intf->setCameraLaunchStatus(on);
+}
+
+bool displayBWTransactionPending() {
+ android::sp<IDisplayConfig> intf = IDisplayConfig::getService();
+ if (intf == NULL) {
+ return 0;
+ }
+
+ int status = 0;
+ intf->displayBWTransactionPending(
+ [&](const auto &tmpError, const auto &tmpStatus) {
+ if (tmpError) {
+ return;
+ }
+
+ status = tmpStatus;
+ });
+
+ return status;
+}
+
+} // namespace display
diff --git a/msm8909/libdisplayconfig/DisplayConfig.h b/msm8909/libdisplayconfig/DisplayConfig.h
new file mode 100644
index 00000000..17b6421e
--- /dev/null
+++ b/msm8909/libdisplayconfig/DisplayConfig.h
@@ -0,0 +1,110 @@
+/*
+* Copyright (c) 2017 The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation. nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __DISPLAY_CONFIG_H__
+#define __DISPLAY_CONFIG_H__
+
+#include <stdint.h>
+#include <vector>
+
+// This header is for clients to use to set/get global display configuration.
+
+namespace display {
+
+enum {
+ DISPLAY_PRIMARY = 0,
+ DISPLAY_EXTERNAL,
+ DISPLAY_VIRTUAL,
+};
+
+enum {
+ EXTERNAL_OFFLINE = 0,
+ EXTERNAL_ONLINE,
+ EXTERNAL_PAUSE,
+ EXTERNAL_RESUME,
+};
+
+enum {
+ DISABLE_METADATA_DYN_REFRESH_RATE = 0,
+ ENABLE_METADATA_DYN_REFRESH_RATE,
+ SET_BINDER_DYN_REFRESH_RATE,
+};
+
+enum {
+ DISPLAY_PORT_DEFAULT = 0,
+ DISPLAY_PORT_DSI,
+ DISPLAY_PORT_DTV,
+ DISPLAY_PORT_WRITEBACK,
+ DISPLAY_PORT_LVDS,
+ DISPLAY_PORT_EDP,
+ DISPLAY_PORT_DP,
+};
+
+struct DisplayAttributes {
+ uint32_t vsync_period = 0; //nanoseconds
+ uint32_t xres = 0;
+ uint32_t yres = 0;
+ float xdpi = 0.0f;
+ float ydpi = 0.0f;
+ int panel_type = DISPLAY_PORT_DEFAULT;
+ bool is_yuv = false;
+};
+
+struct DisplayHDRCapabilities {
+ std::vector<int32_t> supported_hdr_types;
+ float max_luminance = 0.0f;
+ float max_avg_luminance = 0.0f;
+ float min_luminance = 0.0f;
+};
+
+//=============================================================================
+// The functions below run in the client pocess and wherever necessary
+// do a binder call to HWC to get/set data.
+
+int isExternalConnected();
+int setSecondayDisplayStatus(int dpy, uint32_t status);
+int configureDynRefeshRate(uint32_t op, uint32_t refreshRate);
+int getConfigCount(int dpy);
+int getActiveConfig(int dpy);
+int setActiveConfig(int dpy, uint32_t config);
+DisplayAttributes getDisplayAttributes(uint32_t configIndex, int dpy);
+int setPanelBrightness(uint32_t level);
+uint32_t getPanelBrightness();
+int minHdcpEncryptionLevelChanged(int dpy, uint32_t min_enc_level);
+int refreshScreen();
+int controlPartialUpdate(int dpy, bool enable);
+int toggleScreenUpdate(uint32_t on);
+int setIdleTimeout(uint32_t value);
+int getHDRCapabilities(int dpy, DisplayHDRCapabilities *caps);
+int setCameraLaunchStatus(uint32_t on);
+bool displayBWTransactionPending();
+
+} // namespace display
+
+#endif // __DISPLAY_CONFIG_H__
diff --git a/msm8909/libdrmutils/Android.mk b/msm8909/libdrmutils/Android.mk
new file mode 100644
index 00000000..ebcfc8a0
--- /dev/null
+++ b/msm8909/libdrmutils/Android.mk
@@ -0,0 +1,17 @@
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := libdrmutils
+LOCAL_VENDOR_MODULE := true
+LOCAL_MODULE_TAGS := optional
+LOCAL_C_INCLUDES := external/libdrm \
+ $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include
+LOCAL_SHARED_LIBRARIES := libdrm libdl
+LOCAL_CFLAGS := -DLOG_TAG=\"DRMUTILS\" -Wall -std=c++11 -Werror -fno-operator-names
+LOCAL_CLANG := true
+LOCAL_ADDITIONAL_DEPENDENCIES := $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr
+LOCAL_SRC_FILES := drm_master.cpp drm_res_mgr.cpp drm_lib_loader.cpp
+LOCAL_COPY_HEADERS_TO := qcom/display
+LOCAL_COPY_HEADERS := drm_master.h drm_res_mgr.h drm_lib_loader.h drm_logger.h drm_interface.h
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/msm8909/libdrmutils/drm_interface.h b/msm8909/libdrmutils/drm_interface.h
new file mode 100644
index 00000000..4c37e8c7
--- /dev/null
+++ b/msm8909/libdrmutils/drm_interface.h
@@ -0,0 +1,449 @@
+/*
+* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __DRM_INTERFACE_H__
+#define __DRM_INTERFACE_H__
+
+#include <map>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "xf86drm.h"
+#include "xf86drmMode.h"
+
+namespace sde_drm {
+/*
+ * Drm Atomic Operation Codes
+ */
+enum struct DRMOps {
+ /*
+ * Op: Sets plane source crop
+ * Arg: uint32_t - Plane ID
+ * DRMRect - Source Rectangle
+ */
+ PLANE_SET_SRC_RECT,
+ /*
+ * Op: Sets plane destination rect
+ * Arg: uint32_t - Plane ID
+ * DRMRect - Dst Rectangle
+ */
+ PLANE_SET_DST_RECT,
+ /*
+ * Op: Sets plane zorder
+ * Arg: uint32_t - Plane ID
+ * uint32_t - zorder
+ */
+ PLANE_SET_ZORDER,
+ /*
+ * Op: Sets plane rotation flags
+ * Arg: uint32_t - Plane ID
+ * uint32_t - bit mask of rotation flags (See drm_mode.h for enums)
+ */
+ PLANE_SET_ROTATION,
+ /*
+ * Op: Sets plane alpha
+ * Arg: uint32_t - Plane ID
+ * uint32_t - alpha value
+ */
+ PLANE_SET_ALPHA,
+ /*
+ * Op: Sets the blend type
+ * Arg: uint32_t - Plane ID
+ * uint32_t - blend type (see DRMBlendType)
+ */
+ PLANE_SET_BLEND_TYPE,
+ /*
+ * Op: Sets horizontal decimation
+ * Arg: uint32_t - Plane ID
+ * uint32_t - decimation factor
+ */
+ PLANE_SET_H_DECIMATION,
+ /*
+ * Op: Sets vertical decimation
+ * Arg: uint32_t - Plane ID
+ * uint32_t - decimation factor
+ */
+ PLANE_SET_V_DECIMATION,
+ /*
+ * Op: Sets source config flags
+ * Arg: uint32_t - Plane ID
+ * uint32_t - flags to enable or disable a specific op. E.g. deinterlacing
+ */
+ PLANE_SET_SRC_CONFIG,
+ /*
+ * Op: Sets frame buffer ID for plane. Set together with CRTC.
+ * Arg: uint32_t - Plane ID
+ * uint32_t - Framebuffer ID
+ */
+ PLANE_SET_FB_ID,
+ /*
+ * Op: Sets the crtc for this plane. Set together with FB_ID.
+ * Arg: uint32_t - Plane ID
+ * uint32_t - CRTC ID
+ */
+ PLANE_SET_CRTC,
+ /*
+ * Op: Sets acquire fence for this plane's buffer. Set together with FB_ID, CRTC.
+ * Arg: uint32_t - Plane ID
+ * uint32_t - Input fence
+ */
+ PLANE_SET_INPUT_FENCE,
+ /*
+ * Op: Sets scaler config on this plane.
+ * Arg: uint32_t - Plane ID
+ * uint64_t - Address of the scaler config object (version based)
+ */
+ PLANE_SET_SCALER_CONFIG,
+ /*
+ * Op: Activate or deactivate a CRTC
+ * Arg: uint32_t - CRTC ID
+ * uint32_t - 1 to enable, 0 to disable
+ */
+ CRTC_SET_ACTIVE,
+ /*
+ * Op: Sets display mode
+ * Arg: uint32_t - CRTC ID
+ * drmModeModeInfo* - Pointer to display mode
+ */
+ CRTC_SET_MODE,
+ /*
+ * Op: Sets an offset indicating when a release fence should be signalled.
+ * Arg: uint32_t - offset
+ * 0: non-speculative, default
+ * 1: speculative
+ */
+ CRTC_SET_OUTPUT_FENCE_OFFSET,
+ /*
+ * Op: Returns release fence for this frame. Should be called after Commit() on
+ * DRMAtomicReqInterface.
+ * Arg: uint32_t - CRTC ID
+ * int * - Pointer to an integer that will hold the returned fence
+ */
+ CRTC_GET_RELEASE_FENCE,
+ /*
+ * Op: Sets PP feature
+ * Arg: uint32_t - CRTC ID
+ * DRMPPFeatureInfo * - PP feature data pointer
+ */
+ CRTC_SET_POST_PROC,
+ /*
+ * Op: Returns retire fence for this commit. Should be called after Commit() on
+ * DRMAtomicReqInterface.
+ * Arg: uint32_t - Connector ID
+ * int * - Pointer to an integer that will hold the returned fence
+ */
+ CONNECTOR_GET_RETIRE_FENCE,
+ /*
+ * Op: Sets writeback connector destination rect
+ * Arg: uint32_t - Connector ID
+ * DRMRect - Dst Rectangle
+ */
+ CONNECTOR_SET_OUTPUT_RECT,
+ /*
+ * Op: Sets frame buffer ID for writeback connector.
+ * Arg: uint32_t - Connector ID
+ * uint32_t - Framebuffer ID
+ */
+ CONNECTOR_SET_OUTPUT_FB_ID,
+};
+
+enum struct DRMRotation {
+ FLIP_H = 0x1,
+ FLIP_V = 0x2,
+ ROT_90 = 0x4,
+};
+
+enum struct DRMBlendType {
+ UNDEFINED = 0,
+ OPAQUE = 1,
+ PREMULTIPLIED = 2,
+ COVERAGE = 3,
+};
+
+enum struct DRMSrcConfig {
+ DEINTERLACE = 0,
+};
+
+/* Display type to identify a suitable connector */
+enum struct DRMDisplayType {
+ PERIPHERAL,
+ TV,
+ VIRTUAL,
+};
+
+struct DRMRect {
+ uint32_t left; // Left-most pixel coordinate.
+ uint32_t top; // Top-most pixel coordinate.
+ uint32_t right; // Right-most pixel coordinate.
+ uint32_t bottom; // Bottom-most pixel coordinate.
+};
+
+//------------------------------------------------------------------------
+// DRM Info Query Types
+//------------------------------------------------------------------------
+
+enum struct QSEEDVersion {
+ V1,
+ V2,
+ V3,
+};
+
+enum struct SmartDMARevision {
+ V1,
+ V2,
+};
+
+/* Per CRTC Resource Info*/
+struct DRMCrtcInfo {
+ bool has_src_split;
+ uint32_t max_blend_stages;
+ QSEEDVersion qseed_version;
+ SmartDMARevision smart_dma_rev;
+};
+
+enum struct DRMPlaneType {
+ // Has CSC and scaling capability
+ VIG = 0,
+ // Has scaling capability but no CSC
+ RGB,
+ // No scaling support
+ DMA,
+ // Supports a small dimension and doesn't use a CRTC stage
+ CURSOR,
+ MAX,
+};
+
+struct DRMPlaneTypeInfo {
+ DRMPlaneType type;
+ uint32_t master_plane_id;
+ // FourCC format enum and modifier
+ std::vector<std::pair<uint32_t, uint64_t>> formats_supported;
+ uint32_t max_linewidth;
+ uint32_t max_upscale;
+ uint32_t max_downscale;
+ uint32_t max_horizontal_deci;
+ uint32_t max_vertical_deci;
+};
+
+// All DRM Planes as map<Plane_id , plane_type_info> listed from highest to lowest priority
+typedef std::vector<std::pair<uint32_t, DRMPlaneTypeInfo>> DRMPlanesInfo;
+
+enum struct DRMTopology {
+ UNKNOWN, // To be compat with driver defs in sde_kms.h
+ SINGLE_LM,
+ DUAL_LM,
+ PPSPLIT,
+ DUAL_LM_MERGE,
+};
+
+enum struct DRMPanelMode {
+ VIDEO,
+ COMMAND,
+};
+
+/* Per Connector Info*/
+struct DRMConnectorInfo {
+ uint32_t mmWidth;
+ uint32_t mmHeight;
+ uint32_t type;
+ uint32_t num_modes;
+ drmModeModeInfo *modes;
+ DRMTopology topology;
+ std::string panel_name;
+ DRMPanelMode panel_mode;
+ bool is_primary;
+ // Valid only if DRMPanelMode is VIDEO
+ bool dynamic_fps;
+ // FourCC format enum and modifier
+ std::vector<std::pair<uint32_t, uint64_t>> formats_supported;
+ // Valid only if type is DRM_MODE_CONNECTOR_VIRTUAL
+ uint32_t max_linewidth;
+};
+
+/* Identifier token for a display */
+struct DRMDisplayToken {
+ uint32_t conn_id;
+ uint32_t crtc_id;
+};
+
+enum DRMPPFeatureID {
+ kFeaturePcc,
+ kFeatureIgc,
+ kFeaturePgc,
+ kFeatureMixerGc,
+ kFeaturePaV2,
+ kFeatureDither,
+ kFeatureGamut,
+ kFeaturePADither,
+ kPPFeaturesMax,
+};
+
+enum DRMPPPropType {
+ kPropEnum,
+ kPropRange,
+ kPropBlob,
+ kPropTypeMax,
+};
+
+struct DRMPPFeatureInfo {
+ DRMPPFeatureID id;
+ DRMPPPropType type;
+ uint32_t version;
+ uint32_t payload_size;
+ void *payload;
+};
+
+struct DRMScalerLUTInfo {
+ uint32_t dir_lut_size = 0;
+ uint32_t cir_lut_size = 0;
+ uint32_t sep_lut_size = 0;
+ uint64_t dir_lut = 0;
+ uint64_t cir_lut = 0;
+ uint64_t sep_lut = 0;
+};
+
+/* DRM Atomic Request Property Set.
+ *
+ * Helper class to create and populate atomic properties of DRM components
+ * when rendered in DRM atomic mode */
+class DRMAtomicReqInterface {
+ public:
+ virtual ~DRMAtomicReqInterface() {}
+ /* Perform request operation.
+ *
+ * [input]: opcode: operation code from DRMOps list.
+ * var_arg: arguments for DRMOps's can differ in number and
+ * data type. Refer above DRMOps to details.
+ * [return]: Error code if the API fails, 0 on success.
+ */
+ virtual int Perform(DRMOps opcode, ...) = 0;
+
+ /*
+ * Commit the params set via Perform(). Also resets the properties after commit. Needs to be
+ * called every frame.
+ * [input]: synchronous: Determines if the call should block until a h/w flip
+ * [return]: Error code if the API fails, 0 on success.
+ */
+ virtual int Commit(bool synchronous) = 0;
+ /*
+ * Validate the params set via Perform().
+ * [return]: Error code if the API fails, 0 on success.
+ */
+ virtual int Validate() = 0;
+};
+
+class DRMManagerInterface;
+
+/* Populates a singleton instance of DRMManager */
+typedef int (*GetDRMManager)(int fd, DRMManagerInterface **intf);
+
+/* Destroy DRMManager instance */
+typedef int (*DestroyDRMManager)();
+
+/*
+ * DRM Manager Interface - Any class which plans to implement helper function for vendor
+ * specific DRM driver implementation must implement the below interface routines to work
+ * with SDM.
+ */
+
+class DRMManagerInterface {
+ public:
+ virtual ~DRMManagerInterface() {}
+
+ /*
+ * Since SDM completely manages the planes. GetPlanesInfo will provide all
+ * the plane information.
+ * [output]: DRMPlanesInfo: Resource Info for planes.
+ */
+ virtual void GetPlanesInfo(DRMPlanesInfo *info) = 0;
+
+ /*
+ * Will provide all the information of a selected crtc.
+ * [input]: Use crtc id 0 to obtain system wide info
+ * [output]: DRMCrtcInfo: Resource Info for the given CRTC id.
+ */
+ virtual void GetCrtcInfo(uint32_t crtc_id, DRMCrtcInfo *info) = 0;
+
+ /*
+ * Will provide all the information of a selected connector.
+ * [output]: DRMConnectorInfo: Resource Info for the given connector id
+ */
+ virtual void GetConnectorInfo(uint32_t conn_id, DRMConnectorInfo *info) = 0;
+
+ /*
+ * Will query post propcessing feature info of a CRTC.
+ * [output]: DRMPPFeatureInfo: CRTC post processing feature info
+ */
+ virtual void GetCrtcPPInfo(uint32_t crtc_id, DRMPPFeatureInfo &info) = 0;
+ /*
+ * Register a logical display to receive a token.
+ * Each display pipeline in DRM is identified by its CRTC and Connector(s).
+ * On display connect(bootup or hotplug), clients should invoke this interface to
+ * establish the pipeline for the display and should get a DisplayToken
+ * populated with crtc and connnector(s) id's. Here onwards, Client should
+ * use this token to represent the display for any Perform operations if
+ * needed.
+ *
+ * [input]: disp_type - Peripheral / TV / Virtual
+ * [output]: DRMDisplayToken - CRTC and Connector id's for the display
+ * [return]: 0 on success, a negative error value otherwise
+ */
+ virtual int RegisterDisplay(DRMDisplayType disp_type, DRMDisplayToken *tok) = 0;
+
+ /* Client should invoke this interface on display disconnect.
+ * [input]: DRMDisplayToken - identifier for the display.
+ */
+ virtual void UnregisterDisplay(const DRMDisplayToken &token) = 0;
+
+ /*
+ * Creates and returns an instance of DRMAtomicReqInterface corresponding to a display token
+ * returned as part of RegisterDisplay API. Needs to be called per display.
+ * [input]: DRMDisplayToken that identifies a display pipeline
+ * [output]: Pointer to an instance of DRMAtomicReqInterface.
+ * [return]: Error code if the API fails, 0 on success.
+ */
+ virtual int CreateAtomicReq(const DRMDisplayToken &token, DRMAtomicReqInterface **intf) = 0;
+
+ /*
+ * Destroys the instance of DRMAtomicReqInterface
+ * [input]: Pointer to a DRMAtomicReqInterface
+ * [return]: Error code if the API fails, 0 on success.
+ */
+ virtual int DestroyAtomicReq(DRMAtomicReqInterface *intf) = 0;
+ /*
+ * Sets the global scaler LUT
+ * [input]: LUT Info
+ * [return]: Error code if the API fails, 0 on success.
+ */
+ virtual int SetScalerLUT(const DRMScalerLUTInfo &lut_info) = 0;
+};
+
+} // namespace sde_drm
+#endif // __DRM_INTERFACE_H__
diff --git a/msm8909/libdrmutils/drm_lib_loader.cpp b/msm8909/libdrmutils/drm_lib_loader.cpp
new file mode 100644
index 00000000..83c9f1b5
--- /dev/null
+++ b/msm8909/libdrmutils/drm_lib_loader.cpp
@@ -0,0 +1,92 @@
+/*
+* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <dlfcn.h>
+
+#include "drm_lib_loader.h"
+
+#define __CLASS__ "DRMLibLoader"
+
+using std::mutex;
+using std::lock_guard;
+
+namespace drm_utils {
+
+DRMLibLoader *DRMLibLoader::s_instance = nullptr;
+mutex DRMLibLoader::s_lock;
+
+DRMLibLoader *DRMLibLoader::GetInstance() {
+ lock_guard<mutex> obj(s_lock);
+
+ if (!s_instance) {
+ s_instance = new DRMLibLoader();
+ }
+
+ return s_instance;
+}
+
+void DRMLibLoader::Destroy() {
+ lock_guard<mutex> obj(s_lock);
+ if (s_instance) {
+ delete s_instance;
+ s_instance = nullptr;
+ }
+}
+
+DRMLibLoader::DRMLibLoader() {
+ if (Open("libsdedrm.so")) {
+ if (Sym("GetDRMManager", reinterpret_cast<void **>(&func_get_drm_manager_)) &&
+ Sym("DestroyDRMManager", reinterpret_cast<void **>(&func_destroy_drm_manager_))) {
+ is_loaded_ = true;
+ }
+ }
+}
+
+DRMLibLoader::~DRMLibLoader() {
+ if (lib_) {
+ ::dlclose(lib_);
+ lib_ = nullptr;
+ }
+}
+
+bool DRMLibLoader::Open(const char *lib_name) {
+ lib_ = ::dlopen(lib_name, RTLD_NOW);
+
+ return (lib_ != nullptr);
+}
+
+bool DRMLibLoader::Sym(const char *func_name, void **func_ptr) {
+ if (lib_) {
+ *func_ptr = ::dlsym(lib_, func_name);
+ }
+
+ return (*func_ptr != nullptr);
+}
+
+} // namespace drm_utils
diff --git a/msm8909/libdrmutils/drm_lib_loader.h b/msm8909/libdrmutils/drm_lib_loader.h
new file mode 100644
index 00000000..d132d69c
--- /dev/null
+++ b/msm8909/libdrmutils/drm_lib_loader.h
@@ -0,0 +1,64 @@
+/*
+* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __DRM_LIB_LOADER_H__
+#define __DRM_LIB_LOADER_H__
+
+#include <drm_interface.h>
+#include <mutex>
+
+namespace drm_utils {
+
+class DRMLibLoader {
+ public:
+ ~DRMLibLoader();
+ bool IsLoaded() { return is_loaded_; }
+ sde_drm::GetDRMManager FuncGetDRMManager() { return func_get_drm_manager_; }
+ sde_drm::DestroyDRMManager FuncDestroyDRMManager() { return func_destroy_drm_manager_; }
+
+ static DRMLibLoader *GetInstance();
+ static void Destroy();
+
+ private:
+ DRMLibLoader();
+ bool Open(const char *lib_name);
+ bool Sym(const char *func_name, void **func_ptr);
+
+ void *lib_ = {};
+ sde_drm::GetDRMManager func_get_drm_manager_ = {};
+ sde_drm::DestroyDRMManager func_destroy_drm_manager_ = {};
+ bool is_loaded_ = false;
+
+ static DRMLibLoader *s_instance; // Singleton instance
+ static std::mutex s_lock;
+};
+
+} // namespace drm_utils
+
+#endif // __DRM_LIB_LOADER_H__
diff --git a/msm8909/libdrmutils/drm_logger.h b/msm8909/libdrmutils/drm_logger.h
new file mode 100644
index 00000000..d0b07738
--- /dev/null
+++ b/msm8909/libdrmutils/drm_logger.h
@@ -0,0 +1,69 @@
+/*
+* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __DRM_LOGGER_H__
+#define __DRM_LOGGER_H__
+
+#include <utility>
+
+namespace drm_utils {
+
+class DRMLogger {
+ public:
+ virtual ~DRMLogger() {}
+ virtual void Error(const char *format, ...) = 0;
+ virtual void Warning(const char *format, ...) = 0;
+ virtual void Info(const char *format, ...) = 0;
+ virtual void Debug(const char *format, ...) = 0;
+
+ static void Set(DRMLogger *logger) { s_instance = logger; }
+ static DRMLogger *Get() { return s_instance; }
+
+ private:
+ static DRMLogger *s_instance;
+};
+
+#define DRM_LOG(method, format, ...) \
+ if (drm_utils::DRMLogger::Get()) { \
+ drm_utils::DRMLogger::Get()->method(format, ##__VA_ARGS__); \
+ }
+
+#define DRM_LOG_CONTEXT(method, format, ...) \
+ DRM_LOG(method, __CLASS__ "::%s: " format, __FUNCTION__, ##__VA_ARGS__);
+
+#define DRM_LOGE(format, ...) DRM_LOG_CONTEXT(Error, format, ##__VA_ARGS__)
+#define DRM_LOGW(format, ...) DRM_LOG_CONTEXT(Warning, format, ##__VA_ARGS__)
+#define DRM_LOGI(format, ...) DRM_LOG_CONTEXT(Info, format, ##__VA_ARGS__)
+#define DRM_LOGD_IF(pred, format, ...) \
+ if (pred) \
+ DRM_LOG_CONTEXT(Debug, format, ##__VA_ARGS__)
+
+} // namespace drm_utils
+
+#endif // __DRM_LOGGER_H__
diff --git a/msm8909/libdrmutils/drm_master.cpp b/msm8909/libdrmutils/drm_master.cpp
new file mode 100644
index 00000000..09e0729e
--- /dev/null
+++ b/msm8909/libdrmutils/drm_master.cpp
@@ -0,0 +1,149 @@
+/*
+* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <xf86drm.h>
+#include <xf86drmMode.h>
+// Intentionally included after xf86 headers so that they in-turn include libdrm version of drm.h
+// that doesn't use keyword "virtual" for a variable name. Not doing so leads to the kernel version
+// of drm.h being included causing compilation to fail
+#include <drm/msm_drm.h>
+#include <algorithm>
+#include <iterator>
+
+#include "drm_master.h"
+
+#define __CLASS__ "DRMMaster"
+
+using std::mutex;
+using std::lock_guard;
+using std::begin;
+using std::copy;
+using std::end;
+using std::fill;
+
+namespace drm_utils {
+
+DRMLogger *DRMLogger::s_instance = nullptr;
+DRMMaster *DRMMaster::s_instance = nullptr;
+mutex DRMMaster::s_lock;
+
+int DRMMaster::GetInstance(DRMMaster **master) {
+ lock_guard<mutex> obj(s_lock);
+
+ if (!s_instance) {
+ s_instance = new DRMMaster();
+ if (s_instance->Init() < 0) {
+ delete s_instance;
+ s_instance = nullptr;
+ return -ENODEV;
+ }
+ }
+
+ *master = s_instance;
+ return 0;
+}
+
+void DRMMaster::DestroyInstance() {
+ lock_guard<mutex> obj(s_lock);
+ delete s_instance;
+ s_instance = nullptr;
+}
+
+int DRMMaster::Init() {
+ dev_fd_ = drmOpen("msm_drm", nullptr);
+ if (dev_fd_ < 0) {
+ DRM_LOGE("drmOpen failed with error %d", dev_fd_);
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+DRMMaster::~DRMMaster() {
+ drmClose(dev_fd_);
+ dev_fd_ = -1;
+}
+
+int DRMMaster::CreateFbId(const DRMBuffer &drm_buffer, uint32_t *fb_id) {
+ uint32_t gem_handle = 0;
+ int ret = drmPrimeFDToHandle(dev_fd_, drm_buffer.fd, &gem_handle);
+ if (ret) {
+ DRM_LOGE("drmPrimeFDToHandle failed with error %d", ret);
+ return ret;
+ }
+
+ struct drm_mode_fb_cmd2 cmd2 {};
+ cmd2.width = drm_buffer.width;
+ cmd2.height = drm_buffer.height;
+ cmd2.pixel_format = drm_buffer.drm_format;
+ cmd2.flags = DRM_MODE_FB_MODIFIERS;
+ fill(begin(cmd2.handles), begin(cmd2.handles) + drm_buffer.num_planes, gem_handle);
+ copy(begin(drm_buffer.stride), end(drm_buffer.stride), begin(cmd2.pitches));
+ copy(begin(drm_buffer.offset), end(drm_buffer.offset), begin(cmd2.offsets));
+ fill(begin(cmd2.modifier), begin(cmd2.modifier) + drm_buffer.num_planes,
+ drm_buffer.drm_format_modifier);
+
+ if ((ret = drmIoctl(dev_fd_, DRM_IOCTL_MODE_ADDFB2, &cmd2))) {
+ DRM_LOGE("DRM_IOCTL_MODE_ADDFB2 failed with error %d", ret);
+ } else {
+ *fb_id = cmd2.fb_id;
+ }
+
+ struct drm_gem_close gem_close = {};
+ gem_close.handle = gem_handle;
+ int ret1 = drmIoctl(dev_fd_, DRM_IOCTL_GEM_CLOSE, &gem_close);
+ if (ret1) {
+ DRM_LOGE("drmIoctl::DRM_IOCTL_GEM_CLOSE failed with error %d", ret1);
+ return ret1;
+ }
+
+ return ret;
+}
+
+int DRMMaster::RemoveFbId(uint32_t fb_id) {
+ int ret = 0;
+#ifdef DRM_IOCTL_MSM_RMFB2
+ ret = drmIoctl(dev_fd_, DRM_IOCTL_MSM_RMFB2, &fb_id);
+ if (ret) {
+ DRM_LOGE("drmIoctl::DRM_IOCTL_MSM_RMFB2 failed for fb_id %d with error %d", fb_id, errno);
+ }
+#else
+ ret = drmModeRmFB(dev_fd_, fb_id);
+ if (ret) {
+ DRM_LOGE("drmModeRmFB failed for fb_id %d with error %d", fb_id, ret);
+ }
+#endif
+ return ret;
+}
+
+} // namespace drm_utils
diff --git a/msm8909/libdrmutils/drm_master.h b/msm8909/libdrmutils/drm_master.h
new file mode 100644
index 00000000..52a8b028
--- /dev/null
+++ b/msm8909/libdrmutils/drm_master.h
@@ -0,0 +1,95 @@
+/*
+* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __DRM_MASTER_H__
+#define __DRM_MASTER_H__
+
+#include <mutex>
+
+#include "drm_logger.h"
+
+namespace drm_utils {
+
+struct DRMBuffer {
+ int fd = -1;
+ uint32_t width = 0;
+ uint32_t height = 0;
+ uint32_t drm_format = 0;
+ uint64_t drm_format_modifier = 0;
+ uint32_t stride[4] = {};
+ uint32_t offset[4] = {};
+ uint32_t num_planes = 1;
+};
+
+class DRMMaster {
+ public:
+ ~DRMMaster();
+ /* Converts from ION fd --> Prime Handle --> FB_ID.
+ * Input:
+ * drm_buffer: A DRMBuffer obj that packages description of buffer
+ * Output:
+ * fb_id: Pointer to store DRM framebuffer id into
+ * Returns:
+ * ioctl error code
+ */
+ int CreateFbId(const DRMBuffer &drm_buffer, uint32_t *fb_id);
+ /* Removes the fb_id from DRM
+ * Input:
+ * fb_id: DRM FB to be removed
+ * Returns:
+ * ioctl error code
+ */
+ int RemoveFbId(uint32_t fb_id);
+ /* Poplulates master DRM fd
+ * Input:
+ * fd: Pointer to store master fd into
+ */
+ void GetHandle(int *fd) { *fd = dev_fd_; }
+
+ /* Creates an instance of DRMMaster if it doesn't exist and initializes it. Threadsafe.
+ * Input:
+ * master: Pointer to store a pointer to the instance
+ * Returns:
+ * -ENODEV if device cannot be opened or initilization fails
+ */
+ static int GetInstance(DRMMaster **master);
+ static void DestroyInstance();
+
+ private:
+ DRMMaster() {}
+ int Init();
+
+ int dev_fd_ = -1; // Master fd for DRM
+ static DRMMaster *s_instance; // Singleton instance
+ static std::mutex s_lock;
+};
+
+} // namespace drm_utils
+
+#endif // __DRM_MASTER_H__
diff --git a/msm8909/libdrmutils/drm_res_mgr.cpp b/msm8909/libdrmutils/drm_res_mgr.cpp
new file mode 100644
index 00000000..1d29495d
--- /dev/null
+++ b/msm8909/libdrmutils/drm_res_mgr.cpp
@@ -0,0 +1,151 @@
+/*
+* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <errno.h>
+
+#include "drm_master.h"
+#include "drm_res_mgr.h"
+
+#define DEBUG 0
+#define __CLASS__ "DRMResMgr"
+
+using std::mutex;
+using std::lock_guard;
+
+namespace drm_utils {
+
+DRMResMgr *DRMResMgr::s_instance = nullptr;
+mutex DRMResMgr::s_lock;
+
+static bool GetConnector(int dev_fd, drmModeRes *res, drmModeConnector **connector) {
+ for (auto i = 0; i < res->count_connectors; i++) {
+ drmModeConnector *conn = drmModeGetConnector(dev_fd, res->connectors[i]);
+ if (conn && conn->connector_type == DRM_MODE_CONNECTOR_DSI && conn->count_modes &&
+ conn->connection == DRM_MODE_CONNECTED) {
+ *connector = conn;
+ DRM_LOGI("Found connector %d", conn->connector_id);
+ return true;
+ }
+ }
+
+ return false;
+}
+
+static bool GetEncoder(int dev_fd, drmModeConnector *conn, drmModeEncoder **encoder) {
+ for (auto i = 0; i < conn->count_encoders; i++) {
+ drmModeEncoder *enc = drmModeGetEncoder(dev_fd, conn->encoders[i]);
+ if (enc && enc->encoder_type == DRM_MODE_ENCODER_DSI) {
+ *encoder = enc;
+ DRM_LOGI("Found encoder %d", enc->encoder_id);
+ return true;
+ }
+ }
+ return false;
+}
+
+static bool GetCrtc(int dev_fd, drmModeRes *res, drmModeEncoder *enc, drmModeCrtc **crtc) {
+ for (auto i = 0; i < res->count_crtcs; i++) {
+ if (enc->possible_crtcs & (1 << i)) {
+ drmModeCrtc *c = drmModeGetCrtc(dev_fd, res->crtcs[i]);
+ if (c) {
+ *crtc = c;
+ DRM_LOGI("Found crtc %d", c->crtc_id);
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+#define __CLASS__ "DRMResMgr"
+
+int DRMResMgr::GetInstance(DRMResMgr **res_mgr) {
+ lock_guard<mutex> obj(s_lock);
+
+ if (!s_instance) {
+ s_instance = new DRMResMgr();
+ if (s_instance->Init() < 0) {
+ delete s_instance;
+ s_instance = nullptr;
+ return -ENODEV;
+ }
+ }
+
+ *res_mgr = s_instance;
+ return 0;
+}
+
+int DRMResMgr::Init() {
+ DRMMaster *master = nullptr;
+ int dev_fd = -1;
+
+ int ret = DRMMaster::GetInstance(&master);
+ if (ret < 0) {
+ return ret;
+ }
+
+ master->GetHandle(&dev_fd);
+ drmModeRes *res = drmModeGetResources(dev_fd);
+ if (res == nullptr) {
+ DRM_LOGE("drmModeGetResources failed");
+ return -ENODEV;
+ }
+
+ drmModeConnector *conn = nullptr;
+ if (!GetConnector(dev_fd, res, &conn)) {
+ DRM_LOGE("Failed to find a connector");
+ return -ENODEV;
+ }
+
+ drmModeEncoder *enc = nullptr;
+ if (!GetEncoder(dev_fd, conn, &enc)) {
+ DRM_LOGE("Failed to find an encoder");
+ drmModeFreeConnector(conn);
+ return -ENODEV;
+ }
+
+ drmModeCrtc *crtc = nullptr;
+ if (!GetCrtc(dev_fd, res, enc, &crtc)) {
+ DRM_LOGE("Failed to find a crtc");
+ drmModeFreeEncoder(enc);
+ drmModeFreeConnector(conn);
+ drmModeFreeResources(res);
+ return -ENODEV;
+ }
+
+ res_ = res;
+ conn_ = conn;
+ enc_ = enc;
+ crtc_ = crtc;
+
+ return 0;
+}
+
+} // namespace drm_utils
diff --git a/msm8909/libdrmutils/drm_res_mgr.h b/msm8909/libdrmutils/drm_res_mgr.h
new file mode 100644
index 00000000..3a8378c5
--- /dev/null
+++ b/msm8909/libdrmutils/drm_res_mgr.h
@@ -0,0 +1,72 @@
+/*
+* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __DRM_RES_MGR_H__
+#define __DRM_RES_MGR_H__
+
+#include <xf86drm.h>
+#include <xf86drmMode.h>
+
+#include <mutex>
+
+namespace drm_utils {
+
+class DRMResMgr {
+ public:
+ /* Returns the default connector id for primary panel */
+ void GetConnectorId(uint32_t *id) { *id = conn_->connector_id; }
+ /* Returns the default crtc id for primary pipeline */
+ void GetCrtcId(uint32_t *id) { *id = crtc_->crtc_id; }
+ /* Returns the default mode currently used by the connector */
+ void GetMode(drmModeModeInfo *mode) { *mode = conn_->modes[0]; }
+ /* Returns the panel dimensions in mm */
+ void GetDisplayDimInMM(uint32_t *w, uint32_t *h) {
+ *w = conn_->mmWidth;
+ *h = conn_->mmHeight;
+ }
+
+ /* Creates and initializes an instance of DRMResMgr. On success, returns a pointer to it, on
+ * failure returns -ENODEV */
+ static int GetInstance(DRMResMgr **res_mgr);
+
+ private:
+ int Init();
+
+ drmModeRes *res_ = nullptr;
+ drmModeConnector *conn_ = nullptr;
+ drmModeEncoder *enc_ = nullptr;
+ drmModeCrtc *crtc_ = nullptr;
+
+ static DRMResMgr *s_instance;
+ static std::mutex s_lock;
+};
+
+} // namespace drm_utils
+
+#endif // __DRM_RES_MGR_H__
diff --git a/msm8909/libgralloc/Android.mk b/msm8909/libgralloc/Android.mk
index b6e3a8d3..86c0f042 100644
--- a/msm8909/libgralloc/Android.mk
+++ b/msm8909/libgralloc/Android.mk
@@ -18,18 +18,20 @@ include $(LOCAL_PATH)/../common.mk
include $(CLEAR_VARS)
LOCAL_MODULE := gralloc.$(TARGET_BOARD_PLATFORM)
+LOCAL_VENDOR_MODULE := true
LOCAL_MODULE_RELATIVE_PATH := hw
-LOCAL_PROPRIETARY_MODULE := true
LOCAL_MODULE_TAGS := optional
LOCAL_C_INCLUDES := $(common_includes) $(kernel_includes)
-LOCAL_SHARED_LIBRARIES := $(common_libs) libmemalloc libqdMetaData
-LOCAL_SHARED_LIBRARIES += libqdutils libGLESv1_CM
-LOCAL_CFLAGS := $(common_flags) -DLOG_TAG=\"qdgralloc\"
-LOCAL_CLANG := $(common_clang_flags)
+LOCAL_HEADER_LIBRARIES := display_headers
+LOCAL_SHARED_LIBRARIES := $(common_libs) libmemalloc libqdMetaData libqdutils
+ifneq ($(TARGET_IS_HEADLESS), true)
+LOCAL_SHARED_LIBRARIES += libGLESv1_CM
+endif
+LOCAL_CFLAGS := $(common_flags) -DLOG_TAG=\"qdgralloc\" -Wno-sign-conversion
LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps) $(kernel_deps)
LOCAL_SRC_FILES := gpu.cpp gralloc.cpp framebuffer.cpp mapper.cpp
LOCAL_COPY_HEADERS_TO := $(common_header_export_path)
-LOCAL_COPY_HEADERS := gralloc_priv.h gr.h
+LOCAL_COPY_HEADERS := gralloc_priv.h gr.h adreno_utils.h
include $(BUILD_SHARED_LIBRARY)
@@ -37,11 +39,12 @@ include $(BUILD_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := libmemalloc
+LOCAL_VENDOR_MODULE := true
LOCAL_MODULE_TAGS := optional
LOCAL_C_INCLUDES := $(common_includes) $(kernel_includes)
+LOCAL_HEADER_LIBRARIES := display_headers
LOCAL_SHARED_LIBRARIES := $(common_libs) libqdutils libdl
-LOCAL_CFLAGS := $(common_flags) -DLOG_TAG=\"qdmemalloc\"
-LOCAL_CLANG := $(common_clang_flags)
+LOCAL_CFLAGS := $(common_flags) -DLOG_TAG=\"qdmemalloc\" -Wno-sign-conversion
LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps) $(kernel_deps)
LOCAL_SRC_FILES := ionalloc.cpp alloc_controller.cpp
LOCAL_COPY_HEADERS := alloc_controller.h memalloc.h
diff --git a/msm8909/libgralloc/Makefile.am b/msm8909/libgralloc/Makefile.am
new file mode 100644
index 00000000..3cf39601
--- /dev/null
+++ b/msm8909/libgralloc/Makefile.am
@@ -0,0 +1,42 @@
+HEADER_PATH := ${WORKSPACE}/display/display-hal/include
+h_sources = alloc_controller.h \
+ memalloc.h
+
+cpp_sources = ionalloc.cpp \
+ alloc_controller.cpp
+
+memalloc_includedir = $(pkgincludedir)
+memalloc_include_HEADERS = $(h_sources)
+
+lib_LTLIBRARIES = libmemalloc.la
+libmemalloc_la_CC = @CC@
+libmemalloc_la_SOURCES = $(cpp_sources)
+libmemalloc_la_CFLAGS = $(COMMON_CFLAGS) -DLOG_TAG=\"qdmemalloc\"
+libmemalloc_la_CPPFLAGS = $(AM_CPPFLAGS)
+libmemalloc_la_LIBADD = ../libqdutils/libqdutils.la
+libmemalloc_la_LIBADD += -lhardware -lcutils -llog -lutils -ldl
+libmemalloc_la_LDFLAGS = -shared -avoid-version
+
+header_sources = gralloc_priv.h \
+ gr.h \
+ adreno_utils.h \
+ $(HEADER_PATH)/color_metadata.h
+
+c_sources = gpu.cpp \
+ gralloc.cpp \
+ framebuffer.cpp \
+ mapper.cpp
+
+library_includedir = $(pkgincludedir)
+library_include_HEADERS = $(header_sources)
+
+lib_LTLIBRARIES += libgralloc.la
+libgralloc_la_CC = @CC@
+libgralloc_la_SOURCES = $(c_sources)
+libgralloc_la_CFLAGS = $(COMMON_CFLAGS) -DLOG_TAG=\"qdgralloc\"
+libgralloc_la_CPPFLAGS = $(AM_CPPFLAGS)
+libgralloc_la_LIBADD = ../libqdutils/libqdutils.la
+libgralloc_la_LIBADD += ../libqdutils/libqdMetaData.la
+libgralloc_la_LIBADD += -lhardware -lcutils -llog -lutils -lbinder
+libgralloc_la_LIBADD += libmemalloc.la
+libgralloc_la_LDFLAGS = -shared -avoid-version
diff --git a/msm8909/libgralloc/adreno_utils.h b/msm8909/libgralloc/adreno_utils.h
new file mode 100644
index 00000000..baecef99
--- /dev/null
+++ b/msm8909/libgralloc/adreno_utils.h
@@ -0,0 +1,59 @@
+/*
+* Copyright (c) 2015 - 2017, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without modification, are permitted
+* provided that the following conditions are met:
+* * Redistributions of source code must retain the above copyright notice, this list of
+* conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright notice, this list of
+* conditions and the following disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its contributors may be used to
+* endorse or promote products derived from this software without specific prior written
+* permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+// Adreno Pixel Formats
+typedef enum {
+
+ ADRENO_PIXELFORMAT_UNKNOWN = 0,
+ ADRENO_PIXELFORMAT_R10G10B10A2_UNORM = 24, // Vertex, Normalized GL_UNSIGNED_INT_10_10_10_2_OES
+ ADRENO_PIXELFORMAT_R8G8B8A8 = 28,
+ ADRENO_PIXELFORMAT_R8G8B8A8_SRGB = 29,
+ ADRENO_PIXELFORMAT_B5G6R5 = 85,
+ ADRENO_PIXELFORMAT_B5G5R5A1 = 86,
+ ADRENO_PIXELFORMAT_B8G8R8A8 = 90,
+ ADRENO_PIXELFORMAT_B8G8R8A8_SRGB = 91,
+ ADRENO_PIXELFORMAT_B8G8R8X8_SRGB = 93,
+ ADRENO_PIXELFORMAT_NV12 = 103,
+ ADRENO_PIXELFORMAT_P010 = 104,
+ ADRENO_PIXELFORMAT_YUY2 = 107,
+ ADRENO_PIXELFORMAT_B4G4R4A4 = 115,
+ ADRENO_PIXELFORMAT_NV12_EXT = 506, // NV12 with non-std alignment and offsets
+ ADRENO_PIXELFORMAT_R8G8B8X8 = 507, // GL_RGB8 (Internal)
+ ADRENO_PIXELFORMAT_R8G8B8 = 508, // GL_RGB8
+ ADRENO_PIXELFORMAT_A1B5G5R5 = 519, // GL_RGB5_A1
+ ADRENO_PIXELFORMAT_R8G8B8X8_SRGB = 520, // GL_SRGB8
+ ADRENO_PIXELFORMAT_R8G8B8_SRGB = 521, // GL_SRGB8
+ ADRENO_PIXELFORMAT_A2B10G10R10_UNORM = 532,
+ // Vertex, Normalized GL_UNSIGNED_INT_10_10_10_2_OES
+ ADRENO_PIXELFORMAT_R10G10B10X2_UNORM = 537,
+ // Vertex, Normalized GL_UNSIGNED_INT_10_10_10_2_OES
+ ADRENO_PIXELFORMAT_R5G6B5 = 610, // RGBA version of B5G6R5
+ ADRENO_PIXELFORMAT_R5G5B5A1 = 611, // RGBA version of B5G5R5A1
+ ADRENO_PIXELFORMAT_R4G4B4A4 = 612, // RGBA version of B4G4R4A4
+ ADRENO_PIXELFORMAT_UYVY = 614, // YUV 4:2:2 packed progressive (1 plane)
+ ADRENO_PIXELFORMAT_NV21 = 619,
+ ADRENO_PIXELFORMAT_Y8U8V8A8 = 620, // YUV 4:4:4 packed (1 plane)
+ ADRENO_PIXELFORMAT_Y8 = 625, // Single 8-bit luma only channel YUV format
+ ADRENO_PIXELFORMAT_TP10 = 654, // YUV 4:2:0 planar 10 bits/comp (2 planes)
+} ADRENOPIXELFORMAT;
diff --git a/msm8909/libgralloc/alloc_controller.cpp b/msm8909/libgralloc/alloc_controller.cpp
index c7ba7c9e..d2a522ed 100644
--- a/msm8909/libgralloc/alloc_controller.cpp
+++ b/msm8909/libgralloc/alloc_controller.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011-2014,2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011 - 2017, The Linux Foundation. All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -30,74 +30,92 @@
#include <cutils/log.h>
#include <fcntl.h>
#include <dlfcn.h>
+#include <media/msm_media_info.h>
+#include <qdMetaData.h>
+#include <utils/Singleton.h>
+#include <utils/Mutex.h>
+#include <algorithm>
+
#include "gralloc_priv.h"
#include "alloc_controller.h"
#include "memalloc.h"
#include "ionalloc.h"
#include "gr.h"
-#include "comptype.h"
-#include "mdp_version.h"
+#include "qd_utils.h"
-#ifdef VENUS_COLOR_FORMAT
-#include <media/msm_media_info.h>
-#else
-#define VENUS_Y_STRIDE(args...) 0
-#define VENUS_Y_SCANLINES(args...) 0
-#define VENUS_BUFFER_SIZE(args...) 0
+#define ASTC_BLOCK_SIZE 16
+
+#ifndef ION_FLAG_CP_PIXEL
+#define ION_FLAG_CP_PIXEL 0
#endif
-#define ASTC_BLOCK_SIZE 16
+#ifndef ION_FLAG_ALLOW_NON_CONTIG
+#define ION_FLAG_ALLOW_NON_CONTIG 0
+#endif
+
+#ifndef ION_FLAG_CP_CAMERA_PREVIEW
+#define ION_FLAG_CP_CAMERA_PREVIEW 0
+#endif
+
+#ifdef MASTER_SIDE_CP
+#define CP_HEAP_ID ION_SECURE_HEAP_ID
+#define SD_HEAP_ID ION_SECURE_DISPLAY_HEAP_ID
+#define ION_CP_FLAGS (ION_SECURE | ION_FLAG_CP_PIXEL)
+#define ION_SD_FLAGS (ION_SECURE | ION_FLAG_CP_SEC_DISPLAY)
+#define ION_SC_FLAGS (ION_SECURE | ION_FLAG_CP_CAMERA)
+#define ION_SC_PREVIEW_FLAGS (ION_SECURE | ION_FLAG_CP_CAMERA_PREVIEW)
+#else // SLAVE_SIDE_CP
+#define CP_HEAP_ID ION_CP_MM_HEAP_ID
+#define SD_HEAP_ID CP_HEAP_ID
+#define ION_CP_FLAGS (ION_SECURE | ION_FLAG_ALLOW_NON_CONTIG)
+#define ION_SD_FLAGS ION_SECURE
+#define ION_SC_FLAGS ION_SECURE
+#define ION_SC_PREVIEW_FLAGS ION_SECURE
+#endif
+
+#ifndef COLOR_FMT_P010_UBWC
+#define COLOR_FMT_P010_UBWC 9
+#endif
using namespace gralloc;
using namespace qdutils;
+using namespace android;
ANDROID_SINGLETON_STATIC_INSTANCE(AdrenoMemInfo);
+ANDROID_SINGLETON_STATIC_INSTANCE(MDPCapabilityInfo);
+
+static void getYuvUBwcWidthHeight(int, int, int, int&, int&);
+static unsigned int getUBwcSize(int, int, int, const int, const int);
//Common functions
-static bool canFallback(int usage, bool triedSystem)
-{
- // Fallback to system heap when alloc fails unless
- // 1. Composition type is MDP
- // 2. Alloc from system heap was already tried
- // 3. The heap type is requsted explicitly
- // 4. The heap type is protected
- // 5. The buffer is meant for external display only
-
- if(QCCompositionType::getInstance().getCompositionType() &
- COMPOSITION_TYPE_MDP)
- return false;
- if(triedSystem)
- return false;
- if(usage & (GRALLOC_HEAP_MASK | GRALLOC_USAGE_PROTECTED))
- return false;
- if(usage & (GRALLOC_HEAP_MASK | GRALLOC_USAGE_PRIVATE_EXTERNAL_ONLY))
- return false;
- //Return true by default
- return true;
-}
/* The default policy is to return cached buffers unless the client explicity
* sets the PRIVATE_UNCACHED flag or indicates that the buffer will be rarely
* read or written in software. Any combination with a _RARELY_ flag will be
* treated as uncached. */
static bool useUncached(const int& usage) {
- if((usage & GRALLOC_USAGE_PRIVATE_UNCACHED) or
- ((usage & GRALLOC_USAGE_SW_WRITE_MASK) ==
- GRALLOC_USAGE_SW_WRITE_RARELY) or
- ((usage & GRALLOC_USAGE_SW_READ_MASK) ==
- GRALLOC_USAGE_SW_READ_RARELY))
+ if ((usage & GRALLOC_USAGE_PROTECTED) or
+ (usage & GRALLOC_USAGE_PRIVATE_UNCACHED) or
+ ((usage & GRALLOC_USAGE_SW_WRITE_MASK) == GRALLOC_USAGE_SW_WRITE_RARELY) or
+ ((usage & GRALLOC_USAGE_SW_READ_MASK) == GRALLOC_USAGE_SW_READ_RARELY))
return true;
return false;
}
-//-------------- AdrenoMemInfo-----------------------//
+//------------- MDPCapabilityInfo-----------------------//
+MDPCapabilityInfo :: MDPCapabilityInfo() {
+ qdutils::querySDEInfo(HAS_UBWC, &isUBwcSupported);
+ qdutils::querySDEInfo(HAS_WB_UBWC, &isWBUBWCSupported);
+}
+
+//------------- AdrenoMemInfo-----------------------//
AdrenoMemInfo::AdrenoMemInfo()
{
LINK_adreno_compute_aligned_width_and_height = NULL;
LINK_adreno_compute_padding = NULL;
- LINK_adreno_isMacroTilingSupportedByGpu = NULL;
LINK_adreno_compute_compressedfmt_aligned_width_and_height = NULL;
+ LINK_adreno_isUBWCSupportedByGpu = NULL;
LINK_adreno_get_gpu_pixel_alignment = NULL;
libadreno_utils = ::dlopen("libadreno_utils.so", RTLD_NOW);
@@ -106,14 +124,24 @@ AdrenoMemInfo::AdrenoMemInfo()
::dlsym(libadreno_utils, "compute_aligned_width_and_height");
*(void **)&LINK_adreno_compute_padding =
::dlsym(libadreno_utils, "compute_surface_padding");
- *(void **)&LINK_adreno_isMacroTilingSupportedByGpu =
- ::dlsym(libadreno_utils, "isMacroTilingSupportedByGpu");
*(void **)&LINK_adreno_compute_compressedfmt_aligned_width_and_height =
::dlsym(libadreno_utils,
"compute_compressedfmt_aligned_width_and_height");
+ *(void **)&LINK_adreno_isUBWCSupportedByGpu =
+ ::dlsym(libadreno_utils, "isUBWCSupportedByGpu");
*(void **)&LINK_adreno_get_gpu_pixel_alignment =
::dlsym(libadreno_utils, "get_gpu_pixel_alignment");
}
+
+ // Check if the overriding property debug.gralloc.gfx_ubwc_disable
+ // that disables UBWC allocations for the graphics stack is set
+ gfx_ubwc_disable = 0;
+ char property[PROPERTY_VALUE_MAX];
+ property_get("debug.gralloc.gfx_ubwc_disable", property, "0");
+ if(!(strncmp(property, "1", PROPERTY_VALUE_MAX)) ||
+ !(strncmp(property, "true", PROPERTY_VALUE_MAX))) {
+ gfx_ubwc_disable = 1;
+ }
}
AdrenoMemInfo::~AdrenoMemInfo()
@@ -123,78 +151,115 @@ AdrenoMemInfo::~AdrenoMemInfo()
}
}
-int AdrenoMemInfo::isMacroTilingSupportedByGPU()
-{
- if ((libadreno_utils)) {
- if(LINK_adreno_isMacroTilingSupportedByGpu) {
- return LINK_adreno_isMacroTilingSupportedByGpu();
+void AdrenoMemInfo::getAlignedWidthAndHeight(const private_handle_t *hnd, int& aligned_w,
+ int& aligned_h) {
+ MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
+ if(metadata && metadata->operation & UPDATE_BUFFER_GEOMETRY) {
+ int w = metadata->bufferDim.sliceWidth;
+ int h = metadata->bufferDim.sliceHeight;
+ int f = hnd->format;
+ int usage = 0;
+
+ if (hnd->flags & private_handle_t::PRIV_FLAGS_UBWC_ALIGNED) {
+ usage = GRALLOC_USAGE_PRIVATE_ALLOC_UBWC;
}
+
+ getAlignedWidthAndHeight(w, h, f, usage, aligned_w, aligned_h);
+ } else {
+ aligned_w = hnd->width;
+ aligned_h = hnd->height;
+ }
+
+}
+
+void AdrenoMemInfo::getUnalignedWidthAndHeight(const private_handle_t *hnd, int& unaligned_w,
+ int& unaligned_h) {
+ MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
+ if(metadata && metadata->operation & UPDATE_BUFFER_GEOMETRY) {
+ unaligned_w = metadata->bufferDim.sliceWidth;
+ unaligned_h = metadata->bufferDim.sliceHeight;
+ } else {
+ unaligned_w = hnd->unaligned_width;
+ unaligned_h = hnd->unaligned_height;
}
- return 0;
}
+bool isUncompressedRgbFormat(int format)
+{
+ bool is_rgb_format = false;
+
+ switch (format)
+ {
+ case HAL_PIXEL_FORMAT_RGBA_8888:
+ case HAL_PIXEL_FORMAT_RGBX_8888:
+ case HAL_PIXEL_FORMAT_RGB_888:
+ case HAL_PIXEL_FORMAT_RGB_565:
+ case HAL_PIXEL_FORMAT_BGR_565:
+ case HAL_PIXEL_FORMAT_BGRA_8888:
+ case HAL_PIXEL_FORMAT_RGBA_5551:
+ case HAL_PIXEL_FORMAT_RGBA_4444:
+ case HAL_PIXEL_FORMAT_R_8:
+ case HAL_PIXEL_FORMAT_RG_88:
+ case HAL_PIXEL_FORMAT_BGRX_8888:
+ case HAL_PIXEL_FORMAT_BGR_888:
+ case HAL_PIXEL_FORMAT_RGBA_1010102:
+ case HAL_PIXEL_FORMAT_ARGB_2101010:
+ case HAL_PIXEL_FORMAT_RGBX_1010102:
+ case HAL_PIXEL_FORMAT_XRGB_2101010:
+ case HAL_PIXEL_FORMAT_BGRA_1010102:
+ case HAL_PIXEL_FORMAT_ABGR_2101010:
+ case HAL_PIXEL_FORMAT_BGRX_1010102:
+ case HAL_PIXEL_FORMAT_XBGR_2101010: // Intentional fallthrough
+ is_rgb_format = true;
+ break;
+ default:
+ break;
+ }
+
+ return is_rgb_format;
+}
void AdrenoMemInfo::getAlignedWidthAndHeight(int width, int height, int format,
- int tile_enabled, int& aligned_w, int& aligned_h)
+ int usage, int& aligned_w, int& aligned_h)
{
- aligned_w = width;
- aligned_h = height;
- // Currently surface padding is only computed for RGB* surfaces.
- if (format <= HAL_PIXEL_FORMAT_BGRA_8888) {
- aligned_w = ALIGN(width, 32);
- aligned_h = ALIGN(height, 32);
+ bool ubwc_enabled = isUBwcEnabled(format, usage);
- int bpp = 4;
- switch(format)
- {
- case HAL_PIXEL_FORMAT_RGBA_FP16:
- bpp = 8;
- break;
- case HAL_PIXEL_FORMAT_RGB_888:
- bpp = 3;
- break;
- case HAL_PIXEL_FORMAT_RGB_565:
- bpp = 2;
- break;
- default: break;
- }
- if (libadreno_utils) {
- int raster_mode = 0; // Adreno unknown raster mode.
- int padding_threshold = 512; // Threshold for padding surfaces.
- // the function below computes aligned width and aligned height
- // based on linear or macro tile mode selected.
- if(LINK_adreno_compute_aligned_width_and_height) {
- LINK_adreno_compute_aligned_width_and_height(width,
- height, bpp, tile_enabled,
- raster_mode, padding_threshold,
- &aligned_w, &aligned_h);
-
- } else if(LINK_adreno_compute_padding) {
- int surface_tile_height = 1; // Linear surface
- aligned_w = LINK_adreno_compute_padding(width, bpp,
- surface_tile_height, raster_mode,
- padding_threshold);
- ALOGW("%s: Warning!! Old GFX API is used to calculate stride",
- __FUNCTION__);
- } else {
- ALOGW("%s: Warning!! Symbols compute_surface_padding and " \
- "compute_aligned_width_and_height not found", __FUNCTION__);
- }
- }
+ // Currently surface padding is only computed for RGB* surfaces.
+ if (isUncompressedRgbFormat(format) == true) {
+ int tileEnabled = ubwc_enabled;
+ getGpuAlignedWidthHeight(width, height, format, tileEnabled, aligned_w, aligned_h);
+ } else if (ubwc_enabled) {
+ getYuvUBwcWidthHeight(width, height, format, aligned_w, aligned_h);
} else {
+ aligned_w = width;
+ aligned_h = height;
int alignment = 32;
switch (format)
{
case HAL_PIXEL_FORMAT_YCrCb_420_SP:
case HAL_PIXEL_FORMAT_YCbCr_420_SP:
if (LINK_adreno_get_gpu_pixel_alignment) {
- alignment = LINK_adreno_get_gpu_pixel_alignment();
+ alignment = LINK_adreno_get_gpu_pixel_alignment();
}
aligned_w = ALIGN(width, alignment);
break;
case HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO:
aligned_w = ALIGN(width, alignment);
break;
+ case HAL_PIXEL_FORMAT_RAW16:
+ case HAL_PIXEL_FORMAT_Y16:
+ case HAL_PIXEL_FORMAT_Y8:
+ aligned_w = ALIGN(width, 16);
+ break;
+ case HAL_PIXEL_FORMAT_RAW12:
+ aligned_w = ALIGN(width * 12 / 8, 8);
+ break;
+ case HAL_PIXEL_FORMAT_RAW10:
+ aligned_w = ALIGN(width * 10 / 8, 8);
+ break;
+ case HAL_PIXEL_FORMAT_RAW8:
+ aligned_w = ALIGN(width, 8);
+ break;
case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED:
aligned_w = ALIGN(width, 128);
break;
@@ -203,6 +268,8 @@ void AdrenoMemInfo::getAlignedWidthAndHeight(int width, int height, int format,
case HAL_PIXEL_FORMAT_YCrCb_422_SP:
case HAL_PIXEL_FORMAT_YCbCr_422_I:
case HAL_PIXEL_FORMAT_YCrCb_422_I:
+ case HAL_PIXEL_FORMAT_YCbCr_420_P010:
+ case HAL_PIXEL_FORMAT_CbYCrY_422_I:
aligned_w = ALIGN(width, 16);
break;
case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
@@ -210,7 +277,12 @@ void AdrenoMemInfo::getAlignedWidthAndHeight(int width, int height, int format,
aligned_w = VENUS_Y_STRIDE(COLOR_FMT_NV12, width);
aligned_h = VENUS_Y_SCANLINES(COLOR_FMT_NV12, height);
break;
+ case HAL_PIXEL_FORMAT_YCrCb_420_SP_VENUS:
+ aligned_w = VENUS_Y_STRIDE(COLOR_FMT_NV21, width);
+ aligned_h = VENUS_Y_SCANLINES(COLOR_FMT_NV21, height);
+ break;
case HAL_PIXEL_FORMAT_BLOB:
+ case HAL_PIXEL_FORMAT_RAW_OPAQUE:
break;
case HAL_PIXEL_FORMAT_NV21_ZSL:
aligned_w = ALIGN(width, 64);
@@ -253,7 +325,6 @@ void AdrenoMemInfo::getAlignedWidthAndHeight(int width, int height, int format,
LINK_adreno_compute_compressedfmt_aligned_width_and_height(
width, height, format, 0,raster_mode, padding_threshold,
&aligned_w, &aligned_h, &bytesPerPixel);
-
} else {
ALOGW("%s: Warning!! Symbols" \
" compute_compressedfmt_aligned_width_and_height" \
@@ -265,6 +336,106 @@ void AdrenoMemInfo::getAlignedWidthAndHeight(int width, int height, int format,
}
}
+void AdrenoMemInfo::getGpuAlignedWidthHeight(int width, int height, int format,
+ int tile_enabled, int& aligned_w, int& aligned_h)
+{
+ aligned_w = ALIGN(width, 32);
+ aligned_h = ALIGN(height, 32);
+
+ // Don't add any additional padding if debug.gralloc.map_fb_memory
+ // is enabled
+ char property[PROPERTY_VALUE_MAX];
+ if((property_get("debug.gralloc.map_fb_memory", property, NULL) > 0) &&
+ (!strncmp(property, "1", PROPERTY_VALUE_MAX ) ||
+ (!strncasecmp(property,"true", PROPERTY_VALUE_MAX )))) {
+ return;
+ }
+
+ int bpp = 4;
+ switch(format)
+ {
+ case HAL_PIXEL_FORMAT_RGB_888:
+ bpp = 3;
+ break;
+ case HAL_PIXEL_FORMAT_RGB_565:
+ case HAL_PIXEL_FORMAT_BGR_565:
+ case HAL_PIXEL_FORMAT_RGBA_5551:
+ case HAL_PIXEL_FORMAT_RGBA_4444:
+ bpp = 2;
+ break;
+ default: break;
+ }
+
+ if (libadreno_utils) {
+ int raster_mode = 0; // Adreno unknown raster mode.
+ int padding_threshold = 512; // Threshold for padding surfaces.
+ // the function below computes aligned width and aligned height
+ // based on linear or macro tile mode selected.
+ if(LINK_adreno_compute_aligned_width_and_height) {
+ LINK_adreno_compute_aligned_width_and_height(width,
+ height, bpp, tile_enabled,
+ raster_mode, padding_threshold,
+ &aligned_w, &aligned_h);
+
+ } else if(LINK_adreno_compute_padding) {
+ int surface_tile_height = 1; // Linear surface
+ aligned_w = LINK_adreno_compute_padding(width, bpp,
+ surface_tile_height, raster_mode,
+ padding_threshold);
+ ALOGW("%s: Warning!! Old GFX API is used to calculate stride",
+ __FUNCTION__);
+ } else {
+ ALOGW("%s: Warning!! Symbols compute_surface_padding and " \
+ "compute_aligned_width_and_height not found", __FUNCTION__);
+ }
+ }
+}
+
+int AdrenoMemInfo::isUBWCSupportedByGPU(int format)
+{
+ if (!gfx_ubwc_disable && libadreno_utils) {
+ if (LINK_adreno_isUBWCSupportedByGpu) {
+ ADRENOPIXELFORMAT gpu_format = getGpuPixelFormat(format);
+ return LINK_adreno_isUBWCSupportedByGpu(gpu_format);
+ }
+ }
+ return 0;
+}
+
+ADRENOPIXELFORMAT AdrenoMemInfo::getGpuPixelFormat(int hal_format)
+{
+ switch (hal_format) {
+ case HAL_PIXEL_FORMAT_RGBA_8888:
+ return ADRENO_PIXELFORMAT_R8G8B8A8;
+ case HAL_PIXEL_FORMAT_RGBX_8888:
+ return ADRENO_PIXELFORMAT_R8G8B8X8;
+ case HAL_PIXEL_FORMAT_RGB_565:
+ return ADRENO_PIXELFORMAT_B5G6R5;
+ case HAL_PIXEL_FORMAT_BGR_565:
+ return ADRENO_PIXELFORMAT_R5G6B5;
+ case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
+ return ADRENO_PIXELFORMAT_NV12;
+ case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
+ case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC:
+ return ADRENO_PIXELFORMAT_NV12_EXT;
+ case HAL_PIXEL_FORMAT_YCbCr_420_TP10_UBWC:
+ return ADRENO_PIXELFORMAT_TP10;
+ case HAL_PIXEL_FORMAT_YCbCr_420_P010:
+ case HAL_PIXEL_FORMAT_YCbCr_420_P010_UBWC:
+ return ADRENO_PIXELFORMAT_P010;
+ case HAL_PIXEL_FORMAT_RGBA_1010102:
+ return ADRENO_PIXELFORMAT_R10G10B10A2_UNORM;
+ case HAL_PIXEL_FORMAT_RGBX_1010102:
+ return ADRENO_PIXELFORMAT_R10G10B10X2_UNORM;
+ case HAL_PIXEL_FORMAT_ABGR_2101010:
+ return ADRENO_PIXELFORMAT_A2B10G10R10_UNORM;
+ default:
+ ALOGE("%s: No map for format: 0x%x", __FUNCTION__, hal_format);
+ break;
+ }
+ return ADRENO_PIXELFORMAT_UNKNOWN;
+}
+
//-------------- IAllocController-----------------------//
IAllocController* IAllocController::sController = NULL;
IAllocController* IAllocController::getInstance(void)
@@ -280,6 +451,10 @@ IAllocController* IAllocController::getInstance(void)
IonController::IonController()
{
allocateIonMem();
+
+ char property[PROPERTY_VALUE_MAX];
+ property_get("video.disable.ubwc", property, "0");
+ mDisableUBWCForEncode = atoi(property);
}
void IonController::allocateIonMem()
@@ -290,68 +465,59 @@ void IonController::allocateIonMem()
int IonController::allocate(alloc_data& data, int usage)
{
int ionFlags = 0;
+ int ionHeapId = 0;
int ret;
data.uncached = useUncached(usage);
data.allocType = 0;
- if(usage & GRALLOC_USAGE_PRIVATE_UI_CONTIG_HEAP)
- ionFlags |= ION_HEAP(ION_SF_HEAP_ID);
-
- if(usage & GRALLOC_USAGE_PRIVATE_SYSTEM_HEAP)
- ionFlags |= ION_HEAP(ION_SYSTEM_HEAP_ID);
-
- if(usage & GRALLOC_USAGE_PRIVATE_IOMMU_HEAP)
- ionFlags |= ION_HEAP(ION_IOMMU_HEAP_ID);
-
if(usage & GRALLOC_USAGE_PROTECTED) {
- if (usage & GRALLOC_USAGE_PRIVATE_MM_HEAP) {
- ionFlags |= ION_HEAP(ION_CP_MM_HEAP_ID);
- ionFlags |= ION_SECURE;
+ if (usage & GRALLOC_USAGE_PRIVATE_SECURE_DISPLAY) {
+ ionHeapId = ION_HEAP(SD_HEAP_ID);
+ /*
+ * There is currently no flag in ION for Secure Display
+ * VM. Please add it to the define once available.
+ */
+ ionFlags |= ION_SD_FLAGS;
+ } else if (usage & GRALLOC_USAGE_HW_CAMERA_MASK) {
+ ionHeapId = ION_HEAP(SD_HEAP_ID);
+ ionFlags |= (usage & GRALLOC_USAGE_HW_COMPOSER) ? ION_SC_PREVIEW_FLAGS : ION_SC_FLAGS;
} else {
- // for targets/OEMs which do not need HW level protection
- // do not set ion secure flag & MM heap. Fallback to IOMMU heap.
- ionFlags |= ION_HEAP(ION_IOMMU_HEAP_ID);
+ ionHeapId = ION_HEAP(CP_HEAP_ID);
+ ionFlags |= ION_CP_FLAGS;
}
} else if(usage & GRALLOC_USAGE_PRIVATE_MM_HEAP) {
//MM Heap is exclusively a secure heap.
//If it is used for non secure cases, fallback to IOMMU heap
ALOGW("GRALLOC_USAGE_PRIVATE_MM_HEAP \
cannot be used as an insecure heap!\
- trying to use IOMMU instead !!");
- ionFlags |= ION_HEAP(ION_IOMMU_HEAP_ID);
+ trying to use system heap instead !!");
+ ionHeapId |= ION_HEAP(ION_SYSTEM_HEAP_ID);
}
if(usage & GRALLOC_USAGE_PRIVATE_CAMERA_HEAP)
- ionFlags |= ION_HEAP(ION_CAMERA_HEAP_ID);
+ ionHeapId |= ION_HEAP(ION_CAMERA_HEAP_ID);
if(usage & GRALLOC_USAGE_PRIVATE_ADSP_HEAP)
- ionFlags |= ION_HEAP(ION_ADSP_HEAP_ID);
+ ionHeapId |= ION_HEAP(ION_ADSP_HEAP_ID);
if(ionFlags & ION_SECURE)
data.allocType |= private_handle_t::PRIV_FLAGS_SECURE_BUFFER;
- // if no flags are set, default to
- // SF + IOMMU heaps, so that bypass can work
- // we can fall back to system heap if
- // we run out.
- if(!ionFlags)
- ionFlags = ION_HEAP(ION_SF_HEAP_ID) | ION_HEAP(ION_IOMMU_HEAP_ID);
+ // if no ion heap flags are set, default to system heap
+ if(!ionHeapId)
+ ionHeapId = ION_HEAP(ION_SYSTEM_HEAP_ID);
+ //At this point we should have the right heap set, there is no fallback
data.flags = ionFlags;
+ data.heapId = ionHeapId;
ret = mIonAlloc->alloc_buffer(data);
- // Fallback
- if(ret < 0 && canFallback(usage,
- (ionFlags & ION_SYSTEM_HEAP_ID)))
- {
- ALOGW("Falling back to system heap");
- data.flags = ION_HEAP(ION_SYSTEM_HEAP_ID);
- ret = mIonAlloc->alloc_buffer(data);
- }
-
if(ret >= 0 ) {
data.allocType |= private_handle_t::PRIV_FLAGS_USES_ION;
+ } else {
+ ALOGE("%s: Failed to allocate buffer - heap: 0x%x flags: 0x%x",
+ __FUNCTION__, ionHeapId, ionFlags);
}
return ret;
@@ -369,61 +535,50 @@ IMemAlloc* IonController::getAllocator(int flags)
return memalloc;
}
-bool isMacroTileEnabled(int format, int usage)
-{
- bool tileEnabled = false;
+// helper function
+unsigned int getSize(int format, int width, int height, int usage,
+ const int alignedw, const int alignedh) {
- // Check whether GPU & MDSS supports MacroTiling feature
- if(AdrenoMemInfo::getInstance().isMacroTilingSupportedByGPU() &&
- qdutils::MDPVersion::getInstance().supportsMacroTile())
- {
- // check the format
- switch(format)
- {
- case HAL_PIXEL_FORMAT_RGBA_8888:
- case HAL_PIXEL_FORMAT_RGBX_8888:
- case HAL_PIXEL_FORMAT_BGRA_8888:
- case HAL_PIXEL_FORMAT_RGB_565:
- {
- tileEnabled = true;
- // check the usage flags
- if (usage & (GRALLOC_USAGE_SW_READ_MASK |
- GRALLOC_USAGE_SW_WRITE_MASK)) {
- // Application intends to use CPU for rendering
- tileEnabled = false;
- }
- break;
- }
- default:
- break;
- }
+ if (isUBwcEnabled(format, usage)) {
+ return getUBwcSize(width, height, format, alignedw, alignedh);
}
- return tileEnabled;
-}
-// helper function
-unsigned int getSize(int format, int width, int height, const int alignedw,
- const int alignedh) {
unsigned int size = 0;
-
switch (format) {
- case HAL_PIXEL_FORMAT_RGBA_FP16:
- size = alignedw * alignedh * 8;
- break;
case HAL_PIXEL_FORMAT_RGBA_8888:
case HAL_PIXEL_FORMAT_RGBX_8888:
case HAL_PIXEL_FORMAT_BGRA_8888:
case HAL_PIXEL_FORMAT_RGBA_1010102:
+ case HAL_PIXEL_FORMAT_ARGB_2101010:
+ case HAL_PIXEL_FORMAT_RGBX_1010102:
+ case HAL_PIXEL_FORMAT_XRGB_2101010:
+ case HAL_PIXEL_FORMAT_BGRA_1010102:
+ case HAL_PIXEL_FORMAT_ABGR_2101010:
+ case HAL_PIXEL_FORMAT_BGRX_1010102:
+ case HAL_PIXEL_FORMAT_XBGR_2101010:
size = alignedw * alignedh * 4;
break;
case HAL_PIXEL_FORMAT_RGB_888:
size = alignedw * alignedh * 3;
break;
case HAL_PIXEL_FORMAT_RGB_565:
+ case HAL_PIXEL_FORMAT_BGR_565:
+ case HAL_PIXEL_FORMAT_RGBA_5551:
+ case HAL_PIXEL_FORMAT_RGBA_4444:
case HAL_PIXEL_FORMAT_RAW16:
+ case HAL_PIXEL_FORMAT_Y16:
size = alignedw * alignedh * 2;
break;
-
+ case HAL_PIXEL_FORMAT_RAW12:
+ size = ALIGN(alignedw * alignedh, 4096);
+ break;
+ case HAL_PIXEL_FORMAT_RAW10:
+ size = ALIGN(alignedw * alignedh, 4096);
+ break;
+ case HAL_PIXEL_FORMAT_RAW8:
+ case HAL_PIXEL_FORMAT_Y8:
+ size = alignedw * alignedh;
+ break;
// adreno formats
case HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO: // NV21
size = ALIGN(alignedw*alignedh, 4096);
@@ -449,10 +604,14 @@ unsigned int getSize(int format, int width, int height, const int alignedw,
case HAL_PIXEL_FORMAT_YCrCb_420_SP:
size = ALIGN((alignedw*alignedh) + (alignedw* alignedh)/2 + 1, 4096);
break;
+ case HAL_PIXEL_FORMAT_YCbCr_420_P010:
+ size = ALIGN((alignedw * alignedh * 2) + (alignedw * alignedh) + 1, 4096);
+ break;
case HAL_PIXEL_FORMAT_YCbCr_422_SP:
case HAL_PIXEL_FORMAT_YCrCb_422_SP:
case HAL_PIXEL_FORMAT_YCbCr_422_I:
case HAL_PIXEL_FORMAT_YCrCb_422_I:
+ case HAL_PIXEL_FORMAT_CbYCrY_422_I:
if(width & 1) {
ALOGE("width is odd for the YUV422_SP format");
return 0;
@@ -463,7 +622,11 @@ unsigned int getSize(int format, int width, int height, const int alignedw,
case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
size = VENUS_BUFFER_SIZE(COLOR_FMT_NV12, width, height);
break;
+ case HAL_PIXEL_FORMAT_YCrCb_420_SP_VENUS:
+ size = VENUS_BUFFER_SIZE(COLOR_FMT_NV21, width, height);
+ break;
case HAL_PIXEL_FORMAT_BLOB:
+ case HAL_PIXEL_FORMAT_RAW_OPAQUE:
if(height != 1) {
ALOGE("%s: Buffers with format HAL_PIXEL_FORMAT_BLOB \
must have height==1 ", __FUNCTION__);
@@ -519,11 +682,11 @@ unsigned int getBufferSizeAndDimensions(int width, int height, int format,
AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(width,
height,
format,
- false,
+ 0,
alignedw,
alignedh);
- size = getSize(format, width, height, alignedw, alignedh);
+ size = getSize(format, width, height, 0 /* usage */, alignedw, alignedh);
return size;
}
@@ -533,91 +696,166 @@ unsigned int getBufferSizeAndDimensions(int width, int height, int format,
int usage, int& alignedw, int &alignedh)
{
unsigned int size;
- int tileEnabled = isMacroTileEnabled(format, usage);
AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(width,
height,
format,
- tileEnabled,
+ usage,
alignedw,
alignedh);
- size = getSize(format, width, height, alignedw, alignedh);
+ size = getSize(format, width, height, usage, alignedw, alignedh);
return size;
}
+void getYuvUbwcSPPlaneInfo(uint64_t base, int width, int height,
+ int color_format, struct android_ycbcr* ycbcr)
+{
+ // UBWC buffer has these 4 planes in the following sequence:
+ // Y_Meta_Plane, Y_Plane, UV_Meta_Plane, UV_Plane
+ unsigned int y_meta_stride, y_meta_height, y_meta_size;
+ unsigned int y_stride, y_height, y_size;
+ unsigned int c_meta_stride, c_meta_height, c_meta_size;
+ unsigned int alignment = 4096;
+
+ y_meta_stride = VENUS_Y_META_STRIDE(color_format, width);
+ y_meta_height = VENUS_Y_META_SCANLINES(color_format, height);
+ y_meta_size = ALIGN((y_meta_stride * y_meta_height), alignment);
+
+ y_stride = VENUS_Y_STRIDE(color_format, width);
+ y_height = VENUS_Y_SCANLINES(color_format, height);
+ y_size = ALIGN((y_stride * y_height), alignment);
+
+ c_meta_stride = VENUS_UV_META_STRIDE(color_format, width);
+ c_meta_height = VENUS_UV_META_SCANLINES(color_format, height);
+ c_meta_size = ALIGN((c_meta_stride * c_meta_height), alignment);
+
+ ycbcr->y = (void*)(base + y_meta_size);
+ ycbcr->cb = (void*)(base + y_meta_size + y_size + c_meta_size);
+ ycbcr->cr = (void*)(base + y_meta_size + y_size +
+ c_meta_size + 1);
+ ycbcr->ystride = y_stride;
+ ycbcr->cstride = VENUS_UV_STRIDE(color_format, width);
+}
-void getBufferAttributes(int width, int height, int format, int usage,
- int& alignedw, int &alignedh, int& tileEnabled, unsigned int& size)
+void getYuvSPPlaneInfo(uint64_t base, int width, int height, int bpp,
+ struct android_ycbcr* ycbcr)
{
- tileEnabled = isMacroTileEnabled(format, usage);
+ unsigned int ystride, cstride;
- AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(width,
- height,
- format,
- tileEnabled,
- alignedw,
- alignedh);
- size = getSize(format, width, height, alignedw, alignedh);
+ ystride = cstride = width * bpp;
+ ycbcr->y = (void*)base;
+ ycbcr->cb = (void*)(base + ystride * height);
+ ycbcr->cr = (void*)(base + ystride * height + 1);
+ ycbcr->ystride = ystride;
+ ycbcr->cstride = cstride;
+ ycbcr->chroma_step = 2 * bpp;
}
int getYUVPlaneInfo(private_handle_t* hnd, struct android_ycbcr* ycbcr)
{
int err = 0;
+ int width = hnd->width;
+ int height = hnd->height;
+ int format = hnd->format;
+
unsigned int ystride, cstride;
+
memset(ycbcr->reserved, 0, sizeof(ycbcr->reserved));
+ MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
+
+ // Check if UBWC buffer has been rendered in linear format.
+ if (metadata && (metadata->operation & LINEAR_FORMAT)) {
+ format = metadata->linearFormat;
+ }
+
+ // Check metadata if the geometry has been updated.
+ if(metadata && metadata->operation & UPDATE_BUFFER_GEOMETRY) {
+ int usage = 0;
+
+ if (hnd->flags & private_handle_t::PRIV_FLAGS_UBWC_ALIGNED) {
+ usage = GRALLOC_USAGE_PRIVATE_ALLOC_UBWC;
+ }
+
+ AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(metadata->bufferDim.sliceWidth,
+ metadata->bufferDim.sliceHeight, format, usage, width, height);
+ }
// Get the chroma offsets from the handle width/height. We take advantage
// of the fact the width _is_ the stride
- switch (hnd->format) {
+ switch (format) {
//Semiplanar
case HAL_PIXEL_FORMAT_YCbCr_420_SP:
case HAL_PIXEL_FORMAT_YCbCr_422_SP:
case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
case HAL_PIXEL_FORMAT_NV12_ENCODEABLE: //Same as YCbCr_420_SP_VENUS
- ystride = cstride = hnd->width;
- ycbcr->y = (void*)hnd->base;
- ycbcr->cb = (void*)(hnd->base + ystride * hnd->height);
- ycbcr->cr = (void*)(hnd->base + ystride * hnd->height + 1);
- ycbcr->ystride = ystride;
- ycbcr->cstride = cstride;
+ getYuvSPPlaneInfo(hnd->base, width, height, 1, ycbcr);
+ break;
+
+ case HAL_PIXEL_FORMAT_YCbCr_420_P010:
+ getYuvSPPlaneInfo(hnd->base, width, height, 2, ycbcr);
+ break;
+
+ case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC:
+ getYuvUbwcSPPlaneInfo(hnd->base, width, height,
+ COLOR_FMT_NV12_UBWC, ycbcr);
ycbcr->chroma_step = 2;
break;
+ case HAL_PIXEL_FORMAT_YCbCr_420_TP10_UBWC:
+ getYuvUbwcSPPlaneInfo(hnd->base, width, height,
+ COLOR_FMT_NV12_BPP10_UBWC, ycbcr);
+ ycbcr->chroma_step = 3;
+ break;
+ case HAL_PIXEL_FORMAT_YCbCr_420_P010_UBWC:
+ getYuvUbwcSPPlaneInfo(hnd->base, width, height,
+ COLOR_FMT_P010_UBWC, ycbcr);
+ ycbcr->chroma_step = 4;
+ break;
case HAL_PIXEL_FORMAT_YCrCb_420_SP:
case HAL_PIXEL_FORMAT_YCrCb_422_SP:
case HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO:
+ case HAL_PIXEL_FORMAT_YCrCb_420_SP_VENUS:
case HAL_PIXEL_FORMAT_NV21_ZSL:
- ystride = cstride = hnd->width;
- ycbcr->y = (void*)hnd->base;
- ycbcr->cr = (void*)(hnd->base + ystride * hnd->height);
- ycbcr->cb = (void*)(hnd->base + ystride * hnd->height + 1);
- ycbcr->ystride = ystride;
- ycbcr->cstride = cstride;
- ycbcr->chroma_step = 2;
+ case HAL_PIXEL_FORMAT_RAW16:
+ case HAL_PIXEL_FORMAT_Y16:
+ case HAL_PIXEL_FORMAT_RAW12:
+ case HAL_PIXEL_FORMAT_RAW10:
+ case HAL_PIXEL_FORMAT_RAW8:
+ case HAL_PIXEL_FORMAT_Y8:
+ getYuvSPPlaneInfo(hnd->base, width, height, 1, ycbcr);
+ std::swap(ycbcr->cb, ycbcr->cr);
break;
//Planar
case HAL_PIXEL_FORMAT_YV12:
- ystride = hnd->width;
- cstride = ALIGN(hnd->width/2, 16);
+ ystride = width;
+ cstride = ALIGN(width/2, 16);
ycbcr->y = (void*)hnd->base;
- ycbcr->cr = (void*)(hnd->base + ystride * hnd->height);
- ycbcr->cb = (void*)(hnd->base + ystride * hnd->height +
- cstride * hnd->height/2);
+ ycbcr->cr = (void*)(hnd->base + ystride * height);
+ ycbcr->cb = (void*)(hnd->base + ystride * height +
+ cstride * height/2);
ycbcr->ystride = ystride;
ycbcr->cstride = cstride;
ycbcr->chroma_step = 1;
-
+ break;
+ case HAL_PIXEL_FORMAT_CbYCrY_422_I:
+ ystride = width * 2;
+ cstride = 0;
+ ycbcr->y = (void*)hnd->base;
+ ycbcr->cr = NULL;
+ ycbcr->cb = NULL;
+ ycbcr->ystride = ystride;
+ ycbcr->cstride = 0;
+ ycbcr->chroma_step = 0;
break;
//Unsupported formats
case HAL_PIXEL_FORMAT_YCbCr_422_I:
case HAL_PIXEL_FORMAT_YCrCb_422_I:
case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED:
default:
- ALOGD("%s: Invalid format passed: 0x%x", __FUNCTION__,
- hnd->format);
+ ALOGD("%s: Invalid format passed: 0x%x", __FUNCTION__, format);
err = -EINVAL;
}
return err;
@@ -651,9 +889,13 @@ int alloc_buffer(private_handle_t **pHnd, int w, int h, int format, int usage)
return -ENOMEM;
}
+ if(isUBwcEnabled(format, usage)) {
+ data.allocType |= private_handle_t::PRIV_FLAGS_UBWC_ALIGNED;
+ }
+
private_handle_t* hnd = new private_handle_t(data.fd, data.size,
data.allocType, 0, format,
- alignedw, alignedh);
+ alignedw, alignedh, -1, 0, 0, w, h);
hnd->base = (uint64_t) data.base;
hnd->offset = data.offset;
hnd->gpuaddr = 0;
@@ -673,3 +915,309 @@ void free_buffer(private_handle_t *hnd)
delete hnd;
}
+
+// UBWC helper functions
+static bool isUBwcFormat(int format)
+{
+ // Explicitly defined UBWC formats
+ switch(format)
+ {
+ case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC:
+ case HAL_PIXEL_FORMAT_YCbCr_420_TP10_UBWC:
+ case HAL_PIXEL_FORMAT_YCbCr_420_P010_UBWC:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static bool isUBwcSupported(int format)
+{
+ if (MDPCapabilityInfo::getInstance().isUBwcSupportedByMDP()) {
+ // Existing HAL formats with UBWC support
+ switch(format)
+ {
+ case HAL_PIXEL_FORMAT_BGR_565:
+ case HAL_PIXEL_FORMAT_RGBA_8888:
+ case HAL_PIXEL_FORMAT_RGBX_8888:
+ case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
+ case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
+ case HAL_PIXEL_FORMAT_RGBA_1010102:
+ case HAL_PIXEL_FORMAT_RGBX_1010102:
+ return true;
+ default:
+ break;
+ }
+ }
+ return false;
+}
+
+bool isUBwcEnabled(int format, int usage)
+{
+ // Allow UBWC, if client is using an explicitly defined UBWC pixel format.
+ if (isUBwcFormat(format))
+ return true;
+
+ if ((usage & GRALLOC_USAGE_HW_VIDEO_ENCODER) &&
+ gralloc::IAllocController::getInstance()->isDisableUBWCForEncoder()) {
+ return false;
+ }
+
+ // Allow UBWC, if an OpenGL client sets UBWC usage flag and GPU plus MDP
+ // support the format. OR if a non-OpenGL client like Rotator, sets UBWC
+ // usage flag and MDP supports the format.
+ if ((usage & GRALLOC_USAGE_PRIVATE_ALLOC_UBWC) && isUBwcSupported(format)) {
+ bool enable = true;
+ // Query GPU for UBWC only if buffer is intended to be used by GPU.
+ if (usage & (GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_HW_RENDER)) {
+ enable = AdrenoMemInfo::getInstance().isUBWCSupportedByGPU(format);
+ }
+ // Allow UBWC, only if CPU usage flags are not set
+ if (enable && !(usage & (GRALLOC_USAGE_SW_READ_MASK |
+ GRALLOC_USAGE_SW_WRITE_MASK))) {
+ return true;
+ }
+ }
+ return false;
+}
+
+static void getYuvUBwcWidthHeight(int width, int height, int format,
+ int& aligned_w, int& aligned_h)
+{
+ switch (format)
+ {
+ case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
+ case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
+ case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC:
+ aligned_w = VENUS_Y_STRIDE(COLOR_FMT_NV12_UBWC, width);
+ aligned_h = VENUS_Y_SCANLINES(COLOR_FMT_NV12_UBWC, height);
+ break;
+ case HAL_PIXEL_FORMAT_YCbCr_420_TP10_UBWC:
+ // The macro returns the stride which is 4/3 times the width, hence * 3/4
+ aligned_w = (VENUS_Y_STRIDE(COLOR_FMT_NV12_BPP10_UBWC, width) * 3) / 4;
+ aligned_h = VENUS_Y_SCANLINES(COLOR_FMT_NV12_BPP10_UBWC, height);
+ break;
+ case HAL_PIXEL_FORMAT_YCbCr_420_P010_UBWC:
+ // The macro returns the stride which is 2 times the width, hence / 2
+ aligned_w = (VENUS_Y_STRIDE(COLOR_FMT_P010_UBWC, width) / 2);
+ aligned_h = VENUS_Y_SCANLINES(COLOR_FMT_P010_UBWC, height);
+ break;
+ default:
+ ALOGE("%s: Unsupported pixel format: 0x%x", __FUNCTION__, format);
+ aligned_w = 0;
+ aligned_h = 0;
+ break;
+ }
+}
+
+static void getRgbUBwcBlockSize(int bpp, int& block_width, int& block_height)
+{
+ block_width = 0;
+ block_height = 0;
+
+ switch(bpp)
+ {
+ case 2:
+ case 4:
+ block_width = 16;
+ block_height = 4;
+ break;
+ case 8:
+ block_width = 8;
+ block_height = 4;
+ break;
+ case 16:
+ block_width = 4;
+ block_height = 4;
+ break;
+ default:
+ ALOGE("%s: Unsupported bpp: %d", __FUNCTION__, bpp);
+ break;
+ }
+}
+
+static unsigned int getRgbUBwcMetaBufferSize(int width, int height, int bpp)
+{
+ unsigned int size = 0;
+ int meta_width, meta_height;
+ int block_width, block_height;
+
+ getRgbUBwcBlockSize(bpp, block_width, block_height);
+
+ if (!block_width || !block_height) {
+ ALOGE("%s: Unsupported bpp: %d", __FUNCTION__, bpp);
+ return size;
+ }
+
+ // Align meta buffer height to 16 blocks
+ meta_height = ALIGN(((height + block_height - 1) / block_height), 16);
+
+ // Align meta buffer width to 64 blocks
+ meta_width = ALIGN(((width + block_width - 1) / block_width), 64);
+
+ // Align meta buffer size to 4K
+ size = ALIGN((meta_width * meta_height), 4096);
+ return size;
+}
+
+static unsigned int getUBwcSize(int width, int height, int format,
+ const int alignedw, const int alignedh) {
+
+ unsigned int size = 0;
+ switch (format) {
+ case HAL_PIXEL_FORMAT_BGR_565:
+ size = alignedw * alignedh * 2;
+ size += getRgbUBwcMetaBufferSize(width, height, 2);
+ break;
+ case HAL_PIXEL_FORMAT_RGBA_8888:
+ case HAL_PIXEL_FORMAT_RGBX_8888:
+ case HAL_PIXEL_FORMAT_RGBA_1010102:
+ case HAL_PIXEL_FORMAT_RGBX_1010102:
+ size = alignedw * alignedh * 4;
+ size += getRgbUBwcMetaBufferSize(width, height, 4);
+ break;
+ case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
+ case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
+ case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC:
+ size = VENUS_BUFFER_SIZE(COLOR_FMT_NV12_UBWC, width, height);
+ break;
+ case HAL_PIXEL_FORMAT_YCbCr_420_TP10_UBWC:
+ size = VENUS_BUFFER_SIZE(COLOR_FMT_NV12_BPP10_UBWC, width, height);
+ break;
+ case HAL_PIXEL_FORMAT_YCbCr_420_P010_UBWC:
+ size = VENUS_BUFFER_SIZE(COLOR_FMT_P010_UBWC, width, height);
+ break;
+ default:
+ ALOGE("%s: Unsupported pixel format: 0x%x", __FUNCTION__, format);
+ break;
+ }
+ return size;
+}
+
+int getRgbDataAddress(private_handle_t* hnd, void** rgb_data)
+{
+ int err = 0;
+
+ // This api is for RGB* formats
+ if (!isUncompressedRgbFormat(hnd->format)) {
+ return -EINVAL;
+ }
+
+ // linear buffer
+ if (!(hnd->flags & private_handle_t::PRIV_FLAGS_UBWC_ALIGNED)) {
+ *rgb_data = (void*)hnd->base;
+ return err;
+ }
+
+ // Ubwc buffers
+ unsigned int meta_size = 0;
+ switch (hnd->format) {
+ case HAL_PIXEL_FORMAT_BGR_565:
+ meta_size = getRgbUBwcMetaBufferSize(hnd->width, hnd->height, 2);
+ break;
+ case HAL_PIXEL_FORMAT_RGBA_8888:
+ case HAL_PIXEL_FORMAT_RGBX_8888:
+ case HAL_PIXEL_FORMAT_RGBA_1010102:
+ case HAL_PIXEL_FORMAT_RGBX_1010102:
+ meta_size = getRgbUBwcMetaBufferSize(hnd->width, hnd->height, 4);
+ break;
+ default:
+ ALOGE("%s:Unsupported RGB format: 0x%x", __FUNCTION__, hnd->format);
+ err = -EINVAL;
+ break;
+ }
+
+ *rgb_data = (void*)(hnd->base + meta_size);
+ return err;
+}
+
+int getBufferLayout(private_handle_t *hnd, uint32_t stride[4],
+ uint32_t offset[4], uint32_t *num_planes) {
+ if (!hnd || !stride || !offset || !num_planes) {
+ return -EINVAL;
+ }
+
+ struct android_ycbcr yuvInfo = {};
+ *num_planes = 1;
+ stride[0] = 0;
+
+ switch (hnd->format) {
+ case HAL_PIXEL_FORMAT_RGB_565:
+ case HAL_PIXEL_FORMAT_BGR_565:
+ case HAL_PIXEL_FORMAT_RGBA_5551:
+ case HAL_PIXEL_FORMAT_RGBA_4444:
+ stride[0] = hnd->width * 2;
+ break;
+ case HAL_PIXEL_FORMAT_RGB_888:
+ stride[0] = hnd->width * 3;
+ break;
+ case HAL_PIXEL_FORMAT_RGBA_8888:
+ case HAL_PIXEL_FORMAT_BGRA_8888:
+ case HAL_PIXEL_FORMAT_RGBX_8888:
+ case HAL_PIXEL_FORMAT_BGRX_8888:
+ case HAL_PIXEL_FORMAT_RGBA_1010102:
+ case HAL_PIXEL_FORMAT_ARGB_2101010:
+ case HAL_PIXEL_FORMAT_RGBX_1010102:
+ case HAL_PIXEL_FORMAT_XRGB_2101010:
+ case HAL_PIXEL_FORMAT_BGRA_1010102:
+ case HAL_PIXEL_FORMAT_ABGR_2101010:
+ case HAL_PIXEL_FORMAT_BGRX_1010102:
+ case HAL_PIXEL_FORMAT_XBGR_2101010:
+ stride[0] = hnd->width * 4;
+ break;
+ }
+
+ // Format is RGB
+ if (stride[0]) {
+ return 0;
+ }
+
+ (*num_planes)++;
+ int ret = getYUVPlaneInfo(hnd, &yuvInfo);
+ if (ret < 0) {
+ ALOGE("%s failed", __FUNCTION__);
+ return ret;
+ }
+
+ stride[0] = static_cast<uint32_t>(yuvInfo.ystride);
+ offset[0] = static_cast<uint32_t>(
+ reinterpret_cast<uint64_t>(yuvInfo.y) - hnd->base);
+ stride[1] = static_cast<uint32_t>(yuvInfo.cstride);
+ switch (hnd->format) {
+ case HAL_PIXEL_FORMAT_YCbCr_420_SP:
+ case HAL_PIXEL_FORMAT_YCbCr_422_SP:
+ case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
+ case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
+ case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC:
+ case HAL_PIXEL_FORMAT_YCbCr_420_P010:
+ case HAL_PIXEL_FORMAT_YCbCr_420_TP10_UBWC:
+ case HAL_PIXEL_FORMAT_YCbCr_420_P010_UBWC:
+ offset[1] = static_cast<uint32_t>(
+ reinterpret_cast<uint64_t>(yuvInfo.cb) - hnd->base);
+ break;
+ case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+ case HAL_PIXEL_FORMAT_YCrCb_420_SP_VENUS:
+ case HAL_PIXEL_FORMAT_YCrCb_422_SP:
+ offset[1] = static_cast<uint32_t>(
+ reinterpret_cast<uint64_t>(yuvInfo.cr) - hnd->base);
+ break;
+ case HAL_PIXEL_FORMAT_YV12:
+ offset[1] = static_cast<uint32_t>(
+ reinterpret_cast<uint64_t>(yuvInfo.cr) - hnd->base);
+ stride[2] = static_cast<uint32_t>(yuvInfo.cstride);
+ offset[2] = static_cast<uint32_t>(
+ reinterpret_cast<uint64_t>(yuvInfo.cb) - hnd->base);
+ (*num_planes)++;
+ break;
+ default:
+ ALOGW("%s: Unsupported format %s", __FUNCTION__,
+ qdutils::GetHALPixelFormatString(hnd->format));
+ ret = -EINVAL;
+ }
+
+ if (hnd->flags & private_handle_t::PRIV_FLAGS_UBWC_ALIGNED) {
+ std::fill(offset, offset + 4, 0);
+ }
+
+ return 0;
+}
diff --git a/msm8909/libgralloc/alloc_controller.h b/msm8909/libgralloc/alloc_controller.h
index f0b8ed9a..45977e2b 100644
--- a/msm8909/libgralloc/alloc_controller.h
+++ b/msm8909/libgralloc/alloc_controller.h
@@ -29,6 +29,17 @@
#ifndef GRALLOC_ALLOCCONTROLLER_H
#define GRALLOC_ALLOCCONTROLLER_H
+#define SZ_2M 0x200000
+#define SZ_1M 0x100000
+#define SZ_4K 0x1000
+
+/* TODO: Move this to the common makefile */
+#ifdef MASTER_SIDE_CP
+#define SECURE_ALIGN SZ_4K
+#else
+#define SECURE_ALIGN SZ_1M
+#endif
+
namespace gralloc {
struct alloc_data;
@@ -45,6 +56,8 @@ class IAllocController {
virtual IMemAlloc* getAllocator(int flags) = 0;
+ virtual bool isDisableUBWCForEncoder() = 0;
+
virtual ~IAllocController() {};
static IAllocController* getInstance(void);
@@ -61,10 +74,15 @@ class IonController : public IAllocController {
virtual IMemAlloc* getAllocator(int flags);
+ virtual bool isDisableUBWCForEncoder() {
+ return mDisableUBWCForEncode;
+ }
+
IonController();
private:
IonAlloc* mIonAlloc;
+ bool mDisableUBWCForEncode;
void allocateIonMem();
};
diff --git a/msm8909/libgralloc/framebuffer.cpp b/msm8909/libgralloc/framebuffer.cpp
index b0a9a1e7..dd4842f2 100644
--- a/msm8909/libgralloc/framebuffer.cpp
+++ b/msm8909/libgralloc/framebuffer.cpp
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2008 The Android Open Source Project
- * Copyright (c) 2010-2014,2016 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2010-2014 The Linux Foundation. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -34,7 +34,9 @@
#include <linux/fb.h>
#include <linux/msm_mdp.h>
+#ifndef TARGET_HEADLESS
#include <GLES/gl.h>
+#endif
#include "gralloc_priv.h"
#include "fb_priv.h"
@@ -57,7 +59,6 @@ struct fb_context_t {
static int fb_setSwapInterval(struct framebuffer_device_t* dev,
int interval)
{
-#ifdef DEBUG_SWAPINTERVAL
//XXX: Get the value here and implement along with
//single vsync in HWC
char pval[PROPERTY_VALUE_MAX];
@@ -65,7 +66,6 @@ static int fb_setSwapInterval(struct framebuffer_device_t* dev,
int property_interval = atoi(pval);
if (property_interval >= 0)
interval = property_interval;
-#endif
private_module_t* m = reinterpret_cast<private_module_t*>(
dev->common.module);
@@ -101,7 +101,9 @@ static int fb_compositionComplete(struct framebuffer_device_t* dev)
if(!dev) {
return -1;
}
+#ifndef TARGET_HEADLESS
glFinish();
+#endif
return 0;
}
diff --git a/msm8909/libgralloc/gpu.cpp b/msm8909/libgralloc/gpu.cpp
index b95077fc..c57ff902 100644
--- a/msm8909/libgralloc/gpu.cpp
+++ b/msm8909/libgralloc/gpu.cpp
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2010 The Android Open Source Project
- * Copyright (c) 2011-2014 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2014,2017 The Linux Foundation. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,17 +20,17 @@
#include <fcntl.h>
#include <cutils/properties.h>
#include <sys/mman.h>
+#include <linux/msm_ion.h>
+#include <qdMetaData.h>
+#include <algorithm>
#include "gr.h"
#include "gpu.h"
#include "memalloc.h"
#include "alloc_controller.h"
-#include <qdMetaData.h>
using namespace gralloc;
-#define SZ_1M 0x100000
-
gpu_context_t::gpu_context_t(const private_module_t* module,
IAllocController* alloc_ctrl ) :
mAllocCtrl(alloc_ctrl)
@@ -54,6 +54,16 @@ int gpu_context_t::gralloc_alloc_buffer(unsigned int size, int usage,
{
int err = 0;
int flags = 0;
+ int alignedw = 0;
+ int alignedh = 0;
+
+ AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(width,
+ height,
+ format,
+ usage,
+ alignedw,
+ alignedh);
+
size = roundUpToPageSize(size);
alloc_data data;
data.offset = 0;
@@ -64,14 +74,16 @@ int gpu_context_t::gralloc_alloc_buffer(unsigned int size, int usage,
else
data.align = getpagesize();
- /* force 1MB alignment selectively for secure buffers, MDP5 onwards */
-#ifdef MDSS_TARGET
- if ((usage & GRALLOC_USAGE_PROTECTED) &&
- (usage & GRALLOC_USAGE_PRIVATE_MM_HEAP)) {
- data.align = ALIGN((int) data.align, SZ_1M);
+ if (usage & GRALLOC_USAGE_PROTECTED) {
+ if ((usage & GRALLOC_USAGE_PRIVATE_SECURE_DISPLAY) ||
+ (usage & GRALLOC_USAGE_HW_CAMERA_MASK)) {
+ /* The alignment here reflects qsee mmu V7L/V8L requirement */
+ data.align = SZ_2M;
+ } else {
+ data.align = SECURE_ALIGN;
+ }
size = ALIGN(size, data.align);
}
-#endif
data.size = size;
data.pHandle = (uintptr_t) pHandle;
@@ -86,7 +98,7 @@ int gpu_context_t::gralloc_alloc_buffer(unsigned int size, int usage,
eData.size = ROUND_UP_PAGESIZE(sizeof(MetaData_t));
eData.pHandle = data.pHandle;
eData.align = getpagesize();
- int eDataUsage = GRALLOC_USAGE_PRIVATE_SYSTEM_HEAP;
+ int eDataUsage = 0;
int eDataErr = mAllocCtrl->allocate(eData, eDataUsage);
ALOGE_IF(eDataErr, "gralloc failed for eDataErr=%s",
strerror(-eDataErr));
@@ -94,36 +106,11 @@ int gpu_context_t::gralloc_alloc_buffer(unsigned int size, int usage,
if (usage & GRALLOC_USAGE_PRIVATE_EXTERNAL_ONLY) {
flags |= private_handle_t::PRIV_FLAGS_EXTERNAL_ONLY;
}
+
if (usage & GRALLOC_USAGE_PRIVATE_INTERNAL_ONLY) {
flags |= private_handle_t::PRIV_FLAGS_INTERNAL_ONLY;
}
- ColorSpace_t colorSpace = ITU_R_601;
- flags |= private_handle_t::PRIV_FLAGS_ITU_R_601;
- if (bufferType == BUFFER_TYPE_VIDEO) {
- if (usage & GRALLOC_USAGE_HW_CAMERA_WRITE) {
-#ifndef MDSS_TARGET
- colorSpace = ITU_R_601_FR;
- flags |= private_handle_t::PRIV_FLAGS_ITU_R_601_FR;
-#else
- // Per the camera spec ITU 709 format should be set only for
- // video encoding.
- // It should be set to ITU 601 full range format for any other
- // camera buffer
- //
- if (usage & GRALLOC_USAGE_HW_CAMERA_MASK) {
- if (usage & GRALLOC_USAGE_HW_VIDEO_ENCODER) {
- flags |= private_handle_t::PRIV_FLAGS_ITU_R_709;
- colorSpace = ITU_R_709;
- } else {
- flags |= private_handle_t::PRIV_FLAGS_ITU_R_601_FR;
- colorSpace = ITU_R_601_FR;
- }
- }
-#endif
- }
- }
-
if (usage & GRALLOC_USAGE_HW_VIDEO_ENCODER ) {
flags |= private_handle_t::PRIV_FLAGS_VIDEO_ENCODER;
}
@@ -148,8 +135,8 @@ int gpu_context_t::gralloc_alloc_buffer(unsigned int size, int usage,
flags |= private_handle_t::PRIV_FLAGS_SECURE_DISPLAY;
}
- if(isMacroTileEnabled(format, usage)) {
- flags |= private_handle_t::PRIV_FLAGS_TILE_RENDERED;
+ if (isUBwcEnabled(format, usage)) {
+ flags |= private_handle_t::PRIV_FLAGS_UBWC_ALIGNED;
}
if(usage & (GRALLOC_USAGE_SW_READ_MASK | GRALLOC_USAGE_SW_WRITE_MASK)) {
@@ -163,6 +150,10 @@ int gpu_context_t::gralloc_alloc_buffer(unsigned int size, int usage,
flags |= private_handle_t::PRIV_FLAGS_NON_CPU_WRITER;
}
+ if(usage & GRALLOC_USAGE_HW_COMPOSER) {
+ flags |= private_handle_t::PRIV_FLAGS_DISP_CONSUMER;
+ }
+
if(false == data.uncached) {
flags |= private_handle_t::PRIV_FLAGS_CACHED;
}
@@ -170,19 +161,18 @@ int gpu_context_t::gralloc_alloc_buffer(unsigned int size, int usage,
flags |= data.allocType;
uint64_t eBaseAddr = (uint64_t)(eData.base) + eData.offset;
private_handle_t *hnd = new private_handle_t(data.fd, size, flags,
- bufferType, format, width, height, eData.fd, eData.offset,
- eBaseAddr);
+ bufferType, format, alignedw, alignedh,
+ eData.fd, eData.offset, eBaseAddr, width, height);
hnd->offset = data.offset;
hnd->base = (uint64_t)(data.base) + data.offset;
hnd->gpuaddr = 0;
+ ColorSpace_t colorSpace = ITU_R_601;
setMetaData(hnd, UPDATE_COLOR_SPACE, (void*) &colorSpace);
-
*pHandle = hnd;
}
ALOGE_IF(err, "gralloc failed err=%s", strerror(-err));
-
return err;
}
@@ -191,12 +181,9 @@ void gpu_context_t::getGrallocInformationFromFormat(int inputFormat,
{
*bufferType = BUFFER_TYPE_VIDEO;
- if (inputFormat <= HAL_PIXEL_FORMAT_BGRA_8888) {
+ if (isUncompressedRgbFormat(inputFormat) == TRUE) {
// RGB formats
*bufferType = BUFFER_TYPE_UI;
- } else if ((inputFormat == HAL_PIXEL_FORMAT_R_8) ||
- (inputFormat == HAL_PIXEL_FORMAT_RG_88)) {
- *bufferType = BUFFER_TYPE_UI;
}
}
@@ -205,10 +192,7 @@ int gpu_context_t::gralloc_alloc_framebuffer_locked(int usage,
{
private_module_t* m = reinterpret_cast<private_module_t*>(common.module);
- // we don't support framebuffer allocations with graphics heap flags
- if (usage & GRALLOC_HEAP_MASK) {
- return -EINVAL;
- }
+ // This allocation will only happen when gralloc is in fb mode
if (m->framebuffer == NULL) {
ALOGE("%s: Invalid framebuffer", __FUNCTION__);
@@ -287,22 +271,54 @@ int gpu_context_t::alloc_impl(int w, int h, int format, int usage,
//the usage bits, gralloc assigns a format.
if(format == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED ||
format == HAL_PIXEL_FORMAT_YCbCr_420_888) {
- if(usage & GRALLOC_USAGE_HW_VIDEO_ENCODER)
- grallocFormat = HAL_PIXEL_FORMAT_NV12_ENCODEABLE; //NV12
- else if((usage & GRALLOC_USAGE_HW_CAMERA_MASK)
+ if (usage & GRALLOC_USAGE_PRIVATE_ALLOC_UBWC)
+ grallocFormat = HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC;
+ else if(usage & GRALLOC_USAGE_HW_VIDEO_ENCODER) {
+ if(MDPCapabilityInfo::getInstance().isWBUBWCSupportedByMDP() &&
+ !IAllocController::getInstance()->isDisableUBWCForEncoder() &&
+ usage & GRALLOC_USAGE_HW_COMPOSER)
+ grallocFormat = HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC;
+ else
+ grallocFormat = HAL_PIXEL_FORMAT_NV12_ENCODEABLE; //NV12
+ } else if((usage & GRALLOC_USAGE_HW_CAMERA_MASK)
== GRALLOC_USAGE_HW_CAMERA_ZSL)
grallocFormat = HAL_PIXEL_FORMAT_NV21_ZSL; //NV21 ZSL
else if(usage & GRALLOC_USAGE_HW_CAMERA_READ)
grallocFormat = HAL_PIXEL_FORMAT_YCrCb_420_SP; //NV21
- else if(usage & GRALLOC_USAGE_HW_CAMERA_WRITE)
- grallocFormat = HAL_PIXEL_FORMAT_YCrCb_420_SP; //NV21
- else if(usage & GRALLOC_USAGE_HW_COMPOSER)
+ else if(usage & GRALLOC_USAGE_HW_CAMERA_WRITE) {
+ if (format == HAL_PIXEL_FORMAT_YCbCr_420_888) {
+ grallocFormat = HAL_PIXEL_FORMAT_NV21_ZSL; //NV21
+ } else {
+ grallocFormat = HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS; //NV12 preview
+ }
+ } else if(usage & GRALLOC_USAGE_HW_COMPOSER)
//XXX: If we still haven't set a format, default to RGBA8888
grallocFormat = HAL_PIXEL_FORMAT_RGBA_8888;
- //If no other usage flags are detected, default the
- //flexible YUV format to NV21.
- else if(format == HAL_PIXEL_FORMAT_YCbCr_420_888)
- grallocFormat = HAL_PIXEL_FORMAT_YCrCb_420_SP;
+ else if(format == HAL_PIXEL_FORMAT_YCbCr_420_888) {
+ //If no other usage flags are detected, default the
+ //flexible YUV format to NV21_ZSL
+ grallocFormat = HAL_PIXEL_FORMAT_NV21_ZSL;
+ }
+ }
+
+ bool useFbMem = false;
+ char property[PROPERTY_VALUE_MAX];
+ char isUBWC[PROPERTY_VALUE_MAX];
+ if (usage & GRALLOC_USAGE_HW_FB) {
+ if ((property_get("debug.gralloc.map_fb_memory", property, NULL) > 0) &&
+ (!strncmp(property, "1", PROPERTY_VALUE_MAX ) ||
+ (!strncasecmp(property,"true", PROPERTY_VALUE_MAX )))) {
+ useFbMem = true;
+ } else {
+ usage &= ~GRALLOC_USAGE_PRIVATE_ALLOC_UBWC;
+ if (property_get("debug.gralloc.enable_fb_ubwc", isUBWC, NULL) > 0){
+ if ((!strncmp(isUBWC, "1", PROPERTY_VALUE_MAX)) ||
+ (!strncasecmp(isUBWC, "true", PROPERTY_VALUE_MAX))) {
+ // Allocate UBWC aligned framebuffer
+ usage |= GRALLOC_USAGE_PRIVATE_ALLOC_UBWC;
+ }
+ }
+ }
}
getGrallocInformationFromFormat(grallocFormat, &bufferType);
@@ -314,8 +330,12 @@ int gpu_context_t::alloc_impl(int w, int h, int format, int usage,
size = (bufferSize >= size)? bufferSize : size;
int err = 0;
- err = gralloc_alloc_buffer(size, usage, pHandle, bufferType,
- grallocFormat, alignedw, alignedh);
+ if(useFbMem) {
+ err = gralloc_alloc_framebuffer(usage, pHandle);
+ } else {
+ err = gralloc_alloc_buffer(size, usage, pHandle, bufferType,
+ grallocFormat, w, h);
+ }
if (err < 0) {
return err;
@@ -348,6 +368,7 @@ int gpu_context_t::free_impl(private_handle_t const* hnd) {
if (err)
return err;
}
+
delete hnd;
return 0;
}
diff --git a/msm8909/libgralloc/gpu.h b/msm8909/libgralloc/gpu.h
index 82d49a1a..2248d30d 100644
--- a/msm8909/libgralloc/gpu.h
+++ b/msm8909/libgralloc/gpu.h
@@ -23,7 +23,7 @@
#include <stdlib.h>
#include <string.h>
-#include <log/log.h>
+#include <cutils/log.h>
#include "gralloc_priv.h"
#include "fb_priv.h"
diff --git a/msm8909/libgralloc/gr.h b/msm8909/libgralloc/gr.h
index 1f902a55..dad4a38a 100644
--- a/msm8909/libgralloc/gr.h
+++ b/msm8909/libgralloc/gr.h
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2008 The Android Open Source Project
- * Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011 - 2017, The Linux Foundation. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -24,9 +24,11 @@
#include <hardware/gralloc.h>
#include <pthread.h>
#include <errno.h>
+#include <unistd.h>
#include <cutils/native_handle.h>
#include <utils/Singleton.h>
+#include "adreno_utils.h"
/*****************************************************************************/
@@ -34,7 +36,7 @@ struct private_module_t;
struct private_handle_t;
inline unsigned int roundUpToPageSize(unsigned int x) {
- return (x + (PAGE_SIZE-1)) & ~(PAGE_SIZE-1);
+ return (x + (getpagesize()-1)) & ~(getpagesize()-1);
}
template <class Type>
@@ -52,15 +54,6 @@ unsigned int getBufferSizeAndDimensions(int width, int height, int format,
unsigned int getBufferSizeAndDimensions(int width, int height, int format,
int& alignedw, int &alignedh);
-
-// Attributes include aligned width, aligned height, tileEnabled and size of the buffer
-void getBufferAttributes(int width, int height, int format, int usage,
- int& alignedw, int &alignedh,
- int& tileEnabled, unsigned int &size);
-
-
-bool isMacroTileEnabled(int format, int usage);
-
int decideBufferHandlingMechanism(int format, const char *compositionUsed,
int hasBlitEngine, int *needConversion,
int *useBufferDirectly);
@@ -70,7 +63,17 @@ int decideBufferHandlingMechanism(int format, const char *compositionUsed,
int alloc_buffer(private_handle_t **pHnd, int w, int h, int format, int usage);
void free_buffer(private_handle_t *hnd);
int getYUVPlaneInfo(private_handle_t* pHnd, struct android_ycbcr* ycbcr);
+int getRgbDataAddress(private_handle_t* pHnd, void** rgb_data);
+// To query if UBWC is enabled, based on format and usage flags
+bool isUBwcEnabled(int format, int usage);
+
+// Function to check if the format is an RGB format
+bool isUncompressedRgbFormat(int format);
+
+// Returns number of planes, stride and offset of each plane for a given w,h,f
+int getBufferLayout(private_handle_t *hnd, uint32_t stride[4],
+ uint32_t offset[4], uint32_t *num_planes);
/*****************************************************************************/
class Locker {
@@ -106,23 +109,54 @@ class AdrenoMemInfo : public android::Singleton <AdrenoMemInfo>
~AdrenoMemInfo();
/*
+ * Function to compute aligned width and aligned height based on
+ * width, height, format and usage flags.
+ *
+ * @return aligned width, aligned height
+ */
+ void getAlignedWidthAndHeight(int width, int height, int format,
+ int usage, int& aligned_w, int& aligned_h);
+
+ /*
+ * Function to compute aligned width and aligned height based on
+ * private handle
+ *
+ * @return aligned width, aligned height
+ */
+ void getAlignedWidthAndHeight(const private_handle_t *hnd, int& aligned_w, int& aligned_h);
+
+ /*
* Function to compute the adreno aligned width and aligned height
* based on the width and format.
*
* @return aligned width, aligned height
*/
- void getAlignedWidthAndHeight(int width, int height, int format,
+ void getGpuAlignedWidthHeight(int width, int height, int format,
int tileEnabled, int& alignedw, int &alignedh);
/*
- * Function to return whether GPU support MacroTile feature
+ * Function to compute unaligned width and unaligned height based on
+ * private handle
*
- * @return >0 : supported
- * 0 : not supported
+ * @return unaligned width, unaligned height
+ */
+ void getUnalignedWidthAndHeight(const private_handle_t *hnd, int& unaligned_w,
+ int& unaligned_h);
+ /*
+ * Function to query whether GPU supports UBWC for given HAL format
+ * @return > 0 : supported
+ * 0 : not supported
*/
- int isMacroTilingSupportedByGPU();
+ int isUBWCSupportedByGPU(int format);
+
+ /*
+ * Function to get the corresponding Adreno format for given HAL format
+ */
+ ADRENOPIXELFORMAT getGpuPixelFormat(int hal_format);
private:
+ // Overriding flag to disable UBWC alloc for graphics stack
+ int gfx_ubwc_disable;
// Pointer to the padding library.
void *libadreno_utils;
@@ -141,8 +175,6 @@ class AdrenoMemInfo : public android::Singleton <AdrenoMemInfo>
int *aligned_w,
int *aligned_h);
- int (*LINK_adreno_isMacroTilingSupportedByGpu) (void);
-
void(*LINK_adreno_compute_compressedfmt_aligned_width_and_height)(
int width,
int height,
@@ -154,6 +186,33 @@ class AdrenoMemInfo : public android::Singleton <AdrenoMemInfo>
int *aligned_h,
int *bpp);
+ int (*LINK_adreno_isUBWCSupportedByGpu) (ADRENOPIXELFORMAT format);
+
unsigned int (*LINK_adreno_get_gpu_pixel_alignment) ();
};
+
+
+class MDPCapabilityInfo : public android::Singleton <MDPCapabilityInfo>
+{
+ int isUBwcSupported = 0;
+ int isWBUBWCSupported = 0;
+
+ public:
+ MDPCapabilityInfo();
+ /*
+ * Function to return whether MDP supports UBWC feature
+ *
+ * @return 1 : supported
+ * 0 : not supported
+ */
+ int isUBwcSupportedByMDP() { return isUBwcSupported; }
+ /*
+ * Function to return whether MDP WB block outputs UBWC format
+ *
+ * @return 1 : supported
+ * 0 : not supported
+ */
+ int isWBUBWCSupportedByMDP() { return isWBUBWCSupported; }
+};
+
#endif /* GR_H_ */
diff --git a/msm8909/libgralloc/gralloc.cpp b/msm8909/libgralloc/gralloc.cpp
index 79e2e9cc..237b8a80 100644
--- a/msm8909/libgralloc/gralloc.cpp
+++ b/msm8909/libgralloc/gralloc.cpp
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2008, The Android Open Source Project
- * Copyright (c) 2011-2012,2016 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/msm8909/libgralloc/gralloc_priv.h b/msm8909/libgralloc/gralloc_priv.h
deleted file mode 100644
index 4452b5af..00000000
--- a/msm8909/libgralloc/gralloc_priv.h
+++ /dev/null
@@ -1,299 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- * Copyright (c) 2011-2014, The Linux Foundation. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef GRALLOC_PRIV_H_
-#define GRALLOC_PRIV_H_
-
-#include <stdint.h>
-#include <limits.h>
-#include <sys/cdefs.h>
-#include <hardware/gralloc.h>
-#include <pthread.h>
-#include <errno.h>
-#include <unistd.h>
-
-#include <cutils/native_handle.h>
-
-#include <cutils/log.h>
-
-#define ROUND_UP_PAGESIZE(x) ( (((unsigned long)(x)) + PAGE_SIZE-1) & \
- (~(PAGE_SIZE-1)) )
-
-enum {
- /* gralloc usage bits indicating the type
- * of allocation that should be used */
-
- /* SYSTEM heap comes from kernel vmalloc,
- * can never be uncached, is not secured*/
- GRALLOC_USAGE_PRIVATE_SYSTEM_HEAP = GRALLOC_USAGE_PRIVATE_0,
- /* SF heap is used for application buffers, is not secured */
- GRALLOC_USAGE_PRIVATE_UI_CONTIG_HEAP = GRALLOC_USAGE_PRIVATE_1,
- /* IOMMU heap comes from manually allocated pages,
- * can be cached/uncached, is not secured */
- GRALLOC_USAGE_PRIVATE_IOMMU_HEAP = GRALLOC_USAGE_PRIVATE_2,
- /* MM heap is a carveout heap for video, can be secured*/
- GRALLOC_USAGE_PRIVATE_MM_HEAP = GRALLOC_USAGE_PRIVATE_3,
- /* ADSP heap is a carveout heap, is not secured*/
- GRALLOC_USAGE_PRIVATE_ADSP_HEAP = 0x01000000,
-
- /* Set this for allocating uncached memory (using O_DSYNC)
- * cannot be used with noncontiguous heaps */
- GRALLOC_USAGE_PRIVATE_UNCACHED = 0x02000000,
-
- /* Buffer content should be displayed on an primary display only */
- GRALLOC_USAGE_PRIVATE_INTERNAL_ONLY = 0x04000000,
-
- /* Buffer content should be displayed on an external display only */
- GRALLOC_USAGE_PRIVATE_EXTERNAL_ONLY = 0x08000000,
-
- /* This flag is set for WFD usecase */
- GRALLOC_USAGE_PRIVATE_WFD = 0x00200000,
-
- /* CAMERA heap is a carveout heap for camera, is not secured*/
- GRALLOC_USAGE_PRIVATE_CAMERA_HEAP = 0x00400000,
-
- /* This flag is used for SECURE display usecase */
- GRALLOC_USAGE_PRIVATE_SECURE_DISPLAY = 0x00800000,
-};
-
-enum {
- /* Gralloc perform enums
- */
- GRALLOC_MODULE_PERFORM_CREATE_HANDLE_FROM_BUFFER = 1,
- // This will be deprecated from latest graphics drivers. This is kept
- // for those backward compatibility i.e., newer Display HAL + older graphics
- // libraries
- GRALLOC_MODULE_PERFORM_GET_STRIDE,
- GRALLOC_MODULE_PERFORM_GET_CUSTOM_STRIDE_FROM_HANDLE,
- GRALLOC_MODULE_PERFORM_GET_CUSTOM_STRIDE_AND_HEIGHT_FROM_HANDLE,
- GRALLOC_MODULE_PERFORM_GET_ATTRIBUTES,
- GRALLOC_MODULE_PERFORM_GET_COLOR_SPACE_FROM_HANDLE,
- GRALLOC_MODULE_PERFORM_GET_YUV_PLANE_INFO,
-};
-
-#define GRALLOC_HEAP_MASK (GRALLOC_USAGE_PRIVATE_UI_CONTIG_HEAP |\
- GRALLOC_USAGE_PRIVATE_SYSTEM_HEAP |\
- GRALLOC_USAGE_PRIVATE_IOMMU_HEAP |\
- GRALLOC_USAGE_PRIVATE_MM_HEAP |\
- GRALLOC_USAGE_PRIVATE_ADSP_HEAP)
-
-#define INTERLACE_MASK 0x80
-#define S3D_FORMAT_MASK 0xFF000
-/*****************************************************************************/
-enum {
- /* OEM specific HAL formats */
- HAL_PIXEL_FORMAT_RGBA_5551 = 6,
- HAL_PIXEL_FORMAT_RGBA_4444 = 7,
- HAL_PIXEL_FORMAT_NV12_ENCODEABLE = 0x102,
- HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS = 0x7FA30C04,
- HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED = 0x7FA30C03,
- HAL_PIXEL_FORMAT_YCbCr_420_SP = 0x109,
- HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO = 0x7FA30C01,
- HAL_PIXEL_FORMAT_YCrCb_422_SP = 0x10B,
- HAL_PIXEL_FORMAT_R_8 = 0x10D,
- HAL_PIXEL_FORMAT_RG_88 = 0x10E,
- HAL_PIXEL_FORMAT_YCbCr_444_SP = 0x10F,
- HAL_PIXEL_FORMAT_YCrCb_444_SP = 0x110,
- HAL_PIXEL_FORMAT_YCrCb_422_I = 0x111,
- HAL_PIXEL_FORMAT_BGRX_8888 = 0x112,
- HAL_PIXEL_FORMAT_NV21_ZSL = 0x113,
- HAL_PIXEL_FORMAT_INTERLACE = 0x180,
- //v4l2_fourcc('Y', 'U', 'Y', 'L'). 24 bpp YUYV 4:2:2 10 bit per component
- HAL_PIXEL_FORMAT_YCbCr_422_I_10BIT = 0x4C595559,
- //v4l2_fourcc('Y', 'B', 'W', 'C'). 10 bit per component. This compressed
- //format reduces the memory access bandwidth
- HAL_PIXEL_FORMAT_YCbCr_422_I_10BIT_COMPRESSED = 0x43574259,
-
- //Khronos ASTC formats
- HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_4x4_KHR = 0x93B0,
- HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_5x4_KHR = 0x93B1,
- HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_5x5_KHR = 0x93B2,
- HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_6x5_KHR = 0x93B3,
- HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_6x6_KHR = 0x93B4,
- HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_8x5_KHR = 0x93B5,
- HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_8x6_KHR = 0x93B6,
- HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_8x8_KHR = 0x93B7,
- HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_10x5_KHR = 0x93B8,
- HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_10x6_KHR = 0x93B9,
- HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_10x8_KHR = 0x93BA,
- HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_10x10_KHR = 0x93BB,
- HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_12x10_KHR = 0x93BC,
- HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_12x12_KHR = 0x93BD,
- HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR = 0x93D0,
- HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR = 0x93D1,
- HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR = 0x93D2,
- HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR = 0x93D3,
- HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR = 0x93D4,
- HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR = 0x93D5,
- HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR = 0x93D6,
- HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR = 0x93D7,
- HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR = 0x93D8,
- HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR = 0x93D9,
- HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR = 0x93DA,
- HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR = 0x93DB,
- HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR = 0x93DC,
- HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR = 0x93DD,
-};
-
-/* possible formats for 3D content*/
-enum {
- HAL_NO_3D = 0x0000,
- HAL_3D_IN_SIDE_BY_SIDE_L_R = 0x10000,
- HAL_3D_IN_TOP_BOTTOM = 0x20000,
- HAL_3D_IN_INTERLEAVE = 0x40000,
- HAL_3D_IN_SIDE_BY_SIDE_R_L = 0x80000,
- HAL_3D_OUT_SIDE_BY_SIDE = 0x1000,
- HAL_3D_OUT_TOP_BOTTOM = 0x2000,
- HAL_3D_OUT_INTERLEAVE = 0x4000,
- HAL_3D_OUT_MONOSCOPIC = 0x8000
-};
-
-enum {
- BUFFER_TYPE_UI = 0,
- BUFFER_TYPE_VIDEO
-};
-
-/*****************************************************************************/
-
-#ifdef __cplusplus
-struct private_handle_t : public native_handle {
-#else
- struct private_handle_t {
- native_handle_t nativeHandle;
-#endif
- enum {
- PRIV_FLAGS_FRAMEBUFFER = 0x00000001,
- PRIV_FLAGS_USES_PMEM = 0x00000002,
- PRIV_FLAGS_USES_PMEM_ADSP = 0x00000004,
- PRIV_FLAGS_USES_ION = 0x00000008,
- PRIV_FLAGS_USES_ASHMEM = 0x00000010,
- PRIV_FLAGS_NEEDS_FLUSH = 0x00000020,
- PRIV_FLAGS_INTERNAL_ONLY = 0x00000040,
- PRIV_FLAGS_NON_CPU_WRITER = 0x00000080,
- PRIV_FLAGS_NONCONTIGUOUS_MEM = 0x00000100,
- PRIV_FLAGS_CACHED = 0x00000200,
- PRIV_FLAGS_SECURE_BUFFER = 0x00000400,
- // For explicit synchronization
- PRIV_FLAGS_UNSYNCHRONIZED = 0x00000800,
- // Not mapped in userspace
- PRIV_FLAGS_NOT_MAPPED = 0x00001000,
- // Display on external only
- PRIV_FLAGS_EXTERNAL_ONLY = 0x00002000,
- PRIV_FLAGS_VIDEO_ENCODER = 0x00010000,
- PRIV_FLAGS_CAMERA_WRITE = 0x00020000,
- PRIV_FLAGS_CAMERA_READ = 0x00040000,
- PRIV_FLAGS_HW_COMPOSER = 0x00080000,
- PRIV_FLAGS_HW_TEXTURE = 0x00100000,
- PRIV_FLAGS_ITU_R_601 = 0x00200000,
- PRIV_FLAGS_ITU_R_601_FR = 0x00400000,
- PRIV_FLAGS_ITU_R_709 = 0x00800000,
- PRIV_FLAGS_SECURE_DISPLAY = 0x01000000,
- // Buffer is rendered in Tile Format
- PRIV_FLAGS_TILE_RENDERED = 0x02000000,
- // Buffer rendered using CPU/SW renderer
- PRIV_FLAGS_CPU_RENDERED = 0x04000000
- };
-
- // file-descriptors
- int fd;
- int fd_metadata; // fd for the meta-data
- // ints
- int magic;
- int flags;
- unsigned int size;
- unsigned int offset;
- int bufferType;
- uint64_t base __attribute__((aligned(8)));
- unsigned int offset_metadata;
- // The gpu address mapped into the mmu.
- uint64_t gpuaddr __attribute__((aligned(8)));
- int format;
- int width;
- int height;
- uint64_t base_metadata __attribute__((aligned(8)));
-
-#ifdef __cplusplus
- static const int sNumFds = 2;
- static inline int sNumInts() {
- return ((sizeof(private_handle_t) - sizeof(native_handle_t)) /
- sizeof(int)) - sNumFds;
- }
- static const int sMagic = 'gmsm';
-
- private_handle_t(int fd, unsigned int size, int flags, int bufferType,
- int format, int width, int height, int eFd = -1,
- unsigned int eOffset = 0, uint64_t eBase = 0) :
- fd(fd), fd_metadata(eFd), magic(sMagic),
- flags(flags), size(size), offset(0), bufferType(bufferType),
- base(0), offset_metadata(eOffset), gpuaddr(0),
- format(format), width(width), height(height),
- base_metadata(eBase)
- {
- version = (int) sizeof(native_handle);
- numInts = sNumInts();
- numFds = sNumFds;
- }
- ~private_handle_t() {
- base_metadata = 0;
- magic = 0;
- fd_metadata = 0;
- }
-
- bool usesPhysicallyContiguousMemory() {
- return (flags & PRIV_FLAGS_USES_PMEM) != 0;
- }
-
- static int validate(const native_handle* h) {
- const private_handle_t* hnd = (const private_handle_t*)h;
- if (!h || h->version != sizeof(native_handle) ||
- h->numInts != sNumInts() || h->numFds != sNumFds ||
- hnd->magic != sMagic)
- {
- ALOGE("Invalid gralloc handle (at %p): "
- "ver(%d/%zu) ints(%d/%d) fds(%d/%d)"
- "magic(%c%c%c%c/%c%c%c%c)",
- h,
- h ? h->version : -1, sizeof(native_handle),
- h ? h->numInts : -1, sNumInts(),
- h ? h->numFds : -1, sNumFds,
- hnd ? (((hnd->magic >> 24) & 0xFF)?
- ((hnd->magic >> 24) & 0xFF) : '-') : '?',
- hnd ? (((hnd->magic >> 16) & 0xFF)?
- ((hnd->magic >> 16) & 0xFF) : '-') : '?',
- hnd ? (((hnd->magic >> 8) & 0xFF)?
- ((hnd->magic >> 8) & 0xFF) : '-') : '?',
- hnd ? (((hnd->magic >> 0) & 0xFF)?
- ((hnd->magic >> 0) & 0xFF) : '-') : '?',
- (sMagic >> 24) & 0xFF,
- (sMagic >> 16) & 0xFF,
- (sMagic >> 8) & 0xFF,
- (sMagic >> 0) & 0xFF);
- return -EINVAL;
- }
- return 0;
- }
-
- static private_handle_t* dynamicCast(const native_handle* in) {
- if (validate(in) == 0) {
- return (private_handle_t*) in;
- }
- return NULL;
- }
-#endif
- };
-
-#endif /* GRALLOC_PRIV_H_ */
diff --git a/msm8909/libgralloc/ionalloc.cpp b/msm8909/libgralloc/ionalloc.cpp
index 5329e880..329e30f7 100644
--- a/msm8909/libgralloc/ionalloc.cpp
+++ b/msm8909/libgralloc/ionalloc.cpp
@@ -35,8 +35,8 @@
#include <fcntl.h>
#include <cutils/log.h>
#include <errno.h>
-#include <string.h>
#include <utils/Trace.h>
+#include <cutils/trace.h>
#include "gralloc_priv.h"
#include "ionalloc.h"
@@ -77,13 +77,9 @@ int IonAlloc::alloc_buffer(alloc_data& data)
ionAllocData.len = data.size;
ionAllocData.align = data.align;
- ionAllocData.heap_id_mask = data.flags & ~ION_SECURE;
- ionAllocData.flags = data.uncached ? 0 : ION_FLAG_CACHED;
- // ToDo: replace usage of alloc data structure with
- // ionallocdata structure.
- if (data.flags & ION_SECURE)
- ionAllocData.flags |= ION_SECURE;
-
+ ionAllocData.heap_id_mask = data.heapId;
+ ionAllocData.flags = data.flags;
+ ionAllocData.flags |= data.uncached ? 0 : ION_FLAG_CACHED;
err = open_device();
if (err)
return err;
diff --git a/msm8909/libgralloc/mapper.cpp b/msm8909/libgralloc/mapper.cpp
index 99d309cd..e9830e2d 100644
--- a/msm8909/libgralloc/mapper.cpp
+++ b/msm8909/libgralloc/mapper.cpp
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2008 The Android Open Source Project
- * Copyright (c) 2011-2014,2016 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2017, The Linux Foundation. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -55,6 +55,27 @@ static IMemAlloc* getAllocator(int flags)
return memalloc;
}
+static int gralloc_map_metadata(buffer_handle_t handle) {
+ private_handle_t* hnd = (private_handle_t*)handle;
+ hnd->base_metadata = 0;
+ IMemAlloc* memalloc = getAllocator(hnd->flags) ;
+ void *mappedAddress = MAP_FAILED;
+ unsigned int size = 0;
+ if (!(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)) {
+ mappedAddress = MAP_FAILED;
+ size = ROUND_UP_PAGESIZE(sizeof(MetaData_t));
+ int ret = memalloc->map_buffer(&mappedAddress, size,
+ hnd->offset_metadata, hnd->fd_metadata);
+ if(ret || mappedAddress == MAP_FAILED) {
+ ALOGE("Could not mmap metadata for handle %p, fd=%d (%s)",
+ hnd, hnd->fd_metadata, strerror(errno));
+ return -errno;
+ }
+ hnd->base_metadata = uint64_t(mappedAddress);
+ }
+ return 0;
+}
+
static int gralloc_map(gralloc_module_t const* module,
buffer_handle_t handle)
{
@@ -66,8 +87,10 @@ static int gralloc_map(gralloc_module_t const* module,
unsigned int size = 0;
int err = 0;
IMemAlloc* memalloc = getAllocator(hnd->flags) ;
- void *mappedAddress;
- // Dont map FRAMEBUFFER and SECURE_BUFFERS
+ void *mappedAddress = MAP_FAILED;
+ hnd->base = 0;
+
+ // Dont map framebuffer and secure buffers
if (!(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) &&
!(hnd->flags & private_handle_t::PRIV_FLAGS_SECURE_BUFFER)) {
size = hnd->size;
@@ -76,60 +99,62 @@ static int gralloc_map(gralloc_module_t const* module,
if(err || mappedAddress == MAP_FAILED) {
ALOGE("Could not mmap handle %p, fd=%d (%s)",
handle, hnd->fd, strerror(errno));
- hnd->base = 0;
return -errno;
}
- hnd->base = uint64_t(mappedAddress) + hnd->offset;
+ hnd->base = uint64_t(mappedAddress);
+ } else {
+ // Cannot map secure buffers or framebuffers, but still need to map
+ // metadata for secure buffers.
+ // If mapping a secure buffers fails, the framework needs to get
+ // an error code.
+ err = -EACCES;
}
- //Allow mapping of metadata for all buffers and SECURE_BUFFER
- if (!(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)) {
- mappedAddress = MAP_FAILED;
- size = ROUND_UP_PAGESIZE(sizeof(MetaData_t));
- err = memalloc->map_buffer(&mappedAddress, size,
- hnd->offset_metadata, hnd->fd_metadata);
- if(err || mappedAddress == MAP_FAILED) {
- ALOGE("Could not mmap handle %p, fd=%d (%s)",
- handle, hnd->fd_metadata, strerror(errno));
- hnd->base_metadata = 0;
- return -errno;
- }
- hnd->base_metadata = uint64_t(mappedAddress) + hnd->offset_metadata;
+ //Allow mapping of metadata for all buffers including secure ones, but not
+ //of framebuffer
+ int metadata_err = gralloc_map_metadata(handle);
+ if (!err) {
+ err = metadata_err;
}
- return 0;
+ return err;
}
static int gralloc_unmap(gralloc_module_t const* module,
buffer_handle_t handle)
{
ATRACE_CALL();
+ int err = -EINVAL;
if(!module)
- return -EINVAL;
+ return err;
private_handle_t* hnd = (private_handle_t*)handle;
- if (!(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)) {
- int err = -EINVAL;
- void* base = (void*)hnd->base;
- unsigned int size = hnd->size;
- IMemAlloc* memalloc = getAllocator(hnd->flags) ;
- if(memalloc != NULL) {
- err = memalloc->unmap_buffer(base, size, hnd->offset);
- if (err) {
- ALOGE("Could not unmap memory at address %p", (void*)base);
- }
- base = (void*)hnd->base_metadata;
- size = ROUND_UP_PAGESIZE(sizeof(MetaData_t));
- err = memalloc->unmap_buffer(base, size, hnd->offset_metadata);
- if (err) {
- ALOGE("Could not unmap memory at address %p", (void*)base);
- }
+ IMemAlloc* memalloc = getAllocator(hnd->flags) ;
+ if(!memalloc)
+ return err;
+
+ if(hnd->base) {
+ err = memalloc->unmap_buffer((void*)hnd->base, hnd->size, hnd->offset);
+ if (err) {
+ ALOGE("Could not unmap memory at address %p, %s", (void*) hnd->base,
+ strerror(errno));
+ return -errno;
}
+ hnd->base = 0;
}
- /* need to initialize the pointer to NULL otherwise unmapping for that
- * buffer happens twice which leads to crash */
- hnd->base = 0;
- hnd->base_metadata = 0;
+
+ if(hnd->base_metadata) {
+ unsigned int size = ROUND_UP_PAGESIZE(sizeof(MetaData_t));
+ err = memalloc->unmap_buffer((void*)hnd->base_metadata,
+ size, hnd->offset_metadata);
+ if (err) {
+ ALOGE("Could not unmap memory at address %p, %s",
+ (void*) hnd->base_metadata, strerror(errno));
+ return -errno;
+ }
+ hnd->base_metadata = 0;
+ }
+
return 0;
}
@@ -146,25 +171,11 @@ int gralloc_register_buffer(gralloc_module_t const* module,
if (!module || private_handle_t::validate(handle) < 0)
return -EINVAL;
- // In this implementation, we don't need to do anything here
-
- /* NOTE: we need to initialize the buffer as not mapped/not locked
- * because it shouldn't when this function is called the first time
- * in a new process. Ideally these flags shouldn't be part of the
- * handle, but instead maintained in the kernel or at least
- * out-of-line
- */
-
- private_handle_t* hnd = (private_handle_t*)handle;
- hnd->base = 0;
- hnd->base_metadata = 0;
- int err = gralloc_map(module, handle);
- if (err) {
- ALOGE("%s: gralloc_map failed", __FUNCTION__);
- return err;
- }
-
- return 0;
+ int err = gralloc_map(module, handle);
+ /* Do not fail register_buffer for secure buffers*/
+ if (err == -EACCES)
+ err = 0;
+ return err;
}
int gralloc_unregister_buffer(gralloc_module_t const* module,
@@ -178,16 +189,9 @@ int gralloc_unregister_buffer(gralloc_module_t const* module,
* If the buffer has been mapped during a lock operation, it's time
* to un-map it. It's an error to be here with a locked buffer.
* NOTE: the framebuffer is handled differently and is never unmapped.
+ * Also base and base_metadata are reset.
*/
-
- private_handle_t* hnd = (private_handle_t*)handle;
-
- if (hnd->base != 0) {
- gralloc_unmap(module, handle);
- }
- hnd->base = 0;
- hnd->base_metadata = 0;
- return 0;
+ return gralloc_unmap(module, handle);
}
int terminateBuffer(gralloc_module_t const* module,
@@ -200,23 +204,10 @@ int terminateBuffer(gralloc_module_t const* module,
/*
* If the buffer has been mapped during a lock operation, it's time
* to un-map it. It's an error to be here with a locked buffer.
+ * NOTE: the framebuffer is handled differently and is never unmapped.
+ * Also base and base_metadata are reset.
*/
-
- if (hnd->base != 0) {
- // this buffer was mapped, unmap it now
- if (hnd->flags & (private_handle_t::PRIV_FLAGS_USES_PMEM |
- private_handle_t::PRIV_FLAGS_USES_PMEM_ADSP |
- private_handle_t::PRIV_FLAGS_USES_ASHMEM |
- private_handle_t::PRIV_FLAGS_USES_ION)) {
- gralloc_unmap(module, hnd);
- } else {
- ALOGE("terminateBuffer: unmapping a non pmem/ashmem buffer flags = 0x%x",
- hnd->flags);
- gralloc_unmap(module, hnd);
- }
- }
-
- return 0;
+ return gralloc_unmap(module, hnd);
}
static int gralloc_map_and_invalidate (gralloc_module_t const* module,
@@ -327,6 +318,7 @@ int gralloc_perform(struct gralloc_module_t const* module,
int width = va_arg(args, int);
int height = va_arg(args, int);
int format = va_arg(args, int);
+ int alignedw = 0, alignedh = 0;
native_handle_t** handle = va_arg(args, native_handle_t**);
private_handle_t* hnd = (private_handle_t*)native_handle_create(
@@ -339,8 +331,12 @@ int gralloc_perform(struct gralloc_module_t const* module,
hnd->offset = offset;
hnd->base = uint64_t(base) + offset;
hnd->gpuaddr = 0;
- hnd->width = width;
- hnd->height = height;
+ AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(width,
+ height, format, 0, alignedw, alignedh);
+ hnd->width = alignedw;
+ hnd->height = alignedh;
+ hnd->unaligned_width = width;
+ hnd->unaligned_height = height;
hnd->format = format;
*handle = (native_handle_t *)hnd;
res = 0;
@@ -355,45 +351,40 @@ int gralloc_perform(struct gralloc_module_t const* module,
int *stride = va_arg(args, int *);
int alignedw = 0, alignedh = 0;
AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(width,
- 0, format, false, alignedw, alignedh);
+ 0, format, 0, alignedw, alignedh);
*stride = alignedw;
res = 0;
} break;
case GRALLOC_MODULE_PERFORM_GET_CUSTOM_STRIDE_FROM_HANDLE:
{
- private_handle_t* hnd = va_arg(args, private_handle_t*);
+ const private_handle_t* hnd = va_arg(args, private_handle_t*);
int *stride = va_arg(args, int *);
if (private_handle_t::validate(hnd)) {
- va_end(args);
return res;
}
- MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
- if(metadata && metadata->operation & UPDATE_BUFFER_GEOMETRY) {
- *stride = metadata->bufferDim.sliceWidth;
- } else {
- *stride = hnd->width;
- }
+
+ int alignedw = 0, alignedh = 0;
+ AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(hnd, alignedw, alignedh);
+ *stride = alignedw;
+
res = 0;
} break;
case GRALLOC_MODULE_PERFORM_GET_CUSTOM_STRIDE_AND_HEIGHT_FROM_HANDLE:
{
- private_handle_t* hnd = va_arg(args, private_handle_t*);
+ const private_handle_t* hnd = va_arg(args, private_handle_t*);
int *stride = va_arg(args, int *);
int *height = va_arg(args, int *);
if (private_handle_t::validate(hnd)) {
- va_end(args);
return res;
}
- MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
- if(metadata && metadata->operation & UPDATE_BUFFER_GEOMETRY) {
- *stride = metadata->bufferDim.sliceWidth;
- *height = metadata->bufferDim.sliceHeight;
- } else {
- *stride = hnd->width;
- *height = hnd->height;
- }
+
+ int alignedw = 0, alignedh = 0;
+ AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(hnd, alignedw, alignedh);
+ *stride = alignedw;
+ *height = alignedh;
+
res = 0;
} break;
@@ -406,10 +397,9 @@ int gralloc_perform(struct gralloc_module_t const* module,
int *alignedWidth = va_arg(args, int *);
int *alignedHeight = va_arg(args, int *);
int *tileEnabled = va_arg(args,int *);
- *tileEnabled = isMacroTileEnabled(format, usage);
+ *tileEnabled = isUBwcEnabled(format, usage);
AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(width,
- height, format, *tileEnabled, *alignedWidth,
- *alignedHeight);
+ height, format, usage, *alignedWidth, *alignedHeight);
res = 0;
} break;
@@ -418,15 +408,38 @@ int gralloc_perform(struct gralloc_module_t const* module,
private_handle_t* hnd = va_arg(args, private_handle_t*);
int *color_space = va_arg(args, int *);
if (private_handle_t::validate(hnd)) {
- va_end(args);
return res;
}
MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
- if(metadata && metadata->operation & UPDATE_COLOR_SPACE) {
+ if (!metadata) {
+ break;
+#ifdef USE_COLOR_METADATA
+ } else if (metadata->operation & COLOR_METADATA) {
+ ColorMetaData *colorMetadata = &metadata->color;
+ res = 0;
+ switch (colorMetadata->colorPrimaries) {
+ case ColorPrimaries_BT709_5:
+ *color_space = HAL_CSC_ITU_R_709;
+ break;
+ case ColorPrimaries_BT601_6_525:
+ *color_space = ((colorMetadata->range) ?
+ HAL_CSC_ITU_R_601_FR : HAL_CSC_ITU_R_601);
+ break;
+ case ColorPrimaries_BT2020:
+ *color_space = (colorMetadata->range) ?
+ HAL_CSC_ITU_R_2020_FR : HAL_CSC_ITU_R_2020;
+ break;
+ default:
+ res = -EINVAL;
+ break;
+ }
+#endif
+ } else if(metadata->operation & UPDATE_COLOR_SPACE) {
*color_space = metadata->colorSpace;
res = 0;
}
} break;
+
case GRALLOC_MODULE_PERFORM_GET_YUV_PLANE_INFO:
{
private_handle_t* hnd = va_arg(args, private_handle_t*);
@@ -436,6 +449,72 @@ int gralloc_perform(struct gralloc_module_t const* module,
}
} break;
+ case GRALLOC_MODULE_PERFORM_GET_MAP_SECURE_BUFFER_INFO:
+ {
+ private_handle_t* hnd = va_arg(args, private_handle_t*);
+ int *map_secure_buffer = va_arg(args, int *);
+ if (private_handle_t::validate(hnd)) {
+ return res;
+ }
+ MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
+ if(metadata && metadata->operation & MAP_SECURE_BUFFER) {
+ *map_secure_buffer = metadata->mapSecureBuffer;
+ res = 0;
+ } else {
+ *map_secure_buffer = 0;
+ }
+ } break;
+
+ case GRALLOC_MODULE_PERFORM_GET_UBWC_FLAG:
+ {
+ private_handle_t* hnd = va_arg(args, private_handle_t*);
+ int *flag = va_arg(args, int *);
+ if (private_handle_t::validate(hnd)) {
+ return res;
+ }
+ *flag = hnd->flags & private_handle_t::PRIV_FLAGS_UBWC_ALIGNED;
+ MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
+ if (metadata && (metadata->operation & LINEAR_FORMAT)) {
+ *flag = 0;
+ }
+ res = 0;
+ } break;
+
+ case GRALLOC_MODULE_PERFORM_GET_RGB_DATA_ADDRESS:
+ {
+ private_handle_t* hnd = va_arg(args, private_handle_t*);
+ void** rgb_data = va_arg(args, void**);
+ if (!private_handle_t::validate(hnd)) {
+ res = getRgbDataAddress(hnd, rgb_data);
+ }
+ } break;
+
+ case GRALLOC_MODULE_PERFORM_GET_IGC:
+ {
+ private_handle_t* hnd = va_arg(args, private_handle_t*);
+ uint32_t *igc = va_arg(args, uint32_t *);
+ if (!private_handle_t::validate(hnd) && igc) {
+ MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
+ if (metadata && (metadata->operation & SET_IGC)) {
+ *igc = metadata->igc;
+ res = 0;
+ }
+ }
+ } break;
+
+ case GRALLOC_MODULE_PERFORM_SET_IGC:
+ res = 0;
+ break;
+
+ case GRALLOC_MODULE_PERFORM_SET_SINGLE_BUFFER_MODE:
+ {
+ private_handle_t* hnd = va_arg(args, private_handle_t*);
+ uint32_t *enable = va_arg(args, uint32_t*);
+ if (!private_handle_t::validate(hnd)) {
+ setMetaData(hnd, SET_SINGLE_BUFFER_MODE, enable);
+ res = 0;
+ }
+ } break;
default:
break;
}
diff --git a/msm8909/libgralloc/memalloc.h b/msm8909/libgralloc/memalloc.h
index 2bc1ddf8..598d983e 100644
--- a/msm8909/libgralloc/memalloc.h
+++ b/msm8909/libgralloc/memalloc.h
@@ -49,6 +49,7 @@ struct alloc_data {
uintptr_t pHandle;
bool uncached;
unsigned int flags;
+ unsigned int heapId;
int allocType;
};
diff --git a/msm8909/libhdmi/Android.mk b/msm8909/libhdmi/Android.mk
deleted file mode 100644
index b75bf40b..00000000
--- a/msm8909/libhdmi/Android.mk
+++ /dev/null
@@ -1,18 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-include $(LOCAL_PATH)/../common.mk
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := libhdmi
-LOCAL_MODULE_TAGS := optional
-LOCAL_C_INCLUDES := $(common_includes) $(kernel_includes)
-LOCAL_SHARED_LIBRARIES := $(common_libs) liboverlay libqdutils
-LOCAL_CFLAGS := $(common_flags) -DLOG_TAG=\"qdhdmi\" -Wno-float-conversion
-LOCAL_CLANG := true
-LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps)
-
-ifeq ($(TARGET_SUPPORTS_WEARABLES),true)
-LOCAL_SRC_FILES := hdmi_stub.cpp
-else
-LOCAL_SRC_FILES := hdmi.cpp
-endif
-include $(BUILD_SHARED_LIBRARY)
diff --git a/msm8909/libhdmi/hdmi.cpp b/msm8909/libhdmi/hdmi.cpp
deleted file mode 100644
index c20efbff..00000000
--- a/msm8909/libhdmi/hdmi.cpp
+++ /dev/null
@@ -1,699 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- * Copyright (C) 2012-2014, 2016, The Linux Foundation. All rights reserved.
- *
- * Not a Contribution, Apache license notifications and license are
- * retained for attribution purposes only.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define DEBUG 0
-#include <fcntl.h>
-#include <linux/msm_mdp.h>
-#include <video/msm_hdmi_modes.h>
-#include <linux/fb.h>
-#include <sys/ioctl.h>
-#include <cutils/properties.h>
-#include "hwc_utils.h"
-#include "hdmi.h"
-#include "overlayUtils.h"
-#include "overlay.h"
-#include "qd_utils.h"
-
-using namespace android;
-using namespace qdutils;
-
-namespace qhwc {
-#define UNKNOWN_STRING "unknown"
-#define SPD_NAME_LENGTH 16
-
-/* The array gEDIDData contains a list of modes currently
- * supported by HDMI and display, and modes that are not
- * supported i.e. interlaced modes.
-
- * In order to add support for a new mode, the mode must be
- * appended to the end of the array.
- *
- * Each new entry must contain the following:
- * -Mode: a video format defined in msm_hdmi_modes.h
- * -Width: x resolution for the mode
- * -Height: y resolution for the mode
- * -FPS: the frame rate for the mode
- * -Mode Order: the priority for the new mode that is used when determining
- * the best mode when the HDMI display is connected.
- */
-EDIDData gEDIDData [] = {
- EDIDData(HDMI_VFRMT_1440x480i60_4_3, 1440, 480, 60, 1),
- EDIDData(HDMI_VFRMT_1440x480i60_16_9, 1440, 480, 60, 2),
- EDIDData(HDMI_VFRMT_1440x576i50_4_3, 1440, 576, 50, 3),
- EDIDData(HDMI_VFRMT_1440x576i50_16_9, 1440, 576, 50, 4),
- EDIDData(HDMI_VFRMT_1920x1080i60_16_9, 1920, 1080, 60, 5),
- EDIDData(HDMI_VFRMT_640x480p60_4_3, 640, 480, 60, 6),
- EDIDData(HDMI_VFRMT_720x480p60_4_3, 720, 480, 60, 7),
- EDIDData(HDMI_VFRMT_720x480p60_16_9, 720, 480, 60, 8),
- EDIDData(HDMI_VFRMT_720x576p50_4_3, 720, 576, 50, 9),
- EDIDData(HDMI_VFRMT_720x576p50_16_9, 720, 576, 50, 10),
- EDIDData(HDMI_VFRMT_800x600p60_4_3, 800, 600, 60, 11),
- EDIDData(HDMI_VFRMT_848x480p60_16_9, 848, 480, 60, 12),
- EDIDData(HDMI_VFRMT_1024x768p60_4_3, 1024, 768, 60, 13),
- EDIDData(HDMI_VFRMT_1280x1024p60_5_4, 1280, 1024, 60, 14),
- EDIDData(HDMI_VFRMT_1280x720p50_16_9, 1280, 720, 50, 15),
- EDIDData(HDMI_VFRMT_1280x720p60_16_9, 1280, 720, 60, 16),
- EDIDData(HDMI_VFRMT_1280x800p60_16_10, 1280, 800, 60, 17),
- EDIDData(HDMI_VFRMT_1280x960p60_4_3, 1280, 960, 60, 18),
- EDIDData(HDMI_VFRMT_1360x768p60_16_9, 1360, 768, 60, 19),
- EDIDData(HDMI_VFRMT_1366x768p60_16_10, 1366, 768, 60, 20),
- EDIDData(HDMI_VFRMT_1440x900p60_16_10, 1440, 900, 60, 21),
- EDIDData(HDMI_VFRMT_1400x1050p60_4_3, 1400, 1050, 60, 22),
- EDIDData(HDMI_VFRMT_1680x1050p60_16_10, 1680, 1050, 60, 23),
- EDIDData(HDMI_VFRMT_1600x1200p60_4_3, 1600, 1200, 60, 24),
- EDIDData(HDMI_VFRMT_1920x1080p24_16_9, 1920, 1080, 24, 25),
- EDIDData(HDMI_VFRMT_1920x1080p25_16_9, 1920, 1080, 25, 26),
- EDIDData(HDMI_VFRMT_1920x1080p30_16_9, 1920, 1080, 30, 27),
- EDIDData(HDMI_VFRMT_1920x1080p50_16_9, 1920, 1080, 50, 28),
- EDIDData(HDMI_VFRMT_1920x1080p60_16_9, 1920, 1080, 60, 29),
- EDIDData(HDMI_VFRMT_1920x1200p60_16_10, 1920, 1200, 60, 30),
- EDIDData(HDMI_VFRMT_2560x1600p60_16_9, 2560, 1600, 60, 31),
- EDIDData(HDMI_VFRMT_3840x2160p24_16_9, 3840, 2160, 24, 32),
- EDIDData(HDMI_VFRMT_3840x2160p25_16_9, 3840, 2160, 25, 33),
- EDIDData(HDMI_VFRMT_3840x2160p30_16_9, 3840, 2160, 30, 34),
- EDIDData(HDMI_EVFRMT_4096x2160p24_16_9, 4096, 2160, 24, 35),
-};
-
-// Number of modes in gEDIDData
-const int gEDIDCount = (sizeof(gEDIDData)/sizeof(gEDIDData)[0]);
-
-int HDMIDisplay::configure() {
- if(!openFrameBuffer()) {
- ALOGE("%s: Failed to open FB: %d", __FUNCTION__, mFbNum);
- return -1;
- }
- readCEUnderscanInfo();
- readResolution();
- // TODO: Move this to activate
- /* Used for changing the resolution
- * getUserMode will get the preferred
- * mode set thru adb shell */
- mCurrentMode = getUserMode();
- if (mCurrentMode == -1) {
- //Get the best mode and set
- mCurrentMode = getBestMode();
- }
- setAttributes();
- // set system property
- property_set("hw.hdmiON", "1");
-
- // Read the system property to determine if downscale feature is enabled.
- char value[PROPERTY_VALUE_MAX];
- mMDPDownscaleEnabled = false;
- if(property_get("sys.hwc.mdp_downscale_enabled", value, "false")
- && !strcmp(value, "true")) {
- mMDPDownscaleEnabled = true;
- }
- return 0;
-}
-
-void HDMIDisplay::getAttributes(uint32_t& width, uint32_t& height) {
- uint32_t fps = 0;
- getAttrForMode(width, height, fps);
-}
-
-int HDMIDisplay::teardown() {
- closeFrameBuffer();
- resetInfo();
- // unset system property
- property_set("hw.hdmiON", "0");
- return 0;
-}
-
-HDMIDisplay::HDMIDisplay():mFd(-1),
- mCurrentMode(-1), mModeCount(0), mPrimaryWidth(0), mPrimaryHeight(0),
- mUnderscanSupported(false)
-{
- memset(&mVInfo, 0, sizeof(mVInfo));
-
- mDisplayId = HWC_DISPLAY_EXTERNAL;
- // Update the display if HDMI is connected as primary
- if (isHDMIPrimaryDisplay()) {
- mDisplayId = HWC_DISPLAY_PRIMARY;
- }
-
- mFbNum = overlay::Overlay::getInstance()->getFbForDpy(mDisplayId);
- // disable HPD at start, it will be enabled later
- // when the display powers on
- // This helps for framework reboot or adb shell stop/start
- writeHPDOption(0);
-
- // for HDMI - retreive all the modes supported by the driver
- if(mFbNum != -1) {
- supported_video_mode_lut =
- new msm_hdmi_mode_timing_info[HDMI_VFRMT_MAX];
- // Populate the mode table for supported modes
- MSM_HDMI_MODES_INIT_TIMINGS(supported_video_mode_lut);
- MSM_HDMI_MODES_SET_SUPP_TIMINGS(supported_video_mode_lut,
- MSM_HDMI_MODES_ALL);
- // Update the Source Product Information
- // Vendor Name
- setSPDInfo("vendor_name", "ro.product.manufacturer");
- // Product Description
- setSPDInfo("product_description", "ro.product.name");
- }
-
- ALOGD_IF(DEBUG, "%s mDisplayId(%d) mFbNum(%d)",
- __FUNCTION__, mDisplayId, mFbNum);
-}
-/* gets the product manufacturer and product name and writes it
- * to the sysfs node, so that the driver can get that information
- * Used to show QCOM 8974 instead of Input 1 for example
- */
-void HDMIDisplay::setSPDInfo(const char* node, const char* property) {
- char info[PROPERTY_VALUE_MAX];
- ssize_t err = -1;
- int spdFile = openDeviceNode(node, O_RDWR);
- if (spdFile >= 0) {
- memset(info, 0, sizeof(info));
- property_get(property, info, UNKNOWN_STRING);
- ALOGD_IF(DEBUG, "In %s: %s = %s",
- __FUNCTION__, property, info);
- if (strncmp(info, UNKNOWN_STRING, SPD_NAME_LENGTH)) {
- err = write(spdFile, info, strlen(info));
- if (err <= 0) {
- ALOGE("%s: file write failed for '%s'"
- "err no = %d", __FUNCTION__, node, errno);
- }
- } else {
- ALOGD_IF(DEBUG, "%s: property_get failed for SPD %s",
- __FUNCTION__, node);
- }
- close(spdFile);
- }
-}
-
-void HDMIDisplay::setHPD(uint32_t value) {
- ALOGD_IF(DEBUG,"HPD enabled=%d", value);
- writeHPDOption(value);
-}
-
-void HDMIDisplay::setActionSafeDimension(int w, int h) {
- ALOGD_IF(DEBUG,"ActionSafe w=%d h=%d", w, h);
- char actionsafeWidth[PROPERTY_VALUE_MAX];
- char actionsafeHeight[PROPERTY_VALUE_MAX];
- snprintf(actionsafeWidth, sizeof(actionsafeWidth), "%d", w);
- property_set("persist.sys.actionsafe.width", actionsafeWidth);
- snprintf(actionsafeHeight, sizeof(actionsafeHeight), "%d", h);
- property_set("persist.sys.actionsafe.height", actionsafeHeight);
-}
-
-int HDMIDisplay::getModeCount() const {
- ALOGD_IF(DEBUG,"HPD mModeCount=%d", mModeCount);
- return mModeCount;
-}
-
-void HDMIDisplay::readCEUnderscanInfo()
-{
- int hdmiScanInfoFile = -1;
- ssize_t len = -1;
- char scanInfo[17];
- char *ce_info_str = NULL;
- char *save_ptr;
- const char token[] = ", \n";
- int ce_info = -1;
-
- memset(scanInfo, 0, sizeof(scanInfo));
- hdmiScanInfoFile = openDeviceNode("scan_info", O_RDONLY);
- if (hdmiScanInfoFile < 0) {
- return;
- } else {
- len = read(hdmiScanInfoFile, scanInfo, sizeof(scanInfo)-1);
- ALOGD("%s: Scan Info string: %s length = %zu",
- __FUNCTION__, scanInfo, len);
- if (len <= 0) {
- close(hdmiScanInfoFile);
- ALOGE("%s: Scan Info file empty", __FUNCTION__);
- return;
- }
- scanInfo[len] = '\0'; /* null terminate the string */
- close(hdmiScanInfoFile);
- }
-
- /*
- * The scan_info contains the three fields
- * PT - preferred video format
- * IT - video format
- * CE video format - containing the underscan support information
- */
-
- /* PT */
- ce_info_str = strtok_r(scanInfo, token, &save_ptr);
- if (ce_info_str) {
- /* IT */
- ce_info_str = strtok_r(NULL, token, &save_ptr);
- if (ce_info_str) {
- /* CE */
- ce_info_str = strtok_r(NULL, token, &save_ptr);
- if (ce_info_str)
- ce_info = atoi(ce_info_str);
- }
- }
-
- if (ce_info_str) {
- // ce_info contains the underscan information
- if (ce_info == HDMI_SCAN_ALWAYS_UNDERSCANED ||
- ce_info == HDMI_SCAN_BOTH_SUPPORTED)
- // if TV supported underscan, then driver will always underscan
- // hence no need to apply action safe rectangle
- mUnderscanSupported = true;
- } else {
- ALOGE("%s: scan_info string error", __FUNCTION__);
- }
-
- // Store underscan support info in a system property
- const char* prop = (mUnderscanSupported) ? "1" : "0";
- property_set("hw.underscan_supported", prop);
- return;
-}
-
-HDMIDisplay::~HDMIDisplay()
-{
- delete [] supported_video_mode_lut;
- closeFrameBuffer();
-}
-
-/*
- * sets the fb_var_screeninfo from the hdmi_mode_timing_info
- */
-void setDisplayTiming(struct fb_var_screeninfo &info,
- const msm_hdmi_mode_timing_info* mode)
-{
- info.reserved[0] = 0;
- info.reserved[1] = 0;
- info.reserved[2] = 0;
-#ifndef FB_METADATA_VIDEO_INFO_CODE_SUPPORT
- info.reserved[3] = (info.reserved[3] & 0xFFFF) |
- (mode->video_format << 16);
-#endif
- info.xoffset = 0;
- info.yoffset = 0;
- info.xres = mode->active_h;
- info.yres = mode->active_v;
-
- info.pixclock = (mode->pixel_freq)*1000;
- info.vmode = mode->interlaced ?
- FB_VMODE_INTERLACED : FB_VMODE_NONINTERLACED;
-
- info.right_margin = mode->front_porch_h;
- info.hsync_len = mode->pulse_width_h;
- info.left_margin = mode->back_porch_h;
- info.lower_margin = mode->front_porch_v;
- info.vsync_len = mode->pulse_width_v;
- info.upper_margin = mode->back_porch_v;
-}
-
-int HDMIDisplay::parseResolution(char* edidStr)
-{
- char delim = ',';
- int count = 0;
- char *start, *end;
- // EDIDs are string delimited by ','
- // Ex: 16,4,5,3,32,34,1
- // Parse this string to get mode(int)
- start = (char*) edidStr;
- end = &delim;
- while(*end == delim) {
- mEDIDModes[count] = (int) strtol(start, &end, 10);
- start = end+1;
- count++;
- }
- ALOGD_IF(DEBUG, "In %s: count = %d", __FUNCTION__, count);
- for (int i = 0; i < count; i++)
- ALOGD_IF(DEBUG, "Mode[%d] = %d", i, mEDIDModes[i]);
- return count;
-}
-
-bool HDMIDisplay::readResolution()
-{
- ssize_t len = -1;
- char edidStr[128] = {'\0'};
-
- int hdmiEDIDFile = openDeviceNode("edid_modes", O_RDONLY);
- if (hdmiEDIDFile < 0) {
- return false;
- } else {
- len = read(hdmiEDIDFile, edidStr, sizeof(edidStr)-1);
- ALOGD_IF(DEBUG, "%s: EDID string: %s length = %zu",
- __FUNCTION__, edidStr, len);
- if (len <= 0) {
- ALOGE("%s: edid_modes file empty", __FUNCTION__);
- edidStr[0] = '\0';
- }
- else {
- while (len > 1 && isspace(edidStr[len-1])) {
- --len;
- }
- edidStr[len] = '\0';
- }
- close(hdmiEDIDFile);
- }
- if(len > 0) {
- // Get EDID modes from the EDID strings
- mModeCount = parseResolution(edidStr);
- ALOGD_IF(DEBUG, "%s: mModeCount = %d", __FUNCTION__,
- mModeCount);
- }
-
- return (len > 0);
-}
-
-bool HDMIDisplay::openFrameBuffer()
-{
- if (mFd == -1) {
- char strDevPath[MAX_SYSFS_FILE_PATH];
- snprintf(strDevPath, MAX_SYSFS_FILE_PATH, "/dev/graphics/fb%d", mFbNum);
- mFd = open(strDevPath, O_RDWR);
- if (mFd < 0)
- ALOGE("%s: %s is not available", __FUNCTION__, strDevPath);
- }
- return (mFd > 0);
-}
-
-bool HDMIDisplay::closeFrameBuffer()
-{
- int ret = 0;
- if(mFd >= 0) {
- ret = close(mFd);
- mFd = -1;
- }
- return (ret == 0);
-}
-
-// clears the vinfo, edid, best modes
-void HDMIDisplay::resetInfo()
-{
- memset(&mVInfo, 0, sizeof(mVInfo));
- memset(mEDIDModes, 0, sizeof(mEDIDModes));
- mModeCount = 0;
- mCurrentMode = -1;
- mUnderscanSupported = false;
- mXres = 0;
- mYres = 0;
- mVsyncPeriod = 0;
- mMDPScalingMode = false;
- // Reset the underscan supported system property
- const char* prop = "0";
- property_set("hw.underscan_supported", prop);
-}
-
-int HDMIDisplay::getModeOrder(int mode)
-{
- for (int dataIndex = 0; dataIndex < gEDIDCount; dataIndex++) {
- if (gEDIDData[dataIndex].mMode == mode) {
- return gEDIDData[dataIndex].mModeOrder;
- }
- }
- ALOGE("%s Mode not found: %d", __FUNCTION__, mode);
- return -1;
-}
-
-/// Returns the user mode set(if any) using adb shell
-int HDMIDisplay::getUserMode() {
- /* Based on the property set the resolution */
- char property_value[PROPERTY_VALUE_MAX];
- property_get("hw.hdmi.resolution", property_value, "-1");
- int mode = atoi(property_value);
- // We dont support interlaced modes
- if(isValidMode(mode) && !isInterlacedMode(mode)) {
- ALOGD_IF(DEBUG, "%s: setting the HDMI mode = %d", __FUNCTION__, mode);
- return mode;
- }
- return -1;
-}
-
-// Get the best mode for the current HD TV
-int HDMIDisplay::getBestMode() {
- int bestOrder = 0;
- int bestMode = HDMI_VFRMT_640x480p60_4_3;
- // for all the edid read, get the best mode
- for(int i = 0; i < mModeCount; i++) {
- int mode = mEDIDModes[i];
- int order = getModeOrder(mode);
- if (order > bestOrder) {
- bestOrder = order;
- bestMode = mode;
- }
- }
- return bestMode;
-}
-
-inline bool HDMIDisplay::isValidMode(int ID)
-{
- bool valid = false;
- for (int i = 0; i < mModeCount; i++) {
- if(ID == mEDIDModes[i]) {
- valid = true;
- break;
- }
- }
- return valid;
-}
-
-// returns true if the mode(ID) is interlaced mode format
-bool HDMIDisplay::isInterlacedMode(int ID) {
- bool interlaced = false;
- switch(ID) {
- case HDMI_VFRMT_1440x480i60_4_3:
- case HDMI_VFRMT_1440x480i60_16_9:
- case HDMI_VFRMT_1440x576i50_4_3:
- case HDMI_VFRMT_1440x576i50_16_9:
- case HDMI_VFRMT_1920x1080i60_16_9:
- interlaced = true;
- break;
- default:
- interlaced = false;
- break;
- }
- return interlaced;
-}
-
-// Does a put_vscreen info on the HDMI interface which will update
-// the configuration (resolution, timing info) to match mCurrentMode
-void HDMIDisplay::activateDisplay()
-{
- int ret = 0;
- ret = ioctl(mFd, FBIOGET_VSCREENINFO, &mVInfo);
- if(ret < 0) {
- ALOGD("In %s: FBIOGET_VSCREENINFO failed Err Str = %s", __FUNCTION__,
- strerror(errno));
- }
- ALOGD_IF(DEBUG, "%s: GET Info<ID=%d %dx%d (%d,%d,%d),"
- "(%d,%d,%d) %dMHz>", __FUNCTION__,
- mVInfo.reserved[3], mVInfo.xres, mVInfo.yres,
- mVInfo.right_margin, mVInfo.hsync_len, mVInfo.left_margin,
- mVInfo.lower_margin, mVInfo.vsync_len, mVInfo.upper_margin,
- mVInfo.pixclock/1000/1000);
-
- const struct msm_hdmi_mode_timing_info *mode =
- &supported_video_mode_lut[0];
- for (unsigned int i = 0; i < HDMI_VFRMT_MAX; ++i) {
- const struct msm_hdmi_mode_timing_info *cur =
- &supported_video_mode_lut[i];
- if (cur->video_format == (uint32_t)mCurrentMode) {
- mode = cur;
- break;
- }
- }
- setDisplayTiming(mVInfo, mode);
- ALOGD_IF(DEBUG, "%s: SET Info<ID=%d => Info<ID=%d %dx %d"
- "(%d,%d,%d), (%d,%d,%d) %dMHz>", __FUNCTION__, mCurrentMode,
- mode->video_format, mVInfo.xres, mVInfo.yres,
- mVInfo.right_margin, mVInfo.hsync_len, mVInfo.left_margin,
- mVInfo.lower_margin, mVInfo.vsync_len, mVInfo.upper_margin,
- mVInfo.pixclock/1000/1000);
-#ifdef FB_METADATA_VIDEO_INFO_CODE_SUPPORT
- struct msmfb_metadata metadata;
- memset(&metadata, 0 , sizeof(metadata));
- metadata.op = metadata_op_vic;
- metadata.data.video_info_code = mode->video_format;
- if (ioctl(mFd, MSMFB_METADATA_SET, &metadata) == -1) {
- ALOGD("In %s: MSMFB_METADATA_SET failed Err Str = %s",
- __FUNCTION__, strerror(errno));
- }
-#endif
- mVInfo.activate = FB_ACTIVATE_NOW | FB_ACTIVATE_ALL | FB_ACTIVATE_FORCE;
- ret = ioctl(mFd, FBIOPUT_VSCREENINFO, &mVInfo);
- if(ret < 0) {
- ALOGD("In %s: FBIOPUT_VSCREENINFO failed Err Str = %s",
- __FUNCTION__, strerror(errno));
- }
-}
-
-bool HDMIDisplay::writeHPDOption(int userOption) const
-{
- bool ret = true;
- if(mFbNum != -1) {
- int hdmiHPDFile = openDeviceNode("hpd", O_RDWR);
- if (hdmiHPDFile >= 0) {
- ssize_t err = -1;
- ALOGD_IF(DEBUG, "%s: option = %d",
- __FUNCTION__, userOption);
- if(userOption)
- err = write(hdmiHPDFile, "1", 2);
- else
- err = write(hdmiHPDFile, "0" , 2);
- if (err <= 0) {
- ALOGE("%s: file write failed 'hpd'", __FUNCTION__);
- ret = false;
- }
- close(hdmiHPDFile);
- }
- }
- return ret;
-}
-
-
-void HDMIDisplay::setAttributes() {
- uint32_t fps = 0;
- // Always set dpyAttr res to mVInfo res
- getAttrForMode(mXres, mYres, fps);
- mMDPScalingMode = false;
-
- if(overlay::Overlay::getInstance()->isUIScalingOnExternalSupported()
- && mMDPDownscaleEnabled) {
- // if primary resolution is more than the hdmi resolution
- // configure dpy attr to primary resolution and set MDP
- // scaling mode
- // Restrict this upto 1080p resolution max, if target does not
- // support source split feature.
- uint32_t primaryArea = mPrimaryWidth * mPrimaryHeight;
- if(((primaryArea) > (mXres * mYres)) &&
- (((primaryArea) <= SUPPORTED_DOWNSCALE_AREA) ||
- qdutils::MDPVersion::getInstance().isSrcSplit())) {
- // tmpW and tmpH will hold the primary dimensions before we
- // update the aspect ratio if necessary.
- int tmpW = mPrimaryWidth;
- int tmpH = mPrimaryHeight;
- // HDMI is always in landscape, so always assign the higher
- // dimension to hdmi's xres
- if(mPrimaryHeight > mPrimaryWidth) {
- tmpW = mPrimaryHeight;
- tmpH = mPrimaryWidth;
- }
- // The aspect ratios of the external and primary displays
- // can be different. As a result, directly assigning primary
- // resolution could lead to an incorrect final image.
- // We get around this by calculating a new resolution by
- // keeping aspect ratio intact.
- hwc_rect r = {0, 0, 0, 0};
- qdutils::getAspectRatioPosition(tmpW, tmpH, mXres, mYres, r);
- uint32_t newExtW = r.right - r.left;
- uint32_t newExtH = r.bottom - r.top;
- uint32_t alignedExtW;
- uint32_t alignedExtH;
- // On 8994 and below targets MDP supports only 4X downscaling,
- // Restricting selected external resolution to be exactly 4X
- // greater resolution than actual external resolution
- uint32_t maxMDPDownScale =
- qdutils::MDPVersion::getInstance().getMaxMDPDownscale();
- if((mXres * mYres * maxMDPDownScale) < (newExtW * newExtH)) {
- float upScaleFactor = (float)maxMDPDownScale / 2.0f;
- newExtW = (int)((float)mXres * upScaleFactor);
- newExtH = (int)((float)mYres * upScaleFactor);
- }
- // Align it down so that the new aligned resolution does not
- // exceed the maxMDPDownscale factor
- alignedExtW = overlay::utils::aligndown(newExtW, 4);
- alignedExtH = overlay::utils::aligndown(newExtH, 4);
- mXres = alignedExtW;
- mYres = alignedExtH;
- // Set External Display MDP Downscale mode indicator
- mMDPScalingMode = true;
- }
- }
- ALOGD_IF(DEBUG_MDPDOWNSCALE, "Selected external resolution [%d X %d] "
- "maxMDPDownScale %d mMDPScalingMode %d srcSplitEnabled %d "
- "MDPDownscale feature %d",
- mXres, mYres,
- qdutils::MDPVersion::getInstance().getMaxMDPDownscale(),
- mMDPScalingMode, qdutils::MDPVersion::getInstance().isSrcSplit(),
- mMDPDownscaleEnabled);
- mVsyncPeriod = (int) 1000000000l / fps;
- ALOGD_IF(DEBUG, "%s xres=%d, yres=%d", __FUNCTION__, mXres, mYres);
-}
-
-void HDMIDisplay::getAttrForMode(uint32_t& width, uint32_t& height,
- uint32_t& fps) {
- for (int dataIndex = 0; dataIndex < gEDIDCount; dataIndex++) {
- if (gEDIDData[dataIndex].mMode == mCurrentMode) {
- width = gEDIDData[dataIndex].mWidth;
- height = gEDIDData[dataIndex].mHeight;
- fps = gEDIDData[dataIndex].mFps;
- return;
- }
- }
- ALOGE("%s Unable to get attributes for %d", __FUNCTION__, mCurrentMode);
-}
-
-/* returns the fd related to the node specified*/
-int HDMIDisplay::openDeviceNode(const char* node, int fileMode) const {
- char sysFsFilePath[MAX_SYSFS_FILE_PATH];
- memset(sysFsFilePath, 0, sizeof(sysFsFilePath));
- snprintf(sysFsFilePath , sizeof(sysFsFilePath),
- "/sys/devices/virtual/graphics/fb%d/%s",
- mFbNum, node);
-
- int fd = open(sysFsFilePath, fileMode, 0);
-
- if (fd < 0) {
- ALOGE("%s: file '%s' not found : ret = %d err str: %s",
- __FUNCTION__, sysFsFilePath, fd, strerror(errno));
- }
- return fd;
-}
-
-bool HDMIDisplay::isHDMIPrimaryDisplay() {
- int hdmiNode = qdutils::getHDMINode();
- return (hdmiNode == HWC_DISPLAY_PRIMARY);
-}
-
-int HDMIDisplay::getConnectedState() {
- int ret = -1;
- int mFbNum = qdutils::getHDMINode();
- int connectedNode = openDeviceNode("connected", O_RDONLY);
- if(connectedNode >= 0) {
- char opStr[4];
- ssize_t bytesRead = read(connectedNode, opStr, sizeof(opStr) - 1);
- if(bytesRead > 0) {
- opStr[bytesRead] = '\0';
- ret = atoi(opStr);
- ALOGD_IF(DEBUG, "%s: Read %d from connected", __FUNCTION__, ret);
- } else if(bytesRead == 0) {
- ALOGE("%s: HDMI connected node empty", __FUNCTION__);
- } else {
- ALOGE("%s: Read from HDMI connected node failed with error %s",
- __FUNCTION__, strerror(errno));
- }
- close(connectedNode);
- } else {
- ALOGD("%s: /sys/class/graphics/fb%d/connected could not be opened : %s",
- __FUNCTION__, mFbNum, strerror(errno));
- }
- return ret;
-}
-
-void HDMIDisplay::setPrimaryAttributes(uint32_t primaryWidth,
- uint32_t primaryHeight) {
- mPrimaryHeight = primaryHeight;
- mPrimaryWidth = primaryWidth;
-}
-
-};
diff --git a/msm8909/libhdmi/hdmi.h b/msm8909/libhdmi/hdmi.h
deleted file mode 100644
index 605d9be8..00000000
--- a/msm8909/libhdmi/hdmi.h
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- * Copyright (C) 2012-2014, The Linux Foundation. All rights reserved.
- *
- * Not a Contribution, Apache license notifications and license are
- * retained for attribution purposes only.
-
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef HWC_HDMI_DISPLAY_H
-#define HWC_HDMI_DISPLAY_H
-
-#include <linux/fb.h>
-
-struct msm_hdmi_mode_timing_info;
-
-namespace qhwc {
-
-//Type of scanning of EDID(Video Capability Data Block)
-enum hdmi_scansupport_type {
- HDMI_SCAN_NOT_SUPPORTED = 0,
- HDMI_SCAN_ALWAYS_OVERSCANED = 1,
- HDMI_SCAN_ALWAYS_UNDERSCANED = 2,
- HDMI_SCAN_BOTH_SUPPORTED = 3
-};
-
-// Structure to store EDID related data
-struct EDIDData {
- int mMode, mWidth, mHeight, mFps;
- // Predetermined ordering for each mode
- int mModeOrder;
- EDIDData(int mode, int width, int height, int fps, int order)
- : mMode(mode), mWidth(width), mHeight(height), mFps(fps), mModeOrder(order)
- { }
-};
-
-class HDMIDisplay
-{
-public:
- HDMIDisplay();
- ~HDMIDisplay();
- void setHPD(uint32_t startEnd);
- void setActionSafeDimension(int w, int h);
- bool isCEUnderscanSupported() { return mUnderscanSupported; }
- int configure();
- void getAttributes(uint32_t& width, uint32_t& height);
- int teardown();
- uint32_t getWidth() const { return mXres; };
- uint32_t getHeight() const { return mYres; };
- uint32_t getVsyncPeriod() const { return mVsyncPeriod; };
- int getFd() const { return mFd; };
- bool getMDPScalingMode() const { return mMDPScalingMode; }
- void activateDisplay();
- /* Returns true if HDMI is the PRIMARY display device*/
- bool isHDMIPrimaryDisplay();
- int getConnectedState();
- /* when HDMI is an EXTERNAL display, PRIMARY display attributes are needed
- for scaling mode */
- void setPrimaryAttributes(uint32_t primaryWidth, uint32_t primaryHeight);
-
-private:
- int getModeCount() const;
- void setSPDInfo(const char* node, const char* property);
- void readCEUnderscanInfo();
- bool readResolution();
- int parseResolution(char* edidMode);
- bool openFrameBuffer();
- bool closeFrameBuffer();
- bool writeHPDOption(int userOption) const;
- bool isValidMode(int mode);
- int getModeOrder(int mode);
- int getUserMode();
- int getBestMode();
- bool isInterlacedMode(int mode);
- void resetInfo();
- void setAttributes();
- void getAttrForMode(uint32_t& width, uint32_t& height, uint32_t& fps);
- int openDeviceNode(const char* node, int fileMode) const;
-
- int mFd;
- int mFbNum;
- int mCurrentMode;
- int mEDIDModes[64];
- int mModeCount;
- fb_var_screeninfo mVInfo;
- // Holds all the HDMI modes and timing info supported by driver
- msm_hdmi_mode_timing_info* supported_video_mode_lut;
- uint32_t mXres, mYres, mVsyncPeriod, mPrimaryWidth, mPrimaryHeight;
- bool mMDPScalingMode;
- bool mUnderscanSupported;
- // Downscale feature switch, set via system property
- // sys.hwc.mdp_downscale_enabled
- bool mMDPDownscaleEnabled;
- int mDisplayId;
-};
-
-}; //qhwc
-// ---------------------------------------------------------------------------
-#endif //HWC_HDMI_DISPLAY_H
diff --git a/msm8909/libhwcomposer/Android.mk b/msm8909/libhwcomposer/Android.mk
deleted file mode 100644
index 1eafaf0f..00000000
--- a/msm8909/libhwcomposer/Android.mk
+++ /dev/null
@@ -1,71 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-include $(LOCAL_PATH)/../common.mk
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := hwcomposer.$(TARGET_BOARD_PLATFORM)
-LOCAL_MODULE_RELATIVE_PATH := hw
-LOCAL_PROPRIETARY_MODULE := true
-LOCAL_MODULE_TAGS := optional
-LOCAL_C_INCLUDES := $(common_includes) $(kernel_includes) \
- $(TOP)/external/skia/include/core \
- $(TOP)/external/skia/include/images
-
-ifeq ($(strip $(TARGET_USES_QCOM_DISPLAY_PP)),true)
-LOCAL_C_INCLUDES += $(TARGET_OUT_HEADERS)/qdcm/inc \
- $(TARGET_OUT_HEADERS)/common/inc \
- $(TARGET_OUT_HEADERS)/pp/inc
-endif
-
-LOCAL_SHARED_LIBRARIES := $(common_libs) libEGL liboverlay \
- libhdmi libqdutils libhardware_legacy \
- libdl libmemalloc libqservice libsync \
- libbinder libmedia
-
-LOCAL_CFLAGS := $(common_flags) -DLOG_TAG=\"qdhwcomposer\" -Wno-absolute-value \
- -Wno-float-conversion
-
-LOCAL_CLANG := true
-
-ifeq ($(TARGET_USES_QCOM_BSP),true)
-LOCAL_SHARED_LIBRARIES += libhwui
-ifeq ($(GET_FRAMEBUFFER_FORMAT_FROM_HWC),true)
- LOCAL_CFLAGS += -DGET_FRAMEBUFFER_FORMAT_FROM_HWC
-endif
-endif #TARGET_USES_QCOM_BSP
-
-#Enable Dynamic FPS if PHASE_OFFSET is not set
-ifeq ($(VSYNC_EVENT_PHASE_OFFSET_NS),)
- LOCAL_CFLAGS += -DDYNAMIC_FPS
-endif
-
-LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps)
-LOCAL_SRC_FILES := hwc.cpp \
- hwc_utils.cpp \
- hwc_uevents.cpp \
- hwc_vsync.cpp \
- hwc_fbupdate.cpp \
- hwc_mdpcomp.cpp \
- hwc_copybit.cpp \
- hwc_qclient.cpp \
- hwc_dump_layers.cpp \
- hwc_ad.cpp \
- hwc_virtual.cpp
-
-TARGET_MIGRATE_QDCM_LIST := msm8909
-TARGET_MIGRATE_QDCM := $(call is-board-platform-in-list,$(TARGET_MIGRATE_QDCM_LIST))
-
-ifeq ($(TARGET_MIGRATE_QDCM), true)
-ifeq ($(strip $(TARGET_USES_QCOM_DISPLAY_PP)),true)
-LOCAL_SRC_FILES += hwc_qdcm.cpp
-else
-LOCAL_SRC_FILES += hwc_qdcm_legacy.cpp
-endif
-else
-LOCAL_SRC_FILES += hwc_qdcm_legacy.cpp
-endif
-
-ifeq ($(TARGET_SUPPORTS_ANDROID_WEAR), true)
- LOCAL_CFLAGS += -DSUPPORT_BLIT_TO_FB
-endif
-
-include $(BUILD_SHARED_LIBRARY)
diff --git a/msm8909/libhwcomposer/hwc.cpp b/msm8909/libhwcomposer/hwc.cpp
deleted file mode 100644
index c6a7e0a6..00000000
--- a/msm8909/libhwcomposer/hwc.cpp
+++ /dev/null
@@ -1,977 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- * Copyright (C) 2012-2016, The Linux Foundation. All rights reserved.
- *
- * Not a Contribution, Apache license notifications and license are retained
- * for attribution purposes only.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#define ATRACE_TAG (ATRACE_TAG_GRAPHICS | ATRACE_TAG_HAL)
-#include <fcntl.h>
-#include <errno.h>
-
-#include <cutils/log.h>
-#include <cutils/atomic.h>
-#include <EGL/egl.h>
-#include <utils/Trace.h>
-#include <sys/ioctl.h>
-#include <overlay.h>
-#include <overlayRotator.h>
-#include <overlayWriteback.h>
-#include <mdp_version.h>
-#include "hwc_utils.h"
-#include "hwc_fbupdate.h"
-#include "hwc_mdpcomp.h"
-#include "hwc_dump_layers.h"
-#include "hdmi.h"
-#include "hwc_copybit.h"
-#include "hwc_ad.h"
-#include "profiler.h"
-#include "hwc_virtual.h"
-#include "hwc_qdcm.h"
-
-using namespace qhwc;
-using namespace overlay;
-using namespace qQdcm;
-
-#define VSYNC_DEBUG 0
-#define POWER_MODE_DEBUG 1
-
-static int hwc_device_open(const struct hw_module_t* module,
- const char* name,
- struct hw_device_t** device);
-
-static struct hw_module_methods_t hwc_module_methods = {
- .open = hwc_device_open
-};
-
-static void reset_panel(struct hwc_composer_device_1* dev);
-
-hwc_module_t HAL_MODULE_INFO_SYM = {
- .common = {
- .tag = HARDWARE_MODULE_TAG,
- .version_major = 2,
- .version_minor = 0,
- .id = HWC_HARDWARE_MODULE_ID,
- .name = "Qualcomm Hardware Composer Module",
- .author = "CodeAurora Forum",
- .methods = &hwc_module_methods,
- .dso = 0,
- .reserved = {0},
- }
-};
-
-/*
- * Save callback functions registered to HWC
- */
-static void hwc_registerProcs(struct hwc_composer_device_1* dev,
- hwc_procs_t const* procs)
-{
- ALOGI("%s", __FUNCTION__);
- hwc_context_t* ctx = (hwc_context_t*)(dev);
- if(!ctx) {
- ALOGE("%s: Invalid context", __FUNCTION__);
- return;
- }
- ctx->proc = procs;
-
- // Now that we have the functions needed, kick off
- // the uevent & vsync threads
- init_uevent_thread(ctx);
- init_vsync_thread(ctx);
-}
-
-static void setPaddingRound(hwc_context_t *ctx, int numDisplays,
- hwc_display_contents_1_t** displays) {
- ctx->isPaddingRound = false;
- for(int i = 0; i < numDisplays; i++) {
- hwc_display_contents_1_t *list = displays[i];
- if (LIKELY(list && list->numHwLayers > 0)) {
- if((ctx->mPrevHwLayerCount[i] == 1 or
- ctx->mPrevHwLayerCount[i] == 0) and
- (list->numHwLayers > 1)) {
- /* If the previous cycle for dpy 'i' has 0 AppLayers and the
- * current cycle has atleast 1 AppLayer, padding round needs
- * to be invoked in current cycle on all the active displays
- * to free up the resources.
- */
- ctx->isPaddingRound = true;
- }
- ctx->mPrevHwLayerCount[i] = (int)list->numHwLayers;
- } else {
- ctx->mPrevHwLayerCount[i] = 0;
- }
- }
-}
-
-/* Based on certain conditions, isPaddingRound will be set
- * to make this function self-contained */
-static void setDMAState(hwc_context_t *ctx, int numDisplays,
- hwc_display_contents_1_t** displays) {
-
- if(ctx->mRotMgr->getNumActiveSessions() == 0)
- Overlay::setDMAMode(Overlay::DMA_LINE_MODE);
-
- for(int dpy = 0; dpy < numDisplays; dpy++) {
- hwc_display_contents_1_t *list = displays[dpy];
- if (LIKELY(list && list->numHwLayers > 0)) {
- for(size_t layerIndex = 0; layerIndex < list->numHwLayers;
- layerIndex++) {
- if(list->hwLayers[layerIndex].compositionType !=
- HWC_FRAMEBUFFER_TARGET)
- {
- hwc_layer_1_t const* layer = &list->hwLayers[layerIndex];
- private_handle_t *hnd = (private_handle_t *)layer->handle;
-
- /* If a layer requires rotation, set the DMA state
- * to BLOCK_MODE */
-
- if (canUseRotator(ctx, dpy) &&
- (has90Transform(layer) || getRotDownscale(ctx, layer))
- && isRotationDoable(ctx, hnd)) {
- if(not (ctx->mOverlay->isDMAMultiplexingSupported() &&
- dpy)) {
- if(ctx->mOverlay->isPipeTypeAttached(
- overlay::utils::OV_MDP_PIPE_DMA))
- ctx->isPaddingRound = true;
- }
- Overlay::setDMAMode(Overlay::DMA_BLOCK_MODE);
- }
- }
- }
- if(dpy) {
- /* Uncomment the below code for testing purpose.
- Assuming the orientation value is in terms of HAL_TRANSFORM,
- this needs mapping to HAL, if its in different convention */
-
- /* char value[PROPERTY_VALUE_MAX];
- property_get("sys.ext_orientation", value, "0");
- ctx->mExtOrientation = atoi(value);*/
-
- if(ctx->mExtOrientation || ctx->mBufferMirrorMode) {
- if(ctx->mOverlay->isPipeTypeAttached(
- overlay::utils::OV_MDP_PIPE_DMA)) {
- ctx->isPaddingRound = true;
- }
- Overlay::setDMAMode(Overlay::DMA_BLOCK_MODE);
- }
- }
- }
- }
-}
-
-static void setNumActiveDisplays(hwc_context_t *ctx, int numDisplays,
- hwc_display_contents_1_t** displays) {
-
- ctx->numActiveDisplays = 0;
- for(int i = 0; i < numDisplays; i++) {
- hwc_display_contents_1_t *list = displays[i];
- if (LIKELY(list && list->numHwLayers > 0)) {
- /* For display devices like SSD and screenrecord, we cannot
- * rely on isActive and connected attributes of dpyAttr to
- * determine if the displaydevice is active. Hence in case if
- * the layer-list is non-null and numHwLayers > 0, we assume
- * the display device to be active.
- */
- ctx->numActiveDisplays += 1;
- }
- }
-}
-
-static bool validDisplay(int disp) {
- switch(disp) {
- case HWC_DISPLAY_PRIMARY:
- case HWC_DISPLAY_EXTERNAL:
- case HWC_DISPLAY_VIRTUAL:
- return true;
- break;
- default:
- return false;
- }
-}
-
-static void reset(hwc_context_t *ctx, int numDisplays,
- hwc_display_contents_1_t** displays) {
-
-
- for(int i = 0; i < numDisplays; i++) {
- hwc_display_contents_1_t *list = displays[i];
- // XXX:SurfaceFlinger no longer guarantees that this
- // value is reset on every prepare. However, for the layer
- // cache we need to reset it.
- // We can probably rethink that later on
- if (LIKELY(list && list->numHwLayers > 0)) {
- for(size_t j = 0; j < list->numHwLayers; j++) {
- if(list->hwLayers[j].compositionType != HWC_FRAMEBUFFER_TARGET)
- list->hwLayers[j].compositionType = HWC_FRAMEBUFFER;
- }
-
- }
-
- if(ctx->mMDPComp[i])
- ctx->mMDPComp[i]->reset();
- if(ctx->mFBUpdate[i])
- ctx->mFBUpdate[i]->reset();
- if(ctx->mCopyBit[i])
- ctx->mCopyBit[i]->reset();
- if(ctx->mLayerRotMap[i])
- ctx->mLayerRotMap[i]->reset();
- }
-
- ctx->mAD->reset();
-
-}
-
-static void scaleDisplayFrame(hwc_context_t *ctx, int dpy,
- hwc_display_contents_1_t *list) {
- uint32_t origXres = ctx->dpyAttr[dpy].xres;
- uint32_t origYres = ctx->dpyAttr[dpy].yres;
- uint32_t newXres = ctx->dpyAttr[dpy].xres_new;
- uint32_t newYres = ctx->dpyAttr[dpy].yres_new;
- float xresRatio = (float)origXres / (float)newXres;
- float yresRatio = (float)origYres / (float)newYres;
- for (size_t i = 0; i < list->numHwLayers; i++) {
- hwc_layer_1_t *layer = &list->hwLayers[i];
- hwc_rect_t& displayFrame = layer->displayFrame;
- uint32_t layerWidth = displayFrame.right - displayFrame.left;
- uint32_t layerHeight = displayFrame.bottom - displayFrame.top;
- displayFrame.left = (int)(xresRatio * (float)displayFrame.left);
- displayFrame.top = (int)(yresRatio * (float)displayFrame.top);
- displayFrame.right = (int)((float)displayFrame.left +
- (float)layerWidth * xresRatio);
- displayFrame.bottom = (int)((float)displayFrame.top +
- (float)layerHeight * yresRatio);
- }
-}
-
-static int hwc_prepare_primary(hwc_composer_device_1 *dev,
- hwc_display_contents_1_t *list) {
- ATRACE_CALL();
- hwc_context_t* ctx = (hwc_context_t*)(dev);
- const int dpy = HWC_DISPLAY_PRIMARY;
- bool fbComp = false;
- static int compStart = false;
- if (!ctx->mBootAnimCompleted)
- processBootAnimCompleted(ctx);
-
- if (LIKELY(list && (list->numHwLayers > 1 ||
- (ctx->mMDP.version < qdutils::MDP_V4_0 && compStart))) &&
- (ctx->dpyAttr[dpy].isActive ||
- ctx->mHDMIDisplay->isHDMIPrimaryDisplay())
- && !ctx->dpyAttr[dpy].isPause) {
- compStart = true;
-
- // When HDMI is primary we should rely on the first valid
- // draw call in order to activate the display
- if (!ctx->dpyAttr[dpy].isActive) {
- // If the cable is connected after HWC initialization and before
- // the UEvent thread is initialized then we will miss the ONLINE
- // event. We need to update the display appropriately when we get
- // the first valid frame.
- int cableConnected = ctx->mHDMIDisplay->getConnectedState();
- if ((cableConnected == 1) && !ctx->dpyAttr[dpy].connected) {
- qhwc::handle_online(ctx, dpy);
- }
- ctx->mHDMIDisplay->activateDisplay();
- ctx->dpyAttr[dpy].isActive = true;
- }
-
- if (ctx->dpyAttr[dpy].customFBSize &&
- list->flags & HWC_GEOMETRY_CHANGED)
- scaleDisplayFrame(ctx, dpy, list);
-
- reset_layer_prop(ctx, dpy, (int)list->numHwLayers - 1);
- setListStats(ctx, list, dpy);
-
- fbComp = (ctx->mMDPComp[dpy]->prepare(ctx, list) < 0);
-
- if (fbComp) {
- const int fbZ = 0;
- if(not ctx->mFBUpdate[dpy]->prepareAndValidate(ctx, list, fbZ)) {
- ctx->mOverlay->clear(dpy);
- ctx->mLayerRotMap[dpy]->clear();
- }
- }
-
- if (ctx->mMDP.version < qdutils::MDP_V4_0) {
- if(ctx->mCopyBit[dpy])
- ctx->mCopyBit[dpy]->prepare(ctx, list, dpy);
- }
- setGPUHint(ctx, list);
- }
- return 0;
-}
-
-static int hwc_prepare_external(hwc_composer_device_1 *dev,
- hwc_display_contents_1_t *list) {
- ATRACE_CALL();
- hwc_context_t* ctx = (hwc_context_t*)(dev);
- const int dpy = HWC_DISPLAY_EXTERNAL;
-
- if (LIKELY(list && list->numHwLayers > 1) &&
- ctx->dpyAttr[dpy].isActive &&
- ctx->dpyAttr[dpy].connected) {
- reset_layer_prop(ctx, dpy, (int)list->numHwLayers - 1);
- if(!ctx->dpyAttr[dpy].isPause) {
- ctx->dpyAttr[dpy].isConfiguring = false;
- setListStats(ctx, list, dpy);
- if(ctx->mMDPComp[dpy]->prepare(ctx, list) < 0) {
- const int fbZ = 0;
- if(not ctx->mFBUpdate[dpy]->prepareAndValidate(ctx, list, fbZ))
- {
- ctx->mOverlay->clear(dpy);
- ctx->mLayerRotMap[dpy]->clear();
- }
- }
- } else {
- /* External Display is in Pause state.
- * Mark all application layers as OVERLAY so that
- * GPU will not compose.
- */
- for(size_t i = 0 ;i < (size_t)(list->numHwLayers - 1); i++) {
- hwc_layer_1_t *layer = &list->hwLayers[i];
- layer->compositionType = HWC_OVERLAY;
- }
- }
- }
- return 0;
-}
-
-static int hwc_prepare(hwc_composer_device_1 *dev, size_t numDisplays,
- hwc_display_contents_1_t** displays)
-{
- int ret = 0;
- hwc_context_t* ctx = (hwc_context_t*)(dev);
-
- if (ctx->mPanelResetStatus) {
- ALOGW("%s: panel is in bad state. reset the panel", __FUNCTION__);
- reset_panel(dev);
- }
-
- //Will be unlocked at the end of set
- ctx->mDrawLock.lock();
- setPaddingRound(ctx, (int)numDisplays, displays);
- setDMAState(ctx, (int)numDisplays, displays);
- setNumActiveDisplays(ctx, (int)numDisplays, displays);
- reset(ctx, (int)numDisplays, displays);
-
- ctx->mOverlay->configBegin();
- ctx->mRotMgr->configBegin();
- overlay::Writeback::configBegin();
-
- for (int32_t dpy = ((int32_t)numDisplays-1); dpy >=0 ; dpy--) {
- hwc_display_contents_1_t *list = displays[dpy];
- resetROI(ctx, dpy);
- switch(dpy) {
- case HWC_DISPLAY_PRIMARY:
- ret = hwc_prepare_primary(dev, list);
- break;
- case HWC_DISPLAY_EXTERNAL:
- ret = hwc_prepare_external(dev, list);
- break;
- case HWC_DISPLAY_VIRTUAL:
- if(ctx->mHWCVirtual)
- ret = ctx->mHWCVirtual->prepare(dev, list);
- break;
- default:
- ret = -EINVAL;
- }
- }
-
- ctx->mOverlay->configDone();
- ctx->mRotMgr->configDone();
- overlay::Writeback::configDone();
- // If VD list is deleted, mdp overlay pipe objects and writeback object
- // are deleted as part of configDone functions.
- // Proceed with HWCVirtualVDS object deletion.
- if(ctx->mHWCVirtual)
- ctx->mHWCVirtual->destroy(ctx, numDisplays, displays);
-
- return ret;
-}
-
-static int hwc_eventControl(struct hwc_composer_device_1* dev, int dpy,
- int event, int enable)
-{
- ATRACE_CALL();
- int ret = 0;
- hwc_context_t* ctx = (hwc_context_t*)(dev);
- if(!validDisplay(dpy)) {
- return -EINVAL;
- }
-
- switch(event) {
- case HWC_EVENT_VSYNC:
- if (ctx->vstate.enable == enable)
- break;
- ret = hwc_vsync_control(ctx, dpy, enable);
- if(ret == 0)
- ctx->vstate.enable = !!enable;
- ALOGD_IF (VSYNC_DEBUG, "VSYNC state changed to %s",
- (enable)?"ENABLED":"DISABLED");
- break;
-#ifdef QTI_BSP
- case HWC_EVENT_ORIENTATION:
- if(dpy == HWC_DISPLAY_PRIMARY) {
- Locker::Autolock _l(ctx->mDrawLock);
- // store the primary display orientation
- ctx->deviceOrientation = enable;
- }
- break;
-#endif
- default:
- ret = -EINVAL;
- }
- return ret;
-}
-
-static int hwc_setPowerMode(struct hwc_composer_device_1* dev, int dpy,
- int mode)
-{
- ATRACE_CALL();
- hwc_context_t* ctx = (hwc_context_t*)(dev);
- int ret = 0, value = 0;
-
- Locker::Autolock _l(ctx->mDrawLock);
-
- if(!validDisplay(dpy)) {
- return -EINVAL;
- }
-
- ALOGD_IF(POWER_MODE_DEBUG, "%s: Setting mode %d on display: %d",
- __FUNCTION__, mode, dpy);
-
- switch(mode) {
- case HWC_POWER_MODE_OFF:
- // free up all the overlay pipes in use
- // when we get a blank for either display
- // makes sure that all pipes are freed
- ctx->mOverlay->configBegin();
- ctx->mOverlay->configDone();
- ctx->mRotMgr->clear();
- // If VDS is connected, do not clear WB object as it
- // will end up detaching IOMMU. This is required
- // to send black frame to WFD sink on power suspend.
- // Note: With this change, we keep the WriteBack object
- // alive on power suspend for AD use case.
- value = FB_BLANK_POWERDOWN;
- break;
- case HWC_POWER_MODE_DOZE:
- case HWC_POWER_MODE_DOZE_SUSPEND:
- value = FB_BLANK_VSYNC_SUSPEND;
- break;
- case HWC_POWER_MODE_NORMAL:
- value = FB_BLANK_UNBLANK;
- break;
- }
-
- switch(dpy) {
- case HWC_DISPLAY_PRIMARY:
- if(ctx->mHDMIDisplay->isHDMIPrimaryDisplay()) {
- if(ctx->dpyAttr[dpy].connected) {
- // When HDMI is connected as primary we clean up resources
- // and call commit to generate a black frame on the interface.
- // However, we do not call blank since we need the timing
- // generator and HDMI core to remain turned on.
- if((mode == HWC_POWER_MODE_OFF) &&
- (!Overlay::displayCommit(ctx->dpyAttr[dpy].fd))) {
- ALOGE("%s: display commit fail for %d", __FUNCTION__, dpy);
- ret = -1;
- }
- }
- } else {
- if(ioctl(ctx->dpyAttr[dpy].fd, FBIOBLANK, value) < 0 ) {
- ALOGE("%s: ioctl FBIOBLANK failed for Primary with error %s"
- " value %d", __FUNCTION__, strerror(errno), value);
- return -errno;
- }
-
- if(mode == HWC_POWER_MODE_NORMAL) {
- // Enable HPD here, as during bootup POWER_MODE_NORMAL is set
- // when SF is completely initialized
- ctx->mHDMIDisplay->setHPD(1);
- }
-
- ctx->dpyAttr[dpy].isActive = not(mode == HWC_POWER_MODE_OFF);
- }
- //Deliberate fall through since there is no explicit power mode for
- //virtual displays.
- case HWC_DISPLAY_VIRTUAL:
- if(ctx->dpyAttr[HWC_DISPLAY_VIRTUAL].connected) {
- const int dpy = HWC_DISPLAY_VIRTUAL;
- if(mode == HWC_POWER_MODE_OFF and
- (not ctx->dpyAttr[dpy].isPause)) {
- if(!Overlay::displayCommit(ctx->dpyAttr[dpy].fd)) {
- ALOGE("%s: displayCommit failed for virtual", __FUNCTION__);
- ret = -1;
- }
- }
- ctx->dpyAttr[dpy].isActive = not(mode == HWC_POWER_MODE_OFF);
- }
- break;
- case HWC_DISPLAY_EXTERNAL:
- if(mode == HWC_POWER_MODE_OFF) {
- if(!Overlay::displayCommit(ctx->dpyAttr[dpy].fd)) {
- ALOGE("%s: displayCommit failed for external", __FUNCTION__);
- ret = -1;
- }
- }
- ctx->dpyAttr[dpy].isActive = not(mode == HWC_POWER_MODE_OFF);
- break;
- default:
- return -EINVAL;
- }
-
- ALOGD_IF(POWER_MODE_DEBUG, "%s: Done setting mode %d on display %d",
- __FUNCTION__, mode, dpy);
- return ret;
-}
-
-static void reset_panel(struct hwc_composer_device_1* dev)
-{
- int ret = 0;
- hwc_context_t* ctx = (hwc_context_t*)(dev);
-
- if (!ctx->dpyAttr[HWC_DISPLAY_PRIMARY].isActive) {
- ALOGD ("%s : Display OFF - Skip BLANK & UNBLANK", __FUNCTION__);
- ctx->mPanelResetStatus = false;
- return;
- }
-
- ALOGD("%s: setting power mode off", __FUNCTION__);
- ret = hwc_setPowerMode(dev, HWC_DISPLAY_PRIMARY, HWC_POWER_MODE_OFF);
- if (ret < 0) {
- ALOGE("%s: FBIOBLANK failed to BLANK: %s", __FUNCTION__,
- strerror(errno));
- }
-
- ALOGD("%s: setting power mode normal and enabling vsync", __FUNCTION__);
- ret = hwc_setPowerMode(dev, HWC_DISPLAY_PRIMARY, HWC_POWER_MODE_NORMAL);
- if (ret < 0) {
- ALOGE("%s: FBIOBLANK failed to UNBLANK : %s", __FUNCTION__,
- strerror(errno));
- }
- hwc_vsync_control(ctx, HWC_DISPLAY_PRIMARY, 1);
-
- ctx->mPanelResetStatus = false;
-}
-
-
-static int hwc_query(struct hwc_composer_device_1* dev,
- int param, int* value)
-{
- hwc_context_t* ctx = (hwc_context_t*)(dev);
- int supported = HWC_DISPLAY_PRIMARY_BIT;
-
- switch (param) {
- case HWC_BACKGROUND_LAYER_SUPPORTED:
- // Not supported for now
- value[0] = 0;
- break;
- case HWC_DISPLAY_TYPES_SUPPORTED:
- if(ctx->mMDP.hasOverlay) {
- supported |= HWC_DISPLAY_VIRTUAL_BIT;
- if(!(qdutils::MDPVersion::getInstance().is8x26() ||
- qdutils::MDPVersion::getInstance().is8x16() ||
- qdutils::MDPVersion::getInstance().is8x39()))
- supported |= HWC_DISPLAY_EXTERNAL_BIT;
- }
- value[0] = supported;
- break;
- case HWC_FORMAT_RB_SWAP:
- value[0] = 1;
- break;
- case HWC_COLOR_FILL:
- value[0] = 1;
- break;
- default:
- return -EINVAL;
- }
- return 0;
-
-}
-
-
-static int hwc_set_primary(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
- ATRACE_CALL();
- int ret = 0;
- const int dpy = HWC_DISPLAY_PRIMARY;
- if (LIKELY(list) && ctx->dpyAttr[dpy].isActive
- && !ctx->dpyAttr[dpy].isPause) {
- size_t last = list->numHwLayers - 1;
- hwc_layer_1_t *fbLayer = &list->hwLayers[last];
- int fd = -1; //FenceFD from the Copybit(valid in async mode)
- bool copybitDone = false;
-
- if (ctx->mCopyBit[dpy]) {
- if (ctx->mMDP.version < qdutils::MDP_V4_0)
- copybitDone = ctx->mCopyBit[dpy]->draw(ctx, list, dpy, &fd);
- else
- fd = ctx->mMDPComp[dpy]->drawOverlap(ctx, list);
- }
-
- if(list->numHwLayers > 1)
- hwc_sync(ctx, list, dpy, fd);
-
- // Dump the layers for primary
- if(ctx->mHwcDebug[dpy])
- ctx->mHwcDebug[dpy]->dumpLayers(list);
-
- if (!ctx->mMDPComp[dpy]->draw(ctx, list)) {
- ALOGE("%s: MDPComp draw failed", __FUNCTION__);
- ret = -1;
- }
-
- //TODO We dont check for SKIP flag on this layer because we need PAN
- //always. Last layer is always FB
- private_handle_t *hnd = (private_handle_t *)fbLayer->handle;
- if(copybitDone && ((ctx->mMDP.version >= qdutils::MDP_V4_0)
-#ifdef SUPPORT_BLIT_TO_FB
- || (ctx->mMDP.version == qdutils::MDP_V3_0_5)
-#endif
- )) {
- hnd = ctx->mCopyBit[dpy]->getCurrentRenderBuffer();
- }
-
- if(isAbcInUse(ctx) == true) {
- int index = ctx->listStats[dpy].renderBufIndexforABC;
- hwc_layer_1_t *tempLayer = &list->hwLayers[index];
- hnd = (private_handle_t *)tempLayer->handle;
- }
-
- if(hnd) {
- if (!ctx->mFBUpdate[dpy]->draw(ctx, hnd)) {
- ALOGE("%s: FBUpdate draw failed", __FUNCTION__);
- ret = -1;
- }
- }
-
- int lSplit = getLeftSplit(ctx, dpy);
- qhwc::ovutils::Dim lRoi = qhwc::ovutils::Dim(
- ctx->listStats[dpy].lRoi.left,
- ctx->listStats[dpy].lRoi.top,
- ctx->listStats[dpy].lRoi.right - ctx->listStats[dpy].lRoi.left,
- ctx->listStats[dpy].lRoi.bottom - ctx->listStats[dpy].lRoi.top);
-
- qhwc::ovutils::Dim rRoi = qhwc::ovutils::Dim(
- ctx->listStats[dpy].rRoi.left - lSplit,
- ctx->listStats[dpy].rRoi.top,
- ctx->listStats[dpy].rRoi.right - ctx->listStats[dpy].rRoi.left,
- ctx->listStats[dpy].rRoi.bottom - ctx->listStats[dpy].rRoi.top);
-
- if(!Overlay::displayCommit(ctx->dpyAttr[dpy].fd, lRoi, rRoi)) {
- ALOGE("%s: display commit fail for %d dpy!", __FUNCTION__, dpy);
- ret = -1;
- }
-
- }
-
- closeAcquireFds(list);
- return ret;
-}
-
-static int hwc_set_external(hwc_context_t *ctx,
- hwc_display_contents_1_t* list)
-{
- ATRACE_CALL();
- int ret = 0;
-
- const int dpy = HWC_DISPLAY_EXTERNAL;
-
- if (LIKELY(list) && ctx->dpyAttr[dpy].isActive &&
- ctx->dpyAttr[dpy].connected &&
- !ctx->dpyAttr[dpy].isPause) {
- size_t last = list->numHwLayers - 1;
- hwc_layer_1_t *fbLayer = &list->hwLayers[last];
- int fd = -1; //FenceFD from the Copybit(valid in async mode)
- bool copybitDone = false;
- if(ctx->mCopyBit[dpy])
- copybitDone = ctx->mCopyBit[dpy]->draw(ctx, list, dpy, &fd);
-
- if(list->numHwLayers > 1)
- hwc_sync(ctx, list, dpy, fd);
-
- // Dump the layers for external
- if(ctx->mHwcDebug[dpy])
- ctx->mHwcDebug[dpy]->dumpLayers(list);
-
- if (!ctx->mMDPComp[dpy]->draw(ctx, list)) {
- ALOGE("%s: MDPComp draw failed", __FUNCTION__);
- ret = -1;
- }
-
- private_handle_t *hnd = (private_handle_t *)fbLayer->handle;
- if(copybitDone) {
- hnd = ctx->mCopyBit[dpy]->getCurrentRenderBuffer();
- }
-
- if(hnd) {
- if (!ctx->mFBUpdate[dpy]->draw(ctx, hnd)) {
- ALOGE("%s: FBUpdate::draw fail!", __FUNCTION__);
- ret = -1;
- }
- }
-
- if(!Overlay::displayCommit(ctx->dpyAttr[dpy].fd)) {
- ALOGE("%s: display commit fail for %d dpy!", __FUNCTION__, dpy);
- ret = -1;
- }
- }
-
- closeAcquireFds(list);
- return ret;
-}
-
-static int hwc_set(hwc_composer_device_1 *dev,
- size_t numDisplays,
- hwc_display_contents_1_t** displays)
-{
- int ret = 0;
- hwc_context_t* ctx = (hwc_context_t*)(dev);
- for (int dpy = 0; dpy < (int)numDisplays; dpy++) {
- hwc_display_contents_1_t* list = displays[dpy];
- switch(dpy) {
- case HWC_DISPLAY_PRIMARY:
- ret = hwc_set_primary(ctx, list);
- break;
- case HWC_DISPLAY_EXTERNAL:
- ret = hwc_set_external(ctx, list);
- break;
- case HWC_DISPLAY_VIRTUAL:
- if(ctx->mHWCVirtual)
- ret = ctx->mHWCVirtual->set(ctx, list);
- break;
- default:
- ret = -EINVAL;
- }
- }
- // This is only indicative of how many times SurfaceFlinger posts
- // frames to the display.
- CALC_FPS();
- MDPComp::resetIdleFallBack();
- ctx->mVideoTransFlag = false;
- //Was locked at the beginning of prepare
- ctx->mDrawLock.unlock();
- return ret;
-}
-
-int hwc_getDisplayConfigs(struct hwc_composer_device_1* dev, int disp,
- uint32_t* configs, size_t* numConfigs) {
- int ret = 0;
- hwc_context_t* ctx = (hwc_context_t*)(dev);
-
- Locker::Autolock _l(ctx->mDrawLock);
-
- if(!validDisplay(disp)) {
- return -EINVAL;
- }
- //Currently we allow only 1 config, reported as config id # 0
- //This config is passed in to getDisplayAttributes. Ignored for now.
-
- switch(disp) {
- case HWC_DISPLAY_PRIMARY:
- if(*numConfigs > 0) {
- configs[0] = 0;
- *numConfigs = 1;
- }
- ret = 0; //NO_ERROR
- break;
- case HWC_DISPLAY_EXTERNAL:
- case HWC_DISPLAY_VIRTUAL:
- ret = -1; //Not connected
- if(ctx->dpyAttr[disp].connected) {
- ret = 0; //NO_ERROR
- if(*numConfigs > 0) {
- configs[0] = 0;
- *numConfigs = 1;
- }
- }
- break;
- }
- return ret;
-}
-
-int hwc_getDisplayAttributes(struct hwc_composer_device_1* dev, int disp,
- uint32_t /*config*/, const uint32_t* attributes, int32_t* values) {
-
- hwc_context_t* ctx = (hwc_context_t*)(dev);
-
- Locker::Autolock _l(ctx->mDrawLock);
-
- if(!validDisplay(disp)) {
- return -EINVAL;
- }
- //If hotpluggable displays(i.e, HDMI, WFD) are inactive return error
- if( (disp != HWC_DISPLAY_PRIMARY) && !ctx->dpyAttr[disp].connected) {
- return -1;
- }
-
- //From HWComposer
- static const uint32_t DISPLAY_ATTRIBUTES[] = {
- HWC_DISPLAY_VSYNC_PERIOD,
- HWC_DISPLAY_WIDTH,
- HWC_DISPLAY_HEIGHT,
- HWC_DISPLAY_DPI_X,
- HWC_DISPLAY_DPI_Y,
-#ifdef GET_FRAMEBUFFER_FORMAT_FROM_HWC
- HWC_DISPLAY_FBFORMAT,
-#endif
- HWC_DISPLAY_NO_ATTRIBUTE,
- };
-
- const size_t NUM_DISPLAY_ATTRIBUTES = (sizeof(DISPLAY_ATTRIBUTES) /
- sizeof(DISPLAY_ATTRIBUTES)[0]);
-
- for (size_t i = 0; i < NUM_DISPLAY_ATTRIBUTES - 1; i++) {
- switch (attributes[i]) {
- case HWC_DISPLAY_VSYNC_PERIOD:
- values[i] = ctx->dpyAttr[disp].vsync_period;
- break;
- case HWC_DISPLAY_WIDTH:
- if (ctx->dpyAttr[disp].customFBSize)
- values[i] = ctx->dpyAttr[disp].xres_new;
- else
- values[i] = ctx->dpyAttr[disp].xres;
-
- ALOGD("%s disp = %d, width = %d",__FUNCTION__, disp,
- values[i]);
- break;
- case HWC_DISPLAY_HEIGHT:
- if (ctx->dpyAttr[disp].customFBSize)
- values[i] = ctx->dpyAttr[disp].yres_new;
- else
- values[i] = ctx->dpyAttr[disp].yres;
- ALOGD("%s disp = %d, height = %d",__FUNCTION__, disp,
- values[i]);
- break;
- case HWC_DISPLAY_DPI_X:
- values[i] = (int32_t) (ctx->dpyAttr[disp].xdpi*1000.0);
- break;
- case HWC_DISPLAY_DPI_Y:
- values[i] = (int32_t) (ctx->dpyAttr[disp].ydpi*1000.0);
- break;
-#ifdef GET_FRAMEBUFFER_FORMAT_FROM_HWC
- case HWC_DISPLAY_FBFORMAT:
- values[i] = ctx->dpyAttr[disp].fbformat;
- break;
-#endif
- default:
- ALOGE("Unknown display attribute %d",
- attributes[i]);
- return -EINVAL;
- }
- }
- return 0;
-}
-
-void hwc_dump(struct hwc_composer_device_1* dev, char *buff, int buff_len)
-{
- hwc_context_t* ctx = (hwc_context_t*)(dev);
- Locker::Autolock _l(ctx->mDrawLock);
- android::String8 aBuf("");
- dumpsys_log(aBuf, "Qualcomm HWC state:\n");
- dumpsys_log(aBuf, " MDPVersion=%d\n", ctx->mMDP.version);
- dumpsys_log(aBuf, " DisplayPanel=%c\n", ctx->mMDP.panel);
- dumpsys_log(aBuf, " DynRefreshRate=%d\n",
- ctx->dpyAttr[HWC_DISPLAY_PRIMARY].dynRefreshRate);
- for(int dpy = 0; dpy < HWC_NUM_DISPLAY_TYPES; dpy++) {
- if(ctx->mMDPComp[dpy])
- ctx->mMDPComp[dpy]->dump(aBuf, ctx);
- }
- char ovDump[2048] = {'\0'};
- ctx->mOverlay->getDump(ovDump, 2048);
- dumpsys_log(aBuf, ovDump);
- ovDump[0] = '\0';
- ctx->mRotMgr->getDump(ovDump, 1024);
- dumpsys_log(aBuf, ovDump);
- ovDump[0] = '\0';
- if(Writeback::getDump(ovDump, 1024)) {
- dumpsys_log(aBuf, ovDump);
- ovDump[0] = '\0';
- }
- dumpsys_log(aBuf, "Copybit::isAbcInUse=%d\n\n",isAbcInUse(ctx) ? 1 : 0);
- strlcpy(buff, aBuf.string(), buff_len);
-}
-
-int hwc_getActiveConfig(struct hwc_composer_device_1* dev, int disp) {
- hwc_context_t* ctx = (hwc_context_t*)(dev);
- Locker::Autolock _l(ctx->mDrawLock);
- if(!validDisplay(disp)) {
- return -EINVAL;
- }
-
- //Supports only the default config (0th index) for now
- return 0;
-}
-
-int hwc_setActiveConfig(struct hwc_composer_device_1* dev, int disp,
- int index) {
- hwc_context_t* ctx = (hwc_context_t*)(dev);
- Locker::Autolock _l(ctx->mDrawLock);
- if(!validDisplay(disp)) {
- return -EINVAL;
- }
-
- //Supports only the default config (0th index) for now
- return (index == 0) ? index : -EINVAL;
-}
-
-static int hwc_device_close(struct hw_device_t *dev)
-{
- if(!dev) {
- ALOGE("%s: NULL device pointer", __FUNCTION__);
- return -1;
- }
- closeContext((hwc_context_t*)dev);
- free(dev);
-
- return 0;
-}
-
-static int hwc_device_open(const struct hw_module_t* module, const char* name,
- struct hw_device_t** device)
-{
- int status = -EINVAL;
-
- if (!strcmp(name, HWC_HARDWARE_COMPOSER)) {
- struct hwc_context_t *dev;
- dev = (hwc_context_t*)malloc(sizeof(*dev));
- if(dev == NULL)
- return status;
- memset(dev, 0, sizeof(*dev));
-
- //Initialize hwc context
- initContext(dev);
-
- //Setup HWC methods
- dev->device.common.tag = HARDWARE_DEVICE_TAG;
- dev->device.common.version = HWC_DEVICE_API_VERSION_1_5;
- dev->device.common.module = const_cast<hw_module_t*>(module);
- dev->device.common.close = hwc_device_close;
- dev->device.prepare = hwc_prepare;
- dev->device.set = hwc_set;
- dev->device.eventControl = hwc_eventControl;
- dev->device.setPowerMode = hwc_setPowerMode;
- dev->device.query = hwc_query;
- dev->device.registerProcs = hwc_registerProcs;
- dev->device.dump = hwc_dump;
- dev->device.getDisplayConfigs = hwc_getDisplayConfigs;
- dev->device.getDisplayAttributes = hwc_getDisplayAttributes;
- dev->device.getActiveConfig = hwc_getActiveConfig;
- dev->device.setActiveConfig = hwc_setActiveConfig;
- *device = &dev->device.common;
- status = 0;
- }
- return status;
-}
diff --git a/msm8909/libhwcomposer/hwc_ad.cpp b/msm8909/libhwcomposer/hwc_ad.cpp
deleted file mode 100644
index 7e96d97e..00000000
--- a/msm8909/libhwcomposer/hwc_ad.cpp
+++ /dev/null
@@ -1,278 +0,0 @@
-/*
-* Copyright (c) 2013-2014 The Linux Foundation. All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions are
-* met:
-* * Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
-* * Redistributions in binary form must reproduce the above
-* copyright notice, this list of conditions and the following
-* disclaimer in the documentation and/or other materials provided
-* with the distribution.
-* * Neither the name of The Linux Foundation. nor the names of its
-* contributors may be used to endorse or promote products derived
-* from this software without specific prior written permission.
-*
-* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
-* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
-* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
-* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
-* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
-* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-#include <unistd.h>
-#include <overlay.h>
-#include <overlayUtils.h>
-#include <overlayWriteback.h>
-#include <mdp_version.h>
-#include "hwc_ad.h"
-#include "hwc_utils.h"
-
-#define DEBUG 0
-using namespace overlay;
-using namespace overlay::utils;
-namespace qhwc {
-
-//Helper to write data to ad node
-static void adWrite(const int& value) {
- const int wbFbNum = Overlay::getFbForDpy(Overlay::DPY_WRITEBACK);
- char wbFbPath[256];
- snprintf (wbFbPath, sizeof(wbFbPath),
- "/sys/class/graphics/fb%d/ad", wbFbNum);
- int adFd = open(wbFbPath, O_WRONLY);
- if(adFd >= 0) {
- char opStr[4] = "";
- snprintf(opStr, sizeof(opStr), "%d", value);
- ssize_t ret = write(adFd, opStr, strlen(opStr));
- if(ret < 0) {
- ALOGE("%s: Failed to write %d with error %s",
- __func__, value, strerror(errno));
- } else if (ret == 0){
- ALOGE("%s Nothing written to ad", __func__);
- } else {
- ALOGD_IF(DEBUG, "%s: Wrote %d to ad", __func__, value);
- }
- close(adFd);
- } else {
- ALOGE("%s: Failed to open /sys/class/graphics/fb%d/ad with error %s",
- __func__, wbFbNum, strerror(errno));
- }
-}
-
-//Helper to read data from ad node
-static int adRead() {
- const int wbFbNum = Overlay::getFbForDpy(Overlay::DPY_WRITEBACK);
- int ret = -1;
- char wbFbPath[256];
- snprintf (wbFbPath, sizeof(wbFbPath),
- "/sys/class/graphics/fb%d/ad", wbFbNum);
- int adFd = open(wbFbPath, O_RDONLY);
- if(adFd >= 0) {
- char opStr[4];
- ssize_t bytesRead = read(adFd, opStr, sizeof(opStr) - 1);
- if(bytesRead > 0) {
- opStr[bytesRead] = '\0';
- //Should return -1, 0 or 1
- ret = atoi(opStr);
- ALOGD_IF(DEBUG, "%s: Read %d from ad", __func__, ret);
- } else if(bytesRead == 0) {
- ALOGE("%s: ad node empty", __func__);
- } else {
- ALOGE("%s: Read from ad node failed with error %s", __func__,
- strerror(errno));
- }
- close(adFd);
- } else {
- ALOGD("%s: /sys/class/graphics/fb%d/ad could not be opened : %s",
- __func__, wbFbNum, strerror(errno));
- }
- return ret;
-}
-
-AssertiveDisplay::AssertiveDisplay(hwc_context_t *ctx) :
- mTurnedOff(true), mFeatureEnabled(false),
- mDest(overlay::utils::OV_INVALID)
-{
- //Values in ad node:
- //-1 means feature is disabled on device
- // 0 means feature exists but turned off, will be turned on by hwc
- // 1 means feature is turned on by hwc
- // Plus, we do this feature only on split primary displays.
- // Plus, we do this feature only if ro.qcom.ad=2
-
- char property[PROPERTY_VALUE_MAX];
- const int ENABLED = 2;
- int val = 0;
-
- if(property_get("ro.qcom.ad", property, "0") > 0) {
- val = atoi(property);
- }
-
- if(adRead() >= 0 && isDisplaySplit(ctx, HWC_DISPLAY_PRIMARY) &&
- val == ENABLED) {
- ALOGD_IF(DEBUG, "Assertive display feature supported");
- mFeatureEnabled = true;
- // If feature exists but is turned off, set mTurnedOff to true
- mTurnedOff = adRead() > 0 ? false : true;
- }
-}
-
-void AssertiveDisplay::markDoable(hwc_context_t *ctx,
- const hwc_display_contents_1_t* list) {
- mDoable = false;
- if(mFeatureEnabled &&
- !isSecondaryConnected(ctx) &&
- ctx->listStats[HWC_DISPLAY_PRIMARY].yuvCount == 1) {
- int nYuvIndex = ctx->listStats[HWC_DISPLAY_PRIMARY].yuvIndices[0];
- const hwc_layer_1_t* layer = &list->hwLayers[nYuvIndex];
- private_handle_t *hnd = (private_handle_t *)layer->handle;
- qdutils::MDPVersion& mdpHw = qdutils::MDPVersion::getInstance();
- if(hnd && hnd->width <= (int) mdpHw.getMaxMixerWidth()) {
- mDoable = true;
- }
- }
-}
-
-void AssertiveDisplay::turnOffAD() {
- if(mFeatureEnabled) {
- if(!mTurnedOff) {
- const int off = 0;
- adWrite(off);
- mTurnedOff = true;
- }
- }
- mDoable = false;
-}
-
-bool AssertiveDisplay::prepare(hwc_context_t *ctx,
- const hwc_rect_t& crop,
- const Whf& whf,
- const private_handle_t *hnd) {
- if(!isDoable()) {
- //Cleanup one time during this switch
- turnOffAD();
- return false;
- }
-
- Overlay::PipeSpecs pipeSpecs;
- pipeSpecs.formatClass = Overlay::FORMAT_YUV;
- pipeSpecs.dpy = overlay::Overlay::DPY_WRITEBACK;
- pipeSpecs.fb = false;
-
- ovutils::eDest dest = ctx->mOverlay->getPipe(pipeSpecs);
- if(dest == OV_INVALID) {
- ALOGE("%s failed: No VG pipe available", __func__);
- mDoable = false;
- return false;
- }
-
- overlay::Writeback *wb = overlay::Writeback::getInstance();
-
- //Set Security flag on writeback
- if(isSecureBuffer(hnd)) {
- if(!wb->setSecure(isSecureBuffer(hnd))) {
- ALOGE("Failure in setting WB secure flag for ad");
- return false;
- }
- }
-
- if(!wb->configureDpyInfo(hnd->width, hnd->height)) {
- ALOGE("%s: config display failed", __func__);
- mDoable = false;
- return false;
- }
-
- int tmpW, tmpH;
- size_t size;
- int format = ovutils::getHALFormat(wb->getOutputFormat());
- if(format < 0) {
- ALOGE("%s invalid format %d", __func__, format);
- mDoable = false;
- return false;
- }
-
- size = getBufferSizeAndDimensions(hnd->width, hnd->height,
- format, tmpW, tmpH);
-
- if(!wb->configureMemory((uint32_t)size)) {
- ALOGE("%s: config memory failed", __func__);
- mDoable = false;
- return false;
- }
-
- eMdpFlags mdpFlags = OV_MDP_FLAGS_NONE;
- if(isSecureBuffer(hnd)) {
- ovutils::setMdpFlags(mdpFlags,
- ovutils::OV_MDP_SECURE_OVERLAY_SESSION);
- }
-
- PipeArgs parg(mdpFlags, whf, ZORDER_0,
- ROT_FLAGS_NONE);
- hwc_rect_t dst = crop; //input same as output
-
- if(configMdp(ctx->mOverlay, parg, OVERLAY_TRANSFORM_0, crop, dst, NULL,
- dest) < 0) {
- ALOGE("%s: configMdp failed", __func__);
- mDoable = false;
- return false;
- }
-
- mDest = dest;
- int wbFd = wb->getFbFd();
- if(mFeatureEnabled && wbFd >= 0 &&
- !ctx->mOverlay->validateAndSet(overlay::Overlay::DPY_WRITEBACK, wbFd))
- {
- ALOGE("%s: Failed to validate and set overlay for dpy %d"
- ,__FUNCTION__, overlay::Overlay::DPY_WRITEBACK);
- turnOffAD();
- return false;
- }
-
- // Only turn on AD if there are no errors during configuration stage
- // and if it was previously in OFF state.
- if(mFeatureEnabled && mTurnedOff) {
- //write to sysfs, one time during this switch
- const int on = 1;
- adWrite(on);
- mTurnedOff = false;
- }
-
- return true;
-}
-
-bool AssertiveDisplay::draw(hwc_context_t *ctx, int fd, uint32_t offset) {
- if(!isDoable()) {
- return false;
- }
-
- if (!ctx->mOverlay->queueBuffer(fd, offset, mDest)) {
- ALOGE("%s: queueBuffer failed", __func__);
- return false;
- }
-
- overlay::Writeback *wb = overlay::Writeback::getInstance();
- if(!wb->writeSync()) {
- return false;
- }
-
- return true;
-}
-
-int AssertiveDisplay::getDstFd() const {
- overlay::Writeback *wb = overlay::Writeback::getInstance();
- return wb->getDstFd();
-}
-
-uint32_t AssertiveDisplay::getDstOffset() const {
- overlay::Writeback *wb = overlay::Writeback::getInstance();
- return wb->getOffset();
-}
-
-}
diff --git a/msm8909/libhwcomposer/hwc_copybit.cpp b/msm8909/libhwcomposer/hwc_copybit.cpp
deleted file mode 100644
index 4b70b130..00000000
--- a/msm8909/libhwcomposer/hwc_copybit.cpp
+++ /dev/null
@@ -1,1382 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- * Copyright (C) 2012-2016, The Linux Foundation. All rights reserved.
- *
- * Not a Contribution.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define DEBUG_COPYBIT 0
-#include <copybit.h>
-#include <utils/Timers.h>
-#include <mdp_version.h>
-#include "hwc_copybit.h"
-#include "comptype.h"
-#include "gr.h"
-#include "cb_utils.h"
-#include "cb_swap_rect.h"
-#include "math.h"
-#include "sync/sync.h"
-
-using namespace qdutils;
-namespace qhwc {
-
-struct range {
- int current;
- int end;
-};
-struct region_iterator : public copybit_region_t {
-
- region_iterator(hwc_region_t region) {
- mRegion = region;
- r.end = (int)region.numRects;
- r.current = 0;
- this->next = iterate;
- }
-
-private:
- static int iterate(copybit_region_t const * self, copybit_rect_t* rect){
- if (!self || !rect) {
- ALOGE("iterate invalid parameters");
- return 0;
- }
-
- region_iterator const* me =
- static_cast<region_iterator const*>(self);
- if (me->r.current != me->r.end) {
- rect->l = me->mRegion.rects[me->r.current].left;
- rect->t = me->mRegion.rects[me->r.current].top;
- rect->r = me->mRegion.rects[me->r.current].right;
- rect->b = me->mRegion.rects[me->r.current].bottom;
- me->r.current++;
- return 1;
- }
- return 0;
- }
-
- hwc_region_t mRegion;
- mutable range r;
-};
-
-void CopyBit::reset() {
- mIsModeOn = false;
- mCopyBitDraw = false;
-}
-
-bool CopyBit::canUseCopybitForYUV(hwc_context_t *ctx) {
- // return true for non-overlay targets
- if(ctx->mMDP.hasOverlay && ctx->mMDP.version >= qdutils::MDP_V4_0) {
- return false;
- }
- return true;
-}
-
-bool CopyBit::isSmartBlitPossible(const hwc_display_contents_1_t *list){
- if(list->numHwLayers > 2) {
- hwc_rect_t displayFrame0 = {0, 0, 0, 0};
- hwc_rect_t displayFrame1 = {0, 0, 0, 0};
- int layer0_transform = 0;
- int layer1_transform = 0;
- int isYuvLayer0 = 0;
- int isYuvLayer1 = 0;
- for (unsigned int i=0; i<list->numHwLayers -1; i++) {
- hwc_rect_t displayFrame = list->hwLayers[i].displayFrame;
- if (mSwapRect)
- displayFrame = getIntersection(mDirtyRect,
- list->hwLayers[i].displayFrame);
- if (isValidRect(displayFrame) && !isValidRect(displayFrame0)) {
- displayFrame0 = displayFrame;
- private_handle_t *hnd =(private_handle_t *)list->hwLayers[i].handle;
- isYuvLayer0 = isYuvBuffer(hnd);
- layer0_transform = list->hwLayers[i].transform;
- } else if(isValidRect(displayFrame)) {
- displayFrame1 = displayFrame;
- layer1_transform = list->hwLayers[i].transform;
- private_handle_t *hnd =(private_handle_t *)list->hwLayers[i].handle;
- isYuvLayer1 = isYuvBuffer(hnd);
- break;
- }
- }
- /*
- * smart blit enable only if
- * 1. Both layers should have same ROI.
- * 2. Both layers can't be video layer.
- * 3. Should not be any rotation for base RGB layer.
- * 4. In case of base layer as video, next above RGB layer
- * should not contains any rotation.
- */
- if((displayFrame0 == displayFrame1) && not (isYuvLayer1 && isYuvLayer0)) {
- if (isYuvLayer0) {
- if (not layer1_transform) {
- ALOGD_IF(DEBUG_COPYBIT,"%s:Smart Bilt Possible",__FUNCTION__);
- return true;
- }
- } else if (not layer0_transform) {
- ALOGD_IF(DEBUG_COPYBIT,"%s:Smart Bilt Possible",__FUNCTION__);
- return true;
- }
- }
- }
- return false;
-}
-
-bool CopyBit::canUseCopybitForRGB(hwc_context_t *ctx,
- hwc_display_contents_1_t *list,
- int dpy) {
- int compositionType = qdutils::QCCompositionType::
- getInstance().getCompositionType();
-
- if (compositionType & qdutils::COMPOSITION_TYPE_DYN) {
- // DYN Composition:
- // use copybit, if (TotalRGBRenderArea < threashold * FB Area)
- // this is done based on perf inputs in ICS
- // TODO: Above condition needs to be re-evaluated in JB
- int fbWidth = ctx->dpyAttr[dpy].xres;
- int fbHeight = ctx->dpyAttr[dpy].yres;
- unsigned int fbArea = (fbWidth * fbHeight);
- unsigned int renderArea = getRGBRenderingArea(ctx, list);
- ALOGD_IF (DEBUG_COPYBIT, "%s:renderArea %u, fbArea %u",
- __FUNCTION__, renderArea, fbArea);
- double dynThreshold = mDynThreshold;
- if(not isSmartBlitPossible(list))
- dynThreshold -= 1;
-
- if (renderArea < (dynThreshold * fbArea)) {
- return true;
- }
- } else if ((compositionType & qdutils::COMPOSITION_TYPE_MDP)) {
- // MDP composition, use COPYBIT always
- return true;
- } else if ((compositionType & qdutils::COMPOSITION_TYPE_C2D)) {
- // C2D composition, use COPYBIT
- return true;
- }
- return false;
-}
-
-unsigned int CopyBit::getRGBRenderingArea (const hwc_context_t *ctx,
- const hwc_display_contents_1_t *list) {
- //Calculates total rendering area for RGB layers
- unsigned int renderArea = 0;
- unsigned int w=0, h=0;
- // Skipping last layer since FrameBuffer layer should not affect
- // which composition to choose
- for (unsigned int i=0; i<list->numHwLayers -1; i++) {
- private_handle_t *hnd = (private_handle_t *)list->hwLayers[i].handle;
- if (hnd) {
- if (BUFFER_TYPE_UI == hnd->bufferType && !ctx->copybitDrop[i]) {
- getLayerResolution(&list->hwLayers[i], w, h);
- renderArea += (w*h);
- }
- }
- }
- return renderArea;
-}
-
-bool CopyBit::isLayerChanging(hwc_context_t *ctx,
- hwc_display_contents_1_t *list, int k) {
- if((mLayerCache.hnd[k] != list->hwLayers[k].handle) ||
- (mLayerCache.drop[k] != ctx->copybitDrop[k]) ||
- (mLayerCache.displayFrame[k].left !=
- list->hwLayers[k].displayFrame.left) ||
- (mLayerCache.displayFrame[k].top !=
- list->hwLayers[k].displayFrame.top) ||
- (mLayerCache.displayFrame[k].right !=
- list->hwLayers[k].displayFrame.right) ||
- (mLayerCache.displayFrame[k].bottom !=
- list->hwLayers[k].displayFrame.bottom)) {
- return 1;
- }
- return 0;
-}
-
-bool CopyBit::prepareSwapRect(hwc_context_t *ctx,
- hwc_display_contents_1_t *list,
- int dpy) {
- bool canUseSwapRect = 0;
- hwc_rect_t dirtyRect = {0, 0, 0, 0};
- hwc_rect_t displayRect = {0, 0, 0, 0};
- hwc_rect fullFrame = (struct hwc_rect) {0, 0,(int)ctx->dpyAttr[dpy].xres,
- (int)ctx->dpyAttr[dpy].yres};
- if((mLayerCache.layerCount != ctx->listStats[dpy].numAppLayers) ||
- list->flags & HWC_GEOMETRY_CHANGED || not mSwapRectEnable) {
- mLayerCache.reset();
- mFbCache.reset();
- mLayerCache.updateCounts(ctx,list,dpy);
- mDirtyRect = displayRect;
- return 0;
- }
-
- int updatingLayerCount = 0;
- for (int k = ctx->listStats[dpy].numAppLayers-1; k >= 0 ; k--){
- //swap rect will kick in only for single updating layer
- if(isLayerChanging(ctx, list, k)) {
- updatingLayerCount ++;
- hwc_layer_1_t layer = list->hwLayers[k];
- canUseSwapRect = 1;
-#ifdef QTI_BSP
- dirtyRect = getUnion(dirtyRect, calculateDirtyRect(&layer,fullFrame));
-#else
- (void)fullFrame;
-#endif
- displayRect = getUnion(displayRect, layer.displayFrame);
- }
- }
- //since we are using more than one framebuffers,we have to
- //kick in swap rect only if we are getting continuous same
- //dirty rect for same layer at least equal of number of
- //framebuffers
-
- if (canUseSwapRect || updatingLayerCount == 0) {
- if (updatingLayerCount == 0) {
- dirtyRect.left = INVALID_DIMENSION;
- dirtyRect.top = INVALID_DIMENSION;
- dirtyRect.right = INVALID_DIMENSION;
- dirtyRect.bottom = INVALID_DIMENSION;
- canUseSwapRect = 1;
- }
-
- for (int k = ctx->listStats[dpy].numAppLayers-1; k >= 0 ; k--) {
- //disable swap rect in case of scaling and video .
- private_handle_t *hnd =(private_handle_t *)list->hwLayers[k].handle;
- if(needsScaling(&list->hwLayers[k])||( hnd && isYuvBuffer(hnd)) ||
- (list->hwLayers[k].transform & HAL_TRANSFORM_ROT_90)) {
- mFbCache.reset();
- displayRect.bottom = 0;
- displayRect.top = 0;
- displayRect.right = 0;
- displayRect.bottom = 0;
- mDirtyRect = displayRect;
- return 0;
- }
- }
-
- if(mFbCache.getUnchangedFbDRCount(dirtyRect, displayRect) <
- NUM_RENDER_BUFFERS) {
- mFbCache.insertAndUpdateFbCache(dirtyRect, displayRect);
- canUseSwapRect = 0;
- displayRect.bottom = 0;
- displayRect.top = 0;
- displayRect.right = 0;
- displayRect.bottom = 0;
- }
- } else {
- mFbCache.reset();
- canUseSwapRect = 0;
- displayRect.bottom = 0;
- displayRect.top = 0;
- displayRect.right = 0;
- displayRect.bottom = 0;
-
- }
- mDirtyRect = displayRect;
- mLayerCache.updateCounts(ctx,list,dpy);
- return canUseSwapRect;
-}
-
-bool CopyBit::prepareOverlap(hwc_context_t *ctx,
- hwc_display_contents_1_t *list) {
-
- if (ctx->mMDP.version < qdutils::MDP_V4_0) {
- ALOGE("%s: Invalid request", __FUNCTION__);
- return false;
- }
-
- if (mEngine == NULL || !(validateParams(ctx, list))) {
- ALOGE("%s: Invalid Params", __FUNCTION__);
- return false;
- }
- PtorInfo* ptorInfo = &(ctx->mPtorInfo);
-
- // Allocate render buffers if they're not allocated
- int alignW = 0, alignH = 0;
- int finalW = 0, finalH = 0;
- for (int i = 0; i < ptorInfo->count; i++) {
- int ovlapIndex = ptorInfo->layerIndex[i];
- hwc_rect_t overlap = list->hwLayers[ovlapIndex].displayFrame;
- // render buffer width will be the max of two layers
- // Align Widht and height to 32, Mdp would be configured
- // with Aligned overlap w/h
- finalW = max(finalW, ALIGN((overlap.right - overlap.left), 32));
- finalH += ALIGN((overlap.bottom - overlap.top), 32);
- if(finalH > ALIGN((overlap.bottom - overlap.top), 32)) {
- // Calculate the dest top, left will always be zero
- ptorInfo->displayFrame[i].top = (finalH -
- (ALIGN((overlap.bottom - overlap.top), 32)));
- }
- // calculate the right and bottom values
- ptorInfo->displayFrame[i].right = ptorInfo->displayFrame[i].left +
- (overlap.right - overlap.left);
- ptorInfo->displayFrame[i].bottom = ptorInfo->displayFrame[i].top +
- (overlap.bottom - overlap.top);
- }
-
- getBufferSizeAndDimensions(finalW, finalH, HAL_PIXEL_FORMAT_RGBA_8888,
- alignW, alignH);
-
- if ((mAlignedWidth != alignW) || (mAlignedHeight != alignH)) {
- // Overlap rect has changed, so free render buffers
- freeRenderBuffers();
- }
-
- int ret = allocRenderBuffers(alignW, alignH, HAL_PIXEL_FORMAT_RGBA_8888);
-
- if (ret < 0) {
- ALOGE("%s: Render buffer allocation failed", __FUNCTION__);
- return false;
- }
-
- mAlignedWidth = alignW;
- mAlignedHeight = alignH;
- mCurRenderBufferIndex = (mCurRenderBufferIndex + 1) % NUM_RENDER_BUFFERS;
- return true;
-}
-
-bool CopyBit::prepare(hwc_context_t *ctx, hwc_display_contents_1_t *list,
- int dpy) {
-
- if(mEngine == NULL) {
- // No copybit device found - cannot use copybit
- return false;
- }
-
- if(ctx->mThermalBurstMode) {
- ALOGD_IF (DEBUG_COPYBIT, "%s:Copybit failed,"
- "Running in Thermal Burst mode",__FUNCTION__);
- return false;
- }
-
- int compositionType = qdutils::QCCompositionType::
- getInstance().getCompositionType();
-
- if ((compositionType == qdutils::COMPOSITION_TYPE_GPU) ||
- (compositionType == qdutils::COMPOSITION_TYPE_CPU)) {
- //GPU/CPU composition, don't change layer composition type
- return true;
- }
-
- if(!(validateParams(ctx, list))) {
- ALOGE("%s:Invalid Params", __FUNCTION__);
- return false;
- }
-
- if(ctx->listStats[dpy].skipCount) {
- //GPU will be anyways used
- return false;
- }
-
- if (ctx->listStats[dpy].numAppLayers > MAX_NUM_APP_LAYERS) {
- // Reached max layers supported by HWC.
- return false;
- }
-
- int last = (uint32_t)list->numHwLayers - 1;
- mDirtyRect = list->hwLayers[last].displayFrame;
- mSwapRect = prepareSwapRect(ctx, list, dpy);
- ALOGD_IF (DEBUG_COPYBIT, "%s: mSwapRect: %d mDirtyRect: [%d, %d, %d, %d]",
- __FUNCTION__, mSwapRect, mDirtyRect.left,
- mDirtyRect.top, mDirtyRect.right, mDirtyRect.bottom);
-
- bool useCopybitForYUV = canUseCopybitForYUV(ctx);
- bool useCopybitForRGB = canUseCopybitForRGB(ctx, list, dpy);
- LayerProp *layerProp = ctx->layerProp[dpy];
-
- // Following are MDP3 limitations for which we
- // need to fallback to GPU composition:
- // 1. Plane alpha is not supported by MDP3.
- // 2. Scaling is within range
- if (qdutils::MDPVersion::getInstance().getMDPVersion() < 400) {
- for (int i = ctx->listStats[dpy].numAppLayers-1; i >= 0 ; i--) {
- int dst_h, dst_w, src_h, src_w;
- float dx, dy;
- if(ctx->copybitDrop[i]) {
- continue;
- }
- hwc_layer_1_t *layer = (hwc_layer_1_t *) &list->hwLayers[i];
- if (layer->planeAlpha != 0xFF)
- return true;
-
- if (layer->transform) {
- ALOGD_IF (DEBUG_COPYBIT, "%s: Do GPU comp Transform : %d",
- __FUNCTION__, layer->transform);
- return true;
- }
- hwc_rect_t sourceCrop = integerizeSourceCrop(layer->sourceCropf);
-
- if (has90Transform(layer)) {
- src_h = sourceCrop.right - sourceCrop.left;
- src_w = sourceCrop.bottom - sourceCrop.top;
- } else {
- src_h = sourceCrop.bottom - sourceCrop.top;
- src_w = sourceCrop.right - sourceCrop.left;
- }
- dst_h = layer->displayFrame.bottom - layer->displayFrame.top;
- dst_w = layer->displayFrame.right - layer->displayFrame.left;
-
- if(src_w <=0 || src_h<=0 ||dst_w<=0 || dst_h<=0 ) {
- ALOGE("%s: wrong params for display screen_w=%d \
- src_crop_width=%d screen_h=%d src_crop_height=%d",
- __FUNCTION__, dst_w,src_w,dst_h,src_h);
- return false;
- }
- dx = (float)dst_w/(float)src_w;
- dy = (float)dst_h/(float)src_h;
-
- float scale_factor_max = MAX_SCALE_FACTOR;
- float scale_factor_min = MIN_SCALE_FACTOR;
-
- if (isAlphaPresent(layer)) {
- scale_factor_max = MAX_SCALE_FACTOR/4;
- scale_factor_min = MIN_SCALE_FACTOR*4;
- }
-
- if (dx > scale_factor_max || dx < scale_factor_min)
- return false;
-
- if (dy > scale_factor_max || dy < scale_factor_min)
- return false;
- }
- }
-
- //Allocate render buffers if they're not allocated
- if ((ctx->mMDP.version != qdutils::MDP_V3_0_4 &&
-#ifdef SUPPORT_BLIT_TO_FB
- ctx->mMDP.version == qdutils::MDP_V3_0_5
-#else
- ctx->mMDP.version != qdutils::MDP_V3_0_5
-#endif
- ) && (useCopybitForYUV || useCopybitForRGB)) {
- int ret = allocRenderBuffers(mAlignedWidth,
- mAlignedHeight,
- HAL_PIXEL_FORMAT_RGBA_8888);
- if (ret < 0) {
- return false;
- } else {
- mCurRenderBufferIndex = (mCurRenderBufferIndex + 1) %
- NUM_RENDER_BUFFERS;
- }
- }
-
- // We cannot mix copybit layer with layers marked to be drawn on FB
- if (!useCopybitForYUV && ctx->listStats[dpy].yuvCount)
- return true;
-
- mCopyBitDraw = false;
- if (useCopybitForRGB &&
- (useCopybitForYUV || !ctx->listStats[dpy].yuvCount)) {
- mCopyBitDraw = true;
- // numAppLayers-1, as we iterate till 0th layer index
- // Mark all layers to be drawn by copybit
- for (int i = ctx->listStats[dpy].numAppLayers-1; i >= 0 ; i--) {
- layerProp[i].mFlags |= HWC_COPYBIT;
-#ifdef QTI_BSP
- if (ctx->mMDP.version == qdutils::MDP_V3_0_4 ||
- ctx->mMDP.version == qdutils::MDP_V3_0_5)
- list->hwLayers[i].compositionType = HWC_BLIT;
- else
-#endif
- list->hwLayers[i].compositionType = HWC_OVERLAY;
- }
- }
-
- return true;
-}
-
-int CopyBit::clear (private_handle_t* hnd, hwc_rect_t& rect)
-{
- int ret = 0;
- copybit_rect_t clear_rect = {rect.left, rect.top,
- rect.right,
- rect.bottom};
-
- copybit_image_t buf;
- buf.w = ALIGN(getWidth(hnd),32);
- buf.h = getHeight(hnd);
- buf.format = hnd->format;
- buf.base = (void *)hnd->base;
- buf.handle = (native_handle_t *)hnd;
-
- copybit_device_t *copybit = mEngine;
- ret = copybit->clear(copybit, &buf, &clear_rect);
- return ret;
-}
-
-bool CopyBit::drawUsingAppBufferComposition(hwc_context_t *ctx,
- hwc_display_contents_1_t *list,
- int dpy, int *copybitFd) {
- int layerCount = 0;
- uint32_t last = (uint32_t)list->numHwLayers - 1;
- hwc_layer_1_t *fbLayer = &list->hwLayers[last];
- private_handle_t *fbhnd = (private_handle_t *)fbLayer->handle;
-
- if(ctx->enableABC == false)
- return false;
-
- if(ctx->listStats[dpy].numAppLayers > MAX_LAYERS_FOR_ABC )
- return false;
-
- layerCount = ctx->listStats[dpy].numAppLayers;
- //bottom most layer should
- //equal to FB
- hwc_layer_1_t *tmpLayer = &list->hwLayers[0];
- private_handle_t *hnd = (private_handle_t *)tmpLayer->handle;
- if(hnd && fbhnd && (hnd->size == fbhnd->size) &&
- (hnd->width == fbhnd->width) && (hnd->height == fbhnd->height)){
- if(tmpLayer->transform ||
- (list->flags & HWC_GEOMETRY_CHANGED) ||
- (!(hnd->format == HAL_PIXEL_FORMAT_RGBA_8888 ||
- hnd->format == HAL_PIXEL_FORMAT_RGBX_8888)) ||
- (needsScaling(tmpLayer) == true)) {
- return false;
- }else {
- ctx->listStats[dpy].renderBufIndexforABC = 0;
- }
- }
-
- if(ctx->listStats[dpy].renderBufIndexforABC == 0) {
- if(layerCount == 1)
- return true;
-
- if(layerCount == MAX_LAYERS_FOR_ABC) {
- int abcRenderBufIdx = ctx->listStats[dpy].renderBufIndexforABC;
- //enable ABC only for non intersecting layers.
- hwc_rect_t displayFrame =
- list->hwLayers[abcRenderBufIdx].displayFrame;
- for (int i = abcRenderBufIdx + 1; i < layerCount; i++) {
- hwc_rect_t tmpDisplayFrame = list->hwLayers[i].displayFrame;
- hwc_rect_t result = getIntersection(displayFrame,tmpDisplayFrame);
- if (isValidRect(result)) {
- ctx->listStats[dpy].renderBufIndexforABC = -1;
- return false;
- }
- }
- // Pass the Acquire Fence FD to driver for base layer
- private_handle_t *renderBuffer =
- (private_handle_t *)list->hwLayers[abcRenderBufIdx].handle;
- copybit_device_t *copybit = getCopyBitDevice();
- if(list->hwLayers[abcRenderBufIdx].acquireFenceFd >=0){
- copybit->set_sync(copybit,
- list->hwLayers[abcRenderBufIdx].acquireFenceFd);
- }
- for(int i = abcRenderBufIdx + 1; i < layerCount; i++){
- mSwapRect = 0;
- int retVal = drawLayerUsingCopybit(ctx,
- &(list->hwLayers[i]),renderBuffer, 0);
- if(retVal < 0) {
- ALOGE("%s : Copybit failed", __FUNCTION__);
- }
- }
- // Get Release Fence FD of copybit for the App layer(s)
- copybit->flush_get_fence(copybit, copybitFd);
- close(list->hwLayers[last].acquireFenceFd);
- list->hwLayers[last].acquireFenceFd = -1;
- return true;
- }
- }
- return false;
-}
-
-bool CopyBit::draw(hwc_context_t *ctx, hwc_display_contents_1_t *list,
- int dpy, int32_t *fd) {
- // draw layers marked for COPYBIT
- int retVal = true;
- int copybitLayerCount = 0;
- uint32_t last = 0;
- LayerProp *layerProp = ctx->layerProp[dpy];
- private_handle_t *renderBuffer;
-
- if(mCopyBitDraw == false){
- mFbCache.reset(); // there is no layer marked for copybit
- return false ;
- }
-
- if(drawUsingAppBufferComposition(ctx, list, dpy, fd)) {
- mFbCache.reset();
- return true;
- }
- //render buffer
- if (ctx->mMDP.version == qdutils::MDP_V3_0_4 ||
-#ifdef SUPPORT_BLIT_TO_FB
- ctx->mMDP.version != qdutils::MDP_V3_0_5
-#else
- ctx->mMDP.version == qdutils::MDP_V3_0_5
-#endif
- ) {
- last = (uint32_t)list->numHwLayers - 1;
- renderBuffer = (private_handle_t *)list->hwLayers[last].handle;
- } else {
- renderBuffer = getCurrentRenderBuffer();
- }
- if (!renderBuffer) {
- ALOGE("%s: Render buffer layer handle is NULL", __FUNCTION__);
- return false;
- }
-
- if ((ctx->mMDP.version >= qdutils::MDP_V4_0)
-#ifdef SUPPORT_BLIT_TO_FB
- || (ctx->mMDP.version == qdutils::MDP_V3_0_5)
-#endif
- ) {
- //Wait for the previous frame to complete before rendering onto it
- if(mRelFd[mCurRenderBufferIndex] >=0) {
- sync_wait(mRelFd[mCurRenderBufferIndex], 1000);
- close(mRelFd[mCurRenderBufferIndex]);
- mRelFd[mCurRenderBufferIndex] = -1;
- }
- } else {
- if(list->hwLayers[last].acquireFenceFd >=0) {
- copybit_device_t *copybit = getCopyBitDevice();
- copybit->set_sync(copybit, list->hwLayers[last].acquireFenceFd);
- }
- }
-
- //if swap rect on and not getting valid dirtyRect
- //means calling only commit without any draw. Hence avoid
- //clear call as well.
- if (not mSwapRect || isValidRect(mDirtyRect)) {
- if (not CBUtils::uiClearRegion(list, ctx->mMDP.version, layerProp,
- mDirtyRect, mEngine, renderBuffer)){
- mSwapRect = 0;
- }
- }
-
- // numAppLayers-1, as we iterate from 0th layer index with HWC_COPYBIT flag
- for (int i = 0; i <= (ctx->listStats[dpy].numAppLayers-1); i++) {
- if(!(layerProp[i].mFlags & HWC_COPYBIT)) {
- ALOGD_IF(DEBUG_COPYBIT, "%s: Not Marked for copybit", __FUNCTION__);
- continue;
- }
- if(ctx->copybitDrop[i]) {
- continue;
- }
- int ret = -1;
- if (list->hwLayers[i].acquireFenceFd != -1
- && ctx->mMDP.version >= qdutils::MDP_V4_0) {
- // Wait for acquire Fence on the App buffers.
- ret = sync_wait(list->hwLayers[i].acquireFenceFd, 1000);
- if(ret < 0) {
- ALOGE("%s: sync_wait error!! error no = %d err str = %s",
- __FUNCTION__, errno, strerror(errno));
- }
- close(list->hwLayers[i].acquireFenceFd);
- list->hwLayers[i].acquireFenceFd = -1;
- }
- retVal = drawLayerUsingCopybit(ctx, &(list->hwLayers[i]),
- renderBuffer, !i);
- copybitLayerCount++;
- if(retVal < 0) {
- ALOGE("%s : drawLayerUsingCopybit failed", __FUNCTION__);
- }
- }
-
- if (copybitLayerCount) {
- copybit_device_t *copybit = getCopyBitDevice();
- // Async mode
- copybit->flush_get_fence(copybit, fd);
- if((ctx->mMDP.version == qdutils::MDP_V3_0_4 ||
-#ifdef SUPPORT_BLIT_TO_FB
- ctx->mMDP.version != qdutils::MDP_V3_0_5
-#else
- ctx->mMDP.version == qdutils::MDP_V3_0_5
-#endif
- ) && list->hwLayers[last].acquireFenceFd >= 0) {
- close(list->hwLayers[last].acquireFenceFd);
- list->hwLayers[last].acquireFenceFd = -1;
- }
- }
- return true;
-}
-
-int CopyBit::drawOverlap(hwc_context_t *ctx, hwc_display_contents_1_t *list) {
- int fd = -1;
- PtorInfo* ptorInfo = &(ctx->mPtorInfo);
-
- if (ctx->mMDP.version < qdutils::MDP_V4_0) {
- ALOGE("%s: Invalid request", __FUNCTION__);
- return fd;
- }
-
- private_handle_t *renderBuffer = getCurrentRenderBuffer();
-
- if (!renderBuffer) {
- ALOGE("%s: Render buffer layer handle is NULL", __FUNCTION__);
- return fd;
- }
-
- //Clear the transparent or left out region on the render buffer
- LayerProp *layerProp = ctx->layerProp[0];
- hwc_rect_t clearRegion = {0, 0, 0, 0};
- CBUtils::uiClearRegion(list, ctx->mMDP.version, layerProp, clearRegion,
- mEngine, renderBuffer);
-
- int copybitLayerCount = 0;
- for(int j = 0; j < ptorInfo->count; j++) {
- int ovlapIndex = ptorInfo->layerIndex[j];
- hwc_rect_t overlap = list->hwLayers[ovlapIndex].displayFrame;
- if(j) {
- /**
- * It's possible that 2 PTOR layers might have overlapping.
- * In such case, remove the intersection(again if peripheral)
- * from the lower PTOR layer to avoid overlapping.
- * If intersection is not on peripheral then compromise
- * by reducing number of PTOR layers.
- **/
- int prevOvlapIndex = ptorInfo->layerIndex[0];
- hwc_rect_t prevOvlap = list->hwLayers[prevOvlapIndex].displayFrame;
- hwc_rect_t commonRect = getIntersection(prevOvlap, overlap);
- if(isValidRect(commonRect)) {
- overlap = deductRect(overlap, commonRect);
- }
- }
-
- // Draw overlapped content of layers on render buffer
- for (int i = 0; i <= ovlapIndex; i++) {
- hwc_layer_1_t *layer = &list->hwLayers[i];
- if(!isValidRect(getIntersection(layer->displayFrame,
- overlap))) {
- continue;
- }
- if ((list->hwLayers[i].acquireFenceFd != -1)) {
- // Wait for acquire fence on the App buffers.
- if(sync_wait(list->hwLayers[i].acquireFenceFd, 1000) < 0) {
- ALOGE("%s: sync_wait error!! error no = %d err str = %s",
- __FUNCTION__, errno, strerror(errno));
- }
- close(list->hwLayers[i].acquireFenceFd);
- list->hwLayers[i].acquireFenceFd = -1;
- }
- /*
- * Find the intersection of layer display frame with PTOR layer
- * with respect to screen co-ordinates
- *
- * Calculated the destination rect by transforming the overlapping
- * region of layer display frame with respect to PTOR display frame
- *
- * Transform the destination rect on to render buffer
- * */
- hwc_rect_t destRect = getIntersection(overlap, layer->displayFrame);
- destRect.left = destRect.left - overlap.left +
- ptorInfo->displayFrame[j].left;
- destRect.right = destRect.right- overlap.left +
- ptorInfo->displayFrame[j].left;
- destRect.top = destRect.top - overlap.top +
- ptorInfo->displayFrame[j].top;
- destRect.bottom = destRect.bottom - overlap.top +
- ptorInfo->displayFrame[j].top;
-
- int retVal = drawRectUsingCopybit(ctx, layer, renderBuffer,
- overlap, destRect);
- copybitLayerCount++;
- if(retVal < 0) {
- ALOGE("%s: drawRectUsingCopybit failed", __FUNCTION__);
- copybitLayerCount = 0;
- }
- }
- }
-
- if (copybitLayerCount) {
- copybit_device_t *copybit = getCopyBitDevice();
- copybit->flush_get_fence(copybit, &fd);
- }
-
- ALOGD_IF(DEBUG_COPYBIT, "%s: done! copybitLayerCount = %d", __FUNCTION__,
- copybitLayerCount);
- return fd;
-}
-
-int CopyBit::drawRectUsingCopybit(hwc_context_t *dev, hwc_layer_1_t *layer,
- private_handle_t *renderBuffer, hwc_rect_t overlap,
- hwc_rect_t destRect)
-{
- hwc_context_t* ctx = (hwc_context_t*)(dev);
- if (!ctx) {
- ALOGE("%s: null context ", __FUNCTION__);
- return -1;
- }
-
- private_handle_t *hnd = (private_handle_t *)layer->handle;
- if (!hnd) {
- ALOGE("%s: invalid handle", __FUNCTION__);
- return -1;
- }
-
- private_handle_t *dstHandle = (private_handle_t *)renderBuffer;
- if (!dstHandle) {
- ALOGE("%s: RenderBuffer handle is NULL", __FUNCTION__);
- return -1;
- }
-
- // Set the Copybit Source
- copybit_image_t src;
- src.handle = (native_handle_t *)layer->handle;
- src.w = hnd->width;
- src.h = hnd->height;
- src.base = (void *)hnd->base;
- src.format = hnd->format;
- src.horiz_padding = 0;
- src.vert_padding = 0;
-
-
- hwc_rect_t dispFrame = layer->displayFrame;
- hwc_rect_t iRect = getIntersection(dispFrame, overlap);
- hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);
- qhwc::calculate_crop_rects(crop, dispFrame, iRect,
- layer->transform);
-
- // Copybit source rect
- copybit_rect_t srcRect = {crop.left, crop.top, crop.right,
- crop.bottom};
-
- // Copybit destination rect
- copybit_rect_t dstRect = {destRect.left, destRect.top, destRect.right,
- destRect.bottom};
-
- // Copybit dst
- copybit_image_t dst;
- dst.handle = (native_handle_t *)dstHandle;
- dst.w = ALIGN(dstHandle->width, 32);
- dst.h = dstHandle->height;
- dst.base = (void *)dstHandle->base;
- dst.format = dstHandle->format;
-
- copybit_device_t *copybit = mEngine;
-
- // Copybit region is the destRect
- hwc_rect_t regRect = {dstRect.l,dstRect.t, dstRect.r, dstRect.b};
- hwc_region_t region;
- region.numRects = 1;
- region.rects = &regRect;
- region_iterator copybitRegion(region);
- int acquireFd = layer->acquireFenceFd;
-
- copybit->set_parameter(copybit, COPYBIT_FRAMEBUFFER_WIDTH,
- renderBuffer->width);
- copybit->set_parameter(copybit, COPYBIT_FRAMEBUFFER_HEIGHT,
- renderBuffer->height);
- copybit->set_parameter(copybit, COPYBIT_TRANSFORM, layer->transform);
- copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, layer->planeAlpha);
- copybit->set_parameter(copybit, COPYBIT_BLEND_MODE, layer->blending);
- copybit->set_parameter(copybit, COPYBIT_DITHER,
- (dst.format == HAL_PIXEL_FORMAT_RGB_565) ? COPYBIT_ENABLE :
- COPYBIT_DISABLE);
- copybit->set_sync(copybit, acquireFd);
- int err = copybit->stretch(copybit, &dst, &src, &dstRect, &srcRect,
- &copybitRegion);
-
- if (err < 0)
- ALOGE("%s: copybit stretch failed",__FUNCTION__);
-
- return err;
-}
-
-int CopyBit::drawLayerUsingCopybit(hwc_context_t *dev, hwc_layer_1_t *layer,
- private_handle_t *renderBuffer, bool isFG)
-{
- hwc_context_t* ctx = (hwc_context_t*)(dev);
- int err = 0, acquireFd;
- if(!ctx) {
- ALOGE("%s: null context ", __FUNCTION__);
- return -1;
- }
-
- private_handle_t *hnd = (private_handle_t *)layer->handle;
- if(!hnd) {
- if (layer->flags & HWC_COLOR_FILL) { // Color layer
- return fillColorUsingCopybit(layer, renderBuffer);
- }
- ALOGE("%s: invalid handle", __FUNCTION__);
- return -1;
- }
-
- private_handle_t *fbHandle = (private_handle_t *)renderBuffer;
- if(!fbHandle) {
- ALOGE("%s: Framebuffer handle is NULL", __FUNCTION__);
- return -1;
- }
- uint32_t dynamic_fps = 0;
-#ifdef DYNAMIC_FPS
- MetaData_t *mdata = hnd ? (MetaData_t *)hnd->base_metadata : NULL;
- if (mdata && (mdata->operation & UPDATE_REFRESH_RATE)) {
- dynamic_fps = roundOff(mdata->refreshrate);
- }
-#endif
- // Set the copybit source:
- copybit_image_t src;
- src.w = getWidth(hnd);
- src.h = getHeight(hnd);
- src.format = hnd->format;
-
- // Handle R/B swap
- if ((layer->flags & HWC_FORMAT_RB_SWAP)) {
- if (src.format == HAL_PIXEL_FORMAT_RGBA_8888) {
- src.format = HAL_PIXEL_FORMAT_BGRA_8888;
- } else if (src.format == HAL_PIXEL_FORMAT_RGBX_8888) {
- src.format = HAL_PIXEL_FORMAT_BGRX_8888;
- }
- }
-
- src.base = (void *)hnd->base;
- src.handle = (native_handle_t *)layer->handle;
- src.horiz_padding = src.w - getWidth(hnd);
- // Initialize vertical padding to zero for now,
- // this needs to change to accomodate vertical stride
- // if needed in the future
- src.vert_padding = 0;
-
- int layerTransform = layer->transform ;
- // When flip and rotation(90) are present alter the flip,
- // as GPU is doing the flip and rotation in opposite order
- // to that of MDP3.0
- // For 270 degrees, we get 90 + (H+V) which is same as doing
- // flip first and then rotation (H+V) + 90
- if (qdutils::MDPVersion::getInstance().getMDPVersion() < 400) {
- if (((layer->transform& HAL_TRANSFORM_FLIP_H) ||
- (layer->transform & HAL_TRANSFORM_FLIP_V)) &&
- (layer->transform & HAL_TRANSFORM_ROT_90) &&
- !(layer->transform == HAL_TRANSFORM_ROT_270)){
- if(layer->transform & HAL_TRANSFORM_FLIP_H){
- layerTransform ^= HAL_TRANSFORM_FLIP_H;
- layerTransform |= HAL_TRANSFORM_FLIP_V;
- }
- if(layer->transform & HAL_TRANSFORM_FLIP_V){
- layerTransform ^= HAL_TRANSFORM_FLIP_V;
- layerTransform |= HAL_TRANSFORM_FLIP_H;
- }
- }
- }
- // Copybit source rect
- hwc_rect_t sourceCrop = integerizeSourceCrop(layer->sourceCropf);
- copybit_rect_t srcRect = {sourceCrop.left, sourceCrop.top,
- sourceCrop.right,
- sourceCrop.bottom};
-
- // Copybit destination rect
- hwc_rect_t displayFrame = layer->displayFrame;
- copybit_rect_t dstRect = {displayFrame.left, displayFrame.top,
- displayFrame.right,
- displayFrame.bottom};
-#ifdef QTI_BSP
- //change src and dst with dirtyRect
- if(mSwapRect) {
- hwc_rect_t result = getIntersection(displayFrame, mDirtyRect);
- if(!isValidRect(result))
- return true;
- dstRect.l = result.left;
- dstRect.t = result.top;
- dstRect.r = result.right;
- dstRect.b = result.bottom;
-
- srcRect.l += (result.left - displayFrame.left);
- srcRect.t += (result.top - displayFrame.top);
- srcRect.r -= (displayFrame.right - result.right);
- srcRect.b -= (displayFrame.bottom - result.bottom);
- }
-#endif
- // Copybit dst
- copybit_image_t dst;
- dst.w = ALIGN(fbHandle->width,32);
- dst.h = fbHandle->height;
- dst.format = fbHandle->format;
- dst.base = (void *)fbHandle->base;
- dst.handle = (native_handle_t *)fbHandle;
-
- copybit_device_t *copybit = mEngine;
-
- int32_t screen_w = displayFrame.right - displayFrame.left;
- int32_t screen_h = displayFrame.bottom - displayFrame.top;
- int32_t src_crop_width = sourceCrop.right - sourceCrop.left;
- int32_t src_crop_height = sourceCrop.bottom -sourceCrop.top;
-
- // Copybit dst
- float copybitsMaxScale =
- (float)copybit->get(copybit,COPYBIT_MAGNIFICATION_LIMIT);
- float copybitsMinScale =
- (float)copybit->get(copybit,COPYBIT_MINIFICATION_LIMIT);
-
- if (layer->transform & HWC_TRANSFORM_ROT_90) {
- //swap screen width and height
- int tmp = screen_w;
- screen_w = screen_h;
- screen_h = tmp;
- }
- private_handle_t *tmpHnd = NULL;
-
- if(screen_w <=0 || screen_h<=0 ||src_crop_width<=0 || src_crop_height<=0 ) {
- ALOGE("%s: wrong params for display screen_w=%d src_crop_width=%d \
- screen_h=%d src_crop_height=%d", __FUNCTION__, screen_w,
- src_crop_width,screen_h,src_crop_height);
- return -1;
- }
-
- float dsdx = (float)screen_w/(float)src_crop_width;
- float dtdy = (float)screen_h/(float)src_crop_height;
-
- float scaleLimitMax = copybitsMaxScale * copybitsMaxScale;
- float scaleLimitMin = copybitsMinScale * copybitsMinScale;
- if(dsdx > scaleLimitMax ||
- dtdy > scaleLimitMax ||
- dsdx < 1/scaleLimitMin ||
- dtdy < 1/scaleLimitMin) {
- ALOGW("%s: greater than max supported size dsdx=%f dtdy=%f \
- scaleLimitMax=%f scaleLimitMin=%f", __FUNCTION__,dsdx,dtdy,
- scaleLimitMax,1/scaleLimitMin);
- return -1;
- }
- acquireFd = layer->acquireFenceFd;
- if(dsdx > copybitsMaxScale ||
- dtdy > copybitsMaxScale ||
- dsdx < 1/copybitsMinScale ||
- dtdy < 1/copybitsMinScale){
- // The requested scale is out of the range the hardware
- // can support.
- ALOGD("%s:%d::Need to scale twice dsdx=%f, dtdy=%f,copybitsMaxScale=%f,\
- copybitsMinScale=%f,screen_w=%d,screen_h=%d \
- src_crop_width=%d src_crop_height=%d",__FUNCTION__,__LINE__,
- dsdx,dtdy,copybitsMaxScale,1/copybitsMinScale,screen_w,screen_h,
- src_crop_width,src_crop_height);
-
-
- int tmp_w = src_crop_width;
- int tmp_h = src_crop_height;
-
- if (dsdx > copybitsMaxScale)
- tmp_w = (int)((float)src_crop_width*copybitsMaxScale);
- if (dtdy > copybitsMaxScale)
- tmp_h = (int)((float)src_crop_height*copybitsMaxScale);
- // ceil the tmp_w and tmp_h value to maintain proper ratio
- // b/w src and dst (should not cross the desired scale limit
- // due to float -> int )
- if (dsdx < 1/copybitsMinScale)
- tmp_w = (int)ceil((float)src_crop_width/copybitsMinScale);
- if (dtdy < 1/copybitsMinScale)
- tmp_h = (int)ceil((float)src_crop_height/copybitsMinScale);
-
- ALOGD("%s:%d::tmp_w = %d,tmp_h = %d",__FUNCTION__,__LINE__,tmp_w,tmp_h);
-
- int usage = GRALLOC_USAGE_PRIVATE_IOMMU_HEAP;
- int format = fbHandle->format;
-
- // We do not want copybit to generate alpha values from nothing
- if (format == HAL_PIXEL_FORMAT_RGBA_8888 &&
- src.format != HAL_PIXEL_FORMAT_RGBA_8888) {
- format = HAL_PIXEL_FORMAT_RGBX_8888;
- }
- if (0 == alloc_buffer(&tmpHnd, tmp_w, tmp_h, format, usage) && tmpHnd) {
- copybit_image_t tmp_dst;
- copybit_rect_t tmp_rect;
- tmp_dst.w = tmp_w;
- tmp_dst.h = tmp_h;
- tmp_dst.format = tmpHnd->format;
- tmp_dst.handle = tmpHnd;
- tmp_dst.horiz_padding = src.horiz_padding;
- tmp_dst.vert_padding = src.vert_padding;
- tmp_rect.l = 0;
- tmp_rect.t = 0;
- tmp_rect.r = tmp_dst.w;
- tmp_rect.b = tmp_dst.h;
- //create one clip region
- hwc_rect tmp_hwc_rect = {0,0,tmp_rect.r,tmp_rect.b};
- hwc_region_t tmp_hwc_reg = {1,(hwc_rect_t const*)&tmp_hwc_rect};
- region_iterator tmp_it(tmp_hwc_reg);
- copybit->set_parameter(copybit,COPYBIT_TRANSFORM,0);
- //TODO: once, we are able to read layer alpha, update this
- copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, 255);
- copybit->set_sync(copybit, acquireFd);
- err = copybit->stretch(copybit,&tmp_dst, &src, &tmp_rect,
- &srcRect, &tmp_it);
- if(err < 0){
- ALOGE("%s:%d::tmp copybit stretch failed",__FUNCTION__,
- __LINE__);
- if(tmpHnd)
- free_buffer(tmpHnd);
- return err;
- }
- // use release fence as aquire fd for next stretch
- if (ctx->mMDP.version < qdutils::MDP_V4_0) {
- copybit->flush_get_fence(copybit, &acquireFd);
- close(acquireFd);
- acquireFd = -1;
- }
- // copy new src and src rect crop
- src = tmp_dst;
- srcRect = tmp_rect;
- }
- }
- // Copybit region
- hwc_region_t region = layer->visibleRegionScreen;
- //Do not use visible regions in case of scaling
- if (region.numRects > 1) {
- if (needsScaling(layer)) {
- region.numRects = 1;
- region.rects = &layer->displayFrame;
- }
- }
-
- region_iterator copybitRegion(region);
-
- copybit->set_parameter(copybit, COPYBIT_FRAMEBUFFER_WIDTH,
- renderBuffer->width);
- copybit->set_parameter(copybit, COPYBIT_FRAMEBUFFER_HEIGHT,
- renderBuffer->height);
- copybit->set_parameter(copybit, COPYBIT_TRANSFORM,
- layerTransform);
- //TODO: once, we are able to read layer alpha, update this
- copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, 255);
- copybit->set_parameter(copybit, COPYBIT_DYNAMIC_FPS, dynamic_fps);
- copybit->set_parameter(copybit, COPYBIT_BLEND_MODE,
- layer->blending);
- copybit->set_parameter(copybit, COPYBIT_DITHER,
- (dst.format == HAL_PIXEL_FORMAT_RGB_565)?
- COPYBIT_ENABLE : COPYBIT_DISABLE);
- copybit->set_parameter(copybit, COPYBIT_FG_LAYER,
- (layer->blending == HWC_BLENDING_NONE || isFG ) ?
- COPYBIT_ENABLE : COPYBIT_DISABLE);
-
- copybit->set_parameter(copybit, COPYBIT_BLIT_TO_FRAMEBUFFER,
- COPYBIT_ENABLE);
- copybit->set_sync(copybit, acquireFd);
- err = copybit->stretch(copybit, &dst, &src, &dstRect, &srcRect,
- &copybitRegion);
- copybit->set_parameter(copybit, COPYBIT_BLIT_TO_FRAMEBUFFER,
- COPYBIT_DISABLE);
-
- if(tmpHnd) {
- if (ctx->mMDP.version < qdutils::MDP_V4_0){
- int ret = -1, releaseFd;
- // we need to wait for the buffer before freeing
- copybit->flush_get_fence(copybit, &releaseFd);
- ret = sync_wait(releaseFd, 1000);
- if(ret < 0) {
- ALOGE("%s: sync_wait error!! error no = %d err str = %s",
- __FUNCTION__, errno, strerror(errno));
- }
- close(releaseFd);
- }
- free_buffer(tmpHnd);
- }
-
- if(err < 0)
- ALOGE("%s: copybit stretch failed",__FUNCTION__);
- return err;
-}
-
-int CopyBit::fillColorUsingCopybit(hwc_layer_1_t *layer,
- private_handle_t *renderBuffer)
-{
- if (!renderBuffer) {
- ALOGE("%s: Render Buffer is NULL", __FUNCTION__);
- return -1;
- }
-
- // Copybit dst
- copybit_image_t dst;
- dst.w = ALIGN(renderBuffer->width, 32);
- dst.h = renderBuffer->height;
- dst.format = renderBuffer->format;
- dst.base = (void *)renderBuffer->base;
- dst.handle = (native_handle_t *)renderBuffer;
-
- // Copybit dst rect
- hwc_rect_t displayFrame = layer->displayFrame;
- copybit_rect_t dstRect = {displayFrame.left, displayFrame.top,
- displayFrame.right, displayFrame.bottom};
-
- uint32_t color = layer->transform;
- copybit_device_t *copybit = mEngine;
- copybit->set_parameter(copybit, COPYBIT_FRAMEBUFFER_WIDTH,
- renderBuffer->width);
- copybit->set_parameter(copybit, COPYBIT_FRAMEBUFFER_HEIGHT,
- renderBuffer->height);
- copybit->set_parameter(copybit, COPYBIT_DITHER,
- (dst.format == HAL_PIXEL_FORMAT_RGB_565) ?
- COPYBIT_ENABLE : COPYBIT_DISABLE);
- copybit->set_parameter(copybit, COPYBIT_TRANSFORM, 0);
- copybit->set_parameter(copybit, COPYBIT_BLEND_MODE, layer->blending);
- copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, layer->planeAlpha);
- copybit->set_parameter(copybit, COPYBIT_BLIT_TO_FRAMEBUFFER,COPYBIT_ENABLE);
- int res = copybit->fill_color(copybit, &dst, &dstRect, color);
- copybit->set_parameter(copybit,COPYBIT_BLIT_TO_FRAMEBUFFER,COPYBIT_DISABLE);
- return res;
-}
-
-void CopyBit::getLayerResolution(const hwc_layer_1_t* layer,
- unsigned int& width, unsigned int& height)
-{
- hwc_rect_t result = layer->displayFrame;
- if (mSwapRect)
- result = getIntersection(mDirtyRect, result);
-
- width = result.right - result.left;
- height = result.bottom - result.top;
-}
-
-bool CopyBit::validateParams(hwc_context_t *ctx,
- const hwc_display_contents_1_t *list) {
- //Validate parameters
- if (!ctx) {
- ALOGE("%s:Invalid HWC context", __FUNCTION__);
- return false;
- } else if (!list) {
- ALOGE("%s:Invalid HWC layer list", __FUNCTION__);
- return false;
- }
- return true;
-}
-
-
-int CopyBit::allocRenderBuffers(int w, int h, int f)
-{
- int ret = 0;
- for (int i = 0; i < NUM_RENDER_BUFFERS; i++) {
- if (mRenderBuffer[i] == NULL) {
- ret = alloc_buffer(&mRenderBuffer[i],
- w, h, f,
- GRALLOC_USAGE_PRIVATE_IOMMU_HEAP);
- }
- if(ret < 0) {
- freeRenderBuffers();
- break;
- }
- }
- return ret;
-}
-
-void CopyBit::freeRenderBuffers()
-{
- for (int i = 0; i < NUM_RENDER_BUFFERS; i++) {
- if(mRenderBuffer[i]) {
- //Since we are freeing buffer close the fence if it has a valid one.
- if(mRelFd[i] >= 0) {
- close(mRelFd[i]);
- mRelFd[i] = -1;
- }
- free_buffer(mRenderBuffer[i]);
- mRenderBuffer[i] = NULL;
- }
- }
-}
-
-private_handle_t * CopyBit::getCurrentRenderBuffer() {
- return mRenderBuffer[mCurRenderBufferIndex];
-}
-
-void CopyBit::setReleaseFd(int fd) {
- if(mRelFd[mCurRenderBufferIndex] >=0)
- close(mRelFd[mCurRenderBufferIndex]);
- mRelFd[mCurRenderBufferIndex] = dup(fd);
-}
-
-void CopyBit::setReleaseFdSync(int fd) {
- if (mRelFd[mCurRenderBufferIndex] >=0) {
- int ret = -1;
- ret = sync_wait(mRelFd[mCurRenderBufferIndex], 1000);
- if (ret < 0)
- ALOGE("%s: sync_wait error! errno = %d, err str = %s",
- __FUNCTION__, errno, strerror(errno));
- close(mRelFd[mCurRenderBufferIndex]);
- }
- mRelFd[mCurRenderBufferIndex] = dup(fd);
-}
-
-struct copybit_device_t* CopyBit::getCopyBitDevice() {
- return mEngine;
-}
-
-CopyBit::CopyBit(hwc_context_t *ctx, const int& dpy) : mEngine(0),
- mIsModeOn(false), mCopyBitDraw(false), mCurRenderBufferIndex(0) {
-
- getBufferSizeAndDimensions(ctx->dpyAttr[dpy].xres,
- ctx->dpyAttr[dpy].yres,
- HAL_PIXEL_FORMAT_RGBA_8888,
- mAlignedWidth,
- mAlignedHeight);
-
- hw_module_t const *module;
- for (int i = 0; i < NUM_RENDER_BUFFERS; i++) {
- mRenderBuffer[i] = NULL;
- mRelFd[i] = -1;
- }
-
- char value[PROPERTY_VALUE_MAX];
- property_get("debug.hwc.dynThreshold", value, "2");
- mDynThreshold = atof(value);
-
- property_get("debug.sf.swaprect", value, "0");
- mSwapRectEnable = atoi(value) ? true:false ;
- mSwapRect = 0;
- if (hw_get_module(COPYBIT_HARDWARE_MODULE_ID, &module) == 0) {
- if(copybit_open(module, &mEngine) < 0) {
- ALOGE("FATAL ERROR: copybit open failed.");
- }
- } else {
- ALOGE("FATAL ERROR: copybit hw module not found");
- }
-}
-
-CopyBit::~CopyBit()
-{
- freeRenderBuffers();
- if(mEngine)
- {
- copybit_close(mEngine);
- mEngine = NULL;
- }
-}
-CopyBit::LayerCache::LayerCache() {
- reset();
-}
-void CopyBit::LayerCache::reset() {
- memset(&hnd, 0, sizeof(hnd));
- layerCount = 0;
-}
-void CopyBit::LayerCache::updateCounts(hwc_context_t *ctx,
- hwc_display_contents_1_t *list, int dpy)
-{
- layerCount = ctx->listStats[dpy].numAppLayers;
- for (int i=0; i<ctx->listStats[dpy].numAppLayers; i++){
- hnd[i] = list->hwLayers[i].handle;
- displayFrame[i] = list->hwLayers[i].displayFrame;
- drop[i] = ctx->copybitDrop[i];
- }
-}
-
-CopyBit::FbCache::FbCache() {
- reset();
-}
-void CopyBit::FbCache::reset() {
- memset(&FbdirtyRect, 0, sizeof(FbdirtyRect));
- memset(&FbdisplayRect, 0, sizeof(FbdisplayRect));
- FbIndex =0;
-}
-
-void CopyBit::FbCache::insertAndUpdateFbCache(hwc_rect_t dirtyRect,
- hwc_rect_t displayRect) {
- FbIndex = FbIndex % NUM_RENDER_BUFFERS;
- FbdirtyRect[FbIndex] = dirtyRect;
- FbdisplayRect[FbIndex] = displayRect;
- FbIndex++;
-}
-
-int CopyBit::FbCache::getUnchangedFbDRCount(hwc_rect_t dirtyRect,
- hwc_rect_t displayRect){
- int sameDirtyCount = 0;
- for (int i = 0 ; i < NUM_RENDER_BUFFERS ; i++ ){
- if( FbdirtyRect[i] == dirtyRect &&
- FbdisplayRect[i] == displayRect)
- sameDirtyCount++;
- }
- return sameDirtyCount;
-}
-
-}; //namespace qhwc
diff --git a/msm8909/libhwcomposer/hwc_copybit.h b/msm8909/libhwcomposer/hwc_copybit.h
deleted file mode 100644
index c527a4ec..00000000
--- a/msm8909/libhwcomposer/hwc_copybit.h
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- * Copyright (C) 2012-2014, The Linux Foundation. All rights reserved.
- *
- * Not a Contribution, Apache license notifications and license are retained
- * for attribution purposes only.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#ifndef HWC_COPYBIT_H
-#define HWC_COPYBIT_H
-#include "hwc_utils.h"
-
-#define NUM_RENDER_BUFFERS 3
-//These scaling factors are specific for MDP3. Normally scaling factor
-//is only 4, but copybit will create temp buffer to let it run through
-//twice
-#define MAX_SCALE_FACTOR 16
-#define MIN_SCALE_FACTOR 0.0625
-#define MAX_LAYERS_FOR_ABC 2
-#define INVALID_DIMENSION -1
-#define NO_UPDATING_LAYER -2
-namespace qhwc {
-
-class CopyBit {
-public:
- CopyBit(hwc_context_t *ctx, const int& dpy);
- ~CopyBit();
- // API to get copybit engine(non static)
- struct copybit_device_t *getCopyBitDevice();
- //Sets up members and prepares copybit if conditions are met
- bool prepare(hwc_context_t *ctx, hwc_display_contents_1_t *list,
- int dpy);
- //Draws layer if the layer is set for copybit in prepare
- bool draw(hwc_context_t *ctx, hwc_display_contents_1_t *list,
- int dpy, int* fd);
- // resets the values
- void reset();
-
- private_handle_t * getCurrentRenderBuffer();
-
- void setReleaseFd(int fd);
-
- void setReleaseFdSync(int fd);
-
- bool prepareOverlap(hwc_context_t *ctx, hwc_display_contents_1_t *list);
-
- int drawOverlap(hwc_context_t *ctx, hwc_display_contents_1_t *list);
-
-private:
- /* cached data */
- struct LayerCache {
- int layerCount;
- buffer_handle_t hnd[MAX_NUM_APP_LAYERS];
- hwc_rect_t displayFrame[MAX_NUM_APP_LAYERS];
- bool drop[MAX_NUM_APP_LAYERS];
- /* c'tor */
- LayerCache();
- /* clear caching info*/
- void reset();
- void updateCounts(hwc_context_t *ctx, hwc_display_contents_1_t *list,
- int dpy);
- };
- /* framebuffer cache*/
- struct FbCache {
- hwc_rect_t FbdirtyRect[NUM_RENDER_BUFFERS];
- hwc_rect_t FbdisplayRect[NUM_RENDER_BUFFERS];
- int FbIndex;
- FbCache();
- void reset();
- void insertAndUpdateFbCache(hwc_rect_t dirtyRect,
- hwc_rect_t displayRect);
- int getUnchangedFbDRCount(hwc_rect_t dirtyRect,
- hwc_rect_t displayRect);
- };
-
- // holds the copybit device
- struct copybit_device_t *mEngine;
- bool drawUsingAppBufferComposition(hwc_context_t *ctx,
- hwc_display_contents_1_t *list,
- int dpy, int *fd);
- // Helper functions for copybit composition
- int drawLayerUsingCopybit(hwc_context_t *dev, hwc_layer_1_t *layer,
- private_handle_t *renderBuffer, bool isFG);
- // Helper function to draw copybit layer for PTOR comp
- int drawRectUsingCopybit(hwc_context_t *dev, hwc_layer_1_t *layer,
- private_handle_t *renderBuffer, hwc_rect_t overlap,
- hwc_rect_t destRect);
- int fillColorUsingCopybit(hwc_layer_1_t *layer,
- private_handle_t *renderBuffer);
- bool canUseCopybitForYUV (hwc_context_t *ctx);
- bool canUseCopybitForRGB (hwc_context_t *ctx,
- hwc_display_contents_1_t *list, int dpy);
- bool validateParams (hwc_context_t *ctx,
- const hwc_display_contents_1_t *list);
- //Flags if this feature is on.
- bool mIsModeOn;
- // flag that indicates whether CopyBit composition is enabled for this cycle
- bool mCopyBitDraw;
-
- unsigned int getRGBRenderingArea (const hwc_context_t *ctx,
- const hwc_display_contents_1_t *list);
-
- void getLayerResolution(const hwc_layer_1_t* layer,
- unsigned int &width, unsigned int& height);
-
- int allocRenderBuffers(int w, int h, int f);
-
- void freeRenderBuffers();
-
- int clear (private_handle_t* hnd, hwc_rect_t& rect);
-
- private_handle_t* mRenderBuffer[NUM_RENDER_BUFFERS];
-
- // Index of the current intermediate render buffer
- int mCurRenderBufferIndex;
-
- // Release FDs of the intermediate render buffer
- int mRelFd[NUM_RENDER_BUFFERS];
-
- //Dynamic composition threshold for deciding copybit usage.
- double mDynThreshold;
- bool mSwapRectEnable;
- int mAlignedWidth;
- int mAlignedHeight;
- int mSwapRect;
- LayerCache mLayerCache;
- FbCache mFbCache;
- hwc_rect_t mDirtyRect;
- bool prepareSwapRect(hwc_context_t *ctx, hwc_display_contents_1_t *list,
- int dpy);
- bool isLayerChanging(hwc_context_t *ctx,
- hwc_display_contents_1_t *list, int k);
- bool isSmartBlitPossible(const hwc_display_contents_1_t *list);
-};
-
-}; //namespace qhwc
-
-#endif //HWC_COPYBIT_H
diff --git a/msm8909/libhwcomposer/hwc_dump_layers.cpp b/msm8909/libhwcomposer/hwc_dump_layers.cpp
deleted file mode 100644
index 7833823e..00000000
--- a/msm8909/libhwcomposer/hwc_dump_layers.cpp
+++ /dev/null
@@ -1,454 +0,0 @@
-/*
- * Copyright (c) 2012-2014,2016 Linux Foundation. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials provided
- * with the distribution.
- * * Neither the name of Linux Foundation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
- * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
- * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef LOG_TAG
-#define LOG_TAG "qsfdump"
-#endif
-#define LOG_NDEBUG 0
-#include <hwc_utils.h>
-#include <hwc_dump_layers.h>
-#include <cutils/log.h>
-#include <sys/stat.h>
-#include <comptype.h>
-#ifdef QTI_BSP
-// Ignore W(float)conversion errors for external headers
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wconversion"
-#pragma GCC diagnostic ignored "-Wfloat-conversion"
-#include <SkBitmap.h>
-#include <SkImageEncoder.h>
-#pragma GCC diagnostic pop
-#endif
-#ifdef STDC_FORMAT_MACROS
-#include <inttypes.h>
-#endif
-
-namespace qhwc {
-
-// MAX_ALLOWED_FRAMEDUMPS must be capped to (LONG_MAX - 1)
-// 60fps => 216000 frames per hour
-// Below setting of 216000 * 24 * 7 => 1 week or 168 hours of capture.
- enum {
- MAX_ALLOWED_FRAMEDUMPS = (216000 * 24 * 7)
- };
-
-bool HwcDebug::sDumpEnable = false;
-
-HwcDebug::HwcDebug(uint32_t dpy):
- mDumpCntLimRaw(0),
- mDumpCntrRaw(1),
- mDumpCntLimPng(0),
- mDumpCntrPng(1),
- mDpy(dpy) {
- char dumpPropStr[PROPERTY_VALUE_MAX];
- if(mDpy) {
- strlcpy(mDisplayName, "external", sizeof(mDisplayName));
- } else {
- strlcpy(mDisplayName, "primary", sizeof(mDisplayName));
- }
- snprintf(mDumpPropKeyDisplayType, sizeof(mDumpPropKeyDisplayType),
- "debug.sf.dump.%s", (char *)mDisplayName);
-
- if ((property_get("debug.sf.dump.enable", dumpPropStr, NULL) > 0)) {
- if(!strncmp(dumpPropStr, "true", strlen("true"))) {
- sDumpEnable = true;
- }
- }
-}
-
-void HwcDebug::dumpLayers(hwc_display_contents_1_t* list)
-{
- // Check need for dumping layers for debugging.
- if (UNLIKELY(sDumpEnable) && UNLIKELY(needToDumpLayers()) && LIKELY(list)) {
- logHwcProps(list->flags);
- for (size_t i = 0; i < list->numHwLayers; i++) {
- logLayer(i, list->hwLayers);
- dumpLayer(i, list->hwLayers);
- }
- }
-}
-
-bool HwcDebug::needToDumpLayers()
-{
- bool bDumpLayer = false;
- char dumpPropStr[PROPERTY_VALUE_MAX];
- // Enable primary dump and disable external dump by default.
- bool bDumpEnable = !mDpy;
- time_t timeNow;
- tm dumpTime;
-
- // Override the bDumpEnable based on the property value, if the property
- // is present in the build.prop file.
- if ((property_get(mDumpPropKeyDisplayType, dumpPropStr, NULL) > 0)) {
- if(!strncmp(dumpPropStr, "true", strlen("true")))
- bDumpEnable = true;
- else
- bDumpEnable = false;
- }
-
- if (false == bDumpEnable)
- return false;
-
- time(&timeNow);
- localtime_r(&timeNow, &dumpTime);
-
- if ((property_get("debug.sf.dump.png", dumpPropStr, NULL) > 0) &&
- (strncmp(dumpPropStr, mDumpPropStrPng, PROPERTY_VALUE_MAX - 1))) {
- // Strings exist & not equal implies it has changed, so trigger a dump
- strlcpy(mDumpPropStrPng, dumpPropStr, sizeof(mDumpPropStrPng));
- mDumpCntLimPng = atoi(dumpPropStr);
- if (mDumpCntLimPng > MAX_ALLOWED_FRAMEDUMPS) {
- ALOGW("Warning: Using debug.sf.dump.png %d (= max)",
- MAX_ALLOWED_FRAMEDUMPS);
- mDumpCntLimPng = MAX_ALLOWED_FRAMEDUMPS;
- }
- mDumpCntLimPng = (mDumpCntLimPng < 0) ? 0: mDumpCntLimPng;
- if (mDumpCntLimPng) {
- snprintf(mDumpDirPng, sizeof(mDumpDirPng),
- "/data/sfdump.png.%04d.%02d.%02d.%02d.%02d.%02d",
- dumpTime.tm_year + 1900, dumpTime.tm_mon + 1,
- dumpTime.tm_mday, dumpTime.tm_hour,
- dumpTime.tm_min, dumpTime.tm_sec);
- if (0 == mkdir(mDumpDirPng, 0777))
- mDumpCntrPng = 0;
- else {
- ALOGE("Error: %s. Failed to create sfdump directory: %s",
- strerror(errno), mDumpDirPng);
- mDumpCntrPng = mDumpCntLimPng + 1;
- }
- }
- }
-
- if (mDumpCntrPng <= mDumpCntLimPng)
- mDumpCntrPng++;
-
- if ((property_get("debug.sf.dump", dumpPropStr, NULL) > 0) &&
- (strncmp(dumpPropStr, mDumpPropStrRaw, PROPERTY_VALUE_MAX - 1))) {
- // Strings exist & not equal implies it has changed, so trigger a dump
- strlcpy(mDumpPropStrRaw, dumpPropStr, sizeof(mDumpPropStrRaw));
- mDumpCntLimRaw = atoi(dumpPropStr);
- if (mDumpCntLimRaw > MAX_ALLOWED_FRAMEDUMPS) {
- ALOGW("Warning: Using debug.sf.dump %d (= max)",
- MAX_ALLOWED_FRAMEDUMPS);
- mDumpCntLimRaw = MAX_ALLOWED_FRAMEDUMPS;
- }
- mDumpCntLimRaw = (mDumpCntLimRaw < 0) ? 0: mDumpCntLimRaw;
- if (mDumpCntLimRaw) {
- snprintf(mDumpDirRaw, sizeof(mDumpDirRaw),
- "/data/sfdump.raw.%04d.%02d.%02d.%02d.%02d.%02d",
- dumpTime.tm_year + 1900, dumpTime.tm_mon + 1,
- dumpTime.tm_mday, dumpTime.tm_hour,
- dumpTime.tm_min, dumpTime.tm_sec);
- if (0 == mkdir(mDumpDirRaw, 0777))
- mDumpCntrRaw = 0;
- else {
- ALOGE("Error: %s. Failed to create sfdump directory: %s",
- strerror(errno), mDumpDirRaw);
- mDumpCntrRaw = mDumpCntLimRaw + 1;
- }
- }
- }
-
- if (mDumpCntrRaw <= mDumpCntLimRaw)
- mDumpCntrRaw++;
-
- bDumpLayer = (mDumpCntLimPng || mDumpCntLimRaw)? true : false;
- return bDumpLayer;
-}
-
-void HwcDebug::logHwcProps(uint32_t listFlags)
-{
- static int hwcModuleCompType = -1;
- static int sMdpCompMaxLayers = 0;
- static String8 hwcModuleCompTypeLog("");
- if (-1 == hwcModuleCompType) {
- // One time stuff
- char mdpCompPropStr[PROPERTY_VALUE_MAX];
- if (property_get("debug.mdpcomp.maxlayer", mdpCompPropStr, NULL) > 0) {
- sMdpCompMaxLayers = atoi(mdpCompPropStr);
- }
- hwcModuleCompType =
- qdutils::QCCompositionType::getInstance().getCompositionType();
- hwcModuleCompTypeLog.appendFormat("%s%s%s%s%s%s",
- // Is hwc module composition type now a bit-field?!
- (hwcModuleCompType == qdutils::COMPOSITION_TYPE_GPU)?
- "[GPU]": "",
- (hwcModuleCompType & qdutils::COMPOSITION_TYPE_MDP)?
- "[MDP]": "",
- (hwcModuleCompType & qdutils::COMPOSITION_TYPE_C2D)?
- "[C2D]": "",
- (hwcModuleCompType & qdutils::COMPOSITION_TYPE_CPU)?
- "[CPU]": "",
- (hwcModuleCompType & qdutils::COMPOSITION_TYPE_DYN)?
- "[DYN]": "",
- (hwcModuleCompType >= (qdutils::COMPOSITION_TYPE_DYN << 1))?
- "[???]": "");
- }
- ALOGI("Display[%s] Layer[*] %s-HwcModuleCompType, %d-layer MdpComp %s",
- mDisplayName, hwcModuleCompTypeLog.string(), sMdpCompMaxLayers,
- (listFlags & HWC_GEOMETRY_CHANGED)? "[HwcList Geometry Changed]": "");
-}
-
-void HwcDebug::logLayer(size_t layerIndex, hwc_layer_1_t hwLayers[])
-{
- if (NULL == hwLayers) {
- ALOGE("Display[%s] Layer[%zu] Error. No hwc layers to log.",
- mDisplayName, layerIndex);
- return;
- }
-
- hwc_layer_1_t *layer = &hwLayers[layerIndex];
- hwc_rect_t sourceCrop = integerizeSourceCrop(layer->sourceCropf);
- hwc_rect_t displayFrame = layer->displayFrame;
- size_t numHwcRects = layer->visibleRegionScreen.numRects;
- hwc_rect_t const *hwcRects = layer->visibleRegionScreen.rects;
- private_handle_t *hnd = (private_handle_t *)layer->handle;
-
- char pixFormatStr[32] = "None";
- String8 hwcVisRegsScrLog("[None]");
-
- for (size_t i = 0 ; (hwcRects && (i < numHwcRects)); i++) {
- if (0 == i)
- hwcVisRegsScrLog.clear();
- hwcVisRegsScrLog.appendFormat("[%dl, %dt, %dr, %db]",
- hwcRects[i].left, hwcRects[i].top,
- hwcRects[i].right, hwcRects[i].bottom);
- }
-
- if (hnd)
- getHalPixelFormatStr(hnd->format, pixFormatStr, sizeof(pixFormatStr));
-
- // Log Line 1
- ALOGI("Display[%s] Layer[%zu] SrcBuff[%dx%d] SrcCrop[%dl, %dt, %dr, %db] "
- "DispFrame[%dl, %dt, %dr, %db] VisRegsScr%s", mDisplayName, layerIndex,
- (hnd)? getWidth(hnd) : -1, (hnd)? getHeight(hnd) : -1,
- sourceCrop.left, sourceCrop.top,
- sourceCrop.right, sourceCrop.bottom,
- displayFrame.left, displayFrame.top,
- displayFrame.right, displayFrame.bottom,
- hwcVisRegsScrLog.string());
- // Log Line 2
- ALOGI("Display[%s] Layer[%zu] LayerCompType = %s, Format = %s, "
- "Orientation = %s, Flags = %s%s%s, Hints = %s%s%s, "
- "Blending = %s%s%s", mDisplayName, layerIndex,
- (layer->compositionType == HWC_FRAMEBUFFER)? "Framebuffer(GPU)":
- (layer->compositionType == HWC_OVERLAY)? "Overlay":
- (layer->compositionType == HWC_BACKGROUND)? "Background":"???",
- pixFormatStr,
- (layer->transform == 0)? "ROT_0":
- (layer->transform == HWC_TRANSFORM_FLIP_H)? "FLIP_H":
- (layer->transform == HWC_TRANSFORM_FLIP_V)? "FLIP_V":
- (layer->transform == HWC_TRANSFORM_ROT_90)? "ROT_90":
- "ROT_INVALID",
- (layer->flags)? "": "[None]",
- (layer->flags & HWC_SKIP_LAYER)? "[Skip layer]":"",
- (layer->flags & qhwc::HWC_MDPCOMP)? "[MDP Comp]":"",
- (layer->hints)? "":"[None]",
- (layer->hints & HWC_HINT_TRIPLE_BUFFER)? "[Triple Buffer]":"",
- (layer->hints & HWC_HINT_CLEAR_FB)? "[Clear FB]":"",
- (layer->blending == HWC_BLENDING_NONE)? "[None]":"",
- (layer->blending == HWC_BLENDING_PREMULT)? "[PreMult]":"",
- (layer->blending == HWC_BLENDING_COVERAGE)? "[Coverage]":"");
-}
-
-void HwcDebug::dumpLayer(size_t layerIndex, hwc_layer_1_t hwLayers[])
-{
- char dumpLogStrPng[128] = "";
- char dumpLogStrRaw[128] = "";
- bool needDumpPng = (mDumpCntrPng <= mDumpCntLimPng)? true:false;
- bool needDumpRaw = (mDumpCntrRaw <= mDumpCntLimRaw)? true:false;
-
- if (needDumpPng) {
- snprintf(dumpLogStrPng, sizeof(dumpLogStrPng),
- "[png-dump-frame: %03d of %03d]", mDumpCntrPng,
- mDumpCntLimPng);
- }
- if (needDumpRaw) {
- snprintf(dumpLogStrRaw, sizeof(dumpLogStrRaw),
- "[raw-dump-frame: %03d of %03d]", mDumpCntrRaw,
- mDumpCntLimRaw);
- }
-
- if (!(needDumpPng || needDumpRaw))
- return;
-
- if (NULL == hwLayers) {
- ALOGE("Display[%s] Layer[%zu] %s%s Error: No hwc layers to dump.",
- mDisplayName, layerIndex, dumpLogStrRaw, dumpLogStrPng);
- return;
- }
-
- hwc_layer_1_t *layer = &hwLayers[layerIndex];
- private_handle_t *hnd = (private_handle_t *)layer->handle;
- char pixFormatStr[32] = "None";
-
- if (NULL == hnd) {
- ALOGI("Display[%s] Layer[%zu] %s%s Skipping dump: Bufferless layer.",
- mDisplayName, layerIndex, dumpLogStrRaw, dumpLogStrPng);
- return;
- }
-
- getHalPixelFormatStr(hnd->format, pixFormatStr, sizeof(pixFormatStr));
-#ifdef QTI_BSP
- if (needDumpPng && hnd->base) {
- bool bResult = false;
- char dumpFilename[PATH_MAX];
- SkColorType colorType = kUnknown_SkColorType;
- SkAlphaType alphaType = kUnknown_SkAlphaType;
- snprintf(dumpFilename, sizeof(dumpFilename),
- "%s/sfdump%03d.layer%zu.%s.png", mDumpDirPng,
- mDumpCntrPng, layerIndex, mDisplayName);
-
- switch (hnd->format) {
- case HAL_PIXEL_FORMAT_RGBA_8888:
- alphaType = kPremul_SkAlphaType;
- colorType = kRGBA_8888_SkColorType;
- break;
- case HAL_PIXEL_FORMAT_RGBX_8888:
- alphaType = kOpaque_SkAlphaType;
- colorType = kRGBA_8888_SkColorType;
- break;
- case HAL_PIXEL_FORMAT_BGRA_8888:
- alphaType = kPremul_SkAlphaType;
- colorType = kBGRA_8888_SkColorType;
- break;
- case HAL_PIXEL_FORMAT_RGB_565:
- alphaType = kOpaque_SkAlphaType;
- colorType = kRGB_565_SkColorType;
- break;
- default:
- break;
- }
- if (kUnknown_SkColorType != colorType) {
- SkImageInfo info = SkImageInfo::Make(getWidth(hnd), getHeight(hnd),
- colorType, alphaType);
- SkPixmap pixmap(info, (const void*)hnd->base, info.minRowBytes());
- SkFILEWStream file(dumpFilename);
- bResult = SkEncodeImage(&file, pixmap, SkEncodedImageFormat::kPNG, 100);
- ALOGI("Display[%s] Layer[%zu] %s Dump to %s: %s",
- mDisplayName, layerIndex, dumpLogStrPng,
- dumpFilename, bResult ? "Success" : "Fail");
- } else {
- ALOGI("Display[%s] Layer[%zu] %s Skipping dump: Unsupported layer"
- " format %s for png encoder",
- mDisplayName, layerIndex, dumpLogStrPng, pixFormatStr);
- }
- }
-#endif
- if (needDumpRaw && hnd->base) {
- char dumpFilename[PATH_MAX];
- bool bResult = false;
- snprintf(dumpFilename, sizeof(dumpFilename),
- "%s/sfdump%03d.layer%zu.%dx%d.%s.%s.raw",
- mDumpDirRaw, mDumpCntrRaw,
- layerIndex, getWidth(hnd), getHeight(hnd),
- pixFormatStr, mDisplayName);
- FILE* fp = fopen(dumpFilename, "w+");
- if (NULL != fp) {
- bResult = (bool) fwrite((void*)hnd->base, hnd->size, 1, fp);
- fclose(fp);
- }
- ALOGI("Display[%s] Layer[%zu] %s Dump to %s: %s",
- mDisplayName, layerIndex, dumpLogStrRaw,
- dumpFilename, bResult ? "Success" : "Fail");
- }
-}
-
-void HwcDebug::getHalPixelFormatStr(int format, char pixFormatStr[], size_t arraySize)
-{
- if (!pixFormatStr)
- return;
-
- switch(format) {
- case HAL_PIXEL_FORMAT_RGBA_8888:
- strlcpy(pixFormatStr, "RGBA_8888", arraySize);
- break;
- case HAL_PIXEL_FORMAT_RGBX_8888:
- strlcpy(pixFormatStr, "RGBX_8888", arraySize);
- break;
- case HAL_PIXEL_FORMAT_RGB_888:
- strlcpy(pixFormatStr, "RGB_888", arraySize);
- break;
- case HAL_PIXEL_FORMAT_RGB_565:
- strlcpy(pixFormatStr, "RGB_565", arraySize);
- break;
- case HAL_PIXEL_FORMAT_BGRA_8888:
- strlcpy(pixFormatStr, "BGRA_8888", arraySize);
- break;
- case HAL_PIXEL_FORMAT_YV12:
- strlcpy(pixFormatStr, "YV12", arraySize);
- break;
- case HAL_PIXEL_FORMAT_YCbCr_422_SP:
- strlcpy(pixFormatStr, "YCbCr_422_SP_NV16", arraySize);
- break;
- case HAL_PIXEL_FORMAT_YCrCb_420_SP:
- strlcpy(pixFormatStr, "YCrCb_420_SP_NV21", arraySize);
- break;
- case HAL_PIXEL_FORMAT_YCbCr_422_I:
- strlcpy(pixFormatStr, "YCbCr_422_I_YUY2", arraySize);
- break;
- case HAL_PIXEL_FORMAT_YCrCb_422_I:
- strlcpy(pixFormatStr, "YCrCb_422_I_YVYU", arraySize);
- break;
- case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
- strlcpy(pixFormatStr, "NV12_ENCODEABLE", arraySize);
- break;
- case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED:
- strlcpy(pixFormatStr, "YCbCr_420_SP_TILED_TILE_4x2",
- arraySize);
- break;
- case HAL_PIXEL_FORMAT_YCbCr_420_SP:
- strlcpy(pixFormatStr, "YCbCr_420_SP", arraySize);
- break;
- case HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO:
- strlcpy(pixFormatStr, "YCrCb_420_SP_ADRENO", arraySize);
- break;
- case HAL_PIXEL_FORMAT_YCrCb_422_SP:
- strlcpy(pixFormatStr, "YCrCb_422_SP", arraySize);
- break;
- case HAL_PIXEL_FORMAT_R_8:
- strlcpy(pixFormatStr, "R_8", arraySize);
- break;
- case HAL_PIXEL_FORMAT_RG_88:
- strlcpy(pixFormatStr, "RG_88", arraySize);
- break;
- case HAL_PIXEL_FORMAT_INTERLACE:
- strlcpy(pixFormatStr, "INTERLACE", arraySize);
- break;
- case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
- strlcpy(pixFormatStr, "YCbCr_420_SP_VENUS", arraySize);
- break;
- default:
- snprintf(pixFormatStr, arraySize, "Unknown0x%X", format);
- break;
- }
-}
-
-} // namespace qhwc
-
diff --git a/msm8909/libhwcomposer/hwc_dump_layers.h b/msm8909/libhwcomposer/hwc_dump_layers.h
deleted file mode 100644
index 83e56c0f..00000000
--- a/msm8909/libhwcomposer/hwc_dump_layers.h
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * Copyright (c) 2012-2013,2016 Linux Foundation. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials provided
- * with the distribution.
- * * Neither the name of Linux Foundation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
- * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
- * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef HWC_DUMP_LAYERS_H
-#define HWC_DUMP_LAYERS_H
-
-#include <gralloc_priv.h>
-#include <comptype.h>
-#include <hardware/hwcomposer.h>
-
-namespace qhwc {
-
-class HwcDebug {
-private:
-
-// Using static variables for layer dumping since "property_set("debug.sf.dump",
-// property)" does not work.
- int mDumpCntLimRaw;
- int mDumpCntrRaw;
- char mDumpPropStrRaw[PROPERTY_VALUE_MAX];
- char mDumpDirRaw[PATH_MAX];
- int mDumpCntLimPng;
- int mDumpCntrPng;
- char mDumpPropStrPng[PROPERTY_VALUE_MAX];
- char mDumpDirPng[PATH_MAX];
- uint32_t mDpy;
- char mDisplayName[PROPERTY_VALUE_MAX];
- char mDumpPropKeyDisplayType[PROPERTY_KEY_MAX];
- static bool sDumpEnable;
-
-public:
- HwcDebug(uint32_t dpy);
- ~HwcDebug() {};
-
- /*
- * Dump layers for debugging based on "debug.sf.dump*" system property.
- * See needToDumpLayers() for usage.
- *
- * @param: list - The HWC layer-list to dump.
- *
- */
- void dumpLayers(hwc_display_contents_1_t* list);
-
-/*
- * Checks if layers need to be dumped based on system property "debug.sf.dump"
- * for raw dumps and "debug.sf.dump.png" for png dumps.
- *
- * Note: Set "debug.sf.dump.primary" or "debug.sf.dump.external" as true
- * in the device's /system/build.prop file to enable layer logging/capturing
- * feature for primary or external respectively. The feature is disabled by
- * default to avoid per-frame property_get() calls.
- *
- * To turn on layer dump, set "debug.sf.dump.enable" to true in build.prop.
- * By default debug.sf.dump.primary will be set to true for user convenience.
- *
- * To turn on layer dump for primary, do,
- * adb shell setprop debug.sf.dump.primary true
- *
- * To turn on layer dump for external, do,
- * adb shell setprop debug.sf.dump.external true
- *
- * For example, to dump 25 frames in raw format, do,
- * adb shell setprop debug.sf.dump 25
- * Layers are dumped in a time-stamped location: /data/sfdump*.
- *
- * To dump 10 frames in png format, do,
- * adb shell setprop debug.sf.dump.png 10
- * To dump another 25 or so frames in raw format, do,
- * adb shell setprop debug.sf.dump 26
- *
- * To turn off logcat logging of layer-info, set both properties to 0,
- * adb shell setprop debug.sf.dump.png 0
- * adb shell setprop debug.sf.dump 0
- *
- * @return: true if layers need to be dumped (or logcat-ed).
- */
-bool needToDumpLayers();
-
-/*
- * Log a few per-frame hwc properties into logcat.
- *
- * @param: listFlags - Flags used in hwcomposer's list.
- *
- */
-void logHwcProps(uint32_t listFlags);
-
-/*
- * Log a layer's info into logcat.
- *
- * @param: layerIndex - Index of layer being dumped.
- * @param: hwLayers - Address of hwc_layer_1_t to log and dump.
- *
- */
-void logLayer(size_t layerIndex, hwc_layer_1_t hwLayers[]);
-
-/*
- * Dumps a layer buffer into raw/png files.
- *
- * @param: layerIndex - Index of layer being dumped.
- * @param: hwLayers - Address of hwc_layer_1_t to log and dump.
- *
- */
-void dumpLayer(size_t layerIndex, hwc_layer_1_t hwLayers[]);
-
-void getHalPixelFormatStr(int format, char pixelformatstr[], size_t arraySize);
-};
-
-} // namespace qhwc
-
-#endif /* HWC_DUMP_LAYERS_H */
diff --git a/msm8909/libhwcomposer/hwc_fbupdate.cpp b/msm8909/libhwcomposer/hwc_fbupdate.cpp
deleted file mode 100644
index b0032661..00000000
--- a/msm8909/libhwcomposer/hwc_fbupdate.cpp
+++ /dev/null
@@ -1,565 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- * Copyright (C) 2012-2014, The Linux Foundation. All rights reserved.
- *
- * Not a Contribution, Apache license notifications and license are
- * retained for attribution purposes only.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define DEBUG_FBUPDATE 0
-#include <cutils/properties.h>
-#include <gralloc_priv.h>
-#include <overlay.h>
-#include <overlayRotator.h>
-#include "hwc_fbupdate.h"
-#include "mdp_version.h"
-
-using namespace qdutils;
-using namespace overlay;
-using overlay::Rotator;
-using namespace overlay::utils;
-
-namespace qhwc {
-
-namespace ovutils = overlay::utils;
-
-IFBUpdate* IFBUpdate::getObject(hwc_context_t *ctx, const int& dpy) {
- if(qdutils::MDPVersion::getInstance().isSrcSplit()) {
- return new FBSrcSplit(ctx, dpy);
- } else if(isDisplaySplit(ctx, dpy)) {
- return new FBUpdateSplit(ctx, dpy);
- }
- return new FBUpdateNonSplit(ctx, dpy);
-}
-
-IFBUpdate::IFBUpdate(hwc_context_t *ctx, const int& dpy) : mDpy(dpy) {
- unsigned int size = 0;
- uint32_t xres = ctx->dpyAttr[mDpy].xres;
- uint32_t yres = ctx->dpyAttr[mDpy].yres;
- if (ctx->dpyAttr[dpy].customFBSize) {
- //GPU will render and compose at new resolution
- //So need to have FB at new resolution
- xres = ctx->dpyAttr[mDpy].xres_new;
- yres = ctx->dpyAttr[mDpy].yres_new;
- }
- getBufferAttributes((int)xres, (int)yres,
- ctx->dpyAttr[mDpy].fbformat,
- 0,
- mAlignedFBWidth,
- mAlignedFBHeight,
- mTileEnabled, size);
-}
-
-void IFBUpdate::reset() {
- mModeOn = false;
- mRot = NULL;
-}
-
-bool IFBUpdate::prepareAndValidate(hwc_context_t *ctx,
- hwc_display_contents_1 *list, int fbZorder) {
- hwc_layer_1_t *layer = &list->hwLayers[list->numHwLayers - 1];
- mModeOn = prepare(ctx, list, layer->displayFrame, fbZorder) &&
- ctx->mOverlay->validateAndSet(mDpy, ctx->dpyAttr[mDpy].fd);
- return mModeOn;
-}
-
-//================= Low res====================================
-FBUpdateNonSplit::FBUpdateNonSplit(hwc_context_t *ctx, const int& dpy):
- IFBUpdate(ctx, dpy) {}
-
-void FBUpdateNonSplit::reset() {
- IFBUpdate::reset();
- mDest = ovutils::OV_INVALID;
-}
-
-bool FBUpdateNonSplit::preRotateExtDisplay(hwc_context_t *ctx,
- hwc_layer_1_t *layer,
- ovutils::Whf &info,
- hwc_rect_t& sourceCrop,
- ovutils::eMdpFlags& mdpFlags,
- int& rotFlags)
-{
- int extOrient = getExtOrientation(ctx);
- ovutils::eTransform orient = static_cast<ovutils::eTransform >(extOrient);
- if(mDpy && (extOrient & HWC_TRANSFORM_ROT_90)) {
- mRot = ctx->mRotMgr->getNext();
- if(mRot == NULL) return false;
- ctx->mLayerRotMap[mDpy]->add(layer, mRot);
- // Composed FB content will have black bars, if the viewFrame of the
- // external is different from {0, 0, fbWidth, fbHeight}, so intersect
- // viewFrame with sourceCrop to avoid those black bars
- sourceCrop = getIntersection(sourceCrop, ctx->mViewFrame[mDpy]);
- //Configure rotator for pre-rotation
- if(configRotator(mRot, info, sourceCrop, mdpFlags, orient, 0) < 0) {
- ALOGE("%s: configRotator Failed!", __FUNCTION__);
- mRot = NULL;
- return false;
- }
- updateSource(orient, info, sourceCrop, mRot);
- rotFlags |= ovutils::ROT_PREROTATED;
- }
- return true;
-}
-
-bool FBUpdateNonSplit::prepare(hwc_context_t *ctx, hwc_display_contents_1 *list,
- hwc_rect_t fbUpdatingRect, int fbZorder) {
- if(!ctx->mMDP.hasOverlay) {
- ALOGD_IF(DEBUG_FBUPDATE, "%s, this hw doesnt support overlays",
- __FUNCTION__);
- return false;
- }
- mModeOn = configure(ctx, list, fbUpdatingRect, fbZorder);
- return mModeOn;
-}
-
-// Configure
-bool FBUpdateNonSplit::configure(hwc_context_t *ctx, hwc_display_contents_1 *list,
- hwc_rect_t fbUpdatingRect, int fbZorder) {
- bool ret = false;
- hwc_layer_1_t *layer = &list->hwLayers[list->numHwLayers - 1];
- if (LIKELY(ctx->mOverlay)) {
- overlay::Overlay& ov = *(ctx->mOverlay);
-
- ovutils::Whf info(mAlignedFBWidth, mAlignedFBHeight,
- ovutils::getMdpFormat(ctx->dpyAttr[mDpy].fbformat,
- mTileEnabled));
-
- Overlay::PipeSpecs pipeSpecs;
- pipeSpecs.formatClass = Overlay::FORMAT_RGB;
- pipeSpecs.needsScaling = qhwc::needsScaling(layer);
- pipeSpecs.dpy = mDpy;
- pipeSpecs.mixer = Overlay::MIXER_DEFAULT;
- pipeSpecs.fb = true;
-
- ovutils::eDest dest = ov.getPipe(pipeSpecs);
- if(dest == ovutils::OV_INVALID) { //None available
- ALOGE("%s: No pipes available to configure fb for dpy %d",
- __FUNCTION__, mDpy);
- return false;
- }
- mDest = dest;
-
- if((mDpy && ctx->deviceOrientation) &&
- ctx->listStats[mDpy].isDisplayAnimating) {
- fbZorder = 0;
- }
-
- ovutils::eMdpFlags mdpFlags = ovutils::OV_MDP_BLEND_FG_PREMULT;
- ovutils::eZorder zOrder = static_cast<ovutils::eZorder>(fbZorder);
-
- hwc_rect_t sourceCrop = integerizeSourceCrop(layer->sourceCropf);
- hwc_rect_t displayFrame = layer->displayFrame;
-
- // No FB update optimization on (1) Custom FB resolution,
- // (2) External Mirror mode, (3) External orientation
- if(!ctx->dpyAttr[mDpy].customFBSize && !ctx->mBufferMirrorMode
- && !ctx->mExtOrientation) {
- sourceCrop = fbUpdatingRect;
- displayFrame = fbUpdatingRect;
- }
-
- int transform = layer->transform;
- int rotFlags = ovutils::ROT_FLAGS_NONE;
-
- ovutils::eTransform orient =
- static_cast<ovutils::eTransform>(transform);
- // use ext orientation if any
- int extOrient = getExtOrientation(ctx);
-
- // Do not use getNonWormholeRegion() function to calculate the
- // sourceCrop during animation on external display and
- // Dont do wormhole calculation when extorientation is set on External
- // Dont do wormhole calculation when scaling mode is set on External
- if(ctx->listStats[mDpy].isDisplayAnimating && mDpy) {
- sourceCrop = layer->displayFrame;
- } else if((mDpy && !extOrient
- && !ctx->dpyAttr[mDpy].mMDPScalingMode)) {
- if(ctx->mOverlay->isUIScalingOnExternalSupported() &&
- !ctx->dpyAttr[mDpy].customFBSize) {
- getNonWormholeRegion(list, sourceCrop);
- displayFrame = sourceCrop;
- }
- }
- calcExtDisplayPosition(ctx, NULL, mDpy, sourceCrop, displayFrame,
- transform, orient);
- //Store the displayFrame, will be used in getDisplayViewFrame
- ctx->dpyAttr[mDpy].mDstRect = displayFrame;
- setMdpFlags(ctx, layer, mdpFlags, 0, transform);
- // For External use rotator if there is a rotation value set
- ret = preRotateExtDisplay(ctx, layer, info,
- sourceCrop, mdpFlags, rotFlags);
- if(!ret) {
- ALOGE("%s: preRotate for external Failed!", __FUNCTION__);
- return false;
- }
- //For the mdp, since either we are pre-rotating or MDP does flips
- orient = ovutils::OVERLAY_TRANSFORM_0;
- transform = 0;
- ovutils::PipeArgs parg(mdpFlags, info, zOrder,
- static_cast<ovutils::eRotFlags>(rotFlags),
- ovutils::DEFAULT_PLANE_ALPHA,
- (ovutils::eBlending)
- getBlending(layer->blending));
- ret = true;
- if(configMdp(ctx->mOverlay, parg, orient, sourceCrop, displayFrame,
- NULL, mDest) < 0) {
- ALOGE("%s: configMdp failed for dpy %d", __FUNCTION__, mDpy);
- ret = false;
- }
- }
- return ret;
-}
-
-bool FBUpdateNonSplit::draw(hwc_context_t *ctx, private_handle_t *hnd)
-{
- if(!mModeOn) {
- return true;
- }
- bool ret = true;
- overlay::Overlay& ov = *(ctx->mOverlay);
- ovutils::eDest dest = mDest;
- int fd = hnd->fd;
- uint32_t offset = (uint32_t)hnd->offset;
- if(mRot) {
- if(!mRot->queueBuffer(fd, offset))
- return false;
- fd = mRot->getDstMemId();
- offset = mRot->getDstOffset();
- }
- if (!ov.queueBuffer(fd, offset, dest)) {
- ALOGE("%s: queueBuffer failed for FBUpdate", __FUNCTION__);
- ret = false;
- }
- return ret;
-}
-
-//================= High res====================================
-FBUpdateSplit::FBUpdateSplit(hwc_context_t *ctx, const int& dpy):
- IFBUpdate(ctx, dpy) {}
-
-void FBUpdateSplit::reset() {
- IFBUpdate::reset();
- mDestLeft = ovutils::OV_INVALID;
- mDestRight = ovutils::OV_INVALID;
- mRot = NULL;
-}
-
-bool FBUpdateSplit::prepare(hwc_context_t *ctx, hwc_display_contents_1 *list,
- hwc_rect_t fbUpdatingRect, int fbZorder) {
- if(!ctx->mMDP.hasOverlay) {
- ALOGD_IF(DEBUG_FBUPDATE, "%s, this hw doesnt support overlays",
- __FUNCTION__);
- return false;
- }
- mModeOn = configure(ctx, list, fbUpdatingRect, fbZorder);
- ALOGD_IF(DEBUG_FBUPDATE, "%s, mModeOn = %d", __FUNCTION__, mModeOn);
- return mModeOn;
-}
-
-// Configure
-bool FBUpdateSplit::configure(hwc_context_t *ctx,
- hwc_display_contents_1 *list, hwc_rect_t fbUpdatingRect, int fbZorder) {
- bool ret = false;
- hwc_layer_1_t *layer = &list->hwLayers[list->numHwLayers - 1];
- if (LIKELY(ctx->mOverlay)) {
- ovutils::Whf info(mAlignedFBWidth, mAlignedFBHeight,
- ovutils::getMdpFormat(HAL_PIXEL_FORMAT_RGBA_8888,
- mTileEnabled));
-
- overlay::Overlay& ov = *(ctx->mOverlay);
- ovutils::eMdpFlags mdpFlags = ovutils::OV_MDP_BLEND_FG_PREMULT;
- ovutils::eZorder zOrder = static_cast<ovutils::eZorder>(fbZorder);
- ovutils::eTransform orient =
- static_cast<ovutils::eTransform>(layer->transform);
- const int hw_w = ctx->dpyAttr[mDpy].xres;
- const int hw_h = ctx->dpyAttr[mDpy].yres;
- const int lSplit = getLeftSplit(ctx, mDpy);
- mDestLeft = ovutils::OV_INVALID;
- mDestRight = ovutils::OV_INVALID;
- hwc_rect_t sourceCrop = integerizeSourceCrop(layer->sourceCropf);
- hwc_rect_t displayFrame = layer->displayFrame;
-
- // No FB update optimization on (1) Custom FB resolution,
- // (2) External Mirror mode, (3) External orientation
- if(!ctx->dpyAttr[mDpy].customFBSize && !ctx->mBufferMirrorMode
- && !ctx->mExtOrientation) {
- sourceCrop = fbUpdatingRect;
- displayFrame = fbUpdatingRect;
- }
-
- int transform = layer->transform;
- // use ext orientation if any
- int extOrient = getExtOrientation(ctx);
-
- // Do not use getNonWormholeRegion() function to calculate the
- // sourceCrop during animation on external display and
- // Dont do wormhole calculation when extorientation is set on External
- // Dont do wormhole calculation when scaling mode is set on External
- if(ctx->listStats[mDpy].isDisplayAnimating && mDpy) {
- sourceCrop = layer->displayFrame;
- } else if((mDpy && !extOrient
- && !ctx->dpyAttr[mDpy].mMDPScalingMode)) {
- if(!qdutils::MDPVersion::getInstance().is8x26() &&
- !ctx->dpyAttr[mDpy].customFBSize) {
- getNonWormholeRegion(list, sourceCrop);
- displayFrame = sourceCrop;
- }
- }
-
- calcExtDisplayPosition(ctx, NULL, mDpy, sourceCrop, displayFrame,
- transform, orient);
-
- ret = true;
- Overlay::PipeSpecs pipeSpecs;
- pipeSpecs.formatClass = Overlay::FORMAT_RGB;
- pipeSpecs.needsScaling = qhwc::needsScaling(layer);
- pipeSpecs.dpy = mDpy;
- pipeSpecs.fb = true;
-
- /* Configure left pipe */
- if(displayFrame.left < lSplit) {
- pipeSpecs.mixer = Overlay::MIXER_LEFT;
- ovutils::eDest destL = ov.getPipe(pipeSpecs);
- if(destL == ovutils::OV_INVALID) { //None available
- ALOGE("%s: No pipes available to configure fb for dpy %d's left"
- " mixer", __FUNCTION__, mDpy);
- return false;
- }
-
- mDestLeft = destL;
-
- //XXX: FB layer plane alpha is currently sent as zero from
- //surfaceflinger
- ovutils::PipeArgs pargL(mdpFlags,
- info,
- zOrder,
- ovutils::ROT_FLAGS_NONE,
- ovutils::DEFAULT_PLANE_ALPHA,
- (ovutils::eBlending)
- getBlending(layer->blending));
- hwc_rect_t cropL = sourceCrop;
- hwc_rect_t dstL = displayFrame;
- hwc_rect_t scissorL = {0, 0, lSplit, hw_h };
- qhwc::calculate_crop_rects(cropL, dstL, scissorL, 0);
-
- if (configMdp(ctx->mOverlay, pargL, orient, cropL,
- dstL, NULL, destL)< 0) {
- ALOGE("%s: configMdp fails for left FB", __FUNCTION__);
- ret = false;
- }
- }
-
- /* Configure right pipe */
- if(displayFrame.right > lSplit) {
- pipeSpecs.mixer = Overlay::MIXER_RIGHT;
- ovutils::eDest destR = ov.getPipe(pipeSpecs);
- if(destR == ovutils::OV_INVALID) { //None available
- ALOGE("%s: No pipes available to configure fb for dpy %d's"
- " right mixer", __FUNCTION__, mDpy);
- return false;
- }
-
- mDestRight = destR;
- ovutils::eMdpFlags mdpFlagsR = mdpFlags;
- ovutils::setMdpFlags(mdpFlagsR, ovutils::OV_MDSS_MDP_RIGHT_MIXER);
-
- //XXX: FB layer plane alpha is currently sent as zero from
- //surfaceflinger
- ovutils::PipeArgs pargR(mdpFlagsR,
- info,
- zOrder,
- ovutils::ROT_FLAGS_NONE,
- ovutils::DEFAULT_PLANE_ALPHA,
- (ovutils::eBlending)
- getBlending(layer->blending));
-
- hwc_rect_t cropR = sourceCrop;
- hwc_rect_t dstR = displayFrame;
- hwc_rect_t scissorR = {lSplit, 0, hw_w, hw_h };
- qhwc::calculate_crop_rects(cropR, dstR, scissorR, 0);
-
- dstR.left -= lSplit;
- dstR.right -= lSplit;
-
- if (configMdp(ctx->mOverlay, pargR, orient, cropR,
- dstR, NULL, destR) < 0) {
- ALOGE("%s: configMdp fails for right FB", __FUNCTION__);
- ret = false;
- }
- }
- }
- return ret;
-}
-
-bool FBUpdateSplit::draw(hwc_context_t *ctx, private_handle_t *hnd)
-{
- if(!mModeOn) {
- return true;
- }
- bool ret = true;
- overlay::Overlay& ov = *(ctx->mOverlay);
- if(mDestLeft != ovutils::OV_INVALID) {
- if (!ov.queueBuffer(hnd->fd, (uint32_t)hnd->offset, mDestLeft)) {
- ALOGE("%s: queue failed for left of dpy = %d",
- __FUNCTION__, mDpy);
- ret = false;
- }
- }
- if(mDestRight != ovutils::OV_INVALID) {
- if (!ov.queueBuffer(hnd->fd, (uint32_t)hnd->offset, mDestRight)) {
- ALOGE("%s: queue failed for right of dpy = %d",
- __FUNCTION__, mDpy);
- ret = false;
- }
- }
- return ret;
-}
-
-//=================FBSrcSplit====================================
-FBSrcSplit::FBSrcSplit(hwc_context_t *ctx, const int& dpy):
- FBUpdateSplit(ctx, dpy) {}
-
-bool FBSrcSplit::configure(hwc_context_t *ctx, hwc_display_contents_1 *list,
- hwc_rect_t fbUpdatingRect, int fbZorder) {
- hwc_layer_1_t *layer = &list->hwLayers[list->numHwLayers - 1];
- overlay::Overlay& ov = *(ctx->mOverlay);
-
- ovutils::Whf info(mAlignedFBWidth,
- mAlignedFBHeight,
- ovutils::getMdpFormat(HAL_PIXEL_FORMAT_RGBA_8888,
- mTileEnabled));
-
- ovutils::eMdpFlags mdpFlags = OV_MDP_BLEND_FG_PREMULT;
- ovutils::eZorder zOrder = static_cast<ovutils::eZorder>(fbZorder);
-
- ovutils::PipeArgs parg(mdpFlags,
- info,
- zOrder,
- ovutils::ROT_FLAGS_NONE,
- ovutils::DEFAULT_PLANE_ALPHA,
- (ovutils::eBlending)
- getBlending(layer->blending));
-
- hwc_rect_t sourceCrop = integerizeSourceCrop(layer->sourceCropf);
- hwc_rect_t displayFrame = layer->displayFrame;
-
- // No FB update optimization on (1) Custom FB resolution,
- // (2) External Mirror mode, (3) External orientation
- if(!ctx->dpyAttr[mDpy].customFBSize && !ctx->mBufferMirrorMode
- && !ctx->mExtOrientation) {
- sourceCrop = fbUpdatingRect;
- displayFrame = fbUpdatingRect;
- }
- int transform = layer->transform;
- ovutils::eTransform orient =
- static_cast<ovutils::eTransform>(transform);
-
- // use ext orientation if any
- int extOrient = getExtOrientation(ctx);
-
- // Do not use getNonWormholeRegion() function to calculate the
- // sourceCrop during animation on external display and
- // Dont do wormhole calculation when extorientation is set on External
- // Dont do wormhole calculation when scaling mode is set on External
- if(ctx->listStats[mDpy].isDisplayAnimating && mDpy) {
- sourceCrop = layer->displayFrame;
- } else if((mDpy && !extOrient
- && !ctx->dpyAttr[mDpy].mMDPScalingMode)) {
- if(!qdutils::MDPVersion::getInstance().is8x26() &&
- !ctx->dpyAttr[mDpy].customFBSize) {
- getNonWormholeRegion(list, sourceCrop);
- displayFrame = sourceCrop;
- }
- }
-
- calcExtDisplayPosition(ctx, NULL, mDpy, sourceCrop, displayFrame,
- transform, orient);
- hwc_rect_t cropL = sourceCrop;
- hwc_rect_t cropR = sourceCrop;
- hwc_rect_t dstL = displayFrame;
- hwc_rect_t dstR = displayFrame;
-
- //Request left pipe (or 1 by default)
- Overlay::PipeSpecs pipeSpecs;
- pipeSpecs.formatClass = Overlay::FORMAT_RGB;
- pipeSpecs.needsScaling = qhwc::needsScaling(layer);
- pipeSpecs.dpy = mDpy;
- pipeSpecs.mixer = Overlay::MIXER_DEFAULT;
- pipeSpecs.fb = true;
- ovutils::eDest destL = ov.getPipe(pipeSpecs);
- if(destL == ovutils::OV_INVALID) {
- ALOGE("%s: No pipes available to configure fb for dpy %d's left"
- " mixer", __FUNCTION__, mDpy);
- return false;
- }
-
- ovutils::eDest destR = ovutils::OV_INVALID;
-
- /* Use 2 pipes IF
- a) FB's width is > Mixer width or
- b) On primary, driver has indicated with caps to split always. This is
- based on an empirically derived value of panel height.
- */
-
- const bool primarySplitAlways = (mDpy == HWC_DISPLAY_PRIMARY) and
- qdutils::MDPVersion::getInstance().isSrcSplitAlways();
- const uint32_t lSplit = getLeftSplit(ctx, mDpy);
- const uint32_t cropWidth = sourceCrop.right - sourceCrop.left;
-
- if((cropWidth > qdutils::MDPVersion::getInstance().getMaxMixerWidth()) or
- (primarySplitAlways and cropWidth > lSplit)) {
- destR = ov.getPipe(pipeSpecs);
- if(destR == ovutils::OV_INVALID) {
- ALOGE("%s: No pipes available to configure fb for dpy %d's right"
- " mixer", __FUNCTION__, mDpy);
- return false;
- }
-
- if(ctx->mOverlay->comparePipePriority(destL, destR) == -1) {
- qhwc::swap(destL, destR);
- }
-
- //Split crop equally when using 2 pipes
- cropL.right = (sourceCrop.right + sourceCrop.left) / 2;
- cropR.left = cropL.right;
- dstL.right = (displayFrame.right + displayFrame.left) / 2;
- dstR.left = dstL.right;
- }
-
- mDestLeft = destL;
- mDestRight = destR;
-
- if(destL != OV_INVALID) {
- if(configMdp(ctx->mOverlay, parg, orient,
- cropL, dstL, NULL /*metadata*/, destL) < 0) {
- ALOGE("%s: commit failed for left mixer config", __FUNCTION__);
- return false;
- }
- }
-
- //configure right pipe
- if(destR != OV_INVALID) {
- if(configMdp(ctx->mOverlay, parg, orient,
- cropR, dstR, NULL /*metadata*/, destR) < 0) {
- ALOGE("%s: commit failed for right mixer config", __FUNCTION__);
- return false;
- }
- }
-
- return true;
-}
-
-//---------------------------------------------------------------------
-}; //namespace qhwc
diff --git a/msm8909/libhwcomposer/hwc_fbupdate.h b/msm8909/libhwcomposer/hwc_fbupdate.h
deleted file mode 100644
index 545f5bd0..00000000
--- a/msm8909/libhwcomposer/hwc_fbupdate.h
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- * Copyright (C) 2012, The Linux Foundation. All rights reserved.
- *
- * Not a Contribution, Apache license notifications and license are
- * retained for attribution purposes only.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#ifndef HWC_FBUPDATE_H
-#define HWC_FBUPDATE_H
-#include "hwc_utils.h"
-#include "overlay.h"
-
-#define LIKELY( exp ) (__builtin_expect( (exp) != 0, true ))
-#define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false ))
-
-namespace overlay {
- class Rotator;
-}
-
-namespace qhwc {
-namespace ovutils = overlay::utils;
-
-//Framebuffer update Interface
-class IFBUpdate {
-public:
- explicit IFBUpdate(hwc_context_t *ctx, const int& dpy);
- virtual ~IFBUpdate() {};
- // Sets up members and prepares overlay if conditions are met
- virtual bool prepare(hwc_context_t *ctx, hwc_display_contents_1 *list,
- hwc_rect_t fbUpdatingRect, int fbZorder) = 0;
- virtual bool prepareAndValidate(hwc_context_t *ctx,
- hwc_display_contents_1 *list, int fbZorder);
- // Draws layer
- virtual bool draw(hwc_context_t *ctx, private_handle_t *hnd) = 0;
- //Reset values
- virtual void reset();
- //Factory method that returns a low-res or high-res version
- static IFBUpdate *getObject(hwc_context_t *ctx, const int& dpy);
-
-protected:
- const int mDpy; // display to update
- bool mModeOn; // if prepare happened
- overlay::Rotator *mRot;
- int mAlignedFBWidth;
- int mAlignedFBHeight;
- int mTileEnabled;
-};
-
-//Non-Split panel handler.
-class FBUpdateNonSplit : public IFBUpdate {
-public:
- explicit FBUpdateNonSplit(hwc_context_t *ctx, const int& dpy);
- virtual ~FBUpdateNonSplit() {};
- bool prepare(hwc_context_t *ctx, hwc_display_contents_1 *list,
- hwc_rect_t fbUpdatingRect, int fbZorder);
- bool draw(hwc_context_t *ctx, private_handle_t *hnd);
- void reset();
-private:
- bool configure(hwc_context_t *ctx, hwc_display_contents_1 *list,
- hwc_rect_t fbUpdatingRect, int fbZorder);
- bool preRotateExtDisplay(hwc_context_t *ctx,
- hwc_layer_1_t *layer,
- ovutils::Whf &info,
- hwc_rect_t& sourceCrop,
- ovutils::eMdpFlags& mdpFlags,
- int& rotFlags);
- ovutils::eDest mDest; //pipe to draw on
-};
-
-//Split panel handler.
-class FBUpdateSplit : public IFBUpdate {
-public:
- explicit FBUpdateSplit(hwc_context_t *ctx, const int& dpy);
- virtual ~FBUpdateSplit() {};
- bool prepare(hwc_context_t *ctx, hwc_display_contents_1 *list,
- hwc_rect_t fbUpdatingRect, int fbZorder);
- bool draw(hwc_context_t *ctx, private_handle_t *hnd);
- void reset();
-
-protected:
- virtual bool configure(hwc_context_t *ctx, hwc_display_contents_1 *list,
- hwc_rect_t fbUpdatingRect, int fbZorder);
- ovutils::eDest mDestLeft; //left pipe to draw on
- ovutils::eDest mDestRight; //right pipe to draw on
-};
-
-//Source Split Handler
-class FBSrcSplit : public FBUpdateSplit {
-public:
- explicit FBSrcSplit(hwc_context_t *ctx, const int& dpy);
- virtual ~FBSrcSplit() {};
-private:
- bool configure(hwc_context_t *ctx, hwc_display_contents_1 *list,
- hwc_rect_t fbUpdatingRect, int fbZorder);
-};
-
-}; //namespace qhwc
-
-#endif //HWC_FBUPDATE_H
diff --git a/msm8909/libhwcomposer/hwc_mdpcomp.cpp b/msm8909/libhwcomposer/hwc_mdpcomp.cpp
deleted file mode 100644
index 93e09455..00000000
--- a/msm8909/libhwcomposer/hwc_mdpcomp.cpp
+++ /dev/null
@@ -1,2827 +0,0 @@
-/*
- * Copyright (C) 2012-2016, The Linux Foundation. All rights reserved.
- * Not a Contribution, Apache license notifications and license are retained
- * for attribution purposes only.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <math.h>
-#include "hwc_mdpcomp.h"
-#include <sys/ioctl.h>
-#include "hdmi.h"
-#include "qdMetaData.h"
-#include "mdp_version.h"
-#include "hwc_fbupdate.h"
-#include "hwc_ad.h"
-#include <overlayRotator.h>
-#include "hwc_copybit.h"
-#include "qd_utils.h"
-
-using namespace overlay;
-using namespace qdutils;
-using namespace overlay::utils;
-namespace ovutils = overlay::utils;
-
-namespace qhwc {
-
-//==============MDPComp========================================================
-
-IdleInvalidator *MDPComp::sIdleInvalidator = NULL;
-bool MDPComp::sIdleFallBack = false;
-bool MDPComp::sDebugLogs = false;
-bool MDPComp::sEnabled = false;
-bool MDPComp::sEnableMixedMode = true;
-int MDPComp::sSimulationFlags = 0;
-int MDPComp::sMaxPipesPerMixer = MAX_PIPES_PER_MIXER;
-bool MDPComp::sEnableYUVsplit = false;
-bool MDPComp::sSrcSplitEnabled = false;
-bool MDPComp::enablePartialUpdateForMDP3 = false;
-bool MDPComp::sIsPartialUpdateActive = true;
-MDPComp* MDPComp::getObject(hwc_context_t *ctx, const int& dpy) {
- if(qdutils::MDPVersion::getInstance().isSrcSplit()) {
- sSrcSplitEnabled = true;
- return new MDPCompSrcSplit(dpy);
- } else if(isDisplaySplit(ctx, dpy)) {
- return new MDPCompSplit(dpy);
- }
- return new MDPCompNonSplit(dpy);
-}
-
-MDPComp::MDPComp(int dpy) : mDpy(dpy), mModeOn(false), mPrevModeOn(false) {
-};
-
-void MDPComp::dump(android::String8& buf, hwc_context_t *ctx)
-{
- if(mCurrentFrame.layerCount > MAX_NUM_APP_LAYERS)
- return;
-
- dumpsys_log(buf,"HWC Map for Dpy: %s \n",
- (mDpy == 0) ? "\"PRIMARY\"" :
- (mDpy == 1) ? "\"EXTERNAL\"" : "\"VIRTUAL\"");
- dumpsys_log(buf,"CURR_FRAME: layerCount:%2d mdpCount:%2d "
- "fbCount:%2d \n", mCurrentFrame.layerCount,
- mCurrentFrame.mdpCount, mCurrentFrame.fbCount);
- dumpsys_log(buf,"needsFBRedraw:%3s pipesUsed:%2d MaxPipesPerMixer: %d \n",
- (mCurrentFrame.needsRedraw? "YES" : "NO"),
- mCurrentFrame.mdpCount, sMaxPipesPerMixer);
- if(isDisplaySplit(ctx, mDpy)) {
- dumpsys_log(buf, "Programmed ROI's: Left: [%d, %d, %d, %d] "
- "Right: [%d, %d, %d, %d] \n",
- ctx->listStats[mDpy].lRoi.left, ctx->listStats[mDpy].lRoi.top,
- ctx->listStats[mDpy].lRoi.right,
- ctx->listStats[mDpy].lRoi.bottom,
- ctx->listStats[mDpy].rRoi.left,ctx->listStats[mDpy].rRoi.top,
- ctx->listStats[mDpy].rRoi.right,
- ctx->listStats[mDpy].rRoi.bottom);
- } else {
- dumpsys_log(buf, "Programmed ROI: [%d, %d, %d, %d] \n",
- ctx->listStats[mDpy].lRoi.left,ctx->listStats[mDpy].lRoi.top,
- ctx->listStats[mDpy].lRoi.right,
- ctx->listStats[mDpy].lRoi.bottom);
- }
- dumpsys_log(buf," --------------------------------------------- \n");
- dumpsys_log(buf," listIdx | cached? | mdpIndex | comptype | Z \n");
- dumpsys_log(buf," --------------------------------------------- \n");
- for(int index = 0; index < mCurrentFrame.layerCount; index++ )
- dumpsys_log(buf," %7d | %7s | %8d | %9s | %2d \n",
- index,
- (mCurrentFrame.isFBComposed[index] ? "YES" : "NO"),
- mCurrentFrame.layerToMDP[index],
- (mCurrentFrame.isFBComposed[index] ?
- (mCurrentFrame.drop[index] ? "DROP" :
- (mCurrentFrame.needsRedraw ? "GLES" : "CACHE")) : "MDP"),
- (mCurrentFrame.isFBComposed[index] ? mCurrentFrame.fbZ :
- mCurrentFrame.mdpToLayer[mCurrentFrame.layerToMDP[index]].pipeInfo->zOrder));
- dumpsys_log(buf,"\n");
-}
-
-bool MDPComp::init(hwc_context_t *ctx) {
-
- if(!ctx) {
- ALOGE("%s: Invalid hwc context!!",__FUNCTION__);
- return false;
- }
-
- char property[PROPERTY_VALUE_MAX] = {0};
-
- sEnabled = false;
- if((ctx->mMDP.version >= qdutils::MDP_V4_0) &&
- (property_get("persist.hwc.mdpcomp.enable", property, NULL) > 0) &&
- (!strncmp(property, "1", PROPERTY_VALUE_MAX ) ||
- (!strncasecmp(property,"true", PROPERTY_VALUE_MAX )))) {
- sEnabled = true;
- }
-
- sEnableMixedMode = true;
- if((property_get("debug.mdpcomp.mixedmode.disable", property, NULL) > 0) &&
- (!strncmp(property, "1", PROPERTY_VALUE_MAX ) ||
- (!strncasecmp(property,"true", PROPERTY_VALUE_MAX )))) {
- sEnableMixedMode = false;
- }
-
- sMaxPipesPerMixer = MAX_PIPES_PER_MIXER;
- if(property_get("debug.mdpcomp.maxpermixer", property, "-1") > 0) {
- int val = atoi(property);
- if(val >= 0)
- sMaxPipesPerMixer = min(val, MAX_PIPES_PER_MIXER);
- }
-
- if(ctx->mMDP.panel != MIPI_CMD_PANEL &&
- (ctx->mMDP.version >= qdutils::MDP_V4_0)) {
- sIdleInvalidator = IdleInvalidator::getInstance();
- if(sIdleInvalidator->init(timeout_handler, ctx) < 0) {
- delete sIdleInvalidator;
- sIdleInvalidator = NULL;
- }
- }
-
- if(!qdutils::MDPVersion::getInstance().isSrcSplit() &&
- !qdutils::MDPVersion::getInstance().isRotDownscaleEnabled() &&
- property_get("persist.mdpcomp.4k2kSplit", property, "0") > 0 &&
- (!strncmp(property, "1", PROPERTY_VALUE_MAX) ||
- !strncasecmp(property,"true", PROPERTY_VALUE_MAX))) {
- sEnableYUVsplit = true;
- }
-
- bool defaultPTOR = false;
- //Enable PTOR when "persist.hwc.ptor.enable" is not defined for
- //8x16 and 8x39 targets by default
- if((property_get("persist.hwc.ptor.enable", property, NULL) <= 0) &&
- (qdutils::MDPVersion::getInstance().is8x16() ||
- qdutils::MDPVersion::getInstance().is8x39())) {
- defaultPTOR = true;
- }
-
- if (defaultPTOR || (!strncasecmp(property, "true", PROPERTY_VALUE_MAX)) ||
- (!strncmp(property, "1", PROPERTY_VALUE_MAX ))) {
- ctx->mCopyBit[HWC_DISPLAY_PRIMARY] = new CopyBit(ctx,
- HWC_DISPLAY_PRIMARY);
- }
-
- if((property_get("persist.mdp3.partialUpdate", property, NULL) <= 0) &&
- (ctx->mMDP.version == qdutils::MDP_V3_0_5)) {
- enablePartialUpdateForMDP3 = true;
- }
-
- if(!enablePartialUpdateForMDP3 &&
- (!strncmp(property, "1", PROPERTY_VALUE_MAX ) ||
- (!strncasecmp(property,"true", PROPERTY_VALUE_MAX )))) {
- enablePartialUpdateForMDP3 = true;
- }
-
- int retPartialUpdatePref = getPartialUpdatePref(ctx);
- if(retPartialUpdatePref >= 0)
- sIsPartialUpdateActive = (retPartialUpdatePref != 0);
-
- return true;
-}
-
-void MDPComp::reset(hwc_context_t *ctx) {
- const int numLayers = ctx->listStats[mDpy].numAppLayers;
- mCurrentFrame.reset(numLayers);
- ctx->mOverlay->clear(mDpy);
- ctx->mLayerRotMap[mDpy]->clear();
- resetROI(ctx, mDpy);
- memset(&mCurrentFrame.drop, 0, sizeof(mCurrentFrame.drop));
- mCurrentFrame.dropCount = 0;
-}
-
-void MDPComp::reset() {
- mPrevModeOn = mModeOn;
- mModeOn = false;
-}
-
-void MDPComp::timeout_handler(void *udata) {
- struct hwc_context_t* ctx = (struct hwc_context_t*)(udata);
- bool handleTimeout = false;
-
- if(!ctx) {
- ALOGE("%s: received empty data in timer callback", __FUNCTION__);
- return;
- }
-
- ctx->mDrawLock.lock();
-
- /* Handle timeout event only if the previous composition
- on any display is MDP or MIXED*/
- for(int i = 0; i < HWC_NUM_DISPLAY_TYPES; i++) {
- if(ctx->mMDPComp[i])
- handleTimeout =
- ctx->mMDPComp[i]->isMDPComp() || handleTimeout;
- }
-
- if(!handleTimeout) {
- ALOGD_IF(isDebug(), "%s:Do not handle this timeout", __FUNCTION__);
- ctx->mDrawLock.unlock();
- return;
- }
- if(!ctx->proc) {
- ALOGE("%s: HWC proc not registered", __FUNCTION__);
- ctx->mDrawLock.unlock();
- return;
- }
- sIdleFallBack = true;
- ctx->mDrawLock.unlock();
- /* Trigger SF to redraw the current frame */
- ctx->proc->invalidate(ctx->proc);
-}
-
-void MDPComp::setIdleTimeout(const uint32_t& timeout) {
- enum { ONE_REFRESH_PERIOD_MS = 17, ONE_BILLION_MS = 1000000000 };
-
- if(sIdleInvalidator) {
- if(timeout <= ONE_REFRESH_PERIOD_MS) {
- //If the specified timeout is < 1 draw cycle worth, "virtually"
- //disable idle timeout. The ideal way for clients to disable
- //timeout is to set it to 0
- sIdleInvalidator->setIdleTimeout(ONE_BILLION_MS);
- ALOGI("Disabled idle timeout");
- return;
- }
- sIdleInvalidator->setIdleTimeout(timeout);
- ALOGI("Idle timeout set to %u", timeout);
- } else {
- ALOGW("Cannot set idle timeout, IdleInvalidator not enabled");
- }
-}
-
-void MDPComp::setMDPCompLayerFlags(hwc_context_t *ctx,
- hwc_display_contents_1_t* list) {
- LayerProp *layerProp = ctx->layerProp[mDpy];
-
- for(int index = 0; index < ctx->listStats[mDpy].numAppLayers; index++) {
- hwc_layer_1_t* layer = &(list->hwLayers[index]);
- if(!mCurrentFrame.isFBComposed[index]) {
- layerProp[index].mFlags |= HWC_MDPCOMP;
- layer->compositionType = HWC_OVERLAY;
- layer->hints |= HWC_HINT_CLEAR_FB;
- } else {
- /* Drop the layer when its already present in FB OR when it lies
- * outside frame's ROI */
- if(!mCurrentFrame.needsRedraw || mCurrentFrame.drop[index]) {
- layer->compositionType = HWC_OVERLAY;
- }
- }
- }
-}
-
-void MDPComp::setRedraw(hwc_context_t *ctx,
- hwc_display_contents_1_t* list) {
- mCurrentFrame.needsRedraw = false;
- if(!mCachedFrame.isSameFrame(mCurrentFrame, list) ||
- (list->flags & HWC_GEOMETRY_CHANGED) ||
- isSkipPresent(ctx, mDpy)) {
- mCurrentFrame.needsRedraw = true;
- }
-}
-
-MDPComp::FrameInfo::FrameInfo() {
- memset(&mdpToLayer, 0, sizeof(mdpToLayer));
- reset(0);
-}
-
-void MDPComp::FrameInfo::reset(const int& numLayers) {
- for(int i = 0; i < MAX_PIPES_PER_MIXER; i++) {
- if(mdpToLayer[i].pipeInfo) {
- delete mdpToLayer[i].pipeInfo;
- mdpToLayer[i].pipeInfo = NULL;
- //We dont own the rotator
- mdpToLayer[i].rot = NULL;
- }
- }
-
- memset(&mdpToLayer, 0, sizeof(mdpToLayer));
- memset(&layerToMDP, -1, sizeof(layerToMDP));
- memset(&isFBComposed, 1, sizeof(isFBComposed));
-
- layerCount = numLayers;
- fbCount = numLayers;
- mdpCount = 0;
- needsRedraw = true;
- fbZ = -1;
-}
-
-void MDPComp::FrameInfo::map() {
- // populate layer and MDP maps
- int mdpIdx = 0;
- for(int idx = 0; idx < layerCount; idx++) {
- if(!isFBComposed[idx]) {
- mdpToLayer[mdpIdx].listIndex = idx;
- layerToMDP[idx] = mdpIdx++;
- }
- }
-}
-
-MDPComp::LayerCache::LayerCache() {
- reset();
-}
-
-void MDPComp::LayerCache::reset() {
- memset(&isFBComposed, true, sizeof(isFBComposed));
- memset(&drop, false, sizeof(drop));
- layerCount = 0;
-}
-
-void MDPComp::LayerCache::updateCounts(const FrameInfo& curFrame) {
- layerCount = curFrame.layerCount;
- memcpy(&isFBComposed, &curFrame.isFBComposed, sizeof(isFBComposed));
- memcpy(&drop, &curFrame.drop, sizeof(drop));
-}
-
-bool MDPComp::LayerCache::isSameFrame(const FrameInfo& curFrame,
- hwc_display_contents_1_t* list) {
- if(layerCount != curFrame.layerCount)
- return false;
- for(int i = 0; i < curFrame.layerCount; i++) {
- if((curFrame.isFBComposed[i] != isFBComposed[i]) ||
- (curFrame.drop[i] != drop[i])) {
- return false;
- }
- hwc_layer_1_t const* layer = &list->hwLayers[i];
- if(curFrame.isFBComposed[i] && layerUpdating(layer)) {
- return false;
- }
- }
- return true;
-}
-
-bool MDPComp::LayerCache::isSameFrame(hwc_context_t *ctx, int dpy,
- hwc_display_contents_1_t* list) {
-
- if(layerCount != ctx->listStats[dpy].numAppLayers)
- return false;
-
- if((list->flags & HWC_GEOMETRY_CHANGED) ||
- isSkipPresent(ctx, dpy)) {
- return false;
- }
-
- for(int i = 0; i < layerCount; i++) {
- hwc_layer_1_t const* layer = &list->hwLayers[i];
- if(layerUpdating(layer))
- return false;
- }
-
- return true;
-}
-
-bool MDPComp::isSupportedForMDPComp(hwc_context_t *ctx, hwc_layer_1_t* layer) {
- private_handle_t *hnd = (private_handle_t *)layer->handle;
- if((has90Transform(layer) and (not isRotationDoable(ctx, hnd))) ||
- (not isValidDimension(ctx,layer)) ||
- isSkipLayer(layer)) {
- //More conditions here, sRGB+Blend etc
- return false;
- }
- return true;
-}
-
-bool MDPComp::isValidDimension(hwc_context_t *ctx, hwc_layer_1_t *layer) {
- private_handle_t *hnd = (private_handle_t *)layer->handle;
-
- if(!hnd) {
- if (layer->flags & HWC_COLOR_FILL) {
- // Color layer
- return true;
- }
- ALOGD_IF(isDebug(), "%s: layer handle is NULL", __FUNCTION__);
- return false;
- }
-
- //XXX: Investigate doing this with pixel phase on MDSS
- if(!isSecureBuffer(hnd) && isNonIntegralSourceCrop(layer->sourceCropf))
- return false;
-
- hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);
- hwc_rect_t dst = layer->displayFrame;
- bool rotated90 = (bool)(layer->transform & HAL_TRANSFORM_ROT_90);
- int crop_w = rotated90 ? crop.bottom - crop.top : crop.right - crop.left;
- int crop_h = rotated90 ? crop.right - crop.left : crop.bottom - crop.top;
- int dst_w = dst.right - dst.left;
- int dst_h = dst.bottom - dst.top;
- float w_scale = ((float)crop_w / (float)dst_w);
- float h_scale = ((float)crop_h / (float)dst_h);
- MDPVersion& mdpHw = MDPVersion::getInstance();
-
- /* Workaround for MDP HW limitation in DSI command mode panels where
- * FPS will not go beyond 30 if buffers on RGB pipes are of width or height
- * less than 5 pixels
- * There also is a HW limilation in MDP, minimum block size is 2x2
- * Fallback to GPU if height is less than 2.
- */
- if(mdpHw.hasMinCropWidthLimitation() and (crop_w < 5 or crop_h < 5))
- return false;
-
- if((w_scale > 1.0f) || (h_scale > 1.0f)) {
- const uint32_t maxMDPDownscale = mdpHw.getMaxMDPDownscale();
- const float w_dscale = w_scale;
- const float h_dscale = h_scale;
-
- if(ctx->mMDP.version >= qdutils::MDSS_V5) {
-
- if(!mdpHw.supportsDecimation()) {
- /* On targets that doesnt support Decimation (eg.,8x26)
- * maximum downscale support is overlay pipe downscale.
- */
- if(crop_w > (int) mdpHw.getMaxMixerWidth() ||
- w_dscale > maxMDPDownscale ||
- h_dscale > maxMDPDownscale)
- return false;
- } else {
- // Decimation on macrotile format layers is not supported.
- if(isTileRendered(hnd)) {
- /* Bail out if
- * 1. Src crop > Mixer limit on nonsplit MDPComp
- * 2. exceeds maximum downscale limit
- */
- if(((crop_w > (int) mdpHw.getMaxMixerWidth()) &&
- !sSrcSplitEnabled) ||
- w_dscale > maxMDPDownscale ||
- h_dscale > maxMDPDownscale) {
- return false;
- }
- } else if(w_dscale > 64 || h_dscale > 64)
- return false;
- }
- } else { //A-family
- if(w_dscale > maxMDPDownscale || h_dscale > maxMDPDownscale)
- return false;
- }
- }
-
- if((w_scale < 1.0f) || (h_scale < 1.0f)) {
- const uint32_t upscale = mdpHw.getMaxMDPUpscale();
- const float w_uscale = 1.0f / w_scale;
- const float h_uscale = 1.0f / h_scale;
-
- if(w_uscale > upscale || h_uscale > upscale)
- return false;
- }
-
- return true;
-}
-
-bool MDPComp::isFrameDoable(hwc_context_t *ctx) {
- bool ret = true;
-
- if(!isEnabled()) {
- ALOGD_IF(isDebug(),"%s: MDP Comp. not enabled.", __FUNCTION__);
- ret = false;
- } else if((qdutils::MDPVersion::getInstance().is8x26() ||
- qdutils::MDPVersion::getInstance().is8x16() ||
- qdutils::MDPVersion::getInstance().is8x39()) &&
- ctx->mVideoTransFlag &&
- isSecondaryConnected(ctx)) {
- //1 Padding round to shift pipes across mixers
- ALOGD_IF(isDebug(),"%s: MDP Comp. video transition padding round",
- __FUNCTION__);
- ret = false;
- } else if((qdutils::MDPVersion::getInstance().is8x26() ||
- qdutils::MDPVersion::getInstance().is8x16() ||
- qdutils::MDPVersion::getInstance().is8x39()) &&
- !mDpy && isSecondaryAnimating(ctx) &&
- isYuvPresent(ctx,HWC_DISPLAY_VIRTUAL)) {
- ALOGD_IF(isDebug(),"%s: Display animation in progress",
- __FUNCTION__);
- ret = false;
- } else if(qdutils::MDPVersion::getInstance().getTotalPipes() < 8) {
- /* TODO: freeing up all the resources only for the targets having total
- number of pipes < 8. Need to analyze number of VIG pipes used
- for primary in previous draw cycle and accordingly decide
- whether to fall back to full GPU comp or video only comp
- */
- if(isSecondaryConfiguring(ctx)) {
- ALOGD_IF( isDebug(),"%s: External Display connection is pending",
- __FUNCTION__);
- ret = false;
- } else if(ctx->isPaddingRound) {
- ALOGD_IF(isDebug(), "%s: padding round invoked for dpy %d",
- __FUNCTION__,mDpy);
- ret = false;
- }
- }
- return ret;
-}
-
-void MDPCompNonSplit::trimAgainstROI(hwc_context_t *ctx, hwc_rect_t& fbRect) {
- hwc_rect_t roi = ctx->listStats[mDpy].lRoi;
- fbRect = getIntersection(fbRect, roi);
-}
-
-/* 1) Identify layers that are not visible or lying outside the updating ROI and
- * drop them from composition.
- * 2) If we have a scaling layer which needs cropping against generated
- * ROI, reset ROI to full resolution. */
-bool MDPCompNonSplit::validateAndApplyROI(hwc_context_t *ctx,
- hwc_display_contents_1_t* list) {
- int numAppLayers = ctx->listStats[mDpy].numAppLayers;
- hwc_rect_t visibleRect = ctx->listStats[mDpy].lRoi;
-
- for(int i = numAppLayers - 1; i >= 0; i--){
- if(!isValidRect(visibleRect)) {
- mCurrentFrame.drop[i] = true;
- mCurrentFrame.dropCount++;
- continue;
- }
-
- const hwc_layer_1_t* layer = &list->hwLayers[i];
- hwc_rect_t dstRect = layer->displayFrame;
- hwc_rect_t res = getIntersection(visibleRect, dstRect);
-
- if(!isValidRect(res)) {
- mCurrentFrame.drop[i] = true;
- mCurrentFrame.dropCount++;
- } else {
- /* Reset frame ROI when any layer which needs scaling also needs ROI
- * cropping */
- if(!isSameRect(res, dstRect) && needsScaling (layer)) {
- ALOGI("%s: Resetting ROI due to scaling", __FUNCTION__);
- memset(&mCurrentFrame.drop, 0, sizeof(mCurrentFrame.drop));
- mCurrentFrame.dropCount = 0;
- return false;
- }
-
- /* deduct any opaque region from visibleRect */
- if (layer->blending == HWC_BLENDING_NONE &&
- layer->planeAlpha == 0xFF)
- visibleRect = deductRect(visibleRect, res);
- }
- }
- return true;
-}
-
-/* Calculate ROI for the frame by accounting all the layer's dispalyFrame which
- * are updating. If DirtyRegion is applicable, calculate it by accounting all
- * the changing layer's dirtyRegion. */
-void MDPCompNonSplit::generateROI(hwc_context_t *ctx,
- hwc_display_contents_1_t* list) {
- int numAppLayers = ctx->listStats[mDpy].numAppLayers;
- if(!canPartialUpdate(ctx, list))
- return;
-
- struct hwc_rect roi = (struct hwc_rect){0, 0, 0, 0};
- hwc_rect fullFrame = (struct hwc_rect) {0, 0,(int)ctx->dpyAttr[mDpy].xres,
- (int)ctx->dpyAttr[mDpy].yres};
-
- for(int index = 0; index < numAppLayers; index++ ) {
- hwc_layer_1_t* layer = &list->hwLayers[index];
- if (layerUpdating(layer) ||
- isYuvBuffer((private_handle_t *)layer->handle)) {
- hwc_rect_t dirtyRect = (struct hwc_rect){0, 0, 0, 0};;
- if(!needsScaling(layer) && !layer->transform &&
- (!isYuvBuffer((private_handle_t *)layer->handle)))
- {
- dirtyRect = calculateDirtyRect(layer, fullFrame);
- }
-
- roi = getUnion(roi, dirtyRect);
- }
- }
-
- /* No layer is updating. Still SF wants a refresh.*/
- if(!isValidRect(roi))
- return;
-
- // Align ROI coordinates to panel restrictions
- roi = getSanitizeROI(roi, fullFrame);
-
- ctx->listStats[mDpy].lRoi = roi;
- if(!validateAndApplyROI(ctx, list))
- resetROI(ctx, mDpy);
-
- ALOGD_IF(isDebug(),"%s: generated ROI: [%d, %d, %d, %d]", __FUNCTION__,
- ctx->listStats[mDpy].lRoi.left, ctx->listStats[mDpy].lRoi.top,
- ctx->listStats[mDpy].lRoi.right, ctx->listStats[mDpy].lRoi.bottom);
-}
-
-void MDPCompSplit::trimAgainstROI(hwc_context_t *ctx, hwc_rect_t& fbRect) {
- hwc_rect l_roi = ctx->listStats[mDpy].lRoi;
- hwc_rect r_roi = ctx->listStats[mDpy].rRoi;
-
- hwc_rect_t l_fbRect = getIntersection(fbRect, l_roi);
- hwc_rect_t r_fbRect = getIntersection(fbRect, r_roi);
- fbRect = getUnion(l_fbRect, r_fbRect);
-}
-/* 1) Identify layers that are not visible or lying outside BOTH the updating
- * ROI's and drop them from composition. If a layer is spanning across both
- * the halves of the screen but needed by only ROI, the non-contributing
- * half will not be programmed for MDP.
- * 2) If we have a scaling layer which needs cropping against generated
- * ROI, reset ROI to full resolution. */
-bool MDPCompSplit::validateAndApplyROI(hwc_context_t *ctx,
- hwc_display_contents_1_t* list) {
-
- int numAppLayers = ctx->listStats[mDpy].numAppLayers;
-
- hwc_rect_t visibleRectL = ctx->listStats[mDpy].lRoi;
- hwc_rect_t visibleRectR = ctx->listStats[mDpy].rRoi;
-
- for(int i = numAppLayers - 1; i >= 0; i--){
- if(!isValidRect(visibleRectL) && !isValidRect(visibleRectR))
- {
- mCurrentFrame.drop[i] = true;
- mCurrentFrame.dropCount++;
- continue;
- }
-
- const hwc_layer_1_t* layer = &list->hwLayers[i];
- hwc_rect_t dstRect = layer->displayFrame;
-
- hwc_rect_t l_res = getIntersection(visibleRectL, dstRect);
- hwc_rect_t r_res = getIntersection(visibleRectR, dstRect);
- hwc_rect_t res = getUnion(l_res, r_res);
-
- if(!isValidRect(l_res) && !isValidRect(r_res)) {
- mCurrentFrame.drop[i] = true;
- mCurrentFrame.dropCount++;
- } else {
- /* Reset frame ROI when any layer which needs scaling also needs ROI
- * cropping */
- if(!isSameRect(res, dstRect) && needsScaling (layer)) {
- memset(&mCurrentFrame.drop, 0, sizeof(mCurrentFrame.drop));
- mCurrentFrame.dropCount = 0;
- return false;
- }
-
- if (layer->blending == HWC_BLENDING_NONE &&
- layer->planeAlpha == 0xFF) {
- visibleRectL = deductRect(visibleRectL, l_res);
- visibleRectR = deductRect(visibleRectR, r_res);
- }
- }
- }
- return true;
-}
-/* Calculate ROI for the frame by accounting all the layer's dispalyFrame which
- * are updating. If DirtyRegion is applicable, calculate it by accounting all
- * the changing layer's dirtyRegion. */
-void MDPCompSplit::generateROI(hwc_context_t *ctx,
- hwc_display_contents_1_t* list) {
- if(!canPartialUpdate(ctx, list))
- return;
-
- int numAppLayers = ctx->listStats[mDpy].numAppLayers;
- int lSplit = getLeftSplit(ctx, mDpy);
-
- int hw_h = (int)ctx->dpyAttr[mDpy].yres;
- int hw_w = (int)ctx->dpyAttr[mDpy].xres;
-
- struct hwc_rect l_frame = (struct hwc_rect){0, 0, lSplit, hw_h};
- struct hwc_rect r_frame = (struct hwc_rect){lSplit, 0, hw_w, hw_h};
-
- struct hwc_rect l_roi = (struct hwc_rect){0, 0, 0, 0};
- struct hwc_rect r_roi = (struct hwc_rect){0, 0, 0, 0};
-
- for(int index = 0; index < numAppLayers; index++ ) {
- hwc_layer_1_t* layer = &list->hwLayers[index];
- private_handle_t *hnd = (private_handle_t *)layer->handle;
- if (layerUpdating(layer) || isYuvBuffer(hnd)) {
- hwc_rect_t l_dirtyRect = (struct hwc_rect){0, 0, 0, 0};
- hwc_rect_t r_dirtyRect = (struct hwc_rect){0, 0, 0, 0};
- if(!needsScaling(layer) && !layer->transform)
- {
- l_dirtyRect = calculateDirtyRect(layer, l_frame);
- r_dirtyRect = calculateDirtyRect(layer, r_frame);
- }
- if(isValidRect(l_dirtyRect))
- l_roi = getUnion(l_roi, l_dirtyRect);
-
- if(isValidRect(r_dirtyRect))
- r_roi = getUnion(r_roi, r_dirtyRect);
- }
- }
-
- /* For panels that cannot accept commands in both the interfaces, we cannot
- * send two ROI's (for each half). We merge them into single ROI and split
- * them across lSplit for MDP mixer use. The ROI's will be merged again
- * finally before udpating the panel in the driver. */
- if(qdutils::MDPVersion::getInstance().needsROIMerge()) {
- hwc_rect_t temp_roi = getUnion(l_roi, r_roi);
- l_roi = getIntersection(temp_roi, l_frame);
- r_roi = getIntersection(temp_roi, r_frame);
- }
-
- /* No layer is updating. Still SF wants a refresh. */
- if(!isValidRect(l_roi) && !isValidRect(r_roi))
- return;
-
- l_roi = getSanitizeROI(l_roi, l_frame);
- r_roi = getSanitizeROI(r_roi, r_frame);
-
- ctx->listStats[mDpy].lRoi = l_roi;
- ctx->listStats[mDpy].rRoi = r_roi;
-
- if(!validateAndApplyROI(ctx, list))
- resetROI(ctx, mDpy);
-
- ALOGD_IF(isDebug(),"%s: generated L_ROI: [%d, %d, %d, %d]"
- "R_ROI: [%d, %d, %d, %d]", __FUNCTION__,
- ctx->listStats[mDpy].lRoi.left, ctx->listStats[mDpy].lRoi.top,
- ctx->listStats[mDpy].lRoi.right, ctx->listStats[mDpy].lRoi.bottom,
- ctx->listStats[mDpy].rRoi.left, ctx->listStats[mDpy].rRoi.top,
- ctx->listStats[mDpy].rRoi.right, ctx->listStats[mDpy].rRoi.bottom);
-}
-
-/* Checks for conditions where all the layers marked for MDP comp cannot be
- * bypassed. On such conditions we try to bypass atleast YUV layers */
-bool MDPComp::tryFullFrame(hwc_context_t *ctx,
- hwc_display_contents_1_t* list){
-
- const int numAppLayers = ctx->listStats[mDpy].numAppLayers;
- int priDispW = ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres;
-
- // Fall back to video only composition, if AIV video mode is enabled
- if(ctx->listStats[mDpy].mAIVVideoMode) {
- ALOGD_IF(isDebug(), "%s: AIV Video Mode enabled dpy %d",
- __FUNCTION__, mDpy);
- return false;
- }
-
- // No Idle fall back, if secure display or secure RGB layers are present or
- // if there's only a single layer being composed
- if(sIdleFallBack && (!ctx->listStats[mDpy].secureUI &&
- !ctx->listStats[mDpy].secureRGBCount) &&
- (ctx->listStats[mDpy].numAppLayers != 1)) {
- ALOGD_IF(isDebug(), "%s: Idle fallback dpy %d",__FUNCTION__, mDpy);
- return false;
- }
-
- if(!mDpy && isSecondaryAnimating(ctx) &&
- (isYuvPresent(ctx,HWC_DISPLAY_EXTERNAL) ||
- isYuvPresent(ctx,HWC_DISPLAY_VIRTUAL)) ) {
- ALOGD_IF(isDebug(),"%s: Display animation in progress",
- __FUNCTION__);
- return false;
- }
-
- // if secondary is configuring or Padding round, fall back to video only
- // composition and release all assigned non VIG pipes from primary.
- if(isSecondaryConfiguring(ctx)) {
- ALOGD_IF( isDebug(),"%s: External Display connection is pending",
- __FUNCTION__);
- return false;
- } else if(ctx->isPaddingRound) {
- ALOGD_IF(isDebug(), "%s: padding round invoked for dpy %d",
- __FUNCTION__,mDpy);
- return false;
- }
-
- MDPVersion& mdpHw = MDPVersion::getInstance();
- if(mDpy > HWC_DISPLAY_PRIMARY &&
- (priDispW > (int) mdpHw.getMaxMixerWidth()) &&
- (ctx->dpyAttr[mDpy].xres < mdpHw.getMaxMixerWidth())) {
- // Disable MDP comp on Secondary when the primary is highres panel and
- // the secondary is a normal 1080p, because, MDP comp on secondary under
- // in such usecase, decimation gets used for downscale and there will be
- // a quality mismatch when there will be a fallback to GPU comp
- ALOGD_IF(isDebug(), "%s: Disable MDP Compositon for Secondary Disp",
- __FUNCTION__);
- return false;
- }
-
- // check for action safe flag and MDP scaling mode which requires scaling.
- if(ctx->dpyAttr[mDpy].mActionSafePresent
- || ctx->dpyAttr[mDpy].mMDPScalingMode) {
- ALOGD_IF(isDebug(), "%s: Scaling needed for this frame",__FUNCTION__);
- return false;
- }
-
- for(int i = 0; i < numAppLayers; ++i) {
- hwc_layer_1_t* layer = &list->hwLayers[i];
- private_handle_t *hnd = (private_handle_t *)layer->handle;
-
- if(has90Transform(layer) && isRotationDoable(ctx, hnd)) {
- if(!canUseRotator(ctx, mDpy)) {
- ALOGD_IF(isDebug(), "%s: Can't use rotator for dpy %d",
- __FUNCTION__, mDpy);
- return false;
- }
- }
-
- //For 8x26 with panel width>1k, if RGB layer needs HFLIP fail mdp comp
- // may not need it if Gfx pre-rotation can handle all flips & rotations
- int transform = (layer->flags & HWC_COLOR_FILL) ? 0 : layer->transform;
- if( mdpHw.is8x26() && (ctx->dpyAttr[mDpy].xres > 1024) &&
- (transform & HWC_TRANSFORM_FLIP_H) && (!isYuvBuffer(hnd)))
- return false;
- }
-
- if(ctx->mAD->isDoable()) {
- return false;
- }
-
- //If all above hard conditions are met we can do full or partial MDP comp.
- bool ret = false;
- if(fullMDPComp(ctx, list)) {
- ret = true;
- } else if(fullMDPCompWithPTOR(ctx, list)) {
- ret = true;
- } else if(partialMDPComp(ctx, list)) {
- ret = true;
- }
-
- return ret;
-}
-
-bool MDPComp::fullMDPComp(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
-
- if(sSimulationFlags & MDPCOMP_AVOID_FULL_MDP)
- return false;
-
- //Will benefit presentation / secondary-only layer.
- if((mDpy > HWC_DISPLAY_PRIMARY) &&
- (list->numHwLayers - 1) > MAX_SEC_LAYERS) {
- ALOGD_IF(isDebug(), "%s: Exceeds max secondary pipes",__FUNCTION__);
- return false;
- }
-
- const int numAppLayers = ctx->listStats[mDpy].numAppLayers;
- for(int i = 0; i < numAppLayers; i++) {
- hwc_layer_1_t* layer = &list->hwLayers[i];
- if(not mCurrentFrame.drop[i] and
- not isSupportedForMDPComp(ctx, layer)) {
- ALOGD_IF(isDebug(), "%s: Unsupported layer in list",__FUNCTION__);
- return false;
- }
- }
-
- if(!mDpy && isSecondaryConnected(ctx) &&
- (qdutils::MDPVersion::getInstance().is8x16() ||
- qdutils::MDPVersion::getInstance().is8x26() ||
- qdutils::MDPVersion::getInstance().is8x39()) &&
- isYuvPresent(ctx, HWC_DISPLAY_VIRTUAL)) {
- ALOGD_IF(isDebug(), "%s: YUV layer present on secondary", __FUNCTION__);
- return false;
- }
-
- mCurrentFrame.fbCount = 0;
- memcpy(&mCurrentFrame.isFBComposed, &mCurrentFrame.drop,
- sizeof(mCurrentFrame.isFBComposed));
- mCurrentFrame.mdpCount = mCurrentFrame.layerCount - mCurrentFrame.fbCount -
- mCurrentFrame.dropCount;
-
- if(sEnableYUVsplit){
- adjustForSourceSplit(ctx, list);
- }
-
- if(!postHeuristicsHandling(ctx, list)) {
- ALOGD_IF(isDebug(), "post heuristic handling failed");
- reset(ctx);
- return false;
- }
- ALOGD_IF(sSimulationFlags,"%s: FULL_MDP_COMP SUCCEEDED",
- __FUNCTION__);
- return true;
-}
-
-/* Full MDP Composition with Peripheral Tiny Overlap Removal.
- * MDP bandwidth limitations can be avoided, if the overlap region
- * covered by the smallest layer at a higher z-order, gets composed
- * by Copybit on a render buffer, which can be queued to MDP.
- */
-bool MDPComp::fullMDPCompWithPTOR(hwc_context_t *ctx,
- hwc_display_contents_1_t* list) {
-
- const int numAppLayers = ctx->listStats[mDpy].numAppLayers;
- const int stagesForMDP = min(sMaxPipesPerMixer,
- ctx->mOverlay->availablePipes(mDpy, Overlay::MIXER_DEFAULT));
-
- // Hard checks where we cannot use this mode
- if (mDpy || !ctx->mCopyBit[mDpy]) {
- ALOGD_IF(isDebug(), "%s: Feature not supported!", __FUNCTION__);
- return false;
- }
-
- // Frame level checks
- if ((numAppLayers > stagesForMDP) || isSkipPresent(ctx, mDpy) ||
- isYuvPresent(ctx, mDpy) || mCurrentFrame.dropCount ||
- isSecurePresent(ctx, mDpy)) {
- ALOGD_IF(isDebug(), "%s: Frame not supported!", __FUNCTION__);
- return false;
- }
- // MDP comp checks
- for(int i = 0; i < numAppLayers; i++) {
- hwc_layer_1_t* layer = &list->hwLayers[i];
- if(not isSupportedForMDPComp(ctx, layer)) {
- ALOGD_IF(isDebug(), "%s: Unsupported layer in list",__FUNCTION__);
- return false;
- }
- }
-
- if(!mDpy && isSecondaryConnected(ctx) &&
- (qdutils::MDPVersion::getInstance().is8x16() ||
- qdutils::MDPVersion::getInstance().is8x26() ||
- qdutils::MDPVersion::getInstance().is8x39()) &&
- isYuvPresent(ctx, HWC_DISPLAY_VIRTUAL)) {
- ALOGD_IF(isDebug(), "%s: YUV layer present on secondary", __FUNCTION__);
- return false;
- }
-
- /* We cannot use this composition mode, if:
- 1. A below layer needs scaling.
- 2. Overlap is not peripheral to display.
- 3. Overlap or a below layer has 90 degree transform.
- 4. Overlap area > (1/3 * FrameBuffer) area, based on Perf inputs.
- */
-
- int minLayerIndex[MAX_PTOR_LAYERS] = { -1, -1};
- hwc_rect_t overlapRect[MAX_PTOR_LAYERS];
- memset(overlapRect, 0, sizeof(overlapRect));
- int layerPixelCount, minPixelCount = 0;
- int numPTORLayersFound = 0;
- for (int i = numAppLayers-1; (i >= 0 &&
- numPTORLayersFound < MAX_PTOR_LAYERS); i--) {
- hwc_layer_1_t* layer = &list->hwLayers[i];
- hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);
- hwc_rect_t dispFrame = layer->displayFrame;
- layerPixelCount = (crop.right - crop.left) * (crop.bottom - crop.top);
- // PTOR layer should be peripheral and cannot have transform
- if (!isPeripheral(dispFrame, ctx->mViewFrame[mDpy]) ||
- has90Transform(layer)) {
- continue;
- }
- if((3 * (layerPixelCount + minPixelCount)) >
- ((int)ctx->dpyAttr[mDpy].xres * (int)ctx->dpyAttr[mDpy].yres)) {
- // Overlap area > (1/3 * FrameBuffer) area, based on Perf inputs.
- continue;
- }
- bool found = false;
- for (int j = i-1; j >= 0; j--) {
- // Check if the layers below this layer qualifies for PTOR comp
- hwc_layer_1_t* layer = &list->hwLayers[j];
- hwc_rect_t disFrame = layer->displayFrame;
- // Layer below PTOR is intersecting and has 90 degree transform or
- // needs scaling cannot be supported.
- if (isValidRect(getIntersection(dispFrame, disFrame))) {
- if (has90Transform(layer) || needsScaling(layer)) {
- found = false;
- break;
- }
- found = true;
- }
- }
- // Store the minLayer Index
- if(found) {
- minLayerIndex[numPTORLayersFound] = i;
- overlapRect[numPTORLayersFound] = list->hwLayers[i].displayFrame;
- minPixelCount += layerPixelCount;
- numPTORLayersFound++;
- }
- }
-
- // No overlap layers
- if (!numPTORLayersFound)
- return false;
-
- // Store the displayFrame and the sourceCrops of the layers
- hwc_rect_t displayFrame[numAppLayers];
- hwc_rect_t sourceCrop[numAppLayers];
- for(int i = 0; i < numAppLayers; i++) {
- hwc_layer_1_t* layer = &list->hwLayers[i];
- displayFrame[i] = layer->displayFrame;
- sourceCrop[i] = integerizeSourceCrop(layer->sourceCropf);
- }
-
- /**
- * It's possible that 2 PTOR layers might have overlapping.
- * In such case, remove the intersection(again if peripheral)
- * from the lower PTOR layer to avoid overlapping.
- * If intersection is not on peripheral then compromise
- * by reducing number of PTOR layers.
- **/
- hwc_rect_t commonRect = getIntersection(overlapRect[0], overlapRect[1]);
- if(isValidRect(commonRect)) {
- overlapRect[1] = deductRect(overlapRect[1], commonRect);
- list->hwLayers[minLayerIndex[1]].displayFrame = overlapRect[1];
- }
-
- ctx->mPtorInfo.count = numPTORLayersFound;
- for(int i = 0; i < MAX_PTOR_LAYERS; i++) {
- ctx->mPtorInfo.layerIndex[i] = minLayerIndex[i];
- }
-
- if (!ctx->mCopyBit[mDpy]->prepareOverlap(ctx, list)) {
- // reset PTOR
- ctx->mPtorInfo.count = 0;
- if(isValidRect(commonRect)) {
- // If PTORs are intersecting restore displayframe of PTOR[1]
- // before returning, as we have modified it above.
- list->hwLayers[minLayerIndex[1]].displayFrame =
- displayFrame[minLayerIndex[1]];
- }
- return false;
- }
- private_handle_t *renderBuf = ctx->mCopyBit[mDpy]->getCurrentRenderBuffer();
- Whf layerWhf[MAX_PTOR_LAYERS]; // To store w,h,f of PTOR layers
-
- // Store the blending mode, planeAlpha, and transform of PTOR layers
- int32_t blending[numPTORLayersFound];
- uint8_t planeAlpha[numPTORLayersFound];
- uint32_t transform[numPTORLayersFound];
-
- for(int j = 0; j < numPTORLayersFound; j++) {
- int index = ctx->mPtorInfo.layerIndex[j];
-
- // Update src crop of PTOR layer
- hwc_layer_1_t* layer = &list->hwLayers[index];
- layer->sourceCropf.left = (float)ctx->mPtorInfo.displayFrame[j].left;
- layer->sourceCropf.top = (float)ctx->mPtorInfo.displayFrame[j].top;
- layer->sourceCropf.right = (float)ctx->mPtorInfo.displayFrame[j].right;
- layer->sourceCropf.bottom =(float)ctx->mPtorInfo.displayFrame[j].bottom;
-
- // Store & update w, h, format of PTOR layer
- private_handle_t *hnd = (private_handle_t *)layer->handle;
- Whf whf(hnd->width, hnd->height, hnd->format, hnd->size);
- layerWhf[j] = whf;
- hnd->width = renderBuf->width;
- hnd->height = renderBuf->height;
- hnd->format = renderBuf->format;
-
- // Store & update blending mode, planeAlpha and transform of PTOR layer
- blending[j] = layer->blending;
- planeAlpha[j] = layer->planeAlpha;
- transform[j] = layer->transform;
- layer->blending = HWC_BLENDING_NONE;
- layer->planeAlpha = 0xFF;
- layer->transform = 0;
-
- // Remove overlap from crop & displayFrame of below layers
- for (int i = 0; i < index && index !=-1; i++) {
- layer = &list->hwLayers[i];
- if(!isValidRect(getIntersection(layer->displayFrame,
- overlapRect[j]))) {
- continue;
- }
- // Update layer attributes
- hwc_rect_t srcCrop = integerizeSourceCrop(layer->sourceCropf);
- hwc_rect_t destRect = deductRect(layer->displayFrame,
- getIntersection(layer->displayFrame, overlapRect[j]));
- qhwc::calculate_crop_rects(srcCrop, layer->displayFrame, destRect,
- layer->transform);
- layer->sourceCropf.left = (float)srcCrop.left;
- layer->sourceCropf.top = (float)srcCrop.top;
- layer->sourceCropf.right = (float)srcCrop.right;
- layer->sourceCropf.bottom = (float)srcCrop.bottom;
- }
- }
-
- mCurrentFrame.mdpCount = numAppLayers;
- mCurrentFrame.fbCount = 0;
- mCurrentFrame.fbZ = -1;
-
- for (int j = 0; j < numAppLayers; j++) {
- if(isValidRect(list->hwLayers[j].displayFrame)) {
- mCurrentFrame.isFBComposed[j] = false;
- } else {
- mCurrentFrame.mdpCount--;
- mCurrentFrame.drop[j] = true;
- }
- }
-
- bool result = postHeuristicsHandling(ctx, list);
-
- // Restore layer attributes
- for(int i = 0; i < numAppLayers; i++) {
- hwc_layer_1_t* layer = &list->hwLayers[i];
- layer->displayFrame = displayFrame[i];
- layer->sourceCropf.left = (float)sourceCrop[i].left;
- layer->sourceCropf.top = (float)sourceCrop[i].top;
- layer->sourceCropf.right = (float)sourceCrop[i].right;
- layer->sourceCropf.bottom = (float)sourceCrop[i].bottom;
- }
-
- // Restore w,h,f, blending attributes, and transform of PTOR layers
- for (int i = 0; i < numPTORLayersFound; i++) {
- int idx = ctx->mPtorInfo.layerIndex[i];
- hwc_layer_1_t* layer = &list->hwLayers[idx];
- private_handle_t *hnd = (private_handle_t *)list->hwLayers[idx].handle;
- hnd->width = layerWhf[i].w;
- hnd->height = layerWhf[i].h;
- hnd->format = layerWhf[i].format;
- layer->blending = blending[i];
- layer->planeAlpha = planeAlpha[i];
- layer->transform = transform[i];
- }
-
- if (!result) {
- // reset PTOR
- ctx->mPtorInfo.count = 0;
- reset(ctx);
- } else {
- ALOGD_IF(isDebug(), "%s: PTOR Indexes: %d and %d", __FUNCTION__,
- ctx->mPtorInfo.layerIndex[0], ctx->mPtorInfo.layerIndex[1]);
- }
-
- ALOGD_IF(isDebug(), "%s: Postheuristics %s!", __FUNCTION__,
- (result ? "successful" : "failed"));
- return result;
-}
-
-bool MDPComp::partialMDPComp(hwc_context_t *ctx, hwc_display_contents_1_t* list)
-{
- if(!sEnableMixedMode || !isAlphaPresentinFB(ctx, mDpy)) {
- //Mixed mode is disabled/can't be used. No need to even try caching.
- return false;
- }
-
- bool ret = false;
- if(isSkipPresent(ctx, mDpy) or list->flags & HWC_GEOMETRY_CHANGED) {
- //Try load based first
- ret = loadBasedComp(ctx, list) or
- cacheBasedComp(ctx, list);
- } else {
- ret = cacheBasedComp(ctx, list) or
- loadBasedComp(ctx, list);
- }
-
- return ret;
-}
-
-bool MDPComp::cacheBasedComp(hwc_context_t *ctx,
- hwc_display_contents_1_t* list) {
- if(sSimulationFlags & MDPCOMP_AVOID_CACHE_MDP)
- return false;
-
- int numAppLayers = ctx->listStats[mDpy].numAppLayers;
- mCurrentFrame.reset(numAppLayers);
- updateLayerCache(ctx, list, mCurrentFrame);
-
- //If an MDP marked layer is unsupported cannot do partial MDP Comp
- for(int i = 0; i < numAppLayers; i++) {
- if(!mCurrentFrame.isFBComposed[i]) {
- hwc_layer_1_t* layer = &list->hwLayers[i];
- if(not isSupportedForMDPComp(ctx, layer)) {
- ALOGD_IF(isDebug(), "%s: Unsupported layer in list",
- __FUNCTION__);
- reset(ctx);
- return false;
- }
- }
- }
-
- updateYUV(ctx, list, false /*secure only*/, mCurrentFrame);
- /* mark secure RGB layers for MDP comp */
- updateSecureRGB(ctx, list);
- bool ret = markLayersForCaching(ctx, list); //sets up fbZ also
- if(!ret) {
- ALOGD_IF(isDebug(),"%s: batching failed, dpy %d",__FUNCTION__, mDpy);
- reset(ctx);
- return false;
- }
-
- int mdpCount = mCurrentFrame.mdpCount;
-
- if(sEnableYUVsplit){
- adjustForSourceSplit(ctx, list);
- }
-
- //Will benefit cases where a video has non-updating background.
- if((mDpy > HWC_DISPLAY_PRIMARY) and
- (mdpCount > MAX_SEC_LAYERS)) {
- ALOGD_IF(isDebug(), "%s: Exceeds max secondary pipes",__FUNCTION__);
- reset(ctx);
- return false;
- }
-
- if(!postHeuristicsHandling(ctx, list)) {
- ALOGD_IF(isDebug(), "post heuristic handling failed");
- reset(ctx);
- return false;
- }
- ALOGD_IF(sSimulationFlags,"%s: CACHE_MDP_COMP SUCCEEDED",
- __FUNCTION__);
-
- return true;
-}
-
-bool MDPComp::loadBasedComp(hwc_context_t *ctx,
- hwc_display_contents_1_t* list) {
- if(sSimulationFlags & MDPCOMP_AVOID_LOAD_MDP)
- return false;
-
- if(not isLoadBasedCompDoable(ctx)) {
- return false;
- }
-
- const int numAppLayers = ctx->listStats[mDpy].numAppLayers;
- const int numNonDroppedLayers = numAppLayers - mCurrentFrame.dropCount;
- const int stagesForMDP = min(sMaxPipesPerMixer,
- ctx->mOverlay->availablePipes(mDpy, Overlay::MIXER_DEFAULT));
-
- int mdpBatchSize = stagesForMDP - 1; //1 stage for FB
- int fbBatchSize = numNonDroppedLayers - mdpBatchSize;
- int lastMDPSupportedIndex = numAppLayers;
- int dropCount = 0;
-
- //Find the minimum MDP batch size
- for(int i = 0; i < numAppLayers;i++) {
- if(mCurrentFrame.drop[i]) {
- dropCount++;
- continue;
- }
- hwc_layer_1_t* layer = &list->hwLayers[i];
- if(not isSupportedForMDPComp(ctx, layer)) {
- lastMDPSupportedIndex = i;
- mdpBatchSize = min(i - dropCount, stagesForMDP - 1);
- fbBatchSize = numNonDroppedLayers - mdpBatchSize;
- break;
- }
- }
-
- ALOGD_IF(isDebug(), "%s:Before optimizing fbBatch, mdpbatch %d, fbbatch %d "
- "dropped %d", __FUNCTION__, mdpBatchSize, fbBatchSize,
- mCurrentFrame.dropCount);
-
- //Start at a point where the fb batch should at least have 2 layers, for
- //this mode to be justified.
- while(fbBatchSize < 2) {
- ++fbBatchSize;
- --mdpBatchSize;
- }
-
- //If there are no layers for MDP, this mode doesnt make sense.
- if(mdpBatchSize < 1) {
- ALOGD_IF(isDebug(), "%s: No MDP layers after optimizing for fbBatch",
- __FUNCTION__);
- return false;
- }
-
- mCurrentFrame.reset(numAppLayers);
-
- //Try with successively smaller mdp batch sizes until we succeed or reach 1
- while(mdpBatchSize > 0) {
- //Mark layers for MDP comp
- int mdpBatchLeft = mdpBatchSize;
- for(int i = 0; i < lastMDPSupportedIndex and mdpBatchLeft; i++) {
- if(mCurrentFrame.drop[i]) {
- continue;
- }
- mCurrentFrame.isFBComposed[i] = false;
- --mdpBatchLeft;
- }
-
- mCurrentFrame.fbZ = mdpBatchSize;
- mCurrentFrame.fbCount = fbBatchSize;
- mCurrentFrame.mdpCount = mdpBatchSize;
-
- ALOGD_IF(isDebug(), "%s:Trying with: mdpbatch %d fbbatch %d dropped %d",
- __FUNCTION__, mdpBatchSize, fbBatchSize,
- mCurrentFrame.dropCount);
-
- if(postHeuristicsHandling(ctx, list)) {
- ALOGD_IF(isDebug(), "%s: Postheuristics handling succeeded",
- __FUNCTION__);
- ALOGD_IF(sSimulationFlags,"%s: LOAD_MDP_COMP SUCCEEDED",
- __FUNCTION__);
- return true;
- }
-
- reset(ctx);
- --mdpBatchSize;
- ++fbBatchSize;
- }
-
- return false;
-}
-
-bool MDPComp::isLoadBasedCompDoable(hwc_context_t *ctx) {
- if(mDpy or isSecurePresent(ctx, mDpy) or
- isYuvPresent(ctx, mDpy)) {
- return false;
- }
- return true;
-}
-
-bool MDPComp::canPartialUpdate(hwc_context_t *ctx,
- hwc_display_contents_1_t* list){
- if(!qdutils::MDPVersion::getInstance().isPartialUpdateEnabled() ||
- isSkipPresent(ctx, mDpy) || (list->flags & HWC_GEOMETRY_CHANGED) ||
- !sIsPartialUpdateActive || mDpy ) {
- return false;
- }
- if(ctx->listStats[mDpy].secureUI)
- return false;
- return true;
-}
-
-bool MDPComp::tryVideoOnly(hwc_context_t *ctx,
- hwc_display_contents_1_t* list) {
- const bool secureOnly = true;
- return videoOnlyComp(ctx, list, not secureOnly) or
- videoOnlyComp(ctx, list, secureOnly);
-}
-
-bool MDPComp::videoOnlyComp(hwc_context_t *ctx,
- hwc_display_contents_1_t* list, bool secureOnly) {
- if(sSimulationFlags & MDPCOMP_AVOID_VIDEO_ONLY)
- return false;
- int numAppLayers = ctx->listStats[mDpy].numAppLayers;
-
- mCurrentFrame.reset(numAppLayers);
- mCurrentFrame.fbCount -= mCurrentFrame.dropCount;
- updateYUV(ctx, list, secureOnly, mCurrentFrame);
- int mdpCount = mCurrentFrame.mdpCount;
-
- if(!isYuvPresent(ctx, mDpy) or (mdpCount == 0)) {
- reset(ctx);
- return false;
- }
-
- /* Bail out if we are processing only secured video layers
- * and we dont have any */
- if(!isSecurePresent(ctx, mDpy) && secureOnly){
- reset(ctx);
- return false;
- }
-
- if(mCurrentFrame.fbCount)
- mCurrentFrame.fbZ = mCurrentFrame.mdpCount;
-
- if(sEnableYUVsplit){
- adjustForSourceSplit(ctx, list);
- }
-
- if(!postHeuristicsHandling(ctx, list)) {
- ALOGD_IF(isDebug(), "post heuristic handling failed");
- reset(ctx);
- return false;
- }
-
- ALOGD_IF(sSimulationFlags,"%s: VIDEO_ONLY_COMP SUCCEEDED",
- __FUNCTION__);
- return true;
-}
-
-/* if tryFullFrame fails, try to push all video and secure RGB layers to MDP */
-bool MDPComp::tryMDPOnlyLayers(hwc_context_t *ctx,
- hwc_display_contents_1_t* list) {
- // Fall back to video only composition, if AIV video mode is enabled
- if(ctx->listStats[mDpy].mAIVVideoMode) {
- ALOGD_IF(isDebug(), "%s: AIV Video Mode enabled dpy %d",
- __FUNCTION__, mDpy);
- return false;
- }
-
- const bool secureOnly = true;
- return mdpOnlyLayersComp(ctx, list, not secureOnly) or
- mdpOnlyLayersComp(ctx, list, secureOnly);
-
-}
-
-bool MDPComp::mdpOnlyLayersComp(hwc_context_t *ctx,
- hwc_display_contents_1_t* list, bool secureOnly) {
-
- if(sSimulationFlags & MDPCOMP_AVOID_MDP_ONLY_LAYERS)
- return false;
-
- /* Bail out if we are processing only secured video layers
- * and we dont have any */
- if(!isSecurePresent(ctx, mDpy) && secureOnly){
- reset(ctx);
- return false;
- }
-
- int numAppLayers = ctx->listStats[mDpy].numAppLayers;
- mCurrentFrame.reset(numAppLayers);
- mCurrentFrame.fbCount -= mCurrentFrame.dropCount;
-
- updateYUV(ctx, list, secureOnly, mCurrentFrame);
- /* mark secure RGB layers for MDP comp */
- updateSecureRGB(ctx, list);
-
- if(mCurrentFrame.mdpCount == 0) {
- reset(ctx);
- return false;
- }
-
- /* find the maximum batch of layers to be marked for framebuffer */
- bool ret = markLayersForCaching(ctx, list); //sets up fbZ also
- if(!ret) {
- ALOGD_IF(isDebug(),"%s: batching failed, dpy %d",__FUNCTION__, mDpy);
- reset(ctx);
- return false;
- }
-
- if(sEnableYUVsplit){
- adjustForSourceSplit(ctx, list);
- }
-
- if(!postHeuristicsHandling(ctx, list)) {
- ALOGD_IF(isDebug(), "post heuristic handling failed");
- reset(ctx);
- return false;
- }
-
- ALOGD_IF(sSimulationFlags,"%s: MDP_ONLY_LAYERS_COMP SUCCEEDED",
- __FUNCTION__);
- return true;
-}
-
-/* Checks for conditions where YUV layers cannot be bypassed */
-bool MDPComp::isYUVDoable(hwc_context_t* ctx, hwc_layer_1_t* layer) {
- if(isSkipLayer(layer)) {
- ALOGD_IF(isDebug(), "%s: Video marked SKIP dpy %d", __FUNCTION__, mDpy);
- return false;
- }
-
- if(has90Transform(layer) && !canUseRotator(ctx, mDpy)) {
- ALOGD_IF(isDebug(), "%s: no free DMA pipe",__FUNCTION__);
- return false;
- }
-
- if(isSecuring(ctx, layer)) {
- ALOGD_IF(isDebug(), "%s: MDP securing is active", __FUNCTION__);
- return false;
- }
-
- if(!isValidDimension(ctx, layer)) {
- ALOGD_IF(isDebug(), "%s: Buffer is of invalid width",
- __FUNCTION__);
- return false;
- }
-
- if(layer->planeAlpha < 0xFF) {
- ALOGD_IF(isDebug(), "%s: Cannot handle YUV layer with plane alpha\
- in video only mode",
- __FUNCTION__);
- return false;
- }
-
- return true;
-}
-
-/* Checks for conditions where Secure RGB layers cannot be bypassed */
-bool MDPComp::isSecureRGBDoable(hwc_context_t* ctx, hwc_layer_1_t* layer) {
- if(isSkipLayer(layer)) {
- ALOGD_IF(isDebug(), "%s: Secure RGB layer marked SKIP dpy %d",
- __FUNCTION__, mDpy);
- return false;
- }
-
- if(isSecuring(ctx, layer)) {
- ALOGD_IF(isDebug(), "%s: MDP securing is active", __FUNCTION__);
- return false;
- }
-
- if(not isSupportedForMDPComp(ctx, layer)) {
- ALOGD_IF(isDebug(), "%s: Unsupported secure RGB layer",
- __FUNCTION__);
- return false;
- }
- return true;
-}
-
-/* starts at fromIndex and check for each layer to find
- * if it it has overlapping with any Updating layer above it in zorder
- * till the end of the batch. returns true if it finds any intersection */
-bool MDPComp::canPushBatchToTop(const hwc_display_contents_1_t* list,
- int fromIndex, int toIndex) {
- for(int i = fromIndex; i < toIndex; i++) {
- if(mCurrentFrame.isFBComposed[i] && !mCurrentFrame.drop[i]) {
- if(intersectingUpdatingLayers(list, i+1, toIndex, i)) {
- return false;
- }
- }
- }
- return true;
-}
-
-/* Checks if given layer at targetLayerIndex has any
- * intersection with all the updating layers in beween
- * fromIndex and toIndex. Returns true if it finds intersectiion */
-bool MDPComp::intersectingUpdatingLayers(const hwc_display_contents_1_t* list,
- int fromIndex, int toIndex, int targetLayerIndex) {
- for(int i = fromIndex; i <= toIndex; i++) {
- if(!mCurrentFrame.isFBComposed[i]) {
- if(areLayersIntersecting(&list->hwLayers[i],
- &list->hwLayers[targetLayerIndex])) {
- return true;
- }
- }
- }
- return false;
-}
-
-int MDPComp::getBatch(hwc_display_contents_1_t* list,
- int& maxBatchStart, int& maxBatchEnd,
- int& maxBatchCount) {
- int i = 0;
- int fbZOrder =-1;
- int droppedLayerCt = 0;
- while (i < mCurrentFrame.layerCount) {
- int batchCount = 0;
- int batchStart = i;
- int batchEnd = i;
- /* Adjust batch Z order with the dropped layers so far */
- int fbZ = batchStart - droppedLayerCt;
- int firstZReverseIndex = -1;
- int updatingLayersAbove = 0;//Updating layer count in middle of batch
- while(i < mCurrentFrame.layerCount) {
- if(!mCurrentFrame.isFBComposed[i]) {
- if(!batchCount) {
- i++;
- break;
- }
- updatingLayersAbove++;
- i++;
- continue;
- } else {
- if(mCurrentFrame.drop[i]) {
- i++;
- droppedLayerCt++;
- continue;
- } else if(updatingLayersAbove <= 0) {
- batchCount++;
- batchEnd = i;
- i++;
- continue;
- } else { //Layer is FBComposed, not a drop & updatingLayer > 0
-
- // We have a valid updating layer already. If layer-i not
- // have overlapping with all updating layers in between
- // batch-start and i, then we can add layer i to batch.
- if(!intersectingUpdatingLayers(list, batchStart, i-1, i)) {
- batchCount++;
- batchEnd = i;
- i++;
- continue;
- } else if(canPushBatchToTop(list, batchStart, i)) {
- //If All the non-updating layers with in this batch
- //does not have intersection with the updating layers
- //above in z-order, then we can safely move the batch to
- //higher z-order. Increment fbZ as it is moving up.
- if( firstZReverseIndex < 0) {
- firstZReverseIndex = i;
- }
- batchCount++;
- batchEnd = i;
- fbZ += updatingLayersAbove;
- i++;
- updatingLayersAbove = 0;
- continue;
- } else {
- //both failed.start the loop again from here.
- if(firstZReverseIndex >= 0) {
- i = firstZReverseIndex;
- }
- break;
- }
- }
- }
- }
- if(batchCount > maxBatchCount) {
- maxBatchCount = batchCount;
- maxBatchStart = batchStart;
- maxBatchEnd = batchEnd;
- fbZOrder = fbZ;
- }
- }
- return fbZOrder;
-}
-
-bool MDPComp::markLayersForCaching(hwc_context_t* ctx,
- hwc_display_contents_1_t* list) {
- /* Idea is to keep as many non-updating(cached) layers in FB and
- * send rest of them through MDP. This is done in 2 steps.
- * 1. Find the maximum contiguous batch of non-updating layers.
- * 2. See if we can improve this batch size for caching by adding
- * opaque layers around the batch, if they don't have
- * any overlapping with the updating layers in between.
- * NEVER mark an updating layer for caching.
- * But cached ones can be marked for MDP */
-
- int maxBatchStart = -1;
- int maxBatchEnd = -1;
- int maxBatchCount = 0;
- int fbZ = -1;
-
- /* Nothing is cached. No batching needed */
- if(mCurrentFrame.fbCount == 0) {
- return true;
- }
-
- /* No MDP comp layers, try to use other comp modes */
- if(mCurrentFrame.mdpCount == 0) {
- return false;
- }
-
- fbZ = getBatch(list, maxBatchStart, maxBatchEnd, maxBatchCount);
-
- /* reset rest of the layers lying inside ROI for MDP comp */
- for(int i = 0; i < mCurrentFrame.layerCount; i++) {
- hwc_layer_1_t* layer = &list->hwLayers[i];
- if((i < maxBatchStart || i > maxBatchEnd) &&
- mCurrentFrame.isFBComposed[i]){
- if(!mCurrentFrame.drop[i]){
- //If an unsupported layer is being attempted to
- //be pulled out we should fail
- if(not isSupportedForMDPComp(ctx, layer)) {
- return false;
- }
- mCurrentFrame.isFBComposed[i] = false;
- }
- }
- }
-
- // update the frame data
- mCurrentFrame.fbZ = fbZ;
- mCurrentFrame.fbCount = maxBatchCount;
- mCurrentFrame.mdpCount = mCurrentFrame.layerCount -
- mCurrentFrame.fbCount - mCurrentFrame.dropCount;
-
- ALOGD_IF(isDebug(),"%s: cached count: %d",__FUNCTION__,
- mCurrentFrame.fbCount);
-
- return true;
-}
-
-void MDPComp::updateLayerCache(hwc_context_t* ctx,
- hwc_display_contents_1_t* list, FrameInfo& frame) {
- int numAppLayers = ctx->listStats[mDpy].numAppLayers;
- int fbCount = 0;
-
- for(int i = 0; i < numAppLayers; i++) {
- hwc_layer_1_t * layer = &list->hwLayers[i];
- if (!layerUpdating(layer)) {
- if(!frame.drop[i])
- fbCount++;
- frame.isFBComposed[i] = true;
- } else {
- frame.isFBComposed[i] = false;
- }
- }
-
- frame.fbCount = fbCount;
- frame.mdpCount = frame.layerCount - frame.fbCount
- - frame.dropCount;
-
- ALOGD_IF(isDebug(),"%s: MDP count: %d FB count %d drop count: %d",
- __FUNCTION__, frame.mdpCount, frame.fbCount, frame.dropCount);
-}
-
-// drop other non-AIV layers from external display list.
-void MDPComp::dropNonAIVLayers(hwc_context_t* ctx,
- hwc_display_contents_1_t* list) {
- for (size_t i = 0; i < (size_t)ctx->listStats[mDpy].numAppLayers; i++) {
- hwc_layer_1_t * layer = &list->hwLayers[i];
- if(!(isAIVVideoLayer(layer) || isAIVCCLayer(layer))) {
- mCurrentFrame.dropCount++;
- mCurrentFrame.drop[i] = true;
- }
- }
- mCurrentFrame.fbCount -= mCurrentFrame.dropCount;
- mCurrentFrame.mdpCount = mCurrentFrame.layerCount -
- mCurrentFrame.fbCount - mCurrentFrame.dropCount;
- ALOGD_IF(isDebug(),"%s: fb count: %d mdp count %d drop count %d",
- __FUNCTION__, mCurrentFrame.fbCount, mCurrentFrame.mdpCount,
- mCurrentFrame.dropCount);
-}
-
-void MDPComp::updateYUV(hwc_context_t* ctx, hwc_display_contents_1_t* list,
- bool secureOnly, FrameInfo& frame) {
- int nYuvCount = ctx->listStats[mDpy].yuvCount;
- for(int index = 0;index < nYuvCount; index++){
- int nYuvIndex = ctx->listStats[mDpy].yuvIndices[index];
- hwc_layer_1_t* layer = &list->hwLayers[nYuvIndex];
-
- if(mCurrentFrame.drop[nYuvIndex]) {
- continue;
- }
-
- if(!isYUVDoable(ctx, layer)) {
- if(!frame.isFBComposed[nYuvIndex]) {
- frame.isFBComposed[nYuvIndex] = true;
- frame.fbCount++;
- }
- } else {
- if(frame.isFBComposed[nYuvIndex]) {
- private_handle_t *hnd = (private_handle_t *)layer->handle;
- if(!secureOnly || isSecureBuffer(hnd)) {
- frame.isFBComposed[nYuvIndex] = false;
- frame.fbCount--;
- }
- }
- }
- }
-
- frame.mdpCount = frame.layerCount - frame.fbCount - frame.dropCount;
- ALOGD_IF(isDebug(),"%s: fb count: %d",__FUNCTION__, frame.fbCount);
-}
-
-void MDPComp::updateSecureRGB(hwc_context_t* ctx,
- hwc_display_contents_1_t* list) {
- int nSecureRGBCount = ctx->listStats[mDpy].secureRGBCount;
- for(int index = 0;index < nSecureRGBCount; index++){
- int nSecureRGBIndex = ctx->listStats[mDpy].secureRGBIndices[index];
- hwc_layer_1_t* layer = &list->hwLayers[nSecureRGBIndex];
-
- if(!isSecureRGBDoable(ctx, layer)) {
- if(!mCurrentFrame.isFBComposed[nSecureRGBIndex]) {
- mCurrentFrame.isFBComposed[nSecureRGBIndex] = true;
- mCurrentFrame.fbCount++;
- }
- } else {
- if(mCurrentFrame.isFBComposed[nSecureRGBIndex]) {
- mCurrentFrame.isFBComposed[nSecureRGBIndex] = false;
- mCurrentFrame.fbCount--;
- }
- }
- }
-
- mCurrentFrame.mdpCount = mCurrentFrame.layerCount -
- mCurrentFrame.fbCount - mCurrentFrame.dropCount;
- ALOGD_IF(isDebug(),"%s: fb count: %d",__FUNCTION__,
- mCurrentFrame.fbCount);
-}
-
-hwc_rect_t MDPComp::getUpdatingFBRect(hwc_context_t *ctx,
- hwc_display_contents_1_t* list){
- hwc_rect_t fbRect = (struct hwc_rect){0, 0, 0, 0};
-
- /* Update only the region of FB needed for composition */
- for(int i = 0; i < mCurrentFrame.layerCount; i++ ) {
- if(mCurrentFrame.isFBComposed[i] && !mCurrentFrame.drop[i]) {
- hwc_layer_1_t* layer = &list->hwLayers[i];
- hwc_rect_t dst = layer->displayFrame;
- fbRect = getUnion(fbRect, dst);
- }
- }
- trimAgainstROI(ctx, fbRect);
- return fbRect;
-}
-
-bool MDPComp::postHeuristicsHandling(hwc_context_t *ctx,
- hwc_display_contents_1_t* list) {
-
- //Capability checks
- if(!resourceCheck(ctx, list)) {
- ALOGD_IF(isDebug(), "%s: resource check failed", __FUNCTION__);
- return false;
- }
-
- //Limitations checks
- if(!hwLimitationsCheck(ctx, list)) {
- ALOGD_IF(isDebug(), "%s: HW limitations",__FUNCTION__);
- return false;
- }
-
- //Configure framebuffer first if applicable
- if(mCurrentFrame.fbZ >= 0) {
- hwc_rect_t fbRect = getUpdatingFBRect(ctx, list);
- if(!ctx->mFBUpdate[mDpy]->prepare(ctx, list, fbRect, mCurrentFrame.fbZ))
- {
- ALOGD_IF(isDebug(), "%s configure framebuffer failed",
- __FUNCTION__);
- return false;
- }
- }
-
- mCurrentFrame.map();
-
- if(!allocLayerPipes(ctx, list)) {
- ALOGD_IF(isDebug(), "%s: Unable to allocate MDP pipes", __FUNCTION__);
- return false;
- }
-
- for (int index = 0, mdpNextZOrder = 0; index < mCurrentFrame.layerCount;
- index++) {
- if(!mCurrentFrame.isFBComposed[index]) {
- int mdpIndex = mCurrentFrame.layerToMDP[index];
- hwc_layer_1_t* layer = &list->hwLayers[index];
-
- //Leave fbZ for framebuffer. CACHE/GLES layers go here.
- if(mdpNextZOrder == mCurrentFrame.fbZ) {
- mdpNextZOrder++;
- }
- MdpPipeInfo* cur_pipe = mCurrentFrame.mdpToLayer[mdpIndex].pipeInfo;
- cur_pipe->zOrder = mdpNextZOrder++;
-
- private_handle_t *hnd = (private_handle_t *)layer->handle;
- if(isYUVSplitNeeded(hnd) && sEnableYUVsplit){
- if(configure4k2kYuv(ctx, layer,
- mCurrentFrame.mdpToLayer[mdpIndex])
- != 0 ){
- ALOGD_IF(isDebug(), "%s: Failed to configure split pipes \
- for layer %d",__FUNCTION__, index);
- return false;
- }
- else{
- mdpNextZOrder++;
- }
- continue;
- }
- if(configure(ctx, layer, mCurrentFrame.mdpToLayer[mdpIndex]) != 0 ){
- ALOGD_IF(isDebug(), "%s: Failed to configure overlay for \
- layer %d",__FUNCTION__, index);
- return false;
- }
- }
- }
-
- if(!ctx->mOverlay->validateAndSet(mDpy, ctx->dpyAttr[mDpy].fd)) {
- ALOGD_IF(isDebug(), "%s: Failed to validate and set overlay for dpy %d"
- ,__FUNCTION__, mDpy);
- return false;
- }
-
- setRedraw(ctx, list);
- return true;
-}
-
-bool MDPComp::resourceCheck(hwc_context_t* ctx,
- hwc_display_contents_1_t* list) {
- const bool fbUsed = mCurrentFrame.fbCount;
- if(mCurrentFrame.mdpCount > sMaxPipesPerMixer - fbUsed) {
- ALOGD_IF(isDebug(), "%s: Exceeds MAX_PIPES_PER_MIXER",__FUNCTION__);
- return false;
- }
- // Init rotCount to number of rotate sessions used by other displays
- int rotCount = ctx->mRotMgr->getNumActiveSessions();
- // Count the number of rotator sessions required for current display
- for (int index = 0; index < mCurrentFrame.layerCount; index++) {
- if(!mCurrentFrame.isFBComposed[index]) {
- hwc_layer_1_t* layer = &list->hwLayers[index];
- private_handle_t *hnd = (private_handle_t *)layer->handle;
- if(has90Transform(layer) && isRotationDoable(ctx, hnd)) {
- rotCount++;
- }
- }
- }
- // if number of layers to rotate exceeds max rotator sessions, bail out.
- if(rotCount > RotMgr::MAX_ROT_SESS) {
- ALOGD_IF(isDebug(), "%s: Exceeds max rotator sessions %d",
- __FUNCTION__, mDpy);
- return false;
- }
- return true;
-}
-
-bool MDPComp::hwLimitationsCheck(hwc_context_t* ctx,
- hwc_display_contents_1_t* list) {
-
- //A-family hw limitation:
- //If a layer need alpha scaling, MDP can not support.
- if(ctx->mMDP.version < qdutils::MDSS_V5) {
- for(int i = 0; i < mCurrentFrame.layerCount; ++i) {
- if(!mCurrentFrame.isFBComposed[i] &&
- isAlphaScaled( &list->hwLayers[i])) {
- ALOGD_IF(isDebug(), "%s:frame needs alphaScaling",__FUNCTION__);
- return false;
- }
- }
- }
-
- // On 8x26 & 8974 hw, we have a limitation of downscaling+blending.
- //If multiple layers requires downscaling and also they are overlapping
- //fall back to GPU since MDSS can not handle it.
- if(qdutils::MDPVersion::getInstance().is8x74v2() ||
- qdutils::MDPVersion::getInstance().is8x26()) {
- for(int i = 0; i < mCurrentFrame.layerCount-1; ++i) {
- hwc_layer_1_t* botLayer = &list->hwLayers[i];
- if(!mCurrentFrame.isFBComposed[i] &&
- isDownscaleRequired(botLayer)) {
- //if layer-i is marked for MDP and needs downscaling
- //check if any MDP layer on top of i & overlaps with layer-i
- for(int j = i+1; j < mCurrentFrame.layerCount; ++j) {
- hwc_layer_1_t* topLayer = &list->hwLayers[j];
- if(!mCurrentFrame.isFBComposed[j] &&
- isDownscaleRequired(topLayer)) {
- hwc_rect_t r = getIntersection(botLayer->displayFrame,
- topLayer->displayFrame);
- if(isValidRect(r))
- return false;
- }
- }
- }
- }
- }
- return true;
-}
-
-void MDPComp::setDynRefreshRate(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
- //For primary display, set the dynamic refreshrate
- if(!mDpy && qdutils::MDPVersion::getInstance().isDynFpsSupported() &&
- ctx->mUseMetaDataRefreshRate) {
- FrameInfo frame;
- frame.reset(mCurrentFrame.layerCount);
- memset(&frame.drop, 0, sizeof(frame.drop));
- frame.dropCount = 0;
- ALOGD_IF(isDebug(), "%s: Update Cache and YUVInfo for Dyn Refresh Rate",
- __FUNCTION__);
- updateLayerCache(ctx, list, frame);
- updateYUV(ctx, list, false /*secure only*/, frame);
- uint32_t refreshRate = ctx->dpyAttr[mDpy].refreshRate;
- MDPVersion& mdpHw = MDPVersion::getInstance();
- if(sIdleFallBack) {
- //Set minimum panel refresh rate during idle timeout
- refreshRate = mdpHw.getMinFpsSupported();
- } else if((ctx->listStats[mDpy].yuvCount == frame.mdpCount) ||
- (frame.layerCount == 1)) {
- //Set the new fresh rate, if there is only one updating YUV layer
- //or there is one single RGB layer with this request
- refreshRate = ctx->listStats[mDpy].refreshRateRequest;
- }
- setRefreshRate(ctx, mDpy, refreshRate);
- }
-}
-
-int MDPComp::prepare(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
- int ret = 0;
- char property[PROPERTY_VALUE_MAX];
-
- if(!ctx || !list) {
- ALOGE("%s: Invalid context or list",__FUNCTION__);
- mCachedFrame.reset();
- return -1;
- }
-
- const int numLayers = ctx->listStats[mDpy].numAppLayers;
- if(mDpy == HWC_DISPLAY_PRIMARY) {
- sSimulationFlags = 0;
- if(property_get("debug.hwc.simulate", property, NULL) > 0) {
- int currentFlags = atoi(property);
- if(currentFlags != sSimulationFlags) {
- sSimulationFlags = currentFlags;
- ALOGI("%s: Simulation Flag read: 0x%x (%d)", __FUNCTION__,
- sSimulationFlags, sSimulationFlags);
- }
- }
- }
- // reset PTOR
- if(!mDpy)
- memset(&(ctx->mPtorInfo), 0, sizeof(ctx->mPtorInfo));
-
- //reset old data
- mCurrentFrame.reset(numLayers);
- memset(&mCurrentFrame.drop, 0, sizeof(mCurrentFrame.drop));
- mCurrentFrame.dropCount = 0;
-
- //Do not cache the information for next draw cycle.
- if(numLayers > MAX_NUM_APP_LAYERS or (!numLayers)) {
- ALOGI("%s: Unsupported layer count for mdp composition",
- __FUNCTION__);
- mCachedFrame.reset();
-#ifdef DYNAMIC_FPS
- // Reset refresh rate
- setRefreshRate(ctx, mDpy, ctx->dpyAttr[mDpy].refreshRate);
-#endif
- return -1;
- }
-
- // Detect the start of animation and fall back to GPU only once to cache
- // all the layers in FB and display FB content untill animation completes.
- if(ctx->listStats[mDpy].isDisplayAnimating) {
- mCurrentFrame.needsRedraw = false;
- if(ctx->mAnimationState[mDpy] == ANIMATION_STOPPED) {
- mCurrentFrame.needsRedraw = true;
- ctx->mAnimationState[mDpy] = ANIMATION_STARTED;
- }
- setMDPCompLayerFlags(ctx, list);
- mCachedFrame.updateCounts(mCurrentFrame);
-#ifdef DYNAMIC_FPS
- // Reset refresh rate
- setRefreshRate(ctx, mDpy, ctx->dpyAttr[mDpy].refreshRate);
-#endif
- ret = -1;
- return ret;
- } else {
- ctx->mAnimationState[mDpy] = ANIMATION_STOPPED;
- }
-
- if(!mDpy and !isSecondaryConnected(ctx) and !mPrevModeOn and
- mCachedFrame.isSameFrame(ctx,mDpy,list)) {
-
- ALOGD_IF(isDebug(),"%s: Avoid new composition",__FUNCTION__);
- mCurrentFrame.needsRedraw = false;
- setMDPCompLayerFlags(ctx, list);
- mCachedFrame.updateCounts(mCurrentFrame);
- return -1;
-
- }
-
- //Hard conditions, if not met, cannot do MDP comp
- if(isFrameDoable(ctx)) {
- generateROI(ctx, list);
- // if AIV Video mode is enabled, drop all non AIV layers from the
- // external display list.
- if(ctx->listStats[mDpy].mAIVVideoMode) {
- dropNonAIVLayers(ctx, list);
- }
-
- // if tryFullFrame fails, try to push all video and secure RGB layers
- // to MDP for composition.
- mModeOn = tryFullFrame(ctx, list) || tryMDPOnlyLayers(ctx, list) ||
- tryVideoOnly(ctx, list);
- if(mModeOn) {
- setMDPCompLayerFlags(ctx, list);
- } else {
- resetROI(ctx, mDpy);
- reset(ctx);
- memset(&mCurrentFrame.drop, 0, sizeof(mCurrentFrame.drop));
- mCurrentFrame.dropCount = 0;
- ret = -1;
- ALOGE_IF(sSimulationFlags && (mDpy == HWC_DISPLAY_PRIMARY),
- "MDP Composition Strategies Failed");
- }
- } else {
- if ((ctx->mMDP.version == qdutils::MDP_V3_0_5) && ctx->mCopyBit[mDpy] &&
- enablePartialUpdateForMDP3) {
- generateROI(ctx, list);
- for(int i = 0; i < ctx->listStats[mDpy].numAppLayers; i++) {
- ctx->copybitDrop[i] = mCurrentFrame.drop[i];
- }
- }
- ALOGD_IF( isDebug(),"%s: MDP Comp not possible for this frame",
- __FUNCTION__);
- ret = -1;
- }
-
- if(isDebug()) {
- ALOGD("GEOMETRY change: %d",
- (list->flags & HWC_GEOMETRY_CHANGED));
- android::String8 sDump("");
- dump(sDump, ctx);
- ALOGD("%s",sDump.string());
- }
-
-#ifdef DYNAMIC_FPS
- setDynRefreshRate(ctx, list);
-#endif
-
- mCachedFrame.updateCounts(mCurrentFrame);
- return ret;
-}
-
-bool MDPComp::allocSplitVGPipesfor4k2k(hwc_context_t *ctx, int index) {
-
- bool bRet = true;
- int mdpIndex = mCurrentFrame.layerToMDP[index];
- PipeLayerPair& info = mCurrentFrame.mdpToLayer[mdpIndex];
- info.pipeInfo = new MdpYUVPipeInfo;
- info.rot = NULL;
- MdpYUVPipeInfo& pipe_info = *(MdpYUVPipeInfo*)info.pipeInfo;
-
- pipe_info.lIndex = ovutils::OV_INVALID;
- pipe_info.rIndex = ovutils::OV_INVALID;
-
- Overlay::PipeSpecs pipeSpecs;
- pipeSpecs.formatClass = Overlay::FORMAT_YUV;
- pipeSpecs.needsScaling = true;
- pipeSpecs.dpy = mDpy;
- pipeSpecs.fb = false;
-
- pipe_info.lIndex = ctx->mOverlay->getPipe(pipeSpecs);
- if(pipe_info.lIndex == ovutils::OV_INVALID){
- bRet = false;
- ALOGD_IF(isDebug(),"%s: allocating first VG pipe failed",
- __FUNCTION__);
- }
- pipe_info.rIndex = ctx->mOverlay->getPipe(pipeSpecs);
- if(pipe_info.rIndex == ovutils::OV_INVALID){
- bRet = false;
- ALOGD_IF(isDebug(),"%s: allocating second VG pipe failed",
- __FUNCTION__);
- }
- return bRet;
-}
-
-int MDPComp::drawOverlap(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
- int fd = -1;
- if (ctx->mPtorInfo.isActive()) {
- fd = ctx->mCopyBit[mDpy]->drawOverlap(ctx, list);
- if (fd < 0) {
- ALOGD_IF(isDebug(),"%s: failed", __FUNCTION__);
- }
- }
- return fd;
-}
-//=============MDPCompNonSplit==================================================
-
-void MDPCompNonSplit::adjustForSourceSplit(hwc_context_t *ctx,
- hwc_display_contents_1_t* list) {
- //If 4k2k Yuv layer split is possible, and if
- //fbz is above 4k2k layer, increment fb zorder by 1
- //as we split 4k2k layer and increment zorder for right half
- //of the layer
- if(!ctx)
- return;
- if(mCurrentFrame.fbZ >= 0) {
- for (int index = 0, mdpNextZOrder = 0; index < mCurrentFrame.layerCount;
- index++) {
- if(!mCurrentFrame.isFBComposed[index]) {
- if(mdpNextZOrder == mCurrentFrame.fbZ) {
- mdpNextZOrder++;
- }
- mdpNextZOrder++;
- hwc_layer_1_t* layer = &list->hwLayers[index];
- private_handle_t *hnd = (private_handle_t *)layer->handle;
- if(isYUVSplitNeeded(hnd)) {
- if(mdpNextZOrder <= mCurrentFrame.fbZ)
- mCurrentFrame.fbZ += 1;
- mdpNextZOrder++;
- //As we split 4kx2k yuv layer and program to 2 VG pipes
- //(if available) increase mdpcount by 1.
- mCurrentFrame.mdpCount++;
- }
- }
- }
- }
-}
-
-/*
- * Configures pipe(s) for MDP composition
- */
-int MDPCompNonSplit::configure(hwc_context_t *ctx, hwc_layer_1_t *layer,
- PipeLayerPair& PipeLayerPair) {
- MdpPipeInfoNonSplit& mdp_info =
- *(static_cast<MdpPipeInfoNonSplit*>(PipeLayerPair.pipeInfo));
- eMdpFlags mdpFlags = OV_MDP_BACKEND_COMPOSITION;
- eZorder zOrder = static_cast<eZorder>(mdp_info.zOrder);
- eDest dest = mdp_info.index;
-
- ALOGD_IF(isDebug(),"%s: configuring: layer: %p z_order: %d dest_pipe: %d",
- __FUNCTION__, layer, zOrder, dest);
-
- return configureNonSplit(ctx, layer, mDpy, mdpFlags, zOrder, dest,
- &PipeLayerPair.rot);
-}
-
-bool MDPCompNonSplit::allocLayerPipes(hwc_context_t *ctx,
- hwc_display_contents_1_t* list) {
- for(int index = 0; index < mCurrentFrame.layerCount; index++) {
-
- if(mCurrentFrame.isFBComposed[index]) continue;
-
- hwc_layer_1_t* layer = &list->hwLayers[index];
- private_handle_t *hnd = (private_handle_t *)layer->handle;
- if(isYUVSplitNeeded(hnd) && sEnableYUVsplit){
- if(allocSplitVGPipesfor4k2k(ctx, index)){
- continue;
- }
- }
-
- int mdpIndex = mCurrentFrame.layerToMDP[index];
- PipeLayerPair& info = mCurrentFrame.mdpToLayer[mdpIndex];
- info.pipeInfo = new MdpPipeInfoNonSplit;
- info.rot = NULL;
- MdpPipeInfoNonSplit& pipe_info = *(MdpPipeInfoNonSplit*)info.pipeInfo;
-
- Overlay::PipeSpecs pipeSpecs;
- pipeSpecs.formatClass = isYuvBuffer(hnd) ?
- Overlay::FORMAT_YUV : Overlay::FORMAT_RGB;
- pipeSpecs.needsScaling = qhwc::needsScaling(layer) or
- (qdutils::MDPVersion::getInstance().is8x26() and
- ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres > 1024);
- pipeSpecs.dpy = mDpy;
- pipeSpecs.fb = false;
- pipeSpecs.numActiveDisplays = ctx->numActiveDisplays;
-
- pipe_info.index = ctx->mOverlay->getPipe(pipeSpecs);
-
- if(pipe_info.index == ovutils::OV_INVALID) {
- ALOGD_IF(isDebug(), "%s: Unable to get pipe", __FUNCTION__);
- return false;
- }
- }
- return true;
-}
-
-int MDPCompNonSplit::configure4k2kYuv(hwc_context_t *ctx, hwc_layer_1_t *layer,
- PipeLayerPair& PipeLayerPair) {
- MdpYUVPipeInfo& mdp_info =
- *(static_cast<MdpYUVPipeInfo*>(PipeLayerPair.pipeInfo));
- eZorder zOrder = static_cast<eZorder>(mdp_info.zOrder);
- eMdpFlags mdpFlagsL = OV_MDP_BACKEND_COMPOSITION;
- eDest lDest = mdp_info.lIndex;
- eDest rDest = mdp_info.rIndex;
-
- return configureSourceSplit(ctx, layer, mDpy, mdpFlagsL, zOrder,
- lDest, rDest, &PipeLayerPair.rot);
-}
-
-bool MDPCompNonSplit::draw(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
-
- if(!isEnabled() or !mModeOn) {
- ALOGD_IF(isDebug(),"%s: MDP Comp not enabled/configured", __FUNCTION__);
- return true;
- }
-
- overlay::Overlay& ov = *ctx->mOverlay;
- LayerProp *layerProp = ctx->layerProp[mDpy];
-
- int numHwLayers = ctx->listStats[mDpy].numAppLayers;
- for(int i = 0; i < numHwLayers && mCurrentFrame.mdpCount; i++ )
- {
- if(mCurrentFrame.isFBComposed[i]) continue;
-
- hwc_layer_1_t *layer = &list->hwLayers[i];
- private_handle_t *hnd = (private_handle_t *)layer->handle;
- if(!hnd) {
- if (!(layer->flags & HWC_COLOR_FILL)) {
- ALOGE("%s handle null", __FUNCTION__);
- return false;
- }
- // No PLAY for Color layer
- layerProp[i].mFlags &= ~HWC_MDPCOMP;
- continue;
- }
-
- int mdpIndex = mCurrentFrame.layerToMDP[i];
-
- if(isYUVSplitNeeded(hnd) && sEnableYUVsplit)
- {
- MdpYUVPipeInfo& pipe_info =
- *(MdpYUVPipeInfo*)mCurrentFrame.mdpToLayer[mdpIndex].pipeInfo;
- Rotator *rot = mCurrentFrame.mdpToLayer[mdpIndex].rot;
- ovutils::eDest indexL = pipe_info.lIndex;
- ovutils::eDest indexR = pipe_info.rIndex;
- int fd = hnd->fd;
- uint32_t offset = (uint32_t)hnd->offset;
- if(rot) {
- rot->queueBuffer(fd, offset);
- fd = rot->getDstMemId();
- offset = rot->getDstOffset();
- }
- if(indexL != ovutils::OV_INVALID) {
- ovutils::eDest destL = (ovutils::eDest)indexL;
- ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
- using pipe: %d", __FUNCTION__, layer, hnd, indexL );
- if (!ov.queueBuffer(fd, offset, destL)) {
- ALOGE("%s: queueBuffer failed for display:%d",
- __FUNCTION__, mDpy);
- return false;
- }
- }
-
- if(indexR != ovutils::OV_INVALID) {
- ovutils::eDest destR = (ovutils::eDest)indexR;
- ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
- using pipe: %d", __FUNCTION__, layer, hnd, indexR );
- if (!ov.queueBuffer(fd, offset, destR)) {
- ALOGE("%s: queueBuffer failed for display:%d",
- __FUNCTION__, mDpy);
- return false;
- }
- }
- }
- else{
- MdpPipeInfoNonSplit& pipe_info =
- *(MdpPipeInfoNonSplit*)mCurrentFrame.mdpToLayer[mdpIndex].pipeInfo;
- ovutils::eDest dest = pipe_info.index;
- if(dest == ovutils::OV_INVALID) {
- ALOGE("%s: Invalid pipe index (%d)", __FUNCTION__, dest);
- return false;
- }
-
- if(!(layerProp[i].mFlags & HWC_MDPCOMP)) {
- continue;
- }
-
- int fd = hnd->fd;
- uint32_t offset = (uint32_t)hnd->offset;
- int index = ctx->mPtorInfo.getPTORArrayIndex(i);
- if (!mDpy && (index != -1)) {
- hnd = ctx->mCopyBit[mDpy]->getCurrentRenderBuffer();
- fd = hnd->fd;
- offset = 0;
- }
-
- ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
- using pipe: %d", __FUNCTION__, layer,
- hnd, dest );
-
- Rotator *rot = mCurrentFrame.mdpToLayer[mdpIndex].rot;
- if(rot) {
- if(!rot->queueBuffer(fd, offset))
- return false;
- fd = rot->getDstMemId();
- offset = rot->getDstOffset();
- }
-
- if (!ov.queueBuffer(fd, offset, dest)) {
- ALOGE("%s: queueBuffer failed for display:%d ",
- __FUNCTION__, mDpy);
- return false;
- }
- }
-
- layerProp[i].mFlags &= ~HWC_MDPCOMP;
- }
- return true;
-}
-
-//=============MDPCompSplit===================================================
-
-void MDPCompSplit::adjustForSourceSplit(hwc_context_t *ctx,
- hwc_display_contents_1_t* list){
- //if 4kx2k yuv layer is totally present in either in left half
- //or right half then try splitting the yuv layer to avoid decimation
- const int lSplit = getLeftSplit(ctx, mDpy);
- if(mCurrentFrame.fbZ >= 0) {
- for (int index = 0, mdpNextZOrder = 0; index < mCurrentFrame.layerCount;
- index++) {
- if(!mCurrentFrame.isFBComposed[index]) {
- if(mdpNextZOrder == mCurrentFrame.fbZ) {
- mdpNextZOrder++;
- }
- mdpNextZOrder++;
- hwc_layer_1_t* layer = &list->hwLayers[index];
- private_handle_t *hnd = (private_handle_t *)layer->handle;
- if(isYUVSplitNeeded(hnd)) {
- hwc_rect_t dst = layer->displayFrame;
- if((dst.left > lSplit) || (dst.right < lSplit)) {
- mCurrentFrame.mdpCount += 1;
- }
- if(mdpNextZOrder <= mCurrentFrame.fbZ)
- mCurrentFrame.fbZ += 1;
- mdpNextZOrder++;
- }
- }
- }
- }
-}
-
-bool MDPCompSplit::acquireMDPPipes(hwc_context_t *ctx, hwc_layer_1_t* layer,
- MdpPipeInfoSplit& pipe_info) {
-
- const int lSplit = getLeftSplit(ctx, mDpy);
- private_handle_t *hnd = (private_handle_t *)layer->handle;
- hwc_rect_t dst = layer->displayFrame;
- pipe_info.lIndex = ovutils::OV_INVALID;
- pipe_info.rIndex = ovutils::OV_INVALID;
-
- Overlay::PipeSpecs pipeSpecs;
- pipeSpecs.formatClass = isYuvBuffer(hnd) ?
- Overlay::FORMAT_YUV : Overlay::FORMAT_RGB;
- pipeSpecs.needsScaling = qhwc::needsScalingWithSplit(ctx, layer, mDpy);
- pipeSpecs.dpy = mDpy;
- pipeSpecs.mixer = Overlay::MIXER_LEFT;
- pipeSpecs.fb = false;
-
- // Acquire pipe only for the updating half
- hwc_rect_t l_roi = ctx->listStats[mDpy].lRoi;
- hwc_rect_t r_roi = ctx->listStats[mDpy].rRoi;
-
- if (dst.left < lSplit && isValidRect(getIntersection(dst, l_roi))) {
- pipe_info.lIndex = ctx->mOverlay->getPipe(pipeSpecs);
- if(pipe_info.lIndex == ovutils::OV_INVALID)
- return false;
- }
-
- if(dst.right > lSplit && isValidRect(getIntersection(dst, r_roi))) {
- pipeSpecs.mixer = Overlay::MIXER_RIGHT;
- pipe_info.rIndex = ctx->mOverlay->getPipe(pipeSpecs);
- if(pipe_info.rIndex == ovutils::OV_INVALID)
- return false;
- }
-
- return true;
-}
-
-bool MDPCompSplit::allocLayerPipes(hwc_context_t *ctx,
- hwc_display_contents_1_t* list) {
- for(int index = 0 ; index < mCurrentFrame.layerCount; index++) {
-
- if(mCurrentFrame.isFBComposed[index]) continue;
-
- hwc_layer_1_t* layer = &list->hwLayers[index];
- private_handle_t *hnd = (private_handle_t *)layer->handle;
- hwc_rect_t dst = layer->displayFrame;
- const int lSplit = getLeftSplit(ctx, mDpy);
- if(isYUVSplitNeeded(hnd) && sEnableYUVsplit){
- if((dst.left > lSplit)||(dst.right < lSplit)){
- if(allocSplitVGPipesfor4k2k(ctx, index)){
- continue;
- }
- }
- }
- int mdpIndex = mCurrentFrame.layerToMDP[index];
- PipeLayerPair& info = mCurrentFrame.mdpToLayer[mdpIndex];
- info.pipeInfo = new MdpPipeInfoSplit;
- info.rot = NULL;
- MdpPipeInfoSplit& pipe_info = *(MdpPipeInfoSplit*)info.pipeInfo;
-
- if(!acquireMDPPipes(ctx, layer, pipe_info)) {
- ALOGD_IF(isDebug(), "%s: Unable to get pipe for type",
- __FUNCTION__);
- return false;
- }
- }
- return true;
-}
-
-int MDPCompSplit::configure4k2kYuv(hwc_context_t *ctx, hwc_layer_1_t *layer,
- PipeLayerPair& PipeLayerPair) {
- const int lSplit = getLeftSplit(ctx, mDpy);
- hwc_rect_t dst = layer->displayFrame;
- if((dst.left > lSplit)||(dst.right < lSplit)){
- MdpYUVPipeInfo& mdp_info =
- *(static_cast<MdpYUVPipeInfo*>(PipeLayerPair.pipeInfo));
- eZorder zOrder = static_cast<eZorder>(mdp_info.zOrder);
- eMdpFlags mdpFlagsL = OV_MDP_BACKEND_COMPOSITION;
- eDest lDest = mdp_info.lIndex;
- eDest rDest = mdp_info.rIndex;
-
- return configureSourceSplit(ctx, layer, mDpy, mdpFlagsL, zOrder,
- lDest, rDest, &PipeLayerPair.rot);
- }
- else{
- return configure(ctx, layer, PipeLayerPair);
- }
-}
-
-/*
- * Configures pipe(s) for MDP composition
- */
-int MDPCompSplit::configure(hwc_context_t *ctx, hwc_layer_1_t *layer,
- PipeLayerPair& PipeLayerPair) {
- MdpPipeInfoSplit& mdp_info =
- *(static_cast<MdpPipeInfoSplit*>(PipeLayerPair.pipeInfo));
- eZorder zOrder = static_cast<eZorder>(mdp_info.zOrder);
- eMdpFlags mdpFlagsL = OV_MDP_BACKEND_COMPOSITION;
- eDest lDest = mdp_info.lIndex;
- eDest rDest = mdp_info.rIndex;
-
- ALOGD_IF(isDebug(),"%s: configuring: layer: %p z_order: %d dest_pipeL: %d"
- "dest_pipeR: %d",__FUNCTION__, layer, zOrder, lDest, rDest);
-
- return configureSplit(ctx, layer, mDpy, mdpFlagsL, zOrder, lDest,
- rDest, &PipeLayerPair.rot);
-}
-
-bool MDPCompSplit::draw(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
-
- if(!isEnabled() or !mModeOn) {
- ALOGD_IF(isDebug(),"%s: MDP Comp not enabled/configured", __FUNCTION__);
- return true;
- }
-
- overlay::Overlay& ov = *ctx->mOverlay;
- LayerProp *layerProp = ctx->layerProp[mDpy];
-
- int numHwLayers = ctx->listStats[mDpy].numAppLayers;
- for(int i = 0; i < numHwLayers && mCurrentFrame.mdpCount; i++ )
- {
- if(mCurrentFrame.isFBComposed[i]) continue;
-
- hwc_layer_1_t *layer = &list->hwLayers[i];
- private_handle_t *hnd = (private_handle_t *)layer->handle;
- if(!hnd) {
- ALOGE("%s handle null", __FUNCTION__);
- return false;
- }
-
- if(!(layerProp[i].mFlags & HWC_MDPCOMP)) {
- continue;
- }
-
- int mdpIndex = mCurrentFrame.layerToMDP[i];
-
- if(isYUVSplitNeeded(hnd) && sEnableYUVsplit)
- {
- MdpYUVPipeInfo& pipe_info =
- *(MdpYUVPipeInfo*)mCurrentFrame.mdpToLayer[mdpIndex].pipeInfo;
- Rotator *rot = mCurrentFrame.mdpToLayer[mdpIndex].rot;
- ovutils::eDest indexL = pipe_info.lIndex;
- ovutils::eDest indexR = pipe_info.rIndex;
- int fd = hnd->fd;
- uint32_t offset = (uint32_t)hnd->offset;
- if(rot) {
- rot->queueBuffer(fd, offset);
- fd = rot->getDstMemId();
- offset = rot->getDstOffset();
- }
- if(indexL != ovutils::OV_INVALID) {
- ovutils::eDest destL = (ovutils::eDest)indexL;
- ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
- using pipe: %d", __FUNCTION__, layer, hnd, indexL );
- if (!ov.queueBuffer(fd, offset, destL)) {
- ALOGE("%s: queueBuffer failed for display:%d",
- __FUNCTION__, mDpy);
- return false;
- }
- }
-
- if(indexR != ovutils::OV_INVALID) {
- ovutils::eDest destR = (ovutils::eDest)indexR;
- ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
- using pipe: %d", __FUNCTION__, layer, hnd, indexR );
- if (!ov.queueBuffer(fd, offset, destR)) {
- ALOGE("%s: queueBuffer failed for display:%d",
- __FUNCTION__, mDpy);
- return false;
- }
- }
- }
- else{
- MdpPipeInfoSplit& pipe_info =
- *(MdpPipeInfoSplit*)mCurrentFrame.mdpToLayer[mdpIndex].pipeInfo;
- Rotator *rot = mCurrentFrame.mdpToLayer[mdpIndex].rot;
-
- ovutils::eDest indexL = pipe_info.lIndex;
- ovutils::eDest indexR = pipe_info.rIndex;
-
- int fd = hnd->fd;
- uint32_t offset = (uint32_t)hnd->offset;
- int index = ctx->mPtorInfo.getPTORArrayIndex(i);
- if (!mDpy && (index != -1)) {
- hnd = ctx->mCopyBit[mDpy]->getCurrentRenderBuffer();
- fd = hnd->fd;
- offset = 0;
- }
-
- if(ctx->mAD->draw(ctx, fd, offset)) {
- fd = ctx->mAD->getDstFd();
- offset = ctx->mAD->getDstOffset();
- }
-
- if(rot) {
- rot->queueBuffer(fd, offset);
- fd = rot->getDstMemId();
- offset = rot->getDstOffset();
- }
-
- //************* play left mixer **********
- if(indexL != ovutils::OV_INVALID) {
- ovutils::eDest destL = (ovutils::eDest)indexL;
- ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
- using pipe: %d", __FUNCTION__, layer, hnd, indexL );
- if (!ov.queueBuffer(fd, offset, destL)) {
- ALOGE("%s: queueBuffer failed for left mixer",
- __FUNCTION__);
- return false;
- }
- }
-
- //************* play right mixer **********
- if(indexR != ovutils::OV_INVALID) {
- ovutils::eDest destR = (ovutils::eDest)indexR;
- ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
- using pipe: %d", __FUNCTION__, layer, hnd, indexR );
- if (!ov.queueBuffer(fd, offset, destR)) {
- ALOGE("%s: queueBuffer failed for right mixer",
- __FUNCTION__);
- return false;
- }
- }
- }
-
- layerProp[i].mFlags &= ~HWC_MDPCOMP;
- }
-
- return true;
-}
-
-//================MDPCompSrcSplit==============================================
-bool MDPCompSrcSplit::acquireMDPPipes(hwc_context_t *ctx, hwc_layer_1_t* layer,
- MdpPipeInfoSplit& pipe_info) {
- private_handle_t *hnd = (private_handle_t *)layer->handle;
- hwc_rect_t dst = layer->displayFrame;
- hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);
- pipe_info.lIndex = ovutils::OV_INVALID;
- pipe_info.rIndex = ovutils::OV_INVALID;
-
- //If 2 pipes are staged on a single stage of a mixer, then the left pipe
- //should have a higher priority than the right one. Pipe priorities are
- //starting with VG0, VG1 ... , RGB0 ..., DMA1
-
- Overlay::PipeSpecs pipeSpecs;
- pipeSpecs.formatClass = isYuvBuffer(hnd) ?
- Overlay::FORMAT_YUV : Overlay::FORMAT_RGB;
- pipeSpecs.needsScaling = qhwc::needsScaling(layer);
- pipeSpecs.dpy = mDpy;
- pipeSpecs.fb = false;
-
- //1 pipe by default for a layer
- pipe_info.lIndex = ctx->mOverlay->getPipe(pipeSpecs);
- if(pipe_info.lIndex == ovutils::OV_INVALID) {
- return false;
- }
-
- /* Use 2 pipes IF
- a) Layer's crop width is > 2048 or
- b) Layer's dest width > 2048 or
- c) On primary, driver has indicated with caps to split always. This is
- based on an empirically derived value of panel height. Applied only
- if the layer's width is > mixer's width
- */
-
- MDPVersion& mdpHw = MDPVersion::getInstance();
- bool primarySplitAlways = (mDpy == HWC_DISPLAY_PRIMARY) and
- mdpHw.isSrcSplitAlways();
- int lSplit = getLeftSplit(ctx, mDpy);
- int dstWidth = dst.right - dst.left;
- int cropWidth = has90Transform(layer) ? crop.bottom - crop.top :
- crop.right - crop.left;
-
- //TODO Even if a 4k video is going to be rot-downscaled to dimensions under
- //pipe line length, we are still using 2 pipes. This is fine just because
- //this is source split where destination doesn't matter. Evaluate later to
- //see if going through all the calcs to save a pipe is worth it
- if(dstWidth > (int) mdpHw.getMaxMixerWidth() or
- cropWidth > (int) mdpHw.getMaxMixerWidth() or
- (primarySplitAlways and (cropWidth > lSplit))) {
- pipe_info.rIndex = ctx->mOverlay->getPipe(pipeSpecs);
- if(pipe_info.rIndex == ovutils::OV_INVALID) {
- return false;
- }
-
- // Return values
- // 1 Left pipe is higher priority, do nothing.
- // 0 Pipes of same priority.
- //-1 Right pipe is of higher priority, needs swap.
- if(ctx->mOverlay->comparePipePriority(pipe_info.lIndex,
- pipe_info.rIndex) == -1) {
- qhwc::swap(pipe_info.lIndex, pipe_info.rIndex);
- }
- }
-
- return true;
-}
-
-int MDPCompSrcSplit::configure(hwc_context_t *ctx, hwc_layer_1_t *layer,
- PipeLayerPair& PipeLayerPair) {
- private_handle_t *hnd = (private_handle_t *)layer->handle;
- if(!hnd) {
- ALOGE("%s: layer handle is NULL", __FUNCTION__);
- return -1;
- }
- MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
- MdpPipeInfoSplit& mdp_info =
- *(static_cast<MdpPipeInfoSplit*>(PipeLayerPair.pipeInfo));
- Rotator **rot = &PipeLayerPair.rot;
- eZorder z = static_cast<eZorder>(mdp_info.zOrder);
- eDest lDest = mdp_info.lIndex;
- eDest rDest = mdp_info.rIndex;
- hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);
- hwc_rect_t dst = layer->displayFrame;
- int transform = layer->transform;
- eTransform orient = static_cast<eTransform>(transform);
- int rotFlags = ROT_FLAGS_NONE;
- uint32_t format = ovutils::getMdpFormat(hnd->format, isTileRendered(hnd));
- Whf whf(getWidth(hnd), getHeight(hnd), format, hnd->size);
-
- ALOGD_IF(isDebug(),"%s: configuring: layer: %p z_order: %d dest_pipeL: %d"
- "dest_pipeR: %d",__FUNCTION__, layer, z, lDest, rDest);
-
- // Handle R/B swap
- if (layer->flags & HWC_FORMAT_RB_SWAP) {
- if (hnd->format == HAL_PIXEL_FORMAT_RGBA_8888)
- whf.format = getMdpFormat(HAL_PIXEL_FORMAT_BGRA_8888);
- else if (hnd->format == HAL_PIXEL_FORMAT_RGBX_8888)
- whf.format = getMdpFormat(HAL_PIXEL_FORMAT_BGRX_8888);
- }
- // update source crop and destination position of AIV video layer.
- if(ctx->listStats[mDpy].mAIVVideoMode && isYuvBuffer(hnd)) {
- updateCoordinates(ctx, crop, dst, mDpy);
- }
- /* Calculate the external display position based on MDP downscale,
- ActionSafe, and extorientation features. */
- calcExtDisplayPosition(ctx, hnd, mDpy, crop, dst, transform, orient);
-
- int downscale = getRotDownscale(ctx, layer);
- eMdpFlags mdpFlags = OV_MDP_BACKEND_COMPOSITION;
- setMdpFlags(ctx, layer, mdpFlags, downscale, transform);
-
- if(lDest != OV_INVALID && rDest != OV_INVALID) {
- //Enable overfetch
- setMdpFlags(mdpFlags, OV_MDSS_MDP_DUAL_PIPE);
- }
-
- if((has90Transform(layer) or downscale) and isRotationDoable(ctx, hnd)) {
- (*rot) = ctx->mRotMgr->getNext();
- if((*rot) == NULL) return -1;
- ctx->mLayerRotMap[mDpy]->add(layer, *rot);
- //If the video is using a single pipe, enable BWC
- if(rDest == OV_INVALID) {
- BwcPM::setBwc(crop, dst, transform, downscale, mdpFlags);
- }
- //Configure rotator for pre-rotation
- if(configRotator(*rot, whf, crop, mdpFlags, orient, downscale) < 0) {
- ALOGE("%s: configRotator failed!", __FUNCTION__);
- return -1;
- }
- updateSource(orient, whf, crop, *rot);
- rotFlags |= ovutils::ROT_PREROTATED;
- }
-
- //If 2 pipes being used, divide layer into half, crop and dst
- hwc_rect_t cropL = crop;
- hwc_rect_t cropR = crop;
- hwc_rect_t dstL = dst;
- hwc_rect_t dstR = dst;
- if(lDest != OV_INVALID && rDest != OV_INVALID) {
- cropL.right = (crop.right + crop.left) / 2;
- cropR.left = cropL.right;
- sanitizeSourceCrop(cropL, cropR, hnd);
-
- bool cropSwap = false;
- //Swap crops on H flip since 2 pipes are being used
- if((orient & OVERLAY_TRANSFORM_FLIP_H) && (*rot) == NULL) {
- hwc_rect_t tmp = cropL;
- cropL = cropR;
- cropR = tmp;
- cropSwap = true;
- }
-
- //cropSwap trick: If the src and dst widths are both odd, let us say
- //2507, then splitting both into half would cause left width to be 1253
- //and right 1254. If crop is swapped because of H flip, this will cause
- //left crop width to be 1254, whereas left dst width remains 1253, thus
- //inducing a scaling that is unaccounted for. To overcome that we add 1
- //to the dst width if there is a cropSwap. So if the original width was
- //2507, the left dst width will be 1254. Even if the original width was
- //even for ex: 2508, the left dst width will still remain 1254.
- dstL.right = (dst.right + dst.left + cropSwap) / 2;
- dstR.left = dstL.right;
- }
-
- //For the mdp, since either we are pre-rotating or MDP does flips
- orient = OVERLAY_TRANSFORM_0;
- transform = 0;
-
- //configure left pipe
- if(lDest != OV_INVALID) {
- PipeArgs pargL(mdpFlags, whf, z,
- static_cast<eRotFlags>(rotFlags), layer->planeAlpha,
- (ovutils::eBlending) getBlending(layer->blending));
-
- if(configMdp(ctx->mOverlay, pargL, orient,
- cropL, dstL, metadata, lDest) < 0) {
- ALOGE("%s: commit failed for left mixer config", __FUNCTION__);
- return -1;
- }
- }
-
- //configure right pipe
- if(rDest != OV_INVALID) {
- PipeArgs pargR(mdpFlags, whf, z,
- static_cast<eRotFlags>(rotFlags),
- layer->planeAlpha,
- (ovutils::eBlending) getBlending(layer->blending));
- if(configMdp(ctx->mOverlay, pargR, orient,
- cropR, dstR, metadata, rDest) < 0) {
- ALOGE("%s: commit failed for right mixer config", __FUNCTION__);
- return -1;
- }
- }
-
- return 0;
-}
-
-int MDPComp::getPartialUpdatePref(hwc_context_t *ctx) {
- Locker::Autolock _l(ctx->mDrawLock);
- const int fbNum = Overlay::getFbForDpy(Overlay::DPY_PRIMARY);
- char path[MAX_SYSFS_FILE_PATH];
- snprintf (path, sizeof(path), "sys/class/graphics/fb%d/dyn_pu", fbNum);
- int fd = open(path, O_RDONLY);
- if(fd < 0) {
- ALOGE("%s: Failed to open sysfs node: %s", __FUNCTION__, path);
- return -1;
- }
- char value[4];
- ssize_t size_read = read(fd, value, sizeof(value)-1);
- if(size_read <= 0) {
- ALOGE("%s: Failed to read sysfs node: %s", __FUNCTION__, path);
- close(fd);
- return -1;
- }
- close(fd);
- value[size_read] = '\0';
- return atoi(value);
-}
-
-int MDPComp::setPartialUpdatePref(hwc_context_t *ctx, bool enable) {
- Locker::Autolock _l(ctx->mDrawLock);
- const int fbNum = Overlay::getFbForDpy(Overlay::DPY_PRIMARY);
- char path[MAX_SYSFS_FILE_PATH];
- snprintf (path, sizeof(path), "sys/class/graphics/fb%d/dyn_pu", fbNum);
- int fd = open(path, O_WRONLY);
- if(fd < 0) {
- ALOGE("%s: Failed to open sysfs node: %s", __FUNCTION__, path);
- return -1;
- }
- char value[4];
- snprintf(value, sizeof(value), "%d", (int)enable);
- ssize_t ret = write(fd, value, strlen(value));
- if(ret <= 0) {
- ALOGE("%s: Failed to write to sysfs nodes: %s", __FUNCTION__, path);
- close(fd);
- return -1;
- }
- close(fd);
- return 0;
-}
-}; //namespace
-
diff --git a/msm8909/libhwcomposer/hwc_mdpcomp.h b/msm8909/libhwcomposer/hwc_mdpcomp.h
deleted file mode 100644
index e6b02282..00000000
--- a/msm8909/libhwcomposer/hwc_mdpcomp.h
+++ /dev/null
@@ -1,371 +0,0 @@
-/*
- * Copyright (C) 2012-2015, The Linux Foundation. All rights reserved.
- *
- * Not a Contribution, Apache license notifications and license are retained
- * for attribution purposes only.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef HWC_MDP_COMP
-#define HWC_MDP_COMP
-
-#include <hwc_utils.h>
-#include <idle_invalidator.h>
-#include <cutils/properties.h>
-#include <overlay.h>
-
-#define MAX_PIPES_PER_MIXER 4
-
-namespace overlay {
-class Rotator;
-};
-
-namespace qhwc {
-namespace ovutils = overlay::utils;
-
-class MDPComp {
-public:
- explicit MDPComp(int);
- virtual ~MDPComp(){};
- /*sets up mdp comp for the current frame */
- int prepare(hwc_context_t *ctx, hwc_display_contents_1_t* list);
- /* draw */
- virtual bool draw(hwc_context_t *ctx, hwc_display_contents_1_t *list) = 0;
- //Reset values
- void reset();
- /* dumpsys */
- void dump(android::String8& buf, hwc_context_t *ctx);
- bool isGLESOnlyComp() { return (mCurrentFrame.mdpCount == 0); }
- bool isMDPComp() { return mModeOn; }
- int drawOverlap(hwc_context_t *ctx, hwc_display_contents_1_t* list);
- static MDPComp* getObject(hwc_context_t *ctx, const int& dpy);
- /* Handler to invoke frame redraw on Idle Timer expiry */
- static void timeout_handler(void *udata);
- /* Initialize MDP comp*/
- static bool init(hwc_context_t *ctx);
- static void resetIdleFallBack() { sIdleFallBack = false; }
- static bool isIdleFallback() { return sIdleFallBack; }
- static void dynamicDebug(bool enable){ sDebugLogs = enable; }
- static void setIdleTimeout(const uint32_t& timeout);
- static int setPartialUpdatePref(hwc_context_t *ctx, bool enable);
- void setDynRefreshRate(hwc_context_t *ctx, hwc_display_contents_1_t* list);
- static int getPartialUpdatePref(hwc_context_t *ctx);
- static void enablePartialUpdate(bool enable)
- { sIsPartialUpdateActive = enable; };
-
-protected:
- enum { MAX_SEC_LAYERS = 1 }; //TODO add property support
-
- enum ePipeType {
- MDPCOMP_OV_RGB = ovutils::OV_MDP_PIPE_RGB,
- MDPCOMP_OV_VG = ovutils::OV_MDP_PIPE_VG,
- MDPCOMP_OV_DMA = ovutils::OV_MDP_PIPE_DMA,
- MDPCOMP_OV_ANY,
- };
-
- //Simulation flags
- enum {
- MDPCOMP_AVOID_FULL_MDP = 0x001,
- MDPCOMP_AVOID_CACHE_MDP = 0x002,
- MDPCOMP_AVOID_LOAD_MDP = 0x004,
- MDPCOMP_AVOID_VIDEO_ONLY = 0x008,
- MDPCOMP_AVOID_MDP_ONLY_LAYERS = 0x010,
- };
-
- /* mdp pipe data */
- struct MdpPipeInfo {
- int zOrder;
- virtual ~MdpPipeInfo(){};
- };
-
- struct MdpYUVPipeInfo : public MdpPipeInfo{
- ovutils::eDest lIndex;
- ovutils::eDest rIndex;
- virtual ~MdpYUVPipeInfo(){};
- };
-
- /* per layer data */
- struct PipeLayerPair {
- MdpPipeInfo *pipeInfo;
- overlay::Rotator* rot;
- int listIndex;
- };
-
- /* per frame data */
- struct FrameInfo {
- /* maps layer list to mdp list */
- int layerCount;
- int layerToMDP[MAX_NUM_APP_LAYERS];
-
- /* maps mdp list to layer list */
- int mdpCount;
- struct PipeLayerPair mdpToLayer[MAX_PIPES_PER_MIXER];
-
- /* layer composing on FB? */
- int fbCount;
- bool isFBComposed[MAX_NUM_APP_LAYERS];
- /* layers lying outside ROI. Will
- * be dropped off from the composition */
- int dropCount;
- bool drop[MAX_NUM_APP_LAYERS];
-
- bool needsRedraw;
- int fbZ;
-
- /* c'tor */
- FrameInfo();
- /* clear old frame data */
- void reset(const int& numLayers);
- void map();
- };
-
- /* cached data */
- struct LayerCache {
- int layerCount;
- bool isFBComposed[MAX_NUM_APP_LAYERS];
- bool drop[MAX_NUM_APP_LAYERS];
-
- /* c'tor */
- LayerCache();
- /* clear caching info*/
- void reset();
- void updateCounts(const FrameInfo&);
- bool isSameFrame(const FrameInfo& curFrame,
- hwc_display_contents_1_t* list);
- bool isSameFrame(hwc_context_t *ctx, int dpy,
- hwc_display_contents_1_t* list);
- };
-
- /* allocates pipe from pipe book */
- virtual bool allocLayerPipes(hwc_context_t *ctx,
- hwc_display_contents_1_t* list) = 0;
- /* configures MPD pipes */
- virtual int configure(hwc_context_t *ctx, hwc_layer_1_t *layer,
- PipeLayerPair& pipeLayerPair) = 0;
- /* Increments mdpCount if 4k2k yuv layer split is enabled.
- * updates framebuffer z order if fb lies above source-split layer */
- virtual void adjustForSourceSplit(hwc_context_t *ctx,
- hwc_display_contents_1_t* list) = 0;
- /* configures 4kx2k yuv layer*/
- virtual int configure4k2kYuv(hwc_context_t *ctx, hwc_layer_1_t *layer,
- PipeLayerPair& PipeLayerPair) = 0;
- /* generates ROI based on the modified area of the frame */
- virtual void generateROI(hwc_context_t *ctx,
- hwc_display_contents_1_t* list) = 0;
- /* validates the ROI generated for fallback conditions */
- virtual bool validateAndApplyROI(hwc_context_t *ctx,
- hwc_display_contents_1_t* list) = 0;
- /* Trims fbRect calculated against ROI generated */
- virtual void trimAgainstROI(hwc_context_t *ctx, hwc_rect_t& fbRect) = 0;
-
- /* set/reset flags for MDPComp */
- void setMDPCompLayerFlags(hwc_context_t *ctx,
- hwc_display_contents_1_t* list);
- void setRedraw(hwc_context_t *ctx,
- hwc_display_contents_1_t* list);
- /* checks for conditions where mdpcomp is not possible */
- bool isFrameDoable(hwc_context_t *ctx);
- /* checks for conditions where RGB layers cannot be bypassed */
- bool tryFullFrame(hwc_context_t *ctx, hwc_display_contents_1_t* list);
- /* checks if full MDP comp can be done */
- bool fullMDPComp(hwc_context_t *ctx, hwc_display_contents_1_t* list);
- /* Full MDP Composition with Peripheral Tiny Overlap Removal */
- bool fullMDPCompWithPTOR(hwc_context_t *ctx,hwc_display_contents_1_t* list);
- /* check if we can use layer cache to do at least partial MDP comp */
- bool partialMDPComp(hwc_context_t *ctx, hwc_display_contents_1_t* list);
- /* Partial MDP comp that uses caching to save power as primary goal */
- bool cacheBasedComp(hwc_context_t *ctx, hwc_display_contents_1_t* list);
- /* Partial MDP comp that balances the load between MDP and GPU such that
- * MDP is loaded to the max of its capacity. The lower z order layers are
- * fed to MDP, whereas the upper ones to GPU, because the upper ones have
- * lower number of pixels and can reduce GPU processing time */
- bool loadBasedComp(hwc_context_t *ctx, hwc_display_contents_1_t* list);
- /* Checks if its worth doing load based partial comp */
- bool isLoadBasedCompDoable(hwc_context_t *ctx);
- /* checks for conditions where only video can be bypassed */
- bool tryVideoOnly(hwc_context_t *ctx, hwc_display_contents_1_t* list);
- bool videoOnlyComp(hwc_context_t *ctx, hwc_display_contents_1_t* list,
- bool secureOnly);
- /* checks for conditions where only secure RGB and video can be bypassed */
- bool tryMDPOnlyLayers(hwc_context_t *ctx, hwc_display_contents_1_t* list);
- bool mdpOnlyLayersComp(hwc_context_t *ctx, hwc_display_contents_1_t* list,
- bool secureOnly);
- /* checks for conditions where YUV layers cannot be bypassed */
- bool isYUVDoable(hwc_context_t* ctx, hwc_layer_1_t* layer);
- /* checks for conditions where Secure RGB layers cannot be bypassed */
- bool isSecureRGBDoable(hwc_context_t* ctx, hwc_layer_1_t* layer);
- /* checks if MDP/MDSS can process current list w.r.to HW limitations
- * All peculiar HW limitations should go here */
- bool hwLimitationsCheck(hwc_context_t* ctx, hwc_display_contents_1_t* list);
- /* Is debug enabled */
- static bool isDebug() { return sDebugLogs ? true : false; };
- /* Is feature enabled */
- static bool isEnabled() { return sEnabled; };
- /* checks for mdp comp dimension limitation */
- bool isValidDimension(hwc_context_t *ctx, hwc_layer_1_t *layer);
- /* tracks non updating layers*/
- void updateLayerCache(hwc_context_t* ctx, hwc_display_contents_1_t* list,
- FrameInfo& frame);
- /* optimize layers for mdp comp*/
- bool markLayersForCaching(hwc_context_t* ctx,
- hwc_display_contents_1_t* list);
- int getBatch(hwc_display_contents_1_t* list,
- int& maxBatchStart, int& maxBatchEnd,
- int& maxBatchCount);
- bool canPushBatchToTop(const hwc_display_contents_1_t* list,
- int fromIndex, int toIndex);
- bool intersectingUpdatingLayers(const hwc_display_contents_1_t* list,
- int fromIndex, int toIndex, int targetLayerIndex);
-
- /* drop other non-AIV layers from external display list.*/
- void dropNonAIVLayers(hwc_context_t* ctx, hwc_display_contents_1_t* list);
-
- /* updates cache map with YUV info */
- void updateYUV(hwc_context_t* ctx, hwc_display_contents_1_t* list,
- bool secureOnly, FrameInfo& frame);
- /* updates cache map with secure RGB info */
- void updateSecureRGB(hwc_context_t* ctx,
- hwc_display_contents_1_t* list);
- /* Validates if the GPU/MDP layer split chosen by a strategy is supported
- * by MDP.
- * Sets up MDP comp data structures to reflect covnversion from layers to
- * overlay pipes.
- * Configures overlay.
- * Configures if GPU should redraw.
- */
- bool postHeuristicsHandling(hwc_context_t *ctx,
- hwc_display_contents_1_t* list);
- void reset(hwc_context_t *ctx);
- bool isSupportedForMDPComp(hwc_context_t *ctx, hwc_layer_1_t* layer);
- bool resourceCheck(hwc_context_t* ctx, hwc_display_contents_1_t* list);
- hwc_rect_t getUpdatingFBRect(hwc_context_t *ctx,
- hwc_display_contents_1_t* list);
- /* checks for conditions to enable partial udpate */
- bool canPartialUpdate(hwc_context_t *ctx, hwc_display_contents_1_t* list);
-
- int mDpy;
- static bool sEnabled;
- static bool sEnableMixedMode;
- static int sSimulationFlags;
- static bool sDebugLogs;
- static bool sIdleFallBack;
- static int sMaxPipesPerMixer;
- static bool sSrcSplitEnabled;
- static IdleInvalidator *sIdleInvalidator;
- struct FrameInfo mCurrentFrame;
- struct LayerCache mCachedFrame;
- static bool sIsPartialUpdateActive;
- //Enable 4kx2k yuv layer split
- static bool sEnableYUVsplit;
- bool mModeOn; // if prepare happened
- bool allocSplitVGPipesfor4k2k(hwc_context_t *ctx, int index);
- bool mPrevModeOn; //if previous prepare happened
- //Enable Partial Update for MDP3 targets
- static bool enablePartialUpdateForMDP3;
-};
-
-class MDPCompNonSplit : public MDPComp {
-public:
- explicit MDPCompNonSplit(int dpy):MDPComp(dpy){};
- virtual ~MDPCompNonSplit(){};
- virtual bool draw(hwc_context_t *ctx, hwc_display_contents_1_t *list);
-
-private:
- struct MdpPipeInfoNonSplit : public MdpPipeInfo {
- ovutils::eDest index;
- virtual ~MdpPipeInfoNonSplit() {};
- };
-
- /* configure's overlay pipes for the frame */
- virtual int configure(hwc_context_t *ctx, hwc_layer_1_t *layer,
- PipeLayerPair& pipeLayerPair);
-
- /* allocates pipes to selected candidates */
- virtual bool allocLayerPipes(hwc_context_t *ctx,
- hwc_display_contents_1_t* list);
-
- /* Increments mdpCount if 4k2k yuv layer split is enabled.
- * updates framebuffer z order if fb lies above source-split layer */
- virtual void adjustForSourceSplit(hwc_context_t *ctx,
- hwc_display_contents_1_t* list);
-
- /* configures 4kx2k yuv layer to 2 VG pipes*/
- virtual int configure4k2kYuv(hwc_context_t *ctx, hwc_layer_1_t *layer,
- PipeLayerPair& PipeLayerPair);
- /* generates ROI based on the modified area of the frame */
- virtual void generateROI(hwc_context_t *ctx,
- hwc_display_contents_1_t* list);
- /* validates the ROI generated for fallback conditions */
- virtual bool validateAndApplyROI(hwc_context_t *ctx,
- hwc_display_contents_1_t* list);
- /* Trims fbRect calculated against ROI generated */
- virtual void trimAgainstROI(hwc_context_t *ctx, hwc_rect_t& fbRect);
-};
-
-class MDPCompSplit : public MDPComp {
-public:
- explicit MDPCompSplit(int dpy):MDPComp(dpy){};
- virtual ~MDPCompSplit(){};
- virtual bool draw(hwc_context_t *ctx, hwc_display_contents_1_t *list);
-
-protected:
- struct MdpPipeInfoSplit : public MdpPipeInfo {
- ovutils::eDest lIndex;
- ovutils::eDest rIndex;
- virtual ~MdpPipeInfoSplit() {};
- };
-
- virtual bool acquireMDPPipes(hwc_context_t *ctx, hwc_layer_1_t* layer,
- MdpPipeInfoSplit& pipe_info);
-
- /* configure's overlay pipes for the frame */
- virtual int configure(hwc_context_t *ctx, hwc_layer_1_t *layer,
- PipeLayerPair& pipeLayerPair);
-
- /* allocates pipes to selected candidates */
- virtual bool allocLayerPipes(hwc_context_t *ctx,
- hwc_display_contents_1_t* list);
-private:
- /* Increments mdpCount if 4k2k yuv layer split is enabled.
- * updates framebuffer z order if fb lies above source-split layer */
- virtual void adjustForSourceSplit(hwc_context_t *ctx,
- hwc_display_contents_1_t* list);
-
- /* configures 4kx2k yuv layer*/
- virtual int configure4k2kYuv(hwc_context_t *ctx, hwc_layer_1_t *layer,
- PipeLayerPair& PipeLayerPair);
- /* generates ROI based on the modified area of the frame */
- virtual void generateROI(hwc_context_t *ctx,
- hwc_display_contents_1_t* list);
- /* validates the ROI generated for fallback conditions */
- virtual bool validateAndApplyROI(hwc_context_t *ctx,
- hwc_display_contents_1_t* list);
- /* Trims fbRect calculated against ROI generated */
- virtual void trimAgainstROI(hwc_context_t *ctx, hwc_rect_t& fbRect);
-};
-
-class MDPCompSrcSplit : public MDPCompSplit {
-public:
- explicit MDPCompSrcSplit(int dpy) : MDPCompSplit(dpy){};
- virtual ~MDPCompSrcSplit(){};
-private:
- virtual bool acquireMDPPipes(hwc_context_t *ctx, hwc_layer_1_t* layer,
- MdpPipeInfoSplit& pipe_info);
-
- virtual int configure(hwc_context_t *ctx, hwc_layer_1_t *layer,
- PipeLayerPair& pipeLayerPair);
-};
-
-}; //namespace
-#endif
diff --git a/msm8909/libhwcomposer/hwc_qclient.cpp b/msm8909/libhwcomposer/hwc_qclient.cpp
deleted file mode 100644
index 4db4fa7e..00000000
--- a/msm8909/libhwcomposer/hwc_qclient.cpp
+++ /dev/null
@@ -1,401 +0,0 @@
-/*
- * Copyright (c) 2013-15, The Linux Foundation. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials provided
- * with the distribution.
- * * Neither the name of The Linux Foundation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR CLIENTS; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
- * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
- * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <hwc_qclient.h>
-#include <IQService.h>
-#include <hwc_utils.h>
-#include <mdp_version.h>
-#include <hwc_mdpcomp.h>
-#include <hwc_virtual.h>
-#include <overlay.h>
-#include <display_config.h>
-#include <hwc_qdcm.h>
-
-#define QCLIENT_DEBUG 0
-
-using namespace android;
-using namespace qService;
-using namespace qhwc;
-using namespace overlay;
-using namespace qdutils;
-using namespace qQdcm;
-
-namespace qClient {
-
-// ----------------------------------------------------------------------------
-QClient::QClient(hwc_context_t *ctx) : mHwcContext(ctx),
- mMPDeathNotifier(new MPDeathNotifier(ctx))
-{
- ALOGD_IF(QCLIENT_DEBUG, "QClient Constructor invoked");
-}
-
-QClient::~QClient()
-{
- ALOGD_IF(QCLIENT_DEBUG,"QClient Destructor invoked");
-}
-
-static void securing(hwc_context_t *ctx, uint32_t startEnd) {
- //The only way to make this class in this process subscribe to media
- //player's death.
- IMediaDeathNotifier::getMediaPlayerService();
-
- ctx->mDrawLock.lock();
- ctx->mSecuring = startEnd;
- //We're done securing
- if(startEnd == IQService::END)
- ctx->mSecureMode = true;
- ctx->mDrawLock.unlock();
-
- if(ctx->proc)
- ctx->proc->invalidate(ctx->proc);
-}
-
-static void unsecuring(hwc_context_t *ctx, uint32_t startEnd) {
- ctx->mDrawLock.lock();
- ctx->mSecuring = startEnd;
- //We're done unsecuring
- if(startEnd == IQService::END)
- ctx->mSecureMode = false;
- ctx->mDrawLock.unlock();
-
- if(ctx->proc)
- ctx->proc->invalidate(ctx->proc);
-}
-
-void QClient::MPDeathNotifier::died() {
- mHwcContext->mDrawLock.lock();
- ALOGD_IF(QCLIENT_DEBUG, "Media Player died");
- mHwcContext->mSecuring = false;
- mHwcContext->mSecureMode = false;
- mHwcContext->mDrawLock.unlock();
- if(mHwcContext->proc)
- mHwcContext->proc->invalidate(mHwcContext->proc);
-}
-
-static android::status_t screenRefresh(hwc_context_t *ctx) {
- status_t result = NO_INIT;
- if(ctx->proc) {
- ctx->proc->invalidate(ctx->proc);
- result = NO_ERROR;
- }
- return result;
-}
-
-static void setExtOrientation(hwc_context_t *ctx, uint32_t orientation) {
- ctx->mExtOrientation = orientation;
-}
-
-static void isExternalConnected(hwc_context_t* ctx, Parcel* outParcel) {
- int connected;
- connected = ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].connected ? 1 : 0;
- outParcel->writeInt32(connected);
-}
-
-static void getDisplayAttributes(hwc_context_t* ctx, const Parcel* inParcel,
- Parcel* outParcel) {
- int dpy = inParcel->readInt32();
- outParcel->writeInt32(ctx->dpyAttr[dpy].vsync_period);
- if (ctx->dpyAttr[dpy].customFBSize) {
- outParcel->writeInt32(ctx->dpyAttr[dpy].xres_new);
- outParcel->writeInt32(ctx->dpyAttr[dpy].yres_new);
- } else {
- outParcel->writeInt32(ctx->dpyAttr[dpy].xres);
- outParcel->writeInt32(ctx->dpyAttr[dpy].yres);
- }
- outParcel->writeFloat(ctx->dpyAttr[dpy].xdpi);
- outParcel->writeFloat(ctx->dpyAttr[dpy].ydpi);
- //XXX: Need to check what to return for HDMI
- outParcel->writeInt32(ctx->mMDP.panel);
-}
-static void setHSIC(const Parcel* inParcel) {
- int dpy = inParcel->readInt32();
- ALOGD_IF(0, "In %s: dpy = %d", __FUNCTION__, dpy);
- HSICData_t hsic_data;
- hsic_data.hue = inParcel->readInt32();
- hsic_data.saturation = inParcel->readFloat();
- hsic_data.intensity = inParcel->readInt32();
- hsic_data.contrast = inParcel->readFloat();
- //XXX: Actually set the HSIC data through ABL lib
-}
-
-
-static void setBufferMirrorMode(hwc_context_t *ctx, uint32_t enable) {
- ctx->mBufferMirrorMode = enable;
-}
-
-static status_t getDisplayVisibleRegion(hwc_context_t* ctx, int dpy,
- Parcel* outParcel) {
- // Get the info only if the dpy is valid
- if(dpy >= HWC_DISPLAY_PRIMARY && dpy <= HWC_DISPLAY_VIRTUAL) {
- Locker::Autolock _sl(ctx->mDrawLock);
- if(dpy && (ctx->mExtOrientation || ctx->mBufferMirrorMode)) {
- // Return the destRect on external, if external orienation
- // is enabled
- outParcel->writeInt32(ctx->dpyAttr[dpy].mDstRect.left);
- outParcel->writeInt32(ctx->dpyAttr[dpy].mDstRect.top);
- outParcel->writeInt32(ctx->dpyAttr[dpy].mDstRect.right);
- outParcel->writeInt32(ctx->dpyAttr[dpy].mDstRect.bottom);
- } else {
- outParcel->writeInt32(ctx->mViewFrame[dpy].left);
- outParcel->writeInt32(ctx->mViewFrame[dpy].top);
- outParcel->writeInt32(ctx->mViewFrame[dpy].right);
- outParcel->writeInt32(ctx->mViewFrame[dpy].bottom);
- }
- return NO_ERROR;
- } else {
- ALOGE("In %s: invalid dpy index %d", __FUNCTION__, dpy);
- return BAD_VALUE;
- }
-}
-
-// USed for setting the secondary(hdmi/wfd) status
-static void setSecondaryDisplayStatus(hwc_context_t *ctx,
- const Parcel* inParcel) {
- uint32_t dpy = inParcel->readInt32();
- uint32_t status = inParcel->readInt32();
- ALOGD_IF(QCLIENT_DEBUG, "%s: dpy = %d status = %s", __FUNCTION__,
- dpy, getExternalDisplayState(status));
-
- if(dpy > HWC_DISPLAY_PRIMARY && dpy <= HWC_DISPLAY_VIRTUAL) {
- if(dpy == HWC_DISPLAY_VIRTUAL && status == qdutils::EXTERNAL_OFFLINE) {
- ctx->mWfdSyncLock.lock();
- ctx->mWfdSyncLock.signal();
- ctx->mWfdSyncLock.unlock();
- } else if(status == qdutils::EXTERNAL_PAUSE) {
- handle_pause(ctx, dpy);
- } else if(status == qdutils::EXTERNAL_RESUME) {
- handle_resume(ctx, dpy);
- }
- } else {
- ALOGE("%s: Invalid dpy %d", __FUNCTION__, dpy);
- return;
- }
-}
-
-
-static status_t setViewFrame(hwc_context_t* ctx, const Parcel* inParcel) {
- int dpy = inParcel->readInt32();
- if(dpy >= HWC_DISPLAY_PRIMARY && dpy <= HWC_DISPLAY_VIRTUAL) {
- Locker::Autolock _sl(ctx->mDrawLock);
- ctx->mViewFrame[dpy].left = inParcel->readInt32();
- ctx->mViewFrame[dpy].top = inParcel->readInt32();
- ctx->mViewFrame[dpy].right = inParcel->readInt32();
- ctx->mViewFrame[dpy].bottom = inParcel->readInt32();
- ALOGD_IF(QCLIENT_DEBUG, "%s: mViewFrame[%d] = [%d %d %d %d]",
- __FUNCTION__, dpy,
- ctx->mViewFrame[dpy].left, ctx->mViewFrame[dpy].top,
- ctx->mViewFrame[dpy].right, ctx->mViewFrame[dpy].bottom);
- return NO_ERROR;
- } else {
- ALOGE("In %s: invalid dpy index %d", __FUNCTION__, dpy);
- return BAD_VALUE;
- }
-}
-
-static void toggleDynamicDebug(hwc_context_t* ctx, const Parcel* inParcel) {
- int debug_type = inParcel->readInt32();
- bool enable = !!inParcel->readInt32();
- ALOGD("%s: debug_type: %d enable:%d",
- __FUNCTION__, debug_type, enable);
- Locker::Autolock _sl(ctx->mDrawLock);
- switch (debug_type) {
- //break is ignored for DEBUG_ALL to toggle all of them at once
- case IQService::DEBUG_ALL:
- case IQService::DEBUG_MDPCOMP:
- qhwc::MDPComp::dynamicDebug(enable);
- if (debug_type != IQService::DEBUG_ALL)
- break;
- case IQService::DEBUG_VSYNC:
- ctx->vstate.debug = enable;
- if (debug_type != IQService::DEBUG_ALL)
- break;
- case IQService::DEBUG_VD:
- HWCVirtualVDS::dynamicDebug(enable);
- if (debug_type != IQService::DEBUG_ALL)
- break;
- case IQService::DEBUG_PIPE_LIFECYCLE:
- Overlay::debugPipeLifecycle(enable);
- if (debug_type != IQService::DEBUG_ALL)
- break;
- }
-}
-
-static void setIdleTimeout(hwc_context_t* ctx, const Parcel* inParcel) {
- uint32_t timeout = (uint32_t)inParcel->readInt32();
- ALOGD("%s :%u ms", __FUNCTION__, timeout);
- Locker::Autolock _sl(ctx->mDrawLock);
- MDPComp::setIdleTimeout(timeout);
-}
-
-static void configureDynRefreshRate(hwc_context_t* ctx,
- const Parcel* inParcel) {
- uint32_t op = (uint32_t)inParcel->readInt32();
- uint32_t refresh_rate = (uint32_t)inParcel->readInt32();
- MDPVersion& mdpHw = MDPVersion::getInstance();
- uint32_t dpy = HWC_DISPLAY_PRIMARY;
-
- if(mdpHw.isDynFpsSupported()) {
- Locker::Autolock _sl(ctx->mDrawLock);
-
- switch (op) {
- case DISABLE_METADATA_DYN_REFRESH_RATE:
- ctx->mUseMetaDataRefreshRate = false;
- setRefreshRate(ctx, dpy, ctx->dpyAttr[dpy].refreshRate);
- break;
- case ENABLE_METADATA_DYN_REFRESH_RATE:
- ctx->mUseMetaDataRefreshRate = true;
- setRefreshRate(ctx, dpy, ctx->dpyAttr[dpy].refreshRate);
- break;
- case SET_BINDER_DYN_REFRESH_RATE:
- if(ctx->mUseMetaDataRefreshRate)
- ALOGW("%s: Ignoring binder request to change refresh-rate",
- __FUNCTION__);
- else {
- uint32_t rate = roundOff(refresh_rate);
- if((rate >= mdpHw.getMinFpsSupported() &&
- rate <= mdpHw.getMaxFpsSupported())) {
- setRefreshRate(ctx, dpy, rate);
- } else {
- ALOGE("%s: Requested refresh-rate should be between \
- (%d) and (%d). Given (%d)", __FUNCTION__,
- mdpHw.getMinFpsSupported(),
- mdpHw.getMaxFpsSupported(), rate);
- }
- }
- break;
- default:
- ALOGE("%s: Invalid op %d",__FUNCTION__,op);
- }
- }
-}
-
-static status_t setPartialUpdateState(hwc_context_t *ctx, uint32_t state) {
- ALOGD("%s: state: %d", __FUNCTION__, state);
- switch(state) {
- case IQService::PREF_PARTIAL_UPDATE:
- if(qhwc::MDPComp::setPartialUpdatePref(ctx, true) < 0)
- return NO_INIT;
- return NO_ERROR;
- case IQService::PREF_POST_PROCESSING:
- if(qhwc::MDPComp::setPartialUpdatePref(ctx, false) < 0)
- return NO_INIT;
- qhwc::MDPComp::enablePartialUpdate(false);
- return NO_ERROR;
- case IQService::ENABLE_PARTIAL_UPDATE:
- qhwc::MDPComp::enablePartialUpdate(true);
- return NO_ERROR;
- default:
- ALOGE("%s: Invalid state", __FUNCTION__);
- return NO_ERROR;
- };
-}
-
-static void toggleScreenUpdate(hwc_context_t* ctx, uint32_t on) {
- ALOGD("%s: toggle update: %d", __FUNCTION__, on);
- if (on == 0) {
- ctx->mDrawLock.lock();
- ctx->dpyAttr[HWC_DISPLAY_PRIMARY].isPause = true;
- ctx->mOverlay->configBegin();
- ctx->mOverlay->configDone();
- ctx->mRotMgr->clear();
- if(!Overlay::displayCommit(ctx->dpyAttr[0].fd)) {
- ALOGE("%s: Display commit failed", __FUNCTION__);
- }
- ctx->mDrawLock.unlock();
- } else {
- ctx->mDrawLock.lock();
- ctx->dpyAttr[HWC_DISPLAY_PRIMARY].isPause = false;
- ctx->mDrawLock.unlock();
- ctx->proc->invalidate(ctx->proc);
- }
-}
-
-status_t QClient::notifyCallback(uint32_t command, const Parcel* inParcel,
- Parcel* outParcel) {
- status_t ret = NO_ERROR;
-
- switch(command) {
- case IQService::SECURING:
- securing(mHwcContext, inParcel->readInt32());
- break;
- case IQService::UNSECURING:
- unsecuring(mHwcContext, inParcel->readInt32());
- break;
- case IQService::SCREEN_REFRESH:
- return screenRefresh(mHwcContext);
- break;
- case IQService::EXTERNAL_ORIENTATION:
- setExtOrientation(mHwcContext, inParcel->readInt32());
- break;
- case IQService::BUFFER_MIRRORMODE:
- setBufferMirrorMode(mHwcContext, inParcel->readInt32());
- break;
- case IQService::GET_DISPLAY_VISIBLE_REGION:
- ret = getDisplayVisibleRegion(mHwcContext, inParcel->readInt32(),
- outParcel);
- break;
- case IQService::CHECK_EXTERNAL_STATUS:
- isExternalConnected(mHwcContext, outParcel);
- break;
- case IQService::GET_DISPLAY_ATTRIBUTES:
- getDisplayAttributes(mHwcContext, inParcel, outParcel);
- break;
- case IQService::SET_HSIC_DATA:
- setHSIC(inParcel);
- break;
- case IQService::SET_SECONDARY_DISPLAY_STATUS:
- setSecondaryDisplayStatus(mHwcContext, inParcel);
- break;
- case IQService::SET_VIEW_FRAME:
- setViewFrame(mHwcContext, inParcel);
- break;
- case IQService::DYNAMIC_DEBUG:
- toggleDynamicDebug(mHwcContext, inParcel);
- break;
- case IQService::SET_IDLE_TIMEOUT:
- setIdleTimeout(mHwcContext, inParcel);
- break;
- case IQService::SET_PARTIAL_UPDATE:
- ret = setPartialUpdateState(mHwcContext, inParcel->readInt32());
- break;
- case IQService::CONFIGURE_DYN_REFRESH_RATE:
- configureDynRefreshRate(mHwcContext, inParcel);
- case IQService::QDCM_SVC_CMDS:
- qdcmCmdsHandler(mHwcContext, inParcel, outParcel);
- break;
- case IQService::TOGGLE_SCREEN_UPDATE:
- toggleScreenUpdate(mHwcContext, inParcel->readInt32());
- break;
- default:
- ret = NO_ERROR;
- }
- return ret;
-}
-
-}
diff --git a/msm8909/libhwcomposer/hwc_qdcm.cpp b/msm8909/libhwcomposer/hwc_qdcm.cpp
deleted file mode 100644
index 9821e4e6..00000000
--- a/msm8909/libhwcomposer/hwc_qdcm.cpp
+++ /dev/null
@@ -1,292 +0,0 @@
-/*
- * Copyright (c) 2014, The Linux Foundation. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials provided
- * with the distribution.
- * * Neither the name of The Linux Foundation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
- * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
- * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <hwc_qdcm.h>
-#include <hwc_utils.h>
-#include <utils/String16.h>
-#include <mdp_version.h>
-#include "mode_manager.h"
-#include "libmm-disp-apis.h"
-#include "IQService.h"
-
-using namespace android;
-using namespace qService;
-using namespace qhwc;
-using namespace qmode;
-
-namespace qQdcm {
-//----------------------------------------------------------------------------
-void qdcmInitContext(hwc_context_t *ctx)
-{
- loadQdcmLibrary(ctx);
-}
-
-void qdcmCloseContext(hwc_context_t *ctx)
-{
- if (ctx->mQdcmInfo.mQdcmMode) {
- unloadQdcmLibrary(ctx);
- }
-}
-
-void qdcmApplyDefaultAfterBootAnimationDone(hwc_context_t *ctx)
-{
- if (ctx->mQdcmInfo.mQdcmMode)
- ctx->mQdcmInfo.mQdcmMode->applyDefaultMode(0);
-}
-
-static void qdcmSetActiveMode(hwc_context_t *ctx, const Parcel *in, Parcel *out)
-{
- int ret = 0;
-
- if (ctx->mQdcmInfo.mQdcmMode && in && out) {
-
- struct SET_MODE_PROP_IN params =
- { (disp_id_type)in->readInt32(), in->readInt32()};
-
- ret = ctx->mQdcmInfo.mQdcmMode->requestRoute((int)CMD_SET_ACTIVE_MODE,
- (void *)&params, (void *)NULL);
-
- out->writeInt32(ret); //return operation status via binder.
- }
-}
-
-static void qdcmSetDefaultMode(hwc_context_t *ctx, const Parcel *in, Parcel *out)
-{
- int ret = 0;
-
- if (ctx->mQdcmInfo.mQdcmMode && in && out) {
-
- struct SET_MODE_PROP_IN params =
- { (disp_id_type)in->readInt32(), in->readInt32()};
-
- ret = ctx->mQdcmInfo.mQdcmMode->requestRoute((int)CMD_SET_DEFAULT_MODE,
- (void *)&params, (void *)NULL);
-
- out->writeInt32(ret); //return operation status via binder.
- }
-}
-
-static void qdcmGetDefaultMode(hwc_context_t *ctx,
- const Parcel *in, Parcel *out)
-{
- int ret = 0;
-
- if (ctx->mQdcmInfo.mQdcmMode && in && out) {
-
- int params = in->readInt32();
- int modeid = 0;
-
- ret = ctx->mQdcmInfo.mQdcmMode->requestRoute((int)CMD_GET_DEFAULT_MODE,
- (const void *)&params, (void *)&modeid);
-
- out->writeInt32(modeid);
- out->writeInt32(ret); //return operation status via binder.
- }
-}
-
-static void qdcmGetColorBalanceRange(hwc_context_t *ctx __unused,
- const Parcel *in __unused, Parcel *out __unused)
-{
-}
-
-static void qdcmGetColorBalance(hwc_context_t *ctx,
- const Parcel *in, Parcel *out)
-{
- int ret = 0;
-
- if (ctx->mQdcmInfo.mQdcmMode && in && out) {
-
- int params = in->readInt32();
- int warmness = 0;
-
- ret = ctx->mQdcmInfo.mQdcmMode->requestRoute((int)CMD_GET_CB,
- (const void *)&params, (void *)&warmness);
-
- out->writeInt32(warmness);
- out->writeInt32(ret); //return operation status via binder.
- }
-}
-
-static void qdcmSetColorBalance(hwc_context_t *ctx,
- const Parcel *in, Parcel *out)
-{
- int ret = 0;
-
- if (ctx->mQdcmInfo.mQdcmMode && in && out) {
-
- struct SET_CB_IN params =
- { (disp_id_type)in->readInt32(), in->readInt32() };
-
- ALOGD_IF(QDCM_DEBUG, "%s dispID = %d, warmness = %d\n",
- __FUNCTION__, params.id, params.warmness);
-
- ret = ctx->mQdcmInfo.mQdcmMode->requestRoute((int)CMD_SET_CB,
- (const void *)&params, NULL);
-
- out->writeInt32(ret); //return operation status via binder.
- }
-}
-
-static void qdcmSaveModeV2(hwc_context_t *ctx, const Parcel *in, Parcel *out)
-{
- int ret = 0;
-
- if (ctx->mQdcmInfo.mQdcmMode && in && out) {
-
- struct SAVE_DISPLAY_MODE_V2_IN params =
- { (disp_id_type)in->readInt32(),
- in->readCString(),
- (uint32_t)in->readInt32(),
- in->readInt32()
- };
- int value = 0;
-
- ret = ctx->mQdcmInfo.mQdcmMode->requestRoute((int)CMD_SAVE_MODE_V2,
- (const void *)&params, (void *)&value);
-
- out->writeInt32(value);
- out->writeInt32(ret); //return operation status via binder.
- }
-}
-
-static void qdcmSetPaConfig(hwc_context_t *ctx, const Parcel *in, Parcel *out)
-{
- int ret = 0;
-
- if (ctx->mQdcmInfo.mQdcmMode && in && out) {
-
- struct SET_PA_CONFIG_IN params;
-
- params.id = (disp_id_type)in->readInt32();
- params.pa.ops = in->readInt32();
- params.pa.data.hue = in->readInt32();
- params.pa.data.saturation = in->readInt32();
- params.pa.data.value = in->readInt32();
- params.pa.data.contrast = in->readInt32();
- params.pa.data.sat_thresh = in->readInt32();
-
- ret = ctx->mQdcmInfo.mQdcmMode->requestRoute((int)CMD_SET_PA_CONFIG,
- (const void *)&params, NULL);
-
- out->writeInt32(ret); //return operation status via binder.
- }
-}
-
-static void qdcmGetPaConfig(hwc_context_t *ctx, const Parcel *in, Parcel *out)
-{
- int ret = 0;
-
- if (ctx->mQdcmInfo.mQdcmMode && in && out) {
-
- int params = in->readInt32();
- struct disp_pa_config value;
-
- ret = ctx->mQdcmInfo.mQdcmMode->requestRoute((int)CMD_GET_PA_CONFIG,
- (const void *)&params, (void *)&value);
-
- out->writeInt32(value.ops);
- out->writeInt32(value.data.hue);
- out->writeInt32(value.data.saturation);
- out->writeInt32(value.data.value);
- out->writeInt32(value.data.contrast);
- out->writeInt32(value.data.sat_thresh);
-
- out->writeInt32(ret); //return operation status via binder.
- }
-}
-
-static void qdcmGetPaRange(hwc_context_t *ctx, const Parcel *in, Parcel *out)
-{
- int ret = 0;
-
- if (ctx->mQdcmInfo.mQdcmMode && in && out) {
-
- int params = in->readInt32();
- struct disp_pa_range value;
-
- ret = ctx->mQdcmInfo.mQdcmMode->requestRoute((int)CMD_GET_PA_RANGE,
- (const void *)&params, (void *)&value);
-
- out->writeInt32(value.max.hue);
- out->writeInt32(value.max.saturation);
- out->writeInt32(value.max.value);
- out->writeInt32(value.max.contrast);
- out->writeInt32(value.max.sat_thresh);
- out->writeInt32(value.min.hue);
- out->writeInt32(value.min.saturation);
- out->writeInt32(value.min.value);
- out->writeInt32(value.min.contrast);
- out->writeInt32(value.min.sat_thresh);
-
- out->writeInt32(ret); //return operation status via binder.
- }
-}
-
-void qdcmCmdsHandler(hwc_context_t *ctx, const Parcel *in, Parcel *out)
-{
- int subcmd = in->readInt32();
-
- ALOGD_IF(QDCM_DEBUG, "%s enter subcmd = %d\n", __FUNCTION__, subcmd);
- switch (subcmd) {
- case CMD_SET_ACTIVE_MODE:
- qdcmSetActiveMode(ctx, in, out);
- break;
- case CMD_SET_DEFAULT_MODE:
- qdcmSetDefaultMode(ctx, in, out);
- break;
- case CMD_GET_DEFAULT_MODE:
- qdcmGetDefaultMode(ctx, in, out);
- break;
- case CMD_GET_CB_RANGE:
- qdcmGetColorBalanceRange(ctx, in, out);
- break;
- case CMD_GET_CB:
- qdcmGetColorBalance(ctx, in, out);
- break;
- case CMD_SET_CB:
- qdcmSetColorBalance(ctx, in, out);
- break;
- case CMD_SAVE_MODE_V2:
- qdcmSaveModeV2(ctx, in, out);
- break;
- case CMD_SET_PA_CONFIG:
- qdcmSetPaConfig(ctx, in, out);
- break;
- case CMD_GET_PA_CONFIG:
- qdcmGetPaConfig(ctx, in, out);
- break;
- case CMD_GET_PA_RANGE:
- qdcmGetPaRange(ctx, in, out);
- break;
- }
-}
-
-
-} //namespace qQdcm
-
diff --git a/msm8909/libhwcomposer/hwc_qdcm.h b/msm8909/libhwcomposer/hwc_qdcm.h
deleted file mode 100644
index 64531596..00000000
--- a/msm8909/libhwcomposer/hwc_qdcm.h
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright (c) 2014, The Linux Foundation. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials provided
- * with the distribution.
- * * Neither the name of The Linux Foundation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
- * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
- * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef ANDROID_QDCM_H
-#define ANDROID_QDCM_H
-
-#include <utils/Errors.h>
-#include <sys/types.h>
-#include <cutils/log.h>
-#include <hwc_utils.h>
-#include <dlfcn.h>
-#include <binder/Parcel.h>
-#include <cutils/properties.h>
-
-#define QDCM_DEBUG 0
-
-namespace qmode {
-class ModeManager;
-}
-
-using namespace android;
-
-namespace qQdcm {
-// ----------------------------------------------------------------------------
-
-//function prototypes used for QDCM library and service
-static inline void loadQdcmLibrary(hwc_context_t *ctx)
-{
- ctx->mQdcmInfo.mQdcmLib = dlopen("libmm-qdcm.so", RTLD_NOW);
- qmode::ModeManager* (*factory)() = NULL;
-
- if (ctx->mQdcmInfo.mQdcmLib)
- *(void **)&factory = dlsym(ctx->mQdcmInfo.mQdcmLib, "getObject");
-
- if (factory) {
- ctx->mQdcmInfo.mQdcmMode = factory();
- } else {
- ctx->mQdcmInfo.mQdcmMode = NULL;
- ALOGE("QDCM LIbrary load failing!");
- }
-
- ALOGD_IF(QDCM_DEBUG, "QDCM LIbrary loaded successfully!");
-}
-
-static inline void unloadQdcmLibrary(hwc_context_t *ctx)
-{
- void (*destroy)(qmode::ModeManager*) = NULL;
-
- if (ctx->mQdcmInfo.mQdcmLib) {
- *(void **)&destroy = dlsym(ctx->mQdcmInfo.mQdcmLib, "deleteObject");
-
- if (destroy) {
- destroy(ctx->mQdcmInfo.mQdcmMode);
- ctx->mQdcmInfo.mQdcmMode = NULL;
- }
-
- dlclose(ctx->mQdcmInfo.mQdcmLib);
- ctx->mQdcmInfo.mQdcmLib = NULL;
- }
-}
-
-void qdcmInitContext(hwc_context_t *);
-void qdcmCloseContext(hwc_context_t *);
-void qdcmApplyDefaultAfterBootAnimationDone(hwc_context_t *);
-void qdcmCmdsHandler(hwc_context_t*, const Parcel*, Parcel*);
-
-}; // namespace qQdcm
-#endif // ANDROID_QDCM_H
diff --git a/msm8909/libhwcomposer/hwc_uevents.cpp b/msm8909/libhwcomposer/hwc_uevents.cpp
deleted file mode 100644
index 0c85a8db..00000000
--- a/msm8909/libhwcomposer/hwc_uevents.cpp
+++ /dev/null
@@ -1,243 +0,0 @@
-
-/*
- * Copyright (C) 2010 The Android Open Source Project
- * Copyright (C) 2012-14, The Linux Foundation. All rights reserved.
- *
- * Not a Contribution, Apache license notifications and license are
- * retained for attribution purposes only.
-
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#define UEVENT_DEBUG 0
-#include <hardware_legacy/uevent.h>
-#include <utils/Log.h>
-#include <sys/resource.h>
-#include <sys/prctl.h>
-#include <string.h>
-#include <stdlib.h>
-#include "hwc_utils.h"
-#include "hwc_fbupdate.h"
-#include "hwc_mdpcomp.h"
-#include "hwc_copybit.h"
-#include "comptype.h"
-#include "hdmi.h"
-#include "hwc_virtual.h"
-#include "mdp_version.h"
-using namespace overlay;
-namespace qhwc {
-#define HWC_UEVENT_SWITCH_STR "change@/devices/virtual/switch/"
-#define HWC_UEVENT_THREAD_NAME "hwcUeventThread"
-
-/* Parse uevent data for devices which we are interested */
-static int getConnectedDisplay(hwc_context_t* ctx, const char* strUdata)
-{
- int ret = -1;
- // Switch node for HDMI as PRIMARY/EXTERNAL
- if(strcasestr("change@/devices/virtual/switch/hdmi", strUdata)) {
- if (ctx->mHDMIDisplay->isHDMIPrimaryDisplay()) {
- ret = HWC_DISPLAY_PRIMARY;
- } else {
- ret = HWC_DISPLAY_EXTERNAL;
- }
- }
- return ret;
-}
-
-static bool getPanelResetStatus(hwc_context_t* ctx, const char* strUdata, int len)
-{
- const char* iter_str = strUdata;
- if (strcasestr("change@/devices/virtual/graphics/fb0", strUdata)) {
- while(((iter_str - strUdata) <= len) && (*iter_str)) {
- const char* pstr = strstr(iter_str, "PANEL_ALIVE=0");
- if (pstr != NULL) {
- ALOGI("%s: got change event in fb0 with PANEL_ALIVE=0",
- __FUNCTION__);
- ctx->mPanelResetStatus = true;
- return true;
- }
- iter_str += strlen(iter_str)+1;
- }
- }
- return false;
-}
-
-/* Parse uevent data for action requested for the display */
-static int getConnectedState(const char* strUdata, int len)
-{
- const char* iter_str = strUdata;
- while(((iter_str - strUdata) <= len) && (*iter_str)) {
- const char* pstr = strstr(iter_str, "SWITCH_STATE=");
- if (pstr != NULL) {
- return (atoi(pstr + strlen("SWITCH_STATE=")));
- }
- iter_str += strlen(iter_str)+1;
- }
- return -1;
-}
-
-static void handle_uevent(hwc_context_t* ctx, const char* udata, int len)
-{
- bool bpanelReset = getPanelResetStatus(ctx, udata, len);
- if (bpanelReset) {
- ctx->proc->invalidate(ctx->proc);
- return;
- }
-
- int dpy = getConnectedDisplay(ctx, udata);
- if(dpy < 0) {
- ALOGD_IF(UEVENT_DEBUG, "%s: Not disp Event ", __FUNCTION__);
- return;
- }
-
- int switch_state = getConnectedState(udata, len);
-
- ALOGE_IF(UEVENT_DEBUG,"%s: uevent received: %s switch state: %d",
- __FUNCTION__,udata, switch_state);
-
- switch(switch_state) {
- case EXTERNAL_OFFLINE:
- {
- /* Display not connected */
- if(!ctx->dpyAttr[dpy].connected){
- ALOGE_IF(UEVENT_DEBUG,"%s: Ignoring EXTERNAL_OFFLINE event"
- "for display: %d", __FUNCTION__, dpy);
- break;
- }
-
- ctx->mDrawLock.lock();
- handle_offline(ctx, dpy);
- ctx->mDrawLock.unlock();
-
- /* We need to send hotplug to SF only when we are disconnecting
- * HDMI as an external display. */
- if(dpy == HWC_DISPLAY_EXTERNAL) {
- ALOGE_IF(UEVENT_DEBUG,"%s:Sending EXTERNAL OFFLINE hotplug"
- "event", __FUNCTION__);
- ctx->proc->hotplug(ctx->proc, dpy, EXTERNAL_OFFLINE);
- }
- break;
- }
- case EXTERNAL_ONLINE:
- {
- /* Display already connected */
- if(ctx->dpyAttr[dpy].connected) {
- ALOGE_IF(UEVENT_DEBUG,"%s: Ignoring EXTERNAL_ONLINE event"
- "for display: %d", __FUNCTION__, dpy);
- break;
- }
-
- if (ctx->mHDMIDisplay->isHDMIPrimaryDisplay()) {
- ctx->mDrawLock.lock();
- handle_online(ctx, dpy);
- ctx->mDrawLock.unlock();
-
- ctx->proc->invalidate(ctx->proc);
- break;
- } else {
- ctx->mDrawLock.lock();
- //Force composition to give up resources like pipes and
- //close fb. For example if assertive display is going on,
- //fb2 could be open, thus connecting Layer Mixer#0 to
- //WriteBack module. If HDMI attempts to open fb1, the driver
- //will try to attach Layer Mixer#0 to HDMI INT, which will
- //fail, since Layer Mixer#0 is still connected to WriteBack.
- //This block will force composition to close fb2 in above
- //example.
- ctx->dpyAttr[dpy].isConfiguring = true;
- ctx->mDrawLock.unlock();
-
- ctx->proc->invalidate(ctx->proc);
- }
- //2 cycles for slower content
- usleep(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].vsync_period
- * 2 / 1000);
-
- if(isVDConnected(ctx)) {
- // Do not initiate WFD teardown if WFD architecture is based
- // on VDS mechanism.
- // WFD Stack listens to HDMI intent and initiates virtual
- // display teardown.
- // ToDo: Currently non-WFD Virtual display clients do not
- // involve HWC. If there is a change, we need to come up
- // with mechanism of how to address non-WFD Virtual display
- // clients + HDMI
- ctx->mWfdSyncLock.lock();
- ALOGD_IF(HWC_WFDDISPSYNC_LOG,
- "%s: Waiting for wfd-teardown to be signalled",
- __FUNCTION__);
- ctx->mWfdSyncLock.wait();
- ALOGD_IF(HWC_WFDDISPSYNC_LOG,
- "%s: Teardown signalled. Completed waiting in"
- "uevent thread", __FUNCTION__);
- ctx->mWfdSyncLock.unlock();
- }
- ctx->mHDMIDisplay->configure();
- ctx->mHDMIDisplay->activateDisplay();
-
- ctx->mDrawLock.lock();
- updateDisplayInfo(ctx, dpy);
- initCompositionResources(ctx, dpy);
- ctx->dpyAttr[dpy].isPause = false;
- ctx->dpyAttr[dpy].connected = true;
- ctx->dpyAttr[dpy].isConfiguring = true;
- ctx->mDrawLock.unlock();
-
- /* External display is HDMI */
- ALOGE_IF(UEVENT_DEBUG, "%s: Sending EXTERNAL ONLINE"
- "hotplug event", __FUNCTION__);
- ctx->proc->hotplug(ctx->proc, dpy, EXTERNAL_ONLINE);
- break;
- }
- default:
- {
- ALOGE("%s: Invalid state to swtich:%d", __FUNCTION__, switch_state);
- break;
- }
- }
-}
-
-static void *uevent_loop(void *param)
-{
- int len = 0;
- static char udata[PAGE_SIZE];
- hwc_context_t * ctx = reinterpret_cast<hwc_context_t *>(param);
- char thread_name[64] = HWC_UEVENT_THREAD_NAME;
- prctl(PR_SET_NAME, (unsigned long) &thread_name, 0, 0, 0);
- setpriority(PRIO_PROCESS, 0, HAL_PRIORITY_URGENT_DISPLAY);
- if(!uevent_init()) {
- ALOGE("%s: failed to init uevent ",__FUNCTION__);
- return NULL;
- }
-
- while(1) {
- len = uevent_next_event(udata, (int)sizeof(udata) - 2);
- handle_uevent(ctx, udata, len);
- }
-
- return NULL;
-}
-
-void init_uevent_thread(hwc_context_t* ctx)
-{
- pthread_t uevent_thread;
- int ret;
-
- ALOGI("Initializing UEVENT Thread");
- ret = pthread_create(&uevent_thread, NULL, uevent_loop, (void*) ctx);
- if (ret) {
- ALOGE("%s: failed to create %s: %s", __FUNCTION__,
- HWC_UEVENT_THREAD_NAME, strerror(ret));
- }
-}
-
-}; //namespace
diff --git a/msm8909/libhwcomposer/hwc_utils.cpp b/msm8909/libhwcomposer/hwc_utils.cpp
deleted file mode 100644
index 3b320728..00000000
--- a/msm8909/libhwcomposer/hwc_utils.cpp
+++ /dev/null
@@ -1,2907 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- * Copyright (C) 2012-2014,2016, The Linux Foundation All rights reserved.
- *
- * Not a Contribution, Apache license notifications and license are retained
- * for attribution purposes only.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#define ATRACE_TAG (ATRACE_TAG_GRAPHICS | ATRACE_TAG_HAL)
-#define HWC_UTILS_DEBUG 0
-#include <math.h>
-#include <sys/ioctl.h>
-#include <linux/fb.h>
-#include <binder/IServiceManager.h>
-#include <EGL/egl.h>
-#include <cutils/properties.h>
-#include <utils/Trace.h>
-#include <gralloc_priv.h>
-#include <overlay.h>
-#include <overlayRotator.h>
-#include <overlayWriteback.h>
-#include "hwc_utils.h"
-#include "hwc_mdpcomp.h"
-#include "hwc_fbupdate.h"
-#include "hwc_ad.h"
-#include "mdp_version.h"
-#include "hwc_copybit.h"
-#include "hwc_dump_layers.h"
-#include "hdmi.h"
-#include "hwc_qclient.h"
-#include "QService.h"
-#include "comptype.h"
-#include "hwc_virtual.h"
-#include "qd_utils.h"
-#include "hwc_qdcm.h"
-#include <sys/sysinfo.h>
-#include <dlfcn.h>
-
-using namespace qClient;
-using namespace qService;
-using namespace android;
-using namespace overlay;
-using namespace overlay::utils;
-using namespace qQdcm;
-namespace ovutils = overlay::utils;
-
-#ifdef QTI_BSP
-
-#define EGL_GPU_HINT_1 0x32D0
-#define EGL_GPU_HINT_2 0x32D1
-
-#define EGL_GPU_LEVEL_0 0x0
-#define EGL_GPU_LEVEL_1 0x1
-#define EGL_GPU_LEVEL_2 0x2
-#define EGL_GPU_LEVEL_3 0x3
-#define EGL_GPU_LEVEL_4 0x4
-#define EGL_GPU_LEVEL_5 0x5
-
-#endif
-
-#define PROP_DEFAULT_APPBUFFER "hw.sf.app_buff_count"
-#define MAX_RAM_SIZE 512*1024*1024
-#define qHD_WIDTH 540
-
-
-namespace qhwc {
-
-// Std refresh rates for digital videos- 24p, 30p, 48p and 60p
-uint32_t stdRefreshRates[] = { 30, 24, 48, 60 };
-
-static uint32_t getFBformat(fb_var_screeninfo /*vinfo*/) {
- uint32_t fbformat = HAL_PIXEL_FORMAT_RGBA_8888;
-
-#ifdef GET_FRAMEBUFFER_FORMAT_FROM_HWC
- // Here, we are adding the formats that are supported by both GPU and MDP.
- // The formats that fall in this category are RGBA_8888, RGB_565, RGB_888
- switch(vinfo.bits_per_pixel) {
- case 16:
- fbformat = HAL_PIXEL_FORMAT_RGB_565;
- break;
- case 24:
- if ((vinfo.transp.offset == 0) && (vinfo.transp.length == 0))
- fbformat = HAL_PIXEL_FORMAT_RGB_888;
- break;
- case 32:
- if ((vinfo.red.offset == 0) && (vinfo.green.offset == 8) &&
- (vinfo.blue.offset == 16) && (vinfo.transp.offset == 24))
- fbformat = HAL_PIXEL_FORMAT_RGBA_8888;
- break;
- default:
- fbformat = HAL_PIXEL_FORMAT_RGBA_8888;
- }
-#endif
- return fbformat;
-}
-
-bool isValidResolution(hwc_context_t *ctx, uint32_t xres, uint32_t yres)
-{
- return !((xres > qdutils::MDPVersion::getInstance().getMaxMixerWidth() &&
- !isDisplaySplit(ctx, HWC_DISPLAY_PRIMARY)) ||
- (xres < MIN_DISPLAY_XRES || yres < MIN_DISPLAY_YRES));
-}
-
-void changeResolution(hwc_context_t *ctx, int xres_orig, int yres_orig,
- int width, int height) {
- //Store original display resolution.
- ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres_new = xres_orig;
- ctx->dpyAttr[HWC_DISPLAY_PRIMARY].yres_new = yres_orig;
- ctx->dpyAttr[HWC_DISPLAY_PRIMARY].customFBSize = false;
- char property[PROPERTY_VALUE_MAX] = {'\0'};
- char *yptr = NULL;
- if (property_get("debug.hwc.fbsize", property, NULL) > 0) {
- yptr = strcasestr(property,"x");
- if(yptr) {
- int xres_new = atoi(property);
- int yres_new = atoi(yptr + 1);
- if (isValidResolution(ctx,xres_new,yres_new) &&
- xres_new != xres_orig && yres_new != yres_orig) {
- ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres_new = xres_new;
- ctx->dpyAttr[HWC_DISPLAY_PRIMARY].yres_new = yres_new;
- ctx->dpyAttr[HWC_DISPLAY_PRIMARY].customFBSize = true;
-
- //Caluculate DPI according to changed resolution.
- float xdpi = ((float)xres_new * 25.4f) / (float)width;
- float ydpi = ((float)yres_new * 25.4f) / (float)height;
- ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xdpi = xdpi;
- ctx->dpyAttr[HWC_DISPLAY_PRIMARY].ydpi = ydpi;
- }
- }
- }
-}
-
-// Initialize hdmi display attributes based on
-// hdmi display class state
-void updateDisplayInfo(hwc_context_t* ctx, int dpy) {
- struct fb_var_screeninfo info;
-
- if (ioctl(ctx->mHDMIDisplay->getFd(), FBIOGET_VSCREENINFO, &info) == -1) {
- ALOGE("%s:Error in ioctl FBIOGET_VSCREENINFO: %s",
- __FUNCTION__, strerror(errno));
- }
-
- ctx->dpyAttr[dpy].fbformat = getFBformat(info);
- ctx->dpyAttr[dpy].fd = ctx->mHDMIDisplay->getFd();
- ctx->dpyAttr[dpy].xres = ctx->mHDMIDisplay->getWidth();
- ctx->dpyAttr[dpy].yres = ctx->mHDMIDisplay->getHeight();
- ctx->dpyAttr[dpy].mMDPScalingMode = ctx->mHDMIDisplay->getMDPScalingMode();
- ctx->dpyAttr[dpy].vsync_period = ctx->mHDMIDisplay->getVsyncPeriod();
- ctx->mViewFrame[dpy].left = 0;
- ctx->mViewFrame[dpy].top = 0;
- ctx->mViewFrame[dpy].right = ctx->dpyAttr[dpy].xres;
- ctx->mViewFrame[dpy].bottom = ctx->dpyAttr[dpy].yres;
-}
-
-// Reset hdmi display attributes and list stats structures
-void resetDisplayInfo(hwc_context_t* ctx, int dpy) {
- memset(&(ctx->dpyAttr[dpy]), 0, sizeof(ctx->dpyAttr[dpy]));
- memset(&(ctx->listStats[dpy]), 0, sizeof(ctx->listStats[dpy]));
- // We reset the fd to -1 here but External display class is responsible
- // for it when the display is disconnected. This is handled as part of
- // EXTERNAL_OFFLINE event.
- ctx->dpyAttr[dpy].fd = -1;
-}
-
-// Initialize composition resources
-void initCompositionResources(hwc_context_t* ctx, int dpy) {
- ctx->mFBUpdate[dpy] = IFBUpdate::getObject(ctx, dpy);
- ctx->mMDPComp[dpy] = MDPComp::getObject(ctx, dpy);
-}
-
-void destroyCompositionResources(hwc_context_t* ctx, int dpy) {
- if(ctx->mFBUpdate[dpy]) {
- delete ctx->mFBUpdate[dpy];
- ctx->mFBUpdate[dpy] = NULL;
- }
- if(ctx->mMDPComp[dpy]) {
- delete ctx->mMDPComp[dpy];
- ctx->mMDPComp[dpy] = NULL;
- }
-}
-
-static int openFramebufferDevice(hwc_context_t *ctx)
-{
- struct fb_fix_screeninfo finfo;
- struct fb_var_screeninfo info;
-
- int fb_fd = openFb(HWC_DISPLAY_PRIMARY);
- if(fb_fd < 0) {
- ALOGE("%s: Error Opening FB : %s", __FUNCTION__, strerror(errno));
- return -errno;
- }
-
- if (ioctl(fb_fd, FBIOGET_VSCREENINFO, &info) == -1) {
- ALOGE("%s:Error in ioctl FBIOGET_VSCREENINFO: %s", __FUNCTION__,
- strerror(errno));
- close(fb_fd);
- return -errno;
- }
-
- if (int(info.width) <= 0 || int(info.height) <= 0) {
- // the driver doesn't return that information
- // default to 160 dpi
- info.width = (int)(((float)info.xres * 25.4f)/160.0f + 0.5f);
- info.height = (int)(((float)info.yres * 25.4f)/160.0f + 0.5f);
- }
-
- float xdpi = ((float)info.xres * 25.4f) / (float)info.width;
- float ydpi = ((float)info.yres * 25.4f) / (float)info.height;
-
-#ifdef MSMFB_METADATA_GET
- struct msmfb_metadata metadata;
- memset(&metadata, 0 , sizeof(metadata));
- metadata.op = metadata_op_frame_rate;
-
- if (ioctl(fb_fd, MSMFB_METADATA_GET, &metadata) == -1) {
- ALOGE("%s:Error retrieving panel frame rate: %s", __FUNCTION__,
- strerror(errno));
- close(fb_fd);
- return -errno;
- }
-
- float fps = (float)metadata.data.panel_frame_rate;
-#else
- //XXX: Remove reserved field usage on all baselines
- //The reserved[3] field is used to store FPS by the driver.
- float fps = info.reserved[3] & 0xFF;
-#endif
-
- if (ioctl(fb_fd, FBIOGET_FSCREENINFO, &finfo) == -1) {
- ALOGE("%s:Error in ioctl FBIOGET_FSCREENINFO: %s", __FUNCTION__,
- strerror(errno));
- close(fb_fd);
- return -errno;
- }
-
- ctx->dpyAttr[HWC_DISPLAY_PRIMARY].fd = fb_fd;
- //xres, yres may not be 32 aligned
- ctx->dpyAttr[HWC_DISPLAY_PRIMARY].stride = finfo.line_length /(info.xres/8);
- ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres = info.xres;
- ctx->dpyAttr[HWC_DISPLAY_PRIMARY].yres = info.yres;
- ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xdpi = xdpi;
- ctx->dpyAttr[HWC_DISPLAY_PRIMARY].ydpi = ydpi;
- ctx->dpyAttr[HWC_DISPLAY_PRIMARY].refreshRate = (uint32_t)fps;
- ctx->dpyAttr[HWC_DISPLAY_PRIMARY].dynRefreshRate = (uint32_t)fps;
- ctx->dpyAttr[HWC_DISPLAY_PRIMARY].vsync_period =
- (uint32_t)(1000000000l / fps);
- ctx->dpyAttr[HWC_DISPLAY_PRIMARY].fbformat = getFBformat(info);
-
- //To change resolution of primary display
- changeResolution(ctx, info.xres, info.yres, info.width, info.height);
-
- //Unblank primary on first boot
- if(ioctl(fb_fd, FBIOBLANK,FB_BLANK_UNBLANK) < 0) {
- ALOGE("%s: Failed to unblank display", __FUNCTION__);
- return -errno;
- }
- ctx->dpyAttr[HWC_DISPLAY_PRIMARY].isActive = true;
-
- return 0;
-}
-
-static void changeDefaultAppBufferCount() {
- struct sysinfo info;
- unsigned long int ramSize = 0;
- if (!sysinfo(&info)) {
- ramSize = info.totalram ;
- }
- int fb_fd = -1;
- struct fb_var_screeninfo sInfo ={0};
- fb_fd = open("/dev/graphics/fb0", O_RDONLY);
- if (fb_fd >=0) {
- ioctl(fb_fd, FBIOGET_VSCREENINFO, &sInfo);
- close(fb_fd);
- }
- if ((ramSize && ramSize < MAX_RAM_SIZE) &&
- (sInfo.xres && sInfo.xres <= qHD_WIDTH )) {
- property_set(PROP_DEFAULT_APPBUFFER, "3");
- }
-}
-
-void initContext(hwc_context_t *ctx)
-{
- overlay::Overlay::initOverlay();
- ctx->mHDMIDisplay = new HDMIDisplay();
- uint32_t priW = 0, priH = 0;
- // 1. HDMI as Primary
- // -If HDMI cable is connected, read display configs from edid data
- // -If HDMI cable is not connected then use default data in vscreeninfo
- // 2. HDMI as External
- // -Initialize HDMI class for use with external display
- // -Use vscreeninfo to populate display configs
- if(ctx->mHDMIDisplay->isHDMIPrimaryDisplay()) {
- int connected = ctx->mHDMIDisplay->getConnectedState();
- if(connected == 1) {
- ctx->mHDMIDisplay->configure();
- updateDisplayInfo(ctx, HWC_DISPLAY_PRIMARY);
- ctx->dpyAttr[HWC_DISPLAY_PRIMARY].connected = true;
- } else {
- openFramebufferDevice(ctx);
- ctx->dpyAttr[HWC_DISPLAY_PRIMARY].connected = false;
- }
- } else {
- openFramebufferDevice(ctx);
- ctx->dpyAttr[HWC_DISPLAY_PRIMARY].connected = true;
- // Send the primary resolution to the hdmi display class
- // to be used for MDP scaling functionality
- priW = ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres;
- priH = ctx->dpyAttr[HWC_DISPLAY_PRIMARY].yres;
- ctx->mHDMIDisplay->setPrimaryAttributes(priW, priH);
- }
-
- char value[PROPERTY_VALUE_MAX];
- ctx->mMDP.version = qdutils::MDPVersion::getInstance().getMDPVersion();
- ctx->mMDP.hasOverlay = qdutils::MDPVersion::getInstance().hasOverlay();
- ctx->mMDP.panel = qdutils::MDPVersion::getInstance().getPanelType();
- ctx->mOverlay = overlay::Overlay::getInstance();
- ctx->mRotMgr = RotMgr::getInstance();
-
- //default_app_buffer for ferrum
- if (ctx->mMDP.version == qdutils::MDP_V3_0_5) {
- changeDefaultAppBufferCount();
- }
- // Initialize composition objects for the primary display
- initCompositionResources(ctx, HWC_DISPLAY_PRIMARY);
-
- // Check if the target supports copybit compostion (dyn/mdp) to
- // decide if we need to open the copybit module.
- int compositionType =
- qdutils::QCCompositionType::getInstance().getCompositionType();
-
- // Only MDP copybit is used
- if ((compositionType & (qdutils::COMPOSITION_TYPE_DYN |
- qdutils::COMPOSITION_TYPE_MDP)) &&
- ((qdutils::MDPVersion::getInstance().getMDPVersion() ==
- qdutils::MDP_V3_0_4) ||
- (qdutils::MDPVersion::getInstance().getMDPVersion() ==
- qdutils::MDP_V3_0_5))) {
- ctx->mCopyBit[HWC_DISPLAY_PRIMARY] = new CopyBit(ctx,
- HWC_DISPLAY_PRIMARY);
- }
-
- ctx->mHWCVirtual = new HWCVirtualVDS();
- ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].isActive = false;
- ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].connected = false;
- ctx->dpyAttr[HWC_DISPLAY_VIRTUAL].isActive = false;
- ctx->dpyAttr[HWC_DISPLAY_VIRTUAL].connected = false;
- ctx->dpyAttr[HWC_DISPLAY_PRIMARY].mMDPScalingMode= false;
- ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].mMDPScalingMode = false;
- ctx->dpyAttr[HWC_DISPLAY_VIRTUAL].mMDPScalingMode = false;
-
- //Initialize the primary display viewFrame info
- ctx->mViewFrame[HWC_DISPLAY_PRIMARY].left = 0;
- ctx->mViewFrame[HWC_DISPLAY_PRIMARY].top = 0;
- ctx->mViewFrame[HWC_DISPLAY_PRIMARY].right =
- (int)ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres;
- ctx->mViewFrame[HWC_DISPLAY_PRIMARY].bottom =
- (int)ctx->dpyAttr[HWC_DISPLAY_PRIMARY].yres;
-
- for (uint32_t i = 0; i < HWC_NUM_DISPLAY_TYPES; i++) {
- ctx->mHwcDebug[i] = new HwcDebug(i);
- ctx->mLayerRotMap[i] = new LayerRotMap();
- ctx->mAnimationState[i] = ANIMATION_STOPPED;
- ctx->dpyAttr[i].mActionSafePresent = false;
- ctx->dpyAttr[i].mAsWidthRatio = 0;
- ctx->dpyAttr[i].mAsHeightRatio = 0;
- }
-
- for (uint32_t i = 0; i < HWC_NUM_DISPLAY_TYPES; i++) {
- ctx->mPrevHwLayerCount[i] = 0;
- }
-
- MDPComp::init(ctx);
- ctx->mAD = new AssertiveDisplay(ctx);
-
- ctx->vstate.enable = false;
- ctx->vstate.fakevsync = false;
- ctx->mExtOrientation = 0;
- ctx->numActiveDisplays = 1;
-
- //Right now hwc starts the service but anybody could do it, or it could be
- //independent process as well.
- QService::init();
- sp<IQClient> client = new QClient(ctx);
- android::sp<qService::IQService> qservice_sp = interface_cast<IQService>(
- defaultServiceManager()->getService(
- String16("display.qservice")));
- if (qservice_sp.get()) {
- qservice_sp->connect(client);
- } else {
- ALOGE("%s: Failed to acquire service pointer", __FUNCTION__);
- return ;
- }
-
- // Initialize device orientation to its default orientation
- ctx->deviceOrientation = 0;
- ctx->mBufferMirrorMode = false;
-
- property_get("sys.hwc.windowbox_aspect_ratio_tolerance", value, "0");
- ctx->mAspectRatioToleranceLevel = (((float)atoi(value)) / 100.0f);
-
- ctx->enableABC = false;
- property_get("debug.sf.hwc.canUseABC", value, "0");
- ctx->enableABC = atoi(value) ? true : false;
-
- // Initializing boot anim completed check to false
- ctx->mBootAnimCompleted = false;
-
- // Initialize gpu perfomance hint related parameters
-#ifdef QTI_BSP
- ctx->mEglLib = NULL;
- ctx->mpfn_eglGpuPerfHintQCOM = NULL;
- ctx->mpfn_eglGetCurrentDisplay = NULL;
- ctx->mpfn_eglGetCurrentContext = NULL;
- ctx->mGPUHintInfo.mGpuPerfModeEnable = false;
- ctx->mGPUHintInfo.mEGLDisplay = NULL;
- ctx->mGPUHintInfo.mEGLContext = NULL;
- ctx->mGPUHintInfo.mCompositionState = COMPOSITION_STATE_MDP;
- ctx->mGPUHintInfo.mCurrGPUPerfMode = EGL_GPU_LEVEL_0;
- if(property_get("sys.hwc.gpu_perf_mode", value, "0") > 0) {
- int val = atoi(value);
- if(val > 0 && loadEglLib(ctx)) {
- ctx->mGPUHintInfo.mGpuPerfModeEnable = true;
- }
- }
-#endif
- // Read the system property to determine if windowboxing feature is enabled.
- ctx->mWindowboxFeature = false;
- if(property_get("sys.hwc.windowbox_feature", value, "false")
- && !strcmp(value, "true")) {
- ctx->mWindowboxFeature = true;
- }
-
- ctx->mUseMetaDataRefreshRate = true;
- if(property_get("persist.metadata_dynfps.disable", value, "false")
- && !strcmp(value, "true")) {
- ctx->mUseMetaDataRefreshRate = false;
- }
-
- memset(&(ctx->mPtorInfo), 0, sizeof(ctx->mPtorInfo));
-
- //init qdcm service related context.
- qdcmInitContext(ctx);
-
- ALOGI("Initializing Qualcomm Hardware Composer");
- ALOGI("MDP version: %d", ctx->mMDP.version);
-}
-
-void closeContext(hwc_context_t *ctx)
-{
- //close qdcm service related context.
- qdcmCloseContext(ctx);
-
- if(ctx->mOverlay) {
- delete ctx->mOverlay;
- ctx->mOverlay = NULL;
- }
-
- if(ctx->mRotMgr) {
- delete ctx->mRotMgr;
- ctx->mRotMgr = NULL;
- }
-
- for(int i = 0; i < HWC_NUM_DISPLAY_TYPES; i++) {
- if(ctx->mCopyBit[i]) {
- delete ctx->mCopyBit[i];
- ctx->mCopyBit[i] = NULL;
- }
- }
-
- if(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].fd) {
- close(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].fd);
- ctx->dpyAttr[HWC_DISPLAY_PRIMARY].fd = -1;
- }
-
- if(ctx->mHDMIDisplay) {
- delete ctx->mHDMIDisplay;
- ctx->mHDMIDisplay = NULL;
- }
-
- for(int i = 0; i < HWC_NUM_DISPLAY_TYPES; i++) {
- destroyCompositionResources(ctx, i);
-
- if(ctx->mHwcDebug[i]) {
- delete ctx->mHwcDebug[i];
- ctx->mHwcDebug[i] = NULL;
- }
- if(ctx->mLayerRotMap[i]) {
- delete ctx->mLayerRotMap[i];
- ctx->mLayerRotMap[i] = NULL;
- }
- }
- if(ctx->mHWCVirtual) {
- delete ctx->mHWCVirtual;
- ctx->mHWCVirtual = NULL;
- }
- if(ctx->mAD) {
- delete ctx->mAD;
- ctx->mAD = NULL;
- }
-
-#ifdef QTI_BSP
- ctx->mpfn_eglGpuPerfHintQCOM = NULL;
- ctx->mpfn_eglGetCurrentDisplay = NULL;
- ctx->mpfn_eglGetCurrentContext = NULL;
- if(ctx->mEglLib) {
- dlclose(ctx->mEglLib);
- ctx->mEglLib = NULL;
- }
-#endif
-}
-
-uint32_t getRefreshRate(hwc_context_t* ctx, uint32_t requestedRefreshRate) {
-
- qdutils::MDPVersion& mdpHw = qdutils::MDPVersion::getInstance();
- int dpy = HWC_DISPLAY_PRIMARY;
- uint32_t defaultRefreshRate = ctx->dpyAttr[dpy].refreshRate;
- uint32_t rate = defaultRefreshRate;
-
- if(!requestedRefreshRate)
- return defaultRefreshRate;
-
- uint32_t maxNumIterations =
- (uint32_t)ceil(
- (float)mdpHw.getMaxFpsSupported()/
- (float)requestedRefreshRate);
-
- for(uint32_t i = 1; i <= maxNumIterations; i++) {
- rate = i * roundOff(requestedRefreshRate);
- if(rate < mdpHw.getMinFpsSupported()) {
- continue;
- } else if((rate >= mdpHw.getMinFpsSupported() &&
- rate <= mdpHw.getMaxFpsSupported())) {
- break;
- } else {
- rate = defaultRefreshRate;
- break;
- }
- }
- return rate;
-}
-
-//Helper to roundoff the refreshrates to the std refresh-rates
-uint32_t roundOff(uint32_t refreshRate) {
- int count = (int) (sizeof(stdRefreshRates)/sizeof(stdRefreshRates[0]));
- uint32_t rate = refreshRate;
- for(int i=0; i< count; i++) {
- if(abs((int)(stdRefreshRates[i] - refreshRate)) < 2) {
- // Most likely used for video, the fps can fluctuate
- // Ex: b/w 29 and 30 for 30 fps clip
- rate = stdRefreshRates[i];
- break;
- }
- }
- return rate;
-}
-
-//Helper func to set the dyn fps
-void setRefreshRate(hwc_context_t* ctx, int dpy, uint32_t refreshRate) {
- //Update only if different
- if(!ctx || refreshRate == ctx->dpyAttr[dpy].dynRefreshRate)
- return;
- const int fbNum = Overlay::getFbForDpy(dpy);
- char sysfsPath[qdutils::MAX_SYSFS_FILE_PATH];
- snprintf (sysfsPath, sizeof(sysfsPath),
- "/sys/class/graphics/fb%d/dynamic_fps", fbNum);
-
- int fd = open(sysfsPath, O_WRONLY);
- if(fd >= 0) {
- char str[64];
- snprintf(str, sizeof(str), "%d", refreshRate);
- ssize_t ret = write(fd, str, strlen(str));
- if(ret < 0) {
- ALOGE("%s: Failed to write %d with error %s",
- __FUNCTION__, refreshRate, strerror(errno));
- } else {
- ctx->dpyAttr[dpy].dynRefreshRate = refreshRate;
- ALOGD_IF(HWC_UTILS_DEBUG, "%s: Wrote %d to dynamic_fps",
- __FUNCTION__, refreshRate);
- }
- close(fd);
- } else {
- ALOGE("%s: Failed to open %s with error %s", __FUNCTION__, sysfsPath,
- strerror(errno));
- }
-}
-
-void dumpsys_log(android::String8& buf, const char* fmt, ...)
-{
- va_list varargs;
- va_start(varargs, fmt);
- buf.appendFormatV(fmt, varargs);
- va_end(varargs);
-}
-
-int getExtOrientation(hwc_context_t* ctx) {
- int extOrient = ctx->mExtOrientation;
- if(ctx->mBufferMirrorMode)
- extOrient = getMirrorModeOrientation(ctx);
- return extOrient;
-}
-
-/* Calculates the destination position based on the action safe rectangle */
-void getActionSafePosition(hwc_context_t *ctx, int dpy, hwc_rect_t& rect) {
- // Position
- int x = rect.left, y = rect.top;
- int w = rect.right - rect.left;
- int h = rect.bottom - rect.top;
-
- if(!ctx->dpyAttr[dpy].mActionSafePresent)
- return;
- // Read action safe properties
- int asWidthRatio = ctx->dpyAttr[dpy].mAsWidthRatio;
- int asHeightRatio = ctx->dpyAttr[dpy].mAsHeightRatio;
-
- float wRatio = 1.0;
- float hRatio = 1.0;
- float xRatio = 1.0;
- float yRatio = 1.0;
-
- uint32_t fbWidth = ctx->dpyAttr[dpy].xres;
- uint32_t fbHeight = ctx->dpyAttr[dpy].yres;
- if(ctx->dpyAttr[dpy].mMDPScalingMode) {
- // if MDP scaling mode is enabled for external, need to query
- // the actual width and height, as that is the physical w & h
- ctx->mHDMIDisplay->getAttributes(fbWidth, fbHeight);
- }
-
-
- // Since external is rotated 90, need to swap width/height
- int extOrient = getExtOrientation(ctx);
-
- if(extOrient & HWC_TRANSFORM_ROT_90)
- swap(fbWidth, fbHeight);
-
- float asX = 0;
- float asY = 0;
- float asW = (float)fbWidth;
- float asH = (float)fbHeight;
-
- // based on the action safe ratio, get the Action safe rectangle
- asW = ((float)fbWidth * (1.0f - (float)asWidthRatio / 100.0f));
- asH = ((float)fbHeight * (1.0f - (float)asHeightRatio / 100.0f));
- asX = ((float)fbWidth - asW) / 2;
- asY = ((float)fbHeight - asH) / 2;
-
- // calculate the position ratio
- xRatio = (float)x/(float)fbWidth;
- yRatio = (float)y/(float)fbHeight;
- wRatio = (float)w/(float)fbWidth;
- hRatio = (float)h/(float)fbHeight;
-
- //Calculate the position...
- x = int((xRatio * asW) + asX);
- y = int((yRatio * asH) + asY);
- w = int(wRatio * asW);
- h = int(hRatio * asH);
-
- // Convert it back to hwc_rect_t
- rect.left = x;
- rect.top = y;
- rect.right = w + rect.left;
- rect.bottom = h + rect.top;
-
- return;
-}
-
-// This function gets the destination position for Seconday display
-// based on the position and aspect ratio with orientation
-void getAspectRatioPosition(hwc_context_t* ctx, int dpy, int extOrientation,
- hwc_rect_t& inRect, hwc_rect_t& outRect) {
- // Physical display resolution
- float fbWidth = (float)ctx->dpyAttr[dpy].xres;
- float fbHeight = (float)ctx->dpyAttr[dpy].yres;
- //display position(x,y,w,h) in correct aspectratio after rotation
- int xPos = 0;
- int yPos = 0;
- float width = fbWidth;
- float height = fbHeight;
- // Width/Height used for calculation, after rotation
- float actualWidth = fbWidth;
- float actualHeight = fbHeight;
-
- float wRatio = 1.0;
- float hRatio = 1.0;
- float xRatio = 1.0;
- float yRatio = 1.0;
- hwc_rect_t rect = {0, 0, (int)fbWidth, (int)fbHeight};
-
- Dim inPos(inRect.left, inRect.top, inRect.right - inRect.left,
- inRect.bottom - inRect.top);
- Dim outPos(outRect.left, outRect.top, outRect.right - outRect.left,
- outRect.bottom - outRect.top);
-
- Whf whf((uint32_t)fbWidth, (uint32_t)fbHeight, 0);
- eTransform extorient = static_cast<eTransform>(extOrientation);
- // To calculate the destination co-ordinates in the new orientation
- preRotateSource(extorient, whf, inPos);
-
- if(extOrientation & HAL_TRANSFORM_ROT_90) {
- // Swap width/height for input position
- swapWidthHeight(actualWidth, actualHeight);
- qdutils::getAspectRatioPosition((int)fbWidth, (int)fbHeight,
- (int)actualWidth, (int)actualHeight, rect);
- xPos = rect.left;
- yPos = rect.top;
- width = float(rect.right - rect.left);
- height = float(rect.bottom - rect.top);
- }
- xRatio = (float)((float)inPos.x/actualWidth);
- yRatio = (float)((float)inPos.y/actualHeight);
- wRatio = (float)((float)inPos.w/actualWidth);
- hRatio = (float)((float)inPos.h/actualHeight);
-
- //Calculate the pos9ition...
- outPos.x = uint32_t((xRatio * width) + (float)xPos);
- outPos.y = uint32_t((yRatio * height) + (float)yPos);
- outPos.w = uint32_t(wRatio * width);
- outPos.h = uint32_t(hRatio * height);
- ALOGD_IF(HWC_UTILS_DEBUG, "%s: Calculated AspectRatio Position: x = %d,"
- "y = %d w = %d h = %d", __FUNCTION__, outPos.x, outPos.y,
- outPos.w, outPos.h);
-
- // For sidesync, the dest fb will be in portrait orientation, and the crop
- // will be updated to avoid the black side bands, and it will be upscaled
- // to fit the dest RB, so recalculate
- // the position based on the new width and height
- if ((extOrientation & HWC_TRANSFORM_ROT_90) &&
- isOrientationPortrait(ctx)) {
- hwc_rect_t r = {0, 0, 0, 0};
- //Calculate the position
- xRatio = (float)(outPos.x - xPos)/width;
- // GetaspectRatio -- tricky to get the correct aspect ratio
- // But we need to do this.
- qdutils::getAspectRatioPosition((int)width, (int)height,
- (int)width,(int)height, r);
- xPos = r.left;
- yPos = r.top;
- float tempHeight = float(r.bottom - r.top);
- yRatio = (float)yPos/height;
- wRatio = (float)outPos.w/width;
- hRatio = tempHeight/height;
-
- //Map the coordinates back to Framebuffer domain
- outPos.x = uint32_t(xRatio * fbWidth);
- outPos.y = uint32_t(yRatio * fbHeight);
- outPos.w = uint32_t(wRatio * fbWidth);
- outPos.h = uint32_t(hRatio * fbHeight);
-
- ALOGD_IF(HWC_UTILS_DEBUG, "%s: Calculated AspectRatio for device in"
- "portrait: x = %d,y = %d w = %d h = %d", __FUNCTION__,
- outPos.x, outPos.y,
- outPos.w, outPos.h);
- }
- if(ctx->dpyAttr[dpy].mMDPScalingMode) {
- uint32_t extW = 0, extH = 0;
- if(dpy == HWC_DISPLAY_EXTERNAL) {
- ctx->mHDMIDisplay->getAttributes(extW, extH);
- } else if(dpy == HWC_DISPLAY_VIRTUAL) {
- extW = ctx->mHWCVirtual->getScalingWidth();
- extH = ctx->mHWCVirtual->getScalingHeight();
- }
- ALOGD_IF(HWC_UTILS_DEBUG, "%s: Scaling mode extW=%d extH=%d",
- __FUNCTION__, extW, extH);
-
- fbWidth = (float)ctx->dpyAttr[dpy].xres;
- fbHeight = (float)ctx->dpyAttr[dpy].yres;
- //Calculate the position...
- xRatio = (float)outPos.x/fbWidth;
- yRatio = (float)outPos.y/fbHeight;
- wRatio = (float)outPos.w/fbWidth;
- hRatio = (float)outPos.h/fbHeight;
-
- outPos.x = uint32_t(xRatio * (float)extW);
- outPos.y = uint32_t(yRatio * (float)extH);
- outPos.w = uint32_t(wRatio * (float)extW);
- outPos.h = uint32_t(hRatio * (float)extH);
- }
- // Convert Dim to hwc_rect_t
- outRect.left = outPos.x;
- outRect.top = outPos.y;
- outRect.right = outPos.x + outPos.w;
- outRect.bottom = outPos.y + outPos.h;
-
- return;
-}
-
-bool isPrimaryPortrait(hwc_context_t *ctx) {
- int fbWidth = ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres;
- int fbHeight = ctx->dpyAttr[HWC_DISPLAY_PRIMARY].yres;
- if(fbWidth < fbHeight) {
- return true;
- }
- return false;
-}
-
-bool isOrientationPortrait(hwc_context_t *ctx) {
- if(isPrimaryPortrait(ctx)) {
- return !(ctx->deviceOrientation & 0x1);
- }
- return (ctx->deviceOrientation & 0x1);
-}
-
-void calcExtDisplayPosition(hwc_context_t *ctx,
- private_handle_t *hnd,
- int dpy,
- hwc_rect_t& sourceCrop,
- hwc_rect_t& displayFrame,
- int& transform,
- ovutils::eTransform& orient) {
- // Swap width and height when there is a 90deg transform
- int extOrient = getExtOrientation(ctx);
- if(dpy && ctx->mOverlay->isUIScalingOnExternalSupported()) {
- if(!isYuvBuffer(hnd)) {
- if(extOrient & HWC_TRANSFORM_ROT_90) {
- int dstWidth = ctx->dpyAttr[dpy].xres;
- int dstHeight = ctx->dpyAttr[dpy].yres;;
- int srcWidth = ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres;
- int srcHeight = ctx->dpyAttr[HWC_DISPLAY_PRIMARY].yres;
- if(!isPrimaryPortrait(ctx)) {
- swap(srcWidth, srcHeight);
- } // Get Aspect Ratio for external
- qdutils::getAspectRatioPosition(dstWidth, dstHeight, srcWidth,
- srcHeight, displayFrame);
- // Crop - this is needed, because for sidesync, the dest fb will
- // be in portrait orientation, so update the crop to not show the
- // black side bands.
- if (isOrientationPortrait(ctx)) {
- sourceCrop = displayFrame;
- displayFrame.left = 0;
- displayFrame.top = 0;
- displayFrame.right = dstWidth;
- displayFrame.bottom = dstHeight;
- }
- }
- if(ctx->dpyAttr[dpy].mMDPScalingMode) {
- uint32_t extW = 0, extH = 0;
- // if MDP scaling mode is enabled, map the co-ordinates to new
- // domain(downscaled)
- float fbWidth = (float)ctx->dpyAttr[dpy].xres;
- float fbHeight = (float)ctx->dpyAttr[dpy].yres;
- // query MDP configured attributes
- if(dpy == HWC_DISPLAY_EXTERNAL) {
- ctx->mHDMIDisplay->getAttributes(extW, extH);
- } else if(dpy == HWC_DISPLAY_VIRTUAL) {
- extW = ctx->mHWCVirtual->getScalingWidth();
- extH = ctx->mHWCVirtual->getScalingHeight();
- }
- ALOGD_IF(HWC_UTILS_DEBUG, "%s: Scaling mode extW=%d extH=%d",
- __FUNCTION__, extW, extH);
-
- //Calculate the ratio...
- float wRatio = ((float)extW)/fbWidth;
- float hRatio = ((float)extH)/fbHeight;
-
- //convert Dim to hwc_rect_t
- displayFrame.left = int(wRatio*(float)displayFrame.left);
- displayFrame.top = int(hRatio*(float)displayFrame.top);
- displayFrame.right = int(wRatio*(float)displayFrame.right);
- displayFrame.bottom = int(hRatio*(float)displayFrame.bottom);
- ALOGD_IF(DEBUG_MDPDOWNSCALE, "Calculated external display frame"
- " for MDPDownscale feature [%d %d %d %d]",
- displayFrame.left, displayFrame.top,
- displayFrame.right, displayFrame.bottom);
- }
- }else {
- if(extOrient || ctx->dpyAttr[dpy].mMDPScalingMode) {
- getAspectRatioPosition(ctx, dpy, extOrient,
- displayFrame, displayFrame);
- }
- }
- // If there is a external orientation set, use that
- if(extOrient) {
- transform = extOrient;
- orient = static_cast<ovutils::eTransform >(extOrient);
- }
- // Calculate the actionsafe dimensions for External(dpy = 1 or 2)
- getActionSafePosition(ctx, dpy, displayFrame);
- }
-}
-
-/* Returns the orientation which needs to be set on External for
- * SideSync/Buffer Mirrormode
- */
-int getMirrorModeOrientation(hwc_context_t *ctx) {
- int extOrientation = 0;
- int deviceOrientation = ctx->deviceOrientation;
- if(!isPrimaryPortrait(ctx))
- deviceOrientation = (deviceOrientation + 1) % 4;
- if (deviceOrientation == 0)
- extOrientation = HWC_TRANSFORM_ROT_270;
- else if (deviceOrientation == 1)//90
- extOrientation = 0;
- else if (deviceOrientation == 2)//180
- extOrientation = HWC_TRANSFORM_ROT_90;
- else if (deviceOrientation == 3)//270
- extOrientation = HWC_TRANSFORM_FLIP_V | HWC_TRANSFORM_FLIP_H;
-
- return extOrientation;
-}
-
-/* Get External State names */
-const char* getExternalDisplayState(uint32_t external_state) {
- static const char* externalStates[EXTERNAL_MAXSTATES] = {0};
- externalStates[EXTERNAL_OFFLINE] = STR(EXTERNAL_OFFLINE);
- externalStates[EXTERNAL_ONLINE] = STR(EXTERNAL_ONLINE);
- externalStates[EXTERNAL_PAUSE] = STR(EXTERNAL_PAUSE);
- externalStates[EXTERNAL_RESUME] = STR(EXTERNAL_RESUME);
-
- if(external_state >= EXTERNAL_MAXSTATES) {
- return "EXTERNAL_INVALID";
- }
-
- return externalStates[external_state];
-}
-
-bool isDownscaleRequired(hwc_layer_1_t const* layer) {
- hwc_rect_t displayFrame = layer->displayFrame;
- hwc_rect_t sourceCrop = integerizeSourceCrop(layer->sourceCropf);
- int dst_w, dst_h, src_w, src_h;
- dst_w = displayFrame.right - displayFrame.left;
- dst_h = displayFrame.bottom - displayFrame.top;
- src_w = sourceCrop.right - sourceCrop.left;
- src_h = sourceCrop.bottom - sourceCrop.top;
-
- if(((src_w > dst_w) || (src_h > dst_h)))
- return true;
-
- return false;
-}
-bool needsScaling(hwc_layer_1_t const* layer) {
- int dst_w, dst_h, src_w, src_h;
- hwc_rect_t displayFrame = layer->displayFrame;
- hwc_rect_t sourceCrop = integerizeSourceCrop(layer->sourceCropf);
-
- dst_w = displayFrame.right - displayFrame.left;
- dst_h = displayFrame.bottom - displayFrame.top;
- src_w = sourceCrop.right - sourceCrop.left;
- src_h = sourceCrop.bottom - sourceCrop.top;
-
- if(((src_w != dst_w) || (src_h != dst_h)))
- return true;
-
- return false;
-}
-
-// Checks if layer needs scaling with split
-bool needsScalingWithSplit(hwc_context_t* ctx, hwc_layer_1_t const* layer,
- const int& dpy) {
-
- int src_width_l, src_height_l;
- int src_width_r, src_height_r;
- int dst_width_l, dst_height_l;
- int dst_width_r, dst_height_r;
- int hw_w = ctx->dpyAttr[dpy].xres;
- int hw_h = ctx->dpyAttr[dpy].yres;
- hwc_rect_t cropL, dstL, cropR, dstR;
- const int lSplit = getLeftSplit(ctx, dpy);
- hwc_rect_t sourceCrop = integerizeSourceCrop(layer->sourceCropf);
- hwc_rect_t displayFrame = layer->displayFrame;
- private_handle_t *hnd = (private_handle_t *)layer->handle;
-
- cropL = sourceCrop;
- dstL = displayFrame;
- hwc_rect_t scissorL = { 0, 0, lSplit, hw_h };
- scissorL = getIntersection(ctx->mViewFrame[dpy], scissorL);
- qhwc::calculate_crop_rects(cropL, dstL, scissorL, 0);
-
- cropR = sourceCrop;
- dstR = displayFrame;
- hwc_rect_t scissorR = { lSplit, 0, hw_w, hw_h };
- scissorR = getIntersection(ctx->mViewFrame[dpy], scissorR);
- qhwc::calculate_crop_rects(cropR, dstR, scissorR, 0);
-
- // Sanitize Crop to stitch
- sanitizeSourceCrop(cropL, cropR, hnd);
-
- // Calculate the left dst
- dst_width_l = dstL.right - dstL.left;
- dst_height_l = dstL.bottom - dstL.top;
- src_width_l = cropL.right - cropL.left;
- src_height_l = cropL.bottom - cropL.top;
-
- // check if there is any scaling on the left
- if(((src_width_l != dst_width_l) || (src_height_l != dst_height_l)))
- return true;
-
- // Calculate the right dst
- dst_width_r = dstR.right - dstR.left;
- dst_height_r = dstR.bottom - dstR.top;
- src_width_r = cropR.right - cropR.left;
- src_height_r = cropR.bottom - cropR.top;
-
- // check if there is any scaling on the right
- if(((src_width_r != dst_width_r) || (src_height_r != dst_height_r)))
- return true;
-
- return false;
-}
-
-bool isAlphaScaled(hwc_layer_1_t const* layer) {
- if(needsScaling(layer) && isAlphaPresent(layer)) {
- return true;
- }
- return false;
-}
-
-bool isAlphaPresent(hwc_layer_1_t const* layer) {
- private_handle_t *hnd = (private_handle_t *)layer->handle;
- if(hnd) {
- int format = hnd->format;
- switch(format) {
- case HAL_PIXEL_FORMAT_RGBA_8888:
- case HAL_PIXEL_FORMAT_BGRA_8888:
- // In any more formats with Alpha go here..
- return true;
- default : return false;
- }
- }
- return false;
-}
-
-bool isAlphaPresentinFB(hwc_context_t *ctx, int dpy) {
- switch(ctx->dpyAttr[dpy].fbformat) {
- case HAL_PIXEL_FORMAT_RGBA_8888:
- case HAL_PIXEL_FORMAT_BGRA_8888:
- return true;
- default : return false;
- }
- return false;
-}
-
-static void trimLayer(hwc_context_t *ctx, const int& dpy, const int& transform,
- hwc_rect_t& crop, hwc_rect_t& dst) {
- int hw_w = ctx->dpyAttr[dpy].xres;
- int hw_h = ctx->dpyAttr[dpy].yres;
- if(dst.left < 0 || dst.top < 0 ||
- dst.right > hw_w || dst.bottom > hw_h) {
- hwc_rect_t scissor = {0, 0, hw_w, hw_h };
- scissor = getIntersection(ctx->mViewFrame[dpy], scissor);
- qhwc::calculate_crop_rects(crop, dst, scissor, transform);
- }
-}
-
-static void trimList(hwc_context_t *ctx, hwc_display_contents_1_t *list,
- const int& dpy) {
- for(uint32_t i = 0; i < list->numHwLayers - 1; i++) {
- hwc_layer_1_t *layer = &list->hwLayers[i];
- hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);
- int transform = (list->hwLayers[i].flags & HWC_COLOR_FILL) ? 0 :
- list->hwLayers[i].transform;
- trimLayer(ctx, dpy,
- transform,
- (hwc_rect_t&)crop,
- (hwc_rect_t&)list->hwLayers[i].displayFrame);
- layer->sourceCropf.left = (float)crop.left;
- layer->sourceCropf.right = (float)crop.right;
- layer->sourceCropf.top = (float)crop.top;
- layer->sourceCropf.bottom = (float)crop.bottom;
- }
-}
-
-void setListStats(hwc_context_t *ctx,
- hwc_display_contents_1_t *list, int dpy) {
- const int prevYuvCount = ctx->listStats[dpy].yuvCount;
- memset(&ctx->listStats[dpy], 0, sizeof(ListStats));
- ctx->listStats[dpy].numAppLayers = (int)list->numHwLayers - 1;
- ctx->listStats[dpy].fbLayerIndex = (int)list->numHwLayers - 1;
- ctx->listStats[dpy].skipCount = 0;
- ctx->listStats[dpy].preMultipliedAlpha = false;
- ctx->listStats[dpy].isSecurePresent = false;
- ctx->listStats[dpy].yuvCount = 0;
- char property[PROPERTY_VALUE_MAX];
- ctx->listStats[dpy].isDisplayAnimating = false;
- ctx->listStats[dpy].secureUI = false;
- ctx->listStats[dpy].yuv4k2kCount = 0;
- ctx->dpyAttr[dpy].mActionSafePresent = isActionSafePresent(ctx, dpy);
- ctx->listStats[dpy].renderBufIndexforABC = -1;
- ctx->listStats[dpy].secureRGBCount = 0;
- ctx->listStats[dpy].refreshRateRequest = ctx->dpyAttr[dpy].refreshRate;
- uint32_t refreshRate = 0;
- qdutils::MDPVersion& mdpHw = qdutils::MDPVersion::getInstance();
-
- ctx->listStats[dpy].mAIVVideoMode = false;
- resetROI(ctx, dpy);
-
- trimList(ctx, list, dpy);
- optimizeLayerRects(list);
- for (size_t i = 0; i < (size_t)ctx->listStats[dpy].numAppLayers; i++) {
- hwc_layer_1_t const* layer = &list->hwLayers[i];
- private_handle_t *hnd = (private_handle_t *)layer->handle;
-
-#ifdef QTI_BSP
- // Window boxing feature is applicable obly for external display, So
- // enable mAIVVideoMode only for external display
- if(ctx->mWindowboxFeature && dpy && isAIVVideoLayer(layer)) {
- ctx->listStats[dpy].mAIVVideoMode = true;
- }
- if (layer->flags & HWC_SCREENSHOT_ANIMATOR_LAYER) {
- ctx->listStats[dpy].isDisplayAnimating = true;
- }
- if(isSecureDisplayBuffer(hnd)) {
- ctx->listStats[dpy].secureUI = true;
- }
-#endif
- // continue if number of app layers exceeds MAX_NUM_APP_LAYERS
- if(ctx->listStats[dpy].numAppLayers > MAX_NUM_APP_LAYERS)
- continue;
-
- //reset yuv indices
- ctx->listStats[dpy].yuvIndices[i] = -1;
- ctx->listStats[dpy].yuv4k2kIndices[i] = -1;
-
- if (isSecureBuffer(hnd)) {
- ctx->listStats[dpy].isSecurePresent = true;
- if(not isYuvBuffer(hnd)) {
- // cache secureRGB layer parameters like we cache for YUV layers
- int& secureRGBCount = ctx->listStats[dpy].secureRGBCount;
- ctx->listStats[dpy].secureRGBIndices[secureRGBCount] = (int)i;
- secureRGBCount++;
- }
- }
-
- if (isSkipLayer(&list->hwLayers[i])) {
- ctx->listStats[dpy].skipCount++;
- }
-
- if (UNLIKELY(isYuvBuffer(hnd))) {
- int& yuvCount = ctx->listStats[dpy].yuvCount;
- ctx->listStats[dpy].yuvIndices[yuvCount] = (int)i;
- yuvCount++;
-
- if(UNLIKELY(isYUVSplitNeeded(hnd))){
- int& yuv4k2kCount = ctx->listStats[dpy].yuv4k2kCount;
- ctx->listStats[dpy].yuv4k2kIndices[yuv4k2kCount] = (int)i;
- yuv4k2kCount++;
- }
- }
- if(layer->blending == HWC_BLENDING_PREMULT)
- ctx->listStats[dpy].preMultipliedAlpha = true;
-
-#ifdef DYNAMIC_FPS
- if (!dpy && mdpHw.isDynFpsSupported() && ctx->mUseMetaDataRefreshRate){
- /* Dyn fps: get refreshrate from metadata */
- MetaData_t *mdata = hnd ? (MetaData_t *)hnd->base_metadata : NULL;
- if (mdata && (mdata->operation & UPDATE_REFRESH_RATE)) {
- // Valid refreshRate in metadata and within the range
- uint32_t rate = getRefreshRate(ctx, mdata->refreshrate);
- if (!refreshRate) {
- refreshRate = rate;
- } else if(refreshRate != rate) {
- /* Support multiple refresh rates if they are same
- * else set to default.
- */
- refreshRate = ctx->dpyAttr[dpy].refreshRate;
- }
- }
- }
-#endif
- }
- if(ctx->listStats[dpy].yuvCount > 0) {
- if (property_get("hw.cabl.yuv", property, NULL) > 0) {
- if (atoi(property) != 1) {
- property_set("hw.cabl.yuv", "1");
- }
- }
- } else {
- if (property_get("hw.cabl.yuv", property, NULL) > 0) {
- if (atoi(property) != 0) {
- property_set("hw.cabl.yuv", "0");
- }
- }
- }
-
- //The marking of video begin/end is useful on some targets where we need
- //to have a padding round to be able to shift pipes across mixers.
- if(prevYuvCount != ctx->listStats[dpy].yuvCount) {
- ctx->mVideoTransFlag = true;
- }
-
- if(dpy == HWC_DISPLAY_PRIMARY) {
- ctx->mAD->markDoable(ctx, list);
- //Store the requested fresh rate
- ctx->listStats[dpy].refreshRateRequest = refreshRate ?
- refreshRate : ctx->dpyAttr[dpy].refreshRate;
- }
-}
-
-
-static void calc_cut(double& leftCutRatio, double& topCutRatio,
- double& rightCutRatio, double& bottomCutRatio, int orient) {
- if(orient & HAL_TRANSFORM_FLIP_H) {
- swap(leftCutRatio, rightCutRatio);
- }
- if(orient & HAL_TRANSFORM_FLIP_V) {
- swap(topCutRatio, bottomCutRatio);
- }
- if(orient & HAL_TRANSFORM_ROT_90) {
- //Anti clock swapping
- double tmpCutRatio = leftCutRatio;
- leftCutRatio = topCutRatio;
- topCutRatio = rightCutRatio;
- rightCutRatio = bottomCutRatio;
- bottomCutRatio = tmpCutRatio;
- }
-}
-
-bool isSecuring(hwc_context_t* ctx, hwc_layer_1_t const* layer) {
- if((ctx->mMDP.version < qdutils::MDSS_V5) &&
- (ctx->mMDP.version > qdutils::MDP_V3_0) &&
- ctx->mSecuring) {
- return true;
- }
- if (isSecureModePolicy(ctx->mMDP.version)) {
- private_handle_t *hnd = (private_handle_t *)layer->handle;
- if(ctx->mSecureMode) {
- if (! isSecureBuffer(hnd)) {
- ALOGD_IF(HWC_UTILS_DEBUG,"%s:Securing Turning ON ...",
- __FUNCTION__);
- return true;
- }
- } else {
- if (isSecureBuffer(hnd)) {
- ALOGD_IF(HWC_UTILS_DEBUG,"%s:Securing Turning OFF ...",
- __FUNCTION__);
- return true;
- }
- }
- }
- return false;
-}
-
-bool isSecureModePolicy(int mdpVersion) {
- if (mdpVersion < qdutils::MDSS_V5)
- return true;
- else
- return false;
-}
-
-bool isRotatorSupportedFormat(private_handle_t *hnd) {
- // Following rotator src formats are supported by mdp driver
- // TODO: Add more formats in future, if mdp driver adds support
- switch(hnd->format) {
- case HAL_PIXEL_FORMAT_RGBA_8888:
- case HAL_PIXEL_FORMAT_RGB_565:
- case HAL_PIXEL_FORMAT_RGB_888:
- case HAL_PIXEL_FORMAT_BGRA_8888:
- return true;
- default:
- return false;
- }
- return false;
-}
-
-bool isRotationDoable(hwc_context_t *ctx, private_handle_t *hnd) {
- // Rotate layers, if it is YUV type or rendered by CPU and not
- // for the MDP versions below MDP5
- if((isCPURendered(hnd) && isRotatorSupportedFormat(hnd) &&
- !(ctx->mMDP.version < qdutils::MDSS_V5))
- || isYuvBuffer(hnd)) {
- return true;
- }
- return false;
-}
-
-// returns true if Action safe dimensions are set and target supports Actionsafe
-bool isActionSafePresent(hwc_context_t *ctx, int dpy) {
- // if external supports underscan, do nothing
- // it will be taken care in the driver
- // Disable Action safe for 8974 due to HW limitation for downscaling
- // layers with overlapped region
- // Disable Actionsafe for non HDMI displays.
- if(!(dpy == HWC_DISPLAY_EXTERNAL) ||
- qdutils::MDPVersion::getInstance().is8x74v2() ||
- ctx->mHDMIDisplay->isCEUnderscanSupported()) {
- return false;
- }
-
- char value[PROPERTY_VALUE_MAX];
- // Read action safe properties
- property_get("persist.sys.actionsafe.width", value, "0");
- ctx->dpyAttr[dpy].mAsWidthRatio = atoi(value);
- property_get("persist.sys.actionsafe.height", value, "0");
- ctx->dpyAttr[dpy].mAsHeightRatio = atoi(value);
-
- if(!ctx->dpyAttr[dpy].mAsWidthRatio && !ctx->dpyAttr[dpy].mAsHeightRatio) {
- //No action safe ratio set, return
- return false;
- }
- return true;
-}
-
-int getBlending(int blending) {
- switch(blending) {
- case HWC_BLENDING_NONE:
- return overlay::utils::OVERLAY_BLENDING_OPAQUE;
- case HWC_BLENDING_PREMULT:
- return overlay::utils::OVERLAY_BLENDING_PREMULT;
- case HWC_BLENDING_COVERAGE :
- default:
- return overlay::utils::OVERLAY_BLENDING_COVERAGE;
- }
-}
-
-//Crops source buffer against destination and FB boundaries
-void calculate_crop_rects(hwc_rect_t& crop, hwc_rect_t& dst,
- const hwc_rect_t& scissor, int orient) {
-
- int& crop_l = crop.left;
- int& crop_t = crop.top;
- int& crop_r = crop.right;
- int& crop_b = crop.bottom;
- int crop_w = crop.right - crop.left;
- int crop_h = crop.bottom - crop.top;
-
- int& dst_l = dst.left;
- int& dst_t = dst.top;
- int& dst_r = dst.right;
- int& dst_b = dst.bottom;
- int dst_w = abs(dst.right - dst.left);
- int dst_h = abs(dst.bottom - dst.top);
-
- const int& sci_l = scissor.left;
- const int& sci_t = scissor.top;
- const int& sci_r = scissor.right;
- const int& sci_b = scissor.bottom;
-
- double leftCutRatio = 0.0, rightCutRatio = 0.0, topCutRatio = 0.0,
- bottomCutRatio = 0.0;
-
- if(dst_l < sci_l) {
- leftCutRatio = (double)(sci_l - dst_l) / (double)dst_w;
- dst_l = sci_l;
- }
-
- if(dst_r > sci_r) {
- rightCutRatio = (double)(dst_r - sci_r) / (double)dst_w;
- dst_r = sci_r;
- }
-
- if(dst_t < sci_t) {
- topCutRatio = (double)(sci_t - dst_t) / (double)dst_h;
- dst_t = sci_t;
- }
-
- if(dst_b > sci_b) {
- bottomCutRatio = (double)(dst_b - sci_b) / (double)dst_h;
- dst_b = sci_b;
- }
-
- calc_cut(leftCutRatio, topCutRatio, rightCutRatio, bottomCutRatio, orient);
- crop_l += (int)round((double)crop_w * leftCutRatio);
- crop_t += (int)round((double)crop_h * topCutRatio);
- crop_r -= (int)round((double)crop_w * rightCutRatio);
- crop_b -= (int)round((double)crop_h * bottomCutRatio);
-}
-
-bool areLayersIntersecting(const hwc_layer_1_t* layer1,
- const hwc_layer_1_t* layer2) {
- hwc_rect_t irect = getIntersection(layer1->displayFrame,
- layer2->displayFrame);
- return isValidRect(irect);
-}
-
-bool isSameRect(const hwc_rect& rect1, const hwc_rect& rect2)
-{
- return ((rect1.left == rect2.left) && (rect1.top == rect2.top) &&
- (rect1.right == rect2.right) && (rect1.bottom == rect2.bottom));
-}
-
-bool isValidRect(const hwc_rect& rect)
-{
- return ((rect.bottom > rect.top) && (rect.right > rect.left)) ;
-}
-
-bool operator ==(const hwc_rect_t& lhs, const hwc_rect_t& rhs) {
- if(lhs.left == rhs.left && lhs.top == rhs.top &&
- lhs.right == rhs.right && lhs.bottom == rhs.bottom )
- return true ;
- return false;
-}
-
-bool layerUpdating(const hwc_layer_1_t* layer) {
- hwc_region_t surfDamage = layer->surfaceDamage;
- return ((surfDamage.numRects == 0) ||
- isValidRect(layer->surfaceDamage.rects[0]));
-}
-
-hwc_rect_t calculateDirtyRect(const hwc_layer_1_t* layer,
- hwc_rect_t& scissor) {
- hwc_region_t surfDamage = layer->surfaceDamage;
- hwc_rect_t src = integerizeSourceCrop(layer->sourceCropf);
- hwc_rect_t dst = layer->displayFrame;
- int x_off = dst.left - src.left;
- int y_off = dst.top - src.top;
- hwc_rect dirtyRect = (hwc_rect){0, 0, 0, 0};
- hwc_rect_t updatingRect = dst;
-
- if (surfDamage.numRects == 0) {
- // full layer updating, dirty rect is full frame
- dirtyRect = getIntersection(layer->displayFrame, scissor);
- } else {
- for(uint32_t i = 0; i < surfDamage.numRects; i++) {
- updatingRect = moveRect(surfDamage.rects[i], x_off, y_off);
- hwc_rect_t intersect = getIntersection(updatingRect, scissor);
- if(isValidRect(intersect)) {
- dirtyRect = getUnion(intersect, dirtyRect);
- }
- }
- }
- return dirtyRect;
-}
-
-hwc_rect_t moveRect(const hwc_rect_t& rect, const int& x_off, const int& y_off)
-{
- hwc_rect_t res;
-
- if(!isValidRect(rect))
- return (hwc_rect_t){0, 0, 0, 0};
-
- res.left = rect.left + x_off;
- res.top = rect.top + y_off;
- res.right = rect.right + x_off;
- res.bottom = rect.bottom + y_off;
-
- return res;
-}
-
-/* computes the intersection of two rects */
-hwc_rect_t getIntersection(const hwc_rect_t& rect1, const hwc_rect_t& rect2)
-{
- hwc_rect_t res;
-
- if(!isValidRect(rect1) || !isValidRect(rect2)){
- return (hwc_rect_t){0, 0, 0, 0};
- }
-
-
- res.left = max(rect1.left, rect2.left);
- res.top = max(rect1.top, rect2.top);
- res.right = min(rect1.right, rect2.right);
- res.bottom = min(rect1.bottom, rect2.bottom);
-
- if(!isValidRect(res))
- return (hwc_rect_t){0, 0, 0, 0};
-
- return res;
-}
-
-/* computes the union of two rects */
-hwc_rect_t getUnion(const hwc_rect &rect1, const hwc_rect &rect2)
-{
- hwc_rect_t res;
-
- if(!isValidRect(rect1)){
- return rect2;
- }
-
- if(!isValidRect(rect2)){
- return rect1;
- }
-
- res.left = min(rect1.left, rect2.left);
- res.top = min(rect1.top, rect2.top);
- res.right = max(rect1.right, rect2.right);
- res.bottom = max(rect1.bottom, rect2.bottom);
-
- return res;
-}
-
-/* Not a geometrical rect deduction. Deducts rect2 from rect1 only if it results
- * a single rect */
-hwc_rect_t deductRect(const hwc_rect_t& rect1, const hwc_rect_t& rect2) {
-
- hwc_rect_t res = rect1;
-
- if((rect1.left == rect2.left) && (rect1.right == rect2.right)) {
- if((rect1.top == rect2.top) && (rect2.bottom <= rect1.bottom))
- res.top = rect2.bottom;
- else if((rect1.bottom == rect2.bottom)&& (rect2.top >= rect1.top))
- res.bottom = rect2.top;
- }
- else if((rect1.top == rect2.top) && (rect1.bottom == rect2.bottom)) {
- if((rect1.left == rect2.left) && (rect2.right <= rect1.right))
- res.left = rect2.right;
- else if((rect1.right == rect2.right)&& (rect2.left >= rect1.left))
- res.right = rect2.left;
- }
- return res;
-}
-
-void optimizeLayerRects(const hwc_display_contents_1_t *list) {
- int i= (int)list->numHwLayers-2;
- while(i > 0) {
- //see if there is no blending required.
- //If it is opaque see if we can substract this region from below
- //layers.
- if(list->hwLayers[i].blending == HWC_BLENDING_NONE &&
- list->hwLayers[i].planeAlpha == 0xFF) {
- int j= i-1;
- hwc_rect_t& topframe =
- (hwc_rect_t&)list->hwLayers[i].displayFrame;
- while(j >= 0) {
- if(!needsScaling(&list->hwLayers[j])) {
- hwc_layer_1_t* layer = (hwc_layer_1_t*)&list->hwLayers[j];
- hwc_rect_t& bottomframe = layer->displayFrame;
- hwc_rect_t bottomCrop =
- integerizeSourceCrop(layer->sourceCropf);
- int transform = (layer->flags & HWC_COLOR_FILL) ? 0 :
- layer->transform;
-
- hwc_rect_t irect = getIntersection(bottomframe, topframe);
- if(isValidRect(irect)) {
- hwc_rect_t dest_rect;
- //if intersection is valid rect, deduct it
- dest_rect = deductRect(bottomframe, irect);
- qhwc::calculate_crop_rects(bottomCrop, bottomframe,
- dest_rect, transform);
- //Update layer sourceCropf
- layer->sourceCropf.left =(float)bottomCrop.left;
- layer->sourceCropf.top = (float)bottomCrop.top;
- layer->sourceCropf.right = (float)bottomCrop.right;
- layer->sourceCropf.bottom = (float)bottomCrop.bottom;
- }
- }
- j--;
- }
- }
- i--;
- }
-}
-
-void getNonWormholeRegion(hwc_display_contents_1_t* list,
- hwc_rect_t& nwr)
-{
- size_t last = list->numHwLayers - 1;
- hwc_rect_t fbDisplayFrame = list->hwLayers[last].displayFrame;
- //Initiliaze nwr to first frame
- nwr.left = list->hwLayers[0].displayFrame.left;
- nwr.top = list->hwLayers[0].displayFrame.top;
- nwr.right = list->hwLayers[0].displayFrame.right;
- nwr.bottom = list->hwLayers[0].displayFrame.bottom;
-
- for (size_t i = 1; i < last; i++) {
- hwc_rect_t displayFrame = list->hwLayers[i].displayFrame;
- nwr = getUnion(nwr, displayFrame);
- }
-
- //Intersect with the framebuffer
- nwr = getIntersection(nwr, fbDisplayFrame);
-}
-
-bool isExternalActive(hwc_context_t* ctx) {
- return ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].isActive;
-}
-
-void closeAcquireFds(hwc_display_contents_1_t* list) {
- if(LIKELY(list)) {
- for(uint32_t i = 0; i < list->numHwLayers; i++) {
- //Close the acquireFenceFds
- //HWC_FRAMEBUFFER are -1 already by SF, rest we close.
- if(list->hwLayers[i].acquireFenceFd >= 0) {
- close(list->hwLayers[i].acquireFenceFd);
- list->hwLayers[i].acquireFenceFd = -1;
- }
- }
- //Writeback
- if(list->outbufAcquireFenceFd >= 0) {
- close(list->outbufAcquireFenceFd);
- list->outbufAcquireFenceFd = -1;
- }
- }
-}
-
-int hwc_sync(hwc_context_t *ctx, hwc_display_contents_1_t* list, int dpy,
- int fd) {
- ATRACE_CALL();
- int ret = 0;
- int acquireFd[MAX_NUM_APP_LAYERS];
- int count = 0;
- int releaseFd = -1;
- int retireFd = -1;
- int fbFd = -1;
- bool swapzero = false;
-
- struct mdp_buf_sync data;
- memset(&data, 0, sizeof(data));
- data.acq_fen_fd = acquireFd;
- data.rel_fen_fd = &releaseFd;
- data.retire_fen_fd = &retireFd;
- data.flags = MDP_BUF_SYNC_FLAG_RETIRE_FENCE;
-
-#ifdef DEBUG_SWAPINTERVAL
- char property[PROPERTY_VALUE_MAX];
- if(property_get("debug.egl.swapinterval", property, "1") > 0) {
- if(atoi(property) == 0)
- swapzero = true;
- }
-#endif
-
- bool isExtAnimating = false;
- if(dpy)
- isExtAnimating = ctx->listStats[dpy].isDisplayAnimating;
-
- //Send acquireFenceFds to rotator
- for(uint32_t i = 0; i < ctx->mLayerRotMap[dpy]->getCount(); i++) {
- int rotFd = ctx->mRotMgr->getRotDevFd();
- int rotReleaseFd = -1;
- overlay::Rotator* currRot = ctx->mLayerRotMap[dpy]->getRot(i);
- hwc_layer_1_t* currLayer = ctx->mLayerRotMap[dpy]->getLayer(i);
- if((currRot == NULL) || (currLayer == NULL)) {
- continue;
- }
- struct mdp_buf_sync rotData;
- memset(&rotData, 0, sizeof(rotData));
- rotData.acq_fen_fd =
- &currLayer->acquireFenceFd;
- rotData.rel_fen_fd = &rotReleaseFd; //driver to populate this
- rotData.session_id = currRot->getSessId();
- if(currLayer->acquireFenceFd >= 0) {
- rotData.acq_fen_fd_cnt = 1; //1 ioctl call per rot session
- }
- int ret = 0;
- if(LIKELY(!swapzero) and (not ctx->mLayerRotMap[dpy]->isRotCached(i)))
- ret = ioctl(rotFd, MSMFB_BUFFER_SYNC, &rotData);
-
- if(ret < 0) {
- ALOGE("%s: ioctl MSMFB_BUFFER_SYNC failed for rot sync, err=%s",
- __FUNCTION__, strerror(errno));
- close(rotReleaseFd);
- } else {
- close(currLayer->acquireFenceFd);
- //For MDP to wait on.
- currLayer->acquireFenceFd =
- dup(rotReleaseFd);
- //A buffer is free to be used by producer as soon as its copied to
- //rotator
- currLayer->releaseFenceFd =
- rotReleaseFd;
- }
- }
-
- //Accumulate acquireFenceFds for MDP Overlays
- if(list->outbufAcquireFenceFd >= 0) {
- //Writeback output buffer
- if(LIKELY(!swapzero) )
- acquireFd[count++] = list->outbufAcquireFenceFd;
- }
-
- for(uint32_t i = 0; i < list->numHwLayers; i++) {
- if(((isAbcInUse(ctx)== true ) ||
- (list->hwLayers[i].compositionType == HWC_OVERLAY)) &&
- list->hwLayers[i].acquireFenceFd >= 0) {
- if(LIKELY(!swapzero) ) {
- // if ABC is enabled for more than one layer.
- // renderBufIndexforABC will work as FB.Hence
- // set the acquireFD from fd - which is coming from copybit
- if(fd >= 0 && (isAbcInUse(ctx) == true)) {
- if(ctx->listStats[dpy].renderBufIndexforABC ==(int32_t)i)
- acquireFd[count++] = fd;
- else
- continue;
- } else
- acquireFd[count++] = list->hwLayers[i].acquireFenceFd;
- }
- }
- if(list->hwLayers[i].compositionType == HWC_FRAMEBUFFER_TARGET) {
- if(LIKELY(!swapzero) ) {
- if(fd >= 0) {
- //set the acquireFD from fd - which is coming from c2d
- acquireFd[count++] = fd;
- // Buffer sync IOCTL should be async when using c2d fence is
- // used
- data.flags &= ~MDP_BUF_SYNC_FLAG_WAIT;
- } else if(list->hwLayers[i].acquireFenceFd >= 0)
- acquireFd[count++] = list->hwLayers[i].acquireFenceFd;
- }
- }
- }
-
- if ((fd >= 0) && !dpy && ctx->mPtorInfo.isActive()) {
- // Acquire c2d fence of Overlap render buffer
- if(LIKELY(!swapzero) )
- acquireFd[count++] = fd;
- }
-
- data.acq_fen_fd_cnt = count;
- fbFd = ctx->dpyAttr[dpy].fd;
-
- //Waits for acquire fences, returns a release fence
- if(LIKELY(!swapzero)) {
- ret = ioctl(fbFd, MSMFB_BUFFER_SYNC, &data);
- }
-
- if(ret < 0) {
- ALOGE("%s: ioctl MSMFB_BUFFER_SYNC failed, err=%s",
- __FUNCTION__, strerror(errno));
- ALOGE("%s: acq_fen_fd_cnt=%d flags=%d fd=%d dpy=%d numHwLayers=%zu",
- __FUNCTION__, data.acq_fen_fd_cnt, data.flags, fbFd,
- dpy, list->numHwLayers);
- close(releaseFd);
- releaseFd = -1;
- close(retireFd);
- retireFd = -1;
- }
-
- for(uint32_t i = 0; i < list->numHwLayers; i++) {
- if(list->hwLayers[i].compositionType == HWC_OVERLAY ||
-#ifdef QTI_BSP
- list->hwLayers[i].compositionType == HWC_BLIT ||
-#endif
- list->hwLayers[i].compositionType == HWC_FRAMEBUFFER_TARGET) {
- //Populate releaseFenceFds.
- if(UNLIKELY(swapzero)) {
- list->hwLayers[i].releaseFenceFd = -1;
- } else if(isExtAnimating) {
- // Release all the app layer fds immediately,
- // if animation is in progress.
- list->hwLayers[i].releaseFenceFd = -1;
- } else if(list->hwLayers[i].releaseFenceFd < 0 ) {
-#ifdef QTI_BSP
- //If rotator has not already populated this field
- // & if it's a not VPU layer
-
- // if ABC is enabled for more than one layer
- if(fd >= 0 && (isAbcInUse(ctx) == true) &&
- ctx->listStats[dpy].renderBufIndexforABC !=(int32_t)i){
- list->hwLayers[i].releaseFenceFd = dup(fd);
- } else if((list->hwLayers[i].compositionType == HWC_BLIT)&&
- (isAbcInUse(ctx) == false)){
- //For Blit, the app layers should be released when the Blit
- //is complete. This fd was passed from copybit->draw
- list->hwLayers[i].releaseFenceFd = dup(fd);
- } else
-#endif
- {
- list->hwLayers[i].releaseFenceFd = dup(releaseFd);
- }
- }
- }
- }
-
- if(fd >= 0) {
- close(fd);
- fd = -1;
- }
-
- if (ctx->mCopyBit[dpy]) {
- if (!dpy && ctx->mPtorInfo.isActive())
- ctx->mCopyBit[dpy]->setReleaseFdSync(releaseFd);
- else
- ctx->mCopyBit[dpy]->setReleaseFd(releaseFd);
- }
-
- //Signals when MDP finishes reading rotator buffers.
- ctx->mLayerRotMap[dpy]->setReleaseFd(releaseFd);
- close(releaseFd);
- releaseFd = -1;
-
- if(UNLIKELY(swapzero)) {
- list->retireFenceFd = -1;
- } else {
- list->retireFenceFd = retireFd;
- }
- return ret;
-}
-
-void setMdpFlags(hwc_context_t *ctx, hwc_layer_1_t *layer,
- ovutils::eMdpFlags &mdpFlags,
- int rotDownscale, int transform) {
- private_handle_t *hnd = (private_handle_t *)layer->handle;
- MetaData_t *metadata = hnd ? (MetaData_t *)hnd->base_metadata : NULL;
-
- if(layer->blending == HWC_BLENDING_PREMULT) {
- ovutils::setMdpFlags(mdpFlags,
- ovutils::OV_MDP_BLEND_FG_PREMULT);
- }
-
- if(metadata && (metadata->operation & PP_PARAM_INTERLACED) &&
- metadata->interlaced) {
- ovutils::setMdpFlags(mdpFlags,
- ovutils::OV_MDP_DEINTERLACE);
- }
-
- // Mark MDP flags with SECURE_OVERLAY_SESSION for driver
- if(isSecureBuffer(hnd)) {
- ovutils::setMdpFlags(mdpFlags,
- ovutils::OV_MDP_SECURE_OVERLAY_SESSION);
- }
-
- if(isSecureDisplayBuffer(hnd)) {
- // Mark MDP flags with SECURE_DISPLAY_OVERLAY_SESSION for driver
- ovutils::setMdpFlags(mdpFlags,
- ovutils::OV_MDP_SECURE_DISPLAY_OVERLAY_SESSION);
- }
-
- //Pre-rotation will be used using rotator.
- if(has90Transform(layer) && isRotationDoable(ctx, hnd)) {
- ovutils::setMdpFlags(mdpFlags,
- ovutils::OV_MDP_SOURCE_ROTATED_90);
- }
- //No 90 component and no rot-downscale then flips done by MDP
- //If we use rot then it might as well do flips
- if(!(transform & HWC_TRANSFORM_ROT_90) && !rotDownscale) {
- if(transform & HWC_TRANSFORM_FLIP_H) {
- ovutils::setMdpFlags(mdpFlags, ovutils::OV_MDP_FLIP_H);
- }
-
- if(transform & HWC_TRANSFORM_FLIP_V) {
- ovutils::setMdpFlags(mdpFlags, ovutils::OV_MDP_FLIP_V);
- }
- }
-
- if(metadata &&
- ((metadata->operation & PP_PARAM_HSIC)
- || (metadata->operation & PP_PARAM_IGC)
- || (metadata->operation & PP_PARAM_SHARP2))) {
- ovutils::setMdpFlags(mdpFlags, ovutils::OV_MDP_PP_EN);
- }
-}
-
-int configRotator(Rotator *rot, Whf& whf,
- hwc_rect_t& crop, const eMdpFlags& mdpFlags,
- const eTransform& orient, const int& downscale) {
-
- // Fix alignments for TILED format
- if(whf.format == MDP_Y_CRCB_H2V2_TILE ||
- whf.format == MDP_Y_CBCR_H2V2_TILE) {
- whf.w = utils::alignup(whf.w, 64);
- whf.h = utils::alignup(whf.h, 32);
- }
- rot->setSource(whf);
-
- if (qdutils::MDPVersion::getInstance().getMDPVersion() >=
- qdutils::MDSS_V5) {
- Dim rotCrop(crop.left, crop.top, crop.right - crop.left,
- crop.bottom - crop.top);
- rot->setCrop(rotCrop);
- }
-
- rot->setFlags(mdpFlags);
- rot->setTransform(orient);
- rot->setDownscale(downscale);
- if(!rot->commit()) return -1;
- return 0;
-}
-
-int configMdp(Overlay *ov, const PipeArgs& parg,
- const eTransform& orient, const hwc_rect_t& crop,
- const hwc_rect_t& pos, const MetaData_t *metadata,
- const eDest& dest) {
- ov->setSource(parg, dest);
- ov->setTransform(orient, dest);
-
- int crop_w = crop.right - crop.left;
- int crop_h = crop.bottom - crop.top;
- Dim dcrop(crop.left, crop.top, crop_w, crop_h);
- ov->setCrop(dcrop, dest);
-
- int posW = pos.right - pos.left;
- int posH = pos.bottom - pos.top;
- Dim position(pos.left, pos.top, posW, posH);
- ov->setPosition(position, dest);
-
- if (metadata)
- ov->setVisualParams(*metadata, dest);
-
- if (!ov->commit(dest)) {
- return -1;
- }
- return 0;
-}
-
-int configColorLayer(hwc_context_t *ctx, hwc_layer_1_t *layer,
- const int& dpy, eMdpFlags& mdpFlags, eZorder& z,
- const eDest& dest) {
-
- hwc_rect_t dst = layer->displayFrame;
- trimLayer(ctx, dpy, 0, dst, dst);
-
- int w = ctx->dpyAttr[dpy].xres;
- int h = ctx->dpyAttr[dpy].yres;
- int dst_w = dst.right - dst.left;
- int dst_h = dst.bottom - dst.top;
- uint32_t color = layer->transform;
- Whf whf(w, h, getMdpFormat(HAL_PIXEL_FORMAT_RGBA_8888), 0);
-
- ovutils::setMdpFlags(mdpFlags, ovutils::OV_MDP_SOLID_FILL);
- if (layer->blending == HWC_BLENDING_PREMULT)
- ovutils::setMdpFlags(mdpFlags, ovutils::OV_MDP_BLEND_FG_PREMULT);
-
- PipeArgs parg(mdpFlags, whf, z, static_cast<eRotFlags>(0),
- layer->planeAlpha,
- (ovutils::eBlending) getBlending(layer->blending));
-
- // Configure MDP pipe for Color layer
- Dim pos(dst.left, dst.top, dst_w, dst_h);
- ctx->mOverlay->setSource(parg, dest);
- ctx->mOverlay->setColor(color, dest);
- ctx->mOverlay->setTransform(0, dest);
- ctx->mOverlay->setCrop(pos, dest);
- ctx->mOverlay->setPosition(pos, dest);
-
- if (!ctx->mOverlay->commit(dest)) {
- ALOGE("%s: Configure color layer failed!", __FUNCTION__);
- return -1;
- }
- return 0;
-}
-
-void updateSource(eTransform& orient, Whf& whf,
- hwc_rect_t& crop, Rotator *rot) {
- Dim transformedCrop(crop.left, crop.top,
- crop.right - crop.left,
- crop.bottom - crop.top);
- if (qdutils::MDPVersion::getInstance().getMDPVersion() >=
- qdutils::MDSS_V5) {
- //B-family rotator internally could modify destination dimensions if
- //downscaling is supported
- whf = rot->getDstWhf();
- transformedCrop = rot->getDstDimensions();
- } else {
- //A-family rotator rotates entire buffer irrespective of crop, forcing
- //us to recompute the crop based on transform
- orient = static_cast<eTransform>(ovutils::getMdpOrient(orient));
- preRotateSource(orient, whf, transformedCrop);
- }
-
- crop.left = transformedCrop.x;
- crop.top = transformedCrop.y;
- crop.right = transformedCrop.x + transformedCrop.w;
- crop.bottom = transformedCrop.y + transformedCrop.h;
-}
-
-int getRotDownscale(hwc_context_t *ctx, const hwc_layer_1_t *layer) {
- if(not qdutils::MDPVersion::getInstance().isRotDownscaleEnabled()) {
- return 0;
- }
-
- int downscale = 0;
- hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);
- hwc_rect_t dst = layer->displayFrame;
- private_handle_t *hnd = (private_handle_t *)layer->handle;
-
- if(not hnd) {
- return 0;
- }
-
- MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
- bool isInterlaced = metadata && (metadata->operation & PP_PARAM_INTERLACED)
- && metadata->interlaced;
- int transform = layer->transform;
- uint32_t format = ovutils::getMdpFormat(hnd->format, isTileRendered(hnd));
-
- if(isYuvBuffer(hnd)) {
- if(ctx->mMDP.version >= qdutils::MDP_V4_2 &&
- ctx->mMDP.version < qdutils::MDSS_V5) {
- downscale = Rotator::getDownscaleFactor(crop.right - crop.left,
- crop.bottom - crop.top, dst.right - dst.left,
- dst.bottom - dst.top, format, isInterlaced);
- } else {
- Dim adjCrop(crop.left, crop.top, crop.right - crop.left,
- crop.bottom - crop.top);
- Dim pos(dst.left, dst.top, dst.right - dst.left,
- dst.bottom - dst.top);
- if(transform & HAL_TRANSFORM_ROT_90) {
- swap(adjCrop.w, adjCrop.h);
- }
- downscale = Rotator::getDownscaleFactor(adjCrop.w, adjCrop.h, pos.w,
- pos.h, format, isInterlaced);
- }
- }
- return downscale;
-}
-
-bool isZoomModeEnabled(hwc_rect_t crop) {
- // This does not work for zooming in top left corner of the image
- return(crop.top > 0 || crop.left > 0);
-}
-
-void updateCropAIVVideoMode(hwc_context_t *ctx, hwc_rect_t& crop, int dpy) {
- ALOGD_IF(HWC_UTILS_DEBUG, "dpy %d Source crop [%d %d %d %d]", dpy,
- crop.left, crop.top, crop.right, crop.bottom);
- if(isZoomModeEnabled(crop)) {
- Dim srcCrop(crop.left, crop.top,
- crop.right - crop.left,
- crop.bottom - crop.top);
- int extW = ctx->dpyAttr[dpy].xres;
- int extH = ctx->dpyAttr[dpy].yres;
- //Crop the original video in order to fit external display aspect ratio
- if(srcCrop.w * extH < extW * srcCrop.h) {
- int offset = (srcCrop.h - ((srcCrop.w * extH) / extW)) / 2;
- crop.top += offset;
- crop.bottom -= offset;
- } else {
- int offset = (srcCrop.w - ((extW * srcCrop.h) / extH)) / 2;
- crop.left += offset;
- crop.right -= offset;
- }
- ALOGD_IF(HWC_UTILS_DEBUG, "External Resolution [%d %d] dpy %d Modified"
- " source crop [%d %d %d %d]", extW, extH, dpy,
- crop.left, crop.top, crop.right, crop.bottom);
- }
-}
-
-void updateDestAIVVideoMode(hwc_context_t *ctx, hwc_rect_t crop,
- hwc_rect_t& dst, int dpy) {
- ALOGD_IF(HWC_UTILS_DEBUG, "dpy %d Destination position [%d %d %d %d]", dpy,
- dst.left, dst.top, dst.right, dst.bottom);
- Dim srcCrop(crop.left, crop.top,
- crop.right - crop.left,
- crop.bottom - crop.top);
- int extW = ctx->dpyAttr[dpy].xres;
- int extH = ctx->dpyAttr[dpy].yres;
- // Set the destination coordinates of external display to full screen,
- // when zoom in mode is enabled or the ratio between video aspect ratio
- // and external display aspect ratio is below the minimum tolerance level
- // and above maximum tolerance level
- float videoAspectRatio = ((float)srcCrop.w / (float)srcCrop.h);
- float extDisplayAspectRatio = ((float)extW / (float)extH);
- float videoToExternalRatio = videoAspectRatio / extDisplayAspectRatio;
- if((fabs(1.0f - videoToExternalRatio) <= ctx->mAspectRatioToleranceLevel) ||
- (isZoomModeEnabled(crop))) {
- dst.left = 0;
- dst.top = 0;
- dst.right = extW;
- dst.bottom = extH;
- }
- ALOGD_IF(HWC_UTILS_DEBUG, "External Resolution [%d %d] dpy %d Modified"
- " Destination position [%d %d %d %d] Source crop [%d %d %d %d]",
- extW, extH, dpy, dst.left, dst.top, dst.right, dst.bottom,
- crop.left, crop.top, crop.right, crop.bottom);
-}
-
-void updateCoordinates(hwc_context_t *ctx, hwc_rect_t& crop,
- hwc_rect_t& dst, int dpy) {
- updateCropAIVVideoMode(ctx, crop, dpy);
- updateDestAIVVideoMode(ctx, crop, dst, dpy);
-}
-
-int configureNonSplit(hwc_context_t *ctx, hwc_layer_1_t *layer,
- const int& dpy, eMdpFlags& mdpFlags, eZorder& z,
- const eDest& dest, Rotator **rot) {
-
- private_handle_t *hnd = (private_handle_t *)layer->handle;
-
- if(!hnd) {
- if (layer->flags & HWC_COLOR_FILL) {
- // Configure Color layer
- return configColorLayer(ctx, layer, dpy, mdpFlags, z, dest);
- }
- ALOGE("%s: layer handle is NULL", __FUNCTION__);
- return -1;
- }
-
- MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
-
- hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);
- hwc_rect_t dst = layer->displayFrame;
- int transform = layer->transform;
- eTransform orient = static_cast<eTransform>(transform);
- int rotFlags = ovutils::ROT_FLAGS_NONE;
- uint32_t format = ovutils::getMdpFormat(hnd->format, isTileRendered(hnd));
- Whf whf(getWidth(hnd), getHeight(hnd), format, (uint32_t)hnd->size);
-
- // Handle R/B swap
- if (layer->flags & HWC_FORMAT_RB_SWAP) {
- if (hnd->format == HAL_PIXEL_FORMAT_RGBA_8888)
- whf.format = getMdpFormat(HAL_PIXEL_FORMAT_BGRA_8888);
- else if (hnd->format == HAL_PIXEL_FORMAT_RGBX_8888)
- whf.format = getMdpFormat(HAL_PIXEL_FORMAT_BGRX_8888);
- }
- // update source crop and destination position of AIV video layer.
- if(ctx->listStats[dpy].mAIVVideoMode && isYuvBuffer(hnd)) {
- updateCoordinates(ctx, crop, dst, dpy);
- }
- calcExtDisplayPosition(ctx, hnd, dpy, crop, dst, transform, orient);
- int downscale = getRotDownscale(ctx, layer);
- setMdpFlags(ctx, layer, mdpFlags, downscale, transform);
-
- //if 90 component or downscale, use rot
- if((has90Transform(layer) or downscale) and isRotationDoable(ctx, hnd)) {
- *rot = ctx->mRotMgr->getNext();
- if(*rot == NULL) return -1;
- ctx->mLayerRotMap[dpy]->add(layer, *rot);
- // BWC is not tested for other formats So enable it only for YUV format
- if(!dpy && isYuvBuffer(hnd))
- BwcPM::setBwc(crop, dst, transform, downscale, mdpFlags);
- //Configure rotator for pre-rotation
- if(configRotator(*rot, whf, crop, mdpFlags, orient, downscale) < 0) {
- ALOGE("%s: configRotator failed!", __FUNCTION__);
- return -1;
- }
- updateSource(orient, whf, crop, *rot);
- rotFlags |= ROT_PREROTATED;
- }
-
- //For the mdp, since either we are pre-rotating or MDP does flips
- orient = OVERLAY_TRANSFORM_0;
- transform = 0;
- PipeArgs parg(mdpFlags, whf, z,
- static_cast<eRotFlags>(rotFlags), layer->planeAlpha,
- (ovutils::eBlending) getBlending(layer->blending));
-
- if(configMdp(ctx->mOverlay, parg, orient, crop, dst, metadata, dest) < 0) {
- ALOGE("%s: commit failed for low res panel", __FUNCTION__);
- return -1;
- }
- return 0;
-}
-
-//Helper to 1) Ensure crops dont have gaps 2) Ensure L and W are even
-void sanitizeSourceCrop(hwc_rect_t& cropL, hwc_rect_t& cropR,
- private_handle_t *hnd) {
- if(cropL.right - cropL.left) {
- if(isYuvBuffer(hnd)) {
- //Always safe to even down left
- ovutils::even_floor(cropL.left);
- //If right is even, automatically width is even, since left is
- //already even
- ovutils::even_floor(cropL.right);
- }
- //Make sure there are no gaps between left and right splits if the layer
- //is spread across BOTH halves
- if(cropR.right - cropR.left) {
- cropR.left = cropL.right;
- }
- }
-
- if(cropR.right - cropR.left) {
- if(isYuvBuffer(hnd)) {
- //Always safe to even down left
- ovutils::even_floor(cropR.left);
- //If right is even, automatically width is even, since left is
- //already even
- ovutils::even_floor(cropR.right);
- }
- }
-}
-
-int configureSplit(hwc_context_t *ctx, hwc_layer_1_t *layer,
- const int& dpy, eMdpFlags& mdpFlagsL, eZorder& z,
- const eDest& lDest, const eDest& rDest,
- Rotator **rot) {
- private_handle_t *hnd = (private_handle_t *)layer->handle;
- if(!hnd) {
- ALOGE("%s: layer handle is NULL", __FUNCTION__);
- return -1;
- }
-
- MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
-
- int hw_w = ctx->dpyAttr[dpy].xres;
- int hw_h = ctx->dpyAttr[dpy].yres;
- hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);
- hwc_rect_t dst = layer->displayFrame;
- int transform = layer->transform;
- eTransform orient = static_cast<eTransform>(transform);
- int rotFlags = ROT_FLAGS_NONE;
- uint32_t format = ovutils::getMdpFormat(hnd->format, isTileRendered(hnd));
- Whf whf(getWidth(hnd), getHeight(hnd), format, (uint32_t)hnd->size);
-
- // Handle R/B swap
- if (layer->flags & HWC_FORMAT_RB_SWAP) {
- if (hnd->format == HAL_PIXEL_FORMAT_RGBA_8888)
- whf.format = getMdpFormat(HAL_PIXEL_FORMAT_BGRA_8888);
- else if (hnd->format == HAL_PIXEL_FORMAT_RGBX_8888)
- whf.format = getMdpFormat(HAL_PIXEL_FORMAT_BGRX_8888);
- }
-
- // update source crop and destination position of AIV video layer.
- if(ctx->listStats[dpy].mAIVVideoMode && isYuvBuffer(hnd)) {
- updateCoordinates(ctx, crop, dst, dpy);
- }
-
- /* Calculate the external display position based on MDP downscale,
- ActionSafe, and extorientation features. */
- calcExtDisplayPosition(ctx, hnd, dpy, crop, dst, transform, orient);
- int downscale = getRotDownscale(ctx, layer);
- setMdpFlags(ctx, layer, mdpFlagsL, downscale, transform);
-
- if(lDest != OV_INVALID && rDest != OV_INVALID) {
- //Enable overfetch
- setMdpFlags(mdpFlagsL, OV_MDSS_MDP_DUAL_PIPE);
- }
-
- //Will do something only if feature enabled and conditions suitable
- //hollow call otherwise
- if(ctx->mAD->prepare(ctx, crop, whf, hnd)) {
- overlay::Writeback *wb = overlay::Writeback::getInstance();
- whf.format = wb->getOutputFormat();
- }
-
- if((has90Transform(layer) or downscale) and isRotationDoable(ctx, hnd)) {
- (*rot) = ctx->mRotMgr->getNext();
- if((*rot) == NULL) return -1;
- ctx->mLayerRotMap[dpy]->add(layer, *rot);
- //Configure rotator for pre-rotation
- if(configRotator(*rot, whf, crop, mdpFlagsL, orient, downscale) < 0) {
- ALOGE("%s: configRotator failed!", __FUNCTION__);
- return -1;
- }
- updateSource(orient, whf, crop, *rot);
- rotFlags |= ROT_PREROTATED;
- }
-
- eMdpFlags mdpFlagsR = mdpFlagsL;
- setMdpFlags(mdpFlagsR, OV_MDSS_MDP_RIGHT_MIXER);
-
- hwc_rect_t tmp_cropL = {0}, tmp_dstL = {0};
- hwc_rect_t tmp_cropR = {0}, tmp_dstR = {0};
-
- const int lSplit = getLeftSplit(ctx, dpy);
-
- // Calculate Left rects
- if(dst.left < lSplit) {
- tmp_cropL = crop;
- tmp_dstL = dst;
- hwc_rect_t scissor = {0, 0, lSplit, hw_h };
- scissor = getIntersection(ctx->mViewFrame[dpy], scissor);
- qhwc::calculate_crop_rects(tmp_cropL, tmp_dstL, scissor, 0);
- }
-
- // Calculate Right rects
- if(dst.right > lSplit) {
- tmp_cropR = crop;
- tmp_dstR = dst;
- hwc_rect_t scissor = {lSplit, 0, hw_w, hw_h };
- scissor = getIntersection(ctx->mViewFrame[dpy], scissor);
- qhwc::calculate_crop_rects(tmp_cropR, tmp_dstR, scissor, 0);
- }
-
- sanitizeSourceCrop(tmp_cropL, tmp_cropR, hnd);
-
- //When buffer is H-flipped, contents of mixer config also needs to swapped
- //Not needed if the layer is confined to one half of the screen.
- //If rotator has been used then it has also done the flips, so ignore them.
- if((orient & OVERLAY_TRANSFORM_FLIP_H) && (dst.left < lSplit) &&
- (dst.right > lSplit) && (*rot) == NULL) {
- hwc_rect_t new_cropR;
- new_cropR.left = tmp_cropL.left;
- new_cropR.right = new_cropR.left + (tmp_cropR.right - tmp_cropR.left);
-
- hwc_rect_t new_cropL;
- new_cropL.left = new_cropR.right;
- new_cropL.right = tmp_cropR.right;
-
- tmp_cropL.left = new_cropL.left;
- tmp_cropL.right = new_cropL.right;
-
- tmp_cropR.left = new_cropR.left;
- tmp_cropR.right = new_cropR.right;
-
- }
-
- //For the mdp, since either we are pre-rotating or MDP does flips
- orient = OVERLAY_TRANSFORM_0;
- transform = 0;
-
- //configure left mixer
- if(lDest != OV_INVALID) {
- PipeArgs pargL(mdpFlagsL, whf, z,
- static_cast<eRotFlags>(rotFlags), layer->planeAlpha,
- (ovutils::eBlending) getBlending(layer->blending));
-
- if(configMdp(ctx->mOverlay, pargL, orient,
- tmp_cropL, tmp_dstL, metadata, lDest) < 0) {
- ALOGE("%s: commit failed for left mixer config", __FUNCTION__);
- return -1;
- }
- }
-
- //configure right mixer
- if(rDest != OV_INVALID) {
- PipeArgs pargR(mdpFlagsR, whf, z,
- static_cast<eRotFlags>(rotFlags),
- layer->planeAlpha,
- (ovutils::eBlending) getBlending(layer->blending));
- tmp_dstR.right = tmp_dstR.right - lSplit;
- tmp_dstR.left = tmp_dstR.left - lSplit;
- if(configMdp(ctx->mOverlay, pargR, orient,
- tmp_cropR, tmp_dstR, metadata, rDest) < 0) {
- ALOGE("%s: commit failed for right mixer config", __FUNCTION__);
- return -1;
- }
- }
-
- return 0;
-}
-
-int configureSourceSplit(hwc_context_t *ctx, hwc_layer_1_t *layer,
- const int& dpy, eMdpFlags& mdpFlagsL, eZorder& z,
- const eDest& lDest, const eDest& rDest,
- Rotator **rot) {
- private_handle_t *hnd = (private_handle_t *)layer->handle;
- if(!hnd) {
- ALOGE("%s: layer handle is NULL", __FUNCTION__);
- return -1;
- }
-
- MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
-
- hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);;
- hwc_rect_t dst = layer->displayFrame;
- int transform = layer->transform;
- eTransform orient = static_cast<eTransform>(transform);
- const int downscale = 0;
- int rotFlags = ROT_FLAGS_NONE;
- //Splitting only YUV layer on primary panel needs different zorders
- //for both layers as both the layers are configured to single mixer
- eZorder lz = z;
- eZorder rz = (eZorder)(z + 1);
-
- Whf whf(getWidth(hnd), getHeight(hnd),
- getMdpFormat(hnd->format), (uint32_t)hnd->size);
-
- // update source crop and destination position of AIV video layer.
- if(ctx->listStats[dpy].mAIVVideoMode && isYuvBuffer(hnd)) {
- updateCoordinates(ctx, crop, dst, dpy);
- }
-
- /* Calculate the external display position based on MDP downscale,
- ActionSafe, and extorientation features. */
- calcExtDisplayPosition(ctx, hnd, dpy, crop, dst, transform, orient);
-
- setMdpFlags(ctx, layer, mdpFlagsL, 0, transform);
- trimLayer(ctx, dpy, transform, crop, dst);
-
- if(has90Transform(layer) && isRotationDoable(ctx, hnd)) {
- (*rot) = ctx->mRotMgr->getNext();
- if((*rot) == NULL) return -1;
- ctx->mLayerRotMap[dpy]->add(layer, *rot);
- // BWC is not tested for other formats So enable it only for YUV format
- if(!dpy && isYuvBuffer(hnd))
- BwcPM::setBwc(crop, dst, transform, downscale, mdpFlagsL);
- //Configure rotator for pre-rotation
- if(configRotator(*rot, whf, crop, mdpFlagsL, orient, downscale) < 0) {
- ALOGE("%s: configRotator failed!", __FUNCTION__);
- return -1;
- }
- updateSource(orient, whf, crop, *rot);
- rotFlags |= ROT_PREROTATED;
- }
-
- eMdpFlags mdpFlagsR = mdpFlagsL;
- int lSplit = dst.left + (dst.right - dst.left)/2;
-
- hwc_rect_t tmp_cropL = {0}, tmp_dstL = {0};
- hwc_rect_t tmp_cropR = {0}, tmp_dstR = {0};
-
- if(lDest != OV_INVALID) {
- tmp_cropL = crop;
- tmp_dstL = dst;
- hwc_rect_t scissor = {dst.left, dst.top, lSplit, dst.bottom };
- qhwc::calculate_crop_rects(tmp_cropL, tmp_dstL, scissor, 0);
- }
- if(rDest != OV_INVALID) {
- tmp_cropR = crop;
- tmp_dstR = dst;
- hwc_rect_t scissor = {lSplit, dst.top, dst.right, dst.bottom };
- qhwc::calculate_crop_rects(tmp_cropR, tmp_dstR, scissor, 0);
- }
-
- sanitizeSourceCrop(tmp_cropL, tmp_cropR, hnd);
-
- //When buffer is H-flipped, contents of mixer config also needs to swapped
- //Not needed if the layer is confined to one half of the screen.
- //If rotator has been used then it has also done the flips, so ignore them.
- if((orient & OVERLAY_TRANSFORM_FLIP_H) && lDest != OV_INVALID
- && rDest != OV_INVALID && (*rot) == NULL) {
- hwc_rect_t new_cropR;
- new_cropR.left = tmp_cropL.left;
- new_cropR.right = new_cropR.left + (tmp_cropR.right - tmp_cropR.left);
-
- hwc_rect_t new_cropL;
- new_cropL.left = new_cropR.right;
- new_cropL.right = tmp_cropR.right;
-
- tmp_cropL.left = new_cropL.left;
- tmp_cropL.right = new_cropL.right;
-
- tmp_cropR.left = new_cropR.left;
- tmp_cropR.right = new_cropR.right;
-
- }
-
- //For the mdp, since either we are pre-rotating or MDP does flips
- orient = OVERLAY_TRANSFORM_0;
- transform = 0;
-
- //configure left half
- if(lDest != OV_INVALID) {
- PipeArgs pargL(mdpFlagsL, whf, lz,
- static_cast<eRotFlags>(rotFlags), layer->planeAlpha,
- (ovutils::eBlending) getBlending(layer->blending));
-
- if(configMdp(ctx->mOverlay, pargL, orient,
- tmp_cropL, tmp_dstL, metadata, lDest) < 0) {
- ALOGE("%s: commit failed for left half config", __FUNCTION__);
- return -1;
- }
- }
-
- //configure right half
- if(rDest != OV_INVALID) {
- PipeArgs pargR(mdpFlagsR, whf, rz,
- static_cast<eRotFlags>(rotFlags),
- layer->planeAlpha,
- (ovutils::eBlending) getBlending(layer->blending));
- if(configMdp(ctx->mOverlay, pargR, orient,
- tmp_cropR, tmp_dstR, metadata, rDest) < 0) {
- ALOGE("%s: commit failed for right half config", __FUNCTION__);
- return -1;
- }
- }
-
- return 0;
-}
-
-bool canUseRotator(hwc_context_t *ctx, int dpy) {
- if(ctx->mOverlay->isDMAMultiplexingSupported() &&
- isSecondaryConnected(ctx) &&
- !ctx->dpyAttr[HWC_DISPLAY_VIRTUAL].isPause) {
- /* mdss driver on certain targets support multiplexing of DMA pipe
- * in LINE and BLOCK modes for writeback panels.
- */
- if(dpy == HWC_DISPLAY_PRIMARY)
- return false;
- }
- if((ctx->mMDP.version == qdutils::MDP_V3_0_4)
- ||(ctx->mMDP.version == qdutils::MDP_V3_0_5))
- return false;
- return true;
-}
-
-int getLeftSplit(hwc_context_t *ctx, const int& dpy) {
- //Default even split for all displays with high res
- int lSplit = ctx->dpyAttr[dpy].xres / 2;
- if(dpy == HWC_DISPLAY_PRIMARY &&
- qdutils::MDPVersion::getInstance().getLeftSplit()) {
- //Override if split published by driver for primary
- lSplit = qdutils::MDPVersion::getInstance().getLeftSplit();
- }
- return lSplit;
-}
-
-bool isDisplaySplit(hwc_context_t* ctx, int dpy) {
- qdutils::MDPVersion& mdpHw = qdutils::MDPVersion::getInstance();
- if(ctx->dpyAttr[dpy].xres > mdpHw.getMaxMixerWidth()) {
- return true;
- }
- //For testing we could split primary via device tree values
- if(dpy == HWC_DISPLAY_PRIMARY && mdpHw.getRightSplit()) {
- return true;
- }
- return false;
-}
-
-//clear prev layer prop flags and realloc for current frame
-void reset_layer_prop(hwc_context_t* ctx, int dpy, int numAppLayers) {
- if(ctx->layerProp[dpy]) {
- delete[] ctx->layerProp[dpy];
- ctx->layerProp[dpy] = NULL;
- }
- ctx->layerProp[dpy] = new LayerProp[numAppLayers];
-}
-
-bool isAbcInUse(hwc_context_t *ctx){
- return (ctx->enableABC && ctx->listStats[0].renderBufIndexforABC == 0);
-}
-
-void dumpBuffer(private_handle_t *ohnd, char *bufferName) {
- if (ohnd != NULL && ohnd->base) {
- char dumpFilename[PATH_MAX];
- bool bResult = false;
- int width = getWidth(ohnd);
- int height = getHeight(ohnd);
- int format = ohnd->format;
- //dummy aligned w & h.
- int alW = 0, alH = 0;
- int size = getBufferSizeAndDimensions(width, height, format, alW, alH);
- snprintf(dumpFilename, sizeof(dumpFilename), "/data/%s.%s.%dx%d.raw",
- bufferName,
- overlay::utils::getFormatString(utils::getMdpFormat(format)),
- width, height);
- FILE* fp = fopen(dumpFilename, "w+");
- if (NULL != fp) {
- bResult = (bool) fwrite((void*)ohnd->base, size, 1, fp);
- fclose(fp);
- }
- ALOGD("Buffer[%s] Dump to %s: %s",
- bufferName, dumpFilename, bResult ? "Success" : "Fail");
- }
-}
-
-bool isGLESComp(hwc_context_t *ctx,
- hwc_display_contents_1_t* list) {
- int numAppLayers = ctx->listStats[HWC_DISPLAY_PRIMARY].numAppLayers;
- for(int index = 0; index < numAppLayers; index++) {
- hwc_layer_1_t* layer = &(list->hwLayers[index]);
- if(layer->compositionType == HWC_FRAMEBUFFER)
- return true;
- }
- return false;
-}
-
-void setGPUHint(hwc_context_t* ctx, hwc_display_contents_1_t* list) {
-#ifdef QTI_BSP
- struct gpu_hint_info *gpuHint = &ctx->mGPUHintInfo;
- if(!gpuHint->mGpuPerfModeEnable || !ctx || !list)
- return;
-
- /* Set the GPU hint flag to high for MIXED/GPU composition only for
- first frame after MDP -> GPU/MIXED mode transition. Set the GPU
- hint to default if the previous composition is GPU or current GPU
- composition is due to idle fallback */
- if(!gpuHint->mEGLDisplay || !gpuHint->mEGLContext) {
- gpuHint->mEGLDisplay = (*(ctx->mpfn_eglGetCurrentDisplay))();
- if(!gpuHint->mEGLDisplay) {
- ALOGW("%s Warning: EGL current display is NULL", __FUNCTION__);
- return;
- }
- gpuHint->mEGLContext = (*(ctx->mpfn_eglGetCurrentContext))();
- if(!gpuHint->mEGLContext) {
- ALOGW("%s Warning: EGL current context is NULL", __FUNCTION__);
- return;
- }
- }
- if(isGLESComp(ctx, list)) {
- if(gpuHint->mCompositionState != COMPOSITION_STATE_GPU
- && !MDPComp::isIdleFallback()) {
- EGLint attr_list[] = {EGL_GPU_HINT_1,
- EGL_GPU_LEVEL_3,
- EGL_NONE };
- if((gpuHint->mCurrGPUPerfMode != EGL_GPU_LEVEL_3) &&
- !((*(ctx->mpfn_eglGpuPerfHintQCOM))(gpuHint->mEGLDisplay,
- gpuHint->mEGLContext, attr_list))) {
- ALOGW("eglGpuPerfHintQCOM failed for Built in display");
- } else {
- gpuHint->mCurrGPUPerfMode = EGL_GPU_LEVEL_3;
- gpuHint->mCompositionState = COMPOSITION_STATE_GPU;
- }
- } else {
- EGLint attr_list[] = {EGL_GPU_HINT_1,
- EGL_GPU_LEVEL_0,
- EGL_NONE };
- if((gpuHint->mCurrGPUPerfMode != EGL_GPU_LEVEL_0) &&
- !((*(ctx->mpfn_eglGpuPerfHintQCOM))(gpuHint->mEGLDisplay,
- gpuHint->mEGLContext, attr_list))) {
- ALOGW("eglGpuPerfHintQCOM failed for Built in display");
- } else {
- gpuHint->mCurrGPUPerfMode = EGL_GPU_LEVEL_0;
- }
- if(MDPComp::isIdleFallback()) {
- gpuHint->mCompositionState = COMPOSITION_STATE_IDLE_FALLBACK;
- }
- }
- } else {
- /* set the GPU hint flag to default for MDP composition */
- EGLint attr_list[] = {EGL_GPU_HINT_1,
- EGL_GPU_LEVEL_0,
- EGL_NONE };
- if((gpuHint->mCurrGPUPerfMode != EGL_GPU_LEVEL_0) &&
- !((*(ctx->mpfn_eglGpuPerfHintQCOM))(gpuHint->mEGLDisplay,
- gpuHint->mEGLContext, attr_list))) {
- ALOGW("eglGpuPerfHintQCOM failed for Built in display");
- } else {
- gpuHint->mCurrGPUPerfMode = EGL_GPU_LEVEL_0;
- }
- gpuHint->mCompositionState = COMPOSITION_STATE_MDP;
- }
-#else
- (void) ctx;
- (void) list;
-#endif
-}
-
-bool isPeripheral(const hwc_rect_t& rect1, const hwc_rect_t& rect2) {
- // To be peripheral, 3 boundaries should match.
- uint8_t eqBounds = 0;
- if (rect1.left == rect2.left)
- eqBounds++;
- if (rect1.top == rect2.top)
- eqBounds++;
- if (rect1.right == rect2.right)
- eqBounds++;
- if (rect1.bottom == rect2.bottom)
- eqBounds++;
- return (eqBounds == 3);
-}
-
-void processBootAnimCompleted(hwc_context_t *ctx) {
- char value[PROPERTY_VALUE_MAX];
-
- // Applying default mode after bootanimation is finished
- property_get("init.svc.bootanim", value, "running");
-
- if (!strncmp(value,"stopped",strlen("stopped"))) {
- ctx->mBootAnimCompleted = true;
-
- //one-shot action check if bootanimation completed then apply
- //default display mode.
- qdcmApplyDefaultAfterBootAnimationDone(ctx);
- }
-}
-
-void BwcPM::setBwc(const hwc_rect_t& crop, const hwc_rect_t& dst,
- const int& transform,const int& downscale,
- ovutils::eMdpFlags& mdpFlags) {
- //BWC not supported with rot-downscale
- if(downscale) return;
-
- //Target doesnt support Bwc
- qdutils::MDPVersion& mdpHw = qdutils::MDPVersion::getInstance();
- if(!mdpHw.supportsBWC()) {
- return;
- }
- int src_w = crop.right - crop.left;
- int src_h = crop.bottom - crop.top;
- int dst_w = dst.right - dst.left;
- int dst_h = dst.bottom - dst.top;
- if(transform & HAL_TRANSFORM_ROT_90) {
- swap(src_w, src_h);
- }
- //src width > MAX mixer supported dim
- if(src_w > (int) qdutils::MDPVersion::getInstance().getMaxMixerWidth()) {
- return;
- }
- //Decimation necessary, cannot use BWC. H/W requirement.
- if(qdutils::MDPVersion::getInstance().supportsDecimation()) {
- uint8_t horzDeci = 0;
- uint8_t vertDeci = 0;
- ovutils::getDecimationFactor(src_w, src_h, dst_w, dst_h, horzDeci,
- vertDeci);
- if(horzDeci || vertDeci) return;
- }
- //Property
- char value[PROPERTY_VALUE_MAX];
- property_get("debug.disable.bwc", value, "0");
- if(atoi(value)) return;
-
- ovutils::setMdpFlags(mdpFlags, ovutils::OV_MDSS_MDP_BWC_EN);
-}
-
-void LayerRotMap::add(hwc_layer_1_t* layer, Rotator *rot) {
- if(mCount >= RotMgr::MAX_ROT_SESS) return;
- mLayer[mCount] = layer;
- mRot[mCount] = rot;
- mCount++;
-}
-
-void LayerRotMap::reset() {
- for (int i = 0; i < RotMgr::MAX_ROT_SESS; i++) {
- mLayer[i] = 0;
- mRot[i] = 0;
- }
- mCount = 0;
-}
-
-void LayerRotMap::clear() {
- RotMgr::getInstance()->markUnusedTop(mCount);
- reset();
-}
-
-bool LayerRotMap::isRotCached(uint32_t index) const {
- overlay::Rotator* rot = getRot(index);
- hwc_layer_1_t* layer = getLayer(index);
-
- if(rot and layer and layer->handle) {
- private_handle_t *hnd = (private_handle_t *)(layer->handle);
- return (rot->isRotCached(hnd->fd,(uint32_t)(hnd->offset)));
- }
- return false;
-}
-
-void LayerRotMap::setReleaseFd(const int& fence) {
- for(uint32_t i = 0; i < mCount; i++) {
- if(mRot[i] and mLayer[i] and mLayer[i]->handle) {
- /* Ensure that none of the above (Rotator-instance,
- * layer and layer-handle) are NULL*/
- if(isRotCached(i))
- mRot[i]->setPrevBufReleaseFd(dup(fence));
- else
- mRot[i]->setCurrBufReleaseFd(dup(fence));
- }
- }
-}
-
-void resetROI(hwc_context_t *ctx, const int dpy) {
- const int fbXRes = (int)ctx->dpyAttr[dpy].xres;
- const int fbYRes = (int)ctx->dpyAttr[dpy].yres;
- if(isDisplaySplit(ctx, dpy)) {
- const int lSplit = getLeftSplit(ctx, dpy);
- ctx->listStats[dpy].lRoi = (struct hwc_rect){0, 0, lSplit, fbYRes};
- ctx->listStats[dpy].rRoi = (struct hwc_rect){lSplit, 0, fbXRes, fbYRes};
- } else {
- ctx->listStats[dpy].lRoi = (struct hwc_rect){0, 0,fbXRes, fbYRes};
- ctx->listStats[dpy].rRoi = (struct hwc_rect){0, 0, 0, 0};
- }
-}
-
-hwc_rect_t getSanitizeROI(struct hwc_rect roi, hwc_rect boundary)
-{
- if(!isValidRect(roi))
- return roi;
-
- struct hwc_rect t_roi = roi;
-
- const int LEFT_ALIGN = qdutils::MDPVersion::getInstance().getLeftAlign();
- const int WIDTH_ALIGN = qdutils::MDPVersion::getInstance().getWidthAlign();
- const int TOP_ALIGN = qdutils::MDPVersion::getInstance().getTopAlign();
- const int HEIGHT_ALIGN = qdutils::MDPVersion::getInstance().getHeightAlign();
- const int MIN_WIDTH = qdutils::MDPVersion::getInstance().getMinROIWidth();
- const int MIN_HEIGHT = qdutils::MDPVersion::getInstance().getMinROIHeight();
-
- /* Align to minimum width recommended by the panel */
- if((t_roi.right - t_roi.left) < MIN_WIDTH) {
- if((t_roi.left + MIN_WIDTH) > boundary.right)
- t_roi.left = t_roi.right - MIN_WIDTH;
- else
- t_roi.right = t_roi.left + MIN_WIDTH;
- }
-
- /* Align to minimum height recommended by the panel */
- if((t_roi.bottom - t_roi.top) < MIN_HEIGHT) {
- if((t_roi.top + MIN_HEIGHT) > boundary.bottom)
- t_roi.top = t_roi.bottom - MIN_HEIGHT;
- else
- t_roi.bottom = t_roi.top + MIN_HEIGHT;
- }
-
- /* Align left and width to meet panel restrictions */
- if(LEFT_ALIGN)
- t_roi.left = t_roi.left - (t_roi.left % LEFT_ALIGN);
-
- if(WIDTH_ALIGN) {
- int width = t_roi.right - t_roi.left;
- width = WIDTH_ALIGN * ((width + (WIDTH_ALIGN - 1)) / WIDTH_ALIGN);
- t_roi.right = t_roi.left + width;
-
- if(t_roi.right > boundary.right) {
- t_roi.right = boundary.right;
- t_roi.left = t_roi.right - width;
-
- if(LEFT_ALIGN)
- t_roi.left = t_roi.left - (t_roi.left % LEFT_ALIGN);
- }
- }
-
-
- /* Align top and height to meet panel restrictions */
- if(TOP_ALIGN)
- t_roi.top = t_roi.top - (t_roi.top % TOP_ALIGN);
-
- if(HEIGHT_ALIGN) {
- int height = t_roi.bottom - t_roi.top;
- height = HEIGHT_ALIGN * ((height + (HEIGHT_ALIGN - 1)) / HEIGHT_ALIGN);
- t_roi.bottom = t_roi.top + height;
-
- if(t_roi.bottom > boundary.bottom) {
- t_roi.bottom = boundary.bottom;
- t_roi.top = t_roi.bottom - height;
-
- if(TOP_ALIGN)
- t_roi.top = t_roi.top - (t_roi.top % TOP_ALIGN);
- }
- }
-
-
- return t_roi;
-}
-
-void handle_pause(hwc_context_t* ctx, int dpy) {
- if(ctx->dpyAttr[dpy].connected) {
- ctx->mDrawLock.lock();
- ctx->dpyAttr[dpy].isActive = true;
- ctx->dpyAttr[dpy].isPause = true;
- ctx->mDrawLock.unlock();
- ctx->proc->invalidate(ctx->proc);
-
- usleep(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].vsync_period
- * 2 / 1000);
-
- // At this point all the pipes used by External have been
- // marked as UNSET.
- ctx->mDrawLock.lock();
- // Perform commit to unstage the pipes.
- if (!Overlay::displayCommit(ctx->dpyAttr[dpy].fd)) {
- ALOGE("%s: display commit fail! for %d dpy",
- __FUNCTION__, dpy);
- }
- ctx->mDrawLock.unlock();
- ctx->proc->invalidate(ctx->proc);
- }
- return;
-}
-
-void handle_resume(hwc_context_t* ctx, int dpy) {
- if(ctx->dpyAttr[dpy].connected) {
- ctx->mDrawLock.lock();
- ctx->dpyAttr[dpy].isConfiguring = true;
- ctx->dpyAttr[dpy].isActive = true;
- ctx->mDrawLock.unlock();
- ctx->proc->invalidate(ctx->proc);
-
- usleep(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].vsync_period
- * 2 / 1000);
-
- //At this point external has all the pipes it would need.
- ctx->mDrawLock.lock();
- ctx->dpyAttr[dpy].isPause = false;
- ctx->mDrawLock.unlock();
- ctx->proc->invalidate(ctx->proc);
- }
- return;
-}
-
-void clearPipeResources(hwc_context_t* ctx, int dpy) {
- if(ctx->mOverlay) {
- ctx->mOverlay->configBegin();
- ctx->mOverlay->configDone();
- }
- if(ctx->mRotMgr) {
- ctx->mRotMgr->clear();
- }
- // Call a display commit to ensure that pipes and associated
- // fd's are cleaned up.
- if(!Overlay::displayCommit(ctx->dpyAttr[dpy].fd)) {
- ALOGE("%s: display commit failed for %d", __FUNCTION__, dpy);
- }
-}
-
-// Handles online events when HDMI is the primary display. In particular,
-// online events for hdmi connected before AND after boot up and HWC init.
-void handle_online(hwc_context_t* ctx, int dpy) {
- // Close the current fd if it was opened earlier on when HWC
- // was initialized.
- if (ctx->dpyAttr[dpy].fd >= 0) {
- close(ctx->dpyAttr[dpy].fd);
- ctx->dpyAttr[dpy].fd = -1;
- }
- // TODO: If HDMI is connected after the display has booted up,
- // and the best configuration is different from the default
- // then we need to deal with this appropriately.
- ctx->mHDMIDisplay->configure();
- updateDisplayInfo(ctx, dpy);
- initCompositionResources(ctx, dpy);
- ctx->dpyAttr[dpy].connected = true;
-}
-
-// Handles offline events for HDMI. This can be used for offline events
-// initiated by the HDMI driver and the CEC framework.
-void handle_offline(hwc_context_t* ctx, int dpy) {
- destroyCompositionResources(ctx, dpy);
- // Clear all pipe resources and call a display commit to ensure
- // that all the fd's are closed. This will ensure that the HDMI
- // core turns off and that we receive an event the next time the
- // cable is connected.
- if (ctx->mHDMIDisplay->isHDMIPrimaryDisplay()) {
- clearPipeResources(ctx, dpy);
- }
- ctx->mHDMIDisplay->teardown();
- resetDisplayInfo(ctx, dpy);
- ctx->dpyAttr[dpy].connected = false;
- ctx->dpyAttr[dpy].isActive = false;
-}
-
-bool loadEglLib(hwc_context_t* ctx) {
- bool success = false;
-#ifdef QTI_BSP
- dlerror();
-
- ctx->mEglLib = dlopen("libEGL_adreno.so", RTLD_NOW);
- if(ctx->mEglLib) {
- *(void **)&(ctx->mpfn_eglGpuPerfHintQCOM) = dlsym(ctx->mEglLib, "eglGpuPerfHintQCOM");
- *(void **)&(ctx->mpfn_eglGetCurrentDisplay) = dlsym(ctx->mEglLib,"eglGetCurrentDisplay");
- *(void **)&(ctx->mpfn_eglGetCurrentContext) = dlsym(ctx->mEglLib,"eglGetCurrentContext");
- if (!ctx->mpfn_eglGpuPerfHintQCOM ||
- !ctx->mpfn_eglGetCurrentDisplay ||
- !ctx->mpfn_eglGetCurrentContext) {
- ALOGE("Failed to load symbols from libEGL");
- dlclose(ctx->mEglLib);
- ctx->mEglLib = NULL;
- return false;
- }
- success = true;
- ALOGI("Successfully Loaded GPUPerfHint APIs");
- } else {
- ALOGE("Couldn't load libEGL: %s", dlerror());
- }
-#else
- (void) ctx;
-#endif
- return success;
-}
-
-};//namespace qhwc
diff --git a/msm8909/libhwcomposer/hwc_utils.h b/msm8909/libhwcomposer/hwc_utils.h
deleted file mode 100644
index 0b824af4..00000000
--- a/msm8909/libhwcomposer/hwc_utils.h
+++ /dev/null
@@ -1,718 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- * Copyright (C)2012-2016, The Linux Foundation. All rights reserved.
- *
- * Not a Contribution, Apache license notifications and license are retained
- * for attribution purposes only.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef HWC_UTILS_H
-#define HWC_UTILS_H
-
-#define DEBUG_MDPDOWNSCALE 0
-#define HWC_REMOVE_DEPRECATED_VERSIONS 1
-
-#include <fcntl.h>
-#include <math.h>
-#include <hardware/hwcomposer.h>
-#include <gr.h>
-#include <gralloc_priv.h>
-#include <utils/String8.h>
-#include "qdMetaData.h"
-#include "mdp_version.h"
-#include <overlayUtils.h>
-#include <overlayRotator.h>
-#include <EGL/egl.h>
-
-
-#define ALIGN_TO(x, align) (((x) + ((align)-1)) & ~((align)-1))
-#define LIKELY( exp ) (__builtin_expect( (exp) != 0, true ))
-#define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false ))
-#define MAX_NUM_APP_LAYERS 32
-#define MIN_DISPLAY_XRES 200
-#define MIN_DISPLAY_YRES 200
-#define HWC_WFDDISPSYNC_LOG 0
-#define STR(f) #f;
-// Max number of PTOR layers handled
-#define MAX_PTOR_LAYERS 2
-
-#ifdef QTI_BSP
-#include <exhwcomposer_defs.h>
-#endif
-
-//Fwrd decls
-struct hwc_context_t;
-
-namespace ovutils = overlay::utils;
-
-namespace qmode {
-class ModeManager;
-}
-
-namespace overlay {
-class Overlay;
-class Rotator;
-class RotMgr;
-}
-
-namespace qhwc {
-//fwrd decl
-class QueuedBufferStore;
-class HDMIDisplay;
-class VirtualDisplay;
-class IFBUpdate;
-class IVideoOverlay;
-class MDPComp;
-class CopyBit;
-class HwcDebug;
-class AssertiveDisplay;
-class HWCVirtualVDS;
-
-
-struct MDPInfo {
- int version;
- char panel;
- bool hasOverlay;
-};
-
-struct DisplayAttributes {
- uint32_t refreshRate;
- uint32_t dynRefreshRate;
- uint32_t vsync_period; //nanos
- uint32_t xres;
- uint32_t yres;
- uint32_t stride;
- float xdpi;
- float ydpi;
- uint32_t fbformat;
- int fd;
- bool connected; //Applies only to pluggable disp.
- //Connected does not mean it ready to use.
- //It should be active also. (UNBLANKED)
- bool isActive;
- // In pause state, composition is bypassed
- // used for WFD displays and in QDCM calibration mode
- bool isPause;
- // To trigger padding round to clean up mdp
- // pipes
- bool isConfiguring;
- // Indicates whether external/virtual display is in MDP scaling mode
- bool mMDPScalingMode;
- // Ext dst Rect
- hwc_rect_t mDstRect;
- //Action safe attributes
- // Flag to indicate the presence of action safe dimensions for external
- bool mActionSafePresent;
- int mAsWidthRatio;
- int mAsHeightRatio;
-
- //If property fbsize set via adb shell debug.hwc.fbsize = XRESxYRES
- //following fields are used.
- bool customFBSize;
- uint32_t xres_new;
- uint32_t yres_new;
-
-};
-
-struct ListStats {
- int numAppLayers; //Total - 1, excluding FB layer.
- int skipCount;
- int fbLayerIndex; //Always last for now. = numAppLayers
- //Video specific
- int yuvCount;
- int yuvIndices[MAX_NUM_APP_LAYERS];
- bool preMultipliedAlpha;
- int yuv4k2kIndices[MAX_NUM_APP_LAYERS];
- int yuv4k2kCount;
- // Notifies hwcomposer about the start and end of animation
- // This will be set to true during animation, otherwise false.
- bool isDisplayAnimating;
- bool secureUI; // Secure display layer
- bool isSecurePresent;
- hwc_rect_t lRoi; //left ROI
- hwc_rect_t rRoi; //right ROI. Unused in single DSI panels.
- //App Buffer Composition index
- int renderBufIndexforABC;
- // Secure RGB specific
- int secureRGBCount;
- int secureRGBIndices[MAX_NUM_APP_LAYERS];
- //dyn refresh rate-Client requested refreshrate
- uint32_t refreshRateRequest;
- // Flag related to windowboxing feature
- bool mAIVVideoMode;
-};
-
-//PTOR Comp info
-struct PtorInfo {
- int count;
- int layerIndex[MAX_PTOR_LAYERS];
- hwc_rect_t displayFrame[MAX_PTOR_LAYERS];
- bool isActive() { return (count>0); }
- int getPTORArrayIndex(int index) {
- int idx = -1;
- for(int i = 0; i < count; i++) {
- if(index == layerIndex[i])
- idx = i;
- }
- return idx;
- }
-};
-
-struct LayerProp {
- uint32_t mFlags; //qcom specific layer flags
- LayerProp():mFlags(0){};
-};
-
-struct VsyncState {
- bool enable;
- bool fakevsync;
- bool debug;
-};
-
-struct BwcPM {
- static void setBwc(const hwc_rect_t& crop, const hwc_rect_t& dst,
- const int& transform, const int& downscale,
- ovutils::eMdpFlags& mdpFlags);
-};
-
-// LayerProp::flag values
-enum {
- HWC_MDPCOMP = 0x00000001,
- HWC_COPYBIT = 0x00000002,
-};
-
-// AIV specific flags
-enum {
- HWC_AIV_VIDEO = 0x80000000,
- HWC_AIV_CC = 0x40000000,
-};
-
-// HAL specific features
-enum {
- HWC_COLOR_FILL = 0x00000008,
- HWC_FORMAT_RB_SWAP = 0x00000040,
-};
-
-/* External Display states */
-enum {
- EXTERNAL_OFFLINE = 0,
- EXTERNAL_ONLINE,
- EXTERNAL_PAUSE,
- EXTERNAL_RESUME,
- EXTERNAL_MAXSTATES
-};
-
-class LayerRotMap {
-public:
- LayerRotMap() { reset(); }
- void add(hwc_layer_1_t* layer, overlay::Rotator *rot);
- //Resets the mapping of layer to rotator
- void reset();
- //Clears mappings and existing rotator fences
- //Intended to be used during errors
- void clear();
- uint32_t getCount() const;
- hwc_layer_1_t* getLayer(uint32_t index) const;
- overlay::Rotator* getRot(uint32_t index) const;
- bool isRotCached(uint32_t index) const;
- void setReleaseFd(const int& fence);
-private:
- hwc_layer_1_t* mLayer[overlay::RotMgr::MAX_ROT_SESS];
- overlay::Rotator* mRot[overlay::RotMgr::MAX_ROT_SESS];
- uint32_t mCount;
-};
-
-inline uint32_t LayerRotMap::getCount() const {
- return mCount;
-}
-
-inline hwc_layer_1_t* LayerRotMap::getLayer(uint32_t index) const {
- if(index >= mCount) return NULL;
- return mLayer[index];
-}
-
-inline overlay::Rotator* LayerRotMap::getRot(uint32_t index) const {
- if(index >= mCount) return NULL;
- return mRot[index];
-}
-
-inline hwc_rect_t integerizeSourceCrop(const hwc_frect_t& cropF) {
- hwc_rect_t cropI = {0,0,0,0};
- cropI.left = int(ceilf(cropF.left));
- cropI.top = int(ceilf(cropF.top));
- cropI.right = int(floorf(cropF.right));
- cropI.bottom = int(floorf(cropF.bottom));
- return cropI;
-}
-
-inline bool isNonIntegralSourceCrop(const hwc_frect_t& cropF) {
- if(cropF.left - roundf(cropF.left) ||
- cropF.top - roundf(cropF.top) ||
- cropF.right - roundf(cropF.right) ||
- cropF.bottom - roundf(cropF.bottom))
- return true;
- else
- return false;
-}
-
-// -----------------------------------------------------------------------------
-// Utility functions - implemented in hwc_utils.cpp
-void dumpLayer(hwc_layer_1_t const* l);
-void setListStats(hwc_context_t *ctx, hwc_display_contents_1_t *list,
- int dpy);
-void initContext(hwc_context_t *ctx);
-void closeContext(hwc_context_t *ctx);
-//Crops source buffer against destination and FB boundaries
-void calculate_crop_rects(hwc_rect_t& crop, hwc_rect_t& dst,
- const hwc_rect_t& scissor, int orient);
-void getNonWormholeRegion(hwc_display_contents_1_t* list,
- hwc_rect_t& nwr);
-bool isSecuring(hwc_context_t* ctx, hwc_layer_1_t const* layer);
-bool isSecureModePolicy(int mdpVersion);
-// Returns true, if the input layer format is supported by rotator
-bool isRotatorSupportedFormat(private_handle_t *hnd);
-//Returns true, if the layer is YUV or the layer has been rendered by CPU
-bool isRotationDoable(hwc_context_t *ctx, private_handle_t *hnd);
-bool isExternalActive(hwc_context_t* ctx);
-bool isAlphaScaled(hwc_layer_1_t const* layer);
-bool needsScaling(hwc_layer_1_t const* layer);
-bool isDownscaleRequired(hwc_layer_1_t const* layer);
-bool needsScalingWithSplit(hwc_context_t* ctx, hwc_layer_1_t const* layer,
- const int& dpy);
-void sanitizeSourceCrop(hwc_rect_t& cropL, hwc_rect_t& cropR,
- private_handle_t *hnd);
-bool isAlphaPresent(hwc_layer_1_t const* layer);
-bool isAlphaPresentinFB(hwc_context_t* ctx, int dpy);
-int hwc_vsync_control(hwc_context_t* ctx, int dpy, int enable);
-int getBlending(int blending);
-bool isGLESOnlyComp(hwc_context_t *ctx, const int& dpy);
-void reset_layer_prop(hwc_context_t* ctx, int dpy, int numAppLayers);
-bool isAbcInUse(hwc_context_t *ctx);
-
-void dumpBuffer(private_handle_t *ohnd, char *bufferName);
-void updateDisplayInfo(hwc_context_t* ctx, int dpy);
-void resetDisplayInfo(hwc_context_t* ctx, int dpy);
-void initCompositionResources(hwc_context_t* ctx, int dpy);
-void destroyCompositionResources(hwc_context_t* ctx, int dpy);
-void clearPipeResources(hwc_context_t* ctx, int dpy);
-
-//Helper function to dump logs
-void dumpsys_log(android::String8& buf, const char* fmt, ...);
-
-int getExtOrientation(hwc_context_t* ctx);
-bool isValidRect(const hwc_rect_t& rect);
-hwc_rect_t deductRect(const hwc_rect_t& rect1, const hwc_rect_t& rect2);
-bool isSameRect(const hwc_rect& rect1, const hwc_rect& rect2);
-hwc_rect_t moveRect(const hwc_rect_t& rect, const int& x_off, const int& y_off);
-hwc_rect_t getIntersection(const hwc_rect_t& rect1, const hwc_rect_t& rect2);
-hwc_rect_t getUnion(const hwc_rect_t& rect1, const hwc_rect_t& rect2);
-void optimizeLayerRects(const hwc_display_contents_1_t *list);
-bool areLayersIntersecting(const hwc_layer_1_t* layer1,
- const hwc_layer_1_t* layer2);
-bool operator ==(const hwc_rect_t& lhs, const hwc_rect_t& rhs);
-bool layerUpdating(const hwc_layer_1_t* layer);
-/* Calculates the dirtyRegion for the given layer */
-hwc_rect_t calculateDirtyRect(const hwc_layer_1_t* layer,
- hwc_rect_t& scissor);
-
-
-// returns true if Action safe dimensions are set and target supports Actionsafe
-bool isActionSafePresent(hwc_context_t *ctx, int dpy);
-
-/* Calculates the destination position based on the action safe rectangle */
-void getActionSafePosition(hwc_context_t *ctx, int dpy, hwc_rect_t& dst);
-
-void getAspectRatioPosition(hwc_context_t* ctx, int dpy, int extOrientation,
- hwc_rect_t& inRect, hwc_rect_t& outRect);
-
-uint32_t getRefreshRate(hwc_context_t* ctx, uint32_t requestedRefreshRate);
-
-uint32_t roundOff(uint32_t refreshRate);
-
-void setRefreshRate(hwc_context_t *ctx, int dpy, uint32_t refreshRate);
-
-bool isPrimaryPortrait(hwc_context_t *ctx);
-
-bool isOrientationPortrait(hwc_context_t *ctx);
-
-void calcExtDisplayPosition(hwc_context_t *ctx,
- private_handle_t *hnd,
- int dpy,
- hwc_rect_t& sourceCrop,
- hwc_rect_t& displayFrame,
- int& transform,
- ovutils::eTransform& orient);
-
-// Returns the orientation that needs to be set on external for
-// BufferMirrirMode(Sidesync)
-int getMirrorModeOrientation(hwc_context_t *ctx);
-
-/* Get External State names */
-const char* getExternalDisplayState(uint32_t external_state);
-
-// Resets display ROI to full panel resoluion
-void resetROI(hwc_context_t *ctx, const int dpy);
-
-// Aligns updating ROI to panel restrictions
-hwc_rect_t getSanitizeROI(struct hwc_rect roi, hwc_rect boundary);
-
-// Handles wfd Pause and resume events
-void handle_pause(hwc_context_t *ctx, int dpy);
-void handle_resume(hwc_context_t *ctx, int dpy);
-
-// Handle ONLINE/OFFLINE for HDMI display
-void handle_online(hwc_context_t* ctx, int dpy);
-void handle_offline(hwc_context_t* ctx, int dpy);
-
-//Close acquireFenceFds of all layers of incoming list
-void closeAcquireFds(hwc_display_contents_1_t* list);
-
-//Sync point impl.
-int hwc_sync(hwc_context_t *ctx, hwc_display_contents_1_t* list, int dpy,
- int fd);
-
-//Sets appropriate mdp flags for a layer.
-void setMdpFlags(hwc_context_t *ctx, hwc_layer_1_t *layer,
- ovutils::eMdpFlags &mdpFlags,
- int rotDownscale, int transform);
-
-int configRotator(overlay::Rotator *rot, ovutils::Whf& whf,
- hwc_rect_t& crop, const ovutils::eMdpFlags& mdpFlags,
- const ovutils::eTransform& orient, const int& downscale);
-
-int configMdp(overlay::Overlay *ov, const ovutils::PipeArgs& parg,
- const ovutils::eTransform& orient, const hwc_rect_t& crop,
- const hwc_rect_t& pos, const MetaData_t *metadata,
- const ovutils::eDest& dest);
-
-int configColorLayer(hwc_context_t *ctx, hwc_layer_1_t *layer, const int& dpy,
- ovutils::eMdpFlags& mdpFlags, ovutils::eZorder& z,
- const ovutils::eDest& dest);
-
-void updateSource(ovutils::eTransform& orient, ovutils::Whf& whf,
- hwc_rect_t& crop, overlay::Rotator *rot);
-
-bool isZoomModeEnabled(hwc_rect_t crop);
-void updateCropAIVVideoMode(hwc_context_t *ctx, hwc_rect_t& crop, int dpy);
-void updateDestAIVVideoMode(hwc_context_t *ctx, hwc_rect_t& dst, int dpy);
-void updateCoordinates(hwc_context_t *ctx, hwc_rect_t& crop,
- hwc_rect_t& dst, int dpy);
-
-//Routine to configure low resolution panels (<= 2048 width)
-int configureNonSplit(hwc_context_t *ctx, hwc_layer_1_t *layer, const int& dpy,
- ovutils::eMdpFlags& mdpFlags, ovutils::eZorder& z,
- const ovutils::eDest& dest,
- overlay::Rotator **rot);
-
-//Routine to configure high resolution panels (> 2048 width)
-int configureSplit(hwc_context_t *ctx, hwc_layer_1_t *layer, const int& dpy,
- ovutils::eMdpFlags& mdpFlags, ovutils::eZorder& z,
- const ovutils::eDest& lDest,
- const ovutils::eDest& rDest, overlay::Rotator **rot);
-
-//Routine to split and configure high resolution YUV layer (> 2048 width)
-int configureSourceSplit(hwc_context_t *ctx, hwc_layer_1_t *layer,
- const int& dpy,
- ovutils::eMdpFlags& mdpFlags, ovutils::eZorder& z,
- const ovutils::eDest& lDest,
- const ovutils::eDest& rDest, overlay::Rotator **rot);
-
-//On certain targets DMA pipes are used for rotation and they won't be available
-//for line operations. On a per-target basis we can restrict certain use cases
-//from using rotator, since we know before-hand that such scenarios can lead to
-//extreme unavailability of pipes. This can also be done via hybrid calculations
-//also involving many more variables like number of write-back interfaces etc,
-//but the variety of scenarios is too high to warrant that.
-bool canUseRotator(hwc_context_t *ctx, int dpy);
-
-int getLeftSplit(hwc_context_t *ctx, const int& dpy);
-
-bool isDisplaySplit(hwc_context_t* ctx, int dpy);
-
-int getRotDownscale(hwc_context_t *ctx, const hwc_layer_1_t *layer);
-
-// Set the GPU hint flag to high for MIXED/GPU composition only for
-// first frame after MDP to GPU/MIXED mode transition.
-// Set the GPU hint to default if the current composition type is GPU
-// due to idle fallback or MDP composition.
-void setGPUHint(hwc_context_t* ctx, hwc_display_contents_1_t* list);
-
-bool loadEglLib(hwc_context_t* ctx);
-
-// Returns true if rect1 is peripheral to rect2, false otherwise.
-bool isPeripheral(const hwc_rect_t& rect1, const hwc_rect_t& rect2);
-
-// Checks if boot animation has completed and applies default mode
-void processBootAnimCompleted(hwc_context_t *ctx);
-
-// Inline utility functions
-static inline bool isSkipLayer(const hwc_layer_1_t* l) {
- return (UNLIKELY(l && (l->flags & HWC_SKIP_LAYER)));
-}
-
-static inline bool isAIVVideoLayer(const hwc_layer_1_t* l) {
- return (UNLIKELY(l && (l->flags & HWC_AIV_VIDEO)));
-}
-
-static inline bool isAIVCCLayer(const hwc_layer_1_t* l) {
- return (UNLIKELY(l && (l->flags & HWC_AIV_CC)));
-}
-
-// Returns true if the buffer is yuv
-static inline bool isYuvBuffer(const private_handle_t* hnd) {
- return (hnd && (hnd->bufferType == BUFFER_TYPE_VIDEO));
-}
-
-// Returns true if the buffer is yuv and exceeds the mixer width
-static inline bool isYUVSplitNeeded(const private_handle_t* hnd) {
- int maxMixerWidth = qdutils::MDPVersion::getInstance().getMaxMixerWidth();
- return (hnd && (hnd->bufferType == BUFFER_TYPE_VIDEO) &&
- (hnd->width > maxMixerWidth));
-}
-
-// Returns true if the buffer is secure
-static inline bool isSecureBuffer(const private_handle_t* hnd) {
- return (hnd && (private_handle_t::PRIV_FLAGS_SECURE_BUFFER & hnd->flags));
-}
-
-static inline bool isTileRendered(const private_handle_t* hnd) {
- return (hnd && (private_handle_t::PRIV_FLAGS_TILE_RENDERED & hnd->flags));
-}
-
-static inline bool isCPURendered(const private_handle_t* hnd) {
- return (hnd && (private_handle_t::PRIV_FLAGS_CPU_RENDERED & hnd->flags));
-}
-
-//Return true if the buffer is intended for Secure Display
-static inline bool isSecureDisplayBuffer(const private_handle_t* hnd) {
- return (hnd && (hnd->flags & private_handle_t::PRIV_FLAGS_SECURE_DISPLAY));
-}
-
-static inline int getWidth(const private_handle_t* hnd) {
- MetaData_t *metadata = reinterpret_cast<MetaData_t*>(hnd->base_metadata);
- if(metadata && metadata->operation & UPDATE_BUFFER_GEOMETRY) {
- return metadata->bufferDim.sliceWidth;
- }
- return hnd->width;
-}
-
-static inline int getHeight(const private_handle_t* hnd) {
- MetaData_t *metadata = reinterpret_cast<MetaData_t*>(hnd->base_metadata);
- if(metadata && metadata->operation & UPDATE_BUFFER_GEOMETRY) {
- return metadata->bufferDim.sliceHeight;
- }
- return hnd->height;
-}
-
-template<typename T> inline T max(T a, T b) { return (a > b) ? a : b; }
-template<typename T> inline T min(T a, T b) { return (a < b) ? a : b; }
-
-// Initialize uevent thread
-void init_uevent_thread(hwc_context_t* ctx);
-// Initialize vsync thread
-void init_vsync_thread(hwc_context_t* ctx);
-
-inline void getLayerResolution(const hwc_layer_1_t* layer,
- int& width, int& height) {
- hwc_rect_t displayFrame = layer->displayFrame;
- width = displayFrame.right - displayFrame.left;
- height = displayFrame.bottom - displayFrame.top;
-}
-
-static inline int openFb(int dpy) {
- int fd = -1;
- const char *devtmpl = "/dev/graphics/fb%u";
- char name[64] = {0};
- snprintf(name, 64, devtmpl, dpy);
- fd = open(name, O_RDWR);
- return fd;
-}
-
-template <class T>
-inline void swap(T& a, T& b) {
- T tmp = a;
- a = b;
- b = tmp;
-}
-
-}; //qhwc namespace
-
-enum eAnimationState{
- ANIMATION_STOPPED,
- ANIMATION_STARTED,
-};
-
-enum eCompositionState {
- COMPOSITION_STATE_MDP = 0, // Set if composition type is MDP
- COMPOSITION_STATE_GPU, // Set if composition type is GPU or MIXED
- COMPOSITION_STATE_IDLE_FALLBACK, // Set if it is idlefallback
-};
-
-// Structure holds the information about the GPU hint.
-struct gpu_hint_info {
- // system level flag to enable gpu_perf_mode
- bool mGpuPerfModeEnable;
- // Stores the current GPU performance mode DEFAULT/HIGH
- uint32_t mCurrGPUPerfMode;
- // Stores the compositon state GPU, MDP or IDLE_FALLBACK
- bool mCompositionState;
- // Stores the EGLContext of current process
- EGLContext mEGLContext;
- // Stores the EGLDisplay of current process
- EGLDisplay mEGLDisplay;
-};
-
-//struct holds the information about libmm-qdcm.so
-struct qdcm_info {
- qmode::ModeManager *mQdcmMode;
- void *mQdcmLib;
- bool mBootAnimCompleted;
-};
-
-// -----------------------------------------------------------------------------
-// HWC context
-// This structure contains overall state
-struct hwc_context_t {
- hwc_composer_device_1_t device;
- const hwc_procs_t* proc;
-
- //CopyBit objects
- qhwc::CopyBit *mCopyBit[HWC_NUM_DISPLAY_TYPES];
-
- //Overlay object - NULL for non overlay devices
- overlay::Overlay *mOverlay;
- //Holds a few rot objects
- overlay::RotMgr *mRotMgr;
-
- //Primary and external FB updater
- qhwc::IFBUpdate *mFBUpdate[HWC_NUM_DISPLAY_TYPES];
- // HDMI display related object. Used to configure/teardown
- // HDMI when it is connected as primary or external.
- qhwc::HDMIDisplay *mHDMIDisplay;
- qhwc::MDPInfo mMDP;
- qhwc::VsyncState vstate;
- qhwc::DisplayAttributes dpyAttr[HWC_NUM_DISPLAY_TYPES];
- qhwc::ListStats listStats[HWC_NUM_DISPLAY_TYPES];
- qhwc::LayerProp *layerProp[HWC_NUM_DISPLAY_TYPES];
- qhwc::MDPComp *mMDPComp[HWC_NUM_DISPLAY_TYPES];
- qhwc::HwcDebug *mHwcDebug[HWC_NUM_DISPLAY_TYPES];
- hwc_rect_t mViewFrame[HWC_NUM_DISPLAY_TYPES];
- qhwc::AssertiveDisplay *mAD;
- eAnimationState mAnimationState[HWC_NUM_DISPLAY_TYPES];
- qhwc::HWCVirtualVDS *mHWCVirtual;
-
- // stores the #numHwLayers of the previous frame
- // for each display device
- int mPrevHwLayerCount[HWC_NUM_DISPLAY_TYPES];
-
- // stores the primary device orientation
- int deviceOrientation;
- //Securing in progress indicator
- bool mSecuring;
- //Display in secure mode indicator
- bool mSecureMode;
- //Lock to protect drawing data structures
- mutable Locker mDrawLock;
- //Drawing round when we use GPU
- bool isPaddingRound;
- // External Orientation
- int mExtOrientation;
- //Flags the transition of a video session
- bool mVideoTransFlag;
- //Used for SideSync feature
- //which overrides the mExtOrientation
- bool mBufferMirrorMode;
- // Used to synchronize between WFD and Display modules
- mutable Locker mWfdSyncLock;
-
- qhwc::LayerRotMap *mLayerRotMap[HWC_NUM_DISPLAY_TYPES];
- // Panel reset flag will be set if BTA check fails
- bool mPanelResetStatus;
- // number of active Displays
- int numActiveDisplays;
-#ifdef QTI_BSP
- void *mEglLib;
- EGLBoolean (*mpfn_eglGpuPerfHintQCOM)(EGLDisplay, EGLContext, EGLint *);
- EGLDisplay (*mpfn_eglGetCurrentDisplay)();
- EGLContext (*mpfn_eglGetCurrentContext)();
- struct gpu_hint_info mGPUHintInfo;
-#endif
- //App Buffer Composition
- bool enableABC;
- // PTOR Info
- qhwc::PtorInfo mPtorInfo;
- //Running in Thermal burst mode
- bool mThermalBurstMode;
- //Layers out of ROI
- bool copybitDrop[MAX_NUM_APP_LAYERS];
- // Flag related to windowboxing feature
- bool mWindowboxFeature;
- // This denotes the tolerance between video layer and external display
- // aspect ratio
- float mAspectRatioToleranceLevel;
- //Used to notify that boot has completed
- bool mBootAnimCompleted;
- // Provides a way for OEM's to disable setting dynfps via metadata.
- bool mUseMetaDataRefreshRate;
- //struct holds the information about display tuning service library.
- struct qdcm_info mQdcmInfo;
-};
-
-namespace qhwc {
-static inline bool isSkipPresent (hwc_context_t *ctx, int dpy) {
- return ctx->listStats[dpy].skipCount;
-}
-
-static inline bool isYuvPresent (hwc_context_t *ctx, int dpy) {
- return ctx->listStats[dpy].yuvCount;
-}
-
-static inline bool has90Transform(hwc_layer_1_t const* layer) {
- return ((layer->transform & HWC_TRANSFORM_ROT_90) &&
- !(layer->flags & HWC_COLOR_FILL));
-}
-
-inline bool isSecurePresent(hwc_context_t *ctx, int dpy) {
- return ctx->listStats[dpy].isSecurePresent;
-}
-
-static inline bool isSecondaryConfiguring(hwc_context_t* ctx) {
- return (ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].isConfiguring ||
- ctx->dpyAttr[HWC_DISPLAY_VIRTUAL].isConfiguring);
-}
-
-static inline bool isSecondaryConnected(hwc_context_t* ctx) {
- return (ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].connected ||
- ctx->dpyAttr[HWC_DISPLAY_VIRTUAL].connected);
-}
-
-static inline bool isSecondaryAnimating(hwc_context_t* ctx) {
- return (ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].connected &&
- (!ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].isPause) &&
- ctx->listStats[HWC_DISPLAY_EXTERNAL].isDisplayAnimating)
- ||
- (ctx->dpyAttr[HWC_DISPLAY_VIRTUAL].connected &&
- (!ctx->dpyAttr[HWC_DISPLAY_VIRTUAL].isPause) &&
- ctx->listStats[HWC_DISPLAY_VIRTUAL].isDisplayAnimating);
-}
-
-/* Return Virtual Display connection status */
-static inline bool isVDConnected(hwc_context_t* ctx) {
- return ctx->dpyAttr[HWC_DISPLAY_VIRTUAL].connected;
-}
-
-};
-
-#endif //HWC_UTILS_H
diff --git a/msm8909/libhwcomposer/hwc_virtual.cpp b/msm8909/libhwcomposer/hwc_virtual.cpp
deleted file mode 100644
index 2bfb5e73..00000000
--- a/msm8909/libhwcomposer/hwc_virtual.cpp
+++ /dev/null
@@ -1,236 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- * Copyright (C) 2012-2014, The Linux Foundation. All rights reserved.
- *
- * Not a Contribution, Apache license notifications and license are retained
- * for attribution purposes only.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#include <fcntl.h>
-#include <errno.h>
-
-#include <cutils/log.h>
-#include <overlayWriteback.h>
-#include "hwc_utils.h"
-#include "hwc_fbupdate.h"
-#include "hwc_mdpcomp.h"
-#include "hwc_dump_layers.h"
-#include "hwc_copybit.h"
-#include "hwc_virtual.h"
-#include "sync/sync.h"
-#include <utils/Trace.h>
-
-#define HWCVIRTUAL_LOG 0
-
-using namespace qhwc;
-using namespace overlay;
-
-bool HWCVirtualVDS::sVDDumpEnabled = false;
-
-void HWCVirtualVDS::init(hwc_context_t *ctx) {
- const int dpy = HWC_DISPLAY_VIRTUAL;
- mScalingWidth = 0, mScalingHeight = 0;
- initCompositionResources(ctx, dpy);
-
- if(ctx->mFBUpdate[dpy])
- ctx->mFBUpdate[dpy]->reset();
- if(ctx->mMDPComp[dpy])
- ctx->mMDPComp[dpy]->reset();
-}
-
-void HWCVirtualVDS::destroy(hwc_context_t *ctx, size_t /*numDisplays*/,
- hwc_display_contents_1_t** displays) {
- int dpy = HWC_DISPLAY_VIRTUAL;
-
- //Cleanup virtual display objs, since there is no explicit disconnect
- if(ctx->dpyAttr[dpy].connected && (displays[dpy] == NULL)) {
- ctx->dpyAttr[dpy].connected = false;
- ctx->dpyAttr[dpy].isPause = false;
-
- destroyCompositionResources(ctx, dpy);
-
- // signal synclock to indicate successful wfd teardown
- ctx->mWfdSyncLock.lock();
- ctx->mWfdSyncLock.signal();
- ctx->mWfdSyncLock.unlock();
- }
-}
-
-int HWCVirtualVDS::prepare(hwc_composer_device_1 *dev,
- hwc_display_contents_1_t *list) {
- ATRACE_CALL();
- //XXX: Fix when framework support is added
- hwc_context_t* ctx = (hwc_context_t*)(dev);
- const int dpy = HWC_DISPLAY_VIRTUAL;
-
- if (list && list->outbuf && list->numHwLayers > 0) {
- reset_layer_prop(ctx, dpy, (int)list->numHwLayers - 1);
- uint32_t last = (uint32_t)list->numHwLayers - 1;
- hwc_layer_1_t *fbLayer = &list->hwLayers[last];
- int fbWidth = 0, fbHeight = 0;
- getLayerResolution(fbLayer, fbWidth, fbHeight);
- ctx->dpyAttr[dpy].xres = fbWidth;
- ctx->dpyAttr[dpy].yres = fbHeight;
-
- if(ctx->dpyAttr[dpy].connected == false) {
- ctx->dpyAttr[dpy].connected = true;
- ctx->dpyAttr[dpy].isPause = false;
- // We set the vsync period to the primary refresh rate, leaving
- // it up to the consumer to decide how fast to consume frames.
- ctx->dpyAttr[dpy].vsync_period
- = ctx->dpyAttr[HWC_DISPLAY_PRIMARY].vsync_period;
- ctx->dpyAttr[dpy].fbformat = HAL_PIXEL_FORMAT_RGBA_8888;
- init(ctx);
- // Do one padding round for cases where primary has all pipes
- // The virtual composition falls back to GPU in such cases.
- ctx->isPaddingRound = true;
- }
- if(!ctx->dpyAttr[dpy].isPause) {
- ctx->dpyAttr[dpy].isConfiguring = false;
- ctx->dpyAttr[dpy].fd = Writeback::getInstance()->getFbFd();
- private_handle_t *ohnd = (private_handle_t *)list->outbuf;
-
- setMDPScalingMode(ctx, ohnd, dpy);
-
- mScalingWidth = getWidth(ohnd);
- mScalingHeight = getHeight(ohnd);
-
- Writeback::getInstance()->configureDpyInfo(mScalingWidth,
- mScalingHeight);
- setListStats(ctx, list, dpy);
-
- if(ctx->mMDPComp[dpy]->prepare(ctx, list) < 0) {
- const int fbZ = 0;
- if(not ctx->mFBUpdate[dpy]->prepareAndValidate(ctx, list, fbZ))
- {
- ctx->mOverlay->clear(dpy);
- ctx->mLayerRotMap[dpy]->clear();
- }
- }
- } else {
- /* Virtual Display is in Pause state.
- * Mark all application layers as OVERLAY so that
- * GPU will not compose.
- */
- Writeback::getInstance(); //Ensure that WB is active during pause
- for(size_t i = 0 ;i < (size_t)(list->numHwLayers - 1); i++) {
- hwc_layer_1_t *layer = &list->hwLayers[i];
- layer->compositionType = HWC_OVERLAY;
- }
- }
- }
- return 0;
-}
-
-int HWCVirtualVDS::set(hwc_context_t *ctx, hwc_display_contents_1_t *list) {
- ATRACE_CALL();
- int ret = 0;
- const int dpy = HWC_DISPLAY_VIRTUAL;
-
- if (list && list->outbuf && list->numHwLayers > 0) {
- uint32_t last = (uint32_t)list->numHwLayers - 1;
- hwc_layer_1_t *fbLayer = &list->hwLayers[last];
-
- if(ctx->dpyAttr[dpy].connected
- && (!ctx->dpyAttr[dpy].isPause))
- {
- private_handle_t *ohnd = (private_handle_t *)list->outbuf;
- int format = ohnd->format;
- if (format == HAL_PIXEL_FORMAT_RGBA_8888)
- format = HAL_PIXEL_FORMAT_RGBX_8888;
- Writeback::getInstance()->setOutputFormat(
- utils::getMdpFormat(format));
-
- // Configure WB secure mode based on output buffer handle
- if(! Writeback::getInstance()->setSecure(isSecureBuffer(ohnd)))
- {
- ALOGE("Failed to set WB secure mode: %d for virtual display",
- isSecureBuffer(ohnd));
- return false;
- }
-
- int fd = -1; //FenceFD from the Copybit
- hwc_sync(ctx, list, dpy, fd);
-
- // Dump the layers for virtual
- if(ctx->mHwcDebug[dpy])
- ctx->mHwcDebug[dpy]->dumpLayers(list);
-
- if (!ctx->mMDPComp[dpy]->draw(ctx, list)) {
- ALOGE("%s: MDPComp draw failed", __FUNCTION__);
- ret = -1;
- }
- // We need an FB layer handle check to cater for this usecase:
- // Video is playing in landscape on primary, then launch
- // ScreenRecord app.
- // In this scenario, the first VDS draw call will have HWC
- // composition and VDS does nit involve GPU to get eglSwapBuffer
- // to get valid fb handle.
- if (fbLayer->handle && !ctx->mFBUpdate[dpy]->draw(ctx,
- (private_handle_t *)fbLayer->handle)) {
- ALOGE("%s: FBUpdate::draw fail!", __FUNCTION__);
- ret = -1;
- }
-
- Writeback::getInstance()->queueBuffer(ohnd->fd,
- (uint32_t)ohnd->offset);
- if(!Overlay::displayCommit(ctx->dpyAttr[dpy].fd)) {
- ALOGE("%s: display commit fail!", __FUNCTION__);
- ret = -1;
- }
-
- if(sVDDumpEnabled) {
- char bufferName[128];
- // Dumping frame buffer
- sync_wait(fbLayer->acquireFenceFd, 1000);
- snprintf(bufferName, sizeof(bufferName), "vds.fb");
- dumpBuffer((private_handle_t *)fbLayer->handle, bufferName);
- // Dumping WB output for non-secure session
- if(!isSecureBuffer(ohnd)) {
- sync_wait(list->retireFenceFd, 1000);
- snprintf(bufferName, sizeof(bufferName), "vds.wb");
- dumpBuffer(ohnd, bufferName);
- }
- }
- } else if(list->outbufAcquireFenceFd >= 0) {
- //If we dont handle the frame, set retireFenceFd to outbufFenceFd,
- //which will make sure, the framework waits on it and closes it.
- //The other way is to wait on outbufFenceFd ourselves, close it and
- //set retireFenceFd to -1. Since we want hwc to be async, choosing
- //the former.
- //Also dup because, the closeAcquireFds() will close the outbufFence
- list->retireFenceFd = dup(list->outbufAcquireFenceFd);
- }
- }
-
- closeAcquireFds(list);
- return ret;
-}
-
-/* We set scaling mode on the VD if the output handle width and height
- differs from the virtual frame buffer width and height. */
-void HWCVirtualVDS::setMDPScalingMode(hwc_context_t* ctx,
- private_handle_t* ohnd, int dpy) {
- bool scalingMode = false;
- int fbWidth = ctx->dpyAttr[dpy].xres;
- int fbHeight = ctx->dpyAttr[dpy].yres;
- if((getWidth(ohnd) != fbWidth) || (getHeight(ohnd) != fbHeight)) {
- scalingMode = true;
- }
- ctx->dpyAttr[dpy].mMDPScalingMode = scalingMode;
-
- ALOGD_IF(HWCVIRTUAL_LOG, "%s fb(%dx%d) outputBuffer(%dx%d) scalingMode=%d",
- __FUNCTION__, fbWidth, fbHeight,
- getWidth(ohnd), getHeight(ohnd), scalingMode);
-}
diff --git a/msm8909/libhwcomposer/hwc_virtual.h b/msm8909/libhwcomposer/hwc_virtual.h
deleted file mode 100644
index bd1833c5..00000000
--- a/msm8909/libhwcomposer/hwc_virtual.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- * Copyright (C) 2012-2014, The Linux Foundation. All rights reserved.
- *
- * Not a Contribution, Apache license notifications and license are retained
- * for attribution purposes only.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef HWC_VIRTUAL
-#define HWC_VIRTUAL
-
-#include <hwc_utils.h>
-
-namespace qhwc {
-
-class HWCVirtualVDS {
-public:
- HWCVirtualVDS(){};
- ~HWCVirtualVDS(){};
- // Chooses composition type and configures pipe for each layer in virtual
- // display list
- int prepare(hwc_composer_device_1 *dev,
- hwc_display_contents_1_t* list);
- // Queues the buffer for each layer in virtual display list and call display
- // commit.
- int set(hwc_context_t *ctx, hwc_display_contents_1_t *list);
- // instantiates mdpcomp, copybit and fbupdate objects and initialize those
- // objects for virtual display during virtual display connect.
- void init(hwc_context_t *ctx);
- // Destroys mdpcomp, copybit and fbupdate objects and for virtual display
- // during virtual display disconnect.
- void destroy(hwc_context_t *ctx, size_t numDisplays,
- hwc_display_contents_1_t** displays);
- int getScalingHeight() const { return mScalingHeight; };
- int getScalingWidth() const { return mScalingWidth; };
- // We can dump the frame buffer and WB
- // output buffer by dynamically enabling
- // dumping via a binder call:
- // adb shell service call display.qservice 15 i32 3 i32 1
- static bool sVDDumpEnabled;
- static void dynamicDebug(bool enable) {sVDDumpEnabled = enable;};
-
-private:
- // These variables store the resolution that WB is being configured to
- // in the current draw cycle.
- int mScalingWidth, mScalingHeight;
- void setMDPScalingMode(hwc_context_t* ctx,
- private_handle_t* ohnd, int dpy);
-};
-
-}; //namespace
-#endif
diff --git a/msm8909/libhwcomposer/hwc_vsync.cpp b/msm8909/libhwcomposer/hwc_vsync.cpp
deleted file mode 100644
index ea3f672d..00000000
--- a/msm8909/libhwcomposer/hwc_vsync.cpp
+++ /dev/null
@@ -1,239 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- * Copyright (C) 2012-2014, The Linux Foundation. All rights reserved.
- *
- * Not a Contribution, Apache license notifications and license are
- * retained for attribution purposes only.
-
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <cutils/properties.h>
-#include <utils/Log.h>
-#include <fcntl.h>
-#include <sys/ioctl.h>
-#include <linux/msm_mdp.h>
-#include <sys/resource.h>
-#include <sys/prctl.h>
-#include <poll.h>
-#include "hwc_utils.h"
-#include "hdmi.h"
-#include "qd_utils.h"
-#include "string.h"
-#include "overlay.h"
-#include <inttypes.h>
-
-using namespace qdutils;
-namespace qhwc {
-
-#define HWC_VSYNC_THREAD_NAME "hwcVsyncThread"
-#define PANEL_ON_STR "panel_power_on ="
-#define ARRAY_LENGTH(array) (sizeof((array))/sizeof((array)[0]))
-#define MAX_THERMAL_LEVEL 3
-const int MAX_DATA = 64;
-
-int hwc_vsync_control(hwc_context_t* ctx, int dpy, int enable)
-{
- int ret = 0;
- if(!ctx->vstate.fakevsync &&
- ioctl(ctx->dpyAttr[dpy].fd, MSMFB_OVERLAY_VSYNC_CTRL,
- &enable) < 0) {
- ALOGE("%s: vsync control failed. Dpy=%d, enable=%d : %s",
- __FUNCTION__, dpy, enable, strerror(errno));
- ret = -errno;
- }
- return ret;
-}
-
-static void handle_vsync_event(hwc_context_t* ctx, int dpy, char *data)
-{
- // extract timestamp
- uint64_t timestamp = 0;
- if (!strncmp(data, "VSYNC=", strlen("VSYNC="))) {
- timestamp = strtoull(data + strlen("VSYNC="), NULL, 0);
- }
- // send timestamp to SurfaceFlinger
- ALOGD_IF (ctx->vstate.debug, "%s: timestamp %" PRIu64 " sent to SF for dpy=%d",
- __FUNCTION__, timestamp, dpy);
- ctx->proc->vsync(ctx->proc, dpy, timestamp);
-}
-
-static void handle_blank_event(hwc_context_t* ctx, int dpy, char *data)
-{
- if (!strncmp(data, PANEL_ON_STR, strlen(PANEL_ON_STR))) {
- unsigned long int poweron = strtoul(data + strlen(PANEL_ON_STR), NULL, 0);
- ALOGI("%s: dpy:%d panel power state: %ld", __FUNCTION__, dpy, poweron);
- if (!ctx->mHDMIDisplay->isHDMIPrimaryDisplay()) {
- ctx->dpyAttr[dpy].isActive = poweron ? true: false;
- }
- }
-}
-
-static void handle_thermal_event(hwc_context_t* ctx, int dpy, char *data)
-{
- // extract thermal level
- uint64_t thermalLevel = 0;
- if (!strncmp(data, "thermal_level=", strlen("thermal_level="))) {
- thermalLevel = strtoull(data + strlen("thermal_level="), NULL, 0);
- }
-
- if (thermalLevel >= MAX_THERMAL_LEVEL) {
- ALOGD("%s: dpy:%d thermal_level=%" PRIu64 "",__FUNCTION__,dpy,thermalLevel);
- ctx->mThermalBurstMode = true;
- } else
- ctx->mThermalBurstMode = false;
-}
-
-struct event {
- const char* name;
- void (*callback)(hwc_context_t* ctx, int dpy, char *data);
-};
-
-struct event event_list[] = {
- { "vsync_event", handle_vsync_event },
- { "show_blank_event", handle_blank_event },
- { "msm_fb_thermal_level", handle_thermal_event },
-};
-
-#define num_events ARRAY_LENGTH(event_list)
-
-static void *vsync_loop(void *param)
-{
- hwc_context_t * ctx = reinterpret_cast<hwc_context_t *>(param);
-
- char thread_name[64] = HWC_VSYNC_THREAD_NAME;
- prctl(PR_SET_NAME, (unsigned long) &thread_name, 0, 0, 0);
- struct sched_param sched_param = {0};
- sched_param.sched_priority = 5;
- if (sched_setscheduler(gettid(), SCHED_FIFO, &sched_param) != 0) {
- ALOGE("Couldn't set SCHED_FIFO for hwc_vsync");
- }
-
- char vdata[MAX_DATA];
- //Number of physical displays
- //We poll on all the nodes.
- int num_displays = HWC_NUM_DISPLAY_TYPES - 1;
- struct pollfd pfd[num_displays][num_events];
-
- char property[PROPERTY_VALUE_MAX];
- if(property_get("debug.hwc.fakevsync", property, NULL) > 0) {
- if(atoi(property) == 1)
- ctx->vstate.fakevsync = true;
- }
-
- char node_path[MAX_SYSFS_FILE_PATH];
-
- for (int dpy = HWC_DISPLAY_PRIMARY; dpy < num_displays; dpy++) {
- for(size_t ev = 0; ev < num_events; ev++) {
- snprintf(node_path, sizeof(node_path),
- "/sys/class/graphics/fb%d/%s",
- dpy == HWC_DISPLAY_PRIMARY ? 0 :
- overlay::Overlay::getInstance()->
- getFbForDpy(HWC_DISPLAY_EXTERNAL),
- event_list[ev].name);
-
- ALOGI("%s: Reading event %zu for dpy %d from %s", __FUNCTION__,
- ev, dpy, node_path);
- pfd[dpy][ev].fd = open(node_path, O_RDONLY);
-
- if (dpy == HWC_DISPLAY_PRIMARY && pfd[dpy][ev].fd < 0) {
- // Make sure fb device is opened before starting
- // this thread so this never happens.
- ALOGE ("%s:unable to open event node for dpy=%d event=%zu, %s",
- __FUNCTION__, dpy, ev, strerror(errno));
- if (ev == 0) {
- ctx->vstate.fakevsync = true;
- //XXX: Blank events don't work with fake vsync,
- //but we shouldn't be running on fake vsync anyway.
- break;
- }
- }
-
- memset(&vdata, '\0', sizeof(vdata));
- // Read once from the fds to clear the first notify
- pread(pfd[dpy][ev].fd, vdata , MAX_DATA - 1, 0);
- if (pfd[dpy][ev].fd >= 0)
- pfd[dpy][ev].events = POLLPRI | POLLERR;
- }
- }
-
- if (LIKELY(!ctx->vstate.fakevsync)) {
- do {
- int err = poll(reinterpret_cast<struct pollfd *>(pfd),
- (int)(num_displays * num_events), -1);
- if(err > 0) {
- for (int dpy = HWC_DISPLAY_PRIMARY; dpy < num_displays; dpy++) {
- for(size_t ev = 0; ev < num_events; ev++) {
- if (pfd[dpy][ev].revents & POLLPRI) {
- // Clear vdata before writing into it
- memset(&vdata, '\0', sizeof(vdata));
- ssize_t len = pread(pfd[dpy][ev].fd, vdata,
- MAX_DATA - 1, 0);
- if (UNLIKELY(len < 0)) {
- // If the read was just interrupted - it is not
- // a fatal error. Just continue in this case
- ALOGE ("%s: Unable to read event:%zu for \
- dpy=%d : %s",
- __FUNCTION__, ev, dpy, strerror(errno));
- continue;
- }
- vdata[len] = '\0';
- event_list[ev].callback(ctx, dpy, vdata);
- }
- }
- }
- } else {
- ALOGE("%s: poll failed errno: %s", __FUNCTION__,
- strerror(errno));
- continue;
- }
- } while (true);
-
- } else {
-
- //Fake vsync is used only when set explicitly through a property or when
- //the vsync timestamp node cannot be opened at bootup. There is no
- //fallback to fake vsync from the true vsync loop, ever, as the
- //condition can easily escape detection.
- //Also, fake vsync is delivered only for the primary display.
- do {
- usleep(16666);
- uint64_t timestamp = systemTime();
- ctx->proc->vsync(ctx->proc, HWC_DISPLAY_PRIMARY, timestamp);
-
- } while (true);
- }
-
- for (int dpy = HWC_DISPLAY_PRIMARY; dpy <= HWC_DISPLAY_EXTERNAL; dpy++ ) {
- for( size_t event = 0; event < num_events; event++) {
- if(pfd[dpy][event].fd >= 0)
- close (pfd[dpy][event].fd);
- }
- }
-
- return NULL;
-}
-
-void init_vsync_thread(hwc_context_t* ctx)
-{
- int ret;
- pthread_t vsync_thread;
- ALOGI("Initializing VSYNC Thread");
- ret = pthread_create(&vsync_thread, NULL, vsync_loop, (void*) ctx);
- if (ret) {
- ALOGE("%s: failed to create %s: %s", __FUNCTION__,
- HWC_VSYNC_THREAD_NAME, strerror(ret));
- }
-}
-
-}; //namespace
diff --git a/msm8909/liblight/Android.mk b/msm8909/liblight/Android.mk
index 9458a51b..bbb076f0 100644
--- a/msm8909/liblight/Android.mk
+++ b/msm8909/liblight/Android.mk
@@ -13,19 +13,21 @@
# limitations under the License.
LOCAL_PATH:= $(call my-dir)
-include $(LOCAL_PATH)/../common.mk
# HAL module implemenation stored in
# hw/<COPYPIX_HARDWARE_MODULE_ID>.<ro.board.platform>.so
include $(CLEAR_VARS)
-LOCAL_SRC_FILES := lights.c
+LOCAL_C_INCLUDES += $(TARGET_OUT_HEADERS)/common/inc
+LOCAL_C_INCLUDES += $(TARGET_OUT_HEADERS)/qdcm/inc
+
+LOCAL_SRC_FILES := lights.c lights_prv.cpp
LOCAL_MODULE_RELATIVE_PATH := hw
-LOCAL_PROPRIETARY_MODULE := true
-LOCAL_SHARED_LIBRARIES := liblog
-LOCAL_CFLAGS := $(common_flags) -DLOG_TAG=\"qdlights\"
+LOCAL_SHARED_LIBRARIES := liblog libcutils libsdm-disp-vndapis
+LOCAL_HEADER_LIBRARIES := libhardware_headers
+LOCAL_CFLAGS := -DLOG_TAG=\"qdlights\"
LOCAL_CLANG := true
LOCAL_MODULE := lights.$(TARGET_BOARD_PLATFORM)
LOCAL_MODULE_TAGS := optional
-LOCAL_CFLAGS += -Wno-error
+LOCAL_VENDOR_MODULE := true
include $(BUILD_SHARED_LIBRARY)
diff --git a/msm8909/liblight/lights.c b/msm8909/liblight/lights.c
index cf24d501..eed6a250 100644
--- a/msm8909/liblight/lights.c
+++ b/msm8909/liblight/lights.c
@@ -1,6 +1,7 @@
/*
+ * Copyright (C) 2014, 2017 The Linux Foundation. All rights reserved.
+ * Not a contribution
* Copyright (C) 2008 The Android Open Source Project
- * Copyright (C) 2014 The Linux Foundation. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,8 +19,8 @@
// #define LOG_NDEBUG 0
-#include <cutils/log.h>
-
+#include <log/log.h>
+#include <cutils/properties.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
@@ -32,6 +33,11 @@
#include <sys/types.h>
#include <hardware/lights.h>
+#include "lights_prv.h"
+
+#ifndef DEFAULT_LOW_PERSISTENCE_MODE_BRIGHTNESS
+#define DEFAULT_LOW_PERSISTENCE_MODE_BRIGHTNESS 0x80
+#endif
/******************************************************************************/
@@ -39,7 +45,9 @@ static pthread_once_t g_init = PTHREAD_ONCE_INIT;
static pthread_mutex_t g_lock = PTHREAD_MUTEX_INITIALIZER;
static struct light_state_t g_notification;
static struct light_state_t g_battery;
+static int g_last_backlight_mode = BRIGHTNESS_MODE_USER;
static int g_attention = 0;
+static int g_brightness_max = 0;
char const*const RED_LED_FILE
= "/sys/class/leds/red/brightness";
@@ -50,12 +58,12 @@ char const*const GREEN_LED_FILE
char const*const BLUE_LED_FILE
= "/sys/class/leds/blue/brightness";
-char const*const BLUETOOTH_LED_FILE
- = "/sys/class/leds/bt/brightness";
-
char const*const LCD_FILE
= "/sys/class/leds/lcd-backlight/brightness";
+char const*const LCD_FILE2
+ = "/sys/class/backlight/panel0-backlight/brightness";
+
char const*const BUTTON_FILE
= "/sys/class/leds/button-backlight/brightness";
@@ -68,6 +76,9 @@ char const*const GREEN_BLINK_FILE
char const*const BLUE_BLINK_FILE
= "/sys/class/leds/blue/blink";
+char const*const PERSISTENCE_FILE
+ = "/sys/class/graphics/fb0/msm_fb_persist_mode";
+
/**
* device methods
*/
@@ -120,12 +131,59 @@ set_light_backlight(struct light_device_t* dev,
{
int err = 0;
int brightness = rgb_to_brightness(state);
+ unsigned int lpEnabled =
+ state->brightnessMode == BRIGHTNESS_MODE_LOW_PERSISTENCE;
+ if(!dev) {
+ return -1;
+ }
+
+ pthread_mutex_lock(&g_lock);
+ // Toggle low persistence mode state
+ if ((g_last_backlight_mode != state->brightnessMode && lpEnabled) ||
+ (!lpEnabled &&
+ g_last_backlight_mode == BRIGHTNESS_MODE_LOW_PERSISTENCE)) {
+ if ((err = write_int(PERSISTENCE_FILE, lpEnabled)) != 0) {
+ ALOGE("%s: Failed to write to %s: %s\n", __FUNCTION__,
+ PERSISTENCE_FILE, strerror(errno));
+ }
+ if (lpEnabled != 0) {
+ brightness = DEFAULT_LOW_PERSISTENCE_MODE_BRIGHTNESS;
+ }
+ }
+
+ g_last_backlight_mode = state->brightnessMode;
+
+ if (!err) {
+ if (!access(LCD_FILE, F_OK)) {
+ err = write_int(LCD_FILE, brightness);
+ } else {
+ err = write_int(LCD_FILE2, brightness);
+ }
+ }
+
+ pthread_mutex_unlock(&g_lock);
+ return err;
+}
+
+static int
+set_light_backlight_ext(struct light_device_t* dev,
+ struct light_state_t const* state)
+{
+ int err = 0;
+
if(!dev) {
return -1;
}
+
+ int brightness = state->color & 0x00ffffff;
pthread_mutex_lock(&g_lock);
- err = write_int(LCD_FILE, brightness);
+
+ if (brightness >= 0 && brightness <= g_brightness_max) {
+ set_brightness_ext_level(brightness);
+ }
+
pthread_mutex_unlock(&g_lock);
+
return err;
}
@@ -184,15 +242,15 @@ set_speaker_light_locked(struct light_device_t* dev,
if (red) {
if (write_int(RED_BLINK_FILE, blink))
write_int(RED_LED_FILE, 0);
- }
+ }
if (green) {
if (write_int(GREEN_BLINK_FILE, blink))
write_int(GREEN_LED_FILE, 0);
- }
+ }
if (blue) {
if (write_int(BLUE_BLINK_FILE, blink))
write_int(BLUE_LED_FILE, 0);
- }
+ }
} else {
write_int(RED_LED_FILE, red);
write_int(GREEN_LED_FILE, green);
@@ -263,20 +321,6 @@ set_light_buttons(struct light_device_t* dev,
return err;
}
-static int
-set_light_bluetooth(struct light_device_t* dev,
- struct light_state_t const* state)
-{
- int err = 0;
- if(!dev) {
- return -1;
- }
- pthread_mutex_lock(&g_lock);
- err = write_int(BLUETOOTH_LED_FILE, state->color & 0xFF);
- pthread_mutex_unlock(&g_lock);
- return err;
-}
-
/** Close the lights device */
static int
close_lights(struct light_device_t *dev)
@@ -301,18 +345,32 @@ static int open_lights(const struct hw_module_t* module, char const* name,
int (*set_light)(struct light_device_t* dev,
struct light_state_t const* state);
- if (0 == strcmp(LIGHT_ID_BACKLIGHT, name))
- set_light = set_light_backlight;
- else if (0 == strcmp(LIGHT_ID_BATTERY, name))
+ if (0 == strcmp(LIGHT_ID_BACKLIGHT, name)) {
+ char property[PROPERTY_VALUE_MAX];
+ property_get("persist.extend.brightness", property, "0");
+
+ if(!(strncmp(property, "1", PROPERTY_VALUE_MAX)) ||
+ !(strncmp(property, "true", PROPERTY_VALUE_MAX))) {
+ property_get("persist.display.max_brightness", property, "255");
+ g_brightness_max = atoi(property);
+ set_brightness_ext_init();
+ set_light = set_light_backlight_ext;
+ } else
+ set_light = set_light_backlight;
+ } else if (0 == strcmp(LIGHT_ID_BATTERY, name))
set_light = set_light_battery;
else if (0 == strcmp(LIGHT_ID_NOTIFICATIONS, name))
set_light = set_light_notifications;
- else if (0 == strcmp(LIGHT_ID_BUTTONS, name))
- set_light = set_light_buttons;
+ else if (0 == strcmp(LIGHT_ID_BUTTONS, name)) {
+ if (!access(BUTTON_FILE, F_OK)) {
+ // enable light button when the file is present
+ set_light = set_light_buttons;
+ } else {
+ return -EINVAL;
+ }
+ }
else if (0 == strcmp(LIGHT_ID_ATTENTION, name))
set_light = set_light_attention;
- else if (0 == strcmp(LIGHT_ID_BLUETOOTH, name))
- set_light = set_light_bluetooth;
else
return -EINVAL;
@@ -326,7 +384,7 @@ static int open_lights(const struct hw_module_t* module, char const* name,
memset(dev, 0, sizeof(*dev));
dev->common.tag = HARDWARE_DEVICE_TAG;
- dev->common.version = 0;
+ dev->common.version = LIGHTS_DEVICE_API_VERSION_2_0;
dev->common.module = (struct hw_module_t*)module;
dev->common.close = (int (*)(struct hw_device_t*))close_lights;
dev->set_light = set_light;
diff --git a/msm8909/libhwcomposer/hwc_qclient.h b/msm8909/liblight/lights_prv.cpp
index d9553773..f916ed2f 100644
--- a/msm8909/libhwcomposer/hwc_qclient.h
+++ b/msm8909/liblight/lights_prv.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -20,48 +20,35 @@
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR CLIENTS; LOSS OF USE, DATA, OR PROFITS; OR
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef ANDROID_QCLIENT_H
-#define ANDROID_QCLIENT_H
-#include <utils/Errors.h>
-#include <sys/types.h>
-#include <cutils/log.h>
-#include <binder/IServiceManager.h>
-#include <media/IMediaDeathNotifier.h>
-#include <IQClient.h>
-struct hwc_context_t;
+#include <hardware/hwcomposer_defs.h>
+#include "disp_color_apis.h"
+#include "lights_prv.h"
-class Params;
-namespace qClient {
-// ----------------------------------------------------------------------------
+/******************************************************************************/
+static DISPAPI_HANDLE g_ctx;
-class QClient : public BnQClient {
-public:
- QClient(hwc_context_t *ctx);
- virtual ~QClient();
- virtual android::status_t notifyCallback(uint32_t command,
- const android::Parcel* inParcel,
- android::Parcel* outParcel);
+/**
+ * device methods
+ */
+
+void set_brightness_ext_init(void)
+{
+ disp_api_init((DISPAPI_HANDLE*) &g_ctx, 0);
+}
-private:
- //Notifies of Media Player death
- class MPDeathNotifier : public android::IMediaDeathNotifier {
- public:
- MPDeathNotifier(hwc_context_t* ctx) : mHwcContext(ctx){}
- virtual void died();
- hwc_context_t *mHwcContext;
- };
+int set_brightness_ext_level(int level)
+{
+ int err = disp_api_set_panel_brightness_level_ext(g_ctx, HWC_DISPLAY_PRIMARY,
+ level, 0);
- hwc_context_t *mHwcContext;
- const android::sp<android::IMediaDeathNotifier> mMPDeathNotifier;
-};
-}; // namespace qClient
-#endif // ANDROID_QCLIENT_H
+ return err;
+}
diff --git a/msm8909/libhwcomposer/hwc_qdcm_legacy.cpp b/msm8909/liblight/lights_prv.h
index f9ce09fd..e0ec7362 100644
--- a/msm8909/libhwcomposer/hwc_qdcm_legacy.cpp
+++ b/msm8909/liblight/lights_prv.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014,2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -27,53 +27,17 @@
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include <hwc_qdcm.h>
-#include <hwc_utils.h>
-#include <IQService.h>
-#include <mdp_version.h>
-#include <dlfcn.h>
+#ifndef LIGHTS_PRV_H
+#define LIGHTS_PRV_H
-using namespace android;
-using namespace qService;
-using namespace qhwc;
+#ifdef __cplusplus
+extern "C" {
+#endif
-namespace qQdcm {
-//----------------------------------------------------------------------------
-void qdcmInitContext(hwc_context_t* /*ctx*/)
-{
-}
+extern void set_brightness_ext_init(void);
+extern int set_brightness_ext_level(int level);
-void qdcmCloseContext(hwc_context_t* /*ctx*/)
-{
+#ifdef __cplusplus
}
-
-void qdcmApplyDefaultAfterBootAnimationDone(hwc_context_t* /*ctx*/)
-{
- int ret = 0;
- int (*applyMode)(int) = NULL;
- void *modeHandle = NULL;
-
- modeHandle = dlopen("libmm-qdcm.so", RTLD_NOW);
- if (modeHandle) {
- *(void **)&applyMode = dlsym(modeHandle, "applyDefaults");
- if (applyMode) {
- ret = applyMode(HWC_DISPLAY_PRIMARY);
- if (ret)
- ALOGE("%s: Not able to apply default mode", __FUNCTION__);
- } else {
- ALOGE("%s: No symbol applyDefaults found", __FUNCTION__);
- }
- dlclose(modeHandle);
- } else {
- ALOGE("%s: Not able to load libmm-qdcm.so", __FUNCTION__);
- }
-}
-
-//do nothing in case qdcm legacy implementation.
-void qdcmCmdsHandler(hwc_context_t* /*ctx*/, const Parcel* /*in*/, Parcel* /*out*/)
-{
-}
-
-
-} //namespace qQdcm
-
+#endif
+#endif
diff --git a/msm8909/libmemtrack/Android.mk b/msm8909/libmemtrack/Android.mk
index a73cfd75..10fd40a9 100644
--- a/msm8909/libmemtrack/Android.mk
+++ b/msm8909/libmemtrack/Android.mk
@@ -19,12 +19,12 @@ LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE_RELATIVE_PATH := hw
-LOCAL_PROPRIETARY_MODULE := true
+LOCAL_VENDOR_MODULE := true
LOCAL_C_INCLUDES += hardware/libhardware/include
LOCAL_CFLAGS := -Wconversion -Wall -Werror -Wno-sign-conversion
LOCAL_CLANG := true
LOCAL_SHARED_LIBRARIES := liblog
+LOCAL_HEADER_LIBRARIES := libhardware_headers
LOCAL_SRC_FILES := memtrack_msm.c kgsl.c
LOCAL_MODULE := memtrack.$(TARGET_BOARD_PLATFORM)
-LOCAL_CFLAGS += -Wno-error
include $(BUILD_SHARED_LIBRARY)
diff --git a/msm8909/libmemtrack/kgsl.c b/msm8909/libmemtrack/kgsl.c
index ce6a035f..69ee9018 100644
--- a/msm8909/libmemtrack/kgsl.c
+++ b/msm8909/libmemtrack/kgsl.c
@@ -74,7 +74,7 @@ int kgsl_memtrack_get_memory(pid_t pid, enum memtrack_type type,
while (1) {
unsigned long size, mapsize;
char line_type[7];
- char flags[8];
+ char flags[10];
char line_usage[19];
int ret, egl_surface_count = 0, egl_image_count = 0;
@@ -83,12 +83,12 @@ int kgsl_memtrack_get_memory(pid_t pid, enum memtrack_type type,
}
/* Format:
- * gpuaddr useraddr size id flags type usage sglen mapsize egLsrf egLimg
- * 545ba000 545ba000 4096 1 -----pY gpumem arraybuffer 1 4096 0 0
+ * gpuaddr useraddr size id flags type usage sglen mapsize eglsrf eglimg
+ * 545ba000 545ba000 4096 1 -----pY gpumem arraybuffer 1 4096 0 0
*/
- ret = sscanf(line, "%*x %*x %lu %*d %6s %6s %18s %*d %lu %6d %6d\n",
- &size, flags, line_type, line_usage, &mapsize,
- &egl_surface_count, &egl_image_count);
+ ret = sscanf(line, "%*x %*x %lu %*d %9s %6s %18s %*d %lu %6d %6d\n",
+ &size, flags, line_type, line_usage, &mapsize,
+ &egl_surface_count, &egl_image_count);
if (ret != 7) {
continue;
}
@@ -110,6 +110,7 @@ int kgsl_memtrack_get_memory(pid_t pid, enum memtrack_type type,
fclose(fp);
return -ERANGE;
}
+
accounted_size += mapsize;
if (mapsize > size) {
diff --git a/msm8909/liboverlay/Android.mk b/msm8909/liboverlay/Android.mk
deleted file mode 100644
index 5c59d0f9..00000000
--- a/msm8909/liboverlay/Android.mk
+++ /dev/null
@@ -1,23 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-include $(LOCAL_PATH)/../common.mk
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := liboverlay
-LOCAL_MODULE_TAGS := optional
-LOCAL_C_INCLUDES := $(common_includes) $(kernel_includes)
-LOCAL_SHARED_LIBRARIES := $(common_libs) libqdutils libmemalloc \
- libsync libdl
-LOCAL_CFLAGS := $(common_flags) -DLOG_TAG=\"qdoverlay\"
-LOCAL_CLANG := $(common_clang_flags)
-LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps)
-LOCAL_SRC_FILES := \
- overlay.cpp \
- overlayUtils.cpp \
- overlayMdp.cpp \
- overlayRotator.cpp \
- overlayMdpRot.cpp \
- overlayMdssRot.cpp \
- overlayWriteback.cpp \
- pipes/overlayGenPipe.cpp
-
-include $(BUILD_SHARED_LIBRARY)
diff --git a/msm8909/liboverlay/mdpWrapper.h b/msm8909/liboverlay/mdpWrapper.h
deleted file mode 100644
index f689e45f..00000000
--- a/msm8909/liboverlay/mdpWrapper.h
+++ /dev/null
@@ -1,388 +0,0 @@
-/*
-* Copyright (c) 2011, The Linux Foundation. All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions are
-* met:
-* * Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
-* * Redistributions in binary form must reproduce the above
-* copyright notice, this list of conditions and the following
-* disclaimer in the documentation and/or other materials provided
-* with the distribution.
-* * Neither the name of The Linux Foundation nor the names of its
-* contributors may be used to endorse or promote products derived
-* from this software without specific prior written permission.
-*
-* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
-* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
-* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
-* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
-* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
-* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-#ifndef MDP_WRAPPER_H
-#define MDP_WRAPPER_H
-
-#define ATRACE_TAG (ATRACE_TAG_GRAPHICS | ATRACE_TAG_HAL)
-
-/*
-* In order to make overlay::mdp_wrapper shorter, please do something like:
-* namespace mdpwrap = overlay::mdp_wrapper;
-* */
-
-#include <linux/msm_mdp.h>
-#include <linux/msm_rotator.h>
-#include <sys/ioctl.h>
-#include <utils/Log.h>
-#include <utils/Trace.h>
-#include <errno.h>
-#include "overlayUtils.h"
-#include "overlay.h"
-
-#define IOCTL_DEBUG 0
-#define LIKELY( exp ) (__builtin_expect( (exp) != 0, true ))
-#define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false ))
-
-namespace overlay{
-
-namespace mdp_wrapper{
-/* FBIOGET_FSCREENINFO */
-bool getFScreenInfo(int fd, fb_fix_screeninfo& finfo);
-
-/* FBIOGET_VSCREENINFO */
-bool getVScreenInfo(int fd, fb_var_screeninfo& vinfo);
-
-/* FBIOPUT_VSCREENINFO */
-bool setVScreenInfo(int fd, fb_var_screeninfo& vinfo);
-
-/* MSM_ROTATOR_IOCTL_START */
-bool startRotator(int fd, msm_rotator_img_info& rot);
-
-/* MSM_ROTATOR_IOCTL_ROTATE */
-bool rotate(int fd, msm_rotator_data_info& rot);
-
-/* MSMFB_OVERLAY_SET */
-bool setOverlay(int fd, mdp_overlay& ov);
-
-/* MSMFB_OVERLAY_PREPARE */
-int validateAndSet(const int& fd, mdp_overlay_list& list);
-
-/* MSM_ROTATOR_IOCTL_FINISH */
-bool endRotator(int fd, int sessionId);
-
-/* MSMFB_OVERLAY_UNSET */
-bool unsetOverlay(int fd, int ovId);
-
-/* MSMFB_OVERLAY_GET */
-bool getOverlay(int fd, mdp_overlay& ov);
-
-/* MSMFB_OVERLAY_PLAY */
-bool play(int fd, msmfb_overlay_data& od);
-
-/* MSMFB_DISPLAY_COMMIT */
-bool displayCommit(int fd);
-
-/* MSMFB_WRITEBACK_INIT, MSMFB_WRITEBACK_START */
-bool wbInitStart(int fbfd);
-
-/* MSMFB_WRITEBACK_STOP, MSMFB_WRITEBACK_TERMINATE */
-bool wbStopTerminate(int fbfd);
-
-/* MSMFB_WRITEBACK_QUEUE_BUFFER */
-bool wbQueueBuffer(int fbfd, struct msmfb_data& fbData);
-
-/* MSMFB_WRITEBACK_DEQUEUE_BUFFER */
-bool wbDequeueBuffer(int fbfd, struct msmfb_data& fbData);
-
-/* the following are helper functions for dumping
- * msm_mdp and friends*/
-void dump(const char* const s, const msmfb_overlay_data& ov);
-void dump(const char* const s, const msmfb_data& ov);
-void dump(const char* const s, const mdp_overlay& ov);
-void dump(const char* const s, const uint32_t u[], uint32_t cnt);
-void dump(const char* const s, const msmfb_img& ov);
-void dump(const char* const s, const mdp_rect& ov);
-
-/* and rotator */
-void dump(const char* const s, const msm_rotator_img_info& rot);
-void dump(const char* const s, const msm_rotator_data_info& rot);
-
-/* info */
-void dump(const char* const s, const fb_fix_screeninfo& finfo);
-void dump(const char* const s, const fb_var_screeninfo& vinfo);
-
-//---------------Inlines -------------------------------------
-
-inline bool getFScreenInfo(int fd, fb_fix_screeninfo& finfo) {
- ATRACE_CALL();
- if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) < 0) {
- ALOGE("Failed to call ioctl FBIOGET_FSCREENINFO err=%s",
- strerror(errno));
- return false;
- }
- return true;
-}
-
-inline bool getVScreenInfo(int fd, fb_var_screeninfo& vinfo) {
- ATRACE_CALL();
- if (ioctl(fd, FBIOGET_VSCREENINFO, &vinfo) < 0) {
- ALOGE("Failed to call ioctl FBIOGET_VSCREENINFO err=%s",
- strerror(errno));
- return false;
- }
- return true;
-}
-
-inline bool setVScreenInfo(int fd, fb_var_screeninfo& vinfo) {
- ATRACE_CALL();
- if (ioctl(fd, FBIOPUT_VSCREENINFO, &vinfo) < 0) {
- ALOGE("Failed to call ioctl FBIOPUT_VSCREENINFO err=%s",
- strerror(errno));
- return false;
- }
- return true;
-}
-
-inline bool startRotator(int fd, msm_rotator_img_info& rot) {
- ATRACE_CALL();
- if (ioctl(fd, MSM_ROTATOR_IOCTL_START, &rot) < 0){
- ALOGE("Failed to call ioctl MSM_ROTATOR_IOCTL_START err=%s",
- strerror(errno));
- return false;
- }
- return true;
-}
-
-inline bool rotate(int fd, msm_rotator_data_info& rot) {
- ATRACE_CALL();
- if (ioctl(fd, MSM_ROTATOR_IOCTL_ROTATE, &rot) < 0) {
- ALOGE("Failed to call ioctl MSM_ROTATOR_IOCTL_ROTATE err=%s",
- strerror(errno));
- return false;
- }
- return true;
-}
-
-inline bool setOverlay(int fd, mdp_overlay& ov) {
- ATRACE_CALL();
- if (ioctl(fd, MSMFB_OVERLAY_SET, &ov) < 0) {
- ALOGE("Failed to call ioctl MSMFB_OVERLAY_SET err=%s",
- strerror(errno));
- return false;
- }
- return true;
-}
-
-inline int validateAndSet(const int& fd, mdp_overlay_list& list) {
- ATRACE_CALL();
- uint32_t id = 0;
- if(UNLIKELY(Overlay::isDebugPipeLifecycle())) {
- for(uint32_t i = 0; i < list.num_overlays; i++) {
- if(list.overlay_list[i]->id != (uint32_t)MSMFB_NEW_REQUEST) {
- id |= list.overlay_list[i]->id;
- }
- }
-
- ALOGD("%s Total pipes needed: %d, Exisiting pipe mask 0x%04x",
- __FUNCTION__, list.num_overlays, id);
- id = 0;
- }
-
- if (ioctl(fd, MSMFB_OVERLAY_PREPARE, &list) < 0) {
- ALOGD_IF(IOCTL_DEBUG, "Failed to call ioctl MSMFB_OVERLAY_PREPARE "
- "err=%s", strerror(errno));
- return errno;
- }
-
- if(UNLIKELY(Overlay::isDebugPipeLifecycle())) {
- for(uint32_t i = 0; i < list.num_overlays; i++) {
- id |= list.overlay_list[i]->id;
- }
-
- ALOGD("%s Pipe mask after OVERLAY_PREPARE 0x%04x", __FUNCTION__, id);
- }
-
- return 0;
-}
-
-inline bool endRotator(int fd, uint32_t sessionId) {
- ATRACE_CALL();
- if (ioctl(fd, MSM_ROTATOR_IOCTL_FINISH, &sessionId) < 0) {
- ALOGE("Failed to call ioctl MSM_ROTATOR_IOCTL_FINISH err=%s",
- strerror(errno));
- return false;
- }
- return true;
-}
-
-inline bool unsetOverlay(int fd, int ovId) {
- ATRACE_CALL();
- ALOGD_IF(Overlay::isDebugPipeLifecycle(), "%s Unsetting pipe 0x%04x",
- __FUNCTION__, ovId);
-
- if (ioctl(fd, MSMFB_OVERLAY_UNSET, &ovId) < 0) {
- ALOGE("Failed to call ioctl MSMFB_OVERLAY_UNSET err=%s",
- strerror(errno));
- return false;
- }
- return true;
-}
-
-inline bool getOverlay(int fd, mdp_overlay& ov) {
- ATRACE_CALL();
- if (ioctl(fd, MSMFB_OVERLAY_GET, &ov) < 0) {
- ALOGE("Failed to call ioctl MSMFB_OVERLAY_GET err=%s",
- strerror(errno));
- return false;
- }
- return true;
-}
-
-inline bool play(int fd, msmfb_overlay_data& od) {
- ATRACE_CALL();
- if (ioctl(fd, MSMFB_OVERLAY_PLAY, &od) < 0) {
- ALOGE("Failed to call ioctl MSMFB_OVERLAY_PLAY err=%s",
- strerror(errno));
- return false;
- }
- return true;
-}
-
-inline bool displayCommit(int fd, mdp_display_commit& info) {
- ATRACE_CALL();
- ALOGD_IF(Overlay::isDebugPipeLifecycle(), "%s", __FUNCTION__);
-
- if(ioctl(fd, MSMFB_DISPLAY_COMMIT, &info) == -1) {
- ALOGE("Failed to call ioctl MSMFB_DISPLAY_COMMIT err=%s",
- strerror(errno));
- return false;
- }
- return true;
-}
-
-inline bool wbInitStart(int fbfd) {
- ATRACE_CALL();
- if(ioctl(fbfd, MSMFB_WRITEBACK_INIT, NULL) < 0) {
- ALOGE("Failed to call ioctl MSMFB_WRITEBACK_INIT err=%s",
- strerror(errno));
- return false;
- }
- if(ioctl(fbfd, MSMFB_WRITEBACK_START, NULL) < 0) {
- ALOGE("Failed to call ioctl MSMFB_WRITEBACK_START err=%s",
- strerror(errno));
- return false;
- }
- return true;
-}
-
-inline bool wbStopTerminate(int fbfd) {
- ATRACE_CALL();
- if(ioctl(fbfd, MSMFB_WRITEBACK_STOP, NULL) < 0) {
- ALOGE("Failed to call ioctl MSMFB_WRITEBACK_STOP err=%s",
- strerror(errno));
- return false;
- }
- if(ioctl(fbfd, MSMFB_WRITEBACK_TERMINATE, NULL) < 0) {
- ALOGE("Failed to call ioctl MSMFB_WRITEBACK_TERMINATE err=%s",
- strerror(errno));
- return false;
- }
- return true;
-}
-
-inline bool wbQueueBuffer(int fbfd, struct msmfb_data& fbData) {
- ATRACE_CALL();
- if(ioctl(fbfd, MSMFB_WRITEBACK_QUEUE_BUFFER, &fbData) < 0) {
- ALOGE("Failed to call ioctl MSMFB_WRITEBACK_QUEUE_BUFFER err=%s",
- strerror(errno));
- return false;
- }
- return true;
-}
-
-inline bool wbDequeueBuffer(int fbfd, struct msmfb_data& fbData) {
- ATRACE_CALL();
- if(ioctl(fbfd, MSMFB_WRITEBACK_DEQUEUE_BUFFER, &fbData) < 0) {
- ALOGE("Failed to call ioctl MSMFB_WRITEBACK_DEQUEUE_BUFFER err=%s",
- strerror(errno));
- return false;
- }
- return true;
-}
-
-/* dump funcs */
-inline void dump(const char* const s, const msmfb_overlay_data& ov) {
- ALOGE("%s msmfb_overlay_data id=%d",
- s, ov.id);
- dump("data", ov.data);
-}
-inline void dump(const char* const s, const msmfb_data& ov) {
- ALOGE("%s msmfb_data offset=%d memid=%d id=%d flags=0x%x priv=%d",
- s, ov.offset, ov.memory_id, ov.id, ov.flags, ov.priv);
-}
-inline void dump(const char* const s, const mdp_overlay& ov) {
- ALOGE("%s mdp_overlay z=%d alpha=%d mask=%d flags=0x%x id=%d",
- s, ov.z_order, ov.alpha,
- ov.transp_mask, ov.flags, ov.id);
- dump("src", ov.src);
- dump("src_rect", ov.src_rect);
- dump("dst_rect", ov.dst_rect);
- /*
- Commented off to prevent verbose logging, since user_data could have 8 or so
- fields which are mostly 0
- dump("user_data", ov.user_data,
- sizeof(ov.user_data)/sizeof(ov.user_data[0]));
- */
-}
-inline void dump(const char* const s, const msmfb_img& ov) {
- ALOGE("%s msmfb_img w=%d h=%d format=%d %s",
- s, ov.width, ov.height, ov.format,
- overlay::utils::getFormatString(ov.format));
-}
-inline void dump(const char* const s, const mdp_rect& ov) {
- ALOGE("%s mdp_rect x=%d y=%d w=%d h=%d",
- s, ov.x, ov.y, ov.w, ov.h);
-}
-
-inline void dump(const char* const s, const uint32_t u[], uint32_t cnt) {
- ALOGE("%s user_data cnt=%d", s, cnt);
- for(uint32_t i=0; i < cnt; ++i) {
- ALOGE("i=%d val=%d", i, u[i]);
- }
-}
-inline void dump(const char* const s, const msm_rotator_img_info& rot) {
- ALOGE("%s msm_rotator_img_info sessid=%u dstx=%d dsty=%d rot=%d, ena=%d scale=%d",
- s, rot.session_id, rot.dst_x, rot.dst_y,
- rot.rotations, rot.enable, rot.downscale_ratio);
- dump("src", rot.src);
- dump("dst", rot.dst);
- dump("src_rect", rot.src_rect);
-}
-inline void dump(const char* const s, const msm_rotator_data_info& rot) {
- ALOGE("%s msm_rotator_data_info sessid=%u verkey=%d",
- s, rot.session_id, rot.version_key);
- dump("src", rot.src);
- dump("dst", rot.dst);
- dump("src_chroma", rot.src_chroma);
- dump("dst_chroma", rot.dst_chroma);
-}
-inline void dump(const char* const s, const fb_fix_screeninfo& finfo) {
- ALOGE("%s fb_fix_screeninfo type=%d", s, finfo.type);
-}
-inline void dump(const char* const s, const fb_var_screeninfo& vinfo) {
- ALOGE("%s fb_var_screeninfo xres=%d yres=%d",
- s, vinfo.xres, vinfo.yres);
-}
-
-} // mdp_wrapper
-
-} // overlay
-
-#endif // MDP_WRAPPER_H
diff --git a/msm8909/liboverlay/overlay.cpp b/msm8909/liboverlay/overlay.cpp
deleted file mode 100644
index 1a4bf03d..00000000
--- a/msm8909/liboverlay/overlay.cpp
+++ /dev/null
@@ -1,582 +0,0 @@
-/*
-* Copyright (c) 2011-2014, The Linux Foundation. All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions are
-* met:
-* * Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
-* * Redistributions in binary form must reproduce the above
-* copyright notice, this list of conditions and the following
-* disclaimer in the documentation and/or other materials provided
-* with the distribution.
-* * Neither the name of The Linux Foundation nor the names of its
-* contributors may be used to endorse or promote products derived
-* from this software without specific prior written permission.
-*
-* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
-* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
-* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
-* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
-* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
-* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-#include <dlfcn.h>
-#include "overlay.h"
-#include "pipes/overlayGenPipe.h"
-#include "mdp_version.h"
-#include "qdMetaData.h"
-#include "qd_utils.h"
-
-namespace overlay {
-using namespace utils;
-using namespace qdutils;
-
-Overlay::Overlay() {
- int numPipes = qdutils::MDPVersion::getInstance().getTotalPipes();
- PipeBook::NUM_PIPES = (numPipes <= utils::OV_MAX)? numPipes : utils::OV_MAX;
- for(int i = 0; i < PipeBook::NUM_PIPES; i++) {
- mPipeBook[i].init();
- }
-
- initScalar();
- setDMAMultiplexingSupported();
-}
-
-Overlay::~Overlay() {
- for(int i = 0; i < PipeBook::NUM_PIPES; i++) {
- mPipeBook[i].destroy();
- }
- destroyScalar();
-}
-
-void Overlay::configBegin() {
- for(int i = 0; i < PipeBook::NUM_PIPES; i++) {
- //Mark as available for this round.
- PipeBook::resetUse(i);
- PipeBook::resetAllocation(i);
- }
-}
-
-void Overlay::configDone() {
- for(int i = 0; i < PipeBook::NUM_PIPES; i++) {
- if((PipeBook::isNotUsed(i) && !sessionInProgress((eDest)i)) ||
- isSessionEnded((eDest)i)) {
- //Forces UNSET on pipes, flushes rotator memory and session, closes
- //fds
- mPipeBook[i].destroy();
- }
- }
- PipeBook::save();
-}
-
-int Overlay::getPipeId(utils::eDest dest) {
- return mPipeBook[(int)dest].mPipe->getPipeId();
-}
-
-eDest Overlay::getDest(int pipeid) {
- eDest dest = OV_INVALID;
- // finding the dest corresponding to the given pipe
- for(int i=0; i < PipeBook::NUM_PIPES; ++i) {
- if(mPipeBook[i].valid() && mPipeBook[i].mPipe->getPipeId() == pipeid) {
- return (eDest)i;
- }
- }
- return dest;
-}
-
-eDest Overlay::reservePipe(int pipeid) {
- eDest dest = getDest(pipeid);
- PipeBook::setAllocation((int)dest);
- return dest;
-}
-
-eDest Overlay::nextPipe(eMdpPipeType type, const PipeSpecs& pipeSpecs) {
- eDest dest = OV_INVALID;
- int dpy = pipeSpecs.dpy;
- int mixer = pipeSpecs.mixer;
- int formatType = pipeSpecs.formatClass;
- for(int i = 0; i < PipeBook::NUM_PIPES; i++) {
- if( (type == OV_MDP_PIPE_ANY || //Pipe type match
- type == PipeBook::getPipeType((eDest)i)) &&
- (mPipeBook[i].mDisplay == DPY_UNUSED || //Free or same display
- mPipeBook[i].mDisplay == dpy) &&
- (mPipeBook[i].mMixer == MIXER_UNUSED || //Free or same mixer
- mPipeBook[i].mMixer == mixer) &&
- (mPipeBook[i].mFormatType == FORMAT_NONE || //Free or same format
- mPipeBook[i].mFormatType == formatType) &&
- PipeBook::isNotAllocated(i) && //Free pipe
- ( (sDMAMultiplexingSupported && dpy) ||
- !(sDMAMode == DMA_BLOCK_MODE && //DMA pipe in Line mode
- PipeBook::getPipeType((eDest)i) == OV_MDP_PIPE_DMA)) ){
- //DMA-Multiplexing is only supported for WB on 8x26
- dest = (eDest)i;
- PipeBook::setAllocation(i);
- break;
- }
- }
-
- if(dest != OV_INVALID) {
- int index = (int)dest;
- mPipeBook[index].mDisplay = dpy;
- mPipeBook[index].mMixer = mixer;
- mPipeBook[index].mFormatType = formatType;
- if(not mPipeBook[index].valid()) {
- mPipeBook[index].mPipe = new GenericPipe(dpy);
- mPipeBook[index].mSession = PipeBook::NONE;
- }
- }
-
- return dest;
-}
-
-utils::eDest Overlay::getPipe(const PipeSpecs& pipeSpecs) {
- if(MDPVersion::getInstance().is8x26()) {
- return getPipe_8x26(pipeSpecs);
- } else if(MDPVersion::getInstance().is8x16()) {
- return getPipe_8x16(pipeSpecs);
- } else if(MDPVersion::getInstance().is8x39()) {
- return getPipe_8x39(pipeSpecs);
- } else if(MDPVersion::getInstance().is8994()) {
- return getPipe_8994(pipeSpecs);
- }
-
- eDest dest = OV_INVALID;
-
- //The default behavior is to assume RGB and VG pipes have scalars
- if(pipeSpecs.formatClass == FORMAT_YUV) {
- return nextPipe(OV_MDP_PIPE_VG, pipeSpecs);
- } else if(pipeSpecs.fb == false) { //RGB App layers
- if(not pipeSpecs.needsScaling) {
- dest = nextPipe(OV_MDP_PIPE_DMA, pipeSpecs);
- }
- if(dest == OV_INVALID) {
- dest = nextPipe(OV_MDP_PIPE_RGB, pipeSpecs);
- }
- if(dest == OV_INVALID) {
- dest = nextPipe(OV_MDP_PIPE_VG, pipeSpecs);
- }
- } else { //FB layer
- dest = nextPipe(OV_MDP_PIPE_RGB, pipeSpecs);
- if(dest == OV_INVALID) {
- dest = nextPipe(OV_MDP_PIPE_VG, pipeSpecs);
- }
- //Some features can cause FB to have scaling as well.
- //If we ever come to this block with FB needing scaling,
- //the screen will be black for a frame, since the FB won't get a pipe
- //but atleast this will prevent a hang
- if(dest == OV_INVALID and (not pipeSpecs.needsScaling)) {
- dest = nextPipe(OV_MDP_PIPE_DMA, pipeSpecs);
- }
- }
- return dest;
-}
-
-utils::eDest Overlay::getPipe_8x26(const PipeSpecs& pipeSpecs) {
- //Use this to hide all the 8x26 requirements that cannot be humanly
- //described in a generic way
- eDest dest = OV_INVALID;
- if(pipeSpecs.formatClass == FORMAT_YUV) { //video
- return nextPipe(OV_MDP_PIPE_VG, pipeSpecs);
- } else if(pipeSpecs.fb == false) { //RGB app layers
- if((not pipeSpecs.needsScaling) and
- (not (pipeSpecs.numActiveDisplays > 1 &&
- pipeSpecs.dpy == DPY_PRIMARY))) {
- dest = nextPipe(OV_MDP_PIPE_DMA, pipeSpecs);
- }
- if(dest == OV_INVALID) {
- dest = nextPipe(OV_MDP_PIPE_RGB, pipeSpecs);
- }
- if(dest == OV_INVALID) {
- dest = nextPipe(OV_MDP_PIPE_VG, pipeSpecs);
- }
- } else { //FB layer
- //For 8x26 Secondary we use DMA always for FB for inline rotation
- if(pipeSpecs.dpy == DPY_PRIMARY) {
- dest = nextPipe(OV_MDP_PIPE_RGB, pipeSpecs);
- if(dest == OV_INVALID) {
- dest = nextPipe(OV_MDP_PIPE_VG, pipeSpecs);
- }
- }
- if(dest == OV_INVALID and (not pipeSpecs.needsScaling) and
- (not (pipeSpecs.numActiveDisplays > 1 &&
- pipeSpecs.dpy == DPY_PRIMARY))) {
- dest = nextPipe(OV_MDP_PIPE_DMA, pipeSpecs);
- }
- }
- return dest;
-}
-
-utils::eDest Overlay::getPipe_8x16(const PipeSpecs& pipeSpecs) {
- //Having such functions help keeping the interface generic but code specific
- //and rife with assumptions
- eDest dest = OV_INVALID;
- if(pipeSpecs.formatClass == FORMAT_YUV or pipeSpecs.needsScaling) {
- return nextPipe(OV_MDP_PIPE_VG, pipeSpecs);
- } else {
- //Since this is a specific func, we can assume stuff like RGB pipe not
- //having scalar blocks
- dest = nextPipe(OV_MDP_PIPE_RGB, pipeSpecs);
- if(dest == OV_INVALID) {
- dest = nextPipe(OV_MDP_PIPE_DMA, pipeSpecs);
- }
- if(dest == OV_INVALID) {
- dest = nextPipe(OV_MDP_PIPE_VG, pipeSpecs);
- }
- }
- return dest;
-}
-
-utils::eDest Overlay::getPipe_8x39(const PipeSpecs& pipeSpecs) {
- //8x16 & 8x36 has same number of pipes, pipe-types & scaling capabilities.
- //Rely on 8x16 until we see a need to change.
- return getPipe_8x16(pipeSpecs);
-}
-
-utils::eDest Overlay::getPipe_8994(const PipeSpecs& pipeSpecs) {
- //If DMA pipes need to be used in block mode for downscale, there could be
- //cases where consecutive rounds need separate modes, which cannot be
- //supported since we at least need 1 round in between where the DMA is
- //unused
- eDest dest = OV_INVALID;
- if(pipeSpecs.formatClass == FORMAT_YUV) {
- return nextPipe(OV_MDP_PIPE_VG, pipeSpecs);
- } else {
- dest = nextPipe(OV_MDP_PIPE_RGB, pipeSpecs);
- if(dest == OV_INVALID) {
- dest = nextPipe(OV_MDP_PIPE_VG, pipeSpecs);
- }
- if(dest == OV_INVALID and not pipeSpecs.needsScaling) {
- dest = nextPipe(OV_MDP_PIPE_DMA, pipeSpecs);
- }
- }
- return dest;
-}
-
-void Overlay::endAllSessions() {
- for(int i = 0; i < PipeBook::NUM_PIPES; i++) {
- if(mPipeBook[i].valid() && mPipeBook[i].mSession==PipeBook::START)
- mPipeBook[i].mSession = PipeBook::END;
- }
-}
-
-bool Overlay::isPipeTypeAttached(eMdpPipeType type) {
- for(int i = 0; i < PipeBook::NUM_PIPES; i++) {
- if(type == PipeBook::getPipeType((eDest)i) &&
- mPipeBook[i].mDisplay != DPY_UNUSED) {
- return true;
- }
- }
- return false;
-}
-
-int Overlay::comparePipePriority(utils::eDest pipe1Index,
- utils::eDest pipe2Index) {
- validate((int)pipe1Index);
- validate((int)pipe2Index);
- uint8_t pipe1Prio = mPipeBook[(int)pipe1Index].mPipe->getPriority();
- uint8_t pipe2Prio = mPipeBook[(int)pipe2Index].mPipe->getPriority();
- if(pipe1Prio > pipe2Prio)
- return -1;
- if(pipe1Prio < pipe2Prio)
- return 1;
- return 0;
-}
-
-bool Overlay::commit(utils::eDest dest) {
- bool ret = false;
- validate((int)dest);
-
- if(mPipeBook[dest].mPipe->commit()) {
- ret = true;
- PipeBook::setUse((int)dest);
- } else {
- clear(mPipeBook[dest].mDisplay);
- }
- return ret;
-}
-
-bool Overlay::queueBuffer(int fd, uint32_t offset,
- utils::eDest dest) {
- bool ret = false;
- validate((int)dest);
- //Queue only if commit() has succeeded (and the bit set)
- if(PipeBook::isUsed((int)dest)) {
- ret = mPipeBook[dest].mPipe->queueBuffer(fd, offset);
- }
- return ret;
-}
-
-void Overlay::setCrop(const utils::Dim& d,
- utils::eDest dest) {
- validate((int)dest);
- mPipeBook[dest].mPipe->setCrop(d);
-}
-
-void Overlay::setColor(const uint32_t color,
- utils::eDest dest) {
- validate((int)dest);
- mPipeBook[dest].mPipe->setColor(color);
-}
-
-void Overlay::setPosition(const utils::Dim& d,
- utils::eDest dest) {
- validate((int)dest);
- mPipeBook[dest].mPipe->setPosition(d);
-}
-
-void Overlay::setTransform(const int orient,
- utils::eDest dest) {
- validate((int)dest);
-
- utils::eTransform transform =
- static_cast<utils::eTransform>(orient);
- mPipeBook[dest].mPipe->setTransform(transform);
-
-}
-
-void Overlay::setSource(const utils::PipeArgs args,
- utils::eDest dest) {
- validate((int)dest);
-
- setPipeType(dest, PipeBook::getPipeType(dest));
- mPipeBook[dest].mPipe->setSource(args);
-}
-
-void Overlay::setVisualParams(const MetaData_t& metadata, utils::eDest dest) {
- validate((int)dest);
- mPipeBook[dest].mPipe->setVisualParams(metadata);
-}
-
-void Overlay::setPipeType(utils::eDest pipeIndex,
- const utils::eMdpPipeType pType) {
- mPipeBook[pipeIndex].mPipe->setPipeType(pType);
-}
-
-Overlay* Overlay::getInstance() {
- if(sInstance == NULL) {
- sInstance = new Overlay();
- }
- return sInstance;
-}
-
-// Clears any VG pipes allocated to the fb devices
-// Generates a LUT for pipe types.
-int Overlay::initOverlay() {
- int mdpVersion = qdutils::MDPVersion::getInstance().getMDPVersion();
- int numPipesXType[OV_MDP_PIPE_ANY] = {0};
- numPipesXType[OV_MDP_PIPE_RGB] =
- qdutils::MDPVersion::getInstance().getRGBPipes();
- numPipesXType[OV_MDP_PIPE_VG] =
- qdutils::MDPVersion::getInstance().getVGPipes();
- numPipesXType[OV_MDP_PIPE_DMA] =
- qdutils::MDPVersion::getInstance().getDMAPipes();
-
- int index = 0;
- for(int X = 0; X < (int)OV_MDP_PIPE_ANY; X++) { //iterate over types
- for(int j = 0; j < numPipesXType[X]; j++) { //iterate over num
- PipeBook::pipeTypeLUT[index] = (utils::eMdpPipeType)X;
- index++;
- }
- }
-
- if (mdpVersion < qdutils::MDSS_V5 && mdpVersion > qdutils::MDP_V3_0_5) {
- msmfb_mixer_info_req req;
- mdp_mixer_info *minfo = NULL;
- char name[64];
- int fd = -1;
- for(int i = 0; i < MAX_FB_DEVICES; i++) {
- snprintf(name, 64, FB_DEVICE_TEMPLATE, i);
- ALOGD("initoverlay:: opening the device:: %s", name);
- fd = ::open(name, O_RDWR, 0);
- if(fd < 0) {
- ALOGE("cannot open framebuffer(%d)", i);
- return -1;
- }
- //Get the mixer configuration */
- req.mixer_num = i;
- if (ioctl(fd, MSMFB_MIXER_INFO, &req) == -1) {
- ALOGE("ERROR: MSMFB_MIXER_INFO ioctl failed");
- close(fd);
- return -1;
- }
- minfo = req.info;
- for (int j = 0; j < req.cnt; j++) {
- ALOGD("ndx=%d num=%d z_order=%d", minfo->pndx, minfo->pnum,
- minfo->z_order);
- // except the RGB base layer with z_order of -1, clear any
- // other pipes connected to mixer.
- if((minfo->z_order) != -1) {
- int index = minfo->pndx;
- ALOGD("Unset overlay with index: %d at mixer %d", index, i);
- if(ioctl(fd, MSMFB_OVERLAY_UNSET, &index) == -1) {
- ALOGE("ERROR: MSMFB_OVERLAY_UNSET failed");
- close(fd);
- return -1;
- }
- }
- minfo++;
- }
- close(fd);
- fd = -1;
- }
- }
-
- FILE *displayDeviceFP = NULL;
- char fbType[MAX_FRAME_BUFFER_NAME_SIZE];
- char msmFbTypePath[MAX_FRAME_BUFFER_NAME_SIZE];
- const char *strDtvPanel = "dtv panel";
- const char *strWbPanel = "writeback panel";
-
- for(int num = 1; num < MAX_FB_DEVICES; num++) {
- snprintf (msmFbTypePath, sizeof(msmFbTypePath),
- "/sys/class/graphics/fb%d/msm_fb_type", num);
- displayDeviceFP = fopen(msmFbTypePath, "r");
-
- if(displayDeviceFP){
- fread(fbType, sizeof(char), MAX_FRAME_BUFFER_NAME_SIZE,
- displayDeviceFP);
-
- if(strncmp(fbType, strDtvPanel, strlen(strDtvPanel)) == 0) {
- sDpyFbMap[DPY_EXTERNAL] = num;
- } else if(strncmp(fbType, strWbPanel, strlen(strWbPanel)) == 0) {
- sDpyFbMap[DPY_WRITEBACK] = num;
- }
-
- fclose(displayDeviceFP);
- }
- }
-
- return 0;
-}
-
-bool Overlay::displayCommit(const int& fd) {
- utils::Dim lRoi, rRoi;
- return displayCommit(fd, lRoi, rRoi);
-}
-
-bool Overlay::displayCommit(const int& fd, const utils::Dim& lRoi,
- const utils::Dim& rRoi) {
- //Commit
- struct mdp_display_commit info;
- memset(&info, 0, sizeof(struct mdp_display_commit));
- info.flags = MDP_DISPLAY_COMMIT_OVERLAY;
- info.l_roi.x = lRoi.x;
- info.l_roi.y = lRoi.y;
- info.l_roi.w = lRoi.w;
- info.l_roi.h = lRoi.h;
- info.r_roi.x = rRoi.x;
- info.r_roi.y = rRoi.y;
- info.r_roi.w = rRoi.w;
- info.r_roi.h = rRoi.h;
-
- if(!mdp_wrapper::displayCommit(fd, info)) {
- ALOGE("%s: commit failed", __func__);
- return false;
- }
- return true;
-}
-
-void Overlay::getDump(char *buf, size_t len) {
- int totalPipes = 0;
- const char *str = "\nOverlay State\n\n";
- strlcat(buf, str, len);
- for(int i = 0; i < PipeBook::NUM_PIPES; i++) {
- if(mPipeBook[i].valid()) {
- mPipeBook[i].mPipe->getDump(buf, len);
- char str[64] = {'\0'};
- snprintf(str, 64, "Display=%d\n\n", mPipeBook[i].mDisplay);
- strlcat(buf, str, len);
- totalPipes++;
- }
- }
- char str_pipes[64] = {'\0'};
- snprintf(str_pipes, 64, "Pipes=%d\n\n", totalPipes);
- strlcat(buf, str_pipes, len);
-}
-
-void Overlay::clear(int dpy) {
- for(int i = 0; i < PipeBook::NUM_PIPES; i++) {
- if (mPipeBook[i].mDisplay == dpy) {
- // Mark as available for this round
- PipeBook::resetUse(i);
- PipeBook::resetAllocation(i);
- if(getPipeId((utils::eDest)i) == -1) {
- mPipeBook[i].destroy();
- }
- }
- }
-}
-
-bool Overlay::validateAndSet(const int& dpy, const int& fbFd) {
- GenericPipe* pipeArray[PipeBook::NUM_PIPES];
- memset(pipeArray, 0, sizeof(GenericPipe*)*(PipeBook::NUM_PIPES));
-
- int num = 0;
- for(int i = 0; i < PipeBook::NUM_PIPES; i++) {
- if(PipeBook::isUsed(i) && mPipeBook[i].valid() &&
- mPipeBook[i].mDisplay == dpy) {
- pipeArray[num++] = mPipeBook[i].mPipe;
- }
- }
-
- //Protect against misbehaving clients
- return num ? GenericPipe::validateAndSet(pipeArray, num, fbFd) : true;
-}
-
-void Overlay::initScalar() {
- if(sLibScaleHandle == NULL) {
- sLibScaleHandle = dlopen("libscale.so", RTLD_NOW);
- if(sLibScaleHandle) {
- *(void **) &sFnProgramScale =
- dlsym(sLibScaleHandle, "programScale");
- }
- }
-}
-
-void Overlay::destroyScalar() {
- if(sLibScaleHandle) {
- dlclose(sLibScaleHandle);
- sLibScaleHandle = NULL;
- }
-}
-
-void Overlay::PipeBook::init() {
- mPipe = NULL;
- mDisplay = DPY_UNUSED;
- mMixer = MIXER_UNUSED;
- mFormatType = FORMAT_NONE;
-}
-
-void Overlay::PipeBook::destroy() {
- if(mPipe) {
- delete mPipe;
- mPipe = NULL;
- }
- mDisplay = DPY_UNUSED;
- mMixer = MIXER_UNUSED;
- mFormatType = FORMAT_NONE;
- mSession = NONE;
-}
-
-Overlay* Overlay::sInstance = 0;
-int Overlay::sDpyFbMap[DPY_MAX] = {0, -1, -1, -1};
-int Overlay::sDMAMode = DMA_LINE_MODE;
-bool Overlay::sDMAMultiplexingSupported = false;
-bool Overlay::sDebugPipeLifecycle = false;
-int Overlay::PipeBook::NUM_PIPES = 0;
-int Overlay::PipeBook::sPipeUsageBitmap = 0;
-int Overlay::PipeBook::sLastUsageBitmap = 0;
-int Overlay::PipeBook::sAllocatedBitmap = 0;
-utils::eMdpPipeType Overlay::PipeBook::pipeTypeLUT[utils::OV_MAX] =
- {utils::OV_MDP_PIPE_ANY};
-void *Overlay::sLibScaleHandle = NULL;
-int (*Overlay::sFnProgramScale)(struct mdp_overlay_list *) = NULL;
-
-}; // namespace overlay
diff --git a/msm8909/liboverlay/overlay.h b/msm8909/liboverlay/overlay.h
deleted file mode 100644
index 5c93b232..00000000
--- a/msm8909/liboverlay/overlay.h
+++ /dev/null
@@ -1,428 +0,0 @@
-/*
-* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions are
-* met:
-* * Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
-* * Redistributions in binary form must reproduce the above
-* copyright notice, this list of conditions and the following
-* disclaimer in the documentation and/or other materials provided
-* with the distribution.
-* * Neither the name of The Linux Foundation. nor the names of its
-* contributors may be used to endorse or promote products derived
-* from this software without specific prior written permission.
-*
-* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
-* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
-* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
-* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
-* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
-* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-#ifndef OVERLAY_H
-#define OVERLAY_H
-
-#include "overlayUtils.h"
-#include "mdp_version.h"
-#include "utils/threads.h"
-
-struct MetaData_t;
-
-namespace overlay {
-class GenericPipe;
-
-class Overlay : utils::NoCopy {
-public:
- enum { DMA_BLOCK_MODE, DMA_LINE_MODE };
- //Abstract Display types. Each backed by a LayerMixer,
- //represented by a fb node.
- //High res panels can be backed by 2 layer mixers and a single fb node.
- enum { DPY_PRIMARY, DPY_EXTERNAL, DPY_TERTIARY, DPY_WRITEBACK, DPY_UNUSED };
- enum { DPY_MAX = DPY_UNUSED };
- enum { MIXER_LEFT, MIXER_RIGHT, MIXER_UNUSED };
- enum { MIXER_DEFAULT = MIXER_LEFT, MIXER_MAX = MIXER_UNUSED };
- enum { MAX_FB_DEVICES = DPY_MAX };
- enum { FORMAT_YUV, FORMAT_RGB , FORMAT_NONE };
-
- struct PipeSpecs {
- PipeSpecs() : formatClass(FORMAT_RGB), needsScaling(false), fb(false),
- dpy(DPY_PRIMARY), mixer(MIXER_DEFAULT), numActiveDisplays(1) {}
- int formatClass;
- bool needsScaling;
- bool fb;
- int dpy;
- int mixer;
- int numActiveDisplays;
- };
-
- /* dtor close */
- ~Overlay();
-
- /* Marks the beginning of a drawing round, resets usage bits on pipes
- * Should be called when drawing begins before any pipe config is done.
- */
- void configBegin();
-
- /* Marks the end of config for this drawing round
- * Will do garbage collection of pipe objects and thus calling UNSETs,
- * closing FDs, removing rotator objects and memory, if allocated.
- * Should be called after all pipe configs are done.
- */
- void configDone();
-
- /* Get a pipe that supported the specified format class (yuv, rgb) and has
- * scaling capabilities.
- */
- utils::eDest getPipe(const PipeSpecs& pipeSpecs);
- /* Returns the eDest corresponding to an already allocated pipeid.
- * Useful for the reservation case, when libvpu reserves the pipe at its
- * end, and expect the overlay to allocate a given pipe for a layer.
- */
- utils::eDest reservePipe(int pipeid);
- /* getting dest for the given pipeid */
- utils::eDest getDest(int pipeid);
- /* getting overlay.pipeid for the given dest */
- int getPipeId(utils::eDest dest);
-
- void setSource(const utils::PipeArgs args, utils::eDest dest);
- void setCrop(const utils::Dim& d, utils::eDest dest);
- void setColor(const uint32_t color, utils::eDest dest);
- void setTransform(const int orientation, utils::eDest dest);
- void setPosition(const utils::Dim& dim, utils::eDest dest);
- void setVisualParams(const MetaData_t& data, utils::eDest dest);
- bool commit(utils::eDest dest);
- bool queueBuffer(int fd, uint32_t offset, utils::eDest dest);
-
- /* pipe reservation session is running */
- bool sessionInProgress(utils::eDest dest);
- /* pipe reservation session has ended*/
- bool isSessionEnded(utils::eDest dest);
- /* start session for the pipe reservation */
- void startSession(utils::eDest dest);
- /* end all started sesisons */
- void endAllSessions();
- /* Returns available ("unallocated") pipes for a display's mixer */
- int availablePipes(int dpy, int mixer);
- /* Returns available ("unallocated") pipes for a display */
- int availablePipes(int dpy);
- /* Returns available ("unallocated") pipe of given type for a display */
- int availablePipes(int dpy, utils::eMdpPipeType type);
- /* Returns if any of the requested pipe type is attached to any of the
- * displays
- */
- bool isPipeTypeAttached(utils::eMdpPipeType type);
- /* Compare pipe priorities and return
- * 1 if 1st pipe has a higher priority
- * 0 if both have the same priority
- *-1 if 2nd pipe has a higher priority
- */
- int comparePipePriority(utils::eDest pipe1Index, utils::eDest pipe2Index);
- /* Returns pipe dump. Expects a NULL terminated buffer of big enough size
- * to populate.
- */
- /* Returns if DMA pipe multiplexing is supported by the mdss driver */
- static bool isDMAMultiplexingSupported();
- /* Returns if UI scaling on external is supported on the targets */
- static bool isUIScalingOnExternalSupported();
- void getDump(char *buf, size_t len);
- /* Reset usage and allocation bits on all pipes for given display */
- void clear(int dpy);
- /* Validate the set of pipes for a display and set them in driver */
- bool validateAndSet(const int& dpy, const int& fbFd);
-
- /* Closes open pipes, called during startup */
- static int initOverlay();
- /* Returns the singleton instance of overlay */
- static Overlay* getInstance();
- static void setDMAMode(const int& mode);
- static int getDMAMode();
- /* Returns the framebuffer node backing up the display */
- static int getFbForDpy(const int& dpy);
-
- static bool displayCommit(const int& fd);
- /* Overloads display commit with ROI's of each halves.
- * Single interface panels will only update left ROI. */
- static bool displayCommit(const int& fd, const utils::Dim& lRoi,
- const utils::Dim& rRoi);
- /* Logs pipe lifecycle events like set, unset, commit when enabled */
- static void debugPipeLifecycle(const bool& enable);
- /* Returns true if pipe life cycle logging is enabled */
- static bool isDebugPipeLifecycle();
-
-private:
- /* Ctor setup */
- explicit Overlay();
- /*Validate index range, abort if invalid */
- void validate(int index);
- static void setDMAMultiplexingSupported();
- /* Returns an available pipe based on the type of pipe requested. When ANY
- * is requested, the first available VG or RGB is returned. If no pipe is
- * available for the display "dpy" then INV is returned. Note: If a pipe is
- * assigned to a certain display, then it cannot be assigned to another
- * display without being garbage-collected once. To add if a pipe is
- * asisgned to a mixer within a display it cannot be reused for another
- * mixer without being UNSET once*/
- utils::eDest nextPipe(utils::eMdpPipeType, const PipeSpecs& pipeSpecs);
- /* Helpers that enfore target specific policies while returning pipes */
- utils::eDest getPipe_8x26(const PipeSpecs& pipeSpecs);
- utils::eDest getPipe_8x16(const PipeSpecs& pipeSpecs);
- utils::eDest getPipe_8x39(const PipeSpecs& pipeSpecs);
- utils::eDest getPipe_8994(const PipeSpecs& pipeSpecs);
-
- /* Returns the handle to libscale.so's programScale function */
- static int (*getFnProgramScale())(struct mdp_overlay_list *);
- /* Creates a scalar object using libscale.so */
- static void initScalar();
- /* Destroys the scalar object using libscale.so */
- static void destroyScalar();
- /* Sets the pipe type RGB/VG/DMA*/
- void setPipeType(utils::eDest pipeIndex, const utils::eMdpPipeType pType);
-
- /* Just like a Facebook for pipes, but much less profile info */
- struct PipeBook {
- void init();
- void destroy();
- /* Check if pipe exists and return true, false otherwise */
- bool valid();
-
- /* Hardware pipe wrapper */
- GenericPipe *mPipe;
- /* Display using this pipe. Refer to enums above */
- int mDisplay;
- /* Mixer within a split display this pipe is attached to */
- int mMixer;
- /* Format for which this pipe is attached to the mixer*/
- int mFormatType;
-
- /* operations on bitmap */
- static bool pipeUsageUnchanged();
- static void setUse(int index);
- static void resetUse(int index);
- static bool isUsed(int index);
- static bool isNotUsed(int index);
- static void save();
-
- static void setAllocation(int index);
- static void resetAllocation(int index);
- static bool isAllocated(int index);
- static bool isNotAllocated(int index);
-
- static utils::eMdpPipeType getPipeType(utils::eDest dest);
- static const char* getDestStr(utils::eDest dest);
-
- static int NUM_PIPES;
- static utils::eMdpPipeType pipeTypeLUT[utils::OV_MAX];
- /* Session for reserved pipes */
- enum Session {
- NONE,
- START,
- END
- };
- Session mSession;
-
- private:
- //usage tracks if a successful commit happened. So a pipe could be
- //allocated to a display, but it may not end up using it for various
- //reasons. If one display actually uses a pipe then it amy not be
- //used by another display, without an UNSET in between.
- static int sPipeUsageBitmap;
- static int sLastUsageBitmap;
- //Tracks which pipe objects are allocated. This does not imply that they
- //will actually be used. For example, a display might choose to acquire
- //3 pipe objects in one shot and proceed with config only if it gets all
- //3. The bitmap helps allocate different pipe objects on each request.
- static int sAllocatedBitmap;
- };
-
- PipeBook mPipeBook[utils::OV_INVALID]; //Used as max
-
- /* Singleton Instance*/
- static Overlay *sInstance;
- static int sDpyFbMap[DPY_MAX];
- static int sDMAMode;
- static bool sDMAMultiplexingSupported;
- static void *sLibScaleHandle;
- static int (*sFnProgramScale)(struct mdp_overlay_list *);
- static bool sDebugPipeLifecycle;
-
- friend class MdpCtrl;
-};
-
-inline void Overlay::validate(int index) {
- OVASSERT(index >=0 && index < PipeBook::NUM_PIPES, \
- "%s, Index out of bounds: %d", __FUNCTION__, index);
- OVASSERT(mPipeBook[index].valid(), "Pipe does not exist %s",
- PipeBook::getDestStr((utils::eDest)index));
-}
-
-inline int Overlay::availablePipes(int dpy, int mixer) {
- int avail = 0;
- for(int i = 0; i < PipeBook::NUM_PIPES; i++) {
- if( (mPipeBook[i].mDisplay == DPY_UNUSED ||
- mPipeBook[i].mDisplay == dpy) &&
- (mPipeBook[i].mMixer == MIXER_UNUSED ||
- mPipeBook[i].mMixer == mixer) &&
- PipeBook::isNotAllocated(i) &&
- !(Overlay::getDMAMode() == Overlay::DMA_BLOCK_MODE &&
- PipeBook::getPipeType((utils::eDest)i) ==
- utils::OV_MDP_PIPE_DMA)) {
- avail++;
- }
- }
- return avail;
-}
-
-inline int Overlay::availablePipes(int dpy) {
- int avail = 0;
- for(int i = 0; i < PipeBook::NUM_PIPES; i++) {
- if( (mPipeBook[i].mDisplay == DPY_UNUSED ||
- mPipeBook[i].mDisplay == dpy) &&
- PipeBook::isNotAllocated(i) &&
- !(Overlay::getDMAMode() == Overlay::DMA_BLOCK_MODE &&
- PipeBook::getPipeType((utils::eDest)i) ==
- utils::OV_MDP_PIPE_DMA)) {
- avail++;
- }
- }
- return avail;
-}
-
-inline int Overlay::availablePipes(int dpy, utils::eMdpPipeType type) {
- int avail = 0;
- for(int i = 0; i < PipeBook::NUM_PIPES; i++) {
- if((mPipeBook[i].mDisplay == DPY_UNUSED ||
- mPipeBook[i].mDisplay == dpy) &&
- PipeBook::isNotAllocated(i) &&
- type == PipeBook::getPipeType((utils::eDest)i)) {
- avail++;
- }
- }
- return avail;
-}
-
-inline void Overlay::setDMAMode(const int& mode) {
- if(mode == DMA_LINE_MODE || mode == DMA_BLOCK_MODE)
- sDMAMode = mode;
-}
-
-inline void Overlay::setDMAMultiplexingSupported() {
- sDMAMultiplexingSupported = false;
- if(qdutils::MDPVersion::getInstance().is8x26())
- sDMAMultiplexingSupported = true;
-}
-
-inline bool Overlay::isDMAMultiplexingSupported() {
- return sDMAMultiplexingSupported;
-}
-
-inline bool Overlay::isUIScalingOnExternalSupported() {
- if(qdutils::MDPVersion::getInstance().is8x26() or
- qdutils::MDPVersion::getInstance().is8x16() or
- qdutils::MDPVersion::getInstance().is8x39()) {
- return false;
- }
- return true;
-}
-
-inline int Overlay::getDMAMode() {
- return sDMAMode;
-}
-
-inline int Overlay::getFbForDpy(const int& dpy) {
- OVASSERT(dpy >= 0 && dpy < DPY_MAX, "Invalid dpy %d", dpy);
- return sDpyFbMap[dpy];
-}
-
-inline int (*Overlay::getFnProgramScale())(struct mdp_overlay_list *) {
- return sFnProgramScale;
-}
-
-inline void Overlay::debugPipeLifecycle(const bool& enable) {
- sDebugPipeLifecycle = enable;
-}
-
-inline bool Overlay::isDebugPipeLifecycle() {
- return sDebugPipeLifecycle;
-}
-
-inline bool Overlay::PipeBook::valid() {
- return (mPipe != NULL);
-}
-
-inline bool Overlay::PipeBook::pipeUsageUnchanged() {
- return (sPipeUsageBitmap == sLastUsageBitmap);
-}
-
-inline void Overlay::PipeBook::setUse(int index) {
- sPipeUsageBitmap |= (1 << index);
-}
-
-inline void Overlay::PipeBook::resetUse(int index) {
- sPipeUsageBitmap &= ~(1 << index);
-}
-
-inline bool Overlay::PipeBook::isUsed(int index) {
- return sPipeUsageBitmap & (1 << index);
-}
-
-inline bool Overlay::PipeBook::isNotUsed(int index) {
- return !isUsed(index);
-}
-
-inline void Overlay::PipeBook::save() {
- sLastUsageBitmap = sPipeUsageBitmap;
-}
-
-inline void Overlay::PipeBook::setAllocation(int index) {
- sAllocatedBitmap |= (1 << index);
-}
-
-inline void Overlay::PipeBook::resetAllocation(int index) {
- sAllocatedBitmap &= ~(1 << index);
-}
-
-inline bool Overlay::PipeBook::isAllocated(int index) {
- return sAllocatedBitmap & (1 << index);
-}
-
-inline bool Overlay::PipeBook::isNotAllocated(int index) {
- return !isAllocated(index);
-}
-
-inline utils::eMdpPipeType Overlay::PipeBook::getPipeType(utils::eDest dest) {
- return pipeTypeLUT[(int)dest];
-}
-
-inline void Overlay::startSession(utils::eDest dest) {
- mPipeBook[(int)dest].mSession = PipeBook::START;
-}
-
-inline bool Overlay::sessionInProgress(utils::eDest dest) {
- return (mPipeBook[(int)dest].mSession == PipeBook::START);
-}
-
-inline bool Overlay::isSessionEnded(utils::eDest dest) {
- return (mPipeBook[(int)dest].mSession == PipeBook::END);
-}
-
-inline const char* Overlay::PipeBook::getDestStr(utils::eDest dest) {
- switch(getPipeType(dest)) {
- case utils::OV_MDP_PIPE_RGB: return "RGB";
- case utils::OV_MDP_PIPE_VG: return "VG";
- case utils::OV_MDP_PIPE_DMA: return "DMA";
- default: return "Invalid";
- }
- return "Invalid";
-}
-
-}; // overlay
-
-#endif // OVERLAY_H
diff --git a/msm8909/liboverlay/overlayCtrlData.h b/msm8909/liboverlay/overlayCtrlData.h
deleted file mode 100644
index 2eec98c9..00000000
--- a/msm8909/liboverlay/overlayCtrlData.h
+++ /dev/null
@@ -1,249 +0,0 @@
-/*
-* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions are
-* met:
-* * Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
-* * Redistributions in binary form must reproduce the above
-* copyright notice, this list of conditions and the following
-* disclaimer in the documentation and/or other materials provided
-* with the distribution.
-* * Neither the name of The Linux Foundation nor the names of its
-* contributors may be used to endorse or promote products derived
-* from this software without specific prior written permission.
-*
-* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
-* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
-* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
-* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
-* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
-* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-#ifndef OVERLAY_CTRLDATA_H
-#define OVERLAY_CTRLDATA_H
-
-#include "overlayUtils.h"
-#include "overlayMdp.h"
-#include "gralloc_priv.h" // INTERLACE_MASK
-
-namespace ovutils = overlay::utils;
-
-namespace overlay {
-
-/*
-* Sequence to use:
-* init
-* start
-* setXXX
-* close
-* */
-class Ctrl : utils::NoCopy {
-public:
-
- /* ctor */
- explicit Ctrl(const int& dpy);
- /* dtor close */
- ~Ctrl();
-
- /* set source using whf, orient and wait flag */
- void setSource(const utils::PipeArgs& args);
- /* set crop info and pass it down to mdp */
- void setCrop(const utils::Dim& d);
- /* set color for mdp pipe */
- void setColor(const uint32_t color);
- /* set orientation */
- void setTransform(const utils::eTransform& p);
- /* set mdp position using dim */
- void setPosition(const utils::Dim& dim);
- /* set mdp visual params using metadata */
- bool setVisualParams(const MetaData_t &metadata);
- /* set pipe type RGB/DMA/VG */
- void setPipeType(const utils::eMdpPipeType& pType);
- /* mdp set overlay/commit changes */
- bool commit();
-
- /* ctrl id */
- int getPipeId() const;
- /* ctrl fd */
- int getFd() const;
- /* retrieve crop data */
- utils::Dim getCrop() const;
- utils::Dim getPosition() const;
- /* Update the src format based on rotator's dest */
- void updateSrcFormat(const uint32_t& rotDstFormat);
- /* return pipe priority */
- uint8_t getPriority() const;
- /* dump the state of the object */
- void dump() const;
- /* Return the dump in the specified buffer */
- void getDump(char *buf, size_t len);
-
- static bool validateAndSet(Ctrl* ctrlArray[], const int& count,
- const int& fbFd);
-private:
- // mdp ctrl struct(info e.g.)
- MdpCtrl *mMdp;
-};
-
-
-class Data : utils::NoCopy {
-public:
- /* init, reset */
- explicit Data(const int& dpy);
- /* calls close */
- ~Data();
- /* set overlay pipe id in the mdp struct */
- void setPipeId(int id);
- /* get overlay id in the mdp struct */
- int getPipeId() const;
- /* queue buffer to the overlay */
- bool queueBuffer(int fd, uint32_t offset);
- /* sump the state of the obj */
- void dump() const;
- /* Return the dump in the specified buffer */
- void getDump(char *buf, size_t len);
-
-private:
- // mdp data struct
- MdpData *mMdp;
-};
-
-//-------------Inlines-------------------------------
-
-inline Ctrl::Ctrl(const int& dpy) : mMdp(new MdpCtrl(dpy)) {
-}
-
-inline Ctrl::~Ctrl() {
- delete mMdp;
-}
-
-inline void Ctrl::setSource(const utils::PipeArgs& args)
-{
- mMdp->setSource(args);
-}
-
-inline void Ctrl::setPosition(const utils::Dim& dim)
-{
- mMdp->setPosition(dim);
-}
-
-inline void Ctrl::setTransform(const utils::eTransform& orient)
-{
- mMdp->setTransform(orient);
-}
-
-inline void Ctrl::setCrop(const utils::Dim& d)
-{
- mMdp->setCrop(d);
-}
-
-inline void Ctrl::setColor(const uint32_t color)
-{
- mMdp->setColor(color);
-}
-
-inline bool Ctrl::setVisualParams(const MetaData_t &metadata)
-{
- if (!mMdp->setVisualParams(metadata)) {
- ALOGE("Ctrl setVisualParams failed in MDP setVisualParams");
- return false;
- }
- return true;
-}
-
-inline void Ctrl::setPipeType(const utils::eMdpPipeType& pType)
-{
- mMdp->setPipeType(pType);
-}
-
-inline void Ctrl::dump() const {
- ALOGE("== Dump Ctrl start ==");
- mMdp->dump();
- ALOGE("== Dump Ctrl end ==");
-}
-
-inline bool Ctrl::commit() {
- if(!mMdp->set()) {
- ALOGE("Ctrl commit failed set overlay");
- return false;
- }
- return true;
-}
-
-inline int Ctrl::getPipeId() const {
- return mMdp->getPipeId();
-}
-
-inline int Ctrl::getFd() const {
- return mMdp->getFd();
-}
-
-inline void Ctrl::updateSrcFormat(const uint32_t& rotDstFmt) {
- mMdp->updateSrcFormat(rotDstFmt);
-}
-
-inline bool Ctrl::validateAndSet(Ctrl* ctrlArray[], const int& count,
- const int& fbFd) {
- MdpCtrl* mdpCtrlArray[count];
- memset(&mdpCtrlArray, 0, sizeof(mdpCtrlArray));
-
- for(int i = 0; i < count; i++) {
- mdpCtrlArray[i] = ctrlArray[i]->mMdp;
- }
-
- bool ret = MdpCtrl::validateAndSet(mdpCtrlArray, count, fbFd);
- return ret;
-}
-
-inline utils::Dim Ctrl::getCrop() const {
- return mMdp->getSrcRectDim();
-}
-
-inline utils::Dim Ctrl::getPosition() const {
- return mMdp->getDstRectDim();
-}
-
-inline uint8_t Ctrl::getPriority() const {
- return mMdp->getPriority();
-}
-
-inline void Ctrl::getDump(char *buf, size_t len) {
- mMdp->getDump(buf, len);
-}
-
-inline Data::Data(const int& dpy) : mMdp(new MdpData(dpy)) {
-}
-
-inline Data::~Data() {
- delete mMdp;
-}
-
-inline void Data::setPipeId(int id) { mMdp->setPipeId(id); }
-
-inline int Data::getPipeId() const { return mMdp->getPipeId(); }
-
-inline bool Data::queueBuffer(int fd, uint32_t offset) {
- return mMdp->play(fd, offset);
-}
-
-inline void Data::dump() const {
- ALOGE("== Dump Data MDP start ==");
- mMdp->dump();
- ALOGE("== Dump Data MDP end ==");
-}
-
-inline void Data::getDump(char *buf, size_t len) {
- mMdp->getDump(buf, len);
-}
-
-} // overlay
-
-#endif
diff --git a/msm8909/liboverlay/overlayMdp.cpp b/msm8909/liboverlay/overlayMdp.cpp
deleted file mode 100644
index d52864e4..00000000
--- a/msm8909/liboverlay/overlayMdp.cpp
+++ /dev/null
@@ -1,393 +0,0 @@
-/*
-* Copyright (C) 2008 The Android Open Source Project
-* Copyright (c) 2010-2014, The Linux Foundation. All rights reserved.
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
-
-#include <math.h>
-#include <mdp_version.h>
-#include "overlayUtils.h"
-#include "overlayMdp.h"
-#include "mdp_version.h"
-#include <overlay.h>
-
-#define HSIC_SETTINGS_DEBUG 0
-
-using namespace qdutils;
-
-namespace ovutils = overlay::utils;
-namespace overlay {
-
-bool MdpCtrl::init(const int& dpy) {
- int fbnum = Overlay::getFbForDpy(dpy);
- if( fbnum < 0 ) {
- ALOGE("%s: Invalid FB for the display: %d",__FUNCTION__, dpy);
- return false;
- }
-
- // FD init
- if(!utils::openDev(mFd, fbnum,
- Res::fbPath, O_RDWR)){
- ALOGE("Ctrl failed to init fbnum=%d", fbnum);
- return false;
- }
- mDpy = dpy;
- return true;
-}
-
-void MdpCtrl::reset() {
- utils::memset0(mOVInfo);
- mOVInfo.id = MSMFB_NEW_REQUEST;
- mOrientation = utils::OVERLAY_TRANSFORM_0;
- mDpy = 0;
-#ifdef USES_POST_PROCESSING
- memset(&mParams, 0, sizeof(struct compute_params));
- mParams.params.conv_params.order = hsic_order_hsc_i;
- mParams.params.conv_params.interface = interface_rec601;
- mParams.params.conv_params.cc_matrix[0][0] = 1;
- mParams.params.conv_params.cc_matrix[1][1] = 1;
- mParams.params.conv_params.cc_matrix[2][2] = 1;
-#endif
-}
-
-bool MdpCtrl::close() {
- bool result = true;
- if(MSMFB_NEW_REQUEST != static_cast<int>(mOVInfo.id)) {
- if(!mdp_wrapper::unsetOverlay(mFd.getFD(), mOVInfo.id)) {
- ALOGE("MdpCtrl close error in unset");
- result = false;
- }
- }
-#ifdef USES_POST_PROCESSING
- /* free allocated memory in PP */
- if (mOVInfo.overlay_pp_cfg.igc_cfg.c0_c1_data)
- free(mOVInfo.overlay_pp_cfg.igc_cfg.c0_c1_data);
-#endif
- reset();
-
- if(!mFd.close()) {
- result = false;
- }
-
- return result;
-}
-
-void MdpCtrl::setSource(const utils::PipeArgs& args) {
- setSrcWhf(args.whf);
-
- //TODO These are hardcoded. Can be moved out of setSource.
- mOVInfo.transp_mask = 0xffffffff;
-
- //TODO These calls should ideally be a part of setPipeParams API
- setFlags(args.mdpFlags);
- setZ(args.zorder);
- setPlaneAlpha(args.planeAlpha);
- setBlending(args.blending);
-}
-
-void MdpCtrl::setCrop(const utils::Dim& d) {
- setSrcRectDim(d);
-}
-
-void MdpCtrl::setColor(const uint32_t color) {
- mOVInfo.bg_color = color;
-}
-
-void MdpCtrl::setPosition(const overlay::utils::Dim& d) {
- setDstRectDim(d);
-}
-
-void MdpCtrl::setTransform(const utils::eTransform& orient) {
- int rot = utils::getMdpOrient(orient);
- setUserData(rot);
- mOrientation = static_cast<utils::eTransform>(rot);
-}
-
-void MdpCtrl::setPipeType(const utils::eMdpPipeType& pType){
- switch((int) pType){
- case utils::OV_MDP_PIPE_RGB:
- mOVInfo.pipe_type = PIPE_TYPE_RGB;
- break;
- case utils::OV_MDP_PIPE_VG:
- mOVInfo.pipe_type = PIPE_TYPE_VIG;
- break;
- case utils::OV_MDP_PIPE_DMA:
- mOVInfo.pipe_type = PIPE_TYPE_DMA;
- break;
- default:
- mOVInfo.pipe_type = PIPE_TYPE_AUTO;
- break;
- }
-}
-
-void MdpCtrl::doTransform() {
- setRotationFlags();
- utils::Whf whf = getSrcWhf();
- utils::Dim dim = getSrcRectDim();
- utils::preRotateSource(mOrientation, whf, dim);
- setSrcWhf(whf);
- setSrcRectDim(dim);
-}
-
-void MdpCtrl::doDownscale() {
- if(MDPVersion::getInstance().supportsDecimation()) {
- utils::getDecimationFactor(mOVInfo.src_rect.w, mOVInfo.src_rect.h,
- mOVInfo.dst_rect.w, mOVInfo.dst_rect.h, mOVInfo.horz_deci,
- mOVInfo.vert_deci);
- }
-}
-
-bool MdpCtrl::set() {
- int mdpVersion = MDPVersion::getInstance().getMDPVersion();
- //deferred calcs, so APIs could be called in any order.
- doTransform();
- utils::Whf whf = getSrcWhf();
- if(utils::isYuv(whf.format)) {
- utils::normalizeCrop(mOVInfo.src_rect.x, mOVInfo.src_rect.w);
- utils::normalizeCrop(mOVInfo.src_rect.y, mOVInfo.src_rect.h);
- if(mdpVersion < MDSS_V5) {
- utils::even_floor(mOVInfo.dst_rect.w);
- utils::even_floor(mOVInfo.dst_rect.h);
- } else if (mOVInfo.flags & MDP_DEINTERLACE) {
- // For interlaced, crop.h should be 4-aligned
- if (!(mOVInfo.flags & MDP_SOURCE_ROTATED_90) &&
- (mOVInfo.src_rect.h % 4))
- mOVInfo.src_rect.h = utils::aligndown(mOVInfo.src_rect.h, 4);
- // For interlaced, width must be multiple of 4 when rotated 90deg.
- else if ((mOVInfo.flags & MDP_SOURCE_ROTATED_90) &&
- (mOVInfo.src_rect.w % 4))
- mOVInfo.src_rect.w = utils::aligndown(mOVInfo.src_rect.w, 4);
- }
- } else {
- // On 8974 and 8x26, there is a limitation of 1-pixel down-scaling
- if (mdpVersion >= MDSS_V5) {
- if(qdutils::MDPVersion::getInstance().is8x74v2() ||
- qdutils::MDPVersion::getInstance().is8x26()) {
- if (mOVInfo.src_rect.w - mOVInfo.dst_rect.w == 1)
- mOVInfo.src_rect.w -= 1;
- if (mOVInfo.src_rect.h - mOVInfo.dst_rect.h == 1)
- mOVInfo.src_rect.h -= 1;
- }
- }
- }
-
- doDownscale();
- return true;
-}
-
-//Update src format based on rotator's destination format.
-void MdpCtrl::updateSrcFormat(const uint32_t& rotDestFmt) {
- utils::Whf whf = getSrcWhf();
- whf.format = rotDestFmt;
- setSrcWhf(whf);
-}
-
-void MdpCtrl::dump() const {
- ALOGE("== Dump MdpCtrl start ==");
- mFd.dump();
- mdp_wrapper::dump("mOVInfo", mOVInfo);
- ALOGE("== Dump MdpCtrl end ==");
-}
-
-void MdpCtrl::getDump(char *buf, size_t len) {
- ovutils::getDump(buf, len, "Ctrl", mOVInfo);
-}
-
-void MdpData::dump() const {
- ALOGE("== Dump MdpData start ==");
- mFd.dump();
- mdp_wrapper::dump("mOvData", mOvData);
- ALOGE("== Dump MdpData end ==");
-}
-
-void MdpData::getDump(char *buf, size_t len) {
- ovutils::getDump(buf, len, "Data", mOvData);
-}
-
-bool MdpCtrl::setVisualParams(const MetaData_t& data) {
- ALOGD_IF(0, "In %s: data.operation = %d", __FUNCTION__, data.operation);
-
- // Set Color Space for MDP to configure CSC matrix
- mOVInfo.color_space = ITU_R_601;
- if (data.operation & UPDATE_COLOR_SPACE) {
- mOVInfo.color_space = data.colorSpace;
- }
-
-#ifdef USES_POST_PROCESSING
- bool needUpdate = false;
- /* calculate the data */
- if (data.operation & PP_PARAM_HSIC) {
- if (mParams.params.pa_params.hue != data.hsicData.hue) {
- ALOGD_IF(HSIC_SETTINGS_DEBUG,
- "Hue has changed from %d to %d",
- mParams.params.pa_params.hue,data.hsicData.hue);
- needUpdate = true;
- }
-
- if (!isEqual(mParams.params.pa_params.sat,
- data.hsicData.saturation)) {
- ALOGD_IF(HSIC_SETTINGS_DEBUG,
- "Saturation has changed from %f to %f",
- mParams.params.pa_params.sat,
- data.hsicData.saturation);
- needUpdate = true;
- }
-
- if (mParams.params.pa_params.intensity != data.hsicData.intensity) {
- ALOGD_IF(HSIC_SETTINGS_DEBUG,
- "Intensity has changed from %d to %d",
- mParams.params.pa_params.intensity,
- data.hsicData.intensity);
- needUpdate = true;
- }
-
- if (!isEqual(mParams.params.pa_params.contrast,
- data.hsicData.contrast)) {
- ALOGD_IF(HSIC_SETTINGS_DEBUG,
- "Contrast has changed from %f to %f",
- mParams.params.pa_params.contrast,
- data.hsicData.contrast);
- needUpdate = true;
- }
-
- if (needUpdate) {
- mParams.params.pa_params.hue = data.hsicData.hue;
- mParams.params.pa_params.sat = data.hsicData.saturation;
- mParams.params.pa_params.intensity = data.hsicData.intensity;
- mParams.params.pa_params.contrast = data.hsicData.contrast;
- mParams.params.pa_params.ops = MDP_PP_OPS_WRITE | MDP_PP_OPS_ENABLE;
- mParams.operation |= PP_OP_PA;
- }
- }
-
- if (data.operation & PP_PARAM_SHARP2) {
- if (mParams.params.sharp_params.strength != data.Sharp2Data.strength) {
- needUpdate = true;
- }
- if (mParams.params.sharp_params.edge_thr != data.Sharp2Data.edge_thr) {
- needUpdate = true;
- }
- if (mParams.params.sharp_params.smooth_thr !=
- data.Sharp2Data.smooth_thr) {
- needUpdate = true;
- }
- if (mParams.params.sharp_params.noise_thr !=
- data.Sharp2Data.noise_thr) {
- needUpdate = true;
- }
-
- if (needUpdate) {
- mParams.params.sharp_params.strength = data.Sharp2Data.strength;
- mParams.params.sharp_params.edge_thr = data.Sharp2Data.edge_thr;
- mParams.params.sharp_params.smooth_thr =
- data.Sharp2Data.smooth_thr;
- mParams.params.sharp_params.noise_thr = data.Sharp2Data.noise_thr;
- mParams.params.sharp_params.ops =
- MDP_PP_OPS_WRITE | MDP_PP_OPS_ENABLE;
- mParams.operation |= PP_OP_SHARP;
- }
- }
-
- if (data.operation & PP_PARAM_IGC) {
- if (mOVInfo.overlay_pp_cfg.igc_cfg.c0_c1_data == NULL){
- uint32_t *igcData
- = (uint32_t *)malloc(2 * MAX_IGC_LUT_ENTRIES * sizeof(uint32_t));
- if (!igcData) {
- ALOGE("IGC storage allocated failed");
- return false;
- }
- mOVInfo.overlay_pp_cfg.igc_cfg.c0_c1_data = igcData;
- mOVInfo.overlay_pp_cfg.igc_cfg.c2_data
- = igcData + MAX_IGC_LUT_ENTRIES;
- }
-
- memcpy(mParams.params.igc_lut_params.c0,
- data.igcData.c0, sizeof(uint16_t) * MAX_IGC_LUT_ENTRIES);
- memcpy(mParams.params.igc_lut_params.c1,
- data.igcData.c1, sizeof(uint16_t) * MAX_IGC_LUT_ENTRIES);
- memcpy(mParams.params.igc_lut_params.c2,
- data.igcData.c2, sizeof(uint16_t) * MAX_IGC_LUT_ENTRIES);
-
- mParams.params.igc_lut_params.ops
- = MDP_PP_OPS_WRITE | MDP_PP_OPS_ENABLE;
- mParams.operation |= PP_OP_IGC;
- needUpdate = true;
- }
-
- if (data.operation & PP_PARAM_VID_INTFC) {
- mParams.params.conv_params.interface =
- (interface_type) data.video_interface;
- needUpdate = true;
- }
-
- if (needUpdate) {
- display_pp_compute_params(&mParams, &mOVInfo.overlay_pp_cfg);
- }
-#endif
- return true;
-}
-
-bool MdpCtrl::validateAndSet(MdpCtrl* mdpCtrlArray[], const int& count,
- const int& fbFd) {
- mdp_overlay* ovArray[count];
- memset(&ovArray, 0, sizeof(ovArray));
-
- for(int i = 0; i < count; i++) {
- ovArray[i] = &mdpCtrlArray[i]->mOVInfo;
- }
-
- struct mdp_overlay_list list;
- memset(&list, 0, sizeof(struct mdp_overlay_list));
- list.num_overlays = count;
- list.overlay_list = ovArray;
-
- int (*fnProgramScale)(struct mdp_overlay_list *) =
- Overlay::getFnProgramScale();
- if(fnProgramScale) {
- fnProgramScale(&list);
- }
-
- // Error value is based on file errno-base.h
- // 0 - indicates no error.
- int errVal = mdp_wrapper::validateAndSet(fbFd, list);
- if(errVal) {
- /* No dump for failure due to insufficient resource */
- if(errVal != E2BIG) {
- mdp_wrapper::dump("Bad ov dump: ",
- *list.overlay_list[list.processed_overlays]);
- }
- return false;
- }
-
- return true;
-}
-
-
-//// MdpData ////////////
-bool MdpData::init(const int& dpy) {
- int fbnum = Overlay::getFbForDpy(dpy);
- if( fbnum < 0 ) {
- ALOGE("%s: Invalid FB for the display: %d",__FUNCTION__, dpy);
- return false;
- }
-
- // FD init
- if(!utils::openDev(mFd, fbnum, Res::fbPath, O_RDWR)){
- ALOGE("Ctrl failed to init fbnum=%d", fbnum);
- return false;
- }
- return true;
-}
-
-} // overlay
diff --git a/msm8909/liboverlay/overlayMdp.h b/msm8909/liboverlay/overlayMdp.h
deleted file mode 100644
index faed1ef0..00000000
--- a/msm8909/liboverlay/overlayMdp.h
+++ /dev/null
@@ -1,321 +0,0 @@
-/*
-* Copyright (C) 2008 The Android Open Source Project
-* Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
-
-#ifndef OVERLAY_MDP_H
-#define OVERLAY_MDP_H
-
-#include <linux/msm_mdp.h>
-
-#include "overlayUtils.h"
-#include "mdpWrapper.h"
-#include "qdMetaData.h"
-#ifdef USES_POST_PROCESSING
-#include "lib-postproc.h"
-#endif
-
-namespace overlay{
-
-/*
-* Mdp Ctrl holds corresponding fd and MDP related struct.
-* It is simple wrapper to MDP services
-* */
-class MdpCtrl {
-public:
- /* ctor reset */
- explicit MdpCtrl(const int& dpy);
- /* dtor close */
- ~MdpCtrl();
- /* init underlying device using fbnum for dpy */
- bool init(const int& dpy);
- /* unset overlay, reset and close fd */
- bool close();
- /* reset and set ov id to -1 / MSMFB_NEW_REQUEST */
- void reset();
- /* calls overlay set
- * Set would always consult last good known ov instance.
- * Only if it is different, set would actually exectue ioctl.
- * On a sucess ioctl. last good known ov instance is updated */
- bool set();
- /* Sets the source total width, height, format */
- void setSource(const utils::PipeArgs& pargs);
- /*
- * Sets ROI, the unpadded region, for source buffer.
- * Dim - ROI dimensions.
- */
- void setCrop(const utils::Dim& d);
- /* set color for mdp pipe */
- void setColor(const uint32_t color);
- void setTransform(const utils::eTransform& orient);
- /* given a dim and w/h, set overlay dim */
- void setPosition(const utils::Dim& dim);
- /* using user_data, sets/unsets roationvalue in mdp flags */
- void setRotationFlags();
- /* Update the src format with rotator's dest*/
- void updateSrcFormat(const uint32_t& rotDstFormat);
- /* dump state of the object */
- void dump() const;
- /* Return the dump in the specified buffer */
- void getDump(char *buf, size_t len);
- /* returns session id */
- int getPipeId() const;
- /* returns the fd associated to ctrl*/
- int getFd() const;
- /* returns a copy ro dst rect dim */
- utils::Dim getDstRectDim() const;
- /* returns a copy to src rect dim */
- utils::Dim getSrcRectDim() const;
- /* return pipe priority */
- uint8_t getPriority() const;
- /* setVisualParam */
- bool setVisualParams(const MetaData_t& data);
- /* sets pipe type RGB/DMA/VG */
- void setPipeType(const utils::eMdpPipeType& pType);
-
- static bool validateAndSet(MdpCtrl* mdpCtrlArray[], const int& count,
- const int& fbFd);
-private:
- /* Perform transformation calculations */
- void doTransform();
- void doDownscale();
- /* get orient / user_data[0] */
- int getOrient() const;
- /* returns flags from mdp structure */
- int getFlags() const;
- /* set flags to mdp structure */
- void setFlags(int f);
- /* set z order */
- void setZ(utils::eZorder z);
- /* return a copy of src whf*/
- utils::Whf getSrcWhf() const;
- /* set plane alpha */
- void setPlaneAlpha(int planeAlpha);
- /* set blending method */
- void setBlending(overlay::utils::eBlending blending);
-
- /* set src whf */
- void setSrcWhf(const utils::Whf& whf);
- /* set src/dst rect dim */
- void setSrcRectDim(const utils::Dim d);
- void setDstRectDim(const utils::Dim d);
- /* returns user_data[0]*/
- int getUserData() const;
- /* sets user_data[0] */
- void setUserData(int v);
-
- utils::eTransform mOrientation; //Holds requested orientation
- /* Actual overlay mdp structure */
- mdp_overlay mOVInfo;
- /* FD for the mdp fbnum */
- OvFD mFd;
- int mDpy;
-
-#ifdef USES_POST_PROCESSING
- /* PP Compute Params */
- struct compute_params mParams;
-#endif
-};
-
-/* MDP data */
-class MdpData {
-public:
- /* ctor reset data */
- explicit MdpData(const int& dpy);
- /* dtor close*/
- ~MdpData();
- /* init FD */
- bool init(const int& dpy);
- /* memset0 the underlying mdp object */
- void reset();
- /* close fd, and reset */
- bool close();
- /* set id of mdp data */
- void setPipeId(int id);
- /* return ses id of data */
- int getPipeId() const;
- /* get underlying fd*/
- int getFd() const;
- /* get memory_id */
- int getSrcMemoryId() const;
- /* calls wrapper play */
- bool play(int fd, uint32_t offset);
- /* dump state of the object */
- void dump() const;
- /* Return the dump in the specified buffer */
- void getDump(char *buf, size_t len);
-
-private:
-
- /* actual overlay mdp data */
- msmfb_overlay_data mOvData;
- /* fd to mdp fbnum */
- OvFD mFd;
-};
-
-//--------------Inlines---------------------------------
-
-///// MdpCtrl //////
-
-inline MdpCtrl::MdpCtrl(const int& dpy) {
- reset();
- init(dpy);
-}
-
-inline MdpCtrl::~MdpCtrl() {
- close();
-}
-
-inline int MdpCtrl::getOrient() const {
- return getUserData();
-}
-
-inline int MdpCtrl::getPipeId() const {
- return mOVInfo.id;
-}
-
-inline int MdpCtrl::getFd() const {
- return mFd.getFD();
-}
-
-inline int MdpCtrl::getFlags() const {
- return mOVInfo.flags;
-}
-
-inline void MdpCtrl::setFlags(int f) {
- mOVInfo.flags = f;
-}
-
-inline void MdpCtrl::setZ(overlay::utils::eZorder z) {
- mOVInfo.z_order = z;
-}
-
-inline void MdpCtrl::setPlaneAlpha(int planeAlpha) {
- mOVInfo.alpha = planeAlpha;
-}
-
-inline void MdpCtrl::setBlending(overlay::utils::eBlending blending) {
- switch((int) blending) {
- case utils::OVERLAY_BLENDING_OPAQUE:
- mOVInfo.blend_op = BLEND_OP_OPAQUE;
- break;
- case utils::OVERLAY_BLENDING_PREMULT:
- mOVInfo.blend_op = BLEND_OP_PREMULTIPLIED;
- break;
- case utils::OVERLAY_BLENDING_COVERAGE:
- default:
- mOVInfo.blend_op = BLEND_OP_COVERAGE;
- }
-}
-
-inline overlay::utils::Whf MdpCtrl::getSrcWhf() const {
- return utils::Whf( mOVInfo.src.width,
- mOVInfo.src.height,
- mOVInfo.src.format);
-}
-
-inline void MdpCtrl::setSrcWhf(const overlay::utils::Whf& whf) {
- mOVInfo.src.width = whf.w;
- mOVInfo.src.height = whf.h;
- mOVInfo.src.format = whf.format;
-}
-
-inline overlay::utils::Dim MdpCtrl::getSrcRectDim() const {
- return utils::Dim( mOVInfo.src_rect.x,
- mOVInfo.src_rect.y,
- mOVInfo.src_rect.w,
- mOVInfo.src_rect.h);
-}
-
-inline void MdpCtrl::setSrcRectDim(const overlay::utils::Dim d) {
- mOVInfo.src_rect.x = d.x;
- mOVInfo.src_rect.y = d.y;
- mOVInfo.src_rect.w = d.w;
- mOVInfo.src_rect.h = d.h;
-}
-
-inline overlay::utils::Dim MdpCtrl::getDstRectDim() const {
- return utils::Dim( mOVInfo.dst_rect.x,
- mOVInfo.dst_rect.y,
- mOVInfo.dst_rect.w,
- mOVInfo.dst_rect.h);
-}
-
-inline void MdpCtrl::setDstRectDim(const overlay::utils::Dim d) {
- mOVInfo.dst_rect.x = d.x;
- mOVInfo.dst_rect.y = d.y;
- mOVInfo.dst_rect.w = d.w;
- mOVInfo.dst_rect.h = d.h;
-}
-
-inline int MdpCtrl::getUserData() const { return mOVInfo.user_data[0]; }
-
-inline void MdpCtrl::setUserData(int v) { mOVInfo.user_data[0] = v; }
-
-inline void MdpCtrl::setRotationFlags() {
- const int u = getUserData();
- if (u & MDP_ROT_90)
- mOVInfo.flags |= MDP_SOURCE_ROTATED_90;
-}
-
-inline uint8_t MdpCtrl::getPriority() const {
- return mOVInfo.priority;
-}
-
-/////// MdpData //////
-
-inline MdpData::MdpData(const int& dpy) {
- reset();
- init(dpy);
-}
-
-inline MdpData::~MdpData() { close(); }
-
-inline void MdpData::reset() {
- overlay::utils::memset0(mOvData);
- mOvData.data.memory_id = -1;
-}
-
-inline bool MdpData::close() {
- reset();
- return mFd.close();
-}
-
-inline int MdpData::getSrcMemoryId() const { return mOvData.data.memory_id; }
-
-inline void MdpData::setPipeId(int id) { mOvData.id = id; }
-
-inline int MdpData::getPipeId() const { return mOvData.id; }
-
-inline int MdpData::getFd() const { return mFd.getFD(); }
-
-inline bool MdpData::play(int fd, uint32_t offset) {
- mOvData.data.memory_id = fd;
- mOvData.data.offset = offset;
- if(!mdp_wrapper::play(mFd.getFD(), mOvData)){
- ALOGE("MdpData failed to play");
- dump();
- return false;
- }
- return true;
-}
-
-} // overlay
-
-inline bool isEqual(float f1, float f2) {
- return ((int)(f1*100) == (int)(f2*100)) ? true : false;
-}
-
-#endif // OVERLAY_MDP_H
diff --git a/msm8909/liboverlay/overlayMdpRot.cpp b/msm8909/liboverlay/overlayMdpRot.cpp
deleted file mode 100755
index d3228976..00000000
--- a/msm8909/liboverlay/overlayMdpRot.cpp
+++ /dev/null
@@ -1,322 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- * Copyright (c) 2010-2014, The Linux Foundation. All rights reserved.
- * Not a Contribution, Apache license notifications and license are retained
- * for attribution purposes only.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
-*/
-
-#include <math.h>
-#include "overlayUtils.h"
-#include "overlayRotator.h"
-#include "gr.h"
-
-namespace ovutils = overlay::utils;
-
-namespace overlay {
-
-MdpRot::MdpRot() {
- reset();
- init();
-}
-
-MdpRot::~MdpRot() { close(); }
-
-bool MdpRot::enabled() const { return mRotImgInfo.enable; }
-
-void MdpRot::setRotations(uint32_t r) { mRotImgInfo.rotations = (uint8_t)r; }
-
-int MdpRot::getSrcMemId() const {
- return mRotDataInfo.src.memory_id;
-}
-
-int MdpRot::getDstMemId() const {
- return mRotDataInfo.dst.memory_id;
-}
-
-uint32_t MdpRot::getSrcOffset() const {
- return mRotDataInfo.src.offset;
-}
-
-uint32_t MdpRot::getDstOffset() const {
- return mRotDataInfo.dst.offset;
-}
-
-uint32_t MdpRot::getDstFormat() const {
- return mRotImgInfo.dst.format;
-}
-
-//Added for completeness. Not expected to be called.
-utils::Whf MdpRot::getDstWhf() const {
- int alW = 0, alH = 0;
- int halFormat = ovutils::getHALFormat(mRotImgInfo.dst.format);
- getBufferSizeAndDimensions(mRotImgInfo.dst.width, mRotImgInfo.dst.height,
- halFormat, alW, alH);
- return utils::Whf(alW, alH, mRotImgInfo.dst.format);
-}
-
-//Added for completeness. Not expected to be called.
-utils::Dim MdpRot::getDstDimensions() const {
- int alW = 0, alH = 0;
- int halFormat = ovutils::getHALFormat(mRotImgInfo.dst.format);
- getBufferSizeAndDimensions(mRotImgInfo.dst.width, mRotImgInfo.dst.height,
- halFormat, alW, alH);
- return utils::Dim(0, 0, alW, alH);
-}
-
-uint32_t MdpRot::getSessId() const { return mRotImgInfo.session_id; }
-
-void MdpRot::setDownscale(int ds) {
- if ((utils::ROT_DS_EIGHTH == ds) && (mRotImgInfo.src_rect.h & 0xF)) {
- // Ensure src_rect.h is a multiple of 16 for 1/8 downscaling.
- // This is an undocumented MDP Rotator constraint.
- mRotImgInfo.src_rect.h = utils::aligndown(mRotImgInfo.src_rect.h, 16);
- }
- mRotImgInfo.downscale_ratio = ds;
-}
-
-void MdpRot::save() {
- mLSRotImgInfo = mRotImgInfo;
-}
-
-bool MdpRot::rotConfChanged() const {
- // 0 means same
- if(0 == ::memcmp(&mRotImgInfo, &mLSRotImgInfo,
- sizeof (msm_rotator_img_info))) {
- return false;
- }
- return true;
-}
-
-bool MdpRot::init()
-{
- if(!mFd.open(Res::rotPath, O_RDWR)){
- ALOGE("MdpRot failed to init %s", Res::rotPath);
- return false;
- }
- return true;
-}
-
-void MdpRot::setSource(const overlay::utils::Whf& awhf) {
- utils::Whf whf(awhf);
- mRotImgInfo.src.format = whf.format;
-
- mRotImgInfo.src.width = whf.w;
- mRotImgInfo.src.height = whf.h;
-
- mRotImgInfo.src_rect.w = whf.w;
- mRotImgInfo.src_rect.h = whf.h;
-
- mRotImgInfo.dst.width = whf.w;
- mRotImgInfo.dst.height = whf.h;
-}
-
-void MdpRot::setCrop(const utils::Dim& /*crop*/) {
- // NO-OP for non-mdss rotator due to possible h/w limitations
-}
-
-void MdpRot::setFlags(const utils::eMdpFlags& flags) {
- mRotImgInfo.secure = 0;
- if(flags & utils::OV_MDP_SECURE_OVERLAY_SESSION)
- mRotImgInfo.secure = 1;
-}
-
-void MdpRot::setTransform(const utils::eTransform& rot)
-{
- int r = utils::getMdpOrient(rot);
- setRotations(r);
- mOrientation = static_cast<utils::eTransform>(r);
- ALOGE_IF(DEBUG_OVERLAY, "%s: r=%d", __FUNCTION__, r);
-}
-
-void MdpRot::doTransform() {
- if(mOrientation & utils::OVERLAY_TRANSFORM_ROT_90)
- utils::swap(mRotImgInfo.dst.width, mRotImgInfo.dst.height);
-}
-
-bool MdpRot::commit() {
- doTransform();
- if(rotConfChanged()) {
- mRotImgInfo.enable = 1;
- if(!overlay::mdp_wrapper::startRotator(mFd.getFD(), mRotImgInfo)) {
- ALOGE("MdpRot commit failed");
- dump();
- mRotImgInfo.enable = 0;
- return false;
- }
- mRotDataInfo.session_id = mRotImgInfo.session_id;
- }
- return true;
-}
-
-uint32_t MdpRot::calcOutputBufSize() {
- ovutils::Whf destWhf(mRotImgInfo.dst.width,
- mRotImgInfo.dst.height, mRotImgInfo.dst.format);
- return Rotator::calcOutputBufSize(destWhf);
-}
-
-bool MdpRot::open_i(uint32_t numbufs, uint32_t bufsz)
-{
- OvMem mem;
-
- OVASSERT(MAP_FAILED == mem.addr(), "MAP failed in open_i");
-
- if(!mem.open(numbufs, bufsz, mRotImgInfo.secure)){
- ALOGE("%s: Failed to open", __func__);
- mem.close();
- return false;
- }
-
- OVASSERT(MAP_FAILED != mem.addr(), "MAP failed");
- OVASSERT(mem.getFD() != -1, "getFd is -1");
-
- mRotDataInfo.dst.memory_id = mem.getFD();
- mRotDataInfo.dst.offset = 0;
- mMem.mem = mem;
- return true;
-}
-
-bool MdpRot::close() {
- bool success = true;
- if(mFd.valid() && (getSessId() != 0)) {
- if(!mdp_wrapper::endRotator(mFd.getFD(), getSessId())) {
- ALOGE("Mdp Rot error endRotator, fd=%d sessId=%u",
- mFd.getFD(), getSessId());
- success = false;
- }
- }
- if (!mFd.close()) {
- ALOGE("Mdp Rot error closing fd");
- success = false;
- }
- if (!mMem.close()) {
- ALOGE("Mdp Rot error closing mem");
- success = false;
- }
- reset();
- return success;
-}
-
-bool MdpRot::remap(uint32_t numbufs) {
- // if current size changed, remap
- uint32_t opBufSize = calcOutputBufSize();
- if(opBufSize == mMem.size()) {
- ALOGE_IF(DEBUG_OVERLAY, "%s: same size %d", __FUNCTION__, opBufSize);
- return true;
- }
-
- if(!mMem.close()) {
- ALOGE("%s error in closing prev rot mem", __FUNCTION__);
- return false;
- }
-
- ALOGE_IF(DEBUG_OVERLAY, "%s: size changed - remapping", __FUNCTION__);
-
- if(!open_i(numbufs, opBufSize)) {
- ALOGE("%s Error could not open", __FUNCTION__);
- return false;
- }
-
- for (uint32_t i = 0; i < numbufs; ++i) {
- mMem.mRotOffset[i] = i * opBufSize;
- }
-
- return true;
-}
-
-void MdpRot::reset() {
- ovutils::memset0(mRotImgInfo);
- ovutils::memset0(mLSRotImgInfo);
- ovutils::memset0(mRotDataInfo);
- ovutils::memset0(mMem.mRotOffset);
- mMem.mCurrIndex = 0;
- mOrientation = utils::OVERLAY_TRANSFORM_0;
-}
-
-bool MdpRot::queueBuffer(int fd, uint32_t offset) {
- if(enabled() and (not isRotCached(fd,offset))) {
- int prev_fd = getSrcMemId();
- uint32_t prev_offset = getSrcOffset();
-
- mRotDataInfo.src.memory_id = fd;
- mRotDataInfo.src.offset = offset;
-
- if(false == remap(RotMem::ROT_NUM_BUFS)) {
- ALOGE("%s Remap failed, not queueing", __FUNCTION__);
- return false;
- }
-
- mRotDataInfo.dst.offset =
- mMem.mRotOffset[mMem.mCurrIndex];
-
- if(!overlay::mdp_wrapper::rotate(mFd.getFD(), mRotDataInfo)) {
- ALOGE("MdpRot failed rotate");
- dump();
- mRotDataInfo.src.memory_id = prev_fd;
- mRotDataInfo.src.offset = prev_offset;
- return false;
- }
- save();
- mMem.mCurrIndex =
- (mMem.mCurrIndex + 1) % mMem.mem.numBufs();
- }
- return true;
-}
-
-void MdpRot::dump() const {
- ALOGE("== Dump MdpRot start ==");
- mFd.dump();
- mMem.mem.dump();
- mdp_wrapper::dump("mRotImgInfo", mRotImgInfo);
- mdp_wrapper::dump("mRotDataInfo", mRotDataInfo);
- ALOGE("== Dump MdpRot end ==");
-}
-
-void MdpRot::getDump(char *buf, size_t len) const {
- ovutils::getDump(buf, len, "MdpRotCtrl", mRotImgInfo);
- ovutils::getDump(buf, len, "MdpRotData", mRotDataInfo);
-}
-
-int MdpRot::getDownscaleFactor(const int& src_w, const int& src_h,
- const int& dst_w, const int& dst_h, const uint32_t& /*mdpFormat*/,
- const bool& /*isInterlaced*/) {
- int dscale_factor = utils::ROT_DS_NONE;
- // We need this check to engage the rotator whenever possible to assist MDP
- // in performing video downscale.
- // This saves bandwidth and avoids causing the driver to make too many panel
- // -mode switches between BLT (writeback) and non-BLT (Direct) modes.
- // Use-case: Video playback [with downscaling and rotation].
- if (dst_w && dst_h)
- {
- float fDscale = (float)(src_w * src_h) / (float)(dst_w * dst_h);
- uint32_t dscale = (int)sqrtf(fDscale);
-
- if(dscale < 2) {
- // Down-scale to > 50% of orig.
- dscale_factor = utils::ROT_DS_NONE;
- } else if(dscale < 4) {
- // Down-scale to between > 25% to <= 50% of orig.
- dscale_factor = utils::ROT_DS_HALF;
- } else if(dscale < 8) {
- // Down-scale to between > 12.5% to <= 25% of orig.
- dscale_factor = utils::ROT_DS_FOURTH;
- } else {
- // Down-scale to <= 12.5% of orig.
- dscale_factor = utils::ROT_DS_EIGHTH;
- }
- }
- return dscale_factor;
-}
-
-} // namespace overlay
diff --git a/msm8909/liboverlay/overlayMdssRot.cpp b/msm8909/liboverlay/overlayMdssRot.cpp
deleted file mode 100644
index 87e134a9..00000000
--- a/msm8909/liboverlay/overlayMdssRot.cpp
+++ /dev/null
@@ -1,430 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- * Copyright (c) 2010-2014, The Linux Foundation. All rights reserved.
- * Not a Contribution, Apache license notifications and license are retained
- * for attribution purposes only.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
-*/
-
-#include <math.h>
-#include "overlayUtils.h"
-#include "overlayRotator.h"
-
-#define DEBUG_MDSS_ROT 0
-
-#ifdef VENUS_COLOR_FORMAT
-#include <media/msm_media_info.h>
-#else
-#define VENUS_BUFFER_SIZE(args...) 0
-#endif
-
-#ifndef MDSS_MDP_ROT_ONLY
-#define MDSS_MDP_ROT_ONLY 0x80
-#endif
-
-#define MDSS_ROT_MASK (MDP_ROT_90 | MDP_FLIP_UD | MDP_FLIP_LR)
-
-namespace ovutils = overlay::utils;
-
-namespace overlay {
-using namespace utils;
-
-MdssRot::MdssRot() {
- reset();
- init();
-}
-
-MdssRot::~MdssRot() { close(); }
-
-bool MdssRot::enabled() const { return mEnabled; }
-
-void MdssRot::setRotations(uint32_t flags) { mRotInfo.flags |= flags; }
-
-int MdssRot::getSrcMemId() const {
- return mRotData.data.memory_id;
-}
-
-int MdssRot::getDstMemId() const {
- return mRotData.dst_data.memory_id;
-}
-
-uint32_t MdssRot::getSrcOffset() const {
- return mRotData.data.offset;
-}
-
-uint32_t MdssRot::getDstOffset() const {
- return mRotData.dst_data.offset;
-}
-
-uint32_t MdssRot::getDstFormat() const {
- //For mdss src and dst formats are same
- return mRotInfo.src.format;
-}
-
-utils::Whf MdssRot::getDstWhf() const {
- //For Mdss dst_rect itself represents buffer dimensions. We ignore actual
- //aligned values during buffer allocation. Also the driver overwrites the
- //src.format field if destination format is different.
- //This implementation detail makes it possible to retrieve w,h even before
- //buffer allocation, which happens in queueBuffer.
- return utils::Whf(mRotInfo.dst_rect.w, mRotInfo.dst_rect.h,
- mRotInfo.src.format);
-}
-
-utils::Dim MdssRot::getDstDimensions() const {
- return utils::Dim(mRotInfo.dst_rect.x, mRotInfo.dst_rect.y,
- mRotInfo.dst_rect.w, mRotInfo.dst_rect.h);
-}
-
-uint32_t MdssRot::getSessId() const { return mRotInfo.id; }
-
-void MdssRot::save() {
- mLSRotInfo = mRotInfo;
-}
-
-bool MdssRot::rotConfChanged() const {
- // 0 means same
- if(0 == ::memcmp(&mRotInfo, &mLSRotInfo,
- sizeof (mdp_overlay))) {
- return false;
- }
- return true;
-}
-
-bool MdssRot::init() {
- if(!utils::openDev(mFd, 0, Res::fbPath, O_RDWR)) {
- ALOGE("MdssRot failed to init fb0");
- return false;
- }
- return true;
-}
-
-void MdssRot::setSource(const overlay::utils::Whf& awhf) {
- utils::Whf whf(awhf);
-
- mRotInfo.src.format = whf.format;
- mRotInfo.src.width = whf.w;
- mRotInfo.src.height = whf.h;
-}
-
-void MdssRot::setCrop(const utils::Dim& crop) {
- mRotInfo.src_rect.x = crop.x;
- mRotInfo.src_rect.y = crop.y;
- mRotInfo.src_rect.w = crop.w;
- mRotInfo.src_rect.h = crop.h;
-}
-
-void MdssRot::setDownscale(int downscale) {
- mDownscale = downscale;
-}
-
-void MdssRot::setFlags(const utils::eMdpFlags& flags) {
- mRotInfo.flags = flags;
-}
-
-void MdssRot::setTransform(const utils::eTransform& rot)
-{
- // reset rotation flags to avoid stale orientation values
- mRotInfo.flags &= ~MDSS_ROT_MASK;
- int flags = utils::getMdpOrient(rot);
- if (flags != -1)
- setRotations(flags);
- mOrientation = static_cast<utils::eTransform>(flags);
- ALOGE_IF(DEBUG_OVERLAY, "%s: rot=%d", __FUNCTION__, flags);
-}
-
-void MdssRot::doTransform() {
- mRotInfo.flags |= mOrientation;
- if(mOrientation & utils::OVERLAY_TRANSFORM_ROT_90)
- utils::swap(mRotInfo.dst_rect.w, mRotInfo.dst_rect.h);
-}
-
-bool MdssRot::commit() {
- Dim adjCrop(mRotInfo.src_rect.x,mRotInfo.src_rect.y,
- mRotInfo.src_rect.w,mRotInfo.src_rect.h);
- adjCrop = getFormatAdjustedCrop(adjCrop, mRotInfo.src.format,
- mRotInfo.flags & utils::OV_MDP_DEINTERLACE);
- adjCrop = getDownscaleAdjustedCrop(adjCrop, mDownscale);
-
- mRotInfo.src_rect.x = adjCrop.x;
- mRotInfo.src_rect.y = adjCrop.y;
- mRotInfo.src_rect.w = adjCrop.w;
- mRotInfo.src_rect.h = adjCrop.h;
-
- mRotInfo.dst_rect.x = 0;
- mRotInfo.dst_rect.y = 0;
- mRotInfo.dst_rect.w = mDownscale ?
- mRotInfo.src_rect.w / mDownscale : mRotInfo.src_rect.w;
- mRotInfo.dst_rect.h = mDownscale ?
- mRotInfo.src_rect.h / mDownscale : mRotInfo.src_rect.h;
- //Clear for next round
- mDownscale = 0;
-
- doTransform();
-
- mRotInfo.flags |= MDSS_MDP_ROT_ONLY;
- mEnabled = true;
- if(!overlay::mdp_wrapper::setOverlay(mFd.getFD(), mRotInfo)) {
- ALOGE("MdssRot commit failed!");
- dump();
- return (mEnabled = false);
- }
- mRotData.id = mRotInfo.id;
- return true;
-}
-
-bool MdssRot::queueBuffer(int fd, uint32_t offset) {
- if(enabled() and (not isRotCached(fd,offset))) {
- int prev_fd = getSrcMemId();
- uint32_t prev_offset = getSrcOffset();
-
- mRotData.data.memory_id = fd;
- mRotData.data.offset = offset;
-
- if(false == remap(RotMem::ROT_NUM_BUFS)) {
- ALOGE("%s Remap failed, not queuing", __FUNCTION__);
- return false;
- }
-
- mRotData.dst_data.offset =
- mMem.mRotOffset[mMem.mCurrIndex];
-
- if(!overlay::mdp_wrapper::play(mFd.getFD(), mRotData)) {
- ALOGE("MdssRot play failed!");
- dump();
- mRotData.data.memory_id = prev_fd;
- mRotData.data.offset = prev_offset;
- return false;
- }
- save();
- mMem.mCurrIndex =
- (mMem.mCurrIndex + 1) % mMem.mem.numBufs();
- }
- return true;
-}
-
-bool MdssRot::open_i(uint32_t numbufs, uint32_t bufsz)
-{
- OvMem mem;
- OVASSERT(MAP_FAILED == mem.addr(), "MAP failed in open_i");
- bool isSecure = mRotInfo.flags & utils::OV_MDP_SECURE_OVERLAY_SESSION;
-
- if(!mem.open(numbufs, bufsz, isSecure)){
- ALOGE("%s: Failed to open", __func__);
- mem.close();
- return false;
- }
-
- OVASSERT(MAP_FAILED != mem.addr(), "MAP failed");
- OVASSERT(mem.getFD() != -1, "getFd is -1");
-
- mRotData.dst_data.memory_id = mem.getFD();
- mRotData.dst_data.offset = 0;
- mMem.mem = mem;
- return true;
-}
-
-bool MdssRot::remap(uint32_t numbufs) {
- // Calculate the size based on rotator's dst format, w and h.
- uint32_t opBufSize = calcOutputBufSize();
- // If current size changed, remap
- if(opBufSize == mMem.size()) {
- ALOGE_IF(DEBUG_OVERLAY, "%s: same size %d", __FUNCTION__, opBufSize);
- return true;
- }
-
- ALOGE_IF(DEBUG_OVERLAY, "%s: size changed - remapping", __FUNCTION__);
-
- if(!mMem.close()) {
- ALOGE("%s error in closing prev rot mem", __FUNCTION__);
- return false;
- }
-
- if(!open_i(numbufs, opBufSize)) {
- ALOGE("%s Error could not open", __FUNCTION__);
- return false;
- }
-
- for (uint32_t i = 0; i < numbufs; ++i) {
- mMem.mRotOffset[i] = i * opBufSize;
- }
-
- return true;
-}
-
-bool MdssRot::close() {
- bool success = true;
- if(mFd.valid() && (getSessId() != (uint32_t) MSMFB_NEW_REQUEST)) {
- if(!mdp_wrapper::unsetOverlay(mFd.getFD(), getSessId())) {
- ALOGE("MdssRot::close unsetOverlay failed, fd=%d sessId=%d",
- mFd.getFD(), getSessId());
- success = false;
- }
- }
-
- if (!mFd.close()) {
- ALOGE("Mdss Rot error closing fd");
- success = false;
- }
- if (!mMem.close()) {
- ALOGE("Mdss Rot error closing mem");
- success = false;
- }
- reset();
- return success;
-}
-
-void MdssRot::reset() {
- ovutils::memset0(mRotInfo);
- ovutils::memset0(mLSRotInfo);
- ovutils::memset0(mRotData);
- mRotData.data.memory_id = -1;
- mRotInfo.id = MSMFB_NEW_REQUEST;
- ovutils::memset0(mMem.mRotOffset);
- mMem.mCurrIndex = 0;
- mOrientation = utils::OVERLAY_TRANSFORM_0;
- mDownscale = 0;
-}
-
-void MdssRot::dump() const {
- ALOGE("== Dump MdssRot start ==");
- mFd.dump();
- mMem.mem.dump();
- mdp_wrapper::dump("mRotInfo", mRotInfo);
- mdp_wrapper::dump("mRotData", mRotData);
- ALOGE("== Dump MdssRot end ==");
-}
-
-uint32_t MdssRot::calcOutputBufSize() {
- uint32_t opBufSize = 0;
- ovutils::Whf destWhf(mRotInfo.dst_rect.w, mRotInfo.dst_rect.h,
- mRotInfo.src.format); //mdss src and dst formats are same.
-
- if (mRotInfo.flags & ovutils::OV_MDSS_MDP_BWC_EN) {
- opBufSize = calcCompressedBufSize(destWhf);
- } else {
- opBufSize = Rotator::calcOutputBufSize(destWhf);
- }
-
- return opBufSize;
-}
-
-void MdssRot::getDump(char *buf, size_t len) const {
- ovutils::getDump(buf, len, "MdssRotCtrl", mRotInfo);
- ovutils::getDump(buf, len, "MdssRotData", mRotData);
-}
-
-// Calculate the compressed o/p buffer size for BWC
-uint32_t MdssRot::calcCompressedBufSize(const ovutils::Whf& destWhf) {
- uint32_t bufSize = 0;
- //Worst case alignments
- int aWidth = ovutils::align(destWhf.w, 64);
- int aHeight = ovutils::align(destWhf.h, 4);
- /*
- Format | RAU size (width x height)
- ----------------------------------------------
- ARGB | 32 pixel x 4 line
- RGB888 | 32 pixel x 4 line
- Y (Luma) | 64 pixel x 4 line
- CRCB 420 | 32 pixel x 2 line
- CRCB 422 H2V1 | 32 pixel x 4 line
- CRCB 422 H1V2 | 64 pixel x 2 line
-
- Metadata requirements:-
- 1 byte meta data for every 8 RAUs
- 2 byte meta data per RAU
- */
-
- //These blocks attempt to allocate for the worst case in each of the
- //respective format classes, yuv/rgb. The table above is for reference
- if(utils::isYuv(destWhf.format)) {
- int yRauCount = aWidth / 64; //Y
- int cRauCount = aWidth / 32; //C
- int yStride = (64 * 4 * yRauCount) + alignup(yRauCount, 8) / 8;
- int cStride = ((32 * 2 * cRauCount) + alignup(cRauCount, 8) / 8) * 2;
- int yStrideOffset = (aHeight / 4);
- int cStrideOffset = (aHeight / 2);
- bufSize = (yStride * yStrideOffset + cStride * cStrideOffset) +
- (yRauCount * yStrideOffset * 2) +
- (cRauCount * cStrideOffset * 2) * 2;
- ALOGD_IF(DEBUG_MDSS_ROT, "%s:YUV Y RAU Count = %d C RAU Count = %d",
- __FUNCTION__, yRauCount, cRauCount);
- } else {
- int rauCount = aWidth / 32;
- //Single plane
- int stride = (32 * 4 * rauCount) + alignup(rauCount, 8) / 8;
- int strideOffset = (aHeight / 4);
- bufSize = (stride * strideOffset * 4 /*bpp*/) +
- (rauCount * strideOffset * 2);
- ALOGD_IF(DEBUG_MDSS_ROT, "%s:RGB RAU count = %d", __FUNCTION__,
- rauCount);
- }
-
- ALOGD_IF(DEBUG_MDSS_ROT, "%s: aligned width = %d, aligned height = %d "
- "Buf Size = %d", __FUNCTION__, aWidth, aHeight, bufSize);
-
- return bufSize;
-}
-
-int MdssRot::getDownscaleFactor(const int& srcW, const int& srcH,
- const int& dstW, const int& dstH, const uint32_t& mdpFormat,
- const bool& isInterlaced) {
- if(not srcW or not srcH or not dstW or not dstH or isInterlaced) return 0;
-
- Dim crop(0, 0, srcW, srcH);
- Dim adjCrop = getFormatAdjustedCrop(crop, mdpFormat,
- false /*isInterlaced */);
-
- uint32_t downscale = min((adjCrop.w / dstW), (adjCrop.h / dstH));
- //Reduced to a power of 2
- downscale = (uint32_t) powf(2.0f, floorf(log2f((float)downscale)));
-
- if(downscale < 2 or downscale > 32) return 0;
-
- //Allow only 1 line or pixel to be chopped off since the source needs to
- //be aligned to downscale. Progressively try with smaller downscale to see
- //if we can satisfy the threshold
- //For YUV the loop shouldnt be needed, unless in exceptional cases
- Dim dsAdjCrop = getDownscaleAdjustedCrop(adjCrop, downscale);
- while(downscale > 2 and (adjCrop.w > dsAdjCrop.w or
- adjCrop.h > dsAdjCrop.h)) {
- downscale /= 2;
- dsAdjCrop = getDownscaleAdjustedCrop(adjCrop, downscale);
- }
-
- if(not dsAdjCrop.w or not dsAdjCrop.h) return 0;
- return downscale;
-}
-
-Dim MdssRot::getFormatAdjustedCrop(const Dim& crop,
- const uint32_t& mdpFormat, const bool& isInterlaced) {
- Dim adjCrop = crop;
- if (isYuv(mdpFormat)) {
- normalizeCrop(adjCrop.x, adjCrop.w);
- normalizeCrop(adjCrop.y, adjCrop.h);
- // For interlaced, crop.h should be 4-aligned
- if (isInterlaced and (adjCrop.h % 4))
- adjCrop.h = aligndown(adjCrop.h, 4);
- }
- return adjCrop;
-}
-
-Dim MdssRot::getDownscaleAdjustedCrop(const Dim& crop,
- const uint32_t& downscale) {
- uint32_t alignedSrcW = aligndown(crop.w, downscale * 2);
- uint32_t alignedSrcH = aligndown(crop.h, downscale * 2);
- return Dim(crop.x, crop.y, alignedSrcW, alignedSrcH);
-}
-
-} // namespace overlay
diff --git a/msm8909/liboverlay/overlayMem.h b/msm8909/liboverlay/overlayMem.h
deleted file mode 100644
index f0a19220..00000000
--- a/msm8909/liboverlay/overlayMem.h
+++ /dev/null
@@ -1,222 +0,0 @@
-/*
-* Copyright (c) 2011, The Linux Foundation. All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions are
-* met:
-* * Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
-* * Redistributions in binary form must reproduce the above
-* copyright notice, this list of conditions and the following
-* disclaimer in the documentation and/or other materials provided
-* with the distribution.
-* * Neither the name of The Linux Foundation nor the names of its
-* contributors may be used to endorse or promote products derived
-* from this software without specific prior written permission.
-*
-* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
-* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
-* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
-* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
-* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
-* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-
-#ifndef OVERLAY_MEM_H
-#define OVERLAY_MEM_H
-
-#include <sys/mman.h>
-#include <fcntl.h>
-#include <alloc_controller.h>
-#include <memalloc.h>
-
-#include "gralloc_priv.h"
-#include "overlayUtils.h"
-#define SIZE_1M 0x00100000
-
-namespace overlay {
-
-/*
-* Holds base address, offset and the fd
-* */
-class OvMem {
-public:
- /* ctor init*/
- explicit OvMem();
-
- /* dtor DO NOT call close so it can be copied */
- ~OvMem();
-
- /* Use libgralloc to retrieve fd, base addr, alloc type */
- bool open(uint32_t numbufs,
- uint32_t bufSz, bool isSecure);
-
- /* close fd. assign base address to invalid*/
- bool close();
-
- /* return underlying fd */
- int getFD() const;
-
- /* return true if fd is valid and base address is valid */
- bool valid() const;
-
- /* dump the state of the object */
- void dump() const;
-
- /* return underlying address */
- void* addr() const;
-
- /* return underlying offset */
- uint32_t bufSz() const;
-
- /* return number of bufs */
- uint32_t numBufs() const ;
-
-private:
- /* actual os fd */
- int mFd;
-
- /* points to base addr (mmap)*/
- void* mBaseAddr;
-
- /* allocated buffer type determined by gralloc (ashmem, ion, etc) */
- int mAllocType;
-
- /* holds buf size sent down by the client */
- uint32_t mBufSz;
-
- /* num of bufs */
- uint32_t mNumBuffers;
-
- /* gralloc alloc controller */
- gralloc::IAllocController* mAlloc;
-
- /*Holds the aligned buffer size used for actual allocation*/
- uint32_t mBufSzAligned;
-};
-
-//-------------------Inlines-----------------------------------
-
-using gralloc::IMemAlloc;
-using gralloc::alloc_data;
-
-inline OvMem::OvMem() {
- mFd = -1;
- mBaseAddr = MAP_FAILED;
- mAllocType = 0;
- mBufSz = 0;
- mNumBuffers = 0;
- mAlloc = gralloc::IAllocController::getInstance();
-}
-
-inline OvMem::~OvMem() { }
-
-inline bool OvMem::open(uint32_t numbufs,
- uint32_t bufSz, bool isSecure)
-{
- alloc_data data;
- int allocFlags = GRALLOC_USAGE_PRIVATE_IOMMU_HEAP;
- int err = 0;
- OVASSERT(numbufs && bufSz, "numbufs=%d bufSz=%d", numbufs, bufSz);
- mBufSz = bufSz;
-
- if(isSecure) {
- allocFlags = GRALLOC_USAGE_PRIVATE_MM_HEAP;
- allocFlags |= GRALLOC_USAGE_PROTECTED;
- mBufSzAligned = utils::align(bufSz, SIZE_1M);
- data.align = SIZE_1M;
- } else {
- mBufSzAligned = bufSz;
- data.align = getpagesize();
- }
-
- // Allocate uncached rotator buffers
- allocFlags |= GRALLOC_USAGE_PRIVATE_UNCACHED;
-
- mNumBuffers = numbufs;
-
- data.base = 0;
- data.fd = -1;
- data.offset = 0;
- data.size = mBufSzAligned * mNumBuffers;
- data.uncached = true;
-
- err = mAlloc->allocate(data, allocFlags);
- if (err != 0) {
- ALOGE("OvMem: Error allocating memory");
- return false;
- }
-
- mFd = data.fd;
- mBaseAddr = data.base;
- mAllocType = data.allocType;
-
- return true;
-}
-
-inline bool OvMem::close()
-{
- int ret = 0;
-
- if(!valid()) {
- return true;
- }
-
- IMemAlloc* memalloc = mAlloc->getAllocator(mAllocType);
- ret = memalloc->free_buffer(mBaseAddr, mBufSzAligned * mNumBuffers, 0, mFd);
- if (ret != 0) {
- ALOGE("OvMem: error freeing buffer");
- return false;
- }
-
- mFd = -1;
- mBaseAddr = MAP_FAILED;
- mAllocType = 0;
- mBufSz = 0;
- mBufSzAligned = 0;
- mNumBuffers = 0;
- return true;
-}
-
-inline bool OvMem::valid() const
-{
- return (mFd != -1) && (mBaseAddr != MAP_FAILED);
-}
-
-inline int OvMem::getFD() const
-{
- return mFd;
-}
-
-inline void* OvMem::addr() const
-{
- return mBaseAddr;
-}
-
-inline uint32_t OvMem::bufSz() const
-{
- return mBufSz;
-}
-
-inline uint32_t OvMem::numBufs() const
-{
- return mNumBuffers;
-}
-
-inline void OvMem::dump() const
-{
- ALOGE("== Dump OvMem start ==");
- ALOGE("fd=%d addr=%p type=%d bufsz=%u AlignedBufSz=%u",
- mFd, mBaseAddr, mAllocType, mBufSz, mBufSzAligned);
- ALOGE("== Dump OvMem end ==");
-}
-
-} // overlay
-
-#endif // OVERLAY_MEM_H
diff --git a/msm8909/liboverlay/overlayRotator.cpp b/msm8909/liboverlay/overlayRotator.cpp
deleted file mode 100644
index b55f06ac..00000000
--- a/msm8909/liboverlay/overlayRotator.cpp
+++ /dev/null
@@ -1,242 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- * Copyright (c) 2010-2012, The Linux Foundation. All rights reserved.
- * Not a Contribution, Apache license notifications and license are retained
- * for attribution purposes only.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
-*/
-
-#include "overlayRotator.h"
-#include "overlayUtils.h"
-#include "mdp_version.h"
-#include "sync/sync.h"
-#include "gr.h"
-
-namespace ovutils = overlay::utils;
-
-namespace overlay {
-
-//============Rotator=========================
-
-Rotator::Rotator() {
- char property[PROPERTY_VALUE_MAX];
- mRotCacheDisabled = false;
- if((property_get("debug.rotcache.disable", property, NULL) > 0) &&
- (!strncmp(property, "1", PROPERTY_VALUE_MAX ) ||
- (!strncasecmp(property,"true", PROPERTY_VALUE_MAX )))) {
- /* Used in debugging to turnoff rotator caching */
- mRotCacheDisabled = true;
- }
-}
-
-Rotator::~Rotator() {}
-
-Rotator* Rotator::getRotator() {
- int type = getRotatorHwType();
- if(type == TYPE_MDP) {
- return new MdpRot(); //will do reset
- } else if(type == TYPE_MDSS) {
- return new MdssRot();
- } else {
- ALOGE("%s Unknown h/w type %d", __FUNCTION__, type);
- return NULL;
- }
-}
-
-int Rotator::getDownscaleFactor(const int& srcW, const int& srcH,
- const int& dstW, const int& dstH, const uint32_t& mdpFormat,
- const bool& isInterlaced) {
- if(getRotatorHwType() == TYPE_MDSS) {
- return MdssRot::getDownscaleFactor(srcW, srcH, dstW, dstH,
- mdpFormat, isInterlaced);
- }
- return MdpRot::getDownscaleFactor(srcW, srcH, dstW, dstH,
- mdpFormat, isInterlaced);
-}
-
-uint32_t Rotator::calcOutputBufSize(const utils::Whf& destWhf) {
- //dummy aligned w & h.
- int alW = 0, alH = 0;
- int halFormat = ovutils::getHALFormat(destWhf.format);
- //A call into gralloc/memalloc
- return getBufferSizeAndDimensions(
- destWhf.w, destWhf.h, halFormat, alW, alH);
-}
-
-int Rotator::getRotatorHwType() {
- int mdpVersion = qdutils::MDPVersion::getInstance().getMDPVersion();
- if (mdpVersion == qdutils::MDSS_V5)
- return TYPE_MDSS;
- return TYPE_MDP;
-}
-
-bool Rotator::isRotCached(int fd, uint32_t offset) const {
- if(mRotCacheDisabled or rotConfChanged() or rotDataChanged(fd,offset))
- return false;
- return true;
-}
-
-bool Rotator::rotDataChanged(int fd, uint32_t offset) const {
- /* fd and offset are the attributes of the current rotator input buffer.
- * At this instance, getSrcMemId() and getSrcOffset() return the
- * attributes of the previous rotator input buffer */
- if( (fd == getSrcMemId()) and (offset == getSrcOffset()) )
- return false;
- return true;
-}
-
-//============RotMem=========================
-
-bool RotMem::close() {
- bool ret = true;
- if(valid()) {
- if(mem.close() == false) {
- ALOGE("%s error in closing rot mem", __FUNCTION__);
- ret = false;
- }
- }
- return ret;
-}
-
-RotMem::RotMem() : mCurrIndex(0) {
- utils::memset0(mRotOffset);
- for(int i = 0; i < ROT_NUM_BUFS; i++) {
- mRelFence[i] = -1;
- }
-}
-
-RotMem::~RotMem() {
- for(int i = 0; i < ROT_NUM_BUFS; i++) {
- ::close(mRelFence[i]);
- mRelFence[i] = -1;
- }
-}
-
-void RotMem::setCurrBufReleaseFd(const int& fence) {
- int ret = 0;
-
- if(mRelFence[mCurrIndex] >= 0) {
- //Wait for previous usage of this buffer to be over.
- //Can happen if rotation takes > vsync and a fast producer. i.e queue
- //happens in subsequent vsyncs either because content is 60fps or
- //because the producer is hasty sometimes.
- ret = sync_wait(mRelFence[mCurrIndex], 1000);
- if(ret < 0) {
- ALOGE("%s: sync_wait error!! error no = %d err str = %s",
- __FUNCTION__, errno, strerror(errno));
- }
- ::close(mRelFence[mCurrIndex]);
- }
- mRelFence[mCurrIndex] = fence;
-}
-
-void RotMem::setPrevBufReleaseFd(const int& fence) {
- uint32_t numRotBufs = mem.numBufs();
- uint32_t prevIndex = (mCurrIndex + numRotBufs - 1) % (numRotBufs);
-
- if(mRelFence[prevIndex] >= 0) {
- /* No need of any wait as nothing will be written into this
- * buffer by the rotator (this func is called when rotator is
- * in cache mode) */
- ::close(mRelFence[prevIndex]);
- }
-
- mRelFence[prevIndex] = fence;
-}
-
-//============RotMgr=========================
-RotMgr * RotMgr::sRotMgr = NULL;
-
-RotMgr* RotMgr::getInstance() {
- if(sRotMgr == NULL) {
- sRotMgr = new RotMgr();
- }
- return sRotMgr;
-}
-
-RotMgr::RotMgr() {
- for(int i = 0; i < MAX_ROT_SESS; i++) {
- mRot[i] = 0;
- }
- mUseCount = 0;
- mRotDevFd = -1;
-}
-
-RotMgr::~RotMgr() {
- clear();
-}
-
-void RotMgr::configBegin() {
- //Reset the number of objects used
- mUseCount = 0;
-}
-
-void RotMgr::configDone() {
- //Remove the top most unused objects. Videos come and go.
- for(int i = mUseCount; i < MAX_ROT_SESS; i++) {
- if(mRot[i]) {
- delete mRot[i];
- mRot[i] = 0;
- }
- }
-}
-
-Rotator* RotMgr::getNext() {
- //Return a rot object, creating one if necessary
- overlay::Rotator *rot = NULL;
- if(mUseCount >= MAX_ROT_SESS) {
- ALOGW("%s, MAX rotator sessions reached, request rejected", __func__);
- } else {
- if(mRot[mUseCount] == NULL)
- mRot[mUseCount] = overlay::Rotator::getRotator();
- rot = mRot[mUseCount++];
- }
- return rot;
-}
-
-void RotMgr::clear() {
- //Brute force obj destruction, helpful in suspend.
- for(int i = 0; i < MAX_ROT_SESS; i++) {
- if(mRot[i]) {
- delete mRot[i];
- mRot[i] = 0;
- }
- }
- mUseCount = 0;
- ::close(mRotDevFd);
- mRotDevFd = -1;
-}
-
-void RotMgr::getDump(char *buf, size_t len) {
- for(int i = 0; i < MAX_ROT_SESS; i++) {
- if(mRot[i]) {
- mRot[i]->getDump(buf, len);
- }
- }
- char str[4] = {'\0'};
- snprintf(str, 4, "\n");
- strlcat(buf, str, len);
-}
-
-int RotMgr::getRotDevFd() {
- if(mRotDevFd < 0 && Rotator::getRotatorHwType() == Rotator::TYPE_MDSS) {
- mRotDevFd = ::open("/dev/graphics/fb0", O_RDWR, 0);
- if(mRotDevFd < 0) {
- ALOGE("%s failed to open fb0", __FUNCTION__);
- }
- }
- return mRotDevFd;
-}
-
-}
diff --git a/msm8909/liboverlay/overlayRotator.h b/msm8909/liboverlay/overlayRotator.h
deleted file mode 100644
index e045b440..00000000
--- a/msm8909/liboverlay/overlayRotator.h
+++ /dev/null
@@ -1,322 +0,0 @@
-/*
-* Copyright (c) 2011,2013 The Linux Foundation. All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions are
-* met:
-* * Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
-* * Redistributions in binary form must reproduce the above
-* copyright notice, this list of conditions and the following
-* disclaimer in the documentation and/or other materials provided
-* with the distribution.
-* * Neither the name of The Linux Foundation. nor the names of its
-* contributors may be used to endorse or promote products derived
-* from this software without specific prior written permission.
-*
-* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
-* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
-* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
-* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
-* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
-* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-#ifndef OVERlAY_ROTATOR_H
-#define OVERlAY_ROTATOR_H
-
-#include <stdlib.h>
-
-#include "mdpWrapper.h"
-#include "overlayUtils.h"
-#include "overlayMem.h"
-
-namespace overlay {
-
-/*
- Manages the case where new rotator memory needs to be
- allocated, before previous is freed, due to resolution change etc. If we make
- rotator memory to be always max size, irrespctive of source resolution then
- we don't need this RotMem wrapper. The inner class is sufficient.
-*/
-struct RotMem {
- // Max rotator buffers
- enum { ROT_NUM_BUFS = 2 };
- RotMem();
- ~RotMem();
- bool close();
- bool valid() { return mem.valid(); }
- uint32_t size() const { return mem.bufSz(); }
- void setCurrBufReleaseFd(const int& fence);
- void setPrevBufReleaseFd(const int& fence);
-
- // rotator data info dst offset
- uint32_t mRotOffset[ROT_NUM_BUFS];
- int mRelFence[ROT_NUM_BUFS];
- // current slot being used
- uint32_t mCurrIndex;
- OvMem mem;
-};
-
-class Rotator
-{
-public:
- enum { TYPE_MDP, TYPE_MDSS };
- virtual ~Rotator();
- virtual void setSource(const utils::Whf& wfh) = 0;
- virtual void setCrop(const utils::Dim& crop) = 0;
- virtual void setFlags(const utils::eMdpFlags& flags) = 0;
- virtual void setTransform(const utils::eTransform& rot) = 0;
- virtual bool commit() = 0;
- /* return true if the current rotator state is cached */
- virtual bool isRotCached(int fd, uint32_t offset) const;
- /* return true if current rotator config is same as the last round*/
- virtual bool rotConfChanged() const = 0;
- /* return true if the current rotator input buffer fd and offset
- * are same as the last round */
- virtual bool rotDataChanged(int fd, uint32_t offset) const;
- virtual void setDownscale(int ds) = 0;
- /* returns the src buffer of the rotator for the previous/current round,
- * depending on when it is called(before/after the queuebuffer)*/
- virtual int getSrcMemId() const = 0;
- //Mem id and offset should be retrieved only after rotator kickoff
- virtual int getDstMemId() const = 0;
- virtual uint32_t getSrcOffset() const = 0;
- virtual uint32_t getDstOffset() const = 0;
- //Destination width, height, format, position should be retrieved only after
- //rotator configuration is committed via commit API
- virtual uint32_t getDstFormat() const = 0;
- virtual utils::Whf getDstWhf() const = 0;
- virtual utils::Dim getDstDimensions() const = 0;
- virtual uint32_t getSessId() const = 0;
- virtual bool queueBuffer(int fd, uint32_t offset) = 0;
- virtual void dump() const = 0;
- virtual void getDump(char *buf, size_t len) const = 0;
- inline void setCurrBufReleaseFd(const int& fence) {
- mMem.setCurrBufReleaseFd(fence);
- }
- inline void setPrevBufReleaseFd(const int& fence) {
- mMem.setPrevBufReleaseFd(fence);
- }
- static Rotator *getRotator();
- /* Returns downscale by successfully applying constraints
- * Returns 0 if target doesnt support rotator downscaling
- * or if any of the constraints are not met
- */
- static int getDownscaleFactor(const int& srcW, const int& srcH,
- const int& dstW, const int& dstH, const uint32_t& mdpFormat,
- const bool& isInterlaced);
-
-protected:
- /* Rotator memory manager */
- RotMem mMem;
- Rotator();
- static uint32_t calcOutputBufSize(const utils::Whf& destWhf);
-
-private:
- bool mRotCacheDisabled;
- /*Returns rotator h/w type */
- static int getRotatorHwType();
- friend class RotMgr;
-};
-
-/*
-* MDP rot holds MDP's rotation related structures.
-*
-* */
-class MdpRot : public Rotator {
-public:
- virtual ~MdpRot();
- virtual void setSource(const utils::Whf& wfh);
- virtual void setCrop(const utils::Dim& crop);
- virtual void setFlags(const utils::eMdpFlags& flags);
- virtual void setTransform(const utils::eTransform& rot);
- virtual bool commit();
- virtual bool rotConfChanged() const;
- virtual void setDownscale(int ds);
- virtual int getSrcMemId() const;
- virtual int getDstMemId() const;
- virtual uint32_t getSrcOffset() const;
- virtual uint32_t getDstOffset() const;
- virtual uint32_t getDstFormat() const;
- virtual utils::Whf getDstWhf() const;
- virtual utils::Dim getDstDimensions() const;
- virtual uint32_t getSessId() const;
- virtual bool queueBuffer(int fd, uint32_t offset);
- virtual void dump() const;
- virtual void getDump(char *buf, size_t len) const;
-
-private:
- explicit MdpRot();
- bool init();
- bool close();
- void setRotations(uint32_t r);
- bool enabled () const;
- /* remap rot buffers */
- bool remap(uint32_t numbufs);
- bool open_i(uint32_t numbufs, uint32_t bufsz);
- /* Deferred transform calculations */
- void doTransform();
- /* reset underlying data, basically memset 0 */
- void reset();
- /* save mRotImgInfo to be last known good config*/
- void save();
- /* Calculates the rotator's o/p buffer size post the transform calcs and
- * knowing the o/p format depending on whether fastYuv is enabled or not */
- uint32_t calcOutputBufSize();
-
- /* Applies downscale by taking areas
- * Returns a log(downscale)
- * Constraints applied:
- * - downscale should be a power of 2
- * - Max downscale is 1/8
- */
- static int getDownscaleFactor(const int& srcW, const int& srcH,
- const int& dstW, const int& dstH, const uint32_t& mdpFormat,
- const bool& isInterlaced);
-
- /* rot info*/
- msm_rotator_img_info mRotImgInfo;
- /* Last saved rot info*/
- msm_rotator_img_info mLSRotImgInfo;
- /* rot data */
- msm_rotator_data_info mRotDataInfo;
- /* Orientation */
- utils::eTransform mOrientation;
- /* rotator fd */
- OvFD mFd;
-
- friend Rotator* Rotator::getRotator();
- friend int Rotator::getDownscaleFactor(const int& srcW, const int& srcH,
- const int& dstW, const int& dstH, const uint32_t& mdpFormat,
- const bool& isInterlaced);
-};
-
-/*
-+* MDSS Rot holds MDSS's rotation related structures.
-+*
-+* */
-class MdssRot : public Rotator {
-public:
- virtual ~MdssRot();
- virtual void setSource(const utils::Whf& wfh);
- virtual void setCrop(const utils::Dim& crop);
- virtual void setFlags(const utils::eMdpFlags& flags);
- virtual void setTransform(const utils::eTransform& rot);
- virtual bool commit();
- virtual bool rotConfChanged() const;
- virtual void setDownscale(int ds);
- virtual int getSrcMemId() const;
- virtual int getDstMemId() const;
- virtual uint32_t getSrcOffset() const;
- virtual uint32_t getDstOffset() const;
- virtual uint32_t getDstFormat() const;
- virtual utils::Whf getDstWhf() const;
- virtual utils::Dim getDstDimensions() const;
- virtual uint32_t getSessId() const;
- virtual bool queueBuffer(int fd, uint32_t offset);
- virtual void dump() const;
- virtual void getDump(char *buf, size_t len) const;
-
-private:
- explicit MdssRot();
- bool init();
- bool close();
- void setRotations(uint32_t r);
- bool enabled () const;
- /* remap rot buffers */
- bool remap(uint32_t numbufs);
- bool open_i(uint32_t numbufs, uint32_t bufsz);
- /* Deferred transform calculations */
- void doTransform();
- /* reset underlying data, basically memset 0 */
- void reset();
- /* save mRotInfo to be last known good config*/
- void save();
- /* Calculates the rotator's o/p buffer size post the transform calcs and
- * knowing the o/p format depending on whether fastYuv is enabled or not */
- uint32_t calcOutputBufSize();
- // Calculate the compressed o/p buffer size for BWC
- uint32_t calcCompressedBufSize(const utils::Whf& destWhf);
-
- /* Caller's responsibility to swap srcW, srcH if there is a 90 transform
- * Returns actual downscale (not a log value)
- * Constraints applied:
- * - downscale should be a power of 2
- * - Max downscale is 1/32
- * - Equal downscale is applied in both directions
- * - {srcW, srcH} mod downscale = 0
- * - Interlaced content is not supported
- */
- static int getDownscaleFactor(const int& srcW, const int& srcH,
- const int& dstW, const int& dstH, const uint32_t& mdpFormat,
- const bool& isInterlaced);
-
- static utils::Dim getFormatAdjustedCrop(const utils::Dim& crop,
- const uint32_t& mdpFormat, const bool& isInterlaced);
-
- static utils::Dim getDownscaleAdjustedCrop(const utils::Dim& crop,
- const uint32_t& downscale);
-
- /* MdssRot info structure */
- mdp_overlay mRotInfo;
- /* Last saved MdssRot info structure*/
- mdp_overlay mLSRotInfo;
- /* MdssRot data structure */
- msmfb_overlay_data mRotData;
- /* Orientation */
- utils::eTransform mOrientation;
- /* rotator fd */
- OvFD mFd;
- /* Enable/Disable Mdss Rot*/
- bool mEnabled;
- int mDownscale;
-
- friend Rotator* Rotator::getRotator();
- friend int Rotator::getDownscaleFactor(const int& srcW, const int& srcH,
- const int& dstW, const int& dstH, const uint32_t& mdpFormat,
- const bool& isInterlaced);
-};
-
-// Holder of rotator objects. Manages lifetimes
-class RotMgr {
-public:
- //Virtually we can support as many rotator sessions as possible, However
- // more number of rotator sessions leads to performance issues, so
- // restricting the max rotator session to 4
- enum { MAX_ROT_SESS = 4 };
-
- ~RotMgr();
- void configBegin();
- void configDone();
- overlay::Rotator *getNext();
- void clear(); //Removes all instances
- //Resets the usage of top count objects, making them available for reuse
- void markUnusedTop(const uint32_t& count) { mUseCount -= count; }
- /* Returns rot dump.
- * Expects a NULL terminated buffer of big enough size.
- */
- void getDump(char *buf, size_t len);
- int getRotDevFd();
- int getNumActiveSessions() { return mUseCount; }
-
- static RotMgr *getInstance();
-
-private:
- RotMgr();
- static RotMgr *sRotMgr;
-
- overlay::Rotator *mRot[MAX_ROT_SESS];
- uint32_t mUseCount;
- int mRotDevFd;
-};
-
-
-} // overlay
-
-#endif // OVERlAY_ROTATOR_H
diff --git a/msm8909/liboverlay/overlayUtils.cpp b/msm8909/liboverlay/overlayUtils.cpp
deleted file mode 100644
index cbd52aed..00000000
--- a/msm8909/liboverlay/overlayUtils.cpp
+++ /dev/null
@@ -1,399 +0,0 @@
-/*
-* Copyright (c) 2011-2014, The Linux Foundation. All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions are
-* met:
-* * Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
-* * Redistributions in binary form must reproduce the above
-* copyright notice, this list of conditions and the following
-* disclaimer in the documentation and/or other materials provided
-* with the distribution.
-* * Neither the name of The Linux Foundation nor the names of its
-* contributors may be used to endorse or promote products derived
-* from this software without specific prior written permission.
-*
-* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
-* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
-* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
-* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
-* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
-* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-#include <stdlib.h>
-#include <math.h>
-#include <utils/Log.h>
-#include <linux/msm_mdp.h>
-#include <cutils/properties.h>
-#include "gralloc_priv.h"
-#include "overlayUtils.h"
-#include "mdpWrapper.h"
-#include "mdp_version.h"
-#include <hardware/hwcomposer_defs.h>
-
-// just a helper static thingy
-namespace {
-struct IOFile {
- IOFile(const char* s, const char* mode) : fp(0) {
- fp = ::fopen(s, mode);
- if(!fp) {
- ALOGE("Failed open %s", s);
- }
- }
- template <class T>
- size_t read(T& r, size_t elem) {
- if(fp) {
- return ::fread(&r, sizeof(T), elem, fp);
- }
- return 0;
- }
- size_t write(const char* s, uint32_t val) {
- if(fp) {
- return ::fprintf(fp, s, val);
- }
- return 0;
- }
- bool valid() const { return fp != 0; }
- ~IOFile() {
- if(fp) ::fclose(fp);
- fp=0;
- }
- FILE* fp;
-};
-}
-
-namespace overlay {
-
-//----------From class Res ------------------------------
-const char* const Res::fbPath = "/dev/graphics/fb%u";
-const char* const Res::rotPath = "/dev/msm_rotator";
-//--------------------------------------------------------
-
-
-
-namespace utils {
-
-//--------------------------------------------------------
-//Refer to graphics.h, gralloc_priv.h, msm_mdp.h
-int getMdpFormat(int format) {
- switch (format) {
- //From graphics.h
- case HAL_PIXEL_FORMAT_RGBA_8888 :
- return MDP_RGBA_8888;
- case HAL_PIXEL_FORMAT_RGBX_8888:
- return MDP_RGBX_8888;
- case HAL_PIXEL_FORMAT_RGB_888:
- return MDP_RGB_888;
- case HAL_PIXEL_FORMAT_RGB_565:
- return MDP_RGB_565;
- case HAL_PIXEL_FORMAT_BGRA_8888:
- return MDP_BGRA_8888;
- case HAL_PIXEL_FORMAT_BGRX_8888:
- return MDP_BGRX_8888;
- case HAL_PIXEL_FORMAT_YV12:
- return MDP_Y_CR_CB_GH2V2;
- case HAL_PIXEL_FORMAT_YCbCr_422_SP:
- return MDP_Y_CBCR_H2V1;
- case HAL_PIXEL_FORMAT_YCrCb_420_SP:
- return MDP_Y_CRCB_H2V2;
-
- //From gralloc_priv.h
- case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED:
- return MDP_Y_CBCR_H2V2_TILE;
- case HAL_PIXEL_FORMAT_YCbCr_420_SP:
- return MDP_Y_CBCR_H2V2;
- case HAL_PIXEL_FORMAT_YCrCb_422_SP:
- return MDP_Y_CRCB_H2V1;
- case HAL_PIXEL_FORMAT_YCbCr_422_I:
- return MDP_YCBYCR_H2V1;
- case HAL_PIXEL_FORMAT_YCrCb_422_I:
- return MDP_YCRYCB_H2V1;
- case HAL_PIXEL_FORMAT_YCbCr_444_SP:
- return MDP_Y_CBCR_H1V1;
- case HAL_PIXEL_FORMAT_YCrCb_444_SP:
- return MDP_Y_CRCB_H1V1;
- case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
- case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
- //NV12 encodeable format maps to the venus format on
- //B-Family targets
- return MDP_Y_CBCR_H2V2_VENUS;
- default:
- //Unsupported by MDP
- //---graphics.h--------
- //HAL_PIXEL_FORMAT_RGBA_5551
- //HAL_PIXEL_FORMAT_RGBA_4444
- //---gralloc_priv.h-----
- //HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO = 0x7FA30C01
- //HAL_PIXEL_FORMAT_R_8 = 0x10D
- //HAL_PIXEL_FORMAT_RG_88 = 0x10E
- ALOGE("%s: Unsupported HAL format = 0x%x", __func__, format);
- return -1;
- }
- // not reached
- return -1;
-}
-
-// This function returns corresponding tile format
-// MDSS support following RGB tile formats
-// 32 bit formats
-// 16 bit formats
-int getMdpFormat(int format, bool tileEnabled)
-{
- if(!tileEnabled) {
- return getMdpFormat(format);
- }
- switch (format) {
- case HAL_PIXEL_FORMAT_RGBA_8888 :
- return MDP_RGBA_8888_TILE;
- case HAL_PIXEL_FORMAT_RGBX_8888:
- return MDP_RGBX_8888_TILE;
- case HAL_PIXEL_FORMAT_RGB_565:
- return MDP_RGB_565_TILE;
- case HAL_PIXEL_FORMAT_BGRA_8888:
- return MDP_BGRA_8888_TILE;
- case HAL_PIXEL_FORMAT_BGRX_8888:
- return MDP_BGRX_8888_TILE;
- default:
- return getMdpFormat(format);
- }
-}
-
-
-
-//Takes mdp format as input and translates to equivalent HAL format
-//Refer to graphics.h, gralloc_priv.h, msm_mdp.h for formats.
-int getHALFormat(int mdpFormat) {
- switch (mdpFormat) {
- //From graphics.h
- case MDP_RGBA_8888:
- return HAL_PIXEL_FORMAT_RGBA_8888;
- case MDP_RGBX_8888:
- return HAL_PIXEL_FORMAT_RGBX_8888;
- case MDP_RGB_888:
- return HAL_PIXEL_FORMAT_RGB_888;
- case MDP_RGB_565:
- return HAL_PIXEL_FORMAT_RGB_565;
- case MDP_BGRA_8888:
- return HAL_PIXEL_FORMAT_BGRA_8888;
- case MDP_Y_CR_CB_GH2V2:
- return HAL_PIXEL_FORMAT_YV12;
- case MDP_Y_CBCR_H2V1:
- return HAL_PIXEL_FORMAT_YCbCr_422_SP;
- case MDP_Y_CRCB_H2V2:
- return HAL_PIXEL_FORMAT_YCrCb_420_SP;
-
- //From gralloc_priv.h
- case MDP_Y_CBCR_H2V2_TILE:
- return HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED;
- case MDP_Y_CBCR_H2V2:
- return HAL_PIXEL_FORMAT_YCbCr_420_SP;
- case MDP_Y_CRCB_H2V1:
- return HAL_PIXEL_FORMAT_YCrCb_422_SP;
- case MDP_YCBYCR_H2V1:
- return HAL_PIXEL_FORMAT_YCbCr_422_I;
- case MDP_YCRYCB_H2V1:
- return HAL_PIXEL_FORMAT_YCrCb_422_I;
- case MDP_Y_CBCR_H1V1:
- return HAL_PIXEL_FORMAT_YCbCr_444_SP;
- case MDP_Y_CRCB_H1V1:
- return HAL_PIXEL_FORMAT_YCrCb_444_SP;
- case MDP_Y_CBCR_H2V2_VENUS:
- return HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS;
- default:
- ALOGE("%s: Unsupported MDP format = 0x%x", __func__, mdpFormat);
- return -1;
- }
- // not reached
- return -1;
-}
-
-int getMdpOrient(eTransform rotation) {
- int retTrans = 0;
- bool trans90 = false;
- int mdpVersion = qdutils::MDPVersion::getInstance().getMDPVersion();
- bool aFamily = (mdpVersion < qdutils::MDSS_V5);
-
- ALOGD_IF(DEBUG_OVERLAY, "%s: In rotation = %d", __FUNCTION__, rotation);
- if(rotation & OVERLAY_TRANSFORM_ROT_90) {
- retTrans |= MDP_ROT_90;
- trans90 = true;
- }
-
- if(rotation & OVERLAY_TRANSFORM_FLIP_H) {
- if(trans90 && aFamily) {
- //Swap for a-family, since its driver does 90 first
- retTrans |= MDP_FLIP_UD;
- } else {
- retTrans |= MDP_FLIP_LR;
- }
- }
-
- if(rotation & OVERLAY_TRANSFORM_FLIP_V) {
- if(trans90 && aFamily) {
- //Swap for a-family, since its driver does 90 first
- retTrans |= MDP_FLIP_LR;
- } else {
- retTrans |= MDP_FLIP_UD;
- }
- }
-
- ALOGD_IF(DEBUG_OVERLAY, "%s: Out rotation = %d", __FUNCTION__, retTrans);
- return retTrans;
-}
-
-void getDecimationFactor(const int& src_w, const int& src_h,
- const int& dst_w, const int& dst_h, uint8_t& horzDeci,
- uint8_t& vertDeci) {
- horzDeci = 0;
- vertDeci = 0;
- float horDscale = ceilf((float)src_w / (float)dst_w);
- float verDscale = ceilf((float)src_h / (float)dst_h);
- qdutils::MDPVersion& mdpHw = qdutils::MDPVersion::getInstance();
-
- //Next power of 2, if not already
- horDscale = powf(2.0f, ceilf(log2f(horDscale)));
- verDscale = powf(2.0f, ceilf(log2f(verDscale)));
-
- //Since MDP can do downscale and has better quality, split the task
- //between decimator and MDP downscale
- horDscale /= (float)mdpHw.getMaxMDPDownscale();
- verDscale /= (float)mdpHw.getMaxMDPDownscale();
-
- if((int)horDscale)
- horzDeci = (uint8_t)log2f(horDscale);
-
- if((int)verDscale)
- vertDeci = (uint8_t)log2f(verDscale);
-
- if(src_w > (int) mdpHw.getMaxMixerWidth()) {
- //If the client sends us something > what a layer mixer supports
- //then it means it doesn't want to use split-pipe but wants us to
- //decimate. A minimum decimation of 2 will ensure that the width is
- //always within layer mixer limits.
- if(horzDeci < 2)
- horzDeci = 2;
- }
-}
-
-static inline int compute(const uint32_t& x, const uint32_t& y,
- const uint32_t& z) {
- return x - ( y + z );
-}
-
-void preRotateSource(const eTransform& tr, Whf& whf, Dim& srcCrop) {
- if(tr & OVERLAY_TRANSFORM_FLIP_H) {
- srcCrop.x = compute(whf.w, srcCrop.x, srcCrop.w);
- }
- if(tr & OVERLAY_TRANSFORM_FLIP_V) {
- srcCrop.y = compute(whf.h, srcCrop.y, srcCrop.h);
- }
- if(tr & OVERLAY_TRANSFORM_ROT_90) {
- int tmp = srcCrop.x;
- srcCrop.x = compute(whf.h,
- srcCrop.y,
- srcCrop.h);
- srcCrop.y = tmp;
- swap(whf.w, whf.h);
- swap(srcCrop.w, srcCrop.h);
- }
-}
-
-void getDump(char *buf, size_t len, const char *prefix,
- const mdp_overlay& ov) {
- char str[256] = {'\0'};
- snprintf(str, 256,
- "%s id=%d z=%d alpha=%d mask=%d flags=0x%x H.Deci=%d,"
- "V.Deci=%d\n",
- prefix, ov.id, ov.z_order, ov.alpha,
- ov.transp_mask, ov.flags, ov.horz_deci, ov.vert_deci);
- strlcat(buf, str, len);
- getDump(buf, len, "\tsrc", ov.src);
- getDump(buf, len, "\tsrc_rect", ov.src_rect);
- getDump(buf, len, "\tdst_rect", ov.dst_rect);
-}
-
-void getDump(char *buf, size_t len, const char *prefix,
- const msmfb_img& ov) {
- char str_src[256] = {'\0'};
- snprintf(str_src, 256,
- "%s w=%d h=%d format=%d %s\n",
- prefix, ov.width, ov.height, ov.format,
- overlay::utils::getFormatString(ov.format));
- strlcat(buf, str_src, len);
-}
-
-void getDump(char *buf, size_t len, const char *prefix,
- const mdp_rect& ov) {
- char str_rect[256] = {'\0'};
- snprintf(str_rect, 256,
- "%s x=%d y=%d w=%d h=%d\n",
- prefix, ov.x, ov.y, ov.w, ov.h);
- strlcat(buf, str_rect, len);
-}
-
-void getDump(char *buf, size_t len, const char *prefix,
- const msmfb_overlay_data& ov) {
- char str[256] = {'\0'};
- snprintf(str, 256,
- "%s id=%d\n",
- prefix, ov.id);
- strlcat(buf, str, len);
- getDump(buf, len, "\tdata", ov.data);
-}
-
-void getDump(char *buf, size_t len, const char *prefix,
- const msmfb_data& ov) {
- char str_data[256] = {'\0'};
- snprintf(str_data, 256,
- "%s offset=%d memid=%d id=%d flags=0x%x\n",
- prefix, ov.offset, ov.memory_id, ov.id, ov.flags);
- strlcat(buf, str_data, len);
-}
-
-void getDump(char *buf, size_t len, const char *prefix,
- const msm_rotator_img_info& rot) {
- char str[256] = {'\0'};
- snprintf(str, 256, "%s sessid=%u rot=%d, enable=%d downscale=%d\n",
- prefix, rot.session_id, rot.rotations, rot.enable,
- rot.downscale_ratio);
- strlcat(buf, str, len);
- getDump(buf, len, "\tsrc", rot.src);
- getDump(buf, len, "\tdst", rot.dst);
- getDump(buf, len, "\tsrc_rect", rot.src_rect);
-}
-
-void getDump(char *buf, size_t len, const char *prefix,
- const msm_rotator_data_info& rot) {
- char str[256] = {'\0'};
- snprintf(str, 256,
- "%s sessid=%u\n",
- prefix, rot.session_id);
- strlcat(buf, str, len);
- getDump(buf, len, "\tsrc", rot.src);
- getDump(buf, len, "\tdst", rot.dst);
-}
-
-//Helper to even out x,w and y,h pairs
-//x,y are always evened to ceil and w,h are evened to floor
-void normalizeCrop(uint32_t& xy, uint32_t& wh) {
- if(xy & 1) {
- even_ceil(xy);
- if(wh & 1)
- even_floor(wh);
- else
- wh -= 2;
- } else {
- even_floor(wh);
- }
-}
-
-} // utils
-
-} // overlay
diff --git a/msm8909/liboverlay/overlayUtils.h b/msm8909/liboverlay/overlayUtils.h
deleted file mode 100644
index 2b8e3030..00000000
--- a/msm8909/liboverlay/overlayUtils.h
+++ /dev/null
@@ -1,683 +0,0 @@
-/*
-* Copyright (c) 2011-2014, The Linux Foundation. All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions are
-* met:
-* * Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
-* * Redistributions in binary form must reproduce the above
-* copyright notice, this list of conditions and the following
-* disclaimer in the documentation and/or other materials provided
-* with the distribution.
-* * Neither the name of The Linux Foundation nor the names of its
-* contributors may be used to endorse or promote products derived
-* from this software without specific prior written permission.
-*
-* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
-* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
-* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
-* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
-* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
-* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-#ifndef OVERLAY_UTILS_H
-#define OVERLAY_UTILS_H
-
-#include <cutils/log.h> // ALOGE, etc
-#include <errno.h>
-#include <fcntl.h> // open, O_RDWR, etc
-#include <hardware/hardware.h>
-#include <hardware/gralloc.h> // buffer_handle_t
-#include <linux/msm_mdp.h> // flags
-#include <linux/msm_rotator.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <utils/Log.h>
-#include "gralloc_priv.h" //for interlace
-
-// Older platforms do not support Venus
-#ifndef VENUS_COLOR_FORMAT
-#define MDP_Y_CBCR_H2V2_VENUS MDP_IMGTYPE_LIMIT
-#endif
-
-/*
-*
-* Collection of utilities functions/structs/enums etc...
-*
-* */
-
-// comment that out if you want to remove asserts
-// or put it as -D in Android.mk. your choice.
-#define OVERLAY_HAS_ASSERT
-
-#ifdef OVERLAY_HAS_ASSERT
-# define OVASSERT(x, ...) if(!(x)) { ALOGE(__VA_ARGS__); abort(); }
-#else
-# define OVASSERT(x, ...) ALOGE_IF(!(x), __VA_ARGS__)
-#endif // OVERLAY_HAS_ASSERT
-
-#define DEBUG_OVERLAY 0
-#define PROFILE_OVERLAY 0
-
-#ifndef MDSS_MDP_RIGHT_MIXER
-#define MDSS_MDP_RIGHT_MIXER 0x100
-#endif
-
-#ifndef MDP_OV_PIPE_FORCE_DMA
-#define MDP_OV_PIPE_FORCE_DMA 0x4000
-#endif
-
-#ifndef MDSS_MDP_DUAL_PIPE
-#define MDSS_MDP_DUAL_PIPE 0x200
-#endif
-
-#define FB_DEVICE_TEMPLATE "/dev/graphics/fb%u"
-
-namespace overlay {
-
-// fwd
-class Overlay;
-class OvFD;
-
-/* helper function to open by using fbnum */
-bool open(OvFD& fd, uint32_t fbnum, const char* const dev,
- int flags = O_RDWR);
-
-namespace utils {
-struct Whf;
-struct Dim;
-
-inline uint32_t setBit(uint32_t x, uint32_t mask) {
- return (x | mask);
-}
-
-inline uint32_t clrBit(uint32_t x, uint32_t mask) {
- return (x & ~mask);
-}
-
-/* Utility class to help avoid copying instances by making the copy ctor
-* and assignment operator private
-*
-* Usage:
-* class SomeClass : utils::NoCopy {...};
-*/
-class NoCopy {
-protected:
- NoCopy(){}
- ~NoCopy() {}
-private:
- NoCopy(const NoCopy&);
- const NoCopy& operator=(const NoCopy&);
-};
-
-bool isMdssRotator();
-void normalizeCrop(uint32_t& xy, uint32_t& wh);
-
-template <class Type>
-void swapWidthHeight(Type& width, Type& height);
-
-struct Dim {
- Dim () : x(0), y(0),
- w(0), h(0),
- o(0) {}
- Dim(uint32_t _x, uint32_t _y, uint32_t _w, uint32_t _h) :
- x(_x), y(_y),
- w(_w), h(_h) {}
- Dim(uint32_t _x, uint32_t _y, uint32_t _w, uint32_t _h, uint32_t _o) :
- x(_x), y(_y),
- w(_w), h(_h),
- o(_o) {}
- bool check(uint32_t _w, uint32_t _h) const {
- return (x+w <= _w && y+h <= _h);
-
- }
-
- bool operator==(const Dim& d) const {
- return d.x == x && d.y == y &&
- d.w == w && d.h == h &&
- d.o == o;
- }
-
- bool operator!=(const Dim& d) const {
- return !operator==(d);
- }
-
- void dump() const;
- uint32_t x;
- uint32_t y;
- uint32_t w;
- uint32_t h;
- uint32_t o;
-};
-
-// TODO have Whfz
-
-struct Whf {
- Whf() : w(0), h(0), format(0), size(0) {}
- Whf(uint32_t wi, uint32_t he, uint32_t f) :
- w(wi), h(he), format(f), size(0) {}
- Whf(uint32_t wi, uint32_t he, uint32_t f, uint32_t s) :
- w(wi), h(he), format(f), size(s) {}
- // FIXME not comparing size at the moment
- bool operator==(const Whf& whf) const {
- return whf.w == w && whf.h == h &&
- whf.format == format;
- }
- bool operator!=(const Whf& whf) const {
- return !operator==(whf);
- }
- void dump() const;
- uint32_t w;
- uint32_t h;
- uint32_t format;
- uint32_t size;
-};
-
-enum { MAX_PATH_LEN = 256 };
-
-enum { DEFAULT_PLANE_ALPHA = 0xFF };
-
-/**
- * Rotator flags: not to be confused with orientation flags.
- * Usually, you want to open the rotator to make sure it is
- * ready for business.
- * */
- enum eRotFlags {
- ROT_FLAGS_NONE = 0,
- //Use rotator for 0 rotation. It is used anyway for others.
- ROT_0_ENABLED = 1 << 0,
- //Enable rotator downscale optimization for hardware bugs not handled in
- //driver. If downscale optimizatation is required,
- //then rotator will be used even if its 0 rotation case.
- ROT_DOWNSCALE_ENABLED = 1 << 1,
- ROT_PREROTATED = 1 << 2,
-};
-
-enum eRotDownscale {
- ROT_DS_NONE = 0,
- ROT_DS_HALF = 1,
- ROT_DS_FOURTH = 2,
- ROT_DS_EIGHTH = 3,
-};
-
-/*
- * Various mdp flags like PIPE SHARE, DEINTERLACE etc...
- * kernel/common/linux/msm_mdp.h
- * INTERLACE_MASK: hardware/qcom/display/libgralloc/badger/fb_priv.h
- * */
-enum eMdpFlags {
- OV_MDP_FLAGS_NONE = 0,
- OV_MDP_PIPE_SHARE = MDP_OV_PIPE_SHARE,
- OV_MDP_PIPE_FORCE_DMA = MDP_OV_PIPE_FORCE_DMA,
- OV_MDP_DEINTERLACE = MDP_DEINTERLACE,
- OV_MDP_SECURE_OVERLAY_SESSION = MDP_SECURE_OVERLAY_SESSION,
- OV_MDP_SECURE_DISPLAY_OVERLAY_SESSION = MDP_SECURE_DISPLAY_OVERLAY_SESSION,
- OV_MDP_SOURCE_ROTATED_90 = MDP_SOURCE_ROTATED_90,
- OV_MDP_BACKEND_COMPOSITION = MDP_BACKEND_COMPOSITION,
- OV_MDP_BLEND_FG_PREMULT = MDP_BLEND_FG_PREMULT,
- OV_MDP_FLIP_H = MDP_FLIP_LR,
- OV_MDP_FLIP_V = MDP_FLIP_UD,
- OV_MDSS_MDP_RIGHT_MIXER = MDSS_MDP_RIGHT_MIXER,
- OV_MDP_PP_EN = MDP_OVERLAY_PP_CFG_EN,
- OV_MDSS_MDP_BWC_EN = MDP_BWC_EN,
- OV_MDSS_MDP_DUAL_PIPE = MDSS_MDP_DUAL_PIPE,
- OV_MDP_SOLID_FILL = MDP_SOLID_FILL,
-};
-
-enum eZorder {
- ZORDER_0 = 0,
- ZORDER_1,
- ZORDER_2,
- ZORDER_3,
- Z_SYSTEM_ALLOC = 0xFFFF
-};
-
-enum eMdpPipeType {
- OV_MDP_PIPE_RGB = 0,
- OV_MDP_PIPE_VG,
- OV_MDP_PIPE_DMA,
- OV_MDP_PIPE_ANY, //Any
-};
-
-// Identify destination pipes
-// TODO Names useless, replace with int and change all interfaces
-enum eDest {
- OV_P0 = 0,
- OV_P1,
- OV_P2,
- OV_P3,
- OV_P4,
- OV_P5,
- OV_P6,
- OV_P7,
- OV_P8,
- OV_P9,
- OV_INVALID,
- OV_MAX = OV_INVALID,
-};
-
-/* Used when a buffer is split over 2 pipes and sent to display */
-enum {
- OV_LEFT_SPLIT = 0,
- OV_RIGHT_SPLIT,
-};
-
-/* values for copybit_set_parameter(OVERLAY_TRANSFORM) */
-enum eTransform {
- /* No rot */
- OVERLAY_TRANSFORM_0 = 0x0,
- /* flip source image horizontally 0x1 */
- OVERLAY_TRANSFORM_FLIP_H = HAL_TRANSFORM_FLIP_H,
- /* flip source image vertically 0x2 */
- OVERLAY_TRANSFORM_FLIP_V = HAL_TRANSFORM_FLIP_V,
- /* rotate source image 180 degrees
- * It is basically bit-or-ed H | V == 0x3 */
- OVERLAY_TRANSFORM_ROT_180 = HAL_TRANSFORM_ROT_180,
- /* rotate source image 90 degrees 0x4 */
- OVERLAY_TRANSFORM_ROT_90 = HAL_TRANSFORM_ROT_90,
- /* rotate source image 90 degrees and flip horizontally 0x5 */
- OVERLAY_TRANSFORM_ROT_90_FLIP_H = HAL_TRANSFORM_ROT_90 |
- HAL_TRANSFORM_FLIP_H,
- /* rotate source image 90 degrees and flip vertically 0x6 */
- OVERLAY_TRANSFORM_ROT_90_FLIP_V = HAL_TRANSFORM_ROT_90 |
- HAL_TRANSFORM_FLIP_V,
- /* rotate source image 270 degrees
- * Basically 180 | 90 == 0x7 */
- OVERLAY_TRANSFORM_ROT_270 = HAL_TRANSFORM_ROT_270,
- /* rotate invalid like in Transform.h */
- OVERLAY_TRANSFORM_INV = 0x80
-};
-
-enum eBlending {
- OVERLAY_BLENDING_UNDEFINED = 0x0,
- /* No blending */
- OVERLAY_BLENDING_OPAQUE,
- /* src.rgb + dst.rgb*(1-src_alpha) */
- OVERLAY_BLENDING_PREMULT,
- /* src.rgb * src_alpha + dst.rgb (1 - src_alpha) */
- OVERLAY_BLENDING_COVERAGE,
-};
-
-// Used to consolidate pipe params
-struct PipeArgs {
- PipeArgs() : mdpFlags(OV_MDP_FLAGS_NONE),
- zorder(Z_SYSTEM_ALLOC),
- rotFlags(ROT_FLAGS_NONE),
- planeAlpha(DEFAULT_PLANE_ALPHA),
- blending(OVERLAY_BLENDING_COVERAGE){
- }
-
- PipeArgs(eMdpFlags f, Whf _whf,
- eZorder z, eRotFlags r,
- int pA = DEFAULT_PLANE_ALPHA, eBlending b = OVERLAY_BLENDING_COVERAGE) :
- mdpFlags(f),
- whf(_whf),
- zorder(z),
- rotFlags(r),
- planeAlpha(pA),
- blending(b){
- }
-
- eMdpFlags mdpFlags; // for mdp_overlay flags
- Whf whf;
- eZorder zorder; // stage number
- eRotFlags rotFlags;
- int planeAlpha;
- eBlending blending;
-};
-
-// Cannot use HW_OVERLAY_MAGNIFICATION_LIMIT, since at the time
-// of integration, HW_OVERLAY_MAGNIFICATION_LIMIT was a define
-enum { HW_OV_MAGNIFICATION_LIMIT = 20,
- HW_OV_MINIFICATION_LIMIT = 8
-};
-
-inline void setMdpFlags(eMdpFlags& f, eMdpFlags v) {
- f = static_cast<eMdpFlags>(setBit(f, v));
-}
-
-inline void clearMdpFlags(eMdpFlags& f, eMdpFlags v) {
- f = static_cast<eMdpFlags>(clrBit(f, v));
-}
-
-enum { FB0, FB1, FB2 };
-
-struct ScreenInfo {
- ScreenInfo() : mFBWidth(0),
- mFBHeight(0),
- mFBbpp(0),
- mFBystride(0) {}
- void dump(const char* const s) const;
- uint32_t mFBWidth;
- uint32_t mFBHeight;
- uint32_t mFBbpp;
- uint32_t mFBystride;
-};
-
-int getMdpFormat(int format);
-int getMdpFormat(int format, bool tileEnabled);
-int getHALFormat(int mdpFormat);
-void getDecimationFactor(const int& src_w, const int& src_h,
- const int& dst_w, const int& dst_h, uint8_t& horzDeci,
- uint8_t& vertDeci);
-
-/* flip is upside down and such. V, H flip
- * rotation is 90, 180 etc
- * It returns MDP related enum/define that match rot+flip*/
-int getMdpOrient(eTransform rotation);
-const char* getFormatString(int format);
-
-template <class T>
-inline void memset0(T& t) { ::memset(&t, 0, sizeof(t)); }
-
-template <class T> inline void swap ( T& a, T& b )
-{
- T c(a); a=b; b=c;
-}
-
-template<typename T> inline T max(T a, T b) { return (a > b) ? a : b; }
-
-template<typename T> inline T min(T a, T b) { return (a < b) ? a : b; }
-
-inline int alignup(int value, int a) {
- //if align = 0, return the value. Else, do alignment.
- return a ? ((((value - 1) / a) + 1) * a) : value;
-}
-
-inline int aligndown(int value, int a) {
- //if align = 0, return the value. Else, do alignment.
- return a ? ((value) & ~(a-1)) : value;
-}
-
-// FIXME that align should replace the upper one.
-inline int align(int value, int a) {
- //if align = 0, return the value. Else, do alignment.
- return a ? ((value + (a-1)) & ~(a-1)) : value;
-}
-
-inline bool isYuv(uint32_t format) {
- switch(format){
- case MDP_Y_CBCR_H2V1:
- case MDP_Y_CBCR_H2V2:
- case MDP_Y_CRCB_H2V2:
- case MDP_Y_CRCB_H1V1:
- case MDP_Y_CRCB_H2V1:
- case MDP_Y_CRCB_H2V2_TILE:
- case MDP_Y_CBCR_H2V2_TILE:
- case MDP_Y_CR_CB_H2V2:
- case MDP_Y_CR_CB_GH2V2:
- case MDP_Y_CBCR_H2V2_VENUS:
- case MDP_YCBYCR_H2V1:
- case MDP_YCRYCB_H2V1:
- return true;
- default:
- return false;
- }
- return false;
-}
-
-inline bool isRgb(uint32_t format) {
- switch(format) {
- case MDP_RGBA_8888:
- case MDP_BGRA_8888:
- case MDP_RGBX_8888:
- case MDP_RGB_565:
- return true;
- default:
- return false;
- }
- return false;
-}
-
-inline const char* getFormatString(int format){
- #define STR(f) #f;
- static const char* formats[MDP_IMGTYPE_LIMIT + 1] = {0};
- formats[MDP_RGB_565] = STR(MDP_RGB_565);
- formats[MDP_XRGB_8888] = STR(MDP_XRGB_8888);
- formats[MDP_Y_CBCR_H2V2] = STR(MDP_Y_CBCR_H2V2);
- formats[MDP_Y_CBCR_H2V2_ADRENO] = STR(MDP_Y_CBCR_H2V2_ADRENO);
- formats[MDP_ARGB_8888] = STR(MDP_ARGB_8888);
- formats[MDP_RGB_888] = STR(MDP_RGB_888);
- formats[MDP_Y_CRCB_H2V2] = STR(MDP_Y_CRCB_H2V2);
- formats[MDP_YCBYCR_H2V1] = STR(MDP_YCBYCR_H2V1);
- formats[MDP_YCRYCB_H2V1] = STR(MDP_YCRYCB_H2V1);
- formats[MDP_CBYCRY_H2V1] = STR(MDP_CBYCRY_H2V1);
- formats[MDP_Y_CRCB_H2V1] = STR(MDP_Y_CRCB_H2V1);
- formats[MDP_Y_CBCR_H2V1] = STR(MDP_Y_CBCR_H2V1);
- formats[MDP_Y_CRCB_H1V2] = STR(MDP_Y_CRCB_H1V2);
- formats[MDP_Y_CBCR_H1V2] = STR(MDP_Y_CBCR_H1V2);
- formats[MDP_RGBA_8888] = STR(MDP_RGBA_8888);
- formats[MDP_BGRA_8888] = STR(MDP_BGRA_8888);
- formats[MDP_RGBX_8888] = STR(MDP_RGBX_8888);
- formats[MDP_Y_CRCB_H2V2_TILE] = STR(MDP_Y_CRCB_H2V2_TILE);
- formats[MDP_Y_CBCR_H2V2_TILE] = STR(MDP_Y_CBCR_H2V2_TILE);
- formats[MDP_Y_CR_CB_H2V2] = STR(MDP_Y_CR_CB_H2V2);
- formats[MDP_Y_CR_CB_GH2V2] = STR(MDP_Y_CR_CB_GH2V2);
- formats[MDP_Y_CB_CR_H2V2] = STR(MDP_Y_CB_CR_H2V2);
- formats[MDP_Y_CRCB_H1V1] = STR(MDP_Y_CRCB_H1V1);
- formats[MDP_Y_CBCR_H1V1] = STR(MDP_Y_CBCR_H1V1);
- formats[MDP_YCRCB_H1V1] = STR(MDP_YCRCB_H1V1);
- formats[MDP_YCBCR_H1V1] = STR(MDP_YCBCR_H1V1);
- formats[MDP_BGR_565] = STR(MDP_BGR_565);
- formats[MDP_BGR_888] = STR(MDP_BGR_888);
- formats[MDP_Y_CBCR_H2V2_VENUS] = STR(MDP_Y_CBCR_H2V2_VENUS);
- formats[MDP_BGRX_8888] = STR(MDP_BGRX_8888);
- formats[MDP_RGBA_8888_TILE] = STR(MDP_RGBA_8888_TILE);
- formats[MDP_ARGB_8888_TILE] = STR(MDP_ARGB_8888_TILE);
- formats[MDP_ABGR_8888_TILE] = STR(MDP_ABGR_8888_TILE);
- formats[MDP_BGRA_8888_TILE] = STR(MDP_BGRA_8888_TILE);
- formats[MDP_RGBX_8888_TILE] = STR(MDP_RGBX_8888_TILE);
- formats[MDP_XRGB_8888_TILE] = STR(MDP_XRGB_8888_TILE);
- formats[MDP_XBGR_8888_TILE] = STR(MDP_XBGR_8888_TILE);
- formats[MDP_BGRX_8888_TILE] = STR(MDP_BGRX_8888_TILE);
- formats[MDP_RGB_565_TILE] = STR(MDP_RGB_565_TILE);
- formats[MDP_IMGTYPE_LIMIT] = STR(MDP_IMGTYPE_LIMIT);
-
- if(format < 0 || format >= MDP_IMGTYPE_LIMIT) {
- ALOGE("%s wrong fmt %d", __FUNCTION__, format);
- return "Unsupported format";
- }
- if(formats[format] == 0) {
- ALOGE("%s: table missing format %d from header", __FUNCTION__, format);
- return "";
- }
- return formats[format];
-}
-
-inline void Whf::dump() const {
- ALOGE("== Dump WHF w=%d h=%d f=%d s=%d start/end ==",
- w, h, format, size);
-}
-
-inline void Dim::dump() const {
- ALOGE("== Dump Dim x=%d y=%d w=%d h=%d start/end ==", x, y, w, h);
-}
-
-template <class Type>
-void swapWidthHeight(Type& width, Type& height) {
- Type tmp = width;
- width = height;
- height = tmp;
-}
-
-inline void ScreenInfo::dump(const char* const s) const {
- ALOGE("== Dump %s ScreenInfo w=%d h=%d"
- " bpp=%d stride=%d start/end ==",
- s, mFBWidth, mFBHeight, mFBbpp, mFBystride);
-}
-
-inline bool openDev(OvFD& fd, int fbnum,
- const char* const devpath, int flags) {
- return overlay::open(fd, fbnum, devpath, flags);
-}
-
-template <class T>
-inline void even_ceil(T& value) {
- if(value & 1)
- value++;
-}
-
-template <class T>
-inline void even_floor(T& value) {
- if(value & 1)
- value--;
-}
-
-/* Prerotation adjusts crop co-ordinates to the new transformed values within
- * destination buffer. This is necessary only when the entire buffer is rotated
- * irrespective of crop (A-family). If only the crop portion of the buffer is
- * rotated into a destination buffer matching the size of crop, we don't need to
- * use this helper (B-family).
- * @Deprecated as of now, retained for the case where a full buffer needs
- * transform and also as a reference.
- */
-void preRotateSource(const eTransform& tr, Whf& whf, Dim& srcCrop);
-void getDump(char *buf, size_t len, const char *prefix, const mdp_overlay& ov);
-void getDump(char *buf, size_t len, const char *prefix, const msmfb_img& ov);
-void getDump(char *buf, size_t len, const char *prefix, const mdp_rect& ov);
-void getDump(char *buf, size_t len, const char *prefix,
- const msmfb_overlay_data& ov);
-void getDump(char *buf, size_t len, const char *prefix, const msmfb_data& ov);
-void getDump(char *buf, size_t len, const char *prefix,
- const msm_rotator_img_info& ov);
-void getDump(char *buf, size_t len, const char *prefix,
- const msm_rotator_data_info& ov);
-
-} // namespace utils ends
-
-//--------------------Class Res stuff (namespace overlay only) -----------
-
-class Res {
-public:
- // /dev/graphics/fb%u
- static const char* const fbPath;
- // /dev/msm_rotator
- static const char* const rotPath;
-};
-
-
-//--------------------Class OvFD stuff (namespace overlay only) -----------
-
-/*
-* Holds one FD
-* Dtor will NOT close the underlying FD.
-* That enables us to copy that object around
-* */
-class OvFD {
-public:
- /* Ctor */
- explicit OvFD();
-
- /* dtor will NOT close the underlying FD */
- ~OvFD();
-
- /* Open fd using the path given by dev.
- * return false in failure */
- bool open(const char* const dev,
- int flags = O_RDWR);
-
- /* populate path */
- void setPath(const char* const dev);
-
- /* Close fd if we have a valid fd. */
- bool close();
-
- /* returns underlying fd.*/
- int getFD() const;
-
- /* returns true if fd is valid */
- bool valid() const;
-
- /* like operator= */
- void copy(int fd);
-
- /* dump the state of the instance */
- void dump() const;
-private:
- /* helper enum for determine valid/invalid fd */
- enum { INVAL = -1 };
-
- /* actual os fd */
- int mFD;
-
- /* path, for debugging */
- char mPath[utils::MAX_PATH_LEN];
-};
-
-//-------------------Inlines--------------------------
-
-inline bool open(OvFD& fd, uint32_t fbnum, const char* const dev, int flags)
-{
- char dev_name[64] = {0};
- snprintf(dev_name, sizeof(dev_name), dev, fbnum);
- return fd.open(dev_name, flags);
-}
-
-inline OvFD::OvFD() : mFD (INVAL) {
- mPath[0] = 0;
-}
-
-inline OvFD::~OvFD() {
- //no op since copy() can be used to share fd, in 3d cases.
-}
-
-inline bool OvFD::open(const char* const dev, int flags)
-{
- mFD = ::open(dev, flags, 0);
- if (mFD < 0) {
- // FIXME errno, strerror in bionic?
- ALOGE("Cant open device %s err=%d", dev, errno);
- return false;
- }
- setPath(dev);
- return true;
-}
-
-inline void OvFD::setPath(const char* const dev)
-{
- ::strlcpy(mPath, dev, sizeof(mPath));
-}
-
-inline bool OvFD::close()
-{
- int ret = 0;
- if(valid()) {
- ret = ::close(mFD);
- mFD = INVAL;
- }
- return (ret == 0);
-}
-
-inline bool OvFD::valid() const
-{
- return (mFD != INVAL);
-}
-
-inline int OvFD::getFD() const { return mFD; }
-
-inline void OvFD::copy(int fd) {
- mFD = fd;
-}
-
-inline void OvFD::dump() const
-{
- ALOGE("== Dump OvFD fd=%d path=%s start/end ==",
- mFD, mPath);
-}
-
-//--------------- class OvFD stuff ends ---------------------
-
-} // overlay
-
-
-#endif // OVERLAY_UTILS_H
diff --git a/msm8909/liboverlay/overlayWriteback.cpp b/msm8909/liboverlay/overlayWriteback.cpp
deleted file mode 100644
index ed42a9f0..00000000
--- a/msm8909/liboverlay/overlayWriteback.cpp
+++ /dev/null
@@ -1,280 +0,0 @@
-/*
-* Copyright (c) 2013 The Linux Foundation. All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions are
-* met:
-* * Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
-* * Redistributions in binary form must reproduce the above
-* copyright notice, this list of conditions and the following
-* disclaimer in the documentation and/or other materials provided
-* with the distribution.
-* * Neither the name of The Linux Foundation. nor the names of its
-* contributors may be used to endorse or promote products derived
-* from this software without specific prior written permission.
-*
-* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
-* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
-* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
-* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
-* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
-* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-#include "overlay.h"
-#include "overlayWriteback.h"
-#include "mdpWrapper.h"
-
-#define SIZE_1M 0x00100000
-
-namespace overlay {
-
-//=========== class WritebackMem ==============================================
-bool WritebackMem::manageMem(uint32_t size, bool isSecure) {
- if(mBuf.bufSz() == size) {
- return true;
- }
- if(mBuf.valid()) {
- if(!mBuf.close()) {
- ALOGE("%s error closing mem", __func__);
- return false;
- }
- }
- return alloc(size, isSecure);
-}
-
-bool WritebackMem::alloc(uint32_t size, bool isSecure) {
- if(!mBuf.open(NUM_BUFS, size, isSecure)){
- ALOGE("%s: Failed to open", __func__);
- mBuf.close();
- return false;
- }
-
- OVASSERT(MAP_FAILED != mBuf.addr(), "MAP failed");
- OVASSERT(mBuf.getFD() != -1, "getFd is -1");
-
- mCurrOffsetIndex = 0;
- for (uint32_t i = 0; i < NUM_BUFS; i++) {
- mOffsets[i] = i * size;
- }
- return true;
-}
-
-bool WritebackMem::dealloc() {
- bool ret = true;
- if(mBuf.valid()) {
- ret = mBuf.close();
- }
- return ret;
-}
-
-//=========== class Writeback =================================================
-Writeback::Writeback() : mXres(0), mYres(0), mOpFmt(-1), mSecure(false) {
- int fbNum = Overlay::getFbForDpy(Overlay::DPY_WRITEBACK);
- if(!utils::openDev(mFd, fbNum, Res::fbPath, O_RDWR)) {
- ALOGE("%s failed to init %s", __func__, Res::fbPath);
- return;
- }
- startSession();
-}
-
-Writeback::~Writeback() {
- stopSession();
- if (!mFd.close()) {
- ALOGE("%s error closing fd", __func__);
- }
-}
-
-bool Writeback::startSession() {
- if(!mdp_wrapper::wbInitStart(mFd.getFD())) {
- ALOGE("%s failed", __func__);
- return false;
- }
- return true;
-}
-
-bool Writeback::stopSession() {
- if(mFd.valid()) {
- if(!Overlay::displayCommit(mFd.getFD())) {
- ALOGE("%s: displayCommit failed", __func__);
- return false;
- }
- if(!mdp_wrapper::wbStopTerminate(mFd.getFD())) {
- ALOGE("%s: wbStopTerminate failed", __func__);
- return false;
- }
- } else {
- ALOGE("%s Invalid fd", __func__);
- return false;
- }
- return true;
-}
-
-bool Writeback::configureDpyInfo(int xres, int yres) {
- if(mXres != xres || mYres != yres) {
- fb_var_screeninfo vinfo;
- memset(&vinfo, 0, sizeof(fb_var_screeninfo));
- if(!mdp_wrapper::getVScreenInfo(mFd.getFD(), vinfo)) {
- ALOGE("%s failed", __func__);
- return false;
- }
- vinfo.xres = xres;
- vinfo.yres = yres;
- vinfo.xres_virtual = xres;
- vinfo.yres_virtual = yres;
- vinfo.xoffset = 0;
- vinfo.yoffset = 0;
- if(!mdp_wrapper::setVScreenInfo(mFd.getFD(), vinfo)) {
- ALOGE("%s failed", __func__);
- return false;
- }
- mXres = xres;
- mYres = yres;
- }
- return true;
-}
-
-bool Writeback::configureMemory(uint32_t size) {
- if(!mWbMem.manageMem(size, mSecure)) {
- ALOGE("%s failed, memory failure", __func__);
- return false;
- }
- return true;
-}
-
-bool Writeback::queueBuffer(int opFd, uint32_t opOffset) {
- memset(&mFbData, 0, sizeof(struct msmfb_data));
- //Queue
- mFbData.offset = opOffset;
- mFbData.memory_id = opFd;
- mFbData.id = 0;
- mFbData.flags = 0;
- if(!mdp_wrapper::wbQueueBuffer(mFd.getFD(), mFbData)) {
- ALOGE("%s: queuebuffer failed", __func__);
- return false;
- }
- return true;
-}
-
-bool Writeback::dequeueBuffer() {
- //Dequeue
- mFbData.flags = MSMFB_WRITEBACK_DEQUEUE_BLOCKING;
- if(!mdp_wrapper::wbDequeueBuffer(mFd.getFD(), mFbData)) {
- ALOGE("%s: dequeuebuffer failed", __func__);
- return false;
- }
- return true;
-}
-
-bool Writeback::writeSync(int opFd, uint32_t opOffset) {
- if(!queueBuffer(opFd, opOffset)) {
- return false;
- }
- if(!Overlay::displayCommit(mFd.getFD())) {
- return false;
- }
- if(!dequeueBuffer()) {
- return false;
- }
- return true;
-}
-
-bool Writeback::writeSync() {
- mWbMem.useNextBuffer();
- return writeSync(mWbMem.getDstFd(), mWbMem.getOffset());
-}
-
-bool Writeback::setOutputFormat(int mdpFormat) {
- if(mdpFormat != mOpFmt) {
- struct msmfb_metadata metadata;
- memset(&metadata, 0 , sizeof(metadata));
- metadata.op = metadata_op_wb_format;
- metadata.data.mixer_cfg.writeback_format = mdpFormat;
- if (ioctl(mFd.getFD(), MSMFB_METADATA_SET, &metadata) < 0) {
- ALOGE("Error setting MDP Writeback format");
- return false;
- }
- mOpFmt = mdpFormat;
- }
- return true;
-}
-
-int Writeback::getOutputFormat() {
- if(mOpFmt < 0) {
- struct msmfb_metadata metadata;
- memset(&metadata, 0 , sizeof(metadata));
- metadata.op = metadata_op_wb_format;
- if (ioctl(mFd.getFD(), MSMFB_METADATA_GET, &metadata) < 0) {
- ALOGE("Error retrieving MDP Writeback format");
- return -1;
- }
- mOpFmt = metadata.data.mixer_cfg.writeback_format;
- }
- return mOpFmt;
-}
-
-bool Writeback::setSecure(bool isSecure) {
- if(isSecure != mSecure) {
- // Call IOCTL to set WB interface as secure
- struct msmfb_metadata metadata;
- memset(&metadata, 0 , sizeof(metadata));
- metadata.op = metadata_op_wb_secure;
- metadata.data.secure_en = isSecure;
- if (ioctl(mFd.getFD(), MSMFB_METADATA_SET, &metadata) < 0) {
- ALOGE("Error setting MDP WB secure");
- return false;
- }
- mSecure = isSecure;
- }
- return true;
-}
-
-//static
-
-Writeback *Writeback::getInstance() {
- if(sWb == NULL) {
- sWb = new Writeback();
- }
- sUsed = true;
- return sWb;
-}
-
-void Writeback::configDone() {
- if(sUsed == false && sWb) {
- delete sWb;
- sWb = NULL;
- }
-}
-
-void Writeback::clear() {
- sUsed = false;
- if(sWb) {
- delete sWb;
- sWb = NULL;
- }
-}
-
-bool Writeback::getDump(char *buf, size_t len) {
- if(sWb) {
- utils::getDump(buf, len, "WBData", sWb->mFbData);
- char outputBufferInfo[256];
- snprintf(outputBufferInfo, sizeof(outputBufferInfo),
- "OutputBuffer xres=%d yres=%d format=%s\n\n",
- sWb->getWidth(), sWb->getHeight(),
- utils::getFormatString(sWb->getOutputFormat()));
- strlcat(buf, outputBufferInfo, len);
- return true;
- }
- return false;
-}
-
-Writeback *Writeback::sWb = 0;
-bool Writeback::sUsed = false;
-
-} //namespace overlay
diff --git a/msm8909/liboverlay/overlayWriteback.h b/msm8909/liboverlay/overlayWriteback.h
deleted file mode 100644
index 21186e6a..00000000
--- a/msm8909/liboverlay/overlayWriteback.h
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
-* Copyright (c) 2013 The Linux Foundation. All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions are
-* met:
-* * Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
-* * Redistributions in binary form must reproduce the above
-* copyright notice, this list of conditions and the following
-* disclaimer in the documentation and/or other materials provided
-* with the distribution.
-* * Neither the name of The Linux Foundation. nor the names of its
-* contributors may be used to endorse or promote products derived
-* from this software without specific prior written permission.
-*
-* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
-* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
-* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
-* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
-* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
-* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-#ifndef OVERLAY_WRITEBACK_H
-#define OVERLAY_WRITEBACK_H
-
-#include "overlayMem.h"
-
-namespace overlay {
-
-class WritebackMgr;
-
-class WritebackMem {
-public:
- explicit WritebackMem() : mCurrOffsetIndex(0) {
- memset(&mOffsets, 0, sizeof(mOffsets));
- }
- ~WritebackMem() { dealloc(); }
- bool manageMem(uint32_t size, bool isSecure);
- void useNextBuffer() {
- mCurrOffsetIndex = (mCurrOffsetIndex + 1) % NUM_BUFS;
- }
- uint32_t getOffset() const { return mOffsets[mCurrOffsetIndex]; }
- int getDstFd() const { return mBuf.getFD(); }
-private:
- bool alloc(uint32_t size, bool isSecure);
- bool dealloc();
- enum { NUM_BUFS = 2 };
- OvMem mBuf;
- uint32_t mOffsets[NUM_BUFS];
- uint32_t mCurrOffsetIndex;
-};
-
-//Abstracts the WB2 interface of MDP
-//Has modes to either manage memory or work with memory allocated elsewhere
-class Writeback {
-public:
- ~Writeback();
- bool configureDpyInfo(int xres, int yres);
- bool configureMemory(uint32_t size);
- /* Blocking write. (queue, commit, dequeue)
- * This class will do writeback memory management.
- * This class will call display-commit on writeback mixer.
- */
- bool writeSync();
- /* Blocking write. (queue, commit, dequeue)
- * Client must do writeback memory management.
- * Client must not call display-commit on writeback mixer.
- */
- bool writeSync(int opFd, uint32_t opOffset);
- /* Async queue. (Does not write)
- * Client must do writeback memory management.
- * Client must call display-commit on their own.
- * Client must use sync mechanism e.g sync pt.
- */
- bool queueBuffer(int opFd, uint32_t opOffset);
- uint32_t getOffset() const { return mWbMem.getOffset(); }
- int getDstFd() const { return mWbMem.getDstFd(); }
- int getWidth() const { return mXres; }
- int getHeight() const { return mYres; }
- /* Subject to GC if writeback isnt used for a drawing round.
- * Get always if caching the value.
- */
- int getFbFd() const { return mFd.getFD(); }
- int getOutputFormat();
- bool setOutputFormat(int mdpFormat);
- bool setSecure(bool isSecure);
-
- static Writeback* getInstance();
- static void configBegin() { sUsed = false; }
- static void configDone();
- static void clear();
- //Will take a dump of data structure only if there is an instance existing
- //Returns true if dump is added to the input buffer, false otherwise
- static bool getDump(char *buf, size_t len);
-
-private:
- explicit Writeback();
- bool startSession();
- bool stopSession();
- //Actually block_until_write_done for the usage here.
- bool dequeueBuffer();
- OvFD mFd;
- WritebackMem mWbMem;
- struct msmfb_data mFbData;
- int mXres;
- int mYres;
- int mOpFmt;
- bool mSecure;
-
- static bool sUsed;
- static Writeback *sWb;
-};
-
-}
-
-#endif
diff --git a/msm8909/liboverlay/pipes/overlayGenPipe.cpp b/msm8909/liboverlay/pipes/overlayGenPipe.cpp
deleted file mode 100644
index aebaebfb..00000000
--- a/msm8909/liboverlay/pipes/overlayGenPipe.cpp
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
-* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions are
-* met:
-* * Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
-* * Redistributions in binary form must reproduce the above
-* copyright notice, this list of conditions and the following
-* disclaimer in the documentation and/or other materials provided
-* with the distribution.
-* * Neither the name of The Linux Foundation nor the names of its
-* contributors may be used to endorse or promote products derived
-* from this software without specific prior written permission.
-*
-* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
-* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
-* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
-* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
-* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
-* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-#include "overlayGenPipe.h"
-#include "mdp_version.h"
-
-namespace overlay {
-
-GenericPipe::GenericPipe(const int& dpy) : mDpy(dpy),
- mCtrl(new Ctrl(dpy)), mData(new Data(dpy)) {
-}
-
-GenericPipe::~GenericPipe() {
- delete mCtrl;
- delete mData;
-}
-
-void GenericPipe::setSource(const utils::PipeArgs& args) {
- mCtrl->setSource(args);
-}
-
-void GenericPipe::setCrop(const overlay::utils::Dim& d) {
- mCtrl->setCrop(d);
-}
-
-void GenericPipe::setColor(const uint32_t color) {
- mCtrl->setColor(color);
-}
-
-void GenericPipe::setTransform(const utils::eTransform& orient) {
- mCtrl->setTransform(orient);
-}
-
-void GenericPipe::setPosition(const utils::Dim& d) {
- mCtrl->setPosition(d);
-}
-
-bool GenericPipe::setVisualParams(const MetaData_t &metadata)
-{
- return mCtrl->setVisualParams(metadata);
-}
-
-void GenericPipe::setPipeType(const utils::eMdpPipeType& pType) {
- mCtrl->setPipeType(pType);
-}
-
-bool GenericPipe::commit() {
- return mCtrl->commit();
-}
-
-bool GenericPipe::queueBuffer(int fd, uint32_t offset) {
- int pipeId = mCtrl->getPipeId();
- OVASSERT(-1 != pipeId, "Ctrl ID should not be -1");
- // set pipe id from ctrl to data
- mData->setPipeId(pipeId);
-
- return mData->queueBuffer(fd, offset);
-}
-
-utils::Dim GenericPipe::getCrop() const
-{
- return mCtrl->getCrop();
-}
-
-uint8_t GenericPipe::getPriority() const {
- return mCtrl->getPriority();
-}
-
-void GenericPipe::dump() const
-{
- ALOGE("== Dump Generic pipe start ==");
- mCtrl->dump();
- mData->dump();
- ALOGE("== Dump Generic pipe end ==");
-}
-
-void GenericPipe::getDump(char *buf, size_t len) {
- mCtrl->getDump(buf, len);
- mData->getDump(buf, len);
-}
-
-int GenericPipe::getPipeId() {
- return mCtrl->getPipeId();
-}
-
-bool GenericPipe::validateAndSet(GenericPipe* pipeArray[], const int& count,
- const int& fbFd) {
- Ctrl* ctrlArray[count];
- memset(&ctrlArray, 0, sizeof(ctrlArray));
-
- for(int i = 0; i < count; i++) {
- ctrlArray[i] = pipeArray[i]->mCtrl;
- }
-
- return Ctrl::validateAndSet(ctrlArray, count, fbFd);
-}
-
-} //namespace overlay
diff --git a/msm8909/liboverlay/pipes/overlayGenPipe.h b/msm8909/liboverlay/pipes/overlayGenPipe.h
deleted file mode 100644
index 0a2639a1..00000000
--- a/msm8909/liboverlay/pipes/overlayGenPipe.h
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
-* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions are
-* met:
-* * Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
-* * Redistributions in binary form must reproduce the above
-* copyright notice, this list of conditions and the following
-* disclaimer in the documentation and/or other materials provided
-* with the distribution.
-* * Neither the name of The Linux Foundation nor the names of its
-* contributors may be used to endorse or promote products derived
-* from this software without specific prior written permission.
-*
-* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
-* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
-* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
-* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
-* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
-* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-#ifndef OVERLAY_GENERIC_PIPE_H
-#define OVERLAY_GENERIC_PIPE_H
-
-#include "overlayUtils.h"
-#include "overlayCtrlData.h"
-
-namespace overlay {
-
-class GenericPipe : utils::NoCopy {
-public:
- /* ctor */
- explicit GenericPipe(const int& dpy);
- /* dtor */
- ~GenericPipe();
- /* Control APIs */
- /* set source using whf, orient and wait flag */
- void setSource(const utils::PipeArgs& args);
- /* set crop a.k.a the region of interest */
- void setCrop(const utils::Dim& d);
- /* set color for mdp pipe */
- void setColor(const uint32_t color);
- /* set orientation*/
- void setTransform(const utils::eTransform& param);
- /* set mdp posision using dim */
- void setPosition(const utils::Dim& dim);
- /* set visual param */
- bool setVisualParams(const MetaData_t &metadata);
- /* set pipe type RGB/DMA/VG */
- void setPipeType(const utils::eMdpPipeType& pType);
- /* commit changes to the overlay "set"*/
- bool commit();
- /* Data APIs */
- /* queue buffer to the overlay */
- bool queueBuffer(int fd, uint32_t offset);
- /* return cached startup args */
- const utils::PipeArgs& getArgs() const;
- /* retrieve cached crop data */
- utils::Dim getCrop() const;
- /* return pipe priority */
- uint8_t getPriority() const;
- /* dump the state of the object */
- void dump() const;
- /* Return the dump in the specified buffer */
- void getDump(char *buf, size_t len);
- int getPipeId();
-
- static bool validateAndSet(GenericPipe* pipeArray[], const int& count,
- const int& fbFd);
-private:
- int mDpy;
- Ctrl *mCtrl;
- Data *mData;
-};
-
-} //namespace overlay
-
-#endif // OVERLAY_GENERIC_PIPE_H
diff --git a/msm8909/libqdutils/Android.bp b/msm8909/libqdutils/Android.bp
new file mode 100644
index 00000000..3166e8d0
--- /dev/null
+++ b/msm8909/libqdutils/Android.bp
@@ -0,0 +1,42 @@
+cc_library_shared {
+ name: "libqdutils",
+ vendor: true,
+ defaults: ["display_defaults"],
+ header_libs: ["libhardware_headers", "libutils_headers"],
+ shared_libs: [
+ "libbinder",
+ "libqservice",
+ ],
+ cflags: [
+ "-DDEBUG_CALC_FPS",
+ "-DLOG_TAG=\"qdutils\"",
+ "-Wno-sign-conversion",
+ ],
+ srcs: [
+ "qd_utils.cpp",
+ "display_config.cpp",
+ "profiler.cpp"
+ ],
+}
+
+cc_library_shared {
+ name: "libqdMetaData",
+ vendor: true,
+ defaults: ["display_defaults"],
+ cflags: [
+ "-Wno-sign-conversion",
+ "-DLOG_TAG=\"qdmetadata\"",
+ ],
+ srcs: ["qdMetaData.cpp","qd_utils.cpp"],
+}
+
+// Remove after WFD moves to use libqdMetaData directly
+cc_library_shared {
+ name: "libqdMetaData.system",
+ defaults: ["display_defaults"],
+ cflags: [
+ "-Wno-sign-conversion",
+ "-DLOG_TAG=\"qdmetadata\"",
+ ],
+ srcs: ["qdMetaData.cpp","qd_utils.cpp"],
+}
diff --git a/msm8909/libqdutils/Android.mk b/msm8909/libqdutils/Android.mk
deleted file mode 100644
index 444ca32e..00000000
--- a/msm8909/libqdutils/Android.mk
+++ /dev/null
@@ -1,40 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-include $(LOCAL_PATH)/../common.mk
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := libqdutils
-LOCAL_MODULE_TAGS := optional
-LOCAL_SHARED_LIBRARIES := $(common_libs) libui libbinder libqservice
-LOCAL_C_INCLUDES := $(common_includes) $(kernel_includes)
-LOCAL_CFLAGS := $(common_flags) -DLOG_TAG=\"qdutils\" -Wno-float-conversion
-LOCAL_CLANG := $(common_clang_flags)
-
-ifeq ($(TARGET_SUPPORTS_WEARABLES),true)
-LOCAL_CFLAGS += -DHDMI_STUB
-endif
-
-LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps)
-LOCAL_COPY_HEADERS_TO := $(common_header_export_path)
-LOCAL_COPY_HEADERS := display_config.h mdp_version.h
-LOCAL_SRC_FILES := profiler.cpp mdp_version.cpp \
- idle_invalidator.cpp \
- comptype.cpp qd_utils.cpp \
- cb_utils.cpp display_config.cpp \
- cb_swap_rect.cpp
-include $(BUILD_SHARED_LIBRARY)
-
-include $(CLEAR_VARS)
-
-LOCAL_COPY_HEADERS_TO := $(common_header_export_path)
-LOCAL_COPY_HEADERS := qdMetaData.h
-LOCAL_SHARED_LIBRARIES := liblog libcutils
-LOCAL_C_INCLUDES := $(common_includes)
-LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps)
-LOCAL_SRC_FILES := qdMetaData.cpp
-LOCAL_CFLAGS := $(common_flags)
-LOCAL_CFLAGS += -DLOG_TAG=\"DisplayMetaData\"
-LOCAL_CLANG := $(common_clang_flags)
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE := libqdMetaData
-include $(BUILD_SHARED_LIBRARY)
-
diff --git a/msm8909/libqdutils/Makefile.am b/msm8909/libqdutils/Makefile.am
new file mode 100644
index 00000000..01fbf199
--- /dev/null
+++ b/msm8909/libqdutils/Makefile.am
@@ -0,0 +1,32 @@
+h_sources = qdMetaData.h
+
+cpp_sources = qdMetaData.cpp
+
+library_includedir = $(includedir)
+library_include_HEADERS = $(h_sources)
+
+lib_LTLIBRARIES = libqdMetaData.la
+libqdMetaData_la_CC = @CC@
+libqdMetaData_la_SOURCES = $(cpp_sources)
+libqdMetaData_la_CFLAGS = $(AM_CFLAGS) -DLOG_TAG=\"DisplayMetaData\"
+libqdMetaData_la_CPPFLAGS = $(AM_CPPFLAGS)
+libqdMetaData_LDADD = -lcutils -llog
+libqdMetaData_la_LDFLAGS = -shared -avoid-version
+
+header_sources = display_config.h
+
+c_sources = profiler.cpp \
+ qd_utils.cpp \
+ display_config.cpp
+
+library_includedir = $(includedir)
+library_include_HEADERS = $(header_sources)
+
+lib_LTLIBRARIES += libqdutils.la
+libqdutils_la_CC = @CC@
+libqdutils_la_SOURCES = $(c_sources)
+libqdutils_la_CFLAGS = $(COMMON_CFLAGS) -DLOG_TAG=\"qdutils\"
+libqdutils_la_CPPFLAGS = $(AM_CPPFLAGS)
+libqdutils_LDADD = -lhardware -lcutils -llog -lbinder
+libqdutils_la_LIBADD = ../libqservice/libqservice.la
+libqdutils_la_LDFLAGS = -shared -avoid-version \ No newline at end of file
diff --git a/msm8909/libqdutils/cb_swap_rect.cpp b/msm8909/libqdutils/cb_swap_rect.cpp
deleted file mode 100644
index 8c8efec9..00000000
--- a/msm8909/libqdutils/cb_swap_rect.cpp
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2014, The Linux Foundation. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials provided
- * with the distribution.
- * * Neither the name of The Linux Foundation or the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
- * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
- * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "cb_swap_rect.h"
-
-ANDROID_SINGLETON_STATIC_INSTANCE(qdutils::cb_swap_rect);
-
-namespace qdutils {
-
-cb_swap_rect:: cb_swap_rect(){
- swap_rect_feature_on = false ;
-}
-void cb_swap_rect::setSwapRectFeature_on( bool value){
- swap_rect_feature_on = value ;
-}
-bool cb_swap_rect::checkSwapRectFeature_on(){
- return swap_rect_feature_on;
-}
-
-};
diff --git a/msm8909/libqdutils/cb_utils.cpp b/msm8909/libqdutils/cb_utils.cpp
deleted file mode 100644
index ddad35d5..00000000
--- a/msm8909/libqdutils/cb_utils.cpp
+++ /dev/null
@@ -1,134 +0,0 @@
-/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
-* Redistribution and use in source and binary forms, with or without
-* * modification, are permitted provided that the following conditions are
-* met:
-* * Redistributions of source code must retain the above copyrigh
-* notice, this list of conditions and the following disclaimer
-* * Redistributions in binary form must reproduce the above
-* copyright notice, this list of conditions and the following
-* disclaimer in the documentation and/or other materials provided
-* with the distribution.
-* * Neither the name of The Linux Foundation nor the names of its
-* contributors may be used to endorse or promote products derived
-* from this software without specific prior written permission.
-*
-* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
-* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
-* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
-* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-* * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
-* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
-* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-#include "cb_utils.h"
-#include "cb_swap_rect.h"
-#include <ui/Region.h>
-/* get union of two rects into 3rd rect */
-void getUnion(hwc_rect_t& rect1,hwc_rect_t& rect2, hwc_rect_t& irect) {
-
- irect.left = min(rect1.left, rect2.left);
- irect.top = min(rect1.top, rect2.top);
- irect.right = max(rect1.right, rect2.right);
- irect.bottom = max(rect1.bottom, rect2.bottom);
-}
-
-int clear (copybit_device_t *copybit, private_handle_t* hnd, hwc_rect_t& rect)
-{
- int ret = 0;
- copybit_rect_t clear_rect = {rect.left, rect.top,rect.right,rect.bottom};
-
- copybit_image_t buf;
- buf.w = ALIGN(getWidth(hnd),32);
- buf.h = getHeight(hnd);
- buf.format = hnd->format;
- buf.base = (void *)hnd->base;
- buf.handle = (native_handle_t *)hnd;
-
- ret = copybit->clear(copybit, &buf, &clear_rect);
- return ret;
-}
-using namespace android;
-using namespace qhwc;
-namespace qdutils {
-
-int CBUtils::uiClearRegion(hwc_display_contents_1_t* list,
- int version, LayerProp *layerProp, hwc_rect_t dirtyRect,
- copybit_device_t *copybit, private_handle_t *renderBuffer) {
-
- size_t last = list->numHwLayers - 1;
- hwc_rect_t fbFrame = list->hwLayers[last].displayFrame;
- Rect fbFrameRect(fbFrame.left,fbFrame.top,fbFrame.right,fbFrame.bottom);
- Region wormholeRegion(fbFrameRect);
-
- if ((dirtyRect.right - dirtyRect.left > 0) &&
- (dirtyRect.bottom - dirtyRect.top > 0)) {
-#ifdef QTI_BSP
- Rect tmpRect(dirtyRect.left,dirtyRect.top,dirtyRect.right,
- dirtyRect.bottom);
- Region tmpRegion(tmpRect);
- wormholeRegion = wormholeRegion.intersect(tmpRegion);
-#endif
- }
- if(cb_swap_rect::getInstance().checkSwapRectFeature_on() == true){
- wormholeRegion.set(0,0);
- for(size_t i = 0 ; i < last; i++) {
- if(((list->hwLayers[i].blending == HWC_BLENDING_NONE) &&
- (list->hwLayers[i].planeAlpha == 0xFF)) ||
- !(layerProp[i].mFlags & HWC_COPYBIT) ||
- (list->hwLayers[i].flags & HWC_SKIP_HWC_COMPOSITION))
- continue ;
- hwc_rect_t displayFrame = list->hwLayers[i].displayFrame;
- Rect tmpRect(displayFrame.left,displayFrame.top,
- displayFrame.right,displayFrame.bottom);
- wormholeRegion.set(tmpRect);
- }
- }else{
- for (size_t i = 0 ; i < last; i++) {
- // need to take care only in per pixel blending.
- // Restrict calculation only for copybit layers.
- if((list->hwLayers[i].blending != HWC_BLENDING_NONE) ||
- (list->hwLayers[i].planeAlpha != 0xFF) ||
- !(layerProp[i].mFlags & HWC_COPYBIT))
- continue ;
- hwc_rect_t displayFrame = list->hwLayers[i].displayFrame;
- Rect tmpRect(displayFrame.left,displayFrame.top,displayFrame.right,
- displayFrame.bottom);
- Region tmpRegion(tmpRect);
- wormholeRegion.subtractSelf(wormholeRegion.intersect(tmpRegion));
- }
- }
- if(wormholeRegion.isEmpty()){
- return 1;
- }
- //TO DO :- 1. remove union and call clear for each rect.
- Region::const_iterator it = wormholeRegion.begin();
- Region::const_iterator const end = wormholeRegion.end();
- while (it != end) {
- const Rect& r = *it++;
- hwc_rect_t tmpWormRect = {r.left,r.top,r.right,r.bottom};
- if (version == qdutils::MDP_V3_0_4 ||
- version == qdutils::MDP_V3_0_5) {
- int clear_w = tmpWormRect.right - tmpWormRect.left;
- int clear_h = tmpWormRect.bottom - tmpWormRect.top;
- //mdp can't handle solid fill for one line
- //making solid fill as full in this case
- //disable swap rect if presents
- if ((clear_w == 1) || (clear_h ==1)) {
- clear(copybit, renderBuffer, fbFrame);
- return 0;
- } else {
- clear(copybit, renderBuffer, tmpWormRect);
- }
- } else {
- clear(copybit, renderBuffer, tmpWormRect);
- }
- }
- return 1;
-}
-
-}//namespace qdutils
diff --git a/msm8909/libqdutils/comptype.cpp b/msm8909/libqdutils/comptype.cpp
deleted file mode 100644
index a29158a6..00000000
--- a/msm8909/libqdutils/comptype.cpp
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2013, The Linux Foundation. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials provided
- * with the distribution.
- * * Neither the name of The Linux Foundation or the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
- * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
- * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include<comptype.h>
-
-//Instanticate the QCCompositionType Singleton
-ANDROID_SINGLETON_STATIC_INSTANCE(qdutils::QCCompositionType);
diff --git a/msm8909/libqdutils/comptype.h b/msm8909/libqdutils/comptype.h
deleted file mode 100644
index bbadaae3..00000000
--- a/msm8909/libqdutils/comptype.h
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (C) 2012-2013, The Linux Foundation. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials provided
- * with the distribution.
- * * Neither the name of The Linux Foundation or the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
- * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
- * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef INCLUDE_LIBQCOM_COMPTYPES
-#define INCLUDE_LIBQCOM_COMPTYPES
-
-#include <stdint.h>
-#include <string.h>
-#include <utils/Singleton.h>
-#include <cutils/properties.h>
-
-using namespace android;
-namespace qdutils {
-// Enum containing the supported composition types
-enum {
- COMPOSITION_TYPE_GPU = 0,
- COMPOSITION_TYPE_MDP = 0x1,
- COMPOSITION_TYPE_C2D = 0x2,
- COMPOSITION_TYPE_CPU = 0x4,
- COMPOSITION_TYPE_DYN = 0x8
-};
-
-/* This class caches the composition type
- */
-class QCCompositionType : public Singleton <QCCompositionType>
-{
- public:
- QCCompositionType();
- ~QCCompositionType() { }
- int getCompositionType() {return mCompositionType;}
- private:
- int mCompositionType;
-
-};
-
-inline QCCompositionType::QCCompositionType()
-{
- char property[PROPERTY_VALUE_MAX];
- mCompositionType = COMPOSITION_TYPE_GPU;
- if (property_get("debug.composition.type", property, "gpu") > 0) {
- if ((strncmp(property, "mdp", 3)) == 0) {
- mCompositionType = COMPOSITION_TYPE_MDP;
- } else if ((strncmp(property, "c2d", 3)) == 0) {
- mCompositionType = COMPOSITION_TYPE_C2D;
- } else if ((strncmp(property, "dyn", 3)) == 0) {
-#ifdef USE_MDP3
- mCompositionType = COMPOSITION_TYPE_DYN | COMPOSITION_TYPE_MDP;
-#else
- mCompositionType = COMPOSITION_TYPE_DYN | COMPOSITION_TYPE_C2D;
-#endif
- }
- }
-}
-
-}; //namespace qdutils
-#endif //INCLUDE_LIBQCOM_COMPTYPES
diff --git a/msm8909/libqdutils/display_config.cpp b/msm8909/libqdutils/display_config.cpp
index 62422fed..83d912e2 100644
--- a/msm8909/libqdutils/display_config.cpp
+++ b/msm8909/libqdutils/display_config.cpp
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2013-2015 The Linux Foundation. All rights reserved.
+* Copyright (c) 2013-2014, 2016, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -27,14 +27,24 @@
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#include <fcntl.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
#include <display_config.h>
#include <QServiceUtils.h>
+#include <qd_utils.h>
using namespace android;
using namespace qService;
namespace qdutils {
+//=============================================================================
+// The functions below run in the client process and wherever necessary
+// do a binder call to HWC to get/set data.
+
int isExternalConnected(void) {
int ret;
status_t err = (status_t) FAILED_TRANSACTION;
@@ -68,9 +78,9 @@ int getDisplayAttributes(int dpy, DisplayAttributes_t& dpyattr) {
dpyattr.yres = outParcel.readInt32();
dpyattr.xdpi = outParcel.readFloat();
dpyattr.ydpi = outParcel.readFloat();
- dpyattr.panel_type = (char) outParcel.readInt32();
+ dpyattr.panel_type = outParcel.readInt32();
} else {
- ALOGE("%s: Failed to get display attributes err=%d", __FUNCTION__, err);
+ ALOGE("%s() failed with err %d", __FUNCTION__, err);
}
return err;
}
@@ -170,22 +180,189 @@ int configureDynRefreshRate(uint32_t op, uint32_t refreshRate) {
return err;
}
-}; //namespace
+int getConfigCount(int /*dpy*/) {
+ int numConfigs = -1;
+ sp<IQService> binder = getBinder();
+ if(binder != NULL) {
+ Parcel inParcel, outParcel;
+ inParcel.writeInt32(DISPLAY_PRIMARY);
+ status_t err = binder->dispatch(IQService::GET_CONFIG_COUNT,
+ &inParcel, &outParcel);
+ if(!err) {
+ numConfigs = outParcel.readInt32();
+ ALOGI("%s() Received num configs %d", __FUNCTION__, numConfigs);
+ } else {
+ ALOGE("%s() failed with err %d", __FUNCTION__, err);
+ }
+ }
+ return numConfigs;
+}
+
+int getActiveConfig(int dpy) {
+ int configIndex = -1;
+ sp<IQService> binder = getBinder();
+ if(binder != NULL) {
+ Parcel inParcel, outParcel;
+ inParcel.writeInt32(dpy);
+ status_t err = binder->dispatch(IQService::GET_ACTIVE_CONFIG,
+ &inParcel, &outParcel);
+ if(!err) {
+ configIndex = outParcel.readInt32();
+ ALOGI("%s() Received active config index %d", __FUNCTION__,
+ configIndex);
+ } else {
+ ALOGE("%s() failed with err %d", __FUNCTION__, err);
+ }
+ }
+ return configIndex;
+}
+
+int setActiveConfig(int configIndex, int /*dpy*/) {
+ status_t err = (status_t) FAILED_TRANSACTION;
+ sp<IQService> binder = getBinder();
+ if(binder != NULL) {
+ Parcel inParcel, outParcel;
+ inParcel.writeInt32(configIndex);
+ inParcel.writeInt32(DISPLAY_PRIMARY);
+ err = binder->dispatch(IQService::SET_ACTIVE_CONFIG,
+ &inParcel, &outParcel);
+ if(!err) {
+ ALOGI("%s() Successfully set active config index %d", __FUNCTION__,
+ configIndex);
+ } else {
+ ALOGE("%s() failed with err %d", __FUNCTION__, err);
+ }
+ }
+ return err;
+}
+
+DisplayAttributes getDisplayAttributes(int configIndex, int dpy) {
+ DisplayAttributes dpyattr = {};
+ sp<IQService> binder = getBinder();
+ if(binder != NULL) {
+ Parcel inParcel, outParcel;
+ inParcel.writeInt32(configIndex);
+ inParcel.writeInt32(dpy);
+ status_t err = binder->dispatch(
+ IQService::GET_DISPLAY_ATTRIBUTES_FOR_CONFIG, &inParcel,
+ &outParcel);
+ if(!err) {
+ dpyattr.vsync_period = outParcel.readInt32();
+ dpyattr.xres = outParcel.readInt32();
+ dpyattr.yres = outParcel.readInt32();
+ dpyattr.xdpi = outParcel.readFloat();
+ dpyattr.ydpi = outParcel.readFloat();
+ dpyattr.panel_type = outParcel.readInt32();
+ dpyattr.is_yuv = outParcel.readInt32();
+ ALOGI("%s() Received attrs for index %d: xres %d, yres %d",
+ __FUNCTION__, configIndex, dpyattr.xres, dpyattr.yres);
+ } else {
+ ALOGE("%s() failed with err %d", __FUNCTION__, err);
+ }
+ }
+ return dpyattr;
+}
+
+int setPanelMode(int mode) {
+ status_t err = (status_t) FAILED_TRANSACTION;
+ sp<IQService> binder = getBinder();
+ if(binder != NULL) {
+ Parcel inParcel, outParcel;
+ inParcel.writeInt32(mode);
+ err = binder->dispatch(IQService::SET_DISPLAY_MODE,
+ &inParcel, &outParcel);
+ if(!err) {
+ ALOGI("%s() Successfully set the display mode to %d", __FUNCTION__,
+ mode);
+ } else {
+ ALOGE("%s() failed with err %d", __FUNCTION__, err);
+ }
+ }
+ return err;
+}
+
+int setPanelBrightness(int level) {
+ status_t err = (status_t) FAILED_TRANSACTION;
+ sp<IQService> binder = getBinder();
+ Parcel inParcel, outParcel;
+
+ if(binder != NULL) {
+ inParcel.writeInt32(level);
+ status_t err = binder->dispatch(IQService::SET_PANEL_BRIGHTNESS,
+ &inParcel, &outParcel);
+ if(err) {
+ ALOGE("%s() failed with err %d", __FUNCTION__, err);
+ }
+ }
+ return err;
+}
+
+int getPanelBrightness() {
+ int panel_brightness = -1;
+ sp<IQService> binder = getBinder();
+ Parcel inParcel, outParcel;
+
+ if(binder != NULL) {
+ status_t err = binder->dispatch(IQService::GET_PANEL_BRIGHTNESS,
+ &inParcel, &outParcel);
+ if(!err) {
+ panel_brightness = outParcel.readInt32();
+ ALOGI("%s() Current panel brightness value %d", __FUNCTION__,
+ panel_brightness);
+ } else {
+ ALOGE("%s() failed with err %d", __FUNCTION__, err);
+ }
+ }
+ return panel_brightness;
+}
+
+}// namespace
// ----------------------------------------------------------------------------
-// Screen refresh for native daemons linking dynamically to libqdutils
+// Functions for linking dynamically to libqdutils
// ----------------------------------------------------------------------------
+extern "C" int minHdcpEncryptionLevelChanged(int dpy, int min_enc_level) {
+ status_t err = (status_t) FAILED_TRANSACTION;
+ sp<IQService> binder = getBinder();
+ Parcel inParcel, outParcel;
+ inParcel.writeInt32(dpy);
+ inParcel.writeInt32(min_enc_level);
+
+ if(binder != NULL) {
+ err = binder->dispatch(IQService::MIN_HDCP_ENCRYPTION_LEVEL_CHANGED,
+ &inParcel, &outParcel);
+ }
+
+ if(err) {
+ ALOGE("%s: Failed for dpy %d err=%d", __FUNCTION__, dpy, err);
+ } else {
+ err = outParcel.readInt32();
+ }
+
+ return err;
+}
+
extern "C" int refreshScreen() {
int ret = 0;
ret = screenRefresh();
return ret;
}
-// ----------------------------------------------------------------------------
-// Native daemons needs to send enable partial update ack for PU to enable
-// ----------------------------------------------------------------------------
-extern "C" int setPartialUpdateState() {
- int ret = 0;
- ret = setPartialUpdate(IQService::ENABLE_PARTIAL_UPDATE);
- return ret;
+extern "C" int controlPartialUpdate(int dpy, int mode) {
+ status_t err = (status_t) FAILED_TRANSACTION;
+ sp<IQService> binder = getBinder();
+ if(binder != NULL) {
+ Parcel inParcel, outParcel;
+ inParcel.writeInt32(dpy);
+ inParcel.writeInt32(mode);
+ err = binder->dispatch(IQService::CONTROL_PARTIAL_UPDATE, &inParcel, &outParcel);
+ if(err != 0) {
+ ALOGE_IF(getBinder(), "%s() failed with err %d", __FUNCTION__, err);
+ } else {
+ return outParcel.readInt32();
+ }
+ }
+
+ return err;
}
+
diff --git a/msm8909/libqdutils/display_config.h b/msm8909/libqdutils/display_config.h
index e9b2fc3c..6512bf53 100644
--- a/msm8909/libqdutils/display_config.h
+++ b/msm8909/libqdutils/display_config.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013 - 2016 The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -26,24 +26,33 @@
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+
+#ifndef _DISPLAY_CONFIG_H
+#define _DISPLAY_CONFIG_H
+
#include <gralloc_priv.h>
#include <qdMetaData.h>
-#include <mdp_version.h>
#include <hardware/hwcomposer.h>
-// This header is for clients to use to set/get global display configuration
-// The functions in this header run in the client process and wherever necessary
-// do a binder call to HWC to get/set data.
+// This header is for clients to use to set/get global display configuration.
// Only primary and external displays are supported here.
-// WiFi/virtual displays are not supported.
namespace qdutils {
+
+/* TODO: Have all the common enums that need be exposed to clients and which
+ * are also needed in hwc defined here. Remove such definitions we have in
+ * hwc_utils.h
+ */
+
// Use this enum to specify the dpy parameters where needed
enum {
- DISPLAY_PRIMARY = HWC_DISPLAY_PRIMARY,
+ DISPLAY_PRIMARY = HWC_DISPLAY_PRIMARY,
DISPLAY_EXTERNAL = HWC_DISPLAY_EXTERNAL,
- DISPLAY_VIRTUAL = HWC_DISPLAY_VIRTUAL,
+#ifdef QTI_BSP
+ DISPLAY_TERTIARY = HWC_DISPLAY_TERTIARY,
+#endif
+ DISPLAY_VIRTUAL = HWC_DISPLAY_VIRTUAL,
};
// External Display states - used in setSecondaryDisplayStatus()
@@ -61,16 +70,37 @@ enum {
SET_BINDER_DYN_REFRESH_RATE,
};
+enum {
+ DEFAULT_MODE = 0,
+ VIDEO_MODE,
+ COMMAND_MODE,
+};
+
+enum {
+ DISPLAY_PORT_DEFAULT = 0,
+ DISPLAY_PORT_DSI,
+ DISPLAY_PORT_DTV,
+ DISPLAY_PORT_WRITEBACK,
+ DISPLAY_PORT_LVDS,
+ DISPLAY_PORT_EDP,
+ DISPLAY_PORT_DP,
+};
+
// Display Attributes that are available to clients of this library
// Not to be confused with a similar struct in hwc_utils (in the hwc namespace)
-struct DisplayAttributes_t {
- uint32_t vsync_period; //nanoseconds
- uint32_t xres;
- uint32_t yres;
- float xdpi;
- float ydpi;
- char panel_type;
-};
+typedef struct DisplayAttributes {
+ uint32_t vsync_period = 0; //nanoseconds
+ uint32_t xres = 0;
+ uint32_t yres = 0;
+ float xdpi = 0.0f;
+ float ydpi = 0.0f;
+ int panel_type = DISPLAY_PORT_DEFAULT;
+ bool is_yuv = false;
+} DisplayAttributes_t;
+
+//=============================================================================
+// The functions below run in the client process and wherever necessary
+// do a binder call to HWC to get/set data.
// Check if external display is connected. Useful to check before making
// calls for external displays
@@ -98,4 +128,36 @@ int setSecondaryDisplayStatus(int dpy, uint32_t status);
// Enable/Disable/Set refresh rate dynamically
int configureDynRefreshRate(uint32_t op, uint32_t refreshRate);
+
+// Returns the number of configs supported for the display on success.
+// Returns -1 on error.
+// Only primary display supported for now, value of dpy ignored.
+int getConfigCount(int dpy);
+
+// Returns the index of config that is current set for the display on success.
+// Returns -1 on error.
+// Only primary display supported for now, value of dpy ignored.
+int getActiveConfig(int dpy);
+
+// Sets the config for the display on success and returns 0.
+// Returns -1 on error.
+// Only primary display supported for now, value of dpy ignored
+int setActiveConfig(int configIndex, int dpy);
+
+// Returns the attributes for the specified config for the display on success.
+// Returns xres and yres as 0 on error.
+// Only primary display supported for now, value of dpy ignored
+DisplayAttributes getDisplayAttributes(int configIndex, int dpy);
+
+// Set the primary display mode to command or video mode
+int setDisplayMode(int mode);
+
+// Sets the panel brightness of the primary display
+int setPanelBrightness(int level);
+
+// Retrieves the current panel brightness value
+int getPanelBrightness();
+
}; //namespace
+
+#endif
diff --git a/msm8909/libqdutils/idle_invalidator.cpp b/msm8909/libqdutils/idle_invalidator.cpp
deleted file mode 100644
index b8db0bf2..00000000
--- a/msm8909/libqdutils/idle_invalidator.cpp
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- * Copyright (c) 2012, The Linux Foundation. All rights reserved.
-
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials provided
- * with the distribution.
- * * Neither the name of The Linux Foundation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
- * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
- * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "idle_invalidator.h"
-#include <unistd.h>
-#include <poll.h>
-#include <string.h>
-#include <fcntl.h>
-#include <cutils/properties.h>
-
-#define II_DEBUG 0
-#define IDLE_NOTIFY_PATH "/sys/devices/virtual/graphics/fb0/idle_notify"
-#define IDLE_TIME_PATH "/sys/devices/virtual/graphics/fb0/idle_time"
-
-
-static const char *threadName = "IdleInvalidator";
-InvalidatorHandler IdleInvalidator::mHandler = NULL;
-android::sp<IdleInvalidator> IdleInvalidator::sInstance(0);
-
-IdleInvalidator::IdleInvalidator(): Thread(false), mHwcContext(0),
- mTimeoutEventFd(-1) {
- ALOGD_IF(II_DEBUG, "IdleInvalidator::%s", __FUNCTION__);
-}
-
-IdleInvalidator::~IdleInvalidator() {
- if(mTimeoutEventFd >= 0) {
- close(mTimeoutEventFd);
- }
-}
-
-int IdleInvalidator::init(InvalidatorHandler reg_handler, void* user_data) {
- mHandler = reg_handler;
- mHwcContext = user_data;
-
- // Open a sysfs node to receive the timeout notification from driver.
- mTimeoutEventFd = open(IDLE_NOTIFY_PATH, O_RDONLY);
- if (mTimeoutEventFd < 0) {
- ALOGE ("%s:not able to open %s node %s",
- __FUNCTION__, IDLE_NOTIFY_PATH, strerror(errno));
- return -1;
- }
-
- int defaultIdleTime = 70; //ms
- char property[PROPERTY_VALUE_MAX] = {0};
- if((property_get("debug.mdpcomp.idletime", property, NULL) > 0)) {
- defaultIdleTime = atoi(property);
- }
- if(not setIdleTimeout(defaultIdleTime)) {
- close(mTimeoutEventFd);
- mTimeoutEventFd = -1;
- return -1;
- }
-
- //Triggers the threadLoop to run, if not already running.
- run(threadName, android::PRIORITY_LOWEST);
- return 0;
-}
-
-bool IdleInvalidator::setIdleTimeout(const uint32_t& timeout) {
- ALOGD_IF(II_DEBUG, "IdleInvalidator::%s timeout %d",
- __FUNCTION__, timeout);
-
- // Open a sysfs node to send the timeout value to driver.
- int fd = open(IDLE_TIME_PATH, O_WRONLY);
-
- if (fd < 0) {
- ALOGE ("%s:Unable to open %s node %s",
- __FUNCTION__, IDLE_TIME_PATH, strerror(errno));
- return false;
- }
-
- char strSleepTime[64];
- snprintf(strSleepTime, sizeof(strSleepTime), "%d", timeout);
-
- // Notify driver about the timeout value
- ssize_t len = pwrite(fd, strSleepTime, strlen(strSleepTime), 0);
- if(len < -1) {
- ALOGE ("%s:Unable to write into %s node %s",
- __FUNCTION__, IDLE_TIME_PATH, strerror(errno));
- close(fd);
- return false;
- }
-
- close(fd);
- return true;
-}
-
-bool IdleInvalidator::threadLoop() {
- ALOGD_IF(II_DEBUG, "IdleInvalidator::%s", __FUNCTION__);
- struct pollfd pFd;
- pFd.fd = mTimeoutEventFd;
- if (pFd.fd >= 0)
- pFd.events = POLLPRI | POLLERR;
- // Poll for an timeout event from driver
- int err = poll(&pFd, 1, -1);
- if(err > 0) {
- if (pFd.revents & POLLPRI) {
- char data[64];
- // Consume the node by reading it
- ssize_t len = pread(pFd.fd, data, 64, 0);
- ALOGD_IF(II_DEBUG, "IdleInvalidator::%s Idle Timeout fired len %zd",
- __FUNCTION__, len);
- mHandler((void*)mHwcContext);
- }
- }
- return true;
-}
-
-int IdleInvalidator::readyToRun() {
- ALOGD_IF(II_DEBUG, "IdleInvalidator::%s", __FUNCTION__);
- return 0; /*NO_ERROR*/
-}
-
-void IdleInvalidator::onFirstRef() {
- ALOGD_IF(II_DEBUG, "IdleInvalidator::%s", __FUNCTION__);
-}
-
-IdleInvalidator *IdleInvalidator::getInstance() {
- ALOGD_IF(II_DEBUG, "IdleInvalidator::%s", __FUNCTION__);
- if(sInstance.get() == NULL)
- sInstance = new IdleInvalidator();
- return sInstance.get();
-}
diff --git a/msm8909/libqdutils/idle_invalidator.h b/msm8909/libqdutils/idle_invalidator.h
deleted file mode 100644
index 52334a02..00000000
--- a/msm8909/libqdutils/idle_invalidator.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (c) 2012, The Linux Foundation. All rights reserved.
-
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials provided
- * with the distribution.
- * * Neither the name of The Linux Foundation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
- * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
- * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef INCLUDE_IDLEINVALIDATOR
-#define INCLUDE_IDLEINVALIDATOR
-
-#include <cutils/log.h>
-#include <utils/threads.h>
-#include <gr.h>
-
-typedef void (*InvalidatorHandler)(void*);
-
-class IdleInvalidator : public android::Thread {
- IdleInvalidator();
- void *mHwcContext;
- int mTimeoutEventFd;
- static InvalidatorHandler mHandler;
- static android::sp<IdleInvalidator> sInstance;
-
-public:
- ~IdleInvalidator();
- /* init timer obj */
- int init(InvalidatorHandler reg_handler, void* user_data);
- bool setIdleTimeout(const uint32_t& timeout);
-
- /*Overrides*/
- virtual bool threadLoop();
- virtual int readyToRun();
- virtual void onFirstRef();
- static IdleInvalidator *getInstance();
-};
-
-#endif // INCLUDE_IDLEINVALIDATOR
diff --git a/msm8909/libqdutils/mdp_version.cpp b/msm8909/libqdutils/mdp_version.cpp
deleted file mode 100644
index 088f82b6..00000000
--- a/msm8909/libqdutils/mdp_version.cpp
+++ /dev/null
@@ -1,489 +0,0 @@
-/*
- * Copyright (c) 2012-2014, The Linux Foundation. All rights reserved.
-
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials provided
- * with the distribution.
- * * Neither the name of The Linux Foundation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
- * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
- * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#include <cutils/log.h>
-#include <linux/msm_mdp.h>
-#include "mdp_version.h"
-#include "qd_utils.h"
-
-#define DEBUG 0
-
-ANDROID_SINGLETON_STATIC_INSTANCE(qdutils::MDPVersion);
-namespace qdutils {
-
-#define TOKEN_PARAMS_DELIM "="
-
-// chip variants have same major number and minor numbers usually vary
-// for e.g., MDSS_MDP_HW_REV_101 is 0x10010000
-// 1001 - major number
-// 0000 - minor number
-// 8x26 v1 minor number is 0000
-// v2 minor number is 0001 etc..
-#ifndef MDSS_MDP_HW_REV_100
-#define MDSS_MDP_HW_REV_100 0x10000000 //8974 v1
-#endif
-#ifndef MDSS_MDP_HW_REV_101
-#define MDSS_MDP_HW_REV_101 0x10010000 //8x26
-#endif
-#ifndef MDSS_MDP_HW_REV_102
-#define MDSS_MDP_HW_REV_102 0x10020000 //8974 v2
-#endif
-#ifndef MDSS_MDP_HW_REV_103
-#define MDSS_MDP_HW_REV_103 0x10030000 //8084
-#endif
-#ifndef MDSS_MDP_HW_REV_104
-#define MDSS_MDP_HW_REV_104 0x10040000 //Next version
-#endif
-#ifndef MDSS_MDP_HW_REV_105
-#define MDSS_MDP_HW_REV_105 0x10050000 //8994
-#endif
-#ifndef MDSS_MDP_HW_REV_106
-#define MDSS_MDP_HW_REV_106 0x10060000 //8x16
-#endif
-#ifndef MDSS_MDP_HW_REV_107
-#define MDSS_MDP_HW_REV_107 0x10070000 //Next version
-#endif
-#ifndef MDSS_MDP_HW_REV_108
-#define MDSS_MDP_HW_REV_108 0x10080000 //8x39 & 8x36
-#endif
-#ifndef MDSS_MDP_HW_REV_109
-#define MDSS_MDP_HW_REV_109 0x10090000 //Next version
-#endif
-#ifndef MDSS_MDP_HW_REV_200
-#define MDSS_MDP_HW_REV_200 0x20000000 //8092
-#endif
-#ifndef MDSS_MDP_HW_REV_206
-#define MDSS_MDP_HW_REV_206 0x20060000 //Future
-#endif
-
-MDPVersion::MDPVersion()
-{
- mMDPVersion = MDSS_V5;
- mMdpRev = 0;
- mRGBPipes = 0;
- mVGPipes = 0;
- mDMAPipes = 0;
- mFeatures = 0;
- mMDPUpscale = 1;
- mMDPDownscale = 1;
- mMacroTileEnabled = false;
- mLowBw = 0;
- mHighBw = 0;
- mSourceSplit = false;
- mSourceSplitAlways = false;
- mRGBHasNoScalar = false;
- mRotDownscale = false;
-
- // this is the default limit of mixer unless driver reports it.
- // For resolutions beyond this, we use dual/split overlay pipes.
- mMaxMixerWidth = 2048;
-
- updatePanelInfo();
-
- if(!updateSysFsInfo()) {
- ALOGE("Unable to read display sysfs node");
- }
- if (mMdpRev == MDP_V3_0_4){
- mMDPVersion = MDP_V3_0_4;
- }
- else if (mMdpRev == MDP_V3_0_5){
- mMDPVersion = MDP_V3_0_5;
- }
-
- mHasOverlay = false;
- if((mMDPVersion >= MDP_V4_0) ||
- (mMDPVersion == MDP_V_UNKNOWN) ||
- (mMDPVersion == MDP_V3_0_4) ||
- (mMDPVersion == MDP_V3_0_5))
- mHasOverlay = true;
- if(!updateSplitInfo()) {
- ALOGE("Unable to read display split node");
- }
-}
-
-MDPVersion::~MDPVersion() {
- close(mFd);
-}
-
-int MDPVersion::tokenizeParams(char *inputParams, const char *delim,
- char* tokenStr[], int *idx) {
- char *tmp_token = NULL;
- char *temp_ptr;
- int index = 0;
- if (!inputParams) {
- return -1;
- }
- tmp_token = strtok_r(inputParams, delim, &temp_ptr);
- while (tmp_token != NULL) {
- tokenStr[index++] = tmp_token;
- tmp_token = strtok_r(NULL, " ", &temp_ptr);
- }
- *idx = index;
- return 0;
-}
-// This function reads the sysfs node to read the primary panel type
-// and updates information accordingly
-void MDPVersion::updatePanelInfo() {
- FILE *displayDeviceFP = NULL;
- FILE *panelInfoNodeFP = NULL;
- char fbType[MAX_FRAME_BUFFER_NAME_SIZE];
- const char *strCmdPanel = "mipi dsi cmd panel";
- const char *strVideoPanel = "mipi dsi video panel";
- const char *strLVDSPanel = "lvds panel";
- const char *strEDPPanel = "edp panel";
-
- displayDeviceFP = fopen("/sys/class/graphics/fb0/msm_fb_type", "r");
- if(displayDeviceFP){
- fread(fbType, sizeof(char), MAX_FRAME_BUFFER_NAME_SIZE,
- displayDeviceFP);
- if(strncmp(fbType, strCmdPanel, strlen(strCmdPanel)) == 0) {
- mPanelInfo.mType = MIPI_CMD_PANEL;
- }
- else if(strncmp(fbType, strVideoPanel, strlen(strVideoPanel)) == 0) {
- mPanelInfo.mType = MIPI_VIDEO_PANEL;
- }
- else if(strncmp(fbType, strLVDSPanel, strlen(strLVDSPanel)) == 0) {
- mPanelInfo.mType = LVDS_PANEL;
- }
- else if(strncmp(fbType, strEDPPanel, strlen(strEDPPanel)) == 0) {
- mPanelInfo.mType = EDP_PANEL;
- }
- fclose(displayDeviceFP);
- } else {
- ALOGE("Unable to read Primary Panel Information");
- }
-
- panelInfoNodeFP = fopen("/sys/class/graphics/fb0/msm_fb_panel_info", "r");
- if(panelInfoNodeFP){
- size_t len = PAGE_SIZE;
- ssize_t read;
- char *readLine = (char *) malloc (len);
- char property[PROPERTY_VALUE_MAX];
- while((read = getline((char **)&readLine, &len,
- panelInfoNodeFP)) != -1) {
- int token_ct=0;
- char *tokens[10];
- memset(tokens, 0, sizeof(tokens));
-
- if(!tokenizeParams(readLine, TOKEN_PARAMS_DELIM, tokens,
- &token_ct)) {
- if(!strncmp(tokens[0], "pu_en", strlen("pu_en"))) {
- mPanelInfo.mPartialUpdateEnable = atoi(tokens[1]);
- ALOGI("PartialUpdate status: %s",
- mPanelInfo.mPartialUpdateEnable? "Enabled" :
- "Disabled");
- }
- if(!strncmp(tokens[0], "xstart", strlen("xstart"))) {
- mPanelInfo.mLeftAlign = atoi(tokens[1]);
- ALOGI("Left Align: %d", mPanelInfo.mLeftAlign);
- }
- if(!strncmp(tokens[0], "walign", strlen("walign"))) {
- mPanelInfo.mWidthAlign = atoi(tokens[1]);
- ALOGI("Width Align: %d", mPanelInfo.mWidthAlign);
- }
- if(!strncmp(tokens[0], "ystart", strlen("ystart"))) {
- mPanelInfo.mTopAlign = atoi(tokens[1]);
- ALOGI("Top Align: %d", mPanelInfo.mTopAlign);
- }
- if(!strncmp(tokens[0], "halign", strlen("halign"))) {
- mPanelInfo.mHeightAlign = atoi(tokens[1]);
- ALOGI("Height Align: %d", mPanelInfo.mHeightAlign);
- }
- if(!strncmp(tokens[0], "min_w", strlen("min_w"))) {
- mPanelInfo.mMinROIWidth = atoi(tokens[1]);
- ALOGI("Min ROI Width: %d", mPanelInfo.mMinROIWidth);
- }
- if(!strncmp(tokens[0], "min_h", strlen("min_h"))) {
- mPanelInfo.mMinROIHeight = atoi(tokens[1]);
- ALOGI("Min ROI Height: %d", mPanelInfo.mMinROIHeight);
- }
- if(!strncmp(tokens[0], "roi_merge", strlen("roi_merge"))) {
- mPanelInfo.mNeedsROIMerge = atoi(tokens[1]);
- ALOGI("Needs ROI Merge: %d", mPanelInfo.mNeedsROIMerge);
- }
- if(!strncmp(tokens[0], "dyn_fps_en", strlen("dyn_fps_en"))) {
- mPanelInfo.mDynFpsSupported = atoi(tokens[1]);
- ALOGI("Dynamic Fps: %s", mPanelInfo.mDynFpsSupported ?
- "Enabled" : "Disabled");
- }
- if(!strncmp(tokens[0], "min_fps", strlen("min_fps"))) {
- mPanelInfo.mMinFps = atoi(tokens[1]);
- ALOGI("Min Panel fps: %d", mPanelInfo.mMinFps);
- }
- if(!strncmp(tokens[0], "max_fps", strlen("max_fps"))) {
- mPanelInfo.mMaxFps = atoi(tokens[1]);
- ALOGI("Max Panel fps: %d", mPanelInfo.mMaxFps);
- }
- }
- }
- if((property_get("persist.hwc.pubypass", property, 0) > 0) &&
- (!strncmp(property, "1", PROPERTY_VALUE_MAX ) ||
- (!strncasecmp(property,"true", PROPERTY_VALUE_MAX )))) {
- mPanelInfo.mPartialUpdateEnable = 0;
- ALOGI("PartialUpdate disabled by property");
- }
- fclose(panelInfoNodeFP);
- } else {
- ALOGE("Failed to open msm_fb_panel_info node");
- }
-}
-
-// This function reads the sysfs node to read MDP capabilities
-// and parses and updates information accordingly.
-bool MDPVersion::updateSysFsInfo() {
- FILE *sysfsFd;
- size_t len = PAGE_SIZE;
- ssize_t read;
- char *line = NULL;
- char sysfsPath[255];
- memset(sysfsPath, 0, sizeof(sysfsPath));
- snprintf(sysfsPath , sizeof(sysfsPath),
- "/sys/class/graphics/fb0/mdp/caps");
- char property[PROPERTY_VALUE_MAX];
- bool enableMacroTile = false;
-
- if((property_get("persist.hwc.macro_tile_enable", property, NULL) > 0) &&
- (!strncmp(property, "1", PROPERTY_VALUE_MAX ) ||
- (!strncasecmp(property,"true", PROPERTY_VALUE_MAX )))) {
- enableMacroTile = true;
- }
-
- sysfsFd = fopen(sysfsPath, "rb");
-
- if (sysfsFd == NULL) {
- ALOGE("%s: sysFsFile file '%s' not found",
- __FUNCTION__, sysfsPath);
- return false;
- } else {
- line = (char *) malloc(len);
- while((read = getline(&line, &len, sysfsFd)) != -1) {
- int index=0;
- char *tokens[10];
- memset(tokens, 0, sizeof(tokens));
-
- // parse the line and update information accordingly
- if(!tokenizeParams(line, TOKEN_PARAMS_DELIM, tokens, &index)) {
- if(!strncmp(tokens[0], "hw_rev", strlen("hw_rev"))) {
- mMdpRev = atoi(tokens[1]);
- }
- else if(!strncmp(tokens[0], "rgb_pipes", strlen("rgb_pipes"))) {
- mRGBPipes = (uint8_t)atoi(tokens[1]);
- }
- else if(!strncmp(tokens[0], "vig_pipes", strlen("vig_pipes"))) {
- mVGPipes = (uint8_t)atoi(tokens[1]);
- }
- else if(!strncmp(tokens[0], "dma_pipes", strlen("dma_pipes"))) {
- mDMAPipes = (uint8_t)atoi(tokens[1]);
- }
- else if(!strncmp(tokens[0], "max_downscale_ratio",
- strlen("max_downscale_ratio"))) {
- mMDPDownscale = atoi(tokens[1]);
- }
- else if(!strncmp(tokens[0], "max_upscale_ratio",
- strlen("max_upscale_ratio"))) {
- mMDPUpscale = atoi(tokens[1]);
- } else if(!strncmp(tokens[0], "max_bandwidth_low",
- strlen("max_bandwidth_low"))) {
- mLowBw = atol(tokens[1]);
- } else if(!strncmp(tokens[0], "max_bandwidth_high",
- strlen("max_bandwidth_high"))) {
- mHighBw = atol(tokens[1]);
- } else if(!strncmp(tokens[0], "max_mixer_width",
- strlen("max_mixer_width"))) {
- mMaxMixerWidth = atoi(tokens[1]);
- } else if(!strncmp(tokens[0], "features", strlen("features"))) {
- for(int i=1; i<index;i++) {
- if(!strncmp(tokens[i], "bwc", strlen("bwc"))) {
- mFeatures |= MDP_BWC_EN;
- } else if(!strncmp(tokens[i], "decimation",
- strlen("decimation"))) {
- mFeatures |= MDP_DECIMATION_EN;
- } else if(!strncmp(tokens[i], "tile_format",
- strlen("tile_format"))) {
- if(enableMacroTile)
- mMacroTileEnabled = true;
- } else if(!strncmp(tokens[i], "src_split",
- strlen("src_split"))) {
- mSourceSplit = true;
- } else if(!strncmp(tokens[i], "non_scalar_rgb",
- strlen("non_scalar_rgb"))) {
- mRGBHasNoScalar = true;
- } else if(!strncmp(tokens[i], "rotator_downscale",
- strlen("rotator_downscale"))) {
- mRotDownscale = true;
- }
- }
- }
- }
- }
- free(line);
- fclose(sysfsFd);
- }
-
- if(mMDPVersion >= qdutils::MDP_V4_2 and mMDPVersion < qdutils::MDSS_V5) {
- mRotDownscale = true;
- }
-
- if(mSourceSplit) {
- memset(sysfsPath, 0, sizeof(sysfsPath));
- snprintf(sysfsPath , sizeof(sysfsPath),
- "/sys/class/graphics/fb0/msm_fb_src_split_info");
-
- sysfsFd = fopen(sysfsPath, "rb");
- if (sysfsFd == NULL) {
- ALOGE("%s: Opening file %s failed with error %s", __FUNCTION__,
- sysfsPath, strerror(errno));
- return false;
- } else {
- line = (char *) malloc(len);
- if((read = getline(&line, &len, sysfsFd)) != -1) {
- if(!strncmp(line, "src_split_always",
- strlen("src_split_always"))) {
- mSourceSplitAlways = true;
- }
- }
- free(line);
- fclose(sysfsFd);
- }
- }
-
- ALOGD_IF(DEBUG, "%s: mMDPVersion: %d mMdpRev: %x mRGBPipes:%d,"
- "mVGPipes:%d", __FUNCTION__, mMDPVersion, mMdpRev,
- mRGBPipes, mVGPipes);
- ALOGD_IF(DEBUG, "%s:mDMAPipes:%d \t mMDPDownscale:%d, mFeatures:%d",
- __FUNCTION__, mDMAPipes, mMDPDownscale, mFeatures);
- ALOGD_IF(DEBUG, "%s:mLowBw: %lu mHighBw: %lu", __FUNCTION__, mLowBw,
- mHighBw);
-
- return true;
-}
-
-// This function reads the sysfs node to read MDP capabilities
-// and parses and updates information accordingly.
-bool MDPVersion::updateSplitInfo() {
- if(mMDPVersion >= MDSS_V5) {
- char split[64] = {0};
- FILE* fp = fopen("/sys/class/graphics/fb0/msm_fb_split", "r");
- if(fp){
- //Format "left right" space as delimiter
- if(fread(split, sizeof(char), 64, fp)) {
- split[sizeof(split) - 1] = '\0';
- mSplit.mLeft = atoi(split);
- ALOGI_IF(mSplit.mLeft, "Left Split=%d", mSplit.mLeft);
- char *rght = strpbrk(split, " ");
- if(rght)
- mSplit.mRight = atoi(rght + 1);
- ALOGI_IF(mSplit.mRight, "Right Split=%d", mSplit.mRight);
- }
- } else {
- ALOGE("Failed to open mdss_fb_split node");
- return false;
- }
- if(fp)
- fclose(fp);
- }
- return true;
-}
-
-
-bool MDPVersion::hasMinCropWidthLimitation() const {
- return mMdpRev <= MDSS_MDP_HW_REV_102;
-}
-
-bool MDPVersion::supportsDecimation() {
- return mFeatures & MDP_DECIMATION_EN;
-}
-
-uint32_t MDPVersion::getMaxMDPDownscale() {
- return mMDPDownscale;
-}
-
-uint32_t MDPVersion::getMaxMDPUpscale() {
- return mMDPUpscale;
-}
-
-bool MDPVersion::supportsBWC() {
- // BWC - Bandwidth Compression
- return (mFeatures & MDP_BWC_EN);
-}
-
-bool MDPVersion::supportsMacroTile() {
- // MACRO TILE support
- return mMacroTileEnabled;
-}
-
-bool MDPVersion::isSrcSplit() const {
- return mSourceSplit;
-}
-
-bool MDPVersion::isSrcSplitAlways() const {
- return mSourceSplitAlways;
-}
-
-bool MDPVersion::isRGBScalarSupported() const {
- return (!mRGBHasNoScalar);
-}
-
-bool MDPVersion::is8x26() {
- return (mMdpRev >= MDSS_MDP_HW_REV_101 and
- mMdpRev < MDSS_MDP_HW_REV_102);
-}
-
-bool MDPVersion::is8x74v2() {
- return (mMdpRev >= MDSS_MDP_HW_REV_102 and
- mMdpRev < MDSS_MDP_HW_REV_103);
-}
-
-bool MDPVersion::is8084() {
- return (mMdpRev >= MDSS_MDP_HW_REV_103 and
- mMdpRev < MDSS_MDP_HW_REV_104);
-}
-
-bool MDPVersion::is8092() {
- return (mMdpRev >= MDSS_MDP_HW_REV_200 and
- mMdpRev < MDSS_MDP_HW_REV_206);
-}
-
-bool MDPVersion::is8994() {
- return (mMdpRev >= MDSS_MDP_HW_REV_105 and
- mMdpRev < MDSS_MDP_HW_REV_106);
-}
-
-bool MDPVersion::is8x16() {
- return (mMdpRev >= MDSS_MDP_HW_REV_106 and
- mMdpRev < MDSS_MDP_HW_REV_107);
-}
-
-bool MDPVersion::is8x39() {
- return (mMdpRev >= MDSS_MDP_HW_REV_108 and
- mMdpRev < MDSS_MDP_HW_REV_109);
-}
-
-
-}; //namespace qdutils
-
diff --git a/msm8909/libqdutils/mdp_version.h b/msm8909/libqdutils/mdp_version.h
deleted file mode 100644
index 3c7f6a30..00000000
--- a/msm8909/libqdutils/mdp_version.h
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
-
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials provided
- * with the distribution.
- * * Neither the name of The Linux Foundation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
- * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
- * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef INCLUDE_LIBQCOMUTILS_MDPVER
-#define INCLUDE_LIBQCOMUTILS_MDPVER
-
-#include <stdint.h>
-#include <utils/Singleton.h>
-#include <cutils/properties.h>
-
-/* This class gets the MSM type from the soc info
-*/
-using namespace android;
-namespace qdutils {
-// These panel definitions are available at mdss_mdp.h which is internal header
-// file and is not available at <linux/mdss_mdp.h>.
-// ToDo: once it is available at linux/mdss_mdp.h, these below definitions can
-// be removed.
-enum mdp_version {
- MDP_V_UNKNOWN = 0,
- MDP_V2_2 = 220,
- MDP_V3_0 = 300,
- MDP_V3_0_3 = 303,
- MDP_V3_0_4 = 304,
- MDP_V3_0_5 = 305,
- MDP_V3_1 = 310,
- MDP_V4_0 = 400,
- MDP_V4_1 = 410,
- MDP_V4_2 = 420,
- MDP_V4_3 = 430,
- MDP_V4_4 = 440,
- MDSS_V5 = 500,
-};
-
-#define NO_PANEL '0'
-#define MDDI_PANEL '1'
-#define EBI2_PANEL '2'
-#define LCDC_PANEL '3'
-#define EXT_MDDI_PANEL '4'
-#define TV_PANEL '5'
-#define DTV_PANEL '7'
-#define MIPI_VIDEO_PANEL '8'
-#define MIPI_CMD_PANEL '9'
-#define WRITEBACK_PANEL 'a'
-#define LVDS_PANEL 'b'
-#define EDP_PANEL 'c'
-
-class MDPVersion;
-
-struct Split {
- int mLeft;
- int mRight;
- Split() : mLeft(0), mRight(0){}
- int left() { return mLeft; }
- int right() { return mRight; }
- friend class MDPVersion;
-};
-
-struct PanelInfo {
- char mType; // Smart or Dumb
- int mPartialUpdateEnable; // Partial update feature
- int mLeftAlign; // ROI left alignment restriction
- int mWidthAlign; // ROI width alignment restriction
- int mTopAlign; // ROI top alignment restriction
- int mHeightAlign; // ROI height alignment restriction
- int mMinROIWidth; // Min width needed for ROI
- int mMinROIHeight; // Min height needed for ROI
- bool mNeedsROIMerge; // Merge ROI's of both the DSI's
- bool mDynFpsSupported; // Panel Supports dyn fps
- uint32_t mMinFps; // Min fps supported by panel
- uint32_t mMaxFps; // Max fps supported by panel
- PanelInfo() : mType(NO_PANEL), mPartialUpdateEnable(0),
- mLeftAlign(0), mWidthAlign(0), mTopAlign(0), mHeightAlign(0),
- mMinROIWidth(0), mMinROIHeight(0), mNeedsROIMerge(false),
- mDynFpsSupported(0), mMinFps(0), mMaxFps(0) {}
- friend class MDPVersion;
-};
-
-class MDPVersion : public Singleton <MDPVersion>
-{
-public:
- MDPVersion();
- ~MDPVersion();
- int getMDPVersion() {return mMDPVersion;}
- char getPanelType() {return mPanelInfo.mType;}
- bool hasOverlay() {return mHasOverlay;}
- uint8_t getTotalPipes() {
- return (uint8_t)(mRGBPipes + mVGPipes + mDMAPipes);
- }
- uint8_t getRGBPipes() { return mRGBPipes; }
- uint8_t getVGPipes() { return mVGPipes; }
- uint8_t getDMAPipes() { return mDMAPipes; }
- bool supportsDecimation();
- uint32_t getMaxMDPDownscale();
- uint32_t getMaxMDPUpscale();
- bool supportsBWC();
- bool supportsMacroTile();
- int getLeftSplit() { return mSplit.left(); }
- int getRightSplit() { return mSplit.right(); }
- bool isPartialUpdateEnabled() { return mPanelInfo.mPartialUpdateEnable; }
- int getLeftAlign() { return mPanelInfo.mLeftAlign; }
- int getWidthAlign() { return mPanelInfo.mWidthAlign; }
- int getTopAlign() { return mPanelInfo.mTopAlign; }
- int getHeightAlign() { return mPanelInfo.mHeightAlign; }
- int getMinROIWidth() { return mPanelInfo.mMinROIWidth; }
- int getMinROIHeight() { return mPanelInfo.mMinROIHeight; }
- bool needsROIMerge() { return mPanelInfo.mNeedsROIMerge; }
- unsigned long getLowBw() { return mLowBw; }
- unsigned long getHighBw() { return mHighBw; }
- bool isRotDownscaleEnabled() { return mRotDownscale; }
- bool isDynFpsSupported() { return mPanelInfo.mDynFpsSupported; }
- uint32_t getMinFpsSupported() { return mPanelInfo.mMinFps; }
- uint32_t getMaxFpsSupported() { return mPanelInfo.mMaxFps; }
- uint32_t getMaxMixerWidth() const { return mMaxMixerWidth; }
- bool hasMinCropWidthLimitation() const;
- bool isSrcSplit() const;
- bool isSrcSplitAlways() const;
- bool isRGBScalarSupported() const;
- bool is8x26();
- bool is8x74v2();
- bool is8084();
- bool is8092();
- bool is8994();
- bool is8x16();
- bool is8x39();
-
-private:
- bool updateSysFsInfo();
- void updatePanelInfo();
- bool updateSplitInfo();
- int tokenizeParams(char *inputParams, const char *delim,
- char* tokenStr[], int *idx);
- int mFd;
- int mMDPVersion;
- bool mHasOverlay;
- uint32_t mMdpRev;
- uint8_t mRGBPipes;
- uint8_t mVGPipes;
- uint8_t mDMAPipes;
- uint32_t mFeatures;
- uint32_t mMDPDownscale;
- uint32_t mMDPUpscale;
- bool mMacroTileEnabled;
- Split mSplit;
- PanelInfo mPanelInfo;
- unsigned long mLowBw; //kbps
- unsigned long mHighBw; //kbps
- bool mSourceSplit;
- //Additional property on top of source split
- bool mSourceSplitAlways;
- bool mRGBHasNoScalar;
- bool mRotDownscale;
- uint32_t mMaxMixerWidth; //maximum x-res of a given mdss mixer.
-};
-}; //namespace qdutils
-#endif //INCLUDE_LIBQCOMUTILS_MDPVER
diff --git a/msm8909/libqdutils/profiler.cpp b/msm8909/libqdutils/profiler.cpp
index b183e6dd..810b0198 100644
--- a/msm8909/libqdutils/profiler.cpp
+++ b/msm8909/libqdutils/profiler.cpp
@@ -28,6 +28,7 @@
*/
#define LOG_NDDEBUG 0
+#define __STDC_FORMAT_MACROS 1
#include <inttypes.h>
#include "profiler.h"
diff --git a/msm8909/libqdutils/profiler.h b/msm8909/libqdutils/profiler.h
index 5f270b02..9ac8157e 100644
--- a/msm8909/libqdutils/profiler.h
+++ b/msm8909/libqdutils/profiler.h
@@ -33,7 +33,7 @@
#include <stdio.h>
#include <utils/Singleton.h>
#include <cutils/properties.h>
-#include <cutils/log.h>
+#include <log/log.h>
#ifndef DEBUG_CALC_FPS
#define CALC_FPS() ((void)0)
diff --git a/msm8909/libqdutils/qdMetaData.cpp b/msm8909/libqdutils/qdMetaData.cpp
index 9f8a3248..9f73e443 100644
--- a/msm8909/libqdutils/qdMetaData.cpp
+++ b/msm8909/libqdutils/qdMetaData.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2014, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -30,61 +30,71 @@
#include <errno.h>
#include <string.h>
#include <sys/mman.h>
-#include <cutils/log.h>
+#include <log/log.h>
+#include <cinttypes>
#include <gralloc_priv.h>
-#include <inttypes.h>
#include "qdMetaData.h"
-int setMetaData(private_handle_t *handle, DispParamType paramType,
- void *param) {
- if (!handle) {
- ALOGE("%s: Private handle is null!", __func__);
+unsigned long getMetaDataSize() {
+ return static_cast<unsigned long>(ROUND_UP_PAGESIZE(sizeof(MetaData_t)));
+}
+
+static int validateAndMap(private_handle_t* handle) {
+ if (private_handle_t::validate(handle)) {
+ ALOGE("%s: Private handle is invalid - handle:%p", __func__, handle);
return -1;
}
if (handle->fd_metadata == -1) {
- ALOGE("%s: Bad fd for extra data!", __func__);
+ ALOGE("%s: Invalid metadata fd - handle:%p fd: %d",
+ __func__, handle, handle->fd_metadata);
return -1;
}
- if (!param) {
- ALOGE("%s: input param is null!", __func__);
- return -1;
+
+ if (!handle->base_metadata) {
+ auto size = getMetaDataSize();
+ void *base = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED,
+ handle->fd_metadata, 0);
+ if (base == reinterpret_cast<void*>(MAP_FAILED)) {
+ ALOGE("%s: metadata mmap failed - handle:%p fd: %d err: %s",
+ __func__, handle, handle->fd_metadata, strerror(errno));
+
+ return -1;
+ }
+ handle->base_metadata = (uintptr_t) base;
}
- unsigned long size = ROUND_UP_PAGESIZE(sizeof(MetaData_t));
- void *base = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED,
- handle->fd_metadata, 0);
- if (base == reinterpret_cast<void*>(MAP_FAILED)) {
- ALOGE("%s: mmap() failed: error is %s!", __func__, strerror(errno));
- return -1;
+ return 0;
+}
+
+int setMetaData(private_handle_t *handle, DispParamType paramType,
+ void *param) {
+ auto err = validateAndMap(handle);
+ if (err != 0)
+ return err;
+ return setMetaDataVa(reinterpret_cast<MetaData_t*>(handle->base_metadata),
+ paramType, param);
+}
+
+int setMetaDataVa(MetaData_t *data, DispParamType paramType,
+ void *param) {
+ if (data == nullptr)
+ return -EINVAL;
+ // If parameter is NULL reset the specific MetaData Key
+ if (!param) {
+ data->operation &= ~paramType;
+ // param unset
+ return 0;
}
- MetaData_t *data = reinterpret_cast <MetaData_t *>(base);
+
data->operation |= paramType;
switch (paramType) {
- case PP_PARAM_HSIC:
- memcpy((void *)&data->hsicData, param, sizeof(HSICData_t));
- break;
- case PP_PARAM_SHARPNESS:
- data->sharpness = *((int32_t *)param);
- break;
- case PP_PARAM_VID_INTFC:
- data->video_interface = *((int32_t *)param);
- break;
case PP_PARAM_INTERLACED:
data->interlaced = *((int32_t *)param);
break;
- case PP_PARAM_IGC:
- memcpy((void *)&data->igcData, param, sizeof(IGCData_t));
- break;
- case PP_PARAM_SHARP2:
- memcpy((void *)&data->Sharp2Data, param, sizeof(Sharp2Data_t));
- break;
- case PP_PARAM_TIMESTAMP:
- data->timestamp = *((int64_t *)param);
- break;
case UPDATE_BUFFER_GEOMETRY:
- memcpy((void *)&data->bufferDim, param, sizeof(BufferDim_t));
+ data->bufferDim = *((BufferDim_t *)param);
break;
case UPDATE_REFRESH_RATE:
- data->refreshrate = *((uint32_t *)param);
+ data->refreshrate = *((float *)param);
break;
case UPDATE_COLOR_SPACE:
data->colorSpace = *((ColorSpace_t *)param);
@@ -92,12 +102,206 @@ int setMetaData(private_handle_t *handle, DispParamType paramType,
case MAP_SECURE_BUFFER:
data->mapSecureBuffer = *((int32_t *)param);
break;
+ case S3D_FORMAT:
+ data->s3dFormat = *((uint32_t *)param);
+ break;
+ case LINEAR_FORMAT:
+ data->linearFormat = *((uint32_t *)param);
+ break;
+ case SET_IGC:
+ data->igc = *((IGC_t *)param);
+ break;
+ case SET_SINGLE_BUFFER_MODE:
+ data->isSingleBufferMode = *((uint32_t *)param);
+ break;
+ case SET_S3D_COMP:
+ data->s3dComp = *((S3DGpuComp_t *)param);
+ break;
+ case SET_VT_TIMESTAMP:
+ data->vtTimeStamp = *((uint64_t *)param);
+ break;
+ case COLOR_METADATA:
+ data->color = *((ColorMetaData *)param);
+ break;
default:
ALOGE("Unknown paramType %d", paramType);
break;
}
- if(munmap(base, size))
- ALOGE("%s: failed to unmap ptr %p, err %d", __func__, (void*)base,
- errno);
return 0;
}
+
+int clearMetaData(private_handle_t *handle, DispParamType paramType) {
+ auto err = validateAndMap(handle);
+ if (err != 0)
+ return err;
+ return clearMetaDataVa(reinterpret_cast<MetaData_t *>(handle->base_metadata),
+ paramType);
+}
+
+int clearMetaDataVa(MetaData_t *data, DispParamType paramType) {
+ if (data == nullptr)
+ return -EINVAL;
+ data->operation &= ~paramType;
+ switch (paramType) {
+ case SET_S3D_COMP:
+ data->s3dComp.displayId = -1;
+ data->s3dComp.s3dMode = 0;
+ break;
+ default:
+ ALOGE("Unknown paramType %d", paramType);
+ break;
+ }
+ return 0;
+}
+
+int getMetaData(private_handle_t *handle, DispFetchParamType paramType,
+ void *param) {
+ int ret = validateAndMap(handle);
+ if (ret != 0)
+ return ret;
+ return getMetaDataVa(reinterpret_cast<MetaData_t *>(handle->base_metadata),
+ paramType, param);
+}
+
+int getMetaDataVa(MetaData_t *data, DispFetchParamType paramType,
+ void *param) {
+ // Make sure we send 0 only if the operation queried is present
+ int ret = -EINVAL;
+ if (data == nullptr)
+ return ret;
+
+ switch (paramType) {
+ case GET_PP_PARAM_INTERLACED:
+ if (data->operation & PP_PARAM_INTERLACED) {
+ *((int32_t *)param) = data->interlaced;
+ ret = 0;
+ }
+ break;
+ case GET_BUFFER_GEOMETRY:
+ if (data->operation & UPDATE_BUFFER_GEOMETRY) {
+ *((BufferDim_t *)param) = data->bufferDim;
+ ret = 0;
+ }
+ break;
+ case GET_REFRESH_RATE:
+ if (data->operation & UPDATE_REFRESH_RATE) {
+ *((float *)param) = data->refreshrate;
+ ret = 0;
+ }
+ break;
+ case GET_COLOR_SPACE:
+ if (data->operation & UPDATE_COLOR_SPACE) {
+ *((ColorSpace_t *)param) = data->colorSpace;
+ ret = 0;
+ }
+ break;
+ case GET_MAP_SECURE_BUFFER:
+ if (data->operation & MAP_SECURE_BUFFER) {
+ *((int32_t *)param) = data->mapSecureBuffer;
+ ret = 0;
+ }
+ break;
+ case GET_S3D_FORMAT:
+ if (data->operation & S3D_FORMAT) {
+ *((uint32_t *)param) = data->s3dFormat;
+ ret = 0;
+ }
+ break;
+ case GET_LINEAR_FORMAT:
+ if (data->operation & LINEAR_FORMAT) {
+ *((uint32_t *)param) = data->linearFormat;
+ ret = 0;
+ }
+ break;
+ case GET_IGC:
+ if (data->operation & SET_IGC) {
+ *((IGC_t *)param) = data->igc;
+ ret = 0;
+ }
+ break;
+ case GET_SINGLE_BUFFER_MODE:
+ if (data->operation & SET_SINGLE_BUFFER_MODE) {
+ *((uint32_t *)param) = data->isSingleBufferMode;
+ ret = 0;
+ }
+ break;
+ case GET_S3D_COMP:
+ if (data->operation & SET_S3D_COMP) {
+ *((S3DGpuComp_t *)param) = data->s3dComp;
+ ret = 0;
+ }
+ break;
+ case GET_VT_TIMESTAMP:
+ if (data->operation & SET_VT_TIMESTAMP) {
+ *((uint64_t *)param) = data->vtTimeStamp;
+ ret = 0;
+ }
+ break;
+ case GET_COLOR_METADATA:
+ if (data->operation & COLOR_METADATA) {
+ *((ColorMetaData *)param) = data->color;
+ ret = 0;
+ }
+ break;
+ default:
+ ALOGE("Unknown paramType %d", paramType);
+ break;
+ }
+ return ret;
+}
+
+int copyMetaData(struct private_handle_t *src, struct private_handle_t *dst) {
+ auto err = validateAndMap(src);
+ if (err != 0)
+ return err;
+
+ err = validateAndMap(dst);
+ if (err != 0)
+ return err;
+
+ MetaData_t *src_data = reinterpret_cast <MetaData_t *>(src->base_metadata);
+ MetaData_t *dst_data = reinterpret_cast <MetaData_t *>(dst->base_metadata);
+ *dst_data = *src_data;
+ return 0;
+}
+
+int copyMetaDataVaToHandle(MetaData_t *src_data, struct private_handle_t *dst) {
+ int err = -EINVAL;
+ if (src_data == nullptr)
+ return err;
+
+ err = validateAndMap(dst);
+ if (err != 0)
+ return err;
+
+ MetaData_t *dst_data = reinterpret_cast <MetaData_t *>(dst->base_metadata);
+ *dst_data = *src_data;
+ return 0;
+}
+
+int copyMetaDataHandleToVa(struct private_handle_t *src, MetaData_t *dst_data) {
+ int err = -EINVAL;
+ if (dst_data == nullptr)
+ return err;
+
+ err = validateAndMap(src);
+ if (err != 0)
+ return err;
+
+ MetaData_t *src_data = reinterpret_cast <MetaData_t *>(src->base_metadata);
+ *dst_data = *src_data;
+ return 0;
+}
+
+int copyMetaDataVaToVa(MetaData_t *src_data, MetaData_t *dst_data) {
+ int err = -EINVAL;
+ if (src_data == nullptr)
+ return err;
+
+ if (dst_data == nullptr)
+ return err;
+
+ *dst_data = *src_data;
+ return 0;
+}
+
diff --git a/msm8909/libqdutils/qdMetaData.h b/msm8909/libqdutils/qdMetaData.h
index 32d788e6..afe86d31 100644
--- a/msm8909/libqdutils/qdMetaData.h
+++ b/msm8909/libqdutils/qdMetaData.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2014, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -30,16 +30,25 @@
#ifndef _QDMETADATA_H
#define _QDMETADATA_H
+#include <color_metadata.h>
+
#ifdef __cplusplus
extern "C" {
#endif
-#define MAX_IGC_LUT_ENTRIES 256
+#define MAX_UBWC_STATS_LENGTH 32
enum ColorSpace_t{
ITU_R_601,
ITU_R_601_FR,
ITU_R_709,
+ ITU_R_2020,
+ ITU_R_2020_FR,
+};
+
+enum IGC_t {
+ IGC_NotSpecified,
+ IGC_sRGB,
};
struct HSICData_t {
@@ -49,36 +58,52 @@ struct HSICData_t {
float contrast;
};
-struct Sharp2Data_t {
- int32_t strength;
- uint32_t edge_thr;
- uint32_t smooth_thr;
- uint32_t noise_thr;
+struct BufferDim_t {
+ int32_t sliceWidth;
+ int32_t sliceHeight;
};
-struct IGCData_t{
- uint16_t c0[MAX_IGC_LUT_ENTRIES];
- uint16_t c1[MAX_IGC_LUT_ENTRIES];
- uint16_t c2[MAX_IGC_LUT_ENTRIES];
+enum UBWC_Version {
+ UBWC_UNUSED = 0,
+ UBWC_1_0 = 0x1,
+ UBWC_2_0 = 0x2,
+ UBWC_MAX_VERSION = 0xFF,
};
-struct BufferDim_t {
- int32_t sliceWidth;
- int32_t sliceHeight;
+struct UBWC_2_0_Stats {
+ uint32_t nCRStatsTile32; /**< UBWC Stats info for 32 Byte Tile */
+ uint32_t nCRStatsTile64; /**< UBWC Stats info for 64 Byte Tile */
+ uint32_t nCRStatsTile96; /**< UBWC Stats info for 96 Byte Tile */
+ uint32_t nCRStatsTile128; /**< UBWC Stats info for 128 Byte Tile */
+ uint32_t nCRStatsTile160; /**< UBWC Stats info for 160 Byte Tile */
+ uint32_t nCRStatsTile192; /**< UBWC Stats info for 192 Byte Tile */
+ uint32_t nCRStatsTile256; /**< UBWC Stats info for 256 Byte Tile */
+};
+
+struct UBWCStats {
+ enum UBWC_Version version; /* Union depends on this version. */
+ uint8_t bDataValid; /* If [non-zero], CR Stats data is valid.
+ * Consumers may use stats data.
+ * If [zero], CR Stats data is invalid.
+ * Consumers *Shall* not use stats data */
+ union {
+ struct UBWC_2_0_Stats ubwc_stats;
+ uint32_t reserved[MAX_UBWC_STATS_LENGTH]; /* This is for future */
+ };
+};
+
+struct S3DGpuComp_t {
+ int32_t displayId; /* on which display S3D is composed by client */
+ uint32_t s3dMode; /* the S3D format of this layer to be accessed by client */
};
struct MetaData_t {
int32_t operation;
int32_t interlaced;
struct BufferDim_t bufferDim;
- struct HSICData_t hsicData;
- int32_t sharpness;
- int32_t video_interface;
- struct IGCData_t igcData;
- struct Sharp2Data_t Sharp2Data;
- int64_t timestamp;
- uint32_t refreshrate;
+ float refreshrate;
enum ColorSpace_t colorSpace;
+ enum IGC_t igc;
/* Gralloc sets PRIV_SECURE_BUFFER flag to inform that the buffers are from
* ION_SECURE. which should not be mapped. However, for GPU post proc
* feature, GFX needs to map this buffer, in the client context and in SF
@@ -86,25 +111,87 @@ struct MetaData_t {
* for clients to set, and GPU will to read and know when to map the
* SECURE_BUFFER(ION) */
int32_t mapSecureBuffer;
+ /* The supported formats are defined in gralloc_priv.h to
+ * support legacy code*/
+ uint32_t s3dFormat;
+ /* VENUS output buffer is linear for UBWC Interlaced video */
+ uint32_t linearFormat;
+ /* Set by graphics to indicate that this buffer will be written to but not
+ * swapped out */
+ uint32_t isSingleBufferMode;
+ /* Indicate GPU to draw S3D layer on dedicate display device */
+ struct S3DGpuComp_t s3dComp;
+
+ /* Set by camera to program the VT Timestamp */
+ uint64_t vtTimeStamp;
+ /* Color Aspects + HDR info */
+ ColorMetaData color;
+ /* Consumer should read this data as follows based on
+ * Gralloc flag "interlaced" listed above.
+ * [0] : If it is progressive.
+ * [0] : Top field, if it is interlaced.
+ * [1] : Do not read, if it is progressive.
+ * [1] : Bottom field, if it is interlaced.
+ */
+ struct UBWCStats ubwcCRStats[2];
};
enum DispParamType {
- PP_PARAM_HSIC = 0x0001,
- PP_PARAM_SHARPNESS = 0x0002,
- PP_PARAM_INTERLACED = 0x0004,
- PP_PARAM_VID_INTFC = 0x0008,
- PP_PARAM_IGC = 0x0010,
- PP_PARAM_SHARP2 = 0x0020,
- PP_PARAM_TIMESTAMP = 0x0040,
- UPDATE_BUFFER_GEOMETRY = 0x0080,
- UPDATE_REFRESH_RATE = 0x0100,
- UPDATE_COLOR_SPACE = 0x0200,
- MAP_SECURE_BUFFER = 0x400,
+ SET_VT_TIMESTAMP = 0x0001,
+ COLOR_METADATA = 0x0002,
+ PP_PARAM_INTERLACED = 0x0004,
+ UNUSED2 = 0x0008,
+ UNUSED3 = 0x0010,
+ UNUSED4 = 0x0020,
+ SET_UBWC_CR_STATS_INFO = 0x0040,
+ UPDATE_BUFFER_GEOMETRY = 0x0080,
+ UPDATE_REFRESH_RATE = 0x0100,
+ UPDATE_COLOR_SPACE = 0x0200,
+ MAP_SECURE_BUFFER = 0x0400,
+ S3D_FORMAT = 0x0800,
+ LINEAR_FORMAT = 0x1000,
+ SET_IGC = 0x2000,
+ SET_SINGLE_BUFFER_MODE = 0x4000,
+ SET_S3D_COMP = 0x8000,
+};
+
+enum DispFetchParamType {
+ GET_VT_TIMESTAMP = 0x0001,
+ GET_COLOR_METADATA = 0x0002,
+ GET_PP_PARAM_INTERLACED = 0x0004,
+ GET_UBWC_CR_STATS_INFO = 0x0040,
+ GET_BUFFER_GEOMETRY = 0x0080,
+ GET_REFRESH_RATE = 0x0100,
+ GET_COLOR_SPACE = 0x0200,
+ GET_MAP_SECURE_BUFFER = 0x0400,
+ GET_S3D_FORMAT = 0x0800,
+ GET_LINEAR_FORMAT = 0x1000,
+ GET_IGC = 0x2000,
+ GET_SINGLE_BUFFER_MODE = 0x4000,
+ GET_S3D_COMP = 0x8000,
};
struct private_handle_t;
int setMetaData(struct private_handle_t *handle, enum DispParamType paramType,
- void *param);
+ void *param);
+int setMetaDataVa(struct MetaData_t* data, enum DispParamType paramType,
+ void *param);
+
+int getMetaData(struct private_handle_t *handle,
+ enum DispFetchParamType paramType,
+ void *param);
+int getMetaDataVa(struct MetaData_t* data, enum DispFetchParamType paramType,
+ void *param);
+
+int copyMetaData(struct private_handle_t *src, struct private_handle_t *dst);
+int copyMetaDataVaToHandle(struct MetaData_t *src, struct private_handle_t *dst);
+int copyMetaDataHandleToVa(struct private_handle_t* src, struct MetaData_t *dst);
+int copyMetaDataVaToVa(struct MetaData_t *src, struct MetaData_t *dst);
+
+int clearMetaData(struct private_handle_t *handle, enum DispParamType paramType);
+int clearMetaDataVa(struct MetaData_t *data, enum DispParamType paramType);
+
+unsigned long getMetaDataSize();
#ifdef __cplusplus
}
diff --git a/msm8909/libqdutils/qd_utils.cpp b/msm8909/libqdutils/qd_utils.cpp
index 05842167..fc01eab0 100644
--- a/msm8909/libqdutils/qd_utils.cpp
+++ b/msm8909/libqdutils/qd_utils.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013, 2018 The Linux Foundation. All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -27,57 +27,152 @@
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#include <unistd.h>
+#include <gralloc_priv.h>
#include "qd_utils.h"
-#define QD_UTILS_DEBUG 0
namespace qdutils {
-#ifdef HDMI_STUB
-int getHDMINode(void)
-{
- ALOGD_IF(QD_UTILS_DEBUG, "%s: HDMI_STUB\n", __func__);
- return -1;
-}
-int getEdidRawData(char *buffer)
-{
- ALOGD_IF(QD_UTILS_DEBUG, "%s: HDMI_STUB\n", __func__);
- (void) buffer;
+static int parseLine(char *input, char *tokens[], const uint32_t maxToken, uint32_t *count) {
+ char *tmpToken = NULL;
+ char *tmpPtr;
+ uint32_t index = 0;
+ const char *delim = ", =\n";
+ if (!input) {
+ return -1;
+ }
+ tmpToken = strtok_r(input, delim, &tmpPtr);
+ while (tmpToken && index < maxToken) {
+ tokens[index++] = tmpToken;
+ tmpToken = strtok_r(NULL, delim, &tmpPtr);
+ }
+ *count = index;
+
return 0;
}
-#else
-int getHDMINode(void)
-{
+
+static int getExternalNode(const char *type) {
FILE *displayDeviceFP = NULL;
char fbType[MAX_FRAME_BUFFER_NAME_SIZE];
char msmFbTypePath[MAX_FRAME_BUFFER_NAME_SIZE];
int j = 0;
- for(j = 0; j < HWC_NUM_DISPLAY_TYPES; j++) {
+ for(j = 0; j < kFBNodeMax; j++) {
snprintf (msmFbTypePath, sizeof(msmFbTypePath),
- "/sys/class/graphics/fb%d/msm_fb_type", j);
+ "/sys/devices/virtual/graphics/fb%d/msm_fb_type", j);
displayDeviceFP = fopen(msmFbTypePath, "r");
if(displayDeviceFP) {
fread(fbType, sizeof(char), MAX_FRAME_BUFFER_NAME_SIZE,
displayDeviceFP);
- if(strncmp(fbType, "dtv panel", strlen("dtv panel")) == 0) {
- ALOGD("%s: HDMI is at fb%d", __func__, j);
+ if(strncmp(fbType, type, strlen(type)) == 0) {
+ ALOGD("%s: %s is at fb%d", __func__, type, j);
fclose(displayDeviceFP);
break;
}
fclose(displayDeviceFP);
} else {
- ALOGE("%s: Failed to open fb node %d", __func__, j);
+ ALOGE("%s: Failed to open fb node %s", __func__, msmFbTypePath);
}
}
- if (j < HWC_NUM_DISPLAY_TYPES)
+ if (j < kFBNodeMax)
return j;
else
- ALOGE("%s: Failed to find HDMI node", __func__);
+ ALOGE("%s: Failed to find %s node", __func__, type);
return -1;
}
+static int querySDEInfoDRM(HWQueryType type, int *value) {
+ char property[PROPERTY_VALUE_MAX] = {0};
+
+ // TODO(user): If future targets don't support WB UBWC, add separate
+ // properties in target specific system.prop and have clients like WFD
+ // directly rely on those.
+ switch(type) {
+ case HAS_UBWC:
+ case HAS_WB_UBWC: // WFD stack still uses this
+ *value = 1;
+ property_get(DISABLE_UBWC_PROP, property, "0");
+ if(!(strncmp(property, "1", PROPERTY_VALUE_MAX)) ||
+ !(strncmp(property, "true", PROPERTY_VALUE_MAX))) {
+ *value = 0;
+ }
+ break;
+ default:
+ ALOGE("Invalid query type %d", type);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int querySDEInfoFB(HWQueryType type, int *value) {
+ FILE *fileptr = NULL;
+ const char *featureName;
+ char stringBuffer[MAX_STRING_LENGTH];
+ uint32_t tokenCount = 0;
+ const uint32_t maxCount = 10;
+ char *tokens[maxCount] = { NULL };
+
+ switch(type) {
+ case HAS_UBWC:
+ featureName = "ubwc";
+ break;
+ case HAS_WB_UBWC:
+ featureName = "wb_ubwc";
+ break;
+ default:
+ ALOGE("Invalid query type %d", type);
+ return -EINVAL;
+ }
+
+ fileptr = fopen("/sys/devices/virtual/graphics/fb0/mdp/caps", "rb");
+ if (!fileptr) {
+ ALOGE("File '%s' not found", stringBuffer);
+ return -EINVAL;
+ }
+
+ size_t len = MAX_STRING_LENGTH;
+ ssize_t read;
+ char *line = stringBuffer;
+ while ((read = getline(&line, &len, fileptr)) != -1) {
+ // parse the line and update information accordingly
+ if (parseLine(line, tokens, maxCount, &tokenCount)) {
+ continue;
+ }
+
+ if (strncmp(tokens[0], "features", strlen("features"))) {
+ continue;
+ }
+
+ for (uint32_t i = 0; i < tokenCount; i++) {
+ if (!strncmp(tokens[i], featureName, strlen(featureName))) {
+ *value = 1;
+ }
+ }
+ }
+ fclose(fileptr);
+
+ return 0;
+}
+
+int querySDEInfo(HWQueryType type, int *value) {
+ if (!value) {
+ return -EINVAL;
+ }
+
+ if (getDriverType() == DriverType::DRM) {
+ return querySDEInfoDRM(type, value);
+ }
+
+ return querySDEInfoFB(type, value);
+}
+
+int getHDMINode(void) {
+ return getExternalNode("dtv panel");
+}
+
int getEdidRawData(char *buffer)
{
int size;
@@ -91,12 +186,12 @@ int getEdidRawData(char *buffer)
}
snprintf(msmFbTypePath, sizeof(msmFbTypePath),
- "/sys/class/graphics/fb%d/edid_raw_data", node_id);
+ "/sys/devices/virtual/graphics/fb%d/edid_raw_data", node_id);
- edidFile = open(msmFbTypePath, O_RDONLY, 0);
+ edidFile = open(msmFbTypePath, O_RDONLY, 0);
if (edidFile < 0) {
- ALOGE("%s no edid raw data found", __func__);
+ ALOGE("%s no edid raw data found %s", __func__,msmFbTypePath);
return 0;
}
@@ -104,34 +199,162 @@ int getEdidRawData(char *buffer)
close(edidFile);
return size;
}
-#endif
-
-/* Calculates the aspect ratio for based on src & dest */
-void getAspectRatioPosition(int destWidth, int destHeight, int srcWidth,
- int srcHeight, hwc_rect_t& rect) {
- int x =0, y =0;
-
- if (srcWidth * destHeight > destWidth * srcHeight) {
- srcHeight = destWidth * srcHeight / srcWidth;
- srcWidth = destWidth;
- } else if (srcWidth * destHeight < destWidth * srcHeight) {
- srcWidth = destHeight * srcWidth / srcHeight;
- srcHeight = destHeight;
- } else {
- srcWidth = destWidth;
- srcHeight = destHeight;
- }
- if (srcWidth > destWidth) srcWidth = destWidth;
- if (srcHeight > destHeight) srcHeight = destHeight;
- x = (destWidth - srcWidth) / 2;
- y = (destHeight - srcHeight) / 2;
- ALOGD_IF(QD_UTILS_DEBUG, "%s: AS Position: x = %d, y = %d w = %d h = %d",
- __FUNCTION__, x, y, srcWidth , srcHeight);
- // Convert it back to hwc_rect_t
- rect.left = x;
- rect.top = y;
- rect.right = srcWidth + rect.left;
- rect.bottom = srcHeight + rect.top;
+
+bool isDPConnected() {
+ char connectPath[MAX_FRAME_BUFFER_NAME_SIZE];
+ FILE *connectFile = NULL;
+ size_t len = MAX_STRING_LENGTH;
+ char stringBuffer[MAX_STRING_LENGTH];
+ char *line = stringBuffer;
+
+ int nodeId = getExternalNode("dp panel");
+ if (nodeId < 0) {
+ ALOGE("%s no DP node found", __func__);
+ return false;
+ }
+
+ snprintf(connectPath, sizeof(connectPath),
+ "/sys/devices/virtual/graphics/fb%d/connected", nodeId);
+
+ connectFile = fopen(connectPath, "rb");
+ if (!connectFile) {
+ ALOGW("Failed to open connect node for device node %s", connectPath);
+ return false;
+ }
+
+ if (getline(&line, &len, connectFile) < 0) {
+ fclose(connectFile);
+ return false;
+ }
+
+ fclose(connectFile);
+
+ return atoi(line);
+}
+
+int getDPTestConfig(uint32_t *panelBpp, uint32_t *patternType) {
+ if (!panelBpp || !patternType) {
+ return -1;
+ }
+
+ char configPath[MAX_FRAME_BUFFER_NAME_SIZE];
+ FILE *configFile = NULL;
+ uint32_t tokenCount = 0;
+ const uint32_t maxCount = 10;
+ char *tokens[maxCount] = { NULL };
+ size_t len = MAX_STRING_LENGTH;
+ char stringBuffer[MAX_STRING_LENGTH];
+ char *line = stringBuffer;
+
+ int nodeId = getExternalNode("dp panel");
+ if (nodeId < 0) {
+ ALOGE("%s no DP node found", __func__);
+ return -EINVAL;
+ }
+
+ snprintf(configPath, sizeof(configPath),
+ "/sys/devices/virtual/graphics/fb%d/config", nodeId);
+
+ configFile = fopen(configPath, "rb");
+ if (!configFile) {
+ ALOGW("Failed to open config node for device node %s", configPath);
+ return -EINVAL;
+ }
+
+ while (getline(&line, &len, configFile) != -1) {
+ if (!parseLine(line, tokens, maxCount, &tokenCount)) {
+ if (!strncmp(tokens[0], "bpp", strlen("bpp"))) {
+ *panelBpp = static_cast<uint32_t>(atoi(tokens[1]));
+ } else if (!strncmp(tokens[0], "pattern", strlen("pattern"))) {
+ *patternType = static_cast<uint32_t>(atoi(tokens[1]));
+ }
+ }
+ }
+
+ fclose(configFile);
+
+ return 0;
+}
+
+DriverType getDriverType() {
+ const char *fb_caps = "/sys/devices/virtual/graphics/fb0/mdp/caps";
+ // 0 - File exists
+ return access(fb_caps, F_OK) ? DriverType::DRM : DriverType::FB;
+}
+
+const char *GetHALPixelFormatString(int format) {
+ switch (format) {
+ case HAL_PIXEL_FORMAT_RGBA_8888:
+ return "RGBA_8888";
+ case HAL_PIXEL_FORMAT_RGBX_8888:
+ return "RGBX_8888";
+ case HAL_PIXEL_FORMAT_RGB_888:
+ return "RGB_888";
+ case HAL_PIXEL_FORMAT_RGB_565:
+ return "RGB_565";
+ case HAL_PIXEL_FORMAT_BGR_565:
+ return "BGR_565";
+ case HAL_PIXEL_FORMAT_BGRA_8888:
+ return "BGRA_8888";
+ case HAL_PIXEL_FORMAT_RGBA_5551:
+ return "RGBA_5551";
+ case HAL_PIXEL_FORMAT_RGBA_4444:
+ return "RGBA_4444";
+ case HAL_PIXEL_FORMAT_YV12:
+ return "YV12";
+ case HAL_PIXEL_FORMAT_YCbCr_422_SP:
+ return "YCbCr_422_SP_NV16";
+ case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+ return "YCrCb_420_SP_NV21";
+ case HAL_PIXEL_FORMAT_YCbCr_422_I:
+ return "YCbCr_422_I_YUY2";
+ case HAL_PIXEL_FORMAT_YCrCb_422_I:
+ return "YCrCb_422_I_YVYU";
+ case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
+ return "NV12_ENCODEABLE";
+ case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED:
+ return "YCbCr_420_SP_TILED_TILE_4x2";
+ case HAL_PIXEL_FORMAT_YCbCr_420_SP:
+ return "YCbCr_420_SP";
+ case HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO:
+ return "YCrCb_420_SP_ADRENO";
+ case HAL_PIXEL_FORMAT_YCrCb_422_SP:
+ return "YCrCb_422_SP";
+ case HAL_PIXEL_FORMAT_R_8:
+ return "R_8";
+ case HAL_PIXEL_FORMAT_RG_88:
+ return "RG_88";
+ case HAL_PIXEL_FORMAT_INTERLACE:
+ return "INTERLACE";
+ case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
+ return "YCbCr_420_SP_VENUS";
+ case HAL_PIXEL_FORMAT_YCrCb_420_SP_VENUS:
+ return "YCrCb_420_SP_VENUS";
+ case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC:
+ return "YCbCr_420_SP_VENUS_UBWC";
+ case HAL_PIXEL_FORMAT_RGBA_1010102:
+ return "RGBA_1010102";
+ case HAL_PIXEL_FORMAT_ARGB_2101010:
+ return "ARGB_2101010";
+ case HAL_PIXEL_FORMAT_RGBX_1010102:
+ return "RGBX_1010102";
+ case HAL_PIXEL_FORMAT_XRGB_2101010:
+ return "XRGB_2101010";
+ case HAL_PIXEL_FORMAT_BGRA_1010102:
+ return "BGRA_1010102";
+ case HAL_PIXEL_FORMAT_ABGR_2101010:
+ return "ABGR_2101010";
+ case HAL_PIXEL_FORMAT_BGRX_1010102:
+ return "BGRX_1010102";
+ case HAL_PIXEL_FORMAT_XBGR_2101010:
+ return "XBGR_2101010";
+ case HAL_PIXEL_FORMAT_YCbCr_420_P010:
+ return "YCbCr_420_P010";
+ case HAL_PIXEL_FORMAT_YCbCr_420_TP10_UBWC:
+ return "YCbCr_420_TP10_UBWC";
+ default:
+ return "Unknown_format";
+ }
}
}; //namespace qdutils
diff --git a/msm8909/libqdutils/qd_utils.h b/msm8909/libqdutils/qd_utils.h
index 1d4bc19e..eed8661f 100644
--- a/msm8909/libqdutils/qd_utils.h
+++ b/msm8909/libqdutils/qd_utils.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013, The Linux Foundation. All rights reserved.
+ * Copyright (C) 2013, 2017 The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -35,7 +35,7 @@
#include <ctype.h>
#include <fcntl.h>
#include <utils/Errors.h>
-#include <utils/Log.h>
+#include <log/log.h>
#include <linux/fb.h>
#include <sys/ioctl.h>
@@ -45,18 +45,31 @@
#include <hardware/hwcomposer.h>
namespace qdutils {
-#define EDID_RAW_DATA_SIZE 640
-enum qd_utils {
+enum HWQueryType {
+ HAS_UBWC = 1,
+ HAS_WB_UBWC = 2
+};
+
+enum {
+ EDID_RAW_DATA_SIZE = 640,
MAX_FRAME_BUFFER_NAME_SIZE = 128,
MAX_SYSFS_FILE_PATH = 255,
- SUPPORTED_DOWNSCALE_AREA = (1920*1080)
+ MAX_STRING_LENGTH = 1024,
};
-int getHDMINode(void);
+int querySDEInfo(HWQueryType type, int *value);
int getEdidRawData(char *buffer);
+int getHDMINode(void);
+bool isDPConnected();
+int getDPTestConfig(uint32_t *panelBpp, uint32_t *patternType);
-void getAspectRatioPosition(int destWidth, int destHeight, int srcWidth,
- int srcHeight, hwc_rect_t& rect);
+enum class DriverType {
+ FB = 0,
+ DRM,
+};
+DriverType getDriverType();
+const char *GetHALPixelFormatString(int format);
+static const int kFBNodeMax = 4;
}; //namespace qdutils
#endif
diff --git a/msm8909/libqservice/Android.bp b/msm8909/libqservice/Android.bp
new file mode 100644
index 00000000..fe69d393
--- /dev/null
+++ b/msm8909/libqservice/Android.bp
@@ -0,0 +1,16 @@
+cc_library_shared {
+ name: "libqservice",
+ vendor: true,
+ defaults: ["display_defaults"],
+ shared_libs: ["libbinder"],
+ cflags: [
+ "-DLOG_TAG=\"qdqservice\"",
+ "-Wno-sign-conversion",
+ ],
+ srcs: [
+ "QService.cpp",
+ "IQService.cpp",
+ "IQClient.cpp",
+ "IQHDMIClient.cpp",
+ ],
+}
diff --git a/msm8909/libqservice/Android.mk b/msm8909/libqservice/Android.mk
deleted file mode 100644
index e2a82550..00000000
--- a/msm8909/libqservice/Android.mk
+++ /dev/null
@@ -1,21 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-include $(LOCAL_PATH)/../common.mk
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := libqservice
-LOCAL_MODULE_TAGS := optional
-LOCAL_C_INCLUDES := $(common_includes) $(kernel_includes)
-LOCAL_SHARED_LIBRARIES := $(common_libs) libbinder
-LOCAL_CFLAGS := $(common_flags) -DLOG_TAG=\"qdqservice\"
-LOCAL_CFLAGS += -Wno-error
-LOCAL_CLANG := $(common_clang_flags)
-LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps)
-LOCAL_SRC_FILES := QService.cpp \
- IQService.cpp \
- IQClient.cpp
-LOCAL_COPY_HEADERS_TO := $(common_header_export_path)
-LOCAL_COPY_HEADERS := IQService.h \
- IQClient.h
-
-
-include $(BUILD_SHARED_LIBRARY)
diff --git a/msm8909/libqservice/IQHDMIClient.cpp b/msm8909/libqservice/IQHDMIClient.cpp
new file mode 100644
index 00000000..6379e574
--- /dev/null
+++ b/msm8909/libqservice/IQHDMIClient.cpp
@@ -0,0 +1,103 @@
+/*
+* Copyright (c) 2014 The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation. nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+#include <log/log.h>
+#include <binder/Parcel.h>
+#include "IQHDMIClient.h"
+
+using namespace android;
+namespace qClient {
+
+enum {
+ HDMI_CONNECTED = IBinder::FIRST_CALL_TRANSACTION,
+ CEC_MESSAGE_RECEIVED
+};
+
+class BpQHDMIClient : public BpInterface<IQHDMIClient>
+{
+public:
+ BpQHDMIClient(const sp<IBinder>& impl)
+ :BpInterface<IQHDMIClient>(impl)
+ {
+ }
+
+ void onHdmiHotplug(int connected)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IQHDMIClient::getInterfaceDescriptor());
+ data.writeInt32(connected);
+ remote()->transact(HDMI_CONNECTED, data, &reply, IBinder::FLAG_ONEWAY);
+ }
+
+ void onCECMessageRecieved(char *msg, ssize_t len)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IQHDMIClient::getInterfaceDescriptor());
+ data.writeInt32((int32_t)len);
+ void *buf = data.writeInplace(len);
+ if (buf != NULL)
+ memcpy(buf, msg, len);
+ remote()->transact(CEC_MESSAGE_RECEIVED, data, &reply,
+ IBinder::FLAG_ONEWAY);
+ }
+};
+
+IMPLEMENT_META_INTERFACE(QHDMIClient,
+ "android.display.IQHDMIClient");
+
+status_t BnQHDMIClient::onTransact(uint32_t code, const Parcel& data,
+ Parcel* reply, uint32_t flags)
+{
+ switch(code) {
+ case HDMI_CONNECTED: {
+ CHECK_INTERFACE(IQHDMIClient, data, reply);
+ int connected = data.readInt32();
+ onHdmiHotplug(connected);
+ return NO_ERROR;
+ }
+ case CEC_MESSAGE_RECEIVED: {
+ CHECK_INTERFACE(IQHDMIClient, data, reply);
+ ssize_t len = data.readInt32();
+ const void* msg;
+ if(len >= 0 && len <= (ssize_t) data.dataAvail()) {
+ msg = data.readInplace(len);
+ } else {
+ msg = NULL;
+ len = 0;
+ }
+ if (msg != NULL)
+ onCECMessageRecieved((char*) msg, len);
+ return NO_ERROR;
+ }
+ default: {
+ return BBinder::onTransact(code, data, reply, flags);
+ }
+ }
+}
+
+}; //namespace qClient
diff --git a/msm8909/libhwcomposer/hwc_ad.h b/msm8909/libqservice/IQHDMIClient.h
index 0be5f5df..c3d012a4 100644
--- a/msm8909/libhwcomposer/hwc_ad.h
+++ b/msm8909/libqservice/IQHDMIClient.h
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2013 The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -27,40 +27,31 @@
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef HWC_AD_H
-#define HWC_AD_H
+#ifndef HDMI_EVENTS_LISTENER_H_
+#define HDMI_EVENTS_LISTENER_H_
-#include <overlayUtils.h>
-#include <hwc_utils.h>
+#include <utils/RefBase.h>
+#include <binder/IInterface.h>
-struct hwc_context_t;
+namespace qClient {
-namespace qhwc {
-
-class AssertiveDisplay {
+class IQHDMIClient : public android::IInterface
+{
public:
- AssertiveDisplay(hwc_context_t *ctx);
- void markDoable(hwc_context_t *ctx, const hwc_display_contents_1_t* list);
- bool prepare(hwc_context_t *ctx, const hwc_rect_t& crop,
- const overlay::utils::Whf& whf,
- const private_handle_t *hnd);
- bool draw(hwc_context_t *ctx, int fd, uint32_t offset);
- //Resets a few members on each draw round
- void reset() { mDoable = false;
- mDest = overlay::utils::OV_INVALID;
- }
- bool isDoable() const { return mDoable; }
- int getDstFd() const;
- uint32_t getDstOffset() const;
+ DECLARE_META_INTERFACE(QHDMIClient);
+ virtual void onHdmiHotplug(int connected) = 0;
+ virtual void onCECMessageRecieved(char *msg, ssize_t len) = 0;
+};
-private:
- bool mDoable;
- bool mTurnedOff;
- //State of feature existence on certain devices and configs.
- bool mFeatureEnabled;
- overlay::utils::eDest mDest;
- void turnOffAD();
+class BnQHDMIClient : public android::BnInterface<IQHDMIClient>
+{
+public:
+ virtual android::status_t onTransact( uint32_t code,
+ const android::Parcel& data,
+ android::Parcel* reply, uint32_t flags = 0);
};
-}
-#endif
+}; //namespace qhdmi
+
+#endif // HDMI_EVENTS_LISTENER_H_
+
diff --git a/msm8909/libqservice/IQService.cpp b/msm8909/libqservice/IQService.cpp
index 9e2b0f52..d45a141c 100644
--- a/msm8909/libqservice/IQService.cpp
+++ b/msm8909/libqservice/IQService.cpp
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2010 The Android Open Source Project
- * Copyright (C) 2012-2014, The Linux Foundation. All rights reserved.
+ * Copyright (C) 2012-2016, The Linux Foundation. All rights reserved.
*
* Not a Contribution, Apache license notifications and license are
* retained for attribution purposes only.
@@ -25,8 +25,8 @@
#include <binder/IBinder.h>
#include <binder/IInterface.h>
#include <binder/IPCThreadState.h>
+#include <cutils/android_filesystem_config.h>
#include <utils/Errors.h>
-#include <private/android_filesystem_config.h>
#include <IQService.h>
#define QSERVICE_DEBUG 0
@@ -45,13 +45,22 @@ public:
: BpInterface<IQService>(impl) {}
virtual void connect(const sp<IQClient>& client) {
- ALOGD_IF(QSERVICE_DEBUG, "%s: connect client", __FUNCTION__);
+ ALOGD_IF(QSERVICE_DEBUG, "%s: connect HWC client", __FUNCTION__);
Parcel data, reply;
data.writeInterfaceToken(IQService::getInterfaceDescriptor());
data.writeStrongBinder(IInterface::asBinder(client));
- remote()->transact(CONNECT, data, &reply);
+ remote()->transact(CONNECT_HWC_CLIENT, data, &reply);
}
+ virtual void connect(const sp<IQHDMIClient>& client) {
+ ALOGD_IF(QSERVICE_DEBUG, "%s: connect HDMI client", __FUNCTION__);
+ Parcel data, reply;
+ data.writeInterfaceToken(IQService::getInterfaceDescriptor());
+ data.writeStrongBinder(IInterface::asBinder(client));
+ remote()->transact(CONNECT_HDMI_CLIENT, data, &reply);
+ }
+
+
virtual android::status_t dispatch(uint32_t command, const Parcel* inParcel,
Parcel* outParcel) {
ALOGD_IF(QSERVICE_DEBUG, "%s: dispatch in:%p", __FUNCTION__, inParcel);
@@ -70,8 +79,6 @@ IMPLEMENT_META_INTERFACE(QService, "android.display.IQService");
// ----------------------------------------------------------------------
-static void getProcName(int pid, char *buf, int size);
-
status_t BnQService::onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
@@ -80,33 +87,41 @@ status_t BnQService::onTransact(
IPCThreadState* ipc = IPCThreadState::self();
const int callerPid = ipc->getCallingPid();
const int callerUid = ipc->getCallingUid();
- const int MAX_BUF_SIZE = 1024;
- char callingProcName[MAX_BUF_SIZE] = {0};
-
- getProcName(callerPid, callingProcName, MAX_BUF_SIZE);
const bool permission = (callerUid == AID_MEDIA ||
callerUid == AID_GRAPHICS ||
callerUid == AID_ROOT ||
- callerUid == AID_SYSTEM);
+ callerUid == AID_CAMERASERVER ||
+ callerUid == AID_AUDIO ||
+ callerUid == AID_SYSTEM ||
+ callerUid == AID_MEDIA_CODEC);
- if (code == CONNECT) {
+ if (code == CONNECT_HWC_CLIENT) {
CHECK_INTERFACE(IQService, data, reply);
if(callerUid != AID_GRAPHICS) {
- ALOGE("display.qservice CONNECT access denied: \
- pid=%d uid=%d process=%s",
- callerPid, callerUid, callingProcName);
+ ALOGE("display.qservice CONNECT_HWC_CLIENT access denied: pid=%d uid=%d",
+ callerPid, callerUid);
return PERMISSION_DENIED;
}
sp<IQClient> client =
interface_cast<IQClient>(data.readStrongBinder());
connect(client);
return NO_ERROR;
+ } else if(code == CONNECT_HDMI_CLIENT) {
+ CHECK_INTERFACE(IQService, data, reply);
+ if(callerUid != AID_SYSTEM && callerUid != AID_ROOT) {
+ ALOGE("display.qservice CONNECT_HDMI_CLIENT access denied: pid=%d uid=%d",
+ callerPid, callerUid);
+ return PERMISSION_DENIED;
+ }
+ sp<IQHDMIClient> client =
+ interface_cast<IQHDMIClient>(data.readStrongBinder());
+ connect(client);
+ return NO_ERROR;
} else if (code > COMMAND_LIST_START && code < COMMAND_LIST_END) {
if(!permission) {
- ALOGE("display.qservice access denied: command=%d\
- pid=%d uid=%d process=%s", code, callerPid,
- callerUid, callingProcName);
+ ALOGE("display.qservice access denied: command=%d pid=%d uid=%d",
+ code, callerPid, callerUid);
return PERMISSION_DENIED;
}
CHECK_INTERFACE(IQService, data, reply);
@@ -117,20 +132,4 @@ status_t BnQService::onTransact(
}
}
-//Helper
-static void getProcName(int pid, char *buf, int size) {
- int fd = -1;
- snprintf(buf, size, "/proc/%d/cmdline", pid);
- fd = open(buf, O_RDONLY);
- if (fd < 0) {
- strlcpy(buf, "Unknown", size);
- } else {
- ssize_t len = read(fd, buf, size - 1);
- if (len >= 0)
- buf[len] = 0;
-
- close(fd);
- }
-}
-
}; // namespace qService
diff --git a/msm8909/libqservice/IQService.h b/msm8909/libqservice/IQService.h
index 0f0dc4c1..f9aa7fde 100644
--- a/msm8909/libqservice/IQService.h
+++ b/msm8909/libqservice/IQService.h
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2010 The Android Open Source Project
- * Copyright (C) 2012-2015, The Linux Foundation. All rights reserved.
+ * Copyright (C) 2012-2014, 2016-2017 The Linux Foundation. All rights reserved.
*
* Not a Contribution, Apache license notifications and license are
* retained for attribution purposes only.
@@ -28,6 +28,7 @@
#include <binder/IInterface.h>
#include <binder/IBinder.h>
#include <IQClient.h>
+#include <IQHDMIClient.h>
namespace qService {
@@ -39,25 +40,41 @@ public:
DECLARE_META_INTERFACE(QService);
enum {
COMMAND_LIST_START = android::IBinder::FIRST_CALL_TRANSACTION,
- SECURING, // Hardware securing start/end notification
- UNSECURING, // Hardware unsecuring start/end notification
- CONNECT, // Connect to qservice
- SCREEN_REFRESH, // Refresh screen through SF invalidate
- EXTERNAL_ORIENTATION, // Set external orientation
- BUFFER_MIRRORMODE, // Buffer mirrormode
- CHECK_EXTERNAL_STATUS, // Check status of external display
- GET_DISPLAY_ATTRIBUTES, // Get display attributes
- SET_HSIC_DATA, // Set HSIC on dspp
- GET_DISPLAY_VISIBLE_REGION, // Get the visibleRegion for dpy
- SET_SECONDARY_DISPLAY_STATUS, // Sets secondary display status
- SET_PARTIAL_UPDATE, // Preference on partial update feature
- SET_VIEW_FRAME, // Set view frame of display
- DYNAMIC_DEBUG, // Enable more logging on the fly
- SET_IDLE_TIMEOUT, // Set idle timeout for GPU fallback
+ GET_PANEL_BRIGHTNESS = 2, // Provides ability to set the panel brightness
+ SET_PANEL_BRIGHTNESS = 3, // Provides ability to get the panel brightness
+ CONNECT_HWC_CLIENT = 4, // Connect to qservice
+ SCREEN_REFRESH = 5, // Refresh screen through SF invalidate
+ EXTERNAL_ORIENTATION = 6,// Set external orientation
+ BUFFER_MIRRORMODE = 7, // Buffer mirrormode
+ CHECK_EXTERNAL_STATUS = 8,// Check status of external display
+ GET_DISPLAY_ATTRIBUTES = 9,// Get display attributes
+ SET_HSIC_DATA = 10, // Set HSIC on dspp
+ GET_DISPLAY_VISIBLE_REGION = 11,// Get the visibleRegion for dpy
+ SET_SECONDARY_DISPLAY_STATUS = 12,// Sets secondary display status
+ SET_MAX_PIPES_PER_MIXER = 13,// Set max pipes per mixer for MDPComp
+ SET_VIEW_FRAME = 14, // Set view frame of display
+ DYNAMIC_DEBUG = 15, // Enable more logging on the fly
+ SET_IDLE_TIMEOUT = 16, // Set idle timeout for GPU fallback
+ TOGGLE_BWC = 17, // Toggle BWC On/Off on targets that support
/* Enable/Disable/Set refresh rate dynamically */
- CONFIGURE_DYN_REFRESH_RATE,
- QDCM_SVC_CMDS, // request QDCM services.
- TOGGLE_SCREEN_UPDATE, // Provides ability to disable screen updates
+ CONFIGURE_DYN_REFRESH_RATE = 18,
+ CONTROL_PARTIAL_UPDATE = 19, // Provides ability to enable/disable partial update
+ TOGGLE_SCREEN_UPDATES = 20, // Provides ability to set the panel brightness
+ SET_FRAME_DUMP_CONFIG = 21, // Provides ability to set the frame dump config
+ SET_S3D_MODE = 22, // Set the 3D mode as specified in msm_hdmi_modes.h
+ CONNECT_HDMI_CLIENT = 23, // Connect HDMI CEC HAL Client
+ QDCM_SVC_CMDS = 24, // request QDCM services.
+ SET_ACTIVE_CONFIG = 25, //Set a specified display config
+ GET_ACTIVE_CONFIG = 26, //Get the current config index
+ GET_CONFIG_COUNT = 27, //Get the number of supported display configs
+ GET_DISPLAY_ATTRIBUTES_FOR_CONFIG = 28, //Get attr for specified config
+ SET_DISPLAY_MODE = 29, // Set display mode to command or video mode
+ SET_CAMERA_STATUS = 30, // To notify display when camera is on and off
+ MIN_HDCP_ENCRYPTION_LEVEL_CHANGED = 31,
+ GET_BW_TRANSACTION_STATUS = 32, //Client can query BW transaction status.
+ SET_LAYER_MIXER_RESOLUTION = 33, // Enables client to set layer mixer resolution.
+ SET_COLOR_MODE = 34, // Overrides the QDCM mode on the display
+ GET_HDR_CAPABILITIES = 35, // Get HDR capabilities for legacy HWC interface
COMMAND_LIST_END = 400,
};
@@ -72,6 +89,14 @@ public:
DEBUG_VSYNC,
DEBUG_VD,
DEBUG_PIPE_LIFECYCLE,
+ DEBUG_DRIVER_CONFIG,
+ DEBUG_ROTATOR,
+ DEBUG_QDCM,
+ DEBUG_SCALAR,
+ DEBUG_CLIENT,
+ DEBUG_DISPLAY,
+ DEBUG_MAX_VAL = DEBUG_DISPLAY, // Used to check each bit of the debug command paramater.
+ // Update DEBUG_MAX_VAL when adding new debug tag.
};
enum {
@@ -80,8 +105,13 @@ public:
ENABLE_PARTIAL_UPDATE,
};
- // Register a client that can be notified
+ // Register a HWC client that can be notified
+ // This client is generic and is intended to get
+ // dispatches of all events calling into QService
virtual void connect(const android::sp<qClient::IQClient>& client) = 0;
+ // Register an HDMI client. This client gets notification of HDMI events
+ // such as plug/unplug and CEC messages
+ virtual void connect(const android::sp<qClient::IQHDMIClient>& client) = 0;
// Generic function to dispatch binder commands
// The type of command decides how the data is parceled
virtual android::status_t dispatch(uint32_t command,
diff --git a/msm8909/libqservice/Makefile.am b/msm8909/libqservice/Makefile.am
new file mode 100644
index 00000000..79935b8b
--- /dev/null
+++ b/msm8909/libqservice/Makefile.am
@@ -0,0 +1,18 @@
+h_sources = IQService.h \
+ IQClient.h
+
+cpp_sources = QService.cpp \
+ IQService.cpp \
+ IQClient.cpp \
+ IQHDMIClient.cpp
+
+library_includedir = $(includedir)
+library_include_HEADERS = $(h_sources)
+
+lib_LTLIBRARIES = libqservice.la
+libqservice_la_CC = @CC@
+libqservice_la_SOURCES = $(cpp_sources)
+libqservice_la_CFLAGS = $(COMMON_CFLAGS) -DLOG_TAG=\"qdqservice\"
+libqservice_la_CPPFLAGS = $(AM_CPPFLAGS)
+libqservice_LDADD = -lhardware -lcutils -llog -lbinder
+libqservice_la_LDFLAGS = -shared -avoid-version \ No newline at end of file
diff --git a/msm8909/libqservice/QService.cpp b/msm8909/libqservice/QService.cpp
index 12dd9956..546ad7ee 100644
--- a/msm8909/libqservice/QService.cpp
+++ b/msm8909/libqservice/QService.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2014, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2014, 2016, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -50,24 +50,52 @@ QService::~QService()
}
void QService::connect(const sp<qClient::IQClient>& client) {
- ALOGD_IF(QSERVICE_DEBUG,"client connected");
+ ALOGD_IF(QSERVICE_DEBUG,"HWC client connected");
mClient = client;
}
+void QService::connect(const sp<qClient::IQHDMIClient>& client) {
+ ALOGD_IF(QSERVICE_DEBUG,"HDMI client connected");
+ mHDMIClient = client;
+}
+
status_t QService::dispatch(uint32_t command, const Parcel* inParcel,
Parcel* outParcel) {
status_t err = (status_t) FAILED_TRANSACTION;
IPCThreadState* ipc = IPCThreadState::self();
//Rewind parcel in case we're calling from the same process
- if (ipc->getCallingPid() == getpid())
+ bool sameProcess = (ipc->getCallingPid() == getpid());
+ if(sameProcess)
inParcel->setDataPosition(0);
if (mClient.get()) {
ALOGD_IF(QSERVICE_DEBUG, "Dispatching command: %d", command);
err = mClient->notifyCallback(command, inParcel, outParcel);
+ //Rewind parcel in case we're calling from the same process
+ if (sameProcess)
+ outParcel->setDataPosition(0);
}
return err;
}
+void QService::onHdmiHotplug(int connected) {
+ if(mHDMIClient.get()) {
+ ALOGD_IF(QSERVICE_DEBUG, "%s: HDMI hotplug", __FUNCTION__);
+ mHDMIClient->onHdmiHotplug(connected);
+ } else {
+ ALOGW("%s: Failed to get a valid HDMI client", __FUNCTION__);
+ }
+}
+
+void QService::onCECMessageReceived(char *msg, ssize_t len) {
+ if(mHDMIClient.get()) {
+ ALOGD_IF(QSERVICE_DEBUG, "%s: CEC message received", __FUNCTION__);
+ mHDMIClient->onCECMessageRecieved(msg, len);
+ } else {
+ ALOGW("%s: Failed to get a valid HDMI client", __FUNCTION__);
+ }
+}
+
+
void QService::init()
{
if(!sQService) {
diff --git a/msm8909/libqservice/QService.h b/msm8909/libqservice/QService.h
index a8e4cdba..6bb4d7d5 100644
--- a/msm8909/libqservice/QService.h
+++ b/msm8909/libqservice/QService.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2013, 2016, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -32,7 +32,7 @@
#include <utils/Errors.h>
#include <sys/types.h>
-#include <cutils/log.h>
+#include <log/log.h>
#include <binder/IServiceManager.h>
#include <IQService.h>
#include <IQClient.h>
@@ -46,13 +46,17 @@ class QService : public BnQService {
public:
virtual ~QService();
virtual void connect(const android::sp<qClient::IQClient>& client);
+ virtual void connect(const android::sp<qClient::IQHDMIClient>& client);
virtual android::status_t dispatch(uint32_t command,
const android::Parcel* data,
android::Parcel* reply);
+ virtual void onHdmiHotplug(int connected);
+ virtual void onCECMessageReceived(char *msg, ssize_t len);
static void init();
private:
QService();
android::sp<qClient::IQClient> mClient;
+ android::sp<qClient::IQHDMIClient> mHDMIClient;
static QService *sQService;
};
}; // namespace qService
diff --git a/msm8909/libqservice/QServiceUtils.h b/msm8909/libqservice/QServiceUtils.h
index ff09aa97..8f25253c 100644
--- a/msm8909/libqservice/QServiceUtils.h
+++ b/msm8909/libqservice/QServiceUtils.h
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2013-15 The Linux Foundation. All rights reserved.
+* Copyright (c) 2013-14 The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -62,24 +62,12 @@ inline android::status_t sendSingleParam(uint32_t command, uint32_t value) {
// ----------------------------------------------------------------------------
// Convenience wrappers that clients can call
// ----------------------------------------------------------------------------
-inline android::status_t securing(uint32_t startEnd) {
- return sendSingleParam(qService::IQService::SECURING, startEnd);
-}
-
-inline android::status_t unsecuring(uint32_t startEnd) {
- return sendSingleParam(qService::IQService::UNSECURING, startEnd);
-}
-
inline android::status_t screenRefresh() {
return sendSingleParam(qService::IQService::SCREEN_REFRESH, 1);
}
-inline android::status_t setPartialUpdate(uint32_t enable) {
- return sendSingleParam(qService::IQService::SET_PARTIAL_UPDATE, enable);
-}
-
inline android::status_t toggleScreenUpdate(uint32_t on) {
- return sendSingleParam(qService::IQService::TOGGLE_SCREEN_UPDATE, on);
+ return sendSingleParam(qService::IQService::TOGGLE_SCREEN_UPDATES, on);
}
inline android::status_t setExtOrientation(uint32_t orientation) {
@@ -91,4 +79,24 @@ inline android::status_t setBufferMirrorMode(uint32_t enable) {
return sendSingleParam(qService::IQService::BUFFER_MIRRORMODE, enable);
}
+inline android::status_t setCameraLaunchStatus(uint32_t on) {
+ return sendSingleParam(qService::IQService::SET_CAMERA_STATUS, on);
+}
+
+inline bool displayBWTransactionPending() {
+ android::status_t err = (android::status_t) android::FAILED_TRANSACTION;
+ bool ret = false;
+ android::sp<qService::IQService> binder = getBinder();
+ android::Parcel inParcel, outParcel;
+ if(binder != NULL) {
+ err = binder->dispatch(qService::IQService::GET_BW_TRANSACTION_STATUS,
+ &inParcel , &outParcel);
+ if(err != android::NO_ERROR){
+ ALOGE("GET_BW_TRANSACTION_STATUS binder call failed err=%d", err);
+ return ret;
+ }
+ }
+ ret = outParcel.readInt32();
+ return ret;
+}
#endif /* end of include guard: QSERVICEUTILS_H */
diff --git a/msm8909/sdm/include/core/buffer_allocator.h b/msm8909/sdm/include/core/buffer_allocator.h
new file mode 100644
index 00000000..6d77bcde
--- /dev/null
+++ b/msm8909/sdm/include/core/buffer_allocator.h
@@ -0,0 +1,159 @@
+/*
+* Copyright (c) 2015 - 2017, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*! @file buffer_allocator.h
+ @brief Interface file for platform specific buffer allocator.
+
+ @details This interface is used by SDM to allocate internal buffers.
+*/
+
+#ifndef __BUFFER_ALLOCATOR_H__
+#define __BUFFER_ALLOCATOR_H__
+
+#include "layer_buffer.h"
+
+namespace sdm {
+/*! @brief Input configuration set by the client for buffer allocation.
+
+ @sa BufferInfo::BufferConfig
+*/
+
+struct BufferConfig {
+ uint32_t width = 0; //!< Specifies buffer width for buffer allocation.
+ uint32_t height = 0; //!< Specifies buffer height for buffer allocation.
+ LayerBufferFormat format = kFormatInvalid; //!< Specifies buffer format for buffer allocation.
+ uint32_t buffer_count = 0; //!< Specifies number of buffers to be allocated.
+ bool secure = false; //!< Specifies buffer to be allocated from
+ //!< secure region.
+ bool cache = false; //!< Specifies whether the buffer needs to be cache.
+ bool secure_camera = false; //!< Specifies buffer to be allocated from specific
+ //!< secure heap and with a specific alignment.
+ bool gfx_client = false; //!< Specifies whether buffer is used by gfx.
+};
+
+/*! @brief Holds the information about the allocated buffer.
+
+ @sa BufferAllocator::AllocateBuffer
+ @sa BufferAllocator::FreeBuffer
+ @sa BufferAllocator::GetAllocatedBufferInfo
+*/
+struct AllocatedBufferInfo {
+ int fd = -1; //!< Specifies the fd of the allocated buffer.
+ uint32_t stride = 0; //!< Specifies allocated buffer stride in bytes.
+ uint32_t aligned_width = 0; //!< Specifies aligned allocated buffer width in pixels.
+ uint32_t aligned_height = 0; //!< Specifies aligned allocated buffer height in pixels.
+ LayerBufferFormat format = kFormatInvalid; // Specifies buffer format for allocated buffer.
+ uint32_t size = 0; //!< Specifies the size of the allocated buffer.
+};
+
+/*! @brief Holds the information about the input/output configuration of an output buffer.
+
+ @sa BufferAllocator::AllocateBuffer
+ @sa BufferAllocator::FreeBuffer
+*/
+struct BufferInfo {
+ BufferConfig buffer_config; //!< Specifies configuration of a buffer to be allocated.
+ AllocatedBufferInfo alloc_buffer_info; //!< Specifies buffer information of allocated buffer.
+
+ void *private_data = NULL; //!< Pointer to private data.
+};
+
+/*! @brief Buffer allocator implemented by the client
+
+ @details This class declares prototype for BufferAllocator methods which must be
+ implemented by the client. Buffer manager in display manager will use these methods to
+ allocate/deallocate buffers for display manager.
+
+ @sa CoreInterface::CreateCore
+*/
+class BufferAllocator {
+ public:
+ /*! @brief Method to allocate ouput buffer for the given input configuration.
+
+ @details This method allocates memory based on input configuration.
+
+ @param[in] buffer_info \link BufferInfo \endlink
+
+ @return \link DisplayError \endlink
+ */
+ virtual DisplayError AllocateBuffer(BufferInfo *buffer_info) = 0;
+
+
+ /*! @brief Method to deallocate the ouput buffer.
+
+ @details This method deallocates the memory allocated using AllocateBuffer method.
+
+ @param[in] buffer_info \link BufferInfo \endlink
+
+ @return \link DisplayError \endlink
+ */
+ virtual DisplayError FreeBuffer(BufferInfo *buffer_info) = 0;
+
+
+ /*! @brief Method to get the buffer size.
+
+ @details This method returns buffer size for a specific configuration mentioned in buffer info.
+
+ @param[in] buffer_info \link BufferInfo \endlink
+
+ @return \link unsigned int \endlink
+ */
+ virtual uint32_t GetBufferSize(BufferInfo *buffer_info) = 0;
+
+ /*! @brief Method to Get the AllocatedBufferInfo only.
+
+ @details This method populates the AllocatedBufferInfo as per the configuration in BufferInfo,
+ but fd will be invalid.
+
+ @param[in] buffer_info \link BufferInfo \endlink
+
+ @param[out] allocated_buffer_info \link AllocatedBufferInfo \endlink
+
+ @return \link DisplayError \endlink
+ */
+ virtual DisplayError GetAllocatedBufferInfo(const BufferConfig &buffer_config,
+ AllocatedBufferInfo *allocated_buffer_info) = 0;
+
+ /*
+ * Retuns a buffer's layout in terms of number of planes, stride and offset of each plane
+ * Input: AllocatedBufferInfo with a valid aligned width, aligned height, SDM format
+ * Output: stride for each plane, offset of each plane from base, number of planes
+ */
+ virtual DisplayError GetBufferLayout(const AllocatedBufferInfo &buf_info,
+ uint32_t stride[4], uint32_t offset[4],
+ uint32_t *num_planes) { return kErrorNotSupported; }
+
+ protected:
+ virtual ~BufferAllocator() { }
+};
+
+} // namespace sdm
+
+#endif // __BUFFER_ALLOCATOR_H__
+
diff --git a/msm8909/sdm/include/core/buffer_sync_handler.h b/msm8909/sdm/include/core/buffer_sync_handler.h
new file mode 100644
index 00000000..1dc54138
--- /dev/null
+++ b/msm8909/sdm/include/core/buffer_sync_handler.h
@@ -0,0 +1,99 @@
+/*
+* Copyright (c) 2015, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*! @file buffer_sync_handler.h
+ @brief Interface file for platform specific buffer allocator.
+
+ @details SDM will use this interface to wait for buffer sync fd to be signaled/merge
+ the two buffer sync fds into one.
+*/
+
+#ifndef __BUFFER_SYNC_HANDLER_H__
+#define __BUFFER_SYNC_HANDLER_H__
+
+#include "sdm_types.h"
+
+namespace sdm {
+
+/*! @brief Buffer sync handler implemented by the client
+
+ @details This class declares prototype for BufferSyncHandler methods which must be
+ implemented by the client. SDM will use these methods to wait for buffer sync fd to be
+ signaled/merge two buffer sync fds into one.
+
+ @sa CoreInterface::CreateCore
+*/
+class BufferSyncHandler {
+ public:
+ /*! @brief Method to wait for ouput buffer to be released.
+
+ @details This method waits for fd to be signaled by the producer/consumer.
+ It is responsibility of the caller to close file descriptor.
+
+ @param[in] fd
+
+ @return \link DisplayError \endlink
+ */
+
+ virtual DisplayError SyncWait(int fd) = 0;
+
+ /*! @brief Method to merge two sync fds into one sync fd
+
+ @details This method merges two buffer sync fds into one sync fd, if a producer/consumer
+ requires to wait for more than one sync fds. It is responsibility of the caller to close file
+ descriptor.
+
+ @param[in] fd1
+ @param[in] fd2
+ @param[out] merged_fd
+
+ @return \link DisplayError \endlink
+ */
+
+ virtual DisplayError SyncMerge(int fd1, int fd2, int *merged_fd) = 0;
+
+ /*! @brief Method to detect if sync fd is signaled
+
+ @details This method detects if sync fd is signaled. It is responsibility of the caller to
+ close file descriptor.
+
+ @param[in] fd
+
+ @return \link Tue if fd has been signaled \endlink
+ */
+ virtual bool IsSyncSignaled(int fd) = 0;
+
+ protected:
+ virtual ~BufferSyncHandler() { }
+};
+
+} // namespace sdm
+
+#endif // __BUFFER_SYNC_HANDLER_H__
+
diff --git a/msm8909/sdm/include/core/core_interface.h b/msm8909/sdm/include/core/core_interface.h
new file mode 100644
index 00000000..88cbf75c
--- /dev/null
+++ b/msm8909/sdm/include/core/core_interface.h
@@ -0,0 +1,240 @@
+/*
+* Copyright (c) 2014 - 2016, 2018 The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*! @file core_interface.h
+ @brief Interface file for core of the display subsystem.
+
+ @details Display core is primarily used for loading and unloading different display device
+ components viz primary, external and virtual. Display core is a statically linked library which
+ runs in caller's process context.
+*/
+#ifndef __CORE_INTERFACE_H__
+#define __CORE_INTERFACE_H__
+
+#include <stdint.h>
+
+#include "display_interface.h"
+#include "sdm_types.h"
+#include "buffer_allocator.h"
+#include "buffer_sync_handler.h"
+#include "socket_handler.h"
+
+/*! @brief Display manager interface version.
+
+ @details Display manager interfaces are version tagged to maintain backward compatibility. This
+ version is supplied as a default argument during display core initialization.
+
+ Client may use an older version of interfaces and link to a higher version of display manager
+ library, but vice versa is not allowed.
+
+ A 32-bit client must use 32-bit display core library and a 64-bit client must use 64-bit display
+ core library.
+
+ Display manager interfaces follow default data structures alignment. Client must not override the
+ default padding rules while using these interfaces.
+
+ @warning It is assumed that client upgrades or downgrades display core interface all at once
+ and recompile all binaries which use these interfaces. Mix and match of these interfaces can
+ lead to unpredictable behaviour.
+
+ @sa CoreInterface::CreateCore
+*/
+#define SDM_REVISION_MAJOR (1)
+#define SDM_REVISION_MINOR (0)
+
+#define SDM_VERSION_TAG ((uint32_t) ((SDM_REVISION_MAJOR << 24) | (SDM_REVISION_MINOR << 16) | \
+ (sizeof(SDMCompatibility) << 8) | sizeof(int *)))
+
+namespace sdm {
+
+/*! @brief Forward declaration for debug handler.
+*/
+class DebugHandler;
+
+/*! @brief This enum represents max bandwidth limit mode.
+
+ @sa DisplayInterface::SetMaxBandwidthMode
+*/
+enum HWBwModes {
+ kBwDefault, //!< Default state. No change in device bandwidth limit.
+ kBwCamera, //!< Camera is on. Bandwidth limit should be reduced accordingly.
+ kBwVFlip, //!< VFlip is required. Reduce bandwidth limit accordingly.
+ kBwHFlip, //!< HFlip is required. Reduce bandwidth limit accordingly.
+ kBwModeMax, //!< Limiter for maximum available bandwidth modes.
+};
+
+
+/*! @brief Information on hardware for the first display
+
+ @details This structure returns the display type of the first display on the device
+ (internal display or HDMI etc) and whether it is currently connected,
+
+*/
+struct HWDisplayInterfaceInfo {
+ DisplayType type;
+ bool is_connected;
+};
+
+/*! @brief Display core interface.
+
+ @details This class defines display core interfaces. It contains methods which client shall use
+ to create/destroy different display devices. This interface is created during display core
+ CreateCore() and remains valid until DestroyCore().
+
+ @sa CoreInterface::CreateCore
+ @sa CoreInterface::DestroyCore
+*/
+class CoreInterface {
+ public:
+ /*! @brief Method to create and get handle to display core interface.
+
+ @details This method is the entry point into the display core. Client can create and operate on
+ different display devices only through a valid interface handle obtained using this method. An
+ object of display core is created and handle to this object is returned via output parameter.
+ This interface shall be called only once.
+
+ @param[in] debug_handler \link DebugHandler \endlink
+ @param[in] buffer_allocator \link BufferAllocator \endlink
+ @param[in] buffer_sync_handler \link BufferSyncHandler \endlink
+ @param[out] interface \link CoreInterface \endlink
+ @param[in] version \link SDM_VERSION_TAG \endlink. Client must not override this argument.
+
+ @return \link DisplayError \endlink
+
+ @sa DestroyCore
+ */
+ static DisplayError CreateCore(DebugHandler *debug_handler, BufferAllocator *buffer_allocator,
+ BufferSyncHandler *buffer_sync_handler, CoreInterface **interface,
+ uint32_t version = SDM_VERSION_TAG);
+
+ /*! @brief Method to create and get handle to display core interface.
+
+ @details This method is the entry point into the display core. Client can create and operate on
+ different display devices only through a valid interface handle obtained using this method. An
+ object of display core is created and handle to this object is returned via output parameter.
+ This interface shall be called only once.
+
+ @param[in] debug_handler \link DebugHandler \endlink
+ @param[in] buffer_allocator \link BufferAllocator \endlink
+ @param[in] buffer_sync_handler \link BufferSyncHandler \endlink
+ @param[in] socket_handler \link SocketHandler \endlink
+ @param[out] interface \link CoreInterface \endlink
+ @param[in] version \link SDM_VERSION_TAG \endlink. Client must not override this argument.
+
+ @return \link DisplayError \endlink
+
+ @sa DestroyCore
+ */
+ static DisplayError CreateCore(DebugHandler *debug_handler, BufferAllocator *buffer_allocator,
+ BufferSyncHandler *buffer_sync_handler,
+ SocketHandler *socket_handler, CoreInterface **interface,
+ uint32_t version = SDM_VERSION_TAG);
+
+ /*! @brief Method to release handle to display core interface.
+
+ @details The object of corresponding display core is destroyed when this method is invoked.
+ Client must explicitly destroy all created display device objects associated with this handle
+ before invoking this method.
+
+ @param[in] interface \link CoreInterface \endlink
+
+ @return \link DisplayError \endlink
+
+ @sa CreateCore
+ */
+ static DisplayError DestroyCore();
+
+ /*! @brief Method to create a display device for a given type.
+
+ @details Client shall use this method to create each of the connected display type. A handle to
+ interface associated with this object is returned via output parameter which can be used to
+ interact further with the display device.
+
+ @param[in] type \link DisplayType \endlink
+ @param[in] event_handler \link DisplayEventHandler \endlink
+ @param[out] interface \link DisplayInterface \endlink
+
+ @return \link DisplayError \endlink
+
+ @sa DestroyDisplay
+ */
+ virtual DisplayError CreateDisplay(DisplayType type, DisplayEventHandler *event_handler,
+ DisplayInterface **interface) = 0;
+
+ /*! @brief Method to destroy a display device.
+
+ @details Client shall use this method to destroy each of the created display device objects.
+
+ @param[in] interface \link DisplayInterface \endlink
+
+ @return \link DisplayError \endlink
+
+ @sa CreateDisplay
+ */
+ virtual DisplayError DestroyDisplay(DisplayInterface *interface) = 0;
+
+ /*! @brief Method to update the bandwidth limit as per given mode.
+
+ @param[in] mode indicate the mode or use case
+
+ @return \link DisplayError \endlink
+
+ */
+ virtual DisplayError SetMaxBandwidthMode(HWBwModes mode) = 0;
+
+ /*! @brief Method to get characteristics of the first display.
+
+ @details Client shall use this method to determine if the first display is HDMI, and whether
+ it is currently connected.
+
+ @param[in] hw_disp_info structure that this method will fill up with info.
+
+ @return \link DisplayError \endlink
+
+ */
+ virtual DisplayError GetFirstDisplayInterfaceType(HWDisplayInterfaceInfo *hw_disp_info) = 0;
+
+ /*! @brief Method to check color transform supported or not.
+
+ @details Client shall use this method to determine if target supports color transform or not
+
+ @return bool
+
+ */
+ virtual bool IsColorTransformSupported() = 0;
+
+
+ protected:
+ virtual ~CoreInterface() { }
+};
+
+} // namespace sdm
+
+#endif // __CORE_INTERFACE_H__
+
diff --git a/msm8909/sdm/include/core/debug_interface.h b/msm8909/sdm/include/core/debug_interface.h
new file mode 100644
index 00000000..08f65eae
--- /dev/null
+++ b/msm8909/sdm/include/core/debug_interface.h
@@ -0,0 +1,165 @@
+/*
+* Copyright (c) 2015 - 2016, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*! @file debug_interface.h
+ @brief This file provides the debug interface for display manager.
+*/
+#ifndef __DEBUG_INTERFACE_H__
+#define __DEBUG_INTERFACE_H__
+
+namespace sdm {
+
+/*! @brief This enum represents different modules/logical unit tags that a log message may
+ be associated with. Client may use this to filter messages for dynamic logging.
+
+ @sa DebugHandler
+*/
+enum DebugTag {
+ kTagNone, //!< Debug log is not tagged. This type of logs should always be printed.
+ kTagResources, //!< Debug log is tagged for resource management.
+ kTagStrategy, //!< Debug log is tagged for strategy decisions.
+ kTagCompManager, //!< Debug log is tagged for composition manager.
+ kTagDriverConfig, //!< Debug log is tagged for driver config.
+ kTagRotator, //!< Debug log is tagged for rotator.
+ kTagScalar, //!< Debug log is tagged for Scalar Helper.
+ kTagQDCM, //!< Debug log is tagged for display QDCM color managing.
+ kTagDisplay, //!< Debug log is tagged for display core logs.
+ kTagClient, //!< Debug log is tagged for SDM client.
+};
+
+/*! @brief Display debug handler class.
+
+ @details This class defines display debug handler. The handle contains methods which client
+ should implement to get different levels of logging/tracing from display manager. Display manager
+ will call into these methods at appropriate times to send logging/tracing information.
+
+ @sa CoreInterface::CreateCore
+*/
+class DebugHandler {
+ public:
+ /*! @brief Method to handle error messages.
+
+ @param[in] tag \link DebugTag \endlink
+ @param[in] format \link message format with variable argument list \endlink
+ */
+ virtual void Error(DebugTag tag, const char *format, ...) = 0;
+
+ /*! @brief Method to handle warning messages.
+
+ @param[in] tag \link DebugTag \endlink
+ @param[in] format \link message format with variable argument list \endlink
+ */
+ virtual void Warning(DebugTag tag, const char *format, ...) = 0;
+
+ /*! @brief Method to handle informative messages.
+
+ @param[in] tag \link DebugTag \endlink
+ @param[in] format \link message format with variable argument list \endlink
+ */
+ virtual void Info(DebugTag tag, const char *format, ...) = 0;
+
+ /*! @brief Method to handle debug messages.
+
+ @param[in] tag \link DebugTag \endlink
+ @param[in] format \link message format with variable argument list \endlink
+ */
+ virtual void Debug(DebugTag tag, const char *format, ...) = 0;
+
+ /*! @brief Method to handle verbose messages.
+
+ @param[in] tag \link DebugTag \endlink
+ @param[in] format \link message format with variable argument list \endlink
+ */
+ virtual void Verbose(DebugTag tag, const char *format, ...) = 0;
+
+ /*! @brief Method to begin trace for a module/logical unit.
+
+ @param[in] class_name \link name of the class that the function belongs to \endlink
+ @param[in] function_name \link name of the function to be traced \endlink
+ @param[in] custom_string \link custom string for multiple traces within a function \endlink
+ */
+ virtual void BeginTrace(const char *class_name, const char *function_name,
+ const char *custom_string) = 0;
+
+ /*! @brief Method to end trace for a module/logical unit.
+ */
+ virtual void EndTrace() = 0;
+
+ /*! @brief Method to get property value corresponding to give string.
+
+ @param[in] property_name name of the property
+ @param[out] integer converted value corresponding to the property name
+
+ @return \link DisplayError \endlink
+ */
+ virtual DisplayError GetProperty(const char *property_name, int *value) = 0;
+
+ /*! @brief Method to get property value corresponding to give string.
+
+ @param[in] property_name name of the property
+ @param[out] string value corresponding to the property name
+
+ @return \link DisplayError \endlink
+ */
+ virtual DisplayError GetProperty(const char *property_name, char *value) = 0;
+
+ /*! @brief Method to set a property to a given string value.
+
+ @param[in] property_name name of the property
+ @param[in] value new value of the property name
+
+ @return \link DisplayError \endlink
+ */
+ virtual DisplayError SetProperty(const char *property_name, const char *value) = 0;
+
+ protected:
+ virtual ~DebugHandler() { }
+};
+
+/*! @brief Scope tracer template class.
+
+ @details This class template implements the funtionality to capture the trace for function/
+ module. It starts the trace upon object creation and ends the trace upon object destruction.
+*/
+template <class T>
+class ScopeTracer {
+ public:
+ ScopeTracer(const char *class_name, const char *function_name) {
+ T::Get()->BeginTrace(class_name, function_name, "");
+ }
+
+ ~ScopeTracer() { T::Get()->EndTrace(); }
+};
+
+} // namespace sdm
+
+#endif // __DEBUG_INTERFACE_H__
+
+
+
diff --git a/msm8909/sdm/include/core/display_interface.h b/msm8909/sdm/include/core/display_interface.h
new file mode 100644
index 00000000..3101eec6
--- /dev/null
+++ b/msm8909/sdm/include/core/display_interface.h
@@ -0,0 +1,694 @@
+/*
+* Copyright (c) 2014 - 2017, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without modification, are permitted
+* provided that the following conditions are met:
+* * Redistributions of source code must retain the above copyright notice, this list of
+* conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright notice, this list of
+* conditions and the following disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its contributors may be used to
+* endorse or promote products derived from this software without specific prior written
+* permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*! @file display_interface.h
+ @brief Interface file for display device which represents a physical panel or an output buffer
+ where contents can be rendered.
+
+ @details Display device is used to send layer buffers for composition and get them rendered onto
+ the target device. Each display device represents a unique display target which may be either a
+ physical panel or an output buffer..
+*/
+#ifndef __DISPLAY_INTERFACE_H__
+#define __DISPLAY_INTERFACE_H__
+
+#include <stdint.h>
+#include <string>
+#include <vector>
+#include <utility>
+
+#include "layer_stack.h"
+#include "sdm_types.h"
+
+namespace sdm {
+
+typedef std::vector<std::pair<std::string, std::string>> AttrVal;
+
+/*! @brief This enum represents display device types where contents can be rendered.
+
+ @sa CoreInterface::CreateDisplay
+ @sa CoreInterface::IsDisplaySupported
+*/
+enum DisplayType {
+ kPrimary, //!< Main physical display which is attached to the handheld device.
+ kHDMI, //!< HDMI physical display which is generally detachable.
+ kVirtual, //!< Contents would be rendered into the output buffer provided by the client
+ //!< e.g. wireless display.
+ kDisplayMax,
+};
+
+/*! @brief This enum represents states of a display device.
+
+ @sa DisplayInterface::GetDisplayState
+ @sa DisplayInterface::SetDisplayState
+*/
+enum DisplayState {
+ kStateOff, //!< Display is OFF. Contents are not rendered in this state. Client will not
+ //!< receive VSync events in this state. This is default state as well.
+
+ kStateOn, //!< Display is ON. Contents are rendered in this state.
+
+ kStateDoze, //!< Display is ON and it is configured in a low power state.
+
+ kStateDozeSuspend,
+ //!< Display is ON in a low power state and continue showing its current
+ //!< contents indefinitely until the mode changes.
+
+ kStateStandby, //!< Display is OFF. Client will continue to receive VSync events in this state
+ //!< if VSync is enabled. Contents are not rendered in this state.
+};
+
+/*! @brief This enum represents flags to override detail enhancer parameters.
+
+ @sa DisplayInterface::SetDetailEnhancerData
+*/
+enum DetailEnhancerOverrideFlags {
+ kOverrideDEEnable = 0x1, // Specifies to enable detail enhancer
+ kOverrideDESharpen1 = 0x2, // Specifies user defined Sharpening/smooth for noise
+ kOverrideDESharpen2 = 0x4, // Specifies user defined Sharpening/smooth for signal
+ kOverrideDEClip = 0x8, // Specifies user defined DE clip shift
+ kOverrideDELimit = 0x10, // Specifies user defined DE limit value
+ kOverrideDEThrQuiet = 0x20, // Specifies user defined DE quiet threshold
+ kOverrideDEThrDieout = 0x40, // Specifies user defined DE dieout threshold
+ kOverrideDEThrLow = 0x80, // Specifies user defined DE low threshold
+ kOverrideDEThrHigh = 0x100, // Specifies user defined DE high threshold
+ kOverrideDEFilterConfig = 0x200, // Specifies user defined scaling filter config
+ kOverrideDEMax = 0xFFFFFFFF,
+};
+
+/*! @brief This enum represents Y/RGB scaling filter configuration.
+
+ @sa DisplayInterface::SetDetailEnhancerData
+*/
+enum ScalingFilterConfig {
+ kFilterEdgeDirected,
+ kFilterCircular,
+ kFilterSeparable,
+ kFilterBilinear,
+ kFilterMax,
+};
+
+/*! @brief This enum represents the quality level of the content.
+
+ @sa DisplayInterface::SetDetailEnhancerData
+*/
+enum ContentQuality {
+ kContentQualityUnknown, // Default: high artifact and noise
+ kContentQualityLow, // Low quality content, high artifact and noise,
+ kContentQualityMedium, // Medium quality, medium artifact and noise,
+ kContentQualityHigh, // High quality content, low artifact and noise
+ kContentQualityMax,
+};
+
+/*! @brief This enum represents the display port.
+
+ @sa DisplayInterface::GetDisplayPort
+*/
+enum DisplayPort {
+ kPortDefault,
+ kPortDSI, // Display is connected to DSI port.
+ kPortDTV, // Display is connected to DTV port
+ kPortWriteBack, // Display is connected to writeback port
+ kPortLVDS, // Display is connected to LVDS port
+ kPortEDP, // Display is connected to EDP port
+ kPortDP, // Display is connected to DP port.
+};
+
+/*! @brief This enum represents the events received by Display HAL. */
+enum DisplayEvent {
+ kIdleTimeout, // Event triggered by Idle Timer.
+ kThermalEvent, // Event triggered by Thermal.
+};
+
+/*! @brief This structure defines configuration for fixed properties of a display device.
+
+ @sa DisplayInterface::GetConfig
+ @sa DisplayInterface::SetConfig
+*/
+struct DisplayConfigFixedInfo {
+ bool underscan = false; //!< If display support CE underscan.
+ bool secure = false; //!< If this display is capable of handling secure content.
+ bool is_cmdmode = false; //!< If panel is command mode panel.
+ bool hdr_supported = false; //!< if HDR is enabled
+ uint32_t max_luminance = 0; //!< From Panel's peak luminance
+ uint32_t average_luminance = 0; //!< From Panel's average luminance
+ uint32_t min_luminance = 0; //!< From Panel's blackness level
+};
+
+/*! @brief This structure defines configuration for variable properties of a display device.
+
+ @sa DisplayInterface::GetConfig
+ @sa DisplayInterface::SetConfig
+*/
+struct DisplayConfigVariableInfo {
+ uint32_t x_pixels = 0; //!< Total number of pixels in X-direction on the display panel.
+ uint32_t y_pixels = 0; //!< Total number of pixels in Y-direction on the display panel.
+ float x_dpi = 0.0f; //!< Dots per inch in X-direction.
+ float y_dpi = 0.0f; //!< Dots per inch in Y-direction.
+ uint32_t fps = 0; //!< Frame rate per second.
+ uint32_t vsync_period_ns = 0; //!< VSync period in nanoseconds.
+ bool is_yuv = false; //!< If the display output is in YUV format.
+};
+
+/*! @brief Event data associated with VSync event.
+
+ @sa DisplayEventHandler::VSync
+*/
+struct DisplayEventVSync {
+ int64_t timestamp = 0; //!< System monotonic clock timestamp in nanoseconds.
+};
+
+/*! @brief The structure defines the user input for detail enhancer module.
+
+ @sa DisplayInterface::SetDetailEnhancerData
+*/
+struct DisplayDetailEnhancerData {
+ uint32_t override_flags = 0; // flags to specify which data to be set.
+ uint16_t enable = 0; // Detail enchancer enable
+ int16_t sharpen_level1 = 0; // Sharpening/smooth strenght for noise
+ int16_t sharpen_level2 = 0; // Sharpening/smooth strenght for signal
+ uint16_t clip = 0; // DE clip shift
+ uint16_t limit = 0; // DE limit value
+ uint16_t thr_quiet = 0; // DE quiet threshold
+ uint16_t thr_dieout = 0; // DE dieout threshold
+ uint16_t thr_low = 0; // DE low threshold
+ uint16_t thr_high = 0; // DE high threshold
+ int32_t sharp_factor = 50; // sharp_factor specifies sharpness/smoothness level,
+ // range -100..100 positive for sharpness and negative for
+ // smoothness
+ ContentQuality quality_level = kContentQualityUnknown;
+ // Specifies context quality level
+ ScalingFilterConfig filter_config = kFilterEdgeDirected;
+ // Y/RGB filter configuration
+};
+
+/*! @brief Display device event handler implemented by the client.
+
+ @details This class declares prototype for display device event handler methods which must be
+ implemented by the client. Display device will use these methods to notify events to the client.
+ Client must post heavy-weight event handling to a separate thread and unblock display manager
+ thread instantly.
+
+ @sa CoreInterface::CreateDisplay
+*/
+class DisplayEventHandler {
+ public:
+ /*! @brief Event handler for VSync event.
+
+ @details This event is dispatched on every vertical synchronization. The event is disabled by
+ default.
+
+ @param[in] vsync \link DisplayEventVSync \endlink
+
+ @return \link DisplayError \endlink
+
+ @sa DisplayInterface::GetDisplayState
+ @sa DisplayInterface::SetDisplayState
+ */
+ virtual DisplayError VSync(const DisplayEventVSync &vsync) = 0;
+
+ /*! @brief Event handler for Refresh event.
+
+ @details This event is dispatched to trigger a screen refresh. Client must call Prepare() and
+ Commit() in response to it from a separate thread. There is no data associated with this
+ event.
+
+ @return \link DisplayError \endlink
+
+ @sa DisplayInterface::Prepare
+ @sa DisplayInterface::Commit
+ */
+ virtual DisplayError Refresh() = 0;
+
+ /*! @brief Event handler for CEC messages.
+
+ @details This event is dispatched to send CEC messages to the CEC HAL.
+
+ @param[in] message message to be sent
+
+ @return \link DisplayError \endlink
+ */
+ virtual DisplayError CECMessage(char *message) = 0;
+
+ /*! @brief Event handler for events received by Display HAL. */
+ virtual DisplayError HandleEvent(DisplayEvent event) = 0;
+
+ protected:
+ virtual ~DisplayEventHandler() { }
+};
+
+struct PPDisplayAPIPayload;
+struct PPPendingParams;
+
+/*! @brief Display device interface.
+
+ @details This class defines display device interface. It contains methods which client shall use
+ to configure or submit layers for composition on the display device. This interface is created
+ during display device creation and remains valid until destroyed.
+
+ @sa CoreInterface::CreateDisplay
+ @sa CoreInterface::DestroyDisplay
+*/
+class DisplayInterface {
+ public:
+ /*! @brief Method to determine hardware capability to compose layers associated with given frame.
+
+ @details Client shall send all layers associated with a frame targeted for current display
+ using this method and check the layers which can be handled completely in display manager.
+
+ Client shall mark composition type for one of the layer as kCompositionGPUTarget; the GPU
+ composed output would be rendered at the specified layer if some of the layers are not handled
+ by SDM.
+
+ Display manager will set each layer as kCompositionGPU or kCompositionSDE upon return. Client
+ shall render all the layers marked as kCompositionGPU using GPU.
+
+ This method can be called multiple times but only last call prevails. This method must be
+ followed by Commit().
+
+ @param[inout] layer_stack \link LayerStack \endlink
+
+ @return \link DisplayError \endlink
+
+ @sa Commit
+ */
+ virtual DisplayError Prepare(LayerStack *layer_stack) = 0;
+
+ /*! @brief Method to commit layers of a frame submitted in a former call to Prepare().
+
+ @details Client shall call this method to submit layers for final composition. The composed
+ output would be displayed on the panel or written in output buffer.
+
+ Client must ensure that layer stack is same as previous call to Prepare.
+
+ This method shall be called only once for each frame.
+
+ In the event of an error as well, this call will cause any fences returned in the previous call
+ to Commit() to eventually become signaled, so the client's wait on fences can be released to
+ prevent deadlocks.
+
+ @param[in] layer_stack \link LayerStack \endlink
+
+ @return \link DisplayError \endlink
+
+ @sa Prepare
+ */
+ virtual DisplayError Commit(LayerStack *layer_stack) = 0;
+
+ /*! @brief Method to flush any pending buffers/fences submitted previously via Commit() call.
+
+ @details Client shall call this method to request the Display manager to release all buffers and
+ respective fences currently in use. This operation may result in a blank display on the panel
+ until a new frame is submitted for composition.
+
+ @return \link DisplayError \endlink
+
+ @sa Prepare
+ @sa Commit
+ */
+ virtual DisplayError Flush() = 0;
+
+ /*! @brief Method to get current state of the display device.
+
+ @param[out] state \link DisplayState \endlink
+
+ @return \link DisplayError \endlink
+
+ @sa SetDisplayState
+ */
+ virtual DisplayError GetDisplayState(DisplayState *state) = 0;
+
+ /*! @brief Method to get number of configurations(variable properties) supported on the display
+ device.
+
+ @param[out] count Number of modes supported; mode index starts with 0.
+
+ @return \link DisplayError \endlink
+ */
+ virtual DisplayError GetNumVariableInfoConfigs(uint32_t *count) = 0;
+
+ /*! @brief Method to get configuration for fixed properties of the display device.
+
+ @param[out] fixed_info \link DisplayConfigFixedInfo \endlink
+
+ @return \link DisplayError \endlink
+ */
+ virtual DisplayError GetConfig(DisplayConfigFixedInfo *fixed_info) = 0;
+
+ /*! @brief Method to get configuration for variable properties of the display device.
+
+ @param[in] index index of the mode
+ @param[out] variable_info \link DisplayConfigVariableInfo \endlink
+
+ @return \link DisplayError \endlink
+ */
+ virtual DisplayError GetConfig(uint32_t index, DisplayConfigVariableInfo *variable_info) = 0;
+
+ /*! @brief Method to get index of active configuration of the display device.
+
+ @param[out] index index of the mode corresponding to variable properties.
+
+ @return \link DisplayError \endlink
+ */
+ virtual DisplayError GetActiveConfig(uint32_t *index) = 0;
+
+ /*! @brief Method to get VSync event state. Default event state is disabled.
+
+ @param[out] enabled vsync state
+
+ @return \link DisplayError \endlink
+ */
+ virtual DisplayError GetVSyncState(bool *enabled) = 0;
+
+ /*! @brief Method to set current state of the display device.
+
+ @param[in] state \link DisplayState \endlink
+
+ @return \link DisplayError \endlink
+
+ @sa SetDisplayState
+ */
+ virtual DisplayError SetDisplayState(DisplayState state) = 0;
+
+ /*! @brief Method to set active configuration for variable properties of the display device.
+
+ @param[in] variable_info \link DisplayConfigVariableInfo \endlink
+
+ @return \link DisplayError \endlink
+ */
+ virtual DisplayError SetActiveConfig(DisplayConfigVariableInfo *variable_info) = 0;
+
+ /*! @brief Method to set active configuration for variable properties of the display device.
+
+ @param[in] index index of the mode corresponding to variable properties.
+
+ @return \link DisplayError \endlink
+ */
+ virtual DisplayError SetActiveConfig(uint32_t index) = 0;
+
+ /*! @brief Method to set VSync event state. Default event state is disabled.
+
+ @param[out] enabled vsync state
+
+ @return \link DisplayError \endlink
+ */
+ virtual DisplayError SetVSyncState(bool enable) = 0;
+
+ /*! @brief Method to set idle timeout value. Idle fallback is disabled with timeout value 0.
+
+ @param[in] active_ms value in milliseconds.
+
+ @return \link void \endlink
+ */
+ virtual void SetIdleTimeoutMs(uint32_t active_ms) = 0;
+
+ /*! @brief Method to set maximum number of mixer stages for each display.
+
+ @param[in] max_mixer_stages maximum number of mixer stages.
+
+ @return \link DisplayError \endlink
+ */
+ virtual DisplayError SetMaxMixerStages(uint32_t max_mixer_stages) = 0;
+
+ /*! @brief Method to control partial update feature for each display.
+
+ @param[in] enable partial update feature control flag
+ @param[out] pending whether the operation is completed or pending for completion
+
+ @return \link DisplayError \endlink
+ */
+ virtual DisplayError ControlPartialUpdate(bool enable, uint32_t *pending) = 0;
+
+ /*! @brief Method to disable partial update for at least 1 frame.
+ @return \link DisplayError \endlink
+ */
+ virtual DisplayError DisablePartialUpdateOneFrame() = 0;
+
+ /*! @brief Method to set the mode of the primary display.
+
+ @param[in] mode the new display mode.
+
+ @return \link DisplayError \endlink
+ */
+ virtual DisplayError SetDisplayMode(uint32_t mode) = 0;
+
+ /*! @brief Method to get the min and max refresh rate of a display.
+
+ @param[out] min and max refresh rate.
+
+ @return \link DisplayError \endlink
+ */
+ virtual DisplayError GetRefreshRateRange(uint32_t *min_refresh_rate,
+ uint32_t *max_refresh_rate) = 0;
+
+ /*! @brief Method to set the refresh rate of a display.
+
+ @param[in] new refresh rate of the display.
+
+ @return \link DisplayError \endlink
+ */
+ virtual DisplayError SetRefreshRate(uint32_t refresh_rate) = 0;
+
+ /*! @brief Method to query whether scanning is support for the HDMI display.
+
+ @return \link DisplayError \endlink
+ */
+ virtual bool IsUnderscanSupported() = 0;
+
+ /*! @brief Method to set brightness of the primary display.
+
+ @param[in] level the new backlight level.
+
+ @return \link DisplayError \endlink
+ */
+ virtual DisplayError SetPanelBrightness(int level) = 0;
+
+ /*! @brief Method to cache brightness of the primary display.
+
+ @param[in] level the new backlight level.
+
+ @return \link DisplayError \endlink
+ */
+ virtual DisplayError CachePanelBrightness(int level) = 0;
+
+ /*! @brief Method to notify display about change in min HDCP encryption level.
+
+ @param[in] min_enc_level minimum encryption level value.
+
+ @return \link DisplayError \endlink
+ */
+ virtual DisplayError OnMinHdcpEncryptionLevelChange(uint32_t min_enc_level) = 0;
+
+ /*! @brief Method to route display API requests to color service.
+
+ @param[in] in_payload \link PPDisplayAPIPayload \endlink
+ @param[out] out_payload \link PPDisplayPayload \endlink
+ @param[out] pending_action \link PPPendingParams \endlink
+
+ @return \link DisplayError \endlink
+ */
+ virtual DisplayError ColorSVCRequestRoute(const PPDisplayAPIPayload &in_payload,
+ PPDisplayAPIPayload *out_payload,
+ PPPendingParams *pending_action) = 0;
+
+ /*! @brief Method to request the number of color modes supported.
+
+ @param[out] mode_count Number of modes
+
+ @return \link DisplayError \endlink
+ */
+ virtual DisplayError GetColorModeCount(uint32_t *mode_count) = 0;
+
+ /*! @brief Method to request the information of supported color modes.
+
+ @param[inout] mode_count Number of updated modes
+ @param[out] vector of mode strings
+
+ @return \link DisplayError \endlink
+ */
+ virtual DisplayError GetColorModes(uint32_t *mode_count,
+ std::vector<std::string> *color_modes) = 0;
+
+ /*! @brief Method to request the attributes of color mode.
+
+ @param[in] mode name
+ @param[out] vector of mode attributes
+
+ @return \link DisplayError \endlink
+ */
+ virtual DisplayError GetColorModeAttr(const std::string &color_mode,
+ AttrVal *attr_map) = 0;
+
+ /*! @brief Method to set the color mode
+
+ @param[in] mode_name Mode name which needs to be set
+
+ @return \link DisplayError \endlink
+ */
+ virtual DisplayError SetColorMode(const std::string &color_mode) = 0;
+
+ /*! @brief Method to set the color transform
+
+ @param[in] length Mode name which needs to be set
+ @param[in] color_transform 4x4 Matrix for color transform
+
+ @return \link DisplayError \endlink
+ */
+ virtual DisplayError SetColorTransform(const uint32_t length, const double *color_transform) = 0;
+
+ /*! @brief Method to get the default color mode.
+
+ @param[out] default mode name
+
+ @return \link DisplayError \endlink
+ */
+ virtual DisplayError GetDefaultColorMode(std::string *color_mode) = 0;
+
+ /*! @brief Method to request applying default display mode.
+
+ @return \link DisplayError \endlink
+ */
+ virtual DisplayError ApplyDefaultDisplayMode() = 0;
+
+ /*! @brief Method to set the position of the hw cursor.
+
+ @param[in] x \link x position \endlink
+ @param[in] y \link y position \endlink
+
+ @return \link DisplayError \endlink
+ */
+ virtual DisplayError SetCursorPosition(int x, int y) = 0;
+
+ /*! @brief Method to get the brightness level of the display
+
+ @param[out] level brightness level
+
+ @return \link DisplayError \endlink
+ */
+ virtual DisplayError GetPanelBrightness(int *level) = 0;
+
+ /*! @brief Method to set layer mixer resolution.
+
+ @param[in] width layer mixer width
+ @param[in] height layer mixer height
+
+ @return \link DisplayError \endlink
+ */
+ virtual DisplayError SetMixerResolution(uint32_t width, uint32_t height) = 0;
+
+ /*! @brief Method to get layer mixer resolution.
+
+ @param[out] width layer mixer width
+ @param[out] height layer mixer height
+
+ @return \link DisplayError \endlink
+ */
+ virtual DisplayError GetMixerResolution(uint32_t *width, uint32_t *height) = 0;
+
+ /*! @brief Method to set frame buffer configuration.
+
+ @param[in] variable_info \link DisplayConfigVariableInfo \endlink
+
+ @return \link DisplayError \endlink
+ */
+ virtual DisplayError SetFrameBufferConfig(const DisplayConfigVariableInfo &variable_info) = 0;
+
+ /*! @brief Method to get frame buffer configuration.
+
+ @param[out] variable_info \link DisplayConfigVariableInfo \endlink
+
+ @return \link DisplayError \endlink
+ */
+ virtual DisplayError GetFrameBufferConfig(DisplayConfigVariableInfo *variable_info) = 0;
+
+ /*! @brief Method to set detail enhancement data.
+
+ @param[in] de_data \link DisplayDetailEnhancerData \endlink
+
+ @return \link DisplayError \endlink
+ */
+ virtual DisplayError SetDetailEnhancerData(const DisplayDetailEnhancerData &de_data) = 0;
+
+ /*! @brief Method to get display port information.
+
+ @param[out] port \link DisplayPort \endlink
+
+ @return \link DisplayError \endlink
+ */
+ virtual DisplayError GetDisplayPort(DisplayPort *port) = 0;
+
+ /*! @brief Method to query whether it is Primrary device.
+
+ @return true if this interface is primary.
+ */
+ virtual bool IsPrimaryDisplay() = 0;
+
+ /*! @brief Method to toggle composition types handling by SDM.
+
+ @details Client shall call this method to request SDM to enable/disable a specific type of
+ layer composition. If client disables a composition type, SDM will not handle any of the layer
+ composition using the disabled method in a draw cycle. On lack of resources to handle all
+ layers using other enabled composition methods, Prepare() will return an error.
+
+ Request to toggle composition type is applied from subsequent draw cycles.
+
+ Default state of all defined composition types is enabled.
+
+ @param[in] composition_type \link LayerComposition \endlink
+ @param[in] enable \link enable composition type \endlink
+
+ @return \link DisplayError \endlink
+
+ @sa Prepare
+ */
+ virtual DisplayError SetCompositionState(LayerComposition composition_type, bool enable) = 0;
+
+ /*! @brief Method to check whether a client target with the given properties
+ can be supported/handled by hardware.
+
+ @param[in] width client target width
+ @param[in] height client target height
+ @param[in] format client target format
+ @param[in] colorMetaData client target colorMetaData
+
+ @return \link DisplayError \endlink
+ */
+ virtual DisplayError GetClientTargetSupport(uint32_t width, uint32_t height,
+ LayerBufferFormat format,
+ const ColorMetaData &color_metadata) = 0;
+
+ /*
+ * Returns a string consisting of a dump of SDM's display and layer related state
+ * as programmed to driver
+ */
+ virtual std::string Dump() = 0;
+
+ protected:
+ virtual ~DisplayInterface() { }
+};
+
+} // namespace sdm
+
+#endif // __DISPLAY_INTERFACE_H__
+
diff --git a/msm8909/sdm/include/core/layer_buffer.h b/msm8909/sdm/include/core/layer_buffer.h
new file mode 100644
index 00000000..c86e0202
--- /dev/null
+++ b/msm8909/sdm/include/core/layer_buffer.h
@@ -0,0 +1,283 @@
+/*
+* Copyright (c) 2014, 2016-2017, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without modification, are permitted
+* provided that the following conditions are met:
+* * Redistributions of source code must retain the above copyright notice, this list of
+* conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright notice, this list of
+* conditions and the following disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its contributors may be used to
+* endorse or promote products derived from this software without specific prior written
+* permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*! @file layer_buffer.h
+ @brief File for layer buffer structure.
+
+*/
+#ifndef __LAYER_BUFFER_H__
+#define __LAYER_BUFFER_H__
+
+#include <stdint.h>
+#include <color_metadata.h>
+
+#include "sdm_types.h"
+
+namespace sdm {
+
+/*! @brief This enum represents display layer inverse gamma correction (IGC) types.
+
+ @sa Layer
+*/
+enum LayerIGC {
+ kIGCNotSpecified, //!< IGC is not specified.
+ kIGCsRGB, //!< sRGB IGC type.
+};
+
+/*! @brief This enum represents different buffer formats supported by display manager.
+
+ @sa LayerBuffer
+*/
+enum LayerBufferFormat {
+ /* All RGB formats, Any new format will be added towards end of this group to maintain backward
+ compatibility.
+ */
+ kFormatARGB8888, //!< 8-bits Alpha, Red, Green, Blue interleaved in ARGB order.
+ kFormatRGBA8888, //!< 8-bits Red, Green, Blue, Alpha interleaved in RGBA order.
+ kFormatBGRA8888, //!< 8-bits Blue, Green, Red, Alpha interleaved in BGRA order.
+ kFormatXRGB8888, //!< 8-bits Padding, Red, Green, Blue interleaved in XRGB order. No Alpha.
+ kFormatRGBX8888, //!< 8-bits Red, Green, Blue, Padding interleaved in RGBX order. No Alpha.
+ kFormatBGRX8888, //!< 8-bits Blue, Green, Red, Padding interleaved in BGRX order. No Alpha.
+ kFormatRGBA5551, //!< 5-bits Red, Green, Blue, and 1 bit Alpha interleaved in RGBA order.
+ kFormatRGBA4444, //!< 4-bits Red, Green, Blue, Alpha interleaved in RGBA order.
+ kFormatRGB888, //!< 8-bits Red, Green, Blue interleaved in RGB order. No Alpha.
+ kFormatBGR888, //!< 8-bits Blue, Green, Red interleaved in BGR order. No Alpha.
+ kFormatRGB565, //!< 5-bit Red, 6-bit Green, 5-bit Blue interleaved in RGB order. No Alpha.
+ kFormatBGR565, //!< 5-bit Blue, 6-bit Green, 5-bit Red interleaved in BGR order. No Alpha.
+ kFormatRGBA8888Ubwc, //!< UBWC aligned RGBA8888 format
+ kFormatRGBX8888Ubwc, //!< UBWC aligned RGBX8888 format
+ kFormatBGR565Ubwc, //!< UBWC aligned BGR565 format
+ kFormatRGBA1010102, //!< 10-bits Red, Green, Blue, Alpha interleaved in RGBA order.
+ kFormatARGB2101010, //!< 10-bits Alpha, Red, Green, Blue interleaved in ARGB order.
+ kFormatRGBX1010102, //!< 10-bits Red, Green, Blue, Padding interleaved in RGBX order. No Alpha.
+ kFormatXRGB2101010, //!< 10-bits Padding, Red, Green, Blue interleaved in XRGB order. No Alpha.
+ kFormatBGRA1010102, //!< 10-bits Blue, Green, Red, Alpha interleaved in BGRA order.
+ kFormatABGR2101010, //!< 10-bits Alpha, Blue, Green, Red interleaved in ABGR order.
+ kFormatBGRX1010102, //!< 10-bits Blue, Green, Red, Padding interleaved in BGRX order. No Alpha.
+ kFormatXBGR2101010, //!< 10-bits Padding, Blue, Green, Red interleaved in XBGR order. No Alpha.
+ kFormatRGBA1010102Ubwc, //!< UBWC aligned RGBA1010102 format
+ kFormatRGBX1010102Ubwc, //!< UBWC aligned RGBX1010102 format
+ kFormatRGB101010, // 10-bits Red, Green, Blue, interleaved in RGB order. No Alpha.
+
+ /* All YUV-Planar formats, Any new format will be added towards end of this group to maintain
+ backward compatibility.
+ */
+ kFormatYCbCr420Planar = 0x100, //!< Y-plane: y(0), y(1), y(2) ... y(n)
+ //!< 2x2 subsampled U-plane: u(0), u(2) ... u(n-1)
+ //!< 2x2 subsampled V-plane: v(0), v(2) ... v(n-1)
+
+ kFormatYCrCb420Planar, //!< Y-plane: y(0), y(1), y(2) ... y(n)
+ //!< 2x2 subsampled V-plane: v(0), v(2) ... v(n-1)
+ //!< 2x2 subsampled U-plane: u(0), u(2) ... u(n-1)
+
+ kFormatYCrCb420PlanarStride16, //!< kFormatYCrCb420Planar with stride aligned to 16 bytes
+
+ /* All YUV-Semiplanar formats, Any new format will be added towards end of this group to
+ maintain backward compatibility.
+ */
+ kFormatYCbCr420SemiPlanar = 0x200, //!< Y-plane: y(0), y(1), y(2) ... y(n)
+ //!< 2x2 subsampled interleaved UV-plane:
+ //!< u(0), v(0), u(2), v(2) ... u(n-1), v(n-1)
+ //!< aka NV12.
+
+ kFormatYCrCb420SemiPlanar, //!< Y-plane: y(0), y(1), y(2) ... y(n)
+ //!< 2x2 subsampled interleaved VU-plane:
+ //!< v(0), u(0), v(2), u(2) ... v(n-1), u(n-1)
+ //!< aka NV21.
+
+ kFormatYCbCr420SemiPlanarVenus, //!< Y-plane: y(0), y(1), y(2) ... y(n)
+ //!< 2x2 subsampled interleaved UV-plane:
+ //!< u(0), v(0), u(2), v(2) ... u(n-1), v(n-1)
+
+ kFormatYCbCr422H1V2SemiPlanar, //!< Y-plane: y(0), y(1), y(2) ... y(n)
+ //!< vertically subsampled interleaved UV-plane:
+ //!< u(0), v(1), u(2), v(3) ... u(n-1), v(n)
+
+ kFormatYCrCb422H1V2SemiPlanar, //!< Y-plane: y(0), y(1), y(2) ... y(n)
+ //!< vertically subsampled interleaved VU-plane:
+ //!< v(0), u(1), v(2), u(3) ... v(n-1), u(n)
+
+ kFormatYCbCr422H2V1SemiPlanar, //!< Y-plane: y(0), y(1), y(2) ... y(n)
+ //!< horizontally subsampled interleaved UV-plane:
+ //!< u(0), v(1), u(2), v(3) ... u(n-1), v(n)
+
+ kFormatYCrCb422H2V1SemiPlanar, //!< Y-plane: y(0), y(1), y(2) ... y(n)
+ //!< horizontally subsampled interleaved VU-plane:
+ //!< v(0), u(1), v(2), u(3) ... v(n-1), u(n)
+
+ kFormatYCbCr420SPVenusUbwc, //!< UBWC aligned YCbCr420SemiPlanarVenus format
+
+ kFormatYCrCb420SemiPlanarVenus, //!< Y-plane: y(0), y(1), y(2) ... y(n)
+ //!< 2x2 subsampled interleaved UV-plane:
+ //!< v(0), u(0), v(2), u(2) ... v(n-1), u(n-1)
+
+ kFormatYCbCr420P010, //!< 16 bit Y-plane with 5 MSB bits set to 0:
+ //!< y(0), y(1), y(2) ... y(n)
+ //!< 2x2 subsampled interleaved 10 bit UV-plane with
+ //!< 5 MSB bits set to 0:
+ //!< u(0), v(0), u(2), v(2) ... u(n-1), v(n-1)
+ //!< aka P010.
+
+ kFormatYCbCr420TP10Ubwc, //!< UBWC aligned YCbCr420TP10 format.
+
+ kFormatYCbCr420P010Ubwc, //!< UBWC aligned YCbCr420P010 format.
+
+ /* All YUV-Packed formats, Any new format will be added towards end of this group to maintain
+ backward compatibility.
+ */
+ kFormatYCbCr422H2V1Packed = 0x300, //!< Y-plane interleaved with horizontally subsampled U/V by
+ //!< factor of 2
+ //!< y(0), u(0), y(1), v(0), y(2), u(2), y(3), v(2)
+ //!< y(n-1), u(n-1), y(n), v(n-1)
+
+ kFormatCbYCrY422H2V1Packed,
+ kFormatInvalid = 0xFFFFFFFF,
+};
+
+
+/*! @brief This enum represents different types of 3D formats supported.
+
+ @sa LayerBufferS3DFormat
+*/
+enum LayerBufferS3DFormat {
+ kS3dFormatNone, //!< Layer buffer content is not 3D content.
+ kS3dFormatLeftRight, //!< Left and Right view of a 3D content stitched left and right.
+ kS3dFormatRightLeft, //!< Right and Left view of a 3D content stitched left and right.
+ kS3dFormatTopBottom, //!< Left and RightView of a 3D content stitched top and bottom.
+ kS3dFormatFramePacking //!< Left and right view of 3D content coded in consecutive frames.
+};
+
+/*! @brief This structure defines a color sample plane belonging to a buffer format. RGB buffer
+ formats have 1 plane whereas YUV buffer formats may have upto 4 planes.
+
+ @sa LayerBuffer
+*/
+struct LayerBufferPlane {
+ int fd = -1; //!< File descriptor referring to the buffer associated with this plane.
+ uint32_t offset = 0; //!< Offset of the plane in bytes from beginning of the buffer.
+ uint32_t stride = 0; //!< Stride in bytes i.e. length of a scanline including padding.
+};
+
+/*! @brief This structure defines flags associated with a layer buffer. The 1-bit flag can be set
+ to ON(1) or OFF(0).
+
+ @sa LayerBuffer
+*/
+struct LayerBufferFlags {
+ union {
+ struct {
+ uint32_t secure : 1; //!< This flag shall be set by client to indicate that the
+ //!< buffer need to be handled securely.
+
+ uint32_t video : 1; //!< This flag shall be set by client to indicate that the
+ //!< buffer is video/ui buffer.
+
+ uint32_t macro_tile : 1; //!< This flag shall be set by client to indicate that the
+ //!< buffer format is macro tiled.
+
+ uint32_t interlace : 1; //!< This flag shall be set by the client to indicate that
+ //!< the buffer has interlaced content.
+
+ uint32_t secure_display : 1; //!< This flag shall be set by the client to indicate that the
+ //!< secure display session is in progress. Secure display
+ //!< session can not coexist with non-secure session.
+
+ uint32_t secure_camera : 1; //!< This flag shall be set by the client to indicate that the
+ //!< buffer is associated with secure camera session. A secure
+ //!< camera layer can co-exist with non-secure layer(s).
+
+ uint32_t hdr : 1; //!< This flag shall be set by the client to indicate that the
+ //!< the content is HDR.
+ };
+
+ uint32_t flags = 0; //!< For initialization purpose only.
+ //!< Client shall not refer to it directly.
+ };
+};
+
+/*! @brief This structure defines a layer buffer handle which contains raw buffer and its associated
+ properties.
+
+ @sa LayerBuffer
+ @sa LayerStack
+*/
+struct LayerBuffer {
+ uint32_t width = 0; //!< Aligned width of the Layer that this buffer is for.
+ uint32_t height = 0; //!< Aligned height of the Layer that this buffer is for.
+ uint32_t unaligned_width = 0;
+ //!< Unaligned width of the Layer that this buffer is for.
+ uint32_t unaligned_height = 0;
+ //!< Unaligned height of the Layer that this buffer is for.
+ uint32_t size = 0; //!< Size of a single buffer (even if multiple clubbed together)
+ LayerBufferFormat format = kFormatRGBA8888; //!< Format of the buffer content.
+ ColorMetaData color_metadata = {}; //!< CSC + Range + Transfer + Matrix + HDR Info
+ LayerIGC igc = kIGCNotSpecified; //!< IGC that will be applied on this layer.
+ LayerBufferPlane planes[4] = {};
+ //!< Array of planes that this buffer contains. RGB buffer formats
+ //!< have 1 plane whereas YUV buffer formats may have upto 4 planes
+ //!< Total number of planes for the buffer will be interpreted based
+ //!< on the buffer format specified.
+
+ int acquire_fence_fd = -1; //!< File descriptor referring to a sync fence object which will be
+ //!< signaled when buffer can be read/write by display manager.
+ //!< This fence object is set by the client during Commit(). For
+ //!< input buffers client shall signal this fence when buffer
+ //!< content is available and can be read by display manager. For
+ //!< output buffers, client shall signal fence when buffer is ready
+ //!< to be written by display manager.
+
+ //!< This field is used only during Commit() and shall be set to -1
+ //!< by the client when buffer is already available for read/write.
+
+ int release_fence_fd = -1; //!< File descriptor referring to a sync fence object which will be
+ //!< signaled when buffer has been read/written by display manager.
+ //!< This fence object is set by display manager during Commit().
+ //!< For input buffers display manager will signal this fence when
+ //!< buffer has been consumed. For output buffers, display manager
+ //!< will signal this fence when buffer is produced.
+
+ //!< This field is used only during Commit() and will be set to -1
+ //!< by display manager when buffer is already available for
+ //!< read/write.
+
+ LayerBufferFlags flags; //!< Flags associated with this buffer.
+
+ LayerBufferS3DFormat s3d_format = kS3dFormatNone;
+ //!< Represents the format of the buffer content in 3D. This field
+ //!< could be modified by both client and SDM.
+ uint64_t buffer_id __attribute__((aligned(8))) = 0;
+ //!< Specifies the buffer id.
+};
+
+// This enum represents buffer layout types.
+enum BufferLayout {
+ kLinear, //!< Linear data
+ kUBWC, //!< UBWC aligned data
+ kTPTiled //!< Tightly Packed data
+};
+
+} // namespace sdm
+
+#endif // __LAYER_BUFFER_H__
+
diff --git a/msm8909/sdm/include/core/layer_stack.h b/msm8909/sdm/include/core/layer_stack.h
new file mode 100644
index 00000000..f12e5c17
--- /dev/null
+++ b/msm8909/sdm/include/core/layer_stack.h
@@ -0,0 +1,392 @@
+/*
+* Copyright (c) 2014 - 2017, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without modification, are permitted
+* provided that the following conditions are met:
+* * Redistributions of source code must retain the above copyright notice, this list of
+* conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright notice, this list of
+* conditions and the following disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its contributors may be used to
+* endorse or promote products derived from this software without specific prior written
+* permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*! @file layer_stack.h
+ @brief File for display layer stack structure which represents a drawing buffer.
+
+ @details Display layer is a drawing buffer object which will be blended with other drawing buffers
+ under blending rules.
+*/
+#ifndef __LAYER_STACK_H__
+#define __LAYER_STACK_H__
+
+#include <stdint.h>
+#include <utils/constants.h>
+
+#include <vector>
+
+#include "layer_buffer.h"
+#include "sdm_types.h"
+
+namespace sdm {
+
+/*! @brief This enum represents display layer blending types.
+
+ @sa Layer
+*/
+enum LayerBlending {
+ kBlendingPremultiplied, //!< Pixel color is expressed using premultiplied alpha in RGBA tuples.
+ //!< If plane alpha is less than 0xFF, apply modulation as well.
+ //!< pixel.rgb = src.rgb + dest.rgb x (1 - src.a)
+
+ kBlendingOpaque, //!< Pixel color is expressed using straight alpha in color tuples. It
+ //!< is constant blend operation. The layer would appear opaque if plane
+ //!< alpha is 0xFF.
+
+ kBlendingCoverage, //!< Pixel color is expressed using straight alpha in color tuples. If
+ //!< plane alpha is less than 0xff, apply modulation as well.
+ //!< pixel.rgb = src.rgb x src.a + dest.rgb x (1 - src.a)
+};
+
+/*! @brief This enum represents display layer composition types.
+
+ @sa Layer
+*/
+enum LayerComposition {
+ /* ==== List of composition types set by SDM === */
+ /* These composition types represent SDM composition decision for the layers which need to
+ be blended. Composition types are set during Prepare() by SDM.
+ Client can set default composition type to any of the below before calling into Prepare(),
+ however client's input value is ignored and does not play any role in composition decision.
+ */
+ kCompositionGPU, //!< This layer will be drawn onto the target buffer by GPU. Display
+ //!< device will mark the layer for GPU composition if it can not
+ //!< handle composition for it.
+ //!< This composition type is used only if GPUTarget layer is provided
+ //!< in a composition cycle.
+
+ kCompositionGPUS3D, //!< This layer will be drawn onto the target buffer in s3d mode by GPU.
+ //!< Display device will mark the layer for GPU composition if it can
+ //!< not handle composition for it.
+ //!< This composition type is used only if GPUTarget layer is provided
+ //!< in a composition cycle.
+
+ kCompositionSDE, //!< This layer will be composed by SDE. It must not be composed by
+ //!< GPU or Blit.
+
+ kCompositionHWCursor, //!< This layer will be composed by SDE using HW Cursor. It must not be
+ //!< composed by GPU or Blit.
+
+ kCompositionHybrid, //!< This layer will be drawn by a blit engine and SDE together.
+ //!< Display device will split the layer, update the blit rectangle
+ //!< that need to be composed by a blit engine and update original
+ //!< source rectangle that will be composed by SDE.
+ //!< This composition type is used only if GPUTarget and BlitTarget
+ //!< layers are provided in a composition cycle.
+
+ kCompositionBlit, //!< This layer will be composed using Blit Engine.
+ //!< This composition type is used only if BlitTarget layer is provided
+ //!< in a composition cycle.
+
+ /* === List of composition types set by Client === */
+ /* These composition types represent target buffer layers onto which GPU or Blit will draw if SDM
+ decide to have some or all layers drawn by respective composition engine.
+ Client must provide a target buffer layer, if respective composition type is not disabled by
+ an explicit call to SetCompositionState() method. If a composition type is not disabled,
+ providing a target buffer layer is optional. If SDM is unable to handle layers without support
+ of such a composition engine, Prepare() call will return failure.
+ */
+ kCompositionGPUTarget, //!< This layer will hold result of composition for layers marked for
+ //!< GPU composition.
+ //!< If display device does not set any layer for GPU composition then
+ //!< this layer would be ignored. Else, this layer will be composed
+ //!< with other layers marked for SDE composition by SDE.
+ //!< Only one layer shall be marked as target buffer by the caller.
+ //!< GPU target layer shall be placed after all application layers
+ //!< in the layer stack.
+
+ kCompositionBlitTarget, //!< This layer will hold result of composition for blit rectangles
+ //!< from the layers marked for hybrid composition. Nth blit rectangle
+ //!< in a layer shall be composed onto Nth blit target.
+ //!< If display device does not set any layer for hybrid composition
+ //!< then this would be ignored.
+ //!< Blit target layers shall be placed after GPUTarget in the layer
+ //!< stack.
+};
+
+/*! @brief This structure defines rotation and flip values for a display layer.
+
+ @sa Layer
+*/
+struct LayerTransform {
+ float rotation = 0.0f; //!< Left most pixel coordinate.
+ bool flip_horizontal = false; //!< Mirror reversal of the layer across a horizontal axis.
+ bool flip_vertical = false; //!< Mirror reversal of the layer across a vertical axis.
+
+ bool operator==(const LayerTransform& transform) const {
+ return (rotation == transform.rotation && flip_horizontal == transform.flip_horizontal &&
+ flip_vertical == transform.flip_vertical);
+ }
+
+ bool operator!=(const LayerTransform& transform) const {
+ return !operator==(transform);
+ }
+};
+
+/*! @brief This structure defines flags associated with a layer. The 1-bit flag can be set to ON(1)
+ or OFF(0).
+
+ @sa LayerBuffer
+*/
+struct LayerFlags {
+ union {
+ struct {
+ uint32_t skip : 1; //!< This flag shall be set by client to indicate that this layer
+ //!< will be handled by GPU. Display Device will not consider it
+ //!< for composition.
+
+ uint32_t updating : 1; //!< This flag shall be set by client to indicate that this is
+ //!< updating non-updating. so strategy manager will mark them for
+ //!< SDE/GPU composition respectively when the layer stack qualifies
+ //!< for cache based composition.
+
+ uint32_t solid_fill : 1;
+ //!< This flag shall be set by client to indicate that this layer
+ //!< is for solid fill without input buffer. Display Device will
+ //!< use SDE HW feature to achieve it.
+
+ uint32_t cursor : 1; //!< This flag shall be set by client to indicate that this layer
+ //!< is a cursor
+ //!< Display Device may handle this layer using HWCursor
+
+ uint32_t single_buffer : 1; //!< This flag shall be set by client to indicate that the layer
+ //!< uses only a single buffer that will not be swapped out
+ };
+
+ uint32_t flags = 0; //!< For initialization purpose only.
+ //!< Client shall not refer it directly.
+ };
+};
+
+/*! @brief This structure defines flags associated with the layer requests. The 1-bit flag can be
+ set to ON(1) or OFF(0).
+
+ @sa Layer
+*/
+struct LayerRequestFlags {
+ union {
+ struct {
+ uint32_t tone_map : 1; //!< This flag will be set by SDM when the layer needs tone map
+ uint32_t secure: 1; //!< This flag will be set by SDM when the layer must be secure
+ uint32_t flip_buffer: 1; //!< This flag will be set by SDM when the layer needs FBT flip
+ };
+ uint32_t request_flags = 0; //!< For initialization purpose only.
+ //!< Shall not be refered directly.
+ };
+};
+
+/*! @brief This structure defines LayerRequest.
+ Includes width/height/format of the LayerRequest.
+
+ SDM shall set the properties of LayerRequest to be used by the client
+
+ @sa LayerRequest
+*/
+struct LayerRequest {
+ LayerRequestFlags flags; // Flags associated with this request
+ LayerBufferFormat format = kFormatRGBA8888; // Requested format
+ uint32_t width = 0; // Requested unaligned width.
+ uint32_t height = 0; // Requested unalighed height
+};
+
+/*! @brief This structure defines flags associated with a layer stack. The 1-bit flag can be set to
+ ON(1) or OFF(0).
+
+ @sa LayerBuffer
+*/
+struct LayerStackFlags {
+ union {
+ struct {
+ uint32_t geometry_changed : 1; //!< This flag shall be set by client to indicate that the
+ //!< layer set passed to Prepare() has changed by more than
+ //!< just the buffer handles and acquire fences.
+
+ uint32_t skip_present : 1; //!< This flag will be set to true, if the current layer
+ //!< stack contains skip layers.
+
+ uint32_t video_present : 1; //!< This flag will be set to true, if current layer stack
+ //!< contains video.
+
+ uint32_t secure_present : 1; //!< This flag will be set to true, if the current layer
+ //!< stack contains secure layers.
+
+ uint32_t animating : 1; //!< This flag shall be set by client to indicate that the
+ //!< current frame is animating.i
+
+ uint32_t attributes_changed : 1;
+ //!< This flag shall be set by client to indicate that the
+ //!< current frame has some properties changed and
+ //!< needs re-config.
+
+ uint32_t cursor_present : 1; //!< This flag will be set to true if the current layer
+ //!< stack contains cursor layer.
+
+ uint32_t single_buffered_layer_present : 1; //!< Set if stack has single buffered layer
+
+ uint32_t s3d_mode_present : 1; //!< This flag will be set to true, if the current layer
+ //!< stack contains s3d layer, and the layer stack can enter
+ //!< s3d mode.
+
+ uint32_t post_processed_output : 1; // If output_buffer should contain post processed output
+ // This applies only to primary displays currently
+
+ uint32_t hdr_present : 1; //!< Set if stack has HDR content
+ };
+
+ uint32_t flags = 0; //!< For initialization purpose only.
+ //!< Client shall not refer it directly.
+ };
+};
+
+/*! @brief This structure defines a rectanglular area inside a display layer.
+
+ @sa LayerRectArray
+*/
+struct LayerRect {
+ float left = 0.0f; //!< Left-most pixel coordinate.
+ float top = 0.0f; //!< Top-most pixel coordinate.
+ float right = 0.0f; //!< Right-most pixel coordinate.
+ float bottom = 0.0f; //!< Bottom-most pixel coordinate.
+
+ LayerRect() = default;
+
+ LayerRect(float l, float t, float r, float b) : left(l), top(t), right(r), bottom(b) { }
+
+ bool operator==(const LayerRect& rect) const {
+ return left == rect.left && right == rect.right && top == rect.top && bottom == rect.bottom;
+ }
+
+ bool operator!=(const LayerRect& rect) const {
+ return !operator==(rect);
+ }
+};
+
+/*! @brief This structure defines an array of display layer rectangles.
+
+ @sa LayerRect
+*/
+struct LayerRectArray {
+ LayerRect *rect = NULL; //!< Pointer to first element of array.
+ uint32_t count = 0; //!< Number of elements in the array.
+};
+
+/*! @brief This structure defines display layer object which contains layer properties and a drawing
+ buffer.
+
+ @sa LayerArray
+*/
+struct Layer {
+ LayerBuffer input_buffer = {}; //!< Buffer to be composed.
+ //!< If this remains unchanged between two
+ //!< consecutive Prepare() calls and
+ //!< geometry_changed flag is not set for the
+ //!< second call, then the display device will
+ //!< assume that buffer content has not
+ //!< changed.
+
+ LayerComposition composition = kCompositionGPU; //!< Composition type which can be set by either
+ //!< the client or the display device. This value
+ //!< should be preserved between Prepare() and
+ //!< Commit() calls.
+
+ LayerRect src_rect = {}; //!< Rectangular area of the layer buffer to
+ //!< consider for composition.
+
+ LayerRect dst_rect = {}; //!< The target position where the frame will be
+ //!< displayed. Cropping rectangle is scaled to
+ //!< fit into this rectangle. The origin is the
+ //!< top-left corner of the screen.
+
+ std::vector<LayerRect> visible_regions = {}; //!< Visible rectangular areas in screen space.
+ //!< The visible region includes areas overlapped
+ //!< by a translucent layer.
+
+ std::vector<LayerRect> dirty_regions = {}; //!< Rectangular areas in the current frames
+ //!< that have changed in comparison to
+ //!< previous frame.
+
+ std::vector<LayerRect> blit_regions = {}; //!< Rectangular areas of this layer which need
+ //!< to be composed to blit target. Display
+ //!< device will update blit rectangles if a
+ //!< layer composition is set as hybrid. Nth blit
+ //!< rectangle shall be composed onto Nth blit
+ //!< target.
+
+ LayerBlending blending = kBlendingPremultiplied; //!< Blending operation which need to be
+ //!< applied on the layer buffer during
+ //!< composition.
+
+ LayerTransform transform = {}; //!< Rotation/Flip operations which need to be
+ //!< applied to the layer buffer during
+ //!< composition.
+
+ uint8_t plane_alpha = 0xff; //!< Alpha value applied to the whole layer.
+ //!< Value of each pixel is computed as:
+ //!< if(kBlendingPremultiplied) {
+ //!< pixel.RGB = pixel.RGB * planeAlpha/255
+ //!< }
+ //!< pixel.a = pixel.a * planeAlpha
+
+ uint32_t frame_rate = 0; //!< Rate at which frames are being updated for
+ //!< this layer.
+
+ uint32_t solid_fill_color = 0; //!< Solid color used to fill the layer when
+ //!< no content is associated with the layer.
+
+ LayerFlags flags; //!< Flags associated with this layer.
+
+ LayerRequest request = {}; //!< o/p - request on this Layer by SDM.
+
+ Lut3d lut_3d = {}; //!< o/p - Populated by SDM when tone mapping is
+ //!< needed on this layer.
+};
+
+/*! @brief This structure defines a layer stack that contains layers which need to be composed and
+ rendered onto the target.
+
+ @sa DisplayInterface::Prepare
+ @sa DisplayInterface::Commit
+*/
+struct LayerStack {
+ std::vector<Layer *> layers = {}; //!< Vector of layer pointers.
+
+ int retire_fence_fd = -1; //!< File descriptor referring to a sync fence object which
+ //!< will be signaled when this composited frame has been
+ //!< replaced on screen by a subsequent frame on a physical
+ //!< display. The fence object is created and returned during
+ //!< Commit(). Client shall close the returned file
+ //!< descriptor.
+ //!< NOTE: This field applies to a physical display only.
+
+ LayerBuffer *output_buffer = NULL; //!< Pointer to the buffer where composed buffer would be
+ //!< rendered for virtual displays.
+ //!< NOTE: This field applies to a virtual display only.
+
+ LayerStackFlags flags; //!< Flags associated with this layer set.
+};
+
+} // namespace sdm
+
+#endif // __LAYER_STACK_H__
+
diff --git a/msm8909/sdm/include/core/sdm_types.h b/msm8909/sdm/include/core/sdm_types.h
new file mode 100644
index 00000000..f8bb4e39
--- /dev/null
+++ b/msm8909/sdm/include/core/sdm_types.h
@@ -0,0 +1,75 @@
+/*
+* Copyright (c) 2014 - 2017, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*! @file sdm_types.h
+ @brief This file contains miscellaneous data types used across display interfaces.
+*/
+#ifndef __SDM_TYPES_H__
+#define __SDM_TYPES_H__
+
+namespace sdm {
+
+/*! @brief This enum represents different error codes that display interfaces may return.
+*/
+enum DisplayError {
+ kErrorNone, //!< Call executed successfully.
+ kErrorUndefined, //!< An unspecified error has occured.
+ kErrorNotSupported, //!< Requested operation is not supported.
+ kErrorPermission, //!< Operation is not permitted in current state.
+ kErrorVersion, //!< Client is using advanced version of interfaces and calling into an
+ //!< older version of display library.
+ kErrorDataAlignment, //!< Client data structures are not aligned on naturual boundaries.
+ kErrorInstructionSet, //!< 32-bit client is calling into 64-bit library or vice versa.
+ kErrorParameters, //!< Invalid parameters passed to a method.
+ kErrorFileDescriptor, //!< Invalid file descriptor.
+ kErrorMemory, //!< System is running low on memory.
+ kErrorResources, //!< Not enough hardware resources available to execute call.
+ kErrorHardware, //!< A hardware error has occured.
+ kErrorTimeOut, //!< The operation has timed out to prevent client from waiting forever.
+ kErrorShutDown, //!< Driver is processing shutdown sequence
+ kErrorPerfValidation, //!< Bandwidth or Clock requirement validation failure.
+ kErrorNoAppLayers, //!< No App layer(s) in the draw cycle.
+ kErrorNotValidated, //!< Draw cycle has not been validated.
+};
+
+/*! @brief This structure is defined for client and library compatibility check purpose only. This
+ structure is used in SDM_VERSION_TAG definition only. Client should not refer it directly for
+ any purpose.
+*/
+struct SDMCompatibility {
+ char c1;
+ int i1;
+ char c2;
+ int i2;
+};
+
+} // namespace sdm
+
+#endif // __SDM_TYPES_H__
+
diff --git a/msm8909/sdm/include/core/socket_handler.h b/msm8909/sdm/include/core/socket_handler.h
new file mode 100644
index 00000000..e7fe00e4
--- /dev/null
+++ b/msm8909/sdm/include/core/socket_handler.h
@@ -0,0 +1,75 @@
+/*
+* Copyright (c) 2016, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*! @file socket_handler.h
+ @brief Interface file for platform specific Socket Handler.
+
+ @details SDM will use this interface to get the platform specific Socket fd.
+*/
+
+#ifndef __SOCKET_HANDLER_H__
+#define __SOCKET_HANDLER_H__
+
+namespace sdm {
+
+/*! @brief This enum represents Socket types, for which SDM can request the fd.
+
+*/
+enum SocketType {
+ kDpps, //!< Socket for Dpps
+};
+
+/*! @brief Socket handler implemented by the client
+
+ @details This class declares prototype for SocketHandler methods which must be
+ implemented by client. SDM will use these methods to get the platform specific Socket fd.
+
+ @sa CoreInterface::CreateCore
+*/
+class SocketHandler {
+ public:
+ /*! @brief Method to get the platform specific Socket fd for a given socket type.
+
+ @details This method returns the platform specific Socket fd for a given socket type.
+ It is the responsibility of the caller to close the file descriptor.
+
+ @param[in] socket_type
+
+ @return \link int \endlink
+ */
+
+ virtual int GetSocketFd(SocketType socket_type) = 0;
+
+ protected:
+ virtual ~SocketHandler() { }
+};
+
+} // namespace sdm
+
+#endif // __SOCKET_HANDLER_H__
diff --git a/msm8909/sdm/include/private/color_interface.h b/msm8909/sdm/include/private/color_interface.h
new file mode 100644
index 00000000..94be13d3
--- /dev/null
+++ b/msm8909/sdm/include/private/color_interface.h
@@ -0,0 +1,88 @@
+/* Copyright (c) 2015-2017, The Linux Foundataion. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+*/
+
+#ifndef __COLOR_INTERFACE_H__
+#define __COLOR_INTERFACE_H__
+
+#include "core/sdm_types.h"
+#include "color_params.h"
+
+namespace sdm {
+
+#define COLORMGR_LIBRARY_NAME "libsdm-color.so"
+#define CREATE_COLOR_INTERFACE_NAME "CreateColorInterface"
+#define DESTROY_COLOR_INTERFACE_NAME "DestroyColorInterface"
+#define COLOR_REVISION_MAJOR (1)
+#define COLOR_REVISION_MINOR (0)
+
+#define COLOR_VERSION_TAG ((uint16_t)((COLOR_REVISION_MAJOR << 8) | COLOR_REVISION_MINOR))
+
+class ColorInterface;
+
+typedef DisplayError (*CreateColorInterface)(uint16_t version, DisplayType type,
+ const PPHWAttributes &attributes,
+ ColorInterface **interface);
+
+typedef DisplayError (*DestroyColorInterface)(DisplayType type);
+
+class ColorInterface {
+ public:
+ virtual DisplayError ColorSVCRequestRoute(const PPDisplayAPIPayload &in_payload,
+ PPDisplayAPIPayload *out_payload,
+ PPFeaturesConfig *out_features,
+ PPPendingParams *pending_action) = 0;
+
+ virtual DisplayError ApplyDefaultDisplayMode(PPFeaturesConfig *out_features) = 0;
+
+ virtual DisplayError ColorIntfSetColorTransform(PPFeaturesConfig *out_features,
+ uint32_t disp_id, uint32_t length,
+ const double *trans_data) = 0;
+
+ virtual DisplayError ColorIntfSetDisplayMode(PPFeaturesConfig *out_features,
+ uint32_t disp_id, int32_t mode_id) = 0;
+
+ virtual DisplayError ColorIntfGetNumDisplayModes(PPFeaturesConfig *out_features,
+ uint32_t disp_id, uint32_t *mode_cnt) = 0;
+
+ virtual DisplayError ColorIntfEnumerateDisplayModes(PPFeaturesConfig *out_features,
+ uint32_t disp_id, SDEDisplayMode *modes,
+ uint32_t *mode_cnt) = 0;
+ virtual DisplayError ColorIntfGetModeInfo(PPFeaturesConfig *out_features,
+ uint32_t disp_id, int32_t mode_id,
+ AttrVal *query) = 0;
+ virtual DisplayError ColorIntfGetDefaultModeID(PPFeaturesConfig *out_features,
+ uint32_t disp_id, int32_t *mode_id) = 0;
+
+ protected:
+ virtual ~ColorInterface() {}
+};
+
+} // namespace sdm
+
+#endif // __COLOR_INTERFACE_H__
diff --git a/msm8909/sdm/include/private/color_params.h b/msm8909/sdm/include/private/color_params.h
new file mode 100644
index 00000000..897b2347
--- /dev/null
+++ b/msm8909/sdm/include/private/color_params.h
@@ -0,0 +1,636 @@
+/* Copyright (c) 2015-2017, The Linux Foundataion. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+*/
+
+#ifndef __COLOR_PARAMS_H__
+#define __COLOR_PARAMS_H__
+
+#include <stdio.h>
+#include <string.h>
+#include <utils/locker.h>
+#include <utils/constants.h>
+#include <core/sdm_types.h>
+#include <core/display_interface.h>
+
+#include <utility>
+#include <string>
+#include <vector>
+
+#include "hw_info_types.h"
+
+namespace sdm {
+
+typedef std::vector<std::pair<std::string, std::string>> AttrVal;
+
+// Bitmap Pending action to indicate to the caller what's pending to be taken care of.
+enum PendingAction {
+ kInvalidating = BITMAP(0),
+ kApplySolidFill = BITMAP(1),
+ kDisableSolidFill = BITMAP(2),
+ kEnterQDCMMode = BITMAP(3),
+ kExitQDCMMode = BITMAP(4),
+ kSetPanelBrightness = BITMAP(5),
+ kEnableFrameCapture = BITMAP(6),
+ kDisableFrameCapture = BITMAP(7),
+ kConfigureDetailedEnhancer = BITMAP(8),
+ kInvalidatingAndkSetPanelBrightness = BITMAP(9),
+ kModeSet = BITMAP(10),
+ kGetDetailedEnhancerData = BITMAP(21),
+ kNoAction = BITMAP(31),
+};
+
+static const uint32_t kOpsEnable = BITMAP(0);
+static const uint32_t kOpsRead = BITMAP(1);
+static const uint32_t kOpsWrite = BITMAP(2);
+static const uint32_t kOpsDisable = BITMAP(3);
+
+static const uint32_t kOpsGc8BitRoundEnable = BITMAP(4);
+
+static const uint32_t kPaHueEnable = BITMAP(4);
+static const uint32_t kPaSatEnable = BITMAP(5);
+static const uint32_t kPaValEnable = BITMAP(6);
+static const uint32_t kPaContEnable = BITMAP(7);
+
+static const uint32_t kPaSixZoneEnable = BITMAP(8);
+static const uint32_t kPaSkinEnable = BITMAP(9);
+static const uint32_t kPaSkyEnable = BITMAP(10);
+static const uint32_t kPaFoliageEnable = BITMAP(11);
+
+static const uint32_t kLeftSplitMode = BITMAP(28); // 0x10000000
+static const uint32_t kRightSplitMode = BITMAP(29); // 0x20000000
+
+static const int32_t kInvalidModeId = -1;
+
+static const std::string kDynamicRangeAttribute = "DynamicRange";
+static const std::string kColorGamutAttribute = "ColorGamut";
+static const std::string kPictureQualityAttribute = "PictureQuality";
+
+static const std::string kHdr = "hdr";
+static const std::string kSdr = "sdr";
+
+static const std::string kNative = "native";
+static const std::string kDcip3 = "dcip3";
+static const std::string kSrgb = "srgb";
+static const std::string kDisplayP3 = "display_p3";
+
+static const std::string kVivid = "vivid";
+static const std::string kSharp = "sharp";
+static const std::string kStandard = "standard";
+
+// Enum to identify type of dynamic range of color mode.
+enum DynamicRangeType {
+ kSdrType,
+ kHdrType,
+};
+
+// ENUM to identify different Postprocessing feature block to program.
+// Note: For each new entry added here, also need update hw_interface::GetPPFeaturesVersion<>
+// AND HWPrimary::SetPPFeatures<>.
+enum PPGlobalColorFeatureID {
+ kGlobalColorFeaturePcc,
+ kGlobalColorFeatureIgc,
+ kGlobalColorFeaturePgc,
+ kMixerColorFeatureGc,
+ kGlobalColorFeaturePaV2,
+ kGlobalColorFeatureDither,
+ kGlobalColorFeatureGamut,
+ kGlobalColorFeaturePADither,
+ kGlobalColorFeatureCsc,
+ kMaxNumPPFeatures,
+};
+
+struct PPPendingParams {
+ int32_t action = kNoAction;
+ void *params = NULL;
+};
+
+struct PPColorInfo {
+ uint32_t r_bitdepth = 0;
+ uint32_t r = 0;
+ uint32_t g_bitdepth = 0;
+ uint32_t g = 0;
+ uint32_t b_bitdepth = 0;
+ uint32_t b = 0;
+};
+
+struct PPColorFillParams {
+ uint32_t flags = 0;
+ struct {
+ uint32_t width = 0;
+ uint32_t height = 0;
+ int32_t x = 0;
+ int32_t y = 0;
+ } rect;
+
+ PPColorInfo color;
+};
+
+struct PPFeatureVersion {
+ // SDE ASIC versioning its PP block at each specific feature level.
+ static const uint32_t kSDEPpVersionInvalid = 0;
+ static const uint32_t kSDEIgcV17 = 1;
+ static const uint32_t kSDEPgcV17 = 5;
+ static const uint32_t kSDEDitherV17 = 7;
+ static const uint32_t kSDEGamutV17 = 9;
+ static const uint32_t kSDEPaV17 = 11;
+ static const uint32_t kSDEPccV17 = 13;
+ static const uint32_t kSDELegacyPP = 15;
+ static const uint32_t kSDEPADitherV17 = 16;
+ static const uint32_t kSDEIgcV30 = 17;
+ static const uint32_t kSDEGamutV4 = 18;
+
+ uint32_t version[kMaxNumPPFeatures];
+ PPFeatureVersion() { memset(version, 0, sizeof(version)); }
+};
+
+struct PPHWAttributes : HWResourceInfo, HWPanelInfo, DisplayConfigVariableInfo {
+ char panel_name[256] = "generic_panel";
+ PPFeatureVersion version;
+ int panel_max_brightness = 0;
+
+ void Set(const HWResourceInfo &hw_res, const HWPanelInfo &panel_info,
+ const DisplayConfigVariableInfo &attr, const PPFeatureVersion &feature_ver);
+};
+
+struct PPDisplayAPIPayload {
+ bool own_payload = false; // to indicate if *payload is owned by this or just a reference.
+ uint32_t size = 0;
+ uint8_t *payload = NULL;
+
+ PPDisplayAPIPayload() = default;
+ PPDisplayAPIPayload(uint32_t size, uint8_t *param)
+ : size(size), payload(param) {}
+
+ template <typename T>
+ DisplayError CreatePayload(T *&output) {
+ DisplayError ret = kErrorNone;
+
+ payload = new uint8_t[sizeof(T)]();
+ if (!payload) {
+ ret = kErrorMemory;
+ output = NULL;
+ } else {
+ this->size = sizeof(T);
+ output = reinterpret_cast<T *>(payload);
+ own_payload = true;
+ }
+ return ret;
+ }
+
+ DisplayError CreatePayloadBytes(uint32_t size_in_bytes, uint8_t **output) {
+ DisplayError ret = kErrorNone;
+
+ payload = new uint8_t[size_in_bytes]();
+ if (!payload) {
+ ret = kErrorMemory;
+ *output = NULL;
+ } else {
+ this->size = size_in_bytes;
+ *output = payload;
+ own_payload = true;
+ }
+ return ret;
+ }
+
+ inline void DestroyPayload() {
+ if (payload && own_payload) {
+ delete[] payload;
+ payload = NULL;
+ size = 0;
+ } else {
+ payload = NULL;
+ size = 0;
+ }
+ }
+};
+
+struct PPRectInfo {
+ uint32_t width;
+ uint32_t height;
+ int32_t x;
+ int32_t y;
+};
+
+typedef enum {
+ PP_PIXEL_FORMAT_NONE = 0,
+ PP_PIXEL_FORMAT_RGB_888,
+ PP_PIXEL_FORMAT_RGB_2101010,
+ PP_PIXEL_FORMAT_MAX,
+ PP_PIXEL_FORMAT_FORCE32BIT = 0x7FFFFFFF,
+} PPPixelFormats;
+
+struct PPFrameCaptureInputParams {
+ PPRectInfo rect;
+ PPPixelFormats out_pix_format;
+ uint32_t flags;
+};
+
+struct PPFrameCaptureData {
+ PPFrameCaptureInputParams input_params;
+ uint8_t *buffer;
+ uint32_t buffer_stride;
+ uint32_t buffer_size;
+};
+
+static const uint32_t kDeTuningFlagSharpFactor = 0x01;
+static const uint32_t kDeTuningFlagClip = 0x02;
+static const uint32_t kDeTuningFlagThrQuiet = 0x04;
+static const uint32_t kDeTuningFlagThrDieout = 0x08;
+static const uint32_t kDeTuningFlagThrLow = 0x10;
+static const uint32_t kDeTuningFlagThrHigh = 0x20;
+static const uint32_t kDeTuningFlagContentQualLevel = 0x40;
+
+typedef enum {
+ kDeContentQualUnknown,
+ kDeContentQualLow,
+ kDeContentQualMedium,
+ kDeContentQualHigh,
+ kDeContentQualMax,
+} PPDEContentQualLevel;
+
+typedef enum {
+ kDeContentTypeUnknown,
+ kDeContentTypeVideo,
+ kDeContentTypeGraphics,
+ kDeContentTypeMax,
+} PPDEContentType;
+
+struct PPDETuningCfg {
+ uint32_t flags = 0;
+ int32_t sharp_factor = 0;
+ uint16_t thr_quiet = 0;
+ uint16_t thr_dieout = 0;
+ uint16_t thr_low = 0;
+ uint16_t thr_high = 0;
+ uint16_t clip = 0;
+ PPDEContentQualLevel quality = kDeContentQualUnknown;
+ PPDEContentType content_type = kDeContentTypeUnknown;
+};
+
+struct PPDETuningCfgData {
+ uint32_t cfg_en = 0;
+ PPDETuningCfg params;
+ bool cfg_pending = false;
+};
+
+struct SDEGamutCfg {
+ static const int kGamutTableNum = 4;
+ static const int kGamutScaleoffTableNum = 3;
+ static const int kGamutTableSize = 1229;
+ static const int kGamutTableCoarseSize = 32;
+ static const int kGamutScaleoffSize = 16;
+ uint32_t mode;
+ uint32_t map_en;
+ uint32_t tbl_size[kGamutTableNum];
+ uint32_t *c0_data[kGamutTableNum];
+ uint32_t *c1_c2_data[kGamutTableNum];
+ uint32_t tbl_scale_off_sz[kGamutScaleoffTableNum];
+ uint32_t *scale_off_data[kGamutScaleoffTableNum];
+};
+
+struct SDEPccCoeff {
+ uint32_t c = 0;
+ uint32_t r = 0;
+ uint32_t g = 0;
+ uint32_t b = 0;
+ uint32_t rg = 0;
+ uint32_t gb = 0;
+ uint32_t rb = 0;
+ uint32_t rgb = 0;
+};
+
+struct SDEPccCfg {
+ SDEPccCoeff red;
+ SDEPccCoeff green;
+ SDEPccCoeff blue;
+
+ static SDEPccCfg *Init(uint32_t arg __attribute__((__unused__)));
+ SDEPccCfg *GetConfig() { return this; }
+};
+
+struct SDECscCfg {
+ static const uint32_t kCscMVSize = 9;
+ static const uint32_t kCscBVSize = 3;
+ static const uint32_t kCscLVSize = 6;
+ uint32_t flags;
+ uint32_t csc_mv[kCscMVSize];
+ uint32_t csc_pre_bv[kCscBVSize];
+ uint32_t csc_post_bv[kCscBVSize];
+ uint32_t csc_pre_lv[kCscLVSize];
+ uint32_t csc_post_lv[kCscLVSize];
+
+ static SDECscCfg *Init(uint32_t arg __attribute__((__unused__)));
+ SDECscCfg *GetConfig() { return this; }
+};
+
+struct SDEDitherCfg {
+ uint32_t g_y_depth;
+ uint32_t r_cr_depth;
+ uint32_t b_cb_depth;
+ uint32_t length;
+ uint32_t dither_matrix[16];
+ uint32_t temporal_en;
+
+ static SDEDitherCfg *Init(uint32_t arg __attribute__((__unused__)));
+ SDEDitherCfg *GetConfig() { return this; }
+};
+
+struct SDEPADitherData {
+ uint64_t data_flags;
+ uint32_t matrix_size;
+ uint64_t matrix_data_addr;
+ uint32_t strength;
+ uint32_t offset_en;
+};
+
+class SDEPADitherWrapper : private SDEPADitherData {
+ public:
+ static SDEPADitherWrapper *Init(uint32_t arg __attribute__((__unused__)));
+ ~SDEPADitherWrapper() {
+ if (buffer_)
+ delete[] buffer_;
+ }
+ inline SDEPADitherData *GetConfig(void) { return this; }
+
+ private:
+ SDEPADitherWrapper() {}
+ uint32_t *buffer_ = NULL;
+};
+
+struct SDEPaMemColorData {
+ uint32_t adjust_p0 = 0;
+ uint32_t adjust_p1 = 0;
+ uint32_t adjust_p2 = 0;
+ uint32_t blend_gain = 0;
+ uint8_t sat_hold = 0;
+ uint8_t val_hold = 0;
+ uint32_t hue_region = 0;
+ uint32_t sat_region = 0;
+ uint32_t val_region = 0;
+};
+
+struct SDEPaData {
+ static const int kSixZoneLUTSize = 384;
+ uint32_t mode = 0;
+ uint32_t hue_adj = 0;
+ uint32_t sat_adj = 0;
+ uint32_t val_adj = 0;
+ uint32_t cont_adj;
+ SDEPaMemColorData skin;
+ SDEPaMemColorData sky;
+ SDEPaMemColorData foliage;
+ uint32_t six_zone_thresh = 0;
+ uint32_t six_zone_adj_p0 = 0;
+ uint32_t six_zone_adj_p1 = 0;
+ uint8_t six_zone_sat_hold = 0;
+ uint8_t six_zone_val_hold = 0;
+ uint32_t six_zone_len = 0;
+ uint32_t *six_zone_curve_p0 = NULL;
+ uint32_t *six_zone_curve_p1 = NULL;
+};
+
+struct SDEIgcLUTData {
+ static const int kMaxIgcLUTEntries = 256;
+ uint32_t table_fmt = 0;
+ uint32_t len = 0;
+ uint32_t *c0_c1_data = NULL;
+ uint32_t *c2_data = NULL;
+};
+
+struct SDEIgcV30LUTData {
+ static const int kMaxIgcLUTEntries = 256;
+ uint32_t table_fmt = 0;
+ uint32_t len = 0;
+ uint64_t c0_c1_data = 0;
+ uint64_t c2_data = 0;
+ uint32_t strength = 0;
+};
+
+struct SDEPgcLUTData {
+ static const int kPgcLUTEntries = 1024;
+ uint32_t len = 0;
+ uint32_t *c0_data = NULL;
+ uint32_t *c1_data = NULL;
+ uint32_t *c2_data = NULL;
+};
+
+struct SDEDisplayMode {
+ static const int kMaxModeNameSize = 256;
+ int32_t id = -1;
+ uint32_t type = 0;
+ char name[kMaxModeNameSize] = {0};
+};
+
+// Wrapper on HW block config data structure to encapsulate the details of allocating
+// and destroying from the caller.
+class SDEGamutCfgWrapper : private SDEGamutCfg {
+ public:
+ enum GamutMode {
+ GAMUT_FINE_MODE = 0x01,
+ GAMUT_COARSE_MODE,
+ GAMUT_COARSE_MODE_13,
+ };
+
+ // This factory method will be used by libsdm-color.so data producer to be populated with
+ // converted config values for SDE feature blocks.
+ static SDEGamutCfgWrapper *Init(uint32_t arg);
+
+ // Data consumer<Commit thread> will be responsible to destroy it once the feature is commited.
+ ~SDEGamutCfgWrapper() {
+ if (buffer_)
+ delete[] buffer_;
+ }
+
+ // Data consumer will use this method to retrieve contained feature configuration.
+ inline SDEGamutCfg *GetConfig(void) { return this; }
+
+ private:
+ SDEGamutCfgWrapper() {}
+ uint32_t *buffer_ = NULL;
+};
+
+class SDEPaCfgWrapper : private SDEPaData {
+ public:
+ static SDEPaCfgWrapper *Init(uint32_t arg = 0);
+ ~SDEPaCfgWrapper() {
+ if (buffer_)
+ delete[] buffer_;
+ }
+ inline SDEPaData *GetConfig(void) { return this; }
+
+ private:
+ SDEPaCfgWrapper() {}
+ uint32_t *buffer_ = NULL;
+};
+
+class SDEIgcLUTWrapper : private SDEIgcLUTData {
+ public:
+ static SDEIgcLUTWrapper *Init(uint32_t arg __attribute__((__unused__)));
+ ~SDEIgcLUTWrapper() {
+ if (buffer_)
+ delete[] buffer_;
+ }
+ inline SDEIgcLUTData *GetConfig(void) { return this; }
+
+ private:
+ SDEIgcLUTWrapper() {}
+ uint32_t *buffer_ = NULL;
+};
+
+class SDEIgcV30LUTWrapper : private SDEIgcV30LUTData {
+ public:
+ static SDEIgcV30LUTWrapper *Init(uint32_t arg __attribute__((__unused__)));
+ ~SDEIgcV30LUTWrapper() {
+ if (buffer_)
+ delete[] buffer_;
+ }
+ inline SDEIgcV30LUTData *GetConfig(void) { return this; }
+
+ private:
+ SDEIgcV30LUTWrapper(const SDEIgcV30LUTWrapper& src) { /* do not create copies */ }
+ SDEIgcV30LUTWrapper& operator=(const SDEIgcV30LUTWrapper&) { return *this; }
+ SDEIgcV30LUTWrapper() {}
+ uint32_t *buffer_ = NULL;
+};
+
+class SDEPgcLUTWrapper : private SDEPgcLUTData {
+ public:
+ static SDEPgcLUTWrapper *Init(uint32_t arg __attribute__((__unused__)));
+ ~SDEPgcLUTWrapper() {
+ if (buffer_)
+ delete[] buffer_;
+ }
+ inline SDEPgcLUTData *GetConfig(void) { return this; }
+
+ private:
+ SDEPgcLUTWrapper() {}
+ uint32_t *buffer_ = NULL;
+};
+
+// Base Postprocessing features information.
+class PPFeatureInfo {
+ public:
+ uint32_t enable_flags_ = 0; // bitmap to indicate subset of parameters enabling or not.
+ uint32_t feature_version_ = 0;
+ uint32_t feature_id_ = 0;
+ uint32_t disp_id_ = 0;
+ uint32_t pipe_id_ = 0;
+
+ virtual ~PPFeatureInfo() {}
+ virtual void *GetConfigData(void) const = 0;
+};
+
+// Individual Postprocessing feature representing physical attributes and information
+// This template class wrapping around abstract data type representing different
+// post-processing features. It will take output from ColorManager converting from raw metadata.
+// The configuration will directly pass into HWInterface to program the hardware accordingly.
+template <typename T>
+class TPPFeatureInfo : public PPFeatureInfo {
+ public:
+ virtual ~TPPFeatureInfo() {
+ if (params_)
+ delete params_;
+ }
+
+ // API for data consumer to get underlying data configs to program into pp hardware block.
+ virtual void *GetConfigData(void) const { return params_->GetConfig(); }
+
+ // API for data producer to get access to underlying data configs to populate it.
+ T *GetParamsReference(void) { return params_; }
+
+ // API for create this template object.
+ static TPPFeatureInfo *Init(uint32_t arg = 0) {
+ TPPFeatureInfo *info = new TPPFeatureInfo();
+ if (info) {
+ info->params_ = T::Init(arg);
+ if (!info->params_) {
+ delete info;
+ info = NULL;
+ }
+ }
+
+ return info;
+ }
+
+ protected:
+ TPPFeatureInfo() = default;
+
+ private:
+ T *params_ = NULL;
+};
+
+// This singleton class serves as data exchanging central between data producer
+// <libsdm-color.so> and data consumer<SDM and HWC.>
+// This class defines PP pending features to be programmed, which generated from
+// ColorManager. Dirty flag indicates some features are available to be programmed.
+// () Lock is needed since the object wil be accessed from 2 tasks.
+// All API exposed are not threadsafe, it's caller's responsiblity to acquire the locker.
+class PPFeaturesConfig {
+ public:
+ PPFeaturesConfig() { memset(feature_, 0, sizeof(feature_)); }
+ ~PPFeaturesConfig() { Reset(); }
+
+ // ColorManager installs one TFeatureInfo<T> to take the output configs computed
+ // from ColorManager, containing all physical features to be programmed and also compute
+ // metadata/populate into T.
+ inline DisplayError AddFeature(uint32_t feature_id, PPFeatureInfo *feature) {
+ if (feature_id < kMaxNumPPFeatures) {
+ if (feature_[feature_id]) {
+ delete feature_[feature_id];
+ feature_[feature_id] = NULL;
+ }
+ feature_[feature_id] = feature;
+ }
+ return kErrorNone;
+ }
+
+ inline Locker &GetLocker(void) { return locker_; }
+ inline PPFrameCaptureData *GetFrameCaptureData(void) { return &frame_capture_data; }
+ inline PPDETuningCfgData *GetDETuningCfgData(void) { return &de_tuning_data_; }
+ // Once all features are consumed, destroy/release all TFeatureInfo<T> on the list,
+ // then clear dirty_ flag and return the lock to the TFeatureInfo<T> producer.
+ void Reset();
+
+ // Consumer to call this to retrieve all the TFeatureInfo<T> on the list to be programmed.
+ DisplayError RetrieveNextFeature(PPFeatureInfo **feature);
+
+ inline bool IsDirty() { return dirty_; }
+ inline void MarkAsDirty() { dirty_ = true; }
+
+ private:
+ bool dirty_ = 0;
+ Locker locker_;
+ PPFeatureInfo *feature_[kMaxNumPPFeatures]; // reference to TFeatureInfo<T>.
+ uint32_t next_idx_ = 0;
+ PPFrameCaptureData frame_capture_data;
+ PPDETuningCfgData de_tuning_data_;
+};
+
+} // namespace sdm
+
+#endif // __COLOR_PARAMS_H__
diff --git a/msm8909/sdm/include/private/dpps_control_interface.h b/msm8909/sdm/include/private/dpps_control_interface.h
new file mode 100644
index 00000000..8a449079
--- /dev/null
+++ b/msm8909/sdm/include/private/dpps_control_interface.h
@@ -0,0 +1,40 @@
+/*
+* Copyright (c) 2016, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without modification, are permitted
+* provided that the following conditions are met:
+* * Redistributions of source code must retain the above copyright notice, this list of
+* conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright notice, this list of
+* conditions and the following disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its contributors may be used to
+* endorse or promote products derived from this software without specific prior written
+* permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __DPPS_CONTROL_INTERFACE_H__
+#define __DPPS_CONTROL_INTERFACE_H__
+
+namespace sdm {
+
+class DppsControlInterface {
+ public:
+ virtual ~DppsControlInterface() { }
+ virtual DisplayError On() = 0;
+ virtual DisplayError Off() = 0;
+};
+
+} // namespace sdm
+
+#endif // __DPPS_CONTROL_INTERFACE_H__
+
diff --git a/msm8909/sdm/include/private/extension_interface.h b/msm8909/sdm/include/private/extension_interface.h
new file mode 100644
index 00000000..2e5bd49c
--- /dev/null
+++ b/msm8909/sdm/include/private/extension_interface.h
@@ -0,0 +1,87 @@
+/*
+* Copyright (c) 2015 - 2017, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without modification, are permitted
+* provided that the following conditions are met:
+* * Redistributions of source code must retain the above copyright notice, this list of
+* conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright notice, this list of
+* conditions and the following disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its contributors may be used to
+* endorse or promote products derived from this software without specific prior written
+* permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __EXTENSION_INTERFACE_H__
+#define __EXTENSION_INTERFACE_H__
+
+#include <core/sdm_types.h>
+#include <core/display_interface.h>
+
+#include "partial_update_interface.h"
+#include "strategy_interface.h"
+#include "resource_interface.h"
+#include "dpps_control_interface.h"
+
+namespace sdm {
+
+#define EXTENSION_LIBRARY_NAME "libsdmextension.so"
+#define CREATE_EXTENSION_INTERFACE_NAME "CreateExtensionInterface"
+#define DESTROY_EXTENSION_INTERFACE_NAME "DestroyExtensionInterface"
+
+#define EXTENSION_REVISION_MAJOR (1)
+#define EXTENSION_REVISION_MINOR (0)
+
+#define EXTENSION_VERSION_TAG ((uint16_t) ((EXTENSION_REVISION_MAJOR << 8) \
+ | EXTENSION_REVISION_MINOR))
+
+class ExtensionInterface;
+
+typedef DisplayError (*CreateExtensionInterface)(uint16_t version, ExtensionInterface **interface);
+typedef DisplayError (*DestroyExtensionInterface)(ExtensionInterface *interface);
+
+class ExtensionInterface {
+ public:
+ virtual DisplayError CreatePartialUpdate(DisplayType type, const HWResourceInfo &hw_resource_info,
+ const HWPanelInfo &hw_panel_info,
+ const HWMixerAttributes &mixer_attributes,
+ const HWDisplayAttributes &display_attributes,
+ const DisplayConfigVariableInfo &fb_config,
+ PartialUpdateInterface **interface) = 0;
+ virtual DisplayError DestroyPartialUpdate(PartialUpdateInterface *interface) = 0;
+
+ virtual DisplayError CreateStrategyExtn(DisplayType type, BufferAllocator *buffer_allocator,
+ const HWResourceInfo &hw_resource_info,
+ const HWPanelInfo &hw_panel_info,
+ const HWMixerAttributes &mixer_attributes,
+ const DisplayConfigVariableInfo &fb_config,
+ StrategyInterface **interface) = 0;
+ virtual DisplayError DestroyStrategyExtn(StrategyInterface *interface) = 0;
+
+ virtual DisplayError CreateResourceExtn(const HWResourceInfo &hw_resource_info,
+ BufferAllocator *buffer_allocator,
+ BufferSyncHandler *buffer_sync_handler,
+ ResourceInterface **interface) = 0;
+ virtual DisplayError DestroyResourceExtn(ResourceInterface *interface) = 0;
+ virtual DisplayError CreateDppsControlExtn(DppsControlInterface **dpps_control_interface,
+ SocketHandler *socket_handler) = 0;
+ virtual DisplayError DestroyDppsControlExtn(DppsControlInterface *interface) = 0;
+
+ protected:
+ virtual ~ExtensionInterface() { }
+};
+
+} // namespace sdm
+
+#endif // __EXTENSION_INTERFACE_H__
+
diff --git a/msm8909/sdm/include/private/hw_info_types.h b/msm8909/sdm/include/private/hw_info_types.h
new file mode 100644
index 00000000..d4f8d728
--- /dev/null
+++ b/msm8909/sdm/include/private/hw_info_types.h
@@ -0,0 +1,561 @@
+/*
+* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without modification, are permitted
+* provided that the following conditions are met:
+* * Redistributions of source code must retain the above copyright notice, this list of
+* conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright notice, this list of
+* conditions and the following disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its contributors may be used to
+* endorse or promote products derived from this software without specific prior written
+* permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __HW_INFO_TYPES_H__
+#define __HW_INFO_TYPES_H__
+
+#include <stdint.h>
+#include <core/display_interface.h>
+#include <core/core_interface.h>
+#include <vector>
+#include <map>
+#include <string>
+#include <bitset>
+
+namespace sdm {
+using std::string;
+
+const int kMaxSDELayers = 16; // Maximum number of layers that can be handled by MDP5 hardware
+ // in a given layer stack.
+#define MAX_PLANES 4
+
+#define MAX_DETAIL_ENHANCE_CURVE 3
+
+enum HWDeviceType {
+ kDevicePrimary,
+ kDeviceHDMI,
+ kDeviceVirtual,
+ kDeviceRotator,
+ kDeviceMax,
+};
+
+enum HWBlockType {
+ kHWPrimary,
+ kHWHDMI,
+ kHWWriteback0,
+ kHWWriteback1,
+ kHWWriteback2,
+ kHWBlockMax
+};
+
+enum HWDisplayMode {
+ kModeDefault,
+ kModeVideo,
+ kModeCommand,
+};
+
+enum PipeType {
+ kPipeTypeUnused,
+ kPipeTypeVIG,
+ kPipeTypeRGB,
+ kPipeTypeDMA,
+ kPipeTypeCursor,
+};
+
+enum HWSubBlockType {
+ kHWVIGPipe,
+ kHWRGBPipe,
+ kHWDMAPipe,
+ kHWCursorPipe,
+ kHWRotatorInput,
+ kHWRotatorOutput,
+ kHWWBIntfOutput,
+ kHWDestinationScalar,
+ kHWSubBlockMax,
+};
+
+enum HWAlphaInterpolation {
+ kInterpolationPixelRepeat,
+ kInterpolationBilinear,
+ kInterpolationMax,
+};
+
+enum HWBlendingFilter {
+ kBlendFilterCircular,
+ kBlendFilterSeparable,
+ kBlendFilterMax,
+};
+
+enum HWPipeFlags {
+ kIGC = 0x01,
+ kMultiRect = 0x02,
+ kMultiRectParallelMode = 0x04,
+};
+
+enum HWAVRModes {
+ kContinuousMode, // Mode to enable AVR feature for every frame.
+ kOneShotMode, // Mode to enable AVR feature for particular frame.
+};
+
+typedef std::map<HWSubBlockType, std::vector<LayerBufferFormat>> FormatsMap;
+
+struct HWDynBwLimitInfo {
+ uint32_t cur_mode = kBwDefault;
+ uint32_t total_bw_limit[kBwModeMax] = { 0 };
+ uint32_t pipe_bw_limit[kBwModeMax] = { 0 };
+};
+
+struct HWPipeCaps {
+ PipeType type = kPipeTypeUnused;
+ uint32_t id = 0;
+ uint32_t master_pipe_id = 0;
+ uint32_t max_rects = 1;
+};
+
+struct HWRotatorInfo {
+ enum { ROT_TYPE_MDSS, ROT_TYPE_V4L2 };
+ uint32_t type = ROT_TYPE_MDSS;
+ uint32_t num_rotator = 0;
+ bool has_downscale = false;
+ std::string device_path = "";
+ float min_downscale = 2.0f;
+ bool downscale_compression = false;
+
+ void Reset() { *this = HWRotatorInfo(); }
+};
+
+struct HWDestScalarInfo {
+ uint32_t count = 0;
+ uint32_t max_input_width = 0;
+ uint32_t max_output_width = 0;
+ uint32_t max_scale_up = 1;
+};
+
+enum SmartDMARevision {
+ V1,
+ V2,
+};
+
+struct HWResourceInfo {
+ uint32_t hw_version = 0;
+ uint32_t hw_revision = 0;
+ uint32_t num_dma_pipe = 0;
+ uint32_t num_vig_pipe = 0;
+ uint32_t num_rgb_pipe = 0;
+ uint32_t num_cursor_pipe = 0;
+ uint32_t num_blending_stages = 0;
+ uint32_t num_control = 0;
+ uint32_t num_mixer_to_disp = 0;
+ uint32_t smp_total = 0;
+ uint32_t smp_size = 0;
+ uint32_t num_smp_per_pipe = 0;
+ uint32_t max_scale_up = 1;
+ uint32_t max_scale_down = 1;
+ float rot_downscale_max = 0.0f;
+ uint64_t max_bandwidth_low = 0;
+ uint64_t max_bandwidth_high = 0;
+ uint32_t max_mixer_width = 2048;
+ uint32_t max_pipe_width = 2048;
+ uint32_t max_cursor_size = 0;
+ uint32_t max_pipe_bw = 0;
+ uint32_t max_sde_clk = 0;
+ float clk_fudge_factor = 1.0f;
+ uint32_t macrotile_nv12_factor = 0;
+ uint32_t macrotile_factor = 0;
+ uint32_t linear_factor = 0;
+ uint32_t scale_factor = 0;
+ uint32_t extra_fudge_factor = 0;
+ uint32_t amortizable_threshold = 0;
+ uint32_t system_overhead_lines = 0;
+ bool has_bwc = false;
+ bool has_ubwc = false;
+ bool has_decimation = false;
+ bool has_macrotile = false;
+ bool has_non_scalar_rgb = false;
+ bool is_src_split = false;
+ bool perf_calc = false;
+ bool has_dyn_bw_support = false;
+ bool separate_rotator = false;
+ bool has_qseed3 = false;
+ bool has_concurrent_writeback = false;
+ bool has_ppp = false;
+ uint32_t writeback_index = kHWBlockMax;
+ HWDynBwLimitInfo dyn_bw_info;
+ std::vector<HWPipeCaps> hw_pipes;
+ FormatsMap supported_formats_map;
+ HWRotatorInfo hw_rot_info;
+ HWDestScalarInfo hw_dest_scalar_info;
+ bool has_avr = false;
+ bool has_hdr = false;
+ SmartDMARevision smart_dma_rev = SmartDMARevision::V1;
+ void Reset() { *this = HWResourceInfo(); }
+};
+
+struct HWSplitInfo {
+ uint32_t left_split = 0;
+ uint32_t right_split = 0;
+
+ bool operator !=(const HWSplitInfo &split_info) {
+ return ((left_split != split_info.left_split) || (right_split != split_info.right_split));
+ }
+
+ bool operator ==(const HWSplitInfo &split_info) {
+ return !(operator !=(split_info));
+ }
+};
+
+enum HWS3DMode {
+ kS3DModeNone,
+ kS3DModeLR,
+ kS3DModeRL,
+ kS3DModeTB,
+ kS3DModeFP,
+ kS3DModeMax,
+};
+
+struct HWColorPrimaries {
+ uint32_t white_point[2] = {}; // White point
+ uint32_t red[2] = {}; // Red color primary
+ uint32_t green[2] = {}; // Green color primary
+ uint32_t blue[2] = {}; // Blue color primary
+};
+
+struct HWPanelOrientation {
+ bool rotation = false;
+ bool flip_horizontal = false;
+ bool flip_vertical = false;
+};
+
+struct HWPanelInfo {
+ DisplayPort port = kPortDefault; // Display port
+ HWDisplayMode mode = kModeDefault; // Display mode
+ bool partial_update = false; // Partial update feature
+ int left_align = 1; // ROI left alignment restriction
+ int width_align = 1; // ROI width alignment restriction
+ int top_align = 1; // ROI top alignment restriction
+ int height_align = 1; // ROI height alignment restriction
+ int min_roi_width = 1; // Min width needed for ROI
+ int min_roi_height = 1; // Min height needed for ROI
+ bool needs_roi_merge = false; // Merge ROI's of both the DSI's
+ bool dynamic_fps = false; // Panel Supports dynamic fps
+ bool dfps_porch_mode = false; // dynamic fps VFP or HFP mode
+ bool ping_pong_split = false; // Supports Ping pong split
+ uint32_t min_fps = 0; // Min fps supported by panel
+ uint32_t max_fps = 0; // Max fps supported by panel
+ bool is_primary_panel = false; // Panel is primary display
+ bool is_pluggable = false; // Panel is pluggable
+ HWSplitInfo split_info; // Panel split configuration
+ char panel_name[256] = {0}; // Panel name
+ HWS3DMode s3d_mode = kS3DModeNone; // Panel's current s3d mode.
+ int panel_max_brightness = 0; // Max panel brightness
+ uint32_t left_roi_count = 1; // Number if ROI supported on left panel
+ uint32_t right_roi_count = 1; // Number if ROI supported on right panel
+ bool hdr_enabled = false; // HDR feature supported
+ uint32_t peak_luminance = 0; // Panel's peak luminance level
+ uint32_t average_luminance = 0; // Panel's average luminance level
+ uint32_t blackness_level = 0; // Panel's blackness level
+ HWColorPrimaries primaries = {}; // WRGB color primaries
+ HWPanelOrientation panel_orientation = {}; // Panel Orientation
+
+ bool operator !=(const HWPanelInfo &panel_info) {
+ return ((port != panel_info.port) || (mode != panel_info.mode) ||
+ (partial_update != panel_info.partial_update) ||
+ (left_align != panel_info.left_align) || (width_align != panel_info.width_align) ||
+ (top_align != panel_info.top_align) || (height_align != panel_info.height_align) ||
+ (min_roi_width != panel_info.min_roi_width) ||
+ (min_roi_height != panel_info.min_roi_height) ||
+ (needs_roi_merge != panel_info.needs_roi_merge) ||
+ (dynamic_fps != panel_info.dynamic_fps) || (min_fps != panel_info.min_fps) ||
+ (dfps_porch_mode != panel_info.dfps_porch_mode) ||
+ (ping_pong_split != panel_info.ping_pong_split) ||
+ (max_fps != panel_info.max_fps) || (is_primary_panel != panel_info.is_primary_panel) ||
+ (split_info != panel_info.split_info) || (s3d_mode != panel_info.s3d_mode) ||
+ (left_roi_count != panel_info.left_roi_count) ||
+ (right_roi_count != panel_info.right_roi_count));
+ }
+
+ bool operator ==(const HWPanelInfo &panel_info) {
+ return !(operator !=(panel_info));
+ }
+};
+
+struct HWSessionConfig {
+ LayerRect src_rect;
+ LayerRect dst_rect;
+ uint32_t buffer_count = 0;
+ bool secure = false;
+ uint32_t frame_rate = 0;
+ LayerTransform transform;
+ bool secure_camera = false;
+
+ bool operator==(const HWSessionConfig& config) const {
+ return (src_rect == config.src_rect &&
+ dst_rect == config.dst_rect &&
+ buffer_count == config.buffer_count &&
+ secure == config.secure &&
+ frame_rate == config.frame_rate &&
+ transform == config.transform &&
+ secure_camera == config.secure_camera);
+ }
+
+ bool operator!=(const HWSessionConfig& config) const {
+ return !operator==(config);
+ }
+};
+
+struct HWRotateInfo {
+ int pipe_id = -1; // Not actual pipe id, but the relative DMA id
+ int writeback_id = -1; // Writeback block id, but this is the same as DMA id
+ LayerRect src_roi; // Source crop of each split
+ LayerRect dst_roi; // Destination crop of each split
+ bool valid = false;
+ int rotate_id = -1; // Actual rotator session id with driver
+
+ void Reset() { *this = HWRotateInfo(); }
+};
+
+struct HWRotatorSession {
+ HWRotateInfo hw_rotate_info[kMaxRotatePerLayer];
+ uint32_t hw_block_count = 0; // number of rotator hw blocks used by rotator session
+ int session_id = -1; // A handle with Session Manager
+ HWSessionConfig hw_session_config;
+ LayerBuffer input_buffer; // Input to rotator
+ LayerBuffer output_buffer; // Output of rotator, crop width and stride are same
+ float input_compression = 1.0f;
+ float output_compression = 1.0f;
+ bool is_buffer_cached = false;
+};
+
+struct HWScaleLutInfo {
+ uint32_t dir_lut_size = 0;
+ uint32_t cir_lut_size = 0;
+ uint32_t sep_lut_size = 0;
+ uint64_t dir_lut = 0;
+ uint64_t cir_lut = 0;
+ uint64_t sep_lut = 0;
+};
+
+struct HWDetailEnhanceData : DisplayDetailEnhancerData {
+ uint16_t prec_shift = 0;
+ int16_t adjust_a[MAX_DETAIL_ENHANCE_CURVE] = {0};
+ int16_t adjust_b[MAX_DETAIL_ENHANCE_CURVE] = {0};
+ int16_t adjust_c[MAX_DETAIL_ENHANCE_CURVE] = {0};
+};
+
+struct HWPixelExtension {
+ int32_t extension = 0; // Number of pixels extension in left, right, top and bottom directions
+ // for all color components. This pixel value for each color component
+ // should be sum of fetch and repeat pixels.
+
+ int32_t overfetch = 0; // Number of pixels need to be overfetched in left, right, top and bottom
+ // directions from source image for scaling.
+
+ int32_t repeat = 0; // Number of pixels need to be repeated in left, right, top and bottom
+ // directions for scaling.
+};
+
+struct HWPlane {
+ int32_t init_phase_x = 0;
+ int32_t phase_step_x = 0;
+ int32_t init_phase_y = 0;
+ int32_t phase_step_y = 0;
+ HWPixelExtension left;
+ HWPixelExtension top;
+ HWPixelExtension right;
+ HWPixelExtension bottom;
+ uint32_t roi_width = 0;
+ int32_t preload_x = 0;
+ int32_t preload_y = 0;
+ uint32_t src_width = 0;
+ uint32_t src_height = 0;
+};
+
+struct HWScaleData {
+ struct enable {
+ uint8_t scale = 0;
+ uint8_t direction_detection = 0;
+ uint8_t detail_enhance = 0;
+ } enable;
+ uint32_t dst_width = 0;
+ uint32_t dst_height = 0;
+ HWPlane plane[MAX_PLANES];
+ // scale_v2_data fields
+ ScalingFilterConfig y_rgb_filter_cfg = kFilterEdgeDirected;
+ ScalingFilterConfig uv_filter_cfg = kFilterEdgeDirected;
+ HWAlphaInterpolation alpha_filter_cfg = kInterpolationPixelRepeat;
+ HWBlendingFilter blend_cfg = kBlendFilterCircular;
+
+ struct lut_flags {
+ uint8_t lut_swap = 0;
+ uint8_t lut_dir_wr = 0;
+ uint8_t lut_y_cir_wr = 0;
+ uint8_t lut_uv_cir_wr = 0;
+ uint8_t lut_y_sep_wr = 0;
+ uint8_t lut_uv_sep_wr = 0;
+ } lut_flag;
+
+ uint32_t dir_lut_idx = 0;
+ /* for Y(RGB) and UV planes*/
+ uint32_t y_rgb_cir_lut_idx = 0;
+ uint32_t uv_cir_lut_idx = 0;
+ uint32_t y_rgb_sep_lut_idx = 0;
+ uint32_t uv_sep_lut_idx = 0;
+
+ HWDetailEnhanceData detail_enhance;
+};
+
+struct HWDestScaleInfo {
+ uint32_t mixer_width = 0;
+ uint32_t mixer_height = 0;
+ bool scale_update = false;
+ HWScaleData scale_data = {};
+ LayerRect panel_roi = {};
+};
+
+typedef std::map<uint32_t, HWDestScaleInfo *> DestScaleInfoMap;
+
+struct HWAVRInfo {
+ bool enable = false; // Flag to Enable AVR feature
+ HWAVRModes mode = kContinuousMode; // Specifies the AVR mode
+};
+
+struct HWPipeInfo {
+ uint8_t rect = 255;
+ uint32_t pipe_id = 0;
+ HWSubBlockType sub_block_type = kHWSubBlockMax;
+ LayerRect src_roi;
+ LayerRect dst_roi;
+ uint8_t horizontal_decimation = 0;
+ uint8_t vertical_decimation = 0;
+ HWScaleData scale_data;
+ uint32_t z_order = 0;
+ uint8_t flags = 0;
+ bool valid = false;
+
+ void Reset() { *this = HWPipeInfo(); }
+};
+
+struct HWLayerConfig {
+ HWPipeInfo left_pipe; // pipe for left side of output
+ HWPipeInfo right_pipe; // pipe for right side of output
+ HWRotatorSession hw_rotator_session;
+ float compression = 1.0f;
+
+ void Reset() { *this = HWLayerConfig(); }
+};
+
+struct HWHDRLayerInfo {
+ enum HDROperation {
+ kNoOp, // No-op.
+ kSet, // Sets the HDR MetaData - Start of HDR
+ kReset, // resets the previously set HDR Metadata, End of HDR
+ };
+
+ int32_t layer_index = -1;
+ HDROperation operation = kNoOp;
+};
+
+struct HWLayersInfo {
+ LayerStack *stack = NULL; // Input layer stack. Set by the caller.
+ uint32_t app_layer_count = 0; // Total number of app layers. Must not be 0.
+ uint32_t gpu_target_index = 0; // GPU target layer index. 0 if not present.
+
+ std::vector<Layer> hw_layers = {}; // Layers which need to be programmed on the HW
+
+ uint32_t index[kMaxSDELayers] = {}; // Indexes of the layers from the layer stack which need to
+ // be programmed on hardware.
+ uint32_t roi_index[kMaxSDELayers] = {0}; // Stores the ROI index where the layers are visible.
+
+ int sync_handle = -1; // Release fence id for current draw cycle.
+ int set_idle_time_ms = -1; // Set idle time to the new specified value.
+ // -1 indicates no change in idle time since last set value.
+
+ std::vector<LayerRect> left_frame_roi = {}; // Left ROI.
+ std::vector<LayerRect> right_frame_roi = {}; // Right ROI.
+ LayerRect partial_fb_roi = {}; // Damaged area in framebuffer.
+
+ bool roi_split = false; // Indicates separated left and right ROI
+
+ bool use_hw_cursor = false; // Indicates that HWCursor pipe needs to be used for cursor layer
+ DestScaleInfoMap dest_scale_info_map = {};
+ HWHDRLayerInfo hdr_layer_info = {};
+ Handle pvt_data = NULL; // Private data used by sdm extension only.
+};
+
+struct HWLayers {
+ HWLayersInfo info;
+ HWLayerConfig config[kMaxSDELayers];
+ float output_compression = 1.0f;
+ uint32_t bandwidth = 0;
+ uint32_t clock = 0;
+ HWAVRInfo hw_avr_info = {};
+};
+
+struct HWDisplayAttributes : DisplayConfigVariableInfo {
+ bool is_device_split = false;
+ uint32_t v_front_porch = 0; //!< Vertical front porch of panel
+ uint32_t v_back_porch = 0; //!< Vertical back porch of panel
+ uint32_t v_pulse_width = 0; //!< Vertical pulse width of panel
+ uint32_t h_total = 0; //!< Total width of panel (hActive + hFP + hBP + hPulseWidth)
+ uint32_t v_total = 0; //!< Total height of panel (vActive + vFP + vBP + vPulseWidth)
+ std::bitset<32> s3d_config; //!< Stores the bit mask of S3D modes
+
+ void Reset() { *this = HWDisplayAttributes(); }
+
+ bool operator !=(const HWDisplayAttributes &display_attributes) {
+ return ((is_device_split != display_attributes.is_device_split) ||
+ (x_pixels != display_attributes.x_pixels) ||
+ (y_pixels != display_attributes.y_pixels) ||
+ (x_dpi != display_attributes.x_dpi) ||
+ (y_dpi != display_attributes.y_dpi) ||
+ (fps != display_attributes.fps) ||
+ (vsync_period_ns != display_attributes.vsync_period_ns) ||
+ (v_front_porch != display_attributes.v_front_porch) ||
+ (v_back_porch != display_attributes.v_back_porch) ||
+ (v_pulse_width != display_attributes.v_pulse_width) ||
+ (h_total != display_attributes.h_total) ||
+ (is_yuv != display_attributes.is_yuv));
+ }
+
+ bool operator ==(const HWDisplayAttributes &display_attributes) {
+ return !(operator !=(display_attributes));
+ }
+};
+
+struct HWMixerAttributes {
+ uint32_t width = 0; // Layer mixer width
+ uint32_t height = 0; // Layer mixer height
+ uint32_t split_left = 0;
+ LayerBufferFormat output_format = kFormatRGB101010; // Layer mixer output format
+
+ bool operator !=(const HWMixerAttributes &mixer_attributes) {
+ return ((width != mixer_attributes.width) ||
+ (height != mixer_attributes.height) ||
+ (output_format != mixer_attributes.output_format) ||
+ (split_left != mixer_attributes.split_left));
+ }
+
+ bool operator ==(const HWMixerAttributes &mixer_attributes) {
+ return !(operator !=(mixer_attributes));
+ }
+
+ bool IsValid() {
+ return (width > 0 && height > 0);
+ }
+};
+
+} // namespace sdm
+
+#endif // __HW_INFO_TYPES_H__
+
diff --git a/msm8909/sdm/include/private/partial_update_interface.h b/msm8909/sdm/include/private/partial_update_interface.h
new file mode 100644
index 00000000..b753587a
--- /dev/null
+++ b/msm8909/sdm/include/private/partial_update_interface.h
@@ -0,0 +1,55 @@
+/*
+* Copyright (c) 2015, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without modification, are permitted
+* provided that the following conditions are met:
+* * Redistributions of source code must retain the above copyright notice, this list of
+* conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright notice, this list of
+* conditions and the following disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its contributors may be used to
+* endorse or promote products derived from this software without specific prior written
+* permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __PARTIAL_UPDATE_INTERFACE_H__
+#define __PARTIAL_UPDATE_INTERFACE_H__
+
+#include <core/display_interface.h>
+#include <core/buffer_allocator.h>
+#include <core/buffer_sync_handler.h>
+
+#include "hw_info_types.h"
+
+namespace sdm {
+
+struct PUConstraints {
+ bool enable = true; //!< If this is set, PU will be enabled or it will be disabled
+ bool enable_cursor_pu = false; //!< If this is set, PU will consider cursor layer in the layer
+ //!< stack for cursor partial update
+};
+
+class PartialUpdateInterface {
+ public:
+ virtual DisplayError Start(const PUConstraints &pu_constraints) = 0;
+ virtual DisplayError GenerateROI(HWLayersInfo *hw_layers_info) = 0;
+ virtual DisplayError Stop() = 0;
+
+ protected:
+ virtual ~PartialUpdateInterface() { }
+};
+
+} // namespace sdm
+
+#endif // __PARTIAL_UPDATE_INTERFACE_H__
+
diff --git a/msm8909/sdm/include/private/resource_interface.h b/msm8909/sdm/include/private/resource_interface.h
new file mode 100644
index 00000000..356c5662
--- /dev/null
+++ b/msm8909/sdm/include/private/resource_interface.h
@@ -0,0 +1,77 @@
+/*
+* Copyright (c) 2015 - 2017, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without modification, are permitted
+* provided that the following conditions are met:
+* * Redistributions of source code must retain the above copyright notice, this list of
+* conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright notice, this list of
+* conditions and the following disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its contributors may be used to
+* endorse or promote products derived from this software without specific prior written
+* permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __RESOURCE_INTERFACE_H__
+#define __RESOURCE_INTERFACE_H__
+
+#include <core/display_interface.h>
+#include "hw_info_types.h"
+
+namespace sdm {
+
+class ResourceInterface {
+ public:
+ enum ResourceCmd {
+ kCmdResetScalarLUT,
+ kCmdMax,
+ };
+
+ virtual DisplayError RegisterDisplay(DisplayType type,
+ const HWDisplayAttributes &display_attributes,
+ const HWPanelInfo &hw_panel_info,
+ const HWMixerAttributes &mixer_attributes,
+ Handle *display_ctx) = 0;
+ virtual DisplayError UnregisterDisplay(Handle display_ctx) = 0;
+ virtual DisplayError ReconfigureDisplay(Handle display_ctx,
+ const HWDisplayAttributes &display_attributes,
+ const HWPanelInfo &hw_panel_info,
+ const HWMixerAttributes &mixer_attributes) = 0;
+ virtual DisplayError Start(Handle display_ctx) = 0;
+ virtual DisplayError Stop(Handle display_ctx, HWLayers *hw_layers) = 0;
+ virtual DisplayError Prepare(Handle display_ctx, HWLayers *hw_layers) = 0;
+ virtual DisplayError PostPrepare(Handle display_ctx, HWLayers *hw_layers) = 0;
+ virtual DisplayError Commit(Handle display_ctx, HWLayers *hw_layers) = 0;
+ virtual DisplayError PostCommit(Handle display_ctx, HWLayers *hw_layers) = 0;
+ virtual void Purge(Handle display_ctx) = 0;
+ virtual DisplayError SetMaxMixerStages(Handle display_ctx, uint32_t max_mixer_stages) = 0;
+ virtual DisplayError ValidateScaling(const LayerRect &crop, const LayerRect &dst,
+ bool rotate90, BufferLayout layout,
+ bool use_rotator_downscale) = 0;
+ virtual DisplayError ValidateCursorConfig(Handle display_ctx, const Layer *layer,
+ bool is_top) = 0;
+ virtual DisplayError ValidateAndSetCursorPosition(Handle display_ctx, HWLayers *hw_layers,
+ int x, int y,
+ DisplayConfigVariableInfo *fb_config) = 0;
+ virtual DisplayError SetMaxBandwidthMode(HWBwModes mode) = 0;
+ virtual DisplayError GetScaleLutConfig(HWScaleLutInfo *lut_info) = 0;
+ virtual DisplayError SetDetailEnhancerData(Handle display_ctx,
+ const DisplayDetailEnhancerData &de_data) = 0;
+ virtual DisplayError Perform(int cmd, ...) = 0;
+ virtual ~ResourceInterface() { }
+};
+
+} // namespace sdm
+
+#endif // __RESOURCE_INTERFACE_H__
+
diff --git a/msm8909/sdm/include/private/strategy_interface.h b/msm8909/sdm/include/private/strategy_interface.h
new file mode 100644
index 00000000..f903d5f0
--- /dev/null
+++ b/msm8909/sdm/include/private/strategy_interface.h
@@ -0,0 +1,65 @@
+/*
+* Copyright (c) 2014 - 2017, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without modification, are permitted
+* provided that the following conditions are met:
+* * Redistributions of source code must retain the above copyright notice, this list of
+* conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright notice, this list of
+* conditions and the following disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its contributors may be used to
+* endorse or promote products derived from this software without specific prior written
+* permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __STRATEGY_INTERFACE_H__
+#define __STRATEGY_INTERFACE_H__
+
+#include <core/sdm_types.h>
+#include <core/display_interface.h>
+#include "hw_info_types.h"
+
+namespace sdm {
+
+struct StrategyConstraints {
+ bool safe_mode = false; //!< In this mode, strategy manager chooses the composition strategy
+ //!< that requires minimum number of pipe for the current frame. i.e.,
+ //!< video only composition, secure only composition or GPU composition
+
+ bool use_cursor = false; //!< If this is set, strategy manager will configure cursor layer in the
+ //!< layer stack as hw cursor else it will be treated as a normal layer
+
+ uint32_t max_layers = kMaxSDELayers; //!< Maximum number of layers that shall be programmed
+ //!< on hardware for the given layer stack.
+};
+
+class StrategyInterface {
+ public:
+ virtual DisplayError Start(HWLayersInfo *hw_layers_info, uint32_t *max_attempts) = 0;
+ virtual DisplayError GetNextStrategy(StrategyConstraints *constraints) = 0;
+ virtual DisplayError Stop() = 0;
+ virtual DisplayError Reconfigure(const HWPanelInfo &hw_panel_info,
+ const HWResourceInfo &hw_res_info,
+ const HWMixerAttributes &mixer_attributes,
+ const DisplayConfigVariableInfo &fb_config) = 0;
+ virtual DisplayError SetCompositionState(LayerComposition composition_type, bool enable) = 0;
+ virtual DisplayError Purge() = 0;
+ virtual DisplayError SetIdleTimeoutMs(uint32_t active_ms) = 0;
+
+ virtual ~StrategyInterface() { }
+};
+
+} // namespace sdm
+
+#endif // __STRATEGY_INTERFACE_H__
+
diff --git a/msm8909/sdm/include/utils/constants.h b/msm8909/sdm/include/utils/constants.h
new file mode 100644
index 00000000..5efe3571
--- /dev/null
+++ b/msm8909/sdm/include/utils/constants.h
@@ -0,0 +1,84 @@
+/*
+* Copyright (c) 2014 - 2017, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without modification, are permitted
+* provided that the following conditions are met:
+* * Redistributions of source code must retain the above copyright notice, this list of
+* conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright notice, this list of
+* conditions and the following disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its contributors may be used to
+* endorse or promote products derived from this software without specific prior written
+* permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __CONSTANTS_H__
+#define __CONSTANTS_H__
+
+#include <stdlib.h>
+#include <inttypes.h>
+
+#ifndef PRIu64
+#define PRIu64 "llu"
+#endif
+
+#define INT(exp) static_cast<int>(exp)
+#define FLOAT(exp) static_cast<float>(exp)
+#define UINT8(exp) static_cast<uint8_t>(exp)
+#define UINT16(exp) static_cast<uint16_t>(exp)
+#define UINT32(exp) static_cast<uint32_t>(exp)
+#define INT32(exp) static_cast<int32_t>(exp)
+#define UINT64(exp) static_cast<uint64_t>(exp)
+
+#define ROUND_UP(number, step) ((((number) + ((step) - 1)) / (step)) * (step))
+
+#define BITMAP(bit) (1 << (bit))
+
+#define ROUND_UP_ALIGN_DOWN(value, a) FLOAT(FloorToMultipleOf(UINT32(value + 0.5f), UINT32(a)))
+#define ROUND_UP_ALIGN_UP(value, a) FLOAT(CeilToMultipleOf(UINT32(value + 0.5f), UINT32(a)))
+
+#define IDLE_TIMEOUT_DEFAULT_MS 70
+#define IDLE_TIMEOUT_ACTIVE_MS IDLE_TIMEOUT_DEFAULT_MS
+#define IDLE_TIMEOUT_INACTIVE_MS 520
+
+#define IS_RGB_FORMAT(format) (((format) < kFormatYCbCr420Planar) ? true: false)
+
+#define BITS_PER_BYTE 8
+#define BITS_TO_BYTES(x) (((x) + (BITS_PER_BYTE - 1)) / (BITS_PER_BYTE))
+
+// factor value should be in powers of 2(eg: 1, 2, 4, 8)
+template <class T1, class T2>
+inline T1 FloorToMultipleOf(const T1 &value, const T2 &factor) {
+ return (T1)(value & (~(factor - 1)));
+}
+
+template <class T1, class T2>
+inline T1 CeilToMultipleOf(const T1 &value, const T2 &factor) {
+ return (T1)((value + (factor - 1)) & (~(factor - 1)));
+}
+
+namespace sdm {
+
+ const int kThreadPriorityUrgent = -9;
+ const int kMaxRotatePerLayer = 2;
+ const uint32_t kMaxBlitTargetLayers = 2;
+ const int kPageSize = 4096;
+ const uint32_t kGridSize = 129; // size used for non-linear transformation before Tone-mapping
+ const uint32_t kLutDim = 17; // Dim of the 3d LUT for tone-mapping.
+
+ typedef void * Handle;
+
+} // namespace sdm
+
+#endif // __CONSTANTS_H__
+
diff --git a/msm8909/sdm/include/utils/debug.h b/msm8909/sdm/include/utils/debug.h
new file mode 100644
index 00000000..af23a922
--- /dev/null
+++ b/msm8909/sdm/include/utils/debug.h
@@ -0,0 +1,121 @@
+/*
+* Copyright (c) 2014 - 2018, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __DEBUG_H__
+#define __DEBUG_H__
+
+#include <stdint.h>
+#include <core/sdm_types.h>
+#include <core/debug_interface.h>
+#include <core/display_interface.h>
+#include <display_properties.h>
+
+#define DLOG(tag, method, format, ...) Debug::Get()->method(tag, __CLASS__ "::%s: " format, \
+ __FUNCTION__, ##__VA_ARGS__)
+
+#define DLOGE_IF(tag, format, ...) DLOG(tag, Error, format, ##__VA_ARGS__)
+#define DLOGW_IF(tag, format, ...) DLOG(tag, Warning, format, ##__VA_ARGS__)
+#define DLOGI_IF(tag, format, ...) DLOG(tag, Info, format, ##__VA_ARGS__)
+#define DLOGD_IF(tag, format, ...) DLOG(tag, Debug, format, ##__VA_ARGS__)
+#define DLOGV_IF(tag, format, ...) DLOG(tag, Verbose, format, ##__VA_ARGS__)
+
+#define DLOGE(format, ...) DLOGE_IF(kTagNone, format, ##__VA_ARGS__)
+#define DLOGD(format, ...) DLOGD_IF(kTagNone, format, ##__VA_ARGS__)
+#define DLOGW(format, ...) DLOGW_IF(kTagNone, format, ##__VA_ARGS__)
+#define DLOGI(format, ...) DLOGI_IF(kTagNone, format, ##__VA_ARGS__)
+#define DLOGV(format, ...) DLOGV_IF(kTagNone, format, ##__VA_ARGS__)
+
+#define DTRACE_BEGIN(custom_string) Debug::Get()->BeginTrace(__CLASS__, __FUNCTION__, custom_string)
+#define DTRACE_END() Debug::Get()->EndTrace()
+#define DTRACE_SCOPED() ScopeTracer <Debug> scope_tracer(__CLASS__, __FUNCTION__)
+
+namespace sdm {
+
+class Debug {
+ public:
+ static inline void SetDebugHandler(DebugHandler *debug_handler) {
+ debug_.debug_handler_ = debug_handler;
+ }
+ static inline DebugHandler* Get() { return debug_.debug_handler_; }
+ static int GetSimulationFlag();
+ static int GetHDMIResolution();
+ static void GetIdleTimeoutMs(uint32_t *active_ms, uint32_t *inactive_ms);
+ static int GetBootAnimLayerCount();
+ static bool IsRotatorDownScaleDisabled();
+ static bool IsDecimationDisabled();
+ static int GetMaxPipesPerMixer(DisplayType display_type);
+ static int GetMaxUpscale();
+ static bool IsVideoModeEnabled();
+ static bool IsRotatorUbwcDisabled();
+ static bool IsRotatorSplitDisabled();
+ static bool IsScalarDisabled();
+ static bool IsUbwcTiledFrameBuffer();
+ static bool IsAVRDisabled();
+ static bool IsExtAnimDisabled();
+ static bool IsPartialSplitDisabled();
+ static DisplayError GetMixerResolution(uint32_t *width, uint32_t *height);
+ static int GetExtMaxlayers();
+ static bool GetProperty(const char *property_name, char *value);
+ static bool SetProperty(const char *property_name, const char *value);
+
+ private:
+ Debug();
+
+ // By default, drop any log messages/traces coming from Display manager. It will be overriden by
+ // Display manager client when core is successfully initialized.
+ class DefaultDebugHandler : public DebugHandler {
+ public:
+ virtual void Error(DebugTag /*tag*/, const char */*format*/, ...) { }
+ virtual void Warning(DebugTag /*tag*/, const char */*format*/, ...) { }
+ virtual void Info(DebugTag /*tag*/, const char */*format*/, ...) { }
+ virtual void Debug(DebugTag /*tag*/, const char */*format*/, ...) { }
+ virtual void Verbose(DebugTag /*tag*/, const char */*format*/, ...) { }
+ virtual void BeginTrace(const char */*class_name*/, const char */*function_name*/,
+ const char */*custom_string*/) { }
+ virtual void EndTrace() { }
+ virtual DisplayError GetProperty(const char */*property_name*/, int */*value*/) {
+ return kErrorNotSupported;
+ }
+ virtual DisplayError GetProperty(const char */*property_name*/, char */*value*/) {
+ return kErrorNotSupported;
+ }
+ virtual DisplayError SetProperty(const char */*property_name*/, const char */*value*/) {
+ return kErrorNotSupported;
+ }
+ };
+
+ DefaultDebugHandler default_debug_handler_;
+ DebugHandler *debug_handler_;
+ static Debug debug_;
+};
+
+} // namespace sdm
+
+#endif // __DEBUG_H__
+
diff --git a/msm8909/sdm/include/utils/factory.h b/msm8909/sdm/include/utils/factory.h
new file mode 100644
index 00000000..f77a2999
--- /dev/null
+++ b/msm8909/sdm/include/utils/factory.h
@@ -0,0 +1,63 @@
+/*
+* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __FACTORY_H__
+#define __FACTORY_H__
+
+#include <utility>
+#include <map>
+#include <string>
+
+namespace sdm {
+
+template <class Creator>
+class Factory {
+ public:
+ int Add(const std::string &name, const Creator &creator) {
+ map_.insert(std::pair<std::string, Creator>(name, creator));
+
+ return 0;
+ }
+
+ Creator Get(const std::string &name) {
+ typename std::map<std::string, Creator>::iterator it = map_.find(name);
+ if (it != map_.end()) {
+ return it->second;
+ }
+
+ return nullptr;
+ }
+
+ private:
+ std::map<std::string, Creator> map_;
+};
+
+} // namespace sdm
+
+#endif // __FACTORY_H__
diff --git a/msm8909/libqdutils/cb_swap_rect.h b/msm8909/sdm/include/utils/formats.h
index daaeb37f..dd819dcd 100644
--- a/msm8909/libqdutils/cb_swap_rect.h
+++ b/msm8909/sdm/include/utils/formats.h
@@ -1,9 +1,11 @@
-/* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+/*
+* Copyright (c) 2016, The Linux Foundation. All rights reserved.
+*
* Redistribution and use in source and binary forms, with or without
-* * modification, are permitted provided that the following conditions are
+* modification, are permitted provided that the following conditions are
* met:
-* * Redistributions of source code must retain the above copyrigh
-* notice, this list of conditions and the following disclaimer
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
@@ -20,32 +22,24 @@
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-* * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#ifndef __FORMATS_H__
+#define __FORMATS_H__
+
+#include <core/layer_stack.h>
+
+namespace sdm {
-#ifndef CB_SWAP_RECT
-#define CB_SWAP_RECT
+bool IsUBWCFormat(LayerBufferFormat format);
+bool Is10BitFormat(LayerBufferFormat format);
+const char *GetFormatString(const LayerBufferFormat &format);
+BufferLayout GetBufferLayout(LayerBufferFormat format);
-#include <stdint.h>
-#include <utils/Singleton.h>
-#include <cutils/log.h>
+} // namespace sdm
-using namespace android;
-namespace qdutils {
-enum {
-HWC_SKIP_HWC_COMPOSITION = 0x00040000,
-};
+#endif // __FORMATS_H__
-class cb_swap_rect : public Singleton <cb_swap_rect>
-{
- bool swap_rect_feature_on;
- public :
- cb_swap_rect();
- void setSwapRectFeature_on( bool value);
- bool checkSwapRectFeature_on();
-};
-} // namespace qdutils
-#endif
diff --git a/msm8909/sdm/include/utils/locker.h b/msm8909/sdm/include/utils/locker.h
new file mode 100644
index 00000000..0096098d
--- /dev/null
+++ b/msm8909/sdm/include/utils/locker.h
@@ -0,0 +1,166 @@
+/*
+* Copyright (c) 2014 - 2016, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without modification, are permitted
+* provided that the following conditions are met:
+* * Redistributions of source code must retain the above copyright notice, this list of
+* conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright notice, this list of
+* conditions and the following disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its contributors may be used to
+* endorse or promote products derived from this software without specific prior written
+* permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __LOCKER_H__
+#define __LOCKER_H__
+
+#include <stdint.h>
+#include <pthread.h>
+#include <sys/time.h>
+
+#define SCOPE_LOCK(locker) Locker::ScopeLock lock(locker)
+#define SEQUENCE_ENTRY_SCOPE_LOCK(locker) Locker::SequenceEntryScopeLock lock(locker)
+#define SEQUENCE_EXIT_SCOPE_LOCK(locker) Locker::SequenceExitScopeLock lock(locker)
+#define SEQUENCE_WAIT_SCOPE_LOCK(locker) Locker::SequenceWaitScopeLock lock(locker)
+#define SEQUENCE_CANCEL_SCOPE_LOCK(locker) Locker::SequenceCancelScopeLock lock(locker)
+
+namespace sdm {
+
+class Locker {
+ public:
+ class ScopeLock {
+ public:
+ explicit ScopeLock(Locker& locker) : locker_(locker) {
+ locker_.Lock();
+ }
+
+ ~ScopeLock() {
+ locker_.Unlock();
+ }
+
+ private:
+ Locker &locker_;
+ };
+
+ class SequenceEntryScopeLock {
+ public:
+ explicit SequenceEntryScopeLock(Locker& locker) : locker_(locker) {
+ locker_.Lock();
+ locker_.sequence_wait_ = 1;
+ }
+
+ ~SequenceEntryScopeLock() {
+ locker_.Unlock();
+ }
+
+ private:
+ Locker &locker_;
+ };
+
+ class SequenceExitScopeLock {
+ public:
+ explicit SequenceExitScopeLock(Locker& locker) : locker_(locker) {
+ locker_.Lock();
+ locker_.sequence_wait_ = 0;
+ }
+
+ ~SequenceExitScopeLock() {
+ locker_.Broadcast();
+ locker_.Unlock();
+ }
+
+ private:
+ Locker &locker_;
+ };
+
+ class SequenceWaitScopeLock {
+ public:
+ explicit SequenceWaitScopeLock(Locker& locker) : locker_(locker), error_(false) {
+ locker_.Lock();
+
+ while (locker_.sequence_wait_ == 1) {
+ locker_.Wait();
+ error_ = (locker_.sequence_wait_ == -1);
+ }
+ }
+
+ ~SequenceWaitScopeLock() {
+ locker_.Unlock();
+ }
+
+ bool IsError() {
+ return error_;
+ }
+
+ private:
+ Locker &locker_;
+ bool error_;
+ };
+
+ class SequenceCancelScopeLock {
+ public:
+ explicit SequenceCancelScopeLock(Locker& locker) : locker_(locker) {
+ locker_.Lock();
+ locker_.sequence_wait_ = -1;
+ }
+
+ ~SequenceCancelScopeLock() {
+ locker_.Broadcast();
+ locker_.Unlock();
+ }
+
+ private:
+ Locker &locker_;
+ };
+
+ Locker() : sequence_wait_(0) {
+ pthread_mutex_init(&mutex_, 0);
+ pthread_cond_init(&condition_, 0);
+ }
+
+ ~Locker() {
+ pthread_mutex_destroy(&mutex_);
+ pthread_cond_destroy(&condition_);
+ }
+
+ void Lock() { pthread_mutex_lock(&mutex_); }
+ void Unlock() { pthread_mutex_unlock(&mutex_); }
+ void Signal() { pthread_cond_signal(&condition_); }
+ void Broadcast() { pthread_cond_broadcast(&condition_); }
+ void Wait() { pthread_cond_wait(&condition_, &mutex_); }
+ int WaitFinite(int ms) {
+ struct timespec ts;
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+ ts.tv_sec = tv.tv_sec + ms/1000;
+ ts.tv_nsec = tv.tv_usec*1000 + (ms%1000)*1000000;
+ ts.tv_sec += ts.tv_nsec/1000000000L;
+ ts.tv_nsec %= 1000000000L;
+ return pthread_cond_timedwait(&condition_, &mutex_, &ts);
+ }
+
+ private:
+ pthread_mutex_t mutex_;
+ pthread_cond_t condition_;
+ int sequence_wait_; // This flag is set to 1 on sequence entry, 0 on exit, and -1 on cancel.
+ // Some routines will wait for sequence of function calls to finish
+ // so that capturing a transitionary snapshot of context is prevented.
+ // If flag is set to -1, these routines will exit without doing any
+ // further processing.
+};
+
+} // namespace sdm
+
+#endif // __LOCKER_H__
+
diff --git a/msm8909/sdm/include/utils/rect.h b/msm8909/sdm/include/utils/rect.h
new file mode 100644
index 00000000..00273e17
--- /dev/null
+++ b/msm8909/sdm/include/utils/rect.h
@@ -0,0 +1,67 @@
+/*
+* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __RECT_H__
+#define __RECT_H__
+
+#include <stdint.h>
+#include <core/sdm_types.h>
+#include <core/layer_stack.h>
+#include <utils/debug.h>
+
+namespace sdm {
+
+ enum RectOrientation {
+ kOrientationPortrait,
+ kOrientationLandscape,
+ kOrientationUnknown,
+ };
+
+ bool IsValid(const LayerRect &rect);
+ bool IsCongruent(const LayerRect &rect1, const LayerRect &rect2);
+ void LogI(DebugTag debug_tag, const char *prefix, const LayerRect &roi);
+ void Log(DebugTag debug_tag, const char *prefix, const LayerRect &roi);
+ void Normalize(const uint32_t &align_x, const uint32_t &align_y, LayerRect *rect);
+ LayerRect Union(const LayerRect &rect1, const LayerRect &rect2);
+ LayerRect Intersection(const LayerRect &rect1, const LayerRect &rect2);
+ LayerRect Subtract(const LayerRect &rect1, const LayerRect &rect2);
+ LayerRect Reposition(const LayerRect &rect1, const int &x_offset, const int &y_offset);
+ void SplitLeftRight(const LayerRect &in_rect, uint32_t split_count, uint32_t align_x,
+ bool flip_horizontal, LayerRect *out_rects);
+ void SplitTopBottom(const LayerRect &in_rect, uint32_t split_count, uint32_t align_y,
+ bool flip_horizontal, LayerRect *out_rects);
+ void MapRect(const LayerRect &src_domain, const LayerRect &dst_domain, const LayerRect &in_rect,
+ LayerRect *out_rect);
+ void TransformHV(const LayerRect &src_domain, const LayerRect &in_rect,
+ const LayerTransform &transform, LayerRect *out_rect);
+ RectOrientation GetOrientation(const LayerRect &in_rect);
+} // namespace sdm
+
+#endif // __RECT_H__
+
diff --git a/msm8909/sdm/include/utils/sync_task.h b/msm8909/sdm/include/utils/sync_task.h
new file mode 100644
index 00000000..725460a1
--- /dev/null
+++ b/msm8909/sdm/include/utils/sync_task.h
@@ -0,0 +1,143 @@
+/*
+* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __SYNC_TASK_H__
+#define __SYNC_TASK_H__
+
+#include <thread>
+#include <mutex>
+#include <condition_variable> // NOLINT
+
+namespace sdm {
+
+template <class TaskCode>
+class SyncTask {
+ public:
+ // This class need to be overridden by caller to pass on a task context.
+ class TaskContext {
+ public:
+ virtual ~TaskContext() { }
+ };
+
+ // Methods to callback into caller for command codes executions in worker thread.
+ class TaskHandler {
+ public:
+ virtual ~TaskHandler() { }
+ virtual void OnTask(const TaskCode &task_code, TaskContext *task_context) = 0;
+ };
+
+ explicit SyncTask(TaskHandler &task_handler) : task_handler_(task_handler) {
+ // Block caller thread until worker thread has started and ready to listen to task commands.
+ // Worker thread will signal as soon as callback is received in the new thread.
+ std::unique_lock<std::mutex> caller_lock(caller_mutex_);
+ std::thread worker_thread(SyncTaskThread, this);
+ worker_thread_.swap(worker_thread);
+ caller_cv_.wait(caller_lock);
+ }
+
+ ~SyncTask() {
+ // Task code does not matter here.
+ PerformTask(task_code_, nullptr, true);
+ worker_thread_.join();
+ }
+
+ void PerformTask(const TaskCode &task_code, TaskContext *task_context) {
+ PerformTask(task_code, task_context, false);
+ }
+
+ private:
+ void PerformTask(const TaskCode &task_code, TaskContext *task_context, bool terminate) {
+ std::unique_lock<std::mutex> caller_lock(caller_mutex_);
+
+ // New scope to limit scope of worker lock to this block.
+ {
+ // Set task command code and notify worker thread.
+ std::unique_lock<std::mutex> worker_lock(worker_mutex_);
+ task_code_ = task_code;
+ task_context_ = task_context;
+ worker_thread_exit_ = terminate;
+ pending_code_ = true;
+ worker_cv_.notify_one();
+ }
+
+ // Wait for worker thread to finish and signal.
+ caller_cv_.wait(caller_lock);
+ }
+
+ static void SyncTaskThread(SyncTask *sync_task) {
+ if (sync_task) {
+ sync_task->OnThreadCallback();
+ }
+ }
+
+ void OnThreadCallback() {
+ // Acquire worker lock and start waiting for events.
+ // Wait must start before caller thread can post events, otherwise posted events will be lost.
+ // Caller thread will be blocked until worker thread signals readiness.
+ std::unique_lock<std::mutex> worker_lock(worker_mutex_);
+
+ // New scope to limit scope of caller lock to this block.
+ {
+ // Signal caller thread that worker thread is ready to listen to events.
+ std::unique_lock<std::mutex> caller_lock(caller_mutex_);
+ caller_cv_.notify_one();
+ }
+
+ while (!worker_thread_exit_) {
+ // Add predicate to handle spurious interrupts.
+ // Wait for caller thread to signal new command codes.
+ worker_cv_.wait(worker_lock, [this] { return pending_code_; });
+
+ // Call task handler which is implemented by the caller.
+ if (!worker_thread_exit_) {
+ task_handler_.OnTask(task_code_, task_context_);
+ }
+
+ pending_code_ = false;
+ // Notify completion of current task to the caller thread which is blocked.
+ std::unique_lock<std::mutex> caller_lock(caller_mutex_);
+ caller_cv_.notify_one();
+ }
+ }
+
+ TaskHandler &task_handler_;
+ TaskCode task_code_;
+ TaskContext *task_context_ = nullptr;
+ std::thread worker_thread_;
+ std::mutex caller_mutex_;
+ std::mutex worker_mutex_;
+ std::condition_variable caller_cv_;
+ std::condition_variable worker_cv_;
+ bool worker_thread_exit_ = false;
+ bool pending_code_ = false;
+};
+
+} // namespace sdm
+
+#endif // __SYNC_TASK_H__
diff --git a/msm8909/sdm/include/utils/sys.h b/msm8909/sdm/include/utils/sys.h
new file mode 100644
index 00000000..6b40df45
--- /dev/null
+++ b/msm8909/sdm/include/utils/sys.h
@@ -0,0 +1,101 @@
+/*
+* Copyright (c) 2015, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without modification, are permitted
+* provided that the following conditions are met:
+* * Redistributions of source code must retain the above copyright notice, this list of
+* conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright notice, this list of
+* conditions and the following disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its contributors may be used to
+* endorse or promote products derived from this software without specific prior written
+* permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __SYS_H__
+#define __SYS_H__
+
+#include <sys/eventfd.h>
+#include <dlfcn.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <poll.h>
+#include <pthread.h>
+#include <fstream>
+
+#ifdef SDM_VIRTUAL_DRIVER
+#include <virtual_driver.h>
+#endif
+
+namespace sdm {
+
+class Sys {
+ public:
+#ifndef SDM_VIRTUAL_DRIVER
+ typedef std::fstream fstream;
+#else
+ typedef VirtualFStream fstream;
+#endif
+
+ // Pointers to system calls which are either mapped to actual system call or virtual driver.
+#ifdef TARGET_HEADLESS
+ typedef int (*ioctl)(int, unsigned long int, ...); // NOLINT
+#else
+ typedef int (*ioctl)(int, int, ...);
+#endif
+ typedef int (*access)(const char *, int);
+ typedef int (*open)(const char *, int, ...);
+ typedef int (*close)(int);
+ typedef int (*poll)(struct pollfd *, nfds_t, int);
+ typedef ssize_t (*pread)(int, void *, size_t, off_t);
+ typedef ssize_t (*pwrite)(int, const void *, size_t, off_t);
+ typedef int (*pthread_cancel)(pthread_t thread);
+ typedef int (*dup)(int fd);
+ typedef ssize_t (*read)(int, void *, size_t);
+ typedef ssize_t (*write)(int, const void *, size_t);
+ typedef int (*eventfd)(unsigned int, int);
+
+ static bool getline_(fstream &fs, std::string &line); // NOLINT
+
+ static ioctl ioctl_;
+ static access access_;
+ static open open_;
+ static close close_;
+ static poll poll_;
+ static pread pread_;
+ static pwrite pwrite_;
+ static pthread_cancel pthread_cancel_;
+ static dup dup_;
+ static read read_;
+ static write write_;
+ static eventfd eventfd_;
+};
+
+class DynLib {
+ public:
+ ~DynLib();
+ bool Open(const char *lib_name);
+ bool Sym(const char *func_name, void **func_ptr);
+ const char * Error() { return ::dlerror(); }
+ operator bool() const { return lib_ != NULL; }
+
+ private:
+ void Close();
+
+ void *lib_ = NULL;
+};
+
+} // namespace sdm
+
+#endif // __SYS_H__
diff --git a/msm8909/libqdutils/cb_utils.h b/msm8909/sdm/include/utils/utils.h
index 8d26b8e5..b1c55c41 100644
--- a/msm8909/libqdutils/cb_utils.h
+++ b/msm8909/sdm/include/utils/utils.h
@@ -1,9 +1,11 @@
-/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+/*
+* Copyright (c) 2016 - 2017, The Linux Foundation. All rights reserved.
+*
* Redistribution and use in source and binary forms, with or without
-* * modification, are permitted provided that the following conditions are
+* modification, are permitted provided that the following conditions are
* met:
-* * Redistributions of source code must retain the above copyrigh
-* notice, this list of conditions and the following disclaimer
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
@@ -20,26 +22,28 @@
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-* * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#ifndef __UTILS_H__
+#define __UTILS_H__
-#ifndef CB_UTIL_H
-#define CB_UTIL_H
+namespace sdm {
-#include "hwc_utils.h"
-#include "copybit.h"
+float gcd(float a, float b);
+float lcm(float a, float b);
+void CloseFd(int *fd);
-using namespace qhwc;
-namespace qdutils {
-class CBUtils {
-public:
- static int uiClearRegion(hwc_display_contents_1_t* list,
- int version, LayerProp *layerProp, hwc_rect_t dirtyIndex,
- copybit_device_t *copybit, private_handle_t *renderBuffer);
+enum class DriverType {
+ FB = 0,
+ DRM,
};
-}//namespace qdutils
-#endif /* end of include guard: CB_UTIL_H*/
+
+DriverType GetDriverType();
+
+} // namespace sdm
+
+#endif // __UTILS_H__
diff --git a/msm8909/sdm/libs/core/Android.mk b/msm8909/sdm/libs/core/Android.mk
new file mode 100644
index 00000000..7aab09c6
--- /dev/null
+++ b/msm8909/sdm/libs/core/Android.mk
@@ -0,0 +1,82 @@
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+include $(LOCAL_PATH)/../../../common.mk
+
+LOCAL_MODULE := libsdmcore
+LOCAL_VENDOR_MODULE := true
+LOCAL_MODULE_TAGS := optional
+LOCAL_C_INCLUDES := $(common_includes) $(kernel_includes)
+LOCAL_HEADER_LIBRARIES := display_headers
+LOCAL_CFLAGS := -Wno-unused-parameter -DLOG_TAG=\"SDM\" \
+ $(common_flags)
+LOCAL_HW_INTF_PATH_1 := fb
+LOCAL_SHARED_LIBRARIES := libdl libsdmutils
+
+ifneq ($(TARGET_IS_HEADLESS), true)
+ LOCAL_CFLAGS += -DCOMPILE_DRM -isystem external/libdrm
+ LOCAL_SHARED_LIBRARIES += libdrm libdrmutils
+ LOCAL_HW_INTF_PATH_2 := drm
+endif
+
+ifeq ($(TARGET_USES_DRM_PP),true)
+ LOCAL_CFLAGS += -DPP_DRM_ENABLE
+endif
+
+LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps) $(kernel_deps)
+LOCAL_SRC_FILES := core_interface.cpp \
+ core_impl.cpp \
+ display_base.cpp \
+ display_primary.cpp \
+ display_hdmi.cpp \
+ display_virtual.cpp \
+ comp_manager.cpp \
+ strategy.cpp \
+ resource_default.cpp \
+ color_manager.cpp \
+ hw_events_interface.cpp \
+ hw_info_interface.cpp \
+ hw_interface.cpp \
+ $(LOCAL_HW_INTF_PATH_1)/hw_info.cpp \
+ $(LOCAL_HW_INTF_PATH_1)/hw_device.cpp \
+ $(LOCAL_HW_INTF_PATH_1)/hw_primary.cpp \
+ $(LOCAL_HW_INTF_PATH_1)/hw_hdmi.cpp \
+ $(LOCAL_HW_INTF_PATH_1)/hw_virtual.cpp \
+ $(LOCAL_HW_INTF_PATH_1)/hw_color_manager.cpp \
+ $(LOCAL_HW_INTF_PATH_1)/hw_scale.cpp \
+ $(LOCAL_HW_INTF_PATH_1)/hw_events.cpp
+
+ifneq ($(TARGET_IS_HEADLESS), true)
+ LOCAL_SRC_FILES += $(LOCAL_HW_INTF_PATH_2)/hw_info_drm.cpp \
+ $(LOCAL_HW_INTF_PATH_2)/hw_device_drm.cpp \
+ $(LOCAL_HW_INTF_PATH_2)/hw_events_drm.cpp \
+ $(LOCAL_HW_INTF_PATH_2)/hw_scale_drm.cpp \
+ $(LOCAL_HW_INTF_PATH_2)/hw_color_manager_drm.cpp
+endif
+
+include $(BUILD_SHARED_LIBRARY)
+
+SDM_HEADER_PATH := ../../include
+include $(CLEAR_VARS)
+LOCAL_COPY_HEADERS_TO := $(common_header_export_path)/sdm/core
+LOCAL_COPY_HEADERS = $(SDM_HEADER_PATH)/core/buffer_allocator.h \
+ $(SDM_HEADER_PATH)/core/buffer_sync_handler.h \
+ $(SDM_HEADER_PATH)/core/core_interface.h \
+ $(SDM_HEADER_PATH)/core/debug_interface.h \
+ $(SDM_HEADER_PATH)/core/display_interface.h \
+ $(SDM_HEADER_PATH)/core/layer_buffer.h \
+ $(SDM_HEADER_PATH)/core/layer_stack.h \
+ $(SDM_HEADER_PATH)/core/sdm_types.h \
+ $(SDM_HEADER_PATH)/core/socket_handler.h
+include $(BUILD_COPY_HEADERS)
+
+include $(CLEAR_VARS)
+LOCAL_COPY_HEADERS_TO := $(common_header_export_path)/sdm/private
+LOCAL_COPY_HEADERS = $(SDM_HEADER_PATH)/private/color_interface.h \
+ $(SDM_HEADER_PATH)/private/color_params.h \
+ $(SDM_HEADER_PATH)/private/extension_interface.h \
+ $(SDM_HEADER_PATH)/private/hw_info_types.h \
+ $(SDM_HEADER_PATH)/private/partial_update_interface.h \
+ $(SDM_HEADER_PATH)/private/resource_interface.h \
+ $(SDM_HEADER_PATH)/private/strategy_interface.h \
+ $(SDM_HEADER_PATH)/private/dpps_control_interface.h
+include $(BUILD_COPY_HEADERS)
diff --git a/msm8909/sdm/libs/core/Makefile.am b/msm8909/sdm/libs/core/Makefile.am
new file mode 100644
index 00000000..2b45d8e3
--- /dev/null
+++ b/msm8909/sdm/libs/core/Makefile.am
@@ -0,0 +1,47 @@
+HEADER_PATH := ${WORKSPACE}/display/display-hal/sdm/include
+
+c_sources = core_interface.cpp \
+ core_impl.cpp \
+ display_base.cpp \
+ display_primary.cpp \
+ display_hdmi.cpp \
+ display_virtual.cpp \
+ comp_manager.cpp \
+ strategy.cpp \
+ resource_default.cpp \
+ dump_impl.cpp \
+ color_manager.cpp \
+ hw_interface.cpp \
+ hw_info_interface.cpp \
+ hw_events_interface.cpp \
+ fb/hw_info.cpp \
+ fb/hw_device.cpp \
+ fb/hw_primary.cpp \
+ fb/hw_hdmi.cpp \
+ fb/hw_virtual.cpp \
+ fb/hw_color_manager.cpp \
+ fb/hw_scale.cpp \
+ fb/hw_events.cpp
+
+core_h_sources = $(HEADER_PATH)/core/*.h
+
+core_includedir = $(includedir)/sdm/core
+core_include_HEADERS = $(core_h_sources)
+
+private_h_sources = $(HEADER_PATH)/private/*.h
+
+private_includedir = $(includedir)/sdm/private
+private_include_HEADERS = $(private_h_sources)
+
+utils_h_sources = $(HEADER_PATH)/utils/*.h
+
+utils_includedir = $(includedir)/sdm/utils
+utils_include_HEADERS = $(utils_h_sources)
+
+lib_LTLIBRARIES = libsdmcore.la
+libsdmcore_la_CC = @CC@
+libsdmcore_la_SOURCES = $(c_sources)
+libsdmcore_la_CFLAGS = $(COMMON_CFLAGS) -DLOG_TAG=\"SDM\"
+libsdmcore_la_CPPFLAGS = $(AM_CPPFLAGS)
+libsdmcore_la_LIBADD = ../utils/libsdmutils.la
+libsdmcore_la_LDFLAGS = -shared -avoid-version
diff --git a/msm8909/sdm/libs/core/color_manager.cpp b/msm8909/sdm/libs/core/color_manager.cpp
new file mode 100644
index 00000000..938ab991
--- /dev/null
+++ b/msm8909/sdm/libs/core/color_manager.cpp
@@ -0,0 +1,243 @@
+/* Copyright (c) 2015 - 2017, The Linux Foundataion. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+*/
+
+#include <dlfcn.h>
+#include <private/color_interface.h>
+#include <utils/constants.h>
+#include <utils/debug.h>
+#include "color_manager.h"
+
+#define __CLASS__ "ColorManager"
+
+namespace sdm {
+
+DynLib ColorManagerProxy::color_lib_;
+CreateColorInterface ColorManagerProxy::create_intf_ = NULL;
+DestroyColorInterface ColorManagerProxy::destroy_intf_ = NULL;
+HWResourceInfo ColorManagerProxy::hw_res_info_;
+
+// Below two functions are part of concrete implementation for SDM core private
+// color_params.h
+void PPFeaturesConfig::Reset() {
+ for (int i = 0; i < kMaxNumPPFeatures; i++) {
+ if (feature_[i]) {
+ delete feature_[i];
+ feature_[i] = NULL;
+ }
+ }
+ dirty_ = false;
+ next_idx_ = 0;
+}
+
+DisplayError PPFeaturesConfig::RetrieveNextFeature(PPFeatureInfo **feature) {
+ DisplayError ret = kErrorNone;
+ uint32_t i(0);
+
+ for (i = next_idx_; i < kMaxNumPPFeatures; i++) {
+ if (feature_[i]) {
+ *feature = feature_[i];
+ next_idx_ = i + 1;
+ break;
+ }
+ }
+
+ if (i == kMaxNumPPFeatures) {
+ ret = kErrorParameters;
+ next_idx_ = 0;
+ }
+
+ return ret;
+}
+
+DisplayError ColorManagerProxy::Init(const HWResourceInfo &hw_res_info) {
+ DisplayError error = kErrorNone;
+
+ // Load color service library and retrieve its entry points.
+ if (color_lib_.Open(COLORMGR_LIBRARY_NAME)) {
+ if (!color_lib_.Sym(CREATE_COLOR_INTERFACE_NAME, reinterpret_cast<void **>(&create_intf_)) ||
+ !color_lib_.Sym(DESTROY_COLOR_INTERFACE_NAME, reinterpret_cast<void **>(&destroy_intf_))) {
+ DLOGW("Fail to retrieve = %s from %s", CREATE_COLOR_INTERFACE_NAME, COLORMGR_LIBRARY_NAME);
+ error = kErrorResources;
+ }
+ } else {
+ DLOGW("Fail to load = %s", COLORMGR_LIBRARY_NAME);
+ error = kErrorResources;
+ }
+
+ hw_res_info_ = hw_res_info;
+
+ return error;
+}
+
+void ColorManagerProxy::Deinit() {
+ color_lib_.~DynLib();
+}
+
+ColorManagerProxy::ColorManagerProxy(DisplayType type, HWInterface *intf,
+ const HWDisplayAttributes &attr,
+ const HWPanelInfo &info)
+ : device_type_(type), pp_hw_attributes_(), hw_intf_(intf), color_intf_(NULL), pp_features_() {}
+
+ColorManagerProxy *ColorManagerProxy::CreateColorManagerProxy(DisplayType type,
+ HWInterface *hw_intf,
+ const HWDisplayAttributes &attribute,
+ const HWPanelInfo &panel_info) {
+ DisplayError error = kErrorNone;
+ PPFeatureVersion versions;
+
+ // check if all resources are available before invoking factory method from libsdm-color.so.
+ if (!color_lib_ || !create_intf_ || !destroy_intf_) {
+ DLOGW("Information for %s isn't available!", COLORMGR_LIBRARY_NAME);
+ return NULL;
+ }
+
+ ColorManagerProxy *color_manager_proxy =
+ new ColorManagerProxy(type, hw_intf, attribute, panel_info);
+ if (color_manager_proxy) {
+ // 1. need query post-processing feature version from HWInterface.
+ error = color_manager_proxy->hw_intf_->GetPPFeaturesVersion(&versions);
+ PPHWAttributes &hw_attr = color_manager_proxy->pp_hw_attributes_;
+ if (error != kErrorNone) {
+ DLOGW("Fail to get DSPP feature versions");
+ } else {
+ hw_attr.Set(hw_res_info_, panel_info, attribute, versions);
+ DLOGW("PAV2 version is versions = %d, version = %d ",
+ hw_attr.version.version[kGlobalColorFeaturePaV2],
+ versions.version[kGlobalColorFeaturePaV2]);
+ }
+
+ // 2. instantiate concrete ColorInterface from libsdm-color.so, pass all hardware info in.
+ error = create_intf_(COLOR_VERSION_TAG, color_manager_proxy->device_type_, hw_attr,
+ &color_manager_proxy->color_intf_);
+ if (error != kErrorNone) {
+ DLOGW("Unable to instantiate concrete ColorInterface from %s", COLORMGR_LIBRARY_NAME);
+ delete color_manager_proxy;
+ color_manager_proxy = NULL;
+ }
+ }
+
+ return color_manager_proxy;
+}
+
+ColorManagerProxy::~ColorManagerProxy() {
+ if (destroy_intf_)
+ destroy_intf_(device_type_);
+ color_intf_ = NULL;
+}
+
+DisplayError ColorManagerProxy::ColorSVCRequestRoute(const PPDisplayAPIPayload &in_payload,
+ PPDisplayAPIPayload *out_payload,
+ PPPendingParams *pending_action) {
+ DisplayError ret = kErrorNone;
+
+ // On completion, dspp_features_ will be populated and mark dirty with all resolved dspp
+ // feature list with paramaters being transformed into target requirement.
+ ret = color_intf_->ColorSVCRequestRoute(in_payload, out_payload, &pp_features_, pending_action);
+
+ return ret;
+}
+
+DisplayError ColorManagerProxy::ApplyDefaultDisplayMode(void) {
+ DisplayError ret = kErrorNone;
+
+ // On POR, will be invoked from prepare<> request once bootanimation is done.
+ ret = color_intf_->ApplyDefaultDisplayMode(&pp_features_);
+
+ return ret;
+}
+
+bool ColorManagerProxy::NeedsPartialUpdateDisable() {
+ Locker &locker(pp_features_.GetLocker());
+ SCOPE_LOCK(locker);
+
+ return pp_features_.IsDirty();
+}
+
+DisplayError ColorManagerProxy::Commit() {
+ Locker &locker(pp_features_.GetLocker());
+ SCOPE_LOCK(locker);
+
+ DisplayError ret = kErrorNone;
+ if (pp_features_.IsDirty()) {
+ ret = hw_intf_->SetPPFeatures(&pp_features_);
+ }
+
+ return ret;
+}
+
+void PPHWAttributes::Set(const HWResourceInfo &hw_res,
+ const HWPanelInfo &panel_info,
+ const DisplayConfigVariableInfo &attr,
+ const PPFeatureVersion &feature_ver) {
+ HWResourceInfo &res = *this;
+ res = hw_res;
+ HWPanelInfo &panel = *this;
+ panel = panel_info;
+ DisplayConfigVariableInfo &attributes = *this;
+ attributes = attr;
+ version = feature_ver;
+ panel_max_brightness = panel_info.panel_max_brightness;
+
+ if (strlen(panel_info.panel_name)) {
+ snprintf(&panel_name[0], sizeof(panel_name), "%s", &panel_info.panel_name[0]);
+ char *tmp = panel_name;
+ while ((tmp = strstr(tmp, " ")) != NULL)
+ *tmp = '_';
+ if ((tmp = strstr(panel_name, "\n")) != NULL)
+ *tmp = '\0';
+ }
+}
+
+DisplayError ColorManagerProxy::ColorMgrGetNumOfModes(uint32_t *mode_cnt) {
+ return color_intf_->ColorIntfGetNumDisplayModes(&pp_features_, 0, mode_cnt);
+}
+
+DisplayError ColorManagerProxy::ColorMgrGetModes(uint32_t *mode_cnt,
+ SDEDisplayMode *modes) {
+ return color_intf_->ColorIntfEnumerateDisplayModes(&pp_features_, 0, modes, mode_cnt);
+}
+
+DisplayError ColorManagerProxy::ColorMgrSetMode(int32_t color_mode_id) {
+ return color_intf_->ColorIntfSetDisplayMode(&pp_features_, 0, color_mode_id);
+}
+
+DisplayError ColorManagerProxy::ColorMgrGetModeInfo(int32_t mode_id, AttrVal *query) {
+ return color_intf_->ColorIntfGetModeInfo(&pp_features_, 0, mode_id, query);
+}
+
+DisplayError ColorManagerProxy::ColorMgrSetColorTransform(uint32_t length,
+ const double *trans_data) {
+ return color_intf_->ColorIntfSetColorTransform(&pp_features_, 0, length, trans_data);
+}
+
+DisplayError ColorManagerProxy::ColorMgrGetDefaultModeID(int32_t *mode_id) {
+ return color_intf_->ColorIntfGetDefaultModeID(&pp_features_, 0, mode_id);
+}
+
+} // namespace sdm
diff --git a/msm8909/sdm/libs/core/color_manager.h b/msm8909/sdm/libs/core/color_manager.h
new file mode 100644
index 00000000..db050afd
--- /dev/null
+++ b/msm8909/sdm/libs/core/color_manager.h
@@ -0,0 +1,98 @@
+/* Copyright (c) 2015-2017, The Linux Foundataion. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+*/
+
+#ifndef __COLOR_MANAGER_H__
+#define __COLOR_MANAGER_H__
+
+#include <stdlib.h>
+#include <core/sdm_types.h>
+#include <utils/locker.h>
+#include <private/color_interface.h>
+#include <utils/sys.h>
+#include <utils/debug.h>
+#include "hw_interface.h"
+
+namespace sdm {
+
+/*
+ * ColorManager proxy to maintain necessary information to interact with underlying color service.
+ * Each display object has its own proxy.
+ */
+class ColorManagerProxy {
+ public:
+ static DisplayError Init(const HWResourceInfo &hw_res_info);
+ static void Deinit();
+
+ /* Create ColorManagerProxy for this display object, following things need to be happening
+ * 1. Instantiates concrete ColorInerface implementation.
+ * 2. Pass all display object specific informations into it.
+ * 3. Populate necessary resources.
+ * 4. Need get panel name for hw_panel_info_.
+ */
+ static ColorManagerProxy *CreateColorManagerProxy(DisplayType type, HWInterface *hw_intf,
+ const HWDisplayAttributes &attribute,
+ const HWPanelInfo &panel_info);
+
+ /* need reverse the effect of CreateColorManagerProxy. */
+ ~ColorManagerProxy();
+
+ DisplayError ColorSVCRequestRoute(const PPDisplayAPIPayload &in_payload,
+ PPDisplayAPIPayload *out_payload,
+ PPPendingParams *pending_action);
+ DisplayError ApplyDefaultDisplayMode();
+ DisplayError ColorMgrGetNumOfModes(uint32_t *mode_cnt);
+ DisplayError ColorMgrGetModes(uint32_t *mode_cnt, SDEDisplayMode *modes);
+ DisplayError ColorMgrSetMode(int32_t color_mode_id);
+ DisplayError ColorMgrGetModeInfo(int32_t mode_id, AttrVal *query);
+ DisplayError ColorMgrSetColorTransform(uint32_t length, const double *trans_data);
+ DisplayError ColorMgrGetDefaultModeID(int32_t *mode_id);
+ bool NeedsPartialUpdateDisable();
+ DisplayError Commit();
+
+ protected:
+ ColorManagerProxy() {}
+ ColorManagerProxy(DisplayType type, HWInterface *intf, const HWDisplayAttributes &attr,
+ const HWPanelInfo &info);
+
+ private:
+ static DynLib color_lib_;
+ static CreateColorInterface create_intf_;
+ static DestroyColorInterface destroy_intf_;
+ static HWResourceInfo hw_res_info_;
+
+ DisplayType device_type_;
+ PPHWAttributes pp_hw_attributes_;
+ HWInterface *hw_intf_;
+ ColorInterface *color_intf_;
+ PPFeaturesConfig pp_features_;
+};
+
+} // namespace sdm
+
+#endif // __COLOR_MANAGER_H__
diff --git a/msm8909/sdm/libs/core/comp_manager.cpp b/msm8909/sdm/libs/core/comp_manager.cpp
new file mode 100644
index 00000000..5488e460
--- /dev/null
+++ b/msm8909/sdm/libs/core/comp_manager.cpp
@@ -0,0 +1,605 @@
+/*
+* Copyright (c) 2014 - 2017, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without modification, are permitted
+* provided that the following conditions are met:
+* * Redistributions of source code must retain the above copyright notice, this list of
+* conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright notice, this list of
+* conditions and the following disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its contributors may be used to
+* endorse or promote products derived from this software without specific prior written
+* permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <utils/constants.h>
+#include <utils/debug.h>
+#include <core/buffer_allocator.h>
+
+#include "comp_manager.h"
+#include "strategy.h"
+
+#define __CLASS__ "CompManager"
+
+namespace sdm {
+
+static bool NeedsScaledComposition(const DisplayConfigVariableInfo &fb_config,
+ const HWMixerAttributes &mixer_attributes) {
+ return ((fb_config.x_pixels != mixer_attributes.width) ||
+ (fb_config.y_pixels != mixer_attributes.height));
+}
+
+DisplayError CompManager::Init(const HWResourceInfo &hw_res_info,
+ ExtensionInterface *extension_intf,
+ BufferAllocator *buffer_allocator,
+ BufferSyncHandler *buffer_sync_handler,
+ SocketHandler *socket_handler) {
+ SCOPE_LOCK(locker_);
+
+ DisplayError error = kErrorNone;
+
+ if (extension_intf) {
+ error = extension_intf->CreateResourceExtn(hw_res_info, buffer_allocator, buffer_sync_handler,
+ &resource_intf_);
+ extension_intf->CreateDppsControlExtn(&dpps_ctrl_intf_, socket_handler);
+ } else {
+ error = ResourceDefault::CreateResourceDefault(hw_res_info, &resource_intf_);
+ }
+
+ if (error != kErrorNone) {
+ if (extension_intf) {
+ extension_intf->DestroyDppsControlExtn(dpps_ctrl_intf_);
+ }
+ return error;
+ }
+
+ hw_res_info_ = hw_res_info;
+ buffer_allocator_ = buffer_allocator;
+ extension_intf_ = extension_intf;
+
+ return error;
+}
+
+DisplayError CompManager::Deinit() {
+ SCOPE_LOCK(locker_);
+
+ if (extension_intf_) {
+ extension_intf_->DestroyResourceExtn(resource_intf_);
+ extension_intf_->DestroyDppsControlExtn(dpps_ctrl_intf_);
+ } else {
+ ResourceDefault::DestroyResourceDefault(resource_intf_);
+ }
+
+ return kErrorNone;
+}
+
+DisplayError CompManager::RegisterDisplay(DisplayType type,
+ const HWDisplayAttributes &display_attributes,
+ const HWPanelInfo &hw_panel_info,
+ const HWMixerAttributes &mixer_attributes,
+ const DisplayConfigVariableInfo &fb_config,
+ Handle *display_ctx) {
+ SCOPE_LOCK(locker_);
+
+ DisplayError error = kErrorNone;
+
+ DisplayCompositionContext *display_comp_ctx = new DisplayCompositionContext();
+ if (!display_comp_ctx) {
+ return kErrorMemory;
+ }
+
+ Strategy *&strategy = display_comp_ctx->strategy;
+ strategy = new Strategy(extension_intf_, buffer_allocator_, type, hw_res_info_, hw_panel_info,
+ mixer_attributes, display_attributes, fb_config);
+ if (!strategy) {
+ DLOGE("Unable to create strategy");
+ delete display_comp_ctx;
+ return kErrorMemory;
+ }
+
+ error = strategy->Init();
+ if (error != kErrorNone) {
+ delete strategy;
+ delete display_comp_ctx;
+ return error;
+ }
+
+ error = resource_intf_->RegisterDisplay(type, display_attributes, hw_panel_info, mixer_attributes,
+ &display_comp_ctx->display_resource_ctx);
+ if (error != kErrorNone) {
+ strategy->Deinit();
+ delete strategy;
+ delete display_comp_ctx;
+ display_comp_ctx = NULL;
+ return error;
+ }
+
+ registered_displays_[type] = 1;
+ display_comp_ctx->is_primary_panel = hw_panel_info.is_primary_panel;
+ display_comp_ctx->display_type = type;
+ display_comp_ctx->fb_config = fb_config;
+ *display_ctx = display_comp_ctx;
+ // New non-primary display device has been added, so move the composition mode to safe mode until
+ // resources for the added display is configured properly.
+ if (!display_comp_ctx->is_primary_panel) {
+ safe_mode_ = true;
+ max_sde_ext_layers_ = UINT32(Debug::GetExtMaxlayers());
+ }
+
+ display_comp_ctx->scaled_composition = NeedsScaledComposition(fb_config, mixer_attributes);
+ DLOGV_IF(kTagCompManager, "registered display bit mask 0x%x, configured display bit mask 0x%x, " \
+ "display type %d", registered_displays_.to_ulong(), configured_displays_.to_ulong(),
+ display_comp_ctx->display_type);
+
+ return kErrorNone;
+}
+
+DisplayError CompManager::UnregisterDisplay(Handle display_ctx) {
+ SCOPE_LOCK(locker_);
+
+ DisplayCompositionContext *display_comp_ctx =
+ reinterpret_cast<DisplayCompositionContext *>(display_ctx);
+
+ if (!display_comp_ctx) {
+ return kErrorParameters;
+ }
+
+ resource_intf_->UnregisterDisplay(display_comp_ctx->display_resource_ctx);
+
+ Strategy *&strategy = display_comp_ctx->strategy;
+ strategy->Deinit();
+ delete strategy;
+
+ registered_displays_[display_comp_ctx->display_type] = 0;
+ configured_displays_[display_comp_ctx->display_type] = 0;
+
+ if (display_comp_ctx->display_type == kHDMI) {
+ max_layers_ = kMaxSDELayers;
+ }
+
+ DLOGV_IF(kTagCompManager, "registered display bit mask 0x%x, configured display bit mask 0x%x, " \
+ "display type %d", registered_displays_.to_ulong(), configured_displays_.to_ulong(),
+ display_comp_ctx->display_type);
+
+ delete display_comp_ctx;
+ display_comp_ctx = NULL;
+ return kErrorNone;
+}
+
+DisplayError CompManager::ReconfigureDisplay(Handle comp_handle,
+ const HWDisplayAttributes &display_attributes,
+ const HWPanelInfo &hw_panel_info,
+ const HWMixerAttributes &mixer_attributes,
+ const DisplayConfigVariableInfo &fb_config) {
+ SCOPE_LOCK(locker_);
+
+ DisplayError error = kErrorNone;
+ DisplayCompositionContext *display_comp_ctx =
+ reinterpret_cast<DisplayCompositionContext *>(comp_handle);
+
+ error = resource_intf_->ReconfigureDisplay(display_comp_ctx->display_resource_ctx,
+ display_attributes, hw_panel_info, mixer_attributes);
+ if (error != kErrorNone) {
+ return error;
+ }
+
+ if (display_comp_ctx->strategy) {
+ error = display_comp_ctx->strategy->Reconfigure(hw_panel_info, display_attributes,
+ mixer_attributes, fb_config);
+ if (error != kErrorNone) {
+ DLOGE("Unable to Reconfigure strategy.");
+ display_comp_ctx->strategy->Deinit();
+ delete display_comp_ctx->strategy;
+ display_comp_ctx->strategy = NULL;
+ return error;
+ }
+ }
+
+ // For HDMI S3D mode, set max_layers_ to 0 so that primary display would fall back
+ // to GPU composition to release pipes for HDMI.
+ if (display_comp_ctx->display_type == kHDMI) {
+ if (hw_panel_info.s3d_mode != kS3DModeNone) {
+ max_layers_ = 0;
+ } else {
+ max_layers_ = kMaxSDELayers;
+ }
+ }
+
+ display_comp_ctx->scaled_composition = NeedsScaledComposition(fb_config, mixer_attributes);
+ // Update new resolution.
+ display_comp_ctx->fb_config = fb_config;
+
+ return error;
+}
+
+void CompManager::PrepareStrategyConstraints(Handle comp_handle, HWLayers *hw_layers) {
+ DisplayCompositionContext *display_comp_ctx =
+ reinterpret_cast<DisplayCompositionContext *>(comp_handle);
+ StrategyConstraints *constraints = &display_comp_ctx->constraints;
+ bool low_end_hw = ((hw_res_info_.num_vig_pipe + hw_res_info_.num_rgb_pipe +
+ hw_res_info_.num_dma_pipe) <= kSafeModeThreshold);
+
+ constraints->safe_mode = safe_mode_;
+ constraints->use_cursor = false;
+ constraints->max_layers = max_layers_;
+
+ // Limit 2 layer SDE Comp if its not a Primary Display.
+ // Safe mode is the policy for External display on a low end device.
+ if (!display_comp_ctx->is_primary_panel) {
+ constraints->max_layers = max_sde_ext_layers_;
+ constraints->safe_mode = (low_end_hw && !hw_res_info_.separate_rotator) ? true : safe_mode_;
+ if(hw_layers->info.stack->flags.secure_present)
+ secure_external_layer_ = true;
+ else
+ secure_external_layer_ = false;
+ }
+
+ // When Secure layer is present on external, GPU composition should be policy
+ // for Primary on low end devices
+ if(display_comp_ctx->is_primary_panel && (registered_displays_.count() > 1)
+ && low_end_hw && secure_external_layer_) {
+ DLOGV_IF(kTagCompManager,"Secure layer present for LET. Fallingback to GPU");
+ hw_layers->info.stack->flags.skip_present = 1;
+ for(auto &layer : hw_layers->info.stack->layers) {
+ if(layer->composition != kCompositionGPUTarget) {
+ layer->flags.skip = 1;
+ }
+ }
+ }
+
+ // If a strategy fails after successfully allocating resources, then set safe mode
+ if (display_comp_ctx->remaining_strategies != display_comp_ctx->max_strategies) {
+ constraints->safe_mode = true;
+ }
+
+ // Set use_cursor constraint to Strategy
+ constraints->use_cursor = display_comp_ctx->valid_cursor;
+
+ // TODO(user): App layer count will change for hybrid composition
+ uint32_t app_layer_count = UINT32(hw_layers->info.stack->layers.size()) - 1;
+ if (display_comp_ctx->idle_fallback || display_comp_ctx->thermal_fallback_) {
+ // Handle the idle timeout by falling back
+ constraints->safe_mode = true;
+ }
+
+ // Avoid safe mode, if there is only one app layer.
+ if (app_layer_count == 1) {
+ constraints->safe_mode = false;
+ }
+}
+
+void CompManager::PrePrepare(Handle display_ctx, HWLayers *hw_layers) {
+ SCOPE_LOCK(locker_);
+ DisplayCompositionContext *display_comp_ctx =
+ reinterpret_cast<DisplayCompositionContext *>(display_ctx);
+ display_comp_ctx->valid_cursor = SupportLayerAsCursor(display_comp_ctx, hw_layers);
+
+ // pu constraints
+ display_comp_ctx->pu_constraints.enable_cursor_pu = display_comp_ctx->valid_cursor;
+
+ display_comp_ctx->strategy->Start(&hw_layers->info, &display_comp_ctx->max_strategies,
+ display_comp_ctx->pu_constraints);
+ display_comp_ctx->remaining_strategies = display_comp_ctx->max_strategies;
+}
+
+DisplayError CompManager::Prepare(Handle display_ctx, HWLayers *hw_layers) {
+ SCOPE_LOCK(locker_);
+
+ DisplayCompositionContext *display_comp_ctx =
+ reinterpret_cast<DisplayCompositionContext *>(display_ctx);
+ Handle &display_resource_ctx = display_comp_ctx->display_resource_ctx;
+
+ DisplayError error = kErrorUndefined;
+
+ PrepareStrategyConstraints(display_ctx, hw_layers);
+
+ // Select a composition strategy, and try to allocate resources for it.
+ resource_intf_->Start(display_resource_ctx);
+
+ bool exit = false;
+ uint32_t &count = display_comp_ctx->remaining_strategies;
+ for (; !exit && count > 0; count--) {
+ error = display_comp_ctx->strategy->GetNextStrategy(&display_comp_ctx->constraints);
+ if (error != kErrorNone) {
+ // Composition strategies exhausted. Resource Manager could not allocate resources even for
+ // GPU composition. This will never happen.
+ exit = true;
+ }
+
+ if (!exit) {
+ error = resource_intf_->Prepare(display_resource_ctx, hw_layers);
+ // Exit if successfully prepared resource, else try next strategy.
+ exit = (error == kErrorNone);
+ }
+ }
+
+ if (error != kErrorNone) {
+ resource_intf_->Stop(display_resource_ctx, hw_layers);
+ DLOGE("Composition strategies exhausted for display = %d", display_comp_ctx->display_type);
+ return error;
+ }
+
+ error = resource_intf_->Stop(display_resource_ctx, hw_layers);
+
+ return error;
+}
+
+DisplayError CompManager::PostPrepare(Handle display_ctx, HWLayers *hw_layers) {
+ SCOPE_LOCK(locker_);
+ DisplayCompositionContext *display_comp_ctx =
+ reinterpret_cast<DisplayCompositionContext *>(display_ctx);
+ Handle &display_resource_ctx = display_comp_ctx->display_resource_ctx;
+
+ DisplayError error = kErrorNone;
+ error = resource_intf_->PostPrepare(display_resource_ctx, hw_layers);
+ if (error != kErrorNone) {
+ return error;
+ }
+
+ display_comp_ctx->strategy->Stop();
+
+ return kErrorNone;
+}
+
+DisplayError CompManager::Commit(Handle display_ctx, HWLayers *hw_layers) {
+ SCOPE_LOCK(locker_);
+
+ DisplayCompositionContext *display_comp_ctx =
+ reinterpret_cast<DisplayCompositionContext *>(display_ctx);
+
+ return resource_intf_->Commit(display_comp_ctx->display_resource_ctx, hw_layers);
+}
+
+DisplayError CompManager::ReConfigure(Handle display_ctx, HWLayers *hw_layers) {
+ SCOPE_LOCK(locker_);
+
+ DisplayCompositionContext *display_comp_ctx =
+ reinterpret_cast<DisplayCompositionContext *>(display_ctx);
+ Handle &display_resource_ctx = display_comp_ctx->display_resource_ctx;
+
+ DisplayError error = kErrorUndefined;
+ resource_intf_->Start(display_resource_ctx);
+ error = resource_intf_->Prepare(display_resource_ctx, hw_layers);
+
+ if (error != kErrorNone) {
+ DLOGE("Reconfigure failed for display = %d", display_comp_ctx->display_type);
+ }
+
+ resource_intf_->Stop(display_resource_ctx, hw_layers);
+ if (error != kErrorNone) {
+ error = resource_intf_->PostPrepare(display_resource_ctx, hw_layers);
+ }
+
+ return error;
+}
+
+DisplayError CompManager::PostCommit(Handle display_ctx, HWLayers *hw_layers) {
+ SCOPE_LOCK(locker_);
+
+ DisplayError error = kErrorNone;
+ DisplayCompositionContext *display_comp_ctx =
+ reinterpret_cast<DisplayCompositionContext *>(display_ctx);
+ configured_displays_[display_comp_ctx->display_type] = 1;
+ if (configured_displays_ == registered_displays_) {
+ safe_mode_ = false;
+ }
+
+ error = resource_intf_->PostCommit(display_comp_ctx->display_resource_ctx, hw_layers);
+ if (error != kErrorNone) {
+ return error;
+ }
+
+ display_comp_ctx->idle_fallback = false;
+
+ DLOGV_IF(kTagCompManager, "registered display bit mask 0x%x, configured display bit mask 0x%x, " \
+ "display type %d", registered_displays_, configured_displays_,
+ display_comp_ctx->display_type);
+
+ return kErrorNone;
+}
+
+void CompManager::Purge(Handle display_ctx) {
+ SCOPE_LOCK(locker_);
+
+ DisplayCompositionContext *display_comp_ctx =
+ reinterpret_cast<DisplayCompositionContext *>(display_ctx);
+
+ resource_intf_->Purge(display_comp_ctx->display_resource_ctx);
+
+ display_comp_ctx->strategy->Purge();
+}
+
+DisplayError CompManager::SetIdleTimeoutMs(Handle display_ctx, uint32_t active_ms) {
+ SCOPE_LOCK(locker_);
+
+ DisplayCompositionContext *display_comp_ctx =
+ reinterpret_cast<DisplayCompositionContext *>(display_ctx);
+
+ return display_comp_ctx->strategy->SetIdleTimeoutMs(active_ms);
+}
+
+void CompManager::ProcessIdleTimeout(Handle display_ctx) {
+ SCOPE_LOCK(locker_);
+
+ DisplayCompositionContext *display_comp_ctx =
+ reinterpret_cast<DisplayCompositionContext *>(display_ctx);
+
+ if (!display_comp_ctx) {
+ return;
+ }
+
+ display_comp_ctx->idle_fallback = true;
+}
+
+void CompManager::ProcessThermalEvent(Handle display_ctx, int64_t thermal_level) {
+ SCOPE_LOCK(locker_);
+
+ DisplayCompositionContext *display_comp_ctx =
+ reinterpret_cast<DisplayCompositionContext *>(display_ctx);
+
+ if (thermal_level >= kMaxThermalLevel) {
+ display_comp_ctx->thermal_fallback_ = true;
+ } else {
+ display_comp_ctx->thermal_fallback_ = false;
+ }
+}
+
+void CompManager::ProcessIdlePowerCollapse(Handle display_ctx) {
+ SCOPE_LOCK(locker_);
+
+ DisplayCompositionContext *display_comp_ctx =
+ reinterpret_cast<DisplayCompositionContext *>(display_ctx);
+
+ if (display_comp_ctx) {
+ resource_intf_->Perform(ResourceInterface::kCmdResetScalarLUT,
+ display_comp_ctx->display_resource_ctx);
+ }
+}
+
+DisplayError CompManager::SetMaxMixerStages(Handle display_ctx, uint32_t max_mixer_stages) {
+ SCOPE_LOCK(locker_);
+
+ DisplayError error = kErrorNone;
+ DisplayCompositionContext *display_comp_ctx =
+ reinterpret_cast<DisplayCompositionContext *>(display_ctx);
+
+ if (display_comp_ctx) {
+ error = resource_intf_->SetMaxMixerStages(display_comp_ctx->display_resource_ctx,
+ max_mixer_stages);
+ }
+
+ return error;
+}
+
+void CompManager::ControlPartialUpdate(Handle display_ctx, bool enable) {
+ SCOPE_LOCK(locker_);
+
+ DisplayCompositionContext *display_comp_ctx =
+ reinterpret_cast<DisplayCompositionContext *>(display_ctx);
+ display_comp_ctx->pu_constraints.enable = enable;
+}
+
+DisplayError CompManager::ValidateScaling(const LayerRect &crop, const LayerRect &dst,
+ bool rotate90) {
+ BufferLayout layout = Debug::IsUbwcTiledFrameBuffer() ? kUBWC : kLinear;
+ return resource_intf_->ValidateScaling(crop, dst, rotate90, layout, true);
+}
+
+DisplayError CompManager::ValidateAndSetCursorPosition(Handle display_ctx, HWLayers *hw_layers,
+ int x, int y) {
+ DisplayCompositionContext *display_comp_ctx =
+ reinterpret_cast<DisplayCompositionContext *>(display_ctx);
+ Handle &display_resource_ctx = display_comp_ctx->display_resource_ctx;
+ return resource_intf_->ValidateAndSetCursorPosition(display_resource_ctx, hw_layers, x, y,
+ &display_comp_ctx->fb_config);
+}
+
+bool CompManager::SupportLayerAsCursor(Handle comp_handle, HWLayers *hw_layers) {
+ DisplayCompositionContext *display_comp_ctx =
+ reinterpret_cast<DisplayCompositionContext *>(comp_handle);
+ Handle &display_resource_ctx = display_comp_ctx->display_resource_ctx;
+ LayerStack *layer_stack = hw_layers->info.stack;
+ bool supported = false;
+ int32_t gpu_index = -1;
+
+ // HW Cursor cannot be used, if Display configuration needs scaled composition.
+ if (display_comp_ctx->scaled_composition || !layer_stack->flags.cursor_present) {
+ return supported;
+ }
+
+ for (int32_t i = INT32(layer_stack->layers.size() - 1); i >= 0; i--) {
+ Layer *layer = layer_stack->layers.at(UINT32(i));
+ if (layer->composition == kCompositionGPUTarget) {
+ gpu_index = i;
+ break;
+ }
+ }
+ if (gpu_index <= 0) {
+ return supported;
+ }
+ Layer *cursor_layer = layer_stack->layers.at(UINT32(gpu_index) - 1);
+ if (cursor_layer->flags.cursor && !cursor_layer->flags.skip &&
+ resource_intf_->ValidateCursorConfig(display_resource_ctx,
+ cursor_layer, true) == kErrorNone) {
+ supported = true;
+ }
+
+ return supported;
+}
+
+DisplayError CompManager::SetMaxBandwidthMode(HWBwModes mode) {
+ if ((hw_res_info_.has_dyn_bw_support == false) || (mode >= kBwModeMax)) {
+ return kErrorNotSupported;
+ }
+
+ return resource_intf_->SetMaxBandwidthMode(mode);
+}
+
+DisplayError CompManager::GetScaleLutConfig(HWScaleLutInfo *lut_info) {
+ return resource_intf_->GetScaleLutConfig(lut_info);
+}
+
+DisplayError CompManager::SetDetailEnhancerData(Handle display_ctx,
+ const DisplayDetailEnhancerData &de_data) {
+ SCOPE_LOCK(locker_);
+
+ DisplayCompositionContext *display_comp_ctx =
+ reinterpret_cast<DisplayCompositionContext *>(display_ctx);
+
+ return resource_intf_->SetDetailEnhancerData(display_comp_ctx->display_resource_ctx, de_data);
+}
+
+DisplayError CompManager::SetCompositionState(Handle display_ctx,
+ LayerComposition composition_type, bool enable) {
+ SCOPE_LOCK(locker_);
+
+ DisplayCompositionContext *display_comp_ctx =
+ reinterpret_cast<DisplayCompositionContext *>(display_ctx);
+
+ return display_comp_ctx->strategy->SetCompositionState(composition_type, enable);
+}
+
+DisplayError CompManager::ControlDpps(bool enable) {
+ if (dpps_ctrl_intf_) {
+ return enable ? dpps_ctrl_intf_->On() : dpps_ctrl_intf_->Off();
+ }
+
+ return kErrorNone;
+}
+
+bool CompManager::SetDisplayState(Handle display_ctx,
+ DisplayState state, DisplayType display_type) {
+ display_state_[display_type] = state;
+
+ switch (state) {
+ case kStateOff:
+ Purge(display_ctx);
+ configured_displays_.reset(display_type);
+ DLOGV_IF(kTagCompManager, "configured_displays_ = 0x%x", configured_displays_);
+ break;
+
+ case kStateOn:
+ if (registered_displays_.count() > 1) {
+ safe_mode_ = true;
+ DLOGV_IF(kTagCompManager, "safe_mode = %d", safe_mode_);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return true;
+}
+
+} // namespace sdm
diff --git a/msm8909/sdm/libs/core/comp_manager.h b/msm8909/sdm/libs/core/comp_manager.h
new file mode 100644
index 00000000..d1351aeb
--- /dev/null
+++ b/msm8909/sdm/libs/core/comp_manager.h
@@ -0,0 +1,123 @@
+/*
+* Copyright (c) 2014 - 2017, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without modification, are permitted
+* provided that the following conditions are met:
+* * Redistributions of source code must retain the above copyright notice, this list of
+* conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright notice, this list of
+* conditions and the following disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its contributors may be used to
+* endorse or promote products derived from this software without specific prior written
+* permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __COMP_MANAGER_H__
+#define __COMP_MANAGER_H__
+
+#include <core/display_interface.h>
+#include <private/extension_interface.h>
+#include <utils/locker.h>
+#include <bitset>
+
+#include "strategy.h"
+#include "resource_default.h"
+#include "hw_interface.h"
+
+namespace sdm {
+
+class CompManager {
+ public:
+ DisplayError Init(const HWResourceInfo &hw_res_info_, ExtensionInterface *extension_intf,
+ BufferAllocator *buffer_allocator, BufferSyncHandler *buffer_sync_handler,
+ SocketHandler *socket_handler);
+ DisplayError Deinit();
+ DisplayError RegisterDisplay(DisplayType type, const HWDisplayAttributes &display_attributes,
+ const HWPanelInfo &hw_panel_info,
+ const HWMixerAttributes &mixer_attributes,
+ const DisplayConfigVariableInfo &fb_config, Handle *display_ctx);
+ DisplayError UnregisterDisplay(Handle display_ctx);
+ DisplayError ReconfigureDisplay(Handle display_ctx, const HWDisplayAttributes &display_attributes,
+ const HWPanelInfo &hw_panel_info,
+ const HWMixerAttributes &mixer_attributes,
+ const DisplayConfigVariableInfo &fb_config);
+ void PrePrepare(Handle display_ctx, HWLayers *hw_layers);
+ DisplayError Prepare(Handle display_ctx, HWLayers *hw_layers);
+ DisplayError Commit(Handle display_ctx, HWLayers *hw_layers);
+ DisplayError PostPrepare(Handle display_ctx, HWLayers *hw_layers);
+ DisplayError ReConfigure(Handle display_ctx, HWLayers *hw_layers);
+ DisplayError PostCommit(Handle display_ctx, HWLayers *hw_layers);
+ void Purge(Handle display_ctx);
+ DisplayError SetIdleTimeoutMs(Handle display_ctx, uint32_t active_ms);
+ void ProcessIdleTimeout(Handle display_ctx);
+ void ProcessThermalEvent(Handle display_ctx, int64_t thermal_level);
+ void ProcessIdlePowerCollapse(Handle display_ctx);
+ DisplayError SetMaxMixerStages(Handle display_ctx, uint32_t max_mixer_stages);
+ void ControlPartialUpdate(Handle display_ctx, bool enable);
+ DisplayError ValidateScaling(const LayerRect &crop, const LayerRect &dst, bool rotate90);
+ DisplayError ValidateCursorPosition(Handle display_ctx, HWLayers *hw_layers, int x, int y);
+ bool SupportLayerAsCursor(Handle display_ctx, HWLayers *hw_layers);
+ DisplayError ValidateAndSetCursorPosition(Handle display_ctx, HWLayers *hw_layers, int x, int y);
+ bool SetDisplayState(Handle display_ctx, DisplayState state, DisplayType display_type);
+ DisplayError SetMaxBandwidthMode(HWBwModes mode);
+ DisplayError GetScaleLutConfig(HWScaleLutInfo *lut_info);
+ DisplayError SetDetailEnhancerData(Handle display_ctx, const DisplayDetailEnhancerData &de_data);
+ DisplayError SetCompositionState(Handle display_ctx, LayerComposition composition_type,
+ bool enable);
+ DisplayError ControlDpps(bool enable);
+
+ private:
+ static const int kMaxThermalLevel = 3;
+ static const int kSafeModeThreshold = 4;
+
+ void PrepareStrategyConstraints(Handle display_ctx, HWLayers *hw_layers);
+
+ struct DisplayCompositionContext {
+ Strategy *strategy = NULL;
+ StrategyConstraints constraints;
+ Handle display_resource_ctx = NULL;
+ DisplayType display_type = kPrimary;
+ uint32_t max_strategies = 0;
+ uint32_t remaining_strategies = 0;
+ bool idle_fallback = false;
+ bool thermal_fallback_ = false;
+ // Using primary panel flag of hw panel to configure Constraints. We do not need other hw
+ // panel parameters for now.
+ bool is_primary_panel = false;
+ bool valid_cursor = false;
+ PUConstraints pu_constraints = {};
+ bool scaled_composition = false;
+ DisplayConfigVariableInfo fb_config = {};
+ };
+
+ Locker locker_;
+ ResourceInterface *resource_intf_ = NULL;
+ std::bitset<kDisplayMax> registered_displays_; // Bit mask of registered displays
+ std::bitset<kDisplayMax> configured_displays_; // Bit mask of sucessfully configured displays
+ uint32_t display_state_[kDisplayMax] = {};
+ bool safe_mode_ = false; // Flag to notify all displays to be in resource crunch
+ // mode, where strategy manager chooses the best strategy
+ // that uses optimal number of pipes for each display
+ bool secure_external_layer_ = false;
+ HWResourceInfo hw_res_info_;
+ BufferAllocator *buffer_allocator_ = NULL;
+ ExtensionInterface *extension_intf_ = NULL;
+ uint32_t max_layers_ = kMaxSDELayers;
+ uint32_t max_sde_ext_layers_ = 0;
+ DppsControlInterface *dpps_ctrl_intf_ = NULL;
+};
+
+} // namespace sdm
+
+#endif // __COMP_MANAGER_H__
+
diff --git a/msm8909/sdm/libs/core/core_impl.cpp b/msm8909/sdm/libs/core/core_impl.cpp
new file mode 100644
index 00000000..212612c2
--- /dev/null
+++ b/msm8909/sdm/libs/core/core_impl.cpp
@@ -0,0 +1,188 @@
+/*
+* Copyright (c) 2014 - 2018, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without modification, are permitted
+* provided that the following conditions are met:
+* * Redistributions of source code must retain the above copyright notice, this list of
+* conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright notice, this list of
+* conditions and the following disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its contributors may be used to
+* endorse or promote products derived from this software without specific prior written
+* permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <dlfcn.h>
+#include <utils/locker.h>
+#include <utils/constants.h>
+#include <utils/debug.h>
+
+#include "core_impl.h"
+#include "display_primary.h"
+#include "display_hdmi.h"
+#include "display_virtual.h"
+#include "hw_info_interface.h"
+#include "color_manager.h"
+
+#define __CLASS__ "CoreImpl"
+
+namespace sdm {
+
+CoreImpl::CoreImpl(BufferAllocator *buffer_allocator,
+ BufferSyncHandler *buffer_sync_handler,
+ SocketHandler *socket_handler)
+ : buffer_allocator_(buffer_allocator), buffer_sync_handler_(buffer_sync_handler),
+ socket_handler_(socket_handler) {
+}
+
+DisplayError CoreImpl::Init() {
+ SCOPE_LOCK(locker_);
+ DisplayError error = kErrorNone;
+
+ // Try to load extension library & get handle to its interface.
+ if (extension_lib_.Open(EXTENSION_LIBRARY_NAME)) {
+ if (!extension_lib_.Sym(CREATE_EXTENSION_INTERFACE_NAME,
+ reinterpret_cast<void **>(&create_extension_intf_)) ||
+ !extension_lib_.Sym(DESTROY_EXTENSION_INTERFACE_NAME,
+ reinterpret_cast<void **>(&destroy_extension_intf_))) {
+ DLOGE("Unable to load symbols, error = %s", extension_lib_.Error());
+ return kErrorUndefined;
+ }
+
+ error = create_extension_intf_(EXTENSION_VERSION_TAG, &extension_intf_);
+ if (error != kErrorNone) {
+ DLOGE("Unable to create interface");
+ return error;
+ }
+ } else {
+ DLOGW("Unable to load = %s, error = %s", EXTENSION_LIBRARY_NAME, extension_lib_.Error());
+ }
+
+ error = HWInfoInterface::Create(&hw_info_intf_);
+ if (error != kErrorNone) {
+ goto CleanupOnError;
+ }
+
+ if (hw_info_intf_ == NULL) {
+ return kErrorResources;
+ }
+ error = hw_info_intf_->GetHWResourceInfo(&hw_resource_);
+ if (error != kErrorNone) {
+ goto CleanupOnError;
+ }
+
+ error = comp_mgr_.Init(hw_resource_, extension_intf_, buffer_allocator_,
+ buffer_sync_handler_, socket_handler_);
+
+ if (error != kErrorNone) {
+ goto CleanupOnError;
+ }
+
+ error = ColorManagerProxy::Init(hw_resource_);
+ // if failed, doesn't affect display core functionalities.
+ if (error != kErrorNone) {
+ DLOGW("Unable creating color manager and continue without it.");
+ }
+
+ return kErrorNone;
+
+CleanupOnError:
+ if (hw_info_intf_) {
+ HWInfoInterface::Destroy(hw_info_intf_);
+ }
+
+ return error;
+}
+
+DisplayError CoreImpl::Deinit() {
+ SCOPE_LOCK(locker_);
+
+ ColorManagerProxy::Deinit();
+
+ comp_mgr_.Deinit();
+ HWInfoInterface::Destroy(hw_info_intf_);
+
+ return kErrorNone;
+}
+
+DisplayError CoreImpl::CreateDisplay(DisplayType type, DisplayEventHandler *event_handler,
+ DisplayInterface **intf) {
+ SCOPE_LOCK(locker_);
+
+ if (!event_handler || !intf) {
+ return kErrorParameters;
+ }
+
+ DisplayBase *display_base = NULL;
+
+ switch (type) {
+ case kPrimary:
+ display_base = new DisplayPrimary(event_handler, hw_info_intf_, buffer_sync_handler_,
+ buffer_allocator_, &comp_mgr_);
+ break;
+ case kHDMI:
+ display_base = new DisplayHDMI(event_handler, hw_info_intf_, buffer_sync_handler_,
+ buffer_allocator_, &comp_mgr_);
+ break;
+ case kVirtual:
+ display_base = new DisplayVirtual(event_handler, hw_info_intf_, buffer_sync_handler_,
+ buffer_allocator_, &comp_mgr_);
+ break;
+ default:
+ DLOGE("Spurious display type %d", type);
+ return kErrorParameters;
+ }
+
+ if (!display_base) {
+ return kErrorMemory;
+ }
+
+ DisplayError error = display_base->Init();
+ if (error != kErrorNone) {
+ delete display_base;
+ return error;
+ }
+
+ *intf = display_base;
+ return kErrorNone;
+}
+
+DisplayError CoreImpl::DestroyDisplay(DisplayInterface *intf) {
+ SCOPE_LOCK(locker_);
+
+ if (!intf) {
+ return kErrorParameters;
+ }
+
+ DisplayBase *display_base = static_cast<DisplayBase *>(intf);
+ display_base->Deinit();
+ delete display_base;
+
+ return kErrorNone;
+}
+
+DisplayError CoreImpl::SetMaxBandwidthMode(HWBwModes mode) {
+ SCOPE_LOCK(locker_);
+
+ return comp_mgr_.SetMaxBandwidthMode(mode);
+}
+
+DisplayError CoreImpl::GetFirstDisplayInterfaceType(HWDisplayInterfaceInfo *hw_disp_info) {
+ return hw_info_intf_->GetFirstDisplayInterfaceType(hw_disp_info);
+}
+
+bool CoreImpl::IsColorTransformSupported() {
+ return (hw_resource_.has_ppp) ? false : true;
+}
+} // namespace sdm
+
diff --git a/msm8909/sdm/libs/core/core_impl.h b/msm8909/sdm/libs/core/core_impl.h
new file mode 100644
index 00000000..e5156aae
--- /dev/null
+++ b/msm8909/sdm/libs/core/core_impl.h
@@ -0,0 +1,80 @@
+/*
+* Copyright (c) 2014 - 2016, 2018 The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without modification, are permitted
+* provided that the following conditions are met:
+* * Redistributions of source code must retain the above copyright notice, this list of
+* conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright notice, this list of
+* conditions and the following disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its contributors may be used to
+* endorse or promote products derived from this software without specific prior written
+* permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __CORE_IMPL_H__
+#define __CORE_IMPL_H__
+
+#include <core/core_interface.h>
+#include <private/extension_interface.h>
+#include <private/color_interface.h>
+#include <utils/locker.h>
+#include <utils/sys.h>
+
+#include "hw_interface.h"
+#include "comp_manager.h"
+
+#define SET_REVISION(major, minor) ((major << 8) | minor)
+
+namespace sdm {
+
+class CoreImpl : public CoreInterface {
+ public:
+ // This class implements display core interface revision 1.0.
+ static const uint16_t kRevision = SET_REVISION(1, 0);
+ CoreImpl(BufferAllocator *buffer_allocator, BufferSyncHandler *buffer_sync_handler,
+ SocketHandler *socket_handler);
+ virtual ~CoreImpl() { }
+
+ // This method returns the interface revision for the current display core object.
+ // Future revisions will override this method and return the appropriate revision upon query.
+ virtual uint16_t GetRevision() { return kRevision; }
+ virtual DisplayError Init();
+ virtual DisplayError Deinit();
+
+ // Methods from core interface
+ virtual DisplayError CreateDisplay(DisplayType type, DisplayEventHandler *event_handler,
+ DisplayInterface **intf);
+ virtual DisplayError DestroyDisplay(DisplayInterface *intf);
+ virtual DisplayError SetMaxBandwidthMode(HWBwModes mode);
+ virtual DisplayError GetFirstDisplayInterfaceType(HWDisplayInterfaceInfo *hw_disp_info);
+ virtual bool IsColorTransformSupported();
+
+ protected:
+ Locker locker_;
+ BufferAllocator *buffer_allocator_ = NULL;
+ BufferSyncHandler *buffer_sync_handler_ = NULL;
+ HWResourceInfo hw_resource_;
+ CompManager comp_mgr_;
+ HWInfoInterface *hw_info_intf_ = NULL;
+ DynLib extension_lib_;
+ ExtensionInterface *extension_intf_ = NULL;
+ CreateExtensionInterface create_extension_intf_ = NULL;
+ DestroyExtensionInterface destroy_extension_intf_ = NULL;
+ SocketHandler *socket_handler_ = NULL;
+};
+
+} // namespace sdm
+
+#endif // __CORE_IMPL_H__
+
diff --git a/msm8909/sdm/libs/core/core_interface.cpp b/msm8909/sdm/libs/core/core_interface.cpp
new file mode 100644
index 00000000..911ad014
--- /dev/null
+++ b/msm8909/sdm/libs/core/core_interface.cpp
@@ -0,0 +1,133 @@
+/*
+* Copyright (c) 2014 - 2015, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <utils/locker.h>
+#include <utils/constants.h>
+#include <utils/debug.h>
+#include <core/buffer_sync_handler.h>
+
+#include "core_impl.h"
+
+#define __CLASS__ "CoreInterface"
+
+#define GET_REVISION(version) (version >> 16)
+#define GET_DATA_ALIGNMENT(version) ((version >> 8) & 0xFF)
+#define GET_INSTRUCTION_SET(version) (version & 0xFF)
+
+namespace sdm {
+
+// Currently, we support only one client and one session for display core. So, create a global
+// singleton core object.
+struct CoreSingleton {
+ CoreSingleton() : core_impl(NULL) { }
+
+ CoreImpl *core_impl;
+ Locker locker;
+} g_core;
+
+// TODO(user): Have a single structure handle carries all the interface pointers.
+DisplayError CoreInterface::CreateCore(DebugHandler *debug_handler,
+ BufferAllocator *buffer_allocator,
+ BufferSyncHandler *buffer_sync_handler,
+ CoreInterface **interface, uint32_t client_version) {
+ return CreateCore(debug_handler, buffer_allocator, buffer_sync_handler, NULL,
+ interface, client_version);
+}
+
+DisplayError CoreInterface::CreateCore(DebugHandler *debug_handler,
+ BufferAllocator *buffer_allocator,
+ BufferSyncHandler *buffer_sync_handler,
+ SocketHandler *socket_handler,
+ CoreInterface **interface, uint32_t client_version) {
+ SCOPE_LOCK(g_core.locker);
+
+ if (!debug_handler || !buffer_allocator || !buffer_sync_handler || !interface) {
+ return kErrorParameters;
+ }
+
+ // Check compatibility of client and core.
+ uint32_t lib_version = SDM_VERSION_TAG;
+ if (GET_REVISION(client_version) > GET_REVISION(lib_version)) {
+ return kErrorVersion;
+ } else if (GET_DATA_ALIGNMENT(client_version) != GET_DATA_ALIGNMENT(lib_version)) {
+ return kErrorDataAlignment;
+ } else if (GET_INSTRUCTION_SET(client_version) != GET_INSTRUCTION_SET(lib_version)) {
+ return kErrorInstructionSet;
+ }
+
+ CoreImpl *&core_impl = g_core.core_impl;
+ if (core_impl) {
+ return kErrorUndefined;
+ }
+
+ Debug::SetDebugHandler(debug_handler);
+
+ // Create appropriate CoreImpl object based on client version.
+ if (GET_REVISION(client_version) == CoreImpl::kRevision) {
+ core_impl = new CoreImpl(buffer_allocator, buffer_sync_handler, socket_handler);
+ } else {
+ return kErrorNotSupported;
+ }
+
+ if (!core_impl) {
+ return kErrorMemory;
+ }
+
+ DisplayError error = core_impl->Init();
+ if (error != kErrorNone) {
+ delete core_impl;
+ core_impl = NULL;
+ return error;
+ }
+
+ *interface = core_impl;
+ DLOGI("Open interface handle = %p", *interface);
+
+ return kErrorNone;
+}
+
+DisplayError CoreInterface::DestroyCore() {
+ SCOPE_LOCK(g_core.locker);
+
+ DLOGI("Close handle");
+
+ CoreImpl *&core_impl = g_core.core_impl;
+ if (!core_impl) {
+ return kErrorUndefined;
+ }
+
+ core_impl->Deinit();
+ delete core_impl;
+ core_impl = NULL;
+
+ return kErrorNone;
+}
+
+} // namespace sdm
+
diff --git a/msm8909/sdm/libs/core/display_base.cpp b/msm8909/sdm/libs/core/display_base.cpp
new file mode 100644
index 00000000..82467379
--- /dev/null
+++ b/msm8909/sdm/libs/core/display_base.cpp
@@ -0,0 +1,1536 @@
+/*
+* Copyright (c) 2014 - 2018, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without modification, are permitted
+* provided that the following conditions are met:
+* * Redistributions of source code must retain the above copyright notice, this list of
+* conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright notice, this list of
+* conditions and the following disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its contributors may be used to
+* endorse or promote products derived from this software without specific prior written
+* permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <stdio.h>
+#include <utils/constants.h>
+#include <utils/debug.h>
+#include <utils/formats.h>
+#include <utils/rect.h>
+#include <utils/utils.h>
+
+#include <iomanip>
+#include <map>
+#include <sstream>
+#include <string>
+#include <vector>
+#include <algorithm>
+
+#include "display_base.h"
+#include "hw_info_interface.h"
+
+#define __CLASS__ "DisplayBase"
+
+namespace sdm {
+
+// TODO(user): Have a single structure handle carries all the interface pointers and variables.
+DisplayBase::DisplayBase(DisplayType display_type, DisplayEventHandler *event_handler,
+ HWDeviceType hw_device_type, BufferSyncHandler *buffer_sync_handler,
+ BufferAllocator *buffer_allocator, CompManager *comp_manager,
+ HWInfoInterface *hw_info_intf)
+ : display_type_(display_type), event_handler_(event_handler), hw_device_type_(hw_device_type),
+ buffer_sync_handler_(buffer_sync_handler), buffer_allocator_(buffer_allocator),
+ comp_manager_(comp_manager), hw_info_intf_(hw_info_intf) {
+}
+
+DisplayError DisplayBase::Init() {
+ lock_guard<recursive_mutex> obj(recursive_mutex_);
+ DisplayError error = kErrorNone;
+ hw_panel_info_ = HWPanelInfo();
+ hw_intf_->GetHWPanelInfo(&hw_panel_info_);
+
+ uint32_t active_index = 0;
+ hw_intf_->GetActiveConfig(&active_index);
+ hw_intf_->GetDisplayAttributes(active_index, &display_attributes_);
+ fb_config_ = display_attributes_;
+
+ error = Debug::GetMixerResolution(&mixer_attributes_.width, &mixer_attributes_.height);
+ if (error == kErrorNone) {
+ hw_intf_->SetMixerAttributes(mixer_attributes_);
+ }
+
+ error = hw_intf_->GetMixerAttributes(&mixer_attributes_);
+ if (error != kErrorNone) {
+ return error;
+ }
+
+ // Override x_pixels and y_pixels of frame buffer with mixer width and height
+ fb_config_.x_pixels = mixer_attributes_.width;
+ fb_config_.y_pixels = mixer_attributes_.height;
+
+ HWScaleLutInfo lut_info = {};
+ error = comp_manager_->GetScaleLutConfig(&lut_info);
+ if (error == kErrorNone) {
+ error = hw_intf_->SetScaleLutConfig(&lut_info);
+ if (error != kErrorNone) {
+ goto CleanupOnError;
+ }
+ }
+
+ error = comp_manager_->RegisterDisplay(display_type_, display_attributes_, hw_panel_info_,
+ mixer_attributes_, fb_config_, &display_comp_ctx_);
+ if (error != kErrorNone) {
+ goto CleanupOnError;
+ }
+
+ if (hw_info_intf_) {
+ HWResourceInfo hw_resource_info = HWResourceInfo();
+ hw_info_intf_->GetHWResourceInfo(&hw_resource_info);
+ auto max_mixer_stages = hw_resource_info.num_blending_stages;
+ int property_value = Debug::GetMaxPipesPerMixer(display_type_);
+ if (property_value >= 0) {
+ max_mixer_stages = std::min(UINT32(property_value), hw_resource_info.num_blending_stages);
+ }
+ DisplayBase::SetMaxMixerStages(max_mixer_stages);
+ }
+
+ color_mgr_ = ColorManagerProxy::CreateColorManagerProxy(display_type_, hw_intf_,
+ display_attributes_, hw_panel_info_);
+ if (!color_mgr_) {
+ DLOGW("Unable to create ColorManagerProxy for display = %d", display_type_);
+ } else if (InitializeColorModes() != kErrorNone) {
+ DLOGW("InitColorModes failed for display = %d", display_type_);
+ }
+
+ Debug::Get()->GetProperty(DISABLE_HDR_LUT_GEN, &disable_hdr_lut_gen_);
+
+ return kErrorNone;
+
+CleanupOnError:
+ if (display_comp_ctx_) {
+ comp_manager_->UnregisterDisplay(display_comp_ctx_);
+ }
+
+ return error;
+}
+
+DisplayError DisplayBase::Deinit() {
+ { // Scope for lock
+ lock_guard<recursive_mutex> obj(recursive_mutex_);
+ color_modes_.clear();
+ color_mode_map_.clear();
+ color_mode_attr_map_.clear();
+
+ if (color_mgr_) {
+ delete color_mgr_;
+ color_mgr_ = NULL;
+ }
+
+ comp_manager_->UnregisterDisplay(display_comp_ctx_);
+ }
+ HWEventsInterface::Destroy(hw_events_intf_);
+ HWInterface::Destroy(hw_intf_);
+
+ return kErrorNone;
+}
+
+DisplayError DisplayBase::BuildLayerStackStats(LayerStack *layer_stack) {
+ std::vector<Layer *> &layers = layer_stack->layers;
+ HWLayersInfo &hw_layers_info = hw_layers_.info;
+
+ hw_layers_info.stack = layer_stack;
+
+ for (auto &layer : layers) {
+ if (layer->composition == kCompositionGPUTarget) {
+ hw_layers_info.gpu_target_index = hw_layers_info.app_layer_count;
+ break;
+ }
+ hw_layers_info.app_layer_count++;
+ }
+
+ DLOGD_IF(kTagNone, "LayerStack layer_count: %d, app_layer_count: %d, gpu_target_index: %d, "
+ "display type: %d", layers.size(), hw_layers_info.app_layer_count,
+ hw_layers_info.gpu_target_index, display_type_);
+
+ if (!hw_layers_info.app_layer_count) {
+ DLOGW("Layer count is zero");
+ return kErrorNoAppLayers;
+ }
+
+ if (hw_layers_info.gpu_target_index) {
+ return ValidateGPUTargetParams();
+ }
+
+ return kErrorNone;
+}
+
+DisplayError DisplayBase::ValidateGPUTargetParams() {
+ HWLayersInfo &hw_layers_info = hw_layers_.info;
+ Layer *gpu_target_layer = hw_layers_info.stack->layers.at(hw_layers_info.gpu_target_index);
+
+ if (!IsValid(gpu_target_layer->src_rect)) {
+ DLOGE("Invalid src rect for GPU target layer");
+ return kErrorParameters;
+ }
+
+ if (!IsValid(gpu_target_layer->dst_rect)) {
+ DLOGE("Invalid dst rect for GPU target layer");
+ return kErrorParameters;
+ }
+
+ float layer_mixer_width = FLOAT(mixer_attributes_.width);
+ float layer_mixer_height = FLOAT(mixer_attributes_.height);
+ float fb_width = FLOAT(fb_config_.x_pixels);
+ float fb_height = FLOAT(fb_config_.y_pixels);
+ LayerRect src_domain = (LayerRect){0.0f, 0.0f, fb_width, fb_height};
+ LayerRect dst_domain = (LayerRect){0.0f, 0.0f, layer_mixer_width, layer_mixer_height};
+ LayerRect out_rect = gpu_target_layer->dst_rect;
+
+ MapRect(src_domain, dst_domain, gpu_target_layer->dst_rect, &out_rect);
+ Normalize(1, 1, &out_rect);
+
+ auto gpu_target_layer_dst_xpixels = out_rect.right - out_rect.left;
+ auto gpu_target_layer_dst_ypixels = out_rect.bottom - out_rect.top;
+
+ if (gpu_target_layer_dst_xpixels > mixer_attributes_.width ||
+ gpu_target_layer_dst_ypixels > mixer_attributes_.height) {
+ DLOGE("GPU target layer dst rect is not with in limits gpu wxh %fx%f, mixer wxh %dx%d",
+ gpu_target_layer_dst_xpixels, gpu_target_layer_dst_ypixels,
+ mixer_attributes_.width, mixer_attributes_.height);
+ return kErrorParameters;
+ }
+
+ return kErrorNone;
+}
+
+DisplayError DisplayBase::Prepare(LayerStack *layer_stack) {
+ lock_guard<recursive_mutex> obj(recursive_mutex_);
+ DisplayError error = kErrorNone;
+ needs_validate_ = true;
+
+ if (!active_) {
+ return kErrorPermission;
+ }
+
+ if (!layer_stack) {
+ return kErrorParameters;
+ }
+
+ DLOGI_IF(kTagDisplay, "Entering Prepare for display type : %d", display_type_);
+ error = BuildLayerStackStats(layer_stack);
+ if (error != kErrorNone) {
+ return error;
+ }
+
+ error = HandleHDR(layer_stack);
+ if (error != kErrorNone) {
+ DLOGW("HandleHDR failed");
+ return error;
+ }
+
+ if (color_mgr_ && color_mgr_->NeedsPartialUpdateDisable()) {
+ DisablePartialUpdateOneFrame();
+ }
+
+ if (partial_update_control_ == false || disable_pu_one_frame_) {
+ comp_manager_->ControlPartialUpdate(display_comp_ctx_, false /* enable */);
+ disable_pu_one_frame_ = false;
+ }
+
+ comp_manager_->PrePrepare(display_comp_ctx_, &hw_layers_);
+ while (true) {
+ error = comp_manager_->Prepare(display_comp_ctx_, &hw_layers_);
+ if (error != kErrorNone) {
+ break;
+ }
+
+ error = hw_intf_->Validate(&hw_layers_);
+ if (error == kErrorNone) {
+ // Strategy is successful now, wait for Commit().
+ needs_validate_ = false;
+ break;
+ }
+ if (error == kErrorShutDown) {
+ comp_manager_->PostPrepare(display_comp_ctx_, &hw_layers_);
+ return error;
+ }
+ }
+
+ comp_manager_->PostPrepare(display_comp_ctx_, &hw_layers_);
+
+ DLOGI_IF(kTagDisplay, "Exiting Prepare for display type : %d", display_type_);
+ return error;
+}
+
+DisplayError DisplayBase::Commit(LayerStack *layer_stack) {
+ lock_guard<recursive_mutex> obj(recursive_mutex_);
+ DisplayError error = kErrorNone;
+
+ if (!active_) {
+ needs_validate_ = true;
+ return kErrorPermission;
+ }
+
+ if (!layer_stack) {
+ return kErrorParameters;
+ }
+
+ if (needs_validate_) {
+ DLOGE("Commit: Corresponding Prepare() is not called for display = %d", display_type_);
+ return kErrorNotValidated;
+ }
+
+ // Layer stack attributes has changed, need to Reconfigure, currently in use for Hybrid Comp
+ if (layer_stack->flags.attributes_changed) {
+ error = comp_manager_->ReConfigure(display_comp_ctx_, &hw_layers_);
+ if (error != kErrorNone) {
+ return error;
+ }
+
+ error = hw_intf_->Validate(&hw_layers_);
+ if (error != kErrorNone) {
+ return error;
+ }
+ }
+
+ DLOGI_IF(kTagDisplay, "Entering commit for display type : %d", display_type_);
+ CommitLayerParams(layer_stack);
+
+ error = comp_manager_->Commit(display_comp_ctx_, &hw_layers_);
+ if (error != kErrorNone) {
+ return error;
+ }
+
+ // check if feature list cache is dirty and pending.
+ // If dirty, need program to hardware blocks.
+ if (color_mgr_)
+ error = color_mgr_->Commit();
+ if (error != kErrorNone) { // won't affect this execution path.
+ DLOGW("ColorManager::Commit(...) isn't working");
+ }
+
+ error = hw_intf_->Commit(&hw_layers_);
+ if (error != kErrorNone) {
+ return error;
+ }
+
+ PostCommitLayerParams(layer_stack);
+
+ if (partial_update_control_) {
+ comp_manager_->ControlPartialUpdate(display_comp_ctx_, true /* enable */);
+ }
+
+ error = comp_manager_->PostCommit(display_comp_ctx_, &hw_layers_);
+ if (error != kErrorNone) {
+ return error;
+ }
+
+ DLOGI_IF(kTagDisplay, "Exiting commit for display type : %d", display_type_);
+ return kErrorNone;
+}
+
+DisplayError DisplayBase::Flush() {
+ lock_guard<recursive_mutex> obj(recursive_mutex_);
+ DisplayError error = kErrorNone;
+
+ if (!active_) {
+ return kErrorPermission;
+ }
+ hw_layers_.info.hw_layers.clear();
+ error = hw_intf_->Flush();
+ if (error == kErrorNone) {
+ comp_manager_->Purge(display_comp_ctx_);
+ needs_validate_ = true;
+ } else {
+ DLOGW("Unable to flush display = %d", display_type_);
+ }
+
+ return error;
+}
+
+DisplayError DisplayBase::GetDisplayState(DisplayState *state) {
+ lock_guard<recursive_mutex> obj(recursive_mutex_);
+ if (!state) {
+ return kErrorParameters;
+ }
+
+ *state = state_;
+ return kErrorNone;
+}
+
+DisplayError DisplayBase::GetNumVariableInfoConfigs(uint32_t *count) {
+ lock_guard<recursive_mutex> obj(recursive_mutex_);
+ return hw_intf_->GetNumDisplayAttributes(count);
+}
+
+DisplayError DisplayBase::GetConfig(uint32_t index, DisplayConfigVariableInfo *variable_info) {
+ lock_guard<recursive_mutex> obj(recursive_mutex_);
+ HWDisplayAttributes attrib;
+ if (hw_intf_->GetDisplayAttributes(index, &attrib) == kErrorNone) {
+ *variable_info = attrib;
+ return kErrorNone;
+ }
+
+ return kErrorNotSupported;
+}
+
+DisplayError DisplayBase::GetConfig(DisplayConfigFixedInfo *fixed_info) {
+ lock_guard<recursive_mutex> obj(recursive_mutex_);
+ fixed_info->is_cmdmode = (hw_panel_info_.mode == kModeCommand);
+
+ HWResourceInfo hw_resource_info = HWResourceInfo();
+ hw_info_intf_->GetHWResourceInfo(&hw_resource_info);
+ // hdr can be supported by display when target and panel supports HDR.
+ fixed_info->hdr_supported = (hw_resource_info.has_hdr && hw_panel_info_.hdr_enabled);
+ // Populate luminance values only if hdr will be supported on that display
+ fixed_info->max_luminance = fixed_info->hdr_supported ? hw_panel_info_.peak_luminance: 0;
+ fixed_info->average_luminance = fixed_info->hdr_supported ? hw_panel_info_.average_luminance : 0;
+ fixed_info->min_luminance = fixed_info->hdr_supported ? hw_panel_info_.blackness_level: 0;
+
+ return kErrorNone;
+}
+
+DisplayError DisplayBase::GetActiveConfig(uint32_t *index) {
+ lock_guard<recursive_mutex> obj(recursive_mutex_);
+ return hw_intf_->GetActiveConfig(index);
+}
+
+DisplayError DisplayBase::GetVSyncState(bool *enabled) {
+ lock_guard<recursive_mutex> obj(recursive_mutex_);
+ if (!enabled) {
+ return kErrorParameters;
+ }
+
+ *enabled = vsync_enable_;
+
+ return kErrorNone;
+}
+
+DisplayError DisplayBase::SetDisplayState(DisplayState state) {
+ lock_guard<recursive_mutex> obj(recursive_mutex_);
+ DisplayError error = kErrorNone;
+ bool active = false;
+
+ DLOGI("Set state = %d, display %d", state, display_type_);
+
+ if (state == state_) {
+ DLOGI("Same state transition is requested.");
+ return kErrorNone;
+ }
+
+ switch (state) {
+ case kStateOff:
+ hw_layers_.info.hw_layers.clear();
+ error = hw_intf_->Flush();
+ if (error == kErrorNone) {
+ error = hw_intf_->PowerOff();
+ }
+ break;
+
+ case kStateOn:
+ error = hw_intf_->PowerOn();
+ if (error != kErrorNone) {
+ return error;
+ }
+
+ error = comp_manager_->ReconfigureDisplay(display_comp_ctx_, display_attributes_,
+ hw_panel_info_, mixer_attributes_, fb_config_);
+ if (error != kErrorNone) {
+ return error;
+ }
+
+ active = true;
+ break;
+
+ case kStateDoze:
+ error = hw_intf_->Doze();
+ active = true;
+ break;
+
+ case kStateDozeSuspend:
+ error = hw_intf_->DozeSuspend();
+ if (display_type_ != kPrimary) {
+ active = true;
+ }
+
+ break;
+
+ case kStateStandby:
+ error = hw_intf_->Standby();
+ break;
+
+ default:
+ DLOGE("Spurious state = %d transition requested.", state);
+ break;
+ }
+
+ if (error == kErrorNone) {
+ active_ = active;
+ state_ = state;
+ comp_manager_->SetDisplayState(display_comp_ctx_, state, display_type_);
+ }
+
+ return error;
+}
+
+DisplayError DisplayBase::SetActiveConfig(uint32_t index) {
+ lock_guard<recursive_mutex> obj(recursive_mutex_);
+ DisplayError error = kErrorNone;
+ uint32_t active_index = 0;
+
+ hw_intf_->GetActiveConfig(&active_index);
+
+ if (active_index == index) {
+ return kErrorNone;
+ }
+
+ error = hw_intf_->SetDisplayAttributes(index);
+ if (error != kErrorNone) {
+ return error;
+ }
+
+ return ReconfigureDisplay();
+}
+
+DisplayError DisplayBase::SetMaxMixerStages(uint32_t max_mixer_stages) {
+ lock_guard<recursive_mutex> obj(recursive_mutex_);
+ DisplayError error = kErrorNone;
+
+ error = comp_manager_->SetMaxMixerStages(display_comp_ctx_, max_mixer_stages);
+
+ if (error == kErrorNone) {
+ max_mixer_stages_ = max_mixer_stages;
+ }
+
+ return error;
+}
+
+std::string DisplayBase::Dump() {
+ lock_guard<recursive_mutex> obj(recursive_mutex_);
+ HWDisplayAttributes attrib;
+ uint32_t active_index = 0;
+ uint32_t num_modes = 0;
+ std::ostringstream os;
+
+ hw_intf_->GetNumDisplayAttributes(&num_modes);
+ hw_intf_->GetActiveConfig(&active_index);
+ hw_intf_->GetDisplayAttributes(active_index, &attrib);
+
+ os << "device type:" << display_type_;
+ os << "\nstate: " << state_ << " vsync on: " << vsync_enable_ << " max. mixer stages: "
+ << max_mixer_stages_;
+ os << "\nnum configs: " << num_modes << " active config index: " << active_index;
+
+ DisplayConfigVariableInfo &info = attrib;
+
+ uint32_t num_hw_layers = UINT32(hw_layers_.info.hw_layers.size());
+
+ if (num_hw_layers == 0) {
+ os << "\nNo hardware layers programmed";
+ return os.str();
+ }
+
+ LayerBuffer *out_buffer = nullptr;
+ if (hw_layers_.info.stack) {
+ out_buffer = hw_layers_.info.stack->output_buffer;
+ }
+ if (out_buffer != nullptr) {
+ os << "\nres: " << out_buffer->width << "x" << out_buffer->height << " format: "
+ << GetFormatString(out_buffer->format);
+ } else {
+ os.precision(2);
+ os << "\nres: " << info.x_pixels << "x" << info.y_pixels << " dpi: " << std::fixed <<
+ info.x_dpi << "x" << std::fixed << info.y_dpi << " fps: " << info.fps <<
+ " vsync period: " << info.vsync_period_ns;
+ }
+
+ HWLayersInfo &layer_info = hw_layers_.info;
+ for (uint32_t i = 0; i < layer_info.left_frame_roi.size(); i++) {
+ LayerRect &l_roi = layer_info.left_frame_roi.at(i);
+ LayerRect &r_roi = layer_info.right_frame_roi.at(i);
+
+ os << "\nROI(LTRB)#" << i << " LEFT(" << INT(l_roi.left) << " " << INT(l_roi.top) << " " <<
+ INT(l_roi.right) << " " << INT(l_roi.bottom) << ")";
+ if (IsValid(r_roi)) {
+ os << " RIGHT(" << INT(r_roi.left) << " " << INT(r_roi.top) << " " << INT(r_roi.right) << " "
+ << INT(r_roi.bottom) << ")";
+ }
+ }
+
+ LayerRect &fb_roi = layer_info.partial_fb_roi;
+ if (IsValid(fb_roi)) {
+ os << "\nPartial FB ROI(LTRB):(" << INT(fb_roi.left) << " " << INT(fb_roi.top) << " " <<
+ INT(fb_roi.right) << " " << INT(fb_roi.bottom) << ")";
+ }
+
+ const char *header = "\n| Idx | Comp Type | Split | WB | Pipe | W x H | Format | Src Rect (L T R B) | Dst Rect (L T R B) | Z | Flags | Deci(HxV) | CS | Rng |"; //NOLINT
+ const char *newline = "\n|-----|-------------|--------|----|--------|-------------|--------------------------|---------------------|---------------------|----|------------|-----------|----|-----|"; //NOLINT
+ const char *format = "\n| %3s | %11s " "| %6s " "| %2s | 0x%04x | %4d x %4d | %24s " "| %4d %4d %4d %4d " "| %4d %4d %4d %4d " "| %2s | %10s " "| %9s | %2s | %3s |"; //NOLINT
+
+
+ os << "\n";
+ os << newline;
+ os << header;
+ os << newline;
+
+ for (uint32_t i = 0; i < num_hw_layers; i++) {
+ uint32_t layer_index = hw_layers_.info.index[i];
+ // hw-layer from hw layers info
+ Layer &hw_layer = hw_layers_.info.hw_layers.at(i);
+ LayerBuffer *input_buffer = &hw_layer.input_buffer;
+ HWLayerConfig &layer_config = hw_layers_.config[i];
+ HWRotatorSession &hw_rotator_session = layer_config.hw_rotator_session;
+
+ char idx[8] = { 0 };
+ const char *comp_type = GetName(hw_layer.composition);
+ const char *buffer_format = GetFormatString(input_buffer->format);
+ const char *rotate_split[2] = { "Rot-1", "Rot-2" };
+ const char *comp_split[2] = { "Comp-1", "Comp-2" };
+
+ snprintf(idx, sizeof(idx), "%d", layer_index);
+
+ for (uint32_t count = 0; count < hw_rotator_session.hw_block_count; count++) {
+ char writeback_id[8] = { 0 };
+ char row[1024];
+ HWRotateInfo &rotate = hw_rotator_session.hw_rotate_info[count];
+ LayerRect &src_roi = rotate.src_roi;
+ LayerRect &dst_roi = rotate.dst_roi;
+
+ snprintf(writeback_id, sizeof(writeback_id), "%d", rotate.writeback_id);
+
+ snprintf(row, sizeof(row), format, idx, comp_type, rotate_split[count],
+ writeback_id, rotate.pipe_id, input_buffer->width,
+ input_buffer->height, buffer_format, INT(src_roi.left),
+ INT(src_roi.top), INT(src_roi.right), INT(src_roi.bottom),
+ INT(dst_roi.left), INT(dst_roi.top), INT(dst_roi.right),
+ INT(dst_roi.bottom), "-", "- ", "- ", "-", "-");
+ os << row;
+ // print the below only once per layer block, fill with spaces for rest.
+ idx[0] = 0;
+ comp_type = "";
+ }
+
+ if (hw_rotator_session.hw_block_count > 0) {
+ input_buffer = &hw_rotator_session.output_buffer;
+ buffer_format = GetFormatString(input_buffer->format);
+ }
+
+ for (uint32_t count = 0; count < 2; count++) {
+ char decimation[16] = { 0 };
+ char flags[16] = { 0 };
+ char z_order[8] = { 0 };
+ char color_primary[8] = { 0 };
+ char range[8] = { 0 };
+
+ HWPipeInfo &pipe = (count == 0) ? layer_config.left_pipe : layer_config.right_pipe;
+
+ if (!pipe.valid) {
+ continue;
+ }
+
+ LayerRect &src_roi = pipe.src_roi;
+ LayerRect &dst_roi = pipe.dst_roi;
+
+ snprintf(z_order, sizeof(z_order), "%d", pipe.z_order);
+ snprintf(flags, sizeof(flags), "0x%08x", hw_layer.flags.flags);
+ snprintf(decimation, sizeof(decimation), "%3d x %3d", pipe.horizontal_decimation,
+ pipe.vertical_decimation);
+ ColorMetaData &color_metadata = hw_layer.input_buffer.color_metadata;
+ snprintf(color_primary, sizeof(color_primary), "%d", color_metadata.colorPrimaries);
+ snprintf(range, sizeof(range), "%d", color_metadata.range);
+
+ char row[1024];
+ snprintf(row, sizeof(row), format, idx, comp_type, comp_split[count],
+ "-", pipe.pipe_id, input_buffer->width, input_buffer->height,
+ buffer_format, INT(src_roi.left), INT(src_roi.top),
+ INT(src_roi.right), INT(src_roi.bottom), INT(dst_roi.left),
+ INT(dst_roi.top), INT(dst_roi.right), INT(dst_roi.bottom),
+ z_order, flags, decimation, color_primary, range);
+
+ os << row;
+ // print the below only once per layer block, fill with spaces for rest.
+ idx[0] = 0;
+ comp_type = "";
+ }
+ }
+
+ os << newline << "\n";
+
+ return os.str();
+}
+
+const char * DisplayBase::GetName(const LayerComposition &composition) {
+ switch (composition) {
+ case kCompositionGPU: return "GPU";
+ case kCompositionSDE: return "SDE";
+ case kCompositionHWCursor: return "CURSOR";
+ case kCompositionHybrid: return "HYBRID";
+ case kCompositionBlit: return "BLIT";
+ case kCompositionGPUTarget: return "GPU_TARGET";
+ case kCompositionBlitTarget: return "BLIT_TARGET";
+ default: return "UNKNOWN";
+ }
+}
+
+DisplayError DisplayBase::ColorSVCRequestRoute(const PPDisplayAPIPayload &in_payload,
+ PPDisplayAPIPayload *out_payload,
+ PPPendingParams *pending_action) {
+ lock_guard<recursive_mutex> obj(recursive_mutex_);
+ if (color_mgr_)
+ return color_mgr_->ColorSVCRequestRoute(in_payload, out_payload, pending_action);
+ else
+ return kErrorParameters;
+}
+
+DisplayError DisplayBase::GetColorModeCount(uint32_t *mode_count) {
+ lock_guard<recursive_mutex> obj(recursive_mutex_);
+ if (!mode_count) {
+ return kErrorParameters;
+ }
+
+ if (!color_mgr_) {
+ return kErrorNotSupported;
+ }
+
+ DLOGV_IF(kTagQDCM, "Number of modes from color manager = %d", num_color_modes_);
+ *mode_count = num_color_modes_;
+
+ return kErrorNone;
+}
+
+DisplayError DisplayBase::GetColorModes(uint32_t *mode_count,
+ std::vector<std::string> *color_modes) {
+ lock_guard<recursive_mutex> obj(recursive_mutex_);
+ if (!mode_count || !color_modes) {
+ return kErrorParameters;
+ }
+
+ if (!color_mgr_) {
+ return kErrorNotSupported;
+ }
+
+ for (uint32_t i = 0; i < num_color_modes_; i++) {
+ DLOGV_IF(kTagQDCM, "Color Mode[%d]: Name = %s mode_id = %d", i, color_modes_[i].name,
+ color_modes_[i].id);
+ color_modes->at(i) = color_modes_[i].name;
+ }
+
+ return kErrorNone;
+}
+
+DisplayError DisplayBase::GetColorModeAttr(const std::string &color_mode, AttrVal *attr) {
+ lock_guard<recursive_mutex> obj(recursive_mutex_);
+ if (!attr) {
+ return kErrorParameters;
+ }
+
+ if (!color_mgr_) {
+ return kErrorNotSupported;
+ }
+
+ auto it = color_mode_attr_map_.find(color_mode);
+ if (it == color_mode_attr_map_.end()) {
+ DLOGE("Failed: Mode %s without attribute", color_mode.c_str());
+ return kErrorNotSupported;
+ }
+ *attr = it->second;
+
+ return kErrorNone;
+}
+
+DisplayError DisplayBase::SetColorMode(const std::string &color_mode) {
+ lock_guard<recursive_mutex> obj(recursive_mutex_);
+ if (!color_mgr_) {
+ return kErrorNotSupported;
+ }
+
+ DynamicRangeType dynamic_range_type;
+ if (IsSupportColorModeAttribute(color_mode)) {
+ auto it_mode = color_mode_attr_map_.find(color_mode);
+ std::string dynamic_range;
+ GetValueOfModeAttribute(it_mode->second, kDynamicRangeAttribute, &dynamic_range);
+ if (dynamic_range == kHdr) {
+ dynamic_range_type = kHdrType;
+ } else {
+ dynamic_range_type = kSdrType;
+ }
+ } else {
+ if (color_mode.find("hal_hdr") != std::string::npos) {
+ dynamic_range_type = kHdrType;
+ } else {
+ dynamic_range_type = kSdrType;
+ }
+ }
+
+ DisplayError error = kErrorNone;
+ if (disable_hdr_lut_gen_) {
+ error = SetColorModeInternal(color_mode);
+ if (error != kErrorNone) {
+ return error;
+ }
+ // Store the new SDR color mode request by client
+ if (dynamic_range_type == kSdrType) {
+ current_color_mode_ = color_mode;
+ }
+ return error;
+ }
+
+ if (hdr_playback_mode_) {
+ // HDR playback on, If incoming mode is SDR mode,
+ // cache the mode and apply it after HDR playback stop.
+ if (dynamic_range_type == kHdrType) {
+ error = SetColorModeInternal(color_mode);
+ if (error != kErrorNone) {
+ return error;
+ }
+ } else if (dynamic_range_type == kSdrType) {
+ current_color_mode_ = color_mode;
+ }
+ } else {
+ // HDR playback off, do not apply HDR mode
+ if (dynamic_range_type == kHdrType) {
+ DLOGE("Failed: Forbid setting HDR Mode : %s when HDR playback off", color_mode.c_str());
+ return kErrorNotSupported;
+ }
+ error = SetColorModeInternal(color_mode);
+ if (error != kErrorNone) {
+ return error;
+ }
+ current_color_mode_ = color_mode;
+ }
+
+ return error;
+}
+
+DisplayError DisplayBase::SetColorModeInternal(const std::string &color_mode) {
+ DLOGV_IF(kTagQDCM, "Color Mode = %s", color_mode.c_str());
+
+ ColorModeMap::iterator it = color_mode_map_.find(color_mode);
+ if (it == color_mode_map_.end()) {
+ DLOGE("Failed: Unknown Mode : %s", color_mode.c_str());
+ return kErrorNotSupported;
+ }
+
+ SDEDisplayMode *sde_display_mode = it->second;
+
+ DLOGV_IF(kTagQDCM, "Color Mode Name = %s corresponding mode_id = %d", sde_display_mode->name,
+ sde_display_mode->id);
+ DisplayError error = kErrorNone;
+ error = color_mgr_->ColorMgrSetMode(sde_display_mode->id);
+ if (error != kErrorNone) {
+ DLOGE("Failed for mode id = %d", sde_display_mode->id);
+ return error;
+ }
+
+ return error;
+}
+
+DisplayError DisplayBase::GetValueOfModeAttribute(const AttrVal &attr,const std::string &type,
+ std::string *value) {
+ if (!value) {
+ return kErrorParameters;
+ }
+ for (auto &it : attr) {
+ if (it.first.find(type) != std::string::npos) {
+ *value = it.second;
+ }
+ }
+
+ return kErrorNone;
+}
+
+bool DisplayBase::IsSupportColorModeAttribute(const std::string &color_mode) {
+ auto it = color_mode_attr_map_.find(color_mode);
+ if (it == color_mode_attr_map_.end()) {
+ return false;
+ }
+ return true;
+}
+
+DisplayError DisplayBase::GetHdrColorMode(std::string *color_mode, bool *found_hdr) {
+ if (!found_hdr || !color_mode) {
+ return kErrorParameters;
+ }
+ auto it_mode = color_mode_attr_map_.find(current_color_mode_);
+ if (it_mode == color_mode_attr_map_.end()) {
+ DLOGE("Failed: Unknown Mode : %s", current_color_mode_.c_str());
+ return kErrorNotSupported;
+ }
+
+ *found_hdr = false;
+ std::string cur_color_gamut, cur_pic_quality;
+ // get the attributes of current color mode
+ GetValueOfModeAttribute(it_mode->second, kColorGamutAttribute, &cur_color_gamut);
+ GetValueOfModeAttribute(it_mode->second, kPictureQualityAttribute, &cur_pic_quality);
+
+ // found the corresponding HDR mode id which
+ // has the same attributes with current SDR mode.
+ for (auto &it_hdr : color_mode_attr_map_) {
+ std::string dynamic_range, color_gamut, pic_quality;
+ GetValueOfModeAttribute(it_hdr.second, kDynamicRangeAttribute, &dynamic_range);
+ GetValueOfModeAttribute(it_hdr.second, kColorGamutAttribute, &color_gamut);
+ GetValueOfModeAttribute(it_hdr.second, kPictureQualityAttribute, &pic_quality);
+ if (dynamic_range == kHdr && cur_color_gamut == color_gamut &&
+ cur_pic_quality == pic_quality) {
+ *color_mode = it_hdr.first;
+ *found_hdr = true;
+ DLOGV_IF(kTagQDCM, "corresponding hdr mode = %s", color_mode->c_str());
+ return kErrorNone;
+ }
+ }
+
+ // The corresponding HDR mode was not be found,
+ // apply the first HDR mode that we encouter.
+ for (auto &it_hdr : color_mode_attr_map_) {
+ std::string dynamic_range;
+ GetValueOfModeAttribute(it_hdr.second, kDynamicRangeAttribute, &dynamic_range);
+ if (dynamic_range == kHdr) {
+ *color_mode = it_hdr.first;
+ *found_hdr = true;
+ DLOGV_IF(kTagQDCM, "First hdr mode = %s", color_mode->c_str());
+ return kErrorNone;
+ }
+ }
+
+ return kErrorNone;
+}
+
+DisplayError DisplayBase::SetColorTransform(const uint32_t length, const double *color_transform) {
+ lock_guard<recursive_mutex> obj(recursive_mutex_);
+ if (!color_mgr_) {
+ return kErrorNotSupported;
+ }
+
+ if (!color_transform) {
+ return kErrorParameters;
+ }
+
+ return color_mgr_->ColorMgrSetColorTransform(length, color_transform);
+}
+
+DisplayError DisplayBase::GetDefaultColorMode(std::string *color_mode) {
+ lock_guard<recursive_mutex> obj(recursive_mutex_);
+ if (!color_mode) {
+ return kErrorParameters;
+ }
+
+ if (!color_mgr_) {
+ return kErrorNotSupported;
+ }
+
+ int32_t default_id = kInvalidModeId;
+ DisplayError error = color_mgr_->ColorMgrGetDefaultModeID(&default_id);
+ if (error != kErrorNone) {
+ DLOGE("Failed for get default color mode id");
+ return error;
+ }
+
+ for (uint32_t i = 0; i < num_color_modes_; i++) {
+ if (color_modes_[i].id == default_id) {
+ *color_mode = color_modes_[i].name;
+ return kErrorNone;
+ }
+ }
+
+ return kErrorNotSupported;
+}
+
+DisplayError DisplayBase::ApplyDefaultDisplayMode() {
+ lock_guard<recursive_mutex> obj(recursive_mutex_);
+ if (color_mgr_)
+ return color_mgr_->ApplyDefaultDisplayMode();
+ else
+ return kErrorParameters;
+}
+
+DisplayError DisplayBase::SetCursorPosition(int x, int y) {
+ lock_guard<recursive_mutex> obj(recursive_mutex_);
+ if (state_ != kStateOn) {
+ return kErrorNotSupported;
+ }
+
+ DisplayError error = comp_manager_->ValidateAndSetCursorPosition(display_comp_ctx_, &hw_layers_,
+ x, y);
+ if (error == kErrorNone) {
+ return hw_intf_->SetCursorPosition(&hw_layers_, x, y);
+ }
+
+ return kErrorNone;
+}
+
+DisplayError DisplayBase::GetRefreshRateRange(uint32_t *min_refresh_rate,
+ uint32_t *max_refresh_rate) {
+ lock_guard<recursive_mutex> obj(recursive_mutex_);
+ // The min and max refresh rates will be same when the HWPanelInfo does not contain valid rates.
+ // Usually for secondary displays, command mode panels
+ HWDisplayAttributes display_attributes;
+ uint32_t active_index = 0;
+ hw_intf_->GetActiveConfig(&active_index);
+ DisplayError error = hw_intf_->GetDisplayAttributes(active_index, &display_attributes);
+ if (error) {
+ return error;
+ }
+
+ *min_refresh_rate = display_attributes.fps;
+ *max_refresh_rate = display_attributes.fps;
+
+ return error;
+}
+
+DisplayError DisplayBase::SetVSyncState(bool enable) {
+ lock_guard<recursive_mutex> obj(recursive_mutex_);
+ DisplayError error = kErrorNone;
+ if (vsync_enable_ != enable) {
+ error = hw_intf_->SetVSyncState(enable);
+ if (error == kErrorNone) {
+ vsync_enable_ = enable;
+ }
+ }
+ return error;
+}
+
+DisplayError DisplayBase::ReconfigureDisplay() {
+ lock_guard<recursive_mutex> obj(recursive_mutex_);
+ DisplayError error = kErrorNone;
+ HWDisplayAttributes display_attributes;
+ HWMixerAttributes mixer_attributes;
+ HWPanelInfo hw_panel_info;
+ uint32_t active_index = 0;
+
+ error = hw_intf_->GetActiveConfig(&active_index);
+ if (error != kErrorNone) {
+ return error;
+ }
+
+ error = hw_intf_->GetDisplayAttributes(active_index, &display_attributes);
+ if (error != kErrorNone) {
+ return error;
+ }
+
+ error = hw_intf_->GetMixerAttributes(&mixer_attributes);
+ if (error != kErrorNone) {
+ return error;
+ }
+
+ error = hw_intf_->GetHWPanelInfo(&hw_panel_info);
+ if (error != kErrorNone) {
+ return error;
+ }
+
+ if (display_attributes == display_attributes_ && mixer_attributes == mixer_attributes_ &&
+ hw_panel_info == hw_panel_info_) {
+ return kErrorNone;
+ }
+
+ error = comp_manager_->ReconfigureDisplay(display_comp_ctx_, display_attributes, hw_panel_info,
+ mixer_attributes, fb_config_);
+ if (error != kErrorNone) {
+ return error;
+ }
+
+ if (mixer_attributes != mixer_attributes_) {
+ DisablePartialUpdateOneFrame();
+ }
+
+ display_attributes_ = display_attributes;
+ mixer_attributes_ = mixer_attributes;
+ hw_panel_info_ = hw_panel_info;
+
+ return kErrorNone;
+}
+
+DisplayError DisplayBase::SetMixerResolution(uint32_t width, uint32_t height) {
+ lock_guard<recursive_mutex> obj(recursive_mutex_);
+
+ DisplayError error = ReconfigureMixer(width, height);
+ if (error != kErrorNone) {
+ return error;
+ }
+
+ req_mixer_width_ = width;
+ req_mixer_height_ = height;
+
+ return kErrorNone;
+}
+
+DisplayError DisplayBase::GetMixerResolution(uint32_t *width, uint32_t *height) {
+ lock_guard<recursive_mutex> obj(recursive_mutex_);
+ if (!width || !height) {
+ return kErrorParameters;
+ }
+
+ *width = mixer_attributes_.width;
+ *height = mixer_attributes_.height;
+
+ return kErrorNone;
+}
+
+DisplayError DisplayBase::ReconfigureMixer(uint32_t width, uint32_t height) {
+ lock_guard<recursive_mutex> obj(recursive_mutex_);
+ DisplayError error = kErrorNone;
+
+ if (!width || !height) {
+ return kErrorParameters;
+ }
+
+ DLOGD_IF(kTagQDCM, "Reconfiguring mixer with width : %d, height : %d", width, height);
+ HWMixerAttributes mixer_attributes;
+ mixer_attributes.width = width;
+ mixer_attributes.height = height;
+
+ error = hw_intf_->SetMixerAttributes(mixer_attributes);
+ if (error != kErrorNone) {
+ return error;
+ }
+
+ return ReconfigureDisplay();
+}
+
+bool DisplayBase::NeedsDownScale(const LayerRect &src_rect, const LayerRect &dst_rect,
+ bool needs_rotation) {
+ float src_width = FLOAT(src_rect.right - src_rect.left);
+ float src_height = FLOAT(src_rect.bottom - src_rect.top);
+ float dst_width = FLOAT(dst_rect.right - dst_rect.left);
+ float dst_height = FLOAT(dst_rect.bottom - dst_rect.top);
+
+ if (needs_rotation) {
+ std::swap(src_width, src_height);
+ }
+
+ if ((src_width > dst_width) || (src_height > dst_height)) {
+ return true;
+ }
+
+ return false;
+}
+
+bool DisplayBase::NeedsMixerReconfiguration(LayerStack *layer_stack, uint32_t *new_mixer_width,
+ uint32_t *new_mixer_height) {
+ lock_guard<recursive_mutex> obj(recursive_mutex_);
+ uint32_t layer_count = UINT32(layer_stack->layers.size());
+
+ uint32_t fb_width = fb_config_.x_pixels;
+ uint32_t fb_height = fb_config_.y_pixels;
+ uint32_t fb_area = fb_width * fb_height;
+ LayerRect fb_rect = (LayerRect) {0.0f, 0.0f, FLOAT(fb_width), FLOAT(fb_height)};
+ uint32_t mixer_width = mixer_attributes_.width;
+ uint32_t mixer_height = mixer_attributes_.height;
+ uint32_t display_width = display_attributes_.x_pixels;
+ uint32_t display_height = display_attributes_.y_pixels;
+
+ RectOrientation fb_orientation = GetOrientation(fb_rect);
+ uint32_t max_layer_area = 0;
+ uint32_t max_area_layer_index = 0;
+ std::vector<Layer *> layers = layer_stack->layers;
+ uint32_t align_x = display_attributes_.is_device_split ? 4 : 2;
+ uint32_t align_y = 2;
+
+ if (req_mixer_width_ && req_mixer_height_) {
+ DLOGD_IF(kTagDisplay, "Required mixer width : %d, height : %d",
+ req_mixer_width_, req_mixer_height_);
+ *new_mixer_width = req_mixer_width_;
+ *new_mixer_height = req_mixer_height_;
+ return (req_mixer_width_ != mixer_width || req_mixer_height_ != mixer_height);
+ }
+
+ for (uint32_t i = 0; i < layer_count; i++) {
+ Layer *layer = layers.at(i);
+
+ uint32_t layer_width = UINT32(layer->src_rect.right - layer->src_rect.left);
+ uint32_t layer_height = UINT32(layer->src_rect.bottom - layer->src_rect.top);
+ uint32_t layer_area = layer_width * layer_height;
+
+ if (layer_area > max_layer_area) {
+ max_layer_area = layer_area;
+ max_area_layer_index = i;
+ }
+ }
+ DLOGV_IF(kTagDisplay, "Max area layer at index : %d", max_area_layer_index);
+
+ // TODO(user): Mark layer which needs downscaling on GPU fallback as priority layer and use MDP
+ // for composition to avoid quality mismatch between GPU and MDP switch(idle timeout usecase).
+ if (max_layer_area >= fb_area) {
+ Layer *layer = layers.at(max_area_layer_index);
+ bool needs_rotation = (layer->transform.rotation == 90.0f);
+
+ uint32_t layer_width = UINT32(layer->src_rect.right - layer->src_rect.left);
+ uint32_t layer_height = UINT32(layer->src_rect.bottom - layer->src_rect.top);
+ LayerRect layer_dst_rect = {};
+
+ RectOrientation layer_orientation = GetOrientation(layer->src_rect);
+ if (layer_orientation != kOrientationUnknown &&
+ fb_orientation != kOrientationUnknown) {
+ if (layer_orientation != fb_orientation) {
+ std::swap(layer_width, layer_height);
+ }
+ }
+
+ // Align the width and height according to fb's aspect ratio
+ *new_mixer_width = FloorToMultipleOf(UINT32((FLOAT(fb_width) / FLOAT(fb_height)) *
+ layer_height), align_x);
+ *new_mixer_height = FloorToMultipleOf(layer_height, align_y);
+
+ LayerRect dst_domain = {0.0f, 0.0f, FLOAT(*new_mixer_width), FLOAT(*new_mixer_height)};
+
+ MapRect(fb_rect, dst_domain, layer->dst_rect, &layer_dst_rect);
+ if (NeedsDownScale(layer->src_rect, layer_dst_rect, needs_rotation)) {
+ *new_mixer_width = display_width;
+ *new_mixer_height = display_height;
+ }
+
+ return true;
+ }
+
+ return false;
+}
+
+DisplayError DisplayBase::SetFrameBufferConfig(const DisplayConfigVariableInfo &variable_info) {
+ lock_guard<recursive_mutex> obj(recursive_mutex_);
+ uint32_t width = variable_info.x_pixels;
+ uint32_t height = variable_info.y_pixels;
+
+ if (width == 0 || height == 0) {
+ DLOGE("Unsupported resolution: (%dx%d)", width, height);
+ return kErrorParameters;
+ }
+
+ // Create rects to represent the new source and destination crops
+ LayerRect crop = LayerRect(0, 0, FLOAT(width), FLOAT(height));
+ LayerRect dst = LayerRect(0, 0, FLOAT(mixer_attributes_.width), FLOAT(mixer_attributes_.height));
+ // Set rotate90 to false since this is taken care of during regular composition.
+ bool rotate90 = false;
+
+ DisplayError error = comp_manager_->ValidateScaling(crop, dst, rotate90);
+ if (error != kErrorNone) {
+ DLOGE("Unsupported resolution: (%dx%d)", width, height);
+ return kErrorParameters;
+ }
+
+ error = comp_manager_->ReconfigureDisplay(display_comp_ctx_, display_attributes_, hw_panel_info_,
+ mixer_attributes_, variable_info);
+ if (error != kErrorNone) {
+ return error;
+ }
+
+ fb_config_.x_pixels = width;
+ fb_config_.y_pixels = height;
+
+ DLOGI("New framebuffer resolution (%dx%d)", fb_config_.x_pixels, fb_config_.y_pixels);
+
+ return kErrorNone;
+}
+
+DisplayError DisplayBase::GetFrameBufferConfig(DisplayConfigVariableInfo *variable_info) {
+ lock_guard<recursive_mutex> obj(recursive_mutex_);
+ if (!variable_info) {
+ return kErrorParameters;
+ }
+
+ *variable_info = fb_config_;
+
+ return kErrorNone;
+}
+
+DisplayError DisplayBase::SetDetailEnhancerData(const DisplayDetailEnhancerData &de_data) {
+ lock_guard<recursive_mutex> obj(recursive_mutex_);
+ DisplayError error = comp_manager_->SetDetailEnhancerData(display_comp_ctx_, de_data);
+ if (error != kErrorNone) {
+ return error;
+ }
+
+ DisablePartialUpdateOneFrame();
+
+ return kErrorNone;
+}
+
+DisplayError DisplayBase::GetDisplayPort(DisplayPort *port) {
+ lock_guard<recursive_mutex> obj(recursive_mutex_);
+
+ if (!port) {
+ return kErrorParameters;
+ }
+
+ *port = hw_panel_info_.port;
+
+ return kErrorNone;
+}
+
+bool DisplayBase::IsPrimaryDisplay() {
+ lock_guard<recursive_mutex> obj(recursive_mutex_);
+
+ return hw_panel_info_.is_primary_panel;
+}
+
+DisplayError DisplayBase::SetCompositionState(LayerComposition composition_type, bool enable) {
+ lock_guard<recursive_mutex> obj(recursive_mutex_);
+
+ return comp_manager_->SetCompositionState(display_comp_ctx_, composition_type, enable);
+}
+
+void DisplayBase::CommitLayerParams(LayerStack *layer_stack) {
+ // Copy the acquire fence from clients layers to HWLayers
+ uint32_t hw_layers_count = UINT32(hw_layers_.info.hw_layers.size());
+
+ for (uint32_t i = 0; i < hw_layers_count; i++) {
+ Layer *sdm_layer = layer_stack->layers.at(hw_layers_.info.index[i]);
+ Layer &hw_layer = hw_layers_.info.hw_layers.at(i);
+
+ hw_layer.input_buffer.planes[0].fd = sdm_layer->input_buffer.planes[0].fd;
+ hw_layer.input_buffer.planes[0].offset = sdm_layer->input_buffer.planes[0].offset;
+ hw_layer.input_buffer.planes[0].stride = sdm_layer->input_buffer.planes[0].stride;
+ hw_layer.input_buffer.size = sdm_layer->input_buffer.size;
+ hw_layer.input_buffer.acquire_fence_fd = sdm_layer->input_buffer.acquire_fence_fd;
+ }
+
+ return;
+}
+
+void DisplayBase::PostCommitLayerParams(LayerStack *layer_stack) {
+ // Copy the release fence from HWLayers to clients layers
+ uint32_t hw_layers_count = UINT32(hw_layers_.info.hw_layers.size());
+
+ std::vector<uint32_t> fence_dup_flag;
+
+ for (uint32_t i = 0; i < hw_layers_count; i++) {
+ uint32_t sdm_layer_index = hw_layers_.info.index[i];
+ Layer *sdm_layer = layer_stack->layers.at(sdm_layer_index);
+ Layer &hw_layer = hw_layers_.info.hw_layers.at(i);
+
+ // Copy the release fence only once for a SDM Layer.
+ // In S3D use case, two hw layers can share the same input buffer, So make sure to merge the
+ // output fence fd and assign it to layer's input buffer release fence fd.
+ if (std::find(fence_dup_flag.begin(), fence_dup_flag.end(), sdm_layer_index) ==
+ fence_dup_flag.end()) {
+ sdm_layer->input_buffer.release_fence_fd = hw_layer.input_buffer.release_fence_fd;
+ fence_dup_flag.push_back(sdm_layer_index);
+ } else {
+ int temp = -1;
+ buffer_sync_handler_->SyncMerge(hw_layer.input_buffer.release_fence_fd,
+ sdm_layer->input_buffer.release_fence_fd, &temp);
+
+ if (hw_layer.input_buffer.release_fence_fd >= 0) {
+ Sys::close_(hw_layer.input_buffer.release_fence_fd);
+ hw_layer.input_buffer.release_fence_fd = -1;
+ }
+
+ if (sdm_layer->input_buffer.release_fence_fd >= 0) {
+ Sys::close_(sdm_layer->input_buffer.release_fence_fd);
+ sdm_layer->input_buffer.release_fence_fd = -1;
+ }
+
+ sdm_layer->input_buffer.release_fence_fd = temp;
+ }
+ }
+
+ return;
+}
+
+DisplayError DisplayBase::InitializeColorModes() {
+ if (!color_mgr_) {
+ return kErrorNotSupported;
+ }
+
+ DisplayError error = color_mgr_->ColorMgrGetNumOfModes(&num_color_modes_);
+ if (error != kErrorNone || !num_color_modes_) {
+ DLOGV_IF(kTagQDCM, "GetNumModes failed = %d count = %d", error, num_color_modes_);
+ return kErrorNotSupported;
+ }
+ DLOGI("Number of Color Modes = %d", num_color_modes_);
+
+ if (!color_modes_.size()) {
+ color_modes_.resize(num_color_modes_);
+
+ DisplayError error = color_mgr_->ColorMgrGetModes(&num_color_modes_, color_modes_.data());
+ if (error != kErrorNone) {
+ color_modes_.clear();
+ DLOGE("Failed");
+ return error;
+ }
+ int32_t default_id = kInvalidModeId;
+ error = color_mgr_->ColorMgrGetDefaultModeID(&default_id);
+
+ AttrVal var;
+ for (uint32_t i = 0; i < num_color_modes_; i++) {
+ DLOGV_IF(kTagQDCM, "Color Mode[%d]: Name = %s mode_id = %d", i, color_modes_[i].name,
+ color_modes_[i].id);
+ // get the name of default color mode
+ if (color_modes_[i].id == default_id) {
+ current_color_mode_ = color_modes_[i].name;
+ }
+ auto it = color_mode_map_.find(color_modes_[i].name);
+ if (it != color_mode_map_.end()) {
+ if (it->second->id < color_modes_[i].id) {
+ color_mode_map_.erase(it);
+ color_mode_map_.insert(std::make_pair(color_modes_[i].name, &color_modes_[i]));
+ }
+ } else {
+ color_mode_map_.insert(std::make_pair(color_modes_[i].name, &color_modes_[i]));
+ }
+
+ var.clear();
+ error = color_mgr_->ColorMgrGetModeInfo(color_modes_[i].id, &var);
+ if (error != kErrorNone) {
+ DLOGE("Failed for get attributes of mode_id = %d", color_modes_[i].id);
+ continue;
+ }
+ if (!var.empty()) {
+ auto it = color_mode_attr_map_.find(color_modes_[i].name);
+ if (it == color_mode_attr_map_.end()) {
+ color_mode_attr_map_.insert(std::make_pair(color_modes_[i].name, var));
+ }
+ }
+ }
+ }
+
+ return kErrorNone;
+}
+
+DisplayError DisplayBase::HandleHDR(LayerStack *layer_stack) {
+ DisplayError error = kErrorNone;
+
+ if (display_type_ != kPrimary) {
+ // Handling is needed for only primary displays
+ return kErrorNone;
+ }
+
+ if (!layer_stack->flags.hdr_present) {
+ // HDR playback off - set prev mode
+ if (hdr_playback_mode_) {
+ hdr_playback_mode_ = false;
+ if (color_mgr_ && !disable_hdr_lut_gen_) {
+ // Do not apply HDR Mode when hdr lut generation is disabled
+ DLOGI("Setting color mode = %s", current_color_mode_.c_str());
+ // HDR playback off - set prev mode
+ error = SetColorModeInternal(current_color_mode_);
+ }
+ comp_manager_->ControlDpps(true); // Enable Dpps
+ }
+ } else {
+ // hdr is present
+ if (!hdr_playback_mode_ && !layer_stack->flags.animating) {
+ // hdr is starting
+ hdr_playback_mode_ = true;
+ if (color_mgr_ && !disable_hdr_lut_gen_) {
+ std::string hdr_color_mode;
+ if (IsSupportColorModeAttribute(current_color_mode_)) {
+ bool found_hdr = false;
+ error = GetHdrColorMode(&hdr_color_mode, &found_hdr);
+ // try to set "hal-hdr" mode if did not found that
+ // the dynamic range of mode is hdr
+ if (!found_hdr) {
+ hdr_color_mode = "hal_hdr";
+ }
+ } else {
+ hdr_color_mode = "hal_hdr";
+ }
+ DLOGI("Setting color mode = %s", hdr_color_mode.c_str());
+ error = SetColorModeInternal(hdr_color_mode);
+ }
+ comp_manager_->ControlDpps(false); // Disable Dpps
+ }
+ }
+
+ return error;
+}
+
+
+DisplayError DisplayBase::GetClientTargetSupport(uint32_t width, uint32_t height,
+ LayerBufferFormat format,
+ const ColorMetaData &color_metadata) {
+ if (format != kFormatRGBA8888 && format != kFormatRGBA1010102) {
+ DLOGW("Unsupported format = %d", format);
+ return kErrorNotSupported;
+ } else if (ValidateScaling(width, height) != kErrorNone) {
+ DLOGW("Unsupported width = %d height = %d", width, height);
+ return kErrorNotSupported;
+ } else if (color_metadata.transfer && color_metadata.colorPrimaries) {
+ DisplayError error = ValidateDataspace(color_metadata);
+ if (error != kErrorNone) {
+ DLOGW("Unsupported Transfer Request = %d Color Primary = %d",
+ color_metadata.transfer, color_metadata.colorPrimaries);
+ return error;
+ }
+
+ // Check for BT2020 support
+ if (color_metadata.colorPrimaries == ColorPrimaries_BT2020) {
+ DLOGW("Unsupported Color Primary = %d", color_metadata.colorPrimaries);
+ return kErrorNotSupported;
+ }
+ }
+
+ return kErrorNone;
+}
+
+DisplayError DisplayBase::ValidateScaling(uint32_t width, uint32_t height) {
+ uint32_t display_width = display_attributes_.x_pixels;
+ uint32_t display_height = display_attributes_.y_pixels;
+
+ HWResourceInfo hw_resource_info = HWResourceInfo();
+ hw_info_intf_->GetHWResourceInfo(&hw_resource_info);
+ float max_scale_down = FLOAT(hw_resource_info.max_scale_down);
+ float max_scale_up = FLOAT(hw_resource_info.max_scale_up);
+
+ float scale_x = FLOAT(width / display_width);
+ float scale_y = FLOAT(height / display_height);
+
+ if (scale_x > max_scale_down || scale_y > max_scale_down) {
+ return kErrorNotSupported;
+ }
+
+ if (UINT32(scale_x) < 1 && scale_x > 0.0f) {
+ if ((1.0f / scale_x) > max_scale_up) {
+ return kErrorNotSupported;
+ }
+ }
+
+ if (UINT32(scale_y) < 1 && scale_y > 0.0f) {
+ if ((1.0f / scale_y) > max_scale_up) {
+ return kErrorNotSupported;
+ }
+ }
+
+ return kErrorNone;
+}
+
+DisplayError DisplayBase::ValidateDataspace(const ColorMetaData &color_metadata) {
+ // Handle transfer
+ switch (color_metadata.transfer) {
+ case Transfer_sRGB:
+ case Transfer_SMPTE_170M:
+ case Transfer_SMPTE_ST2084:
+ case Transfer_HLG:
+ case Transfer_Linear:
+ case Transfer_Gamma2_2:
+ break;
+ default:
+ DLOGW("Unsupported Transfer Request = %d", color_metadata.transfer);
+ return kErrorNotSupported;
+ }
+
+ // Handle colorPrimaries
+ switch (color_metadata.colorPrimaries) {
+ case ColorPrimaries_BT709_5:
+ case ColorPrimaries_BT601_6_525:
+ case ColorPrimaries_BT601_6_625:
+ case ColorPrimaries_DCIP3:
+ case ColorPrimaries_BT2020:
+ break;
+ default:
+ DLOGW("Unsupported Color Primary = %d", color_metadata.colorPrimaries);
+ return kErrorNotSupported;
+ }
+
+ return kErrorNone;
+}
+
+} // namespace sdm
diff --git a/msm8909/sdm/libs/core/display_base.h b/msm8909/sdm/libs/core/display_base.h
new file mode 100644
index 00000000..e511dac1
--- /dev/null
+++ b/msm8909/sdm/libs/core/display_base.h
@@ -0,0 +1,184 @@
+/*
+* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without modification, are permitted
+* provided that the following conditions are met:
+* * Redistributions of source code must retain the above copyright notice, this list of
+* conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright notice, this list of
+* conditions and the following disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its contributors may be used to
+* endorse or promote products derived from this software without specific prior written
+* permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __DISPLAY_BASE_H__
+#define __DISPLAY_BASE_H__
+
+#include <core/display_interface.h>
+#include <private/strategy_interface.h>
+#include <private/color_interface.h>
+
+#include <map>
+#include <mutex>
+#include <string>
+#include <vector>
+
+#include "hw_interface.h"
+#include "comp_manager.h"
+#include "color_manager.h"
+#include "hw_events_interface.h"
+
+namespace sdm {
+
+using std::recursive_mutex;
+using std::lock_guard;
+
+class DisplayBase : public DisplayInterface {
+ public:
+ DisplayBase(DisplayType display_type, DisplayEventHandler *event_handler,
+ HWDeviceType hw_device_type, BufferSyncHandler *buffer_sync_handler,
+ BufferAllocator *buffer_allocator, CompManager *comp_manager,
+ HWInfoInterface *hw_info_intf);
+ virtual ~DisplayBase() { }
+ virtual DisplayError Init();
+ virtual DisplayError Deinit();
+ DisplayError Prepare(LayerStack *layer_stack);
+ DisplayError Commit(LayerStack *layer_stack);
+ virtual DisplayError Flush();
+ virtual DisplayError GetDisplayState(DisplayState *state);
+ virtual DisplayError GetNumVariableInfoConfigs(uint32_t *count);
+ virtual DisplayError GetConfig(uint32_t index, DisplayConfigVariableInfo *variable_info);
+ virtual DisplayError GetConfig(DisplayConfigFixedInfo *variable_info);
+ virtual DisplayError GetActiveConfig(uint32_t *index);
+ virtual DisplayError GetVSyncState(bool *enabled);
+ virtual DisplayError SetDisplayState(DisplayState state);
+ virtual DisplayError SetActiveConfig(uint32_t index);
+ virtual DisplayError SetActiveConfig(DisplayConfigVariableInfo *variable_info) {
+ return kErrorNotSupported;
+ }
+ virtual DisplayError SetMaxMixerStages(uint32_t max_mixer_stages);
+ virtual DisplayError ControlPartialUpdate(bool enable, uint32_t *pending) {
+ return kErrorNotSupported;
+ }
+ virtual DisplayError DisablePartialUpdateOneFrame() {
+ return kErrorNotSupported;
+ }
+ virtual DisplayError SetDisplayMode(uint32_t mode) {
+ return kErrorNotSupported;
+ }
+ virtual bool IsUnderscanSupported() {
+ return false;
+ }
+ virtual DisplayError SetPanelBrightness(int level) {
+ return kErrorNotSupported;
+ }
+ virtual DisplayError CachePanelBrightness(int level) {
+ return kErrorNotSupported;
+ }
+ virtual DisplayError OnMinHdcpEncryptionLevelChange(uint32_t min_enc_level) {
+ return kErrorNotSupported;
+ }
+ virtual DisplayError ColorSVCRequestRoute(const PPDisplayAPIPayload &in_payload,
+ PPDisplayAPIPayload *out_payload,
+ PPPendingParams *pending_action);
+ virtual DisplayError GetColorModeCount(uint32_t *mode_count);
+ virtual DisplayError GetColorModes(uint32_t *mode_count, std::vector<std::string> *color_modes);
+ virtual DisplayError GetColorModeAttr(const std::string &color_mode, AttrVal *attr);
+ virtual DisplayError SetColorMode(const std::string &color_mode);
+ virtual DisplayError SetColorTransform(const uint32_t length, const double *color_transform);
+ virtual DisplayError GetDefaultColorMode(std::string *color_mode);
+ virtual DisplayError ApplyDefaultDisplayMode(void);
+ virtual DisplayError SetCursorPosition(int x, int y);
+ virtual DisplayError GetRefreshRateRange(uint32_t *min_refresh_rate, uint32_t *max_refresh_rate);
+ virtual DisplayError GetPanelBrightness(int *level) {
+ return kErrorNotSupported;
+ }
+ virtual DisplayError SetVSyncState(bool enable);
+ virtual void SetIdleTimeoutMs(uint32_t active_ms) {}
+ virtual DisplayError SetMixerResolution(uint32_t width, uint32_t height);
+ virtual DisplayError GetMixerResolution(uint32_t *width, uint32_t *height);
+ virtual DisplayError SetFrameBufferConfig(const DisplayConfigVariableInfo &variable_info);
+ virtual DisplayError GetFrameBufferConfig(DisplayConfigVariableInfo *variable_info);
+ virtual DisplayError SetDetailEnhancerData(const DisplayDetailEnhancerData &de_data);
+ virtual DisplayError GetDisplayPort(DisplayPort *port);
+ virtual bool IsPrimaryDisplay();
+ virtual DisplayError SetCompositionState(LayerComposition composition_type, bool enable);
+ virtual DisplayError GetClientTargetSupport(uint32_t width, uint32_t height,
+ LayerBufferFormat format,
+ const ColorMetaData &color_metadata);
+ virtual std::string Dump();
+
+ protected:
+ DisplayError BuildLayerStackStats(LayerStack *layer_stack);
+ virtual DisplayError ValidateGPUTargetParams();
+ void CommitLayerParams(LayerStack *layer_stack);
+ void PostCommitLayerParams(LayerStack *layer_stack);
+ DisplayError HandleHDR(LayerStack *layer_stack);
+ DisplayError ValidateScaling(uint32_t width, uint32_t height);
+ DisplayError ValidateDataspace(const ColorMetaData &color_metadata);
+
+ const char *GetName(const LayerComposition &composition);
+ DisplayError ReconfigureDisplay();
+ bool NeedsMixerReconfiguration(LayerStack *layer_stack, uint32_t *new_mixer_width,
+ uint32_t *new_mixer_height);
+ DisplayError ReconfigureMixer(uint32_t width, uint32_t height);
+ bool NeedsDownScale(const LayerRect &src_rect, const LayerRect &dst_rect, bool needs_rotation);
+ DisplayError InitializeColorModes();
+ DisplayError SetColorModeInternal(const std::string &color_mode);
+ DisplayError GetValueOfModeAttribute(const AttrVal &attr, const std::string &type,
+ std::string *value);
+ DisplayError GetHdrColorMode(std::string *color_mode, bool *found_hdr);
+ bool IsSupportColorModeAttribute(const std::string &color_mode);
+
+ recursive_mutex recursive_mutex_;
+ DisplayType display_type_;
+ DisplayEventHandler *event_handler_ = NULL;
+ HWDeviceType hw_device_type_;
+ HWInterface *hw_intf_ = NULL;
+ HWPanelInfo hw_panel_info_;
+ BufferSyncHandler *buffer_sync_handler_ = NULL;
+ BufferAllocator *buffer_allocator_ {};
+ CompManager *comp_manager_ = NULL;
+ DisplayState state_ = kStateOff;
+ bool active_ = false;
+ Handle hw_device_ = 0;
+ Handle display_comp_ctx_ = 0;
+ HWLayers hw_layers_;
+ bool needs_validate_ = true;
+ bool vsync_enable_ = false;
+ uint32_t max_mixer_stages_ = 0;
+ HWInfoInterface *hw_info_intf_ = NULL;
+ ColorManagerProxy *color_mgr_ = NULL; // each display object owns its ColorManagerProxy
+ bool partial_update_control_ = true;
+ HWEventsInterface *hw_events_intf_ = NULL;
+ bool disable_pu_one_frame_ = false;
+ uint32_t num_color_modes_ = 0;
+ std::vector<SDEDisplayMode> color_modes_;
+ typedef std::map<std::string, SDEDisplayMode *> ColorModeMap;
+ ColorModeMap color_mode_map_ = {};
+ typedef std::map<std::string, AttrVal> ColorModeAttrMap;
+ ColorModeAttrMap color_mode_attr_map_ = {};
+ HWDisplayAttributes display_attributes_ = {};
+ HWMixerAttributes mixer_attributes_ = {};
+ DisplayConfigVariableInfo fb_config_ = {};
+ uint32_t req_mixer_width_ = 0;
+ uint32_t req_mixer_height_ = 0;
+ std::string current_color_mode_ = "hal_native";
+ bool hdr_playback_mode_ = false;
+ int disable_hdr_lut_gen_ = 0;
+};
+
+} // namespace sdm
+
+#endif // __DISPLAY_BASE_H__
diff --git a/msm8909/sdm/libs/core/display_hdmi.cpp b/msm8909/sdm/libs/core/display_hdmi.cpp
new file mode 100644
index 00000000..5f8eeb4d
--- /dev/null
+++ b/msm8909/sdm/libs/core/display_hdmi.cpp
@@ -0,0 +1,303 @@
+/*
+* Copyright (c) 2014 - 2018, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without modification, are permitted
+* provided that the following conditions are met:
+* * Redistributions of source code must retain the above copyright notice, this list of
+* conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright notice, this list of
+* conditions and the following disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its contributors may be used to
+* endorse or promote products derived from this software without specific prior written
+* permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <utils/constants.h>
+#include <utils/debug.h>
+#include <map>
+#include <utility>
+#include <vector>
+
+#include "display_hdmi.h"
+#include "hw_interface.h"
+#include "hw_info_interface.h"
+
+#define __CLASS__ "DisplayHDMI"
+
+namespace sdm {
+
+DisplayHDMI::DisplayHDMI(DisplayEventHandler *event_handler, HWInfoInterface *hw_info_intf,
+ BufferSyncHandler *buffer_sync_handler, BufferAllocator *buffer_allocator,
+ CompManager *comp_manager)
+ : DisplayBase(kHDMI, event_handler, kDeviceHDMI, buffer_sync_handler, buffer_allocator,
+ comp_manager, hw_info_intf) {
+}
+
+DisplayError DisplayHDMI::Init() {
+ lock_guard<recursive_mutex> obj(recursive_mutex_);
+
+ DisplayError error = HWInterface::Create(kHDMI, hw_info_intf_, buffer_sync_handler_,
+ buffer_allocator_, &hw_intf_);
+ if (error != kErrorNone) {
+ return error;
+ }
+
+ uint32_t active_mode_index;
+ char value[64] = "0";
+ Debug::GetProperty(HDMI_S3D_MODE_PROP, value);
+ HWS3DMode mode = (HWS3DMode)atoi(value);
+ if (mode > kS3DModeNone && mode < kS3DModeMax) {
+ active_mode_index = GetBestConfig(mode);
+ } else {
+ active_mode_index = GetBestConfig(kS3DModeNone);
+ }
+
+ error = hw_intf_->SetDisplayAttributes(active_mode_index);
+ if (error != kErrorNone) {
+ HWInterface::Destroy(hw_intf_);
+ }
+
+ error = DisplayBase::Init();
+ if (error != kErrorNone) {
+ HWInterface::Destroy(hw_intf_);
+ return error;
+ }
+
+ GetScanSupport();
+ underscan_supported_ = (scan_support_ == kScanAlwaysUnderscanned) || (scan_support_ == kScanBoth);
+
+ s3d_format_to_mode_.insert(std::pair<LayerBufferS3DFormat, HWS3DMode>
+ (kS3dFormatNone, kS3DModeNone));
+ s3d_format_to_mode_.insert(std::pair<LayerBufferS3DFormat, HWS3DMode>
+ (kS3dFormatLeftRight, kS3DModeLR));
+ s3d_format_to_mode_.insert(std::pair<LayerBufferS3DFormat, HWS3DMode>
+ (kS3dFormatRightLeft, kS3DModeRL));
+ s3d_format_to_mode_.insert(std::pair<LayerBufferS3DFormat, HWS3DMode>
+ (kS3dFormatTopBottom, kS3DModeTB));
+ s3d_format_to_mode_.insert(std::pair<LayerBufferS3DFormat, HWS3DMode>
+ (kS3dFormatFramePacking, kS3DModeFP));
+
+ error = HWEventsInterface::Create(INT(display_type_), this, event_list_, &hw_events_intf_);
+ if (error != kErrorNone) {
+ DisplayBase::Deinit();
+ HWInterface::Destroy(hw_intf_);
+ DLOGE("Failed to create hardware events interface. Error = %d", error);
+ }
+
+ return error;
+}
+
+DisplayError DisplayHDMI::Prepare(LayerStack *layer_stack) {
+ lock_guard<recursive_mutex> obj(recursive_mutex_);
+ DisplayError error = kErrorNone;
+ uint32_t new_mixer_width = 0;
+ uint32_t new_mixer_height = 0;
+ uint32_t display_width = display_attributes_.x_pixels;
+ uint32_t display_height = display_attributes_.y_pixels;
+
+ if (NeedsMixerReconfiguration(layer_stack, &new_mixer_width, &new_mixer_height)) {
+ error = ReconfigureMixer(new_mixer_width, new_mixer_height);
+ if (error != kErrorNone) {
+ ReconfigureMixer(display_width, display_height);
+ }
+ }
+
+ SetS3DMode(layer_stack);
+
+ // Clean hw layers for reuse.
+ hw_layers_ = HWLayers();
+
+ return DisplayBase::Prepare(layer_stack);
+}
+
+DisplayError DisplayHDMI::GetRefreshRateRange(uint32_t *min_refresh_rate,
+ uint32_t *max_refresh_rate) {
+ lock_guard<recursive_mutex> obj(recursive_mutex_);
+ DisplayError error = kErrorNone;
+
+ if (hw_panel_info_.min_fps && hw_panel_info_.max_fps) {
+ *min_refresh_rate = hw_panel_info_.min_fps;
+ *max_refresh_rate = hw_panel_info_.max_fps;
+ } else {
+ error = DisplayBase::GetRefreshRateRange(min_refresh_rate, max_refresh_rate);
+ }
+
+ return error;
+}
+
+DisplayError DisplayHDMI::SetRefreshRate(uint32_t refresh_rate) {
+ lock_guard<recursive_mutex> obj(recursive_mutex_);
+
+ if (!active_) {
+ return kErrorPermission;
+ }
+
+ DisplayError error = hw_intf_->SetRefreshRate(refresh_rate);
+ if (error != kErrorNone) {
+ return error;
+ }
+
+ return DisplayBase::ReconfigureDisplay();
+}
+
+bool DisplayHDMI::IsUnderscanSupported() {
+ lock_guard<recursive_mutex> obj(recursive_mutex_);
+ return underscan_supported_;
+}
+
+DisplayError DisplayHDMI::OnMinHdcpEncryptionLevelChange(uint32_t min_enc_level) {
+ lock_guard<recursive_mutex> obj(recursive_mutex_);
+ return hw_intf_->OnMinHdcpEncryptionLevelChange(min_enc_level);
+}
+
+uint32_t DisplayHDMI::GetBestConfig(HWS3DMode s3d_mode) {
+ uint32_t best_index = 0, index;
+ uint32_t num_modes = 0;
+
+ hw_intf_->GetNumDisplayAttributes(&num_modes);
+
+ // Get display attribute for each mode
+ std::vector<HWDisplayAttributes> attrib(num_modes);
+ for (index = 0; index < num_modes; index++) {
+ hw_intf_->GetDisplayAttributes(index, &attrib[index]);
+ }
+
+ // Select best config for s3d_mode. If s3d is not enabled, s3d_mode is kS3DModeNone
+ for (index = 0; index < num_modes; index ++) {
+ if (attrib[index].s3d_config[s3d_mode]) {
+ break;
+ }
+ }
+ if (index < num_modes) {
+ best_index = UINT32(index);
+ for (size_t index = best_index + 1; index < num_modes; index ++) {
+ if (!attrib[index].s3d_config[s3d_mode])
+ continue;
+
+ // From the available configs, select the best
+ // Ex: 1920x1080@60Hz is better than 1920x1080@30 and 1920x1080@30 is better than 1280x720@60
+ if (attrib[index].y_pixels > attrib[best_index].y_pixels) {
+ best_index = UINT32(index);
+ } else if (attrib[index].y_pixels == attrib[best_index].y_pixels) {
+ if (attrib[index].x_pixels > attrib[best_index].x_pixels) {
+ best_index = UINT32(index);
+ } else if (attrib[index].x_pixels == attrib[best_index].x_pixels) {
+ if (attrib[index].vsync_period_ns < attrib[best_index].vsync_period_ns) {
+ best_index = UINT32(index);
+ }
+ }
+ }
+ }
+ } else {
+ DLOGW("%s, could not support S3D mode from EDID info. S3D mode is %d",
+ __FUNCTION__, s3d_mode);
+ }
+
+ // Used for changing HDMI Resolution - override the best with user set config
+ uint32_t user_config = UINT32(Debug::GetHDMIResolution());
+ if (user_config) {
+ uint32_t config_index = 0;
+ // For the config, get the corresponding index
+ DisplayError error = hw_intf_->GetConfigIndex(user_config, &config_index);
+ if (error == kErrorNone)
+ return config_index;
+ }
+
+ return best_index;
+}
+
+void DisplayHDMI::GetScanSupport() {
+ DisplayError error = kErrorNone;
+ uint32_t video_format = 0;
+ uint32_t max_cea_format = 0;
+ HWScanInfo scan_info = HWScanInfo();
+ hw_intf_->GetHWScanInfo(&scan_info);
+
+ uint32_t active_mode_index = 0;
+ hw_intf_->GetActiveConfig(&active_mode_index);
+
+ error = hw_intf_->GetVideoFormat(active_mode_index, &video_format);
+ if (error != kErrorNone) {
+ return;
+ }
+
+ error = hw_intf_->GetMaxCEAFormat(&max_cea_format);
+ if (error != kErrorNone) {
+ return;
+ }
+
+ // The scan support for a given HDMI TV must be read from scan info corresponding to
+ // Preferred Timing if the preferred timing of the display is currently active, and if it is
+ // valid. In all other cases, we must read the scan support from CEA scan info if
+ // the resolution is a CEA resolution, or from IT scan info for all other resolutions.
+ if (active_mode_index == 0 && scan_info.pt_scan_support != kScanNotSupported) {
+ scan_support_ = scan_info.pt_scan_support;
+ } else if (video_format < max_cea_format) {
+ scan_support_ = scan_info.cea_scan_support;
+ } else {
+ scan_support_ = scan_info.it_scan_support;
+ }
+}
+
+void DisplayHDMI::SetS3DMode(LayerStack *layer_stack) {
+ uint32_t s3d_layer_count = 0;
+ HWS3DMode s3d_mode = kS3DModeNone;
+ uint32_t layer_count = UINT32(layer_stack->layers.size());
+
+ // S3D mode is supported for the following scenarios:
+ // 1. Layer stack containing only one s3d layer which is not skip
+ // 2. Layer stack containing only one secure layer along with one s3d layer
+ for (uint32_t i = 0; i < layer_count; i++) {
+ Layer *layer = layer_stack->layers.at(i);
+ LayerBuffer &layer_buffer = layer->input_buffer;
+
+ if (layer_buffer.s3d_format != kS3dFormatNone) {
+ s3d_layer_count++;
+ if (s3d_layer_count > 1 || layer->flags.skip) {
+ s3d_mode = kS3DModeNone;
+ break;
+ }
+
+ std::map<LayerBufferS3DFormat, HWS3DMode>::iterator it =
+ s3d_format_to_mode_.find(layer_buffer.s3d_format);
+ if (it != s3d_format_to_mode_.end()) {
+ s3d_mode = it->second;
+ }
+ } else if (layer_buffer.flags.secure && layer_count > 2) {
+ s3d_mode = kS3DModeNone;
+ break;
+ }
+ }
+
+ if (hw_intf_->SetS3DMode(s3d_mode) != kErrorNone) {
+ hw_intf_->SetS3DMode(kS3DModeNone);
+ layer_stack->flags.s3d_mode_present = false;
+ } else if (s3d_mode != kS3DModeNone) {
+ layer_stack->flags.s3d_mode_present = true;
+ }
+
+ DisplayBase::ReconfigureDisplay();
+}
+
+DisplayError DisplayHDMI::VSync(int64_t timestamp) {
+ if (vsync_enable_) {
+ DisplayEventVSync vsync;
+ vsync.timestamp = timestamp;
+ event_handler_->VSync(vsync);
+ }
+
+ return kErrorNone;
+}
+
+} // namespace sdm
+
diff --git a/msm8909/sdm/libs/core/display_hdmi.h b/msm8909/sdm/libs/core/display_hdmi.h
new file mode 100644
index 00000000..4758b043
--- /dev/null
+++ b/msm8909/sdm/libs/core/display_hdmi.h
@@ -0,0 +1,71 @@
+/*
+* Copyright (c) 2014 - 2017, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without modification, are permitted
+* provided that the following conditions are met:
+* * Redistributions of source code must retain the above copyright notice, this list of
+* conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright notice, this list of
+* conditions and the following disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its contributors may be used to
+* endorse or promote products derived from this software without specific prior written
+* permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __DISPLAY_HDMI_H__
+#define __DISPLAY_HDMI_H__
+
+#include <vector>
+#include <map>
+
+#include "display_base.h"
+#include "hw_events_interface.h"
+
+namespace sdm {
+
+class HWHDMIInterface;
+
+class DisplayHDMI : public DisplayBase, HWEventHandler {
+ public:
+ DisplayHDMI(DisplayEventHandler *event_handler, HWInfoInterface *hw_info_intf,
+ BufferSyncHandler *buffer_sync_handler, BufferAllocator *buffer_allocator,
+ CompManager *comp_manager);
+ virtual DisplayError Init();
+ virtual DisplayError Prepare(LayerStack *layer_stack);
+ virtual DisplayError GetRefreshRateRange(uint32_t *min_refresh_rate, uint32_t *max_refresh_rate);
+ virtual DisplayError SetRefreshRate(uint32_t refresh_rate);
+ virtual bool IsUnderscanSupported();
+ virtual DisplayError OnMinHdcpEncryptionLevelChange(uint32_t min_enc_level);
+
+ // Implement the HWEventHandlers
+ virtual DisplayError VSync(int64_t timestamp);
+ virtual DisplayError Blank(bool blank) { return kErrorNone; }
+ virtual void IdleTimeout() { }
+ virtual void ThermalEvent(int64_t thermal_level) { }
+ virtual void IdlePowerCollapse() { }
+
+ private:
+ uint32_t GetBestConfig(HWS3DMode s3d_mode);
+ void GetScanSupport();
+ void SetS3DMode(LayerStack *layer_stack);
+
+ bool underscan_supported_ = false;
+ HWScanSupport scan_support_;
+ std::map<LayerBufferS3DFormat, HWS3DMode> s3d_format_to_mode_;
+ std::vector<HWEvent> event_list_ = { HWEvent::VSYNC, HWEvent::IDLE_NOTIFY, HWEvent::EXIT
+ };
+};
+
+} // namespace sdm
+
+#endif // __DISPLAY_HDMI_H__
diff --git a/msm8909/sdm/libs/core/display_primary.cpp b/msm8909/sdm/libs/core/display_primary.cpp
new file mode 100644
index 00000000..af212975
--- /dev/null
+++ b/msm8909/sdm/libs/core/display_primary.cpp
@@ -0,0 +1,338 @@
+/*
+* Copyright (c) 2014 - 2017, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without modification, are permitted
+* provided that the following conditions are met:
+* * Redistributions of source code must retain the above copyright notice, this list of
+* conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright notice, this list of
+* conditions and the following disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its contributors may be used to
+* endorse or promote products derived from this software without specific prior written
+* permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <utils/constants.h>
+#include <utils/debug.h>
+#include <utils/rect.h>
+#include <map>
+#include <algorithm>
+#include <functional>
+#include <vector>
+
+#include "display_primary.h"
+#include "hw_interface.h"
+#include "hw_info_interface.h"
+
+#define __CLASS__ "DisplayPrimary"
+
+namespace sdm {
+
+DisplayPrimary::DisplayPrimary(DisplayEventHandler *event_handler, HWInfoInterface *hw_info_intf,
+ BufferSyncHandler *buffer_sync_handler,
+ BufferAllocator *buffer_allocator, CompManager *comp_manager)
+ : DisplayBase(kPrimary, event_handler, kDevicePrimary, buffer_sync_handler, buffer_allocator,
+ comp_manager, hw_info_intf) {
+}
+
+DisplayError DisplayPrimary::Init() {
+ lock_guard<recursive_mutex> obj(recursive_mutex_);
+
+ DisplayError error = HWInterface::Create(kPrimary, hw_info_intf_, buffer_sync_handler_,
+ buffer_allocator_, &hw_intf_);
+ if (error != kErrorNone) {
+ return error;
+ }
+
+ error = DisplayBase::Init();
+ if (error != kErrorNone) {
+ HWInterface::Destroy(hw_intf_);
+ return error;
+ }
+
+ if (hw_panel_info_.mode == kModeCommand && Debug::IsVideoModeEnabled()) {
+ error = hw_intf_->SetDisplayMode(kModeVideo);
+ if (error != kErrorNone) {
+ DLOGW("Retaining current display mode. Current = %d, Requested = %d", hw_panel_info_.mode,
+ kModeVideo);
+ }
+ }
+
+ avr_prop_disabled_ = Debug::IsAVRDisabled();
+
+ error = HWEventsInterface::Create(INT(display_type_), this, event_list_, &hw_events_intf_);
+ if (error != kErrorNone) {
+ DLOGE("Failed to create hardware events interface. Error = %d", error);
+ DisplayBase::Deinit();
+ HWInterface::Destroy(hw_intf_);
+ }
+
+ return error;
+}
+
+DisplayError DisplayPrimary::Prepare(LayerStack *layer_stack) {
+ lock_guard<recursive_mutex> obj(recursive_mutex_);
+ DisplayError error = kErrorNone;
+ uint32_t new_mixer_width = 0;
+ uint32_t new_mixer_height = 0;
+ uint32_t display_width = display_attributes_.x_pixels;
+ uint32_t display_height = display_attributes_.y_pixels;
+
+ if (NeedsMixerReconfiguration(layer_stack, &new_mixer_width, &new_mixer_height)) {
+ error = ReconfigureMixer(new_mixer_width, new_mixer_height);
+ if (error != kErrorNone) {
+ ReconfigureMixer(display_width, display_height);
+ }
+ }
+
+ // Clean hw layers for reuse.
+ hw_layers_ = HWLayers();
+ hw_layers_.hw_avr_info.enable = NeedsAVREnable();
+
+ return DisplayBase::Prepare(layer_stack);
+}
+
+DisplayError DisplayPrimary::Commit(LayerStack *layer_stack) {
+ lock_guard<recursive_mutex> obj(recursive_mutex_);
+ DisplayError error = kErrorNone;
+ uint32_t app_layer_count = hw_layers_.info.app_layer_count;
+
+ // Enabling auto refresh is async and needs to happen before commit ioctl
+ if (hw_panel_info_.mode == kModeCommand) {
+ bool enable = (app_layer_count == 1) && layer_stack->flags.single_buffered_layer_present;
+ bool need_refresh = layer_stack->flags.single_buffered_layer_present && (app_layer_count > 1);
+
+ hw_intf_->SetAutoRefresh(enable);
+ if (need_refresh) {
+ event_handler_->Refresh();
+ }
+ }
+
+ error = DisplayBase::Commit(layer_stack);
+ if (error != kErrorNone) {
+ return error;
+ }
+
+ DisplayBase::ReconfigureDisplay();
+
+ int idle_time_ms = hw_layers_.info.set_idle_time_ms;
+ if (idle_time_ms >= 0) {
+ hw_intf_->SetIdleTimeoutMs(UINT32(idle_time_ms));
+ }
+
+ if (switch_to_cmd_) {
+ uint32_t pending;
+ switch_to_cmd_ = false;
+ ControlPartialUpdate(true /* enable */, &pending);
+ }
+
+ return error;
+}
+
+DisplayError DisplayPrimary::SetDisplayState(DisplayState state) {
+ lock_guard<recursive_mutex> obj(recursive_mutex_);
+ DisplayError error = kErrorNone;
+ error = DisplayBase::SetDisplayState(state);
+ if (error != kErrorNone) {
+ return error;
+ }
+
+ // Set vsync enable state to false, as driver disables vsync during display power off.
+ if (state == kStateOff) {
+ vsync_enable_ = false;
+ }
+
+ return kErrorNone;
+}
+
+void DisplayPrimary::SetIdleTimeoutMs(uint32_t active_ms) {
+ lock_guard<recursive_mutex> obj(recursive_mutex_);
+
+ if (comp_manager_->SetIdleTimeoutMs(display_comp_ctx_, active_ms) == kErrorNone) {
+ hw_intf_->SetIdleTimeoutMs(active_ms);
+ }
+}
+
+DisplayError DisplayPrimary::SetDisplayMode(uint32_t mode) {
+ DisplayError error = kErrorNone;
+
+ // Limit scope of mutex to this block
+ {
+ lock_guard<recursive_mutex> obj(recursive_mutex_);
+ HWDisplayMode hw_display_mode = static_cast<HWDisplayMode>(mode);
+ uint32_t pending = 0;
+
+ if (!active_) {
+ DLOGW("Invalid display state = %d. Panel must be on.", state_);
+ return kErrorNotSupported;
+ }
+
+ if (hw_display_mode != kModeCommand && hw_display_mode != kModeVideo) {
+ DLOGW("Invalid panel mode parameters. Requested = %d", hw_display_mode);
+ return kErrorParameters;
+ }
+
+ if (hw_display_mode == hw_panel_info_.mode) {
+ DLOGW("Same display mode requested. Current = %d, Requested = %d", hw_panel_info_.mode,
+ hw_display_mode);
+ return kErrorNone;
+ }
+
+ error = hw_intf_->SetDisplayMode(hw_display_mode);
+ if (error != kErrorNone) {
+ DLOGW("Retaining current display mode. Current = %d, Requested = %d", hw_panel_info_.mode,
+ hw_display_mode);
+ return error;
+ }
+
+ if (mode == kModeVideo) {
+ ControlPartialUpdate(false /* enable */, &pending);
+ } else if (mode == kModeCommand) {
+ // Flush idle timeout value currently set.
+ hw_intf_->SetIdleTimeoutMs(0);
+ switch_to_cmd_ = true;
+ }
+ }
+
+ // Request for a new draw cycle. New display mode will get applied on next draw cycle.
+ // New idle time will get configured as part of this.
+ event_handler_->Refresh();
+
+ return error;
+}
+
+DisplayError DisplayPrimary::SetPanelBrightness(int level) {
+ lock_guard<recursive_mutex> obj(recursive_mutex_);
+ return hw_intf_->SetPanelBrightness(level);
+}
+
+DisplayError DisplayPrimary::CachePanelBrightness(int level) {
+ lock_guard<recursive_mutex> obj(recursive_mutex_);
+ return hw_intf_->CachePanelBrightness(level);
+}
+
+DisplayError DisplayPrimary::GetRefreshRateRange(uint32_t *min_refresh_rate,
+ uint32_t *max_refresh_rate) {
+ lock_guard<recursive_mutex> obj(recursive_mutex_);
+ DisplayError error = kErrorNone;
+
+ if (hw_panel_info_.min_fps && hw_panel_info_.max_fps) {
+ *min_refresh_rate = hw_panel_info_.min_fps;
+ *max_refresh_rate = hw_panel_info_.max_fps;
+ } else {
+ error = DisplayBase::GetRefreshRateRange(min_refresh_rate, max_refresh_rate);
+ }
+
+ return error;
+}
+
+DisplayError DisplayPrimary::SetRefreshRate(uint32_t refresh_rate) {
+ lock_guard<recursive_mutex> obj(recursive_mutex_);
+
+ if (!active_ || !hw_panel_info_.dynamic_fps) {
+ return kErrorNotSupported;
+ }
+
+ if (refresh_rate < hw_panel_info_.min_fps || refresh_rate > hw_panel_info_.max_fps) {
+ DLOGE("Invalid Fps = %d request", refresh_rate);
+ return kErrorParameters;
+ }
+
+ DisplayError error = hw_intf_->SetRefreshRate(refresh_rate);
+ if (error != kErrorNone) {
+ return error;
+ }
+
+ return DisplayBase::ReconfigureDisplay();
+}
+
+DisplayError DisplayPrimary::VSync(int64_t timestamp) {
+ if (vsync_enable_) {
+ DisplayEventVSync vsync;
+ vsync.timestamp = timestamp;
+ event_handler_->VSync(vsync);
+ }
+
+ return kErrorNone;
+}
+
+void DisplayPrimary::IdleTimeout() {
+ event_handler_->Refresh();
+ comp_manager_->ProcessIdleTimeout(display_comp_ctx_);
+ event_handler_->HandleEvent(kIdleTimeout);
+}
+
+void DisplayPrimary::ThermalEvent(int64_t thermal_level) {
+ lock_guard<recursive_mutex> obj(recursive_mutex_);
+ comp_manager_->ProcessThermalEvent(display_comp_ctx_, thermal_level);
+ event_handler_->HandleEvent(kThermalEvent);
+}
+
+void DisplayPrimary::IdlePowerCollapse() {
+ lock_guard<recursive_mutex> obj(recursive_mutex_);
+ comp_manager_->ProcessIdlePowerCollapse(display_comp_ctx_);
+}
+
+DisplayError DisplayPrimary::GetPanelBrightness(int *level) {
+ lock_guard<recursive_mutex> obj(recursive_mutex_);
+ return hw_intf_->GetPanelBrightness(level);
+}
+
+DisplayError DisplayPrimary::ControlPartialUpdate(bool enable, uint32_t *pending) {
+ lock_guard<recursive_mutex> obj(recursive_mutex_);
+ if (!pending) {
+ return kErrorParameters;
+ }
+
+ if (!hw_panel_info_.partial_update) {
+ // Nothing to be done.
+ DLOGI("partial update is not applicable for display=%d", display_type_);
+ return kErrorNotSupported;
+ }
+
+ *pending = 0;
+ if (enable == partial_update_control_) {
+ DLOGI("Same state transition is requested.");
+ return kErrorNone;
+ }
+
+ partial_update_control_ = enable;
+
+ if (!enable) {
+ // If the request is to turn off feature, new draw call is required to have
+ // the new setting into effect.
+ *pending = 1;
+ }
+
+ return kErrorNone;
+}
+
+DisplayError DisplayPrimary::DisablePartialUpdateOneFrame() {
+ lock_guard<recursive_mutex> obj(recursive_mutex_);
+ disable_pu_one_frame_ = true;
+
+ return kErrorNone;
+}
+
+bool DisplayPrimary::NeedsAVREnable() {
+ if (avr_prop_disabled_) {
+ return false;
+ }
+
+ return (hw_panel_info_.mode == kModeVideo && ((hw_panel_info_.dynamic_fps &&
+ hw_panel_info_.dfps_porch_mode) || (!hw_panel_info_.dynamic_fps &&
+ hw_panel_info_.min_fps != hw_panel_info_.max_fps)));
+}
+
+} // namespace sdm
+
diff --git a/msm8909/sdm/libs/core/display_primary.h b/msm8909/sdm/libs/core/display_primary.h
new file mode 100644
index 00000000..7cb20e54
--- /dev/null
+++ b/msm8909/sdm/libs/core/display_primary.h
@@ -0,0 +1,75 @@
+/*
+* Copyright (c) 2014 - 2017, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without modification, are permitted
+* provided that the following conditions are met:
+* * Redistributions of source code must retain the above copyright notice, this list of
+* conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright notice, this list of
+* conditions and the following disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its contributors may be used to
+* endorse or promote products derived from this software without specific prior written
+* permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __DISPLAY_PRIMARY_H__
+#define __DISPLAY_PRIMARY_H__
+
+#include <vector>
+
+#include "display_base.h"
+#include "hw_events_interface.h"
+
+namespace sdm {
+
+class HWPrimaryInterface;
+
+class DisplayPrimary : public DisplayBase, HWEventHandler {
+ public:
+ DisplayPrimary(DisplayEventHandler *event_handler, HWInfoInterface *hw_info_intf,
+ BufferSyncHandler *buffer_sync_handler, BufferAllocator *buffer_allocator,
+ CompManager *comp_manager);
+ virtual DisplayError Init();
+ virtual DisplayError Prepare(LayerStack *layer_stack);
+ virtual DisplayError Commit(LayerStack *layer_stack);
+ virtual DisplayError ControlPartialUpdate(bool enable, uint32_t *pending);
+ virtual DisplayError DisablePartialUpdateOneFrame();
+ virtual DisplayError SetDisplayState(DisplayState state);
+ virtual void SetIdleTimeoutMs(uint32_t active_ms);
+ virtual DisplayError SetDisplayMode(uint32_t mode);
+ virtual DisplayError GetRefreshRateRange(uint32_t *min_refresh_rate, uint32_t *max_refresh_rate);
+ virtual DisplayError SetRefreshRate(uint32_t refresh_rate);
+ virtual DisplayError SetPanelBrightness(int level);
+ virtual DisplayError GetPanelBrightness(int *level);
+ virtual DisplayError CachePanelBrightness(int level);
+
+ // Implement the HWEventHandlers
+ virtual DisplayError VSync(int64_t timestamp);
+ virtual DisplayError Blank(bool blank) { return kErrorNone; }
+ virtual void IdleTimeout();
+ virtual void ThermalEvent(int64_t thermal_level);
+ virtual void IdlePowerCollapse();
+
+ private:
+ bool NeedsAVREnable();
+
+ std::vector<HWEvent> event_list_ = { HWEvent::VSYNC, HWEvent::EXIT, HWEvent::IDLE_NOTIFY,
+ HWEvent::SHOW_BLANK_EVENT, HWEvent::THERMAL_LEVEL, HWEvent::IDLE_POWER_COLLAPSE };
+ bool avr_prop_disabled_ = false;
+ bool switch_to_cmd_ = false;
+};
+
+} // namespace sdm
+
+#endif // __DISPLAY_PRIMARY_H__
+
diff --git a/msm8909/sdm/libs/core/display_virtual.cpp b/msm8909/sdm/libs/core/display_virtual.cpp
new file mode 100644
index 00000000..fcdc152b
--- /dev/null
+++ b/msm8909/sdm/libs/core/display_virtual.cpp
@@ -0,0 +1,141 @@
+/*
+* Copyright (c) 2014 - 2017, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without modification, are permitted
+* provided that the following conditions are met:
+* * Redistributions of source code must retain the above copyright notice, this list of
+* conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright notice, this list of
+* conditions and the following disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its contributors may be used to
+* endorse or promote products derived from this software without specific prior written
+* permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <utils/constants.h>
+#include <utils/debug.h>
+
+#include "display_virtual.h"
+#include "hw_interface.h"
+#include "hw_info_interface.h"
+
+#define __CLASS__ "DisplayVirtual"
+
+namespace sdm {
+
+DisplayVirtual::DisplayVirtual(DisplayEventHandler *event_handler, HWInfoInterface *hw_info_intf,
+ BufferSyncHandler *buffer_sync_handler,
+ BufferAllocator *buffer_allocator, CompManager *comp_manager)
+ : DisplayBase(kVirtual, event_handler, kDeviceVirtual, buffer_sync_handler, buffer_allocator,
+ comp_manager, hw_info_intf) {
+}
+
+DisplayError DisplayVirtual::Init() {
+ lock_guard<recursive_mutex> obj(recursive_mutex_);
+
+ DisplayError error = HWInterface::Create(kVirtual, hw_info_intf_, buffer_sync_handler_,
+ buffer_allocator_, &hw_intf_);
+ if (error != kErrorNone) {
+ return error;
+ }
+
+ hw_intf_->GetDisplayAttributes(0 /* active_index */, &display_attributes_);
+
+ error = DisplayBase::Init();
+ if (error != kErrorNone) {
+ HWInterface::Destroy(hw_intf_);
+ }
+
+ return error;
+}
+
+DisplayError DisplayVirtual::GetNumVariableInfoConfigs(uint32_t *count) {
+ lock_guard<recursive_mutex> obj(recursive_mutex_);
+ *count = 1;
+ return kErrorNone;
+}
+
+DisplayError DisplayVirtual::GetConfig(uint32_t index, DisplayConfigVariableInfo *variable_info) {
+ lock_guard<recursive_mutex> obj(recursive_mutex_);
+ *variable_info = display_attributes_;
+ return kErrorNone;
+}
+
+DisplayError DisplayVirtual::GetActiveConfig(uint32_t *index) {
+ lock_guard<recursive_mutex> obj(recursive_mutex_);
+ *index = 0;
+ return kErrorNone;
+}
+
+DisplayError DisplayVirtual::SetActiveConfig(DisplayConfigVariableInfo *variable_info) {
+ lock_guard<recursive_mutex> obj(recursive_mutex_);
+
+ if (!variable_info) {
+ return kErrorParameters;
+ }
+
+ DisplayError error = kErrorNone;
+ HWDisplayAttributes display_attributes;
+ HWMixerAttributes mixer_attributes;
+
+ display_attributes.x_pixels = variable_info->x_pixels;
+ display_attributes.y_pixels = variable_info->y_pixels;
+ display_attributes.fps = variable_info->fps;
+
+ if (display_attributes == display_attributes_) {
+ return kErrorNone;
+ }
+
+ error = hw_intf_->SetDisplayAttributes(display_attributes);
+ if (error != kErrorNone) {
+ return error;
+ }
+
+ error = hw_intf_->GetMixerAttributes(&mixer_attributes);
+ if (error != kErrorNone) {
+ return error;
+ }
+
+ // if display is already connected, unregister display from composition manager and register
+ // the display with new configuration.
+ if (display_comp_ctx_) {
+ comp_manager_->UnregisterDisplay(display_comp_ctx_);
+ }
+
+ error = comp_manager_->RegisterDisplay(display_type_, display_attributes, hw_panel_info_,
+ mixer_attributes, fb_config_, &display_comp_ctx_);
+ if (error != kErrorNone) {
+ return error;
+ }
+
+ display_attributes_ = display_attributes;
+ mixer_attributes_ = mixer_attributes;
+
+ DLOGI("Virtual display resolution changed to[%dx%d]", display_attributes_.x_pixels,
+ display_attributes_.y_pixels);
+
+ return kErrorNone;
+}
+
+DisplayError DisplayVirtual::Prepare(LayerStack *layer_stack) {
+ lock_guard<recursive_mutex> obj(recursive_mutex_);
+
+ // Clean hw layers for reuse.
+ hw_layers_ = HWLayers();
+
+ return DisplayBase::Prepare(layer_stack);
+}
+
+
+} // namespace sdm
+
diff --git a/msm8909/sdm/libs/core/display_virtual.h b/msm8909/sdm/libs/core/display_virtual.h
new file mode 100644
index 00000000..ad0aecb3
--- /dev/null
+++ b/msm8909/sdm/libs/core/display_virtual.h
@@ -0,0 +1,74 @@
+/*
+* Copyright (c) 2014 - 2016, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without modification, are permitted
+* provided that the following conditions are met:
+* * Redistributions of source code must retain the above copyright notice, this list of
+* conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright notice, this list of
+* conditions and the following disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its contributors may be used to
+* endorse or promote products derived from this software without specific prior written
+* permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __DISPLAY_VIRTUAL_H__
+#define __DISPLAY_VIRTUAL_H__
+
+#include <private/hw_info_types.h>
+#include "display_base.h"
+
+namespace sdm {
+
+class HWVirtualInterface;
+
+class DisplayVirtual : public DisplayBase {
+ public:
+ DisplayVirtual(DisplayEventHandler *event_handler, HWInfoInterface *hw_info_intf,
+ BufferSyncHandler *buffer_sync_handler, BufferAllocator *buffer_allocator,
+ CompManager *comp_manager);
+ virtual DisplayError Init();
+ virtual DisplayError Prepare(LayerStack *layer_stack);
+ virtual DisplayError GetNumVariableInfoConfigs(uint32_t *count);
+ virtual DisplayError GetConfig(uint32_t index, DisplayConfigVariableInfo *variable_info);
+ virtual DisplayError GetActiveConfig(uint32_t *index);
+ virtual DisplayError SetActiveConfig(uint32_t index) {
+ return kErrorNotSupported;
+ }
+ virtual DisplayError SetActiveConfig(DisplayConfigVariableInfo *variable_info);
+ virtual DisplayError SetMixerResolution(uint32_t width, uint32_t height) {
+ return kErrorNotSupported;
+ }
+ virtual DisplayError SetVSyncState(bool enable) {
+ return kErrorNotSupported;
+ }
+ virtual DisplayError SetRefreshRate(uint32_t refresh_rate) {
+ return kErrorNotSupported;
+ }
+ virtual DisplayError GetMixerResolution(uint32_t *width, uint32_t *height) {
+ return kErrorNotSupported;
+ }
+ virtual DisplayError SetDetailEnhancerData(const DisplayDetailEnhancerData &de_data) {
+ return kErrorNotSupported;
+ }
+ virtual DisplayError ValidateGPUTargetParams() {
+ // TODO(user): Validate GPU target for virtual display when query display attributes
+ // on virtual display is functional.
+ return kErrorNone;
+ }
+};
+
+} // namespace sdm
+
+#endif // __DISPLAY_VIRTUAL_H__
+
diff --git a/msm8909/sdm/libs/core/drm/hw_color_manager_drm.cpp b/msm8909/sdm/libs/core/drm/hw_color_manager_drm.cpp
new file mode 100644
index 00000000..640a8432
--- /dev/null
+++ b/msm8909/sdm/libs/core/drm/hw_color_manager_drm.cpp
@@ -0,0 +1,294 @@
+/*
+* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#define __CLASS__ "HWColorManagerDRM"
+
+#ifdef PP_DRM_ENABLE
+#include <drm/msm_drm_pp.h>
+#endif
+#include <utils/debug.h>
+#include "hw_color_manager_drm.h"
+
+using sde_drm::kFeaturePcc;
+using sde_drm::kFeatureIgc;
+using sde_drm::kFeaturePgc;
+using sde_drm::kFeatureMixerGc;
+using sde_drm::kFeaturePaV2;
+using sde_drm::kFeatureDither;
+using sde_drm::kFeatureGamut;
+using sde_drm::kFeaturePADither;
+using sde_drm::kPPFeaturesMax;
+
+#ifdef PP_DRM_ENABLE
+static const uint32_t kPgcDataMask = 0x3FF;
+static const uint32_t kPgcShift = 16;
+#endif
+
+namespace sdm {
+
+DisplayError (*HWColorManagerDrm::GetDrmFeature[])(const PPFeatureInfo &, DRMPPFeatureInfo *) = {
+ [kGlobalColorFeaturePcc] = &HWColorManagerDrm::GetDrmPCC,
+ [kGlobalColorFeatureIgc] = &HWColorManagerDrm::GetDrmIGC,
+ [kGlobalColorFeaturePgc] = &HWColorManagerDrm::GetDrmPGC,
+ [kMixerColorFeatureGc] = &HWColorManagerDrm::GetDrmMixerGC,
+ [kGlobalColorFeaturePaV2] = &HWColorManagerDrm::GetDrmPAV2,
+ [kGlobalColorFeatureDither] = &HWColorManagerDrm::GetDrmDither,
+ [kGlobalColorFeatureGamut] = &HWColorManagerDrm::GetDrmGamut,
+ [kGlobalColorFeaturePADither] = &HWColorManagerDrm::GetDrmPADither,
+};
+
+void HWColorManagerDrm::FreeDrmFeatureData(DRMPPFeatureInfo *feature) {
+ if (feature->payload)
+ free(feature->payload);
+}
+
+uint32_t HWColorManagerDrm::GetFeatureVersion(const DRMPPFeatureInfo &feature) {
+ uint32_t version = PPFeatureVersion::kSDEPpVersionInvalid;
+
+ switch (feature.id) {
+ case kFeaturePcc:
+ break;
+ case kFeatureIgc:
+ break;
+ case kFeaturePgc:
+ if (feature.version == 1)
+ version = PPFeatureVersion::kSDEPgcV17;
+ break;
+ case kFeatureMixerGc:
+ break;
+ case kFeaturePaV2:
+ break;
+ case kFeatureDither:
+ break;
+ case kFeatureGamut:
+ if (feature.version == 1)
+ version = PPFeatureVersion::kSDEGamutV17;
+ else if (feature.version == 4)
+ version = PPFeatureVersion::kSDEGamutV4;
+ break;
+ case kFeaturePADither:
+ break;
+ default:
+ break;
+ }
+ return version;
+}
+
+DRMPPFeatureID HWColorManagerDrm::ToDrmFeatureId(uint32_t id) {
+ DRMPPFeatureID ret = kPPFeaturesMax;
+
+ switch (id) {
+ case kGlobalColorFeaturePcc:
+ ret = kFeaturePcc;
+ break;
+ case kGlobalColorFeatureIgc:
+ ret = kFeatureIgc;
+ break;
+ case kGlobalColorFeaturePgc:
+ ret = kFeaturePgc;
+ break;
+ case kMixerColorFeatureGc:
+ ret = kFeatureMixerGc;
+ break;
+ case kGlobalColorFeaturePaV2:
+ ret = kFeaturePaV2;
+ break;
+ case kGlobalColorFeatureDither:
+ ret = kFeatureDither;
+ break;
+ case kGlobalColorFeatureGamut:
+ ret = kFeatureGamut;
+ break;
+ case kGlobalColorFeaturePADither:
+ ret = kFeaturePADither;
+ break;
+ default:
+ break;
+ }
+ return ret;
+}
+
+DisplayError HWColorManagerDrm::GetDrmPCC(const PPFeatureInfo &in_data,
+ DRMPPFeatureInfo *out_data) {
+ DisplayError ret = kErrorNone;
+ return ret;
+}
+
+DisplayError HWColorManagerDrm::GetDrmIGC(const PPFeatureInfo &in_data,
+ DRMPPFeatureInfo *out_data) {
+ DisplayError ret = kErrorNone;
+ return ret;
+}
+
+DisplayError HWColorManagerDrm::GetDrmPGC(const PPFeatureInfo &in_data,
+ DRMPPFeatureInfo *out_data) {
+ DisplayError ret = kErrorNone;
+#ifdef PP_DRM_ENABLE
+ struct SDEPgcLUTData *sde_pgc;
+ struct drm_msm_pgc_lut *mdp_pgc;
+
+ if (!out_data) {
+ DLOGE("Invalid input parameter for gamut");
+ return kErrorParameters;
+ }
+ sde_pgc = (struct SDEPgcLUTData *)in_data.GetConfigData();
+ out_data->id = kFeaturePgc;
+ out_data->type = sde_drm::kPropBlob;
+ out_data->version = in_data.feature_version_;
+ out_data->payload_size = sizeof(struct drm_msm_pgc_lut);
+
+ if (in_data.enable_flags_ & kOpsDisable) {
+ /* feature disable case */
+ out_data->payload = NULL;
+ return ret;
+ } else if (!(in_data.enable_flags_ & kOpsEnable)) {
+ out_data->payload = NULL;
+ return kErrorParameters;
+ }
+
+ mdp_pgc = new drm_msm_pgc_lut();
+ if (!mdp_pgc) {
+ DLOGE("Failed to allocate memory for pgc");
+ return kErrorMemory;
+ }
+
+ if (in_data.enable_flags_ & kOpsEnable)
+ mdp_pgc->flags = PGC_8B_ROUND;
+ else
+ mdp_pgc->flags = 0;
+
+ for (int i = 0, j = 0; i < PGC_TBL_LEN; i++, j += 2) {
+ mdp_pgc->c0[i] = (sde_pgc->c0_data[j] & kPgcDataMask) |
+ (sde_pgc->c0_data[j + 1] & kPgcDataMask) << kPgcShift;
+ mdp_pgc->c1[i] = (sde_pgc->c1_data[j] & kPgcDataMask) |
+ (sde_pgc->c1_data[j + 1] & kPgcDataMask) << kPgcShift;
+ mdp_pgc->c2[i] = (sde_pgc->c2_data[j] & kPgcDataMask) |
+ (sde_pgc->c2_data[j + 1] & kPgcDataMask) << kPgcShift;
+ }
+ out_data->payload = mdp_pgc;
+#endif
+ return ret;
+}
+
+DisplayError HWColorManagerDrm::GetDrmMixerGC(const PPFeatureInfo &in_data,
+ DRMPPFeatureInfo *out_data) {
+ DisplayError ret = kErrorNone;
+ return ret;
+}
+
+DisplayError HWColorManagerDrm::GetDrmPAV2(const PPFeatureInfo &in_data,
+ DRMPPFeatureInfo *out_data) {
+ DisplayError ret = kErrorNone;
+ return ret;
+}
+
+DisplayError HWColorManagerDrm::GetDrmDither(const PPFeatureInfo &in_data,
+ DRMPPFeatureInfo *out_data) {
+ DisplayError ret = kErrorNone;
+ return ret;
+}
+
+DisplayError HWColorManagerDrm::GetDrmGamut(const PPFeatureInfo &in_data,
+ DRMPPFeatureInfo *out_data) {
+ DisplayError ret = kErrorNone;
+#ifdef PP_DRM_ENABLE
+ struct SDEGamutCfg *sde_gamut = NULL;
+ struct drm_msm_3d_gamut *mdp_gamut = NULL;
+ uint32_t size = 0;
+
+ if (!out_data) {
+ DLOGE("Invalid input parameter for gamut");
+ return kErrorParameters;
+ }
+ sde_gamut = (struct SDEGamutCfg *)in_data.GetConfigData();
+ out_data->id = kFeatureGamut;
+ out_data->type = sde_drm::kPropBlob;
+ out_data->version = in_data.feature_version_;
+ out_data->payload_size = sizeof(struct drm_msm_3d_gamut);
+ if (in_data.enable_flags_ & kOpsDisable) {
+ /* feature disable case */
+ out_data->payload = NULL;
+ return ret;
+ } else if (!(in_data.enable_flags_ & kOpsEnable)) {
+ out_data->payload = NULL;
+ return kErrorParameters;
+ }
+
+ mdp_gamut = new drm_msm_3d_gamut();
+ if (!mdp_gamut) {
+ DLOGE("Failed to allocate memory for gamut");
+ return kErrorMemory;
+ }
+
+ if (sde_gamut->map_en)
+ mdp_gamut->flags = GAMUT_3D_MAP_EN;
+ else
+ mdp_gamut->flags = 0;
+
+ switch (sde_gamut->mode) {
+ case SDEGamutCfgWrapper::GAMUT_FINE_MODE:
+ mdp_gamut->mode = GAMUT_3D_MODE_17;
+ size = GAMUT_3D_MODE17_TBL_SZ;
+ break;
+ case SDEGamutCfgWrapper::GAMUT_COARSE_MODE:
+ mdp_gamut->mode = GAMUT_3D_MODE_5;
+ size = GAMUT_3D_MODE5_TBL_SZ;
+ break;
+ case SDEGamutCfgWrapper::GAMUT_COARSE_MODE_13:
+ mdp_gamut->mode = GAMUT_3D_MODE_13;
+ size = GAMUT_3D_MODE13_TBL_SZ;
+ break;
+ default:
+ DLOGE("Invalid gamut mode %d", sde_gamut->mode);
+ free(mdp_gamut);
+ return kErrorParameters;
+ }
+
+ if (sde_gamut->map_en)
+ std::memcpy(mdp_gamut->scale_off, sde_gamut->scale_off_data,
+ sizeof(uint32_t) * GAMUT_3D_SCALE_OFF_SZ * GAMUT_3D_SCALE_OFF_TBL_NUM);
+
+ for (uint32_t row = 0; row < GAMUT_3D_TBL_NUM; row++) {
+ for (uint32_t col = 0; col < size; col++) {
+ mdp_gamut->col[row][col].c0 = sde_gamut->c0_data[row][col];
+ mdp_gamut->col[row][col].c2_c1 = sde_gamut->c1_c2_data[row][col];
+ }
+ }
+ out_data->payload = mdp_gamut;
+#endif
+ return ret;
+}
+
+DisplayError HWColorManagerDrm::GetDrmPADither(const PPFeatureInfo &in_data,
+ DRMPPFeatureInfo *out_data) {
+ DisplayError ret = kErrorNone;
+ return ret;
+}
+
+} // namespace sdm
diff --git a/msm8909/sdm/libs/core/drm/hw_color_manager_drm.h b/msm8909/sdm/libs/core/drm/hw_color_manager_drm.h
new file mode 100644
index 00000000..a10d00bb
--- /dev/null
+++ b/msm8909/sdm/libs/core/drm/hw_color_manager_drm.h
@@ -0,0 +1,64 @@
+/*
+* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __HW_COLOR_MANAGER_DRM_H__
+#define __HW_COLOR_MANAGER_DRM_H__
+
+#include <drm_interface.h>
+#include <private/color_params.h>
+
+using sde_drm::DRMPPFeatureID;
+using sde_drm::DRMPPFeatureInfo;
+
+namespace sdm {
+
+class HWColorManagerDrm {
+ public:
+ static DisplayError (*GetDrmFeature[kMaxNumPPFeatures])(const PPFeatureInfo &in_data,
+ DRMPPFeatureInfo *out_data);
+ static void FreeDrmFeatureData(DRMPPFeatureInfo *feature);
+ static uint32_t GetFeatureVersion(const DRMPPFeatureInfo &feature);
+ static DRMPPFeatureID ToDrmFeatureId(uint32_t id);
+ protected:
+ HWColorManagerDrm() {}
+
+ private:
+ static DisplayError GetDrmPCC(const PPFeatureInfo &in_data, DRMPPFeatureInfo *out_data);
+ static DisplayError GetDrmIGC(const PPFeatureInfo &in_data, DRMPPFeatureInfo *out_data);
+ static DisplayError GetDrmPGC(const PPFeatureInfo &in_data, DRMPPFeatureInfo *out_data);
+ static DisplayError GetDrmMixerGC(const PPFeatureInfo &in_data, DRMPPFeatureInfo *out_data);
+ static DisplayError GetDrmPAV2(const PPFeatureInfo &in_data, DRMPPFeatureInfo *out_data);
+ static DisplayError GetDrmDither(const PPFeatureInfo &in_data, DRMPPFeatureInfo *out_data);
+ static DisplayError GetDrmGamut(const PPFeatureInfo &in_data, DRMPPFeatureInfo *out_data);
+ static DisplayError GetDrmPADither(const PPFeatureInfo &in_data, DRMPPFeatureInfo *out_data);
+};
+
+} // namespace sdm
+
+#endif // __HW_COLOR_MANAGER_DRM_H__
diff --git a/msm8909/sdm/libs/core/drm/hw_device_drm.cpp b/msm8909/sdm/libs/core/drm/hw_device_drm.cpp
new file mode 100644
index 00000000..400856ca
--- /dev/null
+++ b/msm8909/sdm/libs/core/drm/hw_device_drm.cpp
@@ -0,0 +1,1061 @@
+/*
+* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#define __STDC_FORMAT_MACROS
+
+#include <ctype.h>
+#include <drm/drm_fourcc.h>
+#include <drm_lib_loader.h>
+#include <drm_master.h>
+#include <drm_res_mgr.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <linux/fb.h>
+#include <math.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <utils/constants.h>
+#include <utils/debug.h>
+#include <utils/formats.h>
+#include <utils/sys.h>
+#include <private/color_params.h>
+
+#include <algorithm>
+#include <string>
+#include <unordered_map>
+#include <utility>
+#include <vector>
+
+#include "hw_device_drm.h"
+#include "hw_info_interface.h"
+#include "hw_color_manager_drm.h"
+
+#define __CLASS__ "HWDeviceDRM"
+
+#ifndef DRM_FORMAT_MOD_QCOM_COMPRESSED
+#define DRM_FORMAT_MOD_QCOM_COMPRESSED fourcc_mod_code(QCOM, 1)
+#endif
+#ifndef DRM_FORMAT_MOD_QCOM_DX
+#define DRM_FORMAT_MOD_QCOM_DX fourcc_mod_code(QCOM, 0x2)
+#endif
+#ifndef DRM_FORMAT_MOD_QCOM_TIGHT
+#define DRM_FORMAT_MOD_QCOM_TIGHT fourcc_mod_code(QCOM, 0x4)
+#endif
+
+using std::string;
+using std::to_string;
+using std::fstream;
+using std::unordered_map;
+using drm_utils::DRMMaster;
+using drm_utils::DRMResMgr;
+using drm_utils::DRMLibLoader;
+using drm_utils::DRMBuffer;
+using sde_drm::GetDRMManager;
+using sde_drm::DestroyDRMManager;
+using sde_drm::DRMDisplayType;
+using sde_drm::DRMDisplayToken;
+using sde_drm::DRMConnectorInfo;
+using sde_drm::DRMPPFeatureInfo;
+using sde_drm::DRMRect;
+using sde_drm::DRMRotation;
+using sde_drm::DRMBlendType;
+using sde_drm::DRMSrcConfig;
+using sde_drm::DRMOps;
+using sde_drm::DRMTopology;
+
+namespace sdm {
+
+static void GetDRMFormat(LayerBufferFormat format, uint32_t *drm_format,
+ uint64_t *drm_format_modifier) {
+ switch (format) {
+ case kFormatRGBA8888:
+ *drm_format = DRM_FORMAT_ABGR8888;
+ break;
+ case kFormatRGBA8888Ubwc:
+ *drm_format = DRM_FORMAT_ABGR8888;
+ *drm_format_modifier = DRM_FORMAT_MOD_QCOM_COMPRESSED;
+ break;
+ case kFormatRGBA5551:
+ *drm_format = DRM_FORMAT_ABGR1555;
+ break;
+ case kFormatRGBA4444:
+ *drm_format = DRM_FORMAT_ABGR4444;
+ break;
+ case kFormatBGRA8888:
+ *drm_format = DRM_FORMAT_ARGB8888;
+ break;
+ case kFormatRGBX8888:
+ *drm_format = DRM_FORMAT_XBGR8888;
+ break;
+ case kFormatRGBX8888Ubwc:
+ *drm_format = DRM_FORMAT_XBGR8888;
+ *drm_format_modifier = DRM_FORMAT_MOD_QCOM_COMPRESSED;
+ break;
+ case kFormatBGRX8888:
+ *drm_format = DRM_FORMAT_XRGB8888;
+ break;
+ case kFormatRGB888:
+ *drm_format = DRM_FORMAT_BGR888;
+ break;
+ case kFormatRGB565:
+ *drm_format = DRM_FORMAT_BGR565;
+ break;
+ case kFormatBGR565:
+ *drm_format = DRM_FORMAT_RGB565;
+ break;
+ case kFormatBGR565Ubwc:
+ *drm_format = DRM_FORMAT_BGR565;
+ *drm_format_modifier = DRM_FORMAT_MOD_QCOM_COMPRESSED;
+ break;
+ case kFormatRGBA1010102:
+ *drm_format = DRM_FORMAT_ABGR2101010;
+ break;
+ case kFormatRGBA1010102Ubwc:
+ *drm_format = DRM_FORMAT_ABGR2101010;
+ *drm_format_modifier = DRM_FORMAT_MOD_QCOM_COMPRESSED;
+ break;
+ case kFormatARGB2101010:
+ *drm_format = DRM_FORMAT_BGRA1010102;
+ break;
+ case kFormatRGBX1010102:
+ *drm_format = DRM_FORMAT_XBGR2101010;
+ break;
+ case kFormatRGBX1010102Ubwc:
+ *drm_format = DRM_FORMAT_XBGR2101010;
+ *drm_format_modifier = DRM_FORMAT_MOD_QCOM_COMPRESSED;
+ break;
+ case kFormatXRGB2101010:
+ *drm_format = DRM_FORMAT_BGRX1010102;
+ break;
+ case kFormatBGRA1010102:
+ *drm_format = DRM_FORMAT_ARGB2101010;
+ break;
+ case kFormatABGR2101010:
+ *drm_format = DRM_FORMAT_RGBA1010102;
+ break;
+ case kFormatBGRX1010102:
+ *drm_format = DRM_FORMAT_XRGB2101010;
+ break;
+ case kFormatXBGR2101010:
+ *drm_format = DRM_FORMAT_RGBX1010102;
+ break;
+ case kFormatYCbCr420SemiPlanar:
+ *drm_format = DRM_FORMAT_NV12;
+ break;
+ case kFormatYCbCr420SemiPlanarVenus:
+ *drm_format = DRM_FORMAT_NV12;
+ break;
+ case kFormatYCbCr420SPVenusUbwc:
+ *drm_format = DRM_FORMAT_NV12;
+ *drm_format_modifier = DRM_FORMAT_MOD_QCOM_COMPRESSED;
+ break;
+ case kFormatYCrCb420SemiPlanar:
+ *drm_format = DRM_FORMAT_NV21;
+ break;
+ case kFormatYCrCb420SemiPlanarVenus:
+ *drm_format = DRM_FORMAT_NV21;
+ break;
+ case kFormatYCbCr420P010:
+ *drm_format = DRM_FORMAT_NV12;
+ *drm_format_modifier = DRM_FORMAT_MOD_QCOM_DX;
+ break;
+ case kFormatYCbCr420P010Ubwc:
+ *drm_format = DRM_FORMAT_NV12;
+ *drm_format_modifier = DRM_FORMAT_MOD_QCOM_COMPRESSED |
+ DRM_FORMAT_MOD_QCOM_DX;
+ break;
+ case kFormatYCbCr420TP10Ubwc:
+ *drm_format = DRM_FORMAT_NV12;
+ *drm_format_modifier = DRM_FORMAT_MOD_QCOM_COMPRESSED |
+ DRM_FORMAT_MOD_QCOM_DX | DRM_FORMAT_MOD_QCOM_TIGHT;
+ break;
+ case kFormatYCbCr422H2V1SemiPlanar:
+ *drm_format = DRM_FORMAT_NV16;
+ break;
+ case kFormatYCrCb422H2V1SemiPlanar:
+ *drm_format = DRM_FORMAT_NV61;
+ break;
+ case kFormatYCrCb420PlanarStride16:
+ *drm_format = DRM_FORMAT_YVU420;
+ break;
+ default:
+ DLOGW("Unsupported format %s", GetFormatString(format));
+ }
+}
+
+void HWDeviceDRM::Registry::RegisterCurrent(HWLayers *hw_layers) {
+ DRMMaster *master = nullptr;
+ DRMMaster::GetInstance(&master);
+
+ if (!master) {
+ DLOGE("Failed to acquire DRM Master instance");
+ return;
+ }
+
+ HWLayersInfo &hw_layer_info = hw_layers->info;
+ uint32_t hw_layer_count = UINT32(hw_layer_info.hw_layers.size());
+
+ for (uint32_t i = 0; i < hw_layer_count; i++) {
+ Layer &layer = hw_layer_info.hw_layers.at(i);
+ LayerBuffer *input_buffer = &layer.input_buffer;
+ HWRotatorSession *hw_rotator_session = &hw_layers->config[i].hw_rotator_session;
+ HWRotateInfo *hw_rotate_info = &hw_rotator_session->hw_rotate_info[0];
+
+ if (hw_rotate_info->valid) {
+ input_buffer = &hw_rotator_session->output_buffer;
+ }
+
+ int fd = input_buffer->planes[0].fd;
+ if (fd >= 0 && hashmap_[current_index_].find(fd) == hashmap_[current_index_].end()) {
+ AllocatedBufferInfo buf_info {};
+ DRMBuffer layout {};
+ buf_info.fd = layout.fd = fd;
+ buf_info.aligned_width = layout.width = input_buffer->width;
+ buf_info.aligned_height = layout.height = input_buffer->height;
+ buf_info.format = input_buffer->format;
+ GetDRMFormat(buf_info.format, &layout.drm_format, &layout.drm_format_modifier);
+ buffer_allocator_->GetBufferLayout(buf_info, layout.stride, layout.offset,
+ &layout.num_planes);
+ uint32_t fb_id = 0;
+ int ret = master->CreateFbId(layout, &fb_id);
+ if (ret < 0) {
+ DLOGE("CreateFbId failed. width %d, height %d, format: %s, stride %u, error %d",
+ layout.width, layout.height, GetFormatString(buf_info.format), layout.stride[0],
+ errno);
+ } else {
+ hashmap_[current_index_][fd] = fb_id;
+ }
+ }
+ }
+}
+
+void HWDeviceDRM::Registry::UnregisterNext() {
+ DRMMaster *master = nullptr;
+ DRMMaster::GetInstance(&master);
+
+ if (!master) {
+ DLOGE("Failed to acquire DRM Master instance");
+ return;
+ }
+
+ current_index_ = (current_index_ + 1) % kCycleDelay;
+ auto &curr_map = hashmap_[current_index_];
+ for (auto &pair : curr_map) {
+ uint32_t fb_id = pair.second;
+ int ret = master->RemoveFbId(fb_id);
+ if (ret < 0) {
+ DLOGE("Removing fb_id %d failed with error %d", fb_id, errno);
+ }
+ }
+
+ curr_map.clear();
+}
+
+void HWDeviceDRM::Registry::Clear() {
+ for (int i = 0; i < kCycleDelay; i++) {
+ UnregisterNext();
+ }
+ current_index_ = 0;
+}
+
+uint32_t HWDeviceDRM::Registry::GetFbId(int fd) {
+ auto it = hashmap_[current_index_].find(fd);
+ return (it == hashmap_[current_index_].end()) ? 0 : it->second;
+}
+
+HWDeviceDRM::HWDeviceDRM(BufferSyncHandler *buffer_sync_handler, BufferAllocator *buffer_allocator,
+ HWInfoInterface *hw_info_intf)
+ : hw_info_intf_(hw_info_intf), buffer_sync_handler_(buffer_sync_handler),
+ registry_(buffer_allocator) {
+ device_type_ = kDevicePrimary;
+ device_name_ = "Peripheral Display";
+ hw_info_intf_ = hw_info_intf;
+}
+
+DisplayError HWDeviceDRM::Init() {
+ DRMLibLoader *drm_lib = DRMLibLoader::GetInstance();
+ if (drm_lib == nullptr) {
+ DLOGE("Failed to load DRM Lib");
+ return kErrorResources;
+ }
+ default_mode_ = (drm_lib->IsLoaded() == false);
+
+ if (!default_mode_) {
+ DRMMaster *drm_master = {};
+ int dev_fd = -1;
+ DRMMaster::GetInstance(&drm_master);
+ drm_master->GetHandle(&dev_fd);
+ drm_lib->FuncGetDRMManager()(dev_fd, &drm_mgr_intf_);
+ if (drm_mgr_intf_->RegisterDisplay(DRMDisplayType::PERIPHERAL, &token_)) {
+ DLOGE("RegisterDisplay failed");
+ return kErrorResources;
+ }
+
+ drm_mgr_intf_->CreateAtomicReq(token_, &drm_atomic_intf_);
+ drm_mgr_intf_->GetConnectorInfo(token_.conn_id, &connector_info_);
+ InitializeConfigs();
+ drm_atomic_intf_->Perform(DRMOps::CRTC_SET_MODE, token_.crtc_id, &current_mode_);
+
+ drm_atomic_intf_->Perform(DRMOps::CRTC_SET_OUTPUT_FENCE_OFFSET, token_.crtc_id, 1);
+
+ // TODO(user): Enable this and remove the one in SetupAtomic() onces underruns are fixed
+ // drm_atomic_intf_->Perform(DRMOps::CRTC_SET_ACTIVE, token_.crtc_id, 1);
+ // Commit to setup pipeline with mode, which then tells us the topology etc
+ if (drm_atomic_intf_->Commit(true /* synchronous */)) {
+ DLOGE("Setting up CRTC %d, Connector %d for %s failed", token_.crtc_id, token_.conn_id,
+ device_name_);
+ return kErrorResources;
+ }
+
+ // Reload connector info for updated info after 1st commit
+ drm_mgr_intf_->GetConnectorInfo(token_.conn_id, &connector_info_);
+ DLOGI("Setup CRTC %d, Connector %d for %s", token_.crtc_id, token_.conn_id, device_name_);
+ }
+
+ PopulateDisplayAttributes();
+ PopulateHWPanelInfo();
+ UpdateMixerAttributes();
+ hw_info_intf_->GetHWResourceInfo(&hw_resource_);
+
+ // TODO(user): In future, remove has_qseed3 member, add version and pass version to constructor
+ if (hw_resource_.has_qseed3) {
+ hw_scale_ = new HWScaleDRM(HWScaleDRM::Version::V2);
+ }
+
+ return kErrorNone;
+}
+
+DisplayError HWDeviceDRM::Deinit() {
+ delete hw_scale_;
+ registry_.Clear();
+ drm_mgr_intf_->DestroyAtomicReq(drm_atomic_intf_);
+ drm_atomic_intf_ = {};
+ drm_mgr_intf_->UnregisterDisplay(token_);
+ return kErrorNone;
+}
+
+void HWDeviceDRM::InitializeConfigs() {
+ // TODO(user): Update modes
+ current_mode_ = connector_info_.modes[0];
+}
+
+DisplayError HWDeviceDRM::PopulateDisplayAttributes() {
+ drmModeModeInfo mode = {};
+ uint32_t mm_width = 0;
+ uint32_t mm_height = 0;
+ DRMTopology topology = DRMTopology::SINGLE_LM;
+
+ if (default_mode_) {
+ DRMResMgr *res_mgr = nullptr;
+ int ret = DRMResMgr::GetInstance(&res_mgr);
+ if (ret < 0) {
+ DLOGE("Failed to acquire DRMResMgr instance");
+ return kErrorResources;
+ }
+
+ res_mgr->GetMode(&mode);
+ res_mgr->GetDisplayDimInMM(&mm_width, &mm_height);
+ } else {
+ mode = current_mode_;
+ mm_width = connector_info_.mmWidth;
+ mm_height = connector_info_.mmHeight;
+ topology = connector_info_.topology;
+ }
+
+ display_attributes_.x_pixels = mode.hdisplay;
+ display_attributes_.y_pixels = mode.vdisplay;
+ display_attributes_.fps = mode.vrefresh;
+ display_attributes_.vsync_period_ns = UINT32(1000000000L / display_attributes_.fps);
+
+ /*
+ Active Front Sync Back
+ Region Porch Porch
+ <-----------------------><----------------><-------------><-------------->
+ <----- [hv]display ----->
+ <------------- [hv]sync_start ------------>
+ <--------------------- [hv]sync_end --------------------->
+ <-------------------------------- [hv]total ----------------------------->
+ */
+
+ display_attributes_.v_front_porch = mode.vsync_start - mode.vdisplay;
+ display_attributes_.v_pulse_width = mode.vsync_end - mode.vsync_start;
+ display_attributes_.v_back_porch = mode.vtotal - mode.vsync_end;
+ display_attributes_.v_total = mode.vtotal;
+
+ display_attributes_.h_total = mode.htotal;
+ uint32_t h_blanking = mode.htotal - mode.hdisplay;
+ display_attributes_.is_device_split =
+ (topology == DRMTopology::DUAL_LM || topology == DRMTopology::DUAL_LM_MERGE);
+ display_attributes_.h_total += display_attributes_.is_device_split ? h_blanking : 0;
+
+ display_attributes_.x_dpi = (FLOAT(mode.hdisplay) * 25.4f) / FLOAT(mm_width);
+ display_attributes_.y_dpi = (FLOAT(mode.vdisplay) * 25.4f) / FLOAT(mm_height);
+
+ return kErrorNone;
+}
+
+void HWDeviceDRM::PopulateHWPanelInfo() {
+ hw_panel_info_ = {};
+
+ snprintf(hw_panel_info_.panel_name, sizeof(hw_panel_info_.panel_name), "%s",
+ connector_info_.panel_name.c_str());
+ hw_panel_info_.split_info.left_split = display_attributes_.x_pixels;
+ if (display_attributes_.is_device_split) {
+ hw_panel_info_.split_info.left_split = hw_panel_info_.split_info.right_split =
+ display_attributes_.x_pixels / 2;
+ }
+
+ hw_panel_info_.partial_update = 0;
+ hw_panel_info_.left_align = 0;
+ hw_panel_info_.width_align = 0;
+ hw_panel_info_.top_align = 0;
+ hw_panel_info_.height_align = 0;
+ hw_panel_info_.min_roi_width = 0;
+ hw_panel_info_.min_roi_height = 0;
+ hw_panel_info_.needs_roi_merge = 0;
+ hw_panel_info_.dynamic_fps = connector_info_.dynamic_fps;
+ hw_panel_info_.min_fps = 60;
+ hw_panel_info_.max_fps = 60;
+ hw_panel_info_.is_primary_panel = connector_info_.is_primary;
+ hw_panel_info_.is_pluggable = 0;
+
+ if (!default_mode_) {
+ hw_panel_info_.needs_roi_merge = (connector_info_.topology == DRMTopology::DUAL_LM_MERGE);
+ }
+
+ GetHWDisplayPortAndMode();
+ GetHWPanelMaxBrightness();
+
+ DLOGI("%s, Panel Interface = %s, Panel Mode = %s, Is Primary = %d", device_name_,
+ interface_str_.c_str(), hw_panel_info_.mode == kModeVideo ? "Video" : "Command",
+ hw_panel_info_.is_primary_panel);
+ DLOGI("Partial Update = %d, Dynamic FPS = %d", hw_panel_info_.partial_update,
+ hw_panel_info_.dynamic_fps);
+ DLOGI("Align: left = %d, width = %d, top = %d, height = %d", hw_panel_info_.left_align,
+ hw_panel_info_.width_align, hw_panel_info_.top_align, hw_panel_info_.height_align);
+ DLOGI("ROI: min_width = %d, min_height = %d, need_merge = %d", hw_panel_info_.min_roi_width,
+ hw_panel_info_.min_roi_height, hw_panel_info_.needs_roi_merge);
+ DLOGI("FPS: min = %d, max =%d", hw_panel_info_.min_fps, hw_panel_info_.max_fps);
+ DLOGI("Left Split = %d, Right Split = %d", hw_panel_info_.split_info.left_split,
+ hw_panel_info_.split_info.right_split);
+}
+
+void HWDeviceDRM::GetHWDisplayPortAndMode() {
+ hw_panel_info_.port = kPortDefault;
+ hw_panel_info_.mode =
+ (connector_info_.panel_mode == sde_drm::DRMPanelMode::VIDEO) ? kModeVideo : kModeCommand;
+
+ if (default_mode_) {
+ return;
+ }
+
+ switch (connector_info_.type) {
+ case DRM_MODE_CONNECTOR_DSI:
+ hw_panel_info_.port = kPortDSI;
+ interface_str_ = "DSI";
+ break;
+ case DRM_MODE_CONNECTOR_LVDS:
+ hw_panel_info_.port = kPortLVDS;
+ interface_str_ = "LVDS";
+ break;
+ case DRM_MODE_CONNECTOR_eDP:
+ hw_panel_info_.port = kPortEDP;
+ interface_str_ = "EDP";
+ break;
+ case DRM_MODE_CONNECTOR_TV:
+ case DRM_MODE_CONNECTOR_HDMIA:
+ case DRM_MODE_CONNECTOR_HDMIB:
+ hw_panel_info_.port = kPortDTV;
+ interface_str_ = "HDMI";
+ break;
+ case DRM_MODE_CONNECTOR_VIRTUAL:
+ hw_panel_info_.port = kPortWriteBack;
+ interface_str_ = "Virtual";
+ break;
+ case DRM_MODE_CONNECTOR_DisplayPort:
+ // TODO(user): Add when available
+ interface_str_ = "DisplayPort";
+ break;
+ }
+
+ return;
+}
+
+void HWDeviceDRM::GetHWPanelMaxBrightness() {
+ char brightness[kMaxStringLength] = {0};
+ string kMaxBrightnessNode = "/sys/class/backlight/panel0-backlight/max_brightness";
+
+ hw_panel_info_.panel_max_brightness = 255;
+ int fd = Sys::open_(kMaxBrightnessNode.c_str(), O_RDONLY);
+ if (fd < 0) {
+ DLOGW("Failed to open max brightness node = %s, error = %s", kMaxBrightnessNode.c_str(),
+ strerror(errno));
+ return;
+ }
+
+ if (Sys::pread_(fd, brightness, sizeof(brightness), 0) > 0) {
+ hw_panel_info_.panel_max_brightness = atoi(brightness);
+ DLOGI("Max brightness level = %d", hw_panel_info_.panel_max_brightness);
+ } else {
+ DLOGW("Failed to read max brightness level. error = %s", strerror(errno));
+ }
+
+ Sys::close_(fd);
+}
+
+DisplayError HWDeviceDRM::GetActiveConfig(uint32_t *active_config) {
+ *active_config = 0;
+ return kErrorNone;
+}
+
+DisplayError HWDeviceDRM::GetNumDisplayAttributes(uint32_t *count) {
+ *count = 1;
+ return kErrorNone;
+}
+
+DisplayError HWDeviceDRM::GetDisplayAttributes(uint32_t index,
+ HWDisplayAttributes *display_attributes) {
+ *display_attributes = display_attributes_;
+ return kErrorNone;
+}
+
+DisplayError HWDeviceDRM::GetHWPanelInfo(HWPanelInfo *panel_info) {
+ *panel_info = hw_panel_info_;
+ return kErrorNone;
+}
+
+DisplayError HWDeviceDRM::SetDisplayAttributes(uint32_t index) {
+ return kErrorNone;
+}
+
+DisplayError HWDeviceDRM::SetDisplayAttributes(const HWDisplayAttributes &display_attributes) {
+ return kErrorNotSupported;
+}
+
+DisplayError HWDeviceDRM::GetConfigIndex(uint32_t mode, uint32_t *index) {
+ return kErrorNone;
+}
+
+DisplayError HWDeviceDRM::PowerOn() {
+ DTRACE_SCOPED();
+ return kErrorNone;
+}
+
+DisplayError HWDeviceDRM::PowerOff() {
+ return kErrorNone;
+}
+
+DisplayError HWDeviceDRM::Doze() {
+ return kErrorNone;
+}
+
+DisplayError HWDeviceDRM::DozeSuspend() {
+ return kErrorNone;
+}
+
+DisplayError HWDeviceDRM::Standby() {
+ return kErrorNone;
+}
+
+void HWDeviceDRM::SetupAtomic(HWLayers *hw_layers, bool validate) {
+ if (default_mode_) {
+ return;
+ }
+
+ HWLayersInfo &hw_layer_info = hw_layers->info;
+ uint32_t hw_layer_count = UINT32(hw_layer_info.hw_layers.size());
+
+ for (uint32_t i = 0; i < hw_layer_count; i++) {
+ Layer &layer = hw_layer_info.hw_layers.at(i);
+ LayerBuffer *input_buffer = &layer.input_buffer;
+ HWPipeInfo *left_pipe = &hw_layers->config[i].left_pipe;
+ HWPipeInfo *right_pipe = &hw_layers->config[i].right_pipe;
+ HWRotatorSession *hw_rotator_session = &hw_layers->config[i].hw_rotator_session;
+ bool needs_rotation = false;
+
+ for (uint32_t count = 0; count < 2; count++) {
+ HWPipeInfo *pipe_info = (count == 0) ? left_pipe : right_pipe;
+ HWRotateInfo *hw_rotate_info = &hw_rotator_session->hw_rotate_info[count];
+
+ if (hw_rotate_info->valid) {
+ input_buffer = &hw_rotator_session->output_buffer;
+ needs_rotation = true;
+ }
+
+ uint32_t fb_id = registry_.GetFbId(input_buffer->planes[0].fd);
+ if (pipe_info->valid && fb_id) {
+ uint32_t pipe_id = pipe_info->pipe_id;
+ drm_atomic_intf_->Perform(DRMOps::PLANE_SET_ALPHA, pipe_id, layer.plane_alpha);
+ drm_atomic_intf_->Perform(DRMOps::PLANE_SET_ZORDER, pipe_id, pipe_info->z_order);
+ DRMBlendType blending = {};
+ SetBlending(layer.blending, &blending);
+ drm_atomic_intf_->Perform(DRMOps::PLANE_SET_BLEND_TYPE, pipe_id, blending);
+ DRMRect src = {};
+ SetRect(pipe_info->src_roi, &src);
+ drm_atomic_intf_->Perform(DRMOps::PLANE_SET_SRC_RECT, pipe_id, src);
+ DRMRect dst = {};
+ SetRect(pipe_info->dst_roi, &dst);
+ drm_atomic_intf_->Perform(DRMOps::PLANE_SET_DST_RECT, pipe_id, dst);
+
+ uint32_t rot_bit_mask = 0;
+ // In case of rotation, rotator handles flips
+ if (!needs_rotation) {
+ if (layer.transform.flip_horizontal) {
+ rot_bit_mask |= UINT32(DRMRotation::FLIP_H);
+ }
+ if (layer.transform.flip_vertical) {
+ rot_bit_mask |= UINT32(DRMRotation::FLIP_V);
+ }
+ }
+
+ drm_atomic_intf_->Perform(DRMOps::PLANE_SET_ROTATION, pipe_id, rot_bit_mask);
+ drm_atomic_intf_->Perform(DRMOps::PLANE_SET_H_DECIMATION, pipe_id,
+ pipe_info->horizontal_decimation);
+ drm_atomic_intf_->Perform(DRMOps::PLANE_SET_V_DECIMATION, pipe_id,
+ pipe_info->vertical_decimation);
+ uint32_t config = 0;
+ SetSrcConfig(layer.input_buffer, &config);
+ drm_atomic_intf_->Perform(DRMOps::PLANE_SET_SRC_CONFIG, pipe_id, config);;
+ drm_atomic_intf_->Perform(DRMOps::PLANE_SET_FB_ID, pipe_id, fb_id);
+ drm_atomic_intf_->Perform(DRMOps::PLANE_SET_CRTC, pipe_id, token_.crtc_id);
+ if (!validate && input_buffer->acquire_fence_fd >= 0) {
+ drm_atomic_intf_->Perform(DRMOps::PLANE_SET_INPUT_FENCE, pipe_id,
+ input_buffer->acquire_fence_fd);
+ }
+ if (hw_scale_) {
+ SDEScaler scaler_output = {};
+ hw_scale_->SetPlaneScaler(pipe_info->scale_data, &scaler_output);
+ // TODO(user): Remove qseed3 and add version check, then send appropriate scaler object
+ if (hw_resource_.has_qseed3) {
+ drm_atomic_intf_->Perform(DRMOps::PLANE_SET_SCALER_CONFIG, pipe_id,
+ reinterpret_cast<uint64_t>(&scaler_output.scaler_v2));
+ }
+ }
+ }
+ }
+
+ // TODO(user): Remove this and enable the one in Init() onces underruns are fixed
+ drm_atomic_intf_->Perform(DRMOps::CRTC_SET_ACTIVE, token_.crtc_id, 1);
+ }
+}
+
+DisplayError HWDeviceDRM::Validate(HWLayers *hw_layers) {
+ DTRACE_SCOPED();
+
+ registry_.RegisterCurrent(hw_layers);
+ SetupAtomic(hw_layers, true /* validate */);
+
+ int ret = drm_atomic_intf_->Validate();
+ if (ret) {
+ DLOGE("%s failed with error %d", __FUNCTION__, ret);
+ return kErrorHardware;
+ }
+
+ return kErrorNone;
+}
+
+DisplayError HWDeviceDRM::Commit(HWLayers *hw_layers) {
+ DTRACE_SCOPED();
+
+ DisplayError err = kErrorNone;
+ registry_.RegisterCurrent(hw_layers);
+
+ if (default_mode_) {
+ err = DefaultCommit(hw_layers);
+ } else {
+ err = AtomicCommit(hw_layers);
+ }
+
+ registry_.UnregisterNext();
+
+ return err;
+}
+
+DisplayError HWDeviceDRM::DefaultCommit(HWLayers *hw_layers) {
+ DTRACE_SCOPED();
+
+ HWLayersInfo &hw_layer_info = hw_layers->info;
+ LayerStack *stack = hw_layer_info.stack;
+
+ stack->retire_fence_fd = -1;
+ for (Layer &layer : hw_layer_info.hw_layers) {
+ layer.input_buffer.release_fence_fd = -1;
+ }
+
+ DRMMaster *master = nullptr;
+ int ret = DRMMaster::GetInstance(&master);
+ if (ret < 0) {
+ DLOGE("Failed to acquire DRMMaster instance");
+ return kErrorResources;
+ }
+
+ DRMResMgr *res_mgr = nullptr;
+ ret = DRMResMgr::GetInstance(&res_mgr);
+ if (ret < 0) {
+ DLOGE("Failed to acquire DRMResMgr instance");
+ return kErrorResources;
+ }
+
+ int dev_fd = -1;
+ master->GetHandle(&dev_fd);
+
+ uint32_t connector_id = 0;
+ res_mgr->GetConnectorId(&connector_id);
+
+ uint32_t crtc_id = 0;
+ res_mgr->GetCrtcId(&crtc_id);
+
+ drmModeModeInfo mode;
+ res_mgr->GetMode(&mode);
+
+ uint32_t fb_id = registry_.GetFbId(hw_layer_info.hw_layers.at(0).input_buffer.planes[0].fd);
+ ret = drmModeSetCrtc(dev_fd, crtc_id, fb_id, 0 /* x */, 0 /* y */, &connector_id,
+ 1 /* num_connectors */, &mode);
+ if (ret < 0) {
+ DLOGE("drmModeSetCrtc failed dev fd %d, fb_id %d, crtc id %d, connector id %d, %s", dev_fd,
+ fb_id, crtc_id, connector_id, strerror(errno));
+ return kErrorHardware;
+ }
+
+ return kErrorNone;
+}
+
+DisplayError HWDeviceDRM::AtomicCommit(HWLayers *hw_layers) {
+ DTRACE_SCOPED();
+ SetupAtomic(hw_layers, false /* validate */);
+
+ int ret = drm_atomic_intf_->Commit(false /* synchronous */);
+ if (ret) {
+ DLOGE("%s failed with error %d", __FUNCTION__, ret);
+ return kErrorHardware;
+ }
+
+ int release_fence = -1;
+ int retire_fence = -1;
+
+ drm_atomic_intf_->Perform(DRMOps::CRTC_GET_RELEASE_FENCE, token_.crtc_id, &release_fence);
+ drm_atomic_intf_->Perform(DRMOps::CONNECTOR_GET_RETIRE_FENCE, token_.conn_id, &retire_fence);
+
+ HWLayersInfo &hw_layer_info = hw_layers->info;
+ LayerStack *stack = hw_layer_info.stack;
+ stack->retire_fence_fd = retire_fence;
+
+ for (uint32_t i = 0; i < hw_layer_info.hw_layers.size(); i++) {
+ Layer &layer = hw_layer_info.hw_layers.at(i);
+ HWRotatorSession *hw_rotator_session = &hw_layers->config[i].hw_rotator_session;
+ if (hw_rotator_session->hw_block_count) {
+ hw_rotator_session->output_buffer.release_fence_fd = Sys::dup_(release_fence);
+ } else {
+ layer.input_buffer.release_fence_fd = Sys::dup_(release_fence);
+ }
+ }
+
+ hw_layer_info.sync_handle = release_fence;
+
+ return kErrorNone;
+}
+
+DisplayError HWDeviceDRM::Flush() {
+ return kErrorNone;
+}
+
+void HWDeviceDRM::SetBlending(const LayerBlending &source, DRMBlendType *target) {
+ switch (source) {
+ case kBlendingPremultiplied:
+ *target = DRMBlendType::PREMULTIPLIED;
+ break;
+ case kBlendingOpaque:
+ *target = DRMBlendType::OPAQUE;
+ break;
+ case kBlendingCoverage:
+ *target = DRMBlendType::COVERAGE;
+ break;
+ default:
+ *target = DRMBlendType::UNDEFINED;
+ }
+}
+
+
+void HWDeviceDRM::SetSrcConfig(const LayerBuffer &input_buffer, uint32_t *config) {
+ if (input_buffer.flags.interlace) {
+ *config |= (0x01 << UINT32(DRMSrcConfig::DEINTERLACE));
+ }
+}
+
+void HWDeviceDRM::SetRect(const LayerRect &source, DRMRect *target) {
+ target->left = UINT32(source.left);
+ target->top = UINT32(source.top);
+ target->right = UINT32(source.right);
+ target->bottom = UINT32(source.bottom);
+}
+
+bool HWDeviceDRM::EnableHotPlugDetection(int enable) {
+ return true;
+}
+
+void HWDeviceDRM::ResetDisplayParams() {}
+
+DisplayError HWDeviceDRM::SetCursorPosition(HWLayers *hw_layers, int x, int y) {
+ DTRACE_SCOPED();
+ return kErrorNone;
+}
+
+DisplayError HWDeviceDRM::GetPPFeaturesVersion(PPFeatureVersion *vers) {
+ struct DRMPPFeatureInfo info = {};
+
+ for (uint32_t i = 0; i < kMaxNumPPFeatures; i++) {
+ memset(&info, 0, sizeof(struct DRMPPFeatureInfo));
+ info.id = HWColorManagerDrm::ToDrmFeatureId(i);
+ if (info.id >= sde_drm::kPPFeaturesMax)
+ continue;
+ // use crtc_id_ = 0 since PP features are same across all CRTCs
+ drm_mgr_intf_->GetCrtcPPInfo(0, info);
+ vers->version[i] = HWColorManagerDrm::GetFeatureVersion(info);
+ }
+ return kErrorNone;
+}
+
+DisplayError HWDeviceDRM::SetPPFeatures(PPFeaturesConfig *feature_list) {
+ int ret = 0;
+ PPFeatureInfo *feature = NULL;
+ DRMPPFeatureInfo kernel_params = {};
+
+ while (true) {
+ ret = feature_list->RetrieveNextFeature(&feature);
+ if (ret)
+ break;
+
+ if (feature) {
+ DLOGV_IF(kTagDriverConfig, "feature_id = %d", feature->feature_id_);
+ if (!HWColorManagerDrm::GetDrmFeature[feature->feature_id_]) {
+ DLOGE("GetDrmFeature is not valid for feature %d", feature->feature_id_);
+ continue;
+ }
+ ret = HWColorManagerDrm::GetDrmFeature[feature->feature_id_](*feature, &kernel_params);
+ if (!ret)
+ drm_atomic_intf_->Perform(DRMOps::CRTC_SET_POST_PROC, token_.crtc_id, &kernel_params);
+ HWColorManagerDrm::FreeDrmFeatureData(&kernel_params);
+ }
+ }
+
+ // Once all features were consumed, then destroy all feature instance from feature_list,
+ feature_list->Reset();
+
+ return kErrorNone;
+}
+
+DisplayError HWDeviceDRM::SetVSyncState(bool enable) {
+ return kErrorNone;
+}
+
+void HWDeviceDRM::SetIdleTimeoutMs(uint32_t timeout_ms) {}
+
+DisplayError HWDeviceDRM::SetDisplayMode(const HWDisplayMode hw_display_mode) {
+ return kErrorNotSupported;
+}
+
+DisplayError HWDeviceDRM::SetRefreshRate(uint32_t refresh_rate) {
+ return kErrorNotSupported;
+}
+
+DisplayError HWDeviceDRM::SetPanelBrightness(int level) {
+ DisplayError err = kErrorNone;
+ char buffer[kMaxSysfsCommandLength] = {0};
+
+ DLOGV_IF(kTagDriverConfig, "Set brightness level to %d", level);
+ int fd = Sys::open_(kBrightnessNode, O_RDWR);
+ if (fd < 0) {
+ DLOGV_IF(kTagDriverConfig, "Failed to open node = %s, error = %s ", kBrightnessNode,
+ strerror(errno));
+ return kErrorFileDescriptor;
+ }
+
+ int32_t bytes = snprintf(buffer, kMaxSysfsCommandLength, "%d\n", level);
+ ssize_t ret = Sys::pwrite_(fd, buffer, static_cast<size_t>(bytes), 0);
+ if (ret <= 0) {
+ DLOGV_IF(kTagDriverConfig, "Failed to write to node = %s, error = %s ", kBrightnessNode,
+ strerror(errno));
+ err = kErrorHardware;
+ }
+
+ Sys::close_(fd);
+
+ return err;
+}
+
+DisplayError HWDeviceDRM::GetPanelBrightness(int *level) {
+ DisplayError err = kErrorNone;
+ char brightness[kMaxStringLength] = {0};
+
+ if (!level) {
+ DLOGV_IF(kTagDriverConfig, "Invalid input, null pointer.");
+ return kErrorParameters;
+ }
+
+ int fd = Sys::open_(kBrightnessNode, O_RDWR);
+ if (fd < 0) {
+ DLOGV_IF(kTagDriverConfig, "Failed to open brightness node = %s, error = %s", kBrightnessNode,
+ strerror(errno));
+ return kErrorFileDescriptor;
+ }
+
+ if (Sys::pread_(fd, brightness, sizeof(brightness), 0) > 0) {
+ *level = atoi(brightness);
+ DLOGV_IF(kTagDriverConfig, "Brightness level = %d", *level);
+ } else {
+ DLOGV_IF(kTagDriverConfig, "Failed to read panel brightness");
+ err = kErrorHardware;
+ }
+
+ Sys::close_(fd);
+
+ return err;
+}
+
+DisplayError HWDeviceDRM::CachePanelBrightness(int level) {
+ return kErrorNotSupported;
+}
+
+DisplayError HWDeviceDRM::GetHWScanInfo(HWScanInfo *scan_info) {
+ return kErrorNotSupported;
+}
+
+DisplayError HWDeviceDRM::GetVideoFormat(uint32_t config_index, uint32_t *video_format) {
+ return kErrorNotSupported;
+}
+
+DisplayError HWDeviceDRM::GetMaxCEAFormat(uint32_t *max_cea_format) {
+ return kErrorNotSupported;
+}
+
+DisplayError HWDeviceDRM::OnMinHdcpEncryptionLevelChange(uint32_t min_enc_level) {
+ return kErrorNotSupported;
+}
+
+DisplayError HWDeviceDRM::SetS3DMode(HWS3DMode s3d_mode) {
+ return kErrorNotSupported;
+}
+
+DisplayError HWDeviceDRM::SetScaleLutConfig(HWScaleLutInfo *lut_info) {
+ sde_drm::DRMScalerLUTInfo drm_lut_info = {};
+ drm_lut_info.cir_lut = lut_info->cir_lut;
+ drm_lut_info.dir_lut = lut_info->dir_lut;
+ drm_lut_info.sep_lut = lut_info->sep_lut;
+ drm_lut_info.cir_lut_size = lut_info->cir_lut_size;
+ drm_lut_info.dir_lut_size = lut_info->dir_lut_size;
+ drm_lut_info.sep_lut_size = lut_info->sep_lut_size;
+ drm_mgr_intf_->SetScalerLUT(drm_lut_info);
+
+ return kErrorNone;
+}
+
+DisplayError HWDeviceDRM::SetMixerAttributes(const HWMixerAttributes &mixer_attributes) {
+ if (!hw_resource_.hw_dest_scalar_info.count) {
+ return kErrorNotSupported;
+ }
+
+ if (mixer_attributes.width > display_attributes_.x_pixels ||
+ mixer_attributes.height > display_attributes_.y_pixels) {
+ DLOGW("Input resolution exceeds display resolution! input: res %dx%d display: res %dx%d",
+ mixer_attributes.width, mixer_attributes.height, display_attributes_.x_pixels,
+ display_attributes_.y_pixels);
+ return kErrorNotSupported;
+ }
+
+ uint32_t max_input_width = hw_resource_.hw_dest_scalar_info.max_input_width;
+ if (display_attributes_.is_device_split) {
+ max_input_width *= 2;
+ }
+
+ if (mixer_attributes.width > max_input_width) {
+ DLOGW("Input width exceeds width limit! input_width %d width_limit %d", mixer_attributes.width,
+ max_input_width);
+ return kErrorNotSupported;
+ }
+
+ float mixer_aspect_ratio = FLOAT(mixer_attributes.width) / FLOAT(mixer_attributes.height);
+ float display_aspect_ratio =
+ FLOAT(display_attributes_.x_pixels) / FLOAT(display_attributes_.y_pixels);
+
+ if (display_aspect_ratio != mixer_aspect_ratio) {
+ DLOGW("Aspect ratio mismatch! input: res %dx%d display: res %dx%d", mixer_attributes.width,
+ mixer_attributes.height, display_attributes_.x_pixels, display_attributes_.y_pixels);
+ return kErrorNotSupported;
+ }
+
+ float scale_x = FLOAT(display_attributes_.x_pixels) / FLOAT(mixer_attributes.width);
+ float scale_y = FLOAT(display_attributes_.y_pixels) / FLOAT(mixer_attributes.height);
+ float max_scale_up = hw_resource_.hw_dest_scalar_info.max_scale_up;
+ if (scale_x > max_scale_up || scale_y > max_scale_up) {
+ DLOGW(
+ "Up scaling ratio exceeds for destination scalar upscale limit scale_x %f scale_y %f "
+ "max_scale_up %f",
+ scale_x, scale_y, max_scale_up);
+ return kErrorNotSupported;
+ }
+
+ float mixer_split_ratio = FLOAT(mixer_attributes_.split_left) / FLOAT(mixer_attributes_.width);
+
+ mixer_attributes_ = mixer_attributes;
+ mixer_attributes_.split_left = mixer_attributes_.width;
+ if (display_attributes_.is_device_split) {
+ mixer_attributes_.split_left = UINT32(FLOAT(mixer_attributes.width) * mixer_split_ratio);
+ }
+
+ return kErrorNone;
+}
+
+DisplayError HWDeviceDRM::GetMixerAttributes(HWMixerAttributes *mixer_attributes) {
+ if (!mixer_attributes) {
+ return kErrorParameters;
+ }
+
+ mixer_attributes_.width = display_attributes_.x_pixels;
+ mixer_attributes_.height = display_attributes_.y_pixels;
+ mixer_attributes_.split_left = display_attributes_.is_device_split
+ ? hw_panel_info_.split_info.left_split
+ : mixer_attributes_.width;
+ *mixer_attributes = mixer_attributes_;
+
+ return kErrorNone;
+}
+
+void HWDeviceDRM::UpdateMixerAttributes() {
+ mixer_attributes_.width = display_attributes_.x_pixels;
+ mixer_attributes_.height = display_attributes_.y_pixels;
+ mixer_attributes_.split_left = display_attributes_.is_device_split
+ ? hw_panel_info_.split_info.left_split
+ : mixer_attributes_.width;
+}
+
+} // namespace sdm
diff --git a/msm8909/sdm/libs/core/drm/hw_device_drm.h b/msm8909/sdm/libs/core/drm/hw_device_drm.h
new file mode 100644
index 00000000..cc2ae7bc
--- /dev/null
+++ b/msm8909/sdm/libs/core/drm/hw_device_drm.h
@@ -0,0 +1,168 @@
+/*
+* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __HW_DEVICE_DRM_H__
+#define __HW_DEVICE_DRM_H__
+
+#include <drm_interface.h>
+#include <errno.h>
+#include <pthread.h>
+#include <xf86drmMode.h>
+#include <string>
+#include <unordered_map>
+#include <vector>
+
+#include "hw_interface.h"
+#include "hw_scale_drm.h"
+
+#define IOCTL_LOGE(ioctl, type) \
+ DLOGE("ioctl %s, device = %d errno = %d, desc = %s", #ioctl, type, errno, strerror(errno))
+
+namespace sdm {
+class HWInfoInterface;
+
+class HWDeviceDRM : public HWInterface {
+ public:
+ explicit HWDeviceDRM(BufferSyncHandler *buffer_sync_handler, BufferAllocator *buffer_allocator,
+ HWInfoInterface *hw_info_intf);
+ virtual ~HWDeviceDRM() {}
+ virtual DisplayError Init();
+ virtual DisplayError Deinit();
+
+ protected:
+ // From HWInterface
+ virtual DisplayError GetActiveConfig(uint32_t *active_config);
+ virtual DisplayError GetNumDisplayAttributes(uint32_t *count);
+ virtual DisplayError GetDisplayAttributes(uint32_t index,
+ HWDisplayAttributes *display_attributes);
+ virtual DisplayError GetHWPanelInfo(HWPanelInfo *panel_info);
+ virtual DisplayError SetDisplayAttributes(uint32_t index);
+ virtual DisplayError SetDisplayAttributes(const HWDisplayAttributes &display_attributes);
+ virtual DisplayError GetConfigIndex(uint32_t mode, uint32_t *index);
+ virtual DisplayError PowerOn();
+ virtual DisplayError PowerOff();
+ virtual DisplayError Doze();
+ virtual DisplayError DozeSuspend();
+ virtual DisplayError Standby();
+ virtual DisplayError Validate(HWLayers *hw_layers);
+ virtual DisplayError Commit(HWLayers *hw_layers);
+ virtual DisplayError Flush();
+ virtual DisplayError GetPPFeaturesVersion(PPFeatureVersion *vers);
+ virtual DisplayError SetPPFeatures(PPFeaturesConfig *feature_list);
+ virtual DisplayError SetVSyncState(bool enable);
+ virtual void SetIdleTimeoutMs(uint32_t timeout_ms);
+ virtual DisplayError SetDisplayMode(const HWDisplayMode hw_display_mode);
+ virtual DisplayError SetRefreshRate(uint32_t refresh_rate);
+ virtual DisplayError SetPanelBrightness(int level);
+ virtual DisplayError CachePanelBrightness(int level);
+ virtual DisplayError GetHWScanInfo(HWScanInfo *scan_info);
+ virtual DisplayError GetVideoFormat(uint32_t config_index, uint32_t *video_format);
+ virtual DisplayError GetMaxCEAFormat(uint32_t *max_cea_format);
+ virtual DisplayError SetCursorPosition(HWLayers *hw_layers, int x, int y);
+ virtual DisplayError OnMinHdcpEncryptionLevelChange(uint32_t min_enc_level);
+ virtual DisplayError GetPanelBrightness(int *level);
+ virtual DisplayError SetAutoRefresh(bool enable) { return kErrorNone; }
+ virtual DisplayError SetS3DMode(HWS3DMode s3d_mode);
+ virtual DisplayError SetScaleLutConfig(HWScaleLutInfo *lut_info);
+ virtual DisplayError SetMixerAttributes(const HWMixerAttributes &mixer_attributes);
+ virtual DisplayError GetMixerAttributes(HWMixerAttributes *mixer_attributes);
+
+ enum {
+ kHWEventVSync,
+ kHWEventBlank,
+ };
+
+ static const int kMaxStringLength = 1024;
+ static const int kNumPhysicalDisplays = 2;
+ static const int kMaxSysfsCommandLength = 12;
+ static constexpr const char *kBrightnessNode =
+ "/sys/class/backlight/panel0-backlight/brightness";
+
+ DisplayError SetFormat(const LayerBufferFormat &source, uint32_t *target);
+ DisplayError SetStride(HWDeviceType device_type, LayerBufferFormat format, uint32_t width,
+ uint32_t *target);
+ DisplayError PopulateDisplayAttributes();
+ void PopulateHWPanelInfo();
+ void GetHWDisplayPortAndMode();
+ void GetHWPanelMaxBrightness();
+ void ResetDisplayParams();
+ bool EnableHotPlugDetection(int enable);
+ void UpdateMixerAttributes();
+ void InitializeConfigs();
+ void SetBlending(const LayerBlending &source, sde_drm::DRMBlendType *target);
+ void SetSrcConfig(const LayerBuffer &input_buffer, uint32_t *config);
+ void SetRect(const LayerRect &source, sde_drm::DRMRect *target);
+ DisplayError DefaultCommit(HWLayers *hw_layers);
+ DisplayError AtomicCommit(HWLayers *hw_layers);
+ void SetupAtomic(HWLayers *hw_layers, bool validate);
+
+ class Registry {
+ public:
+ explicit Registry(BufferAllocator *buffer_allocator) : buffer_allocator_(buffer_allocator) {}
+ // Call on each validate and commit to register layer buffers
+ void RegisterCurrent(HWLayers *hw_layers);
+ // Call at the end of draw cycle to clear the next slot for business
+ void UnregisterNext();
+ // Call on display disconnect to release all gem handles and fb_ids
+ void Clear();
+ // Finds an fb_id corresponding to an fd in current map
+ uint32_t GetFbId(int fd);
+
+ private:
+ static const int kCycleDelay = 1; // N cycle delay before destroy
+ // fd to fb_id map. fd is used as key only for a single draw cycle between
+ // prepare and commit. It should not be used for caching in future due to fd recycling
+ std::unordered_map<int, uint32_t> hashmap_[kCycleDelay] {};
+ int current_index_ = 0;
+ BufferAllocator *buffer_allocator_ = {};
+ };
+
+ HWResourceInfo hw_resource_ = {};
+ HWPanelInfo hw_panel_info_ = {};
+ HWInfoInterface *hw_info_intf_ = {};
+ BufferSyncHandler *buffer_sync_handler_ = {};
+ HWDeviceType device_type_ = {};
+ const char *device_name_ = {};
+ bool synchronous_commit_ = false;
+ HWDisplayAttributes display_attributes_ = {};
+ HWMixerAttributes mixer_attributes_ = {};
+ sde_drm::DRMManagerInterface *drm_mgr_intf_ = {};
+ sde_drm::DRMAtomicReqInterface *drm_atomic_intf_ = {};
+ sde_drm::DRMDisplayToken token_ = {};
+ drmModeModeInfo current_mode_ = {};
+ bool default_mode_ = false;
+ sde_drm::DRMConnectorInfo connector_info_ = {};
+ std::string interface_str_ = "DSI";
+ HWScaleDRM *hw_scale_ = {};
+ Registry registry_;
+};
+
+} // namespace sdm
+
+#endif // __HW_DEVICE_DRM_H__
diff --git a/msm8909/sdm/libs/core/drm/hw_events_drm.cpp b/msm8909/sdm/libs/core/drm/hw_events_drm.cpp
new file mode 100644
index 00000000..9c9023a9
--- /dev/null
+++ b/msm8909/sdm/libs/core/drm/hw_events_drm.cpp
@@ -0,0 +1,298 @@
+/*
+* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <drm_master.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <math.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/prctl.h>
+#include <sys/resource.h>
+#include <sys/types.h>
+#include <utils/debug.h>
+#include <utils/sys.h>
+#include <xf86drm.h>
+
+#include <algorithm>
+#include <map>
+#include <utility>
+#include <vector>
+
+#include "hw_events_drm.h"
+
+#define __CLASS__ "HWEventsDRM"
+
+namespace sdm {
+
+using drm_utils::DRMMaster;
+
+DisplayError HWEventsDRM::InitializePollFd() {
+ for (uint32_t i = 0; i < event_data_list_.size(); i++) {
+ char data[kMaxStringLength]{};
+ HWEventData &event_data = event_data_list_[i];
+ poll_fds_[i].fd = -1;
+
+ switch (event_data.event_type) {
+ case HWEvent::VSYNC: {
+ poll_fds_[i].events = POLLIN | POLLPRI | POLLERR;
+ DRMMaster *master = nullptr;
+ int ret = DRMMaster::GetInstance(&master);
+ if (ret < 0) {
+ DLOGE("Failed to acquire DRMMaster instance");
+ return kErrorNotSupported;
+ }
+ master->GetHandle(&poll_fds_[i].fd);
+ vsync_index_ = i;
+ } break;
+ case HWEvent::EXIT: {
+ // Create an eventfd to be used to unblock the poll system call when
+ // a thread is exiting.
+ poll_fds_[i].fd = Sys::eventfd_(0, 0);
+ poll_fds_[i].events |= POLLIN;
+ // Clear any existing data
+ Sys::pread_(poll_fds_[i].fd, data, kMaxStringLength, 0);
+ } break;
+ case HWEvent::IDLE_NOTIFY:
+ case HWEvent::SHOW_BLANK_EVENT:
+ case HWEvent::THERMAL_LEVEL:
+ case HWEvent::IDLE_POWER_COLLAPSE:
+ break;
+ }
+ }
+
+ return kErrorNone;
+}
+
+DisplayError HWEventsDRM::SetEventParser() {
+ DisplayError error = kErrorNone;
+
+ for (auto &event_data : event_data_list_) {
+ switch (event_data.event_type) {
+ case HWEvent::VSYNC:
+ event_data.event_parser = &HWEventsDRM::HandleVSync;
+ break;
+ case HWEvent::IDLE_NOTIFY:
+ event_data.event_parser = &HWEventsDRM::HandleIdleTimeout;
+ break;
+ case HWEvent::EXIT:
+ event_data.event_parser = &HWEventsDRM::HandleThreadExit;
+ break;
+ case HWEvent::SHOW_BLANK_EVENT:
+ event_data.event_parser = &HWEventsDRM::HandleBlank;
+ break;
+ case HWEvent::THERMAL_LEVEL:
+ event_data.event_parser = &HWEventsDRM::HandleThermal;
+ break;
+ case HWEvent::IDLE_POWER_COLLAPSE:
+ event_data.event_parser = &HWEventsDRM::HandleIdlePowerCollapse;
+ break;
+ default:
+ error = kErrorParameters;
+ break;
+ }
+ }
+
+ return error;
+}
+
+void HWEventsDRM::PopulateHWEventData(const vector<HWEvent> &event_list) {
+ for (auto &event : event_list) {
+ HWEventData event_data;
+ event_data.event_type = event;
+ event_data_list_.push_back(std::move(event_data));
+ }
+
+ SetEventParser();
+ InitializePollFd();
+}
+
+DisplayError HWEventsDRM::Init(int display_type, HWEventHandler *event_handler,
+ const vector<HWEvent> &event_list) {
+ if (!event_handler)
+ return kErrorParameters;
+
+ event_handler_ = event_handler;
+ poll_fds_.resize(event_list.size());
+ event_thread_name_ += " - " + std::to_string(display_type);
+
+ PopulateHWEventData(event_list);
+
+ if (pthread_create(&event_thread_, NULL, &DisplayEventThread, this) < 0) {
+ DLOGE("Failed to start %s, error = %s", event_thread_name_.c_str());
+ return kErrorResources;
+ }
+
+ return kErrorNone;
+}
+
+DisplayError HWEventsDRM::Deinit() {
+ exit_threads_ = true;
+ Sys::pthread_cancel_(event_thread_);
+
+ for (uint32_t i = 0; i < event_data_list_.size(); i++) {
+ if (event_data_list_[i].event_type == HWEvent::EXIT) {
+ uint64_t exit_value = 1;
+ ssize_t write_size = Sys::write_(poll_fds_[i].fd, &exit_value, sizeof(uint64_t));
+ if (write_size != sizeof(uint64_t)) {
+ DLOGW("Error triggering exit fd (%d). write size = %d, error = %s", poll_fds_[i].fd,
+ write_size, strerror(errno));
+ }
+ }
+ }
+
+ pthread_join(event_thread_, NULL);
+ CloseFds();
+
+ return kErrorNone;
+}
+
+DisplayError HWEventsDRM::CloseFds() {
+ for (uint32_t i = 0; i < event_data_list_.size(); i++) {
+ switch (event_data_list_[i].event_type) {
+ case HWEvent::VSYNC:
+ poll_fds_[i].fd = -1;
+ break;
+ case HWEvent::EXIT:
+ Sys::close_(poll_fds_[i].fd);
+ poll_fds_[i].fd = -1;
+ break;
+ case HWEvent::IDLE_NOTIFY:
+ case HWEvent::SHOW_BLANK_EVENT:
+ case HWEvent::THERMAL_LEVEL:
+ case HWEvent::IDLE_POWER_COLLAPSE:
+ break;
+ default:
+ return kErrorNotSupported;
+ }
+ }
+
+ return kErrorNone;
+}
+
+void *HWEventsDRM::DisplayEventThread(void *context) {
+ if (context) {
+ return reinterpret_cast<HWEventsDRM *>(context)->DisplayEventHandler();
+ }
+
+ return NULL;
+}
+
+void *HWEventsDRM::DisplayEventHandler() {
+ char data[kMaxStringLength]{};
+
+ prctl(PR_SET_NAME, event_thread_name_.c_str(), 0, 0, 0);
+ setpriority(PRIO_PROCESS, 0, kThreadPriorityUrgent);
+
+ while (!exit_threads_) {
+ if (RegisterVSync() != kErrorNone) {
+ pthread_exit(0);
+ return nullptr;
+ }
+
+ int error = Sys::poll_(poll_fds_.data(), UINT32(poll_fds_.size()), -1);
+ if (error <= 0) {
+ DLOGW("poll failed. error = %s", strerror(errno));
+ continue;
+ }
+
+ for (uint32_t i = 0; i < event_data_list_.size(); i++) {
+ pollfd &poll_fd = poll_fds_[i];
+ switch (event_data_list_[i].event_type) {
+ case HWEvent::VSYNC:
+ (this->*(event_data_list_[i]).event_parser)(nullptr);
+ break;
+ case HWEvent::EXIT:
+ if ((poll_fd.revents & POLLIN) &&
+ (Sys::read_(poll_fd.fd, data, kMaxStringLength) > 0)) {
+ (this->*(event_data_list_[i]).event_parser)(data);
+ }
+ break;
+ case HWEvent::IDLE_NOTIFY:
+ case HWEvent::SHOW_BLANK_EVENT:
+ case HWEvent::THERMAL_LEVEL:
+ case HWEvent::IDLE_POWER_COLLAPSE:
+ if (poll_fd.fd >= 0 && (poll_fd.revents & POLLPRI) &&
+ (Sys::pread_(poll_fd.fd, data, kMaxStringLength, 0) > 0)) {
+ (this->*(event_data_list_[i]).event_parser)(data);
+ }
+ break;
+ }
+ }
+ }
+
+ pthread_exit(0);
+
+ return nullptr;
+}
+
+DisplayError HWEventsDRM::RegisterVSync() {
+ drmVBlank vblank{};
+ vblank.request.type = (drmVBlankSeqType)(DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT);
+ vblank.request.sequence = 1;
+ // DRM hack to pass in context to unused field signal. Driver will write this to the node being
+ // polled on, and will be read as part of drm event handling and sent to handler
+ vblank.request.signal = reinterpret_cast<unsigned long>(this); // NOLINT
+ int error = drmWaitVBlank(poll_fds_[vsync_index_].fd, &vblank);
+ if (error < 0) {
+ DLOGE("drmWaitVBlank failed with err %d", errno);
+ return kErrorResources;
+ }
+
+ return kErrorNone;
+}
+
+void HWEventsDRM::HandleVSync(char *data) {
+ if (poll_fds_[vsync_index_].revents & (POLLIN | POLLPRI)) {
+ drmEventContext event = {};
+ event.version = DRM_EVENT_CONTEXT_VERSION;
+ event.vblank_handler = &HWEventsDRM::VSyncHandlerCallback;
+ int error = drmHandleEvent(poll_fds_[vsync_index_].fd, &event);
+ if (error != 0) {
+ DLOGE("drmHandleEvent failed: %i", error);
+ }
+ }
+}
+
+void HWEventsDRM::VSyncHandlerCallback(int fd, unsigned int sequence, unsigned int tv_sec,
+ unsigned int tv_usec, void *data) {
+ int64_t timestamp = (int64_t)(tv_sec)*1000000000 + (int64_t)(tv_usec)*1000;
+ reinterpret_cast<HWEventsDRM *>(data)->event_handler_->VSync(timestamp);
+}
+
+void HWEventsDRM::HandleIdleTimeout(char *data) {
+ event_handler_->IdleTimeout();
+}
+
+void HWEventsDRM::HandleIdlePowerCollapse(char *data) {
+ event_handler_->IdlePowerCollapse();
+}
+
+} // namespace sdm
diff --git a/msm8909/sdm/libs/core/drm/hw_events_drm.h b/msm8909/sdm/libs/core/drm/hw_events_drm.h
new file mode 100644
index 00000000..f114b1fa
--- /dev/null
+++ b/msm8909/sdm/libs/core/drm/hw_events_drm.h
@@ -0,0 +1,90 @@
+/*
+* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __HW_EVENTS_DRM_H__
+#define __HW_EVENTS_DRM_H__
+
+#include <sys/poll.h>
+#include <map>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "hw_events_interface.h"
+#include "hw_interface.h"
+
+namespace sdm {
+
+using std::vector;
+
+class HWEventsDRM : public HWEventsInterface {
+ public:
+ virtual DisplayError Init(int display_type, HWEventHandler *event_handler,
+ const vector<HWEvent> &event_list);
+ virtual DisplayError Deinit();
+
+ private:
+ static const int kMaxStringLength = 1024;
+
+ typedef void (HWEventsDRM::*EventParser)(char *);
+
+ struct HWEventData {
+ HWEvent event_type {};
+ EventParser event_parser {};
+ };
+
+ static void *DisplayEventThread(void *context);
+ static void VSyncHandlerCallback(int fd, unsigned int sequence, unsigned int tv_sec,
+ unsigned int tv_usec, void *data);
+
+ void *DisplayEventHandler();
+ void HandleVSync(char *data);
+ void HandleIdleTimeout(char *data);
+ void HandleThreadExit(char *data) {}
+ void HandleThermal(char *data) {}
+ void HandleBlank(char *data) {}
+ void HandleIdlePowerCollapse(char *data);
+ void PopulateHWEventData(const vector<HWEvent> &event_list);
+ DisplayError SetEventParser();
+ DisplayError InitializePollFd();
+ DisplayError CloseFds();
+ DisplayError RegisterVSync();
+
+ HWEventHandler *event_handler_{};
+ vector<HWEventData> event_data_list_{};
+ vector<pollfd> poll_fds_{};
+ pthread_t event_thread_{};
+ std::string event_thread_name_ = "SDM_EventThread";
+ bool exit_threads_ = false;
+ uint32_t vsync_index_ = 0;
+};
+
+} // namespace sdm
+
+#endif // __HW_EVENTS_DRM_H__
diff --git a/msm8909/sdm/libs/core/drm/hw_info_drm.cpp b/msm8909/sdm/libs/core/drm/hw_info_drm.cpp
new file mode 100644
index 00000000..c59d9db6
--- /dev/null
+++ b/msm8909/sdm/libs/core/drm/hw_info_drm.cpp
@@ -0,0 +1,594 @@
+/*
+* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <dlfcn.h>
+#include <drm/drm_fourcc.h>
+#include <drm_lib_loader.h>
+#include <drm_master.h>
+#include <drm_res_mgr.h>
+#include <fcntl.h>
+#include <media/msm_sde_rotator.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <utils/constants.h>
+#include <utils/debug.h>
+#include <utils/sys.h>
+
+#include <algorithm>
+#include <fstream>
+#include <iostream>
+#include <map>
+#include <memory>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "hw_info_drm.h"
+
+#ifndef DRM_FORMAT_MOD_QCOM_COMPRESSED
+#define DRM_FORMAT_MOD_QCOM_COMPRESSED fourcc_mod_code(QCOM, 1)
+#endif
+#ifndef DRM_FORMAT_MOD_QCOM_DX
+#define DRM_FORMAT_MOD_QCOM_DX fourcc_mod_code(QCOM, 0x2)
+#endif
+#ifndef DRM_FORMAT_MOD_QCOM_TIGHT
+#define DRM_FORMAT_MOD_QCOM_TIGHT fourcc_mod_code(QCOM, 0x4)
+#endif
+
+#define __CLASS__ "HWInfoDRM"
+
+using drm_utils::DRMMaster;
+using drm_utils::DRMResMgr;
+using drm_utils::DRMLogger;
+using drm_utils::DRMLibLoader;
+using sde_drm::GetDRMManager;
+using sde_drm::DRMPlanesInfo;
+using sde_drm::DRMCrtcInfo;
+using sde_drm::DRMPlaneType;
+
+using std::vector;
+using std::map;
+using std::string;
+using std::fstream;
+using std::to_string;
+
+namespace sdm {
+
+class DRMLoggerImpl : public DRMLogger {
+ public:
+#define PRINTLOG(tag, method, format, buf) \
+ va_list list; \
+ va_start(list, format); \
+ vsnprintf(buf, sizeof(buf), format, list); \
+ va_end(list); \
+ Debug::Get()->method(tag, "%s", buf);
+
+ void Error(const char *format, ...) { PRINTLOG(kTagNone, Error, format, buf_); }
+ void Warning(const char *format, ...) { PRINTLOG(kTagDriverConfig, Warning, format, buf_); }
+ void Info(const char *format, ...) { PRINTLOG(kTagDriverConfig, Info, format, buf_); }
+ void Debug(const char *format, ...) { PRINTLOG(kTagDriverConfig, Debug, format, buf_); }
+ void Verbose(const char *format, ...) { PRINTLOG(kTagDriverConfig, Verbose, format, buf_); }
+
+ private:
+ char buf_[1024] = {};
+};
+
+HWResourceInfo *HWInfoDRM::hw_resource_ = nullptr;
+
+HWInfoDRM::HWInfoDRM() {
+ DRMLogger::Set(new DRMLoggerImpl());
+ drm_lib = DRMLibLoader::GetInstance();
+ if (drm_lib == nullptr) {
+ DLOGE("Failed to load DRM Library");
+ return;
+ }
+ default_mode_ = (drm_lib->IsLoaded() == false);
+ if (!default_mode_) {
+ DRMMaster *drm_master = {};
+ int dev_fd = -1;
+ DRMMaster::GetInstance(&drm_master);
+ if (!drm_master) {
+ DLOGE("Failed to acquire DRMMaster instance");
+ return;
+ }
+ drm_master->GetHandle(&dev_fd);
+ drm_lib->FuncGetDRMManager()(dev_fd, &drm_mgr_intf_);
+ }
+}
+
+HWInfoDRM::~HWInfoDRM() {
+ if (hw_resource_ != nullptr) {
+ delete hw_resource_;
+ hw_resource_ = nullptr;
+ }
+
+ if (drm_mgr_intf_) {
+ if (drm_lib != nullptr) {
+ drm_lib->FuncDestroyDRMManager()();
+ }
+ drm_mgr_intf_ = nullptr;
+ }
+
+ drm_lib->Destroy();
+ drm_lib = nullptr;
+ DRMMaster::DestroyInstance();
+}
+
+DisplayError HWInfoDRM::GetDynamicBWLimits(HWResourceInfo *hw_resource) {
+ HWDynBwLimitInfo* bw_info = &hw_resource->dyn_bw_info;
+ for (int index = 0; index < kBwModeMax; index++) {
+ bw_info->total_bw_limit[index] = UINT32(hw_resource->max_bandwidth_low);
+ bw_info->pipe_bw_limit[index] = hw_resource->max_pipe_bw;
+ }
+
+ return kErrorNone;
+}
+
+DisplayError HWInfoDRM::GetHWResourceInfo(HWResourceInfo *hw_resource) {
+ if (hw_resource_) {
+ *hw_resource = *hw_resource_;
+ return kErrorNone;
+ }
+
+ hw_resource->num_blending_stages = 1;
+ hw_resource->max_pipe_width = 2560;
+ hw_resource->max_cursor_size = 128;
+ hw_resource->max_scale_down = 1;
+ hw_resource->max_scale_up = 1;
+ hw_resource->has_decimation = false;
+ hw_resource->max_bandwidth_low = 9600000;
+ hw_resource->max_bandwidth_high = 9600000;
+ hw_resource->max_pipe_bw = 4500000;
+ hw_resource->max_sde_clk = 412500000;
+ hw_resource->clk_fudge_factor = FLOAT(105) / FLOAT(100);
+ hw_resource->macrotile_nv12_factor = 8;
+ hw_resource->macrotile_factor = 4;
+ hw_resource->linear_factor = 1;
+ hw_resource->scale_factor = 1;
+ hw_resource->extra_fudge_factor = 2;
+ hw_resource->amortizable_threshold = 0;
+ hw_resource->system_overhead_lines = 0;
+ hw_resource->hw_dest_scalar_info.count = 0;
+ hw_resource->hw_dest_scalar_info.max_scale_up = 0;
+ hw_resource->hw_dest_scalar_info.max_input_width = 0;
+ hw_resource->hw_dest_scalar_info.max_output_width = 0;
+ hw_resource->is_src_split = true;
+ hw_resource->perf_calc = false;
+ hw_resource->has_dyn_bw_support = false;
+ hw_resource->has_qseed3 = false;
+ hw_resource->has_concurrent_writeback = false;
+
+ // TODO(user): Deprecate
+ hw_resource->hw_version = kHWMdssVersion5;
+ hw_resource->hw_revision = 0;
+ hw_resource->max_mixer_width = 0;
+ hw_resource->writeback_index = 0;
+ hw_resource->has_bwc = false;
+ hw_resource->has_ubwc = true;
+ hw_resource->has_macrotile = true;
+ hw_resource->separate_rotator = true;
+ hw_resource->has_non_scalar_rgb = false;
+
+ GetSystemInfo(hw_resource);
+ GetHWPlanesInfo(hw_resource);
+ GetWBInfo(hw_resource);
+
+ // Disable destination scalar count to 0 if extension library is not present
+ DynLib extension_lib;
+ if (!extension_lib.Open("libsdmextension.so")) {
+ hw_resource->hw_dest_scalar_info.count = 0;
+ }
+
+ DLOGI("Max plane width = %d", hw_resource->max_pipe_width);
+ DLOGI("Max cursor width = %d", hw_resource->max_cursor_size);
+ DLOGI("Max plane upscale = %d", hw_resource->max_scale_up);
+ DLOGI("Max plane downscale = %d", hw_resource->max_scale_down);
+ DLOGI("Has Decimation = %d", hw_resource->has_decimation);
+ DLOGI("Max Blending Stages = %d", hw_resource->num_blending_stages);
+ DLOGI("Has Source Split = %d", hw_resource->is_src_split);
+ DLOGI("Has QSEED3 = %d", hw_resource->has_qseed3);
+ DLOGI("Has UBWC = %d", hw_resource->has_ubwc);
+ DLOGI("Has Concurrent Writeback = %d", hw_resource->has_concurrent_writeback);
+ DLOGI("Max Low Bw = %" PRIu64 "", hw_resource->max_bandwidth_low);
+ DLOGI("Max High Bw = % " PRIu64 "", hw_resource->max_bandwidth_high);
+ DLOGI("Max Pipe Bw = %" PRIu64 " KBps", hw_resource->max_pipe_bw);
+ DLOGI("MaxSDEClock = % " PRIu64 " Hz", hw_resource->max_sde_clk);
+ DLOGI("Clock Fudge Factor = %f", hw_resource->clk_fudge_factor);
+ DLOGI("Prefill factors:");
+ DLOGI("\tTiled_NV12 = %d", hw_resource->macrotile_nv12_factor);
+ DLOGI("\tTiled = %d", hw_resource->macrotile_factor);
+ DLOGI("\tLinear = %d", hw_resource->linear_factor);
+ DLOGI("\tScale = %d", hw_resource->scale_factor);
+ DLOGI("\tFudge_factor = %d", hw_resource->extra_fudge_factor);
+
+ if (hw_resource->separate_rotator || hw_resource->num_dma_pipe) {
+ GetHWRotatorInfo(hw_resource);
+ }
+
+ if (hw_resource->has_dyn_bw_support) {
+ DisplayError ret = GetDynamicBWLimits(hw_resource);
+ if (ret != kErrorNone) {
+ DLOGE("Failed to read dynamic band width info");
+ return ret;
+ }
+
+ DLOGI("Has Support for multiple bw limits shown below");
+ for (int index = 0; index < kBwModeMax; index++) {
+ DLOGI("Mode-index=%d total_bw_limit=%d and pipe_bw_limit=%d", index,
+ hw_resource->dyn_bw_info.total_bw_limit[index],
+ hw_resource->dyn_bw_info.pipe_bw_limit[index]);
+ }
+ }
+
+ if (!hw_resource_) {
+ hw_resource_ = new HWResourceInfo();
+ *hw_resource_ = *hw_resource;
+ }
+
+ return kErrorNone;
+}
+
+void HWInfoDRM::GetSystemInfo(HWResourceInfo *hw_resource) {
+ DRMCrtcInfo info;
+ drm_mgr_intf_->GetCrtcInfo(0 /* system_info */, &info);
+ hw_resource->is_src_split = info.has_src_split;
+ hw_resource->has_qseed3 = (info.qseed_version == sde_drm::QSEEDVersion::V3);
+ hw_resource->num_blending_stages = info.max_blend_stages;
+ hw_resource->smart_dma_rev = (info.smart_dma_rev == sde_drm::SmartDMARevision::V2) ?
+ SmartDMARevision::V2 : SmartDMARevision::V1;
+}
+
+void HWInfoDRM::GetHWPlanesInfo(HWResourceInfo *hw_resource) {
+ DRMPlanesInfo planes;
+ drm_mgr_intf_->GetPlanesInfo(&planes);
+ for (auto &pipe_obj : planes) {
+ HWPipeCaps pipe_caps;
+ string name = {};
+ switch (pipe_obj.second.type) {
+ case DRMPlaneType::DMA:
+ name = "DMA";
+ pipe_caps.type = kPipeTypeDMA;
+ if (!hw_resource->num_dma_pipe) {
+ PopulateSupportedFmts(kHWDMAPipe, pipe_obj.second, hw_resource);
+ }
+ hw_resource->num_dma_pipe++;
+ break;
+ case DRMPlaneType::VIG:
+ name = "VIG";
+ pipe_caps.type = kPipeTypeVIG;
+ if (!hw_resource->num_vig_pipe) {
+ PopulatePipeCaps(pipe_obj.second, hw_resource);
+ PopulateSupportedFmts(kHWVIGPipe, pipe_obj.second, hw_resource);
+ }
+ hw_resource->num_vig_pipe++;
+ break;
+ case DRMPlaneType::CURSOR:
+ name = "CURSOR";
+ pipe_caps.type = kPipeTypeCursor;
+ if (!hw_resource->num_cursor_pipe) {
+ PopulateSupportedFmts(kHWCursorPipe, pipe_obj.second, hw_resource);
+ hw_resource->max_cursor_size = pipe_obj.second.max_linewidth;
+ }
+ hw_resource->num_cursor_pipe++;
+ break;
+ default:
+ continue; // Not adding any other pipe type
+ }
+ pipe_caps.id = pipe_obj.first;
+ pipe_caps.master_pipe_id = pipe_obj.second.master_plane_id;
+ DLOGI("Adding %s Pipe : Id %d", name.c_str(), pipe_obj.first);
+ hw_resource->hw_pipes.push_back(std::move(pipe_caps));
+ }
+}
+
+void HWInfoDRM::PopulatePipeCaps(const sde_drm::DRMPlaneTypeInfo &info,
+ HWResourceInfo *hw_resource) {
+ hw_resource->max_pipe_width = info.max_linewidth;
+ hw_resource->max_scale_down = info.max_downscale;
+ hw_resource->max_scale_up = info.max_upscale;
+ hw_resource->has_decimation = info.max_horizontal_deci > 1 && info.max_vertical_deci > 1;
+}
+
+void HWInfoDRM::PopulateSupportedFmts(HWSubBlockType sub_blk_type,
+ const sde_drm::DRMPlaneTypeInfo &info,
+ HWResourceInfo *hw_resource) {
+ vector<LayerBufferFormat> sdm_formats;
+ FormatsMap &fmts_map = hw_resource->supported_formats_map;
+
+ if (fmts_map.find(sub_blk_type) == fmts_map.end()) {
+ for (auto &fmts : info.formats_supported) {
+ GetSDMFormat(fmts.first, fmts.second, &sdm_formats);
+ }
+
+ fmts_map.insert(make_pair(sub_blk_type, sdm_formats));
+ }
+}
+
+void HWInfoDRM::GetWBInfo(HWResourceInfo *hw_resource) {
+ HWSubBlockType sub_blk_type = kHWWBIntfOutput;
+ vector<LayerBufferFormat> supported_sdm_formats;
+ sde_drm::DRMDisplayToken token;
+
+ // Fake register
+ if (drm_mgr_intf_->RegisterDisplay(sde_drm::DRMDisplayType::VIRTUAL, &token)) {
+ return;
+ }
+
+ sde_drm::DRMConnectorInfo connector_info;
+ drm_mgr_intf_->GetConnectorInfo(token.conn_id, &connector_info);
+ for (auto &fmts : connector_info.formats_supported) {
+ GetSDMFormat(fmts.first, fmts.second, &supported_sdm_formats);
+ }
+
+ hw_resource->supported_formats_map.erase(sub_blk_type);
+ hw_resource->supported_formats_map.insert(make_pair(sub_blk_type, supported_sdm_formats));
+
+ drm_mgr_intf_->UnregisterDisplay(token);
+}
+
+void HWInfoDRM::GetSDMFormat(uint32_t v4l2_format, LayerBufferFormat *sdm_format) {
+ switch (v4l2_format) {
+ case SDE_PIX_FMT_ARGB_8888: *sdm_format = kFormatARGB8888; break;
+ case SDE_PIX_FMT_RGBA_8888: *sdm_format = kFormatRGBA8888; break;
+ case SDE_PIX_FMT_BGRA_8888: *sdm_format = kFormatBGRA8888; break;
+ case SDE_PIX_FMT_RGBX_8888: *sdm_format = kFormatRGBX8888; break;
+ case SDE_PIX_FMT_BGRX_8888: *sdm_format = kFormatBGRX8888; break;
+ case SDE_PIX_FMT_RGBA_5551: *sdm_format = kFormatRGBA5551; break;
+ case SDE_PIX_FMT_RGBA_4444: *sdm_format = kFormatRGBA4444; break;
+ case SDE_PIX_FMT_RGB_888: *sdm_format = kFormatRGB888; break;
+ case SDE_PIX_FMT_BGR_888: *sdm_format = kFormatBGR888; break;
+ case SDE_PIX_FMT_RGB_565: *sdm_format = kFormatRGB565; break;
+ case SDE_PIX_FMT_BGR_565: *sdm_format = kFormatBGR565; break;
+ case SDE_PIX_FMT_Y_CB_CR_H2V2: *sdm_format = kFormatYCbCr420Planar; break;
+ case SDE_PIX_FMT_Y_CR_CB_H2V2: *sdm_format = kFormatYCrCb420Planar; break;
+ case SDE_PIX_FMT_Y_CR_CB_GH2V2: *sdm_format = kFormatYCrCb420PlanarStride16; break;
+ case SDE_PIX_FMT_Y_CBCR_H2V2: *sdm_format = kFormatYCbCr420SemiPlanar; break;
+ case SDE_PIX_FMT_Y_CRCB_H2V2: *sdm_format = kFormatYCrCb420SemiPlanar; break;
+ case SDE_PIX_FMT_Y_CBCR_H1V2: *sdm_format = kFormatYCbCr422H1V2SemiPlanar; break;
+ case SDE_PIX_FMT_Y_CRCB_H1V2: *sdm_format = kFormatYCrCb422H1V2SemiPlanar; break;
+ case SDE_PIX_FMT_Y_CBCR_H2V1: *sdm_format = kFormatYCbCr422H2V1SemiPlanar; break;
+ case SDE_PIX_FMT_Y_CRCB_H2V1: *sdm_format = kFormatYCrCb422H2V1SemiPlanar; break;
+ case SDE_PIX_FMT_YCBYCR_H2V1: *sdm_format = kFormatYCbCr422H2V1Packed; break;
+ case SDE_PIX_FMT_Y_CBCR_H2V2_VENUS: *sdm_format = kFormatYCbCr420SemiPlanarVenus; break;
+ case SDE_PIX_FMT_Y_CRCB_H2V2_VENUS: *sdm_format = kFormatYCrCb420SemiPlanarVenus; break;
+ case SDE_PIX_FMT_RGBA_8888_UBWC: *sdm_format = kFormatRGBA8888Ubwc; break;
+ case SDE_PIX_FMT_RGBX_8888_UBWC: *sdm_format = kFormatRGBX8888Ubwc; break;
+ case SDE_PIX_FMT_RGB_565_UBWC: *sdm_format = kFormatBGR565Ubwc; break;
+ case SDE_PIX_FMT_Y_CBCR_H2V2_UBWC: *sdm_format = kFormatYCbCr420SPVenusUbwc; break;
+ case SDE_PIX_FMT_RGBA_1010102: *sdm_format = kFormatRGBA1010102; break;
+ case SDE_PIX_FMT_ARGB_2101010: *sdm_format = kFormatARGB2101010; break;
+ case SDE_PIX_FMT_RGBX_1010102: *sdm_format = kFormatRGBX1010102; break;
+ case SDE_PIX_FMT_XRGB_2101010: *sdm_format = kFormatXRGB2101010; break;
+ case SDE_PIX_FMT_BGRA_1010102: *sdm_format = kFormatBGRA1010102; break;
+ case SDE_PIX_FMT_ABGR_2101010: *sdm_format = kFormatABGR2101010; break;
+ case SDE_PIX_FMT_BGRX_1010102: *sdm_format = kFormatBGRX1010102; break;
+ case SDE_PIX_FMT_XBGR_2101010: *sdm_format = kFormatXBGR2101010; break;
+ case SDE_PIX_FMT_RGBA_1010102_UBWC: *sdm_format = kFormatRGBA1010102Ubwc; break;
+ case SDE_PIX_FMT_RGBX_1010102_UBWC: *sdm_format = kFormatRGBX1010102Ubwc; break;
+ case SDE_PIX_FMT_Y_CBCR_H2V2_P010: *sdm_format = kFormatYCbCr420P010; break;
+ case SDE_PIX_FMT_Y_CBCR_H2V2_TP10_UBWC: *sdm_format = kFormatYCbCr420TP10Ubwc; break;
+ /* TODO(user) : enable when defined in uapi
+ case SDE_PIX_FMT_Y_CBCR_H2V2_P010_UBWC: *sdm_format = kFormatYCbCr420P010Ubwc; break; */
+ default: *sdm_format = kFormatInvalid;
+ }
+}
+
+void HWInfoDRM::GetRotatorFormatsForType(int fd, uint32_t type,
+ vector<LayerBufferFormat> *supported_formats) {
+ struct v4l2_fmtdesc fmtdesc = {};
+ fmtdesc.type = type;
+ while (!Sys::ioctl_(fd, static_cast<int>(VIDIOC_ENUM_FMT), &fmtdesc)) {
+ LayerBufferFormat sdm_format = kFormatInvalid;
+ GetSDMFormat(fmtdesc.pixelformat, &sdm_format);
+ if (sdm_format != kFormatInvalid) {
+ supported_formats->push_back(sdm_format);
+ }
+ fmtdesc.index++;
+ }
+}
+
+DisplayError HWInfoDRM::GetRotatorSupportedFormats(uint32_t v4l2_index,
+ HWResourceInfo *hw_resource) {
+ string path = "/dev/video" + to_string(v4l2_index);
+ int fd = Sys::open_(path.c_str(), O_RDONLY);
+ if (fd < 0) {
+ DLOGE("Failed to open %s with error %d", path.c_str(), errno);
+ return kErrorNotSupported;
+ }
+
+ vector<LayerBufferFormat> supported_formats = {};
+ GetRotatorFormatsForType(fd, V4L2_BUF_TYPE_VIDEO_OUTPUT, &supported_formats);
+ hw_resource->supported_formats_map.erase(kHWRotatorInput);
+ hw_resource->supported_formats_map.insert(make_pair(kHWRotatorInput, supported_formats));
+
+ supported_formats = {};
+ GetRotatorFormatsForType(fd, V4L2_BUF_TYPE_VIDEO_CAPTURE, &supported_formats);
+ hw_resource->supported_formats_map.erase(kHWRotatorOutput);
+ hw_resource->supported_formats_map.insert(make_pair(kHWRotatorOutput, supported_formats));
+
+ Sys::close_(fd);
+
+ return kErrorNone;
+}
+
+DisplayError HWInfoDRM::GetHWRotatorInfo(HWResourceInfo *hw_resource) {
+ string v4l2_path = "/sys/class/video4linux/video";
+ const uint32_t kMaxV4L2Nodes = 64;
+
+ for (uint32_t i = 0; i < kMaxV4L2Nodes; i++) {
+ string path = v4l2_path + to_string(i) + "/name";
+ Sys::fstream fs(path, fstream::in);
+ if (!fs.is_open()) {
+ continue;
+ }
+
+ string line;
+ if (Sys::getline_(fs, line) && (!strncmp(line.c_str(), "sde_rotator", strlen("sde_rotator")))) {
+ hw_resource->hw_rot_info.device_path = string("/dev/video" + to_string(i));
+ hw_resource->hw_rot_info.num_rotator++;
+ hw_resource->hw_rot_info.type = HWRotatorInfo::ROT_TYPE_V4L2;
+ hw_resource->hw_rot_info.has_downscale = true;
+ GetRotatorSupportedFormats(i, hw_resource);
+
+ string caps_path = v4l2_path + to_string(i) + "/device/caps";
+ Sys::fstream caps_fs(caps_path, fstream::in);
+
+ if (caps_fs.is_open()) {
+ string caps;
+ while (Sys::getline_(caps_fs, caps)) {
+ const string downscale_compression = "downscale_compression=";
+ const string min_downscale = "min_downscale=";
+ if (caps.find(downscale_compression) != string::npos) {
+ hw_resource->hw_rot_info.downscale_compression =
+ std::stoi(string(caps, downscale_compression.length()));
+ } else if (caps.find(min_downscale) != string::npos) {
+ hw_resource->hw_rot_info.min_downscale =
+ std::stof(string(caps, min_downscale.length()));
+ }
+ }
+ }
+
+ // We support only 1 rotator
+ break;
+ }
+ }
+
+ DLOGI("V4L2 Rotator: Count = %d, Downscale = %d, Min_downscale = %f, Downscale_compression = %d",
+ hw_resource->hw_rot_info.num_rotator, hw_resource->hw_rot_info.has_downscale,
+ hw_resource->hw_rot_info.min_downscale, hw_resource->hw_rot_info.downscale_compression);
+
+ return kErrorNone;
+}
+
+void HWInfoDRM::GetSDMFormat(uint32_t drm_format, uint64_t drm_format_modifier,
+ vector<LayerBufferFormat> *sdm_formats) {
+ vector<LayerBufferFormat> &fmts(*sdm_formats);
+ switch (drm_format) {
+ case DRM_FORMAT_BGRA8888:
+ fmts.push_back(kFormatARGB8888);
+ break;
+ case DRM_FORMAT_ABGR8888:
+ fmts.push_back(drm_format_modifier ? kFormatRGBA8888Ubwc : kFormatRGBA8888);
+ break;
+ case DRM_FORMAT_ARGB8888:
+ fmts.push_back(kFormatBGRA8888);
+ break;
+ case DRM_FORMAT_BGRX8888:
+ fmts.push_back(kFormatXRGB8888);
+ break;
+ case DRM_FORMAT_XBGR8888:
+ fmts.push_back(drm_format_modifier ? kFormatRGBX8888Ubwc : kFormatRGBX8888);
+ break;
+ case DRM_FORMAT_XRGB8888:
+ fmts.push_back(kFormatBGRX8888);
+ break;
+ case DRM_FORMAT_ABGR1555:
+ fmts.push_back(kFormatRGBA5551);
+ break;
+ case DRM_FORMAT_ABGR4444:
+ fmts.push_back(kFormatRGBA4444);
+ break;
+ case DRM_FORMAT_BGR888:
+ fmts.push_back(kFormatRGB888);
+ break;
+ case DRM_FORMAT_RGB888:
+ fmts.push_back(kFormatBGR888);
+ break;
+ case DRM_FORMAT_BGR565:
+ fmts.push_back(drm_format_modifier ? kFormatBGR565Ubwc : kFormatRGB565);
+ break;
+ case DRM_FORMAT_RGB565:
+ fmts.push_back(kFormatBGR565);
+ break;
+ case DRM_FORMAT_ABGR2101010:
+ fmts.push_back(drm_format_modifier ? kFormatRGBA1010102Ubwc : kFormatRGBA1010102);
+ break;
+ case DRM_FORMAT_BGRA1010102:
+ fmts.push_back(kFormatARGB2101010);
+ break;
+ case DRM_FORMAT_XBGR2101010:
+ fmts.push_back(drm_format_modifier ? kFormatRGBX1010102Ubwc : kFormatRGBX1010102);
+ break;
+ case DRM_FORMAT_BGRX1010102:
+ fmts.push_back(kFormatXRGB2101010);
+ break;
+ case DRM_FORMAT_ARGB2101010:
+ fmts.push_back(kFormatBGRA1010102);
+ break;
+ case DRM_FORMAT_RGBA1010102:
+ fmts.push_back(kFormatABGR2101010);
+ break;
+ case DRM_FORMAT_XRGB2101010:
+ fmts.push_back(kFormatBGRX1010102);
+ break;
+ case DRM_FORMAT_RGBX1010102:
+ fmts.push_back(kFormatXBGR2101010);
+ break;
+ case DRM_FORMAT_YVU420:
+ fmts.push_back(kFormatYCrCb420PlanarStride16);
+ break;
+ case DRM_FORMAT_NV12:
+ if (drm_format_modifier == (DRM_FORMAT_MOD_QCOM_COMPRESSED |
+ DRM_FORMAT_MOD_QCOM_DX | DRM_FORMAT_MOD_QCOM_TIGHT)) {
+ fmts.push_back(kFormatYCbCr420TP10Ubwc);
+ } else if (drm_format_modifier == (DRM_FORMAT_MOD_QCOM_COMPRESSED |
+ DRM_FORMAT_MOD_QCOM_DX)) {
+ fmts.push_back(kFormatYCbCr420P010Ubwc);
+ } else if (drm_format_modifier == DRM_FORMAT_MOD_QCOM_COMPRESSED) {
+ fmts.push_back(kFormatYCbCr420SPVenusUbwc);
+ } else if (drm_format_modifier == DRM_FORMAT_MOD_QCOM_DX) {
+ fmts.push_back(kFormatYCbCr420P010);
+ } else {
+ fmts.push_back(kFormatYCbCr420SemiPlanarVenus);
+ fmts.push_back(kFormatYCbCr420SemiPlanar);
+ }
+ break;
+ case DRM_FORMAT_NV21:
+ fmts.push_back(kFormatYCrCb420SemiPlanarVenus);
+ fmts.push_back(kFormatYCrCb420SemiPlanar);
+ break;
+ case DRM_FORMAT_NV16:
+ fmts.push_back(kFormatYCbCr422H2V1SemiPlanar);
+ break;
+ default:
+ break;
+ }
+}
+
+DisplayError HWInfoDRM::GetFirstDisplayInterfaceType(HWDisplayInterfaceInfo *hw_disp_info) {
+ hw_disp_info->type = kPrimary;
+ hw_disp_info->is_connected = true;
+
+ return kErrorNone;
+}
+
+} // namespace sdm
diff --git a/msm8909/sdm/libs/core/drm/hw_info_drm.h b/msm8909/sdm/libs/core/drm/hw_info_drm.h
new file mode 100644
index 00000000..6194a4bf
--- /dev/null
+++ b/msm8909/sdm/libs/core/drm/hw_info_drm.h
@@ -0,0 +1,82 @@
+/*
+* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __HW_INFO_DRM_H__
+#define __HW_INFO_DRM_H__
+
+#include <core/core_interface.h>
+#include <core/sdm_types.h>
+#include <drm_interface.h>
+#include <private/hw_info_types.h>
+#include <bitset>
+#include <vector>
+#include <drm_lib_loader.h>
+
+#include "hw_info_interface.h"
+
+namespace sdm {
+
+class HWInfoDRM: public HWInfoInterface {
+ public:
+ HWInfoDRM();
+ virtual ~HWInfoDRM();
+ virtual DisplayError GetHWResourceInfo(HWResourceInfo *hw_resource);
+ virtual DisplayError GetFirstDisplayInterfaceType(HWDisplayInterfaceInfo *hw_disp_info);
+
+ private:
+ DisplayError GetHWRotatorInfo(HWResourceInfo *hw_resource);
+ void GetSystemInfo(HWResourceInfo *hw_resource);
+ void GetHWPlanesInfo(HWResourceInfo *hw_resource);
+ void GetWBInfo(HWResourceInfo *hw_resource);
+ DisplayError GetDynamicBWLimits(HWResourceInfo *hw_resource);
+ void GetSDMFormat(uint32_t drm_format, uint64_t drm_format_modifier,
+ std::vector<LayerBufferFormat> *sdm_formats);
+ void GetSDMFormat(uint32_t v4l2_format, LayerBufferFormat *sdm_format);
+ void GetRotatorFormatsForType(int fd, uint32_t type,
+ std::vector<LayerBufferFormat> *supported_formats);
+ DisplayError GetRotatorSupportedFormats(uint32_t v4l2_index, HWResourceInfo *hw_resource);
+ void PopulateSupportedFmts(HWSubBlockType sub_blk_type, const sde_drm::DRMPlaneTypeInfo &info,
+ HWResourceInfo *hw_resource);
+ void PopulatePipeCaps(const sde_drm::DRMPlaneTypeInfo &info, HWResourceInfo *hw_resource);
+
+
+ sde_drm::DRMManagerInterface *drm_mgr_intf_ = {};
+ bool default_mode_ = false;
+
+ // TODO(user): Read Mdss version from the driver
+ static const int kHWMdssVersion5 = 500; // MDSS_V5
+ static const int kMaxStringLength = 1024;
+ static HWResourceInfo *hw_resource_;
+
+ drm_utils::DRMLibLoader *drm_lib = nullptr;
+};
+
+} // namespace sdm
+
+#endif // __HW_INFO_DRM_H__
diff --git a/msm8909/sdm/libs/core/drm/hw_scale_drm.cpp b/msm8909/sdm/libs/core/drm/hw_scale_drm.cpp
new file mode 100644
index 00000000..96f084e0
--- /dev/null
+++ b/msm8909/sdm/libs/core/drm/hw_scale_drm.cpp
@@ -0,0 +1,157 @@
+/*
+* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <stdio.h>
+#include <utils/debug.h>
+
+#include "hw_scale_drm.h"
+
+#define __CLASS__ "HWScaleDRM"
+
+namespace sdm {
+
+static uint32_t GetScalingFilter(ScalingFilterConfig filter_cfg) {
+ switch (filter_cfg) {
+ case kFilterEdgeDirected:
+ return FILTER_EDGE_DIRECTED_2D;
+ case kFilterCircular:
+ return FILTER_CIRCULAR_2D;
+ case kFilterSeparable:
+ return FILTER_SEPARABLE_1D;
+ case kFilterBilinear:
+ return FILTER_BILINEAR;
+ default:
+ DLOGE("Invalid Scaling Filter");
+ return kFilterMax;
+ }
+}
+
+static uint32_t GetAlphaInterpolation(HWAlphaInterpolation alpha_filter_cfg) {
+ switch (alpha_filter_cfg) {
+ case kInterpolationPixelRepeat:
+ return FILTER_ALPHA_DROP_REPEAT;
+ case kInterpolationBilinear:
+ return FILTER_ALPHA_BILINEAR;
+ default:
+ DLOGE("Invalid Alpha Interpolation");
+ return kInterpolationMax;
+ }
+}
+
+void HWScaleDRM::SetPlaneScaler(const HWScaleData &scale_data, SDEScaler *scaler) {
+ if (version_ == Version::V2) {
+ SetPlaneScalerV2(scale_data, &scaler->scaler_v2);
+ }
+}
+
+void HWScaleDRM::SetPlaneScalerV2(const HWScaleData &scale_data, sde_drm_scaler_v2 *scaler) {
+ if (!scale_data.enable.scale && !scale_data.enable.direction_detection &&
+ !scale_data.enable.detail_enhance) {
+ return;
+ }
+
+ scaler->enable = scale_data.enable.scale;
+ scaler->dir_en = scale_data.enable.direction_detection;
+ scaler->de.enable = scale_data.detail_enhance.enable;
+
+ for (int i = 0; i < SDE_MAX_PLANES; i++) {
+ const HWPlane &plane = scale_data.plane[i];
+ scaler->init_phase_x[i] = plane.init_phase_x;
+ scaler->phase_step_x[i] = plane.phase_step_x;
+ scaler->init_phase_y[i] = plane.init_phase_y;
+ scaler->phase_step_y[i] = plane.phase_step_y;
+
+ // TODO(user): Remove right, bottom from HWPlane and rename to LR, TB similar to qseed3
+ // Also remove roi_width which is unused.
+ scaler->pe.num_ext_pxls_lr[i] = plane.left.extension;
+ scaler->pe.num_ext_pxls_tb[i] = plane.top.extension;
+
+ scaler->pe.left_ftch[i] = plane.left.overfetch;
+ scaler->pe.top_ftch[i] = plane.top.overfetch;
+ scaler->pe.right_ftch[i] = plane.right.overfetch;
+ scaler->pe.btm_ftch[i] = plane.bottom.overfetch;
+
+ scaler->pe.left_rpt[i] = plane.left.repeat;
+ scaler->pe.top_rpt[i] = plane.top.repeat;
+ scaler->pe.right_rpt[i] = plane.right.repeat;
+ scaler->pe.btm_rpt[i] = plane.bottom.repeat;
+
+ scaler->preload_x[i] = UINT32(plane.preload_x);
+ scaler->preload_y[i] = UINT32(plane.preload_y);
+
+ scaler->src_width[i] = plane.src_width;
+ scaler->src_height[i] = plane.src_height;
+ }
+
+ scaler->dst_width = scale_data.dst_width;
+ scaler->dst_height = scale_data.dst_height;
+
+ scaler->y_rgb_filter_cfg = GetScalingFilter(scale_data.y_rgb_filter_cfg);
+ scaler->uv_filter_cfg = GetScalingFilter(scale_data.uv_filter_cfg);
+ scaler->alpha_filter_cfg = GetAlphaInterpolation(scale_data.alpha_filter_cfg);
+ scaler->blend_cfg = scale_data.blend_cfg;
+
+ scaler->lut_flag = (scale_data.lut_flag.lut_swap ? SCALER_LUT_SWAP : 0) |
+ (scale_data.lut_flag.lut_dir_wr ? SCALER_LUT_DIR_WR : 0) |
+ (scale_data.lut_flag.lut_y_cir_wr ? SCALER_LUT_Y_CIR_WR : 0) |
+ (scale_data.lut_flag.lut_uv_cir_wr ? SCALER_LUT_UV_CIR_WR : 0) |
+ (scale_data.lut_flag.lut_y_sep_wr ? SCALER_LUT_Y_SEP_WR : 0) |
+ (scale_data.lut_flag.lut_uv_sep_wr ? SCALER_LUT_UV_SEP_WR : 0);
+
+ scaler->dir_lut_idx = scale_data.dir_lut_idx;
+ scaler->y_rgb_cir_lut_idx = scale_data.y_rgb_cir_lut_idx;
+ scaler->uv_cir_lut_idx = scale_data.uv_cir_lut_idx;
+ scaler->y_rgb_sep_lut_idx = scale_data.y_rgb_sep_lut_idx;
+ scaler->uv_sep_lut_idx = scale_data.uv_sep_lut_idx;
+
+ /* TODO(user): Uncomment when de support is added
+ if (scaler->de.enable) {
+ sde_drm_de_v1 *det_enhance = &scaler->de;
+ det_enhance->sharpen_level1 = scale_data.detail_enhance.sharpen_level1;
+ det_enhance->sharpen_level2 = scale_data.detail_enhance.sharpen_level2;
+ det_enhance->clip = scale_data.detail_enhance.clip;
+ det_enhance->limit = scale_data.detail_enhance.limit;
+ det_enhance->thr_quiet = scale_data.detail_enhance.thr_quiet;
+ det_enhance->thr_dieout = scale_data.detail_enhance.thr_dieout;
+ det_enhance->thr_low = scale_data.detail_enhance.thr_low;
+ det_enhance->thr_high = scale_data.detail_enhance.thr_high;
+ det_enhance->prec_shift = scale_data.detail_enhance.prec_shift;
+
+ for (int i = 0; i < SDE_MAX_DE_CURVES; i++) {
+ det_enhance->adjust_a[i] = scale_data.detail_enhance.adjust_a[i];
+ det_enhance->adjust_b[i] = scale_data.detail_enhance.adjust_b[i];
+ det_enhance->adjust_c[i] = scale_data.detail_enhance.adjust_c[i];
+ }
+ }
+ */
+
+ return;
+}
+
+} // namespace sdm
diff --git a/msm8909/sdm/libs/core/drm/hw_scale_drm.h b/msm8909/sdm/libs/core/drm/hw_scale_drm.h
new file mode 100644
index 00000000..8a4be70b
--- /dev/null
+++ b/msm8909/sdm/libs/core/drm/hw_scale_drm.h
@@ -0,0 +1,63 @@
+/*
+* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __HW_SCALE_DRM_H__
+#define __HW_SCALE_DRM_H__
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <drm.h>
+// The 3 headers above are a workaround to prevent kernel drm.h from being used that has the
+// "virtual" keyword used for a variable. In future replace libdrm version drm.h with kernel
+// version drm/drm.h
+#include <drm/sde_drm.h>
+#include <private/hw_info_types.h>
+
+namespace sdm {
+
+struct SDEScaler {
+ struct sde_drm_scaler_v2 scaler_v2 = {};
+ // More here, maybe in a union
+};
+
+class HWScaleDRM {
+ public:
+ enum class Version { V2 };
+ explicit HWScaleDRM(Version v) : version_(v) {}
+ void SetPlaneScaler(const HWScaleData &scale, SDEScaler *scaler);
+
+ private:
+ void SetPlaneScalerV2(const HWScaleData &scale, sde_drm_scaler_v2 *scaler_v2);
+
+ Version version_ = Version::V2;
+};
+
+} // namespace sdm
+
+#endif // __HW_SCALE_DRM_H__
diff --git a/msm8909/sdm/libs/core/fb/hw_color_manager.cpp b/msm8909/sdm/libs/core/fb/hw_color_manager.cpp
new file mode 100644
index 00000000..051d5cb7
--- /dev/null
+++ b/msm8909/sdm/libs/core/fb/hw_color_manager.cpp
@@ -0,0 +1,188 @@
+/*
+* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <ctype.h>
+#include <math.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/resource.h>
+#include <sys/prctl.h>
+#include <linux/msm_mdp.h>
+#include <utils/constants.h>
+#include <utils/debug.h>
+#include "hw_color_manager.h"
+
+#define __CLASS__ "HWColorManager"
+
+namespace sdm {
+
+DisplayError (*HWColorManager::SetFeature[])(const PPFeatureInfo &, msmfb_mdp_pp *) = {
+ [kGlobalColorFeaturePcc] = &HWColorManager::SetPCC,
+ [kGlobalColorFeatureIgc] = &HWColorManager::SetIGC,
+ [kGlobalColorFeaturePgc] = &HWColorManager::SetPGC,
+ [kMixerColorFeatureGc] = &HWColorManager::SetMixerGC,
+ [kGlobalColorFeaturePaV2] = &HWColorManager::SetPAV2,
+ [kGlobalColorFeatureDither] = &HWColorManager::SetDither,
+ [kGlobalColorFeatureGamut] = &HWColorManager::SetGamut,
+ [kGlobalColorFeaturePADither] = &HWColorManager::SetPADither,
+ [kGlobalColorFeatureCsc] = &HWColorManager::SetCSCLegacy,
+};
+
+DisplayError HWColorManager::SetPCC(const PPFeatureInfo &feature, msmfb_mdp_pp *kernel_params) {
+ DisplayError ret = kErrorNone;
+
+ kernel_params->op = mdp_op_pcc_cfg;
+ kernel_params->data.pcc_cfg_data.version = feature.feature_version_;
+ kernel_params->data.pcc_cfg_data.block = MDP_LOGICAL_BLOCK_DISP_0 + feature.disp_id_;
+ kernel_params->data.pcc_cfg_data.ops = feature.enable_flags_;
+ kernel_params->data.pcc_cfg_data.cfg_payload = feature.GetConfigData();
+ DLOGV_IF(kTagQDCM, "kernel params version = %d, block = %d, flags = %d",
+ kernel_params->data.pcc_cfg_data.version, kernel_params->data.pcc_cfg_data.block,
+ kernel_params->data.pcc_cfg_data.ops);
+
+ return ret;
+}
+
+DisplayError HWColorManager::SetIGC(const PPFeatureInfo &feature, msmfb_mdp_pp *kernel_params) {
+ DisplayError ret = kErrorNone;
+
+ kernel_params->op = mdp_op_lut_cfg;
+ kernel_params->data.lut_cfg_data.lut_type = mdp_lut_igc;
+ kernel_params->data.lut_cfg_data.data.igc_lut_data.block =
+ MDP_LOGICAL_BLOCK_DISP_0 + feature.disp_id_;
+ kernel_params->data.lut_cfg_data.data.igc_lut_data.version = feature.feature_version_;
+ kernel_params->data.lut_cfg_data.data.igc_lut_data.ops = feature.enable_flags_;
+ kernel_params->data.lut_cfg_data.data.igc_lut_data.cfg_payload = feature.GetConfigData();
+
+ return ret;
+}
+
+DisplayError HWColorManager::SetPGC(const PPFeatureInfo &feature, msmfb_mdp_pp *kernel_params) {
+ DisplayError ret = kErrorNone;
+
+ kernel_params->op = mdp_op_lut_cfg;
+ kernel_params->data.lut_cfg_data.lut_type = mdp_lut_pgc;
+ kernel_params->data.lut_cfg_data.data.pgc_lut_data.version = feature.feature_version_;
+ kernel_params->data.lut_cfg_data.data.pgc_lut_data.block =
+ MDP_LOGICAL_BLOCK_DISP_0 + feature.disp_id_;
+ kernel_params->data.lut_cfg_data.data.pgc_lut_data.flags = feature.enable_flags_;
+ kernel_params->data.lut_cfg_data.data.pgc_lut_data.cfg_payload = feature.GetConfigData();
+
+ return ret;
+}
+
+DisplayError HWColorManager::SetMixerGC(const PPFeatureInfo &feature, msmfb_mdp_pp *kernel_params) {
+ DisplayError ret = kErrorNone;
+
+ kernel_params->op = mdp_op_lut_cfg;
+ kernel_params->data.lut_cfg_data.lut_type = mdp_lut_pgc;
+ kernel_params->data.lut_cfg_data.data.pgc_lut_data.version = feature.feature_version_;
+ kernel_params->data.lut_cfg_data.data.pgc_lut_data.block =
+ (MDP_LOGICAL_BLOCK_DISP_0 + feature.disp_id_) | MDSS_PP_LM_CFG;
+ kernel_params->data.lut_cfg_data.data.pgc_lut_data.flags = feature.enable_flags_;
+ kernel_params->data.lut_cfg_data.data.pgc_lut_data.cfg_payload = feature.GetConfigData();
+ return ret;
+}
+
+DisplayError HWColorManager::SetPAV2(const PPFeatureInfo &feature, msmfb_mdp_pp *kernel_params) {
+ DisplayError ret = kErrorNone;
+
+ kernel_params->op = mdp_op_pa_v2_cfg;
+ kernel_params->data.pa_v2_cfg_data.version = feature.feature_version_;
+ kernel_params->data.pa_v2_cfg_data.block = MDP_LOGICAL_BLOCK_DISP_0 + feature.disp_id_;
+ kernel_params->data.pa_v2_cfg_data.flags = feature.enable_flags_;
+ kernel_params->data.pa_v2_cfg_data.cfg_payload = feature.GetConfigData();
+ DLOGV_IF(kTagQDCM, "kernel params version = %d, block = %d, flags = %d",
+ kernel_params->data.pa_v2_cfg_data.version, kernel_params->data.pa_v2_cfg_data.block,
+ kernel_params->data.pa_v2_cfg_data.flags);
+
+ return ret;
+}
+
+DisplayError HWColorManager::SetDither(const PPFeatureInfo &feature, msmfb_mdp_pp *kernel_params) {
+ DisplayError ret = kErrorNone;
+
+ kernel_params->op = mdp_op_dither_cfg;
+ kernel_params->data.dither_cfg_data.version = feature.feature_version_;
+ kernel_params->data.dither_cfg_data.block = MDP_LOGICAL_BLOCK_DISP_0 + feature.disp_id_;
+ kernel_params->data.dither_cfg_data.flags = feature.enable_flags_;
+ kernel_params->data.dither_cfg_data.cfg_payload = feature.GetConfigData();
+
+ return ret;
+}
+
+DisplayError HWColorManager::SetGamut(const PPFeatureInfo &feature, msmfb_mdp_pp *kernel_params) {
+ DisplayError ret = kErrorNone;
+
+ kernel_params->op = mdp_op_gamut_cfg;
+ kernel_params->data.gamut_cfg_data.version = feature.feature_version_;
+ kernel_params->data.gamut_cfg_data.block = MDP_LOGICAL_BLOCK_DISP_0 + feature.disp_id_;
+ kernel_params->data.gamut_cfg_data.flags = feature.enable_flags_;
+ kernel_params->data.gamut_cfg_data.cfg_payload = feature.GetConfigData();
+
+ return ret;
+}
+
+DisplayError HWColorManager::SetPADither(const PPFeatureInfo &feature,
+ msmfb_mdp_pp *kernel_params) {
+ DisplayError ret = kErrorNone;
+#ifdef PA_DITHER
+ kernel_params->op = mdp_op_pa_dither_cfg;
+ kernel_params->data.dither_cfg_data.version = feature.feature_version_;
+ kernel_params->data.dither_cfg_data.block = MDP_LOGICAL_BLOCK_DISP_0 + feature.disp_id_;
+ kernel_params->data.dither_cfg_data.flags = feature.enable_flags_;
+ kernel_params->data.dither_cfg_data.cfg_payload = feature.GetConfigData();
+#endif
+ return ret;
+}
+
+DisplayError HWColorManager::SetCSCLegacy(const PPFeatureInfo &feature, msmfb_mdp_pp *kernel_params) {
+ DisplayError ret = kErrorNone;
+
+ kernel_params->op = mdp_op_csc_cfg;
+ kernel_params->data.csc_cfg_data.block = MDP_BLOCK_DMA_P;
+ std::memcpy(&kernel_params->data.csc_cfg_data.csc_data, feature.GetConfigData(),
+ sizeof(mdp_csc_cfg));
+
+ for( int row = 0; row < 3; row++) {
+ DLOGV_IF(kTagQDCM, "kernel mv[%d][0]=0x%x mv[%d][1]=0x%x mv[%d][2]=0x%x\n",
+ row, kernel_params->data.csc_cfg_data.csc_data.csc_mv[row*3 + 0],
+ row, kernel_params->data.csc_cfg_data.csc_data.csc_mv[row*3 + 1],
+ row, kernel_params->data.csc_cfg_data.csc_data.csc_mv[row*3 + 2]);
+ DLOGV_IF(kTagQDCM, "kernel pre_bv[%d]=%x\n", row,
+ kernel_params->data.csc_cfg_data.csc_data.csc_pre_bv[row]);
+ DLOGV_IF(kTagQDCM, "kernel post_bv[%d]=%x\n", row,
+ kernel_params->data.csc_cfg_data.csc_data.csc_post_bv[row]);
+ }
+ return ret;
+}
+
+} // namespace sdm
diff --git a/msm8909/sdm/libs/core/fb/hw_color_manager.h b/msm8909/sdm/libs/core/fb/hw_color_manager.h
new file mode 100644
index 00000000..46e41f51
--- /dev/null
+++ b/msm8909/sdm/libs/core/fb/hw_color_manager.h
@@ -0,0 +1,60 @@
+/* Copyright (c) 2015-2017, The Linux Foundataion. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+*/
+
+#ifndef __HW_COLOR_MANAGER_H__
+#define __HW_COLOR_MANAGER_H__
+
+#include <linux/msm_mdp_ext.h>
+#include <linux/msm_mdp.h>
+
+#include <private/color_params.h>
+
+namespace sdm {
+
+class HWColorManager {
+ public:
+ static DisplayError SetPCC(const PPFeatureInfo &feature, msmfb_mdp_pp *kernel_params);
+ static DisplayError SetIGC(const PPFeatureInfo &feature, msmfb_mdp_pp *kernel_params);
+ static DisplayError SetPGC(const PPFeatureInfo &feature, msmfb_mdp_pp *kernel_params);
+ static DisplayError SetMixerGC(const PPFeatureInfo &feature, msmfb_mdp_pp *kernel_params);
+ static DisplayError SetPAV2(const PPFeatureInfo &feature, msmfb_mdp_pp *kernel_params);
+ static DisplayError SetDither(const PPFeatureInfo &feature, msmfb_mdp_pp *kernel_params);
+ static DisplayError SetGamut(const PPFeatureInfo &feature, msmfb_mdp_pp *kernel_params);
+ static DisplayError SetPADither(const PPFeatureInfo &feature, msmfb_mdp_pp *kernel_params);
+ static DisplayError SetCSCLegacy(const PPFeatureInfo &feature, msmfb_mdp_pp *kernel_params);
+ static DisplayError (*SetFeature[kMaxNumPPFeatures])(const PPFeatureInfo &feature,
+ msmfb_mdp_pp *kernel_params);
+
+ protected:
+ HWColorManager() {}
+};
+
+} // namespace sdm
+
+#endif // __HW_COLOR_MANAGER_H__
diff --git a/msm8909/sdm/libs/core/fb/hw_device.cpp b/msm8909/sdm/libs/core/fb/hw_device.cpp
new file mode 100644
index 00000000..491c6cfd
--- /dev/null
+++ b/msm8909/sdm/libs/core/fb/hw_device.cpp
@@ -0,0 +1,1368 @@
+/*
+* Copyright (c) 2014 - 2017, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#define __STDC_FORMAT_MACROS
+
+#include <stdio.h>
+#include <ctype.h>
+#include <math.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+#include <inttypes.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <linux/fb.h>
+#include <utils/constants.h>
+#include <utils/debug.h>
+#include <utils/sys.h>
+#include <vector>
+#include <algorithm>
+#include <string>
+
+#include "hw_device.h"
+#include "hw_primary.h"
+#include "hw_hdmi.h"
+#include "hw_virtual.h"
+#include "hw_info_interface.h"
+
+#define __CLASS__ "HWDevice"
+
+using std::string;
+using std::to_string;
+using std::fstream;
+
+namespace sdm {
+
+HWDevice::HWDevice(BufferSyncHandler *buffer_sync_handler)
+ : fb_node_index_(-1), fb_path_("/sys/devices/virtual/graphics/fb"),
+ buffer_sync_handler_(buffer_sync_handler), synchronous_commit_(false) {
+}
+
+DisplayError HWDevice::Init() {
+ // Read the fb node index
+ fb_node_index_ = GetFBNodeIndex(device_type_);
+ if (fb_node_index_ == -1) {
+ DLOGE("device type = %d should be present", device_type_);
+ return kErrorHardware;
+ }
+
+ const char *dev_name = NULL;
+ vector<string> dev_paths = {"/dev/graphics/fb", "/dev/fb"};
+ for (size_t i = 0; i < dev_paths.size(); i++) {
+ dev_paths[i] += to_string(fb_node_index_);
+ if (Sys::access_(dev_paths[i].c_str(), F_OK) >= 0) {
+ dev_name = dev_paths[i].c_str();
+ DLOGI("access(%s) successful", dev_name);
+ break;
+ }
+
+ DLOGI("access(%s), errno = %d, error = %s", dev_paths[i].c_str(), errno, strerror(errno));
+ }
+
+ if (!dev_name) {
+ DLOGE("access() failed for all possible paths");
+ return kErrorHardware;
+ }
+
+ // Populate Panel Info (Used for Partial Update)
+ PopulateHWPanelInfo();
+ // Populate HW Capabilities
+ hw_resource_ = HWResourceInfo();
+ hw_info_intf_->GetHWResourceInfo(&hw_resource_);
+
+ device_fd_ = Sys::open_(dev_name, O_RDWR);
+ if (device_fd_ < 0) {
+ DLOGE("open %s failed errno = %d, error = %s", dev_name, errno, strerror(errno));
+ return kErrorResources;
+ }
+
+ return HWScale::Create(&hw_scale_, hw_resource_.has_qseed3);
+}
+
+DisplayError HWDevice::Deinit() {
+ HWScale::Destroy(hw_scale_);
+
+ if (device_fd_ >= 0) {
+ Sys::close_(device_fd_);
+ device_fd_ = -1;
+ }
+
+ if (stored_retire_fence >= 0) {
+ Sys::close_(stored_retire_fence);
+ stored_retire_fence = -1;
+ }
+ return kErrorNone;
+}
+
+DisplayError HWDevice::GetActiveConfig(uint32_t *active_config) {
+ *active_config = 0;
+ return kErrorNone;
+}
+
+DisplayError HWDevice::GetNumDisplayAttributes(uint32_t *count) {
+ *count = 1;
+ return kErrorNone;
+}
+
+DisplayError HWDevice::GetDisplayAttributes(uint32_t index,
+ HWDisplayAttributes *display_attributes) {
+ return kErrorNone;
+}
+
+DisplayError HWDevice::GetHWPanelInfo(HWPanelInfo *panel_info) {
+ *panel_info = hw_panel_info_;
+ return kErrorNone;
+}
+
+DisplayError HWDevice::SetDisplayAttributes(uint32_t index) {
+ return kErrorNone;
+}
+
+DisplayError HWDevice::SetDisplayAttributes(const HWDisplayAttributes &display_attributes) {
+ return kErrorNotSupported;
+}
+
+DisplayError HWDevice::GetConfigIndex(uint32_t mode, uint32_t *index) {
+ return kErrorNone;
+}
+
+DisplayError HWDevice::PowerOn() {
+ DTRACE_SCOPED();
+
+ if (Sys::ioctl_(device_fd_, FBIOBLANK, FB_BLANK_UNBLANK) < 0) {
+ if (errno == ESHUTDOWN) {
+ DLOGI_IF(kTagDriverConfig, "Driver is processing shutdown sequence");
+ return kErrorShutDown;
+ }
+ IOCTL_LOGE(FB_BLANK_UNBLANK, device_type_);
+ return kErrorHardware;
+ }
+
+ return kErrorNone;
+}
+
+DisplayError HWDevice::PowerOff() {
+ return kErrorNone;
+}
+
+DisplayError HWDevice::Doze() {
+ return kErrorNone;
+}
+
+DisplayError HWDevice::DozeSuspend() {
+ return kErrorNone;
+}
+
+DisplayError HWDevice::Standby() {
+ return kErrorNone;
+}
+
+DisplayError HWDevice::Validate(HWLayers *hw_layers) {
+ DTRACE_SCOPED();
+
+ DisplayError error = kErrorNone;
+
+ HWLayersInfo &hw_layer_info = hw_layers->info;
+ uint32_t hw_layer_count = UINT32(hw_layer_info.hw_layers.size());
+
+ DLOGD_IF(kTagDriverConfig, "************************** %s Validate Input ***********************",
+ device_name_);
+ DLOGD_IF(kTagDriverConfig, "SDE layer count is %d", hw_layer_count);
+
+ mdp_layer_commit_v1 &mdp_commit = mdp_disp_commit_.commit_v1;
+ uint32_t &mdp_layer_count = mdp_commit.input_layer_cnt;
+
+ DLOGI_IF(kTagDriverConfig, "left_roi: x = %d, y = %d, w = %d, h = %d", mdp_commit.left_roi.x,
+ mdp_commit.left_roi.y, mdp_commit.left_roi.w, mdp_commit.left_roi.h);
+ DLOGI_IF(kTagDriverConfig, "right_roi: x = %d, y = %d, w = %d, h = %d", mdp_commit.right_roi.x,
+ mdp_commit.right_roi.y, mdp_commit.right_roi.w, mdp_commit.right_roi.h);
+
+ for (uint32_t i = 0; i < hw_layer_count; i++) {
+ const Layer &layer = hw_layer_info.hw_layers.at(i);
+ LayerBuffer input_buffer = layer.input_buffer;
+ HWPipeInfo *left_pipe = &hw_layers->config[i].left_pipe;
+ HWPipeInfo *right_pipe = &hw_layers->config[i].right_pipe;
+ HWRotatorSession *hw_rotator_session = &hw_layers->config[i].hw_rotator_session;
+ bool is_rotator_used = (hw_rotator_session->hw_block_count != 0);
+ bool is_cursor_pipe_used = (hw_layer_info.use_hw_cursor & layer.flags.cursor);
+
+ for (uint32_t count = 0; count < 2; count++) {
+ HWPipeInfo *pipe_info = (count == 0) ? left_pipe : right_pipe;
+ HWRotateInfo *hw_rotate_info = &hw_rotator_session->hw_rotate_info[count];
+
+ if (hw_rotate_info->valid) {
+ input_buffer = hw_rotator_session->output_buffer;
+ }
+
+ if (pipe_info->valid) {
+ mdp_input_layer &mdp_layer = mdp_in_layers_[mdp_layer_count];
+ mdp_layer_buffer &mdp_buffer = mdp_layer.buffer;
+
+ mdp_buffer.width = input_buffer.width;
+ mdp_buffer.height = input_buffer.height;
+ mdp_buffer.comp_ratio.denom = 1000;
+ mdp_buffer.comp_ratio.numer = UINT32(hw_layers->config[i].compression * 1000);
+
+ if (layer.flags.solid_fill) {
+ mdp_buffer.format = MDP_ARGB_8888;
+ } else {
+ error = SetFormat(input_buffer.format, &mdp_buffer.format);
+ if (error != kErrorNone) {
+ return error;
+ }
+ }
+ mdp_layer.alpha = layer.plane_alpha;
+ mdp_layer.z_order = UINT16(pipe_info->z_order);
+ mdp_layer.transp_mask = 0xffffffff;
+ SetBlending(layer.blending, &mdp_layer.blend_op);
+ mdp_layer.pipe_ndx = pipe_info->pipe_id;
+ mdp_layer.horz_deci = pipe_info->horizontal_decimation;
+ mdp_layer.vert_deci = pipe_info->vertical_decimation;
+#ifdef MDP_COMMIT_RECT_NUM
+ mdp_layer.rect_num = pipe_info->rect;
+#endif
+ SetRect(pipe_info->src_roi, &mdp_layer.src_rect);
+ SetRect(pipe_info->dst_roi, &mdp_layer.dst_rect);
+ SetMDPFlags(&layer, is_rotator_used, is_cursor_pipe_used, &mdp_layer.flags);
+ SetCSC(layer.input_buffer.color_metadata, &mdp_layer.color_space);
+ if (pipe_info->flags & kIGC) {
+ SetIGC(&layer.input_buffer, mdp_layer_count);
+ }
+ if (pipe_info->flags & kMultiRect) {
+ mdp_layer.flags |= MDP_LAYER_MULTIRECT_ENABLE;
+ if (pipe_info->flags & kMultiRectParallelMode) {
+ mdp_layer.flags |= MDP_LAYER_MULTIRECT_PARALLEL_MODE;
+ }
+ }
+ mdp_layer.bg_color = layer.solid_fill_color;
+
+ // HWScaleData to MDP driver
+ hw_scale_->SetHWScaleData(pipe_info->scale_data, mdp_layer_count, &mdp_commit,
+ pipe_info->sub_block_type);
+ mdp_layer.scale = hw_scale_->GetScaleDataRef(mdp_layer_count, pipe_info->sub_block_type);
+
+ mdp_layer_count++;
+
+ DLOGD_IF(kTagDriverConfig, "******************* Layer[%d] %s pipe Input ******************",
+ i, count ? "Right" : "Left");
+ DLOGD_IF(kTagDriverConfig, "in_w %d, in_h %d, in_f %d", mdp_buffer.width, mdp_buffer.height,
+ mdp_buffer.format);
+ DLOGD_IF(kTagDriverConfig, "plane_alpha %d, zorder %d, blending %d, horz_deci %d, "
+ "vert_deci %d, pipe_id = 0x%x, mdp_flags 0x%x", mdp_layer.alpha, mdp_layer.z_order,
+ mdp_layer.blend_op, mdp_layer.horz_deci, mdp_layer.vert_deci, mdp_layer.pipe_ndx,
+ mdp_layer.flags);
+ DLOGV_IF(kTagDriverConfig, "src_rect [%d, %d, %d, %d]", mdp_layer.src_rect.x,
+ mdp_layer.src_rect.y, mdp_layer.src_rect.w, mdp_layer.src_rect.h);
+ DLOGV_IF(kTagDriverConfig, "dst_rect [%d, %d, %d, %d]", mdp_layer.dst_rect.x,
+ mdp_layer.dst_rect.y, mdp_layer.dst_rect.w, mdp_layer.dst_rect.h);
+ hw_scale_->DumpScaleData(mdp_layer.scale);
+ DLOGD_IF(kTagDriverConfig, "*************************************************************");
+ }
+ }
+ }
+
+ // TODO(user): This block should move to the derived class
+ if (device_type_ == kDeviceVirtual) {
+ LayerBuffer *output_buffer = hw_layers->info.stack->output_buffer;
+ mdp_out_layer_.writeback_ndx = hw_resource_.writeback_index;
+ mdp_out_layer_.buffer.width = output_buffer->width;
+ mdp_out_layer_.buffer.height = output_buffer->height;
+ if (output_buffer->flags.secure) {
+ mdp_out_layer_.flags |= MDP_LAYER_SECURE_SESSION;
+ }
+ mdp_out_layer_.buffer.comp_ratio.denom = 1000;
+ mdp_out_layer_.buffer.comp_ratio.numer = UINT32(hw_layers->output_compression * 1000);
+#ifdef OUT_LAYER_COLOR_SPACE
+ SetCSC(output_buffer->color_metadata, &mdp_out_layer_.color_space);
+#endif
+ SetFormat(output_buffer->format, &mdp_out_layer_.buffer.format);
+
+ DLOGI_IF(kTagDriverConfig, "********************* Output buffer Info ************************");
+ DLOGI_IF(kTagDriverConfig, "out_w %d, out_h %d, out_f %d, wb_id %d",
+ mdp_out_layer_.buffer.width, mdp_out_layer_.buffer.height,
+ mdp_out_layer_.buffer.format, mdp_out_layer_.writeback_ndx);
+ DLOGI_IF(kTagDriverConfig, "*****************************************************************");
+ }
+
+ uint32_t index = 0;
+ for (uint32_t i = 0; i < hw_resource_.hw_dest_scalar_info.count; i++) {
+ DestScaleInfoMap::iterator it = hw_layer_info.dest_scale_info_map.find(i);
+
+ if (it == hw_layer_info.dest_scale_info_map.end()) {
+ continue;
+ }
+
+ HWDestScaleInfo *dest_scale_info = it->second;
+
+ mdp_destination_scaler_data *dest_scalar_data = &mdp_dest_scalar_data_[index];
+ hw_scale_->SetHWScaleData(dest_scale_info->scale_data, index, &mdp_commit,
+ kHWDestinationScalar);
+
+ if (dest_scale_info->scale_update) {
+ dest_scalar_data->flags |= MDP_DESTSCALER_SCALE_UPDATE;
+ }
+
+ dest_scalar_data->dest_scaler_ndx = i;
+ dest_scalar_data->lm_width = dest_scale_info->mixer_width;
+ dest_scalar_data->lm_height = dest_scale_info->mixer_height;
+#ifdef MDP_DESTSCALER_ROI_ENABLE
+ SetRect(dest_scale_info->panel_roi, &dest_scalar_data->panel_roi);
+ dest_scalar_data->flags |= MDP_DESTSCALER_ROI_ENABLE;
+#endif
+ dest_scalar_data->scale = reinterpret_cast <uint64_t>
+ (hw_scale_->GetScaleDataRef(index, kHWDestinationScalar));
+
+ index++;
+
+ DLOGD_IF(kTagDriverConfig, "************************ DestScalar[%d] **************************",
+ dest_scalar_data->dest_scaler_ndx);
+ DLOGD_IF(kTagDriverConfig, "Mixer WxH %dx%d flags %x", dest_scalar_data->lm_width,
+ dest_scalar_data->lm_height, dest_scalar_data->flags);
+#ifdef MDP_DESTSCALER_ROI_ENABLE
+ DLOGD_IF(kTagDriverConfig, "Panel ROI [%d, %d, %d, %d]", dest_scalar_data->panel_roi.x,
+ dest_scalar_data->panel_roi.y, dest_scalar_data->panel_roi.w,
+ dest_scalar_data->panel_roi.h);
+#endif
+ DLOGD_IF(kTagDriverConfig, "*****************************************************************");
+ }
+ mdp_commit.dest_scaler_cnt = UINT32(hw_layer_info.dest_scale_info_map.size());
+
+ mdp_commit.flags |= MDP_VALIDATE_LAYER;
+#ifdef MDP_COMMIT_RECT_NUM
+ mdp_commit.flags |= MDP_COMMIT_RECT_NUM;
+#endif
+ if (Sys::ioctl_(device_fd_, INT(MSMFB_ATOMIC_COMMIT), &mdp_disp_commit_) < 0) {
+ if (errno == ESHUTDOWN) {
+ DLOGI_IF(kTagDriverConfig, "Driver is processing shutdown sequence");
+ return kErrorShutDown;
+ }
+ IOCTL_LOGE(MSMFB_ATOMIC_COMMIT, device_type_);
+ DumpLayerCommit(mdp_disp_commit_);
+ return kErrorHardware;
+ }
+
+ return kErrorNone;
+}
+
+void HWDevice::DumpLayerCommit(const mdp_layer_commit &layer_commit) {
+ const mdp_layer_commit_v1 &mdp_commit = layer_commit.commit_v1;
+ const mdp_input_layer *mdp_layers = mdp_commit.input_layers;
+ const mdp_rect &l_roi = mdp_commit.left_roi;
+ const mdp_rect &r_roi = mdp_commit.right_roi;
+
+ DLOGI("mdp_commit: flags = %x, release fence = %x", mdp_commit.flags, mdp_commit.release_fence);
+ DLOGI("left_roi: x = %d, y = %d, w = %d, h = %d", l_roi.x, l_roi.y, l_roi.w, l_roi.h);
+ DLOGI("right_roi: x = %d, y = %d, w = %d, h = %d", r_roi.x, r_roi.y, r_roi.w, r_roi.h);
+ for (uint32_t i = 0; i < mdp_commit.dest_scaler_cnt; i++) {
+ mdp_destination_scaler_data *dest_scalar_data = &mdp_dest_scalar_data_[i];
+ mdp_scale_data_v2 *mdp_scale = reinterpret_cast<mdp_scale_data_v2 *>(dest_scalar_data->scale);
+
+ DLOGI("Dest scalar index %d Mixer WxH %dx%d", dest_scalar_data->dest_scaler_ndx,
+ dest_scalar_data->lm_width, dest_scalar_data->lm_height);
+#ifdef MDP_DESTSCALER_ROI_ENABLE
+ DLOGI("Panel ROI [%d, %d, %d, %d]", dest_scalar_data->panel_roi.x,
+ dest_scalar_data->panel_roi.y, dest_scalar_data->panel_roi.w,
+ dest_scalar_data->panel_roi.h);
+#endif
+ DLOGI("Dest scalar Dst WxH %dx%d", mdp_scale->dst_width, mdp_scale->dst_height);
+ }
+ for (uint32_t i = 0; i < mdp_commit.input_layer_cnt; i++) {
+ const mdp_input_layer &layer = mdp_layers[i];
+ const mdp_rect &src_rect = layer.src_rect;
+ const mdp_rect &dst_rect = layer.dst_rect;
+ DLOGI("layer = %d, pipe_ndx = %x, z = %d, flags = %x",
+ i, layer.pipe_ndx, layer.z_order, layer.flags);
+ DLOGI("src_width = %d, src_height = %d, src_format = %d",
+ layer.buffer.width, layer.buffer.height, layer.buffer.format);
+ DLOGI("src_rect: x = %d, y = %d, w = %d, h = %d",
+ src_rect.x, src_rect.y, src_rect.w, src_rect.h);
+ DLOGI("dst_rect: x = %d, y = %d, w = %d, h = %d",
+ dst_rect.x, dst_rect.y, dst_rect.w, dst_rect.h);
+ }
+}
+
+DisplayError HWDevice::Commit(HWLayers *hw_layers) {
+ DTRACE_SCOPED();
+
+ HWLayersInfo &hw_layer_info = hw_layers->info;
+ uint32_t hw_layer_count = UINT32(hw_layer_info.hw_layers.size());
+
+ DLOGD_IF(kTagDriverConfig, "*************************** %s Commit Input ************************",
+ device_name_);
+ DLOGD_IF(kTagDriverConfig, "SDE layer count is %d", hw_layer_count);
+
+ mdp_layer_commit_v1 &mdp_commit = mdp_disp_commit_.commit_v1;
+ uint32_t mdp_layer_index = 0;
+
+ for (uint32_t i = 0; i < hw_layer_count; i++) {
+ const Layer &layer = hw_layer_info.hw_layers.at(i);
+ LayerBuffer *input_buffer = const_cast<LayerBuffer *>(&layer.input_buffer);
+ HWPipeInfo *left_pipe = &hw_layers->config[i].left_pipe;
+ HWPipeInfo *right_pipe = &hw_layers->config[i].right_pipe;
+ HWRotatorSession *hw_rotator_session = &hw_layers->config[i].hw_rotator_session;
+
+ for (uint32_t count = 0; count < 2; count++) {
+ HWPipeInfo *pipe_info = (count == 0) ? left_pipe : right_pipe;
+ HWRotateInfo *hw_rotate_info = &hw_rotator_session->hw_rotate_info[count];
+
+ if (hw_rotate_info->valid) {
+ input_buffer = &hw_rotator_session->output_buffer;
+ }
+
+ if (pipe_info->valid) {
+ mdp_layer_buffer &mdp_buffer = mdp_in_layers_[mdp_layer_index].buffer;
+ mdp_input_layer &mdp_layer = mdp_in_layers_[mdp_layer_index];
+ if (input_buffer->planes[0].fd >= 0) {
+ mdp_buffer.plane_count = 1;
+ mdp_buffer.planes[0].fd = input_buffer->planes[0].fd;
+ mdp_buffer.planes[0].offset = input_buffer->planes[0].offset;
+ SetStride(device_type_, input_buffer->format, input_buffer->planes[0].stride,
+ &mdp_buffer.planes[0].stride);
+ } else {
+ mdp_buffer.plane_count = 0;
+ }
+
+ mdp_buffer.fence = input_buffer->acquire_fence_fd;
+ mdp_layer_index++;
+
+ DLOGD_IF(kTagDriverConfig, "****************** Layer[%d] %s pipe Input *******************",
+ i, count ? "Right" : "Left");
+ DLOGD_IF(kTagDriverConfig, "in_w %d, in_h %d, in_f %d, horz_deci %d, vert_deci %d",
+ mdp_buffer.width, mdp_buffer.height, mdp_buffer.format, mdp_layer.horz_deci,
+ mdp_layer.vert_deci);
+ DLOGV_IF(kTagDriverConfig, "in_buf_fd %d, in_buf_offset %d, in_buf_stride %d, " \
+ "in_plane_count %d, in_fence %d, layer count %d", mdp_buffer.planes[0].fd,
+ mdp_buffer.planes[0].offset, mdp_buffer.planes[0].stride, mdp_buffer.plane_count,
+ mdp_buffer.fence, mdp_commit.input_layer_cnt);
+ DLOGD_IF(kTagDriverConfig, "*************************************************************");
+ }
+ }
+ }
+
+ // TODO(user): Move to derived class
+ if (device_type_ == kDeviceVirtual) {
+ LayerBuffer *output_buffer = hw_layers->info.stack->output_buffer;
+
+ if (output_buffer->planes[0].fd >= 0) {
+ mdp_out_layer_.buffer.planes[0].fd = output_buffer->planes[0].fd;
+ mdp_out_layer_.buffer.planes[0].offset = output_buffer->planes[0].offset;
+ SetStride(device_type_, output_buffer->format, output_buffer->planes[0].stride,
+ &mdp_out_layer_.buffer.planes[0].stride);
+ mdp_out_layer_.buffer.plane_count = 1;
+ } else {
+ DLOGE("Invalid output buffer fd");
+ return kErrorParameters;
+ }
+
+ mdp_out_layer_.buffer.fence = output_buffer->acquire_fence_fd;
+
+ DLOGI_IF(kTagDriverConfig, "********************** Output buffer Info ***********************");
+ DLOGI_IF(kTagDriverConfig, "out_fd %d, out_offset %d, out_stride %d, acquire_fence %d",
+ mdp_out_layer_.buffer.planes[0].fd, mdp_out_layer_.buffer.planes[0].offset,
+ mdp_out_layer_.buffer.planes[0].stride, mdp_out_layer_.buffer.fence);
+ DLOGI_IF(kTagDriverConfig, "*****************************************************************");
+ }
+
+ mdp_commit.release_fence = -1;
+ mdp_commit.flags &= UINT32(~MDP_VALIDATE_LAYER);
+ if (synchronous_commit_) {
+ mdp_commit.flags |= MDP_COMMIT_WAIT_FOR_FINISH;
+ }
+ if (bl_update_commit && bl_level_update_commit >= 0) {
+#ifdef MDP_COMMIT_UPDATE_BRIGHTNESS
+ mdp_commit.bl_level = (uint32_t)bl_level_update_commit;
+ mdp_commit.flags |= MDP_COMMIT_UPDATE_BRIGHTNESS;
+#endif
+ }
+ if (Sys::ioctl_(device_fd_, INT(MSMFB_ATOMIC_COMMIT), &mdp_disp_commit_) < 0) {
+ if (errno == ESHUTDOWN) {
+ DLOGI_IF(kTagDriverConfig, "Driver is processing shutdown sequence");
+ return kErrorShutDown;
+ }
+ IOCTL_LOGE(MSMFB_ATOMIC_COMMIT, device_type_);
+ DumpLayerCommit(mdp_disp_commit_);
+ synchronous_commit_ = false;
+ return kErrorHardware;
+ }
+
+ LayerStack *stack = hw_layer_info.stack;
+ stack->retire_fence_fd = mdp_commit.retire_fence;
+#ifdef VIDEO_MODE_DEFER_RETIRE_FENCE
+ if (hw_panel_info_.mode == kModeVideo) {
+ stack->retire_fence_fd = stored_retire_fence;
+ stored_retire_fence = mdp_commit.retire_fence;
+ }
+#endif
+ // MDP returns only one release fence for the entire layer stack. Duplicate this fence into all
+ // layers being composed by MDP.
+
+ for (uint32_t i = 0; i < hw_layer_count; i++) {
+ const Layer &layer = hw_layer_info.hw_layers.at(i);
+ LayerBuffer *input_buffer = const_cast<LayerBuffer *>(&layer.input_buffer);
+ HWRotatorSession *hw_rotator_session = &hw_layers->config[i].hw_rotator_session;
+
+ if (hw_rotator_session->hw_block_count) {
+ input_buffer = &hw_rotator_session->output_buffer;
+ input_buffer->release_fence_fd = Sys::dup_(mdp_commit.release_fence);
+ continue;
+ }
+
+ input_buffer->release_fence_fd = Sys::dup_(mdp_commit.release_fence);
+ }
+
+ hw_layer_info.sync_handle = Sys::dup_(mdp_commit.release_fence);
+
+ DLOGI_IF(kTagDriverConfig, "*************************** %s Commit Input ************************",
+ device_name_);
+ DLOGI_IF(kTagDriverConfig, "retire_fence_fd %d", stack->retire_fence_fd);
+ DLOGI_IF(kTagDriverConfig, "*******************************************************************");
+
+ if (mdp_commit.release_fence >= 0) {
+ Sys::close_(mdp_commit.release_fence);
+ }
+
+ if (synchronous_commit_) {
+ // A synchronous commit can be requested when changing the display mode so we need to update
+ // panel info.
+ PopulateHWPanelInfo();
+ synchronous_commit_ = false;
+ }
+
+ if (bl_update_commit)
+ bl_update_commit = false;
+
+ return kErrorNone;
+}
+
+DisplayError HWDevice::Flush() {
+ ResetDisplayParams();
+ mdp_layer_commit_v1 &mdp_commit = mdp_disp_commit_.commit_v1;
+ mdp_commit.input_layer_cnt = 0;
+ mdp_commit.output_layer = NULL;
+
+ mdp_commit.flags &= UINT32(~MDP_VALIDATE_LAYER);
+ if (Sys::ioctl_(device_fd_, INT(MSMFB_ATOMIC_COMMIT), &mdp_disp_commit_) < 0) {
+ if (errno == ESHUTDOWN) {
+ DLOGI_IF(kTagDriverConfig, "Driver is processing shutdown sequence");
+ return kErrorShutDown;
+ }
+ IOCTL_LOGE(MSMFB_ATOMIC_COMMIT, device_type_);
+ DumpLayerCommit(mdp_disp_commit_);
+ return kErrorHardware;
+ }
+ return kErrorNone;
+}
+
+DisplayError HWDevice::SetFormat(const LayerBufferFormat &source, uint32_t *target) {
+ switch (source) {
+ case kFormatARGB8888: *target = MDP_ARGB_8888; break;
+ case kFormatRGBA8888: *target = MDP_RGBA_8888; break;
+ case kFormatBGRA8888: *target = MDP_BGRA_8888; break;
+ case kFormatRGBX8888: *target = MDP_RGBX_8888; break;
+ case kFormatBGRX8888: *target = MDP_BGRX_8888; break;
+ case kFormatRGBA5551: *target = MDP_RGBA_5551; break;
+ case kFormatRGBA4444: *target = MDP_RGBA_4444; break;
+ case kFormatRGB888: *target = MDP_RGB_888; break;
+ case kFormatBGR888: *target = MDP_BGR_888; break;
+ case kFormatRGB565: *target = MDP_RGB_565; break;
+ case kFormatBGR565: *target = MDP_BGR_565; break;
+ case kFormatYCbCr420Planar: *target = MDP_Y_CB_CR_H2V2; break;
+ case kFormatYCrCb420Planar: *target = MDP_Y_CR_CB_H2V2; break;
+ case kFormatYCrCb420PlanarStride16: *target = MDP_Y_CR_CB_GH2V2; break;
+ case kFormatYCbCr420SemiPlanar: *target = MDP_Y_CBCR_H2V2; break;
+ case kFormatYCrCb420SemiPlanar: *target = MDP_Y_CRCB_H2V2; break;
+ case kFormatYCbCr422H1V2SemiPlanar: *target = MDP_Y_CBCR_H1V2; break;
+ case kFormatYCrCb422H1V2SemiPlanar: *target = MDP_Y_CRCB_H1V2; break;
+ case kFormatYCbCr422H2V1SemiPlanar: *target = MDP_Y_CBCR_H2V1; break;
+ case kFormatYCrCb422H2V1SemiPlanar: *target = MDP_Y_CRCB_H2V1; break;
+ case kFormatYCbCr422H2V1Packed: *target = MDP_YCBYCR_H2V1; break;
+ case kFormatYCbCr420SemiPlanarVenus: *target = MDP_Y_CBCR_H2V2_VENUS; break;
+ case kFormatRGBA8888Ubwc: *target = MDP_RGBA_8888_UBWC; break;
+ case kFormatRGBX8888Ubwc: *target = MDP_RGBX_8888_UBWC; break;
+ case kFormatBGR565Ubwc: *target = MDP_RGB_565_UBWC; break;
+ case kFormatYCbCr420SPVenusUbwc: *target = MDP_Y_CBCR_H2V2_UBWC; break;
+ case kFormatCbYCrY422H2V1Packed: *target = MDP_CBYCRY_H2V1; break;
+ case kFormatRGBA1010102: *target = MDP_RGBA_1010102; break;
+ case kFormatARGB2101010: *target = MDP_ARGB_2101010; break;
+ case kFormatRGBX1010102: *target = MDP_RGBX_1010102; break;
+ case kFormatXRGB2101010: *target = MDP_XRGB_2101010; break;
+ case kFormatBGRA1010102: *target = MDP_BGRA_1010102; break;
+ case kFormatABGR2101010: *target = MDP_ABGR_2101010; break;
+ case kFormatBGRX1010102: *target = MDP_BGRX_1010102; break;
+ case kFormatXBGR2101010: *target = MDP_XBGR_2101010; break;
+ case kFormatRGBA1010102Ubwc: *target = MDP_RGBA_1010102_UBWC; break;
+ case kFormatRGBX1010102Ubwc: *target = MDP_RGBX_1010102_UBWC; break;
+ case kFormatYCbCr420P010: *target = MDP_Y_CBCR_H2V2_P010; break;
+ case kFormatYCbCr420TP10Ubwc: *target = MDP_Y_CBCR_H2V2_TP10_UBWC; break;
+ default:
+ DLOGE("Unsupported format type %d", source);
+ return kErrorParameters;
+ }
+
+ return kErrorNone;
+}
+
+DisplayError HWDevice::SetStride(HWDeviceType device_type, LayerBufferFormat format,
+ uint32_t width, uint32_t *target) {
+ // TODO(user): This SetStride function is a workaround to satisfy the driver expectation for
+ // rotator and virtual devices. Eventually this will be taken care in the driver.
+ if (device_type != kDeviceRotator && device_type != kDeviceVirtual) {
+ *target = width;
+ return kErrorNone;
+ }
+
+ switch (format) {
+ case kFormatARGB8888:
+ case kFormatRGBA8888:
+ case kFormatBGRA8888:
+ case kFormatRGBX8888:
+ case kFormatBGRX8888:
+ case kFormatRGBA8888Ubwc:
+ case kFormatRGBX8888Ubwc:
+ case kFormatRGBA1010102:
+ case kFormatARGB2101010:
+ case kFormatRGBX1010102:
+ case kFormatXRGB2101010:
+ case kFormatBGRA1010102:
+ case kFormatABGR2101010:
+ case kFormatBGRX1010102:
+ case kFormatXBGR2101010:
+ case kFormatRGBA1010102Ubwc:
+ case kFormatRGBX1010102Ubwc:
+ *target = width * 4;
+ break;
+ case kFormatRGB888:
+ case kFormatBGR888:
+ *target = width * 3;
+ break;
+ case kFormatRGB565:
+ case kFormatBGR565:
+ case kFormatBGR565Ubwc:
+ *target = width * 2;
+ break;
+ case kFormatYCbCr420SemiPlanarVenus:
+ case kFormatYCbCr420SPVenusUbwc:
+ case kFormatYCbCr420Planar:
+ case kFormatYCrCb420Planar:
+ case kFormatYCrCb420PlanarStride16:
+ case kFormatYCbCr420SemiPlanar:
+ case kFormatYCrCb420SemiPlanar:
+ case kFormatYCbCr420TP10Ubwc:
+ *target = width;
+ break;
+ case kFormatYCbCr422H2V1Packed:
+ case kFormatCbYCrY422H2V1Packed:
+ case kFormatYCrCb422H2V1SemiPlanar:
+ case kFormatYCrCb422H1V2SemiPlanar:
+ case kFormatYCbCr422H2V1SemiPlanar:
+ case kFormatYCbCr422H1V2SemiPlanar:
+ case kFormatYCbCr420P010:
+ case kFormatRGBA5551:
+ case kFormatRGBA4444:
+ *target = width * 2;
+ break;
+ default:
+ DLOGE("Unsupported format type %d", format);
+ return kErrorParameters;
+ }
+
+ return kErrorNone;
+}
+
+void HWDevice::SetBlending(const LayerBlending &source, mdss_mdp_blend_op *target) {
+ switch (source) {
+ case kBlendingPremultiplied: *target = BLEND_OP_PREMULTIPLIED; break;
+ case kBlendingOpaque: *target = BLEND_OP_OPAQUE; break;
+ case kBlendingCoverage: *target = BLEND_OP_COVERAGE; break;
+ default: *target = BLEND_OP_NOT_DEFINED; break;
+ }
+}
+
+void HWDevice::SetRect(const LayerRect &source, mdp_rect *target) {
+ target->x = UINT32(source.left);
+ target->y = UINT32(source.top);
+ target->w = UINT32(source.right) - target->x;
+ target->h = UINT32(source.bottom) - target->y;
+}
+
+void HWDevice::SetMDPFlags(const Layer *layer, const bool &is_rotator_used,
+ bool is_cursor_pipe_used, uint32_t *mdp_flags) {
+ const LayerBuffer &input_buffer = layer->input_buffer;
+
+ // Flips will be taken care by rotator, if layer uses rotator for downscale/rotation. So ignore
+ // flip flags for MDP.
+ if (!is_rotator_used) {
+ if (layer->transform.flip_vertical) {
+ *mdp_flags |= MDP_LAYER_FLIP_UD;
+ }
+
+ if (layer->transform.flip_horizontal) {
+ *mdp_flags |= MDP_LAYER_FLIP_LR;
+ }
+
+ if (input_buffer.flags.interlace) {
+ *mdp_flags |= MDP_LAYER_DEINTERLACE;
+ }
+ }
+
+ if (input_buffer.flags.secure_camera) {
+ *mdp_flags |= MDP_LAYER_SECURE_CAMERA_SESSION;
+ } else if (input_buffer.flags.secure) {
+ *mdp_flags |= MDP_LAYER_SECURE_SESSION;
+ }
+
+ if (input_buffer.flags.secure_display) {
+ *mdp_flags |= MDP_LAYER_SECURE_DISPLAY_SESSION;
+ }
+
+ if (layer->flags.solid_fill) {
+ *mdp_flags |= MDP_LAYER_SOLID_FILL;
+ }
+
+ if (hw_panel_info_.mode != kModeCommand && layer->flags.cursor && is_cursor_pipe_used) {
+ // command mode panels does not support async position update
+ *mdp_flags |= MDP_LAYER_ASYNC;
+ }
+}
+
+int HWDevice::GetFBNodeIndex(HWDeviceType device_type) {
+ for (int i = 0; i < kFBNodeMax; i++) {
+ HWPanelInfo panel_info;
+ GetHWPanelInfoByNode(i, &panel_info);
+ switch (device_type) {
+ case kDevicePrimary:
+ if (panel_info.is_primary_panel) {
+ return i;
+ }
+ break;
+ case kDeviceHDMI:
+ if (panel_info.is_pluggable == true) {
+ if (IsFBNodeConnected(i)) {
+ return i;
+ }
+ }
+ break;
+ case kDeviceVirtual:
+ if (panel_info.port == kPortWriteBack) {
+ return i;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ return -1;
+}
+
+void HWDevice::PopulateHWPanelInfo() {
+ hw_panel_info_ = HWPanelInfo();
+ GetHWPanelInfoByNode(fb_node_index_, &hw_panel_info_);
+ DLOGI("Device type = %d, Display Port = %d, Display Mode = %d, Device Node = %d, Is Primary = %d",
+ device_type_, hw_panel_info_.port, hw_panel_info_.mode, fb_node_index_,
+ hw_panel_info_.is_primary_panel);
+ DLOGI("Partial Update = %d, supported roi_count =%d, Dynamic FPS = %d",
+ hw_panel_info_.partial_update, hw_panel_info_.left_roi_count, hw_panel_info_.dynamic_fps);
+ DLOGI("Align: left = %d, width = %d, top = %d, height = %d",
+ hw_panel_info_.left_align, hw_panel_info_.width_align,
+ hw_panel_info_.top_align, hw_panel_info_.height_align);
+ DLOGI("ROI: min_width = %d, min_height = %d, need_merge = %d",
+ hw_panel_info_.min_roi_width, hw_panel_info_.min_roi_height,
+ hw_panel_info_.needs_roi_merge);
+ DLOGI("FPS: min = %d, max =%d", hw_panel_info_.min_fps, hw_panel_info_.max_fps);
+ DLOGI("Ping Pong Split = %d", hw_panel_info_.ping_pong_split);
+ DLOGI("Left Split = %d, Right Split = %d", hw_panel_info_.split_info.left_split,
+ hw_panel_info_.split_info.right_split);
+}
+
+void HWDevice::GetHWPanelNameByNode(int device_node, HWPanelInfo *panel_info) {
+ string file_name = fb_path_ + to_string(device_node) + "/msm_fb_panel_info";
+
+ Sys::fstream fs(file_name, fstream::in);
+ if (!fs.is_open()) {
+ DLOGW("Failed to open msm_fb_panel_info node device node %d", device_node);
+ return;
+ }
+
+ string line;
+ while (Sys::getline_(fs, line)) {
+ uint32_t token_count = 0;
+ const uint32_t max_count = 10;
+ char *tokens[max_count] = { NULL };
+ if (!ParseLine(line.c_str(), "=\n", tokens, max_count, &token_count)) {
+ if (!strncmp(tokens[0], "panel_name", strlen("panel_name"))) {
+ snprintf(panel_info->panel_name, sizeof(panel_info->panel_name), "%s", tokens[1]);
+ break;
+ }
+ }
+ }
+}
+
+void HWDevice::GetHWPanelInfoByNode(int device_node, HWPanelInfo *panel_info) {
+ string file_name = fb_path_ + to_string(device_node) + "/msm_fb_panel_info";
+
+ Sys::fstream fs(file_name, fstream::in);
+ if (!fs.is_open()) {
+ DLOGW("Failed to open msm_fb_panel_info node device node %d", device_node);
+ return;
+ }
+
+ string line;
+ while (Sys::getline_(fs, line)) {
+ uint32_t token_count = 0;
+ const uint32_t max_count = 10;
+ char *tokens[max_count] = { NULL };
+ if (!ParseLine(line.c_str(), tokens, max_count, &token_count)) {
+ if (!strncmp(tokens[0], "pu_en", strlen("pu_en"))) {
+ panel_info->partial_update = atoi(tokens[1]);
+ } else if (!strncmp(tokens[0], "xstart", strlen("xstart"))) {
+ panel_info->left_align = atoi(tokens[1]);
+ } else if (!strncmp(tokens[0], "walign", strlen("walign"))) {
+ panel_info->width_align = atoi(tokens[1]);
+ } else if (!strncmp(tokens[0], "ystart", strlen("ystart"))) {
+ panel_info->top_align = atoi(tokens[1]);
+ } else if (!strncmp(tokens[0], "halign", strlen("halign"))) {
+ panel_info->height_align = atoi(tokens[1]);
+ } else if (!strncmp(tokens[0], "min_w", strlen("min_w"))) {
+ panel_info->min_roi_width = atoi(tokens[1]);
+ } else if (!strncmp(tokens[0], "min_h", strlen("min_h"))) {
+ panel_info->min_roi_height = atoi(tokens[1]);
+ } else if (!strncmp(tokens[0], "roi_merge", strlen("roi_merge"))) {
+ panel_info->needs_roi_merge = atoi(tokens[1]);
+ } else if (!strncmp(tokens[0], "dyn_fps_en", strlen("dyn_fps_en"))) {
+ panel_info->dynamic_fps = atoi(tokens[1]);
+ } else if (!strncmp(tokens[0], "dfps_porch_mode", strlen("dfps_porch_mode"))) {
+ panel_info->dfps_porch_mode = atoi(tokens[1]);
+ } else if (!strncmp(tokens[0], "is_pingpong_split", strlen("is_pingpong_split"))) {
+ panel_info->ping_pong_split = atoi(tokens[1]);
+ } else if (!strncmp(tokens[0], "min_fps", strlen("min_fps"))) {
+ panel_info->min_fps = UINT32(atoi(tokens[1]));
+ } else if (!strncmp(tokens[0], "max_fps", strlen("max_fps"))) {
+ panel_info->max_fps = UINT32(atoi(tokens[1]));
+ } else if (!strncmp(tokens[0], "primary_panel", strlen("primary_panel"))) {
+ panel_info->is_primary_panel = atoi(tokens[1]);
+ } else if (!strncmp(tokens[0], "is_pluggable", strlen("is_pluggable"))) {
+ panel_info->is_pluggable = atoi(tokens[1]);
+ } else if (!strncmp(tokens[0], "pu_roi_cnt", strlen("pu_roi_cnt"))) {
+ panel_info->left_roi_count = UINT32(atoi(tokens[1]));
+ panel_info->right_roi_count = UINT32(atoi(tokens[1]));
+ } else if (!strncmp(tokens[0], "is_hdr_enabled", strlen("is_hdr_enabled"))) {
+ panel_info->hdr_enabled = atoi(tokens[1]);
+ } else if (!strncmp(tokens[0], "peak_brightness", strlen("peak_brightness"))) {
+ panel_info->peak_luminance = UINT32(atoi(tokens[1]));
+ } else if (!strncmp(tokens[0], "average_brightness", strlen("average_brightness"))) {
+ panel_info->average_luminance = UINT32(atoi(tokens[1]));
+ } else if (!strncmp(tokens[0], "blackness_level", strlen("blackness_level"))) {
+ panel_info->blackness_level = UINT32(atoi(tokens[1]));
+ } else if (!strncmp(tokens[0], "white_chromaticity_x", strlen("white_chromaticity_x"))) {
+ panel_info->primaries.white_point[0] = UINT32(atoi(tokens[1]));
+ } else if (!strncmp(tokens[0], "white_chromaticity_y", strlen("white_chromaticity_y"))) {
+ panel_info->primaries.white_point[1] = UINT32(atoi(tokens[1]));
+ } else if (!strncmp(tokens[0], "red_chromaticity_x", strlen("red_chromaticity_x"))) {
+ panel_info->primaries.red[0] = UINT32(atoi(tokens[1]));
+ } else if (!strncmp(tokens[0], "red_chromaticity_y", strlen("red_chromaticity_y"))) {
+ panel_info->primaries.red[1] = UINT32(atoi(tokens[1]));
+ } else if (!strncmp(tokens[0], "green_chromaticity_x", strlen("green_chromaticity_x"))) {
+ panel_info->primaries.green[0] = UINT32(atoi(tokens[1]));
+ } else if (!strncmp(tokens[0], "green_chromaticity_y", strlen("green_chromaticity_y"))) {
+ panel_info->primaries.green[1] = UINT32(atoi(tokens[1]));
+ } else if (!strncmp(tokens[0], "blue_chromaticity_x", strlen("blue_chromaticity_x"))) {
+ panel_info->primaries.blue[0] = UINT32(atoi(tokens[1]));
+ } else if (!strncmp(tokens[0], "blue_chromaticity_y", strlen("blue_chromaticity_y"))) {
+ panel_info->primaries.blue[1] = UINT32(atoi(tokens[1]));
+ } else if (!strncmp(tokens[0], "panel_orientation", strlen("panel_orientation"))) {
+ int32_t panel_orient = atoi(tokens[1]);
+ panel_info->panel_orientation.flip_horizontal = ((panel_orient & MDP_FLIP_LR) > 0);
+ panel_info->panel_orientation.flip_vertical = ((panel_orient & MDP_FLIP_UD) > 0);
+ panel_info->panel_orientation.rotation = ((panel_orient & MDP_ROT_90) > 0);
+ }
+ }
+ }
+
+ GetHWDisplayPortAndMode(device_node, panel_info);
+ GetSplitInfo(device_node, panel_info);
+ GetHWPanelNameByNode(device_node, panel_info);
+ GetHWPanelMaxBrightnessFromNode(panel_info);
+}
+
+void HWDevice::GetHWDisplayPortAndMode(int device_node, HWPanelInfo *panel_info) {
+ DisplayPort *port = &panel_info->port;
+ HWDisplayMode *mode = &panel_info->mode;
+
+ *port = kPortDefault;
+ *mode = kModeDefault;
+
+ string file_name = fb_path_ + to_string(device_node) + "/msm_fb_type";
+
+ Sys::fstream fs(file_name, fstream::in);
+ if (!fs.is_open()) {
+ DLOGW("File not found %s", file_name.c_str());
+ return;
+ }
+
+ string line;
+ if (!Sys::getline_(fs, line)) {
+ return;
+ }
+
+ if ((strncmp(line.c_str(), "mipi dsi cmd panel", strlen("mipi dsi cmd panel")) == 0)) {
+ *port = kPortDSI;
+ *mode = kModeCommand;
+ } else if ((strncmp(line.c_str(), "mipi dsi video panel", strlen("mipi dsi video panel")) == 0)) {
+ *port = kPortDSI;
+ *mode = kModeVideo;
+ } else if ((strncmp(line.c_str(), "lvds panel", strlen("lvds panel")) == 0)) {
+ *port = kPortLVDS;
+ *mode = kModeVideo;
+ } else if ((strncmp(line.c_str(), "edp panel", strlen("edp panel")) == 0)) {
+ *port = kPortEDP;
+ *mode = kModeVideo;
+ } else if ((strncmp(line.c_str(), "dtv panel", strlen("dtv panel")) == 0)) {
+ *port = kPortDTV;
+ *mode = kModeVideo;
+ } else if ((strncmp(line.c_str(), "writeback panel", strlen("writeback panel")) == 0)) {
+ *port = kPortWriteBack;
+ *mode = kModeCommand;
+ } else if ((strncmp(line.c_str(), "dp panel", strlen("dp panel")) == 0)) {
+ *port = kPortDP;
+ *mode = kModeVideo;
+ }
+
+ return;
+}
+
+void HWDevice::GetSplitInfo(int device_node, HWPanelInfo *panel_info) {
+ // Split info - for MDSS Version 5 - No need to check version here
+ string file_name = fb_path_ + to_string(device_node) + "/msm_fb_split";
+
+ Sys::fstream fs(file_name, fstream::in);
+ if (!fs.is_open()) {
+ DLOGW("File not found %s", file_name.c_str());
+ return;
+ }
+
+ // Format "left right" space as delimiter
+ uint32_t token_count = 0;
+ const uint32_t max_count = 10;
+ char *tokens[max_count] = { NULL };
+ string line;
+ if (Sys::getline_(fs, line)) {
+ if (!ParseLine(line.c_str(), tokens, max_count, &token_count)) {
+ panel_info->split_info.left_split = UINT32(atoi(tokens[0]));
+ panel_info->split_info.right_split = UINT32(atoi(tokens[1]));
+ }
+ }
+}
+
+void HWDevice::GetHWPanelMaxBrightnessFromNode(HWPanelInfo *panel_info) {
+ char brightness[kMaxStringLength] = { 0 };
+ char kMaxBrightnessNode[64] = { 0 };
+
+ snprintf(kMaxBrightnessNode, sizeof(kMaxBrightnessNode), "%s",
+ "/sys/class/leds/lcd-backlight/max_brightness");
+
+ panel_info->panel_max_brightness = 0;
+ int fd = Sys::open_(kMaxBrightnessNode, O_RDONLY);
+ if (fd < 0) {
+ DLOGW("Failed to open max brightness node = %s, error = %s", kMaxBrightnessNode,
+ strerror(errno));
+ return;
+ }
+
+ if (Sys::pread_(fd, brightness, sizeof(brightness), 0) > 0) {
+ panel_info->panel_max_brightness = atoi(brightness);
+ DLOGI("Max brightness level = %d", panel_info->panel_max_brightness);
+ } else {
+ DLOGW("Failed to read max brightness level. error = %s", strerror(errno));
+ }
+ Sys::close_(fd);
+}
+
+int HWDevice::ParseLine(const char *input, char *tokens[], const uint32_t max_token,
+ uint32_t *count) {
+ char *tmp_token = NULL;
+ char *temp_ptr;
+ uint32_t index = 0;
+ const char *delim = ", =\n";
+ if (!input) {
+ return -1;
+ }
+ tmp_token = strtok_r(const_cast<char *>(input), delim, &temp_ptr);
+ while (tmp_token && index < max_token) {
+ tokens[index++] = tmp_token;
+ tmp_token = strtok_r(NULL, delim, &temp_ptr);
+ }
+ *count = index;
+
+ return 0;
+}
+
+int HWDevice::ParseLine(const char *input, const char *delim, char *tokens[],
+ const uint32_t max_token, uint32_t *count) {
+ char *tmp_token = NULL;
+ char *temp_ptr;
+ uint32_t index = 0;
+ if (!input) {
+ return -1;
+ }
+ tmp_token = strtok_r(const_cast<char *>(input), delim, &temp_ptr);
+ while (tmp_token && index < max_token) {
+ tokens[index++] = tmp_token;
+ tmp_token = strtok_r(NULL, delim, &temp_ptr);
+ }
+ *count = index;
+
+ return 0;
+}
+
+bool HWDevice::EnableHotPlugDetection(int enable) {
+ char hpdpath[kMaxStringLength];
+ const char *value = enable ? "1" : "0";
+
+ // Enable HPD for all pluggable devices.
+ for (int i = 0; i < kFBNodeMax; i++) {
+ HWPanelInfo panel_info;
+ GetHWPanelInfoByNode(i, &panel_info);
+ if (panel_info.is_pluggable == true) {
+ snprintf(hpdpath , sizeof(hpdpath), "%s%d/hpd", fb_path_, i);
+
+ ssize_t length = SysFsWrite(hpdpath, value, 1);
+ if (length <= 0) {
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+void HWDevice::ResetDisplayParams() {
+ memset(&mdp_disp_commit_, 0, sizeof(mdp_disp_commit_));
+ memset(&mdp_in_layers_, 0, sizeof(mdp_in_layers_));
+ memset(&mdp_out_layer_, 0, sizeof(mdp_out_layer_));
+ mdp_out_layer_.buffer.fence = -1;
+ hw_scale_->ResetScaleParams();
+ memset(&pp_params_, 0, sizeof(pp_params_));
+ memset(&igc_lut_data_, 0, sizeof(igc_lut_data_));
+
+ for (size_t i = 0; i < mdp_dest_scalar_data_.size(); i++) {
+ mdp_dest_scalar_data_[i] = {};
+ }
+
+ for (uint32_t i = 0; i < kMaxSDELayers * 2; i++) {
+ mdp_in_layers_[i].buffer.fence = -1;
+ }
+
+ mdp_disp_commit_.version = MDP_COMMIT_VERSION_1_0;
+ mdp_disp_commit_.commit_v1.input_layers = mdp_in_layers_;
+ mdp_disp_commit_.commit_v1.output_layer = &mdp_out_layer_;
+ mdp_disp_commit_.commit_v1.release_fence = -1;
+ mdp_disp_commit_.commit_v1.retire_fence = -1;
+ mdp_disp_commit_.commit_v1.dest_scaler = mdp_dest_scalar_data_.data();
+}
+
+void HWDevice::SetCSC(const ColorMetaData &color_metadata, mdp_color_space *color_space) {
+ switch (color_metadata.colorPrimaries) {
+ case ColorPrimaries_BT601_6_525:
+ case ColorPrimaries_BT601_6_625:
+ *color_space = ((color_metadata.range == Range_Full) ? MDP_CSC_ITU_R_601_FR :
+ MDP_CSC_ITU_R_601);
+ break;
+ case ColorPrimaries_BT709_5:
+ *color_space = MDP_CSC_ITU_R_709;
+ break;
+#if defined MDP_CSC_ITU_R_2020 && defined MDP_CSC_ITU_R_2020_FR
+ case ColorPrimaries_BT2020:
+ *color_space = static_cast<mdp_color_space>((color_metadata.range == Range_Full) ?
+ MDP_CSC_ITU_R_2020_FR : MDP_CSC_ITU_R_2020);
+ break;
+#endif
+ default:
+ break;
+ }
+}
+
+void HWDevice::SetIGC(const LayerBuffer *layer_buffer, uint32_t index) {
+ mdp_input_layer &mdp_layer = mdp_in_layers_[index];
+ mdp_overlay_pp_params &pp_params = pp_params_[index];
+ mdp_igc_lut_data_v1_7 &igc_lut_data = igc_lut_data_[index];
+
+ switch (layer_buffer->igc) {
+ case kIGCsRGB:
+ igc_lut_data.table_fmt = mdp_igc_srgb;
+ pp_params.igc_cfg.ops = MDP_PP_OPS_WRITE | MDP_PP_OPS_ENABLE;
+ break;
+
+ default:
+ pp_params.igc_cfg.ops = MDP_PP_OPS_DISABLE;
+ break;
+ }
+
+ pp_params.config_ops = MDP_OVERLAY_PP_IGC_CFG;
+ pp_params.igc_cfg.version = mdp_igc_v1_7;
+ pp_params.igc_cfg.cfg_payload = &igc_lut_data;
+
+ mdp_layer.pp_info = &pp_params;
+ mdp_layer.flags |= MDP_LAYER_PP;
+}
+
+DisplayError HWDevice::SetCursorPosition(HWLayers *hw_layers, int x, int y) {
+ DTRACE_SCOPED();
+
+ HWLayersInfo &hw_layer_info = hw_layers->info;
+ uint32_t count = UINT32(hw_layer_info.hw_layers.size());
+ uint32_t cursor_index = count - 1;
+ HWPipeInfo *left_pipe = &hw_layers->config[cursor_index].left_pipe;
+
+ mdp_async_layer async_layer = {};
+ async_layer.flags = MDP_LAYER_ASYNC;
+ async_layer.pipe_ndx = left_pipe->pipe_id;
+ async_layer.src.x = UINT32(left_pipe->src_roi.left);
+ async_layer.src.y = UINT32(left_pipe->src_roi.top);
+ async_layer.dst.x = UINT32(left_pipe->dst_roi.left);
+ async_layer.dst.y = UINT32(left_pipe->dst_roi.top);
+
+ mdp_position_update pos_update = {};
+ pos_update.input_layer_cnt = 1;
+ pos_update.input_layers = &async_layer;
+ if (Sys::ioctl_(device_fd_, INT(MSMFB_ASYNC_POSITION_UPDATE), &pos_update) < 0) {
+ if (errno == ESHUTDOWN) {
+ DLOGI_IF(kTagDriverConfig, "Driver is processing shutdown sequence");
+ return kErrorShutDown;
+ }
+ IOCTL_LOGE(MSMFB_ASYNC_POSITION_UPDATE, device_type_);
+ return kErrorHardware;
+ }
+
+ return kErrorNone;
+}
+
+DisplayError HWDevice::GetPPFeaturesVersion(PPFeatureVersion *vers) {
+ return kErrorNotSupported;
+}
+
+DisplayError HWDevice::SetPPFeatures(PPFeaturesConfig *feature_list) {
+ return kErrorNotSupported;
+}
+
+DisplayError HWDevice::SetVSyncState(bool enable) {
+ int vsync_on = enable ? 1 : 0;
+ if (Sys::ioctl_(device_fd_, MSMFB_OVERLAY_VSYNC_CTRL, &vsync_on) < 0) {
+ if (errno == ESHUTDOWN) {
+ DLOGI_IF(kTagDriverConfig, "Driver is processing shutdown sequence");
+ return kErrorShutDown;
+ }
+ IOCTL_LOGE(MSMFB_OVERLAY_VSYNC_CTRL, device_type_);
+ return kErrorHardware;
+ }
+ return kErrorNone;
+}
+
+void HWDevice::SetIdleTimeoutMs(uint32_t timeout_ms) {
+}
+
+DisplayError HWDevice::SetDisplayMode(const HWDisplayMode hw_display_mode) {
+ return kErrorNotSupported;
+}
+
+DisplayError HWDevice::SetRefreshRate(uint32_t refresh_rate) {
+ return kErrorNotSupported;
+}
+
+DisplayError HWDevice::SetPanelBrightness(int level) {
+ return kErrorNotSupported;
+}
+
+DisplayError HWDevice::CachePanelBrightness(int level) {
+ return kErrorNotSupported;
+}
+
+DisplayError HWDevice::GetHWScanInfo(HWScanInfo *scan_info) {
+ return kErrorNotSupported;
+}
+
+DisplayError HWDevice::GetVideoFormat(uint32_t config_index, uint32_t *video_format) {
+ return kErrorNotSupported;
+}
+
+DisplayError HWDevice::GetMaxCEAFormat(uint32_t *max_cea_format) {
+ return kErrorNotSupported;
+}
+
+DisplayError HWDevice::OnMinHdcpEncryptionLevelChange(uint32_t min_enc_level) {
+ return kErrorNotSupported;
+}
+
+DisplayError HWDevice::GetPanelBrightness(int *level) {
+ return kErrorNotSupported;
+}
+
+ssize_t HWDevice::SysFsWrite(const char* file_node, const char* value, ssize_t length) {
+ int fd = Sys::open_(file_node, O_RDWR, 0);
+ if (fd < 0) {
+ DLOGW("Open failed = %s", file_node);
+ return -1;
+ }
+ ssize_t len = Sys::pwrite_(fd, value, static_cast<size_t>(length), 0);
+ if (len <= 0) {
+ DLOGE("Write failed for path %s with value %s", file_node, value);
+ }
+ Sys::close_(fd);
+
+ return len;
+}
+
+bool HWDevice::IsFBNodeConnected(int fb_node) {
+ string file_name = fb_path_ + to_string(fb_node) + "/connected";
+
+ Sys::fstream fs(file_name, fstream::in);
+ if (!fs.is_open()) {
+ DLOGW("File not found %s", file_name.c_str());
+ return false;
+ }
+
+ string line;
+ if (!Sys::getline_(fs, line)) {
+ return false;
+ }
+
+ return atoi(line.c_str());
+}
+
+DisplayError HWDevice::SetS3DMode(HWS3DMode s3d_mode) {
+ return kErrorNotSupported;
+}
+
+DisplayError HWDevice::SetScaleLutConfig(HWScaleLutInfo *lut_info) {
+ mdp_scale_luts_info mdp_lut_info = {};
+ mdp_set_cfg cfg = {};
+
+ if (!hw_resource_.has_qseed3) {
+ DLOGV_IF(kTagDriverConfig, "No support for QSEED3 luts");
+ return kErrorNone;
+ }
+
+ if (!lut_info->dir_lut_size && !lut_info->dir_lut && !lut_info->cir_lut_size &&
+ !lut_info->cir_lut && !lut_info->sep_lut_size && !lut_info->sep_lut) {
+ // HWSupports QSEED3, but LutInfo is invalid as scalar is disabled by property or
+ // its loading failed. Driver will use default settings/filter
+ return kErrorNone;
+ }
+
+ mdp_lut_info.dir_lut_size = lut_info->dir_lut_size;
+ mdp_lut_info.dir_lut = lut_info->dir_lut;
+ mdp_lut_info.cir_lut_size = lut_info->cir_lut_size;
+ mdp_lut_info.cir_lut = lut_info->cir_lut;
+ mdp_lut_info.sep_lut_size = lut_info->sep_lut_size;
+ mdp_lut_info.sep_lut = lut_info->sep_lut;
+
+ cfg.flags = MDP_QSEED3_LUT_CFG;
+ cfg.len = sizeof(mdp_scale_luts_info);
+ cfg.payload = reinterpret_cast<uint64_t>(&mdp_lut_info);
+
+ if (Sys::ioctl_(device_fd_, MSMFB_MDP_SET_CFG, &cfg) < 0) {
+ if (errno == ESHUTDOWN) {
+ DLOGI_IF(kTagDriverConfig, "Driver is processing shutdown sequence");
+ return kErrorShutDown;
+ }
+ IOCTL_LOGE(MSMFB_MDP_SET_CFG, device_type_);
+ return kErrorHardware;
+ }
+
+ return kErrorNone;
+}
+
+DisplayError HWDevice::SetMixerAttributes(const HWMixerAttributes &mixer_attributes) {
+ if (!hw_resource_.hw_dest_scalar_info.count) {
+ return kErrorNotSupported;
+ }
+
+ if (mixer_attributes.width > display_attributes_.x_pixels ||
+ mixer_attributes.height > display_attributes_.y_pixels) {
+ DLOGW_IF(kTagDriverConfig, "Input resolution exceeds display resolution! input: res %dx%d "\
+ "display: res %dx%d", mixer_attributes.width, mixer_attributes.height,
+ display_attributes_.x_pixels, display_attributes_.y_pixels);
+ return kErrorNotSupported;
+ }
+
+ uint32_t max_input_width = hw_resource_.hw_dest_scalar_info.max_input_width;
+ if (display_attributes_.is_device_split) {
+ max_input_width *= 2;
+ }
+
+ if (mixer_attributes.width > max_input_width) {
+ DLOGW_IF(kTagDriverConfig, "Input width exceeds width limit! input_width %d width_limit %d",
+ mixer_attributes.width, max_input_width);
+ return kErrorNotSupported;
+ }
+
+ float mixer_aspect_ratio = FLOAT(mixer_attributes.width) / FLOAT(mixer_attributes.height);
+ float display_aspect_ratio =
+ FLOAT(display_attributes_.x_pixels) / FLOAT(display_attributes_.y_pixels);
+
+ if (display_aspect_ratio != mixer_aspect_ratio) {
+ DLOGW_IF(kTagDriverConfig, "Aspect ratio mismatch! input: res %dx%d display: res %dx%d",
+ mixer_attributes.width, mixer_attributes.height, display_attributes_.x_pixels,
+ display_attributes_.y_pixels);
+ return kErrorNotSupported;
+ }
+
+ float scale_x = FLOAT(display_attributes_.x_pixels) / FLOAT(mixer_attributes.width);
+ float scale_y = FLOAT(display_attributes_.y_pixels) / FLOAT(mixer_attributes.height);
+ float max_scale_up = hw_resource_.hw_dest_scalar_info.max_scale_up;
+ if (scale_x > max_scale_up || scale_y > max_scale_up) {
+ DLOGW_IF(kTagDriverConfig, "Up scaling ratio exceeds for destination scalar upscale " \
+ "limit scale_x %f scale_y %f max_scale_up %f", scale_x, scale_y, max_scale_up);
+ return kErrorNotSupported;
+ }
+
+ float mixer_split_ratio = FLOAT(mixer_attributes_.split_left) / FLOAT(mixer_attributes_.width);
+
+ mixer_attributes_ = mixer_attributes;
+ mixer_attributes_.split_left = mixer_attributes_.width;
+ if (display_attributes_.is_device_split) {
+ mixer_attributes_.split_left = UINT32(FLOAT(mixer_attributes.width) * mixer_split_ratio);
+ }
+
+ return kErrorNone;
+}
+
+DisplayError HWDevice::GetMixerAttributes(HWMixerAttributes *mixer_attributes) {
+ if (!mixer_attributes) {
+ return kErrorParameters;
+ }
+
+ *mixer_attributes = mixer_attributes_;
+
+ return kErrorNone;
+}
+
+} // namespace sdm
+
diff --git a/msm8909/sdm/libs/core/fb/hw_device.h b/msm8909/sdm/libs/core/fb/hw_device.h
new file mode 100644
index 00000000..374df568
--- /dev/null
+++ b/msm8909/sdm/libs/core/fb/hw_device.h
@@ -0,0 +1,167 @@
+/*
+* Copyright (c) 2014 - 2017, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without modification, are permitted
+* provided that the following conditions are met:
+* * Redistributions of source code must retain the above copyright notice, this list of
+* conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright notice, this list of
+* conditions and the following disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its contributors may be used to
+* endorse or promote products derived from this software without specific prior written
+* permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __HW_DEVICE_H__
+#define __HW_DEVICE_H__
+
+#include <errno.h>
+#include <linux/msm_mdp_ext.h>
+#include <linux/mdss_rotator.h>
+#include <pthread.h>
+#include <vector>
+
+#include "hw_interface.h"
+#include "hw_scale.h"
+
+#define IOCTL_LOGE(ioctl, type) DLOGE("ioctl %s, device = %d errno = %d, desc = %s", #ioctl, \
+ type, errno, strerror(errno))
+
+#ifndef MDP_LAYER_MULTIRECT_ENABLE
+#define MDP_LAYER_MULTIRECT_ENABLE 0
+#endif
+
+#ifndef MDP_LAYER_MULTIRECT_PARALLEL_MODE
+#define MDP_LAYER_MULTIRECT_PARALLEL_MODE 0
+#endif
+
+#ifndef MDP_LAYER_SECURE_CAMERA_SESSION
+#define MDP_LAYER_SECURE_CAMERA_SESSION 0
+#endif
+
+namespace sdm {
+class HWInfoInterface;
+
+class HWDevice : public HWInterface {
+ public:
+ virtual ~HWDevice() {}
+ virtual DisplayError Init();
+ virtual DisplayError Deinit();
+
+ protected:
+ explicit HWDevice(BufferSyncHandler *buffer_sync_handler);
+
+ // From HWInterface
+ virtual DisplayError GetActiveConfig(uint32_t *active_config);
+ virtual DisplayError GetNumDisplayAttributes(uint32_t *count);
+ virtual DisplayError GetDisplayAttributes(uint32_t index,
+ HWDisplayAttributes *display_attributes);
+ virtual DisplayError GetHWPanelInfo(HWPanelInfo *panel_info);
+ virtual DisplayError SetDisplayAttributes(uint32_t index);
+ virtual DisplayError SetDisplayAttributes(const HWDisplayAttributes &display_attributes);
+ virtual DisplayError GetConfigIndex(uint32_t mode, uint32_t *index);
+ virtual DisplayError PowerOn();
+ virtual DisplayError PowerOff();
+ virtual DisplayError Doze();
+ virtual DisplayError DozeSuspend();
+ virtual DisplayError Standby();
+ virtual DisplayError Validate(HWLayers *hw_layers);
+ virtual DisplayError Commit(HWLayers *hw_layers);
+ virtual DisplayError Flush();
+ virtual DisplayError GetPPFeaturesVersion(PPFeatureVersion *vers);
+ virtual DisplayError SetPPFeatures(PPFeaturesConfig *feature_list);
+ virtual DisplayError SetVSyncState(bool enable);
+ virtual void SetIdleTimeoutMs(uint32_t timeout_ms);
+ virtual DisplayError SetDisplayMode(const HWDisplayMode hw_display_mode);
+ virtual DisplayError SetRefreshRate(uint32_t refresh_rate);
+ virtual DisplayError SetPanelBrightness(int level);
+ virtual DisplayError CachePanelBrightness(int level);
+ virtual DisplayError GetHWScanInfo(HWScanInfo *scan_info);
+ virtual DisplayError GetVideoFormat(uint32_t config_index, uint32_t *video_format);
+ virtual DisplayError GetMaxCEAFormat(uint32_t *max_cea_format);
+ virtual DisplayError SetCursorPosition(HWLayers *hw_layers, int x, int y);
+ virtual DisplayError OnMinHdcpEncryptionLevelChange(uint32_t min_enc_level);
+ virtual DisplayError GetPanelBrightness(int *level);
+ virtual DisplayError SetAutoRefresh(bool enable) { return kErrorNone; }
+ virtual DisplayError SetS3DMode(HWS3DMode s3d_mode);
+ virtual DisplayError SetScaleLutConfig(HWScaleLutInfo *lut_info);
+ virtual DisplayError SetMixerAttributes(const HWMixerAttributes &mixer_attributes);
+ virtual DisplayError GetMixerAttributes(HWMixerAttributes *mixer_attributes);
+
+ enum {
+ kHWEventVSync,
+ kHWEventBlank,
+ };
+
+ static const int kMaxStringLength = 1024;
+ static const int kNumPhysicalDisplays = 2;
+ // This indicates the number of fb devices created in the driver for all interfaces. Any addition
+ // of new fb devices should be added here.
+ static const int kFBNodeMax = 4;
+
+ void DumpLayerCommit(const mdp_layer_commit &layer_commit);
+ DisplayError SetFormat(const LayerBufferFormat &source, uint32_t *target);
+ DisplayError SetStride(HWDeviceType device_type, LayerBufferFormat format,
+ uint32_t width, uint32_t *target);
+ void SetBlending(const LayerBlending &source, mdss_mdp_blend_op *target);
+ void SetRect(const LayerRect &source, mdp_rect *target);
+ void SetMDPFlags(const Layer *layer, const bool &is_rotator_used,
+ bool is_cursor_pipe_used, uint32_t *mdp_flags);
+ // Retrieves HW FrameBuffer Node Index
+ int GetFBNodeIndex(HWDeviceType device_type);
+ // Populates HWPanelInfo based on node index
+ void PopulateHWPanelInfo();
+ void GetHWPanelInfoByNode(int device_node, HWPanelInfo *panel_info);
+ void GetHWPanelNameByNode(int device_node, HWPanelInfo *panel_info);
+ void GetHWDisplayPortAndMode(int device_node, HWPanelInfo *panel_info);
+ void GetSplitInfo(int device_node, HWPanelInfo *panel_info);
+ void GetHWPanelMaxBrightnessFromNode(HWPanelInfo *panel_info);
+ int ParseLine(const char *input, char *tokens[], const uint32_t max_token, uint32_t *count);
+ int ParseLine(const char *input, const char *delim, char *tokens[],
+ const uint32_t max_token, uint32_t *count);
+ void ResetDisplayParams();
+ void SetCSC(const ColorMetaData &color_metadata, mdp_color_space *color_space);
+ void SetIGC(const LayerBuffer *layer_buffer, uint32_t index);
+
+ bool EnableHotPlugDetection(int enable);
+ ssize_t SysFsWrite(const char* file_node, const char* value, ssize_t length);
+ bool IsFBNodeConnected(int fb_node);
+
+ HWResourceInfo hw_resource_;
+ HWPanelInfo hw_panel_info_;
+ HWInfoInterface *hw_info_intf_;
+ int fb_node_index_;
+ const char *fb_path_;
+ BufferSyncHandler *buffer_sync_handler_;
+ int device_fd_ = -1;
+ int stored_retire_fence = -1;
+ HWDeviceType device_type_;
+ mdp_layer_commit mdp_disp_commit_;
+ mdp_input_layer mdp_in_layers_[kMaxSDELayers * 2]; // split panel (left + right)
+ HWScale *hw_scale_ = NULL;
+ mdp_overlay_pp_params pp_params_[kMaxSDELayers * 2];
+ mdp_igc_lut_data_v1_7 igc_lut_data_[kMaxSDELayers * 2];
+ mdp_output_layer mdp_out_layer_;
+ const char *device_name_;
+ bool synchronous_commit_;
+ HWDisplayAttributes display_attributes_ = {};
+ HWMixerAttributes mixer_attributes_ = {};
+ std::vector<mdp_destination_scaler_data> mdp_dest_scalar_data_;
+ int bl_level_update_commit = -1;
+ bool bl_update_commit = false;
+};
+
+} // namespace sdm
+
+#endif // __HW_DEVICE_H__
+
diff --git a/msm8909/sdm/libs/core/fb/hw_events.cpp b/msm8909/sdm/libs/core/fb/hw_events.cpp
new file mode 100644
index 00000000..52a80112
--- /dev/null
+++ b/msm8909/sdm/libs/core/fb/hw_events.cpp
@@ -0,0 +1,237 @@
+/*
+* Copyright (c) 2015 - 2017, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/resource.h>
+#include <sys/prctl.h>
+#include <utils/debug.h>
+#include <utils/sys.h>
+#include <pthread.h>
+#include <algorithm>
+#include <vector>
+#include <map>
+#include <utility>
+
+#include "hw_events.h"
+
+#define __CLASS__ "HWEvents"
+
+namespace sdm {
+
+pollfd HWEvents::InitializePollFd(HWEventData *event_data) {
+ char node_path[kMaxStringLength] = {0};
+ char data[kMaxStringLength] = {0};
+ pollfd poll_fd = {0};
+ poll_fd.fd = -1;
+
+ if (event_data->event_type == HWEvent::EXIT) {
+ // Create an eventfd to be used to unblock the poll system call when
+ // a thread is exiting.
+ poll_fd.fd = Sys::eventfd_(0, 0);
+ poll_fd.events |= POLLIN;
+ exit_fd_ = poll_fd.fd;
+ } else {
+ snprintf(node_path, sizeof(node_path), "%s%d/%s", fb_path_, fb_num_,
+ map_event_to_node_[event_data->event_type]);
+ poll_fd.fd = Sys::open_(node_path, O_RDONLY);
+ poll_fd.events |= POLLPRI | POLLERR;
+ }
+
+ if (poll_fd.fd < 0) {
+ DLOGW("open failed for display=%d event=%s, error=%s", fb_num_,
+ map_event_to_node_[event_data->event_type], strerror(errno));
+ return poll_fd;
+ }
+
+ // Read once on all fds to clear data on all fds.
+ Sys::pread_(poll_fd.fd, data , kMaxStringLength, 0);
+
+ return poll_fd;
+}
+
+DisplayError HWEvents::SetEventParser(HWEvent event_type, HWEventData *event_data) {
+ DisplayError error = kErrorNone;
+ switch (event_type) {
+ case HWEvent::VSYNC:
+ event_data->event_parser = &HWEvents::HandleVSync;
+ break;
+ case HWEvent::IDLE_NOTIFY:
+ event_data->event_parser = &HWEvents::HandleIdleTimeout;
+ break;
+ case HWEvent::EXIT:
+ event_data->event_parser = &HWEvents::HandleThreadExit;
+ break;
+ case HWEvent::SHOW_BLANK_EVENT:
+ event_data->event_parser = &HWEvents::HandleBlank;
+ break;
+ case HWEvent::THERMAL_LEVEL:
+ event_data->event_parser = &HWEvents::HandleThermal;
+ break;
+ case HWEvent::IDLE_POWER_COLLAPSE:
+ event_data->event_parser = &HWEvents::HandleIdlePowerCollapse;
+ break;
+ default:
+ error = kErrorParameters;
+ break;
+ }
+
+ return error;
+}
+
+void HWEvents::PopulateHWEventData() {
+ for (uint32_t i = 0; i < event_list_.size(); i++) {
+ HWEventData event_data;
+ event_data.event_type = event_list_[i];
+ SetEventParser(event_list_[i], &event_data);
+ poll_fds_[i] = InitializePollFd(&event_data);
+ event_data_list_.push_back(event_data);
+ }
+}
+
+DisplayError HWEvents::Init(int fb_num, HWEventHandler *event_handler,
+ const vector<HWEvent> &event_list) {
+ if (!event_handler)
+ return kErrorParameters;
+
+ event_handler_ = event_handler;
+ fb_num_ = fb_num;
+ event_list_ = event_list;
+ poll_fds_.resize(event_list_.size());
+ event_thread_name_ += " - " + std::to_string(fb_num_);
+ map_event_to_node_ = {{HWEvent::VSYNC, "vsync_event"}, {HWEvent::EXIT, "thread_exit"},
+ {HWEvent::IDLE_NOTIFY, "idle_notify"}, {HWEvent::SHOW_BLANK_EVENT, "show_blank_event"},
+ {HWEvent::THERMAL_LEVEL, "msm_fb_thermal_level"}, {HWEvent::IDLE_POWER_COLLAPSE, "idle_power_collapse"}};
+
+ PopulateHWEventData();
+
+ if (pthread_create(&event_thread_, NULL, &DisplayEventThread, this) < 0) {
+ DLOGE("Failed to start %s, error = %s", event_thread_name_.c_str());
+ return kErrorResources;
+ }
+
+ return kErrorNone;
+}
+
+DisplayError HWEvents::Deinit() {
+ exit_threads_ = true;
+ Sys::pthread_cancel_(event_thread_);
+
+ uint64_t exit_value = 1;
+ ssize_t write_size = Sys::write_(exit_fd_, &exit_value, sizeof(uint64_t));
+ if (write_size != sizeof(uint64_t))
+ DLOGW("Error triggering exit_fd_ (%d). write size = %d, error = %s", exit_fd_, write_size,
+ strerror(errno));
+
+ pthread_join(event_thread_, NULL);
+
+ for (uint32_t i = 0; i < event_list_.size(); i++) {
+ Sys::close_(poll_fds_[i].fd);
+ poll_fds_[i].fd = -1;
+ }
+
+ return kErrorNone;
+}
+
+void* HWEvents::DisplayEventThread(void *context) {
+ if (context) {
+ return reinterpret_cast<HWEvents *>(context)->DisplayEventHandler();
+ }
+
+ return NULL;
+}
+
+void* HWEvents::DisplayEventHandler() {
+ char data[kMaxStringLength] = {0};
+
+ prctl(PR_SET_NAME, event_thread_name_.c_str(), 0, 0, 0);
+ setpriority(PRIO_PROCESS, 0, kThreadPriorityUrgent);
+
+ while (!exit_threads_) {
+ int error = Sys::poll_(poll_fds_.data(), UINT32(event_list_.size()), -1);
+
+ if (error <= 0) {
+ DLOGW("poll failed. error = %s", strerror(errno));
+ continue;
+ }
+
+ for (uint32_t event = 0; event < event_list_.size(); event++) {
+ pollfd &poll_fd = poll_fds_[event];
+
+ if (event_list_.at(event) == HWEvent::EXIT) {
+ if ((poll_fd.revents & POLLIN) && (Sys::read_(poll_fd.fd, data, kMaxStringLength) > 0)) {
+ (this->*(event_data_list_[event]).event_parser)(data);
+ }
+ } else {
+ if ((poll_fd.revents & POLLPRI) &&
+ (Sys::pread_(poll_fd.fd, data, kMaxStringLength, 0) > 0)) {
+ (this->*(event_data_list_[event]).event_parser)(data);
+ }
+ }
+ }
+ }
+
+ pthread_exit(0);
+
+ return NULL;
+}
+
+void HWEvents::HandleVSync(char *data) {
+ int64_t timestamp = 0;
+ if (!strncmp(data, "VSYNC=", strlen("VSYNC="))) {
+ timestamp = strtoll(data + strlen("VSYNC="), NULL, 0);
+ }
+
+ event_handler_->VSync(timestamp);
+}
+
+void HWEvents::HandleIdleTimeout(char *data) {
+ event_handler_->IdleTimeout();
+}
+
+void HWEvents::HandleThermal(char *data) {
+ int64_t thermal_level = 0;
+ if (!strncmp(data, "thermal_level=", strlen("thermal_level="))) {
+ thermal_level = strtoll(data + strlen("thermal_level="), NULL, 0);
+ }
+
+ DLOGI("Received thermal notification with thermal level = %d", thermal_level);
+
+ event_handler_->ThermalEvent(thermal_level);
+}
+
+void HWEvents::HandleIdlePowerCollapse(char *data) {
+ event_handler_->IdlePowerCollapse();
+}
+
+} // namespace sdm
diff --git a/msm8909/sdm/libs/core/fb/hw_events.h b/msm8909/sdm/libs/core/fb/hw_events.h
new file mode 100644
index 00000000..b4607a87
--- /dev/null
+++ b/msm8909/sdm/libs/core/fb/hw_events.h
@@ -0,0 +1,86 @@
+/*
+* Copyright (c) 2015 - 2017, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without modification, are permitted
+* provided that the following conditions are met:
+* * Redistributions of source code must retain the above copyright notice, this list of
+* conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright notice, this list of
+* conditions and the following disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its contributors may be used to
+* endorse or promote products derived from this software without specific prior written
+* permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __HW_EVENTS_H__
+#define __HW_EVENTS_H__
+
+#include <sys/poll.h>
+#include <string>
+#include <vector>
+#include <map>
+#include <utility>
+
+#include "hw_interface.h"
+#include "hw_events_interface.h"
+
+namespace sdm {
+
+using std::vector;
+using std::map;
+
+class HWEvents : public HWEventsInterface {
+ public:
+ virtual DisplayError Init(int fb_num, HWEventHandler *event_handler,
+ const vector<HWEvent> &event_list);
+ virtual DisplayError Deinit();
+
+ private:
+ static const int kMaxStringLength = 1024;
+
+ typedef void (HWEvents::*EventParser)(char *);
+
+ struct HWEventData {
+ HWEvent event_type {};
+ EventParser event_parser {};
+ };
+
+ static void* DisplayEventThread(void *context);
+ void* DisplayEventHandler();
+ void HandleVSync(char *data);
+ void HandleBlank(char *data) { }
+ void HandleIdleTimeout(char *data);
+ void HandleThermal(char *data);
+ void HandleThreadExit(char *data) { }
+ void HandleIdlePowerCollapse(char *data);
+ void PopulateHWEventData();
+ DisplayError SetEventParser(HWEvent event_type, HWEventData *event_data);
+ pollfd InitializePollFd(HWEventData *event_data);
+
+ HWEventHandler *event_handler_ = {};
+ vector<HWEvent> event_list_ = {};
+ vector<HWEventData> event_data_list_ = {};
+ vector<pollfd> poll_fds_ = {};
+ map<HWEvent, const char *> map_event_to_node_ = {};
+ pthread_t event_thread_ = {};
+ std::string event_thread_name_ = "SDM_EventThread";
+ bool exit_threads_ = false;
+ const char* fb_path_ = "/sys/devices/virtual/graphics/fb";
+ int fb_num_ = -1;
+ int exit_fd_ = -1;
+};
+
+} // namespace sdm
+
+#endif // __HW_EVENTS_H__
+
diff --git a/msm8909/sdm/libs/core/fb/hw_hdmi.cpp b/msm8909/sdm/libs/core/fb/hw_hdmi.cpp
new file mode 100644
index 00000000..15b47da0
--- /dev/null
+++ b/msm8909/sdm/libs/core/fb/hw_hdmi.cpp
@@ -0,0 +1,1129 @@
+/*
+* Copyright (c) 2015 - 2017, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <linux/videodev2.h>
+#include <utils/debug.h>
+#include <utils/sys.h>
+#include <utils/formats.h>
+
+#include <vector>
+#include <map>
+#include <utility>
+
+#include "hw_hdmi.h"
+
+#define __CLASS__ "HWHDMI"
+
+#define MIN_HDR_RESET_WAITTIME_SEC 2
+
+namespace sdm {
+
+#ifdef MDP_HDR_STREAM
+static int32_t GetEOTF(const GammaTransfer &transfer) {
+ int32_t mdp_transfer = -1;
+
+ switch (transfer) {
+ case Transfer_SMPTE_ST2084:
+ mdp_transfer = MDP_HDR_EOTF_SMTPE_ST2084;
+ break;
+ case Transfer_HLG:
+ mdp_transfer = MDP_HDR_EOTF_HLG;
+ break;
+ default:
+ DLOGW("Unknown Transfer: %d", transfer);
+ }
+
+ return mdp_transfer;
+}
+
+static int32_t GetColoriMetry(const LayerBuffer & layer_buffer) {
+ bool is_yuv = layer_buffer.flags.video;
+ int32_t colorimetry = -1;
+
+ if (is_yuv) {
+ switch (layer_buffer.color_metadata.colorPrimaries) {
+ case ColorPrimaries_BT601_6_525:
+ case ColorPrimaries_BT601_6_625:
+ colorimetry = MDP_COLORIMETRY_YCBCR_ITU_R_BT_601;
+ break;
+ case ColorPrimaries_BT709_5:
+ colorimetry = MDP_COLORIMETRY_YCBCR_ITU_R_BT_709;
+ break;
+ case ColorPrimaries_BT2020:
+ colorimetry = MDP_COLORIMETRY_YCBCR_ITU_R_BT_2020_YCBCR;
+ break;
+ default:
+ DLOGW("Unknown color primary = %d for YUV", layer_buffer.color_metadata.colorPrimaries);
+ }
+ }
+
+ return colorimetry;
+}
+
+static int32_t GetPixelEncoding(const LayerBuffer &layer_buffer) {
+ bool is_yuv = layer_buffer.flags.video;
+ int32_t mdp_pixel_encoding = -1;
+ mdp_pixel_encoding = MDP_PIXEL_ENCODING_RGB; // set RGB as default
+
+ if (is_yuv) {
+ switch (layer_buffer.format) {
+ case kFormatYCbCr420SemiPlanarVenus:
+ case kFormatYCbCr420SPVenusUbwc:
+ case kFormatYCbCr420Planar:
+ case kFormatYCrCb420Planar:
+ case kFormatYCrCb420PlanarStride16:
+ case kFormatYCbCr420SemiPlanar:
+ case kFormatYCrCb420SemiPlanar:
+ case kFormatYCbCr420P010:
+ case kFormatYCbCr420TP10Ubwc:
+ mdp_pixel_encoding = MDP_PIXEL_ENCODING_YCBCR_420;
+ break;
+ case kFormatYCbCr422H2V1Packed:
+ case kFormatYCrCb422H2V1SemiPlanar:
+ case kFormatYCrCb422H1V2SemiPlanar:
+ case kFormatYCbCr422H2V1SemiPlanar:
+ case kFormatYCbCr422H1V2SemiPlanar:
+ mdp_pixel_encoding = MDP_PIXEL_ENCODING_YCBCR_422;
+ break;
+ default: // other yuv formats
+ DLOGW("New YUV format = %d, need to add support", layer_buffer.format);
+ break;
+ }
+ }
+
+ return mdp_pixel_encoding;
+}
+static int32_t GetBitsPerComponent(const LayerBuffer &layer_buffer) {
+ bool is_yuv = layer_buffer.flags.video;
+ bool is_10_bit = Is10BitFormat(layer_buffer.format);
+ int32_t mdp_bpc = -1;
+
+ if (is_yuv) {
+ mdp_bpc = is_10_bit ? MDP_YUV_10_BPC : MDP_YUV_8_BPC;
+ } else {
+ mdp_bpc = is_10_bit ? MDP_RGB_10_BPC : MDP_RGB_8_BPC;
+ }
+
+ return mdp_bpc;
+}
+
+static uint32_t GetRange(const ColorRange &range) {
+ return ((range == Range_Full) ? MDP_DYNAMIC_RANGE_VESA : MDP_DYNAMIC_RANGE_CEA);
+}
+
+static uint32_t GetContentType(const LayerBuffer &layer_buffer) {
+ return (layer_buffer.flags.video ? MDP_CONTENT_TYPE_VIDEO : MDP_CONTENT_TYPE_GRAPHICS);
+}
+#endif
+
+static bool MapHDMIDisplayTiming(const msm_hdmi_mode_timing_info *mode,
+ fb_var_screeninfo *info) {
+ if (!mode || !info) {
+ return false;
+ }
+
+ info->reserved[0] = 0;
+ info->reserved[1] = 0;
+ info->reserved[2] = 0;
+ info->reserved[3] = (info->reserved[3] & 0xFFFF) | (mode->video_format << 16);
+ info->xoffset = 0;
+ info->yoffset = 0;
+ info->xres = mode->active_h;
+ info->yres = mode->active_v;
+ info->pixclock = (mode->pixel_freq) * 1000;
+ info->vmode = mode->interlaced ? FB_VMODE_INTERLACED : FB_VMODE_NONINTERLACED;
+ info->right_margin = mode->front_porch_h;
+ info->hsync_len = mode->pulse_width_h;
+ info->left_margin = mode->back_porch_h;
+ info->lower_margin = mode->front_porch_v;
+ info->vsync_len = mode->pulse_width_v;
+ info->upper_margin = mode->back_porch_v;
+
+ info->grayscale = V4L2_PIX_FMT_RGB24;
+ // If the mode supports YUV420 set grayscale to the FOURCC value for YUV420.
+ std::bitset<32> pixel_formats = mode->pixel_formats;
+ if (pixel_formats[1]) {
+ info->grayscale = V4L2_PIX_FMT_NV12;
+ }
+
+ if (!mode->active_low_h) {
+ info->sync |= (uint32_t)FB_SYNC_HOR_HIGH_ACT;
+ } else {
+ info->sync &= (uint32_t)~FB_SYNC_HOR_HIGH_ACT;
+ }
+
+ if (!mode->active_low_v) {
+ info->sync |= (uint32_t)FB_SYNC_VERT_HIGH_ACT;
+ } else {
+ info->sync &= (uint32_t)~FB_SYNC_VERT_HIGH_ACT;
+ }
+
+ return true;
+}
+
+HWHDMI::HWHDMI(BufferSyncHandler *buffer_sync_handler, HWInfoInterface *hw_info_intf)
+ : HWDevice(buffer_sync_handler), hw_scan_info_(), active_config_index_(0) {
+ HWDevice::device_type_ = kDeviceHDMI;
+ HWDevice::device_name_ = "HDMI Display Device";
+ HWDevice::hw_info_intf_ = hw_info_intf;
+ (void)hdr_reset_start_;
+ (void)hdr_reset_end_;
+ (void)reset_hdr_flag_;
+ (void)cdm_color_space_;
+}
+
+DisplayError HWHDMI::Init() {
+ DisplayError error = kErrorNone;
+
+ SetSourceProductInformation("vendor_name", "ro.product.manufacturer");
+ SetSourceProductInformation("product_description", "ro.product.name");
+
+ error = HWDevice::Init();
+ if (error != kErrorNone) {
+ return error;
+ }
+
+ mdp_dest_scalar_data_.resize(hw_resource_.hw_dest_scalar_info.count);
+
+ error = ReadEDIDInfo();
+ if (error != kErrorNone) {
+ Deinit();
+ return error;
+ }
+
+ if (!IsResolutionFilePresent()) {
+ Deinit();
+ return kErrorHardware;
+ }
+
+ error = ReadTimingInfo();
+ if (error != kErrorNone) {
+ Deinit();
+ return error;
+ }
+
+ ReadScanInfo();
+
+ GetPanelS3DMode();
+
+ s3d_mode_sdm_to_mdp_.insert(std::pair<HWS3DMode, msm_hdmi_s3d_mode>
+ (kS3DModeNone, HDMI_S3D_NONE));
+ s3d_mode_sdm_to_mdp_.insert(std::pair<HWS3DMode, msm_hdmi_s3d_mode>
+ (kS3DModeLR, HDMI_S3D_SIDE_BY_SIDE));
+ s3d_mode_sdm_to_mdp_.insert(std::pair<HWS3DMode, msm_hdmi_s3d_mode>
+ (kS3DModeRL, HDMI_S3D_SIDE_BY_SIDE));
+ s3d_mode_sdm_to_mdp_.insert(std::pair<HWS3DMode, msm_hdmi_s3d_mode>
+ (kS3DModeTB, HDMI_S3D_TOP_AND_BOTTOM));
+ s3d_mode_sdm_to_mdp_.insert(std::pair<HWS3DMode, msm_hdmi_s3d_mode>
+ (kS3DModeFP, HDMI_S3D_FRAME_PACKING));
+
+ return error;
+}
+
+DisplayError HWHDMI::GetNumDisplayAttributes(uint32_t *count) {
+ *count = UINT32(hdmi_modes_.size());
+ if (*count <= 0) {
+ return kErrorHardware;
+ }
+
+ return kErrorNone;
+}
+
+DisplayError HWHDMI::GetActiveConfig(uint32_t *active_config_index) {
+ *active_config_index = active_config_index_;
+ return kErrorNone;
+}
+
+DisplayError HWHDMI::ReadEDIDInfo() {
+ ssize_t length = -1;
+ char edid_str[kPageSize] = {'\0'};
+ char edid_path[kMaxStringLength] = {'\0'};
+ snprintf(edid_path, sizeof(edid_path), "%s%d/edid_modes", fb_path_, fb_node_index_);
+ int edid_file = Sys::open_(edid_path, O_RDONLY);
+ if (edid_file < 0) {
+ DLOGE("EDID file open failed.");
+ return kErrorHardware;
+ }
+
+ length = Sys::pread_(edid_file, edid_str, sizeof(edid_str)-1, 0);
+ if (length <= 0) {
+ DLOGE("%s: edid_modes file empty");
+ return kErrorHardware;
+ }
+ Sys::close_(edid_file);
+
+ DLOGI("EDID mode string: %s", edid_str);
+ while (length > 1 && isspace(edid_str[length-1])) {
+ --length;
+ }
+ edid_str[length] = '\0';
+
+ if (length > 0) {
+ // Get EDID modes from the EDID string
+ char *ptr = edid_str;
+ const uint32_t edid_count_max = 128;
+ char *tokens[edid_count_max] = { NULL };
+ uint32_t hdmi_mode_count = 0;
+
+ ParseLine(ptr, tokens, edid_count_max, &hdmi_mode_count);
+
+ supported_video_modes_.resize(hdmi_mode_count);
+
+ hdmi_modes_.resize(hdmi_mode_count);
+ for (uint32_t i = 0; i < hdmi_mode_count; i++) {
+ hdmi_modes_[i] = UINT32(atoi(tokens[i]));
+ }
+ }
+
+ return kErrorNone;
+}
+
+DisplayError HWHDMI::GetDisplayAttributes(uint32_t index,
+ HWDisplayAttributes *display_attributes) {
+ DTRACE_SCOPED();
+
+ if (index >= hdmi_modes_.size()) {
+ return kErrorNotSupported;
+ }
+
+ // Get the resolution info from the look up table
+ msm_hdmi_mode_timing_info *timing_mode = &supported_video_modes_[0];
+ for (uint32_t i = 0; i < hdmi_modes_.size(); i++) {
+ msm_hdmi_mode_timing_info *cur = &supported_video_modes_[i];
+ if (cur->video_format == hdmi_modes_[index]) {
+ timing_mode = cur;
+ break;
+ }
+ }
+ display_attributes->x_pixels = timing_mode->active_h;
+ display_attributes->y_pixels = timing_mode->active_v;
+ display_attributes->v_front_porch = timing_mode->front_porch_v;
+ display_attributes->v_back_porch = timing_mode->back_porch_v;
+ display_attributes->v_pulse_width = timing_mode->pulse_width_v;
+ uint32_t h_blanking = timing_mode->front_porch_h + timing_mode->back_porch_h +
+ timing_mode->pulse_width_h;
+ display_attributes->h_total = timing_mode->active_h + h_blanking;
+ display_attributes->x_dpi = 0;
+ display_attributes->y_dpi = 0;
+ display_attributes->fps = timing_mode->refresh_rate / 1000;
+ display_attributes->vsync_period_ns = UINT32(1000000000L / display_attributes->fps);
+ display_attributes->is_device_split = false;
+ if (display_attributes->x_pixels > hw_resource_.max_mixer_width) {
+ display_attributes->is_device_split = true;
+ display_attributes->h_total += h_blanking;
+ }
+
+ GetDisplayS3DSupport(index, display_attributes);
+ std::bitset<32> pixel_formats = timing_mode->pixel_formats;
+
+ display_attributes->is_yuv = pixel_formats[1];
+
+ return kErrorNone;
+}
+
+DisplayError HWHDMI::SetDisplayAttributes(uint32_t index) {
+ DTRACE_SCOPED();
+
+ if (index > hdmi_modes_.size()) {
+ return kErrorNotSupported;
+ }
+
+ // Variable screen info
+ fb_var_screeninfo vscreeninfo = {};
+ if (Sys::ioctl_(device_fd_, FBIOGET_VSCREENINFO, &vscreeninfo) < 0) {
+ IOCTL_LOGE(FBIOGET_VSCREENINFO, device_type_);
+ return kErrorHardware;
+ }
+
+ DLOGI("GetInfo<Mode=%d %dx%d (%d,%d,%d),(%d,%d,%d) %dMHz>", vscreeninfo.reserved[3],
+ vscreeninfo.xres, vscreeninfo.yres, vscreeninfo.right_margin, vscreeninfo.hsync_len,
+ vscreeninfo.left_margin, vscreeninfo.lower_margin, vscreeninfo.vsync_len,
+ vscreeninfo.upper_margin, vscreeninfo.pixclock/1000000);
+
+ msm_hdmi_mode_timing_info *timing_mode = &supported_video_modes_[0];
+ for (uint32_t i = 0; i < hdmi_modes_.size(); i++) {
+ msm_hdmi_mode_timing_info *cur = &supported_video_modes_[i];
+ if (cur->video_format == hdmi_modes_[index]) {
+ timing_mode = cur;
+ break;
+ }
+ }
+
+ if (MapHDMIDisplayTiming(timing_mode, &vscreeninfo) == false) {
+ return kErrorParameters;
+ }
+
+ msmfb_metadata metadata = {};
+ metadata.op = metadata_op_vic;
+ metadata.data.video_info_code = timing_mode->video_format;
+ if (Sys::ioctl_(device_fd_, MSMFB_METADATA_SET, &metadata) < 0) {
+ IOCTL_LOGE(MSMFB_METADATA_SET, device_type_);
+ return kErrorHardware;
+ }
+
+ DLOGI("SetInfo<Mode=%d %dx%d (%d,%d,%d),(%d,%d,%d) %dMHz>", vscreeninfo.reserved[3] & 0xFF00,
+ vscreeninfo.xres, vscreeninfo.yres, vscreeninfo.right_margin, vscreeninfo.hsync_len,
+ vscreeninfo.left_margin, vscreeninfo.lower_margin, vscreeninfo.vsync_len,
+ vscreeninfo.upper_margin, vscreeninfo.pixclock/1000000);
+
+ vscreeninfo.activate = FB_ACTIVATE_NOW | FB_ACTIVATE_ALL | FB_ACTIVATE_FORCE;
+ if (Sys::ioctl_(device_fd_, FBIOPUT_VSCREENINFO, &vscreeninfo) < 0) {
+ IOCTL_LOGE(FBIOPUT_VSCREENINFO, device_type_);
+ return kErrorHardware;
+ }
+
+ active_config_index_ = index;
+
+ frame_rate_ = timing_mode->refresh_rate;
+
+ // Get the display attributes for current active config index
+ GetDisplayAttributes(active_config_index_, &display_attributes_);
+ UpdateMixerAttributes();
+
+ supported_s3d_modes_.clear();
+ supported_s3d_modes_.push_back(kS3DModeNone);
+ for (uint32_t mode = kS3DModeNone + 1; mode < kS3DModeMax; mode ++) {
+ if (display_attributes_.s3d_config[(HWS3DMode)mode]) {
+ supported_s3d_modes_.push_back((HWS3DMode)mode);
+ }
+ }
+
+ SetS3DMode(kS3DModeNone);
+
+ return kErrorNone;
+}
+
+DisplayError HWHDMI::GetConfigIndex(uint32_t mode, uint32_t *index) {
+ // Check if the mode is valid and return corresponding index
+ for (uint32_t i = 0; i < hdmi_modes_.size(); i++) {
+ if (hdmi_modes_[i] == mode) {
+ *index = i;
+ DLOGI("Index = %d for config = %d", *index, mode);
+ return kErrorNone;
+ }
+ }
+
+ DLOGE("Config = %d not supported", mode);
+ return kErrorNotSupported;
+}
+
+DisplayError HWHDMI::Validate(HWLayers *hw_layers) {
+ HWDevice::ResetDisplayParams();
+ return HWDevice::Validate(hw_layers);
+}
+
+DisplayError HWHDMI::Commit(HWLayers *hw_layers) {
+ DisplayError error = UpdateHDRMetaData(hw_layers);
+ if (error != kErrorNone) {
+ return error;
+ }
+ if (cdm_color_space_commit_) {
+#ifdef MDP_COMMIT_UPDATE_CDM_COLOR_SPACE
+ mdp_layer_commit_v1 &mdp_commit = mdp_disp_commit_.commit_v1;
+ mdp_commit.cdm_color_space = cdm_color_space_;
+ mdp_commit.flags |= MDP_COMMIT_UPDATE_CDM_COLOR_SPACE;
+#endif
+ }
+
+ error = HWDevice::Commit(hw_layers);
+ if (cdm_color_space_commit_)
+ cdm_color_space_commit_ = false;
+
+ return error;
+}
+
+DisplayError HWHDMI::GetHWScanInfo(HWScanInfo *scan_info) {
+ if (!scan_info) {
+ return kErrorParameters;
+ }
+ *scan_info = hw_scan_info_;
+ return kErrorNone;
+}
+
+DisplayError HWHDMI::GetVideoFormat(uint32_t config_index, uint32_t *video_format) {
+ if (config_index > hdmi_modes_.size()) {
+ return kErrorNotSupported;
+ }
+
+ *video_format = hdmi_modes_[config_index];
+
+ return kErrorNone;
+}
+
+DisplayError HWHDMI::GetMaxCEAFormat(uint32_t *max_cea_format) {
+ *max_cea_format = HDMI_VFRMT_END;
+
+ return kErrorNone;
+}
+
+DisplayError HWHDMI::OnMinHdcpEncryptionLevelChange(uint32_t min_enc_level) {
+ DisplayError error = kErrorNone;
+ int fd = -1;
+ char data[kMaxStringLength] = {'\0'};
+
+ snprintf(data, sizeof(data), "%s%d/hdcp2p2/min_level_change", fb_path_, fb_node_index_);
+
+ fd = Sys::open_(data, O_WRONLY);
+ if (fd < 0) {
+ DLOGW("File '%s' could not be opened.", data);
+ return kErrorHardware;
+ }
+
+ snprintf(data, sizeof(data), "%d", min_enc_level);
+
+ ssize_t err = Sys::pwrite_(fd, data, strlen(data), 0);
+ if (err <= 0) {
+ DLOGE("Write failed, Error = %s", strerror(errno));
+ error = kErrorHardware;
+ }
+
+ Sys::close_(fd);
+
+ return error;
+}
+
+HWScanSupport HWHDMI::MapHWScanSupport(uint32_t value) {
+ switch (value) {
+ // TODO(user): Read the scan type from driver defined values instead of hardcoding
+ case 0:
+ return kScanNotSupported;
+ case 1:
+ return kScanAlwaysOverscanned;
+ case 2:
+ return kScanAlwaysUnderscanned;
+ case 3:
+ return kScanBoth;
+ default:
+ return kScanNotSupported;
+ break;
+ }
+}
+
+void HWHDMI::ReadScanInfo() {
+ int scan_info_file = -1;
+ ssize_t len = -1;
+ char data[kPageSize] = {'\0'};
+
+ snprintf(data, sizeof(data), "%s%d/scan_info", fb_path_, fb_node_index_);
+ scan_info_file = Sys::open_(data, O_RDONLY);
+ if (scan_info_file < 0) {
+ DLOGW("File '%s' not found.", data);
+ return;
+ }
+
+ memset(&data[0], 0, sizeof(data));
+ len = Sys::pread_(scan_info_file, data, sizeof(data) - 1, 0);
+ if (len <= 0) {
+ Sys::close_(scan_info_file);
+ DLOGW("File %s%d/scan_info is empty.", fb_path_, fb_node_index_);
+ return;
+ }
+ data[len] = '\0';
+ Sys::close_(scan_info_file);
+
+ const uint32_t scan_info_max_count = 3;
+ uint32_t scan_info_count = 0;
+ char *tokens[scan_info_max_count] = { NULL };
+ ParseLine(data, tokens, scan_info_max_count, &scan_info_count);
+ if (scan_info_count != scan_info_max_count) {
+ DLOGW("Failed to parse scan info string %s", data);
+ return;
+ }
+
+ hw_scan_info_.pt_scan_support = MapHWScanSupport(UINT32(atoi(tokens[0])));
+ hw_scan_info_.it_scan_support = MapHWScanSupport(UINT32(atoi(tokens[1])));
+ hw_scan_info_.cea_scan_support = MapHWScanSupport(UINT32(atoi(tokens[2])));
+ DLOGI("PT %d IT %d CEA %d", hw_scan_info_.pt_scan_support, hw_scan_info_.it_scan_support,
+ hw_scan_info_.cea_scan_support);
+}
+
+int HWHDMI::OpenResolutionFile(int file_mode) {
+ char file_path[kMaxStringLength];
+ memset(file_path, 0, sizeof(file_path));
+ snprintf(file_path , sizeof(file_path), "%s%d/res_info", fb_path_, fb_node_index_);
+
+ int fd = Sys::open_(file_path, file_mode);
+
+ if (fd < 0) {
+ DLOGE("file '%s' not found : ret = %d err str: %s", file_path, fd, strerror(errno));
+ }
+
+ return fd;
+}
+
+// Method to request HDMI driver to write a new page of timing info into res_info node
+void HWHDMI::RequestNewPage(uint32_t page_number) {
+ char page_string[kPageSize];
+ int fd = OpenResolutionFile(O_WRONLY);
+ if (fd < 0) {
+ return;
+ }
+
+ snprintf(page_string, sizeof(page_string), "%d", page_number);
+
+ DLOGI_IF(kTagDriverConfig, "page=%s", page_string);
+
+ ssize_t err = Sys::pwrite_(fd, page_string, sizeof(page_string), 0);
+ if (err <= 0) {
+ DLOGE("Write to res_info failed (%s)", strerror(errno));
+ }
+
+ Sys::close_(fd);
+}
+
+// Reads the contents of res_info node into a buffer if the file is not empty
+bool HWHDMI::ReadResolutionFile(char *config_buffer) {
+ ssize_t bytes_read = 0;
+ int fd = OpenResolutionFile(O_RDONLY);
+ if (fd >= 0) {
+ bytes_read = Sys::pread_(fd, config_buffer, kPageSize, 0);
+ Sys::close_(fd);
+ }
+
+ DLOGI_IF(kTagDriverConfig, "bytes_read = %d", bytes_read);
+
+ return (bytes_read > 0);
+}
+
+// Populates the internal timing info structure with the timing info obtained
+// from the HDMI driver
+DisplayError HWHDMI::ReadTimingInfo() {
+ uint32_t config_index = 0;
+ uint32_t page_number = MSM_HDMI_INIT_RES_PAGE;
+ uint32_t size = sizeof(msm_hdmi_mode_timing_info);
+
+ while (true) {
+ char config_buffer[kPageSize] = {0};
+ msm_hdmi_mode_timing_info *info = reinterpret_cast<msm_hdmi_mode_timing_info *>(config_buffer);
+ RequestNewPage(page_number);
+
+ if (!ReadResolutionFile(config_buffer)) {
+ break;
+ }
+
+ while (info->video_format && size < kPageSize && config_index < hdmi_modes_.size()) {
+ supported_video_modes_[config_index] = *info;
+ size += sizeof(msm_hdmi_mode_timing_info);
+
+ DLOGI_IF(kTagDriverConfig, "Config=%d Mode %d: (%dx%d) @ %d, pixel formats %d",
+ config_index,
+ supported_video_modes_[config_index].video_format,
+ supported_video_modes_[config_index].active_h,
+ supported_video_modes_[config_index].active_v,
+ supported_video_modes_[config_index].refresh_rate,
+ supported_video_modes_[config_index].pixel_formats);
+
+ info++;
+ config_index++;
+ }
+
+ size = sizeof(msm_hdmi_mode_timing_info);
+ // Request HDMI driver to populate res_info with more
+ // timing information
+ page_number++;
+ }
+
+ if (page_number == MSM_HDMI_INIT_RES_PAGE || config_index == 0) {
+ DLOGE("No timing information found.");
+ return kErrorHardware;
+ }
+
+ return kErrorNone;
+}
+
+bool HWHDMI::IsResolutionFilePresent() {
+ bool is_file_present = false;
+ int fd = OpenResolutionFile(O_RDONLY);
+ if (fd >= 0) {
+ is_file_present = true;
+ Sys::close_(fd);
+ }
+
+ return is_file_present;
+}
+
+void HWHDMI::SetSourceProductInformation(const char *node, const char *name) {
+ char property_value[kMaxStringLength];
+ char sys_fs_path[kMaxStringLength];
+ int hdmi_node_index = GetFBNodeIndex(kDeviceHDMI);
+ if (hdmi_node_index < 0) {
+ return;
+ }
+
+ ssize_t length = 0;
+ bool prop_read_success = Debug::GetProperty(name, property_value);
+ if (!prop_read_success) {
+ return;
+ }
+
+ snprintf(sys_fs_path , sizeof(sys_fs_path), "%s%d/%s", fb_path_, hdmi_node_index, node);
+ length = HWDevice::SysFsWrite(sys_fs_path, property_value,
+ static_cast<ssize_t>(strlen(property_value)));
+ if (length <= 0) {
+ DLOGW("Failed to write %s = %s", node, property_value);
+ }
+}
+
+DisplayError HWHDMI::GetDisplayS3DSupport(uint32_t index,
+ HWDisplayAttributes *attrib) {
+ ssize_t length = -1;
+ char edid_s3d_str[kPageSize] = {'\0'};
+ char edid_s3d_path[kMaxStringLength] = {'\0'};
+ snprintf(edid_s3d_path, sizeof(edid_s3d_path), "%s%d/edid_3d_modes", fb_path_, fb_node_index_);
+
+ if (index > hdmi_modes_.size()) {
+ return kErrorNotSupported;
+ }
+
+ attrib->s3d_config[kS3DModeNone] = 1;
+
+ // Three level inception!
+ // The string looks like 16=SSH,4=FP:TAB:SSH,5=FP:SSH,32=FP:TAB:SSH
+ // Initialize all the pointers to NULL to avoid crash in function strtok_r()
+ char *saveptr_l1 = NULL, *saveptr_l2 = NULL, *saveptr_l3 = NULL;
+ char *l1 = NULL, *l2 = NULL, *l3 = NULL;
+
+ int edid_s3d_node = Sys::open_(edid_s3d_path, O_RDONLY);
+ if (edid_s3d_node < 0) {
+ DLOGW("%s could not be opened : %s", edid_s3d_path, strerror(errno));
+ return kErrorNotSupported;
+ }
+
+ length = Sys::pread_(edid_s3d_node, edid_s3d_str, sizeof(edid_s3d_str)-1, 0);
+ if (length <= 0) {
+ Sys::close_(edid_s3d_node);
+ return kErrorNotSupported;
+ }
+
+ l1 = strtok_r(edid_s3d_str, ",", &saveptr_l1);
+ while (l1 != NULL) {
+ l2 = strtok_r(l1, "=", &saveptr_l2);
+ if (l2 != NULL) {
+ if (hdmi_modes_[index] == (uint32_t)atoi(l2)) {
+ l3 = strtok_r(saveptr_l2, ":", &saveptr_l3);
+ while (l3 != NULL) {
+ if (strncmp("SSH", l3, strlen("SSH")) == 0) {
+ attrib->s3d_config[kS3DModeLR] = 1;
+ attrib->s3d_config[kS3DModeRL] = 1;
+ } else if (strncmp("TAB", l3, strlen("TAB")) == 0) {
+ attrib->s3d_config[kS3DModeTB] = 1;
+ } else if (strncmp("FP", l3, strlen("FP")) == 0) {
+ attrib->s3d_config[kS3DModeFP] = 1;
+ }
+ l3 = strtok_r(NULL, ":", &saveptr_l3);
+ }
+ }
+ }
+ l1 = strtok_r(NULL, ",", &saveptr_l1);
+ }
+
+ Sys::close_(edid_s3d_node);
+ return kErrorNone;
+}
+
+bool HWHDMI::IsSupportedS3DMode(HWS3DMode s3d_mode) {
+ for (uint32_t i = 0; i < supported_s3d_modes_.size(); i++) {
+ if (supported_s3d_modes_[i] == s3d_mode) {
+ return true;
+ }
+ }
+ return false;
+}
+
+DisplayError HWHDMI::SetS3DMode(HWS3DMode s3d_mode) {
+ if (!IsSupportedS3DMode(s3d_mode)) {
+ DLOGW("S3D mode is not supported s3d_mode = %d", s3d_mode);
+ return kErrorNotSupported;
+ }
+
+ std::map<HWS3DMode, msm_hdmi_s3d_mode>::iterator it = s3d_mode_sdm_to_mdp_.find(s3d_mode);
+ if (it == s3d_mode_sdm_to_mdp_.end()) {
+ return kErrorNotSupported;
+ }
+ msm_hdmi_s3d_mode s3d_mdp_mode = it->second;
+
+ if (active_mdp_s3d_mode_ == s3d_mdp_mode) {
+ // HDMI_S3D_SIDE_BY_SIDE is an mdp mapping for kS3DModeLR and kS3DModeRL s3d modes. So no need
+ // to update the s3d_mode node. hw_panel_info needs to be updated to differentiate these two s3d
+ // modes in strategy
+ hw_panel_info_.s3d_mode = s3d_mode;
+ return kErrorNone;
+ }
+
+ ssize_t length = -1;
+ char s3d_mode_path[kMaxStringLength] = {'\0'};
+ char s3d_mode_string[kMaxStringLength] = {'\0'};
+ snprintf(s3d_mode_path, sizeof(s3d_mode_path), "%s%d/s3d_mode", fb_path_, fb_node_index_);
+
+ int s3d_mode_node = Sys::open_(s3d_mode_path, O_RDWR);
+ if (s3d_mode_node < 0) {
+ DLOGW("%s could not be opened : %s", s3d_mode_path, strerror(errno));
+ return kErrorNotSupported;
+ }
+
+ snprintf(s3d_mode_string, sizeof(s3d_mode_string), "%d", s3d_mdp_mode);
+ length = Sys::pwrite_(s3d_mode_node, s3d_mode_string, sizeof(s3d_mode_string), 0);
+ if (length <= 0) {
+ DLOGW("Failed to write into s3d node: %s", strerror(errno));
+ Sys::close_(s3d_mode_node);
+ return kErrorNotSupported;
+ }
+
+ active_mdp_s3d_mode_ = s3d_mdp_mode;
+ hw_panel_info_.s3d_mode = s3d_mode;
+ Sys::close_(s3d_mode_node);
+
+ DLOGI_IF(kTagDriverConfig, "Set s3d mode %d", hw_panel_info_.s3d_mode);
+ return kErrorNone;
+}
+
+DisplayError HWHDMI::GetPanelS3DMode() {
+ ssize_t length = -1;
+ char s3d_mode_path[kMaxStringLength] = {'\0'};
+ char s3d_mode_string[kMaxStringLength] = {'\0'};
+ snprintf(s3d_mode_path, sizeof(s3d_mode_path), "%s%d/s3d_mode", fb_path_, fb_node_index_);
+ int panel_s3d_mode = 0;
+
+ int s3d_mode_node = Sys::open_(s3d_mode_path, O_RDWR);
+ if (s3d_mode_node < 0) {
+ DLOGE("%s could not be opened : %s", s3d_mode_path, strerror(errno));
+ return kErrorNotSupported;
+ }
+
+ length = Sys::pread_(s3d_mode_node, s3d_mode_string, sizeof(s3d_mode_string), 0);
+ if (length <= 0) {
+ DLOGE("Failed read s3d node: %s", strerror(errno));
+ Sys::close_(s3d_mode_node);
+ return kErrorNotSupported;
+ }
+
+ panel_s3d_mode = atoi(s3d_mode_string);
+ if (panel_s3d_mode < HDMI_S3D_NONE || panel_s3d_mode >= HDMI_S3D_MAX) {
+ Sys::close_(s3d_mode_node);
+ DLOGW("HDMI panel S3D mode is not supported panel_s3d_mode = %d", panel_s3d_mode);
+ return kErrorUndefined;
+ }
+
+ active_mdp_s3d_mode_ = static_cast<msm_hdmi_s3d_mode>(panel_s3d_mode);
+ Sys::close_(s3d_mode_node);
+
+ DLOGI_IF(kTagDriverConfig, "Get HDMI panel s3d mode %d", active_mdp_s3d_mode_);
+ return kErrorNone;
+}
+
+DisplayError HWHDMI::GetDynamicFrameRateMode(uint32_t refresh_rate, uint32_t *mode,
+ DynamicFPSData *data, uint32_t *config_index) {
+ msm_hdmi_mode_timing_info *cur = NULL;
+ msm_hdmi_mode_timing_info *dst = NULL;
+ uint32_t i = 0;
+ int pre_refresh_rate_diff = 0;
+ bool pre_unstd_mode = false;
+
+ for (i = 0; i < hdmi_modes_.size(); i++) {
+ msm_hdmi_mode_timing_info *timing_mode = &supported_video_modes_[i];
+ if (timing_mode->video_format == hdmi_modes_[active_config_index_]) {
+ cur = timing_mode;
+ break;
+ }
+ }
+
+ if (cur == NULL) {
+ DLOGE("can't find timing info for active config index(%d)", active_config_index_);
+ return kErrorUndefined;
+ }
+
+ if (cur->refresh_rate != frame_rate_) {
+ pre_unstd_mode = true;
+ }
+
+ if (i >= hdmi_modes_.size()) {
+ return kErrorNotSupported;
+ }
+
+ dst = cur;
+ pre_refresh_rate_diff = static_cast<int>(dst->refresh_rate) - static_cast<int>(refresh_rate);
+
+ for (i = 0; i < hdmi_modes_.size(); i++) {
+ msm_hdmi_mode_timing_info *timing_mode = &supported_video_modes_[i];
+ if (cur->active_h == timing_mode->active_h &&
+ cur->active_v == timing_mode->active_v &&
+ cur->pixel_formats == timing_mode->pixel_formats ) {
+ int cur_refresh_rate_diff = static_cast<int>(timing_mode->refresh_rate) -
+ static_cast<int>(refresh_rate);
+ if (abs(pre_refresh_rate_diff) > abs(cur_refresh_rate_diff)) {
+ pre_refresh_rate_diff = cur_refresh_rate_diff;
+ dst = timing_mode;
+ }
+ }
+ }
+
+ if (pre_refresh_rate_diff > kThresholdRefreshRate) {
+ return kErrorNotSupported;
+ }
+
+ GetConfigIndex(dst->video_format, config_index);
+
+ data->hor_front_porch = dst->front_porch_h;
+ data->hor_back_porch = dst->back_porch_h;
+ data->hor_pulse_width = dst->pulse_width_h;
+ data->clk_rate_hz = dst->pixel_freq;
+ data->fps = refresh_rate;
+
+ if (dst->front_porch_h != cur->front_porch_h) {
+ *mode = kModeHFP;
+ }
+
+ if (dst->refresh_rate != refresh_rate || dst->pixel_freq != cur->pixel_freq) {
+ if (*mode == kModeHFP) {
+ if (dst->refresh_rate != refresh_rate) {
+ *mode = kModeHFPCalcClock;
+ } else {
+ *mode = kModeClockHFP;
+ }
+ } else {
+ *mode = kModeClock;
+ }
+ }
+
+ if (pre_unstd_mode && (*mode == kModeHFP)) {
+ *mode = kModeClockHFP;
+ }
+
+ return kErrorNone;
+}
+
+DisplayError HWHDMI::SetRefreshRate(uint32_t refresh_rate) {
+ char mode_path[kMaxStringLength] = {0};
+ char node_path[kMaxStringLength] = {0};
+ uint32_t mode = kModeClock;
+ uint32_t config_index = 0;
+ DynamicFPSData data;
+ DisplayError error = kErrorNone;
+
+ if (refresh_rate == frame_rate_) {
+ return error;
+ }
+
+ error = GetDynamicFrameRateMode(refresh_rate, &mode, &data, &config_index);
+ if (error != kErrorNone) {
+ return error;
+ }
+
+ snprintf(mode_path, sizeof(mode_path), "%s%d/msm_fb_dfps_mode", fb_path_, fb_node_index_);
+ snprintf(node_path, sizeof(node_path), "%s%d/dynamic_fps", fb_path_, fb_node_index_);
+
+ int fd_mode = Sys::open_(mode_path, O_WRONLY);
+ if (fd_mode < 0) {
+ DLOGE("Failed to open %s with error %s", mode_path, strerror(errno));
+ return kErrorFileDescriptor;
+ }
+
+ char dfps_mode[kMaxStringLength];
+ snprintf(dfps_mode, sizeof(dfps_mode), "%d", mode);
+ DLOGI_IF(kTagDriverConfig, "Setting dfps_mode = %d", mode);
+ ssize_t len = Sys::pwrite_(fd_mode, dfps_mode, strlen(dfps_mode), 0);
+ if (len < 0) {
+ DLOGE("Failed to enable dfps mode %d with error %s", mode, strerror(errno));
+ Sys::close_(fd_mode);
+ return kErrorUndefined;
+ }
+ Sys::close_(fd_mode);
+
+ int fd_node = Sys::open_(node_path, O_WRONLY);
+ if (fd_node < 0) {
+ DLOGE("Failed to open %s with error %s", node_path, strerror(errno));
+ return kErrorFileDescriptor;
+ }
+
+ char refresh_rate_string[kMaxStringLength];
+ if (mode == kModeHFP || mode == kModeClock) {
+ snprintf(refresh_rate_string, sizeof(refresh_rate_string), "%d", data.fps);
+ DLOGI_IF(kTagDriverConfig, "Setting refresh rate = %d", data.fps);
+ } else {
+ snprintf(refresh_rate_string, sizeof(refresh_rate_string), "%d %d %d %d %d",
+ data.hor_front_porch, data.hor_back_porch, data.hor_pulse_width,
+ data.clk_rate_hz, data.fps);
+ }
+ len = Sys::pwrite_(fd_node, refresh_rate_string, strlen(refresh_rate_string), 0);
+ if (len < 0) {
+ DLOGE("Failed to write %d with error %s", refresh_rate, strerror(errno));
+ Sys::close_(fd_node);
+ return kErrorUndefined;
+ }
+ Sys::close_(fd_node);
+
+ error = ReadTimingInfo();
+ if (error != kErrorNone) {
+ return error;
+ }
+
+ GetDisplayAttributes(config_index, &display_attributes_);
+ UpdateMixerAttributes();
+
+ frame_rate_ = refresh_rate;
+ active_config_index_ = config_index;
+
+ DLOGI_IF(kTagDriverConfig, "config_index(%d) Mode(%d) frame_rate(%d)",
+ config_index,
+ mode,
+ frame_rate_);
+
+ return kErrorNone;
+}
+
+void HWHDMI::UpdateMixerAttributes() {
+ mixer_attributes_.width = display_attributes_.x_pixels;
+ mixer_attributes_.height = display_attributes_.y_pixels;
+ mixer_attributes_.split_left = display_attributes_.is_device_split ?
+ (display_attributes_.x_pixels / 2) : mixer_attributes_.width;
+}
+
+DisplayError HWHDMI::UpdateHDRMetaData(HWLayers *hw_layers) {
+ if (!hw_panel_info_.hdr_enabled) {
+ return kErrorNone;
+ }
+
+ DisplayError error = kErrorNone;
+
+#ifdef MDP_HDR_STREAM
+ const HWHDRLayerInfo &hdr_layer_info = hw_layers->info.hdr_layer_info;
+ char hdr_stream_path[kMaxStringLength] = {};
+ snprintf(hdr_stream_path, sizeof(hdr_stream_path), "%s%d/hdr_stream", fb_path_, fb_node_index_);
+
+ Layer hdr_layer = {};
+ if (hdr_layer_info.operation == HWHDRLayerInfo::kSet && hdr_layer_info.layer_index > -1) {
+ hdr_layer = *(hw_layers->info.stack->layers.at(UINT32(hdr_layer_info.layer_index)));
+ }
+
+ const LayerBuffer *layer_buffer = &hdr_layer.input_buffer;
+ const MasteringDisplay &mastering_display = layer_buffer->color_metadata.masteringDisplayInfo;
+ const ContentLightLevel &light_level = layer_buffer->color_metadata.contentLightLevel;
+ const Primaries &primaries = mastering_display.primaries;
+
+ mdp_hdr_stream_ctrl hdr_ctrl = {};
+ if (hdr_layer_info.operation == HWHDRLayerInfo::kSet) {
+ int32_t eotf = GetEOTF(layer_buffer->color_metadata.transfer);
+ hdr_ctrl.hdr_stream.eotf = (eotf < 0) ? 0 : UINT32(eotf);
+ hdr_ctrl.hdr_stream.white_point_x = primaries.whitePoint[0];
+ hdr_ctrl.hdr_stream.white_point_y = primaries.whitePoint[1];
+ hdr_ctrl.hdr_stream.display_primaries_x[0] = primaries.rgbPrimaries[0][0];
+ hdr_ctrl.hdr_stream.display_primaries_y[0] = primaries.rgbPrimaries[0][1];
+ hdr_ctrl.hdr_stream.display_primaries_x[1] = primaries.rgbPrimaries[1][0];
+ hdr_ctrl.hdr_stream.display_primaries_y[1] = primaries.rgbPrimaries[1][1];
+ hdr_ctrl.hdr_stream.display_primaries_x[2] = primaries.rgbPrimaries[2][0];
+ hdr_ctrl.hdr_stream.display_primaries_y[2] = primaries.rgbPrimaries[2][1];
+ hdr_ctrl.hdr_stream.min_luminance = mastering_display.minDisplayLuminance;
+ hdr_ctrl.hdr_stream.max_luminance = mastering_display.maxDisplayLuminance/10000;
+ hdr_ctrl.hdr_stream.max_content_light_level = light_level.maxContentLightLevel;
+ hdr_ctrl.hdr_stream.max_average_light_level = light_level.minPicAverageLightLevel;
+ hdr_ctrl.hdr_state = HDR_ENABLE;
+ reset_hdr_flag_ = false;
+#ifdef MDP_COMMIT_UPDATE_CDM_COLOR_SPACE
+ HWDevice::SetCSC(layer_buffer->color_metadata, &cdm_color_space_);
+ cdm_color_space_commit_ = true;
+#endif
+ // DP related
+ int32_t pixel_encoding = GetPixelEncoding(hdr_layer.input_buffer);
+ hdr_ctrl.hdr_stream.pixel_encoding = (pixel_encoding < 0) ? 0 : UINT32(pixel_encoding);
+ int32_t colorimetry = GetColoriMetry(hdr_layer.input_buffer);
+ hdr_ctrl.hdr_stream.colorimetry = (colorimetry < 0) ? 0 : UINT32(colorimetry);
+ hdr_ctrl.hdr_stream.range = GetRange(hdr_layer.input_buffer.color_metadata.range);
+ int32_t bits_per_component = GetBitsPerComponent(hdr_layer.input_buffer);
+ hdr_ctrl.hdr_stream.bits_per_component =
+ (bits_per_component < 0) ? 0 : UINT32(bits_per_component);
+ hdr_ctrl.hdr_stream.content_type = GetContentType(hdr_layer.input_buffer);
+
+ DLOGD_IF(kTagDriverConfig, "kSet: HDR Stream : MaxDisplayLuminance = %d\n"
+ "MinDisplayLuminance = %d MaxContentLightLevel = %d MaxAverageLightLevel = %d\n"
+ "Red_x = %d Red_y = %d Green_x = %d Green_y = %d Blue_x = %d Blue_y = %d\n"
+ "WhitePoint_x = %d WhitePoint_y = %d EOTF = %d PixelEncoding = %d Colorimetry = %d\n"
+ "Range = %d BPC = %d ContentType = %d hdr_state = %d",
+ hdr_ctrl.hdr_stream.max_luminance, hdr_ctrl.hdr_stream.min_luminance,
+ hdr_ctrl.hdr_stream.max_content_light_level, hdr_ctrl.hdr_stream.max_average_light_level,
+ hdr_ctrl.hdr_stream.display_primaries_x[0], hdr_ctrl.hdr_stream.display_primaries_y[0],
+ hdr_ctrl.hdr_stream.display_primaries_x[1], hdr_ctrl.hdr_stream.display_primaries_y[1],
+ hdr_ctrl.hdr_stream.display_primaries_x[2], hdr_ctrl.hdr_stream.display_primaries_y[2],
+ hdr_ctrl.hdr_stream.white_point_x, hdr_ctrl.hdr_stream.white_point_x,
+ hdr_ctrl.hdr_stream.eotf, hdr_ctrl.hdr_stream.pixel_encoding,
+ hdr_ctrl.hdr_stream.colorimetry, hdr_ctrl.hdr_stream.range,
+ hdr_ctrl.hdr_stream.bits_per_component, hdr_ctrl.hdr_stream.content_type,
+ hdr_ctrl.hdr_state);
+ } else if (hdr_layer_info.operation == HWHDRLayerInfo::kReset) {
+ memset(&hdr_ctrl.hdr_stream, 0, sizeof(hdr_ctrl.hdr_stream));
+ hdr_ctrl.hdr_state = HDR_RESET;
+ reset_hdr_flag_ = true;
+ hdr_reset_start_ = time(NULL);
+#ifdef MDP_COMMIT_UPDATE_CDM_COLOR_SPACE
+ cdm_color_space_ = (mdp_color_space) MDP_CSC_DEFAULT;
+ cdm_color_space_commit_ = true;
+#endif
+ DLOGD_IF(kTagDriverConfig, "kReset: HDR Stream: HDR_RESET");
+ } else if (hdr_layer_info.operation == HWHDRLayerInfo::kNoOp) {
+ if (reset_hdr_flag_) {
+ hdr_reset_end_ = time(NULL);
+
+ if ((hdr_reset_end_ - hdr_reset_start_) >= MIN_HDR_RESET_WAITTIME_SEC) {
+ reset_hdr_flag_ = false;
+ memset(&hdr_ctrl.hdr_stream, 0, sizeof(hdr_ctrl.hdr_stream));
+ hdr_ctrl.hdr_state = HDR_DISABLE;
+ DLOGD_IF(kTagDriverConfig, "kNoOp: HDR Stream: HDR_DISABLE");
+ } else {
+ return kErrorNone;
+ }
+ } else {
+ return kErrorNone;
+ }
+ }
+
+ int fd = Sys::open_(hdr_stream_path, O_WRONLY);
+ if (fd < 0) {
+ DLOGE("Failed to open %s with error %s", hdr_stream_path, strerror(errno));
+ return kErrorFileDescriptor;
+ }
+
+ const void *hdr_metadata = reinterpret_cast<const void*>(&hdr_ctrl);
+ ssize_t len = Sys::pwrite_(fd, hdr_metadata, sizeof(hdr_ctrl), 0);
+ if (len <= 0) {
+ DLOGE("Failed to write hdr_metadata");
+ error = kErrorUndefined;
+ }
+ Sys::close_(fd);
+#endif
+
+ return error;
+}
+
+} // namespace sdm
+
diff --git a/msm8909/sdm/libs/core/fb/hw_hdmi.h b/msm8909/sdm/libs/core/fb/hw_hdmi.h
new file mode 100644
index 00000000..1496a24c
--- /dev/null
+++ b/msm8909/sdm/libs/core/fb/hw_hdmi.h
@@ -0,0 +1,130 @@
+/*
+* Copyright (c) 2015 - 2017, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without modification, are permitted
+* provided that the following conditions are met:
+* * Redistributions of source code must retain the above copyright notice, this list of
+* conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright notice, this list of
+* conditions and the following disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its contributors may be used to
+* endorse or promote products derived from this software without specific prior written
+* permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __HW_HDMI_H__
+#define __HW_HDMI_H__
+
+#include <video/msm_hdmi_modes.h>
+#include <map>
+#include <vector>
+
+#include "hw_device.h"
+
+namespace sdm {
+
+using std::vector;
+
+class HWHDMI : public HWDevice {
+ public:
+ HWHDMI(BufferSyncHandler *buffer_sync_handler, HWInfoInterface *hw_info_intf);
+
+ protected:
+ enum HWFramerateUpdate {
+ // Switch framerate by switch to other standard modes though panel blank/unblank
+ kModeSuspendResume,
+ // Switch framerate by tuning pixel clock
+ kModeClock,
+ // Switch framerate by tuning vertical front porch
+ kModeVFP,
+ // Switch framerate by tuning horizontal front porch
+ kModeHFP,
+ // Switch framerate by tuning horizontal front porch and clock
+ kModeClockHFP,
+ // Switch framerate by tuning horizontal front porch and re-caculate clock
+ kModeHFPCalcClock,
+ kModeMAX
+ };
+
+ /**
+ * struct DynamicFPSData - defines dynamic fps related data
+ * @hor_front_porch: horizontal front porch
+ * @hor_back_porch: horizontal back porch
+ * @hor_pulse_width: horizontal pulse width
+ * @clk_rate_hz: panel clock rate in HZ
+ * @fps: frames per second
+ */
+ struct DynamicFPSData {
+ uint32_t hor_front_porch;
+ uint32_t hor_back_porch;
+ uint32_t hor_pulse_width;
+ uint32_t clk_rate_hz;
+ uint32_t fps;
+ };
+
+ virtual DisplayError Init();
+ virtual DisplayError GetNumDisplayAttributes(uint32_t *count);
+ // Requirement to call this only after the first config has been explicitly set by client
+ virtual DisplayError GetActiveConfig(uint32_t *active_config);
+ virtual DisplayError GetDisplayAttributes(uint32_t index,
+ HWDisplayAttributes *display_attributes);
+ virtual DisplayError GetHWScanInfo(HWScanInfo *scan_info);
+ virtual DisplayError GetVideoFormat(uint32_t config_index, uint32_t *video_format);
+ virtual DisplayError GetMaxCEAFormat(uint32_t *max_cea_format);
+ virtual DisplayError OnMinHdcpEncryptionLevelChange(uint32_t min_enc_level);
+ virtual DisplayError SetDisplayAttributes(uint32_t index);
+ virtual DisplayError GetConfigIndex(uint32_t mode, uint32_t *index);
+ virtual DisplayError Validate(HWLayers *hw_layers);
+ virtual DisplayError Commit(HWLayers *hw_layers);
+ virtual DisplayError SetS3DMode(HWS3DMode s3d_mode);
+ virtual DisplayError SetRefreshRate(uint32_t refresh_rate);
+
+ private:
+ DisplayError ReadEDIDInfo();
+ void ReadScanInfo();
+ HWScanSupport MapHWScanSupport(uint32_t value);
+ int OpenResolutionFile(int file_mode);
+ void RequestNewPage(uint32_t page_number);
+ DisplayError ReadTimingInfo();
+ bool ReadResolutionFile(char *config_buffer);
+ bool IsResolutionFilePresent();
+ void SetSourceProductInformation(const char *node, const char *name);
+ DisplayError GetDisplayS3DSupport(uint32_t index,
+ HWDisplayAttributes *attrib);
+ DisplayError GetPanelS3DMode();
+ bool IsSupportedS3DMode(HWS3DMode s3d_mode);
+ void UpdateMixerAttributes();
+ DisplayError UpdateHDRMetaData(HWLayers *hw_layers);
+
+ DisplayError GetDynamicFrameRateMode(uint32_t refresh_rate, uint32_t*mode,
+ DynamicFPSData *data, uint32_t *config_index);
+ static const int kThresholdRefreshRate = 1000;
+ vector<uint32_t> hdmi_modes_;
+ // Holds the hdmi timing information. Ex: resolution, fps etc.,
+ vector<msm_hdmi_mode_timing_info> supported_video_modes_;
+ HWScanInfo hw_scan_info_;
+ uint32_t active_config_index_;
+ std::map<HWS3DMode, msm_hdmi_s3d_mode> s3d_mode_sdm_to_mdp_;
+ vector<HWS3DMode> supported_s3d_modes_;
+ msm_hdmi_s3d_mode active_mdp_s3d_mode_ = HDMI_S3D_NONE;
+ uint32_t frame_rate_ = 0;
+ time_t hdr_reset_start_ = 0, hdr_reset_end_ = 0;
+ bool reset_hdr_flag_ = false;
+ mdp_color_space cdm_color_space_ = {};
+ bool cdm_color_space_commit_ = false;
+};
+
+} // namespace sdm
+
+#endif // __HW_HDMI_H__
+
diff --git a/msm8909/sdm/libs/core/fb/hw_info.cpp b/msm8909/sdm/libs/core/fb/hw_info.cpp
new file mode 100644
index 00000000..636acb92
--- /dev/null
+++ b/msm8909/sdm/libs/core/fb/hw_info.cpp
@@ -0,0 +1,565 @@
+/*
+* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without modification, are permitted
+* provided that the following conditions are met:
+* * Redistributions of source code must retain the above copyright notice, this list of
+* conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright notice, this list of
+* conditions and the following disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its contributors may be used to
+* endorse or promote products derived from this software without specific prior written
+* permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <utils/constants.h>
+#include <utils/debug.h>
+#include <utils/sys.h>
+#include <dlfcn.h>
+
+#include <algorithm>
+#include <iostream>
+#include <fstream>
+#include <map>
+#include <memory>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "hw_info.h"
+
+#define __CLASS__ "HWInfo"
+
+using std::vector;
+using std::map;
+using std::string;
+using std::fstream;
+using std::to_string;
+
+namespace sdm {
+
+// kDefaultFormatSupport contains the bit map of supported formats for each hw blocks.
+// For eg: if Cursor supports MDP_RGBA_8888[bit-13] and MDP_RGB_565[bit-0], then cursor pipe array
+// contains { 0x01[0-3], 0x00[4-7], 0x00[8-12], 0x01[13-16], 0x00[17-20], 0x00[21-24], 0x00[24-28] }
+const std::bitset<8> HWInfo::kDefaultFormatSupport[kHWSubBlockMax][
+ BITS_TO_BYTES(MDP_IMGTYPE_LIMIT1)] = {
+ { 0xFF, 0xF5, 0x1C, 0x1E, 0x20, 0xFF, 0x01, 0x00, 0xFE, 0x1F }, // kHWVIGPipe
+ { 0x33, 0xE0, 0x00, 0x16, 0x00, 0xBF, 0x00, 0x00, 0xFE, 0x07 }, // kHWRGBPipe
+ { 0x33, 0xE0, 0x00, 0x16, 0x00, 0xBF, 0x00, 0x00, 0xFE, 0x07 }, // kHWDMAPipe
+ { 0x12, 0x60, 0x0C, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00 }, // kHWCursorPipe
+ { 0xFF, 0xF5, 0x1C, 0x1E, 0x20, 0xFF, 0x01, 0x00, 0xFE, 0x1F }, // kHWRotatorInput
+ { 0xFF, 0xF5, 0x1C, 0x1E, 0x20, 0xFF, 0x01, 0x00, 0xFE, 0x1F }, // kHWRotatorOutput
+ { 0x3F, 0xF4, 0x10, 0x1E, 0x20, 0xFF, 0x01, 0x00, 0xAA, 0x16 }, // kHWWBIntfOutput
+};
+
+int HWInfo::ParseString(const char *input, char *tokens[], const uint32_t max_token,
+ const char *delim, uint32_t *count) {
+ char *tmp_token = NULL;
+ char *temp_ptr;
+ uint32_t index = 0;
+ if (!input) {
+ return -1;
+ }
+ tmp_token = strtok_r(const_cast<char *>(input), delim, &temp_ptr);
+ while (tmp_token && index < max_token) {
+ tokens[index++] = tmp_token;
+ tmp_token = strtok_r(NULL, delim, &temp_ptr);
+ }
+ *count = index;
+
+ return 0;
+}
+
+DisplayError HWInfo::GetDynamicBWLimits(HWResourceInfo *hw_resource) {
+ Sys::fstream fs(kBWModeBitmap, fstream::in);
+ if (!fs.is_open()) {
+ DLOGE("File '%s' not found", kBWModeBitmap);
+ return kErrorHardware;
+ }
+
+ HWDynBwLimitInfo* bw_info = &hw_resource->dyn_bw_info;
+ for (int index = 0; index < kBwModeMax; index++) {
+ bw_info->total_bw_limit[index] = UINT32(hw_resource->max_bandwidth_low);
+ bw_info->pipe_bw_limit[index] = hw_resource->max_pipe_bw;
+ }
+
+ uint32_t token_count = 0;
+ const uint32_t max_count = kBwModeMax;
+ char *tokens[max_count] = { NULL };
+ string line;
+ while (Sys::getline_(fs, line)) {
+ if (!ParseString(line.c_str(), tokens, max_count, ":, =\n", &token_count)) {
+ if (!strncmp(tokens[0], "default_pipe", strlen("default_pipe"))) {
+ bw_info->pipe_bw_limit[kBwDefault] = UINT32(atoi(tokens[1]));
+ } else if (!strncmp(tokens[0], "camera_pipe", strlen("camera_pipe"))) {
+ bw_info->pipe_bw_limit[kBwCamera] = UINT32(atoi(tokens[1]));
+ } else if (!strncmp(tokens[0], "vflip_pipe", strlen("vflip_pipe"))) {
+ bw_info->pipe_bw_limit[kBwVFlip] = UINT32(atoi(tokens[1]));
+ } else if (!strncmp(tokens[0], "hflip_pipe", strlen("hflip_pipe"))) {
+ bw_info->pipe_bw_limit[kBwHFlip] = UINT32(atoi(tokens[1]));
+ } else if (!strncmp(tokens[0], "default", strlen("default"))) {
+ bw_info->total_bw_limit[kBwDefault] = UINT32(atoi(tokens[1]));
+ } else if (!strncmp(tokens[0], "camera", strlen("camera"))) {
+ bw_info->total_bw_limit[kBwCamera] = UINT32(atoi(tokens[1]));
+ } else if (!strncmp(tokens[0], "vflip", strlen("vflip"))) {
+ bw_info->total_bw_limit[kBwVFlip] = UINT32(atoi(tokens[1]));
+ } else if (!strncmp(tokens[0], "hflip", strlen("hflip"))) {
+ bw_info->total_bw_limit[kBwHFlip] = UINT32(atoi(tokens[1]));
+ }
+ }
+ }
+
+ return kErrorNone;
+}
+
+DisplayError HWInfo::GetHWResourceInfo(HWResourceInfo *hw_resource) {
+ if (hw_resource_) {
+ *hw_resource = *hw_resource_;
+ return kErrorNone;
+ }
+ string fb_path = "/sys/devices/virtual/graphics/fb"
+ + to_string(kHWCapabilitiesNode) + "/mdp/caps";
+
+ Sys::fstream fs(fb_path, fstream::in);
+ if (!fs.is_open()) {
+ DLOGE("File '%s' not found", fb_path.c_str());
+ return kErrorHardware;
+ }
+
+ hw_resource_ = new HWResourceInfo;
+
+ InitSupportedFormatMap(hw_resource_);
+ hw_resource_->hw_version = kHWMdssVersion5;
+
+ uint32_t token_count = 0;
+ const uint32_t max_count = 256;
+ char *tokens[max_count] = { NULL };
+ string line;
+ while (Sys::getline_(fs, line)) {
+ // parse the line and update information accordingly
+ if (!ParseString(line.c_str(), tokens, max_count, ":, =\n", &token_count)) {
+ if (!strncmp(tokens[0], "mdp_version", strlen("mdp_version"))) {
+ hw_resource_->hw_version = UINT32(atoi(tokens[1])); // HW Version 3/5
+ } else if (!strncmp(tokens[0], "hw_rev", strlen("hw_rev"))) {
+ hw_resource_->hw_revision = UINT32(atoi(tokens[1])); // HW Rev, v1/v2
+ } else if (!strncmp(tokens[0], "rot_input_fmts", strlen("rot_input_fmts"))) {
+ ParseFormats(&tokens[1], (token_count - 1), kHWRotatorInput, hw_resource_);
+ } else if (!strncmp(tokens[0], "rot_output_fmts", strlen("rot_output_fmts"))) {
+ ParseFormats(&tokens[1], (token_count - 1), kHWRotatorOutput, hw_resource_);
+ } else if (!strncmp(tokens[0], "wb_output_fmts", strlen("wb_output_fmts"))) {
+ ParseFormats(&tokens[1], (token_count - 1), kHWWBIntfOutput, hw_resource_);
+ } else if (!strncmp(tokens[0], "blending_stages", strlen("blending_stages"))) {
+ hw_resource_->num_blending_stages = UINT8(atoi(tokens[1]));
+ } else if (!strncmp(tokens[0], "max_downscale_ratio", strlen("max_downscale_ratio"))) {
+ hw_resource_->max_scale_down = UINT32(atoi(tokens[1]));
+ } else if (!strncmp(tokens[0], "max_upscale_ratio", strlen("max_upscale_ratio"))) {
+ hw_resource_->max_scale_up = UINT32(atoi(tokens[1]));
+ } else if (!strncmp(tokens[0], "rot_dwnscale_max", strlen("rot_dwnscale_max"))) {
+ hw_resource_->rot_downscale_max = FLOAT(atoi(tokens[1]));
+ } else if (!strncmp(tokens[0], "max_bandwidth_low", strlen("max_bandwidth_low"))) {
+ hw_resource_->max_bandwidth_low = UINT64(atol(tokens[1]));
+ } else if (!strncmp(tokens[0], "max_bandwidth_high", strlen("max_bandwidth_high"))) {
+ hw_resource_->max_bandwidth_high = UINT64(atol(tokens[1]));
+ } else if (!strncmp(tokens[0], "max_mixer_width", strlen("max_mixer_width"))) {
+ hw_resource_->max_mixer_width = UINT32(atoi(tokens[1]));
+ } else if (!strncmp(tokens[0], "max_pipe_width", strlen("max_pipe_width"))) {
+ hw_resource_->max_pipe_width = UINT32(atoi(tokens[1]));
+ } else if (!strncmp(tokens[0], "max_cursor_size", strlen("max_cursor_size"))) {
+ hw_resource_->max_cursor_size = UINT32(atoi(tokens[1]));
+ } else if (!strncmp(tokens[0], "max_pipe_bw", strlen("max_pipe_bw"))) {
+ hw_resource_->max_pipe_bw = UINT32(atoi(tokens[1]));
+ } else if (!strncmp(tokens[0], "max_mdp_clk", strlen("max_mdp_clk"))) {
+ hw_resource_->max_sde_clk = UINT32(atoi(tokens[1]));
+ } else if (!strncmp(tokens[0], "clk_fudge_factor", strlen("clk_fudge_factor"))) {
+ hw_resource_->clk_fudge_factor = FLOAT(atoi(tokens[1])) / FLOAT(atoi(tokens[2]));
+ } else if (!strncmp(tokens[0], "fmt_mt_nv12_factor", strlen("fmt_mt_nv12_factor"))) {
+ hw_resource_->macrotile_nv12_factor = UINT32(atoi(tokens[1]));
+ } else if (!strncmp(tokens[0], "fmt_mt_factor", strlen("fmt_mt_factor"))) {
+ hw_resource_->macrotile_factor = UINT32(atoi(tokens[1]));
+ } else if (!strncmp(tokens[0], "fmt_linear_factor", strlen("fmt_linear_factor"))) {
+ hw_resource_->linear_factor = UINT32(atoi(tokens[1]));
+ } else if (!strncmp(tokens[0], "scale_factor", strlen("scale_factor"))) {
+ hw_resource_->scale_factor = UINT32(atoi(tokens[1]));
+ } else if (!strncmp(tokens[0], "xtra_ff_factor", strlen("xtra_ff_factor"))) {
+ hw_resource_->extra_fudge_factor = UINT32(atoi(tokens[1]));
+ } else if (!strncmp(tokens[0], "amortizable_threshold", strlen("amortizable_threshold"))) {
+ hw_resource_->amortizable_threshold = UINT32(atoi(tokens[1]));
+ } else if (!strncmp(tokens[0], "system_overhead_lines", strlen("system_overhead_lines"))) {
+ hw_resource_->system_overhead_lines = UINT32(atoi(tokens[1]));
+ } else if (!strncmp(tokens[0], "wb_intf_index", strlen("wb_intf_index"))) {
+ hw_resource_->writeback_index = UINT32(atoi(tokens[1]));
+ } else if (!strncmp(tokens[0], "dest_scaler_count", strlen("dest_scaler_count"))) {
+ hw_resource_->hw_dest_scalar_info.count = UINT32(atoi(tokens[1]));
+ } else if (!strncmp(tokens[0], "max_dest_scale_up", strlen("max_dest_scale_up"))) {
+ hw_resource_->hw_dest_scalar_info.max_scale_up = UINT32(atoi(tokens[1]));
+ } else if (!strncmp(tokens[0], "max_dest_scaler_input_width",
+ strlen("max_dest_scaler_input_width"))) {
+ hw_resource_->hw_dest_scalar_info.max_input_width = UINT32(atoi(tokens[1]));
+ } else if (!strncmp(tokens[0], "max_dest_scaler_output_width",
+ strlen("max_dest_scaler_output_width"))) {
+ hw_resource_->hw_dest_scalar_info.max_output_width = UINT32(atoi(tokens[1]));
+ } else if (!strncmp(tokens[0], "features", strlen("features"))) {
+ for (uint32_t i = 0; i < token_count; i++) {
+ if (!strncmp(tokens[i], "bwc", strlen("bwc"))) {
+ hw_resource_->has_bwc = true;
+ } else if (!strncmp(tokens[i], "ubwc", strlen("ubwc"))) {
+ hw_resource_->has_ubwc = true;
+ } else if (!strncmp(tokens[i], "decimation", strlen("decimation"))) {
+ hw_resource_->has_decimation = true;
+ } else if (!strncmp(tokens[i], "tile_format", strlen("tile_format"))) {
+ hw_resource_->has_macrotile = true;
+ } else if (!strncmp(tokens[i], "src_split", strlen("src_split"))) {
+ hw_resource_->is_src_split = true;
+ } else if (!strncmp(tokens[i], "non_scalar_rgb", strlen("non_scalar_rgb"))) {
+ hw_resource_->has_non_scalar_rgb = true;
+ } else if (!strncmp(tokens[i], "perf_calc", strlen("perf_calc"))) {
+ hw_resource_->perf_calc = true;
+ } else if (!strncmp(tokens[i], "dynamic_bw_limit", strlen("dynamic_bw_limit"))) {
+ hw_resource_->has_dyn_bw_support = true;
+ } else if (!strncmp(tokens[i], "separate_rotator", strlen("separate_rotator"))) {
+ hw_resource_->separate_rotator = true;
+ } else if (!strncmp(tokens[i], "qseed3", strlen("qseed3"))) {
+ hw_resource_->has_qseed3 = true;
+ } else if (!strncmp(tokens[i], "has_ppp", strlen("has_ppp"))) {
+ hw_resource_->has_ppp = true;
+ } else if (!strncmp(tokens[i], "concurrent_writeback", strlen("concurrent_writeback"))) {
+ hw_resource_->has_concurrent_writeback = true;
+ } else if (!strncmp(tokens[i], "avr", strlen("avr"))) {
+ hw_resource_->has_avr = true;
+ } else if (!strncmp(tokens[i], "hdr", strlen("hdr"))) {
+ hw_resource_->has_hdr = true;
+ }
+ }
+ } else if (!strncmp(tokens[0], "pipe_count", strlen("pipe_count"))) {
+ uint32_t pipe_count = UINT8(atoi(tokens[1]));
+ for (uint32_t i = 0; i < pipe_count; i++) {
+ Sys::getline_(fs, line);
+ if (!ParseString(line.c_str(), tokens, max_count, ": =\n", &token_count)) {
+ HWPipeCaps pipe_caps;
+ pipe_caps.type = kPipeTypeUnused;
+ for (uint32_t j = 0; j < token_count; j += 2) {
+ if (!strncmp(tokens[j], "pipe_type", strlen("pipe_type"))) {
+ if (!strncmp(tokens[j+1], "vig", strlen("vig"))) {
+ pipe_caps.type = kPipeTypeVIG;
+ hw_resource_->num_vig_pipe++;
+ } else if (!strncmp(tokens[j+1], "rgb", strlen("rgb"))) {
+ pipe_caps.type = kPipeTypeRGB;
+ hw_resource_->num_rgb_pipe++;
+ } else if (!strncmp(tokens[j+1], "dma", strlen("dma"))) {
+ pipe_caps.type = kPipeTypeDMA;
+ hw_resource_->num_dma_pipe++;
+ } else if (!strncmp(tokens[j+1], "cursor", strlen("cursor"))) {
+ pipe_caps.type = kPipeTypeCursor;
+ hw_resource_->num_cursor_pipe++;
+ }
+ } else if (!strncmp(tokens[j], "pipe_ndx", strlen("pipe_ndx"))) {
+ pipe_caps.id = UINT32(atoi(tokens[j+1]));
+ } else if (!strncmp(tokens[j], "rects", strlen("rects"))) {
+ pipe_caps.max_rects = UINT32(atoi(tokens[j+1]));
+ } else if (!strncmp(tokens[j], "fmts_supported", strlen("fmts_supported"))) {
+ char *tokens_fmt[max_count] = { NULL };
+ uint32_t token_fmt_count = 0;
+ if (!ParseString(tokens[j+1], tokens_fmt, max_count, ",\n", &token_fmt_count)) {
+ if (pipe_caps.type == kPipeTypeVIG) {
+ ParseFormats(tokens_fmt, token_fmt_count, kHWVIGPipe, hw_resource_);
+ } else if (pipe_caps.type == kPipeTypeRGB) {
+ ParseFormats(tokens_fmt, token_fmt_count, kHWRGBPipe, hw_resource_);
+ } else if (pipe_caps.type == kPipeTypeDMA) {
+ ParseFormats(tokens_fmt, token_fmt_count, kHWDMAPipe, hw_resource_);
+ } else if (pipe_caps.type == kPipeTypeCursor) {
+ ParseFormats(tokens_fmt, token_fmt_count, kHWCursorPipe, hw_resource_);
+ }
+ }
+ }
+ }
+ hw_resource_->hw_pipes.push_back(pipe_caps);
+ }
+ }
+ }
+ }
+ }
+
+ // Disable destination scalar count to 0 if extension library is not present
+ DynLib extension_lib;
+ if (!extension_lib.Open("libsdmextension.so")) {
+ hw_resource_->hw_dest_scalar_info.count = 0;
+ }
+
+ DLOGI("SDE Version = %d, SDE Revision = %x, RGB = %d, VIG = %d, DMA = %d, Cursor = %d",
+ hw_resource_->hw_version, hw_resource_->hw_revision, hw_resource_->num_rgb_pipe,
+ hw_resource_->num_vig_pipe, hw_resource_->num_dma_pipe, hw_resource_->num_cursor_pipe);
+ DLOGI("Upscale Ratio = %d, Downscale Ratio = %d, Blending Stages = %d",
+ hw_resource_->max_scale_up, hw_resource_->max_scale_down,
+ hw_resource_->num_blending_stages);
+ DLOGI("SourceSplit = %d QSEED3 = %d", hw_resource_->is_src_split, hw_resource_->has_qseed3);
+ DLOGI("BWC = %d, UBWC = %d, Decimation = %d, Tile Format = %d Concurrent Writeback = %d",
+ hw_resource_->has_bwc, hw_resource_->has_ubwc, hw_resource_->has_decimation,
+ hw_resource_->has_macrotile, hw_resource_->has_concurrent_writeback);
+ DLOGI("MaxLowBw = %" PRIu64 " , MaxHighBw = % " PRIu64 "", hw_resource_->max_bandwidth_low,
+ hw_resource_->max_bandwidth_high);
+ DLOGI("MaxPipeBw = %" PRIu64 " KBps, MaxSDEClock = % " PRIu64 " Hz, ClockFudgeFactor = %f",
+ hw_resource_->max_pipe_bw, hw_resource_->max_sde_clk, hw_resource_->clk_fudge_factor);
+ DLOGI("Prefill factors: Tiled_NV12 = %d, Tiled = %d, Linear = %d, Scale = %d, Fudge_factor = %d",
+ hw_resource_->macrotile_nv12_factor, hw_resource_->macrotile_factor,
+ hw_resource_->linear_factor, hw_resource_->scale_factor, hw_resource_->extra_fudge_factor);
+
+ // Avoid rotator for MDP3 harware.
+ if ((hw_resource_->separate_rotator || hw_resource_->num_dma_pipe) && !hw_resource_->has_ppp) {
+ GetHWRotatorInfo(hw_resource_);
+ }
+
+ // If the driver doesn't spell out the wb index, assume it to be the number of rotators,
+ // based on legacy implementation.
+ if (hw_resource_->writeback_index == kHWBlockMax) {
+ hw_resource_->writeback_index = hw_resource_->hw_rot_info.num_rotator;
+ }
+
+ if (hw_resource_->has_dyn_bw_support) {
+ DisplayError ret = GetDynamicBWLimits(hw_resource_);
+ if (ret != kErrorNone) {
+ DLOGE("Failed to read dynamic band width info");
+ return ret;
+ }
+
+ DLOGI("Has Support for multiple bw limits shown below");
+ for (int index = 0; index < kBwModeMax; index++) {
+ DLOGI("Mode-index=%d total_bw_limit=%d and pipe_bw_limit=%d",
+ index, hw_resource_->dyn_bw_info.total_bw_limit[index],
+ hw_resource_->dyn_bw_info.pipe_bw_limit[index]);
+ }
+ }
+
+ *hw_resource = *hw_resource_;
+
+ return kErrorNone;
+}
+
+DisplayError HWInfo::GetHWRotatorInfo(HWResourceInfo *hw_resource) {
+ if (GetMDSSRotatorInfo(hw_resource) != kErrorNone)
+ return GetV4L2RotatorInfo(hw_resource);
+
+ return kErrorNone;
+}
+
+DisplayError HWInfo::GetMDSSRotatorInfo(HWResourceInfo *hw_resource) {
+ Sys::fstream fs(kRotatorCapsPath, fstream::in);
+ if (!fs.is_open()) {
+ DLOGW("File '%s' not found", kRotatorCapsPath);
+ return kErrorNotSupported;
+ }
+
+ uint32_t token_count = 0;
+ const uint32_t max_count = 10;
+ char *tokens[max_count] = { NULL };
+ string line;
+
+ hw_resource->hw_rot_info.type = HWRotatorInfo::ROT_TYPE_MDSS;
+ while (Sys::getline_(fs, line)) {
+ if (!ParseString(line.c_str(), tokens, max_count, ":, =\n", &token_count)) {
+ if (!strncmp(tokens[0], "wb_count", strlen("wb_count"))) {
+ hw_resource->hw_rot_info.num_rotator = UINT8(atoi(tokens[1]));
+ hw_resource->hw_rot_info.device_path = "/dev/mdss_rotator";
+ } else if (!strncmp(tokens[0], "downscale", strlen("downscale"))) {
+ hw_resource->hw_rot_info.has_downscale = UINT8(atoi(tokens[1]));
+ }
+ }
+ }
+
+ DLOGI("MDSS Rotator: Count = %d, Downscale = %d, Min_downscale = %f",
+ hw_resource->hw_rot_info.num_rotator, hw_resource->hw_rot_info.has_downscale,
+ hw_resource->hw_rot_info.min_downscale);
+
+ return kErrorNone;
+}
+
+DisplayError HWInfo::GetV4L2RotatorInfo(HWResourceInfo *hw_resource) {
+ string v4l2_path = "/sys/class/video4linux/video";
+ const uint32_t kMaxV4L2Nodes = 64;
+ bool found = false;
+
+ for (uint32_t i = 0; (i < kMaxV4L2Nodes) && (false == found); i++) {
+ string path = v4l2_path + to_string(i) + "/name";
+ Sys::fstream fs(path, fstream::in);
+ if (!fs.is_open()) {
+ continue;
+ }
+
+ string line;
+ if (Sys::getline_(fs, line) &&
+ (!strncmp(line.c_str(), "sde_rotator", strlen("sde_rotator")))) {
+ hw_resource->hw_rot_info.device_path = string("/dev/video" + to_string(i));
+ hw_resource->hw_rot_info.num_rotator++;
+ hw_resource->hw_rot_info.type = HWRotatorInfo::ROT_TYPE_V4L2;
+ hw_resource->hw_rot_info.has_downscale = true;
+
+ string caps_path = v4l2_path + to_string(i) + "/device/caps";
+ Sys::fstream caps_fs(caps_path, fstream::in);
+
+ if (caps_fs.is_open()) {
+ uint32_t token_count = 0;
+ const uint32_t max_count = 10;
+ char *tokens[max_count] = { NULL };
+ string caps;
+ while (Sys::getline_(caps_fs, caps)) {
+ if (!ParseString(caps.c_str(), tokens, max_count, ":, =\n", &token_count)) {
+ if (!strncmp(tokens[0], "downscale_compression", strlen("downscale_compression"))) {
+ hw_resource->hw_rot_info.downscale_compression = UINT8(atoi(tokens[1]));
+ } else if (!strncmp(tokens[0], "min_downscale", strlen("min_downscale"))) {
+ hw_resource->hw_rot_info.min_downscale = FLOAT(atof(tokens[1]));
+ }
+ }
+ }
+ }
+
+ // We support only 1 rotator
+ found = true;
+ }
+ }
+
+ DLOGI("V4L2 Rotator: Count = %d, Downscale = %d, Min_downscale = %f, Downscale_compression = %d",
+ hw_resource->hw_rot_info.num_rotator, hw_resource->hw_rot_info.has_downscale,
+ hw_resource->hw_rot_info.min_downscale, hw_resource->hw_rot_info.downscale_compression);
+
+ return kErrorNone;
+}
+
+LayerBufferFormat HWInfo::GetSDMFormat(int mdp_format) {
+ switch (mdp_format) {
+ case MDP_ARGB_8888: return kFormatARGB8888;
+ case MDP_RGBA_8888: return kFormatRGBA8888;
+ case MDP_BGRA_8888: return kFormatBGRA8888;
+ case MDP_XRGB_8888: return kFormatXRGB8888;
+ case MDP_RGBX_8888: return kFormatRGBX8888;
+ case MDP_BGRX_8888: return kFormatBGRX8888;
+ case MDP_RGBA_5551: return kFormatRGBA5551;
+ case MDP_RGBA_4444: return kFormatRGBA4444;
+ case MDP_RGB_888: return kFormatRGB888;
+ case MDP_BGR_888: return kFormatBGR888;
+ case MDP_RGB_565: return kFormatRGB565;
+ case MDP_BGR_565: return kFormatBGR565;
+ case MDP_RGBA_8888_UBWC: return kFormatRGBA8888Ubwc;
+ case MDP_RGBX_8888_UBWC: return kFormatRGBX8888Ubwc;
+ case MDP_RGB_565_UBWC: return kFormatBGR565Ubwc;
+ case MDP_Y_CB_CR_H2V2: return kFormatYCbCr420Planar;
+ case MDP_Y_CR_CB_H2V2: return kFormatYCrCb420Planar;
+ case MDP_Y_CR_CB_GH2V2: return kFormatYCrCb420PlanarStride16;
+ case MDP_Y_CBCR_H2V2: return kFormatYCbCr420SemiPlanar;
+ case MDP_Y_CRCB_H2V2: return kFormatYCrCb420SemiPlanar;
+ case MDP_Y_CBCR_H2V2_VENUS: return kFormatYCbCr420SemiPlanarVenus;
+ case MDP_Y_CBCR_H1V2: return kFormatYCbCr422H1V2SemiPlanar;
+ case MDP_Y_CRCB_H1V2: return kFormatYCrCb422H1V2SemiPlanar;
+ case MDP_Y_CBCR_H2V1: return kFormatYCbCr422H2V1SemiPlanar;
+ case MDP_Y_CRCB_H2V1: return kFormatYCrCb422H2V1SemiPlanar;
+ case MDP_Y_CBCR_H2V2_UBWC: return kFormatYCbCr420SPVenusUbwc;
+ case MDP_Y_CRCB_H2V2_VENUS: return kFormatYCrCb420SemiPlanarVenus;
+ case MDP_YCBYCR_H2V1: return kFormatYCbCr422H2V1Packed;
+ case MDP_RGBA_1010102: return kFormatRGBA1010102;
+ case MDP_ARGB_2101010: return kFormatARGB2101010;
+ case MDP_RGBX_1010102: return kFormatRGBX1010102;
+ case MDP_XRGB_2101010: return kFormatXRGB2101010;
+ case MDP_BGRA_1010102: return kFormatBGRA1010102;
+ case MDP_ABGR_2101010: return kFormatABGR2101010;
+ case MDP_BGRX_1010102: return kFormatBGRX1010102;
+ case MDP_XBGR_2101010: return kFormatXBGR2101010;
+ case MDP_RGBA_1010102_UBWC: return kFormatRGBA1010102Ubwc;
+ case MDP_RGBX_1010102_UBWC: return kFormatRGBX1010102Ubwc;
+ case MDP_Y_CBCR_H2V2_P010: return kFormatYCbCr420P010;
+ case MDP_Y_CBCR_H2V2_TP10_UBWC: return kFormatYCbCr420TP10Ubwc;
+ default: return kFormatInvalid;
+ }
+}
+
+void HWInfo::InitSupportedFormatMap(HWResourceInfo *hw_resource) {
+ hw_resource->supported_formats_map.clear();
+
+ for (int sub_blk_type = INT(kHWVIGPipe); sub_blk_type < INT(kHWSubBlockMax); sub_blk_type++) {
+ PopulateSupportedFormatMap(kDefaultFormatSupport[sub_blk_type], MDP_IMGTYPE_LIMIT1,
+ (HWSubBlockType)sub_blk_type, hw_resource);
+ }
+}
+
+void HWInfo::ParseFormats(char *tokens[], uint32_t token_count, HWSubBlockType sub_blk_type,
+ HWResourceInfo *hw_resource) {
+ if (token_count > BITS_TO_BYTES(MDP_IMGTYPE_LIMIT1)) {
+ return;
+ }
+
+ std::unique_ptr<std::bitset<8>[]> format_supported(new std::bitset<8>[token_count]);
+ for (uint32_t i = 0; i < token_count; i++) {
+ format_supported[i] = UINT8(atoi(tokens[i]));
+ }
+
+ PopulateSupportedFormatMap(format_supported.get(), (token_count << 3), sub_blk_type, hw_resource);
+}
+
+void HWInfo::PopulateSupportedFormatMap(const std::bitset<8> *format_supported,
+ uint32_t format_count, HWSubBlockType sub_blk_type,
+ HWResourceInfo *hw_resource) {
+ vector <LayerBufferFormat> supported_sdm_formats;
+ for (uint32_t mdp_format = 0; mdp_format < format_count; mdp_format++) {
+ if (format_supported[mdp_format >> 3][mdp_format & 7]) {
+ LayerBufferFormat sdm_format = GetSDMFormat(INT(mdp_format));
+ if (sdm_format != kFormatInvalid) {
+ supported_sdm_formats.push_back(sdm_format);
+ }
+ }
+ }
+
+ hw_resource->supported_formats_map.erase(sub_blk_type);
+ hw_resource->supported_formats_map.insert(make_pair(sub_blk_type, supported_sdm_formats));
+}
+
+DisplayError HWInfo::GetFirstDisplayInterfaceType(HWDisplayInterfaceInfo *hw_disp_info) {
+ Sys::fstream fs("/sys/devices/virtual/graphics/fb0/msm_fb_type", fstream::in);
+ if (!fs.is_open()) {
+ return kErrorHardware;
+ }
+
+ string line;
+ if (!Sys::getline_(fs, line)) {
+ return kErrorHardware;
+ }
+
+ if (!strncmp(line.c_str(), "dtv panel", strlen("dtv panel")) ||
+ !strncmp(line.c_str(), "dp panel", strlen("dp panel"))) {
+ hw_disp_info->type = kHDMI;
+ DLOGI("First display is HDMI");
+ } else {
+ hw_disp_info->type = kPrimary;
+ DLOGI("First display is internal display");
+ }
+
+ fs.close();
+ fs.open("/sys/devices/virtual/graphics/fb0/connected", fstream::in);
+ if (!fs.is_open()) {
+ // If fb0 is for a DSI/connected panel, then connected node will not exist.
+ hw_disp_info->is_connected = true;
+ } else {
+ if (!Sys::getline_(fs, line)) {
+ return kErrorHardware;
+ }
+
+ hw_disp_info->is_connected = (!strncmp(line.c_str(), "1", strlen("1")));
+ }
+
+ return kErrorNone;
+}
+
+} // namespace sdm
+
diff --git a/msm8909/sdm/libs/core/fb/hw_info.h b/msm8909/sdm/libs/core/fb/hw_info.h
new file mode 100644
index 00000000..cbceba06
--- /dev/null
+++ b/msm8909/sdm/libs/core/fb/hw_info.h
@@ -0,0 +1,81 @@
+/*
+* Copyright (c) 2015 - 2017, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without modification, are permitted
+* provided that the following conditions are met:
+* * Redistributions of source code must retain the above copyright notice, this list of
+* conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright notice, this list of
+* conditions and the following disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its contributors may be used to
+* endorse or promote products derived from this software without specific prior written
+* permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __HW_INFO_H__
+#define __HW_INFO_H__
+
+#include <core/sdm_types.h>
+#include <core/core_interface.h>
+#include <private/hw_info_types.h>
+#include <linux/msm_mdp.h>
+#include <bitset>
+
+#include "hw_info_interface.h"
+
+#ifndef MDP_IMGTYPE_END
+#define MDP_IMGTYPE_LIMIT1 0x100
+#endif
+
+namespace sdm {
+
+class HWInfo: public HWInfoInterface {
+ public:
+ virtual ~HWInfo() { delete hw_resource_; }
+ virtual DisplayError GetHWResourceInfo(HWResourceInfo *hw_resource);
+ virtual DisplayError GetFirstDisplayInterfaceType(HWDisplayInterfaceInfo *hw_disp_info);
+
+ private:
+ virtual DisplayError GetHWRotatorInfo(HWResourceInfo *hw_resource);
+ virtual DisplayError GetMDSSRotatorInfo(HWResourceInfo *hw_resource);
+ virtual DisplayError GetV4L2RotatorInfo(HWResourceInfo *hw_resource);
+
+ // TODO(user): Read Mdss version from the driver
+ static const int kHWMdssVersion5 = 500; // MDSS_V5
+ static const int kMaxStringLength = 1024;
+ // MDP Capabilities are replicated across all frame buffer devices.
+ // However, we rely on reading the capabalities from fbO since this
+ // is guaranteed to be available.
+ static const int kHWCapabilitiesNode = 0;
+ static const std::bitset<8> kDefaultFormatSupport[kHWSubBlockMax][
+ BITS_TO_BYTES(MDP_IMGTYPE_LIMIT1)];
+ static constexpr const char *kRotatorCapsPath = "/sys/devices/virtual/rotator/mdss_rotator/caps";
+ static constexpr const char *kBWModeBitmap
+ = "/sys/devices/virtual/graphics/fb0/mdp/bw_mode_bitmap";
+
+ static int ParseString(const char *input, char *tokens[], const uint32_t max_token,
+ const char *delim, uint32_t *count);
+ DisplayError GetDynamicBWLimits(HWResourceInfo *hw_resource);
+ LayerBufferFormat GetSDMFormat(int mdp_format);
+ void InitSupportedFormatMap(HWResourceInfo *hw_resource);
+ void ParseFormats(char *tokens[], uint32_t token_count, HWSubBlockType sub_block_type,
+ HWResourceInfo *hw_resource);
+ void PopulateSupportedFormatMap(const std::bitset<8> *format_supported, uint32_t format_count,
+ HWSubBlockType sub_blk_type, HWResourceInfo *hw_resource);
+ HWResourceInfo *hw_resource_ = NULL;
+};
+
+} // namespace sdm
+
+#endif // __HW_INFO_H__
+
diff --git a/msm8909/sdm/libs/core/fb/hw_primary.cpp b/msm8909/sdm/libs/core/fb/hw_primary.cpp
new file mode 100644
index 00000000..60a658b4
--- /dev/null
+++ b/msm8909/sdm/libs/core/fb/hw_primary.cpp
@@ -0,0 +1,687 @@
+/*
+* Copyright (c) 2015 - 2017, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <pthread.h>
+#include <fcntl.h>
+#include <sys/prctl.h>
+#include <sys/ioctl.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <utils/debug.h>
+#include <utils/sys.h>
+#include <core/display_interface.h>
+#include <linux/msm_mdp_ext.h>
+#include <utils/rect.h>
+
+#include <string>
+
+#include "hw_primary.h"
+#include "hw_color_manager.h"
+
+#define __CLASS__ "HWPrimary"
+
+#ifndef MDP_COMMIT_CWB_EN
+#define MDP_COMMIT_CWB_EN 0x800
+#endif
+
+#ifndef MDP_COMMIT_CWB_DSPP
+#define MDP_COMMIT_CWB_DSPP 0x1000
+#endif
+
+#ifndef MDP_COMMIT_AVR_EN
+#define MDP_COMMIT_AVR_EN 0x08
+#endif
+
+#ifndef MDP_COMMIT_AVR_ONE_SHOT_MODE
+#define MDP_COMMIT_AVR_ONE_SHOT_MODE 0x10
+#endif
+
+#ifndef MDP_COMMIT_PARTIAL_UPDATE_DUAL_ROI
+#define MDP_COMMIT_PARTIAL_UPDATE_DUAL_ROI 0x20
+#endif
+
+namespace sdm {
+
+using std::string;
+using std::to_string;
+using std::fstream;
+
+HWPrimary::HWPrimary(BufferSyncHandler *buffer_sync_handler, HWInfoInterface *hw_info_intf)
+ : HWDevice(buffer_sync_handler) {
+ HWDevice::device_type_ = kDevicePrimary;
+ HWDevice::device_name_ = "Primary Display Device";
+ HWDevice::hw_info_intf_ = hw_info_intf;
+}
+
+DisplayError HWPrimary::Init() {
+ DisplayError error = kErrorNone;
+
+ error = HWDevice::Init();
+ if (error != kErrorNone) {
+ return error;
+ }
+
+ mdp_dest_scalar_data_.resize(hw_resource_.hw_dest_scalar_info.count);
+
+ error = PopulateDisplayAttributes();
+ if (error != kErrorNone) {
+ return error;
+ }
+
+ UpdateMixerAttributes();
+
+ // Need to enable HPD, but toggle at start when HDMI is external
+ // This helps for framework reboot or adb shell stop/start
+ EnableHotPlugDetection(0);
+ EnableHotPlugDetection(1);
+ InitializeConfigs();
+
+ avr_prop_disabled_ = Debug::IsAVRDisabled();
+
+ return error;
+}
+
+bool HWPrimary::GetCurrentModeFromSysfs(size_t *curr_x_pixels, size_t *curr_y_pixels) {
+ bool ret = false;
+ string mode_path = fb_path_ + string("0/mode");
+
+ Sys::fstream fs(mode_path, fstream::in);
+ if (!fs.is_open()) {
+ return false;
+ }
+
+ string line;
+ if (Sys::getline_(fs, line)) {
+ // String is of form "U:1600x2560p-0". Documentation/fb/modedb.txt in
+ // kernel has more info on the format.
+ size_t xpos = line.find(':');
+ size_t ypos = line.find('x');
+
+ if (xpos == string::npos || ypos == string::npos) {
+ DLOGI("Resolution switch not supported");
+ } else {
+ *curr_x_pixels = static_cast<size_t>(atoi(line.c_str() + xpos + 1));
+ *curr_y_pixels = static_cast<size_t>(atoi(line.c_str() + ypos + 1));
+ DLOGI("Current Config: %u x %u", *curr_x_pixels, *curr_y_pixels);
+ ret = true;
+ }
+ }
+
+ return ret;
+}
+
+void HWPrimary::InitializeConfigs() {
+ size_t curr_x_pixels = 0;
+ size_t curr_y_pixels = 0;
+
+ if (!GetCurrentModeFromSysfs(&curr_x_pixels, &curr_y_pixels)) {
+ return;
+ }
+
+ string modes_path = string(fb_path_) + string("0/modes");
+
+ Sys::fstream fs(modes_path, fstream::in);
+ if (!fs.is_open()) {
+ DLOGI("Unable to process modes");
+ return;
+ }
+
+ string line;
+ while (Sys::getline_(fs, line)) {
+ DisplayConfigVariableInfo config;
+ // std::getline (unlike ::getline) removes \n while driver expects it in mode, so add back
+ line += '\n';
+ size_t xpos = line.find(':');
+ size_t ypos = line.find('x');
+
+ if (xpos == string::npos || ypos == string::npos) {
+ continue;
+ }
+
+ config.x_pixels = UINT32(atoi(line.c_str() + xpos + 1));
+ config.y_pixels = UINT32(atoi(line.c_str() + ypos + 1));
+ DLOGI("Found mode %d x %d", config.x_pixels, config.y_pixels);
+ display_configs_.push_back(config);
+ display_config_strings_.push_back(string(line.c_str()));
+
+ if (curr_x_pixels == config.x_pixels && curr_y_pixels == config.y_pixels) {
+ active_config_index_ = UINT32(display_configs_.size() - 1);
+ DLOGI("Active config index %u", active_config_index_);
+ }
+ }
+}
+
+DisplayError HWPrimary::GetNumDisplayAttributes(uint32_t *count) {
+ *count = IsResolutionSwitchEnabled() ? UINT32(display_configs_.size()) : 1;
+ return kErrorNone;
+}
+
+DisplayError HWPrimary::GetActiveConfig(uint32_t *active_config_index) {
+ *active_config_index = active_config_index_;
+ return kErrorNone;
+}
+
+DisplayError HWPrimary::GetDisplayAttributes(uint32_t index,
+ HWDisplayAttributes *display_attributes) {
+ if (!display_attributes) {
+ return kErrorParameters;
+ }
+
+ if (IsResolutionSwitchEnabled() && index >= display_configs_.size()) {
+ return kErrorParameters;
+ }
+
+ *display_attributes = display_attributes_;
+ if (IsResolutionSwitchEnabled()) {
+ // Overwrite only the parent portion of object
+ display_attributes->x_pixels = display_configs_.at(index).x_pixels;
+ display_attributes->y_pixels = display_configs_.at(index).y_pixels;
+ }
+
+ return kErrorNone;
+}
+
+DisplayError HWPrimary::PopulateDisplayAttributes() {
+ DTRACE_SCOPED();
+
+ // Variable screen info
+ fb_var_screeninfo var_screeninfo = {};
+
+ if (Sys::ioctl_(device_fd_, FBIOGET_VSCREENINFO, &var_screeninfo) < 0) {
+ IOCTL_LOGE(FBIOGET_VSCREENINFO, device_type_);
+ return kErrorHardware;
+ }
+
+ // Frame rate
+ msmfb_metadata meta_data = {};
+ meta_data.op = metadata_op_frame_rate;
+ if (Sys::ioctl_(device_fd_, MSMFB_METADATA_GET, &meta_data) < 0) {
+ IOCTL_LOGE(MSMFB_METADATA_GET, device_type_);
+ return kErrorHardware;
+ }
+
+ // If driver doesn't return width/height information, default to 320 dpi
+ if (INT(var_screeninfo.width) <= 0 || INT(var_screeninfo.height) <= 0) {
+ var_screeninfo.width = UINT32(((FLOAT(var_screeninfo.xres) * 25.4f)/320.0f) + 0.5f);
+ var_screeninfo.height = UINT32(((FLOAT(var_screeninfo.yres) * 25.4f)/320.0f) + 0.5f);
+ DLOGW("Driver doesn't report panel physical width and height - defaulting to 320dpi");
+ }
+
+ display_attributes_.x_pixels = var_screeninfo.xres;
+ display_attributes_.y_pixels = var_screeninfo.yres;
+ display_attributes_.v_front_porch = var_screeninfo.lower_margin;
+ display_attributes_.v_back_porch = var_screeninfo.upper_margin;
+ display_attributes_.v_pulse_width = var_screeninfo.vsync_len;
+ uint32_t h_blanking = var_screeninfo.right_margin + var_screeninfo.left_margin +
+ var_screeninfo.hsync_len;
+ display_attributes_.h_total = var_screeninfo.xres + h_blanking;
+ display_attributes_.x_dpi =
+ (FLOAT(var_screeninfo.xres) * 25.4f) / FLOAT(var_screeninfo.width);
+ display_attributes_.y_dpi =
+ (FLOAT(var_screeninfo.yres) * 25.4f) / FLOAT(var_screeninfo.height);
+ display_attributes_.fps = meta_data.data.panel_frame_rate;
+ display_attributes_.vsync_period_ns = UINT32(1000000000L / display_attributes_.fps);
+ display_attributes_.is_device_split = (hw_panel_info_.split_info.right_split ||
+ (var_screeninfo.xres > hw_resource_.max_mixer_width));
+ display_attributes_.h_total += (display_attributes_.is_device_split ||
+ hw_panel_info_.ping_pong_split)? h_blanking : 0;
+
+ return kErrorNone;
+}
+
+DisplayError HWPrimary::SetDisplayAttributes(uint32_t index) {
+ DisplayError ret = kErrorNone;
+
+ if (!IsResolutionSwitchEnabled()) {
+ return kErrorNotSupported;
+ }
+
+ if (index >= display_configs_.size()) {
+ return kErrorParameters;
+ }
+
+ string mode_path = string(fb_path_) + string("0/mode");
+ int fd = Sys::open_(mode_path.c_str(), O_WRONLY);
+
+ if (fd < 0) {
+ DLOGE("Opening mode failed");
+ return kErrorNotSupported;
+ }
+
+ ssize_t written = Sys::pwrite_(fd, display_config_strings_.at(index).c_str(),
+ display_config_strings_.at(index).length(), 0);
+ if (written > 0) {
+ DLOGI("Successfully set config %u", index);
+ PopulateHWPanelInfo();
+ PopulateDisplayAttributes();
+ UpdateMixerAttributes();
+ active_config_index_ = index;
+ } else {
+ DLOGE("Writing config index %u failed with error: %s", index, strerror(errno));
+ ret = kErrorParameters;
+ }
+
+ Sys::close_(fd);
+
+ return ret;
+}
+
+DisplayError HWPrimary::SetRefreshRate(uint32_t refresh_rate) {
+ char node_path[kMaxStringLength] = {0};
+
+ if (hw_resource_.has_avr && !avr_prop_disabled_) {
+ return kErrorNotSupported;
+ }
+
+ snprintf(node_path, sizeof(node_path), "%s%d/dynamic_fps", fb_path_, fb_node_index_);
+
+ int fd = Sys::open_(node_path, O_WRONLY);
+ if (fd < 0) {
+ DLOGE("Failed to open %s with error %s", node_path, strerror(errno));
+ return kErrorFileDescriptor;
+ }
+
+ char refresh_rate_string[kMaxStringLength];
+ snprintf(refresh_rate_string, sizeof(refresh_rate_string), "%d", refresh_rate);
+ DLOGI_IF(kTagDriverConfig, "Setting refresh rate = %d", refresh_rate);
+ ssize_t len = Sys::pwrite_(fd, refresh_rate_string, strlen(refresh_rate_string), 0);
+ if (len < 0) {
+ DLOGE("Failed to write %d with error %s", refresh_rate, strerror(errno));
+ Sys::close_(fd);
+ return kErrorUndefined;
+ }
+ Sys::close_(fd);
+
+ DisplayError error = PopulateDisplayAttributes();
+ if (error != kErrorNone) {
+ return error;
+ }
+
+ return kErrorNone;
+}
+
+DisplayError HWPrimary::GetConfigIndex(uint32_t mode, uint32_t *index) {
+ return HWDevice::GetConfigIndex(mode, index);
+}
+
+DisplayError HWPrimary::PowerOff() {
+ if (Sys::ioctl_(device_fd_, FBIOBLANK, FB_BLANK_POWERDOWN) < 0) {
+ IOCTL_LOGE(FB_BLANK_POWERDOWN, device_type_);
+ return kErrorHardware;
+ }
+
+ auto_refresh_ = false;
+
+ return kErrorNone;
+}
+
+DisplayError HWPrimary::Doze() {
+ if (Sys::ioctl_(device_fd_, FBIOBLANK, FB_BLANK_NORMAL) < 0) {
+ IOCTL_LOGE(FB_BLANK_NORMAL, device_type_);
+ return kErrorHardware;
+ }
+
+ return kErrorNone;
+}
+
+DisplayError HWPrimary::DozeSuspend() {
+ if (Sys::ioctl_(device_fd_, FBIOBLANK, FB_BLANK_VSYNC_SUSPEND) < 0) {
+ IOCTL_LOGE(FB_BLANK_VSYNC_SUSPEND, device_type_);
+ return kErrorHardware;
+ }
+
+ return kErrorNone;
+}
+
+DisplayError HWPrimary::Validate(HWLayers *hw_layers) {
+ HWLayersInfo &hw_layer_info = hw_layers->info;
+ LayerStack *stack = hw_layer_info.stack;
+
+ HWDevice::ResetDisplayParams();
+
+ mdp_layer_commit_v1 &mdp_commit = mdp_disp_commit_.commit_v1;
+
+ LayerRect left_roi = hw_layer_info.left_frame_roi.at(0);
+ LayerRect right_roi = hw_layer_info.right_frame_roi.at(0);
+
+ mdp_commit.left_roi.x = UINT32(left_roi.left);
+ mdp_commit.left_roi.y = UINT32(left_roi.top);
+ mdp_commit.left_roi.w = UINT32(left_roi.right - left_roi.left);
+ mdp_commit.left_roi.h = UINT32(left_roi.bottom - left_roi.top);
+
+ // Update second roi information in right_roi
+ if (hw_layer_info.left_frame_roi.size() == 2) {
+ mdp_commit.flags |= MDP_COMMIT_PARTIAL_UPDATE_DUAL_ROI;
+ right_roi = hw_layer_info.left_frame_roi.at(1);
+ }
+
+ // SDM treats ROI as one full coordinate system.
+ // In case source split is disabled, However, Driver assumes Mixer to operate in
+ // different co-ordinate system.
+ if (IsValid(right_roi)) {
+ mdp_commit.right_roi.x = UINT32(right_roi.left);
+ if (!hw_resource_.is_src_split) {
+ mdp_commit.right_roi.x = UINT32(right_roi.left) - mixer_attributes_.split_left;
+ }
+ mdp_commit.right_roi.y = UINT32(right_roi.top);
+ mdp_commit.right_roi.w = UINT32(right_roi.right - right_roi.left);
+ mdp_commit.right_roi.h = UINT32(right_roi.bottom - right_roi.top);
+ }
+
+ if (stack->output_buffer && hw_resource_.has_concurrent_writeback) {
+ LayerBuffer *output_buffer = stack->output_buffer;
+ mdp_out_layer_.writeback_ndx = hw_resource_.writeback_index;
+ mdp_out_layer_.buffer.width = output_buffer->unaligned_width;
+ mdp_out_layer_.buffer.height = output_buffer->unaligned_height;
+ mdp_out_layer_.buffer.comp_ratio.denom = 1000;
+ mdp_out_layer_.buffer.comp_ratio.numer = UINT32(hw_layers->output_compression * 1000);
+ mdp_out_layer_.buffer.fence = -1;
+#ifdef OUT_LAYER_COLOR_SPACE
+ SetCSC(output_buffer->color_metadata, &mdp_out_layer_.color_space);
+#endif
+ SetFormat(output_buffer->format, &mdp_out_layer_.buffer.format);
+ mdp_commit.flags |= MDP_COMMIT_CWB_EN;
+ mdp_commit.flags |= (stack->flags.post_processed_output) ? MDP_COMMIT_CWB_DSPP : 0;
+ DLOGI_IF(kTagDriverConfig, "****************** Conc WB Output buffer Info ******************");
+ DLOGI_IF(kTagDriverConfig, "out_w %d, out_h %d, out_f %d, wb_id %d DSPP output %d",
+ mdp_out_layer_.buffer.width, mdp_out_layer_.buffer.height,
+ mdp_out_layer_.buffer.format, mdp_out_layer_.writeback_ndx,
+ stack->flags.post_processed_output);
+ DLOGI_IF(kTagDriverConfig, "****************************************************************");
+ }
+
+ if (hw_resource_.has_avr) {
+ SetAVRFlags(hw_layers->hw_avr_info, &mdp_commit.flags);
+ }
+
+ return HWDevice::Validate(hw_layers);
+}
+
+DisplayError HWPrimary::Commit(HWLayers *hw_layers) {
+ LayerBuffer *output_buffer = hw_layers->info.stack->output_buffer;
+
+ if (hw_resource_.has_concurrent_writeback && output_buffer) {
+ if (output_buffer->planes[0].fd >= 0) {
+ mdp_out_layer_.buffer.planes[0].fd = output_buffer->planes[0].fd;
+ mdp_out_layer_.buffer.planes[0].offset = output_buffer->planes[0].offset;
+ SetStride(device_type_, output_buffer->format, output_buffer->planes[0].stride,
+ &mdp_out_layer_.buffer.planes[0].stride);
+ mdp_out_layer_.buffer.plane_count = 1;
+ mdp_out_layer_.buffer.fence = -1;
+
+ DLOGI_IF(kTagDriverConfig, "****************** Conc WB Output buffer Info ****************");
+ DLOGI_IF(kTagDriverConfig, "out_fd %d, out_offset %d, out_stride %d",
+ mdp_out_layer_.buffer.planes[0].fd, mdp_out_layer_.buffer.planes[0].offset,
+ mdp_out_layer_.buffer.planes[0].stride);
+ DLOGI_IF(kTagDriverConfig, "**************************************************************");
+ } else {
+ DLOGE("Invalid output buffer fd");
+ return kErrorParameters;
+ }
+ }
+
+ DisplayError ret = HWDevice::Commit(hw_layers);
+
+ if (ret == kErrorNone && hw_resource_.has_concurrent_writeback && output_buffer) {
+ output_buffer->release_fence_fd = mdp_out_layer_.buffer.fence;
+ }
+
+ return ret;
+}
+
+void HWPrimary::SetIdleTimeoutMs(uint32_t timeout_ms) {
+ char node_path[kMaxStringLength] = {0};
+
+ DLOGI_IF(kTagDriverConfig, "Setting idle timeout to = %d ms", timeout_ms);
+
+ snprintf(node_path, sizeof(node_path), "%s%d/idle_time", fb_path_, fb_node_index_);
+
+ // Open a sysfs node to send the timeout value to driver.
+ int fd = Sys::open_(node_path, O_WRONLY);
+ if (fd < 0) {
+ DLOGE("Unable to open %s, node %s", node_path, strerror(errno));
+ return;
+ }
+
+ char timeout_string[64];
+ snprintf(timeout_string, sizeof(timeout_string), "%d", timeout_ms);
+
+ // Notify driver about the timeout value
+ ssize_t length = Sys::pwrite_(fd, timeout_string, strlen(timeout_string), 0);
+ if (length <= 0) {
+ DLOGE("Unable to write into %s, node %s", node_path, strerror(errno));
+ }
+
+ Sys::close_(fd);
+}
+
+DisplayError HWPrimary::SetVSyncState(bool enable) {
+ DTRACE_SCOPED();
+ return HWDevice::SetVSyncState(enable);
+}
+
+DisplayError HWPrimary::SetDisplayMode(const HWDisplayMode hw_display_mode) {
+ uint32_t mode = kModeDefault;
+
+ switch (hw_display_mode) {
+ case kModeVideo:
+ mode = kModeLPMVideo;
+ break;
+ case kModeCommand:
+ mode = kModeLPMCommand;
+ break;
+ default:
+ DLOGW("Failed to translate SDE display mode %d to a MSMFB_LPM_ENABLE mode",
+ hw_display_mode);
+ return kErrorParameters;
+ }
+
+ if (Sys::ioctl_(device_fd_, INT(MSMFB_LPM_ENABLE), &mode) < 0) {
+ IOCTL_LOGE(MSMFB_LPM_ENABLE, device_type_);
+ return kErrorHardware;
+ }
+
+ DLOGI("Triggering display mode change to %d on next commit.", hw_display_mode);
+ synchronous_commit_ = true;
+
+ return kErrorNone;
+}
+
+DisplayError HWPrimary::SetPanelBrightness(int level) {
+ char buffer[kMaxSysfsCommandLength] = {0};
+
+ DLOGV_IF(kTagDriverConfig, "Set brightness level to %d", level);
+ int fd = Sys::open_(kBrightnessNode, O_RDWR);
+ if (fd < 0) {
+ DLOGV_IF(kTagDriverConfig, "Failed to open node = %s, error = %s ", kBrightnessNode,
+ strerror(errno));
+ return kErrorFileDescriptor;
+ }
+
+ int32_t bytes = snprintf(buffer, kMaxSysfsCommandLength, "%d\n", level);
+ if (bytes < 0) {
+ DLOGV_IF(kTagDriverConfig, "Failed to copy new brightness level = %d", level);
+ Sys::close_(fd);
+ return kErrorUndefined;
+ }
+
+ ssize_t ret = Sys::pwrite_(fd, buffer, static_cast<size_t>(bytes), 0);
+ if (ret <= 0) {
+ DLOGV_IF(kTagDriverConfig, "Failed to write to node = %s, error = %s ", kBrightnessNode,
+ strerror(errno));
+ Sys::close_(fd);
+ return kErrorUndefined;
+ }
+ Sys::close_(fd);
+
+ return kErrorNone;
+}
+
+DisplayError HWPrimary::GetPanelBrightness(int *level) {
+ char brightness[kMaxStringLength] = {0};
+
+ if (!level) {
+ DLOGV_IF(kTagDriverConfig, "Invalid input, null pointer.");
+ return kErrorParameters;
+ }
+
+ int fd = Sys::open_(kBrightnessNode, O_RDWR);
+ if (fd < 0) {
+ DLOGV_IF(kTagDriverConfig, "Failed to open brightness node = %s, error = %s", kBrightnessNode,
+ strerror(errno));
+ return kErrorFileDescriptor;
+ }
+
+ if (Sys::pread_(fd, brightness, sizeof(brightness), 0) > 0) {
+ *level = atoi(brightness);
+ DLOGV_IF(kTagDriverConfig, "Brightness level = %d", *level);
+ }
+ Sys::close_(fd);
+
+ return kErrorNone;
+}
+
+DisplayError HWPrimary::CachePanelBrightness(int level) {
+ bl_level_update_commit = level;
+ bl_update_commit = true;
+ return kErrorNone;
+}
+
+DisplayError HWPrimary::SetAutoRefresh(bool enable) {
+ const int kWriteLength = 2;
+ char buffer[kWriteLength] = {'\0'};
+ ssize_t bytes = snprintf(buffer, kWriteLength, "%d", enable);
+
+ if (enable == auto_refresh_) {
+ return kErrorNone;
+ }
+
+ if (HWDevice::SysFsWrite(kAutoRefreshNode, buffer, bytes) <= 0) { // Returns bytes written
+ return kErrorUndefined;
+ }
+
+ auto_refresh_ = enable;
+
+ return kErrorNone;
+}
+
+DisplayError HWPrimary::GetPPFeaturesVersion(PPFeatureVersion *vers) {
+ mdp_pp_feature_version version = {};
+
+#ifdef PA_DITHER
+ uint32_t feature_id_mapping[kMaxNumPPFeatures] = { PCC, IGC, GC, GC, PA,
+ DITHER, GAMUT, PA_DITHER };
+#else
+ uint32_t feature_id_mapping[kMaxNumPPFeatures] = { PCC, IGC, GC, GC, PA, DITHER, GAMUT };
+#endif
+
+ if (hw_resource_.hw_version != kHWMdssVersion3) {
+ // Do not query kGlobalColorFeatureCsc for kHWMdssVersion5
+ for (int i(0); i < (kMaxNumPPFeatures - 1); i++) {
+ version.pp_feature = feature_id_mapping[i];
+
+ if (Sys::ioctl_(device_fd_, INT(MSMFB_MDP_PP_GET_FEATURE_VERSION), &version) < 0) {
+ IOCTL_LOGE(MSMFB_MDP_PP_GET_FEATURE_VERSION, device_type_);
+ return kErrorHardware;
+ }
+ vers->version[i] = version.version_info;
+ }
+ } else {
+ for (int i(0); i < kMaxNumPPFeatures; i++) {
+ version.pp_feature = feature_id_mapping[i];
+ vers->version[i] = mdp_pp_legacy;
+ }
+ }
+
+ return kErrorNone;
+}
+
+// It was entered with PPFeaturesConfig::locker_ being hold.
+DisplayError HWPrimary::SetPPFeatures(PPFeaturesConfig *feature_list) {
+ msmfb_mdp_pp kernel_params = {};
+ int ret = 0;
+ PPFeatureInfo *feature = NULL;
+
+ while (true) {
+ ret = feature_list->RetrieveNextFeature(&feature);
+ if (ret)
+ break;
+
+ if (feature) {
+ DLOGV_IF(kTagDriverConfig, "feature_id = %d", feature->feature_id_);
+
+ if ((feature->feature_id_ < kMaxNumPPFeatures)) {
+ HWColorManager::SetFeature[feature->feature_id_](*feature, &kernel_params);
+ if (Sys::ioctl_(device_fd_, INT(MSMFB_MDP_PP), &kernel_params) < 0) {
+ IOCTL_LOGE(MSMFB_MDP_PP, device_type_);
+
+ feature_list->Reset();
+ return kErrorHardware;
+ }
+ }
+ }
+ } // while(true)
+
+ // Once all features were consumed, then destroy all feature instance from feature_list,
+ // Then mark it as non-dirty of PPFeaturesConfig cache.
+ feature_list->Reset();
+
+ return kErrorNone;
+}
+
+DisplayError HWPrimary::SetMixerAttributes(const HWMixerAttributes &mixer_attributes) {
+ if (IsResolutionSwitchEnabled()) {
+ return kErrorNotSupported;
+ }
+
+ return HWDevice::SetMixerAttributes(mixer_attributes);
+}
+
+void HWPrimary::UpdateMixerAttributes() {
+ mixer_attributes_.width = display_attributes_.x_pixels;
+ mixer_attributes_.height = display_attributes_.y_pixels;
+ mixer_attributes_.split_left = display_attributes_.is_device_split ?
+ hw_panel_info_.split_info.left_split : mixer_attributes_.width;
+}
+
+void HWPrimary::SetAVRFlags(const HWAVRInfo &hw_avr_info, uint32_t *avr_flags) {
+ if (hw_avr_info.enable) {
+ *avr_flags |= MDP_COMMIT_AVR_EN;
+ }
+
+ if (hw_avr_info.mode == kOneShotMode) {
+ *avr_flags |= MDP_COMMIT_AVR_ONE_SHOT_MODE;
+ }
+}
+
+} // namespace sdm
+
diff --git a/msm8909/sdm/libs/core/fb/hw_primary.h b/msm8909/sdm/libs/core/fb/hw_primary.h
new file mode 100644
index 00000000..a8251456
--- /dev/null
+++ b/msm8909/sdm/libs/core/fb/hw_primary.h
@@ -0,0 +1,96 @@
+/*
+* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without modification, are permitted
+* provided that the following conditions are met:
+* * Redistributions of source code must retain the above copyright notice, this list of
+* conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright notice, this list of
+* conditions and the following disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its contributors may be used to
+* endorse or promote products derived from this software without specific prior written
+* permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __HW_PRIMARY_H__
+#define __HW_PRIMARY_H__
+
+#include <sys/poll.h>
+#include <vector>
+#include <string>
+
+#include "hw_device.h"
+
+namespace sdm {
+
+class HWPrimary : public HWDevice {
+ public:
+ HWPrimary(BufferSyncHandler *buffer_sync_handler, HWInfoInterface *hw_info_intf);
+
+ protected:
+ virtual DisplayError Init();
+ virtual DisplayError GetNumDisplayAttributes(uint32_t *count);
+ virtual DisplayError GetActiveConfig(uint32_t *active_config);
+ virtual DisplayError GetDisplayAttributes(uint32_t index,
+ HWDisplayAttributes *display_attributes);
+ virtual DisplayError SetDisplayAttributes(uint32_t index);
+ virtual DisplayError GetConfigIndex(uint32_t mode, uint32_t *index);
+ virtual DisplayError PowerOff();
+ virtual DisplayError Doze();
+ virtual DisplayError DozeSuspend();
+ virtual DisplayError Validate(HWLayers *hw_layers);
+ virtual DisplayError Commit(HWLayers *hw_layers);
+ virtual void SetIdleTimeoutMs(uint32_t timeout_ms);
+ virtual DisplayError SetVSyncState(bool enable);
+ virtual DisplayError SetDisplayMode(const HWDisplayMode hw_display_mode);
+ virtual DisplayError SetRefreshRate(uint32_t refresh_rate);
+ virtual DisplayError SetPanelBrightness(int level);
+ virtual DisplayError CachePanelBrightness(int level);
+ virtual DisplayError GetPPFeaturesVersion(PPFeatureVersion *vers);
+ virtual DisplayError SetPPFeatures(PPFeaturesConfig *feature_list);
+ virtual DisplayError GetPanelBrightness(int *level);
+ virtual DisplayError SetAutoRefresh(bool enable);
+ virtual DisplayError SetMixerAttributes(const HWMixerAttributes &mixer_attributes);
+
+ private:
+ // Panel modes for the MSMFB_LPM_ENABLE ioctl
+ enum {
+ kModeLPMVideo,
+ kModeLPMCommand,
+ };
+
+ enum {
+ kMaxSysfsCommandLength = 12,
+ };
+
+ static const int kHWMdssVersion3 = 3;
+ DisplayError PopulateDisplayAttributes();
+ void InitializeConfigs();
+ bool IsResolutionSwitchEnabled() { return !display_configs_.empty(); }
+ bool GetCurrentModeFromSysfs(size_t *curr_x_pixels, size_t *curr_y_pixels);
+ void UpdateMixerAttributes();
+ void SetAVRFlags(const HWAVRInfo &hw_avr_info, uint32_t *avr_flags);
+
+ std::vector<DisplayConfigVariableInfo> display_configs_;
+ std::vector<std::string> display_config_strings_;
+ uint32_t active_config_index_ = 0;
+ const char *kBrightnessNode = "/sys/class/leds/lcd-backlight/brightness";
+ const char *kAutoRefreshNode = "/sys/devices/virtual/graphics/fb0/msm_cmd_autorefresh_en";
+ bool auto_refresh_ = false;
+ bool avr_prop_disabled_ = false;
+};
+
+} // namespace sdm
+
+#endif // __HW_PRIMARY_H__
+
diff --git a/msm8909/sdm/libs/core/fb/hw_scale.cpp b/msm8909/sdm/libs/core/fb/hw_scale.cpp
new file mode 100644
index 00000000..02585704
--- /dev/null
+++ b/msm8909/sdm/libs/core/fb/hw_scale.cpp
@@ -0,0 +1,314 @@
+/*
+* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without modification, are permitted
+* provided that the following conditions are met:
+* * Redistributions of source code must retain the above copyright notice, this list of
+* conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright notice, this list of
+* conditions and the following disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its contributors may be used to
+* endorse or promote products derived from this software without specific prior written
+* permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <stdio.h>
+#include <utils/debug.h>
+#include "hw_scale.h"
+
+#define __CLASS__ "HWScale"
+
+namespace sdm {
+
+DisplayError HWScale::Create(HWScale **intf, bool has_qseed3) {
+ if (has_qseed3) {
+ *intf = new HWScaleV2();
+ } else {
+ *intf = new HWScaleV1();
+ }
+
+ return kErrorNone;
+}
+
+DisplayError HWScale::Destroy(HWScale *intf) {
+ delete intf;
+
+ return kErrorNone;
+}
+
+void HWScaleV1::SetHWScaleData(const HWScaleData &scale_data, uint32_t index,
+ mdp_layer_commit_v1 *mdp_commit, HWSubBlockType sub_block_type) {
+ if (!scale_data.enable.scale) {
+ return;
+ }
+
+ if (sub_block_type == kHWDestinationScalar) {
+ return;
+ }
+
+ mdp_input_layer *mdp_layer = &mdp_commit->input_layers[index];
+ mdp_layer->flags |= MDP_LAYER_ENABLE_PIXEL_EXT;
+ mdp_scale_data *mdp_scale = &scale_data_v1_.at(index);
+ mdp_scale->enable_pxl_ext = scale_data.enable.scale;
+ for (int i = 0; i < MAX_PLANES; i++) {
+ const HWPlane &plane = scale_data.plane[i];
+ mdp_scale->init_phase_x[i] = plane.init_phase_x;
+ mdp_scale->phase_step_x[i] = plane.phase_step_x;
+ mdp_scale->init_phase_y[i] = plane.init_phase_y;
+ mdp_scale->phase_step_y[i] = plane.phase_step_y;
+
+ mdp_scale->num_ext_pxls_left[i] = plane.left.extension;
+ mdp_scale->left_ftch[i] = plane.left.overfetch;
+ mdp_scale->left_rpt[i] = plane.left.repeat;
+
+ mdp_scale->num_ext_pxls_top[i] = plane.top.extension;
+ mdp_scale->top_ftch[i] = plane.top.overfetch;
+ mdp_scale->top_rpt[i] = plane.top.repeat;
+
+ mdp_scale->num_ext_pxls_right[i] = plane.right.extension;
+ mdp_scale->right_ftch[i] = plane.right.overfetch;
+ mdp_scale->right_rpt[i] = plane.right.repeat;
+
+ mdp_scale->num_ext_pxls_btm[i] = plane.bottom.extension;
+ mdp_scale->btm_ftch[i] = plane.bottom.overfetch;
+ mdp_scale->btm_rpt[i] = plane.bottom.repeat;
+
+ mdp_scale->roi_w[i] = plane.roi_width;
+ }
+
+ return;
+}
+
+void* HWScaleV1::GetScaleDataRef(uint32_t index, HWSubBlockType sub_block_type) {
+ if (sub_block_type != kHWDestinationScalar) {
+ return &scale_data_v1_.at(index);
+ }
+
+ return NULL;
+}
+
+void HWScaleV1::DumpScaleData(void *mdp_scale) {
+ if (!mdp_scale) {
+ return;
+ }
+
+ mdp_scale_data *scale = reinterpret_cast<mdp_scale_data *>(mdp_scale);
+ if (scale->enable_pxl_ext) {
+ DLOGD_IF(kTagDriverConfig, "Scale Enable = %d", scale->enable_pxl_ext);
+ for (int j = 0; j < MAX_PLANES; j++) {
+ DLOGV_IF(kTagDriverConfig, "Scale Data[%d] : Phase=[%x %x %x %x] Pixel_Ext=[%d %d %d %d]",
+ j, scale->init_phase_x[j], scale->phase_step_x[j], scale->init_phase_y[j],
+ scale->phase_step_y[j], scale->num_ext_pxls_left[j], scale->num_ext_pxls_top[j],
+ scale->num_ext_pxls_right[j], scale->num_ext_pxls_btm[j]);
+ DLOGV_IF(kTagDriverConfig, "Fetch=[%d %d %d %d] Repeat=[%d %d %d %d] roi_width = %d",
+ scale->left_ftch[j], scale->top_ftch[j], scale->right_ftch[j], scale->btm_ftch[j],
+ scale->left_rpt[j], scale->top_rpt[j], scale->right_rpt[j], scale->btm_rpt[j],
+ scale->roi_w[j]);
+ }
+ }
+
+ return;
+}
+
+void HWScaleV2::SetHWScaleData(const HWScaleData &scale_data, uint32_t index,
+ mdp_layer_commit_v1 *mdp_commit, HWSubBlockType sub_block_type) {
+ if (!scale_data.enable.scale && !scale_data.enable.direction_detection &&
+ !scale_data.enable.detail_enhance ) {
+ return;
+ }
+
+ mdp_scale_data_v2 *mdp_scale;
+ if (sub_block_type != kHWDestinationScalar) {
+ mdp_input_layer *mdp_layer = &mdp_commit->input_layers[index];
+ mdp_layer->flags |= MDP_LAYER_ENABLE_QSEED3_SCALE;
+ mdp_scale = &scale_data_v2_.at(index);
+ } else {
+ mdp_scale_data_v2 mdp_dest_scale = {0};
+
+ dest_scale_data_v2_.insert(std::make_pair(index, mdp_dest_scale));
+ mdp_scale = &dest_scale_data_v2_[index];
+ }
+
+ mdp_scale->enable = (scale_data.enable.scale ? ENABLE_SCALE : 0) |
+ (scale_data.enable.direction_detection ? ENABLE_DIRECTION_DETECTION : 0) |
+ (scale_data.enable.detail_enhance ? ENABLE_DETAIL_ENHANCE : 0);
+
+ if (sub_block_type == kHWDestinationScalar) {
+ mdp_destination_scaler_data *mdp_dest_scalar =
+ reinterpret_cast<mdp_destination_scaler_data *>(mdp_commit->dest_scaler);
+
+ mdp_dest_scalar[index].flags = mdp_scale->enable ? MDP_DESTSCALER_ENABLE : 0;
+
+ if (scale_data.enable.detail_enhance) {
+ mdp_dest_scalar[index].flags |= MDP_DESTSCALER_ENHANCER_UPDATE;
+ }
+ }
+
+ for (int i = 0; i < MAX_PLANES; i++) {
+ const HWPlane &plane = scale_data.plane[i];
+ mdp_scale->init_phase_x[i] = plane.init_phase_x;
+ mdp_scale->phase_step_x[i] = plane.phase_step_x;
+ mdp_scale->init_phase_y[i] = plane.init_phase_y;
+ mdp_scale->phase_step_y[i] = plane.phase_step_y;
+
+ mdp_scale->num_ext_pxls_left[i] = UINT32(plane.left.extension);
+ mdp_scale->left_ftch[i] = plane.left.overfetch;
+ mdp_scale->left_rpt[i] = plane.left.repeat;
+
+ mdp_scale->num_ext_pxls_top[i] = UINT32(plane.top.extension);
+ mdp_scale->top_ftch[i] = UINT32(plane.top.overfetch);
+ mdp_scale->top_rpt[i] = UINT32(plane.top.repeat);
+
+ mdp_scale->num_ext_pxls_right[i] = UINT32(plane.right.extension);
+ mdp_scale->right_ftch[i] = plane.right.overfetch;
+ mdp_scale->right_rpt[i] = plane.right.repeat;
+
+ mdp_scale->num_ext_pxls_btm[i] = UINT32(plane.bottom.extension);
+ mdp_scale->btm_ftch[i] = UINT32(plane.bottom.overfetch);
+ mdp_scale->btm_rpt[i] = UINT32(plane.bottom.repeat);
+
+ mdp_scale->roi_w[i] = plane.roi_width;
+
+ mdp_scale->preload_x[i] = UINT32(plane.preload_x);
+ mdp_scale->preload_y[i] = UINT32(plane.preload_y);
+
+ mdp_scale->src_width[i] = plane.src_width;
+ mdp_scale->src_height[i] = plane.src_height;
+ }
+
+ mdp_scale->dst_width = scale_data.dst_width;
+ mdp_scale->dst_height = scale_data.dst_height;
+
+ mdp_scale->y_rgb_filter_cfg = GetMDPScalingFilter(scale_data.y_rgb_filter_cfg);
+ mdp_scale->uv_filter_cfg = GetMDPScalingFilter(scale_data.uv_filter_cfg);
+ mdp_scale->alpha_filter_cfg = GetMDPAlphaInterpolation(scale_data.alpha_filter_cfg);
+ mdp_scale->blend_cfg = scale_data.blend_cfg;
+
+ mdp_scale->lut_flag = (scale_data.lut_flag.lut_swap ? SCALER_LUT_SWAP : 0) |
+ (scale_data.lut_flag.lut_dir_wr ? SCALER_LUT_DIR_WR : 0) |
+ (scale_data.lut_flag.lut_y_cir_wr ? SCALER_LUT_Y_CIR_WR : 0) |
+ (scale_data.lut_flag.lut_uv_cir_wr ? SCALER_LUT_UV_CIR_WR : 0) |
+ (scale_data.lut_flag.lut_y_sep_wr ? SCALER_LUT_Y_SEP_WR : 0) |
+ (scale_data.lut_flag.lut_uv_sep_wr ? SCALER_LUT_UV_SEP_WR : 0);
+
+ mdp_scale->dir_lut_idx = scale_data.dir_lut_idx;
+ mdp_scale->y_rgb_cir_lut_idx = scale_data.y_rgb_cir_lut_idx;
+ mdp_scale->uv_cir_lut_idx = scale_data.uv_cir_lut_idx;
+ mdp_scale->y_rgb_sep_lut_idx = scale_data.y_rgb_sep_lut_idx;
+ mdp_scale->uv_sep_lut_idx = scale_data.uv_sep_lut_idx;
+
+ if (mdp_scale->enable & ENABLE_DETAIL_ENHANCE) {
+ mdp_det_enhance_data *mdp_det_enhance = &mdp_scale->detail_enhance;
+ mdp_det_enhance->enable = scale_data.detail_enhance.enable;
+ mdp_det_enhance->sharpen_level1 = scale_data.detail_enhance.sharpen_level1;
+ mdp_det_enhance->sharpen_level2 = scale_data.detail_enhance.sharpen_level2;
+ mdp_det_enhance->clip = scale_data.detail_enhance.clip;
+ mdp_det_enhance->limit = scale_data.detail_enhance.limit;
+ mdp_det_enhance->thr_quiet = scale_data.detail_enhance.thr_quiet;
+ mdp_det_enhance->thr_dieout = scale_data.detail_enhance.thr_dieout;
+ mdp_det_enhance->thr_low = scale_data.detail_enhance.thr_low;
+ mdp_det_enhance->thr_high = scale_data.detail_enhance.thr_high;
+ mdp_det_enhance->prec_shift = scale_data.detail_enhance.prec_shift;
+
+ for (int i = 0; i < MAX_DET_CURVES; i++) {
+ mdp_det_enhance->adjust_a[i] = scale_data.detail_enhance.adjust_a[i];
+ mdp_det_enhance->adjust_b[i] = scale_data.detail_enhance.adjust_b[i];
+ mdp_det_enhance->adjust_c[i] = scale_data.detail_enhance.adjust_c[i];
+ }
+ }
+
+ return;
+}
+
+void* HWScaleV2::GetScaleDataRef(uint32_t index, HWSubBlockType sub_block_type) {
+ if (sub_block_type != kHWDestinationScalar) {
+ return &scale_data_v2_.at(index);
+ } else {
+ return &dest_scale_data_v2_[index];
+ }
+}
+
+uint32_t HWScaleV2::GetMDPScalingFilter(ScalingFilterConfig filter_cfg) {
+ switch (filter_cfg) {
+ case kFilterEdgeDirected:
+ return FILTER_EDGE_DIRECTED_2D;
+ case kFilterCircular:
+ return FILTER_CIRCULAR_2D;
+ case kFilterSeparable:
+ return FILTER_SEPARABLE_1D;
+ case kFilterBilinear:
+ return FILTER_BILINEAR;
+ default:
+ DLOGE("Invalid Scaling Filter");
+ return kFilterMax;
+ }
+}
+
+uint32_t HWScaleV2::GetMDPAlphaInterpolation(HWAlphaInterpolation alpha_filter_cfg) {
+ switch (alpha_filter_cfg) {
+ case kInterpolationPixelRepeat:
+ return FILTER_ALPHA_DROP_REPEAT;
+ case kInterpolationBilinear:
+ return FILTER_ALPHA_BILINEAR;
+ default:
+ DLOGE("Invalid Alpha Interpolation");
+ return kInterpolationMax;
+ }
+}
+
+void HWScaleV2::DumpScaleData(void *mdp_scale) {
+ if (!mdp_scale) {
+ return;
+ }
+
+ mdp_scale_data_v2 *scale = reinterpret_cast<mdp_scale_data_v2 *>(mdp_scale);
+ if (scale->enable) {
+ DLOGD_IF(kTagDriverConfig, "Scale Enable = %d", scale->enable);
+ for (int j = 0; j < MAX_PLANES; j++) {
+ DLOGV_IF(kTagDriverConfig, "Scale Data[%d]: Phase_init[x y]=[%x %x] Phase_step:[x y]=[%x %x]",
+ j, scale->init_phase_x[j], scale->init_phase_y[j], scale->phase_step_x[j],
+ scale->phase_step_y[j]);
+ DLOGV_IF(kTagDriverConfig, "Preload[x y]=[%x %x], Pixel Ext=[%d %d] Ovfetch=[%d %d %d %d]",
+ scale->preload_x[j], scale->preload_y[j], scale->num_ext_pxls_left[j],
+ scale->num_ext_pxls_top[j], scale->left_ftch[j], scale->top_ftch[j], scale->right_ftch[j],
+ scale->btm_ftch[j]);
+ DLOGV_IF(kTagDriverConfig, "Repeat=[%d %d %d %d] Src[w x h]=[%d %d] roi_width = %d",
+ scale->left_rpt[j], scale->top_rpt[j], scale->right_rpt[j], scale->btm_rpt[j],
+ scale->src_width[j], scale->src_height[j], scale->roi_w[j]);
+ }
+
+ DLOGD_IF(kTagDriverConfig, "LUT flags = %d", scale->lut_flag);
+ DLOGV_IF(kTagDriverConfig, "y_rgb_filter=%d, uv_filter=%d, alpha_filter=%d, blend_cfg=%d",
+ scale->y_rgb_filter_cfg, scale->uv_filter_cfg, scale->alpha_filter_cfg, scale->blend_cfg);
+ DLOGV_IF(kTagDriverConfig, "dir_lut=%d, y_rgb_cir=%d, uv_cir=%d, y_rgb_sep=%d, uv_sep=%d",
+ scale->dir_lut_idx, scale->y_rgb_cir_lut_idx, scale->uv_cir_lut_idx,
+ scale->y_rgb_sep_lut_idx, scale->uv_sep_lut_idx);
+ if (scale->enable & ENABLE_DETAIL_ENHANCE) {
+ mdp_det_enhance_data *de = &scale->detail_enhance;
+ DLOGV_IF(kTagDriverConfig, "Detail Enhance: enable: %d sharpen_level1: %d sharpen_level2: %d",
+ de->enable, de->sharpen_level1, de->sharpen_level2);
+ DLOGV_IF(kTagDriverConfig, "clip: %d limit:%d thr_quiet: %d thr_dieout: %d",
+ de->clip, de->limit, de->thr_quiet, de->thr_dieout);
+ DLOGV_IF(kTagDriverConfig, "thr_low: %d thr_high: %d prec_shift: %d", de->thr_low,
+ de->thr_high, de->prec_shift);
+ for (uint32_t i = 0; i < MAX_DET_CURVES; i++) {
+ DLOGV_IF(kTagDriverConfig, "adjust_a[%d]: %d adjust_b[%d]: %d adjust_c[%d]: %d", i,
+ de->adjust_a[i], i, de->adjust_b[i], i, de->adjust_c[i]);
+ }
+ }
+ }
+
+ return;
+}
+
+} // namespace sdm
diff --git a/msm8909/sdm/libs/core/fb/hw_scale.h b/msm8909/sdm/libs/core/fb/hw_scale.h
new file mode 100644
index 00000000..7590833b
--- /dev/null
+++ b/msm8909/sdm/libs/core/fb/hw_scale.h
@@ -0,0 +1,85 @@
+/*
+* Copyright (c) 2016, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without modification, are permitted
+* provided that the following conditions are met:
+* * Redistributions of source code must retain the above copyright notice, this list of
+* conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright notice, this list of
+* conditions and the following disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its contributors may be used to
+* endorse or promote products derived from this software without specific prior written
+* permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __HW_SCALE_H__
+#define __HW_SCALE_H__
+
+#include <linux/msm_mdp_ext.h>
+#include <private/hw_info_types.h>
+
+#include <cstring>
+#include <array>
+#include <map>
+
+namespace sdm {
+
+class HWScale {
+ public:
+ static DisplayError Create(HWScale **intf, bool has_qseed3);
+ static DisplayError Destroy(HWScale *intf);
+
+ virtual void SetHWScaleData(const HWScaleData &scale, uint32_t index,
+ mdp_layer_commit_v1 *mdp_commit, HWSubBlockType sub_block_type) = 0;
+ virtual void* GetScaleDataRef(uint32_t index, HWSubBlockType sub_block_type) = 0;
+ virtual void DumpScaleData(void *mdp_scale) = 0;
+ virtual void ResetScaleParams() = 0;
+ protected:
+ virtual ~HWScale() { }
+};
+
+class HWScaleV1 : public HWScale {
+ public:
+ virtual void SetHWScaleData(const HWScaleData &scale, uint32_t index,
+ mdp_layer_commit_v1 *mdp_commit, HWSubBlockType sub_block_type);
+ virtual void* GetScaleDataRef(uint32_t index, HWSubBlockType sub_block_type);
+ virtual void DumpScaleData(void *mdp_scale);
+ virtual void ResetScaleParams() { scale_data_v1_ = {}; }
+
+ protected:
+ ~HWScaleV1() {}
+ std::array<mdp_scale_data, (kMaxSDELayers * 2)> scale_data_v1_ = {};
+};
+
+class HWScaleV2 : public HWScale {
+ public:
+ virtual void SetHWScaleData(const HWScaleData &scale, uint32_t index,
+ mdp_layer_commit_v1 *mdp_commit, HWSubBlockType sub_block_type);
+ virtual void* GetScaleDataRef(uint32_t index, HWSubBlockType sub_block_type);
+ virtual void DumpScaleData(void *mdp_scale);
+ virtual void ResetScaleParams() { scale_data_v2_ = {}; dest_scale_data_v2_ = {}; }
+
+ protected:
+ ~HWScaleV2() {}
+ std::array<mdp_scale_data_v2, (kMaxSDELayers * 2)> scale_data_v2_ = {};
+ std::map<uint32_t, mdp_scale_data_v2> dest_scale_data_v2_ = {};
+
+ private:
+ uint32_t GetMDPAlphaInterpolation(HWAlphaInterpolation alpha_filter_cfg);
+ uint32_t GetMDPScalingFilter(ScalingFilterConfig filter_cfg);
+};
+
+} // namespace sdm
+
+#endif // __HW_SCALE_H__
+
diff --git a/msm8909/sdm/libs/core/fb/hw_virtual.cpp b/msm8909/sdm/libs/core/fb/hw_virtual.cpp
new file mode 100644
index 00000000..21017a5c
--- /dev/null
+++ b/msm8909/sdm/libs/core/fb/hw_virtual.cpp
@@ -0,0 +1,86 @@
+/*
+* Copyright (c) 2015 - 2016, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <utils/debug.h>
+#include "hw_virtual.h"
+
+#define __CLASS__ "HWVirtual"
+
+namespace sdm {
+
+HWVirtual::HWVirtual(BufferSyncHandler *buffer_sync_handler, HWInfoInterface *hw_info_intf)
+ : HWDevice(buffer_sync_handler) {
+ HWDevice::device_type_ = kDeviceVirtual;
+ HWDevice::device_name_ = "Virtual Display Device";
+ HWDevice::hw_info_intf_ = hw_info_intf;
+}
+
+DisplayError HWVirtual::Init() {
+ return HWDevice::Init();
+}
+
+DisplayError HWVirtual::Validate(HWLayers *hw_layers) {
+ HWDevice::ResetDisplayParams();
+ return HWDevice::Validate(hw_layers);
+}
+
+DisplayError HWVirtual::GetMixerAttributes(HWMixerAttributes *mixer_attributes) {
+ mixer_attributes->width = display_attributes_.x_pixels;
+ mixer_attributes->height = display_attributes_.y_pixels;
+ mixer_attributes_.split_left = display_attributes_.is_device_split ?
+ (display_attributes_.x_pixels / 2) : mixer_attributes_.width;
+
+ return kErrorNone;
+}
+
+DisplayError HWVirtual::SetDisplayAttributes(const HWDisplayAttributes &display_attributes) {
+ if (display_attributes.x_pixels == 0 || display_attributes.y_pixels == 0) {
+ return kErrorParameters;
+ }
+
+ display_attributes_ = display_attributes;
+
+ if (display_attributes_.x_pixels > hw_resource_.max_mixer_width) {
+ display_attributes_.is_device_split = true;
+ }
+
+ return kErrorNone;
+}
+
+DisplayError HWVirtual::GetDisplayAttributes(uint32_t index,
+ HWDisplayAttributes *display_attributes) {
+ display_attributes->fps = 60;
+ // TODO(user): Need to update WB fps
+
+ return kErrorNone;
+}
+
+
+} // namespace sdm
+
diff --git a/msm8909/sdm/libs/core/fb/hw_virtual.h b/msm8909/sdm/libs/core/fb/hw_virtual.h
new file mode 100644
index 00000000..1c204cdf
--- /dev/null
+++ b/msm8909/sdm/libs/core/fb/hw_virtual.h
@@ -0,0 +1,52 @@
+/*
+* Copyright (c) 2015 - 2016, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without modification, are permitted
+* provided that the following conditions are met:
+* * Redistributions of source code must retain the above copyright notice, this list of
+* conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright notice, this list of
+* conditions and the following disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its contributors may be used to
+* endorse or promote products derived from this software without specific prior written
+* permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __HW_VIRTUAL_H__
+#define __HW_VIRTUAL_H__
+
+#include "hw_device.h"
+
+namespace sdm {
+
+class HWVirtual : public HWDevice {
+ public:
+ HWVirtual(BufferSyncHandler *buffer_sync_handler, HWInfoInterface *hw_info_intf);
+ virtual DisplayError SetVSyncState(bool enable) { return kErrorNotSupported; }
+ virtual DisplayError SetMixerAttributes(const HWMixerAttributes &mixer_attributes) {
+ return kErrorNotSupported;
+ }
+ virtual DisplayError GetMixerAttributes(HWMixerAttributes *mixer_attributes);
+ virtual DisplayError SetDisplayAttributes(const HWDisplayAttributes &display_attributes);
+ virtual DisplayError GetDisplayAttributes(uint32_t index,
+ HWDisplayAttributes *display_attributes);
+
+ protected:
+ virtual DisplayError Init();
+ virtual DisplayError Validate(HWLayers *hw_layers);
+};
+
+} // namespace sdm
+
+#endif // __HW_VIRTUAL_H__
+
diff --git a/msm8909/sdm/libs/core/hw_events_interface.cpp b/msm8909/sdm/libs/core/hw_events_interface.cpp
new file mode 100644
index 00000000..ed62b86b
--- /dev/null
+++ b/msm8909/sdm/libs/core/hw_events_interface.cpp
@@ -0,0 +1,75 @@
+/*
+* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <utils/utils.h>
+#include <vector>
+
+#include "hw_events_interface.h"
+#include "fb/hw_events.h"
+#ifdef COMPILE_DRM
+#include "drm/hw_events_drm.h"
+#endif
+
+#define __CLASS__ "HWEventsInterface"
+
+namespace sdm {
+
+DisplayError HWEventsInterface::Create(int display_type, HWEventHandler *event_handler,
+ const std::vector<HWEvent> &event_list,
+ HWEventsInterface **intf) {
+ DisplayError error = kErrorNone;
+ HWEventsInterface *hw_events = nullptr;
+ if (GetDriverType() == DriverType::FB) {
+ hw_events = new HWEvents();
+ } else {
+#ifdef COMPILE_DRM
+ hw_events = new HWEventsDRM();
+#endif
+ }
+
+ error = hw_events->Init(display_type, event_handler, event_list);
+ if (error != kErrorNone) {
+ delete hw_events;
+ } else {
+ *intf = hw_events;
+ }
+
+ return error;
+}
+
+DisplayError HWEventsInterface::Destroy(HWEventsInterface *intf) {
+ if (intf) {
+ intf->Deinit();
+ delete intf;
+ }
+
+ return kErrorNone;
+}
+
+} // namespace sdm
diff --git a/msm8909/sdm/libs/core/hw_events_interface.h b/msm8909/sdm/libs/core/hw_events_interface.h
new file mode 100644
index 00000000..17fb7df3
--- /dev/null
+++ b/msm8909/sdm/libs/core/hw_events_interface.h
@@ -0,0 +1,63 @@
+/*
+* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without modification, are permitted
+* provided that the following conditions are met:
+* * Redistributions of source code must retain the above copyright notice, this list of
+* conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright notice, this list of
+* conditions and the following disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its contributors may be used to
+* endorse or promote products derived from this software without specific prior written
+* permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __HW_EVENTS_INTERFACE_H__
+#define __HW_EVENTS_INTERFACE_H__
+
+#include <private/hw_info_types.h>
+#include <inttypes.h>
+#include <utility>
+#include <vector>
+
+namespace sdm {
+
+class HWEventHandler;
+
+enum HWEvent {
+ VSYNC = 0,
+ EXIT,
+ IDLE_NOTIFY,
+ SHOW_BLANK_EVENT,
+ THERMAL_LEVEL,
+ IDLE_POWER_COLLAPSE,
+};
+
+class HWEventsInterface {
+ public:
+ virtual DisplayError Init(int display_type, HWEventHandler *event_handler,
+ const std::vector<HWEvent> &event_list) = 0;
+ virtual DisplayError Deinit() = 0;
+
+ static DisplayError Create(int display_type, HWEventHandler *event_handler,
+ const std::vector<HWEvent> &event_list, HWEventsInterface **intf);
+ static DisplayError Destroy(HWEventsInterface *intf);
+
+ protected:
+ virtual ~HWEventsInterface() { }
+};
+
+} // namespace sdm
+
+#endif // __HW_EVENTS_INTERFACE_H__
+
diff --git a/msm8909/sdm/libs/core/hw_info_interface.cpp b/msm8909/sdm/libs/core/hw_info_interface.cpp
new file mode 100644
index 00000000..1773fe52
--- /dev/null
+++ b/msm8909/sdm/libs/core/hw_info_interface.cpp
@@ -0,0 +1,62 @@
+/*
+* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <utils/utils.h>
+
+#include "hw_info_interface.h"
+#include "fb/hw_info.h"
+#ifdef COMPILE_DRM
+#include "drm/hw_info_drm.h"
+#endif
+
+#define __CLASS__ "HWInfoInterface"
+
+namespace sdm {
+
+DisplayError HWInfoInterface::Create(HWInfoInterface **intf) {
+ if (GetDriverType() == DriverType::FB) {
+ *intf = new HWInfo();
+ } else {
+#ifdef COMPILE_DRM
+ *intf = new HWInfoDRM();
+#endif
+ }
+
+ return kErrorNone;
+}
+
+DisplayError HWInfoInterface::Destroy(HWInfoInterface *intf) {
+ if (intf) {
+ delete intf;
+ }
+
+ return kErrorNone;
+}
+
+} // namespace sdm
diff --git a/msm8909/sdm/libs/core/hw_info_interface.h b/msm8909/sdm/libs/core/hw_info_interface.h
new file mode 100644
index 00000000..401c8bf6
--- /dev/null
+++ b/msm8909/sdm/libs/core/hw_info_interface.h
@@ -0,0 +1,48 @@
+/*
+* Copyright (c) 2014 - 2016, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without modification, are permitted
+* provided that the following conditions are met:
+* * Redistributions of source code must retain the above copyright notice, this list of
+* conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright notice, this list of
+* conditions and the following disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its contributors may be used to
+* endorse or promote products derived from this software without specific prior written
+* permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __HW_INFO_INTERFACE_H__
+#define __HW_INFO_INTERFACE_H__
+
+#include <inttypes.h>
+#include <core/core_interface.h>
+#include <private/hw_info_types.h>
+
+namespace sdm {
+
+class HWInfoInterface {
+ public:
+ static DisplayError Create(HWInfoInterface **intf);
+ static DisplayError Destroy(HWInfoInterface *intf);
+ virtual DisplayError GetHWResourceInfo(HWResourceInfo *hw_resource) = 0;
+ virtual DisplayError GetFirstDisplayInterfaceType(HWDisplayInterfaceInfo *hw_disp_info) = 0;
+
+ protected:
+ virtual ~HWInfoInterface() { }
+};
+
+} // namespace sdm
+
+#endif // __HW_INFO_INTERFACE_H__
+
diff --git a/msm8909/sdm/libs/core/hw_interface.cpp b/msm8909/sdm/libs/core/hw_interface.cpp
new file mode 100644
index 00000000..b5c9fe90
--- /dev/null
+++ b/msm8909/sdm/libs/core/hw_interface.cpp
@@ -0,0 +1,102 @@
+/*
+* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <utils/debug.h>
+#include <utils/utils.h>
+
+#include "hw_interface.h"
+#include "fb/hw_device.h"
+#include "fb/hw_primary.h"
+#include "fb/hw_hdmi.h"
+#include "fb/hw_virtual.h"
+#ifdef COMPILE_DRM
+#include "drm/hw_device_drm.h"
+#endif
+
+#define __CLASS__ "HWInterface"
+
+namespace sdm {
+
+DisplayError HWInterface::Create(DisplayType type, HWInfoInterface *hw_info_intf,
+ BufferSyncHandler *buffer_sync_handler,
+ BufferAllocator *buffer_allocator, HWInterface **intf) {
+ DisplayError error = kErrorNone;
+ HWInterface *hw = nullptr;
+ DriverType driver_type = GetDriverType();
+
+ switch (type) {
+ case kPrimary:
+ if (driver_type == DriverType::FB) {
+ hw = new HWPrimary(buffer_sync_handler, hw_info_intf);
+ } else {
+#ifdef COMPILE_DRM
+ hw = new HWDeviceDRM(buffer_sync_handler, buffer_allocator, hw_info_intf);
+#endif
+ }
+ break;
+ case kHDMI:
+ if (driver_type == DriverType::FB) {
+ hw = new HWHDMI(buffer_sync_handler, hw_info_intf);
+ } else {
+ return kErrorNotSupported;
+ }
+ break;
+ case kVirtual:
+ if (driver_type == DriverType::FB) {
+ hw = new HWVirtual(buffer_sync_handler, hw_info_intf);
+ } else {
+ return kErrorNotSupported;
+ }
+ break;
+ default:
+ DLOGE("Undefined display type");
+ return kErrorUndefined;
+ }
+
+ error = hw->Init();
+ if (error != kErrorNone) {
+ delete hw;
+ DLOGE("Init on HW Intf type %d failed", type);
+ return error;
+ }
+ *intf = hw;
+
+ return error;
+}
+
+DisplayError HWInterface::Destroy(HWInterface *intf) {
+ if (intf) {
+ intf->Deinit();
+ delete intf;
+ }
+
+ return kErrorNone;
+}
+
+} // namespace sdm
diff --git a/msm8909/sdm/libs/core/hw_interface.h b/msm8909/sdm/libs/core/hw_interface.h
new file mode 100644
index 00000000..312ad985
--- /dev/null
+++ b/msm8909/sdm/libs/core/hw_interface.h
@@ -0,0 +1,120 @@
+/*
+* Copyright (c) 2014 - 2017, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without modification, are permitted
+* provided that the following conditions are met:
+* * Redistributions of source code must retain the above copyright notice, this list of
+* conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright notice, this list of
+* conditions and the following disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its contributors may be used to
+* endorse or promote products derived from this software without specific prior written
+* permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __HW_INTERFACE_H__
+#define __HW_INTERFACE_H__
+
+#include <core/buffer_allocator.h>
+#include <core/buffer_sync_handler.h>
+#include <core/display_interface.h>
+#include <private/hw_info_types.h>
+#include <private/color_interface.h>
+#include <utils/constants.h>
+
+#include "hw_info_interface.h"
+
+namespace sdm {
+
+enum HWScanSupport {
+ kScanNotSupported,
+ kScanAlwaysOverscanned,
+ kScanAlwaysUnderscanned,
+ kScanBoth,
+};
+
+struct HWScanInfo {
+ HWScanSupport pt_scan_support; // Scan support for preferred timing
+ HWScanSupport it_scan_support; // Scan support for digital monitor or industry timings
+ HWScanSupport cea_scan_support; // Scan support for CEA resolution timings
+
+ HWScanInfo() : pt_scan_support(kScanNotSupported), it_scan_support(kScanNotSupported),
+ cea_scan_support(kScanNotSupported) { }
+};
+
+// HWEventHandler - Implemented in DisplayBase and HWInterface implementation
+class HWEventHandler {
+ public:
+ virtual DisplayError VSync(int64_t timestamp) = 0;
+ virtual DisplayError Blank(bool blank) = 0;
+ virtual void IdleTimeout() = 0;
+ virtual void ThermalEvent(int64_t thermal_level) = 0;
+ virtual void IdlePowerCollapse() = 0;
+
+ protected:
+ virtual ~HWEventHandler() { }
+};
+
+class HWInterface {
+ public:
+ static DisplayError Create(DisplayType type, HWInfoInterface *hw_info_intf,
+ BufferSyncHandler *buffer_sync_handler,
+ BufferAllocator *buffer_allocator, HWInterface **intf);
+ static DisplayError Destroy(HWInterface *intf);
+
+ virtual DisplayError Init() = 0;
+ virtual DisplayError Deinit() = 0;
+ virtual DisplayError GetActiveConfig(uint32_t *active_config) = 0;
+ virtual DisplayError GetNumDisplayAttributes(uint32_t *count) = 0;
+ virtual DisplayError GetDisplayAttributes(uint32_t index,
+ HWDisplayAttributes *display_attributes) = 0;
+ virtual DisplayError GetHWPanelInfo(HWPanelInfo *panel_info) = 0;
+ virtual DisplayError SetDisplayAttributes(uint32_t index) = 0;
+ virtual DisplayError SetDisplayAttributes(const HWDisplayAttributes &display_attributes) = 0;
+ virtual DisplayError GetConfigIndex(uint32_t mode, uint32_t *index) = 0;
+ virtual DisplayError PowerOn() = 0;
+ virtual DisplayError PowerOff() = 0;
+ virtual DisplayError Doze() = 0;
+ virtual DisplayError DozeSuspend() = 0;
+ virtual DisplayError Standby() = 0;
+ virtual DisplayError Validate(HWLayers *hw_layers) = 0;
+ virtual DisplayError Commit(HWLayers *hw_layers) = 0;
+ virtual DisplayError Flush() = 0;
+ virtual DisplayError GetPPFeaturesVersion(PPFeatureVersion *vers) = 0;
+ virtual DisplayError SetPPFeatures(PPFeaturesConfig *feature_list) = 0;
+ virtual DisplayError SetVSyncState(bool enable) = 0;
+ virtual void SetIdleTimeoutMs(uint32_t timeout_ms) = 0;
+ virtual DisplayError SetDisplayMode(const HWDisplayMode hw_display_mode) = 0;
+ virtual DisplayError SetRefreshRate(uint32_t refresh_rate) = 0;
+ virtual DisplayError SetPanelBrightness(int level) = 0;
+ virtual DisplayError CachePanelBrightness(int level) = 0;
+ virtual DisplayError GetHWScanInfo(HWScanInfo *scan_info) = 0;
+ virtual DisplayError GetVideoFormat(uint32_t config_index, uint32_t *video_format) = 0;
+ virtual DisplayError GetMaxCEAFormat(uint32_t *max_cea_format) = 0;
+ virtual DisplayError SetCursorPosition(HWLayers *hw_layers, int x, int y) = 0;
+ virtual DisplayError OnMinHdcpEncryptionLevelChange(uint32_t min_enc_level) = 0;
+ virtual DisplayError GetPanelBrightness(int *level) = 0;
+ virtual DisplayError SetAutoRefresh(bool enable) = 0;
+ virtual DisplayError SetS3DMode(HWS3DMode s3d_mode) = 0;
+ virtual DisplayError SetScaleLutConfig(HWScaleLutInfo *lut_info) = 0;
+ virtual DisplayError SetMixerAttributes(const HWMixerAttributes &mixer_attributes) = 0;
+ virtual DisplayError GetMixerAttributes(HWMixerAttributes *mixer_attributes) = 0;
+
+ protected:
+ virtual ~HWInterface() { }
+};
+
+} // namespace sdm
+
+#endif // __HW_INTERFACE_H__
+
diff --git a/msm8909/sdm/libs/core/resource_default.cpp b/msm8909/sdm/libs/core/resource_default.cpp
new file mode 100644
index 00000000..6a4f3e5b
--- /dev/null
+++ b/msm8909/sdm/libs/core/resource_default.cpp
@@ -0,0 +1,950 @@
+/*
+* Copyright (c) 2014 - 2016, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without modification, are permitted
+* provided that the following conditions are met:
+* * Redistributions of source code must retain the above copyright notice, this list of
+* conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright notice, this list of
+* conditions and the following disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its contributors may be used to
+* endorse or promote products derived from this software without specific prior written
+* permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <math.h>
+#include <utils/constants.h>
+#include <utils/debug.h>
+#include <utils/rect.h>
+#include <utils/formats.h>
+#include <utils/sys.h>
+#include <dlfcn.h>
+#include <algorithm>
+
+#include "resource_default.h"
+
+#define __CLASS__ "ResourceDefault"
+
+namespace sdm {
+
+DisplayError ResourceDefault::CreateResourceDefault(const HWResourceInfo &hw_resource_info,
+ ResourceInterface **resource_intf) {
+ DisplayError error = kErrorNone;
+
+ ResourceDefault *resource_default = new ResourceDefault(hw_resource_info);
+ if (!resource_default) {
+ return kErrorNone;
+ }
+
+ error = resource_default->Init();
+ if (error != kErrorNone) {
+ delete resource_default;
+ }
+
+ *resource_intf = resource_default;
+
+ return kErrorNone;
+}
+
+DisplayError ResourceDefault::DestroyResourceDefault(ResourceInterface *resource_intf) {
+ ResourceDefault *resource_default = static_cast<ResourceDefault *>(resource_intf);
+
+ resource_default->Deinit();
+ delete resource_default;
+
+ return kErrorNone;
+}
+
+ResourceDefault::ResourceDefault(const HWResourceInfo &hw_res_info)
+ : hw_res_info_(hw_res_info) {
+}
+
+DisplayError ResourceDefault::Init() {
+ DisplayError error = kErrorNone;
+
+ num_pipe_ = hw_res_info_.num_vig_pipe + hw_res_info_.num_rgb_pipe + hw_res_info_.num_dma_pipe;
+
+ if (!num_pipe_) {
+ DLOGE("Number of H/W pipes is Zero!");
+ return kErrorParameters;
+ }
+
+ src_pipes_.resize(num_pipe_);
+
+ // Priority order of pipes: VIG, RGB, DMA
+ uint32_t vig_index = 0;
+ uint32_t rgb_index = hw_res_info_.num_vig_pipe;
+ uint32_t dma_index = rgb_index + hw_res_info_.num_rgb_pipe;
+
+ for (uint32_t i = 0; i < num_pipe_; i++) {
+ const HWPipeCaps &pipe_caps = hw_res_info_.hw_pipes.at(i);
+ if (pipe_caps.type == kPipeTypeVIG) {
+ src_pipes_[vig_index].type = kPipeTypeVIG;
+ src_pipes_[vig_index].index = i;
+ src_pipes_[vig_index].mdss_pipe_id = pipe_caps.id;
+ vig_index++;
+ } else if (pipe_caps.type == kPipeTypeRGB) {
+ src_pipes_[rgb_index].type = kPipeTypeRGB;
+ src_pipes_[rgb_index].index = i;
+ src_pipes_[rgb_index].mdss_pipe_id = pipe_caps.id;
+ rgb_index++;
+ } else if (pipe_caps.type == kPipeTypeDMA) {
+ src_pipes_[dma_index].type = kPipeTypeDMA;
+ src_pipes_[dma_index].index = i;
+ src_pipes_[dma_index].mdss_pipe_id = pipe_caps.id;
+ dma_index++;
+ }
+ }
+
+ for (uint32_t i = 0; i < num_pipe_; i++) {
+ src_pipes_[i].priority = INT(i);
+ }
+
+ DLOGI("hw_rev=%x, DMA=%d RGB=%d VIG=%d", hw_res_info_.hw_revision, hw_res_info_.num_dma_pipe,
+ hw_res_info_.num_rgb_pipe, hw_res_info_.num_vig_pipe);
+
+ if (hw_res_info_.max_scale_down < 1 || hw_res_info_.max_scale_up < 1) {
+ DLOGE("Max scaling setting is invalid! max_scale_down = %d, max_scale_up = %d",
+ hw_res_info_.max_scale_down, hw_res_info_.max_scale_up);
+ hw_res_info_.max_scale_down = 1;
+ hw_res_info_.max_scale_up = 1;
+ }
+
+ // TODO(user): clean it up, query from driver for initial pipe status.
+#ifndef SDM_VIRTUAL_DRIVER
+ rgb_index = hw_res_info_.num_vig_pipe;
+ src_pipes_[rgb_index].owner = kPipeOwnerKernelMode;
+ src_pipes_[rgb_index + 1].owner = kPipeOwnerKernelMode;
+#endif
+
+ return error;
+}
+
+DisplayError ResourceDefault::Deinit() {
+ return kErrorNone;
+}
+
+DisplayError ResourceDefault::RegisterDisplay(DisplayType type,
+ const HWDisplayAttributes &display_attributes,
+ const HWPanelInfo &hw_panel_info,
+ const HWMixerAttributes &mixer_attributes,
+ Handle *display_ctx) {
+ DisplayError error = kErrorNone;
+
+ HWBlockType hw_block_id = kHWBlockMax;
+ switch (type) {
+ case kPrimary:
+ if (!hw_block_ctx_[kHWPrimary].is_in_use) {
+ hw_block_id = kHWPrimary;
+ }
+ break;
+
+ case kHDMI:
+ if (!hw_block_ctx_[kHWHDMI].is_in_use) {
+ hw_block_id = kHWHDMI;
+ }
+ break;
+
+ default:
+ DLOGW("RegisterDisplay, invalid type %d", type);
+ return kErrorParameters;
+ }
+
+ if (hw_block_id == kHWBlockMax) {
+ return kErrorResources;
+ }
+
+ DisplayResourceContext *display_resource_ctx = new DisplayResourceContext();
+ if (!display_resource_ctx) {
+ return kErrorMemory;
+ }
+
+ hw_block_ctx_[hw_block_id].is_in_use = true;
+
+ display_resource_ctx->display_attributes = display_attributes;
+ display_resource_ctx->hw_block_id = hw_block_id;
+ display_resource_ctx->mixer_attributes = mixer_attributes;
+
+ *display_ctx = display_resource_ctx;
+ return error;
+}
+
+DisplayError ResourceDefault::UnregisterDisplay(Handle display_ctx) {
+ DisplayResourceContext *display_resource_ctx =
+ reinterpret_cast<DisplayResourceContext *>(display_ctx);
+ Purge(display_ctx);
+
+ hw_block_ctx_[display_resource_ctx->hw_block_id].is_in_use = false;
+
+ delete display_resource_ctx;
+
+ return kErrorNone;
+}
+
+DisplayError ResourceDefault::ReconfigureDisplay(Handle display_ctx,
+ const HWDisplayAttributes &display_attributes,
+ const HWPanelInfo &hw_panel_info,
+ const HWMixerAttributes &mixer_attributes) {
+ SCOPE_LOCK(locker_);
+
+ DisplayResourceContext *display_resource_ctx =
+ reinterpret_cast<DisplayResourceContext *>(display_ctx);
+
+ display_resource_ctx->display_attributes = display_attributes;
+ display_resource_ctx->mixer_attributes = mixer_attributes;
+
+ return kErrorNone;
+}
+
+DisplayError ResourceDefault::Start(Handle display_ctx) {
+ locker_.Lock();
+
+ return kErrorNone;
+}
+
+DisplayError ResourceDefault::Stop(Handle display_ctx, HWLayers *hw_layers) {
+ locker_.Unlock();
+
+ return kErrorNone;
+}
+
+DisplayError ResourceDefault::Prepare(Handle display_ctx, HWLayers *hw_layers) {
+ DisplayResourceContext *display_resource_ctx =
+ reinterpret_cast<DisplayResourceContext *>(display_ctx);
+
+ DisplayError error = kErrorNone;
+ const struct HWLayersInfo &layer_info = hw_layers->info;
+ HWBlockType hw_block_id = display_resource_ctx->hw_block_id;
+
+ DLOGV_IF(kTagResources, "==== Resource reserving start: hw_block = %d ====", hw_block_id);
+
+ if (layer_info.hw_layers.size() > 1) {
+ DLOGV_IF(kTagResources, "More than one FB layers");
+ return kErrorResources;
+ }
+
+ const Layer &layer = layer_info.hw_layers.at(0);
+
+ if (layer.composition != kCompositionGPUTarget) {
+ DLOGV_IF(kTagResources, "Not an FB layer");
+ return kErrorParameters;
+ }
+
+ error = Config(display_resource_ctx, hw_layers);
+ if (error != kErrorNone) {
+ DLOGV_IF(kTagResources, "Resource config failed");
+ return error;
+ }
+
+ for (uint32_t i = 0; i < num_pipe_; i++) {
+ if (src_pipes_[i].hw_block_id == hw_block_id && src_pipes_[i].owner == kPipeOwnerUserMode) {
+ src_pipes_[i].ResetState();
+ }
+ }
+
+ uint32_t left_index = num_pipe_;
+ uint32_t right_index = num_pipe_;
+ bool need_scale = false;
+
+ struct HWLayerConfig &layer_config = hw_layers->config[0];
+
+ HWPipeInfo *left_pipe = &layer_config.left_pipe;
+ HWPipeInfo *right_pipe = &layer_config.right_pipe;
+
+ // left pipe is needed
+ if (left_pipe->valid) {
+ need_scale = IsScalingNeeded(left_pipe);
+ left_index = GetPipe(hw_block_id, need_scale);
+ if (left_index >= num_pipe_) {
+ DLOGV_IF(kTagResources, "Get left pipe failed: hw_block_id = %d, need_scale = %d",
+ hw_block_id, need_scale);
+ ResourceStateLog();
+ goto CleanupOnError;
+ }
+ }
+
+ error = SetDecimationFactor(left_pipe);
+ if (error != kErrorNone) {
+ goto CleanupOnError;
+ }
+
+ if (!right_pipe->valid) {
+ // assign single pipe
+ if (left_index < num_pipe_) {
+ left_pipe->pipe_id = src_pipes_[left_index].mdss_pipe_id;
+ }
+ DLOGV_IF(kTagResources, "1 pipe acquired for FB layer, left_pipe = %x", left_pipe->pipe_id);
+ return kErrorNone;
+ }
+
+ need_scale = IsScalingNeeded(right_pipe);
+
+ right_index = GetPipe(hw_block_id, need_scale);
+ if (right_index >= num_pipe_) {
+ DLOGV_IF(kTagResources, "Get right pipe failed: hw_block_id = %d, need_scale = %d", hw_block_id,
+ need_scale);
+ ResourceStateLog();
+ goto CleanupOnError;
+ }
+
+ if (src_pipes_[right_index].priority < src_pipes_[left_index].priority) {
+ // Swap pipe based on priority
+ std::swap(left_index, right_index);
+ }
+
+ // assign dual pipes
+ left_pipe->pipe_id = src_pipes_[left_index].mdss_pipe_id;
+ right_pipe->pipe_id = src_pipes_[right_index].mdss_pipe_id;
+
+ error = SetDecimationFactor(right_pipe);
+ if (error != kErrorNone) {
+ goto CleanupOnError;
+ }
+
+ DLOGV_IF(kTagResources, "2 pipes acquired for FB layer, left_pipe = %x, right_pipe = %x",
+ left_pipe->pipe_id, right_pipe->pipe_id);
+
+ return kErrorNone;
+
+CleanupOnError:
+ DLOGV_IF(kTagResources, "Resource reserving failed! hw_block = %d", hw_block_id);
+
+ return kErrorResources;
+}
+
+DisplayError ResourceDefault::PostPrepare(Handle display_ctx, HWLayers *hw_layers) {
+ SCOPE_LOCK(locker_);
+
+ return kErrorNone;
+}
+
+DisplayError ResourceDefault::Commit(Handle display_ctx, HWLayers *hw_layers) {
+ SCOPE_LOCK(locker_);
+
+ return kErrorNone;
+}
+
+DisplayError ResourceDefault::PostCommit(Handle display_ctx, HWLayers *hw_layers) {
+ SCOPE_LOCK(locker_);
+ DisplayResourceContext *display_resource_ctx =
+ reinterpret_cast<DisplayResourceContext *>(display_ctx);
+ HWBlockType hw_block_id = display_resource_ctx->hw_block_id;
+ uint64_t frame_count = display_resource_ctx->frame_count;
+
+ DLOGV_IF(kTagResources, "Resource for hw_block = %d, frame_count = %d", hw_block_id, frame_count);
+
+ // handoff pipes which are used by splash screen
+ if ((frame_count == 0) && (hw_block_id == kHWPrimary)) {
+ for (uint32_t i = 0; i < num_pipe_; i++) {
+ if (src_pipes_[i].hw_block_id == hw_block_id && src_pipes_[i].owner == kPipeOwnerKernelMode) {
+ src_pipes_[i].owner = kPipeOwnerUserMode;
+ }
+ }
+ }
+
+ if (hw_layers->info.sync_handle >= 0)
+ Sys::close_(hw_layers->info.sync_handle);
+
+ display_resource_ctx->frame_count++;
+
+ return kErrorNone;
+}
+
+void ResourceDefault::Purge(Handle display_ctx) {
+ SCOPE_LOCK(locker_);
+
+ DisplayResourceContext *display_resource_ctx =
+ reinterpret_cast<DisplayResourceContext *>(display_ctx);
+ HWBlockType hw_block_id = display_resource_ctx->hw_block_id;
+
+ for (uint32_t i = 0; i < num_pipe_; i++) {
+ if (src_pipes_[i].hw_block_id == hw_block_id && src_pipes_[i].owner == kPipeOwnerUserMode) {
+ src_pipes_[i].ResetState();
+ }
+ }
+ DLOGV_IF(kTagResources, "display id = %d", display_resource_ctx->hw_block_id);
+}
+
+DisplayError ResourceDefault::SetMaxMixerStages(Handle display_ctx, uint32_t max_mixer_stages) {
+ SCOPE_LOCK(locker_);
+
+ return kErrorNone;
+}
+
+uint32_t ResourceDefault::SearchPipe(HWBlockType hw_block_id, SourcePipe *src_pipes,
+ uint32_t num_pipe) {
+ uint32_t index = num_pipe_;
+ SourcePipe *src_pipe;
+
+ // search the pipe being used
+ for (uint32_t i = 0; i < num_pipe; i++) {
+ src_pipe = &src_pipes[i];
+ if (src_pipe->owner == kPipeOwnerUserMode && src_pipe->hw_block_id == kHWBlockMax) {
+ index = src_pipe->index;
+ src_pipe->hw_block_id = hw_block_id;
+ break;
+ }
+ }
+
+ return index;
+}
+
+uint32_t ResourceDefault::NextPipe(PipeType type, HWBlockType hw_block_id) {
+ uint32_t num_pipe = 0;
+ SourcePipe *src_pipes = NULL;
+
+ switch (type) {
+ case kPipeTypeVIG:
+ src_pipes = &src_pipes_[0];
+ num_pipe = hw_res_info_.num_vig_pipe;
+ break;
+ case kPipeTypeRGB:
+ src_pipes = &src_pipes_[hw_res_info_.num_vig_pipe];
+ num_pipe = hw_res_info_.num_rgb_pipe;
+ break;
+ case kPipeTypeDMA:
+ default:
+ src_pipes = &src_pipes_[hw_res_info_.num_vig_pipe + hw_res_info_.num_rgb_pipe];
+ num_pipe = hw_res_info_.num_dma_pipe;
+ break;
+ }
+
+ return SearchPipe(hw_block_id, src_pipes, num_pipe);
+}
+
+uint32_t ResourceDefault::GetPipe(HWBlockType hw_block_id, bool need_scale) {
+ uint32_t index = num_pipe_;
+
+ // The default behavior is to assume RGB and VG pipes have scalars
+ if (!need_scale) {
+ index = NextPipe(kPipeTypeDMA, hw_block_id);
+ }
+
+ if ((index >= num_pipe_) && (!need_scale || !hw_res_info_.has_non_scalar_rgb)) {
+ index = NextPipe(kPipeTypeRGB, hw_block_id);
+ }
+
+ if (index >= num_pipe_) {
+ index = NextPipe(kPipeTypeVIG, hw_block_id);
+ }
+
+ return index;
+}
+
+bool ResourceDefault::IsScalingNeeded(const HWPipeInfo *pipe_info) {
+ const LayerRect &src_roi = pipe_info->src_roi;
+ const LayerRect &dst_roi = pipe_info->dst_roi;
+
+ return ((dst_roi.right - dst_roi.left) != (src_roi.right - src_roi.left)) ||
+ ((dst_roi.bottom - dst_roi.top) != (src_roi.bottom - src_roi.top));
+}
+
+void ResourceDefault::ResourceStateLog() {
+ DLOGV_IF(kTagResources, "==== resource manager pipe state ====");
+ uint32_t i;
+ for (i = 0; i < num_pipe_; i++) {
+ SourcePipe *src_pipe = &src_pipes_[i];
+ DLOGV_IF(kTagResources, "index = %d, id = %x, hw_block = %d, owner = %s",
+ src_pipe->index, src_pipe->mdss_pipe_id, src_pipe->hw_block_id,
+ (src_pipe->owner == kPipeOwnerUserMode) ? "user mode" : "kernel mode");
+ }
+}
+
+DisplayError ResourceDefault::SrcSplitConfig(DisplayResourceContext *display_resource_ctx,
+ const LayerRect &src_rect, const LayerRect &dst_rect,
+ HWLayerConfig *layer_config) {
+ HWPipeInfo *left_pipe = &layer_config->left_pipe;
+ HWPipeInfo *right_pipe = &layer_config->right_pipe;
+ float src_width = src_rect.right - src_rect.left;
+ float dst_width = dst_rect.right - dst_rect.left;
+
+ // Layer cannot qualify for SrcSplit if source or destination width exceeds max pipe width.
+ if ((src_width > hw_res_info_.max_pipe_width) || (dst_width > hw_res_info_.max_pipe_width)) {
+ SplitRect(src_rect, dst_rect, &left_pipe->src_roi, &left_pipe->dst_roi, &right_pipe->src_roi,
+ &right_pipe->dst_roi);
+ left_pipe->valid = true;
+ right_pipe->valid = true;
+ } else {
+ left_pipe->src_roi = src_rect;
+ left_pipe->dst_roi = dst_rect;
+ left_pipe->valid = true;
+ right_pipe->Reset();
+ }
+
+ return kErrorNone;
+}
+
+DisplayError ResourceDefault::DisplaySplitConfig(DisplayResourceContext *display_resource_ctx,
+ const LayerRect &src_rect, const LayerRect &dst_rect,
+ HWLayerConfig *layer_config) {
+ HWMixerAttributes &mixer_attributes = display_resource_ctx->mixer_attributes;
+
+ // for display split case
+ HWPipeInfo *left_pipe = &layer_config->left_pipe;
+ HWPipeInfo *right_pipe = &layer_config->right_pipe;
+ LayerRect scissor_left, scissor_right, dst_left, crop_left, crop_right, dst_right;
+
+ scissor_left.right = FLOAT(mixer_attributes.split_left);
+ scissor_left.bottom = FLOAT(mixer_attributes.height);
+
+ scissor_right.left = FLOAT(mixer_attributes.split_left);
+ scissor_right.top = 0.0f;
+ scissor_right.right = FLOAT(mixer_attributes.width);
+ scissor_right.bottom = FLOAT(mixer_attributes.height);
+
+ crop_left = src_rect;
+ dst_left = dst_rect;
+ crop_right = crop_left;
+ dst_right = dst_left;
+
+ bool crop_left_valid = CalculateCropRects(scissor_left, &crop_left, &dst_left);
+ bool crop_right_valid = false;
+
+ if (IsValid(scissor_right)) {
+ crop_right_valid = CalculateCropRects(scissor_right, &crop_right, &dst_right);
+ }
+
+ // Reset left_pipe and right_pipe to invalid by default
+ left_pipe->Reset();
+ right_pipe->Reset();
+
+ if (crop_left_valid) {
+ // assign left pipe
+ left_pipe->src_roi = crop_left;
+ left_pipe->dst_roi = dst_left;
+ left_pipe->valid = true;
+ }
+
+ // assign right pipe if needed
+ if (crop_right_valid) {
+ right_pipe->src_roi = crop_right;
+ right_pipe->dst_roi = dst_right;
+ right_pipe->valid = true;
+ }
+
+ return kErrorNone;
+}
+
+DisplayError ResourceDefault::Config(DisplayResourceContext *display_resource_ctx,
+ HWLayers *hw_layers) {
+ HWLayersInfo &layer_info = hw_layers->info;
+ DisplayError error = kErrorNone;
+ const Layer &layer = layer_info.hw_layers.at(0);
+
+ error = ValidateLayerParams(&layer);
+ if (error != kErrorNone) {
+ return error;
+ }
+
+ struct HWLayerConfig *layer_config = &hw_layers->config[0];
+ HWPipeInfo &left_pipe = layer_config->left_pipe;
+ HWPipeInfo &right_pipe = layer_config->right_pipe;
+
+ LayerRect src_rect = layer.src_rect;
+ LayerRect dst_rect = layer.dst_rect;
+
+ error = ValidateDimensions(src_rect, dst_rect);
+ if (error != kErrorNone) {
+ return error;
+ }
+
+ BufferLayout layout = GetBufferLayout(layer.input_buffer.format);
+ error = ValidateScaling(src_rect, dst_rect, false /*rotated90 */, layout,
+ false /* use_rotator_downscale */);
+ if (error != kErrorNone) {
+ return error;
+ }
+
+ if (hw_res_info_.is_src_split) {
+ error = SrcSplitConfig(display_resource_ctx, src_rect, dst_rect, layer_config);
+ } else {
+ error = DisplaySplitConfig(display_resource_ctx, src_rect, dst_rect, layer_config);
+ }
+
+ if (error != kErrorNone) {
+ return error;
+ }
+
+ error = AlignPipeConfig(&layer, &left_pipe, &right_pipe);
+ if (error != kErrorNone) {
+ return error;
+ }
+
+ // set z_order, left_pipe should always be valid
+ left_pipe.z_order = 0;
+
+ DLOGV_IF(kTagResources, "==== FB layer Config ====");
+ Log(kTagResources, "input layer src_rect", layer.src_rect);
+ Log(kTagResources, "input layer dst_rect", layer.dst_rect);
+ Log(kTagResources, "cropped src_rect", src_rect);
+ Log(kTagResources, "cropped dst_rect", dst_rect);
+ Log(kTagResources, "left pipe src", layer_config->left_pipe.src_roi);
+ Log(kTagResources, "left pipe dst", layer_config->left_pipe.dst_roi);
+ if (right_pipe.valid) {
+ right_pipe.z_order = 0;
+ Log(kTagResources, "right pipe src", layer_config->right_pipe.src_roi);
+ Log(kTagResources, "right pipe dst", layer_config->right_pipe.dst_roi);
+ }
+
+ return error;
+}
+
+bool ResourceDefault::CalculateCropRects(const LayerRect &scissor, LayerRect *crop,
+ LayerRect *dst) {
+ float &crop_left = crop->left;
+ float &crop_top = crop->top;
+ float &crop_right = crop->right;
+ float &crop_bottom = crop->bottom;
+ float crop_width = crop->right - crop->left;
+ float crop_height = crop->bottom - crop->top;
+
+ float &dst_left = dst->left;
+ float &dst_top = dst->top;
+ float &dst_right = dst->right;
+ float &dst_bottom = dst->bottom;
+ float dst_width = dst->right - dst->left;
+ float dst_height = dst->bottom - dst->top;
+
+ const float &sci_left = scissor.left;
+ const float &sci_top = scissor.top;
+ const float &sci_right = scissor.right;
+ const float &sci_bottom = scissor.bottom;
+
+ float left_cut_ratio = 0.0, right_cut_ratio = 0.0, top_cut_ratio = 0.0, bottom_cut_ratio = 0.0;
+ bool need_cut = false;
+
+ if (dst_left < sci_left) {
+ left_cut_ratio = (sci_left - dst_left) / dst_width;
+ dst_left = sci_left;
+ need_cut = true;
+ }
+
+ if (dst_right > sci_right) {
+ right_cut_ratio = (dst_right - sci_right) / dst_width;
+ dst_right = sci_right;
+ need_cut = true;
+ }
+
+ if (dst_top < sci_top) {
+ top_cut_ratio = (sci_top - dst_top) / (dst_height);
+ dst_top = sci_top;
+ need_cut = true;
+ }
+
+ if (dst_bottom > sci_bottom) {
+ bottom_cut_ratio = (dst_bottom - sci_bottom) / (dst_height);
+ dst_bottom = sci_bottom;
+ need_cut = true;
+ }
+
+ if (!need_cut)
+ return true;
+
+ crop_left += crop_width * left_cut_ratio;
+ crop_top += crop_height * top_cut_ratio;
+ crop_right -= crop_width * right_cut_ratio;
+ crop_bottom -= crop_height * bottom_cut_ratio;
+ Normalize(1, 1, crop);
+ Normalize(1, 1, dst);
+ if (IsValid(*crop) && IsValid(*dst))
+ return true;
+ else
+ return false;
+}
+
+DisplayError ResourceDefault::ValidateLayerParams(const Layer *layer) {
+ const LayerRect &src = layer->src_rect;
+ const LayerRect &dst = layer->dst_rect;
+ const LayerBuffer &input_buffer = layer->input_buffer;
+
+ if (input_buffer.format == kFormatInvalid) {
+ DLOGV_IF(kTagResources, "Invalid input buffer format %d", input_buffer.format);
+ return kErrorNotSupported;
+ }
+
+ if (!IsValid(src) || !IsValid(dst)) {
+ Log(kTagResources, "input layer src_rect", src);
+ Log(kTagResources, "input layer dst_rect", dst);
+ return kErrorNotSupported;
+ }
+
+ // Make sure source in integral only if it is a non secure layer.
+ if (!input_buffer.flags.secure &&
+ ((src.left - roundf(src.left) != 0.0f) ||
+ (src.top - roundf(src.top) != 0.0f) ||
+ (src.right - roundf(src.right) != 0.0f) ||
+ (src.bottom - roundf(src.bottom) != 0.0f))) {
+ DLOGV_IF(kTagResources, "Input ROI is not integral");
+ return kErrorNotSupported;
+ }
+
+ return kErrorNone;
+}
+
+DisplayError ResourceDefault::ValidateDimensions(const LayerRect &crop, const LayerRect &dst) {
+ if (!IsValid(crop)) {
+ Log(kTagResources, "Invalid crop rect", crop);
+ return kErrorNotSupported;
+ }
+
+ if (!IsValid(dst)) {
+ Log(kTagResources, "Invalid dst rect", dst);
+ return kErrorNotSupported;
+ }
+
+ float crop_width = crop.right - crop.left;
+ float crop_height = crop.bottom - crop.top;
+ float dst_width = dst.right - dst.left;
+ float dst_height = dst.bottom - dst.top;
+
+ if ((UINT32(crop_width - dst_width) == 1) || (UINT32(crop_height - dst_height) == 1)) {
+ DLOGV_IF(kTagResources, "One pixel downscaling detected crop_w = %.0f, dst_w = %.0f, " \
+ "crop_h = %.0f, dst_h = %.0f", crop_width, dst_width, crop_height, dst_height);
+ return kErrorNotSupported;
+ }
+
+ return kErrorNone;
+}
+
+DisplayError ResourceDefault::ValidatePipeParams(HWPipeInfo *pipe_info, LayerBufferFormat format) {
+ DisplayError error = kErrorNone;
+
+ const LayerRect &src_rect = pipe_info->src_roi;
+ const LayerRect &dst_rect = pipe_info->dst_roi;
+
+ error = ValidateDimensions(src_rect, dst_rect);
+ if (error != kErrorNone) {
+ return error;
+ }
+
+ BufferLayout layout = GetBufferLayout(format);
+ error = ValidateScaling(src_rect, dst_rect, false /* rotated90 */, layout,
+ false /* use_rotator_downscale */);
+ if (error != kErrorNone) {
+ return error;
+ }
+
+ return kErrorNone;
+}
+
+DisplayError ResourceDefault::ValidateScaling(const LayerRect &crop, const LayerRect &dst,
+ bool rotate90, BufferLayout layout,
+ bool use_rotator_downscale) {
+ DisplayError error = kErrorNone;
+
+ float scale_x = 1.0f;
+ float scale_y = 1.0f;
+
+ error = GetScaleFactor(crop, dst, &scale_x, &scale_y);
+ if (error != kErrorNone) {
+ return error;
+ }
+
+ error = ValidateDownScaling(scale_x, scale_y, (layout != kLinear));
+ if (error != kErrorNone) {
+ return error;
+ }
+
+ error = ValidateUpScaling(scale_x, scale_y);
+ if (error != kErrorNone) {
+ return error;
+ }
+
+ return kErrorNone;
+}
+
+DisplayError ResourceDefault::ValidateDownScaling(float scale_x, float scale_y, bool ubwc_tiled) {
+ if ((UINT32(scale_x) > 1) || (UINT32(scale_y) > 1)) {
+ float max_scale_down = FLOAT(hw_res_info_.max_scale_down);
+
+ // MDP H/W cannot apply decimation on UBWC tiled framebuffer
+ if (!ubwc_tiled && hw_res_info_.has_decimation) {
+ max_scale_down *= FLOAT(kMaxDecimationDownScaleRatio);
+ }
+
+ if (scale_x > max_scale_down || scale_y > max_scale_down) {
+ DLOGV_IF(kTagResources,
+ "Scaling down is over the limit: scale_x = %.0f, scale_y = %.0f, " \
+ "has_deci = %d", scale_x, scale_y, hw_res_info_.has_decimation);
+ return kErrorNotSupported;
+ }
+ }
+
+ DLOGV_IF(kTagResources, "scale_x = %.4f, scale_y = %.4f", scale_x, scale_y);
+
+ return kErrorNone;
+}
+
+DisplayError ResourceDefault::ValidateUpScaling(float scale_x, float scale_y) {
+ float max_scale_up = FLOAT(hw_res_info_.max_scale_up);
+
+ if (UINT32(scale_x) < 1 && scale_x > 0.0f) {
+ if ((1.0f / scale_x) > max_scale_up) {
+ DLOGV_IF(kTagResources, "Scaling up is over limit scale_x = %f", 1.0f / scale_x);
+ return kErrorNotSupported;
+ }
+ }
+
+ if (UINT32(scale_y) < 1 && scale_y > 0.0f) {
+ if ((1.0f / scale_y) > max_scale_up) {
+ DLOGV_IF(kTagResources, "Scaling up is over limit scale_y = %f", 1.0f / scale_y);
+ return kErrorNotSupported;
+ }
+ }
+
+ DLOGV_IF(kTagResources, "scale_x = %.4f, scale_y = %.4f", scale_x, scale_y);
+
+ return kErrorNone;
+}
+
+DisplayError ResourceDefault::GetScaleFactor(const LayerRect &crop, const LayerRect &dst,
+ float *scale_x, float *scale_y) {
+ float crop_width = crop.right - crop.left;
+ float crop_height = crop.bottom - crop.top;
+ float dst_width = dst.right - dst.left;
+ float dst_height = dst.bottom - dst.top;
+
+ *scale_x = crop_width / dst_width;
+ *scale_y = crop_height / dst_height;
+
+ return kErrorNone;
+}
+
+DisplayError ResourceDefault::SetDecimationFactor(HWPipeInfo *pipe) {
+ float src_h = pipe->src_roi.bottom - pipe->src_roi.top;
+ float dst_h = pipe->dst_roi.bottom - pipe->dst_roi.top;
+ float down_scale_h = src_h / dst_h;
+
+ float src_w = pipe->src_roi.right - pipe->src_roi.left;
+ float dst_w = pipe->dst_roi.right - pipe->dst_roi.left;
+ float down_scale_w = src_w / dst_w;
+
+ pipe->horizontal_decimation = 0;
+ pipe->vertical_decimation = 0;
+
+ if (CalculateDecimation(down_scale_w, &pipe->horizontal_decimation) != kErrorNone) {
+ return kErrorNotSupported;
+ }
+
+ if (CalculateDecimation(down_scale_h, &pipe->vertical_decimation) != kErrorNone) {
+ return kErrorNotSupported;
+ }
+
+ DLOGI_IF(kTagResources, "horizontal_decimation %d, vertical_decimation %d",
+ pipe->horizontal_decimation, pipe->vertical_decimation);
+
+ return kErrorNone;
+}
+
+void ResourceDefault::SplitRect(const LayerRect &src_rect, const LayerRect &dst_rect,
+ LayerRect *src_left, LayerRect *dst_left, LayerRect *src_right,
+ LayerRect *dst_right) {
+ // Split rectangle horizontally and evenly into two.
+ float src_width = src_rect.right - src_rect.left;
+ float dst_width = dst_rect.right - dst_rect.left;
+ float src_width_ori = src_width;
+ src_width = ROUND_UP_ALIGN_DOWN(src_width / 2, 1);
+ dst_width = ROUND_UP_ALIGN_DOWN(dst_width * src_width / src_width_ori, 1);
+
+ src_left->left = src_rect.left;
+ src_left->right = src_rect.left + src_width;
+ src_right->left = src_left->right;
+ src_right->right = src_rect.right;
+
+ src_left->top = src_rect.top;
+ src_left->bottom = src_rect.bottom;
+ src_right->top = src_rect.top;
+ src_right->bottom = src_rect.bottom;
+
+ dst_left->top = dst_rect.top;
+ dst_left->bottom = dst_rect.bottom;
+ dst_right->top = dst_rect.top;
+ dst_right->bottom = dst_rect.bottom;
+
+ dst_left->left = dst_rect.left;
+ dst_left->right = dst_rect.left + dst_width;
+ dst_right->left = dst_left->right;
+ dst_right->right = dst_rect.right;
+}
+
+DisplayError ResourceDefault::AlignPipeConfig(const Layer *layer, HWPipeInfo *left_pipe,
+ HWPipeInfo *right_pipe) {
+ DisplayError error = kErrorNone;
+ if (!left_pipe->valid) {
+ DLOGE_IF(kTagResources, "left_pipe should not be invalid");
+ return kErrorNotSupported;
+ }
+
+ error = ValidatePipeParams(left_pipe, layer->input_buffer.format);
+ if (error != kErrorNone) {
+ goto PipeConfigExit;
+ }
+
+ if (right_pipe->valid) {
+ // Make sure the left and right ROI are conjunct
+ right_pipe->src_roi.left = left_pipe->src_roi.right;
+ right_pipe->dst_roi.left = left_pipe->dst_roi.right;
+ error = ValidatePipeParams(right_pipe, layer->input_buffer.format);
+ }
+
+PipeConfigExit:
+ if (error != kErrorNone) {
+ DLOGV_IF(kTagResources, "AlignPipeConfig failed");
+ }
+ return error;
+}
+
+DisplayError ResourceDefault::CalculateDecimation(float downscale, uint8_t *decimation) {
+ float max_down_scale = FLOAT(hw_res_info_.max_scale_down);
+
+ if (downscale <= max_down_scale) {
+ *decimation = 0;
+ return kErrorNone;
+ } else if (!hw_res_info_.has_decimation) {
+ DLOGE("Downscaling exceeds the maximum MDP downscale limit but decimation not enabled");
+ return kErrorNotSupported;
+ }
+
+ // Decimation is the remaining downscale factor after doing max SDE downscale.
+ // In SDE, decimation is supported in powers of 2.
+ // For ex: If a pipe needs downscale of 8 but max_down_scale is 4
+ // So decimation = powf(2.0, ceilf(log2f(8 / 4))) = powf(2.0, 1.0) = 2
+ *decimation = UINT8(ceilf(log2f(downscale / max_down_scale)));
+ return kErrorNone;
+}
+
+DisplayError ResourceDefault::ValidateCursorConfig(Handle display_ctx, const Layer *layer,
+ bool is_top) {
+ return kErrorNotSupported;
+}
+
+DisplayError ResourceDefault::ValidateAndSetCursorPosition(Handle display_ctx, HWLayers *hw_layers,
+ int x, int y,
+ DisplayConfigVariableInfo *fb_config) {
+ return kErrorNotSupported;
+}
+
+DisplayError ResourceDefault::SetMaxBandwidthMode(HWBwModes mode) {
+ return kErrorNotSupported;
+}
+
+DisplayError ResourceDefault::GetScaleLutConfig(HWScaleLutInfo *lut_info) {
+ return kErrorNone;
+}
+
+DisplayError ResourceDefault::SetDetailEnhancerData(Handle display_ctx,
+ const DisplayDetailEnhancerData &de_data) {
+ return kErrorNotSupported;
+}
+
+} // namespace sdm
diff --git a/msm8909/sdm/libs/core/resource_default.h b/msm8909/sdm/libs/core/resource_default.h
new file mode 100644
index 00000000..a67eb09b
--- /dev/null
+++ b/msm8909/sdm/libs/core/resource_default.h
@@ -0,0 +1,150 @@
+/*
+* Copyright (c) 2014 - 2017, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without modification, are permitted
+* provided that the following conditions are met:
+* * Redistributions of source code must retain the above copyright notice, this list of
+* conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright notice, this list of
+* conditions and the following disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its contributors may be used to
+* endorse or promote products derived from this software without specific prior written
+* permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __RESOURCE_DEFAULT_H__
+#define __RESOURCE_DEFAULT_H__
+
+#include <core/display_interface.h>
+#include <private/resource_interface.h>
+#include <utils/locker.h>
+#include <vector>
+
+#include "hw_interface.h"
+
+namespace sdm {
+
+class ResourceDefault : public ResourceInterface {
+ public:
+ static DisplayError CreateResourceDefault(const HWResourceInfo &hw_resource_info,
+ ResourceInterface **resource_intf);
+ static DisplayError DestroyResourceDefault(ResourceInterface *resource_intf);
+ virtual DisplayError RegisterDisplay(DisplayType type,
+ const HWDisplayAttributes &display_attributes,
+ const HWPanelInfo &hw_panel_info,
+ const HWMixerAttributes &mixer_attributes,
+ Handle *display_ctx);
+ virtual DisplayError UnregisterDisplay(Handle display_ctx);
+ virtual DisplayError ReconfigureDisplay(Handle display_ctx,
+ const HWDisplayAttributes &display_attributes,
+ const HWPanelInfo &hw_panel_info,
+ const HWMixerAttributes &mixer_attributes);
+ virtual DisplayError Start(Handle display_ctx);
+ virtual DisplayError Stop(Handle display_ctx, HWLayers *hw_layers);
+ virtual DisplayError Prepare(Handle display_ctx, HWLayers *hw_layers);
+ virtual DisplayError PostPrepare(Handle display_ctx, HWLayers *hw_layers);
+ virtual DisplayError Commit(Handle display_ctx, HWLayers *hw_layers);
+ virtual DisplayError PostCommit(Handle display_ctx, HWLayers *hw_layers);
+ virtual void Purge(Handle display_ctx);
+ virtual DisplayError SetMaxMixerStages(Handle display_ctx, uint32_t max_mixer_stages);
+ virtual DisplayError ValidateScaling(const LayerRect &crop, const LayerRect &dst, bool rotate90,
+ BufferLayout layout, bool use_rotator_downscale);
+ DisplayError ValidateCursorConfig(Handle display_ctx, const Layer *layer, bool is_top);
+ DisplayError ValidateAndSetCursorPosition(Handle display_ctx, HWLayers *hw_layers, int x, int y,
+ DisplayConfigVariableInfo *fb_config);
+ DisplayError SetMaxBandwidthMode(HWBwModes mode);
+ virtual DisplayError SetDetailEnhancerData(Handle display_ctx,
+ const DisplayDetailEnhancerData &de_data);
+ virtual DisplayError Perform(int cmd, ...) { return kErrorNone; }
+
+ private:
+ enum PipeOwner {
+ kPipeOwnerUserMode, // Pipe state when it is available for reservation
+ kPipeOwnerKernelMode, // Pipe state when pipe is owned by kernel
+ };
+
+ // todo: retrieve all these from kernel
+ enum {
+ kMaxDecimationDownScaleRatio = 16,
+ };
+
+ struct SourcePipe {
+ PipeType type;
+ PipeOwner owner;
+ uint32_t mdss_pipe_id;
+ uint32_t index;
+ HWBlockType hw_block_id;
+ int priority;
+
+ SourcePipe() : type(kPipeTypeUnused), owner(kPipeOwnerUserMode), mdss_pipe_id(0),
+ index(0), hw_block_id(kHWBlockMax), priority(0) { }
+
+ inline void ResetState() { hw_block_id = kHWBlockMax;}
+ };
+
+ struct DisplayResourceContext {
+ HWDisplayAttributes display_attributes;
+ HWBlockType hw_block_id;
+ uint64_t frame_count;
+ HWMixerAttributes mixer_attributes;
+
+ DisplayResourceContext() : hw_block_id(kHWBlockMax), frame_count(0) { }
+ };
+
+ struct HWBlockContext {
+ bool is_in_use;
+ HWBlockContext() : is_in_use(false) { }
+ };
+
+ explicit ResourceDefault(const HWResourceInfo &hw_res_info);
+ DisplayError Init();
+ DisplayError Deinit();
+ uint32_t NextPipe(PipeType pipe_type, HWBlockType hw_block_id);
+ uint32_t SearchPipe(HWBlockType hw_block_id, SourcePipe *src_pipes, uint32_t num_pipe);
+ uint32_t GetPipe(HWBlockType hw_block_id, bool need_scale);
+ bool IsScalingNeeded(const HWPipeInfo *pipe_info);
+ DisplayError Config(DisplayResourceContext *display_resource_ctx, HWLayers *hw_layers);
+ DisplayError DisplaySplitConfig(DisplayResourceContext *display_resource_ctx,
+ const LayerRect &src_rect, const LayerRect &dst_rect,
+ HWLayerConfig *layer_config);
+ DisplayError SrcSplitConfig(DisplayResourceContext *display_resource_ctx,
+ const LayerRect &src_rect, const LayerRect &dst_rect,
+ HWLayerConfig *layer_config);
+ bool CalculateCropRects(const LayerRect &scissor, LayerRect *crop, LayerRect *dst);
+ DisplayError ValidateLayerParams(const Layer *layer);
+ DisplayError ValidateDimensions(const LayerRect &crop, const LayerRect &dst);
+ DisplayError ValidatePipeParams(HWPipeInfo *pipe_info, LayerBufferFormat format);
+ DisplayError ValidateDownScaling(float scale_x, float scale_y, bool ubwc_tiled);
+ DisplayError ValidateUpScaling(float scale_x, float scale_y);
+ DisplayError GetScaleFactor(const LayerRect &crop, const LayerRect &dst, float *scale_x,
+ float *scale_y);
+ DisplayError SetDecimationFactor(HWPipeInfo *pipe);
+ void SplitRect(const LayerRect &src_rect, const LayerRect &dst_rect, LayerRect *src_left,
+ LayerRect *dst_left, LayerRect *src_right, LayerRect *dst_right);
+ DisplayError AlignPipeConfig(const Layer *layer, HWPipeInfo *left_pipe,
+ HWPipeInfo *right_pipe);
+ void ResourceStateLog(void);
+ DisplayError CalculateDecimation(float downscale, uint8_t *decimation);
+ DisplayError GetScaleLutConfig(HWScaleLutInfo *lut_info);
+
+ Locker locker_;
+ HWResourceInfo hw_res_info_;
+ HWBlockContext hw_block_ctx_[kHWBlockMax];
+ std::vector<SourcePipe> src_pipes_;
+ uint32_t num_pipe_ = 0;
+};
+
+} // namespace sdm
+
+#endif // __RESOURCE_DEFAULT_H__
+
diff --git a/msm8909/sdm/libs/core/strategy.cpp b/msm8909/sdm/libs/core/strategy.cpp
new file mode 100644
index 00000000..8398bbd4
--- /dev/null
+++ b/msm8909/sdm/libs/core/strategy.cpp
@@ -0,0 +1,265 @@
+/*
+* Copyright (c) 2014 - 2017, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without modification, are permitted
+* provided that the following conditions are met:
+* * Redistributions of source code must retain the above copyright notice, this list of
+* conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright notice, this list of
+* conditions and the following disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its contributors may be used to
+* endorse or promote products derived from this software without specific prior written
+* permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <utils/constants.h>
+#include <utils/debug.h>
+
+#include "strategy.h"
+#include "utils/rect.h"
+
+#define __CLASS__ "Strategy"
+
+namespace sdm {
+
+Strategy::Strategy(ExtensionInterface *extension_intf, BufferAllocator *buffer_allocator,
+ DisplayType type,
+ const HWResourceInfo &hw_resource_info, const HWPanelInfo &hw_panel_info,
+ const HWMixerAttributes &mixer_attributes,
+ const HWDisplayAttributes &display_attributes,
+ const DisplayConfigVariableInfo &fb_config)
+ : extension_intf_(extension_intf), display_type_(type), hw_resource_info_(hw_resource_info),
+ hw_panel_info_(hw_panel_info), mixer_attributes_(mixer_attributes),
+ display_attributes_(display_attributes), fb_config_(fb_config),
+ buffer_allocator_(buffer_allocator) {
+}
+
+DisplayError Strategy::Init() {
+ DisplayError error = kErrorNone;
+
+ if (extension_intf_) {
+ error = extension_intf_->CreateStrategyExtn(display_type_, buffer_allocator_, hw_resource_info_,
+ hw_panel_info_, mixer_attributes_, fb_config_,
+ &strategy_intf_);
+ if (error != kErrorNone) {
+ DLOGE("Failed to create strategy");
+ return error;
+ }
+
+ error = extension_intf_->CreatePartialUpdate(display_type_, hw_resource_info_, hw_panel_info_,
+ mixer_attributes_, display_attributes_, fb_config_,
+ &partial_update_intf_);
+ }
+
+ return kErrorNone;
+}
+
+DisplayError Strategy::Deinit() {
+ if (strategy_intf_) {
+ if (partial_update_intf_) {
+ extension_intf_->DestroyPartialUpdate(partial_update_intf_);
+ }
+
+ extension_intf_->DestroyStrategyExtn(strategy_intf_);
+ }
+
+ return kErrorNone;
+}
+
+DisplayError Strategy::Start(HWLayersInfo *hw_layers_info, uint32_t *max_attempts,
+ const PUConstraints &pu_constraints) {
+ DisplayError error = kErrorNone;
+
+ hw_layers_info_ = hw_layers_info;
+ extn_start_success_ = false;
+ tried_default_ = false;
+
+ if (!disable_gpu_comp_ && !hw_layers_info_->gpu_target_index) {
+ DLOGE("GPU composition is enabled and GPU target buffer not provided.");
+ return kErrorNotSupported;
+ }
+
+ if (partial_update_intf_) {
+ partial_update_intf_->Start(pu_constraints);
+ }
+ GenerateROI();
+
+ if (strategy_intf_) {
+ error = strategy_intf_->Start(hw_layers_info_, max_attempts);
+ if (error == kErrorNone) {
+ extn_start_success_ = true;
+ return kErrorNone;
+ }
+ }
+
+ *max_attempts = 1;
+
+ return kErrorNone;
+}
+
+DisplayError Strategy::Stop() {
+ if (strategy_intf_) {
+ return strategy_intf_->Stop();
+ }
+
+ return kErrorNone;
+}
+
+DisplayError Strategy::GetNextStrategy(StrategyConstraints *constraints) {
+ DisplayError error = kErrorNone;
+
+ if (extn_start_success_) {
+ error = strategy_intf_->GetNextStrategy(constraints);
+ if (error == kErrorNone) {
+ return kErrorNone;
+ }
+ }
+
+ // Do not fallback to GPU if GPU comp is disabled.
+ if (disable_gpu_comp_) {
+ return kErrorNotSupported;
+ }
+
+ // Default composition is already tried.
+ if (tried_default_) {
+ return kErrorUndefined;
+ }
+
+ // Mark all application layers for GPU composition. Find GPU target buffer and store its index for
+ // programming the hardware.
+ LayerStack *layer_stack = hw_layers_info_->stack;
+ for (uint32_t i = 0; i < hw_layers_info_->app_layer_count; i++) {
+ layer_stack->layers.at(i)->composition = kCompositionGPU;
+ layer_stack->layers.at(i)->request.flags.request_flags = 0; // Reset layer request
+ }
+
+ if (!extn_start_success_) {
+ // When mixer resolution and panel resolutions are same (1600x2560) and FB resolution is
+ // 1080x1920 FB_Target destination coordinates(mapped to FB resolution 1080x1920) need to
+ // be mapped to destination coordinates of mixer resolution(1600x2560).
+ Layer *gpu_target_layer = layer_stack->layers.at(hw_layers_info_->gpu_target_index);
+ float layer_mixer_width = FLOAT(mixer_attributes_.width);
+ float layer_mixer_height = FLOAT(mixer_attributes_.height);
+ float fb_width = FLOAT(fb_config_.x_pixels);
+ float fb_height = FLOAT(fb_config_.y_pixels);
+ LayerRect src_domain = (LayerRect){0.0f, 0.0f, fb_width, fb_height};
+ LayerRect dst_domain = (LayerRect){0.0f, 0.0f, layer_mixer_width, layer_mixer_height};
+
+ Layer layer = *gpu_target_layer;
+ hw_layers_info_->index[0] = hw_layers_info_->gpu_target_index;
+ MapRect(src_domain, dst_domain, layer.dst_rect, &layer.dst_rect);
+ hw_layers_info_->hw_layers.clear();
+ hw_layers_info_->hw_layers.push_back(layer);
+ }
+
+ tried_default_ = true;
+
+ return kErrorNone;
+}
+
+void Strategy::GenerateROI() {
+ bool split_display = false;
+
+ if (partial_update_intf_ && partial_update_intf_->GenerateROI(hw_layers_info_) == kErrorNone) {
+ return;
+ }
+
+ float layer_mixer_width = mixer_attributes_.width;
+ float layer_mixer_height = mixer_attributes_.height;
+
+ if (!hw_resource_info_.is_src_split && display_attributes_.is_device_split) {
+ split_display = true;
+ }
+
+ hw_layers_info_->left_frame_roi = {};
+ hw_layers_info_->right_frame_roi = {};
+
+ if (split_display) {
+ float left_split = FLOAT(mixer_attributes_.split_left);
+ hw_layers_info_->left_frame_roi.push_back(LayerRect(0.0f, 0.0f,
+ left_split, layer_mixer_height));
+ hw_layers_info_->right_frame_roi.push_back(LayerRect(left_split,
+ 0.0f, layer_mixer_width, layer_mixer_height));
+ } else {
+ hw_layers_info_->left_frame_roi.push_back(LayerRect(0.0f, 0.0f,
+ layer_mixer_width, layer_mixer_height));
+ hw_layers_info_->right_frame_roi.push_back(LayerRect(0.0f, 0.0f, 0.0f, 0.0f));
+ }
+}
+
+DisplayError Strategy::Reconfigure(const HWPanelInfo &hw_panel_info,
+ const HWDisplayAttributes &display_attributes,
+ const HWMixerAttributes &mixer_attributes,
+ const DisplayConfigVariableInfo &fb_config) {
+ DisplayError error = kErrorNone;
+
+ if (!extension_intf_) {
+ return kErrorNone;
+ }
+
+ // TODO(user): PU Intf will not be created for video mode panels, hence re-evaluate if
+ // reconfigure is needed.
+ if (partial_update_intf_) {
+ extension_intf_->DestroyPartialUpdate(partial_update_intf_);
+ partial_update_intf_ = NULL;
+ }
+
+ extension_intf_->CreatePartialUpdate(display_type_, hw_resource_info_, hw_panel_info,
+ mixer_attributes, display_attributes, fb_config,
+ &partial_update_intf_);
+
+ error = strategy_intf_->Reconfigure(hw_panel_info, hw_resource_info_, mixer_attributes,
+ fb_config);
+ if (error != kErrorNone) {
+ return error;
+ }
+
+ hw_panel_info_ = hw_panel_info;
+ display_attributes_ = display_attributes;
+ mixer_attributes_ = mixer_attributes;
+ fb_config_ = fb_config;
+
+ return kErrorNone;
+}
+
+DisplayError Strategy::SetCompositionState(LayerComposition composition_type, bool enable) {
+ DLOGI("composition type = %d, enable = %d", composition_type, enable);
+
+ if (composition_type == kCompositionGPU) {
+ disable_gpu_comp_ = !enable;
+ }
+
+ if (strategy_intf_) {
+ return strategy_intf_->SetCompositionState(composition_type, enable);
+ }
+
+ return kErrorNone;
+}
+
+DisplayError Strategy::Purge() {
+ if (strategy_intf_) {
+ return strategy_intf_->Purge();
+ }
+
+ return kErrorNone;
+}
+
+DisplayError Strategy::SetIdleTimeoutMs(uint32_t active_ms) {
+ if (strategy_intf_) {
+ return strategy_intf_->SetIdleTimeoutMs(active_ms);
+ }
+
+ return kErrorNotSupported;
+}
+
+} // namespace sdm
diff --git a/msm8909/sdm/libs/core/strategy.h b/msm8909/sdm/libs/core/strategy.h
new file mode 100644
index 00000000..f05f66b6
--- /dev/null
+++ b/msm8909/sdm/libs/core/strategy.h
@@ -0,0 +1,79 @@
+/*
+* Copyright (c) 2014 - 2017, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without modification, are permitted
+* provided that the following conditions are met:
+* * Redistributions of source code must retain the above copyright notice, this list of
+* conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright notice, this list of
+* conditions and the following disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its contributors may be used to
+* endorse or promote products derived from this software without specific prior written
+* permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __STRATEGY_H__
+#define __STRATEGY_H__
+
+#include <core/display_interface.h>
+#include <private/extension_interface.h>
+#include <core/buffer_allocator.h>
+
+namespace sdm {
+
+class Strategy {
+ public:
+ Strategy(ExtensionInterface *extension_intf, BufferAllocator *buffer_allocator,
+ DisplayType type,
+ const HWResourceInfo &hw_resource_info, const HWPanelInfo &hw_panel_info,
+ const HWMixerAttributes &mixer_attributes, const HWDisplayAttributes &display_attributes,
+ const DisplayConfigVariableInfo &fb_config);
+
+ DisplayError Init();
+ DisplayError Deinit();
+
+ DisplayError Start(HWLayersInfo *hw_layers_info, uint32_t *max_attempts,
+ const PUConstraints &pu_constraints);
+ DisplayError GetNextStrategy(StrategyConstraints *constraints);
+ DisplayError Stop();
+ DisplayError Reconfigure(const HWPanelInfo &hw_panel_info,
+ const HWDisplayAttributes &hw_display_attributes,
+ const HWMixerAttributes &mixer_attributes,
+ const DisplayConfigVariableInfo &fb_config);
+ DisplayError SetCompositionState(LayerComposition composition_type, bool enable);
+ DisplayError Purge();
+ DisplayError SetIdleTimeoutMs(uint32_t active_ms);
+
+ private:
+ void GenerateROI();
+
+ ExtensionInterface *extension_intf_ = NULL;
+ StrategyInterface *strategy_intf_ = NULL;
+ PartialUpdateInterface *partial_update_intf_ = NULL;
+ DisplayType display_type_;
+ HWResourceInfo hw_resource_info_;
+ HWPanelInfo hw_panel_info_;
+ HWLayersInfo *hw_layers_info_ = NULL;
+ HWMixerAttributes mixer_attributes_ = {};
+ HWDisplayAttributes display_attributes_ = {};
+ DisplayConfigVariableInfo fb_config_ = {};
+ bool extn_start_success_ = false;
+ bool tried_default_ = false;
+ bool disable_gpu_comp_ = false;
+ BufferAllocator *buffer_allocator_ = NULL;
+};
+
+} // namespace sdm
+
+#endif // __STRATEGY_H__
+
diff --git a/msm8909/sdm/libs/hwc/Android.mk b/msm8909/sdm/libs/hwc/Android.mk
new file mode 100644
index 00000000..a2142e33
--- /dev/null
+++ b/msm8909/sdm/libs/hwc/Android.mk
@@ -0,0 +1,39 @@
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+include $(LOCAL_PATH)/../../../common.mk
+ifeq ($(use_hwc2),false)
+
+LOCAL_MODULE := hwcomposer.$(TARGET_BOARD_PLATFORM)
+LOCAL_VENDOR_MODULE := true
+LOCAL_MODULE_RELATIVE_PATH := hw
+LOCAL_MODULE_TAGS := optional
+LOCAL_C_INCLUDES := $(common_includes)
+LOCAL_HEADER_LIBRARIES := display_headers
+
+LOCAL_CFLAGS := $(common_flags) -Wno-missing-field-initializers -Wno-unused-parameter \
+ -std=c++11 -fcolor-diagnostics -Wno-sign-conversion -DLOG_TAG=\"SDM\"
+LOCAL_CLANG := true
+
+LOCAL_SHARED_LIBRARIES := libsdmcore libqservice libbinder libhardware libhardware_legacy \
+ libutils libcutils libsync libmemalloc libqdutils libdl \
+ libpowermanager libsdmutils libgpu_tonemapper libc++ liblog \
+ libdrmutils libui
+
+LOCAL_SRC_FILES := hwc_session.cpp \
+ hwc_display.cpp \
+ hwc_display_null.cpp \
+ hwc_display_primary.cpp \
+ hwc_display_external.cpp \
+ hwc_display_virtual.cpp \
+ hwc_debugger.cpp \
+ hwc_buffer_allocator.cpp \
+ hwc_buffer_sync_handler.cpp \
+ hwc_color_manager.cpp \
+ blit_engine_c2d.cpp \
+ cpuhint.cpp \
+ hwc_tonemapper.cpp \
+ hwc_socket_handler.cpp \
+ hwc_display_external_test.cpp
+
+include $(BUILD_SHARED_LIBRARY)
+endif
diff --git a/msm8909/sdm/libs/hwc/blit_engine.h b/msm8909/sdm/libs/hwc/blit_engine.h
new file mode 100644
index 00000000..6fa9733e
--- /dev/null
+++ b/msm8909/sdm/libs/hwc/blit_engine.h
@@ -0,0 +1,66 @@
+/*
+* Copyright (c) 2015, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*! @file blit_engine.h
+ @brief Interface file for Blit based compositior.
+
+ @details The client can use this interface to get the blit composition done
+
+*/
+
+#ifndef __BLIT_ENGINE_H__
+#define __BLIT_ENGINE_H__
+
+namespace sdm {
+
+/*! @brief Blit Engine implemented by the client
+
+ @details This class declares prototype for BlitEngine Interface which must be
+ implemented by the client. HWC will use this interface to use a Blit engine to get the
+ composition done.
+
+*/
+class BlitEngine {
+ public:
+ BlitEngine() { }
+ virtual ~BlitEngine() { }
+
+ virtual int Init() = 0;
+ virtual void DeInit() = 0;
+ virtual int Prepare(LayerStack *layer_stack) = 0;
+ virtual int PreCommit(hwc_display_contents_1_t *content_list, LayerStack *layer_stack) = 0;
+ virtual int Commit(hwc_display_contents_1_t *content_list, LayerStack *layer_stack) = 0;
+ virtual void PostCommit(LayerStack *layer_stack) = 0;
+ virtual bool BlitActive() = 0;
+ virtual void SetFrameDumpConfig(uint32_t count) = 0;
+};
+
+} // namespace sdm
+
+#endif // __BLIT_ENGINE_H__
diff --git a/msm8909/sdm/libs/hwc/blit_engine_c2d.cpp b/msm8909/sdm/libs/hwc/blit_engine_c2d.cpp
new file mode 100644
index 00000000..4efe2f1a
--- /dev/null
+++ b/msm8909/sdm/libs/hwc/blit_engine_c2d.cpp
@@ -0,0 +1,608 @@
+/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+* Portions formerly licensed under Apache License, Version 2.0, are re licensed
+* under section 4 of Apache License, Version 2.0.
+
+* Copyright (C) 2010 The Android Open Source Project
+
+* Not a Contribution.
+
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+
+* http://www.apache.org/licenses/LICENSE-2.0
+
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#include <hardware/hardware.h>
+#include <sync/sync.h>
+#include <copybit.h>
+#include <memalloc.h>
+#include <alloc_controller.h>
+#include <gr.h>
+
+#include <utils/constants.h>
+#include <utils/rect.h>
+#include <utils/formats.h>
+#include <algorithm>
+
+#include "blit_engine_c2d.h"
+#include "hwc_debugger.h"
+
+#define __CLASS__ "BlitEngineC2D"
+
+// TODO(user): Remove pragma after fixing sign conversion errors
+#if defined(__clang__)
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wsign-conversion"
+#endif
+
+namespace sdm {
+
+
+BlitEngineC2d::RegionIterator::RegionIterator(LayerRectArray rect) {
+ rect_array = rect;
+ r.end = INT(rect.count);
+ r.current = 0;
+ this->next = iterate;
+}
+
+int BlitEngineC2d::RegionIterator::iterate(copybit_region_t const *self, copybit_rect_t *rect) {
+ if (!self || !rect) {
+ DLOGE("iterate invalid parameters");
+ return 0;
+ }
+
+ RegionIterator const *me = static_cast<RegionIterator const*>(self);
+ if (me->r.current != me->r.end) {
+ rect->l = INT(me->rect_array.rect[me->r.current].left);
+ rect->t = INT(me->rect_array.rect[me->r.current].top);
+ rect->r = INT(me->rect_array.rect[me->r.current].right);
+ rect->b = INT(me->rect_array.rect[me->r.current].bottom);
+ me->r.current++;
+ return 1;
+ }
+ return 0;
+}
+
+BlitEngineC2d::BlitEngineC2d() {
+ for (uint32_t i = 0; i < kNumBlitTargetBuffers; i++) {
+ blit_target_buffer_[i] = NULL;
+ release_fence_fd_[i] = -1;
+ }
+}
+
+BlitEngineC2d::~BlitEngineC2d() {
+ if (blit_engine_c2d_) {
+ copybit_close(blit_engine_c2d_);
+ blit_engine_c2d_ = NULL;
+ }
+ FreeBlitTargetBuffers();
+}
+
+int BlitEngineC2d::Init() {
+ hw_module_t const *module;
+ if (hw_get_module("copybit", &module) == 0) {
+ if (copybit_open(module, &blit_engine_c2d_) < 0) {
+ DLOGI("CopyBitC2D Open failed.");
+ return -1;
+ }
+ DLOGI("Opened Copybit Module");
+ } else {
+ DLOGI("Copybit HW Module not found");
+ return -1;
+ }
+
+ return 0;
+}
+
+void BlitEngineC2d::DeInit() {
+ FreeBlitTargetBuffers();
+ if (blit_engine_c2d_) {
+ copybit_close(blit_engine_c2d_);
+ blit_engine_c2d_ = NULL;
+ }
+}
+
+int BlitEngineC2d::AllocateBlitTargetBuffers(uint32_t width, uint32_t height, uint32_t format,
+ uint32_t usage) {
+ int status = 0;
+ if (width <= 0 || height <= 0) {
+ return false;
+ }
+
+ if (blit_target_buffer_[0]) {
+ // Free and reallocate the buffers if the w/h changes
+ if (INT(width) != blit_target_buffer_[0]->width ||
+ INT(height) != blit_target_buffer_[0]->height) {
+ FreeBlitTargetBuffers();
+ }
+ }
+
+ for (uint32_t i = 0; i < kNumBlitTargetBuffers; i++) {
+ if (blit_target_buffer_[i] == NULL) {
+ status = alloc_buffer(&blit_target_buffer_[i], width, height, format, usage);
+ }
+ if (status < 0) {
+ DLOGE("Allocation of Blit target Buffer failed");
+ FreeBlitTargetBuffers();
+ break;
+ }
+ }
+
+ return status;
+}
+
+void BlitEngineC2d::FreeBlitTargetBuffers() {
+ for (uint32_t i = 0; i < kNumBlitTargetBuffers; i++) {
+ private_handle_t **target_buffer = &blit_target_buffer_[i];
+ if (*target_buffer) {
+ // Free the valid fence
+ if (release_fence_fd_[i] >= 0) {
+ close(release_fence_fd_[i]);
+ release_fence_fd_[i] = -1;
+ }
+ free_buffer(*target_buffer);
+ *target_buffer = NULL;
+ }
+ }
+}
+
+int BlitEngineC2d::ClearTargetBuffer(private_handle_t* hnd, const LayerRect& rect) {
+ int status = 0;
+ copybit_rect_t clear_rect = {INT(rect.left), INT(rect.top), INT(rect.right), INT(rect.bottom)};
+
+ copybit_image_t buffer;
+ buffer.w = ALIGN((hnd->width), 32);
+ buffer.h = hnd->height;
+ buffer.format = hnd->format;
+ buffer.base = reinterpret_cast<void *>(hnd->base);
+ buffer.handle = reinterpret_cast<native_handle_t *>(hnd);
+ int dst_format_mode = COPYBIT_LINEAR;
+ if (hnd->flags & private_handle_t::PRIV_FLAGS_UBWC_ALIGNED) {
+ dst_format_mode = COPYBIT_UBWC_COMPRESSED;
+ }
+ blit_engine_c2d_->set_parameter(blit_engine_c2d_, COPYBIT_DST_FORMAT_MODE, dst_format_mode);
+
+ status = blit_engine_c2d_->clear(blit_engine_c2d_, &buffer, &clear_rect);
+ return status;
+}
+
+void BlitEngineC2d::PostCommit(LayerStack *layer_stack) {
+ int fence_fd = -1;
+ uint32_t count = 0;
+ int fd = -1;
+
+ for (uint32_t i = blit_target_start_index_-2; (i > 0) && (count < num_blit_target_); i--) {
+ Layer *layer = layer_stack->layers.at(i);
+ LayerBuffer &layer_buffer = layer->input_buffer;
+ if (layer->composition == kCompositionBlit) {
+ int index = blit_target_start_index_ + count;
+ layer_buffer.release_fence_fd =
+ layer_stack->layers.at(index)->input_buffer.release_fence_fd;
+ fence_fd = layer_buffer.release_fence_fd;
+ close(layer_buffer.acquire_fence_fd);
+ layer_buffer.acquire_fence_fd = -1;
+ layer_stack->layers.at(index)->input_buffer.release_fence_fd = -1;
+ fd = layer_stack->layers.at(index)->input_buffer.acquire_fence_fd;
+ layer_stack->layers.at(index)->input_buffer.acquire_fence_fd = -1;
+ count++;
+ }
+ }
+
+ if (fd >= 0) {
+ // Close the C2D fence FD
+ close(fd);
+ }
+ SetReleaseFence(fence_fd);
+}
+
+// Sync wait to close the previous fd
+void BlitEngineC2d::SetReleaseFence(int fd) {
+ if (release_fence_fd_[current_blit_target_index_] >= 0) {
+ int ret = -1;
+ ret = sync_wait(release_fence_fd_[current_blit_target_index_], 1000);
+ if (ret < 0) {
+ DLOGE("sync_wait error! errno = %d, err str = %s", errno, strerror(errno));
+ }
+ close(release_fence_fd_[current_blit_target_index_]);
+ }
+ release_fence_fd_[current_blit_target_index_] = dup(fd);
+}
+
+bool BlitEngineC2d::BlitActive() {
+ return blit_active_;
+}
+
+void BlitEngineC2d::SetFrameDumpConfig(uint32_t count) {
+ dump_frame_count_ = count;
+ dump_frame_index_ = 0;
+}
+
+int BlitEngineC2d::Prepare(LayerStack *layer_stack) {
+ blit_target_start_index_ = 0;
+
+ uint32_t layer_count = UINT32(layer_stack->layers.size());
+ uint32_t gpu_target_index = layer_count - 1; // default assumption
+ uint32_t i = 0;
+
+ for (; i < layer_count; i++) {
+ Layer *layer = layer_stack->layers.at(i);
+
+ // No 10 bit support for C2D
+ if (Is10BitFormat(layer->input_buffer.format)) {
+ return -1;
+ }
+
+ if (layer->composition == kCompositionGPUTarget) {
+ // Need FBT size for allocating buffers
+ gpu_target_index = i;
+ break;
+ }
+ }
+
+ if ((layer_count - 1) == gpu_target_index) {
+ // No blit target layer
+ return -1;
+ }
+
+ blit_target_start_index_ = ++i;
+ num_blit_target_ = layer_count - blit_target_start_index_;
+
+ LayerBuffer &layer_buffer = layer_stack->layers.at(gpu_target_index)->input_buffer;
+ int fbwidth = INT(layer_buffer.unaligned_width);
+ int fbheight = INT(layer_buffer.unaligned_height);
+ if ((fbwidth < 0) || (fbheight < 0)) {
+ return -1;
+ }
+
+ current_blit_target_index_ = (current_blit_target_index_ + 1) % kNumBlitTargetBuffers;
+ int k = blit_target_start_index_;
+
+ for (uint32_t j = 0; j < num_blit_target_; j++, k++) {
+ Layer *layer = layer_stack->layers.at(k);
+ LayerBuffer &layer_buffer = layer->input_buffer;
+ int aligned_w = 0;
+ int aligned_h = 0;
+
+ // Set the buffer height and width
+ AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(fbwidth, fbheight/3,
+ INT(HAL_PIXEL_FORMAT_RGBA_8888), 0, aligned_w, aligned_h);
+ layer_buffer.width = aligned_w;
+ layer_buffer.height = aligned_h;
+ layer_buffer.unaligned_width = fbwidth;
+ layer_buffer.unaligned_height = fbheight/3;
+
+ layer->plane_alpha = 0xFF;
+ layer->blending = kBlendingOpaque;
+ layer->composition = kCompositionBlitTarget;
+ layer->frame_rate = layer_stack->layers.at(gpu_target_index)->frame_rate;
+ }
+
+ return 0;
+}
+
+int BlitEngineC2d::PreCommit(hwc_display_contents_1_t *content_list, LayerStack *layer_stack) {
+ int status = 0;
+ uint32_t num_app_layers = (uint32_t) content_list->numHwLayers-1;
+ int target_width = 0;
+ int target_height = 0;
+ int target_aligned_width = 0;
+ int target_aligned_height = 0;
+ uint32_t processed_blit = 0;
+ LayerRect dst_rects[kMaxBlitTargetLayers];
+ bool blit_needed = false;
+ uint32_t usage = 0;
+
+ if (!num_app_layers) {
+ return -1;
+ }
+
+ for (uint32_t i = num_app_layers-1; (i > 0) && (processed_blit < num_blit_target_); i--) {
+ Layer *layer = layer_stack->layers.at(i);
+ if (layer->composition != kCompositionBlit) {
+ continue;
+ }
+ blit_needed = true;
+ layer_stack->flags.attributes_changed = true;
+
+ Layer *blit_layer = layer_stack->layers.at(blit_target_start_index_ + processed_blit);
+ LayerRect &blit_src_rect = blit_layer->src_rect;
+ int width = INT(layer->dst_rect.right - layer->dst_rect.left);
+ int height = INT(layer->dst_rect.bottom - layer->dst_rect.top);
+ int aligned_w = 0;
+ int aligned_h = 0;
+ usage = GRALLOC_USAGE_PRIVATE_IOMMU_HEAP | GRALLOC_USAGE_HW_TEXTURE;
+ if (blit_engine_c2d_->get(blit_engine_c2d_, COPYBIT_UBWC_SUPPORT) > 0) {
+ usage |= GRALLOC_USAGE_PRIVATE_ALLOC_UBWC;
+ }
+ // TODO(user): FrameBuffer is assumed to be RGBA
+ target_width = std::max(target_width, width);
+ target_height += height;
+
+ AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(width, height,
+ INT(HAL_PIXEL_FORMAT_RGBA_8888), usage, aligned_w, aligned_h);
+
+ target_aligned_width = std::max(target_aligned_width, aligned_w);
+ target_aligned_height += aligned_h;
+
+ // Left will be zero always
+ dst_rects[processed_blit].top = FLOAT(target_aligned_height - aligned_h);
+ dst_rects[processed_blit].right = dst_rects[processed_blit].left +
+ (layer->dst_rect.right - layer->dst_rect.left);
+ dst_rects[processed_blit].bottom = (dst_rects[processed_blit].top +
+ (layer->dst_rect.bottom - layer->dst_rect.top));
+ blit_src_rect = dst_rects[processed_blit];
+ processed_blit++;
+ }
+
+ // Allocate a single buffer of RGBA8888 format
+ if (blit_needed && (AllocateBlitTargetBuffers(target_width, target_height,
+ HAL_PIXEL_FORMAT_RGBA_8888, usage) < 0)) {
+ status = -1;
+ return status;
+ }
+
+ if (blit_needed) {
+ for (uint32_t j = 0; j < num_blit_target_; j++) {
+ Layer *layer = layer_stack->layers.at(j + content_list->numHwLayers);
+ private_handle_t *target_buffer = blit_target_buffer_[current_blit_target_index_];
+ // Set the fd information
+ layer->input_buffer.width = target_aligned_width;
+ layer->input_buffer.height = target_aligned_height;
+ layer->input_buffer.unaligned_width = target_width;
+ layer->input_buffer.unaligned_height = target_height;
+ if (target_buffer->flags & private_handle_t::PRIV_FLAGS_UBWC_ALIGNED) {
+ layer->input_buffer.format = kFormatRGBA8888Ubwc;
+ }
+ layer->input_buffer.planes[0].fd = target_buffer->fd;
+ layer->input_buffer.planes[0].offset = 0;
+ layer->input_buffer.planes[0].stride = target_buffer->width;
+ }
+ }
+
+ return status;
+}
+
+int BlitEngineC2d::Commit(hwc_display_contents_1_t *content_list, LayerStack *layer_stack) {
+ int fd = -1;
+ int status = 0;
+ bool hybrid_present = false;
+ uint32_t num_app_layers = (uint32_t) content_list->numHwLayers-1;
+ private_handle_t *target_buffer = blit_target_buffer_[current_blit_target_index_];
+ blit_active_ = false;
+
+ if (!num_app_layers) {
+ return -1;
+ }
+
+ // if not Blit Targets return
+ for (uint32_t i = 0; i < num_app_layers; i++) {
+ Layer *layer = layer_stack->layers.at(i);
+ if (layer->composition == kCompositionHybrid || layer->composition == kCompositionBlit) {
+ hybrid_present = true;
+ }
+ }
+
+ if (!hybrid_present) {
+ return status;
+ }
+
+ // Clear blit target buffer
+ LayerRect clear_rect;
+ clear_rect.left = 0;
+ clear_rect.top = 0;
+ clear_rect.right = FLOAT(target_buffer->width);
+ clear_rect.bottom = FLOAT(target_buffer->height);
+ ClearTargetBuffer(target_buffer, clear_rect);
+
+ int copybit_layer_count = 0;
+ uint32_t processed_blit = 0;
+ for (uint32_t i = num_app_layers-1; (i > 0) && (processed_blit < num_blit_target_) &&
+ (status == 0); i--) {
+ Layer *layer = layer_stack->layers.at(i);
+ if (layer->composition != kCompositionBlit) {
+ continue;
+ }
+
+ for (uint32_t k = 0; k <= i; k++) {
+ Layer *bottom_layer = layer_stack->layers.at(k);
+ LayerBuffer &layer_buffer = bottom_layer->input_buffer;
+ // if layer below the blit layer does not intersect, ignore that layer
+ LayerRect inter_sect = Intersection(layer->dst_rect, bottom_layer->dst_rect);
+ if (bottom_layer->composition != kCompositionHybrid && !IsValid(inter_sect)) {
+ continue;
+ }
+ if (bottom_layer->composition == kCompositionGPU ||
+ bottom_layer->composition == kCompositionSDE ||
+ bottom_layer->composition == kCompositionGPUTarget) {
+ continue;
+ }
+
+ // For each layer marked as Hybrid, wait for acquire fence and then blit using the C2D
+ if (layer_buffer.acquire_fence_fd >= 0) {
+ // Wait for acquire fence on the App buffers.
+ if (sync_wait(layer_buffer.acquire_fence_fd, 1000) < 0) {
+ DLOGE("sync_wait error!! error no = %d err str = %s", errno, strerror(errno));
+ }
+ layer_buffer.acquire_fence_fd = -1;
+ }
+ hwc_layer_1_t *hwc_layer = &content_list->hwLayers[k];
+ LayerRect &src_rect = bottom_layer->blit_regions.at(processed_blit);
+ Layer *blit_layer = layer_stack->layers.at(blit_target_start_index_ + processed_blit);
+ LayerRect dest_rect = blit_layer->src_rect;
+ int ret_val = DrawRectUsingCopybit(hwc_layer, bottom_layer, src_rect, dest_rect);
+ copybit_layer_count++;
+ if (ret_val < 0) {
+ copybit_layer_count = 0;
+ DLOGE("DrawRectUsingCopyBit failed");
+ status = -1;
+ break;
+ }
+ }
+ processed_blit++;
+ }
+
+ if (copybit_layer_count) {
+ blit_active_ = true;
+ blit_engine_c2d_->flush_get_fence(blit_engine_c2d_, &fd);
+ }
+
+ if (blit_active_) {
+ // dump the render buffer
+ DumpBlitTargetBuffer(fd);
+
+ // Set the fd to the LayerStack BlitTargets fd
+ uint32_t layer_count = UINT32(layer_stack->layers.size());
+ for (uint32_t k = blit_target_start_index_; k < layer_count; k++) {
+ Layer *layer = layer_stack->layers.at(k);
+ LayerBuffer &layer_buffer = layer->input_buffer;
+ layer_buffer.acquire_fence_fd = fd;
+ }
+ }
+
+ return status;
+}
+
+int BlitEngineC2d::DrawRectUsingCopybit(hwc_layer_1_t *hwc_layer, Layer *layer,
+ LayerRect blit_rect, LayerRect blit_dest_Rect) {
+ private_handle_t *target_buffer = blit_target_buffer_[current_blit_target_index_];
+ const private_handle_t *hnd = static_cast<const private_handle_t *>(hwc_layer->handle);
+ LayerBuffer &layer_buffer = layer->input_buffer;
+
+ // Set the Copybit Source
+ copybit_image_t src;
+ src.handle = const_cast<native_handle_t *>(hwc_layer->handle);
+ src.w = hnd->width;
+ src.h = hnd->height;
+ src.base = reinterpret_cast<void *>(hnd->base);
+ src.format = hnd->format;
+ src.horiz_padding = 0;
+ src.vert_padding = 0;
+
+ // Copybit source rect
+ copybit_rect_t src_rect = {INT(blit_rect.left), INT(blit_rect.top), INT(blit_rect.right),
+ INT(blit_rect.bottom)};
+
+ // Copybit destination rect
+ copybit_rect_t dst_rect = {INT(blit_dest_Rect.left), INT(blit_dest_Rect.top),
+ INT(blit_dest_Rect.right), INT(blit_dest_Rect.bottom)};
+
+ // Copybit destination buffer
+ copybit_image_t dst;
+ dst.handle = static_cast<native_handle_t *>(target_buffer);
+ dst.w = ALIGN(target_buffer->width, 32);
+ dst.h = ALIGN((target_buffer->height), 32);
+ dst.base = reinterpret_cast<void *>(target_buffer->base);
+ dst.format = target_buffer->format;
+
+ // Copybit region is the destRect
+ LayerRect region_rect;
+ region_rect.left = FLOAT(dst_rect.l);
+ region_rect.top = FLOAT(dst_rect.t);
+ region_rect.right = FLOAT(dst_rect.r);
+ region_rect.bottom = FLOAT(dst_rect.b);
+
+ LayerRectArray region;
+ region.count = 1;
+ region.rect = &region_rect;
+ RegionIterator copybitRegion(region);
+ int acquireFd = layer_buffer.acquire_fence_fd;
+
+ // FRAMEBUFFER_WIDTH/HEIGHT for c2d is the target buffer w/h
+ blit_engine_c2d_->set_parameter(blit_engine_c2d_, COPYBIT_FRAMEBUFFER_WIDTH,
+ target_buffer->width);
+ blit_engine_c2d_->set_parameter(blit_engine_c2d_, COPYBIT_FRAMEBUFFER_HEIGHT,
+ target_buffer->height);
+ int transform = 0;
+ if (layer->transform.rotation != 0.0f) transform |= COPYBIT_TRANSFORM_ROT_90;
+ if (layer->transform.flip_horizontal) transform |= COPYBIT_TRANSFORM_FLIP_H;
+ if (layer->transform.flip_vertical) transform |= COPYBIT_TRANSFORM_FLIP_V;
+ blit_engine_c2d_->set_parameter(blit_engine_c2d_, COPYBIT_TRANSFORM, transform);
+ blit_engine_c2d_->set_parameter(blit_engine_c2d_, COPYBIT_PLANE_ALPHA, hwc_layer->planeAlpha);
+ blit_engine_c2d_->set_parameter(blit_engine_c2d_, COPYBIT_BLEND_MODE, hwc_layer->blending);
+ blit_engine_c2d_->set_parameter(blit_engine_c2d_, COPYBIT_DITHER,
+ (dst.format == HAL_PIXEL_FORMAT_RGB_565) ? COPYBIT_ENABLE : COPYBIT_DISABLE);
+
+ int src_format_mode = COPYBIT_LINEAR;
+ if (hnd->flags & private_handle_t::PRIV_FLAGS_UBWC_ALIGNED) {
+ src_format_mode = COPYBIT_UBWC_COMPRESSED;
+ }
+ blit_engine_c2d_->set_parameter(blit_engine_c2d_, COPYBIT_SRC_FORMAT_MODE, src_format_mode);
+
+ blit_engine_c2d_->set_sync(blit_engine_c2d_, acquireFd);
+ int err = blit_engine_c2d_->stretch(blit_engine_c2d_, &dst, &src, &dst_rect, &src_rect,
+ &copybitRegion);
+
+ if (err < 0) {
+ DLOGE("copybit stretch failed");
+ }
+
+ return err;
+}
+
+void BlitEngineC2d::DumpBlitTargetBuffer(int fd) {
+ if (!dump_frame_count_) {
+ return;
+ }
+
+ private_handle_t *target_buffer = blit_target_buffer_[current_blit_target_index_];
+
+ if (fd >= 0) {
+ int error = sync_wait(fd, 1000);
+ if (error < 0) {
+ DLOGW("sync_wait error errno = %d, desc = %s", errno, strerror(errno));
+ return;
+ }
+ }
+
+ char dump_file_name[PATH_MAX];
+ size_t result = 0;
+ snprintf(dump_file_name, sizeof(dump_file_name), "/data/misc/display/frame_dump_primary"
+ "/blit_target_%d.raw", (dump_frame_index_));
+ FILE* fp = fopen(dump_file_name, "w+");
+ if (fp) {
+ result = fwrite(reinterpret_cast<void *>(target_buffer->base), target_buffer->size, 1, fp);
+ fclose(fp);
+ }
+ dump_frame_count_--;
+ dump_frame_index_++;
+}
+
+} // namespace sdm
+#if defined(__clang__)
+#pragma clang diagnostic pop
+#endif
+
diff --git a/msm8909/sdm/libs/hwc/blit_engine_c2d.h b/msm8909/sdm/libs/hwc/blit_engine_c2d.h
new file mode 100644
index 00000000..6536d442
--- /dev/null
+++ b/msm8909/sdm/libs/hwc/blit_engine_c2d.h
@@ -0,0 +1,121 @@
+/* Copyright (c) 2012 - 2016, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+* Portions formerly licensed under Apache License, Version 2.0, are re licensed
+* under section 4 of Apache License, Version 2.0.
+
+* Copyright (C) 2010 The Android Open Source Project
+
+* Not a Contribution.
+
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+
+* http://www.apache.org/licenses/LICENSE-2.0
+
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+/*! @file blit_engine.h
+ @brief Interface file for Blit based compositior.
+
+ @details The client can use this interface to get the blit composition done
+
+*/
+
+#include <hardware/hwcomposer.h>
+#include <core/layer_stack.h>
+#include <copybit.h>
+#include "blit_engine.h"
+
+#ifndef __BLIT_ENGINE_C2D_H__
+#define __BLIT_ENGINE_C2D_H__
+
+namespace sdm {
+
+// C2D Blit implemented by the client
+// This class implements the BlitEngine Interface which is used to get the
+// Blit composition using C2D
+class BlitEngineC2d : public BlitEngine {
+ public:
+ BlitEngineC2d();
+ virtual ~BlitEngineC2d();
+
+ virtual int Init();
+ virtual void DeInit();
+ virtual int Prepare(LayerStack *layer_stack);
+ virtual int PreCommit(hwc_display_contents_1_t *content_list, LayerStack *layer_stack);
+ virtual int Commit(hwc_display_contents_1_t *content_list, LayerStack *layer_stack);
+ virtual void PostCommit(LayerStack *layer_stack);
+ virtual bool BlitActive();
+ virtual void SetFrameDumpConfig(uint32_t count);
+
+
+ private:
+ static const uint32_t kNumBlitTargetBuffers = 3;
+
+ struct Range {
+ int current;
+ int end;
+ };
+
+ struct RegionIterator : public copybit_region_t {
+ explicit RegionIterator(LayerRectArray rect);
+ private:
+ static int iterate(copybit_region_t const *self, copybit_rect_t *rect);
+ LayerRectArray rect_array;
+ mutable Range r;
+ };
+
+ int AllocateBlitTargetBuffers(uint32_t width, uint32_t height, uint32_t format, uint32_t usage);
+ void FreeBlitTargetBuffers();
+ int ClearTargetBuffer(private_handle_t* hnd, const LayerRect& rect);
+ int DrawRectUsingCopybit(hwc_layer_1_t *hwc_layer, Layer *layer, LayerRect blit_rect,
+ LayerRect blit_dest_Rect);
+ void SetReleaseFence(int fence_fd);
+ void DumpBlitTargetBuffer(int fd);
+
+ copybit_device_t *blit_engine_c2d_ = NULL;
+ private_handle_t *blit_target_buffer_[kNumBlitTargetBuffers];
+ uint32_t current_blit_target_index_ = 0;
+ int release_fence_fd_[kNumBlitTargetBuffers];
+ uint32_t num_blit_target_ = 0;
+ int blit_target_start_index_ = 0;
+ bool blit_active_ = false;
+ uint32_t dump_frame_count_ = 0;
+ uint32_t dump_frame_index_ = 0;
+};
+
+} // namespace sdm
+
+#endif // __BLIT_ENGINE_C2D_H__
diff --git a/msm8909/sdm/libs/hwc/cpuhint.cpp b/msm8909/sdm/libs/hwc/cpuhint.cpp
new file mode 100644
index 00000000..2675c9bf
--- /dev/null
+++ b/msm8909/sdm/libs/hwc/cpuhint.cpp
@@ -0,0 +1,108 @@
+/* Copyright (c) 2015,2018 The Linux Foundataion. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+*/
+
+#include <cutils/properties.h>
+#include <dlfcn.h>
+#include <utils/debug.h>
+
+#include "cpuhint.h"
+#include "hwc_debugger.h"
+
+#define __CLASS__ "CPUHint"
+
+namespace sdm {
+
+DisplayError CPUHint::Init(HWCDebugHandler *debug_handler) {
+ char path[PROPERTY_VALUE_MAX];
+ if (debug_handler->GetProperty("ro.vendor.extension_library", path) != kErrorNone) {
+ DLOGI("Vendor Extension Library not enabled");
+ return kErrorNotSupported;
+ }
+
+ int pre_enable_window = -1;
+ debug_handler->GetProperty(PERF_HINT_WINDOW_PROP, &pre_enable_window);
+ if (pre_enable_window <= 0) {
+ DLOGI("Invalid CPU Hint Pre-enable Window %d", pre_enable_window);
+ return kErrorNotSupported;
+ }
+
+ DLOGI("CPU Hint Pre-enable Window %d", pre_enable_window);
+ pre_enable_window_ = pre_enable_window;
+
+ if (vendor_ext_lib_.Open(path)) {
+ if (!vendor_ext_lib_.Sym("perf_lock_acq", reinterpret_cast<void **>(&fn_lock_acquire_)) ||
+ !vendor_ext_lib_.Sym("perf_lock_rel", reinterpret_cast<void **>(&fn_lock_release_))) {
+ DLOGW("Failed to load symbols for Vendor Extension Library");
+ return kErrorNotSupported;
+ }
+ DLOGI("Successfully Loaded Vendor Extension Library symbols");
+ enabled_ = true;
+ } else {
+ DLOGW("Failed to open %s : %s", path, vendor_ext_lib_.Error());
+ }
+
+ return kErrorNone;
+}
+
+void CPUHint::Set() {
+ if (!enabled_) {
+ return;
+ }
+ if (lock_acquired_) {
+ return;
+ }
+ if (frame_countdown_) {
+ --frame_countdown_;
+ return;
+ }
+
+ int hint = HINT;
+ lock_handle_ = fn_lock_acquire_(0 /*handle*/, 0/*duration*/,
+ &hint, sizeof(hint) / sizeof(int));
+ if (lock_handle_ >= 0) {
+ lock_acquired_ = true;
+ }
+}
+
+void CPUHint::Reset() {
+ if (!enabled_) {
+ return;
+ }
+
+ frame_countdown_ = pre_enable_window_;
+
+ if (!lock_acquired_) {
+ return;
+ }
+
+ fn_lock_release_(lock_handle_);
+ lock_acquired_ = false;
+}
+
+} // namespace sdm
diff --git a/msm8909/sdm/libs/hwc/cpuhint.h b/msm8909/sdm/libs/hwc/cpuhint.h
new file mode 100644
index 00000000..e7587630
--- /dev/null
+++ b/msm8909/sdm/libs/hwc/cpuhint.h
@@ -0,0 +1,61 @@
+/* Copyright (c) 2015, The Linux Foundataion. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+*/
+
+#ifndef __CPUHINT_H__
+#define __CPUHINT_H__
+
+#include <core/sdm_types.h>
+#include <utils/sys.h>
+
+namespace sdm {
+
+class HWCDebugHandler;
+
+class CPUHint {
+ public:
+ DisplayError Init(HWCDebugHandler *debug_handler);
+ void Set();
+ void Reset();
+
+ private:
+ enum { HINT = 0x4501 /* 45-display layer hint, 01-Enable */ };
+ bool enabled_ = false;
+ // frames to wait before setting this hint
+ int pre_enable_window_ = 0;
+ int frame_countdown_ = 0;
+ int lock_handle_ = 0;
+ bool lock_acquired_ = false;
+ DynLib vendor_ext_lib_;
+ int (*fn_lock_acquire_)(int handle, int duration, int *hints, int num_args) = NULL;
+ int (*fn_lock_release_)(int value) = NULL;
+};
+
+} // namespace sdm
+
+#endif // __CPUHINT_H__
diff --git a/msm8909/sdm/libs/hwc/hwc_buffer_allocator.cpp b/msm8909/sdm/libs/hwc/hwc_buffer_allocator.cpp
new file mode 100644
index 00000000..25f366f0
--- /dev/null
+++ b/msm8909/sdm/libs/hwc/hwc_buffer_allocator.cpp
@@ -0,0 +1,330 @@
+/*
+* Copyright (c) 2015 - 2017, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <gralloc_priv.h>
+#include <memalloc.h>
+#include <gr.h>
+#include <alloc_controller.h>
+#include <utils/constants.h>
+#include <utils/debug.h>
+#include <core/buffer_allocator.h>
+
+#include "hwc_debugger.h"
+#include "hwc_buffer_allocator.h"
+
+#define __CLASS__ "HWCBufferAllocator"
+
+namespace sdm {
+
+HWCBufferAllocator::HWCBufferAllocator() {
+ alloc_controller_ = gralloc::IAllocController::getInstance();
+}
+
+DisplayError HWCBufferAllocator::AllocateBuffer(BufferInfo *buffer_info) {
+ gralloc::alloc_data data;
+
+ const BufferConfig &buffer_config = buffer_info->buffer_config;
+ AllocatedBufferInfo *alloc_buffer_info = &buffer_info->alloc_buffer_info;
+ MetaBufferInfo *meta_buffer_info = new MetaBufferInfo();
+
+ if (!meta_buffer_info) {
+ return kErrorMemory;
+ }
+
+ int alloc_flags = INT(GRALLOC_USAGE_PRIVATE_IOMMU_HEAP);
+ int error = 0;
+
+ int width = INT(buffer_config.width);
+ int height = INT(buffer_config.height);
+ int format;
+
+ if (buffer_config.secure_camera) {
+ alloc_flags = GRALLOC_USAGE_HW_CAMERA_WRITE;
+ alloc_flags |= (GRALLOC_USAGE_PROTECTED | GRALLOC_USAGE_HW_COMPOSER);
+ data.align = SZ_2M;
+ } else if (buffer_config.secure) {
+ alloc_flags = INT(GRALLOC_USAGE_PRIVATE_MM_HEAP);
+ alloc_flags |= INT(GRALLOC_USAGE_PROTECTED);
+ data.align = SECURE_ALIGN;
+ } else {
+ data.align = UINT32(getpagesize());
+ }
+
+ if (buffer_config.cache == false) {
+ // Allocate uncached buffers
+ alloc_flags |= GRALLOC_USAGE_PRIVATE_UNCACHED;
+ }
+
+ error = SetBufferInfo(buffer_config.format, &format, &alloc_flags);
+ if (error != 0) {
+ delete meta_buffer_info;
+ return kErrorParameters;
+ }
+
+ int aligned_width = 0, aligned_height = 0;
+ uint32_t buffer_size = getBufferSizeAndDimensions(width, height, format, alloc_flags,
+ aligned_width, aligned_height);
+
+ buffer_size = ROUND_UP(buffer_size, data.align) * buffer_config.buffer_count;
+
+ data.base = 0;
+ data.fd = -1;
+ data.offset = 0;
+ data.size = buffer_size;
+ data.uncached = !buffer_config.cache;
+
+ error = alloc_controller_->allocate(data, alloc_flags);
+ if (error != 0) {
+ DLOGE("Error allocating memory size %d uncached %d", data.size, data.uncached);
+ delete meta_buffer_info;
+ return kErrorMemory;
+ }
+
+ alloc_buffer_info->fd = data.fd;
+ // TODO(user): define stride for all planes and fix stride in bytes
+ alloc_buffer_info->stride = UINT32(aligned_width);
+ alloc_buffer_info->aligned_width = UINT32(aligned_width);
+ alloc_buffer_info->aligned_height = UINT32(aligned_height);
+ alloc_buffer_info->size = buffer_size;
+
+ meta_buffer_info->base_addr = data.base;
+ meta_buffer_info->alloc_type = data.allocType;
+
+ buffer_info->private_data = meta_buffer_info;
+
+ return kErrorNone;
+}
+
+DisplayError HWCBufferAllocator::FreeBuffer(BufferInfo *buffer_info) {
+ int ret = 0;
+ AllocatedBufferInfo *alloc_buffer_info = &buffer_info->alloc_buffer_info;
+
+ // Deallocate the buffer, only if the buffer fd is valid.
+ if (alloc_buffer_info->fd > 0) {
+ MetaBufferInfo *meta_buffer_info = static_cast<MetaBufferInfo *> (buffer_info->private_data);
+ gralloc::IMemAlloc *memalloc = alloc_controller_->getAllocator(meta_buffer_info->alloc_type);
+ if (memalloc == NULL) {
+ DLOGE("Memalloc handle is NULL, alloc type %d", meta_buffer_info->alloc_type);
+ return kErrorResources;
+ }
+
+ ret = memalloc->free_buffer(meta_buffer_info->base_addr, alloc_buffer_info->size, 0,
+ alloc_buffer_info->fd);
+ if (ret != 0) {
+ DLOGE("Error freeing buffer base_addr %p size %d fd %d", meta_buffer_info->base_addr,
+ alloc_buffer_info->size, alloc_buffer_info->fd);
+ return kErrorMemory;
+ }
+
+ alloc_buffer_info->fd = -1;
+ alloc_buffer_info->stride = 0;
+ alloc_buffer_info->aligned_width = 0;
+ alloc_buffer_info->aligned_height = 0;
+ alloc_buffer_info->size = 0;
+
+ meta_buffer_info->base_addr = NULL;
+ meta_buffer_info->alloc_type = 0;
+
+ delete meta_buffer_info;
+ meta_buffer_info = NULL;
+ }
+
+ return kErrorNone;
+}
+
+uint32_t HWCBufferAllocator::GetBufferSize(BufferInfo *buffer_info) {
+ uint32_t align = UINT32(getpagesize());
+
+ const BufferConfig &buffer_config = buffer_info->buffer_config;
+
+ int alloc_flags = INT(GRALLOC_USAGE_PRIVATE_IOMMU_HEAP);
+
+ int width = INT(buffer_config.width);
+ int height = INT(buffer_config.height);
+ int format;
+
+ if (buffer_config.secure_camera) {
+ alloc_flags = GRALLOC_USAGE_HW_CAMERA_WRITE;
+ alloc_flags |= (GRALLOC_USAGE_PROTECTED | GRALLOC_USAGE_HW_COMPOSER);
+ align = SZ_2M;
+ } else if (buffer_config.secure) {
+ alloc_flags = INT(GRALLOC_USAGE_PRIVATE_MM_HEAP);
+ alloc_flags |= INT(GRALLOC_USAGE_PROTECTED);
+ align = SECURE_ALIGN;
+ }
+
+ if (buffer_config.cache == false) {
+ // Allocate uncached buffers
+ alloc_flags |= GRALLOC_USAGE_PRIVATE_UNCACHED;
+ }
+
+ if (SetBufferInfo(buffer_config.format, &format, &alloc_flags) < 0) {
+ return 0;
+ }
+
+ int aligned_width = 0;
+ int aligned_height = 0;
+ uint32_t buffer_size = getBufferSizeAndDimensions(width, height, format, alloc_flags,
+ aligned_width, aligned_height);
+
+ buffer_size = ROUND_UP(buffer_size, align) * buffer_config.buffer_count;
+
+ return buffer_size;
+}
+
+int HWCBufferAllocator::SetBufferInfo(LayerBufferFormat format, int *target, int *flags) {
+ switch (format) {
+ case kFormatRGBA8888: *target = HAL_PIXEL_FORMAT_RGBA_8888; break;
+ case kFormatRGBX8888: *target = HAL_PIXEL_FORMAT_RGBX_8888; break;
+ case kFormatRGB888: *target = HAL_PIXEL_FORMAT_RGB_888; break;
+ case kFormatRGB565: *target = HAL_PIXEL_FORMAT_RGB_565; break;
+ case kFormatBGR565: *target = HAL_PIXEL_FORMAT_BGR_565; break;
+ case kFormatBGRA8888: *target = HAL_PIXEL_FORMAT_BGRA_8888; break;
+ case kFormatYCrCb420PlanarStride16: *target = HAL_PIXEL_FORMAT_YV12; break;
+ case kFormatYCrCb420SemiPlanar: *target = HAL_PIXEL_FORMAT_YCrCb_420_SP; break;
+ case kFormatYCbCr420SemiPlanar: *target = HAL_PIXEL_FORMAT_YCbCr_420_SP; break;
+ case kFormatYCbCr422H2V1Packed: *target = HAL_PIXEL_FORMAT_YCbCr_422_I; break;
+ case kFormatCbYCrY422H2V1Packed: *target = HAL_PIXEL_FORMAT_CbYCrY_422_I; break;
+ case kFormatYCbCr422H2V1SemiPlanar: *target = HAL_PIXEL_FORMAT_YCbCr_422_SP; break;
+ case kFormatYCbCr420SemiPlanarVenus: *target = HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS; break;
+ case kFormatYCrCb420SemiPlanarVenus: *target = HAL_PIXEL_FORMAT_YCrCb_420_SP_VENUS; break;
+ case kFormatYCbCr420SPVenusUbwc:
+ *target = HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC;
+ *flags |= GRALLOC_USAGE_PRIVATE_ALLOC_UBWC;
+ break;
+ case kFormatRGBA5551: *target = HAL_PIXEL_FORMAT_RGBA_5551; break;
+ case kFormatRGBA4444: *target = HAL_PIXEL_FORMAT_RGBA_4444; break;
+ case kFormatRGBA1010102: *target = HAL_PIXEL_FORMAT_RGBA_1010102; break;
+ case kFormatARGB2101010: *target = HAL_PIXEL_FORMAT_ARGB_2101010; break;
+ case kFormatRGBX1010102: *target = HAL_PIXEL_FORMAT_RGBX_1010102; break;
+ case kFormatXRGB2101010: *target = HAL_PIXEL_FORMAT_XRGB_2101010; break;
+ case kFormatBGRA1010102: *target = HAL_PIXEL_FORMAT_BGRA_1010102; break;
+ case kFormatABGR2101010: *target = HAL_PIXEL_FORMAT_ABGR_2101010; break;
+ case kFormatBGRX1010102: *target = HAL_PIXEL_FORMAT_BGRX_1010102; break;
+ case kFormatXBGR2101010: *target = HAL_PIXEL_FORMAT_XBGR_2101010; break;
+ case kFormatYCbCr420P010: *target = HAL_PIXEL_FORMAT_YCbCr_420_P010; break;
+ case kFormatYCbCr420TP10Ubwc:
+ *target = HAL_PIXEL_FORMAT_YCbCr_420_TP10_UBWC;
+ *flags |= GRALLOC_USAGE_PRIVATE_ALLOC_UBWC;
+ break;
+ case kFormatYCbCr420P010Ubwc:
+ *target = HAL_PIXEL_FORMAT_YCbCr_420_P010_UBWC;
+ *flags |= GRALLOC_USAGE_PRIVATE_ALLOC_UBWC;
+ break;
+ case kFormatRGBA8888Ubwc:
+ *target = HAL_PIXEL_FORMAT_RGBA_8888;
+ *flags |= GRALLOC_USAGE_PRIVATE_ALLOC_UBWC;
+ break;
+ case kFormatRGBX8888Ubwc:
+ *target = HAL_PIXEL_FORMAT_RGBX_8888;
+ *flags |= GRALLOC_USAGE_PRIVATE_ALLOC_UBWC;
+ break;
+ case kFormatBGR565Ubwc:
+ *target = HAL_PIXEL_FORMAT_BGR_565;
+ *flags |= GRALLOC_USAGE_PRIVATE_ALLOC_UBWC;
+ break;
+ case kFormatRGBA1010102Ubwc:
+ *target = HAL_PIXEL_FORMAT_RGBA_1010102;
+ *flags |= GRALLOC_USAGE_PRIVATE_ALLOC_UBWC;
+ break;
+ case kFormatRGBX1010102Ubwc:
+ *target = HAL_PIXEL_FORMAT_RGBX_1010102;
+ *flags |= GRALLOC_USAGE_PRIVATE_ALLOC_UBWC;
+ break;
+ default:
+ DLOGE("Unsupported format = 0x%x", format);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+DisplayError HWCBufferAllocator::GetAllocatedBufferInfo(const BufferConfig &buffer_config,
+ AllocatedBufferInfo *allocated_buffer_info) {
+ int width = INT(buffer_config.width);
+ int height = INT(buffer_config.height);
+ int alloc_flags = INT(GRALLOC_USAGE_PRIVATE_IOMMU_HEAP);
+
+ if (buffer_config.secure) {
+ alloc_flags = INT(GRALLOC_USAGE_PRIVATE_MM_HEAP);
+ alloc_flags |= INT(GRALLOC_USAGE_PROTECTED);
+ }
+
+ if (buffer_config.cache == false) {
+ // Allocate uncached buffers
+ alloc_flags |= GRALLOC_USAGE_PRIVATE_UNCACHED;
+ }
+
+ int format;
+ int error = SetBufferInfo(buffer_config.format, &format, &alloc_flags);
+ if (error) {
+ DLOGE("Failed: format = %d or width = %d height = %d", buffer_config.format, width, height);
+ return kErrorNotSupported;
+ }
+
+ int width_aligned = 0, height_aligned = 0;
+ uint32_t buffer_size = 0;
+ buffer_size = getBufferSizeAndDimensions(width, height, format, alloc_flags,
+ width_aligned, height_aligned);
+
+ allocated_buffer_info->stride = UINT32(width_aligned);
+ allocated_buffer_info->aligned_width = UINT32(width_aligned);
+ allocated_buffer_info->aligned_height = UINT32(height_aligned);
+ allocated_buffer_info->size = UINT32(buffer_size);
+ allocated_buffer_info->format = buffer_config.format;
+
+ return kErrorNone;
+}
+
+DisplayError HWCBufferAllocator::GetBufferLayout(const AllocatedBufferInfo &buf_info,
+ uint32_t stride[4], uint32_t offset[4],
+ uint32_t *num_planes) {
+ private_handle_t hnd(-1, 0, 0, 0, 0, 0, 0);
+ int format = HAL_PIXEL_FORMAT_RGBA_8888;
+ int flags = 0;
+
+ SetBufferInfo(buf_info.format, &format, &flags);
+ // Setup only the required stuff, skip rest
+ hnd.format = format;
+ hnd.width = buf_info.aligned_width;
+ hnd.height = buf_info.aligned_height;
+ if (flags & GRALLOC_USAGE_PRIVATE_ALLOC_UBWC) {
+ hnd.flags = private_handle_t::PRIV_FLAGS_UBWC_ALIGNED;
+ }
+
+ int ret = getBufferLayout(&hnd, stride, offset, num_planes);
+ if (ret < 0) {
+ DLOGE("getBufferLayout failed");
+ return kErrorParameters;
+ }
+
+ return kErrorNone;
+}
+
+} // namespace sdm
diff --git a/msm8909/sdm/libs/hwc/hwc_buffer_allocator.h b/msm8909/sdm/libs/hwc/hwc_buffer_allocator.h
new file mode 100644
index 00000000..a8cf4621
--- /dev/null
+++ b/msm8909/sdm/libs/hwc/hwc_buffer_allocator.h
@@ -0,0 +1,70 @@
+/*
+* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#ifndef __HWC_BUFFER_ALLOCATOR_H__
+#define __HWC_BUFFER_ALLOCATOR_H__
+
+#include <sys/mman.h>
+#include <fcntl.h>
+
+namespace gralloc {
+
+class IAllocController;
+
+} // namespace gralloc
+
+namespace sdm {
+
+class HWCBufferAllocator : public BufferAllocator {
+ public:
+ HWCBufferAllocator();
+
+ DisplayError AllocateBuffer(BufferInfo *buffer_info);
+ DisplayError FreeBuffer(BufferInfo *buffer_info);
+ uint32_t GetBufferSize(BufferInfo *buffer_info);
+ DisplayError GetAllocatedBufferInfo(const BufferConfig &buffer_config,
+ AllocatedBufferInfo *allocated_buffer_info);
+ DisplayError GetBufferLayout(const AllocatedBufferInfo &buf_info,
+ uint32_t stride[4], uint32_t offset[4],
+ uint32_t *num_planes);
+ int SetBufferInfo(LayerBufferFormat format, int *target, int *flags);
+
+ private:
+ struct MetaBufferInfo {
+ int alloc_type; //!< Specifies allocation type set by the buffer allocator.
+ void *base_addr; //!< Specifies the base address of the allocated output buffer.
+ };
+
+ gralloc::IAllocController *alloc_controller_;
+};
+
+} // namespace sdm
+#endif // __HWC_BUFFER_ALLOCATOR_H__
+
diff --git a/msm8909/sdm/libs/hwc/hwc_buffer_sync_handler.cpp b/msm8909/sdm/libs/hwc/hwc_buffer_sync_handler.cpp
new file mode 100644
index 00000000..f2dacb22
--- /dev/null
+++ b/msm8909/sdm/libs/hwc/hwc_buffer_sync_handler.cpp
@@ -0,0 +1,92 @@
+/*
+* Copyright (c) 2015, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <errno.h>
+#include <sync/sync.h>
+#include <utils/constants.h>
+#include <utils/debug.h>
+
+#include "hwc_debugger.h"
+#include "hwc_buffer_sync_handler.h"
+
+#define __CLASS__ "HWCBufferSyncHandler"
+
+namespace sdm {
+
+DisplayError HWCBufferSyncHandler::SyncWait(int fd) {
+ int error = 0;
+
+ if (fd >= 0) {
+ error = sync_wait(fd, 1000);
+ if (error < 0) {
+ DLOGE("sync_wait error errno = %d, desc = %s", errno, strerror(errno));
+ return kErrorTimeOut;
+ }
+ }
+
+ return kErrorNone;
+}
+
+DisplayError HWCBufferSyncHandler::SyncMerge(int fd1, int fd2, int *merged_fd) {
+ DisplayError error = kErrorNone;
+
+ // Merge the two fences. In the case where one of the fences is not a
+ // valid fence (e.g. NO_FENCE) merge the one valid fence with itself so
+ // that a new fence with the given name is created.
+ // TODO(user): "SyncMerge"string should be replaced with user-defined string to represent
+ // why it is merged.
+ if (fd1 >= 0 && fd2 >= 0) {
+ *merged_fd = sync_merge("SyncMerge", fd1, fd2);
+ } else if (fd1 >= 0) {
+ *merged_fd = sync_merge("SyncMerge", fd1, fd1);
+ } else if (fd2 >= 0) {
+ *merged_fd = sync_merge("SyncMerge", fd2, fd2);
+ } else {
+ *merged_fd = -1;
+ return kErrorNone;
+ }
+
+ if (*merged_fd == -1) {
+ DLOGE("Sync merge error! fd1 %d fd2 %d", fd1, fd2);
+ error = kErrorFileDescriptor;
+ }
+
+ return error;
+}
+
+bool HWCBufferSyncHandler::IsSyncSignaled(int fd) {
+ if (sync_wait(fd, 0) < 0) {
+ return false;
+ } else {
+ return true;
+ }
+}
+
+} // namespace sdm
+
diff --git a/msm8909/sdm/libs/hwc/hwc_buffer_sync_handler.h b/msm8909/sdm/libs/hwc/hwc_buffer_sync_handler.h
new file mode 100644
index 00000000..81479d81
--- /dev/null
+++ b/msm8909/sdm/libs/hwc/hwc_buffer_sync_handler.h
@@ -0,0 +1,53 @@
+/*
+* Copyright (c) 2015, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#ifndef __HWC_BUFFER_SYNC_HANDLER_H__
+#define __HWC_BUFFER_SYNC_HANDLER_H__
+
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <core/sdm_types.h>
+#include <core/buffer_sync_handler.h>
+
+namespace sdm {
+
+class HWCBufferSyncHandler : public BufferSyncHandler {
+ public:
+ HWCBufferSyncHandler() { }
+
+ virtual DisplayError SyncWait(int fd);
+ virtual DisplayError SyncMerge(int fd1, int fd2, int *merged_fd);
+ virtual bool IsSyncSignaled(int fd);
+};
+
+} // namespace sdm
+#endif // __HWC_BUFFER_SYNC_HANDLER_H__
+
+
diff --git a/msm8909/sdm/libs/hwc/hwc_color_manager.cpp b/msm8909/sdm/libs/hwc/hwc_color_manager.cpp
new file mode 100644
index 00000000..a02f1ce0
--- /dev/null
+++ b/msm8909/sdm/libs/hwc/hwc_color_manager.cpp
@@ -0,0 +1,651 @@
+/*
+* Copyright (c) 2015 - 2017, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <dlfcn.h>
+#include <powermanager/IPowerManager.h>
+#include <cutils/sockets.h>
+#include <cutils/native_handle.h>
+#include <utils/String16.h>
+#include <binder/Parcel.h>
+#include <gralloc_priv.h>
+#include <hardware/hwcomposer.h>
+#include <hardware/hwcomposer_defs.h>
+#include <QService.h>
+
+#include <core/dump_interface.h>
+#include <utils/constants.h>
+#include <utils/debug.h>
+#include <core/buffer_allocator.h>
+#include <private/color_params.h>
+#include "hwc_buffer_allocator.h"
+#include "hwc_buffer_sync_handler.h"
+#include "hwc_session.h"
+#include "hwc_debugger.h"
+
+#define __CLASS__ "HWCColorManager"
+
+namespace sdm {
+
+uint32_t HWCColorManager::Get8BitsARGBColorValue(const PPColorFillParams &params) {
+ uint32_t argb_color = ((params.color.r << 16) & 0xff0000) | ((params.color.g << 8) & 0xff00) |
+ ((params.color.b) & 0xff);
+ return argb_color;
+}
+
+int HWCColorManager::CreatePayloadFromParcel(const android::Parcel &in, uint32_t *disp_id,
+ PPDisplayAPIPayload *sink) {
+ int ret = 0;
+ uint32_t id(0);
+ uint32_t size(0);
+
+ id = UINT32(in.readInt32());
+ size = UINT32(in.readInt32());
+ if (size > 0 && size == in.dataAvail()) {
+ const void *data = in.readInplace(size);
+ const uint8_t *temp = reinterpret_cast<const uint8_t *>(data);
+
+ sink->size = size;
+ sink->payload = const_cast<uint8_t *>(temp);
+ *disp_id = id;
+ } else {
+ DLOGW("Failing size checking, size = %d", size);
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+void HWCColorManager::MarshallStructIntoParcel(const PPDisplayAPIPayload &data,
+ android::Parcel *out_parcel) {
+ out_parcel->writeInt32(INT32(data.size));
+ if (data.payload)
+ out_parcel->write(data.payload, data.size);
+}
+
+HWCColorManager *HWCColorManager::CreateColorManager() {
+ HWCColorManager *color_mgr = new HWCColorManager();
+
+ if (color_mgr) {
+ // Load display API interface library. And retrieve color API function tables.
+ DynLib &color_apis_lib = color_mgr->color_apis_lib_;
+ if (color_apis_lib.Open(DISPLAY_API_INTERFACE_LIBRARY_NAME)) {
+ if (!color_apis_lib.Sym(DISPLAY_API_FUNC_TABLES, &color_mgr->color_apis_)) {
+ DLOGE("Fail to retrieve = %s from %s", DISPLAY_API_FUNC_TABLES,
+ DISPLAY_API_INTERFACE_LIBRARY_NAME);
+ delete color_mgr;
+ return NULL;
+ }
+ } else {
+ DLOGW("Unable to load = %s", DISPLAY_API_INTERFACE_LIBRARY_NAME);
+ delete color_mgr;
+ return NULL;
+ }
+ DLOGI("Successfully loaded %s", DISPLAY_API_INTERFACE_LIBRARY_NAME);
+
+ // Load diagclient library and invokes its entry point to pass in display APIs.
+ DynLib &diag_client_lib = color_mgr->diag_client_lib_;
+ if (diag_client_lib.Open(QDCM_DIAG_CLIENT_LIBRARY_NAME)) {
+ if (!diag_client_lib.Sym(INIT_QDCM_DIAG_CLIENT_NAME,
+ reinterpret_cast<void **>(&color_mgr->qdcm_diag_init_)) ||
+ !diag_client_lib.Sym(DEINIT_QDCM_DIAG_CLIENT_NAME,
+ reinterpret_cast<void **>(&color_mgr->qdcm_diag_deinit_))) {
+ DLOGE("Fail to retrieve = %s from %s", INIT_QDCM_DIAG_CLIENT_NAME,
+ QDCM_DIAG_CLIENT_LIBRARY_NAME);
+ } else {
+ // invoke Diag Client entry point to initialize.
+ color_mgr->qdcm_diag_init_(color_mgr->color_apis_);
+ DLOGI("Successfully loaded %s and %s and diag_init'ed", DISPLAY_API_INTERFACE_LIBRARY_NAME,
+ QDCM_DIAG_CLIENT_LIBRARY_NAME);
+ }
+ } else {
+ DLOGW("Unable to load = %s", QDCM_DIAG_CLIENT_LIBRARY_NAME);
+ // only QDCM Diag client failed to be loaded and system still should function.
+ }
+ } else {
+ DLOGE("Unable to create HWCColorManager");
+ return NULL;
+ }
+
+ return color_mgr;
+}
+
+HWCColorManager::~HWCColorManager() {
+}
+
+void HWCColorManager::DestroyColorManager() {
+ if (qdcm_mode_mgr_) {
+ delete qdcm_mode_mgr_;
+ }
+ if (qdcm_diag_deinit_) {
+ qdcm_diag_deinit_();
+ }
+ delete this;
+}
+
+int HWCColorManager::EnableQDCMMode(bool enable, HWCDisplay *hwc_display) {
+ int ret = 0;
+
+ if (!qdcm_mode_mgr_) {
+ qdcm_mode_mgr_ = HWCQDCMModeManager::CreateQDCMModeMgr();
+ if (!qdcm_mode_mgr_) {
+ DLOGE("Unable to create QDCM operating mode manager.");
+ ret = -EFAULT;
+ }
+ }
+
+ if (qdcm_mode_mgr_) {
+ ret = qdcm_mode_mgr_->EnableQDCMMode(enable, hwc_display);
+ }
+
+ return ret;
+}
+
+bool HWCColorManager::SolidFillLayersPrepare(hwc_display_contents_1_t **displays,
+ HWCDisplay *hwc_display) {
+ SCOPE_LOCK(locker_);
+
+ // Query HWCColorManager if QDCM tool requesting SOLID_FILL mode.
+ uint32_t solid_fill_color = Get8BitsARGBColorValue(solid_fill_params_);
+ hwc_display_contents_1_t *layer_list = displays[HWC_DISPLAY_PRIMARY];
+
+ if (solid_fill_enable_ && solid_fill_layers_ && layer_list) {
+ // 1. shallow copy HWC_FRAMEBUFFER_TARGET layer info solid fill layer list.
+ solid_fill_layers_->hwLayers[1] = layer_list->hwLayers[layer_list->numHwLayers - 1];
+
+ // 2. continue the prepare<> on solid_fill_layers.
+ hwc_display->Perform(HWCDisplayPrimary::SET_QDCM_SOLID_FILL_INFO, solid_fill_color);
+ hwc_display->Prepare(solid_fill_layers_); // RECT info included.
+
+ // 3. Set HWC_OVERLAY to all SF layers before returning to framework.
+ for (size_t i = 0; i < (layer_list->numHwLayers - 1); i++) {
+ hwc_layer_1_t *layer = &layer_list->hwLayers[i];
+ layer->compositionType = HWC_OVERLAY;
+ }
+
+ return true;
+ } else if (!solid_fill_enable_) {
+ hwc_display->Perform(HWCDisplayPrimary::UNSET_QDCM_SOLID_FILL_INFO, 0);
+ }
+
+ return false;
+}
+
+bool HWCColorManager::SolidFillLayersSet(hwc_display_contents_1_t **displays,
+ HWCDisplay *hwc_display) {
+ // Query HWCColorManager if QDCM tool requesting SOLID_FILL mode.
+ SCOPE_LOCK(locker_);
+ hwc_display_contents_1_t *layer_list = displays[HWC_DISPLAY_PRIMARY];
+ if (solid_fill_enable_ && solid_fill_layers_ && layer_list) {
+ hwc_display->Commit(solid_fill_layers_);
+
+ // SurfaceFlinger layer stack is dropped in solid fill case and replaced with local layer stack
+ // Close acquire fence fds associated with SF layer stack
+ // Close release/retire fence fds returned along with local layer stack
+ for (size_t i = 0; i < (layer_list->numHwLayers - 1); i++) {
+ int &fence_fd = layer_list->hwLayers[i].acquireFenceFd;
+ if (fence_fd >= 0) {
+ close(fence_fd);
+ fence_fd = -1;
+ }
+ }
+
+ for (size_t i = 0; i < (solid_fill_layers_->numHwLayers - 1); i++) {
+ int &fence_fd = solid_fill_layers_->hwLayers[i].releaseFenceFd;
+ if (fence_fd >= 0) {
+ close(fence_fd);
+ fence_fd = -1;
+ }
+ }
+ if (solid_fill_layers_->retireFenceFd >= 0) {
+ close(solid_fill_layers_->retireFenceFd);
+ solid_fill_layers_->retireFenceFd = -1;
+ }
+
+ return true;
+ }
+
+ return false;
+}
+
+int HWCColorManager::CreateSolidFillLayers(HWCDisplay *hwc_display) {
+ int ret = 0;
+
+ if (!solid_fill_layers_) {
+ uint32_t size = sizeof(hwc_display_contents_1) + kNumSolidFillLayers * sizeof(hwc_layer_1_t);
+ uint32_t primary_width = 0;
+ uint32_t primary_height = 0;
+
+ hwc_display->GetMixerResolution(&primary_width, &primary_height);
+ uint8_t *buf = new uint8_t[size]();
+ // handle for solid fill layer with fd = -1.
+ private_handle_t *handle =
+ new private_handle_t(-1, 0, private_handle_t::PRIV_FLAGS_FRAMEBUFFER, BUFFER_TYPE_UI,
+ HAL_PIXEL_FORMAT_RGBA_8888, INT32(primary_width),
+ INT32(primary_height));
+
+ if (!buf || !handle) {
+ DLOGE("Failed to allocate memory.");
+ if (buf)
+ delete[] buf;
+ if (handle)
+ delete handle;
+
+ return -ENOMEM;
+ }
+
+ solid_fill_layers_ = reinterpret_cast<hwc_display_contents_1 *>(buf);
+ hwc_layer_1_t &layer = solid_fill_layers_->hwLayers[0];
+ layer.handle = handle;
+ }
+
+ solid_fill_layers_->flags = HWC_GEOMETRY_CHANGED;
+ solid_fill_layers_->numHwLayers = kNumSolidFillLayers;
+ solid_fill_layers_->retireFenceFd = -1;
+ solid_fill_layers_->outbuf = NULL;
+ solid_fill_layers_->outbufAcquireFenceFd = -1;
+
+ hwc_layer_1_t &layer = solid_fill_layers_->hwLayers[0];
+ hwc_rect_t solid_fill_rect = {
+ INT(solid_fill_params_.rect.x),
+ INT(solid_fill_params_.rect.y),
+ solid_fill_params_.rect.x + INT(solid_fill_params_.rect.width),
+ solid_fill_params_.rect.y + INT(solid_fill_params_.rect.height),
+ };
+
+ layer.compositionType = HWC_FRAMEBUFFER;
+ layer.blending = HWC_BLENDING_PREMULT;
+ layer.sourceCropf.left = solid_fill_params_.rect.x;
+ layer.sourceCropf.top = solid_fill_params_.rect.y;
+ layer.sourceCropf.right = UINT32(solid_fill_params_.rect.x) + solid_fill_params_.rect.width;
+ layer.sourceCropf.bottom = UINT32(solid_fill_params_.rect.y) + solid_fill_params_.rect.height;
+ layer.acquireFenceFd = -1;
+ layer.releaseFenceFd = -1;
+ layer.flags = 0;
+ layer.transform = 0;
+ layer.hints = 0;
+ layer.planeAlpha = 0xff;
+ layer.displayFrame = solid_fill_rect;
+ layer.visibleRegionScreen.numRects = 1;
+ layer.visibleRegionScreen.rects = &layer.displayFrame;
+ layer.surfaceDamage.numRects = 0;
+
+ return ret;
+}
+
+void HWCColorManager::DestroySolidFillLayers() {
+ if (solid_fill_layers_) {
+ hwc_layer_1_t &layer = solid_fill_layers_->hwLayers[0];
+ uint8_t *buf = reinterpret_cast<uint8_t *>(solid_fill_layers_);
+ private_handle_t const *hnd = reinterpret_cast<private_handle_t const *>(layer.handle);
+
+ if (hnd)
+ delete hnd;
+
+ if (buf)
+ delete[] buf;
+
+ solid_fill_layers_ = NULL;
+ }
+}
+
+int HWCColorManager::SetSolidFill(const void *params, bool enable, HWCDisplay *hwc_display) {
+ SCOPE_LOCK(locker_);
+ int ret = 0;
+
+ if (params) {
+ solid_fill_params_ = *reinterpret_cast<const PPColorFillParams *>(params);
+ } else {
+ solid_fill_params_ = PPColorFillParams();
+ }
+
+ if (enable) {
+ // will create solid fill layers for rendering if not present.
+ ret = CreateSolidFillLayers(hwc_display);
+ } else {
+ DestroySolidFillLayers();
+ }
+ solid_fill_enable_ = enable;
+
+ return ret;
+}
+
+int HWCColorManager::SetFrameCapture(void *params, bool enable, HWCDisplay *hwc_display) {
+ SCOPE_LOCK(locker_);
+ int ret = 0;
+
+ PPFrameCaptureData *frame_capture_data = reinterpret_cast<PPFrameCaptureData*>(params);
+
+ if (enable) {
+ std::memset(&buffer_info, 0x00, sizeof(buffer_info));
+ hwc_display->GetPanelResolution(&buffer_info.buffer_config.width,
+ &buffer_info.buffer_config.height);
+ if (frame_capture_data->input_params.out_pix_format == PP_PIXEL_FORMAT_RGB_888) {
+ buffer_info.buffer_config.format = kFormatRGB888;
+ } else if (frame_capture_data->input_params.out_pix_format == PP_PIXEL_FORMAT_RGB_2101010) {
+ buffer_info.buffer_config.format = kFormatRGBA1010102;
+ } else {
+ DLOGE("Pixel-format: %d NOT support.", frame_capture_data->input_params.out_pix_format);
+ return -EFAULT;
+ }
+
+ buffer_info.buffer_config.buffer_count = 1;
+ buffer_info.alloc_buffer_info.fd = -1;
+ buffer_info.alloc_buffer_info.stride = 0;
+ buffer_info.alloc_buffer_info.size = 0;
+
+ buffer_allocator_ = new HWCBufferAllocator();
+ if (buffer_allocator_ == NULL) {
+ DLOGE("Memory allocation for buffer_allocator_ FAILED");
+ return -ENOMEM;
+ }
+
+ ret = buffer_allocator_->AllocateBuffer(&buffer_info);
+ if (ret != 0) {
+ DLOGE("Buffer allocation failed. ret: %d", ret);
+ delete buffer_allocator_;
+ buffer_allocator_ = NULL;
+ return -ENOMEM;
+ } else {
+ void *buffer = mmap(NULL, buffer_info.alloc_buffer_info.size,
+ PROT_READ|PROT_WRITE,
+ MAP_SHARED, buffer_info.alloc_buffer_info.fd, 0);
+
+ if (buffer == MAP_FAILED) {
+ DLOGE("mmap failed. err = %d", errno);
+ frame_capture_data->buffer = NULL;
+ ret = buffer_allocator_->FreeBuffer(&buffer_info);
+ delete buffer_allocator_;
+ buffer_allocator_ = NULL;
+ return -EFAULT;
+ } else {
+ frame_capture_data->buffer = reinterpret_cast<uint8_t *>(buffer);
+ frame_capture_data->buffer_stride = buffer_info.alloc_buffer_info.aligned_width;
+ frame_capture_data->buffer_size = buffer_info.alloc_buffer_info.size;
+ }
+ ret = hwc_display->FrameCaptureAsync(buffer_info, 1);
+ if (ret < 0) {
+ DLOGE("FrameCaptureAsync failed. ret = %d", ret);
+ }
+ }
+ } else {
+ ret = hwc_display->GetFrameCaptureStatus();
+ if (!ret) {
+ if (frame_capture_data->buffer != NULL) {
+ if (munmap(frame_capture_data->buffer, buffer_info.alloc_buffer_info.size) != 0) {
+ DLOGE("munmap failed. err = %d", errno);
+ }
+ }
+ if (buffer_allocator_ != NULL) {
+ std::memset(frame_capture_data, 0x00, sizeof(PPFrameCaptureData));
+ ret = buffer_allocator_->FreeBuffer(&buffer_info);
+ if (ret != 0) {
+ DLOGE("FreeBuffer failed. ret = %d", ret);
+ }
+ delete buffer_allocator_;
+ buffer_allocator_ = NULL;
+ }
+ } else {
+ DLOGE("GetFrameCaptureStatus failed. ret = %d", ret);
+ }
+ }
+ return ret;
+}
+
+int HWCColorManager::SetHWDetailedEnhancerConfig(void *params, HWCDisplay *hwc_display) {
+ int err = -1;
+ DisplayDetailEnhancerData de_data;
+
+ PPDETuningCfgData *de_tuning_cfg_data = reinterpret_cast<PPDETuningCfgData*>(params);
+ if (de_tuning_cfg_data->cfg_pending == true) {
+ if (!de_tuning_cfg_data->cfg_en) {
+ de_data.enable = 0;
+ } else {
+ de_data.override_flags = kOverrideDEEnable;
+ de_data.enable = 1;
+
+ if (de_tuning_cfg_data->params.flags & kDeTuningFlagSharpFactor) {
+ de_data.override_flags |= kOverrideDESharpen1;
+ de_data.sharp_factor = de_tuning_cfg_data->params.sharp_factor;
+ }
+
+ if (de_tuning_cfg_data->params.flags & kDeTuningFlagClip) {
+ de_data.override_flags |= kOverrideDEClip;
+ de_data.clip = de_tuning_cfg_data->params.clip;
+ }
+
+ if (de_tuning_cfg_data->params.flags & kDeTuningFlagThrQuiet) {
+ de_data.override_flags |= kOverrideDEThrQuiet;
+ de_data.thr_quiet = de_tuning_cfg_data->params.thr_quiet;
+ }
+
+ if (de_tuning_cfg_data->params.flags & kDeTuningFlagThrDieout) {
+ de_data.override_flags |= kOverrideDEThrDieout;
+ de_data.thr_dieout = de_tuning_cfg_data->params.thr_dieout;
+ }
+
+ if (de_tuning_cfg_data->params.flags & kDeTuningFlagThrLow) {
+ de_data.override_flags |= kOverrideDEThrLow;
+ de_data.thr_low = de_tuning_cfg_data->params.thr_low;
+ }
+
+ if (de_tuning_cfg_data->params.flags & kDeTuningFlagThrHigh) {
+ de_data.override_flags |= kOverrideDEThrHigh;
+ de_data.thr_high = de_tuning_cfg_data->params.thr_high;
+ }
+
+ if (de_tuning_cfg_data->params.flags & kDeTuningFlagContentQualLevel) {
+ switch (de_tuning_cfg_data->params.quality) {
+ case kDeContentQualLow:
+ de_data.quality_level = kContentQualityLow;
+ break;
+ case kDeContentQualMedium:
+ de_data.quality_level = kContentQualityMedium;
+ break;
+ case kDeContentQualHigh:
+ de_data.quality_level = kContentQualityHigh;
+ break;
+ case kDeContentQualUnknown:
+ default:
+ de_data.quality_level = kContentQualityUnknown;
+ break;
+ }
+ }
+ }
+ err = hwc_display->SetDetailEnhancerConfig(de_data);
+ if (err) {
+ DLOGW("SetDetailEnhancerConfig failed. err = %d", err);
+ }
+ de_tuning_cfg_data->cfg_pending = false;
+ }
+ return err;
+}
+
+void HWCColorManager::SetColorModeDetailEnhancer(HWCDisplay *hwc_display) {
+ SCOPE_LOCK(locker_);
+ int err = -1;
+ PPPendingParams pending_action;
+ PPDisplayAPIPayload req_payload;
+
+ pending_action.action = kGetDetailedEnhancerData;
+ pending_action.params = NULL;
+
+ if (hwc_display) {
+ err = hwc_display->ColorSVCRequestRoute(req_payload, NULL, &pending_action);
+ if (!err && pending_action.action == kConfigureDetailedEnhancer) {
+ err = SetHWDetailedEnhancerConfig(pending_action.params, hwc_display);
+ }
+ }
+ return;
+}
+
+int HWCColorManager::SetDetailedEnhancer(void *params, HWCDisplay *hwc_display) {
+ SCOPE_LOCK(locker_);
+ int err = -1;
+ err = SetHWDetailedEnhancerConfig(params, hwc_display);
+ return err;
+}
+
+const HWCQDCMModeManager::ActiveFeatureCMD HWCQDCMModeManager::kActiveFeatureCMD[] = {
+ HWCQDCMModeManager::ActiveFeatureCMD("cabl:on", "cabl:off", "cabl:status", "running"),
+ HWCQDCMModeManager::ActiveFeatureCMD("ad:on", "ad:off", "ad:query:status", "running"),
+ HWCQDCMModeManager::ActiveFeatureCMD("svi:on", "svi:off", "svi:status", "running"),
+};
+
+const char *const HWCQDCMModeManager::kSocketName = "pps";
+const char *const HWCQDCMModeManager::kTagName = "surfaceflinger";
+const char *const HWCQDCMModeManager::kPackageName = "colormanager";
+
+HWCQDCMModeManager *HWCQDCMModeManager::CreateQDCMModeMgr() {
+ HWCQDCMModeManager *mode_mgr = new HWCQDCMModeManager();
+
+ if (!mode_mgr) {
+ DLOGW("No memory to create HWCQDCMModeManager.");
+ return NULL;
+ } else {
+ mode_mgr->socket_fd_ =
+ ::socket_local_client(kSocketName, ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM);
+ if (mode_mgr->socket_fd_ < 0) {
+ // it should not be disastrous and we still can grab wakelock in QDCM mode.
+ DLOGW("Unable to connect to dpps socket!");
+ }
+
+ // retrieve system GPU idle timeout value for later to recover.
+ mode_mgr->entry_timeout_ = UINT32(HWCDebugHandler::GetIdleTimeoutMs());
+
+ // acquire the binder handle to Android system PowerManager for later use.
+ android::sp<android::IBinder> binder =
+ android::defaultServiceManager()->checkService(android::String16("power"));
+ if (binder == NULL) {
+ DLOGW("Application can't connect to power manager service");
+ delete mode_mgr;
+ mode_mgr = NULL;
+ } else {
+ mode_mgr->power_mgr_ = android::interface_cast<android::IPowerManager>(binder);
+ }
+ }
+
+ return mode_mgr;
+}
+
+HWCQDCMModeManager::~HWCQDCMModeManager() {
+ if (socket_fd_ >= 0)
+ ::close(socket_fd_);
+}
+
+int HWCQDCMModeManager::AcquireAndroidWakeLock(bool enable) {
+ int ret = 0;
+
+ if (enable) {
+ if (wakelock_token_ == NULL) {
+ android::sp<android::IBinder> binder = new android::BBinder();
+ android::status_t status = power_mgr_->acquireWakeLock(
+ (kFullWakeLock | kAcquireCauseWakeup | kONAfterRelease), binder,
+ android::String16(kTagName), android::String16(kPackageName));
+ if (status == android::NO_ERROR) {
+ wakelock_token_ = binder;
+ }
+ }
+ } else {
+ if (wakelock_token_ != NULL && power_mgr_ != NULL) {
+ power_mgr_->releaseWakeLock(wakelock_token_, 0);
+ wakelock_token_.clear();
+ wakelock_token_ = NULL;
+ }
+ }
+
+ return ret;
+}
+
+int HWCQDCMModeManager::EnableActiveFeatures(bool enable,
+ const HWCQDCMModeManager::ActiveFeatureCMD &cmds,
+ bool *was_running) {
+ int ret = 0;
+ ssize_t size = 0;
+ char response[kSocketCMDMaxLength] = {
+ 0,
+ };
+
+ if (socket_fd_ < 0) {
+ DLOGW("No socket connection available!");
+ return -EFAULT;
+ }
+
+ if (!enable) { // if client requesting to disable it.
+ // query CABL status, if off, no action. keep the status.
+ size = ::write(socket_fd_, cmds.cmd_query_status, strlen(cmds.cmd_query_status));
+ if (size < 0) {
+ DLOGW("Unable to send data over socket %s", ::strerror(errno));
+ ret = -EFAULT;
+ } else {
+ size = ::read(socket_fd_, response, kSocketCMDMaxLength);
+ if (size < 0) {
+ DLOGW("Unable to read data over socket %s", ::strerror(errno));
+ ret = -EFAULT;
+ } else if (!strncmp(response, cmds.running, strlen(cmds.running))) {
+ *was_running = true;
+ }
+ }
+
+ if (*was_running) { // if was running, it's requested to disable it.
+ size = ::write(socket_fd_, cmds.cmd_off, strlen(cmds.cmd_off));
+ if (size < 0) {
+ DLOGW("Unable to send data over socket %s", ::strerror(errno));
+ ret = -EFAULT;
+ }
+ }
+ } else { // if was running, need enable it back.
+ if (*was_running) {
+ size = ::write(socket_fd_, cmds.cmd_on, strlen(cmds.cmd_on));
+ if (size < 0) {
+ DLOGW("Unable to send data over socket %s", ::strerror(errno));
+ ret = -EFAULT;
+ }
+ }
+ }
+
+ return ret;
+}
+
+int HWCQDCMModeManager::EnableQDCMMode(bool enable, HWCDisplay *hwc_display) {
+ int ret = 0;
+
+ ret = EnableActiveFeatures((enable ? false : true), kActiveFeatureCMD[kCABLFeature],
+ &cabl_was_running_);
+ ret = AcquireAndroidWakeLock(enable);
+
+ // if enter QDCM mode, disable GPU fallback idle timeout.
+ if (hwc_display) {
+ uint32_t timeout = enable ? 0 : entry_timeout_;
+ hwc_display->SetIdleTimeoutMs(timeout);
+ }
+
+ return ret;
+}
+
+} // namespace sdm
diff --git a/msm8909/sdm/libs/hwc/hwc_color_manager.h b/msm8909/sdm/libs/hwc/hwc_color_manager.h
new file mode 100644
index 00000000..20d2b391
--- /dev/null
+++ b/msm8909/sdm/libs/hwc/hwc_color_manager.h
@@ -0,0 +1,149 @@
+/* Copyright (c) 2015-2017, The Linux Foundataion. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+*/
+
+#ifndef __HWC_COLOR_MANAGER_H__
+#define __HWC_COLOR_MANAGER_H__
+
+#include <stdlib.h>
+#include <binder/Parcel.h>
+#include <powermanager/IPowerManager.h>
+#include <binder/BinderService.h>
+#include <core/sdm_types.h>
+#include <utils/locker.h>
+#include <utils/sys.h>
+
+namespace sdm {
+
+// This macro defines name for display APIs interface wrapper library.
+// This macro shall be used to load library using dlopen().
+#define DISPLAY_API_INTERFACE_LIBRARY_NAME "libsdm-disp-vndapis.so"
+
+// This macro defines variable name of display color APIs function tables
+// This macro shall be used to specify name of the variable in dlsym().
+#define DISPLAY_API_FUNC_TABLES "display_color_apis_ftables"
+#define QDCM_DIAG_CLIENT_LIBRARY_NAME "libsdm-diag.so"
+#define INIT_QDCM_DIAG_CLIENT_NAME "QDCMDiagInit"
+#define DEINIT_QDCM_DIAG_CLIENT_NAME "QDCMDiagDeInit"
+
+typedef int (*QDCMDiagInit)(void *ftables);
+
+typedef int (*QDCMDiagDeInit)(void);
+
+// Class to encapsulte all details of managing QDCM operating mode.
+class HWCQDCMModeManager {
+ public:
+ static const uint32_t kSocketCMDMaxLength = 4096;
+ static const uint32_t kFullWakeLock = 0x0000001a;
+ static const uint32_t kAcquireCauseWakeup = 0x10000000;
+ static const uint32_t kONAfterRelease = 0x20000000;
+ enum ActiveFeatureID {
+ kCABLFeature,
+ kADFeature,
+ kSVIFeature,
+ kMaxNumActiveFeature,
+ };
+
+ struct ActiveFeatureCMD {
+ const char *cmd_on = NULL;
+ const char *cmd_off = NULL;
+ const char *cmd_query_status = NULL;
+ const char *running = NULL;
+ ActiveFeatureCMD(const char *arg1, const char *arg2, const char *arg3, const char *arg4)
+ : cmd_on(arg1), cmd_off(arg2), cmd_query_status(arg3), running(arg4) {}
+ };
+
+ static const ActiveFeatureCMD kActiveFeatureCMD[kMaxNumActiveFeature];
+
+ public:
+ static HWCQDCMModeManager *CreateQDCMModeMgr();
+ ~HWCQDCMModeManager();
+ int EnableQDCMMode(bool enable, HWCDisplay *hwc_display);
+
+ protected:
+ bool SendSocketCmd();
+ int AcquireAndroidWakeLock(bool enable);
+ int EnableActiveFeatures(bool enable);
+ int EnableActiveFeatures(bool enable, const ActiveFeatureCMD &cmds, bool *was_running);
+
+ private:
+ bool cabl_was_running_ = false;
+ int socket_fd_ = -1;
+ android::sp<android::IBinder> wakelock_token_ = NULL;
+ android::sp<android::IPowerManager> power_mgr_ = NULL;
+ uint32_t entry_timeout_ = 0;
+ static const char *const kSocketName;
+ static const char *const kTagName;
+ static const char *const kPackageName;
+};
+
+// Class to encapsulte all HWC/OS specific behaviours for ColorManager.
+class HWCColorManager {
+ public:
+ static const int kNumSolidFillLayers = 2;
+ static HWCColorManager *CreateColorManager();
+ static int CreatePayloadFromParcel(const android::Parcel &in, uint32_t *disp_id,
+ PPDisplayAPIPayload *sink);
+ static void MarshallStructIntoParcel(const PPDisplayAPIPayload &data,
+ android::Parcel *out_parcel);
+
+ ~HWCColorManager();
+ void DestroyColorManager();
+ int EnableQDCMMode(bool enable, HWCDisplay *hwc_display);
+ int SetSolidFill(const void *params, bool enable, HWCDisplay *hwc_display);
+ bool SolidFillLayersPrepare(hwc_display_contents_1_t **displays, HWCDisplay *hwc_display);
+ bool SolidFillLayersSet(hwc_display_contents_1_t **displays, HWCDisplay *hwc_display);
+ int SetFrameCapture(void *params, bool enable, HWCDisplay *hwc_display);
+ int SetDetailedEnhancer(void *params, HWCDisplay *hwc_display);
+ void SetColorModeDetailEnhancer(HWCDisplay *hwc_display);
+ int SetHWDetailedEnhancerConfig(void *params, HWCDisplay *hwc_display);
+
+ protected:
+ int CreateSolidFillLayers(HWCDisplay *hwc_display);
+ void DestroySolidFillLayers();
+ static uint32_t Get8BitsARGBColorValue(const PPColorFillParams &params);
+
+ private:
+ DynLib color_apis_lib_;
+ DynLib diag_client_lib_;
+ void *color_apis_ = NULL;
+ QDCMDiagInit qdcm_diag_init_ = NULL;
+ QDCMDiagDeInit qdcm_diag_deinit_ = NULL;
+ HWCQDCMModeManager *qdcm_mode_mgr_ = NULL;
+
+ bool solid_fill_enable_ = false;
+ PPColorFillParams solid_fill_params_;
+ hwc_display_contents_1_t *solid_fill_layers_ = NULL;
+ HWCBufferAllocator *buffer_allocator_ = NULL;
+ BufferInfo buffer_info;
+ Locker locker_;
+};
+
+} // namespace sdm
+
+#endif // __HWC_COLOR_MANAGER_H__
diff --git a/msm8909/sdm/libs/hwc/hwc_debugger.cpp b/msm8909/sdm/libs/hwc/hwc_debugger.cpp
new file mode 100644
index 00000000..18a448d5
--- /dev/null
+++ b/msm8909/sdm/libs/hwc/hwc_debugger.cpp
@@ -0,0 +1,232 @@
+/*
+* Copyright (c) 2014 - 2018, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <utils/constants.h>
+#include <cutils/properties.h>
+#include <utils/debug.h>
+
+#include "hwc_debugger.h"
+
+namespace sdm {
+
+HWCDebugHandler HWCDebugHandler::debug_handler_;
+std::bitset<32> HWCDebugHandler::debug_flags_ = 0x1;
+int32_t HWCDebugHandler::verbose_level_ = 0x0;
+
+void HWCDebugHandler::DebugAll(bool enable, int verbose_level) {
+ if (enable) {
+ debug_flags_ = 0x7FFFFFFF;
+ if (verbose_level) {
+ // Enable verbose scalar logs only when explicitely enabled
+ debug_flags_[kTagScalar] = 0;
+ }
+ verbose_level_ = verbose_level;
+ } else {
+ debug_flags_ = 0x1; // kTagNone should always be printed.
+ verbose_level_ = 0;
+ }
+}
+
+void HWCDebugHandler::DebugResources(bool enable, int verbose_level) {
+ if (enable) {
+ debug_flags_[kTagResources] = 1;
+ verbose_level_ = verbose_level;
+ } else {
+ debug_flags_[kTagResources] = 0;
+ verbose_level_ = 0;
+ }
+}
+
+void HWCDebugHandler::DebugStrategy(bool enable, int verbose_level) {
+ if (enable) {
+ debug_flags_[kTagStrategy] = 1;
+ verbose_level_ = verbose_level;
+ } else {
+ debug_flags_[kTagStrategy] = 0;
+ verbose_level_ = 0;
+ }
+}
+
+void HWCDebugHandler::DebugCompManager(bool enable, int verbose_level) {
+ if (enable) {
+ debug_flags_[kTagCompManager] = 1;
+ verbose_level_ = verbose_level;
+ } else {
+ debug_flags_[kTagCompManager] = 0;
+ verbose_level_ = 0;
+ }
+}
+
+void HWCDebugHandler::DebugDriverConfig(bool enable, int verbose_level) {
+ if (enable) {
+ debug_flags_[kTagDriverConfig] = 1;
+ verbose_level_ = verbose_level;
+ } else {
+ debug_flags_[kTagDriverConfig] = 0;
+ verbose_level_ = 0;
+ }
+}
+
+void HWCDebugHandler::DebugRotator(bool enable, int verbose_level) {
+ if (enable) {
+ debug_flags_[kTagRotator] = 1;
+ verbose_level_ = verbose_level;
+ } else {
+ debug_flags_[kTagRotator] = 0;
+ verbose_level_ = 0;
+ }
+}
+
+void HWCDebugHandler::DebugScalar(bool enable, int verbose_level) {
+ if (enable) {
+ debug_flags_[kTagScalar] = 1;
+ verbose_level_ = verbose_level;
+ } else {
+ debug_flags_[kTagScalar] = 0;
+ verbose_level_ = 0;
+ }
+}
+
+void HWCDebugHandler::DebugQdcm(bool enable, int verbose_level) {
+ if (enable) {
+ debug_flags_[kTagQDCM] = 1;
+ verbose_level_ = verbose_level;
+ } else {
+ debug_flags_[kTagQDCM] = 0;
+ verbose_level_ = 0;
+ }
+}
+
+void HWCDebugHandler::DebugClient(bool enable, int verbose_level) {
+ if (enable) {
+ debug_flags_[kTagClient] = 1;
+ verbose_level_ = verbose_level;
+ } else {
+ debug_flags_[kTagClient] = 0;
+ verbose_level_ = 0;
+ }
+}
+
+void HWCDebugHandler::DebugDisplay(bool enable, int verbose_level) {
+ if (enable) {
+ debug_flags_[kTagDisplay] = 1;
+ verbose_level_ = verbose_level;
+ } else {
+ debug_flags_[kTagDisplay] = 0;
+ verbose_level_ = 0;
+ }
+}
+
+void HWCDebugHandler::Error(DebugTag tag, const char *format, ...) {
+ if (debug_flags_[tag]) {
+ va_list list;
+ va_start(list, format);
+ __android_log_vprint(ANDROID_LOG_ERROR, LOG_TAG, format, list);
+ }
+}
+
+void HWCDebugHandler::Warning(DebugTag tag, const char *format, ...) {
+ if (debug_flags_[tag]) {
+ va_list list;
+ va_start(list, format);
+ __android_log_vprint(ANDROID_LOG_WARN, LOG_TAG, format, list);
+ }
+}
+
+void HWCDebugHandler::Info(DebugTag tag, const char *format, ...) {
+ if (debug_flags_[tag]) {
+ va_list list;
+ va_start(list, format);
+ __android_log_vprint(ANDROID_LOG_INFO, LOG_TAG, format, list);
+ }
+}
+
+void HWCDebugHandler::Debug(DebugTag tag, const char *format, ...) {
+ if (debug_flags_[tag]) {
+ va_list list;
+ va_start(list, format);
+ __android_log_vprint(ANDROID_LOG_DEBUG, LOG_TAG, format, list);
+ }
+}
+
+void HWCDebugHandler::Verbose(DebugTag tag, const char *format, ...) {
+ if (debug_flags_[tag] && verbose_level_) {
+ va_list list;
+ va_start(list, format);
+ __android_log_vprint(ANDROID_LOG_VERBOSE, LOG_TAG, format, list);
+ }
+}
+
+void HWCDebugHandler::BeginTrace(const char *class_name, const char *function_name,
+ const char *custom_string) {
+ char name[PATH_MAX] = {0};
+ snprintf(name, sizeof(name), "%s::%s::%s", class_name, function_name, custom_string);
+ atrace_begin(ATRACE_TAG, name);
+}
+
+void HWCDebugHandler::EndTrace() {
+ atrace_end(ATRACE_TAG);
+}
+
+int HWCDebugHandler::GetIdleTimeoutMs() {
+ int value = IDLE_TIMEOUT_DEFAULT_MS;
+ debug_handler_.GetProperty(IDLE_TIME_PROP, &value);
+
+ return value;
+}
+
+DisplayError HWCDebugHandler::GetProperty(const char *property_name, int *value) {
+ char property[PROPERTY_VALUE_MAX];
+
+ if (property_get(property_name, property, NULL) > 0) {
+ *value = atoi(property);
+ return kErrorNone;
+ }
+
+ return kErrorNotSupported;
+}
+
+DisplayError HWCDebugHandler::GetProperty(const char *property_name, char *value) {
+ if (property_get(property_name, value, NULL) > 0) {
+ return kErrorNone;
+ }
+
+ return kErrorNotSupported;
+}
+
+DisplayError HWCDebugHandler::SetProperty(const char *property_name, const char *value) {
+ if (property_set(property_name, value) == 0) {
+ return kErrorNone;
+ }
+
+ return kErrorNotSupported;
+}
+
+} // namespace sdm
+
diff --git a/msm8909/sdm/libs/hwc/hwc_debugger.h b/msm8909/sdm/libs/hwc/hwc_debugger.h
new file mode 100644
index 00000000..3a3d7872
--- /dev/null
+++ b/msm8909/sdm/libs/hwc/hwc_debugger.h
@@ -0,0 +1,81 @@
+/*
+* Copyright (c) 2014 - 2017, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __HWC_DEBUGGER_H__
+#define __HWC_DEBUGGER_H__
+
+#define ATRACE_TAG (ATRACE_TAG_GRAPHICS | ATRACE_TAG_HAL)
+
+#include <core/sdm_types.h>
+#include <core/debug_interface.h>
+#include <log/log.h>
+#include <utils/Trace.h>
+#include <bitset>
+
+namespace sdm {
+
+class HWCDebugHandler : public DebugHandler {
+ public:
+ static inline DebugHandler* Get() { return &debug_handler_; }
+ static const char* DumpDir() { return "/data/vendor/display"; }
+
+ static void DebugAll(bool enable, int verbose_level);
+ static void DebugResources(bool enable, int verbose_level);
+ static void DebugStrategy(bool enable, int verbose_level);
+ static void DebugCompManager(bool enable, int verbose_level);
+ static void DebugDriverConfig(bool enable, int verbose_level);
+ static void DebugRotator(bool enable, int verbose_level);
+ static void DebugScalar(bool enable, int verbose_level);
+ static void DebugQdcm(bool enable, int verbose_level);
+ static void DebugClient(bool enable, int verbose_level);
+ static void DebugDisplay(bool enable, int verbose_level);
+ static int GetIdleTimeoutMs();
+
+ virtual void Error(DebugTag tag, const char *format, ...);
+ virtual void Warning(DebugTag tag, const char *format, ...);
+ virtual void Info(DebugTag tag, const char *format, ...);
+ virtual void Debug(DebugTag tag, const char *format, ...);
+ virtual void Verbose(DebugTag tag, const char *format, ...);
+ virtual void BeginTrace(const char *class_name, const char *function_name,
+ const char *custom_string);
+ virtual void EndTrace();
+ virtual DisplayError GetProperty(const char *property_name, int *value);
+ virtual DisplayError GetProperty(const char *property_name, char *value);
+ virtual DisplayError SetProperty(const char *property_name, const char *value);
+
+ private:
+ static HWCDebugHandler debug_handler_;
+ static std::bitset<32> debug_flags_;
+ static int32_t verbose_level_;
+};
+
+} // namespace sdm
+
+#endif // __HWC_DEBUGGER_H__
+
diff --git a/msm8909/sdm/libs/hwc/hwc_display.cpp b/msm8909/sdm/libs/hwc/hwc_display.cpp
new file mode 100644
index 00000000..47915c7b
--- /dev/null
+++ b/msm8909/sdm/libs/hwc/hwc_display.cpp
@@ -0,0 +1,1536 @@
+/*
+* Copyright (c) 2014 - 2017, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <math.h>
+#include <errno.h>
+#include <gralloc_priv.h>
+#include <gr.h>
+#include <utils/constants.h>
+#include <utils/formats.h>
+#include <utils/rect.h>
+#include <utils/debug.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sync/sync.h>
+#include <cutils/properties.h>
+#include <qd_utils.h>
+#include <map>
+#include <utility>
+#include <vector>
+#include <string>
+
+#include "blit_engine_c2d.h"
+#include "hwc_debugger.h"
+#include "hwc_display.h"
+#include "hwc_tonemapper.h"
+
+#ifdef QTI_BSP
+#include <hardware/display_defs.h>
+#endif
+
+#define __CLASS__ "HWCDisplay"
+
+namespace sdm {
+
+void HWCColorMode::Init() {
+ int ret = PopulateColorModes();
+ if (ret != 0) {
+ DLOGW("Failed!!");
+ }
+ return;
+}
+
+int HWCColorMode::SetColorMode(const std::string &color_mode) {
+ if (color_modes_.empty()) {
+ DLOGW("No Color Modes supported");
+ return -1;
+ }
+
+ std::vector<std::string>::iterator it = std::find(color_modes_.begin(), color_modes_.end(),
+ color_mode);
+ if (it == color_modes_.end()) {
+ DLOGE("Invalid colorMode request: %s", color_mode.c_str());
+ return -1;
+ }
+
+ DisplayError error = display_intf_->SetColorMode(color_mode);
+ if (error != kErrorNone) {
+ DLOGE("Failed to set color_mode = %s", color_mode.c_str());
+ return -1;
+ }
+ current_color_mode_ = color_mode;
+
+ return 0;
+}
+
+const std::vector<std::string> &HWCColorMode::GetColorModes() {
+ return color_modes_;
+}
+
+int HWCColorMode::SetColorTransform(uint32_t matrix_count, const float *matrix) {
+ if (matrix_count > kColorTransformMatrixCount) {
+ DLOGE("Transform matrix count = %d, exceeds max = %d", matrix_count,
+ kColorTransformMatrixCount);
+ return -1;
+ }
+
+ double color_matrix[kColorTransformMatrixCount] = {0};
+ CopyColorTransformMatrix(matrix, color_matrix);
+ DisplayError error = display_intf_->SetColorTransform(matrix_count, color_matrix);
+ if (error != kErrorNone) {
+ DLOGE("Failed!");
+ return -1;
+ }
+
+ return 0;
+}
+
+int HWCColorMode::PopulateColorModes() {
+ uint32_t color_mode_count = 0;
+ DisplayError error = display_intf_->GetColorModeCount(&color_mode_count);
+ if (error != kErrorNone || (color_mode_count == 0)) {
+ return -1;
+ }
+
+ DLOGI("Color Mode count = %d", color_mode_count);
+
+ color_modes_.resize(color_mode_count);
+
+ // SDM returns modes which is string
+ error = display_intf_->GetColorModes(&color_mode_count, &color_modes_);
+ if (error != kErrorNone) {
+ DLOGE("GetColorModes Failed for count = %d", color_mode_count);
+ return -1;
+ }
+
+ return 0;
+}
+
+HWCDisplay::HWCDisplay(CoreInterface *core_intf, hwc_procs_t const **hwc_procs, DisplayType type,
+ int id, bool needs_blit, qService::QService *qservice,
+ DisplayClass display_class)
+ : core_intf_(core_intf), hwc_procs_(hwc_procs), type_(type), id_(id), needs_blit_(needs_blit),
+ qservice_(qservice), display_class_(display_class) {
+}
+
+int HWCDisplay::Init() {
+ DisplayError error = core_intf_->CreateDisplay(type_, this, &display_intf_);
+ if (error != kErrorNone) {
+ DLOGE("Display create failed. Error = %d display_type %d event_handler %p disp_intf %p",
+ error, type_, this, &display_intf_);
+ return -EINVAL;
+ }
+
+ HWCDebugHandler::Get()->GetProperty("sys.hwc_disable_hdr", &disable_hdr_handling_);
+ if (disable_hdr_handling_) {
+ DLOGI("HDR Handling disabled");
+ }
+
+ int property_swap_interval = 1;
+ HWCDebugHandler::Get()->GetProperty("debug.egl.swapinterval", &property_swap_interval);
+ if (property_swap_interval == 0) {
+ swap_interval_zero_ = true;
+ }
+
+ int blit_enabled = 0;
+ HWCDebugHandler::Get()->GetProperty("persist.hwc.blit.comp", &blit_enabled);
+ if (needs_blit_ && blit_enabled) {
+ blit_engine_ = new BlitEngineC2d();
+ if (!blit_engine_) {
+ DLOGI("Create Blit Engine C2D failed");
+ } else {
+ if (blit_engine_->Init() < 0) {
+ DLOGI("Blit Engine Init failed, Blit Composition will not be used!!");
+ delete blit_engine_;
+ blit_engine_ = NULL;
+ }
+ }
+ }
+
+ tone_mapper_ = new HWCToneMapper();
+
+ display_intf_->GetRefreshRateRange(&min_refresh_rate_, &max_refresh_rate_);
+ current_refresh_rate_ = max_refresh_rate_;
+
+ s3d_format_hwc_to_sdm_.insert(std::pair<int, LayerBufferS3DFormat>(HAL_NO_3D, kS3dFormatNone));
+ s3d_format_hwc_to_sdm_.insert(std::pair<int, LayerBufferS3DFormat>(HAL_3D_SIDE_BY_SIDE_L_R,
+ kS3dFormatLeftRight));
+ s3d_format_hwc_to_sdm_.insert(std::pair<int, LayerBufferS3DFormat>(HAL_3D_SIDE_BY_SIDE_R_L,
+ kS3dFormatRightLeft));
+ s3d_format_hwc_to_sdm_.insert(std::pair<int, LayerBufferS3DFormat>(HAL_3D_TOP_BOTTOM,
+ kS3dFormatTopBottom));
+
+ disable_animation_ = Debug::IsExtAnimDisabled();
+
+ return 0;
+}
+
+int HWCDisplay::Deinit() {
+ DisplayError error = core_intf_->DestroyDisplay(display_intf_);
+ if (error != kErrorNone) {
+ DLOGE("Display destroy failed. Error = %d", error);
+ return -EINVAL;
+ }
+
+ if (blit_engine_) {
+ blit_engine_->DeInit();
+ delete blit_engine_;
+ blit_engine_ = NULL;
+ }
+
+ delete tone_mapper_;
+ tone_mapper_ = NULL;
+
+ return 0;
+}
+
+int HWCDisplay::EventControl(int event, int enable) {
+ DisplayError error = kErrorNone;
+
+ if (shutdown_pending_) {
+ return 0;
+ }
+
+ switch (event) {
+ case HWC_EVENT_VSYNC:
+ error = display_intf_->SetVSyncState(enable);
+ break;
+ default:
+ DLOGW("Unsupported event = %d", event);
+ }
+
+ if (error != kErrorNone) {
+ if (error == kErrorShutDown) {
+ shutdown_pending_ = true;
+ return 0;
+ }
+ DLOGE("Failed. event = %d, enable = %d, error = %d", event, enable, error);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+int HWCDisplay::SetPowerMode(int mode) {
+ DLOGI("display = %d, mode = %d", id_, mode);
+ DisplayState state = kStateOff;
+ bool flush_on_error = flush_on_error_;
+
+ if (shutdown_pending_) {
+ return 0;
+ }
+
+ switch (mode) {
+ case HWC_POWER_MODE_OFF:
+ // During power off, all of the buffers are released.
+ // Do not flush until a buffer is successfully submitted again.
+ flush_on_error = false;
+ state = kStateOff;
+ tone_mapper_->Terminate();
+ break;
+
+ case HWC_POWER_MODE_NORMAL:
+ state = kStateOn;
+ last_power_mode_ = HWC_POWER_MODE_NORMAL;
+ break;
+
+ case HWC_POWER_MODE_DOZE:
+ state = kStateDoze;
+ last_power_mode_ = HWC_POWER_MODE_DOZE;
+ break;
+
+ case HWC_POWER_MODE_DOZE_SUSPEND:
+ state = kStateDozeSuspend;
+ last_power_mode_ = HWC_POWER_MODE_DOZE_SUSPEND;
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ DisplayError error = display_intf_->SetDisplayState(state);
+ if (error == kErrorNone) {
+ flush_on_error_ = flush_on_error;
+ } else {
+ if (error == kErrorShutDown) {
+ shutdown_pending_ = true;
+ return 0;
+ }
+ DLOGE("Set state failed. Error = %d", error);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+int HWCDisplay::GetDisplayConfigs(uint32_t *configs, size_t *num_configs) {
+ if (*num_configs > 0) {
+ configs[0] = 0;
+ *num_configs = 1;
+ }
+
+ return 0;
+}
+
+int HWCDisplay::GetDisplayAttributes(uint32_t config, const uint32_t *display_attributes,
+ int32_t *values) {
+ DisplayConfigVariableInfo variable_config;
+ DisplayError error = display_intf_->GetFrameBufferConfig(&variable_config);
+ if (error != kErrorNone) {
+ DLOGV("Get variable config failed. Error = %d", error);
+ return -EINVAL;
+ }
+
+ for (int i = 0; display_attributes[i] != HWC_DISPLAY_NO_ATTRIBUTE; i++) {
+ switch (display_attributes[i]) {
+ case HWC_DISPLAY_VSYNC_PERIOD:
+ values[i] = INT32(variable_config.vsync_period_ns);
+ break;
+ case HWC_DISPLAY_WIDTH:
+ values[i] = INT32(variable_config.x_pixels);
+ break;
+ case HWC_DISPLAY_HEIGHT:
+ values[i] = INT32(variable_config.y_pixels);
+ break;
+ case HWC_DISPLAY_DPI_X:
+ values[i] = INT32(variable_config.x_dpi * 1000.0f);
+ break;
+ case HWC_DISPLAY_DPI_Y:
+ values[i] = INT32(variable_config.y_dpi * 1000.0f);
+ break;
+ default:
+ DLOGW("Spurious attribute type = %d", display_attributes[i]);
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+
+int HWCDisplay::GetActiveConfig() {
+ return 0;
+}
+
+int HWCDisplay::SetActiveConfig(int index) {
+ return -1;
+}
+
+DisplayError HWCDisplay::SetMixerResolution(uint32_t width, uint32_t height) {
+ return kErrorNotSupported;
+}
+
+void HWCDisplay::SetFrameDumpConfig(uint32_t count, uint32_t bit_mask_layer_type) {
+ dump_frame_count_ = count;
+ dump_frame_index_ = 0;
+ dump_input_layers_ = ((bit_mask_layer_type & (1 << INPUT_LAYER_DUMP)) != 0);
+
+ if (blit_engine_) {
+ blit_engine_->SetFrameDumpConfig(count);
+ }
+
+ if (tone_mapper_) {
+ tone_mapper_->SetFrameDumpConfig(count);
+ }
+
+ DLOGI("num_frame_dump %d, input_layer_dump_enable %d", dump_frame_count_, dump_input_layers_);
+}
+
+uint32_t HWCDisplay::GetLastPowerMode() {
+ return last_power_mode_;
+}
+
+DisplayError HWCDisplay::VSync(const DisplayEventVSync &vsync) {
+ const hwc_procs_t *hwc_procs = *hwc_procs_;
+
+ if (!hwc_procs) {
+ return kErrorParameters;
+ }
+
+ hwc_procs->vsync(hwc_procs, id_, vsync.timestamp);
+
+ return kErrorNone;
+}
+
+DisplayError HWCDisplay::Refresh() {
+ return kErrorNotSupported;
+}
+
+DisplayError HWCDisplay::CECMessage(char *message) {
+ if (qservice_) {
+ qservice_->onCECMessageReceived(message, 0);
+ } else {
+ DLOGW("Qservice instance not available.");
+ }
+
+ return kErrorNone;
+}
+
+int HWCDisplay::AllocateLayerStack(hwc_display_contents_1_t *content_list) {
+ if (!content_list || !content_list->numHwLayers) {
+ DLOGW("Invalid content list");
+ return -EINVAL;
+ }
+
+ size_t num_hw_layers = content_list->numHwLayers;
+ uint32_t blit_target_count = 0;
+
+ if (blit_engine_) {
+ blit_target_count = kMaxBlitTargetLayers;
+ }
+
+ FreeLayerStack();
+
+ for (size_t i = 0; i < num_hw_layers + blit_target_count; i++) {
+ Layer *layer = new Layer();
+ layer_stack_.layers.push_back(layer);
+ }
+
+ return 0;
+}
+
+void HWCDisplay::FreeLayerStack() {
+ for (Layer *layer : layer_stack_.layers) {
+ delete layer;
+ }
+ layer_stack_ = {};
+}
+
+int HWCDisplay::PrepareLayerParams(hwc_layer_1_t *hwc_layer, Layer* layer) {
+ const private_handle_t *pvt_handle = static_cast<const private_handle_t *>(hwc_layer->handle);
+
+ LayerBuffer &layer_buffer = layer->input_buffer;
+
+ if (pvt_handle) {
+ layer_buffer.planes[0].fd = pvt_handle->fd;
+ layer_buffer.format = GetSDMFormat(pvt_handle->format, pvt_handle->flags);
+ int aligned_width, aligned_height;
+ int unaligned_width, unaligned_height;
+
+ AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(pvt_handle, aligned_width,
+ aligned_height);
+ AdrenoMemInfo::getInstance().getUnalignedWidthAndHeight(pvt_handle, unaligned_width,
+ unaligned_height);
+
+ layer_buffer.width = UINT32(aligned_width);
+ layer_buffer.height = UINT32(aligned_height);
+ layer_buffer.unaligned_width = UINT32(unaligned_width);
+ layer_buffer.unaligned_height = UINT32(unaligned_height);
+
+ if (SetMetaData(pvt_handle, layer) != kErrorNone) {
+ return -EINVAL;
+ }
+
+ if (pvt_handle->bufferType == BUFFER_TYPE_VIDEO) {
+ layer_stack_.flags.video_present = true;
+ layer_buffer.flags.video = true;
+ }
+ // TZ Protected Buffer - L1
+ if (pvt_handle->flags & private_handle_t::PRIV_FLAGS_SECURE_BUFFER) {
+ layer_stack_.flags.secure_present = true;
+ layer_buffer.flags.secure = true;
+ if (pvt_handle->flags & private_handle_t::PRIV_FLAGS_CAMERA_WRITE) {
+ layer_buffer.flags.secure_camera = true;
+ }
+ }
+ // Gralloc Usage Protected Buffer - L3 - which needs to be treated as Secure & avoid fallback
+ if (pvt_handle->flags & private_handle_t::PRIV_FLAGS_PROTECTED_BUFFER) {
+ layer_stack_.flags.secure_present = true;
+ }
+ if (pvt_handle->flags & private_handle_t::PRIV_FLAGS_SECURE_DISPLAY) {
+ layer_buffer.flags.secure_display = true;
+ }
+
+ // check if this is special solid_fill layer without input_buffer.
+ if (solid_fill_enable_ && pvt_handle->fd == -1) {
+ layer->flags.solid_fill = true;
+ layer->solid_fill_color = solid_fill_color_;
+ }
+ } else {
+ // for FBT layer
+ if (hwc_layer->compositionType == HWC_FRAMEBUFFER_TARGET) {
+ uint32_t x_pixels;
+ uint32_t y_pixels;
+ int aligned_width;
+ int aligned_height;
+ int usage = GRALLOC_USAGE_HW_FB;
+ int format = HAL_PIXEL_FORMAT_RGBA_8888;
+ int ubwc_enabled = 0;
+ int flags = 0;
+ HWCDebugHandler::Get()->GetProperty("debug.gralloc.enable_fb_ubwc", &ubwc_enabled);
+ bool linear = layer_stack_.output_buffer && !IsUBWCFormat(layer_stack_.output_buffer->format);
+ if ((ubwc_enabled == 1) && !linear) {
+ usage |= GRALLOC_USAGE_PRIVATE_ALLOC_UBWC;
+ flags |= private_handle_t::PRIV_FLAGS_UBWC_ALIGNED;
+ }
+
+ GetFrameBufferResolution(&x_pixels, &y_pixels);
+
+ AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(INT(x_pixels), INT(y_pixels), format,
+ usage, aligned_width, aligned_height);
+ layer_buffer.width = UINT32(aligned_width);
+ layer_buffer.height = UINT32(aligned_height);
+ layer_buffer.unaligned_width = x_pixels;
+ layer_buffer.unaligned_height = y_pixels;
+ layer_buffer.format = GetSDMFormat(format, flags);
+ }
+ }
+
+ return 0;
+}
+
+void HWCDisplay::CommitLayerParams(hwc_layer_1_t *hwc_layer, Layer *layer) {
+ const private_handle_t *pvt_handle = static_cast<const private_handle_t *>(hwc_layer->handle);
+ LayerBuffer &layer_buffer = layer->input_buffer;
+
+ if (pvt_handle) {
+ layer_buffer.planes[0].fd = pvt_handle->fd;
+ layer_buffer.planes[0].offset = pvt_handle->offset;
+ layer_buffer.planes[0].stride = UINT32(pvt_handle->width);
+ layer_buffer.size = pvt_handle->size;
+ }
+
+ // if swapinterval property is set to 0 then close and reset the acquireFd
+ if (swap_interval_zero_ && hwc_layer->acquireFenceFd >= 0) {
+ close(hwc_layer->acquireFenceFd);
+ hwc_layer->acquireFenceFd = -1;
+ }
+ layer_buffer.acquire_fence_fd = hwc_layer->acquireFenceFd;
+}
+
+int HWCDisplay::PrePrepareLayerStack(hwc_display_contents_1_t *content_list) {
+ if (shutdown_pending_) {
+ return 0;
+ }
+
+ size_t num_hw_layers = content_list->numHwLayers;
+
+ use_blit_comp_ = false;
+ metadata_refresh_rate_ = 0;
+ display_rect_ = LayerRect();
+
+ // Configure each layer
+ for (size_t i = 0; i < num_hw_layers; i++) {
+ hwc_layer_1_t &hwc_layer = content_list->hwLayers[i];
+
+ const private_handle_t *pvt_handle = static_cast<const private_handle_t *>(hwc_layer.handle);
+ Layer *layer = layer_stack_.layers.at(i);
+ int ret = PrepareLayerParams(&content_list->hwLayers[i], layer);
+
+ if (ret != kErrorNone) {
+ return ret;
+ }
+
+ layer->flags.skip = ((hwc_layer.flags & HWC_SKIP_LAYER) > 0);
+ layer->flags.solid_fill = (hwc_layer.flags & kDimLayer) || solid_fill_enable_;
+ if (layer->flags.skip || layer->flags.solid_fill) {
+ layer->dirty_regions.clear();
+ }
+
+ hwc_rect_t scaled_display_frame = hwc_layer.displayFrame;
+ ApplyScanAdjustment(&scaled_display_frame);
+
+ SetRect(scaled_display_frame, &layer->dst_rect);
+ if (pvt_handle) {
+ bool NonIntegralSourceCrop = IsNonIntegralSourceCrop(hwc_layer.sourceCropf);
+ bool secure = (pvt_handle->flags & private_handle_t::PRIV_FLAGS_SECURE_BUFFER) ||
+ (pvt_handle->flags & private_handle_t::PRIV_FLAGS_PROTECTED_BUFFER) ||
+ (pvt_handle->flags & private_handle_t::PRIV_FLAGS_SECURE_DISPLAY);
+ if (NonIntegralSourceCrop && (!secure && pvt_handle->bufferType != BUFFER_TYPE_VIDEO)) {
+ layer->flags.skip = true;
+ }
+ }
+ SetRect(hwc_layer.sourceCropf, &layer->src_rect);
+
+ uint32_t num_visible_rects = UINT32(hwc_layer.visibleRegionScreen.numRects);
+ uint32_t num_dirty_rects = UINT32(hwc_layer.surfaceDamage.numRects);
+
+ for (uint32_t j = 0; j < num_visible_rects; j++) {
+ LayerRect visible_rect = {};
+ SetRect(hwc_layer.visibleRegionScreen.rects[j], &visible_rect);
+ layer->visible_regions.push_back(visible_rect);
+ }
+
+ for (uint32_t j = 0; j < num_dirty_rects; j++) {
+ LayerRect dirty_rect = {};
+ SetRect(hwc_layer.surfaceDamage.rects[j], &dirty_rect);
+ layer->dirty_regions.push_back(dirty_rect);
+ }
+
+ if (blit_engine_) {
+ for (uint32_t j = 0; j < kMaxBlitTargetLayers; j++) {
+ LayerRect blit_rect = {};
+ layer->blit_regions.push_back(blit_rect);
+ }
+ }
+
+ SetComposition(hwc_layer.compositionType, &layer->composition);
+ if (hwc_layer.compositionType != HWC_FRAMEBUFFER_TARGET) {
+ display_rect_ = Union(display_rect_, layer->dst_rect);
+ }
+
+ // For dim layers, SurfaceFlinger
+ // - converts planeAlpha to per pixel alpha,
+ // - sets appropriate RGB color,
+ // - sets planeAlpha to 0xff,
+ // - blending to Premultiplied.
+ // This can be achieved at hardware by
+ // - solid fill ARGB to appropriate value,
+ // - incoming planeAlpha,
+ // - blending to Coverage.
+ if (hwc_layer.flags & kDimLayer) {
+ layer->input_buffer.format = kFormatARGB8888;
+ layer->solid_fill_color = 0xff000000;
+#ifdef QTI_BSP
+ // Get ARGB color from HWC Dim Layer color
+ uint32_t a = UINT32(hwc_layer.color.a) << 24;
+ uint32_t r = UINT32(hwc_layer.color.r) << 16;
+ uint32_t g = UINT32(hwc_layer.color.g) << 8;
+ uint32_t b = UINT32(hwc_layer.color.b);
+ layer->solid_fill_color = a | r | g | b;
+#endif
+ SetBlending(HWC_BLENDING_COVERAGE, &layer->blending);
+ } else {
+ SetBlending(hwc_layer.blending, &layer->blending);
+ LayerTransform &layer_transform = layer->transform;
+ uint32_t &hwc_transform = hwc_layer.transform;
+ layer_transform.flip_horizontal = ((hwc_transform & HWC_TRANSFORM_FLIP_H) > 0);
+ layer_transform.flip_vertical = ((hwc_transform & HWC_TRANSFORM_FLIP_V) > 0);
+ layer_transform.rotation = ((hwc_transform & HWC_TRANSFORM_ROT_90) ? 90.0f : 0.0f);
+ }
+
+ // TODO(user): Remove below block.
+ // For solid fill, only dest rect need to be specified.
+ if (layer->flags.solid_fill) {
+ LayerBuffer &input_buffer = layer->input_buffer;
+ input_buffer.width = UINT32(layer->dst_rect.right - layer->dst_rect.left);
+ input_buffer.height = UINT32(layer->dst_rect.bottom - layer->dst_rect.top);
+ input_buffer.unaligned_width = input_buffer.width;
+ input_buffer.unaligned_height = input_buffer.height;
+ layer->src_rect.left = 0;
+ layer->src_rect.top = 0;
+ layer->src_rect.right = input_buffer.width;
+ layer->src_rect.bottom = input_buffer.height;
+ }
+
+ layer->plane_alpha = hwc_layer.planeAlpha;
+ layer->flags.cursor = ((hwc_layer.flags & HWC_IS_CURSOR_LAYER) > 0);
+ layer->flags.updating = true;
+
+ if (num_hw_layers <= kMaxLayerCount) {
+ layer->flags.updating = IsLayerUpdating(content_list, layer);
+ }
+#ifdef QTI_BSP
+ if (hwc_layer.flags & HWC_SCREENSHOT_ANIMATOR_LAYER) {
+ layer_stack_.flags.animating = true;
+ }
+#endif
+ if (layer->flags.skip) {
+ layer_stack_.flags.skip_present = true;
+ }
+
+ if (layer->flags.cursor) {
+ layer_stack_.flags.cursor_present = true;
+ }
+
+ PrepareDynamicRefreshRate(layer);
+
+ layer->input_buffer.buffer_id = reinterpret_cast<uint64_t>(hwc_layer.handle);
+ }
+
+ // Prepare the Blit Target
+ if (blit_engine_) {
+ // TODO(user): Fix this to enable BLIT
+#if 0
+ int ret = blit_engine_->Prepare(&layer_stack_);
+ if (ret) {
+ // Blit engine cannot handle this layer stack, hence set the layer stack
+ // count to num_hw_layers
+ layer_stack_.layer_count -= kMaxBlitTargetLayers;
+ } else {
+ use_blit_comp_ = true;
+ }
+#endif
+ }
+
+ // Configure layer stack
+ layer_stack_.flags.geometry_changed = ((content_list->flags & HWC_GEOMETRY_CHANGED) > 0);
+
+ return 0;
+}
+
+void HWCDisplay::SetLayerS3DMode(const LayerBufferS3DFormat &source, uint32_t *target) {
+#ifdef QTI_BSP
+ switch (source) {
+ case kS3dFormatNone: *target = HWC_S3DMODE_NONE; break;
+ case kS3dFormatLeftRight: *target = HWC_S3DMODE_LR; break;
+ case kS3dFormatRightLeft: *target = HWC_S3DMODE_RL; break;
+ case kS3dFormatTopBottom: *target = HWC_S3DMODE_TB; break;
+ case kS3dFormatFramePacking: *target = HWC_S3DMODE_FP; break;
+ default: *target = HWC_S3DMODE_MAX; break;
+ }
+#endif
+}
+
+int HWCDisplay::PrepareLayerStack(hwc_display_contents_1_t *content_list) {
+ if (shutdown_pending_) {
+ return 0;
+ }
+
+ size_t num_hw_layers = content_list->numHwLayers;
+
+ if (!skip_prepare_cnt) {
+ DisplayError error = display_intf_->Prepare(&layer_stack_);
+ if (error != kErrorNone) {
+ if (error == kErrorShutDown) {
+ shutdown_pending_ = true;
+ } else if ((error != kErrorPermission) && (error != kErrorNoAppLayers)) {
+ DLOGE("Prepare failed. Error = %d", error);
+ // To prevent surfaceflinger infinite wait, flush the previous frame during Commit()
+ // so that previous buffer and fences are released, and override the error.
+ flush_ = true;
+ } else {
+ DLOGV("Prepare failed for Display = %d Error = %d", type_, error);
+ }
+ return 0;
+ }
+ } else {
+ // Skip is not set
+ MarkLayersForGPUBypass(content_list);
+ skip_prepare_cnt = skip_prepare_cnt - 1;
+ DLOGI("SecureDisplay %s, Skip Prepare/Commit and Flush", secure_display_active_ ? "Starting" :
+ "Stopping");
+ flush_ = true;
+ }
+
+ for (size_t i = 0; i < num_hw_layers; i++) {
+ hwc_layer_1_t &hwc_layer = content_list->hwLayers[i];
+ Layer *layer = layer_stack_.layers.at(i);
+ LayerComposition composition = layer->composition;
+ private_handle_t* pvt_handle = static_cast<private_handle_t*>
+ (const_cast<native_handle_t*>(hwc_layer.handle));
+ MetaData_t *meta_data = pvt_handle ?
+ reinterpret_cast<MetaData_t *>(pvt_handle->base_metadata) : NULL;
+
+ if ((composition == kCompositionSDE) || (composition == kCompositionHybrid) ||
+ (composition == kCompositionBlit)) {
+ hwc_layer.hints |= HWC_HINT_CLEAR_FB;
+ }
+ SetComposition(composition, &hwc_layer.compositionType);
+
+ if (meta_data != NULL) {
+ if (composition == kCompositionGPUS3D) {
+ // Align HWC and client's dispaly ID in case of HDMI as primary
+ meta_data->s3dComp.displayId =
+ display_intf_->IsPrimaryDisplay() ? HWC_DISPLAY_PRIMARY: id_;
+ SetLayerS3DMode(layer->input_buffer.s3d_format,
+ &meta_data->s3dComp.s3dMode);
+ }
+ }
+ }
+
+ return 0;
+}
+
+int HWCDisplay::CommitLayerStack(hwc_display_contents_1_t *content_list) {
+ if (!content_list || !content_list->numHwLayers) {
+ DLOGW("Invalid content list");
+ return -EINVAL;
+ }
+
+ if (shutdown_pending_) {
+ return 0;
+ }
+
+ int status = 0;
+
+ size_t num_hw_layers = content_list->numHwLayers;
+
+ DumpInputBuffers(content_list);
+
+ if (!flush_) {
+ for (size_t i = 0; i < num_hw_layers; i++) {
+ CommitLayerParams(&content_list->hwLayers[i], layer_stack_.layers.at(i));
+ }
+
+ if (use_blit_comp_) {
+ status = blit_engine_->PreCommit(content_list, &layer_stack_);
+ if (status == 0) {
+ status = blit_engine_->Commit(content_list, &layer_stack_);
+ if (status != 0) {
+ DLOGE("Blit Comp Failed!");
+ }
+ }
+ }
+
+ if (layer_stack_.flags.hdr_present) {
+ status = tone_mapper_->HandleToneMap(content_list, &layer_stack_);
+ if (status != 0) {
+ DLOGE("Error handling HDR in ToneMapper");
+ }
+ } else {
+ tone_mapper_->Terminate();
+ }
+
+ DisplayError error = kErrorUndefined;
+ if (status == 0) {
+ error = display_intf_->Commit(&layer_stack_);
+ status = 0;
+ }
+
+ if (error == kErrorNone) {
+ // A commit is successfully submitted, start flushing on failure now onwards.
+ flush_on_error_ = true;
+ } else {
+ if (error == kErrorShutDown) {
+ shutdown_pending_ = true;
+ return status;
+ } else if (error != kErrorPermission) {
+ DLOGE("Commit failed. Error = %d", error);
+ // To prevent surfaceflinger infinite wait, flush the previous frame during Commit()
+ // so that previous buffer and fences are released, and override the error.
+ flush_ = true;
+ } else {
+ DLOGI("Commit failed for Display = %d Error = %d", type_, error);
+ }
+ }
+ }
+
+ return status;
+}
+
+int HWCDisplay::PostCommitLayerStack(hwc_display_contents_1_t *content_list) {
+ size_t num_hw_layers = content_list->numHwLayers;
+ int status = 0;
+
+ // Do no call flush on errors, if a successful buffer is never submitted.
+ if (flush_ && flush_on_error_) {
+ display_intf_->Flush();
+ }
+
+
+ if (tone_mapper_ && tone_mapper_->IsActive()) {
+ tone_mapper_->PostCommit(&layer_stack_);
+ }
+
+ // Set the release fence fd to the blit engine
+ if (use_blit_comp_ && blit_engine_->BlitActive()) {
+ blit_engine_->PostCommit(&layer_stack_);
+ }
+
+ for (size_t i = 0; i < num_hw_layers; i++) {
+ hwc_layer_1_t &hwc_layer = content_list->hwLayers[i];
+ Layer *layer = layer_stack_.layers.at(i);
+ LayerBuffer &layer_buffer = layer->input_buffer;
+
+ if (!flush_) {
+ // If swapinterval property is set to 0 or for single buffer layers, do not update f/w
+ // release fences and discard fences from driver
+ if (swap_interval_zero_ || layer->flags.single_buffer) {
+ hwc_layer.releaseFenceFd = -1;
+ close(layer_buffer.release_fence_fd);
+ layer_buffer.release_fence_fd = -1;
+ } else if (layer->composition != kCompositionGPU) {
+ hwc_layer.releaseFenceFd = layer_buffer.release_fence_fd;
+ }
+
+ // During animation on external/virtual display, SDM will use the cached
+ // framebuffer layer throughout animation and do not allow framework to do eglswapbuffer on
+ // framebuffer target. So graphics doesn't close the release fence fd of framebuffer target,
+ // Hence close the release fencefd of framebuffer target here.
+ if (disable_animation_) {
+ if (layer->composition == kCompositionGPUTarget && animating_) {
+ close(hwc_layer.releaseFenceFd);
+ hwc_layer.releaseFenceFd = -1;
+ }
+ }
+ }
+
+ if (hwc_layer.acquireFenceFd >= 0) {
+ close(hwc_layer.acquireFenceFd);
+ hwc_layer.acquireFenceFd = -1;
+ }
+ }
+
+ if (!flush_) {
+ animating_ = layer_stack_.flags.animating;
+ // if swapinterval property is set to 0 then close and reset the list retire fence
+ if (swap_interval_zero_) {
+ close(layer_stack_.retire_fence_fd);
+ layer_stack_.retire_fence_fd = -1;
+ }
+ content_list->retireFenceFd = layer_stack_.retire_fence_fd;
+
+ if (dump_frame_count_) {
+ dump_frame_count_--;
+ dump_frame_index_++;
+ }
+ }
+
+ flush_ = false;
+
+ return status;
+}
+
+bool HWCDisplay::IsLayerUpdating(hwc_display_contents_1_t *content_list, const Layer *layer) {
+ // Layer should be considered updating if
+ // a) layer is in single buffer mode, or
+ // b) valid dirty_regions(android specific hint for updating status), or
+ // c) layer stack geometry has changed
+ return (layer->flags.single_buffer || IsSurfaceUpdated(layer->dirty_regions) ||
+ (layer_stack_.flags.geometry_changed));
+}
+
+bool HWCDisplay::IsNonIntegralSourceCrop(const hwc_frect_t &source) {
+ if ((source.left != roundf(source.left)) ||
+ (source.top != roundf(source.top)) ||
+ (source.right != roundf(source.right)) ||
+ (source.bottom != roundf(source.bottom))) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+void HWCDisplay::SetRect(const hwc_rect_t &source, LayerRect *target) {
+ target->left = FLOAT(source.left);
+ target->top = FLOAT(source.top);
+ target->right = FLOAT(source.right);
+ target->bottom = FLOAT(source.bottom);
+}
+
+void HWCDisplay::SetRect(const hwc_frect_t &source, LayerRect *target) {
+ target->left = floorf(source.left);
+ target->top = floorf(source.top);
+ target->right = ceilf(source.right);
+ target->bottom = ceilf(source.bottom);
+}
+
+void HWCDisplay::SetComposition(const int32_t &source, LayerComposition *target) {
+ switch (source) {
+ case HWC_FRAMEBUFFER_TARGET: *target = kCompositionGPUTarget; break;
+ default: *target = kCompositionGPU; break;
+ }
+}
+
+void HWCDisplay::SetComposition(const LayerComposition &source, int32_t *target) {
+ switch (source) {
+ case kCompositionGPUTarget: *target = HWC_FRAMEBUFFER_TARGET; break;
+ case kCompositionGPU: *target = HWC_FRAMEBUFFER; break;
+ case kCompositionGPUS3D: *target = HWC_FRAMEBUFFER; break;
+ case kCompositionHWCursor: *target = HWC_CURSOR_OVERLAY; break;
+ default: *target = HWC_OVERLAY; break;
+ }
+}
+
+void HWCDisplay::SetBlending(const int32_t &source, LayerBlending *target) {
+ switch (source) {
+ case HWC_BLENDING_PREMULT: *target = kBlendingPremultiplied; break;
+ case HWC_BLENDING_COVERAGE: *target = kBlendingCoverage; break;
+ default: *target = kBlendingOpaque; break;
+ }
+}
+
+void HWCDisplay::SetIdleTimeoutMs(uint32_t timeout_ms) {
+ return;
+}
+
+DisplayError HWCDisplay::SetMaxMixerStages(uint32_t max_mixer_stages) {
+ DisplayError error = kErrorNone;
+
+ if (display_intf_) {
+ error = display_intf_->SetMaxMixerStages(max_mixer_stages);
+ }
+
+ return error;
+}
+
+LayerBufferFormat HWCDisplay::GetSDMFormat(const int32_t &source, const int flags) {
+ LayerBufferFormat format = kFormatInvalid;
+ if (flags & private_handle_t::PRIV_FLAGS_UBWC_ALIGNED) {
+ switch (source) {
+ case HAL_PIXEL_FORMAT_RGBA_8888: format = kFormatRGBA8888Ubwc; break;
+ case HAL_PIXEL_FORMAT_RGBX_8888: format = kFormatRGBX8888Ubwc; break;
+ case HAL_PIXEL_FORMAT_BGR_565: format = kFormatBGR565Ubwc; break;
+ case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
+ case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC:
+ case HAL_PIXEL_FORMAT_NV12_ENCODEABLE: format = kFormatYCbCr420SPVenusUbwc; break;
+ case HAL_PIXEL_FORMAT_RGBA_1010102: format = kFormatRGBA1010102Ubwc; break;
+ case HAL_PIXEL_FORMAT_RGBX_1010102: format = kFormatRGBX1010102Ubwc; break;
+ case HAL_PIXEL_FORMAT_YCbCr_420_TP10_UBWC: format = kFormatYCbCr420TP10Ubwc; break;
+ case HAL_PIXEL_FORMAT_YCbCr_420_P010_UBWC: format = kFormatYCbCr420P010Ubwc; break;
+ default:
+ DLOGE("Unsupported format type for UBWC %d", source);
+ return kFormatInvalid;
+ }
+ return format;
+ }
+
+ switch (source) {
+ case HAL_PIXEL_FORMAT_RGBA_8888: format = kFormatRGBA8888; break;
+ case HAL_PIXEL_FORMAT_RGBA_5551: format = kFormatRGBA5551; break;
+ case HAL_PIXEL_FORMAT_RGBA_4444: format = kFormatRGBA4444; break;
+ case HAL_PIXEL_FORMAT_BGRA_8888: format = kFormatBGRA8888; break;
+ case HAL_PIXEL_FORMAT_RGBX_8888: format = kFormatRGBX8888; break;
+ case HAL_PIXEL_FORMAT_BGRX_8888: format = kFormatBGRX8888; break;
+ case HAL_PIXEL_FORMAT_RGB_888: format = kFormatRGB888; break;
+ case HAL_PIXEL_FORMAT_RGB_565: format = kFormatRGB565; break;
+ case HAL_PIXEL_FORMAT_BGR_565: format = kFormatBGR565; break;
+ case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
+ case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS: format = kFormatYCbCr420SemiPlanarVenus; break;
+ case HAL_PIXEL_FORMAT_YCrCb_420_SP_VENUS: format = kFormatYCrCb420SemiPlanarVenus; break;
+ case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC: format = kFormatYCbCr420SPVenusUbwc; break;
+ case HAL_PIXEL_FORMAT_YV12: format = kFormatYCrCb420PlanarStride16; break;
+ case HAL_PIXEL_FORMAT_YCrCb_420_SP: format = kFormatYCrCb420SemiPlanar; break;
+ case HAL_PIXEL_FORMAT_YCbCr_420_SP: format = kFormatYCbCr420SemiPlanar; break;
+ case HAL_PIXEL_FORMAT_YCbCr_422_SP: format = kFormatYCbCr422H2V1SemiPlanar; break;
+ case HAL_PIXEL_FORMAT_YCbCr_422_I: format = kFormatYCbCr422H2V1Packed; break;
+ case HAL_PIXEL_FORMAT_CbYCrY_422_I: format = kFormatCbYCrY422H2V1Packed; break;
+ case HAL_PIXEL_FORMAT_RGBA_1010102: format = kFormatRGBA1010102; break;
+ case HAL_PIXEL_FORMAT_ARGB_2101010: format = kFormatARGB2101010; break;
+ case HAL_PIXEL_FORMAT_RGBX_1010102: format = kFormatRGBX1010102; break;
+ case HAL_PIXEL_FORMAT_XRGB_2101010: format = kFormatXRGB2101010; break;
+ case HAL_PIXEL_FORMAT_BGRA_1010102: format = kFormatBGRA1010102; break;
+ case HAL_PIXEL_FORMAT_ABGR_2101010: format = kFormatABGR2101010; break;
+ case HAL_PIXEL_FORMAT_BGRX_1010102: format = kFormatBGRX1010102; break;
+ case HAL_PIXEL_FORMAT_XBGR_2101010: format = kFormatXBGR2101010; break;
+ case HAL_PIXEL_FORMAT_YCbCr_420_P010: format = kFormatYCbCr420P010; break;
+ case HAL_PIXEL_FORMAT_YCbCr_420_TP10_UBWC: format = kFormatYCbCr420TP10Ubwc; break;
+ case HAL_PIXEL_FORMAT_YCbCr_420_P010_UBWC: format = kFormatYCbCr420P010Ubwc; break;
+ default:
+ DLOGW("Unsupported format type = %d", source);
+ return kFormatInvalid;
+ }
+
+ return format;
+}
+
+void HWCDisplay::DumpInputBuffers(hwc_display_contents_1_t *content_list) {
+ size_t num_hw_layers = content_list->numHwLayers;
+ char dir_path[PATH_MAX];
+
+ if (!dump_frame_count_ || flush_ || !dump_input_layers_) {
+ return;
+ }
+
+ snprintf(dir_path, sizeof(dir_path), "/data/misc/display/frame_dump_%s", GetDisplayString());
+
+ if (mkdir(dir_path, 0777) != 0 && errno != EEXIST) {
+ DLOGW("Failed to create %s directory errno = %d, desc = %s", dir_path, errno, strerror(errno));
+ return;
+ }
+
+ // if directory exists already, need to explicitly change the permission.
+ if (errno == EEXIST && chmod(dir_path, 0777) != 0) {
+ DLOGW("Failed to change permissions on %s directory", dir_path);
+ return;
+ }
+
+ for (uint32_t i = 0; i < num_hw_layers; i++) {
+ hwc_layer_1_t &hwc_layer = content_list->hwLayers[i];
+ const private_handle_t *pvt_handle = static_cast<const private_handle_t *>(hwc_layer.handle);
+
+ if (hwc_layer.acquireFenceFd >= 0) {
+ int error = sync_wait(hwc_layer.acquireFenceFd, 1000);
+ if (error < 0) {
+ DLOGW("sync_wait error errno = %d, desc = %s", errno, strerror(errno));
+ return;
+ }
+ }
+
+ if (pvt_handle && pvt_handle->base) {
+ char dump_file_name[PATH_MAX];
+ size_t result = 0;
+
+ snprintf(dump_file_name, sizeof(dump_file_name), "%s/input_layer%d_%dx%d_%s_frame%d.raw",
+ dir_path, i, pvt_handle->width, pvt_handle->height,
+ qdutils::GetHALPixelFormatString(pvt_handle->format), dump_frame_index_);
+
+ FILE* fp = fopen(dump_file_name, "w+");
+ if (fp) {
+ result = fwrite(reinterpret_cast<void *>(pvt_handle->base), pvt_handle->size, 1, fp);
+ fclose(fp);
+ }
+
+ DLOGI("Frame Dump %s: is %s", dump_file_name, result ? "Successful" : "Failed");
+ }
+ }
+}
+
+void HWCDisplay::DumpOutputBuffer(const BufferInfo& buffer_info, void *base, int fence) {
+ char dir_path[PATH_MAX];
+
+ snprintf(dir_path, sizeof(dir_path), "/data/misc/display/frame_dump_%s", GetDisplayString());
+
+ if (mkdir(dir_path, 777) != 0 && errno != EEXIST) {
+ DLOGW("Failed to create %s directory errno = %d, desc = %s", dir_path, errno, strerror(errno));
+ return;
+ }
+
+ // if directory exists already, need to explicitly change the permission.
+ if (errno == EEXIST && chmod(dir_path, 0777) != 0) {
+ DLOGW("Failed to change permissions on %s directory", dir_path);
+ return;
+ }
+
+ if (base) {
+ char dump_file_name[PATH_MAX];
+ size_t result = 0;
+
+ if (fence >= 0) {
+ int error = sync_wait(fence, 1000);
+ if (error < 0) {
+ DLOGW("sync_wait error errno = %d, desc = %s", errno, strerror(errno));
+ return;
+ }
+ }
+
+ snprintf(dump_file_name, sizeof(dump_file_name), "%s/output_layer_%dx%d_%s_frame%d.raw",
+ dir_path, buffer_info.alloc_buffer_info.aligned_width,
+ buffer_info.alloc_buffer_info.aligned_height,
+ GetFormatString(buffer_info.buffer_config.format), dump_frame_index_);
+
+ FILE* fp = fopen(dump_file_name, "w+");
+ if (fp) {
+ result = fwrite(base, buffer_info.alloc_buffer_info.size, 1, fp);
+ fclose(fp);
+ }
+
+ DLOGI("Frame Dump of %s is %s", dump_file_name, result ? "Successful" : "Failed");
+ }
+}
+
+const char *HWCDisplay::GetDisplayString() {
+ switch (type_) {
+ case kPrimary:
+ return "primary";
+ case kHDMI:
+ return "hdmi";
+ case kVirtual:
+ return "virtual";
+ default:
+ return "invalid";
+ }
+}
+
+int HWCDisplay::SetFrameBufferResolution(uint32_t x_pixels, uint32_t y_pixels) {
+ DisplayConfigVariableInfo fb_config;
+ DisplayError error = display_intf_->GetFrameBufferConfig(&fb_config);
+ if (error != kErrorNone) {
+ DLOGV("Get frame buffer config failed. Error = %d", error);
+ return -EINVAL;
+ }
+
+ fb_config.x_pixels = x_pixels;
+ fb_config.y_pixels = y_pixels;
+
+ error = display_intf_->SetFrameBufferConfig(fb_config);
+ if (error != kErrorNone) {
+ DLOGV("Set frame buffer config failed. Error = %d", error);
+ return -EINVAL;
+ }
+
+ DLOGI("New framebuffer resolution (%dx%d)", x_pixels, y_pixels);
+
+ return 0;
+}
+
+void HWCDisplay::GetFrameBufferResolution(uint32_t *x_pixels, uint32_t *y_pixels) {
+ DisplayConfigVariableInfo fb_config;
+ display_intf_->GetFrameBufferConfig(&fb_config);
+
+ *x_pixels = fb_config.x_pixels;
+ *y_pixels = fb_config.y_pixels;
+}
+
+DisplayError HWCDisplay::GetMixerResolution(uint32_t *x_pixels, uint32_t *y_pixels) {
+ return display_intf_->GetMixerResolution(x_pixels, y_pixels);
+}
+
+
+void HWCDisplay::GetPanelResolution(uint32_t *x_pixels, uint32_t *y_pixels) {
+ DisplayConfigVariableInfo display_config;
+ uint32_t active_index = 0;
+
+ display_intf_->GetActiveConfig(&active_index);
+ display_intf_->GetConfig(active_index, &display_config);
+
+ *x_pixels = display_config.x_pixels;
+ *y_pixels = display_config.y_pixels;
+}
+
+int HWCDisplay::SetDisplayStatus(uint32_t display_status) {
+ int status = 0;
+ const hwc_procs_t *hwc_procs = *hwc_procs_;
+
+ switch (display_status) {
+ case kDisplayStatusResume:
+ display_paused_ = false;
+ case kDisplayStatusOnline:
+ status = SetPowerMode(HWC_POWER_MODE_NORMAL);
+ break;
+ case kDisplayStatusPause:
+ display_paused_ = true;
+ case kDisplayStatusOffline:
+ status = SetPowerMode(HWC_POWER_MODE_OFF);
+ break;
+ default:
+ DLOGW("Invalid display status %d", display_status);
+ return -EINVAL;
+ }
+
+ if (display_status == kDisplayStatusResume ||
+ display_status == kDisplayStatusPause) {
+ hwc_procs->invalidate(hwc_procs);
+ }
+
+ return status;
+}
+
+int HWCDisplay::SetCursorPosition(int x, int y) {
+ DisplayError error = kErrorNone;
+
+ if (shutdown_pending_) {
+ return 0;
+ }
+
+ error = display_intf_->SetCursorPosition(x, y);
+ if (error != kErrorNone) {
+ if (error == kErrorShutDown) {
+ shutdown_pending_ = true;
+ return 0;
+ }
+ DLOGE("Failed for x = %d y = %d, Error = %d", x, y, error);
+ return -1;
+ }
+
+ return 0;
+}
+
+int HWCDisplay::OnMinHdcpEncryptionLevelChange(uint32_t min_enc_level) {
+ DisplayError error = display_intf_->OnMinHdcpEncryptionLevelChange(min_enc_level);
+ if (error != kErrorNone) {
+ DLOGE("Failed. Error = %d", error);
+ return -1;
+ }
+
+ return 0;
+}
+
+void HWCDisplay::MarkLayersForGPUBypass(hwc_display_contents_1_t *content_list) {
+ for (size_t i = 0 ; i < (content_list->numHwLayers - 1); i++) {
+ hwc_layer_1_t *layer = &content_list->hwLayers[i];
+ layer->compositionType = HWC_OVERLAY;
+ }
+}
+
+void HWCDisplay::ApplyScanAdjustment(hwc_rect_t *display_frame) {
+}
+
+DisplayError HWCDisplay::SetCSC(const MetaData_t *meta_data, ColorMetaData *color_metadata) {
+ if (meta_data->operation & COLOR_METADATA) {
+#ifdef USE_COLOR_METADATA
+ *color_metadata = meta_data->color;
+#endif
+ } else if (meta_data->operation & UPDATE_COLOR_SPACE) {
+ ColorSpace_t csc = meta_data->colorSpace;
+ color_metadata->range = Range_Limited;
+
+ if (csc == ITU_R_601_FR || csc == ITU_R_2020_FR) {
+ color_metadata->range = Range_Full;
+ }
+
+ switch (csc) {
+ case ITU_R_601:
+ case ITU_R_601_FR:
+ // display driver uses 601 irrespective of 525 or 625
+ color_metadata->colorPrimaries = ColorPrimaries_BT601_6_525;
+ break;
+ case ITU_R_709:
+ color_metadata->colorPrimaries = ColorPrimaries_BT709_5;
+ break;
+ case ITU_R_2020:
+ case ITU_R_2020_FR:
+ color_metadata->colorPrimaries = ColorPrimaries_BT2020;
+ break;
+ default:
+ DLOGE("Unsupported CSC: %d", csc);
+ return kErrorNotSupported;
+ }
+ }
+
+ return kErrorNone;
+}
+
+DisplayError HWCDisplay::SetIGC(IGC_t source, LayerIGC *target) {
+ switch (source) {
+ case IGC_NotSpecified: *target = kIGCNotSpecified; break;
+ case IGC_sRGB: *target = kIGCsRGB; break;
+ default:
+ DLOGE("Unsupported IGC: %d", source);
+ return kErrorNotSupported;
+ }
+
+ return kErrorNone;
+}
+
+DisplayError HWCDisplay::SetMetaData(const private_handle_t *pvt_handle, Layer *layer) {
+ const MetaData_t *meta_data = reinterpret_cast<MetaData_t *>(pvt_handle->base_metadata);
+ LayerBuffer &layer_buffer = layer->input_buffer;
+
+ if (!meta_data) {
+ return kErrorNone;
+ }
+
+ if (SetCSC(meta_data, &layer_buffer.color_metadata) != kErrorNone) {
+ return kErrorNotSupported;
+ }
+
+ bool hdr_layer = layer_buffer.color_metadata.colorPrimaries == ColorPrimaries_BT2020 &&
+ (layer_buffer.color_metadata.transfer == Transfer_SMPTE_ST2084 ||
+ layer_buffer.color_metadata.transfer == Transfer_HLG);
+ if (hdr_layer && !disable_hdr_handling_) {
+ // dont honor HDR when its handling is disabled
+ layer_buffer.flags.hdr = true;
+ layer_stack_.flags.hdr_present = true;
+ }
+
+ if (meta_data->operation & SET_IGC) {
+ if (SetIGC(meta_data->igc, &layer_buffer.igc) != kErrorNone) {
+ return kErrorNotSupported;
+ }
+ }
+
+ if (meta_data->operation & UPDATE_REFRESH_RATE) {
+ layer->frame_rate = RoundToStandardFPS(meta_data->refreshrate);
+ }
+
+ if ((meta_data->operation & PP_PARAM_INTERLACED) && meta_data->interlaced) {
+ layer_buffer.flags.interlace = true;
+ }
+
+ if (meta_data->operation & LINEAR_FORMAT) {
+ layer_buffer.format = GetSDMFormat(INT32(meta_data->linearFormat), 0);
+ }
+
+ if (meta_data->operation & SET_SINGLE_BUFFER_MODE) {
+ layer->flags.single_buffer = meta_data->isSingleBufferMode;
+ // Graphics can set this operation on all types of layers including FB and set the actual value
+ // to 0. To protect against SET operations of 0 value, we need to do a logical OR.
+ layer_stack_.flags.single_buffered_layer_present |= meta_data->isSingleBufferMode;
+ }
+
+ if (meta_data->operation & S3D_FORMAT) {
+ std::map<int, LayerBufferS3DFormat>::iterator it =
+ s3d_format_hwc_to_sdm_.find(INT32(meta_data->s3dFormat));
+ if (it != s3d_format_hwc_to_sdm_.end()) {
+ layer->input_buffer.s3d_format = it->second;
+ } else {
+ DLOGW("Invalid S3D format %d", meta_data->s3dFormat);
+ }
+ }
+
+ return kErrorNone;
+}
+
+int HWCDisplay::SetPanelBrightness(int level) {
+ int ret = 0;
+ if (display_intf_)
+ ret = display_intf_->SetPanelBrightness(level);
+ else
+ ret = -EINVAL;
+
+ return ret;
+}
+
+int HWCDisplay::GetPanelBrightness(int *level) {
+ return display_intf_->GetPanelBrightness(level);
+}
+
+int HWCDisplay::CachePanelBrightness(int level) {
+ int ret = 0;
+ if (display_intf_)
+ ret = display_intf_->CachePanelBrightness(level);
+ else
+ ret = -EINVAL;
+
+ return ret;
+}
+
+int HWCDisplay::ToggleScreenUpdates(bool enable) {
+ const hwc_procs_t *hwc_procs = *hwc_procs_;
+ display_paused_ = enable ? false : true;
+ hwc_procs->invalidate(hwc_procs);
+ return 0;
+}
+
+int HWCDisplay::ColorSVCRequestRoute(const PPDisplayAPIPayload &in_payload,
+ PPDisplayAPIPayload *out_payload,
+ PPPendingParams *pending_action) {
+ int ret = 0;
+
+ if (display_intf_)
+ ret = display_intf_->ColorSVCRequestRoute(in_payload, out_payload, pending_action);
+ else
+ ret = -EINVAL;
+
+ return ret;
+}
+
+int HWCDisplay::GetVisibleDisplayRect(hwc_rect_t* visible_rect) {
+ if (!IsValid(display_rect_)) {
+ return -EINVAL;
+ }
+
+ visible_rect->left = INT(display_rect_.left);
+ visible_rect->top = INT(display_rect_.top);
+ visible_rect->right = INT(display_rect_.right);
+ visible_rect->bottom = INT(display_rect_.bottom);
+ DLOGI("Dpy = %d Visible Display Rect(%d %d %d %d)", visible_rect->left, visible_rect->top,
+ visible_rect->right, visible_rect->bottom);
+
+ return 0;
+}
+
+void HWCDisplay::SetSecureDisplay(bool secure_display_active, bool force_flush) {
+ secure_display_active_ = secure_display_active;
+ return;
+}
+
+int HWCDisplay::SetActiveDisplayConfig(int config) {
+ return display_intf_->SetActiveConfig(UINT32(config)) == kErrorNone ? 0 : -1;
+}
+
+int HWCDisplay::GetActiveDisplayConfig(uint32_t *config) {
+ return display_intf_->GetActiveConfig(config) == kErrorNone ? 0 : -1;
+}
+
+int HWCDisplay::GetDisplayConfigCount(uint32_t *count) {
+ return display_intf_->GetNumVariableInfoConfigs(count) == kErrorNone ? 0 : -1;
+}
+
+int HWCDisplay::GetDisplayAttributesForConfig(int config,
+ DisplayConfigVariableInfo *display_attributes) {
+ return display_intf_->GetConfig(UINT32(config), display_attributes) == kErrorNone ? 0 : -1;
+}
+
+int HWCDisplay::GetDisplayFixedConfig(DisplayConfigFixedInfo *fixed_info) {
+ return display_intf_->GetConfig(fixed_info) == kErrorNone ? 0 : -1;
+}
+
+// TODO(user): HWC needs to know updating for dyn_fps, cpu hint features,
+// once the features are moved to SDM, the two functions below can be removed.
+uint32_t HWCDisplay::GetUpdatingLayersCount(uint32_t app_layer_count) {
+ uint32_t updating_count = 0;
+
+ for (uint i = 0; i < app_layer_count; i++) {
+ Layer *layer = layer_stack_.layers.at(i);
+ if (layer->flags.updating) {
+ updating_count++;
+ }
+ }
+
+ return updating_count;
+}
+
+bool HWCDisplay::SingleVideoLayerUpdating(uint32_t app_layer_count) {
+ uint32_t updating_count = 0;
+
+ for (uint i = 0; i < app_layer_count; i++) {
+ Layer *layer = layer_stack_.layers[i];
+ // TODO(user): disable DRC feature in S3D playbacl case.S3D video
+ // need play in dedicate resolution and fps, if DRC switch the
+ // mode to an non S3D supported mode, it would break S3D playback.
+ // Need figure out a way to make S3D and DRC co-exist.
+ if (layer->flags.updating && (layer->input_buffer.flags.video == true) &&
+ (layer->input_buffer.s3d_format == kS3dFormatNone)) {
+ updating_count++;
+ }
+ }
+
+ return (updating_count == 1);
+}
+
+uint32_t HWCDisplay::RoundToStandardFPS(float fps) {
+ static const uint32_t standard_fps[4] = {30, 24, 48, 60};
+ uint32_t frame_rate = (uint32_t)(fps);
+
+ int count = INT(sizeof(standard_fps) / sizeof(standard_fps[0]));
+ for (int i = 0; i < count; i++) {
+ if ((standard_fps[i] - frame_rate) < 2) {
+ // Most likely used for video, the fps can fluctuate
+ // Ex: b/w 29 and 30 for 30 fps clip
+ return standard_fps[i];
+ }
+ }
+
+ return frame_rate;
+}
+
+uint32_t HWCDisplay::SanitizeRefreshRate(uint32_t req_refresh_rate) {
+ uint32_t refresh_rate = req_refresh_rate;
+
+ if (refresh_rate < min_refresh_rate_) {
+ // Pick the next multiple of request which is within the range
+ refresh_rate = (((min_refresh_rate_ / refresh_rate) +
+ ((min_refresh_rate_ % refresh_rate) ? 1 : 0)) * refresh_rate);
+ }
+
+ if (refresh_rate > max_refresh_rate_) {
+ refresh_rate = max_refresh_rate_;
+ }
+
+ return refresh_rate;
+}
+
+DisplayClass HWCDisplay::GetDisplayClass() {
+ return display_class_;
+}
+
+void HWCDisplay::PrepareDynamicRefreshRate(Layer *layer) {
+ if (layer->frame_rate > metadata_refresh_rate_) {
+ metadata_refresh_rate_ = SanitizeRefreshRate(layer->frame_rate);
+ } else {
+ layer->frame_rate = current_refresh_rate_;
+ }
+}
+
+bool HWCDisplay::IsSurfaceUpdated(const std::vector<LayerRect> &dirty_regions) {
+ // based on dirty_regions determine if its updating
+ // dirty_rect count = 0 - whole layer - updating.
+ // dirty_rect count = 1 or more valid rects - updating.
+ // dirty_rect count = 1 with (0,0,0,0) - not updating.
+ return (dirty_regions.empty() || IsValid(dirty_regions.at(0)));
+}
+
+int HWCDisplay::GetDisplayPort(DisplayPort *port) {
+ return display_intf_->GetDisplayPort(port) == kErrorNone ? 0 : -1;
+}
+
+
+} // namespace sdm
diff --git a/msm8909/sdm/libs/hwc/hwc_display.h b/msm8909/sdm/libs/hwc/hwc_display.h
new file mode 100644
index 00000000..b0a40d5b
--- /dev/null
+++ b/msm8909/sdm/libs/hwc/hwc_display.h
@@ -0,0 +1,266 @@
+/*
+* Copyright (c) 2014 - 2017, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without modification, are permitted
+* provided that the following conditions are met:
+* * Redistributions of source code must retain the above copyright notice, this list of
+* conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright notice, this list of
+* conditions and the following disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its contributors may be used to
+* endorse or promote products derived from this software without specific prior written
+* permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __HWC_DISPLAY_H__
+#define __HWC_DISPLAY_H__
+
+#include <hardware/hwcomposer.h>
+#include <core/core_interface.h>
+#include <qdMetaData.h>
+#include <QService.h>
+#include <private/color_params.h>
+#include <map>
+#include <vector>
+#include <string>
+
+namespace sdm {
+
+class BlitEngine;
+class HWCToneMapper;
+
+// Subclasses set this to their type. This has to be different from DisplayType.
+// This is to avoid RTTI and dynamic_cast
+enum DisplayClass {
+ DISPLAY_CLASS_PRIMARY,
+ DISPLAY_CLASS_EXTERNAL,
+ DISPLAY_CLASS_VIRTUAL,
+ DISPLAY_CLASS_NULL
+};
+
+class HWCColorMode {
+ public:
+ explicit HWCColorMode(DisplayInterface *display_intf) : display_intf_(display_intf) {}
+ ~HWCColorMode() {}
+ void Init();
+ void DeInit() {}
+ int SetColorMode(const std::string &color_mode);
+ const std::vector<std::string> &GetColorModes();
+ int SetColorTransform(uint32_t matrix_count, const float *matrix);
+
+ private:
+ static const uint32_t kColorTransformMatrixCount = 16;
+ template <class T>
+ void CopyColorTransformMatrix(const T *input_matrix, double *output_matrix) {
+ for (uint32_t i = 0; i < kColorTransformMatrixCount; i++) {
+ output_matrix[i] = static_cast<double>(input_matrix[i]);
+ }
+ }
+ int PopulateColorModes();
+ DisplayInterface *display_intf_ = NULL;
+ std::vector<std::string> color_modes_ = {};
+ std::string current_color_mode_ = {};
+};
+
+class HWCDisplay : public DisplayEventHandler {
+ public:
+ enum {
+ SET_METADATA_DYN_REFRESH_RATE,
+ SET_BINDER_DYN_REFRESH_RATE,
+ SET_DISPLAY_MODE,
+ SET_QDCM_SOLID_FILL_INFO,
+ UNSET_QDCM_SOLID_FILL_INFO,
+ };
+
+ virtual ~HWCDisplay() { }
+ virtual int Init();
+ virtual int Deinit();
+ virtual int Prepare(hwc_display_contents_1_t *content_list) = 0;
+ virtual int Commit(hwc_display_contents_1_t *content_list) = 0;
+ virtual int EventControl(int event, int enable);
+ virtual int SetPowerMode(int mode);
+
+ // Framebuffer configurations
+ virtual int GetDisplayConfigs(uint32_t *configs, size_t *num_configs);
+ virtual int GetDisplayAttributes(uint32_t config, const uint32_t *display_attributes,
+ int32_t *values);
+ virtual int GetActiveConfig();
+ virtual int SetActiveConfig(int index);
+
+ virtual void SetIdleTimeoutMs(uint32_t timeout_ms);
+ virtual void SetFrameDumpConfig(uint32_t count, uint32_t bit_mask_layer_type);
+ virtual DisplayError SetMaxMixerStages(uint32_t max_mixer_stages);
+ virtual DisplayError ControlPartialUpdate(bool enable, uint32_t *pending) {
+ return kErrorNotSupported;
+ }
+ virtual uint32_t GetLastPowerMode();
+ virtual int SetFrameBufferResolution(uint32_t x_pixels, uint32_t y_pixels);
+ virtual void GetFrameBufferResolution(uint32_t *x_pixels, uint32_t *y_pixels);
+ virtual int SetDisplayStatus(uint32_t display_status);
+ virtual int OnMinHdcpEncryptionLevelChange(uint32_t min_enc_level);
+ virtual int Perform(uint32_t operation, ...);
+ virtual int SetCursorPosition(int x, int y);
+ virtual void SetSecureDisplay(bool secure_display_active, bool force_flush);
+ virtual DisplayError SetMixerResolution(uint32_t width, uint32_t height);
+ virtual DisplayError GetMixerResolution(uint32_t *width, uint32_t *height);
+ virtual void GetPanelResolution(uint32_t *width, uint32_t *height);
+
+ // Captures frame output in the buffer specified by output_buffer_info. The API is
+ // non-blocking and the client is expected to check operation status later on.
+ // Returns -1 if the input is invalid.
+ virtual int FrameCaptureAsync(const BufferInfo& output_buffer_info, bool post_processed) {
+ return -1;
+ }
+ // Returns the status of frame capture operation requested with FrameCaptureAsync().
+ // -EAGAIN : No status obtain yet, call API again after another frame.
+ // < 0 : Operation happened but failed.
+ // 0 : Success.
+ virtual int GetFrameCaptureStatus() { return -EAGAIN; }
+
+ virtual DisplayError SetDetailEnhancerConfig(const DisplayDetailEnhancerData &de_data) {
+ return kErrorNotSupported;
+ }
+
+ // Display Configurations
+ virtual int SetActiveDisplayConfig(int config);
+ virtual int GetActiveDisplayConfig(uint32_t *config);
+ virtual int GetDisplayConfigCount(uint32_t *count);
+ virtual int GetDisplayAttributesForConfig(int config,
+ DisplayConfigVariableInfo *display_attributes);
+ virtual int GetDisplayFixedConfig(DisplayConfigFixedInfo *fixed_info);
+
+ int SetPanelBrightness(int level);
+ int GetPanelBrightness(int *level);
+ int CachePanelBrightness(int level);
+ int ToggleScreenUpdates(bool enable);
+ int ColorSVCRequestRoute(const PPDisplayAPIPayload &in_payload,
+ PPDisplayAPIPayload *out_payload,
+ PPPendingParams *pending_action);
+ int GetVisibleDisplayRect(hwc_rect_t* rect);
+ DisplayClass GetDisplayClass();
+ int GetDisplayPort(DisplayPort *port);
+
+ protected:
+ enum DisplayStatus {
+ kDisplayStatusOffline = 0,
+ kDisplayStatusOnline,
+ kDisplayStatusPause,
+ kDisplayStatusResume,
+ };
+
+ // Dim layer flag set by SurfaceFlinger service.
+ static const uint32_t kDimLayer = 0x80000000;
+
+ // Maximum number of layers supported by display manager.
+ static const uint32_t kMaxLayerCount = 32;
+
+ HWCDisplay(CoreInterface *core_intf, hwc_procs_t const **hwc_procs, DisplayType type, int id,
+ bool needs_blit, qService::QService *qservice, DisplayClass display_class);
+
+ // DisplayEventHandler methods
+ virtual DisplayError VSync(const DisplayEventVSync &vsync);
+ virtual DisplayError Refresh();
+ virtual DisplayError CECMessage(char *message);
+
+ int AllocateLayerStack(hwc_display_contents_1_t *content_list);
+ void FreeLayerStack();
+ virtual int PrePrepareLayerStack(hwc_display_contents_1_t *content_list);
+ virtual int PrepareLayerStack(hwc_display_contents_1_t *content_list);
+ virtual int CommitLayerStack(hwc_display_contents_1_t *content_list);
+ virtual int PostCommitLayerStack(hwc_display_contents_1_t *content_list);
+ virtual void DumpOutputBuffer(const BufferInfo& buffer_info, void *base, int fence);
+ virtual uint32_t RoundToStandardFPS(float fps);
+ virtual uint32_t SanitizeRefreshRate(uint32_t req_refresh_rate);
+ virtual void PrepareDynamicRefreshRate(Layer *layer);
+ virtual DisplayError DisablePartialUpdateOneFrame() {
+ return kErrorNotSupported;
+ }
+ inline void SetRect(const hwc_rect_t &source, LayerRect *target);
+ inline void SetRect(const hwc_frect_t &source, LayerRect *target);
+ inline void SetComposition(const int32_t &source, LayerComposition *target);
+ inline void SetComposition(const LayerComposition &source, int32_t *target);
+ inline void SetBlending(const int32_t &source, LayerBlending *target);
+ int SetFormat(const int32_t &source, const int flags, LayerBufferFormat *target);
+ void SetLayerS3DMode(const LayerBufferS3DFormat &source, uint32_t *target);
+ LayerBufferFormat GetSDMFormat(const int32_t &source, const int flags);
+ const char *GetDisplayString();
+ void MarkLayersForGPUBypass(hwc_display_contents_1_t *content_list);
+ virtual void ApplyScanAdjustment(hwc_rect_t *display_frame);
+ DisplayError SetCSC(const MetaData_t *meta_data, ColorMetaData *color_metadata);
+ DisplayError SetIGC(IGC_t source, LayerIGC *target);
+ DisplayError SetMetaData(const private_handle_t *pvt_handle, Layer *layer);
+ bool NeedsFrameBufferRefresh(hwc_display_contents_1_t *content_list);
+ bool IsLayerUpdating(hwc_display_contents_1_t *content_list, const Layer *layer);
+ bool IsNonIntegralSourceCrop(const hwc_frect_t &source);
+ uint32_t GetUpdatingLayersCount(uint32_t app_layer_count);
+ bool SingleVideoLayerUpdating(uint32_t app_layer_count);
+ bool IsSurfaceUpdated(const std::vector<LayerRect> &dirty_regions);
+
+ enum {
+ INPUT_LAYER_DUMP,
+ OUTPUT_LAYER_DUMP,
+ };
+
+ CoreInterface *core_intf_;
+ hwc_procs_t const **hwc_procs_;
+ DisplayType type_;
+ int id_;
+ bool needs_blit_ = false;
+ DisplayInterface *display_intf_ = NULL;
+ LayerStack layer_stack_;
+ bool flush_on_error_ = false;
+ bool flush_ = false;
+ uint32_t dump_frame_count_ = 0;
+ uint32_t dump_frame_index_ = 0;
+ bool dump_input_layers_ = false;
+ uint32_t last_power_mode_;
+ bool swap_interval_zero_ = false;
+ bool display_paused_ = false;
+ uint32_t min_refresh_rate_ = 0;
+ uint32_t max_refresh_rate_ = 0;
+ uint32_t current_refresh_rate_ = 0;
+ bool use_metadata_refresh_rate_ = false;
+ uint32_t metadata_refresh_rate_ = 0;
+ uint32_t force_refresh_rate_ = 0;
+ bool boot_animation_completed_ = false;
+ bool shutdown_pending_ = false;
+ bool use_blit_comp_ = false;
+ bool secure_display_active_ = false;
+ uint32_t skip_prepare_cnt = 0;
+ bool solid_fill_enable_ = false;
+ bool disable_animation_ = false;
+ uint32_t solid_fill_color_ = 0;
+ LayerRect display_rect_;
+ std::map<int, LayerBufferS3DFormat> s3d_format_hwc_to_sdm_;
+ bool animating_ = false;
+ HWCToneMapper *tone_mapper_ = NULL;
+ HWCColorMode *color_mode_ = NULL;
+ int disable_hdr_handling_ = 0; // disables HDR handling.
+
+ private:
+ void DumpInputBuffers(hwc_display_contents_1_t *content_list);
+ int PrepareLayerParams(hwc_layer_1_t *hwc_layer, Layer *layer);
+ void CommitLayerParams(hwc_layer_1_t *hwc_layer, Layer *layer);
+ BlitEngine *blit_engine_ = NULL;
+ qService::QService *qservice_ = NULL;
+ DisplayClass display_class_;
+};
+
+inline int HWCDisplay::Perform(uint32_t operation, ...) {
+ return 0;
+}
+
+} // namespace sdm
+
+#endif // __HWC_DISPLAY_H__
+
diff --git a/msm8909/sdm/libs/hwc/hwc_display_external.cpp b/msm8909/sdm/libs/hwc/hwc_display_external.cpp
new file mode 100644
index 00000000..a5358190
--- /dev/null
+++ b/msm8909/sdm/libs/hwc/hwc_display_external.cpp
@@ -0,0 +1,336 @@
+/*
+* Copyright (c) 2014 - 2016, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <cutils/properties.h>
+#include <utils/constants.h>
+#include <utils/debug.h>
+#include <algorithm>
+
+#include "hwc_display_external.h"
+#include "hwc_debugger.h"
+
+#define __CLASS__ "HWCDisplayExternal"
+
+namespace sdm {
+
+int HWCDisplayExternal::Create(CoreInterface *core_intf, hwc_procs_t const **hwc_procs,
+ qService::QService *qservice, HWCDisplay **hwc_display) {
+ return Create(core_intf, hwc_procs, 0, 0, qservice, false, hwc_display);
+}
+
+int HWCDisplayExternal::Create(CoreInterface *core_intf, hwc_procs_t const **hwc_procs,
+ uint32_t primary_width, uint32_t primary_height,
+ qService::QService *qservice, bool use_primary_res,
+ HWCDisplay **hwc_display) {
+ uint32_t external_width = 0;
+ uint32_t external_height = 0;
+ int drc_enabled = 0;
+ int drc_reset_fps_enabled = 0;
+ DisplayError error = kErrorNone;
+
+ HWCDisplay *hwc_display_external = new HWCDisplayExternal(core_intf, hwc_procs, qservice);
+ int status = hwc_display_external->Init();
+ if (status) {
+ delete hwc_display_external;
+ return status;
+ }
+
+ error = hwc_display_external->GetMixerResolution(&external_width, &external_height);
+ if (error != kErrorNone) {
+ return -EINVAL;
+ }
+
+ if (primary_width && primary_height) {
+ // use_primary_res means HWCDisplayExternal should directly set framebuffer resolution to the
+ // provided primary_width and primary_height
+ if (use_primary_res) {
+ external_width = primary_width;
+ external_height = primary_height;
+ } else {
+ int downscale_enabled = 0;
+ HWCDebugHandler::Get()->GetProperty("sdm.debug.downscale_external", &downscale_enabled);
+ if (downscale_enabled) {
+ GetDownscaleResolution(primary_width, primary_height, &external_width, &external_height);
+ }
+ }
+ }
+
+ status = hwc_display_external->SetFrameBufferResolution(external_width, external_height);
+ if (status) {
+ Destroy(hwc_display_external);
+ return status;
+ }
+
+ HWCDebugHandler::Get()->GetProperty("sdm.hdmi.drc_enabled", &(drc_enabled));
+ reinterpret_cast<HWCDisplayExternal *>(hwc_display_external)->drc_enabled_ = drc_enabled;
+
+ HWCDebugHandler::Get()->GetProperty("sdm.hdmi.drc_reset_fps", &(drc_reset_fps_enabled));
+ reinterpret_cast<HWCDisplayExternal *>(hwc_display_external)->drc_reset_fps_enabled_ =
+ drc_reset_fps_enabled;
+
+ *hwc_display = hwc_display_external;
+
+ return status;
+}
+
+void HWCDisplayExternal::Destroy(HWCDisplay *hwc_display) {
+ hwc_display->Deinit();
+ delete hwc_display;
+}
+
+HWCDisplayExternal::HWCDisplayExternal(CoreInterface *core_intf, hwc_procs_t const **hwc_procs,
+ qService::QService *qservice)
+ : HWCDisplay(core_intf, hwc_procs, kHDMI, HWC_DISPLAY_EXTERNAL, false, qservice,
+ DISPLAY_CLASS_EXTERNAL) {
+}
+
+int HWCDisplayExternal::Prepare(hwc_display_contents_1_t *content_list) {
+ int status = 0;
+ DisplayError error = kErrorNone;
+
+ if (secure_display_active_) {
+ MarkLayersForGPUBypass(content_list);
+ return status;
+ }
+
+ status = AllocateLayerStack(content_list);
+ if (status) {
+ return status;
+ }
+
+ status = PrePrepareLayerStack(content_list);
+ if (status) {
+ return status;
+ }
+
+ if (content_list->numHwLayers <= 1) {
+ flush_ = true;
+ return 0;
+ }
+
+ bool one_video_updating_layer = SingleVideoLayerUpdating(UINT32(content_list->numHwLayers - 1));
+
+ uint32_t refresh_rate = GetOptimalRefreshRate(one_video_updating_layer);
+ if (current_refresh_rate_ != refresh_rate) {
+ error = display_intf_->SetRefreshRate(refresh_rate);
+ if (error == kErrorNone) {
+ // On success, set current refresh rate to new refresh rate
+ current_refresh_rate_ = refresh_rate;
+ }
+ }
+
+ status = PrepareLayerStack(content_list);
+ if (status) {
+ return status;
+ }
+
+ return 0;
+}
+
+int HWCDisplayExternal::Commit(hwc_display_contents_1_t *content_list) {
+ int status = 0;
+
+ if (secure_display_active_) {
+ return status;
+ }
+
+ status = HWCDisplay::CommitLayerStack(content_list);
+ if (status) {
+ return status;
+ }
+
+ status = HWCDisplay::PostCommitLayerStack(content_list);
+ if (status) {
+ return status;
+ }
+
+ return 0;
+}
+
+void HWCDisplayExternal::ApplyScanAdjustment(hwc_rect_t *display_frame) {
+ if (display_intf_->IsUnderscanSupported()) {
+ return;
+ }
+
+ // Read user defined width and height ratio
+ int width = 0, height = 0;
+ HWCDebugHandler::Get()->GetProperty("sdm.external_action_safe_width", &width);
+ float width_ratio = FLOAT(width) / 100.0f;
+ HWCDebugHandler::Get()->GetProperty("sdm.external_action_safe_height", &height);
+ float height_ratio = FLOAT(height) / 100.0f;
+
+ if (width_ratio == 0.0f || height_ratio == 0.0f) {
+ return;
+ }
+
+ uint32_t mixer_width = 0;
+ uint32_t mixer_height = 0;
+ GetMixerResolution(&mixer_width, &mixer_height);
+
+ if (mixer_width == 0 || mixer_height == 0) {
+ DLOGV("Invalid mixer dimensions (%d, %d)", mixer_width, mixer_height);
+ return;
+ }
+
+ uint32_t new_mixer_width = UINT32(mixer_width * FLOAT(1.0f - width_ratio));
+ uint32_t new_mixer_height = UINT32(mixer_height * FLOAT(1.0f - height_ratio));
+
+ int x_offset = INT((FLOAT(mixer_width) * width_ratio) / 2.0f);
+ int y_offset = INT((FLOAT(mixer_height) * height_ratio) / 2.0f);
+
+ display_frame->left = (display_frame->left * INT32(new_mixer_width) / INT32(mixer_width))
+ + x_offset;
+ display_frame->top = (display_frame->top * INT32(new_mixer_height) / INT32(mixer_height)) +
+ y_offset;
+ display_frame->right = ((display_frame->right * INT32(new_mixer_width)) / INT32(mixer_width)) +
+ x_offset;
+ display_frame->bottom = ((display_frame->bottom * INT32(new_mixer_height)) / INT32(mixer_height))
+ + y_offset;
+}
+
+void HWCDisplayExternal::SetSecureDisplay(bool secure_display_active, bool force_flush) {
+ if (secure_display_active_ != secure_display_active) {
+ secure_display_active_ = secure_display_active;
+
+ if (secure_display_active_) {
+ DisplayError error = display_intf_->Flush();
+ if (error != kErrorNone) {
+ DLOGE("Flush failed. Error = %d", error);
+ }
+ }
+ }
+ return;
+}
+
+static void AdjustSourceResolution(uint32_t dst_width, uint32_t dst_height, uint32_t *src_width,
+ uint32_t *src_height) {
+ *src_height = (dst_width * (*src_height)) / (*src_width);
+ *src_width = dst_width;
+}
+
+void HWCDisplayExternal::GetDownscaleResolution(uint32_t primary_width, uint32_t primary_height,
+ uint32_t *non_primary_width, uint32_t *non_primary_height) {
+ uint32_t primary_area = primary_width * primary_height;
+ uint32_t non_primary_area = (*non_primary_width) * (*non_primary_height);
+
+ if (primary_area > non_primary_area) {
+ if (primary_height > primary_width) {
+ std::swap(primary_height, primary_width);
+ }
+ AdjustSourceResolution(primary_width, primary_height, non_primary_width, non_primary_height);
+ }
+}
+
+uint32_t HWCDisplayExternal::RoundToStandardFPS(float fps) {
+ static const uint32_t standard_fps[] = {23976, 24000, 25000, 29970, 30000, 50000, 59940, 60000};
+ static const uint32_t mapping_fps[] = {59940, 60000, 60000, 59940, 60000, 50000, 59940, 60000};
+ uint32_t frame_rate = (uint32_t)(fps * 1000);
+
+ // process non valid
+ if (frame_rate == 0) {
+ return current_refresh_rate_;
+ }
+
+ int count = INT(sizeof(standard_fps) / sizeof(standard_fps[0]));
+ for (int i = 0; i < count; i++) {
+ // Most likely used for video, the fps for frames should be stable from video side.
+ if (standard_fps[i] > frame_rate) {
+ if (i > 0) {
+ if ((standard_fps[i] - frame_rate) > (frame_rate - standard_fps[i-1])) {
+ return mapping_fps[i-1];
+ } else {
+ return mapping_fps[i];
+ }
+ } else {
+ return mapping_fps[i];
+ }
+ }
+ }
+
+ return standard_fps[count - 1];
+}
+
+void HWCDisplayExternal::PrepareDynamicRefreshRate(Layer *layer) {
+ if (layer->input_buffer.flags.video) {
+ if (layer->frame_rate != 0) {
+ metadata_refresh_rate_ = SanitizeRefreshRate(layer->frame_rate);
+ } else {
+ metadata_refresh_rate_ = current_refresh_rate_;
+ }
+ layer->frame_rate = current_refresh_rate_;
+ } else if (!layer->frame_rate) {
+ layer->frame_rate = current_refresh_rate_;
+ }
+}
+
+void HWCDisplayExternal::ForceRefreshRate(uint32_t refresh_rate) {
+ if ((refresh_rate && (refresh_rate < min_refresh_rate_ || refresh_rate > max_refresh_rate_)) ||
+ force_refresh_rate_ == refresh_rate) {
+ // Cannot honor force refresh rate, as its beyond the range or new request is same
+ return;
+ }
+
+ force_refresh_rate_ = refresh_rate;
+}
+
+uint32_t HWCDisplayExternal::GetOptimalRefreshRate(bool one_updating_layer) {
+ if (force_refresh_rate_) {
+ return force_refresh_rate_;
+ } else if (one_updating_layer && drc_enabled_) {
+ return metadata_refresh_rate_;
+ }
+
+ if (drc_reset_fps_enabled_) {
+ DisplayConfigVariableInfo fb_config;
+ display_intf_->GetFrameBufferConfig(&fb_config);
+ return (fb_config.fps * 1000);
+ }
+
+ return current_refresh_rate_;
+}
+
+int HWCDisplayExternal::Perform(uint32_t operation, ...) {
+ va_list args;
+ va_start(args, operation);
+ int val = va_arg(args, int32_t);
+ va_end(args);
+ switch (operation) {
+ case SET_BINDER_DYN_REFRESH_RATE:
+ ForceRefreshRate(UINT32(val));
+ break;
+ default:
+ DLOGW("Invalid operation %d", operation);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+} // namespace sdm
+
diff --git a/msm8909/sdm/libs/hwc/hwc_display_external.h b/msm8909/sdm/libs/hwc/hwc_display_external.h
new file mode 100644
index 00000000..c5ac3d75
--- /dev/null
+++ b/msm8909/sdm/libs/hwc/hwc_display_external.h
@@ -0,0 +1,64 @@
+/*
+* Copyright (c) 2014, 2016, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without modification, are permitted
+* provided that the following conditions are met:
+* * Redistributions of source code must retain the above copyright notice, this list of
+* conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright notice, this list of
+* conditions and the following disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its contributors may be used to
+* endorse or promote products derived from this software without specific prior written
+* permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __HWC_DISPLAY_EXTERNAL_H__
+#define __HWC_DISPLAY_EXTERNAL_H__
+
+#include "hwc_display.h"
+
+namespace sdm {
+
+class HWCDisplayExternal : public HWCDisplay {
+ public:
+ static int Create(CoreInterface *core_intf, hwc_procs_t const **hwc_procs, uint32_t primary_width,
+ uint32_t primary_height, qService::QService *qservice, bool use_primary_res,
+ HWCDisplay **hwc_display);
+ static int Create(CoreInterface *core_intf, hwc_procs_t const **hwc_procs,
+ qService::QService *qservice, HWCDisplay **hwc_display);
+ static void Destroy(HWCDisplay *hwc_display);
+ virtual int Prepare(hwc_display_contents_1_t *content_list);
+ virtual int Commit(hwc_display_contents_1_t *content_list);
+ virtual void SetSecureDisplay(bool secure_display_active, bool force_flush);
+ virtual int Perform(uint32_t operation, ...);
+
+ protected:
+ virtual uint32_t RoundToStandardFPS(float fps);
+ virtual void PrepareDynamicRefreshRate(Layer *layer);
+ int drc_enabled_ = 0;
+ int drc_reset_fps_enabled_ = 0;
+
+ private:
+ HWCDisplayExternal(CoreInterface *core_intf, hwc_procs_t const **hwc_procs,
+ qService::QService *qservice);
+ void ApplyScanAdjustment(hwc_rect_t *display_frame);
+ static void GetDownscaleResolution(uint32_t primary_width, uint32_t primary_height,
+ uint32_t *virtual_width, uint32_t *virtual_height);
+ void ForceRefreshRate(uint32_t refresh_rate);
+ uint32_t GetOptimalRefreshRate(bool one_updating_layer);
+};
+
+} // namespace sdm
+
+#endif // __HWC_DISPLAY_EXTERNAL_H__
+
diff --git a/msm8909/sdm/libs/hwc/hwc_display_external_test.cpp b/msm8909/sdm/libs/hwc/hwc_display_external_test.cpp
new file mode 100644
index 00000000..e629cd61
--- /dev/null
+++ b/msm8909/sdm/libs/hwc/hwc_display_external_test.cpp
@@ -0,0 +1,764 @@
+/*
+* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <cutils/properties.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <utils/constants.h>
+#include <utils/debug.h>
+#include <utils/formats.h>
+#include <algorithm>
+#include <array>
+#include <sstream>
+#include <string>
+#include <fstream>
+
+#include "hwc_display_external_test.h"
+#include "hwc_debugger.h"
+
+#define __CLASS__ "HWCDisplayExternalTest"
+
+namespace sdm {
+
+using std::array;
+
+int HWCDisplayExternalTest::Create(CoreInterface *core_intf, hwc_procs_t const **hwc_procs,
+ qService::QService *qservice, uint32_t panel_bpp,
+ uint32_t pattern_type, HWCDisplay **hwc_display) {
+ HWCDisplay *hwc_external_test = new HWCDisplayExternalTest(core_intf, hwc_procs, qservice,
+ panel_bpp, pattern_type);
+
+ int status = static_cast<HWCDisplayExternalTest *>(hwc_external_test)->Init();
+ if (status) {
+ delete hwc_external_test;
+ return status;
+ }
+
+ *hwc_display = hwc_external_test;
+
+ DLOGI("panel_bpp %d, pattern_type %d", panel_bpp, pattern_type);
+
+ return status;
+}
+
+void HWCDisplayExternalTest::Destroy(HWCDisplay *hwc_display) {
+ static_cast<HWCDisplayExternalTest *>(hwc_display)->Deinit();
+
+ delete hwc_display;
+}
+
+HWCDisplayExternalTest::HWCDisplayExternalTest(CoreInterface *core_intf,
+ hwc_procs_t const **hwc_procs,
+ qService::QService *qservice, uint32_t panel_bpp,
+ uint32_t pattern_type)
+ : HWCDisplay(core_intf, hwc_procs, kHDMI, HWC_DISPLAY_EXTERNAL, false, qservice,
+ DISPLAY_CLASS_EXTERNAL), panel_bpp_(panel_bpp), pattern_type_(pattern_type) {
+}
+
+int HWCDisplayExternalTest::Init() {
+ uint32_t external_width = 0;
+ uint32_t external_height = 0;
+
+ int status = HWCDisplay::Init();
+ if (status) {
+ return status;
+ }
+
+ buffer_allocator_ = new HWCBufferAllocator();
+
+ status = CreateLayerStack();
+ if (status) {
+ Deinit();
+ return status;
+ }
+
+ DisplayError error = HWCDisplay::GetMixerResolution(&external_width, &external_height);
+ if (error != kErrorNone) {
+ Deinit();
+ return -EINVAL;
+ }
+
+ status = HWCDisplay::SetFrameBufferResolution(external_width, external_height);
+ if (status) {
+ Deinit();
+ return status;
+ }
+
+ return status;
+}
+
+int HWCDisplayExternalTest::Deinit() {
+ DestroyLayerStack();
+
+ delete buffer_allocator_;
+ buffer_allocator_ = NULL;
+
+ return HWCDisplay::Deinit();
+}
+
+
+int HWCDisplayExternalTest::Prepare(hwc_display_contents_1_t *content_list) {
+ int status = 0;
+
+ if (secure_display_active_) {
+ MarkLayersForGPUBypass(content_list);
+ return status;
+ }
+
+ if (!content_list || !content_list->numHwLayers) {
+ DLOGW("Invalid content list");
+ return -EINVAL;
+ }
+
+ if (shutdown_pending_) {
+ return 0;
+ }
+
+ DisplayError error = display_intf_->Prepare(&layer_stack_);
+ if (error != kErrorNone) {
+ if (error == kErrorShutDown) {
+ shutdown_pending_ = true;
+ } else if (error != kErrorPermission) {
+ DLOGE("Prepare failed. Error = %d", error);
+ // To prevent surfaceflinger infinite wait, flush the previous frame during Commit()
+ // so that previous buffer and fences are released, and override the error.
+ flush_ = true;
+ }
+ }
+
+ MarkLayersForGPUBypass(content_list);
+
+ return 0;
+}
+
+int HWCDisplayExternalTest::Commit(hwc_display_contents_1_t *content_list) {
+ int status = 0;
+
+ if (secure_display_active_) {
+ return status;
+ }
+
+ if (!content_list || !content_list->numHwLayers) {
+ DLOGW("Invalid content list");
+ return -EINVAL;
+ }
+
+ if (shutdown_pending_) {
+ return 0;
+ }
+
+ DumpInputBuffer();
+
+ if (!flush_) {
+ DisplayError error = kErrorUndefined;
+
+ error = display_intf_->Commit(&layer_stack_);
+ if (error == kErrorNone) {
+ // A commit is successfully submitted, start flushing on failure now onwards.
+ flush_on_error_ = true;
+ } else {
+ if (error == kErrorShutDown) {
+ shutdown_pending_ = true;
+ return status;
+ } else if (error != kErrorPermission) {
+ DLOGE("Commit failed. Error = %d", error);
+ // To prevent surfaceflinger infinite wait, flush the previous frame during Commit()
+ // so that previous buffer and fences are released, and override the error.
+ flush_ = true;
+ }
+ }
+ }
+
+ return PostCommit(content_list);
+}
+
+void HWCDisplayExternalTest::SetSecureDisplay(bool secure_display_active, bool force_flush) {
+ if (secure_display_active_ != secure_display_active) {
+ secure_display_active_ = secure_display_active;
+
+ if (secure_display_active_) {
+ DisplayError error = display_intf_->Flush();
+ if (error != kErrorNone) {
+ DLOGE("Flush failed. Error = %d", error);
+ }
+ }
+ }
+ return;
+}
+
+int HWCDisplayExternalTest::Perform(uint32_t operation, ...) {
+ return 0;
+}
+
+void HWCDisplayExternalTest::DumpInputBuffer() {
+ if (!dump_frame_count_ || flush_ || !dump_input_layers_) {
+ return;
+ }
+
+ const char *dir_path = "/data/misc/display/frame_dump_external";
+ uint32_t width = buffer_info_.alloc_buffer_info.aligned_width;
+ uint32_t height = buffer_info_.alloc_buffer_info.aligned_height;
+ string format_str = GetFormatString(buffer_info_.buffer_config.format);
+
+ char *buffer = reinterpret_cast<char *>(mmap(NULL, buffer_info_.alloc_buffer_info.size,
+ PROT_READ|PROT_WRITE, MAP_SHARED,
+ buffer_info_.alloc_buffer_info.fd, 0));
+ if (buffer == MAP_FAILED) {
+ DLOGW("mmap failed. err = %d", errno);
+ return;
+ }
+
+ if (mkdir(dir_path, 0777) != 0 && errno != EEXIST) {
+ DLOGW("Failed to create %s directory errno = %d, desc = %s", dir_path, errno, strerror(errno));
+ return;
+ }
+
+ // if directory exists already, need to explicitly change the permission.
+ if (errno == EEXIST && chmod(dir_path, 0777) != 0) {
+ DLOGW("Failed to change permissions on %s directory", dir_path);
+ return;
+ }
+
+ if (buffer) {
+ std::stringstream dump_file_name;
+ dump_file_name << dir_path;
+ dump_file_name << "/input_layer_" << width << "x" << height << "_" << format_str << ".raw";
+
+ std::fstream fs;
+ fs.open(dump_file_name.str().c_str(), std::fstream::in | std::fstream::out | std::fstream::app);
+ if (!fs.is_open()) {
+ DLOGI("File open failed %s", dump_file_name.str().c_str());
+ return;
+ }
+
+ fs.write(buffer, (std::streamsize)buffer_info_.alloc_buffer_info.size);
+ fs.close();
+
+ DLOGI("Frame Dump %s: is successful", dump_file_name.str().c_str());
+ }
+
+ // Dump only once as the content is going to be same for all draw cycles
+ if (dump_frame_count_) {
+ dump_frame_count_ = 0;
+ }
+
+ if (munmap(buffer, buffer_info_.alloc_buffer_info.size) != 0) {
+ DLOGW("munmap failed. err = %d", errno);
+ return;
+ }
+}
+
+void HWCDisplayExternalTest::CalcCRC(uint32_t color_val, std::bitset<16> *crc_data) {
+ std::bitset<16> color = {};
+ std::bitset<16> temp_crc = {};
+
+ switch (panel_bpp_) {
+ case kDisplayBpp18:
+ color = (color_val & 0xFC) << 8;
+ break;
+ case kDisplayBpp24:
+ color = color_val << 8;
+ break;
+ case kDisplayBpp30:
+ color = color_val << 6;
+ break;
+ default:
+ return;
+ }
+
+ temp_crc[15] = (*crc_data)[0] ^ (*crc_data)[1] ^ (*crc_data)[2] ^ (*crc_data)[3] ^
+ (*crc_data)[4] ^ (*crc_data)[5] ^ (*crc_data)[6] ^ (*crc_data)[7] ^
+ (*crc_data)[8] ^ (*crc_data)[9] ^ (*crc_data)[10] ^ (*crc_data)[11] ^
+ (*crc_data)[12] ^ (*crc_data)[14] ^ (*crc_data)[15] ^ color[0] ^ color[1] ^
+ color[2] ^ color[3] ^ color[4] ^ color[5] ^ color[6] ^ color[7] ^ color[8] ^
+ color[9] ^ color[10] ^ color[11] ^ color[12] ^ color[14] ^ color[15];
+
+ temp_crc[14] = (*crc_data)[12] ^ (*crc_data)[13] ^ color[12] ^ color[13];
+ temp_crc[13] = (*crc_data)[11] ^ (*crc_data)[12] ^ color[11] ^ color[12];
+ temp_crc[12] = (*crc_data)[10] ^ (*crc_data)[11] ^ color[10] ^ color[11];
+ temp_crc[11] = (*crc_data)[9] ^ (*crc_data)[10] ^ color[9] ^ color[10];
+ temp_crc[10] = (*crc_data)[8] ^ (*crc_data)[9] ^ color[8] ^ color[9];
+ temp_crc[9] = (*crc_data)[7] ^ (*crc_data)[8] ^ color[7] ^ color[8];
+ temp_crc[8] = (*crc_data)[6] ^ (*crc_data)[7] ^ color[6] ^ color[7];
+ temp_crc[7] = (*crc_data)[5] ^ (*crc_data)[6] ^ color[5] ^ color[6];
+ temp_crc[6] = (*crc_data)[4] ^ (*crc_data)[5] ^ color[4] ^ color[5];
+ temp_crc[5] = (*crc_data)[3] ^ (*crc_data)[4] ^ color[3] ^ color[4];
+ temp_crc[4] = (*crc_data)[2] ^ (*crc_data)[3] ^ color[2] ^ color[3];
+ temp_crc[3] = (*crc_data)[1] ^ (*crc_data)[2] ^ (*crc_data)[15] ^ color[1] ^ color[2] ^ color[15];
+ temp_crc[2] = (*crc_data)[0] ^ (*crc_data)[1] ^ (*crc_data)[14] ^ color[0] ^ color[1] ^ color[14];
+
+ temp_crc[1] = (*crc_data)[1] ^ (*crc_data)[2] ^ (*crc_data)[3] ^ (*crc_data)[4] ^ (*crc_data)[5] ^
+ (*crc_data)[6] ^ (*crc_data)[7] ^ (*crc_data)[8] ^ (*crc_data)[9] ^
+ (*crc_data)[10] ^ (*crc_data)[11] ^ (*crc_data)[12] ^ (*crc_data)[13] ^
+ (*crc_data)[14] ^ color[1] ^ color[2] ^ color[3] ^ color[4] ^ color[5] ^ color[6] ^
+ color[7] ^ color[8] ^ color[9] ^ color[10] ^ color[11] ^ color[12] ^ color[13] ^
+ color[14];
+
+ temp_crc[0] = (*crc_data)[0] ^ (*crc_data)[1] ^ (*crc_data)[2] ^ (*crc_data)[3] ^ (*crc_data)[4] ^
+ (*crc_data)[5] ^ (*crc_data)[6] ^ (*crc_data)[7] ^ (*crc_data)[8] ^ (*crc_data)[9] ^
+ (*crc_data)[10] ^ (*crc_data)[11] ^ (*crc_data)[12] ^ (*crc_data)[13] ^
+ (*crc_data)[15] ^ color[0] ^ color[1] ^ color[2] ^ color[3] ^ color[4] ^ color[5] ^
+ color[6] ^ color[7] ^ color[8] ^ color[9] ^ color[10] ^ color[11] ^ color[12] ^
+ color[13] ^ color[15];
+
+ (*crc_data) = temp_crc;
+}
+
+int HWCDisplayExternalTest::FillBuffer() {
+ uint8_t *buffer = reinterpret_cast<uint8_t *>(mmap(NULL, buffer_info_.alloc_buffer_info.size,
+ PROT_READ|PROT_WRITE, MAP_SHARED,
+ buffer_info_.alloc_buffer_info.fd, 0));
+ if (buffer == MAP_FAILED) {
+ DLOGE("mmap failed. err = %d", errno);
+ return -EFAULT;
+ }
+
+ switch (pattern_type_) {
+ case kPatternColorRamp:
+ GenerateColorRamp(buffer);
+ break;
+ case kPatternBWVertical:
+ GenerateBWVertical(buffer);
+ break;
+ case kPatternColorSquare:
+ GenerateColorSquare(buffer);
+ break;
+ default:
+ DLOGW("Invalid Pattern type %d", pattern_type_);
+ return -EINVAL;
+ }
+
+ if (munmap(buffer, buffer_info_.alloc_buffer_info.size) != 0) {
+ DLOGE("munmap failed. err = %d", errno);
+ return -EFAULT;
+ }
+
+ return 0;
+}
+
+int HWCDisplayExternalTest::GetStride(LayerBufferFormat format, uint32_t width, uint32_t *stride) {
+ switch (format) {
+ case kFormatRGBA8888:
+ case kFormatRGBA1010102:
+ *stride = width * 4;
+ break;
+ case kFormatRGB888:
+ *stride = width * 3;
+ break;
+ default:
+ DLOGE("Unsupported format type %d", format);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+void HWCDisplayExternalTest::PixelCopy(uint32_t red, uint32_t green, uint32_t blue, uint32_t alpha,
+ uint8_t **buffer) {
+ LayerBufferFormat format = buffer_info_.buffer_config.format;
+
+ switch (format) {
+ case kFormatRGBA8888:
+ *(*buffer)++ = UINT8(red & 0xFF);
+ *(*buffer)++ = UINT8(green & 0xFF);
+ *(*buffer)++ = UINT8(blue & 0xFF);
+ *(*buffer)++ = UINT8(alpha & 0xFF);
+ break;
+ case kFormatRGB888:
+ *(*buffer)++ = UINT8(red & 0xFF);
+ *(*buffer)++ = UINT8(green & 0xFF);
+ *(*buffer)++ = UINT8(blue & 0xFF);
+ break;
+ case kFormatRGBA1010102:
+ // Lower 8 bits of red
+ *(*buffer)++ = UINT8(red & 0xFF);
+
+ // Upper 2 bits of Red + Lower 6 bits of green
+ *(*buffer)++ = UINT8(((green & 0x3F) << 2) | ((red >> 0x8) & 0x3));
+
+ // Upper 4 bits of green + Lower 4 bits of blue
+ *(*buffer)++ = UINT8(((blue & 0xF) << 4) | ((green >> 6) & 0xF));
+
+ // Upper 6 bits of blue + Lower 2 bits of alpha
+ *(*buffer)++ = UINT8(((alpha & 0x3) << 6) | ((blue >> 4) & 0x3F));
+ break;
+ default:
+ DLOGW("format not supported format = %d", format);
+ break;
+ }
+}
+
+void HWCDisplayExternalTest::GenerateColorRamp(uint8_t *buffer) {
+ uint32_t width = buffer_info_.buffer_config.width;
+ uint32_t height = buffer_info_.buffer_config.height;
+ LayerBufferFormat format = buffer_info_.buffer_config.format;
+ uint32_t aligned_width = buffer_info_.alloc_buffer_info.aligned_width;
+ uint32_t buffer_stride = 0;
+
+ uint32_t color_ramp = 0;
+ uint32_t start_color_val = 0;
+ uint32_t step_size = 1;
+ uint32_t ramp_width = 0;
+ uint32_t ramp_height = 0;
+ uint32_t shift_by = 0;
+
+ std::bitset<16> crc_red = {};
+ std::bitset<16> crc_green = {};
+ std::bitset<16> crc_blue = {};
+
+ switch (panel_bpp_) {
+ case kDisplayBpp18:
+ ramp_height = 64;
+ ramp_width = 64;
+ shift_by = 2;
+ break;
+ case kDisplayBpp24:
+ ramp_height = 64;
+ ramp_width = 256;
+ break;
+ case kDisplayBpp30:
+ ramp_height = 32;
+ ramp_width = 256;
+ start_color_val = 0x180;
+ break;
+ default:
+ return;
+ }
+
+ GetStride(format, aligned_width, &buffer_stride);
+
+ for (uint32_t loop_height = 0; loop_height < height; loop_height++) {
+ uint32_t color_value = start_color_val;
+ uint8_t *temp = buffer + (loop_height * buffer_stride);
+
+ for (uint32_t loop_width = 0; loop_width < width; loop_width++) {
+ if (color_ramp == kColorRedRamp) {
+ PixelCopy(color_value, 0, 0, 0, &temp);
+ CalcCRC(color_value, &crc_red);
+ CalcCRC(0, &crc_green);
+ CalcCRC(0, &crc_blue);
+ }
+ if (color_ramp == kColorGreenRamp) {
+ PixelCopy(0, color_value, 0, 0, &temp);
+ CalcCRC(0, &crc_red);
+ CalcCRC(color_value, &crc_green);
+ CalcCRC(0, &crc_blue);
+ }
+ if (color_ramp == kColorBlueRamp) {
+ PixelCopy(0, 0, color_value, 0, &temp);
+ CalcCRC(0, &crc_red);
+ CalcCRC(0, &crc_green);
+ CalcCRC(color_value, &crc_blue);
+ }
+ if (color_ramp == kColorWhiteRamp) {
+ PixelCopy(color_value, color_value, color_value, 0, &temp);
+ CalcCRC(color_value, &crc_red);
+ CalcCRC(color_value, &crc_green);
+ CalcCRC(color_value, &crc_blue);
+ }
+
+ color_value = (start_color_val + (((loop_width + 1) % ramp_width) * step_size)) << shift_by;
+ }
+
+ if (panel_bpp_ == kDisplayBpp30 && ((loop_height + 1) % ramp_height) == 0) {
+ if (start_color_val == 0x180) {
+ start_color_val = 0;
+ step_size = 4;
+ } else {
+ start_color_val = 0x180;
+ step_size = 1;
+ color_ramp = (color_ramp + 1) % 4;
+ }
+ continue;
+ }
+
+ if (((loop_height + 1) % ramp_height) == 0) {
+ color_ramp = (color_ramp + 1) % 4;
+ }
+ }
+
+ DLOGI("CRC red %x", crc_red.to_ulong());
+ DLOGI("CRC green %x", crc_green.to_ulong());
+ DLOGI("CRC blue %x", crc_blue.to_ulong());
+}
+
+void HWCDisplayExternalTest::GenerateBWVertical(uint8_t *buffer) {
+ uint32_t width = buffer_info_.buffer_config.width;
+ uint32_t height = buffer_info_.buffer_config.height;
+ LayerBufferFormat format = buffer_info_.buffer_config.format;
+ uint32_t aligned_width = buffer_info_.alloc_buffer_info.aligned_width;
+ uint32_t buffer_stride = 0;
+ uint32_t bits_per_component = panel_bpp_ / 3;
+ uint32_t max_color_val = (1 << bits_per_component) - 1;
+
+ std::bitset<16> crc_red = {};
+ std::bitset<16> crc_green = {};
+ std::bitset<16> crc_blue = {};
+
+ if (panel_bpp_ == kDisplayBpp18) {
+ max_color_val <<= 2;
+ }
+
+ GetStride(format, aligned_width, &buffer_stride);
+
+ for (uint32_t loop_height = 0; loop_height < height; loop_height++) {
+ uint32_t color = 0;
+ uint8_t *temp = buffer + (loop_height * buffer_stride);
+
+ for (uint32_t loop_width = 0; loop_width < width; loop_width++) {
+ if (color == kColorBlack) {
+ PixelCopy(0, 0, 0, 0, &temp);
+ CalcCRC(0, &crc_red);
+ CalcCRC(0, &crc_green);
+ CalcCRC(0, &crc_blue);
+ }
+ if (color == kColorWhite) {
+ PixelCopy(max_color_val, max_color_val, max_color_val, 0, &temp);
+ CalcCRC(max_color_val, &crc_red);
+ CalcCRC(max_color_val, &crc_green);
+ CalcCRC(max_color_val, &crc_blue);
+ }
+
+ color = (color + 1) % 2;
+ }
+ }
+
+ DLOGI("CRC red %x", crc_red.to_ulong());
+ DLOGI("CRC green %x", crc_green.to_ulong());
+ DLOGI("CRC blue %x", crc_blue.to_ulong());
+}
+
+void HWCDisplayExternalTest::GenerateColorSquare(uint8_t *buffer) {
+ uint32_t width = buffer_info_.buffer_config.width;
+ uint32_t height = buffer_info_.buffer_config.height;
+ LayerBufferFormat format = buffer_info_.buffer_config.format;
+ uint32_t aligned_width = buffer_info_.alloc_buffer_info.aligned_width;
+ uint32_t buffer_stride = 0;
+ uint32_t max_color_val = 0;
+ uint32_t min_color_val = 0;
+
+ std::bitset<16> crc_red = {};
+ std::bitset<16> crc_green = {};
+ std::bitset<16> crc_blue = {};
+
+ switch (panel_bpp_) {
+ case kDisplayBpp18:
+ max_color_val = 63 << 2; // CEA Dynamic range for 18bpp 0 - 63
+ min_color_val = 0;
+ break;
+ case kDisplayBpp24:
+ max_color_val = 235; // CEA Dynamic range for 24bpp 16 - 235
+ min_color_val = 16;
+ break;
+ case kDisplayBpp30:
+ max_color_val = 940; // CEA Dynamic range for 30bpp 64 - 940
+ min_color_val = 64;
+ break;
+ default:
+ return;
+ }
+
+ array<array<uint32_t, 3>, 8> colors = {{
+ {{max_color_val, max_color_val, max_color_val}}, // White Color
+ {{max_color_val, max_color_val, min_color_val}}, // Yellow Color
+ {{min_color_val, max_color_val, max_color_val}}, // Cyan Color
+ {{min_color_val, max_color_val, min_color_val}}, // Green Color
+ {{max_color_val, min_color_val, max_color_val}}, // Megenta Color
+ {{max_color_val, min_color_val, min_color_val}}, // Red Color
+ {{min_color_val, min_color_val, max_color_val}}, // Blue Color
+ {{min_color_val, min_color_val, min_color_val}}, // Black Color
+ }};
+
+ GetStride(format, aligned_width, &buffer_stride);
+
+ for (uint32_t loop_height = 0; loop_height < height; loop_height++) {
+ uint32_t color = 0;
+ uint8_t *temp = buffer + (loop_height * buffer_stride);
+
+ for (uint32_t loop_width = 0; loop_width < width; loop_width++) {
+ PixelCopy(colors[color][0], colors[color][1], colors[color][2], 0, &temp);
+ CalcCRC(colors[color][0], &crc_red);
+ CalcCRC(colors[color][1], &crc_green);
+ CalcCRC(colors[color][2], &crc_blue);
+
+ if (((loop_width + 1) % 64) == 0) {
+ color = (color + 1) % colors.size();
+ }
+ }
+
+ if (((loop_height + 1) % 64) == 0) {
+ std::reverse(colors.begin(), (colors.end() - 1));
+ }
+ }
+
+ DLOGI("CRC red %x", crc_red.to_ulong());
+ DLOGI("CRC green %x", crc_green.to_ulong());
+ DLOGI("CRC blue %x", crc_blue.to_ulong());
+}
+
+int HWCDisplayExternalTest::InitLayer(Layer *layer) {
+ uint32_t active_config = 0;
+ DisplayConfigVariableInfo var_info = {};
+
+ GetActiveDisplayConfig(&active_config);
+
+ GetDisplayAttributesForConfig(INT32(active_config), &var_info);
+
+ layer->flags.updating = 1;
+ layer->src_rect = LayerRect(0, 0, var_info.x_pixels, var_info.y_pixels);
+ layer->dst_rect = layer->src_rect;
+ layer->frame_rate = var_info.fps;
+ layer->blending = kBlendingPremultiplied;
+
+ layer->input_buffer.unaligned_width = var_info.x_pixels;
+ layer->input_buffer.unaligned_height = var_info.y_pixels;
+ buffer_info_.buffer_config.format = kFormatRGBA8888;
+
+ if (layer->composition != kCompositionGPUTarget) {
+ buffer_info_.buffer_config.width = var_info.x_pixels;
+ buffer_info_.buffer_config.height = var_info.y_pixels;
+ switch (panel_bpp_) {
+ case kDisplayBpp18:
+ case kDisplayBpp24:
+ buffer_info_.buffer_config.format = kFormatRGB888;
+ break;
+ case kDisplayBpp30:
+ buffer_info_.buffer_config.format = kFormatRGBA1010102;
+ break;
+ default:
+ DLOGW("panel bpp not supported %d", panel_bpp_);
+ return -EINVAL;
+ }
+ buffer_info_.buffer_config.buffer_count = 1;
+
+ int ret = buffer_allocator_->AllocateBuffer(&buffer_info_);
+ if (ret != 0) {
+ DLOGE("Buffer allocation failed. ret: %d", ret);
+ return -ENOMEM;
+ }
+
+ ret = FillBuffer();
+ if (ret != 0) {
+ buffer_allocator_->FreeBuffer(&buffer_info_);
+ return ret;
+ }
+
+ layer->input_buffer.width = buffer_info_.alloc_buffer_info.aligned_width;
+ layer->input_buffer.height = buffer_info_.alloc_buffer_info.aligned_height;
+ layer->input_buffer.size = buffer_info_.alloc_buffer_info.size;
+ layer->input_buffer.planes[0].fd = buffer_info_.alloc_buffer_info.fd;
+ layer->input_buffer.planes[0].stride = buffer_info_.alloc_buffer_info.stride;
+ layer->input_buffer.format = buffer_info_.buffer_config.format;
+
+ DLOGI("Input buffer WxH %dx%d format %s size %d fd %d stride %d", layer->input_buffer.width,
+ layer->input_buffer.height, GetFormatString(layer->input_buffer.format),
+ layer->input_buffer.size, layer->input_buffer.planes[0].fd,
+ layer->input_buffer.planes[0].stride);
+ }
+
+ return 0;
+}
+
+int HWCDisplayExternalTest::DeinitLayer(Layer *layer) {
+ if (layer->composition != kCompositionGPUTarget) {
+ int ret = buffer_allocator_->FreeBuffer(&buffer_info_);
+ if (ret != 0) {
+ DLOGE("Buffer deallocation failed. ret: %d", ret);
+ return -ENOMEM;
+ }
+ }
+
+ return 0;
+}
+
+int HWCDisplayExternalTest::CreateLayerStack() {
+ for (uint32_t i = 0; i < (kTestLayerCnt + 1 /* one dummy gpu_target layer */); i++) {
+ Layer *layer = new Layer();
+
+ if (i == kTestLayerCnt) {
+ layer->composition = kCompositionGPUTarget;
+ }
+
+ int ret = InitLayer(layer);
+ if (ret != 0) {
+ delete layer;
+ return ret;
+ }
+ layer_stack_.layers.push_back(layer);
+ }
+
+ return 0;
+}
+
+int HWCDisplayExternalTest::DestroyLayerStack() {
+ for (uint32_t i = 0; i < UINT32(layer_stack_.layers.size()); i++) {
+ Layer *layer = layer_stack_.layers.at(i);
+ int ret = DeinitLayer(layer);
+ if (ret != 0) {
+ return ret;
+ }
+
+ delete layer;
+ }
+
+ layer_stack_.layers = {};
+
+ return 0;
+}
+
+int HWCDisplayExternalTest::PostCommit(hwc_display_contents_1_t *content_list) {
+ int status = 0;
+
+ // Do no call flush on errors, if a successful buffer is never submitted.
+ if (flush_ && flush_on_error_) {
+ display_intf_->Flush();
+ }
+
+ if (!flush_) {
+ for (size_t i = 0; i < layer_stack_.layers.size(); i++) {
+ Layer *layer = layer_stack_.layers.at(i);
+ LayerBuffer &layer_buffer = layer->input_buffer;
+
+ close(layer_buffer.release_fence_fd);
+ layer_buffer.release_fence_fd = -1;
+ }
+
+ close(layer_stack_.retire_fence_fd);
+ layer_stack_.retire_fence_fd = -1;
+ content_list->retireFenceFd = -1;
+ }
+
+ flush_ = false;
+
+ return status;
+}
+
+} // namespace sdm
+
diff --git a/msm8909/sdm/libs/hwc/hwc_display_external_test.h b/msm8909/sdm/libs/hwc/hwc_display_external_test.h
new file mode 100644
index 00000000..050823e2
--- /dev/null
+++ b/msm8909/sdm/libs/hwc/hwc_display_external_test.h
@@ -0,0 +1,102 @@
+/*
+* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without modification, are permitted
+* provided that the following conditions are met:
+* * Redistributions of source code must retain the above copyright notice, this list of
+* conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright notice, this list of
+* conditions and the following disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its contributors may be used to
+* endorse or promote products derived from this software without specific prior written
+* permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __HWC_DISPLAY_EXTERNAL_TEST_H__
+#define __HWC_DISPLAY_EXTERNAL_TEST_H__
+
+#include<bitset>
+
+#include "hwc_display.h"
+#include "hwc_buffer_allocator.h"
+
+namespace sdm {
+
+class HWCDisplayExternalTest : public HWCDisplay {
+ public:
+ static int Create(CoreInterface *core_intf, hwc_procs_t const **hwc_procs,
+ qService::QService *qservice, uint32_t panel_bpp, uint32_t pattern_type,
+ HWCDisplay **hwc_display);
+ static void Destroy(HWCDisplay *hwc_display);
+ virtual int Prepare(hwc_display_contents_1_t *content_list);
+ virtual int Commit(hwc_display_contents_1_t *content_list);
+ virtual void SetSecureDisplay(bool secure_display_active, bool force_flush);
+ virtual int Perform(uint32_t operation, ...);
+
+ protected:
+ HWCBufferAllocator *buffer_allocator_ = NULL;
+ BufferInfo buffer_info_ = {};
+ uint32_t panel_bpp_ = 0;
+ uint32_t pattern_type_ = 0;
+
+ enum ColorPatternType {
+ kPatternNone = 0,
+ kPatternColorRamp,
+ kPatternBWVertical,
+ kPatternColorSquare,
+ };
+
+ enum DisplayBpp {
+ kDisplayBpp18 = 18,
+ kDisplayBpp24 = 24,
+ kDisplayBpp30 = 30,
+ };
+
+ enum ColorRamp {
+ kColorRedRamp = 0,
+ kColorGreenRamp = 1,
+ kColorBlueRamp = 2,
+ kColorWhiteRamp = 3,
+ };
+
+ enum Colors {
+ kColorBlack = 0,
+ kColorWhite = 1,
+ };
+
+ private:
+ HWCDisplayExternalTest(CoreInterface *core_intf, hwc_procs_t const **hwc_procs,
+ qService::QService *qservice, uint32_t panel_bpp, uint32_t pattern_type);
+ int Init();
+ int Deinit();
+ void DumpInputBuffer();
+ void CalcCRC(uint32_t color_value, std::bitset<16> *crc_data);
+ int FillBuffer();
+ int GetStride(LayerBufferFormat format, uint32_t width, uint32_t *stride);
+ void PixelCopy(uint32_t red, uint32_t green, uint32_t blue, uint32_t alpha, uint8_t **buffer);
+ void GenerateColorRamp(uint8_t *buffer);
+ void GenerateBWVertical(uint8_t *buffer);
+ void GenerateColorSquare(uint8_t *buffer);
+ int InitLayer(Layer *layer);
+ int DeinitLayer(Layer *layer);
+ int CreateLayerStack();
+ int DestroyLayerStack();
+ int PostCommit(hwc_display_contents_1_t *content_list);
+
+ static const uint32_t kTestLayerCnt = 1;
+};
+
+} // namespace sdm
+
+#endif // __HWC_DISPLAY_EXTERNAL_TEST_H__
+
diff --git a/msm8909/sdm/libs/hwc/hwc_display_null.cpp b/msm8909/sdm/libs/hwc/hwc_display_null.cpp
new file mode 100644
index 00000000..649f40c3
--- /dev/null
+++ b/msm8909/sdm/libs/hwc/hwc_display_null.cpp
@@ -0,0 +1,120 @@
+/*
+* Copyright (c) 2016, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without modification, are permitted
+* provided that the following conditions are met:
+* * Redistributions of source code must retain the above copyright notice, this list of
+* conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright notice, this list of
+* conditions and the following disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its contributors may be used to
+* endorse or promote products derived from this software without specific prior written
+* permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <hardware/hwcomposer_defs.h>
+#include <utils/constants.h>
+#include <utils/debug.h>
+#include "hwc_display_null.h"
+
+#define __CLASS__ "HWCDisplayNull"
+
+namespace sdm {
+
+int HWCDisplayNull::Create(CoreInterface *core_intf, hwc_procs_t const **hwc_procs,
+ HWCDisplay **hwc_display) {
+ int status;
+
+ DLOGI("Null display is being created");
+ HWCDisplayNull *hwc_display_null = new HWCDisplayNull(core_intf, hwc_procs);
+
+ status = hwc_display_null->Init();
+ if (status) {
+ delete hwc_display_null;
+ return status;
+ }
+
+ *hwc_display = hwc_display_null;
+
+ return 0;
+}
+
+void HWCDisplayNull::Destroy(HWCDisplay *hwc_display) {
+ DLOGI("Null display is being destroyed");
+ hwc_display->Deinit();
+ delete hwc_display;
+}
+
+// We pass the display type as HWC_DISPLAY_PRIMARY to HWCDisplay, but since we override
+// and don't chain to HWCDisplay::Init(), that type does not actually get used.
+HWCDisplayNull::HWCDisplayNull(CoreInterface *core_intf, hwc_procs_t const **hwc_procs)
+ : HWCDisplay(core_intf, hwc_procs, kPrimary, HWC_DISPLAY_PRIMARY, false, NULL,
+ DISPLAY_CLASS_NULL) {
+}
+
+int HWCDisplayNull::Init() {
+ // Don't call HWCDisplay::Init() for null display, we don't want the chain of
+ // DisplayPrimary / HWPrimary etc objects to be created.
+ return 0;
+}
+
+int HWCDisplayNull::Deinit() {
+ return 0;
+}
+
+int HWCDisplayNull::Prepare(hwc_display_contents_1_t *content_list) {
+ for (size_t i = 0; i < content_list->numHwLayers; i++) {
+ if (content_list->hwLayers[i].compositionType == HWC_FRAMEBUFFER_TARGET ||
+ content_list->hwLayers[i].compositionType == HWC_BACKGROUND) {
+ continue;
+ }
+
+ content_list->hwLayers[i].compositionType = HWC_OVERLAY;
+ }
+
+ return 0;
+}
+
+int HWCDisplayNull::Commit(hwc_display_contents_1_t *content_list) {
+ // HWCSession::Commit (from where this is called) already closes all the acquire
+ // fences once we return from here. So no need to close acquire fences here.
+ for (size_t i = 0; i < content_list->numHwLayers; i++) {
+ content_list->hwLayers[i].releaseFenceFd = -1;
+ }
+
+ return 0;
+}
+
+#define NULL_DISPLAY_FPS 60
+
+int HWCDisplayNull::GetDisplayAttributes(uint32_t config, const uint32_t *display_attributes,
+ int32_t *values) {
+ for (int i = 0; display_attributes[i] != HWC_DISPLAY_NO_ATTRIBUTE; i++) {
+ // We fake display resolution as 1080P by default, though it can be overriden through a call to
+ // SetResolution(), and DPI as 160, though what the DPI value does is not clear
+ switch (display_attributes[i]) {
+ case HWC_DISPLAY_VSYNC_PERIOD:
+ values[i] = INT32(1000000000L / NULL_DISPLAY_FPS);
+ break;
+ case HWC_DISPLAY_WIDTH:
+ values[i] = static_cast<int32_t>(x_res_);
+ break;
+ case HWC_DISPLAY_HEIGHT:
+ values[i] = static_cast<int32_t>(y_res_);
+ break;
+ }
+ }
+ return 0;
+}
+
+} // namespace sdm
diff --git a/msm8909/sdm/libs/hwc/hwc_display_null.h b/msm8909/sdm/libs/hwc/hwc_display_null.h
new file mode 100644
index 00000000..f1e0e5e8
--- /dev/null
+++ b/msm8909/sdm/libs/hwc/hwc_display_null.h
@@ -0,0 +1,106 @@
+/*
+* Copyright (c) 2016, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without modification, are permitted
+* provided that the following conditions are met:
+* * Redistributions of source code must retain the above copyright notice, this list of
+* conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright notice, this list of
+* conditions and the following disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its contributors may be used to
+* endorse or promote products derived from this software without specific prior written
+* permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __HWC_DISPLAY_NULL_H__
+#define __HWC_DISPLAY_NULL_H__
+
+#include <qdMetaData.h>
+#include <gralloc_priv.h>
+#include "hwc_display.h"
+
+namespace sdm {
+
+class HWCDisplayNull : public HWCDisplay {
+ public:
+ static int Create(CoreInterface *core_intf, hwc_procs_t const **hwc_procs,
+ HWCDisplay **hwc_display);
+ static void Destroy(HWCDisplay *hwc_display);
+ virtual int Init();
+ virtual int Deinit();
+ virtual int Prepare(hwc_display_contents_1_t *content_list);
+ virtual int Commit(hwc_display_contents_1_t *content_list);
+ virtual int EventControl(int event, int enable) { return 0; }
+ virtual int SetPowerMode(int mode) { return 0; }
+
+ // Framebuffer configurations
+ virtual int GetDisplayConfigs(uint32_t *configs, size_t *num_configs) {
+ return HWCDisplay::GetDisplayConfigs(configs, num_configs);
+ }
+
+ virtual int GetDisplayAttributes(uint32_t config, const uint32_t *display_attributes,
+ int32_t *values);
+ virtual int GetActiveConfig() { return 0; }
+ virtual int SetActiveConfig(int index) { return -1; }
+
+ virtual void SetIdleTimeoutMs(uint32_t timeout_ms) { return; }
+ virtual void SetFrameDumpConfig(uint32_t count, uint32_t bit_mask_layer_type) { return; }
+ virtual DisplayError SetMaxMixerStages(uint32_t max_mixer_stages) { return kErrorNone; }
+ virtual DisplayError ControlPartialUpdate(bool enable, uint32_t *pending) { return kErrorNone; }
+ virtual uint32_t GetLastPowerMode() { return 0; }
+ virtual int SetFrameBufferResolution(uint32_t x_pixels, uint32_t y_pixels) { return 0; }
+
+ virtual void GetFrameBufferResolution(uint32_t *x_pixels, uint32_t *y_pixels) {
+ *x_pixels = x_res_;
+ *y_pixels = y_res_;
+ }
+
+ virtual void GetPanelResolution(uint32_t *x_pixels, uint32_t *y_pixels) {
+ *x_pixels = x_res_;
+ *y_pixels = y_res_;
+ }
+
+ virtual int SetDisplayStatus(uint32_t display_status) { return 0; }
+ virtual int OnMinHdcpEncryptionLevelChange(uint32_t min_enc_level) { return 0; }
+ virtual int Perform(uint32_t operation, ...) { return 0; }
+ virtual int SetCursorPosition(int x, int y) { return 0; }
+ virtual void SetSecureDisplay(bool secure_display_active, bool force_flush) { return; }
+
+ // Display Configurations
+ virtual int SetActiveDisplayConfig(int config) { return 0; }
+ virtual int GetActiveDisplayConfig(uint32_t *config) { return -1; }
+ virtual int GetDisplayConfigCount(uint32_t *count) { return -1; }
+ virtual int GetDisplayAttributesForConfig(int config,
+ DisplayConfigVariableInfo *display_attributes) {
+ return -1;
+ }
+ virtual bool IsValidContentList(hwc_display_contents_1_t *content_list) {
+ return true;
+ }
+
+ void SetResolution(uint32_t x_res, uint32_t y_res) {
+ x_res_ = x_res;
+ y_res_ = y_res;
+ }
+
+
+ private:
+ HWCDisplayNull(CoreInterface *core_intf, hwc_procs_t const **hwc_procs);
+ uint32_t x_res_ = 1920;
+ uint32_t y_res_ = 1080;
+};
+
+} // namespace sdm
+
+#endif // __HWC_DISPLAY_NULL_H__
+
diff --git a/msm8909/sdm/libs/hwc/hwc_display_primary.cpp b/msm8909/sdm/libs/hwc/hwc_display_primary.cpp
new file mode 100644
index 00000000..ba351b5b
--- /dev/null
+++ b/msm8909/sdm/libs/hwc/hwc_display_primary.cpp
@@ -0,0 +1,574 @@
+/*
+* Copyright (c) 2014 - 2017, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <cutils/properties.h>
+#include <sync/sync.h>
+#include <utils/constants.h>
+#include <utils/debug.h>
+#include <stdarg.h>
+#include <sys/mman.h>
+
+#include <gr.h>
+#include "hwc_display_primary.h"
+#include "hwc_debugger.h"
+
+#define __CLASS__ "HWCDisplayPrimary"
+
+namespace sdm {
+
+int HWCDisplayPrimary::Create(CoreInterface *core_intf, BufferAllocator *buffer_allocator,
+ hwc_procs_t const **hwc_procs, qService::QService *qservice,
+ HWCDisplay **hwc_display) {
+ int status = 0;
+ uint32_t primary_width = 0;
+ uint32_t primary_height = 0;
+
+ HWCDisplay *hwc_display_primary = new HWCDisplayPrimary(core_intf, buffer_allocator,
+ hwc_procs, qservice);
+ status = hwc_display_primary->Init();
+ if (status) {
+ delete hwc_display_primary;
+ return status;
+ }
+
+ hwc_display_primary->GetMixerResolution(&primary_width, &primary_height);
+ int width = 0, height = 0;
+ HWCDebugHandler::Get()->GetProperty("sdm.fb_size_width", &width);
+ HWCDebugHandler::Get()->GetProperty("sdm.fb_size_height", &height);
+ if (width > 0 && height > 0) {
+ primary_width = UINT32(width);
+ primary_height = UINT32(height);
+ }
+
+ status = hwc_display_primary->SetFrameBufferResolution(primary_width, primary_height);
+ if (status) {
+ Destroy(hwc_display_primary);
+ return status;
+ }
+
+ *hwc_display = hwc_display_primary;
+
+ return status;
+}
+
+void HWCDisplayPrimary::Destroy(HWCDisplay *hwc_display) {
+ hwc_display->Deinit();
+ delete hwc_display;
+}
+
+HWCDisplayPrimary::HWCDisplayPrimary(CoreInterface *core_intf,
+ BufferAllocator *buffer_allocator,
+ hwc_procs_t const **hwc_procs,
+ qService::QService *qservice)
+ : HWCDisplay(core_intf, hwc_procs, kPrimary, HWC_DISPLAY_PRIMARY, true, qservice,
+ DISPLAY_CLASS_PRIMARY), buffer_allocator_(buffer_allocator) {
+}
+
+int HWCDisplayPrimary::Init() {
+ cpu_hint_.Init(static_cast<HWCDebugHandler*>(HWCDebugHandler::Get()));
+
+ use_metadata_refresh_rate_ = true;
+ int disable_metadata_dynfps = 0;
+ HWCDebugHandler::Get()->GetProperty("persist.metadata_dynfps.disable", &disable_metadata_dynfps);
+ if (disable_metadata_dynfps) {
+ use_metadata_refresh_rate_ = false;
+ }
+
+ int status = HWCDisplay::Init();
+ if (status) {
+ return status;
+ }
+ color_mode_ = new HWCColorMode(display_intf_);
+ color_mode_->Init();
+
+ return status;
+}
+
+int HWCDisplayPrimary::Deinit() {
+ color_mode_->DeInit();
+ delete color_mode_;
+ color_mode_ = NULL;
+
+ return HWCDisplay::Deinit();
+}
+
+
+void HWCDisplayPrimary::ProcessBootAnimCompleted(hwc_display_contents_1_t *list) {
+ uint32_t numBootUpLayers = 0;
+
+ numBootUpLayers = static_cast<uint32_t>(Debug::GetBootAnimLayerCount());
+
+ if (numBootUpLayers == 0) {
+ numBootUpLayers = 2;
+ }
+ /* All other checks namely "init.svc.bootanim" or
+ * HWC_GEOMETRY_CHANGED fail in correctly identifying the
+ * exact bootup transition to homescreen
+ */
+ char cryptoState[PROPERTY_VALUE_MAX];
+ char voldDecryptState[PROPERTY_VALUE_MAX];
+ bool isEncrypted = false;
+ bool main_class_services_started = false;
+ if (property_get("ro.crypto.state", cryptoState, "unencrypted")) {
+ if (!strcmp(cryptoState, "encrypted")) {
+ isEncrypted = true;
+ if (property_get("vold.decrypt", voldDecryptState, "") &&
+ !strcmp(voldDecryptState, "trigger_restart_framework"))
+ main_class_services_started = true;
+ }
+ }
+ if ((!isEncrypted ||(isEncrypted && main_class_services_started)) &&
+ (list->numHwLayers > numBootUpLayers)) {
+ boot_animation_completed_ = true;
+ // Applying default mode after bootanimation is finished And
+ // If Data is Encrypted, it is ready for access.
+ if (display_intf_)
+ display_intf_->ApplyDefaultDisplayMode();
+ }
+}
+
+int HWCDisplayPrimary::Prepare(hwc_display_contents_1_t *content_list) {
+ int status = 0;
+ DisplayError error = kErrorNone;
+
+ if (!boot_animation_completed_)
+ ProcessBootAnimCompleted(content_list);
+
+ if (display_paused_) {
+ MarkLayersForGPUBypass(content_list);
+ return status;
+ }
+
+ status = AllocateLayerStack(content_list);
+ if (status) {
+ return status;
+ }
+
+ status = PrePrepareLayerStack(content_list);
+ if (status) {
+ return status;
+ }
+
+ bool pending_output_dump = dump_frame_count_ && dump_output_to_file_;
+
+ if (frame_capture_buffer_queued_ || pending_output_dump) {
+ // RHS values were set in FrameCaptureAsync() called from a binder thread. They are picked up
+ // here in a subsequent draw round.
+ layer_stack_.output_buffer = &output_buffer_;
+ layer_stack_.flags.post_processed_output = post_processed_output_;
+ }
+
+ uint32_t num_updating_layers = GetUpdatingLayersCount(UINT32(content_list->numHwLayers - 1));
+ bool one_updating_layer = (num_updating_layers == 1);
+
+ if (num_updating_layers != 0) {
+ ToggleCPUHint(one_updating_layer);
+ }
+
+ uint32_t refresh_rate = GetOptimalRefreshRate(one_updating_layer);
+ // TODO(user): Need to read current refresh rate to avoid
+ // redundant calls to set refresh rate during idle fall back.
+ if ((current_refresh_rate_ != refresh_rate) || (handle_idle_timeout_)) {
+ error = display_intf_->SetRefreshRate(refresh_rate);
+ }
+
+ if (error == kErrorNone) {
+ // On success, set current refresh rate to new refresh rate
+ current_refresh_rate_ = refresh_rate;
+ }
+
+ if (handle_idle_timeout_) {
+ handle_idle_timeout_ = false;
+ }
+
+ if (content_list->numHwLayers <= 1) {
+ flush_ = true;
+ }
+
+ status = PrepareLayerStack(content_list);
+ if (status) {
+ return status;
+ }
+
+ return 0;
+}
+
+int HWCDisplayPrimary::Commit(hwc_display_contents_1_t *content_list) {
+ int status = 0;
+
+ DisplayConfigFixedInfo display_config;
+ display_intf_->GetConfig(&display_config);
+ if (content_list->numHwLayers <= 1 && display_config.is_cmdmode) {
+ DLOGV("Skipping null commit on cmd mode panel");
+ flush_ = false;
+ return 0;
+ }
+
+ if (display_paused_) {
+ if (content_list->outbufAcquireFenceFd >= 0) {
+ // If we do not handle the frame set retireFenceFd to outbufAcquireFenceFd,
+ // which will make sure the framework waits on it and closes it.
+ content_list->retireFenceFd = dup(content_list->outbufAcquireFenceFd);
+ close(content_list->outbufAcquireFenceFd);
+ content_list->outbufAcquireFenceFd = -1;
+ }
+
+ DisplayError error = display_intf_->Flush();
+ if (error != kErrorNone) {
+ DLOGE("Flush failed. Error = %d", error);
+ }
+ return status;
+ }
+
+ status = HWCDisplay::CommitLayerStack(content_list);
+ if (status) {
+ return status;
+ }
+
+ HandleFrameOutput();
+
+ status = HWCDisplay::PostCommitLayerStack(content_list);
+ if (status) {
+ return status;
+ }
+
+ return 0;
+}
+
+int HWCDisplayPrimary::Perform(uint32_t operation, ...) {
+ va_list args;
+ va_start(args, operation);
+ int val = va_arg(args, int32_t);
+ va_end(args);
+ switch (operation) {
+ case SET_METADATA_DYN_REFRESH_RATE:
+ SetMetaDataRefreshRateFlag(val);
+ break;
+ case SET_BINDER_DYN_REFRESH_RATE:
+ ForceRefreshRate(UINT32(val));
+ break;
+ case SET_DISPLAY_MODE:
+ SetDisplayMode(UINT32(val));
+ break;
+ case SET_QDCM_SOLID_FILL_INFO:
+ SetQDCMSolidFillInfo(true, UINT32(val));
+ break;
+ case UNSET_QDCM_SOLID_FILL_INFO:
+ SetQDCMSolidFillInfo(false, UINT32(val));
+ break;
+ default:
+ DLOGW("Invalid operation %d", operation);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+DisplayError HWCDisplayPrimary::SetDisplayMode(uint32_t mode) {
+ DisplayError error = kErrorNone;
+
+ if (display_intf_) {
+ error = display_intf_->SetDisplayMode(mode);
+ }
+
+ return error;
+}
+
+void HWCDisplayPrimary::SetMetaDataRefreshRateFlag(bool enable) {
+ int disable_metadata_dynfps = 0;
+
+ HWCDebugHandler::Get()->GetProperty("persist.metadata_dynfps.disable", &disable_metadata_dynfps);
+ if (disable_metadata_dynfps) {
+ return;
+ }
+ use_metadata_refresh_rate_ = enable;
+}
+
+void HWCDisplayPrimary::SetQDCMSolidFillInfo(bool enable, uint32_t color) {
+ solid_fill_enable_ = enable;
+ solid_fill_color_ = color;
+}
+
+void HWCDisplayPrimary::ToggleCPUHint(bool set) {
+ if (set) {
+ cpu_hint_.Set();
+ } else {
+ cpu_hint_.Reset();
+ }
+}
+
+void HWCDisplayPrimary::SetSecureDisplay(bool secure_display_active, bool force_flush) {
+ if (secure_display_active_ != secure_display_active) {
+ // Skip Prepare and call Flush for null commit
+ DLOGI("SecureDisplay state changed from %d to %d Needs Flush!!", secure_display_active_,
+ secure_display_active);
+ secure_display_active_ = secure_display_active;
+ skip_prepare_cnt = 1;
+
+ // Issue two null commits for command mode panels when external displays are connected.
+ // Two null commits are required to handle non secure to secure transitions at 30fps.
+ // TODO(user): Need two null commits on video mode also to handle transition cases of
+ // primary at higher fps (ex60) and external at lower fps.
+
+ // Avoid flush for command mode panels when no external displays are connected.
+ // This is to avoid flicker/blink on primary during transitions.
+ DisplayConfigFixedInfo display_config;
+ display_intf_->GetConfig(&display_config);
+ if (display_config.is_cmdmode) {
+ if (force_flush) {
+ DLOGI("Issue two null commits for command mode panels");
+ skip_prepare_cnt = 2;
+ } else {
+ DLOGI("Avoid flush for command mode panel when no external displays are connected");
+ skip_prepare_cnt = 0;
+ }
+ }
+ }
+}
+
+void HWCDisplayPrimary::ForceRefreshRate(uint32_t refresh_rate) {
+ if ((refresh_rate && (refresh_rate < min_refresh_rate_ || refresh_rate > max_refresh_rate_)) ||
+ force_refresh_rate_ == refresh_rate) {
+ // Cannot honor force refresh rate, as its beyond the range or new request is same
+ return;
+ }
+
+ const hwc_procs_t *hwc_procs = *hwc_procs_;
+ force_refresh_rate_ = refresh_rate;
+
+ hwc_procs->invalidate(hwc_procs);
+
+ return;
+}
+
+uint32_t HWCDisplayPrimary::GetOptimalRefreshRate(bool one_updating_layer) {
+ if (force_refresh_rate_) {
+ return force_refresh_rate_;
+ } else if (handle_idle_timeout_) {
+ return min_refresh_rate_;
+ } else if (use_metadata_refresh_rate_ && one_updating_layer && metadata_refresh_rate_) {
+ return metadata_refresh_rate_;
+ }
+
+ return max_refresh_rate_;
+}
+
+DisplayError HWCDisplayPrimary::Refresh() {
+ const hwc_procs_t *hwc_procs = *hwc_procs_;
+ DisplayError error = kErrorNone;
+
+ if (!hwc_procs) {
+ return kErrorParameters;
+ }
+
+ hwc_procs->invalidate(hwc_procs);
+ handle_idle_timeout_ = true;
+
+ return error;
+}
+
+void HWCDisplayPrimary::SetIdleTimeoutMs(uint32_t timeout_ms) {
+ display_intf_->SetIdleTimeoutMs(timeout_ms);
+}
+
+static void SetLayerBuffer(const BufferInfo& output_buffer_info, LayerBuffer *output_buffer) {
+ const BufferConfig& buffer_config = output_buffer_info.buffer_config;
+ const AllocatedBufferInfo &alloc_buffer_info = output_buffer_info.alloc_buffer_info;
+
+ output_buffer->width = alloc_buffer_info.aligned_width;
+ output_buffer->height = alloc_buffer_info.aligned_height;
+ output_buffer->unaligned_width = buffer_config.width;
+ output_buffer->unaligned_height = buffer_config.height;
+ output_buffer->format = buffer_config.format;
+ output_buffer->planes[0].fd = alloc_buffer_info.fd;
+ output_buffer->planes[0].stride = alloc_buffer_info.stride;
+}
+
+void HWCDisplayPrimary::HandleFrameOutput() {
+ if (frame_capture_buffer_queued_) {
+ HandleFrameCapture();
+ } else if (dump_output_to_file_) {
+ HandleFrameDump();
+ }
+}
+
+void HWCDisplayPrimary::HandleFrameCapture() {
+ if (output_buffer_.release_fence_fd >= 0) {
+ frame_capture_status_ = sync_wait(output_buffer_.release_fence_fd, 1000);
+ ::close(output_buffer_.release_fence_fd);
+ output_buffer_.release_fence_fd = -1;
+ }
+
+ frame_capture_buffer_queued_ = false;
+ post_processed_output_ = false;
+ output_buffer_ = {};
+}
+
+void HWCDisplayPrimary::HandleFrameDump() {
+ if (dump_frame_count_ && output_buffer_.release_fence_fd >= 0) {
+ int ret = sync_wait(output_buffer_.release_fence_fd, 1000);
+ ::close(output_buffer_.release_fence_fd);
+ output_buffer_.release_fence_fd = -1;
+ if (ret < 0) {
+ DLOGE("sync_wait error errno = %d, desc = %s", errno, strerror(errno));
+ } else {
+ DumpOutputBuffer(output_buffer_info_, output_buffer_base_, layer_stack_.retire_fence_fd);
+ }
+ }
+
+ if (0 == dump_frame_count_) {
+ dump_output_to_file_ = false;
+ // Unmap and Free buffer
+ if (munmap(output_buffer_base_, output_buffer_info_.alloc_buffer_info.size) != 0) {
+ DLOGE("unmap failed with err %d", errno);
+ }
+ if (buffer_allocator_->FreeBuffer(&output_buffer_info_) != 0) {
+ DLOGE("FreeBuffer failed");
+ }
+
+ post_processed_output_ = false;
+ output_buffer_ = {};
+ output_buffer_info_ = {};
+ output_buffer_base_ = nullptr;
+ }
+}
+
+void HWCDisplayPrimary::SetFrameDumpConfig(uint32_t count, uint32_t bit_mask_layer_type) {
+ HWCDisplay::SetFrameDumpConfig(count, bit_mask_layer_type);
+ dump_output_to_file_ = bit_mask_layer_type & (1 << OUTPUT_LAYER_DUMP);
+ DLOGI("output_layer_dump_enable %d", dump_output_to_file_);
+
+ if (!count || !dump_output_to_file_) {
+ return;
+ }
+
+ // Allocate and map output buffer
+ output_buffer_info_ = {};
+ // Since we dump DSPP output use Panel resolution.
+ GetPanelResolution(&output_buffer_info_.buffer_config.width,
+ &output_buffer_info_.buffer_config.height);
+ output_buffer_info_.buffer_config.format = kFormatRGB888;
+ output_buffer_info_.buffer_config.buffer_count = 1;
+ if (buffer_allocator_->AllocateBuffer(&output_buffer_info_) != 0) {
+ DLOGE("Buffer allocation failed");
+ output_buffer_info_ = {};
+ return;
+ }
+
+ void *buffer = mmap(NULL, output_buffer_info_.alloc_buffer_info.size,
+ PROT_READ | PROT_WRITE,
+ MAP_SHARED, output_buffer_info_.alloc_buffer_info.fd, 0);
+
+ if (buffer == MAP_FAILED) {
+ DLOGE("mmap failed with err %d", errno);
+ buffer_allocator_->FreeBuffer(&output_buffer_info_);
+ output_buffer_info_ = {};
+ return;
+ }
+
+ output_buffer_base_ = buffer;
+ post_processed_output_ = true;
+ DisablePartialUpdateOneFrame();
+}
+
+int HWCDisplayPrimary::FrameCaptureAsync(const BufferInfo& output_buffer_info,
+ bool post_processed_output) {
+ // Note: This function is called in context of a binder thread and a lock is already held
+ if (output_buffer_info.alloc_buffer_info.fd < 0) {
+ DLOGE("Invalid fd %d", output_buffer_info.alloc_buffer_info.fd);
+ return -1;
+ }
+
+ auto panel_width = 0u;
+ auto panel_height = 0u;
+ auto fb_width = 0u;
+ auto fb_height = 0u;
+
+ GetPanelResolution(&panel_width, &panel_height);
+ GetFrameBufferResolution(&fb_width, &fb_height);
+
+ if (post_processed_output && (output_buffer_info.buffer_config.width < panel_width ||
+ output_buffer_info.buffer_config.height < panel_height)) {
+ DLOGE("Buffer dimensions should not be less than panel resolution");
+ return -1;
+ } else if (!post_processed_output && (output_buffer_info.buffer_config.width < fb_width ||
+ output_buffer_info.buffer_config.height < fb_height)) {
+ DLOGE("Buffer dimensions should not be less than FB resolution");
+ return -1;
+ }
+
+ SetLayerBuffer(output_buffer_info, &output_buffer_);
+ post_processed_output_ = post_processed_output;
+ frame_capture_buffer_queued_ = true;
+ // Status is only cleared on a new call to dump and remains valid otherwise
+ frame_capture_status_ = -EAGAIN;
+ DisablePartialUpdateOneFrame();
+
+ return 0;
+}
+
+DisplayError HWCDisplayPrimary::SetDetailEnhancerConfig(
+ const DisplayDetailEnhancerData &de_data) {
+ DisplayError error = kErrorNotSupported;
+ if (display_intf_) {
+ error = display_intf_->SetDetailEnhancerData(de_data);
+ }
+ return error;
+}
+
+DisplayError HWCDisplayPrimary::ControlPartialUpdate(bool enable, uint32_t *pending) {
+ DisplayError error = kErrorNone;
+
+ if (display_intf_) {
+ error = display_intf_->ControlPartialUpdate(enable, pending);
+ }
+
+ return error;
+}
+
+DisplayError HWCDisplayPrimary::DisablePartialUpdateOneFrame() {
+ DisplayError error = kErrorNone;
+
+ if (display_intf_) {
+ error = display_intf_->DisablePartialUpdateOneFrame();
+ }
+
+ return error;
+}
+
+DisplayError HWCDisplayPrimary::SetMixerResolution(uint32_t width, uint32_t height) {
+ return display_intf_->SetMixerResolution(width, height);
+}
+
+DisplayError HWCDisplayPrimary::GetMixerResolution(uint32_t *width, uint32_t *height) {
+ return display_intf_->GetMixerResolution(width, height);
+}
+
+} // namespace sdm
+
diff --git a/msm8909/sdm/libs/hwc/hwc_display_primary.h b/msm8909/sdm/libs/hwc/hwc_display_primary.h
new file mode 100644
index 00000000..8a2ff87c
--- /dev/null
+++ b/msm8909/sdm/libs/hwc/hwc_display_primary.h
@@ -0,0 +1,91 @@
+/*
+* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without modification, are permitted
+* provided that the following conditions are met:
+* * Redistributions of source code must retain the above copyright notice, this list of
+* conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright notice, this list of
+* conditions and the following disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its contributors may be used to
+* endorse or promote products derived from this software without specific prior written
+* permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __HWC_DISPLAY_PRIMARY_H__
+#define __HWC_DISPLAY_PRIMARY_H__
+
+#include "cpuhint.h"
+#include "hwc_display.h"
+
+namespace sdm {
+
+class HWCDisplayPrimary : public HWCDisplay {
+ public:
+ static int Create(CoreInterface *core_intf, BufferAllocator *buffer_allocator,
+ hwc_procs_t const **hwc_procs, qService::QService *qservice,
+ HWCDisplay **hwc_display);
+ static void Destroy(HWCDisplay *hwc_display);
+ virtual int Init();
+ virtual int Deinit();
+ virtual int Prepare(hwc_display_contents_1_t *content_list);
+ virtual int Commit(hwc_display_contents_1_t *content_list);
+ virtual int Perform(uint32_t operation, ...);
+ virtual void SetSecureDisplay(bool secure_display_active, bool force_flush);
+ virtual DisplayError Refresh();
+ virtual void SetIdleTimeoutMs(uint32_t timeout_ms);
+ virtual void SetFrameDumpConfig(uint32_t count, uint32_t bit_mask_layer_type);
+ virtual int FrameCaptureAsync(const BufferInfo& output_buffer_info, bool post_processed);
+ virtual int GetFrameCaptureStatus() { return frame_capture_status_; }
+ virtual DisplayError SetDetailEnhancerConfig(const DisplayDetailEnhancerData &de_data);
+ virtual DisplayError ControlPartialUpdate(bool enable, uint32_t *pending);
+
+ private:
+ HWCDisplayPrimary(CoreInterface *core_intf, BufferAllocator *buffer_allocator,
+ hwc_procs_t const **hwc_procs, qService::QService *qservice);
+ void SetMetaDataRefreshRateFlag(bool enable);
+ virtual DisplayError SetDisplayMode(uint32_t mode);
+ virtual DisplayError DisablePartialUpdateOneFrame();
+ void ProcessBootAnimCompleted(hwc_display_contents_1_t *content_list);
+ void SetQDCMSolidFillInfo(bool enable, uint32_t color);
+ void ToggleCPUHint(bool set);
+ void ForceRefreshRate(uint32_t refresh_rate);
+ uint32_t GetOptimalRefreshRate(bool one_updating_layer);
+ void HandleFrameOutput();
+ void HandleFrameCapture();
+ void HandleFrameDump();
+ DisplayError SetMixerResolution(uint32_t width, uint32_t height);
+ DisplayError GetMixerResolution(uint32_t *width, uint32_t *height);
+
+ BufferAllocator *buffer_allocator_ = nullptr;
+ CPUHint cpu_hint_;
+ bool handle_idle_timeout_ = false;
+
+ // Primary output buffer configuration
+ LayerBuffer output_buffer_ = {};
+ bool post_processed_output_ = false;
+
+ // Members for 1 frame capture in a client provided buffer
+ bool frame_capture_buffer_queued_ = false;
+ int frame_capture_status_ = -EAGAIN;
+
+ // Members for N frame output dump to file
+ bool dump_output_to_file_ = false;
+ BufferInfo output_buffer_info_ = {};
+ void *output_buffer_base_ = nullptr;
+};
+
+} // namespace sdm
+
+#endif // __HWC_DISPLAY_PRIMARY_H__
+
diff --git a/msm8909/sdm/libs/hwc/hwc_display_virtual.cpp b/msm8909/sdm/libs/hwc/hwc_display_virtual.cpp
new file mode 100644
index 00000000..0279fc2a
--- /dev/null
+++ b/msm8909/sdm/libs/hwc/hwc_display_virtual.cpp
@@ -0,0 +1,334 @@
+/*
+* Copyright (c) 2014 - 2016, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <utils/constants.h>
+#include <utils/debug.h>
+#include <sync/sync.h>
+#include <stdarg.h>
+#include <gr.h>
+
+#include "hwc_display_virtual.h"
+#include "hwc_debugger.h"
+
+#define __CLASS__ "HWCDisplayVirtual"
+
+namespace sdm {
+
+int HWCDisplayVirtual::Create(CoreInterface *core_intf, hwc_procs_t const **hwc_procs,
+ uint32_t primary_width, uint32_t primary_height,
+ hwc_display_contents_1_t *content_list,
+ HWCDisplay **hwc_display) {
+ int status = 0;
+ HWCDisplayVirtual *hwc_display_virtual = new HWCDisplayVirtual(core_intf, hwc_procs);
+ uint32_t virtual_width = 0, virtual_height = 0;
+
+ status = hwc_display_virtual->Init();
+ if (status) {
+ delete hwc_display_virtual;
+ return status;
+ }
+
+ status = hwc_display_virtual->SetPowerMode(HWC_POWER_MODE_NORMAL);
+ if (status) {
+ Destroy(hwc_display_virtual);
+ return status;
+ }
+
+ // TODO(user): Need to update resolution(and not aligned resolution) on writeback.
+ status = hwc_display_virtual->SetOutputSliceFromMetadata(content_list);
+ if (status) {
+ Destroy(hwc_display_virtual);
+ return status;
+ }
+
+ hwc_display_virtual->GetMixerResolution(&virtual_width, &virtual_height);
+
+ if (content_list->numHwLayers < 1) {
+ Destroy(hwc_display_virtual);
+ return -1;
+ }
+
+ hwc_layer_1_t &fb_layer = content_list->hwLayers[content_list->numHwLayers-1];
+ int fb_width = fb_layer.displayFrame.right - fb_layer.displayFrame.left;
+ int fb_height = fb_layer.displayFrame.bottom - fb_layer.displayFrame.top;
+
+ status = hwc_display_virtual->SetFrameBufferResolution(UINT32(fb_width), UINT32(fb_height));
+
+ if (status) {
+ Destroy(hwc_display_virtual);
+ return status;
+ }
+
+ *hwc_display = static_cast<HWCDisplay *>(hwc_display_virtual);
+
+ return 0;
+}
+
+void HWCDisplayVirtual::Destroy(HWCDisplay *hwc_display) {
+ hwc_display->Deinit();
+ delete hwc_display;
+}
+
+HWCDisplayVirtual::HWCDisplayVirtual(CoreInterface *core_intf, hwc_procs_t const **hwc_procs)
+ : HWCDisplay(core_intf, hwc_procs, kVirtual, HWC_DISPLAY_VIRTUAL, false, NULL,
+ DISPLAY_CLASS_VIRTUAL) {
+}
+
+int HWCDisplayVirtual::Init() {
+ output_buffer_ = new LayerBuffer();
+ if (!output_buffer_) {
+ return -ENOMEM;
+ }
+
+ return HWCDisplay::Init();
+}
+
+int HWCDisplayVirtual::Deinit() {
+ int status = 0;
+
+ status = HWCDisplay::Deinit();
+ if (status) {
+ return status;
+ }
+
+ if (output_buffer_) {
+ delete output_buffer_;
+ output_buffer_ = NULL;
+ }
+
+ return status;
+}
+
+int HWCDisplayVirtual::Prepare(hwc_display_contents_1_t *content_list) {
+ int status = 0;
+
+ status = SetOutputSliceFromMetadata(content_list);
+ if (status) {
+ return status;
+ }
+
+ if (display_paused_) {
+ MarkLayersForGPUBypass(content_list);
+ return status;
+ }
+
+ status = AllocateLayerStack(content_list);
+ if (status) {
+ return status;
+ }
+
+ status = SetOutputBuffer(content_list);
+ if (status) {
+ return status;
+ }
+
+ status = PrePrepareLayerStack(content_list);
+ if (status) {
+ return status;
+ }
+
+ status = PrepareLayerStack(content_list);
+ if (status) {
+ return status;
+ }
+
+ return 0;
+}
+
+int HWCDisplayVirtual::Commit(hwc_display_contents_1_t *content_list) {
+ int status = 0;
+ if (display_paused_) {
+ DisplayError error = display_intf_->Flush();
+ if (error != kErrorNone) {
+ DLOGE("Flush failed. Error = %d", error);
+ }
+ return status;
+ }
+
+ CommitOutputBufferParams(content_list);
+
+ status = HWCDisplay::CommitLayerStack(content_list);
+ if (status) {
+ return status;
+ }
+
+ if (dump_frame_count_ && !flush_ && dump_output_layer_) {
+ const private_handle_t *output_handle = (const private_handle_t *)(content_list->outbuf);
+ if (output_handle && output_handle->base) {
+ BufferInfo buffer_info;
+ buffer_info.buffer_config.width = static_cast<uint32_t>(output_handle->width);
+ buffer_info.buffer_config.height = static_cast<uint32_t>(output_handle->height);
+ buffer_info.buffer_config.format = GetSDMFormat(output_handle->format, output_handle->flags);
+ buffer_info.alloc_buffer_info.size = static_cast<uint32_t>(output_handle->size);
+ DumpOutputBuffer(buffer_info, reinterpret_cast<void *>(output_handle->base),
+ layer_stack_.retire_fence_fd);
+ }
+ }
+
+ status = HWCDisplay::PostCommitLayerStack(content_list);
+ if (status) {
+ return status;
+ }
+
+ return 0;
+}
+
+int HWCDisplayVirtual::SetOutputSliceFromMetadata(hwc_display_contents_1_t *content_list) {
+ const private_handle_t *output_handle =
+ static_cast<const private_handle_t *>(content_list->outbuf);
+ DisplayError error = kErrorNone;
+ int status = 0;
+
+ if (output_handle) {
+ int output_handle_format = output_handle->format;
+ if (output_handle_format == HAL_PIXEL_FORMAT_RGBA_8888) {
+ output_handle_format = HAL_PIXEL_FORMAT_RGBX_8888;
+ }
+
+ LayerBufferFormat format = GetSDMFormat(output_handle_format, output_handle->flags);
+ if (format == kFormatInvalid) {
+ return -EINVAL;
+ }
+
+ int active_width;
+ int active_height;
+
+ AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(output_handle, active_width,
+ active_height);
+
+ if ((active_width != INT(output_buffer_->width)) ||
+ (active_height!= INT(output_buffer_->height)) ||
+ (format != output_buffer_->format)) {
+ // Populate virtual display attributes based on displayFrame of FBT.
+ // For DRC, use width and height populated in metadata (unaligned values)
+ // for setting attributes of virtual display. This is needed because if
+ // we use aligned width and height, scaling will be required for FBT layer.
+ DisplayConfigVariableInfo variable_info;
+ hwc_layer_1_t &fbt_layer = content_list->hwLayers[content_list->numHwLayers-1];
+ hwc_rect_t &frame = fbt_layer.displayFrame;
+ int fbt_width = frame.right - frame.left;
+ int fbt_height = frame.bottom - frame.top;
+ const MetaData_t *meta_data = reinterpret_cast<MetaData_t *>(output_handle->base_metadata);
+ if (meta_data && meta_data->operation & UPDATE_BUFFER_GEOMETRY) {
+ variable_info.x_pixels = UINT32(meta_data->bufferDim.sliceWidth);
+ variable_info.y_pixels = UINT32(meta_data->bufferDim.sliceHeight);
+ } else {
+ variable_info.x_pixels = UINT32(fbt_width);
+ variable_info.y_pixels = UINT32(fbt_height);
+ }
+ // TODO(user): Need to get the framerate of primary display and update it.
+ variable_info.fps = 60;
+
+ error = display_intf_->SetActiveConfig(&variable_info);
+ if (error != kErrorNone) {
+ return -EINVAL;
+ }
+
+ status = SetOutputBuffer(content_list);
+ if (status) {
+ return status;
+ }
+ }
+ }
+
+ return 0;
+}
+
+int HWCDisplayVirtual::SetOutputBuffer(hwc_display_contents_1_t *content_list) {
+ const private_handle_t *output_handle =
+ static_cast<const private_handle_t *>(content_list->outbuf);
+
+ if (output_handle) {
+ int output_handle_format = output_handle->format;
+
+ if (output_handle_format == HAL_PIXEL_FORMAT_RGBA_8888) {
+ output_handle_format = HAL_PIXEL_FORMAT_RGBX_8888;
+ }
+
+ output_buffer_->format = GetSDMFormat(output_handle_format, output_handle->flags);
+
+ if (output_buffer_->format == kFormatInvalid) {
+ return -EINVAL;
+ }
+
+ int aligned_width, aligned_height;
+ int unaligned_width, unaligned_height;
+
+ AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(output_handle, aligned_width,
+ aligned_height);
+ AdrenoMemInfo::getInstance().getUnalignedWidthAndHeight(output_handle, unaligned_width,
+ unaligned_height);
+
+ output_buffer_->width = UINT32(aligned_width);
+ output_buffer_->height = UINT32(aligned_height);
+ output_buffer_->unaligned_width = UINT32(unaligned_width);
+ output_buffer_->unaligned_height = UINT32(unaligned_height);
+ output_buffer_->flags.secure = 0;
+ output_buffer_->flags.video = 0;
+
+ const MetaData_t *meta_data = reinterpret_cast<MetaData_t *>(output_handle->base_metadata);
+ if (meta_data && SetCSC(meta_data, &output_buffer_->color_metadata) != kErrorNone) {
+ return kErrorNotSupported;
+ }
+
+ // TZ Protected Buffer - L1
+ if (output_handle->flags & private_handle_t::PRIV_FLAGS_SECURE_BUFFER) {
+ output_buffer_->flags.secure = 1;
+ }
+ }
+
+ layer_stack_.output_buffer = output_buffer_;
+
+ return 0;
+}
+
+void HWCDisplayVirtual::CommitOutputBufferParams(hwc_display_contents_1_t *content_list) {
+ const private_handle_t *output_handle =
+ static_cast<const private_handle_t *>(content_list->outbuf);
+
+ // Fill output buffer parameters (width, height, format, plane information, fence)
+ output_buffer_->acquire_fence_fd = content_list->outbufAcquireFenceFd;
+
+ if (output_handle) {
+ // ToDo: Need to extend for non-RGB formats
+ output_buffer_->planes[0].fd = output_handle->fd;
+ output_buffer_->planes[0].offset = output_handle->offset;
+ output_buffer_->planes[0].stride = UINT32(output_handle->width);
+ }
+}
+
+void HWCDisplayVirtual::SetFrameDumpConfig(uint32_t count, uint32_t bit_mask_layer_type) {
+ HWCDisplay::SetFrameDumpConfig(count, bit_mask_layer_type);
+ dump_output_layer_ = ((bit_mask_layer_type & (1 << OUTPUT_LAYER_DUMP)) != 0);
+
+ DLOGI("output_layer_dump_enable %d", dump_output_layer_);
+}
+
+} // namespace sdm
+
diff --git a/msm8909/sdm/libs/hwc/hwc_display_virtual.h b/msm8909/sdm/libs/hwc/hwc_display_virtual.h
new file mode 100644
index 00000000..77e16d53
--- /dev/null
+++ b/msm8909/sdm/libs/hwc/hwc_display_virtual.h
@@ -0,0 +1,64 @@
+/*
+* Copyright (c) 2014,2016 The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without modification, are permitted
+* provided that the following conditions are met:
+* * Redistributions of source code must retain the above copyright notice, this list of
+* conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright notice, this list of
+* conditions and the following disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its contributors may be used to
+* endorse or promote products derived from this software without specific prior written
+* permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __HWC_DISPLAY_VIRTUAL_H__
+#define __HWC_DISPLAY_VIRTUAL_H__
+
+#include <qdMetaData.h>
+#include <gralloc_priv.h>
+#include "hwc_display.h"
+
+namespace sdm {
+
+class HWCDisplayVirtual : public HWCDisplay {
+ public:
+ static int Create(CoreInterface *core_intf, hwc_procs_t const **hwc_procs,
+ uint32_t primary_width, uint32_t primary_height,
+ hwc_display_contents_1_t *content_list, HWCDisplay **hwc_display);
+ static void Destroy(HWCDisplay *hwc_display);
+ static bool IsValidContentList(hwc_display_contents_1_t *content_list);
+ virtual int Init();
+ virtual int Deinit();
+ virtual int Prepare(hwc_display_contents_1_t *content_list);
+ virtual int Commit(hwc_display_contents_1_t *content_list);
+ virtual void SetFrameDumpConfig(uint32_t count, uint32_t bit_mask_layer_type);
+
+ private:
+ HWCDisplayVirtual(CoreInterface *core_intf, hwc_procs_t const **hwc_procs);
+ int SetOutputBuffer(hwc_display_contents_1_t *content_list);
+ int SetOutputSliceFromMetadata(hwc_display_contents_1_t *content_list);
+ void CommitOutputBufferParams(hwc_display_contents_1_t *content_list);
+
+ bool dump_output_layer_ = false;
+ LayerBuffer *output_buffer_ = NULL;
+};
+
+inline bool HWCDisplayVirtual::IsValidContentList(hwc_display_contents_1_t *content_list) {
+ return (content_list && content_list->numHwLayers > 0 && content_list->outbuf);
+}
+
+} // namespace sdm
+
+#endif // __HWC_DISPLAY_VIRTUAL_H__
+
diff --git a/msm8909/sdm/libs/hwc/hwc_session.cpp b/msm8909/sdm/libs/hwc/hwc_session.cpp
new file mode 100644
index 00000000..31594408
--- /dev/null
+++ b/msm8909/sdm/libs/hwc/hwc_session.cpp
@@ -0,0 +1,1734 @@
+/*
+* Copyright (c) 2014 - 2018, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <core/dump_interface.h>
+#include <core/buffer_allocator.h>
+#include <private/color_params.h>
+#include <utils/constants.h>
+#include <utils/String16.h>
+#include <cutils/properties.h>
+#include <hardware_legacy/uevent.h>
+#include <sys/resource.h>
+#include <sys/prctl.h>
+#include <binder/Parcel.h>
+#include <QService.h>
+#include <gr.h>
+#include <gralloc_priv.h>
+#include <display_config.h>
+#include <utils/debug.h>
+#include <sync/sync.h>
+#include <profiler.h>
+#include <bitset>
+#include <vector>
+
+#include "hwc_buffer_allocator.h"
+#include "hwc_buffer_sync_handler.h"
+#include "hwc_session.h"
+#include "hwc_debugger.h"
+#include "hwc_display_null.h"
+#include "hwc_display_primary.h"
+#include "hwc_display_virtual.h"
+#include "hwc_display_external_test.h"
+#include "qd_utils.h"
+
+#define __CLASS__ "HWCSession"
+
+#define HWC_UEVENT_SWITCH_HDMI "change@/devices/virtual/switch/hdmi"
+#define HWC_UEVENT_GRAPHICS_FB0 "change@/devices/virtual/graphics/fb0"
+
+static sdm::HWCSession::HWCModuleMethods g_hwc_module_methods;
+
+hwc_module_t HAL_MODULE_INFO_SYM = {
+ .common = {
+ .tag = HARDWARE_MODULE_TAG,
+ .version_major = 2,
+ .version_minor = 0,
+ .id = HWC_HARDWARE_MODULE_ID,
+ .name = "QTI Hardware Composer Module",
+ .author = "CodeAurora Forum",
+ .methods = &g_hwc_module_methods,
+ .dso = 0,
+ .reserved = {0},
+ }
+};
+
+namespace sdm {
+
+Locker HWCSession::locker_;
+
+static void Invalidate(const struct hwc_procs *procs) {
+}
+
+static void VSync(const struct hwc_procs* procs, int disp, int64_t timestamp) {
+}
+
+static void Hotplug(const struct hwc_procs* procs, int disp, int connected) {
+}
+
+HWCSession::HWCSession(const hw_module_t *module) {
+ // By default, drop any events. Calls will be routed to SurfaceFlinger after registerProcs.
+ hwc_procs_default_.invalidate = Invalidate;
+ hwc_procs_default_.vsync = VSync;
+ hwc_procs_default_.hotplug = Hotplug;
+
+ hwc_composer_device_1_t::common.tag = HARDWARE_DEVICE_TAG;
+ hwc_composer_device_1_t::common.version = HWC_DEVICE_API_VERSION_1_5;
+ hwc_composer_device_1_t::common.module = const_cast<hw_module_t*>(module);
+ hwc_composer_device_1_t::common.close = Close;
+ hwc_composer_device_1_t::prepare = Prepare;
+ hwc_composer_device_1_t::set = Set;
+ hwc_composer_device_1_t::eventControl = EventControl;
+ hwc_composer_device_1_t::setPowerMode = SetPowerMode;
+ hwc_composer_device_1_t::query = Query;
+ hwc_composer_device_1_t::registerProcs = RegisterProcs;
+ hwc_composer_device_1_t::dump = Dump;
+ hwc_composer_device_1_t::getDisplayConfigs = GetDisplayConfigs;
+ hwc_composer_device_1_t::getDisplayAttributes = GetDisplayAttributes;
+ hwc_composer_device_1_t::getActiveConfig = GetActiveConfig;
+ hwc_composer_device_1_t::setActiveConfig = SetActiveConfig;
+ hwc_composer_device_1_t::setCursorPositionAsync = SetCursorPositionAsync;
+}
+
+int HWCSession::Init() {
+ int status = -EINVAL;
+ const char *qservice_name = "display.qservice";
+
+ // Start QService and connect to it.
+ qService::QService::init();
+ android::sp<qService::IQService> iqservice = android::interface_cast<qService::IQService>(
+ android::defaultServiceManager()->getService(android::String16(qservice_name)));
+
+ if (iqservice.get()) {
+ iqservice->connect(android::sp<qClient::IQClient>(this));
+ qservice_ = reinterpret_cast<qService::QService* >(iqservice.get());
+ } else {
+ DLOGE("Failed to acquire %s", qservice_name);
+ return -EINVAL;
+ }
+
+ DisplayError error = CoreInterface::CreateCore(HWCDebugHandler::Get(), &buffer_allocator_,
+ &buffer_sync_handler_, &socket_handler_,
+ &core_intf_);
+ if (error != kErrorNone) {
+ DLOGE("Display core initialization failed. Error = %d", error);
+ return -EINVAL;
+ }
+
+ SCOPE_LOCK(uevent_locker_);
+
+ if (pthread_create(&uevent_thread_, NULL, &HWCUeventThread, this) < 0) {
+ DLOGE("Failed to start = %s, error = %s", uevent_thread_name_, strerror(errno));
+ CoreInterface::DestroyCore();
+ return -errno;
+ }
+
+ // Wait for uevent_init() to happen and let the uevent thread wait for uevents, so that hdmi
+ // connect/disconnect events won't be missed
+ uevent_locker_.Wait();
+
+ // Read which display is first, and create it and store it in primary slot
+ HWDisplayInterfaceInfo hw_disp_info;
+ error = core_intf_->GetFirstDisplayInterfaceType(&hw_disp_info);
+ if (error == kErrorNone) {
+ if (hw_disp_info.type == kHDMI) {
+ // HDMI is primary display. If already connected, then create it and store in
+ // primary display slot. If not connected, create a NULL display for now.
+ HWCDebugHandler::Get()->SetProperty("persist.sys.is_hdmi_primary", "1");
+ is_hdmi_primary_ = true;
+ if (hw_disp_info.is_connected) {
+ status = CreateExternalDisplay(HWC_DISPLAY_PRIMARY, 0, 0, false);
+ is_hdmi_yuv_ = IsDisplayYUV(HWC_DISPLAY_PRIMARY);
+ } else {
+ // NullDisplay simply closes all its fences, and advertizes a standard
+ // resolution to SurfaceFlinger
+ status = HWCDisplayNull::Create(core_intf_, &hwc_procs_,
+ &hwc_display_[HWC_DISPLAY_PRIMARY]);
+ }
+ } else {
+ // Create and power on primary display
+ status = HWCDisplayPrimary::Create(core_intf_, &buffer_allocator_, &hwc_procs_, qservice_,
+ &hwc_display_[HWC_DISPLAY_PRIMARY]);
+ }
+ } else {
+ // Create and power on primary display
+ status = HWCDisplayPrimary::Create(core_intf_, &buffer_allocator_, &hwc_procs_, qservice_,
+ &hwc_display_[HWC_DISPLAY_PRIMARY]);
+ }
+
+ if (status) {
+ CoreInterface::DestroyCore();
+ uevent_thread_exit_ = true;
+ pthread_join(uevent_thread_, NULL);
+ return status;
+ }
+
+ color_mgr_ = HWCColorManager::CreateColorManager();
+ if (!color_mgr_) {
+ DLOGW("Failed to load HWCColorManager.");
+ }
+
+ connected_displays_[HWC_DISPLAY_PRIMARY] = 1;
+ struct rlimit fd_limit = {};
+ getrlimit(RLIMIT_NOFILE, &fd_limit);
+ fd_limit.rlim_cur = fd_limit.rlim_cur * 2;
+ auto err = setrlimit(RLIMIT_NOFILE, &fd_limit);
+ if (err) {
+ DLOGW("Unable to increase fd limit - err: %d, %s", errno, strerror(errno));
+ }
+ return 0;
+}
+
+int HWCSession::Deinit() {
+ HWCDisplayPrimary::Destroy(hwc_display_[HWC_DISPLAY_PRIMARY]);
+ hwc_display_[HWC_DISPLAY_PRIMARY] = 0;
+ if (color_mgr_) {
+ color_mgr_->DestroyColorManager();
+ }
+ uevent_thread_exit_ = true;
+ pthread_join(uevent_thread_, NULL);
+
+ DisplayError error = CoreInterface::DestroyCore();
+ if (error != kErrorNone) {
+ DLOGE("Display core de-initialization failed. Error = %d", error);
+ }
+
+ connected_displays_[HWC_DISPLAY_PRIMARY] = 0;
+ return 0;
+}
+
+int HWCSession::Open(const hw_module_t *module, const char *name, hw_device_t **device) {
+ SEQUENCE_WAIT_SCOPE_LOCK(locker_);
+
+ if (!module || !name || !device) {
+ DLOGE("Invalid parameters.");
+ return -EINVAL;
+ }
+
+ if (!strcmp(name, HWC_HARDWARE_COMPOSER)) {
+ HWCSession *hwc_session = new HWCSession(module);
+ if (!hwc_session) {
+ return -ENOMEM;
+ }
+
+ int status = hwc_session->Init();
+ if (status != 0) {
+ delete hwc_session;
+ return status;
+ }
+
+ hwc_composer_device_1_t *composer_device = hwc_session;
+ *device = reinterpret_cast<hw_device_t *>(composer_device);
+ }
+
+ return 0;
+}
+
+int HWCSession::Close(hw_device_t *device) {
+ SEQUENCE_WAIT_SCOPE_LOCK(locker_);
+
+ if (!device) {
+ return -EINVAL;
+ }
+
+ hwc_composer_device_1_t *composer_device = reinterpret_cast<hwc_composer_device_1_t *>(device);
+ HWCSession *hwc_session = static_cast<HWCSession *>(composer_device);
+
+ hwc_session->Deinit();
+ delete hwc_session;
+
+ return 0;
+}
+
+int HWCSession::Prepare(hwc_composer_device_1 *device, size_t num_displays,
+ hwc_display_contents_1_t **displays) {
+ DTRACE_SCOPED();
+
+ if (!device || !displays || num_displays > HWC_NUM_DISPLAY_TYPES) {
+ return -EINVAL;
+ }
+
+ HWCSession *hwc_session = static_cast<HWCSession *>(device);
+ hwc_procs_t const *hwc_procs = NULL;
+ bool hotplug_connect = false;
+
+ // Hold mutex only in this scope.
+ {
+ SEQUENCE_ENTRY_SCOPE_LOCK(locker_);
+
+ hwc_procs = hwc_session->hwc_procs_;
+
+ if (hwc_session->reset_panel_) {
+ DLOGW("panel is in bad state, resetting the panel");
+ hwc_session->ResetPanel();
+ }
+
+ if (hwc_session->need_invalidate_) {
+ hwc_procs->invalidate(hwc_procs);
+ hwc_session->need_invalidate_ = false;
+ }
+
+ hwc_session->HandleSecureDisplaySession(displays);
+
+ if (hwc_session->color_mgr_) {
+ HWCDisplay *primary_display = hwc_session->hwc_display_[HWC_DISPLAY_PRIMARY];
+ if (primary_display && !hwc_session->is_hdmi_primary_) {
+ int ret = hwc_session->color_mgr_->SolidFillLayersPrepare(displays, primary_display);
+ if (ret)
+ return 0;
+ }
+ }
+
+ for (ssize_t dpy = static_cast<ssize_t>(num_displays - 1); dpy >= 0; dpy--) {
+ hwc_display_contents_1_t *content_list = displays[dpy];
+ // If external display is connected, ignore virtual display content list.
+ // If virtual display content list is valid, connect virtual display if not connected.
+ // If virtual display content list is invalid, disconnect virtual display if connected.
+ // If external display connection is pending, connect external display when virtual
+ // display is destroyed.
+ // If HDMI is primary and the output format is YUV then ignore the virtual display
+ // content list.
+ if (dpy == HWC_DISPLAY_VIRTUAL) {
+ if (hwc_session->hwc_display_[HWC_DISPLAY_EXTERNAL] ||
+ (hwc_session->is_hdmi_primary_ && hwc_session->is_hdmi_yuv_)) {
+ continue;
+ }
+
+ bool valid_content = HWCDisplayVirtual::IsValidContentList(content_list);
+ bool connected = (hwc_session->hwc_display_[HWC_DISPLAY_VIRTUAL] != NULL);
+
+ if (valid_content && !connected) {
+ hwc_session->ConnectDisplay(HWC_DISPLAY_VIRTUAL, content_list);
+ } else if (!valid_content && connected) {
+ hwc_session->DisconnectDisplay(HWC_DISPLAY_VIRTUAL);
+
+ if (hwc_session->external_pending_connect_) {
+ DLOGI("Process pending external display connection");
+ hwc_session->ConnectDisplay(HWC_DISPLAY_EXTERNAL, NULL);
+ hwc_session->external_pending_connect_ = false;
+ hotplug_connect = true;
+ }
+ }
+ }
+
+ if (hwc_session->hwc_display_[dpy]) {
+ if (!content_list) {
+ DLOGI("Display[%d] connected. content_list is null", dpy);
+ } else if (!content_list->numHwLayers) {
+ DLOGE("Display[%d] connected. numHwLayers is zero", dpy);
+ } else {
+ hwc_session->hwc_display_[dpy]->Prepare(content_list);
+ }
+ }
+ }
+ }
+
+ if (hotplug_connect) {
+ // notify client
+ hwc_procs->hotplug(hwc_procs, HWC_DISPLAY_EXTERNAL, true);
+ }
+ // Return 0, else client will go into bad state
+ return 0;
+}
+
+int HWCSession::GetVsyncPeriod(int disp) {
+ SCOPE_LOCK(locker_);
+ // default value
+ int32_t vsync_period = 1000000000l / 60;
+ const uint32_t attribute = HWC_DISPLAY_VSYNC_PERIOD;
+
+ if (hwc_display_[disp]) {
+ hwc_display_[disp]->GetDisplayAttributes(0, &attribute, &vsync_period);
+ }
+
+ return vsync_period;
+}
+
+int HWCSession::Set(hwc_composer_device_1 *device, size_t num_displays,
+ hwc_display_contents_1_t **displays) {
+ DTRACE_SCOPED();
+
+ SEQUENCE_EXIT_SCOPE_LOCK(locker_);
+
+ if (!device || !displays || num_displays > HWC_NUM_DISPLAY_TYPES) {
+ return -EINVAL;
+ }
+
+ HWCSession *hwc_session = static_cast<HWCSession *>(device);
+
+ if (hwc_session->color_mgr_) {
+ HWCDisplay *primary_display = hwc_session->hwc_display_[HWC_DISPLAY_PRIMARY];
+ if (primary_display) {
+ int ret = hwc_session->color_mgr_->SolidFillLayersSet(displays, primary_display);
+ if (ret)
+ return 0;
+ hwc_session->color_mgr_->SetColorModeDetailEnhancer(primary_display);
+ }
+ }
+
+ for (size_t dpy = 0; dpy < num_displays; dpy++) {
+ hwc_display_contents_1_t *content_list = displays[dpy];
+
+ // Drop virtual display composition if virtual display object could not be created
+ // due to HDMI concurrency.
+ if (dpy == HWC_DISPLAY_VIRTUAL && !hwc_session->hwc_display_[HWC_DISPLAY_VIRTUAL]) {
+ CloseAcquireFds(content_list);
+ if (content_list) {
+ content_list->retireFenceFd = -1;
+ }
+
+ continue;
+ }
+
+ if (hwc_session->hwc_display_[dpy]) {
+ hwc_session->hwc_display_[dpy]->Commit(content_list);
+ }
+ CloseAcquireFds(content_list);
+ }
+
+ if (hwc_session->new_bw_mode_) {
+ hwc_display_contents_1_t *content_list = displays[HWC_DISPLAY_PRIMARY];
+ hwc_session->new_bw_mode_ = false;
+ if (hwc_session->bw_mode_release_fd_ >= 0) {
+ close(hwc_session->bw_mode_release_fd_);
+ }
+ hwc_session->bw_mode_release_fd_ = dup(content_list->retireFenceFd);
+ }
+
+ // This is only indicative of how many times SurfaceFlinger posts
+ // frames to the display.
+ CALC_FPS();
+
+ // Return 0, else client will go into bad state
+ return 0;
+}
+
+void HWCSession::CloseAcquireFds(hwc_display_contents_1_t *content_list) {
+ if (content_list) {
+ for (size_t i = 0; i < content_list->numHwLayers; i++) {
+ int &acquireFenceFd = content_list->hwLayers[i].acquireFenceFd;
+ if (acquireFenceFd >= 0) {
+ close(acquireFenceFd);
+ acquireFenceFd = -1;
+ }
+ }
+
+ int &outbufAcquireFenceFd = content_list->outbufAcquireFenceFd;
+ if (outbufAcquireFenceFd >= 0) {
+ close(outbufAcquireFenceFd);
+ outbufAcquireFenceFd = -1;
+ }
+ }
+}
+
+bool HWCSession::IsDisplayYUV(int disp) {
+ int error = -EINVAL;
+ bool is_yuv = false;
+ DisplayConfigVariableInfo attributes = {};
+
+ if (disp < 0 || disp >= HWC_NUM_DISPLAY_TYPES || !hwc_display_[disp]) {
+ DLOGE("Invalid input parameters. Display = %d", disp);
+ return is_yuv;
+ }
+
+ uint32_t active_config = 0;
+ error = hwc_display_[disp]->GetActiveDisplayConfig(&active_config);
+ if (!error) {
+ error = hwc_display_[disp]->GetDisplayAttributesForConfig(INT(active_config), &attributes);
+ if (error == 0) {
+ is_yuv = attributes.is_yuv;
+ } else {
+ DLOGW("Error querying display attributes. Display = %d, Config = %d", disp, active_config);
+ }
+ }
+
+ return is_yuv;
+}
+
+int HWCSession::EventControl(hwc_composer_device_1 *device, int disp, int event, int enable) {
+ SCOPE_LOCK(locker_);
+
+ if (!device) {
+ return -EINVAL;
+ }
+
+ HWCSession *hwc_session = static_cast<HWCSession *>(device);
+ int status = -EINVAL;
+ if (hwc_session->hwc_display_[disp]) {
+ status = hwc_session->hwc_display_[disp]->EventControl(event, enable);
+ }
+
+ return status;
+}
+
+int HWCSession::SetPowerMode(hwc_composer_device_1 *device, int disp, int mode) {
+ SEQUENCE_WAIT_SCOPE_LOCK(locker_);
+
+ if (!device) {
+ return -EINVAL;
+ }
+
+ HWCSession *hwc_session = static_cast<HWCSession *>(device);
+ int status = -EINVAL;
+ if (hwc_session->hwc_display_[disp]) {
+ status = hwc_session->hwc_display_[disp]->SetPowerMode(mode);
+ }
+
+ return status;
+}
+
+int HWCSession::Query(hwc_composer_device_1 *device, int param, int *value) {
+ SCOPE_LOCK(locker_);
+
+ if (!device || !value) {
+ return -EINVAL;
+ }
+
+ int status = 0;
+
+ switch (param) {
+ case HWC_BACKGROUND_LAYER_SUPPORTED:
+ value[0] = 1;
+ break;
+
+ default:
+ status = -EINVAL;
+ }
+
+ return status;
+}
+
+void HWCSession::RegisterProcs(hwc_composer_device_1 *device, hwc_procs_t const *procs) {
+ SCOPE_LOCK(locker_);
+
+ if (!device || !procs) {
+ return;
+ }
+
+ HWCSession *hwc_session = static_cast<HWCSession *>(device);
+ hwc_session->hwc_procs_ = procs;
+}
+
+void HWCSession::Dump(hwc_composer_device_1 *device, char *buffer, int length) {
+ SEQUENCE_WAIT_SCOPE_LOCK(locker_);
+
+ if (!device || !buffer || !length) {
+ return;
+ }
+
+ DumpInterface::GetDump(buffer, UINT32(length));
+}
+
+int HWCSession::GetDisplayConfigs(hwc_composer_device_1 *device, int disp, uint32_t *configs,
+ size_t *num_configs) {
+ SCOPE_LOCK(locker_);
+
+ if (!device || !configs || !num_configs) {
+ return -EINVAL;
+ }
+
+ if (disp < HWC_DISPLAY_PRIMARY || disp > HWC_NUM_PHYSICAL_DISPLAY_TYPES) {
+ return -EINVAL;
+ }
+
+ HWCSession *hwc_session = static_cast<HWCSession *>(device);
+ int status = -EINVAL;
+ if (hwc_session->hwc_display_[disp]) {
+ status = hwc_session->hwc_display_[disp]->GetDisplayConfigs(configs, num_configs);
+ }
+
+ return status;
+}
+
+int HWCSession::GetDisplayAttributes(hwc_composer_device_1 *device, int disp, uint32_t config,
+ const uint32_t *display_attributes, int32_t *values) {
+ SCOPE_LOCK(locker_);
+
+ if (!device || !display_attributes || !values) {
+ return -EINVAL;
+ }
+
+ if (disp < HWC_DISPLAY_PRIMARY || disp > HWC_NUM_PHYSICAL_DISPLAY_TYPES) {
+ return -EINVAL;
+ }
+
+ HWCSession *hwc_session = static_cast<HWCSession *>(device);
+ int status = -EINVAL;
+ if (hwc_session->hwc_display_[disp]) {
+ status = hwc_session->hwc_display_[disp]->GetDisplayAttributes(config, display_attributes,
+ values);
+ }
+
+ return status;
+}
+
+int HWCSession::GetActiveConfig(hwc_composer_device_1 *device, int disp) {
+ SCOPE_LOCK(locker_);
+
+ if (!device) {
+ return -EINVAL;
+ }
+
+ if (disp < HWC_DISPLAY_PRIMARY || disp > HWC_NUM_PHYSICAL_DISPLAY_TYPES) {
+ return -EINVAL;
+ }
+
+ HWCSession *hwc_session = static_cast<HWCSession *>(device);
+ int active_config = -1;
+ if (hwc_session->hwc_display_[disp]) {
+ active_config = hwc_session->hwc_display_[disp]->GetActiveConfig();
+ }
+
+ return active_config;
+}
+
+int HWCSession::SetActiveConfig(hwc_composer_device_1 *device, int disp, int index) {
+ SEQUENCE_WAIT_SCOPE_LOCK(locker_);
+
+ if (!device) {
+ return -EINVAL;
+ }
+
+ if (disp < HWC_DISPLAY_PRIMARY || disp > HWC_NUM_PHYSICAL_DISPLAY_TYPES) {
+ return -EINVAL;
+ }
+
+ HWCSession *hwc_session = static_cast<HWCSession *>(device);
+ int status = -EINVAL;
+
+ if (hwc_session->hwc_display_[disp]) {
+ status = hwc_session->hwc_display_[disp]->SetActiveConfig(index);
+ }
+
+ return status;
+}
+
+int HWCSession::SetCursorPositionAsync(hwc_composer_device_1 *device, int disp, int x, int y) {
+ DTRACE_SCOPED();
+
+ SCOPE_LOCK(locker_);
+
+ if (!device || (disp < HWC_DISPLAY_PRIMARY) || (disp > HWC_DISPLAY_VIRTUAL)) {
+ return -EINVAL;
+ }
+
+ int status = -EINVAL;
+ HWCSession *hwc_session = static_cast<HWCSession *>(device);
+ if (hwc_session->hwc_display_[disp]) {
+ status = hwc_session->hwc_display_[disp]->SetCursorPosition(x, y);
+ }
+
+ return status;
+}
+
+int HWCSession::ConnectDisplay(int disp, hwc_display_contents_1_t *content_list) {
+ DLOGI("Display = %d", disp);
+
+ int status = 0;
+ uint32_t primary_width = 0;
+ uint32_t primary_height = 0;
+
+ hwc_display_[HWC_DISPLAY_PRIMARY]->GetFrameBufferResolution(&primary_width, &primary_height);
+
+ if (disp == HWC_DISPLAY_EXTERNAL) {
+ status = CreateExternalDisplay(disp, primary_width, primary_height, false);
+ connected_displays_[HWC_DISPLAY_EXTERNAL] = 1;
+ } else if (disp == HWC_DISPLAY_VIRTUAL) {
+ status = HWCDisplayVirtual::Create(core_intf_, &hwc_procs_, primary_width, primary_height,
+ content_list, &hwc_display_[disp]);
+ connected_displays_[HWC_DISPLAY_VIRTUAL] = 1;
+ } else {
+ DLOGE("Invalid display type");
+ return -1;
+ }
+
+ if (!status) {
+ hwc_display_[disp]->SetSecureDisplay(secure_display_active_, true);
+ }
+
+ return status;
+}
+
+int HWCSession::DisconnectDisplay(int disp) {
+ DLOGI("Display = %d", disp);
+
+ if (disp == HWC_DISPLAY_EXTERNAL) {
+ HWCDisplayExternal::Destroy(hwc_display_[disp]);
+ connected_displays_[HWC_DISPLAY_EXTERNAL] = 0;
+ } else if (disp == HWC_DISPLAY_VIRTUAL) {
+ HWCDisplayVirtual::Destroy(hwc_display_[disp]);
+ connected_displays_[HWC_DISPLAY_VIRTUAL] = 0;
+ } else {
+ DLOGE("Invalid display type");
+ return -1;
+ }
+
+ hwc_display_[disp] = NULL;
+
+ return 0;
+}
+
+android::status_t HWCSession::notifyCallback(uint32_t command, const android::Parcel *input_parcel,
+ android::Parcel *output_parcel) {
+ SEQUENCE_WAIT_SCOPE_LOCK(locker_);
+
+ android::status_t status = 0;
+
+ switch (command) {
+ case qService::IQService::DYNAMIC_DEBUG:
+ DynamicDebug(input_parcel);
+ break;
+
+ case qService::IQService::SCREEN_REFRESH:
+ hwc_procs_->invalidate(hwc_procs_);
+ break;
+
+ case qService::IQService::SET_IDLE_TIMEOUT:
+ if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
+ uint32_t timeout = UINT32(input_parcel->readInt32());
+ hwc_display_[HWC_DISPLAY_PRIMARY]->SetIdleTimeoutMs(timeout);
+ }
+ break;
+
+ case qService::IQService::SET_FRAME_DUMP_CONFIG:
+ SetFrameDumpConfig(input_parcel);
+ break;
+
+ case qService::IQService::SET_MAX_PIPES_PER_MIXER:
+ status = SetMaxMixerStages(input_parcel);
+ break;
+
+ case qService::IQService::SET_DISPLAY_MODE:
+ status = SetDisplayMode(input_parcel);
+ break;
+
+ case qService::IQService::SET_SECONDARY_DISPLAY_STATUS:
+ status = SetSecondaryDisplayStatus(input_parcel, output_parcel);
+ break;
+
+ case qService::IQService::CONFIGURE_DYN_REFRESH_RATE:
+ status = ConfigureRefreshRate(input_parcel);
+ break;
+
+ case qService::IQService::SET_VIEW_FRAME:
+ break;
+
+ case qService::IQService::TOGGLE_SCREEN_UPDATES:
+ status = ToggleScreenUpdates(input_parcel, output_parcel);
+ break;
+
+ case qService::IQService::QDCM_SVC_CMDS:
+ status = QdcmCMDHandler(input_parcel, output_parcel);
+ break;
+
+ case qService::IQService::MIN_HDCP_ENCRYPTION_LEVEL_CHANGED:
+ status = OnMinHdcpEncryptionLevelChange(input_parcel, output_parcel);
+ break;
+
+ case qService::IQService::CONTROL_PARTIAL_UPDATE:
+ status = ControlPartialUpdate(input_parcel, output_parcel);
+ break;
+
+ case qService::IQService::SET_ACTIVE_CONFIG:
+ status = HandleSetActiveDisplayConfig(input_parcel, output_parcel);
+ break;
+
+ case qService::IQService::GET_ACTIVE_CONFIG:
+ status = HandleGetActiveDisplayConfig(input_parcel, output_parcel);
+ break;
+
+ case qService::IQService::GET_CONFIG_COUNT:
+ status = HandleGetDisplayConfigCount(input_parcel, output_parcel);
+ break;
+
+ case qService::IQService::GET_DISPLAY_ATTRIBUTES_FOR_CONFIG:
+ status = HandleGetDisplayAttributesForConfig(input_parcel, output_parcel);
+ break;
+
+ case qService::IQService::GET_PANEL_BRIGHTNESS:
+ status = GetPanelBrightness(input_parcel, output_parcel);
+ break;
+
+ case qService::IQService::SET_PANEL_BRIGHTNESS:
+ status = SetPanelBrightness(input_parcel, output_parcel);
+ break;
+
+ case qService::IQService::GET_DISPLAY_VISIBLE_REGION:
+ status = GetVisibleDisplayRect(input_parcel, output_parcel);
+ break;
+
+ case qService::IQService::SET_CAMERA_STATUS:
+ status = SetDynamicBWForCamera(input_parcel, output_parcel);
+ break;
+
+ case qService::IQService::GET_BW_TRANSACTION_STATUS:
+ status = GetBWTransactionStatus(input_parcel, output_parcel);
+ break;
+
+ case qService::IQService::SET_LAYER_MIXER_RESOLUTION:
+ status = SetMixerResolution(input_parcel);
+ break;
+
+ case qService::IQService::GET_HDR_CAPABILITIES:
+ status = GetHdrCapabilities(input_parcel, output_parcel);
+ break;
+
+ default:
+ DLOGW("QService command = %d is not supported", command);
+ return -EINVAL;
+ }
+
+ return status;
+}
+
+android::status_t HWCSession::ToggleScreenUpdates(const android::Parcel *input_parcel,
+ android::Parcel *output_parcel) {
+ int input = input_parcel->readInt32();
+ int error = android::BAD_VALUE;
+
+ if (hwc_display_[HWC_DISPLAY_PRIMARY] && (input <= 1) && (input >= 0)) {
+ error = hwc_display_[HWC_DISPLAY_PRIMARY]->ToggleScreenUpdates(input == 1);
+ if (error != 0) {
+ DLOGE("Failed to toggle screen updates = %d. Error = %d", input, error);
+ }
+ }
+ output_parcel->writeInt32(error);
+
+ return error;
+}
+
+android::status_t HWCSession::SetPanelBrightness(const android::Parcel *input_parcel,
+ android::Parcel *output_parcel) {
+ int level = input_parcel->readInt32();
+ int error = android::BAD_VALUE;
+
+ if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
+ error = hwc_display_[HWC_DISPLAY_PRIMARY]->SetPanelBrightness(level);
+ if (error != 0) {
+ DLOGE("Failed to set the panel brightness = %d. Error = %d", level, error);
+ }
+ }
+ output_parcel->writeInt32(error);
+
+ return error;
+}
+
+android::status_t HWCSession::GetPanelBrightness(const android::Parcel *input_parcel,
+ android::Parcel *output_parcel) {
+ int error = android::BAD_VALUE;
+ int ret = error;
+
+ if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
+ error = hwc_display_[HWC_DISPLAY_PRIMARY]->GetPanelBrightness(&ret);
+ if (error != 0) {
+ ret = error;
+ DLOGE("Failed to get the panel brightness. Error = %d", error);
+ }
+ }
+ output_parcel->writeInt32(ret);
+
+ return error;
+}
+
+android::status_t HWCSession::ControlPartialUpdate(const android::Parcel *input_parcel,
+ android::Parcel *out) {
+ DisplayError error = kErrorNone;
+ int ret = 0;
+ uint32_t disp_id = UINT32(input_parcel->readInt32());
+ uint32_t enable = UINT32(input_parcel->readInt32());
+
+ if (disp_id != HWC_DISPLAY_PRIMARY) {
+ DLOGW("CONTROL_PARTIAL_UPDATE is not applicable for display = %d", disp_id);
+ ret = -EINVAL;
+ out->writeInt32(ret);
+ return ret;
+ }
+
+ if (!hwc_display_[HWC_DISPLAY_PRIMARY]) {
+ DLOGE("primary display object is not instantiated");
+ ret = -EINVAL;
+ out->writeInt32(ret);
+ return ret;
+ }
+
+ uint32_t pending = 0;
+ error = hwc_display_[HWC_DISPLAY_PRIMARY]->ControlPartialUpdate(enable, &pending);
+
+ if (error == kErrorNone) {
+ if (!pending) {
+ out->writeInt32(ret);
+ return ret;
+ }
+ } else if (error == kErrorNotSupported) {
+ out->writeInt32(ret);
+ return ret;
+ } else {
+ ret = -EINVAL;
+ out->writeInt32(ret);
+ return ret;
+ }
+
+ // Todo(user): Unlock it before sending events to client. It may cause deadlocks in future.
+ hwc_procs_->invalidate(hwc_procs_);
+
+ // Wait until partial update control is complete
+ ret = locker_.WaitFinite(kPartialUpdateControlTimeoutMs);
+
+ out->writeInt32(ret);
+
+ return ret;
+}
+
+android::status_t HWCSession::HandleSetActiveDisplayConfig(const android::Parcel *input_parcel,
+ android::Parcel *output_parcel) {
+ int config = input_parcel->readInt32();
+ int dpy = input_parcel->readInt32();
+ int error = android::BAD_VALUE;
+
+ if (dpy > HWC_DISPLAY_VIRTUAL) {
+ return android::BAD_VALUE;
+ }
+
+ if (hwc_display_[dpy]) {
+ error = hwc_display_[dpy]->SetActiveDisplayConfig(config);
+ if (error == 0) {
+ hwc_procs_->invalidate(hwc_procs_);
+ }
+ }
+
+ return error;
+}
+
+android::status_t HWCSession::HandleGetActiveDisplayConfig(const android::Parcel *input_parcel,
+ android::Parcel *output_parcel) {
+ int dpy = input_parcel->readInt32();
+ int error = android::BAD_VALUE;
+
+ if (dpy > HWC_DISPLAY_VIRTUAL) {
+ return android::BAD_VALUE;
+ }
+
+ if (hwc_display_[dpy]) {
+ uint32_t config = 0;
+ error = hwc_display_[dpy]->GetActiveDisplayConfig(&config);
+ if (error == 0) {
+ output_parcel->writeInt32(INT(config));
+ }
+ }
+
+ return error;
+}
+
+android::status_t HWCSession::HandleGetDisplayConfigCount(const android::Parcel *input_parcel,
+ android::Parcel *output_parcel) {
+ int dpy = input_parcel->readInt32();
+ int error = android::BAD_VALUE;
+
+ if (dpy > HWC_DISPLAY_VIRTUAL) {
+ return android::BAD_VALUE;
+ }
+
+ uint32_t count = 0;
+ if (hwc_display_[dpy]) {
+ error = hwc_display_[dpy]->GetDisplayConfigCount(&count);
+ if (error == 0) {
+ output_parcel->writeInt32(INT(count));
+ }
+ }
+
+ return error;
+}
+
+android::status_t HWCSession::SetDisplayPort(DisplayPort sdm_disp_port, int *hwc_disp_port) {
+ if (!hwc_disp_port) {
+ return -EINVAL;
+ }
+
+ switch (sdm_disp_port) {
+ case kPortDSI:
+ *hwc_disp_port = qdutils::DISPLAY_PORT_DSI;
+ break;
+ case kPortDTV:
+ *hwc_disp_port = qdutils::DISPLAY_PORT_DTV;
+ break;
+ case kPortLVDS:
+ *hwc_disp_port = qdutils::DISPLAY_PORT_LVDS;
+ break;
+ case kPortEDP:
+ *hwc_disp_port = qdutils::DISPLAY_PORT_EDP;
+ break;
+ case kPortWriteBack:
+ *hwc_disp_port = qdutils::DISPLAY_PORT_WRITEBACK;
+ break;
+ case kPortDP:
+ *hwc_disp_port = qdutils::DISPLAY_PORT_DP;
+ break;
+ case kPortDefault:
+ *hwc_disp_port = qdutils::DISPLAY_PORT_DEFAULT;
+ break;
+ default:
+ DLOGE("Invalid sdm display port %d", sdm_disp_port);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+android::status_t HWCSession::HandleGetDisplayAttributesForConfig(const android::Parcel
+ *input_parcel,
+ android::Parcel *output_parcel) {
+ int config = input_parcel->readInt32();
+ int dpy = input_parcel->readInt32();
+ int error = android::BAD_VALUE;
+ DisplayConfigVariableInfo display_attributes;
+ DisplayPort sdm_disp_port = kPortDefault;
+ int hwc_disp_port = qdutils::DISPLAY_PORT_DEFAULT;
+
+ if (dpy < HWC_DISPLAY_PRIMARY || dpy >= HWC_NUM_DISPLAY_TYPES || config < 0) {
+ return android::BAD_VALUE;
+ }
+
+ if (hwc_display_[dpy]) {
+ error = hwc_display_[dpy]->GetDisplayAttributesForConfig(config, &display_attributes);
+ if (error == 0) {
+ hwc_display_[dpy]->GetDisplayPort(&sdm_disp_port);
+
+ SetDisplayPort(sdm_disp_port, &hwc_disp_port);
+
+ output_parcel->writeInt32(INT(display_attributes.vsync_period_ns));
+ output_parcel->writeInt32(INT(display_attributes.x_pixels));
+ output_parcel->writeInt32(INT(display_attributes.y_pixels));
+ output_parcel->writeFloat(display_attributes.x_dpi);
+ output_parcel->writeFloat(display_attributes.y_dpi);
+ output_parcel->writeInt32(hwc_disp_port);
+ output_parcel->writeInt32(display_attributes.is_yuv);
+ }
+ }
+
+ return error;
+}
+
+android::status_t HWCSession::SetSecondaryDisplayStatus(const android::Parcel *input_parcel,
+ android::Parcel *output_parcel) {
+ int ret = -EINVAL;
+
+ uint32_t display_id = UINT32(input_parcel->readInt32());
+ uint32_t display_status = UINT32(input_parcel->readInt32());
+
+ DLOGI("Display = %d, Status = %d", display_id, display_status);
+
+ if (display_id >= HWC_NUM_DISPLAY_TYPES) {
+ DLOGE("Invalid display_id");
+ } else if (display_id == HWC_DISPLAY_PRIMARY) {
+ DLOGE("Not supported for this display");
+ } else if (!hwc_display_[display_id]) {
+ DLOGW("Display is not connected");
+ } else {
+ ret = hwc_display_[display_id]->SetDisplayStatus(display_status);
+ }
+
+ output_parcel->writeInt32(ret);
+
+ return ret;
+}
+
+android::status_t HWCSession::ConfigureRefreshRate(const android::Parcel *input_parcel) {
+ uint32_t operation = UINT32(input_parcel->readInt32());
+ switch (operation) {
+ case qdutils::DISABLE_METADATA_DYN_REFRESH_RATE:
+ return hwc_display_[HWC_DISPLAY_PRIMARY]->Perform(
+ HWCDisplayPrimary::SET_METADATA_DYN_REFRESH_RATE, false);
+ case qdutils::ENABLE_METADATA_DYN_REFRESH_RATE:
+ return hwc_display_[HWC_DISPLAY_PRIMARY]->Perform(
+ HWCDisplayPrimary::SET_METADATA_DYN_REFRESH_RATE, true);
+ case qdutils::SET_BINDER_DYN_REFRESH_RATE:
+ {
+ uint32_t refresh_rate = UINT32(input_parcel->readInt32());
+ return hwc_display_[HWC_DISPLAY_PRIMARY]->Perform(
+ HWCDisplayPrimary::SET_BINDER_DYN_REFRESH_RATE,
+ refresh_rate);
+ }
+ default:
+ DLOGW("Invalid operation %d", operation);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+android::status_t HWCSession::SetDisplayMode(const android::Parcel *input_parcel) {
+ uint32_t mode = UINT32(input_parcel->readInt32());
+ return hwc_display_[HWC_DISPLAY_PRIMARY]->Perform(HWCDisplayPrimary::SET_DISPLAY_MODE, mode);
+}
+
+android::status_t HWCSession::SetMaxMixerStages(const android::Parcel *input_parcel) {
+ DisplayError error = kErrorNone;
+ std::bitset<32> bit_mask_display_type = UINT32(input_parcel->readInt32());
+ uint32_t max_mixer_stages = UINT32(input_parcel->readInt32());
+
+ if (bit_mask_display_type[HWC_DISPLAY_PRIMARY]) {
+ if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
+ error = hwc_display_[HWC_DISPLAY_PRIMARY]->SetMaxMixerStages(max_mixer_stages);
+ if (error != kErrorNone) {
+ return -EINVAL;
+ }
+ }
+ }
+
+ if (bit_mask_display_type[HWC_DISPLAY_EXTERNAL]) {
+ if (hwc_display_[HWC_DISPLAY_EXTERNAL]) {
+ error = hwc_display_[HWC_DISPLAY_EXTERNAL]->SetMaxMixerStages(max_mixer_stages);
+ if (error != kErrorNone) {
+ return -EINVAL;
+ }
+ }
+ }
+
+ if (bit_mask_display_type[HWC_DISPLAY_VIRTUAL]) {
+ if (hwc_display_[HWC_DISPLAY_VIRTUAL]) {
+ error = hwc_display_[HWC_DISPLAY_VIRTUAL]->SetMaxMixerStages(max_mixer_stages);
+ if (error != kErrorNone) {
+ return -EINVAL;
+ }
+ }
+ }
+
+ return 0;
+}
+
+android::status_t HWCSession::SetDynamicBWForCamera(const android::Parcel *input_parcel,
+ android::Parcel *output_parcel) {
+ DisplayError error = kErrorNone;
+ uint32_t camera_status = UINT32(input_parcel->readInt32());
+ HWBwModes mode = camera_status > 0 ? kBwCamera : kBwDefault;
+
+ // trigger invalidate to apply new bw caps.
+ hwc_procs_->invalidate(hwc_procs_);
+
+ error = core_intf_->SetMaxBandwidthMode(mode);
+ if (error != kErrorNone) {
+ return -EINVAL;
+ }
+
+ new_bw_mode_ = true;
+ need_invalidate_ = true;
+
+ return 0;
+}
+
+android::status_t HWCSession::GetBWTransactionStatus(const android::Parcel *input_parcel,
+ android::Parcel *output_parcel) {
+ bool state = true;
+
+ if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
+ if (sync_wait(bw_mode_release_fd_, 0) < 0) {
+ DLOGI("bw_transaction_release_fd is not yet signalled: err= %s", strerror(errno));
+ state = false;
+ }
+ output_parcel->writeInt32(state);
+ }
+
+ return 0;
+}
+
+void HWCSession::SetFrameDumpConfig(const android::Parcel *input_parcel) {
+ uint32_t frame_dump_count = UINT32(input_parcel->readInt32());
+ std::bitset<32> bit_mask_display_type = UINT32(input_parcel->readInt32());
+ uint32_t bit_mask_layer_type = UINT32(input_parcel->readInt32());
+
+ if (bit_mask_display_type[HWC_DISPLAY_PRIMARY]) {
+ if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
+ hwc_display_[HWC_DISPLAY_PRIMARY]->SetFrameDumpConfig(frame_dump_count, bit_mask_layer_type);
+ }
+ }
+
+ if (bit_mask_display_type[HWC_DISPLAY_EXTERNAL]) {
+ if (hwc_display_[HWC_DISPLAY_EXTERNAL]) {
+ hwc_display_[HWC_DISPLAY_EXTERNAL]->SetFrameDumpConfig(frame_dump_count, bit_mask_layer_type);
+ }
+ }
+
+ if (bit_mask_display_type[HWC_DISPLAY_VIRTUAL]) {
+ if (hwc_display_[HWC_DISPLAY_VIRTUAL]) {
+ hwc_display_[HWC_DISPLAY_VIRTUAL]->SetFrameDumpConfig(frame_dump_count, bit_mask_layer_type);
+ }
+ }
+}
+
+android::status_t HWCSession::SetMixerResolution(const android::Parcel *input_parcel) {
+ DisplayError error = kErrorNone;
+ uint32_t dpy = UINT32(input_parcel->readInt32());
+
+ if (dpy != HWC_DISPLAY_PRIMARY) {
+ DLOGI("Resoulution change not supported for this display %d", dpy);
+ return -EINVAL;
+ }
+
+ if (!hwc_display_[HWC_DISPLAY_PRIMARY]) {
+ DLOGI("Primary display is not initialized");
+ return -EINVAL;
+ }
+
+ uint32_t width = UINT32(input_parcel->readInt32());
+ uint32_t height = UINT32(input_parcel->readInt32());
+
+ error = hwc_display_[HWC_DISPLAY_PRIMARY]->SetMixerResolution(width, height);
+ if (error != kErrorNone) {
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+android::status_t HWCSession::GetHdrCapabilities(const android::Parcel *input_parcel,
+ android::Parcel *output_parcel) {
+ uint32_t display_id = UINT32(input_parcel->readInt32());
+ if (display_id >= HWC_NUM_DISPLAY_TYPES) {
+ DLOGE("Invalid display id = %d", display_id);
+ return -EINVAL;
+ }
+
+ if (hwc_display_[display_id] == NULL) {
+ DLOGW("Display = %d not initialized", display_id);
+ return -EINVAL;
+ }
+
+ DisplayConfigFixedInfo fixed_info = {};
+ int ret = hwc_display_[display_id]->GetDisplayFixedConfig(&fixed_info);
+ if (ret) {
+ DLOGE("Failed");
+ return ret;
+ }
+
+ if (!fixed_info.hdr_supported) {
+ DLOGI("HDR is not supported");
+ return 0;
+ }
+
+ std::vector<int32_t> supported_hdr_types;
+ // Only HDR10 supported now, in future add other supported HDR formats(HLG, DolbyVision)
+ supported_hdr_types.push_back(HAL_HDR_HDR10);
+
+ static const float kLuminanceFactor = 10000.0;
+ // luminance is expressed in the unit of 0.0001 cd/m2, convert it to 1cd/m2.
+ float max_luminance = FLOAT(fixed_info.max_luminance)/kLuminanceFactor;
+ float max_average_luminance = FLOAT(fixed_info.average_luminance)/kLuminanceFactor;
+ float min_luminance = FLOAT(fixed_info.min_luminance)/kLuminanceFactor;
+
+ if (output_parcel != nullptr) {
+ output_parcel->writeInt32Vector(supported_hdr_types);
+ output_parcel->writeFloat(max_luminance);
+ output_parcel->writeFloat(max_average_luminance);
+ output_parcel->writeFloat(min_luminance);
+ }
+
+ return 0;
+}
+
+void HWCSession::DynamicDebug(const android::Parcel *input_parcel) {
+ int type = input_parcel->readInt32();
+ bool enable = (input_parcel->readInt32() > 0);
+ DLOGI("type = %d enable = %d", type, enable);
+ int verbose_level = input_parcel->readInt32();
+
+ switch (type) {
+ case qService::IQService::DEBUG_ALL:
+ HWCDebugHandler::DebugAll(enable, verbose_level);
+ break;
+
+ case qService::IQService::DEBUG_MDPCOMP:
+ HWCDebugHandler::DebugStrategy(enable, verbose_level);
+ HWCDebugHandler::DebugCompManager(enable, verbose_level);
+ break;
+
+ case qService::IQService::DEBUG_PIPE_LIFECYCLE:
+ HWCDebugHandler::DebugResources(enable, verbose_level);
+ break;
+
+ case qService::IQService::DEBUG_DRIVER_CONFIG:
+ HWCDebugHandler::DebugDriverConfig(enable, verbose_level);
+ break;
+
+ case qService::IQService::DEBUG_ROTATOR:
+ HWCDebugHandler::DebugResources(enable, verbose_level);
+ HWCDebugHandler::DebugDriverConfig(enable, verbose_level);
+ HWCDebugHandler::DebugRotator(enable, verbose_level);
+ break;
+
+ case qService::IQService::DEBUG_QDCM:
+ HWCDebugHandler::DebugQdcm(enable, verbose_level);
+ break;
+
+ default:
+ DLOGW("type = %d is not supported", type);
+ }
+}
+
+android::status_t HWCSession::QdcmCMDHandler(const android::Parcel *input_parcel,
+ android::Parcel *output_parcel) {
+ int ret = 0;
+ int32_t *brightness_value = NULL;
+ uint32_t display_id(0);
+ PPPendingParams pending_action;
+ PPDisplayAPIPayload resp_payload, req_payload;
+
+ if (!color_mgr_) {
+ return -1;
+ }
+
+ pending_action.action = kNoAction;
+ pending_action.params = NULL;
+
+ // Read display_id, payload_size and payload from in_parcel.
+ ret = HWCColorManager::CreatePayloadFromParcel(*input_parcel, &display_id, &req_payload);
+ if (!ret) {
+ if (HWC_DISPLAY_PRIMARY == display_id && hwc_display_[HWC_DISPLAY_PRIMARY])
+ ret = hwc_display_[HWC_DISPLAY_PRIMARY]->ColorSVCRequestRoute(req_payload,
+ &resp_payload, &pending_action);
+
+ if (HWC_DISPLAY_EXTERNAL == display_id && hwc_display_[HWC_DISPLAY_EXTERNAL])
+ ret = hwc_display_[HWC_DISPLAY_EXTERNAL]->ColorSVCRequestRoute(req_payload, &resp_payload,
+ &pending_action);
+ }
+
+ if (ret) {
+ output_parcel->writeInt32(ret); // first field in out parcel indicates return code.
+ req_payload.DestroyPayload();
+ resp_payload.DestroyPayload();
+ return ret;
+ }
+
+ switch (pending_action.action) {
+ case kInvalidating:
+ hwc_procs_->invalidate(hwc_procs_);
+ break;
+ case kEnterQDCMMode:
+ ret = color_mgr_->EnableQDCMMode(true, hwc_display_[HWC_DISPLAY_PRIMARY]);
+ break;
+ case kExitQDCMMode:
+ ret = color_mgr_->EnableQDCMMode(false, hwc_display_[HWC_DISPLAY_PRIMARY]);
+ break;
+ case kApplySolidFill:
+ ret = color_mgr_->SetSolidFill(pending_action.params,
+ true, hwc_display_[HWC_DISPLAY_PRIMARY]);
+ hwc_procs_->invalidate(hwc_procs_);
+ break;
+ case kDisableSolidFill:
+ ret = color_mgr_->SetSolidFill(pending_action.params,
+ false, hwc_display_[HWC_DISPLAY_PRIMARY]);
+ hwc_procs_->invalidate(hwc_procs_);
+ break;
+ case kSetPanelBrightness:
+ brightness_value = reinterpret_cast<int32_t*>(resp_payload.payload);
+ if (brightness_value == NULL) {
+ DLOGE("Brightness value is Null");
+ return -EINVAL;
+ }
+ if (HWC_DISPLAY_PRIMARY == display_id)
+ ret = hwc_display_[HWC_DISPLAY_PRIMARY]->SetPanelBrightness(*brightness_value);
+ break;
+ case kEnableFrameCapture:
+ ret = color_mgr_->SetFrameCapture(pending_action.params,
+ true, hwc_display_[HWC_DISPLAY_PRIMARY]);
+ hwc_procs_->invalidate(hwc_procs_);
+ break;
+ case kDisableFrameCapture:
+ ret = color_mgr_->SetFrameCapture(pending_action.params,
+ false, hwc_display_[HWC_DISPLAY_PRIMARY]);
+ break;
+ case kConfigureDetailedEnhancer:
+ ret = color_mgr_->SetDetailedEnhancer(pending_action.params,
+ hwc_display_[HWC_DISPLAY_PRIMARY]);
+ hwc_procs_->invalidate(hwc_procs_);
+ break;
+ case kInvalidatingAndkSetPanelBrightness:
+ brightness_value = reinterpret_cast<int32_t*>(resp_payload.payload);
+ if (brightness_value == NULL) {
+ DLOGE("Brightness value is Null");
+ return -EINVAL;
+ }
+ if (HWC_DISPLAY_PRIMARY == display_id)
+ ret = hwc_display_[HWC_DISPLAY_PRIMARY]->CachePanelBrightness(*brightness_value);
+ hwc_procs_->invalidate(hwc_procs_);
+ break;
+ case kNoAction:
+ break;
+ default:
+ DLOGW("Invalid pending action = %d!", pending_action.action);
+ break;
+ }
+
+ // for display API getter case, marshall returned params into out_parcel.
+ output_parcel->writeInt32(ret);
+ HWCColorManager::MarshallStructIntoParcel(resp_payload, output_parcel);
+ req_payload.DestroyPayload();
+ resp_payload.DestroyPayload();
+
+ return (ret? -EINVAL : 0);
+}
+
+android::status_t HWCSession::OnMinHdcpEncryptionLevelChange(const android::Parcel *input_parcel,
+ android::Parcel *output_parcel) {
+ int ret = -EINVAL;
+ uint32_t display_id = UINT32(input_parcel->readInt32());
+ uint32_t min_enc_level = UINT32(input_parcel->readInt32());
+
+ DLOGI("Display %d", display_id);
+
+ if (display_id >= HWC_NUM_DISPLAY_TYPES) {
+ DLOGE("Invalid display_id");
+ } else if (display_id != HWC_DISPLAY_EXTERNAL) {
+ DLOGE("Not supported for display");
+ } else if (!hwc_display_[display_id]) {
+ DLOGW("Display is not connected");
+ } else {
+ ret = hwc_display_[display_id]->OnMinHdcpEncryptionLevelChange(min_enc_level);
+ }
+
+ output_parcel->writeInt32(ret);
+
+ return ret;
+}
+
+void* HWCSession::HWCUeventThread(void *context) {
+ if (context) {
+ return reinterpret_cast<HWCSession *>(context)->HWCUeventThreadHandler();
+ }
+
+ return NULL;
+}
+
+void* HWCSession::HWCUeventThreadHandler() {
+ static char uevent_data[PAGE_SIZE];
+ int length = 0;
+
+ uevent_locker_.Lock();
+ prctl(PR_SET_NAME, uevent_thread_name_, 0, 0, 0);
+ setpriority(PRIO_PROCESS, 0, HAL_PRIORITY_URGENT_DISPLAY);
+ if (!uevent_init()) {
+ DLOGE("Failed to init uevent");
+ pthread_exit(0);
+ uevent_locker_.Signal();
+ uevent_locker_.Unlock();
+ return NULL;
+ }
+
+ uevent_locker_.Signal();
+ uevent_locker_.Unlock();
+
+ while (!uevent_thread_exit_) {
+ // keep last 2 zeroes to ensure double 0 termination
+ length = uevent_next_event(uevent_data, INT32(sizeof(uevent_data)) - 2);
+
+ if (strcasestr(HWC_UEVENT_SWITCH_HDMI, uevent_data)) {
+ DLOGI("Uevent HDMI = %s", uevent_data);
+ int connected = GetEventValue(uevent_data, length, "SWITCH_STATE=");
+ if (connected >= 0) {
+ DLOGI("HDMI = %s", connected ? "connected" : "disconnected");
+ if (HotPlugHandler(connected) == -1) {
+ DLOGE("Failed handling Hotplug = %s", connected ? "connected" : "disconnected");
+ }
+ }
+ } else if (strcasestr(HWC_UEVENT_GRAPHICS_FB0, uevent_data)) {
+ DLOGI("Uevent FB0 = %s", uevent_data);
+ int panel_reset = GetEventValue(uevent_data, length, "PANEL_ALIVE=");
+ if (panel_reset == 0) {
+ if (hwc_procs_) {
+ reset_panel_ = true;
+ hwc_procs_->invalidate(hwc_procs_);
+ } else {
+ DLOGW("Ignore resetpanel - hwc_proc not registered");
+ }
+ }
+ }
+ }
+ pthread_exit(0);
+
+ return NULL;
+}
+
+int HWCSession::GetEventValue(const char *uevent_data, int length, const char *event_info) {
+ const char *iterator_str = uevent_data;
+ while (((iterator_str - uevent_data) <= length) && (*iterator_str)) {
+ const char *pstr = strstr(iterator_str, event_info);
+ if (pstr != NULL) {
+ return (atoi(iterator_str + strlen(event_info)));
+ }
+ iterator_str += strlen(iterator_str) + 1;
+ }
+
+ return -1;
+}
+
+void HWCSession::ResetPanel() {
+ int status = -EINVAL;
+
+ DLOGI("Powering off primary");
+ status = hwc_display_[HWC_DISPLAY_PRIMARY]->SetPowerMode(HWC_POWER_MODE_OFF);
+ if (status) {
+ DLOGE("power-off on primary failed with error = %d", status);
+ }
+
+ DLOGI("Restoring power mode on primary");
+ int32_t mode = INT(hwc_display_[HWC_DISPLAY_PRIMARY]->GetLastPowerMode());
+ status = hwc_display_[HWC_DISPLAY_PRIMARY]->SetPowerMode(mode);
+ if (status) {
+ DLOGE("Setting power mode = %d on primary failed with error = %d", mode, status);
+ }
+
+ status = hwc_display_[HWC_DISPLAY_PRIMARY]->EventControl(HWC_EVENT_VSYNC, 1);
+ if (status) {
+ DLOGE("enabling vsync failed for primary with error = %d", status);
+ }
+
+ reset_panel_ = false;
+}
+
+int HWCSession::HotPlugHandler(bool connected) {
+ int status = 0;
+ bool notify_hotplug = false;
+ bool refresh_screen = false;
+
+ // To prevent sending events to client while a lock is held, acquire scope locks only within
+ // below scope so that those get automatically unlocked after the scope ends.
+ {
+ SEQUENCE_WAIT_SCOPE_LOCK(locker_);
+
+ if (!hwc_display_[HWC_DISPLAY_PRIMARY]) {
+ DLOGE("Primay display is not connected.");
+ return -1;
+ }
+
+
+ HWCDisplay *primary_display = hwc_display_[HWC_DISPLAY_PRIMARY];
+ HWCDisplay *external_display = NULL;
+ HWCDisplay *null_display = NULL;
+
+ if (primary_display->GetDisplayClass() == DISPLAY_CLASS_EXTERNAL) {
+ external_display = static_cast<HWCDisplayExternal *>(hwc_display_[HWC_DISPLAY_PRIMARY]);
+ } else if (primary_display->GetDisplayClass() == DISPLAY_CLASS_NULL) {
+ null_display = static_cast<HWCDisplayNull *>(hwc_display_[HWC_DISPLAY_PRIMARY]);
+ }
+
+ // If primary display connected is a NULL display, then replace it with the external display
+ if (connected) {
+ // If we are in HDMI as primary and the primary display just got plugged in
+ if (is_hdmi_primary_ && null_display) {
+ uint32_t primary_width, primary_height;
+ int status = 0;
+ null_display->GetFrameBufferResolution(&primary_width, &primary_height);
+ delete null_display;
+ hwc_display_[HWC_DISPLAY_PRIMARY] = NULL;
+
+ // Create external display with a forced framebuffer resolution to that of what the NULL
+ // display had. This is necessary because SurfaceFlinger does not dynamically update
+ // framebuffer resolution once it reads it at bootup. So we always have to have the NULL
+ // display/external display both at the bootup resolution.
+ status = CreateExternalDisplay(HWC_DISPLAY_PRIMARY, primary_width, primary_height, true);
+ if (status) {
+ DLOGE("Could not create external display");
+ return -1;
+ }
+
+ status = hwc_display_[HWC_DISPLAY_PRIMARY]->SetPowerMode(HWC_POWER_MODE_NORMAL);
+ if (status) {
+ DLOGE("power-on on primary failed with error = %d", status);
+ }
+
+ is_hdmi_yuv_ = IsDisplayYUV(HWC_DISPLAY_PRIMARY);
+
+ // Next, go ahead and enable vsync on external display. This is expliclity required
+ // because in HDMI as primary case, SurfaceFlinger may not be aware of underlying
+ // changing display. and thus may not explicitly enable vsync
+
+ status = hwc_display_[HWC_DISPLAY_PRIMARY]->EventControl(HWC_EVENT_VSYNC, true);
+ if (status) {
+ DLOGE("Error enabling vsync for HDMI as primary case");
+ }
+ // Don't do hotplug notification for HDMI as primary case for now
+ notify_hotplug = false;
+ refresh_screen = true;
+ } else {
+ if (hwc_display_[HWC_DISPLAY_EXTERNAL]) {
+ DLOGE("HDMI is already connected");
+ return -1;
+ }
+
+ // Connect external display if virtual display is not connected.
+ // Else, defer external display connection and process it when virtual display
+ // tears down; Do not notify SurfaceFlinger since connection is deferred now.
+ if (!hwc_display_[HWC_DISPLAY_VIRTUAL]) {
+ status = ConnectDisplay(HWC_DISPLAY_EXTERNAL, NULL);
+ if (status) {
+ return status;
+ }
+ notify_hotplug = true;
+ } else {
+ DLOGI("Virtual display is connected, pending connection");
+ external_pending_connect_ = true;
+ }
+ }
+ } else {
+ // Do not return error if external display is not in connected status.
+ // Due to virtual display concurrency, external display connection might be still pending
+ // but hdmi got disconnected before pending connection could be processed.
+
+ if (is_hdmi_primary_ && external_display) {
+ uint32_t x_res, y_res;
+ external_display->GetFrameBufferResolution(&x_res, &y_res);
+ // Need to manually disable VSYNC as SF is not aware of connect/disconnect cases
+ // for HDMI as primary
+ external_display->EventControl(HWC_EVENT_VSYNC, false);
+ HWCDisplayExternal::Destroy(external_display);
+
+ HWCDisplayNull *null_display;
+
+ int status = HWCDisplayNull::Create(core_intf_, &hwc_procs_,
+ reinterpret_cast<HWCDisplay **>(&null_display));
+
+ if (status) {
+ DLOGE("Could not create Null display when primary got disconnected");
+ return -1;
+ }
+
+ null_display->SetResolution(x_res, y_res);
+ hwc_display_[HWC_DISPLAY_PRIMARY] = null_display;
+
+ // Don't do hotplug notification for HDMI as primary case for now
+ notify_hotplug = false;
+ } else {
+ if (hwc_display_[HWC_DISPLAY_EXTERNAL]) {
+ status = DisconnectDisplay(HWC_DISPLAY_EXTERNAL);
+ notify_hotplug = true;
+ }
+ external_pending_connect_ = false;
+ }
+ }
+ }
+
+ if (connected && (notify_hotplug || refresh_screen)) {
+ // trigger screen refresh to ensure sufficient resources are available to process new
+ // new display connection.
+ hwc_procs_->invalidate(hwc_procs_);
+ uint32_t vsync_period = UINT32(GetVsyncPeriod(HWC_DISPLAY_PRIMARY));
+ usleep(vsync_period * 2 / 1000);
+ }
+ // notify client
+ if (notify_hotplug) {
+ hwc_procs_->hotplug(hwc_procs_, HWC_DISPLAY_EXTERNAL, connected);
+ }
+
+ qservice_->onHdmiHotplug(INT(connected));
+
+ return 0;
+}
+
+void HWCSession::HandleSecureDisplaySession(hwc_display_contents_1_t **displays) {
+ secure_display_active_ = false;
+ if (!*displays) {
+ DLOGW("Invalid display contents");
+ return;
+ }
+
+ hwc_display_contents_1_t *content_list = displays[HWC_DISPLAY_PRIMARY];
+ if (!content_list) {
+ DLOGW("Invalid primary content list");
+ return;
+ }
+ size_t num_hw_layers = content_list->numHwLayers;
+
+ for (size_t i = 0; i < num_hw_layers - 1; i++) {
+ hwc_layer_1_t &hwc_layer = content_list->hwLayers[i];
+ const private_handle_t *pvt_handle = static_cast<const private_handle_t *>(hwc_layer.handle);
+ if (pvt_handle && pvt_handle->flags & private_handle_t::PRIV_FLAGS_SECURE_DISPLAY) {
+ secure_display_active_ = true;
+ }
+ }
+
+ // Force flush on primary during transitions(secure<->non secure)
+ // when external displays are connected.
+ bool force_flush = false;
+ if ((connected_displays_[HWC_DISPLAY_PRIMARY] == 1) &&
+ ((connected_displays_[HWC_DISPLAY_EXTERNAL] == 1) ||
+ (connected_displays_[HWC_DISPLAY_VIRTUAL] == 1))) {
+ force_flush = true;
+ }
+
+ for (ssize_t dpy = static_cast<ssize_t>(HWC_NUM_DISPLAY_TYPES - 1); dpy >= 0; dpy--) {
+ if (hwc_display_[dpy]) {
+ hwc_display_[dpy]->SetSecureDisplay(secure_display_active_, force_flush);
+ }
+ }
+}
+
+android::status_t HWCSession::GetVisibleDisplayRect(const android::Parcel *input_parcel,
+ android::Parcel *output_parcel) {
+ int dpy = input_parcel->readInt32();
+
+ if (dpy < HWC_DISPLAY_PRIMARY || dpy >= HWC_NUM_DISPLAY_TYPES) {
+ return android::BAD_VALUE;;
+ }
+
+ if (!hwc_display_[dpy]) {
+ return android::NO_INIT;
+ }
+
+ hwc_rect_t visible_rect = {0, 0, 0, 0};
+ int error = hwc_display_[dpy]->GetVisibleDisplayRect(&visible_rect);
+ if (error < 0) {
+ return error;
+ }
+
+ output_parcel->writeInt32(visible_rect.left);
+ output_parcel->writeInt32(visible_rect.top);
+ output_parcel->writeInt32(visible_rect.right);
+ output_parcel->writeInt32(visible_rect.bottom);
+
+ return android::NO_ERROR;
+}
+
+int HWCSession::CreateExternalDisplay(int disp, uint32_t primary_width, uint32_t primary_height,
+ bool use_primary_res) {
+ uint32_t panel_bpp = 0;
+ uint32_t pattern_type = 0;
+
+ if (qdutils::isDPConnected()) {
+ qdutils::getDPTestConfig(&panel_bpp, &pattern_type);
+ }
+
+ if (panel_bpp && pattern_type) {
+ return HWCDisplayExternalTest::Create(core_intf_, &hwc_procs_, qservice_, panel_bpp,
+ pattern_type, &hwc_display_[disp]);
+ }
+
+ return HWCDisplayExternal::Create(core_intf_, &hwc_procs_, primary_width, primary_height,
+ qservice_, use_primary_res, &hwc_display_[disp]);
+}
+
+} // namespace sdm
+
diff --git a/msm8909/sdm/libs/hwc/hwc_session.h b/msm8909/sdm/libs/hwc/hwc_session.h
new file mode 100644
index 00000000..1cd3e336
--- /dev/null
+++ b/msm8909/sdm/libs/hwc/hwc_session.h
@@ -0,0 +1,162 @@
+/*
+* Copyright (c) 2014 - 2017, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without modification, are permitted
+* provided that the following conditions are met:
+* * Redistributions of source code must retain the above copyright notice, this list of
+* conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright notice, this list of
+* conditions and the following disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its contributors may be used to
+* endorse or promote products derived from this software without specific prior written
+* permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __HWC_SESSION_H__
+#define __HWC_SESSION_H__
+
+#include <hardware/hwcomposer.h>
+#include <core/core_interface.h>
+#include <utils/locker.h>
+
+#include "hwc_display_primary.h"
+#include "hwc_display_external.h"
+#include "hwc_display_virtual.h"
+#include "hwc_color_manager.h"
+#include "hwc_socket_handler.h"
+
+namespace sdm {
+
+class HWCSession : hwc_composer_device_1_t, public qClient::BnQClient {
+ public:
+ struct HWCModuleMethods : public hw_module_methods_t {
+ HWCModuleMethods() {
+ hw_module_methods_t::open = HWCSession::Open;
+ }
+ };
+
+ explicit HWCSession(const hw_module_t *module);
+ int Init();
+ int Deinit();
+
+ private:
+ static const int kExternalConnectionTimeoutMs = 500;
+ static const int kPartialUpdateControlTimeoutMs = 100;
+
+ // hwc methods
+ static int Open(const hw_module_t *module, const char* name, hw_device_t **device);
+ static int Close(hw_device_t *device);
+ static int Prepare(hwc_composer_device_1 *device, size_t num_displays,
+ hwc_display_contents_1_t **displays);
+ static int Set(hwc_composer_device_1 *device, size_t num_displays,
+ hwc_display_contents_1_t **displays);
+ static int EventControl(hwc_composer_device_1 *device, int disp, int event, int enable);
+ static int SetPowerMode(hwc_composer_device_1 *device, int disp, int mode);
+ static int Query(hwc_composer_device_1 *device, int param, int *value);
+ static void RegisterProcs(hwc_composer_device_1 *device, hwc_procs_t const *procs);
+ static void Dump(hwc_composer_device_1 *device, char *buffer, int length);
+ // These config functions always return FB params, the actual display params may differ.
+ static int GetDisplayConfigs(hwc_composer_device_1 *device, int disp, uint32_t *configs,
+ size_t *numConfigs);
+ static int GetDisplayAttributes(hwc_composer_device_1 *device, int disp, uint32_t config,
+ const uint32_t *display_attributes, int32_t *values);
+ static int GetActiveConfig(hwc_composer_device_1 *device, int disp);
+ static int SetActiveConfig(hwc_composer_device_1 *device, int disp, int index);
+ static int SetCursorPositionAsync(hwc_composer_device_1 *device, int disp, int x, int y);
+ static void CloseAcquireFds(hwc_display_contents_1_t *content_list);
+ bool IsDisplayYUV(int disp);
+
+ // Uevent thread
+ static void* HWCUeventThread(void *context);
+ void* HWCUeventThreadHandler();
+ int GetEventValue(const char *uevent_data, int length, const char *event_info);
+ int HotPlugHandler(bool connected);
+ void ResetPanel();
+ int ConnectDisplay(int disp, hwc_display_contents_1_t *content_list);
+ int DisconnectDisplay(int disp);
+ void HandleSecureDisplaySession(hwc_display_contents_1_t **displays);
+ int GetVsyncPeriod(int disp);
+ int CreateExternalDisplay(int disp, uint32_t primary_width, uint32_t primary_height,
+ bool use_primary_res);
+
+ // QClient methods
+ virtual android::status_t notifyCallback(uint32_t command, const android::Parcel *input_parcel,
+ android::Parcel *output_parcel);
+ void DynamicDebug(const android::Parcel *input_parcel);
+ void SetFrameDumpConfig(const android::Parcel *input_parcel);
+ android::status_t SetMaxMixerStages(const android::Parcel *input_parcel);
+ android::status_t SetDisplayMode(const android::Parcel *input_parcel);
+ android::status_t SetSecondaryDisplayStatus(const android::Parcel *input_parcel,
+ android::Parcel *output_parcel);
+ android::status_t ToggleScreenUpdates(const android::Parcel *input_parcel,
+ android::Parcel *output_parcel);
+ android::status_t ConfigureRefreshRate(const android::Parcel *input_parcel);
+ android::status_t QdcmCMDHandler(const android::Parcel *input_parcel,
+ android::Parcel *output_parcel);
+ android::status_t ControlPartialUpdate(const android::Parcel *input_parcel, android::Parcel *out);
+ android::status_t OnMinHdcpEncryptionLevelChange(const android::Parcel *input_parcel,
+ android::Parcel *output_parcel);
+ android::status_t SetPanelBrightness(const android::Parcel *input_parcel,
+ android::Parcel *output_parcel);
+ android::status_t GetPanelBrightness(const android::Parcel *input_parcel,
+ android::Parcel *output_parcel);
+ // These functions return the actual display config info as opposed to FB
+ android::status_t HandleSetActiveDisplayConfig(const android::Parcel *input_parcel,
+ android::Parcel *output_parcel);
+ android::status_t HandleGetActiveDisplayConfig(const android::Parcel *input_parcel,
+ android::Parcel *output_parcel);
+ android::status_t HandleGetDisplayConfigCount(const android::Parcel *input_parcel,
+ android::Parcel *output_parcel);
+ android::status_t HandleGetDisplayAttributesForConfig(const android::Parcel *input_parcel,
+ android::Parcel *output_parcel);
+ android::status_t GetVisibleDisplayRect(const android::Parcel *input_parcel,
+ android::Parcel *output_parcel);
+
+ android::status_t SetDynamicBWForCamera(const android::Parcel *input_parcel,
+ android::Parcel *output_parcel);
+ android::status_t GetBWTransactionStatus(const android::Parcel *input_parcel,
+ android::Parcel *output_parcel);
+ android::status_t SetMixerResolution(const android::Parcel *input_parcel);
+ android::status_t SetDisplayPort(DisplayPort sdm_disp_port, int *hwc_disp_port);
+ android::status_t GetHdrCapabilities(const android::Parcel *input_parcel,
+ android::Parcel *output_parcel);
+
+ static Locker locker_;
+ CoreInterface *core_intf_ = NULL;
+ hwc_procs_t hwc_procs_default_;
+ hwc_procs_t const *hwc_procs_ = &hwc_procs_default_;
+ HWCDisplay *hwc_display_[HWC_NUM_DISPLAY_TYPES] = { NULL };
+ pthread_t uevent_thread_;
+ bool uevent_thread_exit_ = false;
+ const char *uevent_thread_name_ = "HWC_UeventThread";
+ HWCBufferAllocator buffer_allocator_;
+ HWCBufferSyncHandler buffer_sync_handler_;
+ HWCColorManager *color_mgr_ = NULL;
+ bool reset_panel_ = false;
+ bool secure_display_active_ = false;
+ bool external_pending_connect_ = false;
+ bool new_bw_mode_ = false;
+ bool need_invalidate_ = false;
+ int bw_mode_release_fd_ = -1;
+ qService::QService *qservice_ = NULL;
+ bool is_hdmi_primary_ = false;
+ bool is_hdmi_yuv_ = false;
+ std::bitset<HWC_NUM_DISPLAY_TYPES> connected_displays_; // Bit mask of connected displays
+ HWCSocketHandler socket_handler_;
+ Locker uevent_locker_;
+};
+
+} // namespace sdm
+
+#endif // __HWC_SESSION_H__
+
diff --git a/msm8909/sdm/libs/hwc/hwc_socket_handler.cpp b/msm8909/sdm/libs/hwc/hwc_socket_handler.cpp
new file mode 100644
index 00000000..7ebaab48
--- /dev/null
+++ b/msm8909/sdm/libs/hwc/hwc_socket_handler.cpp
@@ -0,0 +1,48 @@
+/*
+* Copyright (c) 2016, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <cutils/sockets.h>
+#include "hwc_socket_handler.h"
+
+#define __CLASS__ "HWCSocketHandler"
+
+#define DPPS_SOCKET "pps"
+
+namespace sdm {
+
+int HWCSocketHandler::GetSocketFd(SocketType socket_type) {
+ switch (socket_type) {
+ case kDpps:
+ return socket_local_client(DPPS_SOCKET, ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM);
+ default:
+ return -1;
+ }
+}
+
+} // namespace sdm
diff --git a/msm8909/sdm/libs/hwc/hwc_socket_handler.h b/msm8909/sdm/libs/hwc/hwc_socket_handler.h
new file mode 100644
index 00000000..5b2292a2
--- /dev/null
+++ b/msm8909/sdm/libs/hwc/hwc_socket_handler.h
@@ -0,0 +1,47 @@
+/*
+* Copyright (c) 2016, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#ifndef __HWC_SOCKET_HANDLER_H__
+#define __HWC_SOCKET_HANDLER_H__
+
+#include <core/socket_handler.h>
+
+namespace sdm {
+
+class HWCSocketHandler : public SocketHandler {
+ public:
+ HWCSocketHandler() { }
+
+ virtual int GetSocketFd(SocketType socket_type);
+};
+
+} // namespace sdm
+
+#endif // __HWC_SOCKET_HANDLER_H__
diff --git a/msm8909/sdm/libs/hwc/hwc_tonemapper.cpp b/msm8909/sdm/libs/hwc/hwc_tonemapper.cpp
new file mode 100644
index 00000000..c09ff9e2
--- /dev/null
+++ b/msm8909/sdm/libs/hwc/hwc_tonemapper.cpp
@@ -0,0 +1,341 @@
+/*
+* Copyright (c) 2016 - 2017, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <alloc_controller.h>
+#include <gr.h>
+#include <gralloc_priv.h>
+#include <memalloc.h>
+#include <sync/sync.h>
+
+#include <TonemapFactory.h>
+
+#include <core/buffer_allocator.h>
+
+#include <utils/constants.h>
+#include <utils/debug.h>
+#include <utils/formats.h>
+#include <utils/rect.h>
+#include <utils/utils.h>
+
+#include <vector>
+
+#include "hwc_debugger.h"
+#include "hwc_tonemapper.h"
+
+#define __CLASS__ "HWCToneMapper"
+
+namespace sdm {
+
+ToneMapSession::~ToneMapSession() {
+ delete gpu_tone_mapper_;
+ gpu_tone_mapper_ = NULL;
+ FreeIntermediateBuffers();
+}
+
+DisplayError ToneMapSession::AllocateIntermediateBuffers(int w, int h, int format, int usage) {
+ for (uint8_t i = 0; i < kNumIntermediateBuffers; i++) {
+ int status = alloc_buffer(&intermediate_buffer_[i], w, h, format, usage);
+ if (status < 0) {
+ FreeIntermediateBuffers();
+ return kErrorMemory;
+ }
+ }
+
+ return kErrorNone;
+}
+
+void ToneMapSession::FreeIntermediateBuffers() {
+ for (uint8_t i = 0; i < kNumIntermediateBuffers; i++) {
+ private_handle_t *buffer = intermediate_buffer_[i];
+ if (buffer) {
+ // Free the valid fence
+ if (release_fence_fd_[i] >= 0) {
+ CloseFd(&release_fence_fd_[i]);
+ }
+ free_buffer(buffer);
+ intermediate_buffer_[i] = NULL;
+ }
+ }
+}
+
+void ToneMapSession::UpdateBuffer(int acquire_fence, LayerBuffer *buffer) {
+ // Acquire fence will be closed by HWC Display.
+ // Fence returned by GPU will be closed in PostCommit.
+ buffer->acquire_fence_fd = acquire_fence;
+ buffer->size = intermediate_buffer_[current_buffer_index_]->size;
+ buffer->planes[0].fd = intermediate_buffer_[current_buffer_index_]->fd;
+}
+
+void ToneMapSession::SetReleaseFence(int fd) {
+ CloseFd(&release_fence_fd_[current_buffer_index_]);
+ // Used to give to GPU tonemapper along with input layer fd
+ release_fence_fd_[current_buffer_index_] = dup(fd);
+}
+
+void ToneMapSession::SetToneMapConfig(Layer *layer) {
+ // HDR -> SDR is FORWARD and SDR - > HDR is INVERSE
+ tone_map_config_.type = layer->input_buffer.flags.hdr ? TONEMAP_FORWARD : TONEMAP_INVERSE;
+ tone_map_config_.colorPrimaries = layer->input_buffer.color_metadata.colorPrimaries;
+ tone_map_config_.transfer = layer->input_buffer.color_metadata.transfer;
+ tone_map_config_.secure = layer->request.flags.secure;
+ tone_map_config_.format = layer->request.format;
+}
+
+bool ToneMapSession::IsSameToneMapConfig(Layer *layer) {
+ LayerBuffer& buffer = layer->input_buffer;
+ private_handle_t *handle = intermediate_buffer_[0];
+ int tonemap_type = buffer.flags.hdr ? TONEMAP_FORWARD : TONEMAP_INVERSE;
+
+ return ((tonemap_type == tone_map_config_.type) &&
+ (buffer.color_metadata.colorPrimaries == tone_map_config_.colorPrimaries) &&
+ (buffer.color_metadata.transfer == tone_map_config_.transfer) &&
+ (layer->request.flags.secure == tone_map_config_.secure) &&
+ (layer->request.format == tone_map_config_.format) &&
+ (layer->request.width == UINT32(handle->unaligned_width)) &&
+ (layer->request.height == UINT32(handle->unaligned_height)));
+}
+
+int HWCToneMapper::HandleToneMap(hwc_display_contents_1_t *content_list, LayerStack *layer_stack) {
+ uint32_t gpu_count = 0;
+ DisplayError error = kErrorNone;
+
+ for (uint32_t i = 0; i < layer_stack->layers.size(); i++) {
+ uint32_t session_index = 0;
+ Layer *layer = layer_stack->layers.at(i);
+ if (layer->composition == kCompositionGPU) {
+ gpu_count++;
+ }
+
+ if (layer->request.flags.tone_map) {
+ switch (layer->composition) {
+ case kCompositionGPUTarget:
+ if (!gpu_count) {
+ // When all layers are on FrameBuffer and if they do not update in the next draw cycle,
+ // then SDM marks them for SDE Composition because the cached FB layer gets displayed.
+ // GPU count will be 0 in this case. Try to use the existing tone-mapped frame buffer.
+ // No ToneMap/Blit is required. Just update the buffer & acquire fence fd of FB layer.
+ if (!tone_map_sessions_.empty()) {
+ ToneMapSession *fb_tone_map_session = tone_map_sessions_.at(fb_session_index_);
+ fb_tone_map_session->UpdateBuffer(-1 /* acquire_fence */, &layer->input_buffer);
+ fb_tone_map_session->layer_index_ = INT(i);
+ fb_tone_map_session->acquired_ = true;
+ return 0;
+ }
+ }
+ error = AcquireToneMapSession(layer, &session_index);
+ fb_session_index_ = session_index;
+ break;
+ default:
+ error = AcquireToneMapSession(layer, &session_index);
+ break;
+ }
+
+ if (error != kErrorNone) {
+ Terminate();
+ return -1;
+ }
+
+ ToneMapSession *session = tone_map_sessions_.at(session_index);
+ ToneMap(&content_list->hwLayers[i], layer, session);
+ session->layer_index_ = INT(i);
+ }
+ }
+
+ return 0;
+}
+
+void HWCToneMapper::ToneMap(hwc_layer_1_t *hwc_layer, Layer* layer, ToneMapSession *session) {
+ int fence_fd = -1;
+ int acquire_fd = -1;
+ int merged_fd = -1;
+
+ uint8_t buffer_index = session->current_buffer_index_;
+ const private_handle_t *dst_hnd = session->intermediate_buffer_[buffer_index];
+ const private_handle_t *src_hnd = static_cast<const private_handle_t *>(hwc_layer->handle);
+
+ acquire_fd = dup(layer->input_buffer.acquire_fence_fd);
+ buffer_sync_handler_.SyncMerge(session->release_fence_fd_[buffer_index], acquire_fd, &merged_fd);
+
+ if (acquire_fd >= 0) {
+ CloseFd(&acquire_fd);
+ }
+
+ if (session->release_fence_fd_[buffer_index] >= 0) {
+ CloseFd(&session->release_fence_fd_[buffer_index]);
+ }
+
+ DTRACE_BEGIN("GPU_TM_BLIT");
+ fence_fd = session->gpu_tone_mapper_->blit(reinterpret_cast<const void *>(dst_hnd),
+ reinterpret_cast<const void *>(src_hnd), merged_fd);
+ DTRACE_END();
+
+ DumpToneMapOutput(session, &fence_fd);
+ session->UpdateBuffer(fence_fd, &layer->input_buffer);
+}
+
+void HWCToneMapper::PostCommit(LayerStack *layer_stack) {
+ auto it = tone_map_sessions_.begin();
+ while (it != tone_map_sessions_.end()) {
+ uint32_t session_index = UINT32(std::distance(tone_map_sessions_.begin(), it));
+ ToneMapSession *session = tone_map_sessions_.at(session_index);
+ Layer *layer = layer_stack->layers.at(UINT32(session->layer_index_));
+ if (session->acquired_) {
+ // Close the fd returned by GPU ToneMapper and set release fence.
+ LayerBuffer &layer_buffer = layer->input_buffer;
+ CloseFd(&layer_buffer.acquire_fence_fd);
+ session->SetReleaseFence(layer_buffer.release_fence_fd);
+ session->acquired_ = false;
+ it++;
+ } else {
+ delete session;
+ it = tone_map_sessions_.erase(it);
+ }
+ }
+}
+
+void HWCToneMapper::Terminate() {
+ if (tone_map_sessions_.size()) {
+ while (!tone_map_sessions_.empty()) {
+ delete tone_map_sessions_.back();
+ tone_map_sessions_.pop_back();
+ }
+ fb_session_index_ = 0;
+ }
+}
+
+void HWCToneMapper::SetFrameDumpConfig(uint32_t count) {
+ DLOGI("Dump FrameConfig count = %d", count);
+ dump_frame_count_ = count;
+ dump_frame_index_ = 0;
+}
+
+void HWCToneMapper::DumpToneMapOutput(ToneMapSession *session, int *acquire_fd) {
+ if (!dump_frame_count_) {
+ return;
+ }
+
+ private_handle_t *target_buffer = session->intermediate_buffer_[session->current_buffer_index_];
+
+ if (*acquire_fd >= 0) {
+ int error = sync_wait(*acquire_fd, 1000);
+ if (error < 0) {
+ DLOGW("sync_wait error errno = %d, desc = %s", errno, strerror(errno));
+ return;
+ }
+ }
+
+ size_t result = 0;
+ char dump_file_name[PATH_MAX];
+ snprintf(dump_file_name, sizeof(dump_file_name), "/data/misc/display/frame_dump_primary"
+ "/tonemap_%dx%d_frame%d.raw", target_buffer->width, target_buffer->height,
+ dump_frame_index_);
+
+ FILE* fp = fopen(dump_file_name, "w+");
+ if (fp) {
+ DLOGI("base addr = %x", target_buffer->base);
+ result = fwrite(reinterpret_cast<void *>(target_buffer->base), target_buffer->size, 1, fp);
+ fclose(fp);
+ }
+ dump_frame_count_--;
+ dump_frame_index_++;
+ CloseFd(acquire_fd);
+}
+
+DisplayError HWCToneMapper::AcquireToneMapSession(Layer *layer, uint32_t *session_index) {
+ Color10Bit *grid_entries = NULL;
+ int grid_size = 0;
+
+ if (layer->lut_3d.validGridEntries) {
+ grid_entries = layer->lut_3d.gridEntries;
+ grid_size = INT(layer->lut_3d.gridSize);
+ }
+
+ // When the property sdm.disable_hdr_lut_gen is set, the lutEntries and gridEntries in
+ // the Lut3d will be NULL, clients needs to allocate the memory and set correct 3D Lut
+ // for Tonemapping.
+ if (!layer->lut_3d.lutEntries || !layer->lut_3d.dim) {
+ // Atleast lutEntries must be valid for GPU Tonemapper.
+ DLOGE("Invalid Lut Entries or lut dimension = %d", layer->lut_3d.dim);
+ return kErrorParameters;
+ }
+
+ // Check if we can re-use an existing tone map session.
+ for (uint32_t i = 0; i < tone_map_sessions_.size(); i++) {
+ ToneMapSession *tonemap_session = tone_map_sessions_.at(i);
+ if (!tonemap_session->acquired_ && tonemap_session->IsSameToneMapConfig(layer)) {
+ tonemap_session->current_buffer_index_ = (tonemap_session->current_buffer_index_ + 1) %
+ ToneMapSession::kNumIntermediateBuffers;
+ tonemap_session->acquired_ = true;
+ *session_index = i;
+ return kErrorNone;
+ }
+ }
+
+ ToneMapSession *session = new ToneMapSession();
+
+ session->SetToneMapConfig(layer);
+ session->gpu_tone_mapper_ = TonemapperFactory_GetInstance(session->tone_map_config_.type,
+ layer->lut_3d.lutEntries,
+ layer->lut_3d.dim,
+ grid_entries, grid_size,
+ session->tone_map_config_.secure);
+
+ if (session->gpu_tone_mapper_ == NULL) {
+ DLOGE("Get Tonemapper failed!");
+ delete session;
+ return kErrorNotSupported;
+ }
+
+ int status, format;
+ DisplayError error = kErrorNone;
+ int usage = INT(GRALLOC_USAGE_PRIVATE_IOMMU_HEAP | GRALLOC_USAGE_HW_TEXTURE);
+
+ if (layer->request.flags.secure) {
+ usage = INT(GRALLOC_USAGE_PRIVATE_MM_HEAP);
+ usage |= INT(GRALLOC_USAGE_PROTECTED);
+ }
+
+ status = buffer_allocator_.SetBufferInfo(layer->request.format, &format, &usage);
+ error = session->AllocateIntermediateBuffers(INT(layer->request.width),
+ INT(layer->request.height), format, usage);
+
+ if (error != kErrorNone) {
+ DLOGE("Allocation of Intermediate Buffers failed!");
+ delete session;
+ return error;
+ }
+
+ session->acquired_ = true;
+ tone_map_sessions_.push_back(session);
+ *session_index = UINT32(tone_map_sessions_.size() - 1);
+
+ return kErrorNone;
+}
+
+} // namespace sdm
diff --git a/msm8909/sdm/libs/hwc/hwc_tonemapper.h b/msm8909/sdm/libs/hwc/hwc_tonemapper.h
new file mode 100644
index 00000000..0a463fe3
--- /dev/null
+++ b/msm8909/sdm/libs/hwc/hwc_tonemapper.h
@@ -0,0 +1,101 @@
+/*
+* Copyright (c) 2016 - 2017, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __HWC_TONEMAPPER_H__
+#define __HWC_TONEMAPPER_H__
+
+#include <fcntl.h>
+#include <sys/mman.h>
+
+#include <hardware/hwcomposer.h>
+
+#include <core/layer_stack.h>
+#include <utils/sys.h>
+#include <vector>
+#include "hwc_buffer_sync_handler.h"
+#include "hwc_buffer_allocator.h"
+
+class Tonemapper;
+
+namespace sdm {
+
+struct ToneMapConfig {
+ int type = 0;
+ ColorPrimaries colorPrimaries = ColorPrimaries_Max;
+ GammaTransfer transfer = Transfer_Max;
+ LayerBufferFormat format = kFormatRGBA8888;
+ bool secure = false;
+};
+
+class ToneMapSession {
+ public:
+ ~ToneMapSession();
+ DisplayError AllocateIntermediateBuffers(int width, int height, int format, int usage);
+ void FreeIntermediateBuffers();
+ void UpdateBuffer(int acquire_fence, LayerBuffer *buffer);
+ void SetReleaseFence(int fd);
+ void SetToneMapConfig(Layer *layer);
+ bool IsSameToneMapConfig(Layer *layer);
+
+ static const uint8_t kNumIntermediateBuffers = 2;
+ Tonemapper *gpu_tone_mapper_ = NULL;
+ ToneMapConfig tone_map_config_ = {};
+ uint8_t current_buffer_index_ = 0;
+ private_handle_t *intermediate_buffer_[kNumIntermediateBuffers] = {NULL, NULL};
+ int release_fence_fd_[kNumIntermediateBuffers] = {-1, -1};
+ bool acquired_ = false;
+ int layer_index_ = -1;
+};
+
+class HWCToneMapper {
+ public:
+ HWCToneMapper() {}
+ ~HWCToneMapper() {}
+
+ int HandleToneMap(hwc_display_contents_1_t *content_list, LayerStack *layer_stack);
+ bool IsActive() { return !tone_map_sessions_.empty(); }
+ void PostCommit(LayerStack *layer_stack);
+ void SetFrameDumpConfig(uint32_t count);
+ void Terminate();
+
+ private:
+ void ToneMap(hwc_layer_1_t *hwc_layer, Layer *layer, ToneMapSession *session);
+ DisplayError AcquireToneMapSession(Layer *layer, uint32_t *session_index);
+ void DumpToneMapOutput(ToneMapSession *session, int *acquire_fence);
+
+ std::vector<ToneMapSession*> tone_map_sessions_;
+ HWCBufferSyncHandler buffer_sync_handler_ = {};
+ HWCBufferAllocator buffer_allocator_ = {};
+ uint32_t dump_frame_count_ = 0;
+ uint32_t dump_frame_index_ = 0;
+ uint32_t fb_session_index_ = 0;
+};
+
+} // namespace sdm
+#endif // __HWC_TONEMAPPER_H__
diff --git a/msm8909/sdm/libs/hwc2/Android.mk b/msm8909/sdm/libs/hwc2/Android.mk
new file mode 100644
index 00000000..2d03c130
--- /dev/null
+++ b/msm8909/sdm/libs/hwc2/Android.mk
@@ -0,0 +1,67 @@
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+include $(LOCAL_PATH)/../../../common.mk
+
+ifeq ($(use_hwc2),true)
+
+LOCAL_MODULE := hwcomposer.$(TARGET_BOARD_PLATFORM)
+LOCAL_VENDOR_MODULE := true
+LOCAL_MODULE_RELATIVE_PATH := hw
+LOCAL_MODULE_TAGS := optional
+LOCAL_C_INCLUDES := $(common_includes)
+LOCAL_HEADER_LIBRARIES := display_headers
+
+LOCAL_CFLAGS := -Wno-missing-field-initializers -Wno-unused-parameter \
+ -std=c++11 -fcolor-diagnostics\
+ -DLOG_TAG=\"SDM\" $(common_flags) \
+ -I $(display_top)/sdm/libs/hwc
+ifeq ($(TARGET_EXCLUDES_DISPLAY_PP), true)
+LOCAL_CFLAGS += -DEXCLUDE_DISPLAY_PP
+endif
+
+LOCAL_CLANG := true
+
+# TODO: Remove libui after addressing gpu_tonemapper issues
+LOCAL_SHARED_LIBRARIES := libsdmcore libqservice libbinder libhardware libhardware_legacy \
+ libutils libcutils libsync libqdutils libqdMetaData libdl libdrmutils \
+ libsdmutils libc++ liblog libgrallocutils libdl \
+ vendor.display.config@1.0 libhidlbase libhidltransport \
+ libui libgpu_tonemapper
+
+ifneq ($(TARGET_USES_GRALLOC1), true)
+ LOCAL_SHARED_LIBRARIES += libmemalloc
+endif
+
+ifeq ($(display_config_version), DISPLAY_CONFIG_1_1)
+LOCAL_SHARED_LIBRARIES += vendor.display.config@1.1
+endif
+
+LOCAL_SRC_FILES := hwc_session.cpp \
+ hwc_session_services.cpp \
+ hwc_display.cpp \
+ hwc_display_primary.cpp \
+ hwc_display_external.cpp \
+ hwc_display_virtual.cpp \
+ ../hwc/hwc_debugger.cpp \
+ ../hwc/hwc_buffer_sync_handler.cpp \
+ hwc_color_manager.cpp \
+ hwc_layers.cpp \
+ hwc_callbacks.cpp \
+ ../hwc/cpuhint.cpp \
+ ../hwc/hwc_socket_handler.cpp \
+ display_null.cpp \
+ hwc_tonemapper.cpp \
+ hwc_display_external_test.cpp
+
+ifneq ($(TARGET_USES_GRALLOC1), true)
+ LOCAL_SRC_FILES += ../hwc/hwc_buffer_allocator.cpp
+else
+ LOCAL_SRC_FILES += hwc_buffer_allocator.cpp
+endif
+
+ifeq ($(TARGET_HAS_WIDE_COLOR_DISPLAY), true)
+ LOCAL_CFLAGS += -DFEATURE_WIDE_COLOR
+endif
+
+include $(BUILD_SHARED_LIBRARY)
+endif
diff --git a/msm8909/sdm/libs/hwc2/display_null.cpp b/msm8909/sdm/libs/hwc2/display_null.cpp
new file mode 100644
index 00000000..16f4da66
--- /dev/null
+++ b/msm8909/sdm/libs/hwc2/display_null.cpp
@@ -0,0 +1,68 @@
+/*
+* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "display_null.h"
+
+#define __CLASS__ "DisplayNull"
+
+namespace sdm {
+
+DisplayError DisplayNull::Commit(LayerStack *layer_stack) {
+ for (Layer *layer : layer_stack->layers) {
+ if (layer->composition != kCompositionGPUTarget) {
+ layer->composition = kCompositionSDE;
+ layer->input_buffer.release_fence_fd = -1;
+ }
+ }
+ layer_stack->retire_fence_fd = -1;
+
+ return kErrorNone;
+}
+
+DisplayError DisplayNull::GetDisplayState(DisplayState *state) {
+ *state = state_;
+ return kErrorNone;
+}
+
+DisplayError DisplayNull::SetDisplayState(DisplayState state) {
+ state_ = state;
+ return kErrorNone;
+}
+
+DisplayError DisplayNull::SetFrameBufferConfig(const DisplayConfigVariableInfo &variable_info) {
+ fb_config_ = variable_info;
+ return kErrorNone;
+}
+
+DisplayError DisplayNull::GetFrameBufferConfig(DisplayConfigVariableInfo *variable_info) {
+ *variable_info = fb_config_;
+ return kErrorNone;
+}
+
+} // namespace sdm
diff --git a/msm8909/sdm/libs/hwc2/display_null.h b/msm8909/sdm/libs/hwc2/display_null.h
new file mode 100644
index 00000000..c2db54e1
--- /dev/null
+++ b/msm8909/sdm/libs/hwc2/display_null.h
@@ -0,0 +1,110 @@
+/*
+* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __DISPLAY_NULL_H__
+#define __DISPLAY_NULL_H__
+
+#include <core/display_interface.h>
+#include <string>
+#include <vector>
+
+namespace sdm {
+
+#define MAKE_NO_OP(virtual_method_name) \
+ virtual DisplayError virtual_method_name { return kErrorNone; }
+
+class DisplayNull : public DisplayInterface {
+ public:
+ virtual ~DisplayNull() { }
+ virtual DisplayError Commit(LayerStack *layer_stack);
+ virtual DisplayError GetDisplayState(DisplayState *state);
+ virtual DisplayError SetDisplayState(DisplayState state);
+ virtual DisplayError SetFrameBufferConfig(const DisplayConfigVariableInfo &variable_info);
+ virtual DisplayError GetFrameBufferConfig(DisplayConfigVariableInfo *variable_info);
+ virtual bool IsUnderscanSupported() { return true; }
+ virtual void SetIdleTimeoutMs(uint32_t active_ms) { }
+ virtual bool IsPrimaryDisplay() { return true; }
+
+ void SetActive(bool active) {
+ active_ = active;
+ }
+
+ bool IsActive() {
+ return active_;
+ }
+
+ MAKE_NO_OP(Prepare(LayerStack *))
+ MAKE_NO_OP(Flush())
+ MAKE_NO_OP(GetNumVariableInfoConfigs(uint32_t *))
+ MAKE_NO_OP(GetConfig(uint32_t, DisplayConfigVariableInfo *))
+ MAKE_NO_OP(GetConfig(DisplayConfigFixedInfo *))
+ MAKE_NO_OP(GetActiveConfig(uint32_t *))
+ MAKE_NO_OP(GetVSyncState(bool *))
+ MAKE_NO_OP(SetActiveConfig(uint32_t))
+ MAKE_NO_OP(SetActiveConfig(DisplayConfigVariableInfo *))
+ MAKE_NO_OP(SetMaxMixerStages(uint32_t))
+ MAKE_NO_OP(ControlPartialUpdate(bool, uint32_t *))
+ MAKE_NO_OP(DisablePartialUpdateOneFrame())
+ MAKE_NO_OP(SetDisplayMode(uint32_t))
+ MAKE_NO_OP(SetPanelBrightness(int))
+ MAKE_NO_OP(CachePanelBrightness(int))
+ MAKE_NO_OP(OnMinHdcpEncryptionLevelChange(uint32_t))
+ MAKE_NO_OP(ColorSVCRequestRoute(const PPDisplayAPIPayload &, PPDisplayAPIPayload *,
+ PPPendingParams *))
+ MAKE_NO_OP(GetColorModeCount(uint32_t *))
+ MAKE_NO_OP(GetColorModes(uint32_t *, std::vector<std::string> *))
+ MAKE_NO_OP(GetColorModeAttr(const std::string &, AttrVal *))
+ MAKE_NO_OP(SetColorMode(const std::string &))
+ MAKE_NO_OP(SetColorModeById(int32_t))
+ MAKE_NO_OP(SetColorTransform(const uint32_t, const double *))
+ MAKE_NO_OP(GetDefaultColorMode(std::string *))
+ MAKE_NO_OP(ApplyDefaultDisplayMode())
+ MAKE_NO_OP(SetCursorPosition(int, int))
+ MAKE_NO_OP(GetRefreshRateRange(uint32_t *, uint32_t *))
+ MAKE_NO_OP(SetRefreshRate(uint32_t))
+ MAKE_NO_OP(GetPanelBrightness(int *))
+ MAKE_NO_OP(SetVSyncState(bool))
+ MAKE_NO_OP(SetMixerResolution(uint32_t, uint32_t))
+ MAKE_NO_OP(GetMixerResolution(uint32_t *, uint32_t *))
+ MAKE_NO_OP(SetDetailEnhancerData(const DisplayDetailEnhancerData &))
+ MAKE_NO_OP(GetDisplayPort(DisplayPort *))
+ MAKE_NO_OP(SetCompositionState(LayerComposition, bool))
+ MAKE_NO_OP(GetClientTargetSupport(uint32_t, uint32_t, LayerBufferFormat,
+ const ColorMetaData &))
+ std::string Dump() { return ""; }
+
+ private:
+ bool active_ = false;
+ DisplayState state_ = kStateOff;
+ DisplayConfigVariableInfo fb_config_ = {};
+};
+
+} // namespace sdm
+
+#endif // __DISPLAY_NULL_H__
diff --git a/msm8909/sdm/libs/hwc2/hwc_buffer_allocator.cpp b/msm8909/sdm/libs/hwc2/hwc_buffer_allocator.cpp
new file mode 100644
index 00000000..a1796630
--- /dev/null
+++ b/msm8909/sdm/libs/hwc2/hwc_buffer_allocator.cpp
@@ -0,0 +1,409 @@
+/*
+* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <gralloc_priv.h>
+
+#include <core/buffer_allocator.h>
+#include <utils/constants.h>
+#include <utils/debug.h>
+
+#include "hwc_buffer_allocator.h"
+#include "hwc_debugger.h"
+#include "gr_utils.h"
+
+#define __CLASS__ "HWCBufferAllocator"
+
+namespace sdm {
+
+DisplayError HWCBufferAllocator::Init() {
+ int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module_);
+ if (err != 0) {
+ DLOGE("FATAL: can not get GRALLOC module");
+ return kErrorResources;
+ }
+
+ err = gralloc1_open(module_, &gralloc_device_);
+ if (err != 0) {
+ DLOGE("FATAL: can not open GRALLOC device");
+ return kErrorResources;
+ }
+
+ if (gralloc_device_ == nullptr) {
+ DLOGE("FATAL: gralloc device is null");
+ return kErrorResources;
+ }
+
+ ReleaseBuffer_ = reinterpret_cast<GRALLOC1_PFN_RELEASE>(
+ gralloc_device_->getFunction(gralloc_device_, GRALLOC1_FUNCTION_RELEASE));
+ Perform_ = reinterpret_cast<GRALLOC1_PFN_PERFORM>(
+ gralloc_device_->getFunction(gralloc_device_, GRALLOC1_FUNCTION_PERFORM));
+ Lock_ = reinterpret_cast<GRALLOC1_PFN_LOCK>(
+ gralloc_device_->getFunction(gralloc_device_, GRALLOC1_FUNCTION_LOCK));
+ Unlock_ = reinterpret_cast<GRALLOC1_PFN_UNLOCK>(
+ gralloc_device_->getFunction(gralloc_device_, GRALLOC1_FUNCTION_UNLOCK));
+
+ return kErrorNone;
+}
+
+DisplayError HWCBufferAllocator::Deinit() {
+ if (gralloc_device_ != nullptr) {
+ int err = gralloc1_close(gralloc_device_);
+ if (err != 0) {
+ DLOGE("FATAL: can not close GRALLOC device");
+ return kErrorResources;
+ }
+ }
+ return kErrorNone;
+}
+
+DisplayError HWCBufferAllocator::AllocateBuffer(BufferInfo *buffer_info) {
+ const BufferConfig &buffer_config = buffer_info->buffer_config;
+ AllocatedBufferInfo *alloc_buffer_info = &buffer_info->alloc_buffer_info;
+ uint32_t width = buffer_config.width;
+ uint32_t height = buffer_config.height;
+ int format;
+ uint64_t alloc_flags = 0;
+ int error = SetBufferInfo(buffer_config.format, &format, &alloc_flags);
+ if (error != 0) {
+ return kErrorParameters;
+ }
+
+ if (buffer_config.secure) {
+ alloc_flags |= GRALLOC1_PRODUCER_USAGE_PROTECTED;
+ }
+
+ if (buffer_config.secure_camera) {
+ alloc_flags |= GRALLOC1_PRODUCER_USAGE_CAMERA;
+ }
+
+ if (!buffer_config.cache) {
+ // Allocate uncached buffers
+ alloc_flags |= GRALLOC_USAGE_PRIVATE_UNCACHED;
+ }
+
+ if (buffer_config.gfx_client) {
+ alloc_flags |= GRALLOC1_CONSUMER_USAGE_GPU_TEXTURE;
+ }
+
+ uint64_t producer_usage = alloc_flags;
+ uint64_t consumer_usage = (alloc_flags | GRALLOC1_CONSUMER_USAGE_HWCOMPOSER);
+ // CreateBuffer
+ private_handle_t *hnd = nullptr;
+ Perform_(gralloc_device_, GRALLOC1_MODULE_PERFORM_ALLOCATE_BUFFER, width, height, format,
+ producer_usage, consumer_usage, &hnd);
+
+ if (hnd) {
+ alloc_buffer_info->fd = hnd->fd;
+ alloc_buffer_info->stride = UINT32(hnd->width);
+ alloc_buffer_info->aligned_width = UINT32(hnd->width);
+ alloc_buffer_info->aligned_height = UINT32(hnd->height);
+ alloc_buffer_info->size = hnd->size;
+ } else {
+ DLOGE("Failed to allocate memory");
+ return kErrorMemory;
+ }
+
+ buffer_info->private_data = reinterpret_cast<void *>(hnd);
+ return kErrorNone;
+}
+
+DisplayError HWCBufferAllocator::FreeBuffer(BufferInfo *buffer_info) {
+ DisplayError err = kErrorNone;
+ buffer_handle_t hnd = static_cast<private_handle_t *>(buffer_info->private_data);
+ ReleaseBuffer_(gralloc_device_, hnd);
+ AllocatedBufferInfo *alloc_buffer_info = &buffer_info->alloc_buffer_info;
+
+ alloc_buffer_info->fd = -1;
+ alloc_buffer_info->stride = 0;
+ alloc_buffer_info->size = 0;
+ buffer_info->private_data = NULL;
+ return err;
+}
+
+void HWCBufferAllocator::GetCustomWidthAndHeight(const private_handle_t *handle, int *width,
+ int *height) {
+ Perform_(gralloc_device_, GRALLOC_MODULE_PERFORM_GET_CUSTOM_STRIDE_AND_HEIGHT_FROM_HANDLE, handle,
+ width, height);
+}
+
+void HWCBufferAllocator::GetAlignedWidthAndHeight(int width, int height, int format,
+ uint32_t alloc_type, int *aligned_width,
+ int *aligned_height) {
+ int tile_enabled;
+ gralloc1_producer_usage_t producer_usage = GRALLOC1_PRODUCER_USAGE_NONE;
+ gralloc1_consumer_usage_t consumer_usage = GRALLOC1_CONSUMER_USAGE_NONE;
+ if (alloc_type & GRALLOC_USAGE_HW_FB) {
+ consumer_usage = GRALLOC1_CONSUMER_USAGE_CLIENT_TARGET;
+ }
+ if (alloc_type & GRALLOC_USAGE_PRIVATE_ALLOC_UBWC) {
+ producer_usage = GRALLOC_USAGE_PRIVATE_ALLOC_UBWC;
+ }
+
+ Perform_(gralloc_device_, GRALLOC_MODULE_PERFORM_GET_ATTRIBUTES, width, height, format,
+ producer_usage, consumer_usage, aligned_width, aligned_height, &tile_enabled);
+}
+
+uint32_t HWCBufferAllocator::GetBufferSize(BufferInfo *buffer_info) {
+ const BufferConfig &buffer_config = buffer_info->buffer_config;
+ uint64_t alloc_flags = GRALLOC_USAGE_PRIVATE_IOMMU_HEAP;
+
+ int width = INT(buffer_config.width);
+ int height = INT(buffer_config.height);
+ int format;
+
+ if (buffer_config.secure) {
+ alloc_flags |= INT(GRALLOC_USAGE_PROTECTED);
+ }
+
+ if (!buffer_config.cache) {
+ // Allocate uncached buffers
+ alloc_flags |= GRALLOC_USAGE_PRIVATE_UNCACHED;
+ }
+
+ if (SetBufferInfo(buffer_config.format, &format, &alloc_flags) < 0) {
+ return 0;
+ }
+
+ uint32_t aligned_width = 0, aligned_height = 0, buffer_size = 0;
+ gralloc1_producer_usage_t producer_usage = GRALLOC1_PRODUCER_USAGE_NONE;
+ gralloc1_consumer_usage_t consumer_usage = GRALLOC1_CONSUMER_USAGE_NONE;
+ // TODO(user): Currently both flags are treated similarly in gralloc
+ producer_usage = gralloc1_producer_usage_t(alloc_flags);
+ consumer_usage = gralloc1_consumer_usage_t(alloc_flags);
+ gralloc1::BufferInfo info(width, height, format, producer_usage, consumer_usage);
+ GetBufferSizeAndDimensions(info, &buffer_size, &aligned_width, &aligned_height);
+ return buffer_size;
+}
+
+int HWCBufferAllocator::SetBufferInfo(LayerBufferFormat format, int *target, uint64_t *flags) {
+ switch (format) {
+ case kFormatRGBA8888:
+ *target = HAL_PIXEL_FORMAT_RGBA_8888;
+ break;
+ case kFormatRGBX8888:
+ *target = HAL_PIXEL_FORMAT_RGBX_8888;
+ break;
+ case kFormatRGB888:
+ *target = HAL_PIXEL_FORMAT_RGB_888;
+ break;
+ case kFormatRGB565:
+ *target = HAL_PIXEL_FORMAT_RGB_565;
+ break;
+ case kFormatBGR565:
+ *target = HAL_PIXEL_FORMAT_BGR_565;
+ break;
+ case kFormatBGR888:
+ *target = HAL_PIXEL_FORMAT_BGR_888;
+ break;
+ case kFormatBGRA8888:
+ *target = HAL_PIXEL_FORMAT_BGRA_8888;
+ break;
+ case kFormatYCrCb420PlanarStride16:
+ *target = HAL_PIXEL_FORMAT_YV12;
+ break;
+ case kFormatYCrCb420SemiPlanar:
+ *target = HAL_PIXEL_FORMAT_YCrCb_420_SP;
+ break;
+ case kFormatYCbCr420SemiPlanar:
+ *target = HAL_PIXEL_FORMAT_YCbCr_420_SP;
+ break;
+ case kFormatYCbCr422H2V1Packed:
+ *target = HAL_PIXEL_FORMAT_YCbCr_422_I;
+ break;
+ case kFormatCbYCrY422H2V1Packed:
+ *target = HAL_PIXEL_FORMAT_CbYCrY_422_I;
+ break;
+ case kFormatYCbCr422H2V1SemiPlanar:
+ *target = HAL_PIXEL_FORMAT_YCbCr_422_SP;
+ break;
+ case kFormatYCbCr420SemiPlanarVenus:
+ *target = HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS;
+ break;
+ case kFormatYCrCb420SemiPlanarVenus:
+ *target = HAL_PIXEL_FORMAT_YCrCb_420_SP_VENUS;
+ break;
+ case kFormatYCbCr420SPVenusUbwc:
+ *target = HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC;
+ *flags |= GRALLOC_USAGE_PRIVATE_ALLOC_UBWC;
+ break;
+ case kFormatRGBA5551:
+ *target = HAL_PIXEL_FORMAT_RGBA_5551;
+ break;
+ case kFormatRGBA4444:
+ *target = HAL_PIXEL_FORMAT_RGBA_4444;
+ break;
+ case kFormatRGBA1010102:
+ *target = HAL_PIXEL_FORMAT_RGBA_1010102;
+ break;
+ case kFormatARGB2101010:
+ *target = HAL_PIXEL_FORMAT_ARGB_2101010;
+ break;
+ case kFormatRGBX1010102:
+ *target = HAL_PIXEL_FORMAT_RGBX_1010102;
+ break;
+ case kFormatXRGB2101010:
+ *target = HAL_PIXEL_FORMAT_XRGB_2101010;
+ break;
+ case kFormatBGRA1010102:
+ *target = HAL_PIXEL_FORMAT_BGRA_1010102;
+ break;
+ case kFormatABGR2101010:
+ *target = HAL_PIXEL_FORMAT_ABGR_2101010;
+ break;
+ case kFormatBGRX1010102:
+ *target = HAL_PIXEL_FORMAT_BGRX_1010102;
+ break;
+ case kFormatXBGR2101010:
+ *target = HAL_PIXEL_FORMAT_XBGR_2101010;
+ break;
+ case kFormatYCbCr420P010:
+ *target = HAL_PIXEL_FORMAT_YCbCr_420_P010;
+ break;
+ case kFormatYCbCr420TP10Ubwc:
+ *target = HAL_PIXEL_FORMAT_YCbCr_420_TP10_UBWC;
+ *flags |= GRALLOC_USAGE_PRIVATE_ALLOC_UBWC;
+ break;
+ case kFormatYCbCr420P010Ubwc:
+ *target = HAL_PIXEL_FORMAT_YCbCr_420_P010_UBWC;
+ *flags |= GRALLOC_USAGE_PRIVATE_ALLOC_UBWC;
+ break;
+ case kFormatRGBA8888Ubwc:
+ *target = HAL_PIXEL_FORMAT_RGBA_8888;
+ *flags |= GRALLOC_USAGE_PRIVATE_ALLOC_UBWC;
+ break;
+ case kFormatRGBX8888Ubwc:
+ *target = HAL_PIXEL_FORMAT_RGBX_8888;
+ *flags |= GRALLOC_USAGE_PRIVATE_ALLOC_UBWC;
+ break;
+ case kFormatBGR565Ubwc:
+ *target = HAL_PIXEL_FORMAT_BGR_565;
+ *flags |= GRALLOC_USAGE_PRIVATE_ALLOC_UBWC;
+ break;
+ case kFormatRGBA1010102Ubwc:
+ *target = HAL_PIXEL_FORMAT_RGBA_1010102;
+ *flags |= GRALLOC_USAGE_PRIVATE_ALLOC_UBWC;
+ break;
+ case kFormatRGBX1010102Ubwc:
+ *target = HAL_PIXEL_FORMAT_RGBX_1010102;
+ *flags |= GRALLOC_USAGE_PRIVATE_ALLOC_UBWC;
+ break;
+ default:
+ DLOGE("Unsupported format = 0x%x", format);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+DisplayError HWCBufferAllocator::GetAllocatedBufferInfo(
+ const BufferConfig &buffer_config, AllocatedBufferInfo *allocated_buffer_info) {
+ // TODO(user): This API should pass the buffer_info of the already allocated buffer
+ // The private_data can then be typecast to the private_handle and used directly.
+ uint64_t alloc_flags = GRALLOC_USAGE_PRIVATE_IOMMU_HEAP;
+
+ int width = INT(buffer_config.width);
+ int height = INT(buffer_config.height);
+ int format;
+
+ if (buffer_config.secure) {
+ alloc_flags |= INT(GRALLOC_USAGE_PROTECTED);
+ }
+
+ if (!buffer_config.cache) {
+ // Allocate uncached buffers
+ alloc_flags |= GRALLOC_USAGE_PRIVATE_UNCACHED;
+ }
+
+ if (SetBufferInfo(buffer_config.format, &format, &alloc_flags) < 0) {
+ return kErrorParameters;
+ }
+
+ uint32_t aligned_width = 0, aligned_height = 0, buffer_size = 0;
+ gralloc1_producer_usage_t producer_usage = GRALLOC1_PRODUCER_USAGE_NONE;
+ gralloc1_consumer_usage_t consumer_usage = GRALLOC1_CONSUMER_USAGE_NONE;
+ // TODO(user): Currently both flags are treated similarly in gralloc
+ producer_usage = gralloc1_producer_usage_t(alloc_flags);
+ consumer_usage = gralloc1_consumer_usage_t(alloc_flags);
+ gralloc1::BufferInfo info(width, height, format, producer_usage, consumer_usage);
+ GetBufferSizeAndDimensions(info, &buffer_size, &aligned_width, &aligned_height);
+ allocated_buffer_info->stride = UINT32(aligned_width);
+ allocated_buffer_info->aligned_width = UINT32(aligned_width);
+ allocated_buffer_info->aligned_height = UINT32(aligned_height);
+ allocated_buffer_info->size = UINT32(buffer_size);
+
+ return kErrorNone;
+}
+
+DisplayError HWCBufferAllocator::GetBufferLayout(const AllocatedBufferInfo &buf_info,
+ uint32_t stride[4], uint32_t offset[4],
+ uint32_t *num_planes) {
+ // TODO(user): Transition APIs to not need a private handle
+ private_handle_t hnd(-1, 0, 0, 0, 0, 0, 0);
+ int format = HAL_PIXEL_FORMAT_RGBA_8888;
+ uint64_t flags = 0;
+
+ SetBufferInfo(buf_info.format, &format, &flags);
+ // Setup only the required stuff, skip rest
+ hnd.format = format;
+ hnd.width = INT32(buf_info.aligned_width);
+ hnd.height = INT32(buf_info.aligned_height);
+ if (flags & GRALLOC_USAGE_PRIVATE_ALLOC_UBWC) {
+ hnd.flags = private_handle_t::PRIV_FLAGS_UBWC_ALIGNED;
+ }
+
+ int ret = gralloc1::GetBufferLayout(&hnd, stride, offset, num_planes);
+ if (ret < 0) {
+ DLOGE("GetBufferLayout failed");
+ return kErrorParameters;
+ }
+
+ return kErrorNone;
+}
+
+DisplayError HWCBufferAllocator::MapBuffer(const private_handle_t *handle, int acquire_fence) {
+ void* buffer_ptr = NULL;
+ const gralloc1_rect_t accessRegion = {
+ .left = 0,
+ .top = 0,
+ .width = 0,
+ .height = 0
+ };
+ Lock_(gralloc_device_, handle, GRALLOC1_PRODUCER_USAGE_CPU_READ, GRALLOC1_CONSUMER_USAGE_NONE,
+ &accessRegion, &buffer_ptr, acquire_fence);
+ if (!buffer_ptr) {
+ return kErrorUndefined;
+ }
+
+ return kErrorNone;
+}
+
+DisplayError HWCBufferAllocator::UnmapBuffer(const private_handle_t *handle, int* release_fence) {
+ return (DisplayError)(Unlock_(gralloc_device_, handle, release_fence));
+}
+
+} // namespace sdm
diff --git a/msm8909/sdm/libs/hwc2/hwc_buffer_allocator.h b/msm8909/sdm/libs/hwc2/hwc_buffer_allocator.h
new file mode 100644
index 00000000..2cc50b1d
--- /dev/null
+++ b/msm8909/sdm/libs/hwc2/hwc_buffer_allocator.h
@@ -0,0 +1,80 @@
+/*
+* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+#ifdef USE_GRALLOC1
+#ifndef __HWC_BUFFER_ALLOCATOR_H__
+#define __HWC_BUFFER_ALLOCATOR_H__
+
+#include <fcntl.h>
+#include <sys/mman.h>
+
+#include <hardware/gralloc1.h>
+#include "gralloc_priv.h"
+
+namespace sdm {
+
+template <class Type>
+inline Type ALIGN(Type x, Type align) {
+ return (x + align - 1) & ~(align - 1);
+}
+
+class HWCBufferAllocator : public BufferAllocator {
+ public:
+ DisplayError Init();
+ DisplayError Deinit();
+ DisplayError AllocateBuffer(BufferInfo *buffer_info);
+ DisplayError FreeBuffer(BufferInfo *buffer_info);
+ uint32_t GetBufferSize(BufferInfo *buffer_info);
+
+ void GetCustomWidthAndHeight(const private_handle_t *handle, int *width, int *height);
+ void GetAlignedWidthAndHeight(int width, int height, int format, uint32_t alloc_type,
+ int *aligned_width, int *aligned_height);
+ DisplayError GetAllocatedBufferInfo(const BufferConfig &buffer_config,
+ AllocatedBufferInfo *allocated_buffer_info);
+ DisplayError GetBufferLayout(const AllocatedBufferInfo &buf_info,
+ uint32_t stride[4], uint32_t offset[4],
+ uint32_t *num_planes);
+ int SetBufferInfo(LayerBufferFormat format, int *target, uint64_t *flags);
+ DisplayError MapBuffer(const private_handle_t *handle, int acquire_fence);
+ DisplayError UnmapBuffer(const private_handle_t *handle, int* release_fence);
+
+ private:
+ gralloc1_device_t *gralloc_device_ = nullptr;
+ const hw_module_t *module_;
+ GRALLOC1_PFN_RELEASE ReleaseBuffer_ = nullptr;
+ GRALLOC1_PFN_PERFORM Perform_ = nullptr;
+ GRALLOC1_PFN_LOCK Lock_ = nullptr;
+ GRALLOC1_PFN_UNLOCK Unlock_ = nullptr;
+};
+
+} // namespace sdm
+#endif // __HWC_BUFFER_ALLOCATOR_H__
+#else
+#include "../hwc/hwc_buffer_allocator.h"
+#endif // __HWC_BUFFER_ALLOCATOR_H__
+
diff --git a/msm8909/sdm/libs/hwc2/hwc_callbacks.cpp b/msm8909/sdm/libs/hwc2/hwc_callbacks.cpp
new file mode 100644
index 00000000..3be3bf64
--- /dev/null
+++ b/msm8909/sdm/libs/hwc2/hwc_callbacks.cpp
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation. nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <utils/constants.h>
+#include <utils/debug.h>
+#include "hwc_callbacks.h"
+
+#define __CLASS__ "HWCCallbacks"
+
+namespace sdm {
+
+HWC2::Error HWCCallbacks::Hotplug(hwc2_display_t display, HWC2::Connection state) {
+ if (!hotplug_) {
+ return HWC2::Error::NoResources;
+ }
+ hotplug_(hotplug_data_, display, INT32(state));
+ return HWC2::Error::None;
+}
+
+HWC2::Error HWCCallbacks::Refresh(hwc2_display_t display) {
+ if (!refresh_) {
+ return HWC2::Error::NoResources;
+ }
+ refresh_(refresh_data_, display);
+ return HWC2::Error::None;
+}
+
+HWC2::Error HWCCallbacks::Vsync(hwc2_display_t display, int64_t timestamp) {
+ if (!vsync_) {
+ return HWC2::Error::NoResources;
+ }
+ vsync_(vsync_data_, display, timestamp);
+ return HWC2::Error::None;
+}
+
+HWC2::Error HWCCallbacks::Register(HWC2::Callback descriptor, hwc2_callback_data_t callback_data,
+ hwc2_function_pointer_t pointer) {
+ switch (descriptor) {
+ case HWC2::Callback::Hotplug:
+ hotplug_data_ = callback_data;
+ hotplug_ = reinterpret_cast<HWC2_PFN_HOTPLUG>(pointer);
+ break;
+ case HWC2::Callback::Refresh:
+ refresh_data_ = callback_data;
+ refresh_ = reinterpret_cast<HWC2_PFN_REFRESH>(pointer);
+ break;
+ case HWC2::Callback::Vsync:
+ vsync_data_ = callback_data;
+ vsync_ = reinterpret_cast<HWC2_PFN_VSYNC>(pointer);
+ break;
+ default:
+ return HWC2::Error::BadParameter;
+ }
+ return HWC2::Error::None;
+}
+
+} // namespace sdm
diff --git a/msm8909/sdm/libs/hwc2/hwc_callbacks.h b/msm8909/sdm/libs/hwc2/hwc_callbacks.h
new file mode 100644
index 00000000..d3f4e529
--- /dev/null
+++ b/msm8909/sdm/libs/hwc2/hwc_callbacks.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation. nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __HWC_CALLBACKS_H__
+#define __HWC_CALLBACKS_H__
+
+#define HWC2_INCLUDE_STRINGIFICATION
+#define HWC2_USE_CPP11
+#include <hardware/hwcomposer2.h>
+#undef HWC2_INCLUDE_STRINGIFICATION
+#undef HWC2_USE_CPP11
+
+namespace sdm {
+
+class HWCCallbacks {
+ public:
+ HWC2::Error Hotplug(hwc2_display_t display, HWC2::Connection state);
+ HWC2::Error Refresh(hwc2_display_t display);
+ HWC2::Error Vsync(hwc2_display_t display, int64_t timestamp);
+ HWC2::Error Register(HWC2::Callback, hwc2_callback_data_t callback_data,
+ hwc2_function_pointer_t pointer);
+
+ bool VsyncCallbackRegistered() { return (vsync_ != nullptr && vsync_data_ != nullptr); }
+
+ private:
+ hwc2_callback_data_t hotplug_data_ = nullptr;
+ hwc2_callback_data_t refresh_data_ = nullptr;
+ hwc2_callback_data_t vsync_data_ = nullptr;
+
+ HWC2_PFN_HOTPLUG hotplug_ = nullptr;
+ HWC2_PFN_REFRESH refresh_ = nullptr;
+ HWC2_PFN_VSYNC vsync_ = nullptr;
+};
+
+} // namespace sdm
+
+#endif // __HWC_CALLBACKS_H__
diff --git a/msm8909/sdm/libs/hwc2/hwc_color_manager.cpp b/msm8909/sdm/libs/hwc2/hwc_color_manager.cpp
new file mode 100644
index 00000000..5578fde1
--- /dev/null
+++ b/msm8909/sdm/libs/hwc2/hwc_color_manager.cpp
@@ -0,0 +1,461 @@
+/*
+* Copyright (c) 2015 - 2017, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <dlfcn.h>
+#include <cutils/sockets.h>
+#include <cutils/native_handle.h>
+#include <utils/String16.h>
+#include <binder/Parcel.h>
+#include <gralloc_priv.h>
+#include <hardware/hwcomposer.h>
+#include <hardware/hwcomposer_defs.h>
+#include <QService.h>
+
+#include <utils/constants.h>
+#include <utils/debug.h>
+#include <core/buffer_allocator.h>
+#include <private/color_params.h>
+#include "hwc_buffer_allocator.h"
+#include "hwc_buffer_sync_handler.h"
+#include "hwc_session.h"
+#include "hwc_debugger.h"
+
+#define __CLASS__ "HWCColorManager"
+
+namespace sdm {
+
+uint32_t HWCColorManager::Get8BitsARGBColorValue(const PPColorFillParams &params) {
+ uint32_t argb_color = ((params.color.r << 16) & 0xff0000) | ((params.color.g << 8) & 0xff00) |
+ ((params.color.b) & 0xff);
+ return argb_color;
+}
+
+int HWCColorManager::CreatePayloadFromParcel(const android::Parcel &in, uint32_t *disp_id,
+ PPDisplayAPIPayload *sink) {
+ int ret = 0;
+ uint32_t id(0);
+ uint32_t size(0);
+
+ id = UINT32(in.readInt32());
+ size = UINT32(in.readInt32());
+ if (size > 0 && size == in.dataAvail()) {
+ const void *data = in.readInplace(size);
+ const uint8_t *temp = reinterpret_cast<const uint8_t *>(data);
+
+ sink->size = size;
+ sink->payload = const_cast<uint8_t *>(temp);
+ *disp_id = id;
+ } else {
+ DLOGW("Failing size checking, size = %d", size);
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+void HWCColorManager::MarshallStructIntoParcel(const PPDisplayAPIPayload &data,
+ android::Parcel *out_parcel) {
+ out_parcel->writeInt32(INT32(data.size));
+ if (data.payload)
+ out_parcel->write(data.payload, data.size);
+}
+
+HWCColorManager *HWCColorManager::CreateColorManager(HWCBufferAllocator * buffer_allocator) {
+ HWCColorManager *color_mgr = new HWCColorManager(buffer_allocator);
+
+ if (color_mgr) {
+ // Load display API interface library. And retrieve color API function tables.
+ DynLib &color_apis_lib = color_mgr->color_apis_lib_;
+ if (color_apis_lib.Open(DISPLAY_API_INTERFACE_LIBRARY_NAME)) {
+ if (!color_apis_lib.Sym(DISPLAY_API_FUNC_TABLES, &color_mgr->color_apis_)) {
+ DLOGE("Fail to retrieve = %s from %s", DISPLAY_API_FUNC_TABLES,
+ DISPLAY_API_INTERFACE_LIBRARY_NAME);
+ delete color_mgr;
+ return NULL;
+ }
+ } else {
+ DLOGW("Unable to load = %s", DISPLAY_API_INTERFACE_LIBRARY_NAME);
+ delete color_mgr;
+ return NULL;
+ }
+ DLOGI("Successfully loaded %s", DISPLAY_API_INTERFACE_LIBRARY_NAME);
+
+ // Load diagclient library and invokes its entry point to pass in display APIs.
+ DynLib &diag_client_lib = color_mgr->diag_client_lib_;
+ if (diag_client_lib.Open(QDCM_DIAG_CLIENT_LIBRARY_NAME)) {
+ if (!diag_client_lib.Sym(INIT_QDCM_DIAG_CLIENT_NAME,
+ reinterpret_cast<void **>(&color_mgr->qdcm_diag_init_)) ||
+ !diag_client_lib.Sym(DEINIT_QDCM_DIAG_CLIENT_NAME,
+ reinterpret_cast<void **>(&color_mgr->qdcm_diag_deinit_))) {
+ DLOGE("Fail to retrieve = %s from %s", INIT_QDCM_DIAG_CLIENT_NAME,
+ QDCM_DIAG_CLIENT_LIBRARY_NAME);
+ } else {
+ // invoke Diag Client entry point to initialize.
+ color_mgr->qdcm_diag_init_(color_mgr->color_apis_);
+ DLOGI("Successfully loaded %s and %s and diag_init'ed", DISPLAY_API_INTERFACE_LIBRARY_NAME,
+ QDCM_DIAG_CLIENT_LIBRARY_NAME);
+ }
+ } else {
+ DLOGW("Unable to load = %s", QDCM_DIAG_CLIENT_LIBRARY_NAME);
+ // only QDCM Diag client failed to be loaded and system still should function.
+ }
+ } else {
+ DLOGE("Unable to create HWCColorManager");
+ return NULL;
+ }
+
+ return color_mgr;
+}
+
+HWCColorManager::HWCColorManager(HWCBufferAllocator *buffer_allocator) :
+ buffer_allocator_(buffer_allocator) {
+}
+
+HWCColorManager::~HWCColorManager() {
+}
+
+void HWCColorManager::DestroyColorManager() {
+ if (qdcm_mode_mgr_) {
+ delete qdcm_mode_mgr_;
+ }
+ if (qdcm_diag_deinit_) {
+ qdcm_diag_deinit_();
+ }
+ delete this;
+}
+
+int HWCColorManager::EnableQDCMMode(bool enable, HWCDisplay *hwc_display) {
+ int ret = 0;
+
+ if (!qdcm_mode_mgr_) {
+ qdcm_mode_mgr_ = HWCQDCMModeManager::CreateQDCMModeMgr();
+ if (!qdcm_mode_mgr_) {
+ DLOGE("Unable to create QDCM operating mode manager.");
+ ret = -EFAULT;
+ }
+ }
+
+ if (qdcm_mode_mgr_) {
+ ret = qdcm_mode_mgr_->EnableQDCMMode(enable, hwc_display);
+ }
+
+ return ret;
+}
+
+int HWCColorManager::SetSolidFill(const void *params, bool enable, HWCDisplay *hwc_display) {
+ SCOPE_LOCK(locker_);
+
+ if (params) {
+ solid_fill_params_ = *reinterpret_cast<const PPColorFillParams *>(params);
+ } else {
+ solid_fill_params_ = PPColorFillParams();
+ }
+
+ uint32_t solid_fill_color = Get8BitsARGBColorValue(solid_fill_params_);
+ if (enable) {
+ LayerRect solid_fill_rect = {
+ FLOAT(solid_fill_params_.rect.x), FLOAT(solid_fill_params_.rect.y),
+ FLOAT(solid_fill_params_.rect.x) + FLOAT(solid_fill_params_.rect.width),
+ FLOAT(solid_fill_params_.rect.y) + FLOAT(solid_fill_params_.rect.height),
+ };
+
+ hwc_display->Perform(HWCDisplayPrimary::SET_QDCM_SOLID_FILL_INFO, solid_fill_color);
+ hwc_display->Perform(HWCDisplayPrimary::SET_QDCM_SOLID_FILL_RECT, &solid_fill_rect);
+ } else {
+ hwc_display->Perform(HWCDisplayPrimary::UNSET_QDCM_SOLID_FILL_INFO, 0);
+ }
+
+ return 0;
+}
+
+int HWCColorManager::SetFrameCapture(void *params, bool enable, HWCDisplay *hwc_display) {
+ SCOPE_LOCK(locker_);
+ int ret = 0;
+
+ PPFrameCaptureData *frame_capture_data = reinterpret_cast<PPFrameCaptureData *>(params);
+
+ if (enable) {
+ std::memset(&buffer_info, 0x00, sizeof(buffer_info));
+ hwc_display->GetPanelResolution(&buffer_info.buffer_config.width,
+ &buffer_info.buffer_config.height);
+ if (frame_capture_data->input_params.out_pix_format == PP_PIXEL_FORMAT_RGB_888) {
+ buffer_info.buffer_config.format = kFormatRGB888;
+ } else if (frame_capture_data->input_params.out_pix_format == PP_PIXEL_FORMAT_RGB_2101010) {
+ buffer_info.buffer_config.format = kFormatRGBA1010102;
+ } else {
+ DLOGE("Pixel-format: %d NOT support.", frame_capture_data->input_params.out_pix_format);
+ return -EFAULT;
+ }
+
+ buffer_info.buffer_config.buffer_count = 1;
+ buffer_info.alloc_buffer_info.fd = -1;
+ buffer_info.alloc_buffer_info.stride = 0;
+ buffer_info.alloc_buffer_info.size = 0;
+
+ ret = buffer_allocator_->AllocateBuffer(&buffer_info);
+ if (ret != 0) {
+ DLOGE("Buffer allocation failed. ret: %d", ret);
+ return -ENOMEM;
+ } else {
+ void *buffer = mmap(NULL, buffer_info.alloc_buffer_info.size, PROT_READ | PROT_WRITE,
+ MAP_SHARED, buffer_info.alloc_buffer_info.fd, 0);
+
+ if (buffer == MAP_FAILED) {
+ DLOGE("mmap failed. err = %d", errno);
+ frame_capture_data->buffer = NULL;
+ ret = buffer_allocator_->FreeBuffer(&buffer_info);
+ return -EFAULT;
+ } else {
+ frame_capture_data->buffer = reinterpret_cast<uint8_t *>(buffer);
+ frame_capture_data->buffer_stride = buffer_info.alloc_buffer_info.stride;
+ frame_capture_data->buffer_size = buffer_info.alloc_buffer_info.size;
+ }
+ ret = hwc_display->FrameCaptureAsync(buffer_info, 1);
+ if (ret < 0) {
+ DLOGE("FrameCaptureAsync failed. ret = %d", ret);
+ }
+ }
+ } else {
+ ret = hwc_display->GetFrameCaptureStatus();
+ if (!ret) {
+ if (frame_capture_data->buffer != NULL) {
+ if (munmap(frame_capture_data->buffer, buffer_info.alloc_buffer_info.size) != 0) {
+ DLOGE("munmap failed. err = %d", errno);
+ }
+ }
+ if (buffer_allocator_ != NULL) {
+ std::memset(frame_capture_data, 0x00, sizeof(PPFrameCaptureData));
+ ret = buffer_allocator_->FreeBuffer(&buffer_info);
+ if (ret != 0) {
+ DLOGE("FreeBuffer failed. ret = %d", ret);
+ }
+ }
+ } else {
+ DLOGE("GetFrameCaptureStatus failed. ret = %d", ret);
+ }
+ }
+ return ret;
+}
+
+int HWCColorManager::SetHWDetailedEnhancerConfig(void *params, HWCDisplay *hwc_display) {
+ int err = -1;
+ DisplayDetailEnhancerData de_data;
+
+ PPDETuningCfgData *de_tuning_cfg_data = reinterpret_cast<PPDETuningCfgData*>(params);
+ if (de_tuning_cfg_data->cfg_pending == true) {
+ if (!de_tuning_cfg_data->cfg_en) {
+ de_data.enable = 0;
+ } else {
+ de_data.override_flags = kOverrideDEEnable;
+ de_data.enable = 1;
+
+ if (de_tuning_cfg_data->params.flags & kDeTuningFlagSharpFactor) {
+ de_data.override_flags |= kOverrideDESharpen1;
+ de_data.sharp_factor = de_tuning_cfg_data->params.sharp_factor;
+ }
+
+ if (de_tuning_cfg_data->params.flags & kDeTuningFlagClip) {
+ de_data.override_flags |= kOverrideDEClip;
+ de_data.clip = de_tuning_cfg_data->params.clip;
+ }
+
+ if (de_tuning_cfg_data->params.flags & kDeTuningFlagThrQuiet) {
+ de_data.override_flags |= kOverrideDEThrQuiet;
+ de_data.thr_quiet = de_tuning_cfg_data->params.thr_quiet;
+ }
+
+ if (de_tuning_cfg_data->params.flags & kDeTuningFlagThrDieout) {
+ de_data.override_flags |= kOverrideDEThrDieout;
+ de_data.thr_dieout = de_tuning_cfg_data->params.thr_dieout;
+ }
+
+ if (de_tuning_cfg_data->params.flags & kDeTuningFlagThrLow) {
+ de_data.override_flags |= kOverrideDEThrLow;
+ de_data.thr_low = de_tuning_cfg_data->params.thr_low;
+ }
+
+ if (de_tuning_cfg_data->params.flags & kDeTuningFlagThrHigh) {
+ de_data.override_flags |= kOverrideDEThrHigh;
+ de_data.thr_high = de_tuning_cfg_data->params.thr_high;
+ }
+
+ if (de_tuning_cfg_data->params.flags & kDeTuningFlagContentQualLevel) {
+ switch (de_tuning_cfg_data->params.quality) {
+ case kDeContentQualLow:
+ de_data.quality_level = kContentQualityLow;
+ break;
+ case kDeContentQualMedium:
+ de_data.quality_level = kContentQualityMedium;
+ break;
+ case kDeContentQualHigh:
+ de_data.quality_level = kContentQualityHigh;
+ break;
+ case kDeContentQualUnknown:
+ default:
+ de_data.quality_level = kContentQualityUnknown;
+ break;
+ }
+ }
+ }
+ err = hwc_display->SetDetailEnhancerConfig(de_data);
+ if (err) {
+ DLOGW("SetDetailEnhancerConfig failed. err = %d", err);
+ }
+ de_tuning_cfg_data->cfg_pending = false;
+ }
+ return err;
+}
+
+void HWCColorManager::SetColorModeDetailEnhancer(HWCDisplay *hwc_display) {
+ SCOPE_LOCK(locker_);
+ int err = -1;
+ PPPendingParams pending_action;
+ PPDisplayAPIPayload req_payload;
+
+ pending_action.action = kGetDetailedEnhancerData;
+ pending_action.params = NULL;
+
+ if (hwc_display) {
+ err = hwc_display->ColorSVCRequestRoute(req_payload, NULL, &pending_action);
+ if (!err && pending_action.action == kConfigureDetailedEnhancer) {
+ err = SetHWDetailedEnhancerConfig(pending_action.params, hwc_display);
+ }
+ }
+ return;
+}
+
+int HWCColorManager::SetDetailedEnhancer(void *params, HWCDisplay *hwc_display) {
+ SCOPE_LOCK(locker_);
+ int err = -1;
+ err = SetHWDetailedEnhancerConfig(params, hwc_display);
+ return err;
+}
+
+const HWCQDCMModeManager::ActiveFeatureCMD HWCQDCMModeManager::kActiveFeatureCMD[] = {
+ HWCQDCMModeManager::ActiveFeatureCMD("cabl:on", "cabl:off", "cabl:status", "running"),
+ HWCQDCMModeManager::ActiveFeatureCMD("ad:on", "ad:off", "ad:query:status", "running"),
+ HWCQDCMModeManager::ActiveFeatureCMD("svi:on", "svi:off", "svi:status", "running"),
+};
+
+const char *const HWCQDCMModeManager::kSocketName = "pps";
+const char *const HWCQDCMModeManager::kTagName = "surfaceflinger";
+const char *const HWCQDCMModeManager::kPackageName = "colormanager";
+
+HWCQDCMModeManager *HWCQDCMModeManager::CreateQDCMModeMgr() {
+ HWCQDCMModeManager *mode_mgr = new HWCQDCMModeManager();
+
+ if (!mode_mgr) {
+ DLOGW("No memory to create HWCQDCMModeManager.");
+ return NULL;
+ } else {
+ mode_mgr->socket_fd_ =
+ ::socket_local_client(kSocketName, ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM);
+ if (mode_mgr->socket_fd_ < 0) {
+ // it should not be disastrous and we still can grab wakelock in QDCM mode.
+ DLOGW("Unable to connect to dpps socket!");
+ }
+
+ // retrieve system GPU idle timeout value for later to recover.
+ mode_mgr->entry_timeout_ = UINT32(HWCDebugHandler::GetIdleTimeoutMs());
+ }
+
+ return mode_mgr;
+}
+
+HWCQDCMModeManager::~HWCQDCMModeManager() {
+ if (socket_fd_ >= 0)
+ ::close(socket_fd_);
+}
+
+int HWCQDCMModeManager::EnableActiveFeatures(bool enable,
+ const HWCQDCMModeManager::ActiveFeatureCMD &cmds,
+ bool *was_running) {
+ int ret = 0;
+ ssize_t size = 0;
+ char response[kSocketCMDMaxLength] = {
+ 0,
+ };
+
+ if (socket_fd_ < 0) {
+ DLOGW("No socket connection available!");
+ return -EFAULT;
+ }
+
+ if (!enable) { // if client requesting to disable it.
+ // query CABL status, if off, no action. keep the status.
+ size = ::write(socket_fd_, cmds.cmd_query_status, strlen(cmds.cmd_query_status));
+ if (size < 0) {
+ DLOGW("Unable to send data over socket %s", ::strerror(errno));
+ ret = -EFAULT;
+ } else {
+ size = ::read(socket_fd_, response, kSocketCMDMaxLength);
+ if (size < 0) {
+ DLOGW("Unable to read data over socket %s", ::strerror(errno));
+ ret = -EFAULT;
+ } else if (!strncmp(response, cmds.running, strlen(cmds.running))) {
+ *was_running = true;
+ }
+ }
+
+ if (*was_running) { // if was running, it's requested to disable it.
+ size = ::write(socket_fd_, cmds.cmd_off, strlen(cmds.cmd_off));
+ if (size < 0) {
+ DLOGW("Unable to send data over socket %s", ::strerror(errno));
+ ret = -EFAULT;
+ }
+ }
+ } else { // if was running, need enable it back.
+ if (*was_running) {
+ size = ::write(socket_fd_, cmds.cmd_on, strlen(cmds.cmd_on));
+ if (size < 0) {
+ DLOGW("Unable to send data over socket %s", ::strerror(errno));
+ ret = -EFAULT;
+ }
+ }
+ }
+
+ return ret;
+}
+
+int HWCQDCMModeManager::EnableQDCMMode(bool enable, HWCDisplay *hwc_display) {
+ int ret = 0;
+
+ ret = EnableActiveFeatures((enable ? false : true), kActiveFeatureCMD[kCABLFeature],
+ &cabl_was_running_);
+
+ // if enter QDCM mode, disable GPU fallback idle timeout.
+ if (hwc_display) {
+ uint32_t timeout = enable ? 0 : entry_timeout_;
+ hwc_display->SetIdleTimeoutMs(timeout);
+ }
+
+ return ret;
+}
+
+} // namespace sdm
diff --git a/msm8909/sdm/libs/hwc2/hwc_color_manager.h b/msm8909/sdm/libs/hwc2/hwc_color_manager.h
new file mode 100644
index 00000000..f88a5bbb
--- /dev/null
+++ b/msm8909/sdm/libs/hwc2/hwc_color_manager.h
@@ -0,0 +1,143 @@
+/* Copyright (c) 2015-2017, The Linux Foundataion. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+*/
+
+#ifndef __HWC_COLOR_MANAGER_H__
+#define __HWC_COLOR_MANAGER_H__
+
+#include <stdlib.h>
+#include <binder/Parcel.h>
+#include <binder/BinderService.h>
+#include <core/sdm_types.h>
+#include <utils/locker.h>
+
+namespace sdm {
+
+// This macro defines name for display APIs interface wrapper library.
+// This macro shall be used to load library using dlopen().
+#define DISPLAY_API_INTERFACE_LIBRARY_NAME "libsdm-disp-vndapis.so"
+
+// This macro defines variable name of display color APIs function tables
+// This macro shall be used to specify name of the variable in dlsym().
+#define DISPLAY_API_FUNC_TABLES "display_color_apis_ftables"
+#define QDCM_DIAG_CLIENT_LIBRARY_NAME "libsdm-diag.so"
+#define INIT_QDCM_DIAG_CLIENT_NAME "QDCMDiagInit"
+#define DEINIT_QDCM_DIAG_CLIENT_NAME "QDCMDiagDeInit"
+
+typedef int (*QDCMDiagInit)(void *ftables);
+
+typedef int (*QDCMDiagDeInit)(void);
+
+// Class to encapsulte all details of managing QDCM operating mode.
+class HWCQDCMModeManager {
+ public:
+ static const uint32_t kSocketCMDMaxLength = 4096;
+ static const uint32_t kFullWakeLock = 0x0000001a;
+ static const uint32_t kAcquireCauseWakeup = 0x10000000;
+ static const uint32_t kONAfterRelease = 0x20000000;
+ enum ActiveFeatureID {
+ kCABLFeature,
+ kADFeature,
+ kSVIFeature,
+ kMaxNumActiveFeature,
+ };
+
+ struct ActiveFeatureCMD {
+ const char *cmd_on = NULL;
+ const char *cmd_off = NULL;
+ const char *cmd_query_status = NULL;
+ const char *running = NULL;
+ ActiveFeatureCMD(const char *arg1, const char *arg2, const char *arg3, const char *arg4)
+ : cmd_on(arg1), cmd_off(arg2), cmd_query_status(arg3), running(arg4) {}
+ };
+
+ static const ActiveFeatureCMD kActiveFeatureCMD[kMaxNumActiveFeature];
+
+ public:
+ static HWCQDCMModeManager *CreateQDCMModeMgr();
+ ~HWCQDCMModeManager();
+ int EnableQDCMMode(bool enable, HWCDisplay *hwc_display);
+
+ protected:
+ bool SendSocketCmd();
+ int AcquireAndroidWakeLock(bool enable);
+ int EnableActiveFeatures(bool enable);
+ int EnableActiveFeatures(bool enable, const ActiveFeatureCMD &cmds, bool *was_running);
+
+ private:
+ bool cabl_was_running_ = false;
+ int socket_fd_ = -1;
+ android::sp<android::IBinder> wakelock_token_ = NULL;
+ uint32_t entry_timeout_ = 0;
+ static const char *const kSocketName;
+ static const char *const kTagName;
+ static const char *const kPackageName;
+};
+
+// Class to encapsulte all HWC/OS specific behaviours for ColorManager.
+class HWCColorManager {
+ public:
+ static const int kNumSolidFillLayers = 2;
+ static HWCColorManager *CreateColorManager(HWCBufferAllocator *buffer_allocator);
+ static int CreatePayloadFromParcel(const android::Parcel &in, uint32_t *disp_id,
+ PPDisplayAPIPayload *sink);
+ static void MarshallStructIntoParcel(const PPDisplayAPIPayload &data,
+ android::Parcel *out_parcel);
+
+ explicit HWCColorManager(HWCBufferAllocator *buffer_allocator);
+ ~HWCColorManager();
+ void DestroyColorManager();
+ int EnableQDCMMode(bool enable, HWCDisplay *hwc_display);
+ int SetSolidFill(const void *params, bool enable, HWCDisplay *hwc_display);
+ int SetFrameCapture(void *params, bool enable, HWCDisplay *hwc_display);
+ int SetDetailedEnhancer(void *params, HWCDisplay *hwc_display);
+ void SetColorModeDetailEnhancer(HWCDisplay *hwc_display);
+ int SetHWDetailedEnhancerConfig(void *params, HWCDisplay *hwc_display);
+
+ protected:
+ int CreateSolidFillLayers(HWCDisplay *hwc_display);
+ void DestroySolidFillLayers();
+ static uint32_t Get8BitsARGBColorValue(const PPColorFillParams &params);
+
+ private:
+ DynLib color_apis_lib_;
+ DynLib diag_client_lib_;
+ void *color_apis_ = NULL;
+ QDCMDiagInit qdcm_diag_init_ = NULL;
+ QDCMDiagDeInit qdcm_diag_deinit_ = NULL;
+ HWCQDCMModeManager *qdcm_mode_mgr_ = NULL;
+
+ PPColorFillParams solid_fill_params_;
+ HWCBufferAllocator *buffer_allocator_ = NULL;
+ BufferInfo buffer_info;
+ Locker locker_;
+};
+
+} // namespace sdm
+
+#endif // __HWC_COLOR_MANAGER_H__
diff --git a/msm8909/sdm/libs/hwc2/hwc_display.cpp b/msm8909/sdm/libs/hwc2/hwc_display.cpp
new file mode 100644
index 00000000..3a159ba9
--- /dev/null
+++ b/msm8909/sdm/libs/hwc2/hwc_display.cpp
@@ -0,0 +1,2049 @@
+/*
+ * Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
+ * Not a Contribution.
+ *
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <cutils/properties.h>
+#include <errno.h>
+#include <math.h>
+#include <sync/sync.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <utils/constants.h>
+#include <utils/debug.h>
+#include <utils/formats.h>
+#include <utils/rect.h>
+#include <qd_utils.h>
+
+#include <algorithm>
+#include <iomanip>
+#include <map>
+#include <sstream>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "hwc_display.h"
+#include "hwc_debugger.h"
+#include "blit_engine_c2d.h"
+#include "hwc_tonemapper.h"
+
+#ifndef USE_GRALLOC1
+#include <gr.h>
+#endif
+
+#ifdef QTI_BSP
+#include <hardware/display_defs.h>
+#endif
+
+#define __CLASS__ "HWCDisplay"
+
+namespace sdm {
+
+std::bitset<kDisplayMax> HWCDisplay::validated_ = 0;
+
+// This weight function is needed because the color primaries are not sorted by gamut size
+static ColorPrimaries WidestPrimaries(ColorPrimaries p1, ColorPrimaries p2) {
+ int weight = 10;
+ int lp1 = p1, lp2 = p2;
+ // TODO(user) add weight to other wide gamut primaries
+ if (lp1 == ColorPrimaries_BT2020) {
+ lp1 *= weight;
+ }
+ if (lp1 == ColorPrimaries_BT2020) {
+ lp2 *= weight;
+ }
+ if (lp1 >= lp2) {
+ return p1;
+ } else {
+ return p2;
+ }
+}
+
+HWCColorMode::HWCColorMode(DisplayInterface *display_intf) : display_intf_(display_intf) {}
+
+HWC2::Error HWCColorMode::Init() {
+ PopulateColorModes();
+ return ApplyDefaultColorMode();
+}
+
+HWC2::Error HWCColorMode::DeInit() {
+ color_mode_transform_map_.clear();
+ return HWC2::Error::None;
+}
+
+uint32_t HWCColorMode::GetColorModeCount() {
+ uint32_t count = UINT32(color_mode_transform_map_.size());
+ DLOGI("Supported color mode count = %d", count);
+#ifdef EXCLUDE_DISPLAY_PP
+ return count;
+#else
+ return std::max(1U, count);
+#endif
+}
+
+HWC2::Error HWCColorMode::GetColorModes(uint32_t *out_num_modes,
+ android_color_mode_t *out_modes) {
+ auto it = color_mode_transform_map_.begin();
+ for (auto i = 0; it != color_mode_transform_map_.end(); it++, i++) {
+ out_modes[i] = it->first;
+ DLOGI("Supports color mode[%d] = %d", i, it->first);
+ }
+ *out_num_modes = UINT32(color_mode_transform_map_.size());
+ return HWC2::Error::None;
+}
+
+HWC2::Error HWCColorMode::SetColorMode(android_color_mode_t mode) {
+ // first mode in 2D matrix is the mode (identity)
+ if (mode < HAL_COLOR_MODE_NATIVE || mode > HAL_COLOR_MODE_DISPLAY_P3) {
+ DLOGE("Could not find mode: %d", mode);
+ return HWC2::Error::BadParameter;
+ }
+ if (color_mode_transform_map_.find(mode) == color_mode_transform_map_.end()) {
+ return HWC2::Error::Unsupported;
+ }
+
+ auto status = HandleColorModeTransform(mode, current_color_transform_, color_matrix_);
+ if (status != HWC2::Error::None) {
+ DLOGE("failed for mode = %d", mode);
+ }
+
+ DLOGV_IF(kTagClient, "Color mode %d successfully set.", mode);
+ return status;
+}
+
+HWC2::Error HWCColorMode::RestoreColorTransform() {
+ DisplayError error = display_intf_->SetColorTransform(kColorTransformMatrixCount, color_matrix_);
+ if (error != kErrorNone) {
+ DLOGI_IF(kTagClient,"Failed to set Color Transform");
+ return HWC2::Error::BadParameter;
+ }
+
+ return HWC2::Error::None;
+}
+
+HWC2::Error HWCColorMode::SetColorTransform(const float *matrix, android_color_transform_t hint) {
+ DTRACE_SCOPED();
+ double color_matrix[kColorTransformMatrixCount] = {0};
+ CopyColorTransformMatrix(matrix, color_matrix);
+
+ auto status = HandleColorModeTransform(current_color_mode_, hint, color_matrix);
+ if (status != HWC2::Error::None) {
+ DLOGE("failed for hint = %d", hint);
+ }
+
+ return status;
+}
+
+HWC2::Error HWCColorMode::HandleColorModeTransform(android_color_mode_t mode,
+ android_color_transform_t hint,
+ const double *matrix) {
+ android_color_transform_t transform_hint = hint;
+ std::string color_mode_transform;
+ bool use_matrix = false;
+ if (hint != HAL_COLOR_TRANSFORM_ARBITRARY_MATRIX) {
+ // if the mode + transfrom request from HWC matches one mode in SDM, set that
+ if (color_mode_transform.empty()) {
+ transform_hint = HAL_COLOR_TRANSFORM_IDENTITY;
+ use_matrix = true;
+ } else {
+ color_mode_transform = color_mode_transform_map_[mode][hint];
+ }
+ } else {
+ use_matrix = true;
+ transform_hint = HAL_COLOR_TRANSFORM_IDENTITY;
+ }
+
+ // if the mode count is 1, then only native mode is supported, so just apply matrix w/o
+ // setting mode
+ if (color_mode_transform_map_.size() > 1U && current_color_mode_ != mode) {
+ color_mode_transform = color_mode_transform_map_[mode][transform_hint];
+ DisplayError error = display_intf_->SetColorMode(color_mode_transform);
+ if (error != kErrorNone) {
+ DLOGE("Failed to set color_mode = %d transform_hint = %d", mode, hint);
+ // failure to force client composition
+ return HWC2::Error::Unsupported;
+ }
+ DLOGI("Setting Color Mode = %d Transform Hint = %d Success", mode, hint);
+ }
+
+ if (use_matrix) {
+ DisplayError error = display_intf_->SetColorTransform(kColorTransformMatrixCount, matrix);
+ if (error != kErrorNone) {
+ DLOGE("Failed to set Color Transform Matrix");
+ // failure to force client composition
+ return HWC2::Error::Unsupported;
+ }
+ }
+
+ current_color_mode_ = mode;
+ current_color_transform_ = hint;
+ CopyColorTransformMatrix(matrix, color_matrix_);
+
+ return HWC2::Error::None;
+}
+
+void HWCColorMode::PopulateColorModes() {
+ uint32_t color_mode_count = 0;
+ // SDM returns modes which is string combination of mode + transform.
+ DisplayError error = display_intf_->GetColorModeCount(&color_mode_count);
+ if (error != kErrorNone || (color_mode_count == 0)) {
+#ifndef EXCLUDE_DISPLAY_PP
+ DLOGW("GetColorModeCount failed, use native color mode");
+ PopulateTransform(HAL_COLOR_MODE_NATIVE, "native", "identity");
+#endif
+ return;
+ }
+
+ DLOGV_IF(kTagClient, "Color Modes supported count = %d", color_mode_count);
+
+ const std::string color_transform = "identity";
+ std::vector<std::string> color_modes(color_mode_count);
+ error = display_intf_->GetColorModes(&color_mode_count, &color_modes);
+ for (uint32_t i = 0; i < color_mode_count; i++) {
+ std::string &mode_string = color_modes.at(i);
+ DLOGV_IF(kTagClient, "Color Mode[%d] = %s", i, mode_string.c_str());
+ AttrVal attr;
+ error = display_intf_->GetColorModeAttr(mode_string, &attr);
+ std::string color_gamut, dynamic_range, pic_quality;
+ if (!attr.empty()) {
+ for (auto &it : attr) {
+ if (it.first.find(kColorGamutAttribute) != std::string::npos) {
+ color_gamut = it.second;
+ } else if (it.first.find(kDynamicRangeAttribute) != std::string::npos) {
+ dynamic_range = it.second;
+ } else if (it.first.find(kPictureQualityAttribute) != std::string::npos) {
+ pic_quality = it.second;
+ }
+ }
+
+ DLOGV_IF(kTagClient, "color_gamut : %s, dynamic_range : %s, pic_quality : %s",
+ color_gamut.c_str(), dynamic_range.c_str(), pic_quality.c_str());
+
+ if (dynamic_range == kHdr) {
+ continue;
+ }
+ if ((color_gamut == kNative) &&
+ (pic_quality.empty() || pic_quality == kStandard)) {
+ PopulateTransform(HAL_COLOR_MODE_NATIVE, mode_string, color_transform);
+ } else if ((color_gamut == kSrgb) &&
+ (pic_quality.empty() || pic_quality == kStandard)) {
+ PopulateTransform(HAL_COLOR_MODE_SRGB, mode_string, color_transform);
+ } else if ((color_gamut == kDcip3) &&
+ (pic_quality.empty() || pic_quality == kStandard)) {
+ PopulateTransform(HAL_COLOR_MODE_DISPLAY_P3, mode_string, color_transform);
+ } else if ((color_gamut == kDisplayP3) &&
+ (pic_quality.empty() || pic_quality == kStandard)) {
+ PopulateTransform(HAL_COLOR_MODE_DISPLAY_P3, mode_string, color_transform);
+ }
+ }
+
+ // Look at the mode name, if no color gamut is found
+ if (color_gamut.empty()) {
+ if (mode_string.find("hal_native") != std::string::npos) {
+ PopulateTransform(HAL_COLOR_MODE_NATIVE, mode_string, mode_string);
+ } else if (mode_string.find("hal_srgb") != std::string::npos) {
+ PopulateTransform(HAL_COLOR_MODE_SRGB, mode_string, mode_string);
+ } else if (mode_string.find("hal_adobe") != std::string::npos) {
+ PopulateTransform(HAL_COLOR_MODE_ADOBE_RGB, mode_string, mode_string);
+ } else if (mode_string.find("hal_dci_p3") != std::string::npos) {
+ PopulateTransform(HAL_COLOR_MODE_DCI_P3, mode_string, mode_string);
+ } else if (mode_string.find("hal_display_p3") != std::string::npos) {
+ PopulateTransform(HAL_COLOR_MODE_DISPLAY_P3, mode_string, mode_string);
+ }
+ }
+ }
+}
+
+void HWCColorMode::PopulateTransform(const android_color_mode_t &mode,
+ const std::string &color_mode,
+ const std::string &color_transform) {
+ // TODO(user): Check the substring from QDCM
+ if (color_transform.find("identity") != std::string::npos) {
+ color_mode_transform_map_[mode][HAL_COLOR_TRANSFORM_IDENTITY] = color_mode;
+ } else if (color_transform.find("arbitrary") != std::string::npos) {
+ // no color mode for arbitrary
+ } else if (color_transform.find("inverse") != std::string::npos) {
+ color_mode_transform_map_[mode][HAL_COLOR_TRANSFORM_VALUE_INVERSE] = color_mode;
+ } else if (color_transform.find("grayscale") != std::string::npos) {
+ color_mode_transform_map_[mode][HAL_COLOR_TRANSFORM_GRAYSCALE] = color_mode;
+ } else if (color_transform.find("correct_protonopia") != std::string::npos) {
+ color_mode_transform_map_[mode][HAL_COLOR_TRANSFORM_CORRECT_PROTANOPIA] = color_mode;
+ } else if (color_transform.find("correct_deuteranopia") != std::string::npos) {
+ color_mode_transform_map_[mode][HAL_COLOR_TRANSFORM_CORRECT_DEUTERANOPIA] = color_mode;
+ } else if (color_transform.find("correct_tritanopia") != std::string::npos) {
+ color_mode_transform_map_[mode][HAL_COLOR_TRANSFORM_CORRECT_TRITANOPIA] = color_mode;
+ } else {
+ color_mode_transform_map_[mode][HAL_COLOR_TRANSFORM_IDENTITY] = color_mode;
+ }
+}
+
+HWC2::Error HWCColorMode::ApplyDefaultColorMode() {
+ android_color_mode_t color_mode = HAL_COLOR_MODE_NATIVE;
+ if (color_mode_transform_map_.size() == 1U) {
+ color_mode = color_mode_transform_map_.begin()->first;
+ } else if (color_mode_transform_map_.size() > 1U) {
+ std::string default_color_mode;
+ bool found = false;
+ DisplayError error = display_intf_->GetDefaultColorMode(&default_color_mode);
+ if (error == kErrorNone) {
+ // get the default mode corresponding android_color_mode_t
+ for (auto &it_mode : color_mode_transform_map_) {
+ for (auto &it : it_mode.second) {
+ if (it.second == default_color_mode) {
+ found = true;
+ break;
+ }
+ }
+ if (found) {
+ color_mode = it_mode.first;
+ break;
+ }
+ }
+ }
+
+ // return the first andrid_color_mode_t when we encouter if not found
+ if (!found) {
+ color_mode = color_mode_transform_map_.begin()->first;
+ }
+ }
+ return SetColorMode(color_mode);
+}
+
+void HWCColorMode::Dump(std::ostringstream* os) {
+ *os << "color modes supported: ";
+ for (auto it : color_mode_transform_map_) {
+ *os << it.first <<" ";
+ }
+ *os << "current mode: " << current_color_mode_ << std::endl;
+ *os << "current transform: ";
+ for (uint32_t i = 0; i < kColorTransformMatrixCount; i++) {
+ if (i % 4 == 0) {
+ *os << std::endl;
+ }
+ *os << std::fixed << std::setprecision(2) << std::setw(6) << std::setfill(' ')
+ << color_matrix_[i] << " ";
+ }
+ *os << std::endl;
+}
+
+HWCDisplay::HWCDisplay(CoreInterface *core_intf, HWCCallbacks *callbacks, DisplayType type,
+ hwc2_display_t id, bool needs_blit, qService::QService *qservice,
+ DisplayClass display_class, BufferAllocator *buffer_allocator)
+ : core_intf_(core_intf),
+ callbacks_(callbacks),
+ type_(type),
+ id_(id),
+ needs_blit_(needs_blit),
+ qservice_(qservice),
+ display_class_(display_class) {
+ buffer_allocator_ = static_cast<HWCBufferAllocator *>(buffer_allocator);
+}
+
+int HWCDisplay::Init() {
+ DisplayError error = core_intf_->CreateDisplay(type_, this, &display_intf_);
+ if (error != kErrorNone) {
+ DLOGE("Display create failed. Error = %d display_type %d event_handler %p disp_intf %p", error,
+ type_, this, &display_intf_);
+ return -EINVAL;
+ }
+
+ validated_.reset();
+ HWCDebugHandler::Get()->GetProperty(DISABLE_HDR, &disable_hdr_handling_);
+ if (disable_hdr_handling_) {
+ DLOGI("HDR Handling disabled");
+ }
+
+ int property_swap_interval = 1;
+ HWCDebugHandler::Get()->GetProperty("debug.egl.swapinterval", &property_swap_interval);
+ if (property_swap_interval == 0) {
+ swap_interval_zero_ = true;
+ }
+
+ client_target_ = new HWCLayer(id_, buffer_allocator_);
+
+ int blit_enabled = 0;
+ HWCDebugHandler::Get()->GetProperty(DISABLE_BLIT_COMPOSITION_PROP, &blit_enabled);
+ if (needs_blit_ && blit_enabled) {
+ // TODO(user): Add blit engine when needed
+ }
+
+ error = display_intf_->GetNumVariableInfoConfigs(&num_configs_);
+ if (error != kErrorNone) {
+ DLOGE("Getting config count failed. Error = %d", error);
+ return -EINVAL;
+ }
+
+ tone_mapper_ = new HWCToneMapper(buffer_allocator_);
+
+ display_intf_->GetRefreshRateRange(&min_refresh_rate_, &max_refresh_rate_);
+ current_refresh_rate_ = max_refresh_rate_;
+
+ GetUnderScanConfig();
+ DLOGI("Display created with id: %d", id_);
+
+ return 0;
+}
+
+int HWCDisplay::Deinit() {
+ DisplayError error = core_intf_->DestroyDisplay(display_intf_);
+ if (error != kErrorNone) {
+ DLOGE("Display destroy failed. Error = %d", error);
+ return -EINVAL;
+ }
+
+ delete client_target_;
+ for (auto hwc_layer : layer_set_) {
+ delete hwc_layer;
+ }
+
+ if (color_mode_) {
+ color_mode_->DeInit();
+ delete color_mode_;
+ }
+
+ delete tone_mapper_;
+ tone_mapper_ = nullptr;
+
+ return 0;
+}
+
+// LayerStack operations
+HWC2::Error HWCDisplay::CreateLayer(hwc2_layer_t *out_layer_id) {
+ HWCLayer *layer = *layer_set_.emplace(new HWCLayer(id_, buffer_allocator_));
+ layer_map_.emplace(std::make_pair(layer->GetId(), layer));
+ *out_layer_id = layer->GetId();
+ geometry_changes_ |= GeometryChanges::kAdded;
+ validated_.reset();
+ return HWC2::Error::None;
+}
+
+HWCLayer *HWCDisplay::GetHWCLayer(hwc2_layer_t layer_id) {
+ const auto map_layer = layer_map_.find(layer_id);
+ if (map_layer == layer_map_.end()) {
+ DLOGE("[%" PRIu64 "] GetLayer(%" PRIu64 ") failed: no such layer", id_, layer_id);
+ return nullptr;
+ } else {
+ return map_layer->second;
+ }
+}
+
+HWC2::Error HWCDisplay::DestroyLayer(hwc2_layer_t layer_id) {
+ const auto map_layer = layer_map_.find(layer_id);
+ if (map_layer == layer_map_.end()) {
+ DLOGE("[%" PRIu64 "] destroyLayer(%" PRIu64 ") failed: no such layer", id_, layer_id);
+ return HWC2::Error::BadLayer;
+ }
+ const auto layer = map_layer->second;
+ layer_map_.erase(map_layer);
+ const auto z_range = layer_set_.equal_range(layer);
+ for (auto current = z_range.first; current != z_range.second; ++current) {
+ if (*current == layer) {
+ current = layer_set_.erase(current);
+ delete layer;
+ break;
+ }
+ }
+
+ geometry_changes_ |= GeometryChanges::kRemoved;
+ validated_.reset();
+ return HWC2::Error::None;
+}
+
+
+void HWCDisplay::BuildLayerStack() {
+ layer_stack_ = LayerStack();
+ display_rect_ = LayerRect();
+ metadata_refresh_rate_ = 0;
+ auto working_primaries = ColorPrimaries_BT709_5;
+ bool secure_display_active = false;
+ layer_stack_.flags.animating = animating_;
+
+ // Add one layer for fb target
+ // TODO(user): Add blit target layers
+ for (auto hwc_layer : layer_set_) {
+ Layer *layer = hwc_layer->GetSDMLayer();
+ layer->flags = {}; // Reset earlier flags
+ if (hwc_layer->GetClientRequestedCompositionType() == HWC2::Composition::Client) {
+ layer->flags.skip = true;
+ } else if (hwc_layer->GetClientRequestedCompositionType() == HWC2::Composition::SolidColor) {
+ layer->flags.solid_fill = true;
+ }
+
+ if (!hwc_layer->ValidateAndSetCSC()) {
+#ifdef FEATURE_WIDE_COLOR
+ layer->flags.skip = true;
+#endif
+ }
+
+ working_primaries = WidestPrimaries(working_primaries,
+ layer->input_buffer.color_metadata.colorPrimaries);
+
+ // set default composition as GPU for SDM
+ layer->composition = kCompositionGPU;
+
+ if (swap_interval_zero_) {
+ if (layer->input_buffer.acquire_fence_fd >= 0) {
+ close(layer->input_buffer.acquire_fence_fd);
+ layer->input_buffer.acquire_fence_fd = -1;
+ }
+ }
+
+ const private_handle_t *handle =
+ reinterpret_cast<const private_handle_t *>(layer->input_buffer.buffer_id);
+ if (handle) {
+#ifdef USE_GRALLOC1
+ if (handle->buffer_type == BUFFER_TYPE_VIDEO) {
+#else
+ if (handle->bufferType == BUFFER_TYPE_VIDEO) {
+#endif
+ layer_stack_.flags.video_present = true;
+ }
+ // TZ Protected Buffer - L1
+ if (handle->flags & private_handle_t::PRIV_FLAGS_SECURE_BUFFER) {
+ layer_stack_.flags.secure_present = true;
+ }
+ // Gralloc Usage Protected Buffer - L3 - which needs to be treated as Secure & avoid fallback
+ if (handle->flags & private_handle_t::PRIV_FLAGS_PROTECTED_BUFFER) {
+ layer_stack_.flags.secure_present = true;
+ }
+ }
+
+ if (layer->flags.skip) {
+ layer_stack_.flags.skip_present = true;
+ }
+
+ if (layer->input_buffer.flags.secure_display) {
+ secure_display_active = true;
+ }
+
+ if (hwc_layer->GetClientRequestedCompositionType() == HWC2::Composition::Cursor) {
+ // Currently we support only one HWCursor & only at top most z-order
+ if ((*layer_set_.rbegin())->GetId() == hwc_layer->GetId()) {
+ layer->flags.cursor = true;
+ layer_stack_.flags.cursor_present = true;
+ }
+ }
+
+ bool hdr_layer = layer->input_buffer.color_metadata.colorPrimaries == ColorPrimaries_BT2020 &&
+ (layer->input_buffer.color_metadata.transfer == Transfer_SMPTE_ST2084 ||
+ layer->input_buffer.color_metadata.transfer == Transfer_HLG);
+ if (hdr_layer && !disable_hdr_handling_) {
+ // dont honor HDR when its handling is disabled
+ layer->input_buffer.flags.hdr = true;
+ layer_stack_.flags.hdr_present = true;
+ }
+
+ // TODO(user): Move to a getter if this is needed at other places
+ hwc_rect_t scaled_display_frame = {INT(layer->dst_rect.left), INT(layer->dst_rect.top),
+ INT(layer->dst_rect.right), INT(layer->dst_rect.bottom)};
+ if (hwc_layer->GetGeometryChanges() & kDisplayFrame) {
+ ApplyScanAdjustment(&scaled_display_frame);
+ }
+ hwc_layer->SetLayerDisplayFrame(scaled_display_frame);
+ // SDM requires these details even for solid fill
+ if (layer->flags.solid_fill) {
+ LayerBuffer *layer_buffer = &layer->input_buffer;
+ layer_buffer->width = UINT32(layer->dst_rect.right - layer->dst_rect.left);
+ layer_buffer->height = UINT32(layer->dst_rect.bottom - layer->dst_rect.top);
+ layer_buffer->unaligned_width = layer_buffer->width;
+ layer_buffer->unaligned_height = layer_buffer->height;
+ layer_buffer->acquire_fence_fd = -1;
+ layer_buffer->release_fence_fd = -1;
+ layer->src_rect.left = 0;
+ layer->src_rect.top = 0;
+ layer->src_rect.right = layer_buffer->width;
+ layer->src_rect.bottom = layer_buffer->height;
+ }
+
+ if (layer->frame_rate > metadata_refresh_rate_) {
+ metadata_refresh_rate_ = SanitizeRefreshRate(layer->frame_rate);
+ } else {
+ layer->frame_rate = current_refresh_rate_;
+ }
+ display_rect_ = Union(display_rect_, layer->dst_rect);
+ geometry_changes_ |= hwc_layer->GetGeometryChanges();
+
+ layer->flags.updating = true;
+ if (layer_set_.size() <= kMaxLayerCount) {
+ layer->flags.updating = IsLayerUpdating(layer);
+ }
+
+ layer_stack_.layers.push_back(layer);
+ }
+
+
+#ifdef FEATURE_WIDE_COLOR
+ for (auto hwc_layer : layer_set_) {
+ auto layer = hwc_layer->GetSDMLayer();
+ if (layer->input_buffer.color_metadata.colorPrimaries != working_primaries &&
+ !hwc_layer->SupportLocalConversion(working_primaries)) {
+ layer->flags.skip = true;
+ }
+ if (layer->flags.skip) {
+ layer_stack_.flags.skip_present = true;
+ }
+ }
+#endif
+
+ // TODO(user): Set correctly when SDM supports geometry_changes as bitmask
+ layer_stack_.flags.geometry_changed = UINT32(geometry_changes_ > 0);
+ // Append client target to the layer stack
+
+ Layer *sdm_client_target = client_target_->GetSDMLayer();
+ layer_stack_.layers.push_back(sdm_client_target);
+ // fall back frame composition to GPU when client target is 10bit
+ // TODO(user): clarify the behaviour from Client(SF) and SDM Extn -
+ // when handling 10bit FBT, as it would affect blending
+ if (Is10BitFormat(sdm_client_target->input_buffer.format)) {
+ // Must fall back to client composition
+ MarkLayersForClientComposition();
+ }
+
+ // set secure display
+ SetSecureDisplay(secure_display_active);
+}
+
+void HWCDisplay::BuildSolidFillStack() {
+ layer_stack_ = LayerStack();
+ display_rect_ = LayerRect();
+
+ layer_stack_.layers.push_back(solid_fill_layer_);
+ layer_stack_.flags.geometry_changed = 1U;
+ // Append client target to the layer stack
+ layer_stack_.layers.push_back(client_target_->GetSDMLayer());
+}
+
+HWC2::Error HWCDisplay::SetLayerZOrder(hwc2_layer_t layer_id, uint32_t z) {
+ const auto map_layer = layer_map_.find(layer_id);
+ if (map_layer == layer_map_.end()) {
+ DLOGE("[%" PRIu64 "] updateLayerZ failed to find layer", id_);
+ return HWC2::Error::BadLayer;
+ }
+
+ const auto layer = map_layer->second;
+ const auto z_range = layer_set_.equal_range(layer);
+ bool layer_on_display = false;
+ for (auto current = z_range.first; current != z_range.second; ++current) {
+ if (*current == layer) {
+ if ((*current)->GetZ() == z) {
+ // Don't change anything if the Z hasn't changed
+ return HWC2::Error::None;
+ }
+ current = layer_set_.erase(current);
+ layer_on_display = true;
+ break;
+ }
+ }
+
+ if (!layer_on_display) {
+ DLOGE("[%" PRIu64 "] updateLayerZ failed to find layer on display", id_);
+ return HWC2::Error::BadLayer;
+ }
+
+ layer->SetLayerZOrder(z);
+ layer_set_.emplace(layer);
+ return HWC2::Error::None;
+}
+
+HWC2::Error HWCDisplay::SetVsyncEnabled(HWC2::Vsync enabled) {
+ DLOGV("Display ID: %d enabled: %s", id_, to_string(enabled).c_str());
+ DisplayError error = kErrorNone;
+
+ if (shutdown_pending_ || !callbacks_->VsyncCallbackRegistered()) {
+ return HWC2::Error::None;
+ }
+
+ bool state;
+ if (enabled == HWC2::Vsync::Enable)
+ state = true;
+ else if (enabled == HWC2::Vsync::Disable)
+ state = false;
+ else
+ return HWC2::Error::BadParameter;
+
+ error = display_intf_->SetVSyncState(state);
+
+ if (error != kErrorNone) {
+ if (error == kErrorShutDown) {
+ shutdown_pending_ = true;
+ return HWC2::Error::None;
+ }
+ DLOGE("Failed. enabled = %s, error = %d", to_string(enabled).c_str(), error);
+ return HWC2::Error::BadDisplay;
+ }
+
+ return HWC2::Error::None;
+}
+
+HWC2::Error HWCDisplay::SetPowerMode(HWC2::PowerMode mode) {
+ DLOGV("display = %d, mode = %s", id_, to_string(mode).c_str());
+ DisplayState state = kStateOff;
+ bool flush_on_error = flush_on_error_;
+
+ if (shutdown_pending_) {
+ return HWC2::Error::None;
+ }
+
+ switch (mode) {
+ case HWC2::PowerMode::Off:
+ // During power off, all of the buffers are released.
+ // Do not flush until a buffer is successfully submitted again.
+ flush_on_error = false;
+ state = kStateOff;
+ if (tone_mapper_) {
+ tone_mapper_->Terminate();
+ }
+ break;
+ case HWC2::PowerMode::On:
+ state = kStateOn;
+ last_power_mode_ = HWC2::PowerMode::On;
+ break;
+ case HWC2::PowerMode::Doze:
+ state = kStateDoze;
+ last_power_mode_ = HWC2::PowerMode::Doze;
+ break;
+ case HWC2::PowerMode::DozeSuspend:
+ state = kStateDozeSuspend;
+ last_power_mode_ = HWC2::PowerMode::DozeSuspend;
+ break;
+ default:
+ return HWC2::Error::BadParameter;
+ }
+
+ DisplayError error = display_intf_->SetDisplayState(state);
+ validated_.reset();
+
+ if (error == kErrorNone) {
+ flush_on_error_ = flush_on_error;
+ } else {
+ if (error == kErrorShutDown) {
+ shutdown_pending_ = true;
+ return HWC2::Error::None;
+ }
+ DLOGE("Set state failed. Error = %d", error);
+ return HWC2::Error::BadParameter;
+ }
+
+ return HWC2::Error::None;
+}
+
+HWC2::Error HWCDisplay::GetClientTargetSupport(uint32_t width, uint32_t height, int32_t format,
+ int32_t dataspace) {
+ ColorMetaData color_metadata = {};
+ if (dataspace != HAL_DATASPACE_UNKNOWN) {
+ GetColorPrimary(dataspace, &(color_metadata.colorPrimaries));
+ GetTransfer(dataspace, &(color_metadata.transfer));
+ GetRange(dataspace, &(color_metadata.range));
+ }
+
+ LayerBufferFormat sdm_format = GetSDMFormat(format, 0);
+ if (display_intf_->GetClientTargetSupport(width, height, sdm_format,
+ color_metadata) != kErrorNone) {
+ return HWC2::Error::Unsupported;
+ }
+
+ return HWC2::Error::None;
+}
+
+HWC2::Error HWCDisplay::GetColorModes(uint32_t *out_num_modes, android_color_mode_t *out_modes) {
+ if (out_modes) {
+ out_modes[0] = HAL_COLOR_MODE_NATIVE;
+ }
+ *out_num_modes = 1;
+
+ return HWC2::Error::None;
+}
+
+HWC2::Error HWCDisplay::GetDisplayConfigs(uint32_t *out_num_configs, hwc2_config_t *out_configs) {
+ if (out_configs == nullptr) {
+ *out_num_configs = num_configs_;
+ return HWC2::Error::None;
+ }
+
+ *out_num_configs = num_configs_;
+
+ for (uint32_t i = 0; i < num_configs_; i++) {
+ out_configs[i] = i;
+ }
+
+ return HWC2::Error::None;
+}
+
+HWC2::Error HWCDisplay::GetDisplayAttribute(hwc2_config_t config, HWC2::Attribute attribute,
+ int32_t *out_value) {
+ DisplayConfigVariableInfo variable_config;
+ // Get display attributes from config index only if resolution switch is supported.
+ // Otherwise always send mixer attributes. This is to support destination scaler.
+ if (num_configs_ > 1) {
+ if (GetDisplayAttributesForConfig(INT(config), &variable_config) != kErrorNone) {
+ DLOGE("Get variable config failed");
+ return HWC2::Error::BadDisplay;
+ }
+ } else {
+ if (display_intf_->GetFrameBufferConfig(&variable_config) != kErrorNone) {
+ DLOGV("Get variable config failed");
+ return HWC2::Error::BadDisplay;
+ }
+ }
+
+ switch (attribute) {
+ case HWC2::Attribute::VsyncPeriod:
+ *out_value = INT32(variable_config.vsync_period_ns);
+ break;
+ case HWC2::Attribute::Width:
+ *out_value = INT32(variable_config.x_pixels);
+ break;
+ case HWC2::Attribute::Height:
+ *out_value = INT32(variable_config.y_pixels);
+ break;
+ case HWC2::Attribute::DpiX:
+ *out_value = INT32(variable_config.x_dpi * 1000.0f);
+ break;
+ case HWC2::Attribute::DpiY:
+ *out_value = INT32(variable_config.y_dpi * 1000.0f);
+ break;
+ default:
+ DLOGW("Spurious attribute type = %s", to_string(attribute).c_str());
+ *out_value = -1;
+ return HWC2::Error::BadConfig;
+ }
+
+ return HWC2::Error::None;
+}
+
+HWC2::Error HWCDisplay::GetDisplayName(uint32_t *out_size, char *out_name) {
+ // TODO(user): Get panel name and EDID name and populate it here
+ if (out_name == nullptr) {
+ *out_size = 32;
+ } else {
+ std::string name;
+ switch (id_) {
+ case HWC_DISPLAY_PRIMARY:
+ name = "Primary Display";
+ break;
+ case HWC_DISPLAY_EXTERNAL:
+ name = "External Display";
+ break;
+ case HWC_DISPLAY_VIRTUAL:
+ name = "Virtual Display";
+ break;
+ default:
+ name = "Unknown";
+ break;
+ }
+ std::strncpy(out_name, name.c_str(), name.size());
+ *out_size = UINT32(name.size());
+ }
+ return HWC2::Error::None;
+}
+
+HWC2::Error HWCDisplay::GetDisplayType(int32_t *out_type) {
+ if (out_type != nullptr) {
+ if (id_ == HWC_DISPLAY_VIRTUAL) {
+ *out_type = HWC2_DISPLAY_TYPE_VIRTUAL;
+ } else {
+ *out_type = HWC2_DISPLAY_TYPE_PHYSICAL;
+ }
+ return HWC2::Error::None;
+ } else {
+ return HWC2::Error::BadParameter;
+ }
+}
+
+HWC2::Error HWCDisplay::GetActiveConfig(hwc2_config_t *out_config) {
+ if (out_config == nullptr) {
+ return HWC2::Error::BadDisplay;
+ }
+
+ uint32_t active_index = 0;
+ if (GetActiveDisplayConfig(&active_index) != kErrorNone) {
+ return HWC2::Error::BadConfig;
+ }
+
+ *out_config = active_index;
+
+ return HWC2::Error::None;
+}
+
+HWC2::Error HWCDisplay::SetClientTarget(buffer_handle_t target, int32_t acquire_fence,
+ int32_t dataspace, hwc_region_t damage) {
+ // TODO(user): SurfaceFlinger gives us a null pointer here when doing full SDE composition
+ // The error is problematic for layer caching as it would overwrite our cached client target.
+ // Reported bug 28569722 to resolve this.
+ // For now, continue to use the last valid buffer reported to us for layer caching.
+ if (target == nullptr) {
+ return HWC2::Error::None;
+ }
+
+ if (acquire_fence == 0) {
+ DLOGE("acquire_fence is zero");
+ return HWC2::Error::BadParameter;
+ }
+
+ client_target_->SetLayerBuffer(target, acquire_fence);
+ client_target_->SetLayerSurfaceDamage(damage);
+ if (client_target_->GetLayerDataspace() != dataspace) {
+ client_target_->SetLayerDataspace(dataspace);
+ Layer *sdm_layer = client_target_->GetSDMLayer();
+ // Data space would be validated at GetClientTargetSupport, so just use here.
+ sdm::GetSDMColorSpace(dataspace, &sdm_layer->input_buffer.color_metadata);
+ }
+
+ return HWC2::Error::None;
+}
+
+HWC2::Error HWCDisplay::SetActiveConfig(hwc2_config_t config) {
+ if (SetActiveDisplayConfig(config) != kErrorNone) {
+ return HWC2::Error::BadConfig;
+ }
+
+ validated_.reset();
+ return HWC2::Error::None;
+}
+
+DisplayError HWCDisplay::SetMixerResolution(uint32_t width, uint32_t height) {
+ return kErrorNotSupported;
+}
+
+void HWCDisplay::SetFrameDumpConfig(uint32_t count, uint32_t bit_mask_layer_type) {
+ dump_frame_count_ = count;
+ dump_frame_index_ = 0;
+ dump_input_layers_ = ((bit_mask_layer_type & (1 << INPUT_LAYER_DUMP)) != 0);
+
+ if (tone_mapper_) {
+ tone_mapper_->SetFrameDumpConfig(count);
+ }
+
+ DLOGI("num_frame_dump %d, input_layer_dump_enable %d", dump_frame_count_, dump_input_layers_);
+ validated_.reset();
+}
+
+HWC2::PowerMode HWCDisplay::GetLastPowerMode() {
+ return last_power_mode_;
+}
+
+DisplayError HWCDisplay::VSync(const DisplayEventVSync &vsync) {
+ callbacks_->Vsync(id_, vsync.timestamp);
+ return kErrorNone;
+}
+
+DisplayError HWCDisplay::Refresh() {
+ return kErrorNotSupported;
+}
+
+DisplayError HWCDisplay::CECMessage(char *message) {
+ if (qservice_) {
+ qservice_->onCECMessageReceived(message, 0);
+ } else {
+ DLOGW("Qservice instance not available.");
+ }
+
+ return kErrorNone;
+}
+
+DisplayError HWCDisplay::HandleEvent(DisplayEvent event) {
+ switch (event) {
+ case kIdleTimeout:
+ break;
+ case kThermalEvent:
+ validated_.reset();
+ break;
+ default:
+ DLOGW("Unknown event: %d", event);
+ break;
+ }
+
+ return kErrorNone;
+}
+
+HWC2::Error HWCDisplay::PrepareLayerStack(uint32_t *out_num_types, uint32_t *out_num_requests) {
+ layer_changes_.clear();
+ layer_requests_.clear();
+ if (shutdown_pending_) {
+ return HWC2::Error::BadDisplay;
+ }
+
+ if (!skip_prepare_) {
+ DisplayError error = display_intf_->Prepare(&layer_stack_);
+ if (error != kErrorNone) {
+ if (error == kErrorShutDown) {
+ shutdown_pending_ = true;
+ } else if (error != kErrorPermission) {
+ DLOGE("Prepare failed. Error = %d", error);
+ // To prevent surfaceflinger infinite wait, flush the previous frame during Commit()
+ // so that previous buffer and fences are released, and override the error.
+ flush_ = true;
+ }
+ return HWC2::Error::BadDisplay;
+ } else {
+ validated_.set(type_);
+ }
+ } else {
+ // Skip is not set
+ MarkLayersForGPUBypass();
+ skip_prepare_ = false;
+ DLOGI("SecureDisplay %s, Skip Prepare/Commit and Flush",
+ secure_display_active_ ? "Starting" : "Stopping");
+ flush_ = true;
+ }
+
+ for (auto hwc_layer : layer_set_) {
+ Layer *layer = hwc_layer->GetSDMLayer();
+ LayerComposition &composition = layer->composition;
+
+ if ((composition == kCompositionSDE) || (composition == kCompositionHybrid) ||
+ (composition == kCompositionBlit)) {
+ layer_requests_[hwc_layer->GetId()] = HWC2::LayerRequest::ClearClientTarget;
+ }
+
+ HWC2::Composition requested_composition = hwc_layer->GetClientRequestedCompositionType();
+ // Set SDM composition to HWC2 type in HWCLayer
+ hwc_layer->SetComposition(composition);
+ HWC2::Composition device_composition = hwc_layer->GetDeviceSelectedCompositionType();
+ // Update the changes list only if the requested composition is different from SDM comp type
+ // TODO(user): Take Care of other comptypes(BLIT)
+ if (requested_composition != device_composition) {
+ layer_changes_[hwc_layer->GetId()] = device_composition;
+ }
+ hwc_layer->ResetValidation();
+ }
+ client_target_->ResetValidation();
+ *out_num_types = UINT32(layer_changes_.size());
+ *out_num_requests = UINT32(layer_requests_.size());
+ skip_validate_ = false;
+ if (*out_num_types > 0) {
+ return HWC2::Error::HasChanges;
+ } else {
+ return HWC2::Error::None;
+ }
+}
+
+HWC2::Error HWCDisplay::AcceptDisplayChanges() {
+ if (layer_set_.empty()) {
+ return HWC2::Error::None;
+ }
+
+ if (!validated_.test(type_)) {
+ return HWC2::Error::NotValidated;
+ }
+
+ for (const auto& change : layer_changes_) {
+ auto hwc_layer = layer_map_[change.first];
+ auto composition = change.second;
+ if (hwc_layer != nullptr) {
+ hwc_layer->UpdateClientCompositionType(composition);
+ } else {
+ DLOGW("Invalid layer: %" PRIu64, change.first);
+ }
+ }
+ return HWC2::Error::None;
+}
+
+HWC2::Error HWCDisplay::GetChangedCompositionTypes(uint32_t *out_num_elements,
+ hwc2_layer_t *out_layers, int32_t *out_types) {
+ if (layer_set_.empty()) {
+ return HWC2::Error::None;
+ }
+
+ if (!validated_.test(type_)) {
+ DLOGW("Display is not validated");
+ return HWC2::Error::NotValidated;
+ }
+
+ *out_num_elements = UINT32(layer_changes_.size());
+ if (out_layers != nullptr && out_types != nullptr) {
+ int i = 0;
+ for (auto change : layer_changes_) {
+ out_layers[i] = change.first;
+ out_types[i] = INT32(change.second);
+ i++;
+ }
+ }
+ return HWC2::Error::None;
+}
+
+HWC2::Error HWCDisplay::GetReleaseFences(uint32_t *out_num_elements, hwc2_layer_t *out_layers,
+ int32_t *out_fences) {
+ if (out_layers != nullptr && out_fences != nullptr) {
+ int i = 0;
+ for (auto hwc_layer : layer_set_) {
+ out_layers[i] = hwc_layer->GetId();
+ out_fences[i] = hwc_layer->PopReleaseFence();
+ i++;
+ }
+ }
+ *out_num_elements = UINT32(layer_set_.size());
+ return HWC2::Error::None;
+}
+
+HWC2::Error HWCDisplay::GetDisplayRequests(int32_t *out_display_requests,
+ uint32_t *out_num_elements, hwc2_layer_t *out_layers,
+ int32_t *out_layer_requests) {
+ if (layer_set_.empty()) {
+ return HWC2::Error::None;
+ }
+
+ // No display requests for now
+ // Use for sharing blit buffers and
+ // writing wfd buffer directly to output if there is full GPU composition
+ // and no color conversion needed
+ if (!validated_.test(type_)) {
+ DLOGW("Display is not validated");
+ return HWC2::Error::NotValidated;
+ }
+
+ *out_display_requests = 0;
+ *out_num_elements = UINT32(layer_requests_.size());
+ if (out_layers != nullptr && out_layer_requests != nullptr) {
+ int i = 0;
+ for (auto &request : layer_requests_) {
+ out_layers[i] = request.first;
+ out_layer_requests[i] = INT32(request.second);
+ i++;
+ }
+ }
+
+ auto client_target_layer = client_target_->GetSDMLayer();
+ if (client_target_layer->request.flags.flip_buffer) {
+ *out_display_requests = INT32(HWC2::DisplayRequest::FlipClientTarget);
+ }
+
+ return HWC2::Error::None;
+}
+
+HWC2::Error HWCDisplay::GetHdrCapabilities(uint32_t *out_num_types, int32_t *out_types,
+ float *out_max_luminance,
+ float *out_max_average_luminance,
+ float *out_min_luminance) {
+ DisplayConfigFixedInfo fixed_info = {};
+ display_intf_->GetConfig(&fixed_info);
+
+ if (!fixed_info.hdr_supported) {
+ *out_num_types = 0;
+ DLOGI("HDR is not supported");
+ return HWC2::Error::None;
+ }
+
+ if (out_types == nullptr) {
+ // 1(now) - because we support only HDR10, change when HLG & DOLBY vision are supported
+ *out_num_types = 1;
+ } else {
+ // Only HDR10 supported
+ *out_types = HAL_HDR_HDR10;
+ static const float kLuminanceFactor = 10000.0;
+ // luminance is expressed in the unit of 0.0001 cd/m2, convert it to 1cd/m2.
+ *out_max_luminance = FLOAT(fixed_info.max_luminance)/kLuminanceFactor;
+ *out_max_average_luminance = FLOAT(fixed_info.average_luminance)/kLuminanceFactor;
+ *out_min_luminance = FLOAT(fixed_info.min_luminance)/kLuminanceFactor;
+ }
+
+ return HWC2::Error::None;
+}
+
+
+HWC2::Error HWCDisplay::CommitLayerStack(void) {
+ if (shutdown_pending_ || layer_set_.empty()) {
+ return HWC2::Error::None;
+ }
+
+ if (skip_validate_ && !CanSkipValidate()) {
+ validated_.reset(type_);
+ }
+
+ if (!validated_.test(type_)) {
+ DLOGV_IF(kTagClient, "Display %d is not validated", id_);
+ return HWC2::Error::NotValidated;
+ }
+
+ DumpInputBuffers();
+
+ if (!flush_) {
+ DisplayError error = kErrorUndefined;
+ int status = 0;
+ if (tone_mapper_) {
+ if (layer_stack_.flags.hdr_present) {
+ status = tone_mapper_->HandleToneMap(&layer_stack_);
+ if (status != 0) {
+ DLOGE("Error handling HDR in ToneMapper");
+ }
+ } else {
+ tone_mapper_->Terminate();
+ }
+ }
+ error = display_intf_->Commit(&layer_stack_);
+
+ if (error == kErrorNone) {
+ // A commit is successfully submitted, start flushing on failure now onwards.
+ flush_on_error_ = true;
+ } else {
+ if (error == kErrorShutDown) {
+ shutdown_pending_ = true;
+ return HWC2::Error::Unsupported;
+ } else if (error == kErrorNotValidated) {
+ validated_.reset(type_);
+ return HWC2::Error::NotValidated;
+ } else if (error != kErrorPermission) {
+ DLOGE("Commit failed. Error = %d", error);
+ // To prevent surfaceflinger infinite wait, flush the previous frame during Commit()
+ // so that previous buffer and fences are released, and override the error.
+ flush_ = true;
+ }
+ }
+ }
+
+ skip_validate_ = true;
+ return HWC2::Error::None;
+}
+
+HWC2::Error HWCDisplay::PostCommitLayerStack(int32_t *out_retire_fence) {
+ auto status = HWC2::Error::None;
+
+ // Do no call flush on errors, if a successful buffer is never submitted.
+ if (flush_ && flush_on_error_) {
+ display_intf_->Flush();
+ validated_.reset();
+ }
+
+ if (tone_mapper_ && tone_mapper_->IsActive()) {
+ tone_mapper_->PostCommit(&layer_stack_);
+ }
+
+ // TODO(user): No way to set the client target release fence on SF
+ int32_t &client_target_release_fence =
+ client_target_->GetSDMLayer()->input_buffer.release_fence_fd;
+ if (client_target_release_fence >= 0) {
+ close(client_target_release_fence);
+ client_target_release_fence = -1;
+ }
+ client_target_->ResetGeometryChanges();
+
+ for (auto hwc_layer : layer_set_) {
+ hwc_layer->ResetGeometryChanges();
+ Layer *layer = hwc_layer->GetSDMLayer();
+ LayerBuffer *layer_buffer = &layer->input_buffer;
+
+ if (!flush_) {
+ // If swapinterval property is set to 0 or for single buffer layers, do not update f/w
+ // release fences and discard fences from driver
+ if (swap_interval_zero_ || layer->flags.single_buffer) {
+ close(layer_buffer->release_fence_fd);
+ } else if (layer->composition != kCompositionGPU) {
+ hwc_layer->PushReleaseFence(layer_buffer->release_fence_fd);
+ } else {
+ hwc_layer->PushReleaseFence(-1);
+ }
+ } else {
+ // In case of flush, we don't return an error to f/w, so it will get a release fence out of
+ // the hwc_layer's release fence queue. We should push a -1 to preserve release fence
+ // circulation semantics.
+ hwc_layer->PushReleaseFence(-1);
+ }
+
+ layer_buffer->release_fence_fd = -1;
+ if (layer_buffer->acquire_fence_fd >= 0) {
+ close(layer_buffer->acquire_fence_fd);
+ layer_buffer->acquire_fence_fd = -1;
+ }
+ }
+
+ *out_retire_fence = -1;
+ if (!flush_) {
+ // if swapinterval property is set to 0 then close and reset the list retire fence
+ if (swap_interval_zero_) {
+ close(layer_stack_.retire_fence_fd);
+ layer_stack_.retire_fence_fd = -1;
+ }
+ *out_retire_fence = layer_stack_.retire_fence_fd;
+ layer_stack_.retire_fence_fd = -1;
+
+ if (dump_frame_count_) {
+ dump_frame_count_--;
+ dump_frame_index_++;
+ }
+ }
+
+ geometry_changes_ = GeometryChanges::kNone;
+ flush_ = false;
+
+ ClearRequestFlags();
+
+ return status;
+}
+
+void HWCDisplay::SetIdleTimeoutMs(uint32_t timeout_ms) {
+ return;
+}
+
+DisplayError HWCDisplay::SetMaxMixerStages(uint32_t max_mixer_stages) {
+ DisplayError error = kErrorNone;
+
+ if (display_intf_) {
+ error = display_intf_->SetMaxMixerStages(max_mixer_stages);
+ validated_.reset();
+ }
+
+ return error;
+}
+
+LayerBufferFormat HWCDisplay::GetSDMFormat(const int32_t &source, const int flags) {
+ LayerBufferFormat format = kFormatInvalid;
+ if (flags & private_handle_t::PRIV_FLAGS_UBWC_ALIGNED) {
+ switch (source) {
+ case HAL_PIXEL_FORMAT_RGBA_8888:
+ format = kFormatRGBA8888Ubwc;
+ break;
+ case HAL_PIXEL_FORMAT_RGBX_8888:
+ format = kFormatRGBX8888Ubwc;
+ break;
+ case HAL_PIXEL_FORMAT_BGR_565:
+ format = kFormatBGR565Ubwc;
+ break;
+ case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
+ case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC:
+ case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
+ format = kFormatYCbCr420SPVenusUbwc;
+ break;
+ case HAL_PIXEL_FORMAT_RGBA_1010102:
+ format = kFormatRGBA1010102Ubwc;
+ break;
+ case HAL_PIXEL_FORMAT_RGBX_1010102:
+ format = kFormatRGBX1010102Ubwc;
+ break;
+ case HAL_PIXEL_FORMAT_YCbCr_420_TP10_UBWC:
+ format = kFormatYCbCr420TP10Ubwc;
+ break;
+ case HAL_PIXEL_FORMAT_YCbCr_420_P010_UBWC:
+ format = kFormatYCbCr420P010Ubwc;
+ break;
+ default:
+ DLOGE("Unsupported format type for UBWC %d", source);
+ return kFormatInvalid;
+ }
+ return format;
+ }
+
+ switch (source) {
+ case HAL_PIXEL_FORMAT_RGBA_8888:
+ format = kFormatRGBA8888;
+ break;
+ case HAL_PIXEL_FORMAT_RGBA_5551:
+ format = kFormatRGBA5551;
+ break;
+ case HAL_PIXEL_FORMAT_RGBA_4444:
+ format = kFormatRGBA4444;
+ break;
+ case HAL_PIXEL_FORMAT_BGRA_8888:
+ format = kFormatBGRA8888;
+ break;
+ case HAL_PIXEL_FORMAT_RGBX_8888:
+ format = kFormatRGBX8888;
+ break;
+ case HAL_PIXEL_FORMAT_BGRX_8888:
+ format = kFormatBGRX8888;
+ break;
+ case HAL_PIXEL_FORMAT_RGB_888:
+ format = kFormatRGB888;
+ break;
+ case HAL_PIXEL_FORMAT_RGB_565:
+ format = kFormatRGB565;
+ break;
+ case HAL_PIXEL_FORMAT_BGR_565:
+ format = kFormatBGR565;
+ break;
+ case HAL_PIXEL_FORMAT_BGR_888:
+ format = kFormatBGR888;
+ break;
+ case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
+ case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
+ format = kFormatYCbCr420SemiPlanarVenus;
+ break;
+ case HAL_PIXEL_FORMAT_YCrCb_420_SP_VENUS:
+ format = kFormatYCrCb420SemiPlanarVenus;
+ break;
+ case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC:
+ format = kFormatYCbCr420SPVenusUbwc;
+ break;
+ case HAL_PIXEL_FORMAT_YV12:
+ format = kFormatYCrCb420PlanarStride16;
+ break;
+ case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+ format = kFormatYCrCb420SemiPlanar;
+ break;
+ case HAL_PIXEL_FORMAT_YCbCr_420_SP:
+ format = kFormatYCbCr420SemiPlanar;
+ break;
+ case HAL_PIXEL_FORMAT_YCbCr_422_SP:
+ format = kFormatYCbCr422H2V1SemiPlanar;
+ break;
+ case HAL_PIXEL_FORMAT_YCbCr_422_I:
+ format = kFormatYCbCr422H2V1Packed;
+ break;
+ case HAL_PIXEL_FORMAT_CbYCrY_422_I:
+ format = kFormatCbYCrY422H2V1Packed;
+ break;
+ case HAL_PIXEL_FORMAT_RGBA_1010102:
+ format = kFormatRGBA1010102;
+ break;
+ case HAL_PIXEL_FORMAT_ARGB_2101010:
+ format = kFormatARGB2101010;
+ break;
+ case HAL_PIXEL_FORMAT_RGBX_1010102:
+ format = kFormatRGBX1010102;
+ break;
+ case HAL_PIXEL_FORMAT_XRGB_2101010:
+ format = kFormatXRGB2101010;
+ break;
+ case HAL_PIXEL_FORMAT_BGRA_1010102:
+ format = kFormatBGRA1010102;
+ break;
+ case HAL_PIXEL_FORMAT_ABGR_2101010:
+ format = kFormatABGR2101010;
+ break;
+ case HAL_PIXEL_FORMAT_BGRX_1010102:
+ format = kFormatBGRX1010102;
+ break;
+ case HAL_PIXEL_FORMAT_XBGR_2101010:
+ format = kFormatXBGR2101010;
+ break;
+ case HAL_PIXEL_FORMAT_YCbCr_420_P010:
+ format = kFormatYCbCr420P010;
+ break;
+ case HAL_PIXEL_FORMAT_YCbCr_420_TP10_UBWC:
+ format = kFormatYCbCr420TP10Ubwc;
+ break;
+ case HAL_PIXEL_FORMAT_YCbCr_420_P010_UBWC:
+ format = kFormatYCbCr420P010Ubwc;
+ break;
+ default:
+ DLOGW("Unsupported format type = %d", source);
+ return kFormatInvalid;
+ }
+
+ return format;
+}
+
+void HWCDisplay::DumpInputBuffers() {
+ char dir_path[PATH_MAX];
+
+ if (!dump_frame_count_ || flush_ || !dump_input_layers_) {
+ return;
+ }
+
+ DLOGI("dump_frame_count %d dump_input_layers %d", dump_frame_count_, dump_input_layers_);
+ snprintf(dir_path, sizeof(dir_path), "%s/frame_dump_%s", HWCDebugHandler::DumpDir(),
+ GetDisplayString());
+
+ if (mkdir(dir_path, 0777) != 0 && errno != EEXIST) {
+ DLOGW("Failed to create %s directory errno = %d, desc = %s", dir_path, errno, strerror(errno));
+ return;
+ }
+
+ // if directory exists already, need to explicitly change the permission.
+ if (errno == EEXIST && chmod(dir_path, 0777) != 0) {
+ DLOGW("Failed to change permissions on %s directory", dir_path);
+ return;
+ }
+
+ for (uint32_t i = 0; i < layer_stack_.layers.size(); i++) {
+ auto layer = layer_stack_.layers.at(i);
+ const private_handle_t *pvt_handle =
+ reinterpret_cast<const private_handle_t *>(layer->input_buffer.buffer_id);
+ auto acquire_fence_fd = layer->input_buffer.acquire_fence_fd;
+
+ if (acquire_fence_fd >= 0) {
+ int error = sync_wait(acquire_fence_fd, 1000);
+ if (error < 0) {
+ DLOGW("sync_wait error errno = %d, desc = %s", errno, strerror(errno));
+ return;
+ }
+ }
+
+ DLOGI("Dump layer[%d] of %d pvt_handle %x pvt_handle->base %x", i, layer_stack_.layers.size(),
+ pvt_handle, pvt_handle? pvt_handle->base : 0);
+
+ if (!pvt_handle) {
+ DLOGE("Buffer handle is null");
+ return;
+ }
+
+ if (!pvt_handle->base) {
+ DisplayError error = buffer_allocator_->MapBuffer(pvt_handle, -1);
+ if (error != kErrorNone) {
+ DLOGE("Failed to map buffer, error = %d", error);
+ return;
+ }
+ }
+
+ char dump_file_name[PATH_MAX];
+ size_t result = 0;
+
+ snprintf(dump_file_name, sizeof(dump_file_name), "%s/input_layer%d_%dx%d_%s_frame%d.raw",
+ dir_path, i, pvt_handle->width, pvt_handle->height,
+ qdutils::GetHALPixelFormatString(pvt_handle->format), dump_frame_index_);
+
+ FILE *fp = fopen(dump_file_name, "w+");
+ if (fp) {
+ result = fwrite(reinterpret_cast<void *>(pvt_handle->base), pvt_handle->size, 1, fp);
+ fclose(fp);
+ }
+
+ int release_fence = -1;
+ DisplayError error = buffer_allocator_->UnmapBuffer(pvt_handle, &release_fence);
+ if (error != kErrorNone) {
+ DLOGE("Failed to unmap buffer, error = %d", error);
+ return;
+ }
+
+ DLOGI("Frame Dump %s: is %s", dump_file_name, result ? "Successful" : "Failed");
+ }
+}
+
+void HWCDisplay::DumpOutputBuffer(const BufferInfo &buffer_info, void *base, int fence) {
+ char dir_path[PATH_MAX];
+
+ snprintf(dir_path, sizeof(dir_path), "%s/frame_dump_%s", HWCDebugHandler::DumpDir(),
+ GetDisplayString());
+
+ if (mkdir(dir_path, 777) != 0 && errno != EEXIST) {
+ DLOGW("Failed to create %s directory errno = %d, desc = %s", dir_path, errno, strerror(errno));
+ return;
+ }
+
+ // if directory exists already, need to explicitly change the permission.
+ if (errno == EEXIST && chmod(dir_path, 0777) != 0) {
+ DLOGW("Failed to change permissions on %s directory", dir_path);
+ return;
+ }
+
+ if (base) {
+ char dump_file_name[PATH_MAX];
+ size_t result = 0;
+
+ if (fence >= 0) {
+ int error = sync_wait(fence, 1000);
+ if (error < 0) {
+ DLOGW("sync_wait error errno = %d, desc = %s", errno, strerror(errno));
+ return;
+ }
+ }
+
+ snprintf(dump_file_name, sizeof(dump_file_name), "%s/output_layer_%dx%d_%s_frame%d.raw",
+ dir_path, buffer_info.buffer_config.width, buffer_info.buffer_config.height,
+ GetFormatString(buffer_info.buffer_config.format), dump_frame_index_);
+
+ FILE *fp = fopen(dump_file_name, "w+");
+ if (fp) {
+ result = fwrite(base, buffer_info.alloc_buffer_info.size, 1, fp);
+ fclose(fp);
+ }
+
+ DLOGI("Frame Dump of %s is %s", dump_file_name, result ? "Successful" : "Failed");
+ }
+}
+
+const char *HWCDisplay::GetDisplayString() {
+ switch (type_) {
+ case kPrimary:
+ return "primary";
+ case kHDMI:
+ return "hdmi";
+ case kVirtual:
+ return "virtual";
+ default:
+ return "invalid";
+ }
+}
+
+int HWCDisplay::SetFrameBufferResolution(uint32_t x_pixels, uint32_t y_pixels) {
+ if (x_pixels <= 0 || y_pixels <= 0) {
+ DLOGW("Unsupported config: x_pixels=%d, y_pixels=%d", x_pixels, y_pixels);
+ return -EINVAL;
+ }
+
+ DisplayConfigVariableInfo fb_config;
+ DisplayError error = display_intf_->GetFrameBufferConfig(&fb_config);
+ if (error != kErrorNone) {
+ DLOGV("Get frame buffer config failed. Error = %d", error);
+ return -EINVAL;
+ }
+
+ fb_config.x_pixels = x_pixels;
+ fb_config.y_pixels = y_pixels;
+
+ error = display_intf_->SetFrameBufferConfig(fb_config);
+ if (error != kErrorNone) {
+ DLOGV("Set frame buffer config failed. Error = %d", error);
+ return -EINVAL;
+ }
+
+ // Create rects to represent the new source and destination crops
+ LayerRect crop = LayerRect(0, 0, FLOAT(x_pixels), FLOAT(y_pixels));
+ hwc_rect_t scaled_display_frame = {0, 0, INT(x_pixels), INT(y_pixels)};
+ ApplyScanAdjustment(&scaled_display_frame);
+ client_target_->SetLayerDisplayFrame(scaled_display_frame);
+
+ auto client_target_layer = client_target_->GetSDMLayer();
+ client_target_layer->src_rect = crop;
+
+ int aligned_width;
+ int aligned_height;
+ uint32_t usage = GRALLOC_USAGE_HW_FB;
+ int format = HAL_PIXEL_FORMAT_RGBA_8888;
+ int ubwc_disabled = 0;
+ int flags = 0;
+
+ // By default UBWC is enabled and below property is global enable/disable for all
+ // buffers allocated through gralloc , including framebuffer targets.
+ HWCDebugHandler::Get()->GetProperty(DISABLE_UBWC_PROP, &ubwc_disabled);
+ if (!ubwc_disabled) {
+ usage |= GRALLOC_USAGE_PRIVATE_ALLOC_UBWC;
+ flags |= private_handle_t::PRIV_FLAGS_UBWC_ALIGNED;
+ }
+
+#ifdef USE_GRALLOC1
+ buffer_allocator_->GetAlignedWidthAndHeight(INT(x_pixels), INT(y_pixels), format, usage,
+ &aligned_width, &aligned_height);
+#else
+ AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(INT(x_pixels), INT(y_pixels), format,
+ INT(usage), aligned_width, aligned_height);
+#endif
+
+ // TODO(user): How does the dirty region get set on the client target? File bug on Google
+ client_target_layer->composition = kCompositionGPUTarget;
+ client_target_layer->input_buffer.format = GetSDMFormat(format, flags);
+ client_target_layer->input_buffer.width = UINT32(aligned_width);
+ client_target_layer->input_buffer.height = UINT32(aligned_height);
+ client_target_layer->input_buffer.unaligned_width = x_pixels;
+ client_target_layer->input_buffer.unaligned_height = y_pixels;
+ client_target_layer->plane_alpha = 255;
+
+ DLOGI("New framebuffer resolution (%dx%d)", fb_config.x_pixels, fb_config.y_pixels);
+
+ return 0;
+}
+
+void HWCDisplay::GetFrameBufferResolution(uint32_t *x_pixels, uint32_t *y_pixels) {
+ DisplayConfigVariableInfo fb_config;
+ display_intf_->GetFrameBufferConfig(&fb_config);
+
+ *x_pixels = fb_config.x_pixels;
+ *y_pixels = fb_config.y_pixels;
+}
+
+DisplayError HWCDisplay::GetMixerResolution(uint32_t *x_pixels, uint32_t *y_pixels) {
+ return display_intf_->GetMixerResolution(x_pixels, y_pixels);
+}
+
+void HWCDisplay::GetPanelResolution(uint32_t *x_pixels, uint32_t *y_pixels) {
+ DisplayConfigVariableInfo display_config;
+ uint32_t active_index = 0;
+
+ display_intf_->GetActiveConfig(&active_index);
+ display_intf_->GetConfig(active_index, &display_config);
+
+ *x_pixels = display_config.x_pixels;
+ *y_pixels = display_config.y_pixels;
+}
+
+int HWCDisplay::SetDisplayStatus(DisplayStatus display_status) {
+ int status = 0;
+
+ switch (display_status) {
+ case kDisplayStatusResume:
+ display_paused_ = false;
+ case kDisplayStatusOnline:
+ status = INT32(SetPowerMode(HWC2::PowerMode::On));
+ break;
+ case kDisplayStatusPause:
+ display_paused_ = true;
+ case kDisplayStatusOffline:
+ status = INT32(SetPowerMode(HWC2::PowerMode::Off));
+ break;
+ default:
+ DLOGW("Invalid display status %d", display_status);
+ return -EINVAL;
+ }
+
+ if (display_status == kDisplayStatusResume || display_status == kDisplayStatusPause) {
+ callbacks_->Refresh(HWC_DISPLAY_PRIMARY);
+ validated_.reset();
+ }
+
+ return status;
+}
+
+HWC2::Error HWCDisplay::SetCursorPosition(hwc2_layer_t layer, int x, int y) {
+ if (shutdown_pending_) {
+ return HWC2::Error::None;
+ }
+
+ HWCLayer *hwc_layer = GetHWCLayer(layer);
+ if (hwc_layer == nullptr) {
+ return HWC2::Error::BadLayer;
+ }
+ if (hwc_layer->GetDeviceSelectedCompositionType() != HWC2::Composition::Cursor) {
+ return HWC2::Error::None;
+ }
+ if (!skip_validate_ && validated_.test(type_)) {
+ // the device is currently in the middle of the validate/present sequence,
+ // cannot set the Position(as per HWC2 spec)
+ return HWC2::Error::NotValidated;
+ }
+
+ DisplayState state;
+ if (display_intf_->GetDisplayState(&state) == kErrorNone) {
+ if (state != kStateOn) {
+ return HWC2::Error::None;
+ }
+ }
+
+ // TODO(user): HWC1.5 was not letting SetCursorPosition before validateDisplay,
+ // but HWC2.0 doesn't let setting cursor position after validate before present.
+ // Need to revisit.
+
+ auto error = display_intf_->SetCursorPosition(x, y);
+ if (error != kErrorNone) {
+ if (error == kErrorShutDown) {
+ shutdown_pending_ = true;
+ return HWC2::Error::None;
+ }
+
+ DLOGE("Failed for x = %d y = %d, Error = %d", x, y, error);
+ return HWC2::Error::BadDisplay;
+ }
+
+ return HWC2::Error::None;
+}
+
+int HWCDisplay::OnMinHdcpEncryptionLevelChange(uint32_t min_enc_level) {
+ DisplayError error = display_intf_->OnMinHdcpEncryptionLevelChange(min_enc_level);
+ if (error != kErrorNone) {
+ DLOGE("Failed. Error = %d", error);
+ return -1;
+ }
+
+ validated_.reset();
+ return 0;
+}
+
+void HWCDisplay::MarkLayersForGPUBypass() {
+ for (auto hwc_layer : layer_set_) {
+ auto layer = hwc_layer->GetSDMLayer();
+ layer->composition = kCompositionSDE;
+ }
+ validated_.set(type_);
+}
+
+void HWCDisplay::MarkLayersForClientComposition() {
+ // ClientComposition - GPU comp, to achieve this, set skip flag so that
+ // SDM does not handle this layer and hwc_layer composition will be
+ // set correctly at the end of Prepare.
+ DLOGV_IF(kTagClient, "HWC Layers marked for GPU comp");
+ for (auto hwc_layer : layer_set_) {
+ Layer *layer = hwc_layer->GetSDMLayer();
+ layer->flags.skip = true;
+ }
+ layer_stack_.flags.skip_present = true;
+}
+
+void HWCDisplay::ApplyScanAdjustment(hwc_rect_t *display_frame) {
+}
+
+int HWCDisplay::SetPanelBrightness(int level) {
+ int ret = 0;
+ if (display_intf_) {
+ ret = display_intf_->SetPanelBrightness(level);
+ validated_.reset();
+ } else {
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+int HWCDisplay::GetPanelBrightness(int *level) {
+ return display_intf_->GetPanelBrightness(level);
+}
+
+int HWCDisplay::ToggleScreenUpdates(bool enable) {
+ display_paused_ = enable ? false : true;
+ callbacks_->Refresh(HWC_DISPLAY_PRIMARY);
+ validated_.reset();
+ return 0;
+}
+
+int HWCDisplay::ColorSVCRequestRoute(const PPDisplayAPIPayload &in_payload,
+ PPDisplayAPIPayload *out_payload,
+ PPPendingParams *pending_action) {
+ int ret = 0;
+
+ if (display_intf_)
+ ret = display_intf_->ColorSVCRequestRoute(in_payload, out_payload, pending_action);
+ else
+ ret = -EINVAL;
+
+ return ret;
+}
+
+void HWCDisplay::SolidFillPrepare() {
+ if (solid_fill_enable_) {
+ if (solid_fill_layer_ == NULL) {
+ // Create a dummy layer here
+ solid_fill_layer_ = new Layer();
+ }
+ uint32_t primary_width = 0, primary_height = 0;
+ GetMixerResolution(&primary_width, &primary_height);
+
+ LayerBuffer *layer_buffer = &solid_fill_layer_->input_buffer;
+ layer_buffer->width = primary_width;
+ layer_buffer->height = primary_height;
+ layer_buffer->unaligned_width = primary_width;
+ layer_buffer->unaligned_height = primary_height;
+ layer_buffer->acquire_fence_fd = -1;
+ layer_buffer->release_fence_fd = -1;
+
+ LayerRect rect;
+ rect.top = 0; rect.left = 0;
+ rect.right = primary_width;
+ rect.bottom = primary_height;
+
+ solid_fill_layer_->composition = kCompositionGPU;
+ solid_fill_layer_->src_rect = rect;
+ solid_fill_layer_->dst_rect = rect;
+
+ solid_fill_layer_->blending = kBlendingPremultiplied;
+ solid_fill_layer_->solid_fill_color = solid_fill_color_;
+ solid_fill_layer_->frame_rate = 60;
+ solid_fill_layer_->visible_regions.push_back(solid_fill_layer_->dst_rect);
+ solid_fill_layer_->flags.updating = 1;
+ solid_fill_layer_->flags.solid_fill = true;
+ } else {
+ // delete the dummy layer
+ delete solid_fill_layer_;
+ solid_fill_layer_ = NULL;
+ }
+
+ if (solid_fill_enable_ && solid_fill_layer_) {
+ BuildSolidFillStack();
+ MarkLayersForGPUBypass();
+ }
+
+ return;
+}
+
+void HWCDisplay::SolidFillCommit() {
+ if (solid_fill_enable_ && solid_fill_layer_) {
+ LayerBuffer *layer_buffer = &solid_fill_layer_->input_buffer;
+ if (layer_buffer->release_fence_fd > 0) {
+ close(layer_buffer->release_fence_fd);
+ layer_buffer->release_fence_fd = -1;
+ }
+ if (layer_stack_.retire_fence_fd > 0) {
+ close(layer_stack_.retire_fence_fd);
+ layer_stack_.retire_fence_fd = -1;
+ }
+ }
+}
+
+int HWCDisplay::GetVisibleDisplayRect(hwc_rect_t *visible_rect) {
+ if (!IsValid(display_rect_)) {
+ return -EINVAL;
+ }
+
+ visible_rect->left = INT(display_rect_.left);
+ visible_rect->top = INT(display_rect_.top);
+ visible_rect->right = INT(display_rect_.right);
+ visible_rect->bottom = INT(display_rect_.bottom);
+ DLOGI("Dpy = %d Visible Display Rect(%d %d %d %d)", visible_rect->left, visible_rect->top,
+ visible_rect->right, visible_rect->bottom);
+
+ return 0;
+}
+
+void HWCDisplay::SetSecureDisplay(bool secure_display_active) {
+ if (secure_display_active_ != secure_display_active) {
+ DLOGI("SecureDisplay state changed from %d to %d Needs Flush!!", secure_display_active_,
+ secure_display_active);
+ secure_display_active_ = secure_display_active;
+ skip_prepare_ = true;
+ }
+ return;
+}
+
+int HWCDisplay::SetActiveDisplayConfig(uint32_t config) {
+ int status = (display_intf_->SetActiveConfig(config) == kErrorNone) ? 0 : -1;
+ validated_.reset();
+ return status;
+}
+
+int HWCDisplay::GetActiveDisplayConfig(uint32_t *config) {
+ return display_intf_->GetActiveConfig(config) == kErrorNone ? 0 : -1;
+}
+
+int HWCDisplay::GetDisplayConfigCount(uint32_t *count) {
+ return display_intf_->GetNumVariableInfoConfigs(count) == kErrorNone ? 0 : -1;
+}
+
+int HWCDisplay::GetDisplayAttributesForConfig(int config,
+ DisplayConfigVariableInfo *display_attributes) {
+ return display_intf_->GetConfig(UINT32(config), display_attributes) == kErrorNone ? 0 : -1;
+}
+
+uint32_t HWCDisplay::GetUpdatingLayersCount(void) {
+ uint32_t updating_count = 0;
+
+ for (uint i = 0; i < layer_stack_.layers.size(); i++) {
+ auto layer = layer_stack_.layers.at(i);
+ if (layer->flags.updating) {
+ updating_count++;
+ }
+ }
+
+ return updating_count;
+}
+
+bool HWCDisplay::IsLayerUpdating(const Layer *layer) {
+ // Layer should be considered updating if
+ // a) layer is in single buffer mode, or
+ // b) valid dirty_regions(android specific hint for updating status), or
+ // c) layer stack geometry has changed (TODO(user): Remove when SDM accepts
+ // geometry_changed as bit fields).
+ return (layer->flags.single_buffer || IsSurfaceUpdated(layer->dirty_regions) ||
+ geometry_changes_);
+}
+
+bool HWCDisplay::IsSurfaceUpdated(const std::vector<LayerRect> &dirty_regions) {
+ // based on dirty_regions determine if its updating
+ // dirty_rect count = 0 - whole layer - updating.
+ // dirty_rect count = 1 or more valid rects - updating.
+ // dirty_rect count = 1 with (0,0,0,0) - not updating.
+ return (dirty_regions.empty() || IsValid(dirty_regions.at(0)));
+}
+
+uint32_t HWCDisplay::SanitizeRefreshRate(uint32_t req_refresh_rate) {
+ uint32_t refresh_rate = req_refresh_rate;
+
+ if (refresh_rate < min_refresh_rate_) {
+ // Pick the next multiple of request which is within the range
+ refresh_rate =
+ (((min_refresh_rate_ / refresh_rate) + ((min_refresh_rate_ % refresh_rate) ? 1 : 0)) *
+ refresh_rate);
+ }
+
+ if (refresh_rate > max_refresh_rate_) {
+ refresh_rate = max_refresh_rate_;
+ }
+
+ return refresh_rate;
+}
+
+DisplayClass HWCDisplay::GetDisplayClass() {
+ return display_class_;
+}
+
+void HWCDisplay::CloseAcquireFds() {
+ for (auto hwc_layer : layer_set_) {
+ auto layer = hwc_layer->GetSDMLayer();
+ if (layer->input_buffer.acquire_fence_fd >= 0) {
+ close(layer->input_buffer.acquire_fence_fd);
+ layer->input_buffer.acquire_fence_fd = -1;
+ }
+ }
+ int32_t &client_target_acquire_fence =
+ client_target_->GetSDMLayer()->input_buffer.acquire_fence_fd;
+ if (client_target_acquire_fence >= 0) {
+ close(client_target_acquire_fence);
+ client_target_acquire_fence = -1;
+ }
+}
+
+void HWCDisplay::ClearRequestFlags() {
+ for (Layer *layer : layer_stack_.layers) {
+ layer->request.flags = {};
+ }
+}
+
+std::string HWCDisplay::Dump() {
+ std::ostringstream os;
+ os << "\n------------HWC----------------\n";
+ os << "HWC2 display_id: " << id_ << std::endl;
+ for (auto layer : layer_set_) {
+ auto sdm_layer = layer->GetSDMLayer();
+ auto transform = sdm_layer->transform;
+ os << "layer: " << std::setw(4) << layer->GetId();
+ os << " z: " << layer->GetZ();
+ os << " compositon: " <<
+ to_string(layer->GetClientRequestedCompositionType()).c_str();
+ os << "/" <<
+ to_string(layer->GetDeviceSelectedCompositionType()).c_str();
+ os << " alpha: " << std::to_string(sdm_layer->plane_alpha).c_str();
+ os << " format: " << std::setw(22) << GetFormatString(sdm_layer->input_buffer.format);
+ os << " dataspace:" << std::hex << "0x" << std::setw(8) << std::setfill('0')
+ << layer->GetLayerDataspace() << std::dec << std::setfill(' ');
+ os << " transform: " << transform.rotation << "/" << transform.flip_horizontal <<
+ "/"<< transform.flip_vertical;
+ os << " buffer_id: " << std::hex << "0x" << sdm_layer->input_buffer.buffer_id << std::dec
+ << std::endl;
+ }
+
+ if (color_mode_) {
+ os << "\n----------Color Modes---------\n";
+ color_mode_->Dump(&os);
+ }
+
+ if (display_intf_) {
+ os << "\n------------SDM----------------\n";
+ os << display_intf_->Dump();
+ }
+
+ os << "\n";
+
+ return os.str();
+}
+
+bool HWCDisplay::CanSkipValidate() {
+ // Layer Stack checks
+ if (layer_stack_.flags.hdr_present && (tone_mapper_ && tone_mapper_->IsActive())) {
+ DLOGV_IF(kTagClient, "HDR content present with tone mapping enabled. Returning false.");
+ return false;
+ }
+
+ if (client_target_->NeedsValidation()) {
+ DLOGV_IF(kTagClient, "Framebuffer target needs validation. Returning false.");
+ return false;
+ }
+
+ for (auto hwc_layer : layer_set_) {
+ if (hwc_layer->NeedsValidation()) {
+ DLOGV_IF(kTagClient, "hwc_layer[%d] needs validation. Returning false.",
+ hwc_layer->GetId());
+ return false;
+ }
+
+ // Do not allow Skip Validate, if any layer needs GPU Composition.
+ if (hwc_layer->GetDeviceSelectedCompositionType() == HWC2::Composition::Client) {
+ DLOGV_IF(kTagClient, "hwc_layer[%d] is GPU composed. Returning false.",
+ hwc_layer->GetId());
+ return false;
+ }
+ }
+
+ return true;
+}
+
+} // namespace sdm
diff --git a/msm8909/sdm/libs/hwc2/hwc_display.h b/msm8909/sdm/libs/hwc2/hwc_display.h
new file mode 100644
index 00000000..0c69be7b
--- /dev/null
+++ b/msm8909/sdm/libs/hwc2/hwc_display.h
@@ -0,0 +1,317 @@
+/*
+ * Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
+ * Not a Contribution.
+ *
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __HWC_DISPLAY_H__
+#define __HWC_DISPLAY_H__
+
+#include <sys/stat.h>
+#include <QService.h>
+#include <core/core_interface.h>
+#include <hardware/hwcomposer.h>
+#include <private/color_params.h>
+#include <qdMetaData.h>
+#include <map>
+#include <queue>
+#include <set>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "hwc_buffer_allocator.h"
+#include "hwc_callbacks.h"
+#include "hwc_layers.h"
+
+namespace sdm {
+
+class BlitEngine;
+class HWCToneMapper;
+
+// Subclasses set this to their type. This has to be different from DisplayType.
+// This is to avoid RTTI and dynamic_cast
+enum DisplayClass {
+ DISPLAY_CLASS_PRIMARY,
+ DISPLAY_CLASS_EXTERNAL,
+ DISPLAY_CLASS_VIRTUAL,
+ DISPLAY_CLASS_NULL
+};
+
+class HWCColorMode {
+ public:
+ explicit HWCColorMode(DisplayInterface *display_intf);
+ ~HWCColorMode() {}
+ HWC2::Error Init();
+ HWC2::Error DeInit();
+ void Dump(std::ostringstream* os);
+ uint32_t GetColorModeCount();
+ HWC2::Error GetColorModes(uint32_t *out_num_modes, android_color_mode_t *out_modes);
+ HWC2::Error SetColorMode(android_color_mode_t mode);
+ HWC2::Error SetColorTransform(const float *matrix, android_color_transform_t hint);
+ HWC2::Error RestoreColorTransform();
+
+ private:
+ static const uint32_t kColorTransformMatrixCount = 16;
+
+ HWC2::Error HandleColorModeTransform(android_color_mode_t mode,
+ android_color_transform_t hint, const double *matrix);
+ void PopulateColorModes();
+ void PopulateTransform(const android_color_mode_t &mode,
+ const std::string &color_mode, const std::string &color_transform);
+ template <class T>
+ void CopyColorTransformMatrix(const T *input_matrix, double *output_matrix) {
+ for (uint32_t i = 0; i < kColorTransformMatrixCount; i++) {
+ output_matrix[i] = static_cast<double>(input_matrix[i]);
+ }
+ }
+ HWC2::Error ApplyDefaultColorMode();
+
+ DisplayInterface *display_intf_ = NULL;
+ android_color_mode_t current_color_mode_ = HAL_COLOR_MODE_NATIVE;
+ android_color_transform_t current_color_transform_ = HAL_COLOR_TRANSFORM_IDENTITY;
+ typedef std::map<android_color_transform_t, std::string> TransformMap;
+ std::map<android_color_mode_t, TransformMap> color_mode_transform_map_ = {};
+ double color_matrix_[kColorTransformMatrixCount] = { 1.0, 0.0, 0.0, 0.0, \
+ 0.0, 1.0, 0.0, 0.0, \
+ 0.0, 0.0, 1.0, 0.0, \
+ 0.0, 0.0, 0.0, 1.0 };
+};
+
+class HWCDisplay : public DisplayEventHandler {
+ public:
+ enum DisplayStatus {
+ kDisplayStatusInvalid = -1,
+ kDisplayStatusOffline,
+ kDisplayStatusOnline,
+ kDisplayStatusPause,
+ kDisplayStatusResume,
+ };
+
+ virtual ~HWCDisplay() {}
+ virtual int Init();
+ virtual int Deinit();
+
+ // Framebuffer configurations
+ virtual void SetIdleTimeoutMs(uint32_t timeout_ms);
+ virtual void SetFrameDumpConfig(uint32_t count, uint32_t bit_mask_layer_type);
+ virtual DisplayError SetMaxMixerStages(uint32_t max_mixer_stages);
+ virtual DisplayError ControlPartialUpdate(bool enable, uint32_t *pending) {
+ return kErrorNotSupported;
+ }
+ virtual HWC2::PowerMode GetLastPowerMode();
+ virtual int SetFrameBufferResolution(uint32_t x_pixels, uint32_t y_pixels);
+ virtual void GetFrameBufferResolution(uint32_t *x_pixels, uint32_t *y_pixels);
+ virtual int SetDisplayStatus(DisplayStatus display_status);
+ virtual int OnMinHdcpEncryptionLevelChange(uint32_t min_enc_level);
+ virtual int Perform(uint32_t operation, ...);
+ virtual void SetSecureDisplay(bool secure_display_active);
+ virtual DisplayError SetMixerResolution(uint32_t width, uint32_t height);
+ virtual DisplayError GetMixerResolution(uint32_t *width, uint32_t *height);
+ virtual void GetPanelResolution(uint32_t *width, uint32_t *height);
+ virtual std::string Dump();
+
+ // Captures frame output in the buffer specified by output_buffer_info. The API is
+ // non-blocking and the client is expected to check operation status later on.
+ // Returns -1 if the input is invalid.
+ virtual int FrameCaptureAsync(const BufferInfo &output_buffer_info, bool post_processed) {
+ return -1;
+ }
+ // Returns the status of frame capture operation requested with FrameCaptureAsync().
+ // -EAGAIN : No status obtain yet, call API again after another frame.
+ // < 0 : Operation happened but failed.
+ // 0 : Success.
+ virtual int GetFrameCaptureStatus() { return -EAGAIN; }
+
+ virtual DisplayError SetDetailEnhancerConfig(const DisplayDetailEnhancerData &de_data) {
+ return kErrorNotSupported;
+ }
+
+ // Display Configurations
+ virtual int SetActiveDisplayConfig(uint32_t config);
+ virtual int GetActiveDisplayConfig(uint32_t *config);
+ virtual int GetDisplayConfigCount(uint32_t *count);
+ virtual int GetDisplayAttributesForConfig(int config,
+ DisplayConfigVariableInfo *display_attributes);
+ virtual int SetState(bool connected) {
+ return kErrorNotSupported;
+ }
+ int SetPanelBrightness(int level);
+ int GetPanelBrightness(int *level);
+ int ToggleScreenUpdates(bool enable);
+ int ColorSVCRequestRoute(const PPDisplayAPIPayload &in_payload, PPDisplayAPIPayload *out_payload,
+ PPPendingParams *pending_action);
+ void SolidFillPrepare();
+ void SolidFillCommit();
+ DisplayClass GetDisplayClass();
+ int GetVisibleDisplayRect(hwc_rect_t *rect);
+ void BuildLayerStack(void);
+ void BuildSolidFillStack(void);
+ HWCLayer *GetHWCLayer(hwc2_layer_t layer);
+ void ResetValidation() { validated_.reset(); }
+ uint32_t GetGeometryChanges() { return geometry_changes_; }
+
+ // HWC2 APIs
+ virtual HWC2::Error AcceptDisplayChanges(void);
+ virtual HWC2::Error GetActiveConfig(hwc2_config_t *out_config);
+ virtual HWC2::Error SetActiveConfig(hwc2_config_t config);
+ virtual HWC2::Error SetClientTarget(buffer_handle_t target, int32_t acquire_fence,
+ int32_t dataspace, hwc_region_t damage);
+ virtual HWC2::Error SetColorMode(android_color_mode_t mode) {
+ return HWC2::Error::Unsupported;
+ }
+ virtual HWC2::Error RestoreColorTransform() {
+ return HWC2::Error::Unsupported;
+ }
+ virtual HWC2::Error SetColorTransform(const float *matrix, android_color_transform_t hint) {
+ return HWC2::Error::Unsupported;
+ }
+ virtual HWC2::Error HandleColorModeTransform(android_color_mode_t mode,
+ android_color_transform_t hint,
+ const double *matrix) {
+ return HWC2::Error::Unsupported;
+ }
+ virtual HWC2::Error GetDisplayConfigs(uint32_t *out_num_configs, hwc2_config_t *out_configs);
+ virtual HWC2::Error GetDisplayAttribute(hwc2_config_t config, HWC2::Attribute attribute,
+ int32_t *out_value);
+ virtual HWC2::Error GetClientTargetSupport(uint32_t width, uint32_t height, int32_t format,
+ int32_t dataspace);
+ virtual HWC2::Error GetColorModes(uint32_t *outNumModes, android_color_mode_t *outModes);
+ virtual HWC2::Error GetChangedCompositionTypes(uint32_t *out_num_elements,
+ hwc2_layer_t *out_layers, int32_t *out_types);
+ virtual HWC2::Error GetDisplayRequests(int32_t *out_display_requests, uint32_t *out_num_elements,
+ hwc2_layer_t *out_layers, int32_t *out_layer_requests);
+ virtual HWC2::Error GetDisplayName(uint32_t *out_size, char *out_name);
+ virtual HWC2::Error GetDisplayType(int32_t *out_type);
+ virtual HWC2::Error SetCursorPosition(hwc2_layer_t layer, int x, int y);
+ virtual HWC2::Error SetVsyncEnabled(HWC2::Vsync enabled);
+ virtual HWC2::Error SetPowerMode(HWC2::PowerMode mode);
+ virtual HWC2::Error CreateLayer(hwc2_layer_t *out_layer_id);
+ virtual HWC2::Error DestroyLayer(hwc2_layer_t layer_id);
+ virtual HWC2::Error SetLayerZOrder(hwc2_layer_t layer_id, uint32_t z);
+ virtual HWC2::Error Validate(uint32_t *out_num_types, uint32_t *out_num_requests) = 0;
+ virtual HWC2::Error GetReleaseFences(uint32_t *out_num_elements, hwc2_layer_t *out_layers,
+ int32_t *out_fences);
+ virtual HWC2::Error Present(int32_t *out_retire_fence) = 0;
+ virtual HWC2::Error GetHdrCapabilities(uint32_t *out_num_types, int32_t* out_types,
+ float* out_max_luminance,
+ float* out_max_average_luminance,
+ float* out_min_luminance);
+ virtual HWC2::Error SetDisplayAnimating(bool animating) {
+ animating_ = animating;
+ validated_ = false;
+ return HWC2::Error::None;
+ }
+
+ protected:
+ // Maximum number of layers supported by display manager.
+ static const uint32_t kMaxLayerCount = 32;
+
+ HWCDisplay(CoreInterface *core_intf, HWCCallbacks *callbacks, DisplayType type, hwc2_display_t id,
+ bool needs_blit, qService::QService *qservice, DisplayClass display_class,
+ BufferAllocator *buffer_allocator);
+
+ // DisplayEventHandler methods
+ virtual DisplayError VSync(const DisplayEventVSync &vsync);
+ virtual DisplayError Refresh();
+ virtual DisplayError CECMessage(char *message);
+ virtual DisplayError HandleEvent(DisplayEvent event);
+ virtual void DumpOutputBuffer(const BufferInfo &buffer_info, void *base, int fence);
+ virtual HWC2::Error PrepareLayerStack(uint32_t *out_num_types, uint32_t *out_num_requests);
+ virtual HWC2::Error CommitLayerStack(void);
+ virtual HWC2::Error PostCommitLayerStack(int32_t *out_retire_fence);
+ virtual DisplayError DisablePartialUpdateOneFrame() {
+ return kErrorNotSupported;
+ }
+ LayerBufferFormat GetSDMFormat(const int32_t &source, const int flags);
+ const char *GetDisplayString();
+ void MarkLayersForGPUBypass(void);
+ void MarkLayersForClientComposition(void);
+ virtual void ApplyScanAdjustment(hwc_rect_t *display_frame);
+ uint32_t GetUpdatingLayersCount(void);
+ bool IsSurfaceUpdated(const std::vector<LayerRect> &dirty_regions);
+ bool IsLayerUpdating(const Layer *layer);
+ uint32_t SanitizeRefreshRate(uint32_t req_refresh_rate);
+ virtual void CloseAcquireFds();
+ virtual void ClearRequestFlags();
+ virtual void GetUnderScanConfig() { }
+
+ enum {
+ INPUT_LAYER_DUMP,
+ OUTPUT_LAYER_DUMP,
+ };
+
+ static std::bitset<kDisplayMax> validated_;
+ CoreInterface *core_intf_ = nullptr;
+ HWCCallbacks *callbacks_ = nullptr;
+ HWCBufferAllocator *buffer_allocator_ = NULL;
+ DisplayType type_;
+ hwc2_display_t id_;
+ bool needs_blit_ = false;
+ DisplayInterface *display_intf_ = NULL;
+ LayerStack layer_stack_;
+ HWCLayer *client_target_ = nullptr; // Also known as framebuffer target
+ std::map<hwc2_layer_t, HWCLayer *> layer_map_; // Look up by Id - TODO
+ std::multiset<HWCLayer *, SortLayersByZ> layer_set_; // Maintain a set sorted by Z
+ std::map<hwc2_layer_t, HWC2::Composition> layer_changes_;
+ std::map<hwc2_layer_t, HWC2::LayerRequest> layer_requests_;
+ bool flush_on_error_ = false;
+ bool flush_ = false;
+ uint32_t dump_frame_count_ = 0;
+ uint32_t dump_frame_index_ = 0;
+ bool dump_input_layers_ = false;
+ HWC2::PowerMode last_power_mode_;
+ bool swap_interval_zero_ = false;
+ bool display_paused_ = false;
+ uint32_t min_refresh_rate_ = 0;
+ uint32_t max_refresh_rate_ = 0;
+ uint32_t current_refresh_rate_ = 0;
+ bool use_metadata_refresh_rate_ = false;
+ uint32_t metadata_refresh_rate_ = 0;
+ uint32_t force_refresh_rate_ = 0;
+ bool boot_animation_completed_ = false;
+ bool shutdown_pending_ = false;
+ bool use_blit_comp_ = false;
+ bool secure_display_active_ = false;
+ bool skip_prepare_ = false;
+ bool solid_fill_enable_ = false;
+ Layer *solid_fill_layer_ = NULL;
+ LayerRect solid_fill_rect_ = {};
+ uint32_t solid_fill_color_ = 0;
+ LayerRect display_rect_;
+ bool color_tranform_failed_ = false;
+ HWCColorMode *color_mode_ = NULL;
+ HWCToneMapper *tone_mapper_ = nullptr;
+ uint32_t num_configs_ = 0;
+ int disable_hdr_handling_ = 0; // disables HDR handling.
+
+ private:
+ void DumpInputBuffers(void);
+ bool CanSkipValidate();
+ qService::QService *qservice_ = NULL;
+ DisplayClass display_class_;
+ uint32_t geometry_changes_ = GeometryChanges::kNone;
+ bool skip_validate_ = false;
+ bool animating_ = false;
+};
+
+inline int HWCDisplay::Perform(uint32_t operation, ...) {
+ return 0;
+}
+
+} // namespace sdm
+
+#endif // __HWC_DISPLAY_H__
diff --git a/msm8909/sdm/libs/hwc2/hwc_display_external.cpp b/msm8909/sdm/libs/hwc2/hwc_display_external.cpp
new file mode 100644
index 00000000..440d80a3
--- /dev/null
+++ b/msm8909/sdm/libs/hwc2/hwc_display_external.cpp
@@ -0,0 +1,280 @@
+/*
+* Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <cutils/properties.h>
+#include <utils/constants.h>
+#include <utils/debug.h>
+#include <algorithm>
+
+#include "hwc_display_external.h"
+#include "hwc_debugger.h"
+
+#define __CLASS__ "HWCDisplayExternal"
+
+namespace sdm {
+
+int HWCDisplayExternal::Create(CoreInterface *core_intf, HWCBufferAllocator *buffer_allocator,
+ HWCCallbacks *callbacks, qService::QService *qservice,
+ HWCDisplay **hwc_display) {
+ return Create(core_intf, buffer_allocator, callbacks, 0, 0, qservice, false, hwc_display);
+}
+
+int HWCDisplayExternal::Create(CoreInterface *core_intf, HWCBufferAllocator *buffer_allocator,
+ HWCCallbacks *callbacks,
+ uint32_t primary_width, uint32_t primary_height,
+ qService::QService *qservice, bool use_primary_res,
+ HWCDisplay **hwc_display) {
+ uint32_t external_width = 0;
+ uint32_t external_height = 0;
+ DisplayError error = kErrorNone;
+
+ HWCDisplay *hwc_display_external = new HWCDisplayExternal(core_intf, buffer_allocator, callbacks,
+ qservice);
+ int status = hwc_display_external->Init();
+ if (status) {
+ delete hwc_display_external;
+ return status;
+ }
+
+ error = hwc_display_external->GetMixerResolution(&external_width, &external_height);
+ if (error != kErrorNone) {
+ Destroy(hwc_display_external);
+ return -EINVAL;
+ }
+
+ if (primary_width && primary_height) {
+ // use_primary_res means HWCDisplayExternal should directly set framebuffer resolution to the
+ // provided primary_width and primary_height
+ if (use_primary_res) {
+ external_width = primary_width;
+ external_height = primary_height;
+ } else {
+ int downscale_enabled = 0;
+ HWCDebugHandler::Get()->GetProperty(ENABLE_EXTERNAL_DOWNSCALE_PROP, &downscale_enabled);
+ if (downscale_enabled) {
+ GetDownscaleResolution(primary_width, primary_height, &external_width, &external_height);
+ }
+ }
+ }
+
+ status = hwc_display_external->SetFrameBufferResolution(external_width, external_height);
+ if (status) {
+ Destroy(hwc_display_external);
+ return status;
+ }
+
+ *hwc_display = hwc_display_external;
+
+ return status;
+}
+
+void HWCDisplayExternal::Destroy(HWCDisplay *hwc_display) {
+ hwc_display->Deinit();
+ delete hwc_display;
+}
+
+HWCDisplayExternal::HWCDisplayExternal(CoreInterface *core_intf,
+ HWCBufferAllocator *buffer_allocator,
+ HWCCallbacks *callbacks,
+ qService::QService *qservice)
+ : HWCDisplay(core_intf, callbacks, kHDMI, HWC_DISPLAY_EXTERNAL, false, qservice,
+ DISPLAY_CLASS_EXTERNAL, buffer_allocator) {
+}
+
+HWC2::Error HWCDisplayExternal::Validate(uint32_t *out_num_types, uint32_t *out_num_requests) {
+ auto status = HWC2::Error::None;
+
+ if (secure_display_active_) {
+ MarkLayersForGPUBypass();
+ return status;
+ }
+
+ BuildLayerStack();
+
+ if (layer_set_.empty()) {
+ flush_ = true;
+ return status;
+ }
+
+ status = PrepareLayerStack(out_num_types, out_num_requests);
+ return status;
+}
+
+HWC2::Error HWCDisplayExternal::Present(int32_t *out_retire_fence) {
+ auto status = HWC2::Error::None;
+
+ if (!secure_display_active_) {
+ status = HWCDisplay::CommitLayerStack();
+ if (status == HWC2::Error::None) {
+ status = HWCDisplay::PostCommitLayerStack(out_retire_fence);
+ }
+ }
+ CloseAcquireFds();
+ return status;
+}
+
+void HWCDisplayExternal::ApplyScanAdjustment(hwc_rect_t *display_frame) {
+ if ((underscan_width_ <= 0) || (underscan_height_ <= 0)) {
+ return;
+ }
+
+ float width_ratio = FLOAT(underscan_width_) / 100.0f;
+ float height_ratio = FLOAT(underscan_height_) / 100.0f;
+
+ uint32_t mixer_width = 0;
+ uint32_t mixer_height = 0;
+ GetMixerResolution(&mixer_width, &mixer_height);
+
+ if (mixer_width == 0 || mixer_height == 0) {
+ DLOGV("Invalid mixer dimensions (%d, %d)", mixer_width, mixer_height);
+ return;
+ }
+
+ uint32_t new_mixer_width = UINT32(mixer_width * FLOAT(1.0f - width_ratio));
+ uint32_t new_mixer_height = UINT32(mixer_height * FLOAT(1.0f - height_ratio));
+
+ int x_offset = INT((FLOAT(mixer_width) * width_ratio) / 2.0f);
+ int y_offset = INT((FLOAT(mixer_height) * height_ratio) / 2.0f);
+
+ display_frame->left = (display_frame->left * INT32(new_mixer_width) / INT32(mixer_width))
+ + x_offset;
+ display_frame->top = (display_frame->top * INT32(new_mixer_height) / INT32(mixer_height)) +
+ y_offset;
+ display_frame->right = ((display_frame->right * INT32(new_mixer_width)) / INT32(mixer_width)) +
+ x_offset;
+ display_frame->bottom = ((display_frame->bottom * INT32(new_mixer_height)) / INT32(mixer_height))
+ + y_offset;
+}
+
+void HWCDisplayExternal::SetSecureDisplay(bool secure_display_active) {
+ if (secure_display_active_ != secure_display_active) {
+ secure_display_active_ = secure_display_active;
+
+ if (secure_display_active_) {
+ DisplayError error = display_intf_->Flush();
+ validated_.reset();
+ if (error != kErrorNone) {
+ DLOGE("Flush failed. Error = %d", error);
+ }
+ }
+ }
+ return;
+}
+
+static void AdjustSourceResolution(uint32_t dst_width, uint32_t dst_height, uint32_t *src_width,
+ uint32_t *src_height) {
+ *src_height = (dst_width * (*src_height)) / (*src_width);
+ *src_width = dst_width;
+}
+
+void HWCDisplayExternal::GetDownscaleResolution(uint32_t primary_width, uint32_t primary_height,
+ uint32_t *non_primary_width,
+ uint32_t *non_primary_height) {
+ uint32_t primary_area = primary_width * primary_height;
+ uint32_t non_primary_area = (*non_primary_width) * (*non_primary_height);
+
+ if (primary_area > non_primary_area) {
+ if (primary_height > primary_width) {
+ std::swap(primary_height, primary_width);
+ }
+ AdjustSourceResolution(primary_width, primary_height, non_primary_width, non_primary_height);
+ }
+}
+
+int HWCDisplayExternal::SetState(bool connected) {
+ DisplayError error = kErrorNone;
+ DisplayState state = kStateOff;
+ DisplayConfigVariableInfo fb_config = {};
+
+ if (connected) {
+ if (display_null_.IsActive()) {
+ error = core_intf_->CreateDisplay(type_, this, &display_intf_);
+ if (error != kErrorNone) {
+ DLOGE("Display create failed. Error = %d display_type %d event_handler %p disp_intf %p",
+ error, type_, this, &display_intf_);
+ return -EINVAL;
+ }
+
+ // Restore HDMI attributes when display is reconnected.
+ // This is to ensure that surfaceflinger & sdm are in sync.
+ display_null_.GetFrameBufferConfig(&fb_config);
+ int status = SetFrameBufferResolution(fb_config.x_pixels, fb_config.y_pixels);
+ if (status) {
+ DLOGW("Set frame buffer config failed. Error = %d", error);
+ return -1;
+ }
+
+ display_null_.GetDisplayState(&state);
+ display_intf_->SetDisplayState(state);
+ validated_.reset();
+
+ SetVsyncEnabled(HWC2::Vsync::Enable);
+
+ display_null_.SetActive(false);
+ DLOGI("Display is connected successfully.");
+ } else {
+ DLOGI("Display is already connected.");
+ }
+ } else {
+ if (!display_null_.IsActive()) {
+ // Preserve required attributes of HDMI display that surfaceflinger sees.
+ // Restore HDMI attributes when display is reconnected.
+ display_intf_->GetDisplayState(&state);
+ display_null_.SetDisplayState(state);
+
+ error = display_intf_->GetFrameBufferConfig(&fb_config);
+ if (error != kErrorNone) {
+ DLOGW("Get frame buffer config failed. Error = %d", error);
+ return -1;
+ }
+ display_null_.SetFrameBufferConfig(fb_config);
+
+ SetVsyncEnabled(HWC2::Vsync::Disable);
+ core_intf_->DestroyDisplay(display_intf_);
+ display_intf_ = &display_null_;
+
+ display_null_.SetActive(true);
+ DLOGI("Display is disconnected successfully.");
+ } else {
+ DLOGI("Display is already disconnected.");
+ }
+ }
+
+ return 0;
+}
+
+void HWCDisplayExternal::GetUnderScanConfig() {
+ if (!display_intf_->IsUnderscanSupported()) {
+ // Read user defined underscan width and height
+ HWCDebugHandler::Get()->GetProperty(EXTERNAL_ACTION_SAFE_WIDTH_PROP, &underscan_width_);
+ HWCDebugHandler::Get()->GetProperty(EXTERNAL_ACTION_SAFE_HEIGHT_PROP, &underscan_height_);
+ }
+}
+
+} // namespace sdm
diff --git a/msm8909/sdm/libs/hwc2/hwc_display_external.h b/msm8909/sdm/libs/hwc2/hwc_display_external.h
new file mode 100644
index 00000000..fbee6a3d
--- /dev/null
+++ b/msm8909/sdm/libs/hwc2/hwc_display_external.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials provided
+ with the distribution.
+ * Neither the name of The Linux Foundation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __HWC_DISPLAY_EXTERNAL_H__
+#define __HWC_DISPLAY_EXTERNAL_H__
+
+#include "hwc_display.h"
+#include "display_null.h"
+
+namespace sdm {
+
+class HWCDisplayExternal : public HWCDisplay {
+ public:
+ static int Create(CoreInterface *core_intf, HWCBufferAllocator *buffer_allocator,
+ HWCCallbacks *callbacks, uint32_t primary_width,
+ uint32_t primary_height, qService::QService *qservice, bool use_primary_res,
+ HWCDisplay **hwc_display);
+ static int Create(CoreInterface *core_intf, HWCBufferAllocator *buffer_allocator,
+ HWCCallbacks *callbacks, qService::QService *qservice,
+ HWCDisplay **hwc_display);
+ static void Destroy(HWCDisplay *hwc_display);
+ virtual HWC2::Error Validate(uint32_t *out_num_types, uint32_t *out_num_requests);
+ virtual HWC2::Error Present(int32_t *out_retire_fence);
+ virtual void SetSecureDisplay(bool secure_display_active);
+ virtual int SetState(bool connected);
+
+ private:
+ HWCDisplayExternal(CoreInterface *core_intf, HWCBufferAllocator *buffer_allocator,
+ HWCCallbacks *callbacks, qService::QService *qservice);
+ void ApplyScanAdjustment(hwc_rect_t *display_frame);
+ void GetUnderScanConfig();
+ static void GetDownscaleResolution(uint32_t primary_width, uint32_t primary_height,
+ uint32_t *virtual_width, uint32_t *virtual_height);
+
+ DisplayNull display_null_;
+ int underscan_width_ = 0;
+ int underscan_height_ = 0;
+};
+
+} // namespace sdm
+
+#endif // __HWC_DISPLAY_EXTERNAL_H__
diff --git a/msm8909/sdm/libs/hwc2/hwc_display_external_test.cpp b/msm8909/sdm/libs/hwc2/hwc_display_external_test.cpp
new file mode 100644
index 00000000..fcbe326f
--- /dev/null
+++ b/msm8909/sdm/libs/hwc2/hwc_display_external_test.cpp
@@ -0,0 +1,750 @@
+/*
+* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <cutils/properties.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <utils/constants.h>
+#include <utils/debug.h>
+#include <utils/formats.h>
+#include <algorithm>
+#include <array>
+#include <sstream>
+#include <string>
+#include <fstream>
+
+#include "hwc_display_external_test.h"
+#include "hwc_debugger.h"
+
+#define __CLASS__ "HWCDisplayExternalTest"
+
+namespace sdm {
+
+using std::array;
+
+int HWCDisplayExternalTest::Create(CoreInterface *core_intf,
+ HWCBufferAllocator *buffer_allocator,
+ HWCCallbacks *callbacks,
+ qService::QService *qservice, uint32_t panel_bpp,
+ uint32_t pattern_type, HWCDisplay **hwc_display) {
+ HWCDisplay *hwc_external_test = new HWCDisplayExternalTest(core_intf, buffer_allocator,
+ callbacks, qservice,
+ panel_bpp, pattern_type);
+
+ int status = static_cast<HWCDisplayExternalTest *>(hwc_external_test)->Init();
+ if (status) {
+ delete hwc_external_test;
+ return status;
+ }
+
+ *hwc_display = hwc_external_test;
+
+ DLOGE("EXTERNAL panel_bpp %d, pattern_type %d", panel_bpp, pattern_type);
+
+ return status;
+}
+
+void HWCDisplayExternalTest::Destroy(HWCDisplay *hwc_display) {
+ static_cast<HWCDisplayExternalTest *>(hwc_display)->Deinit();
+
+ delete hwc_display;
+}
+
+HWCDisplayExternalTest::HWCDisplayExternalTest(CoreInterface *core_intf,
+ HWCBufferAllocator *buffer_allocator,
+ HWCCallbacks *callbacks,
+ qService::QService *qservice, uint32_t panel_bpp,
+ uint32_t pattern_type)
+ : HWCDisplay(core_intf, callbacks, kHDMI, HWC_DISPLAY_EXTERNAL, false, qservice,
+ DISPLAY_CLASS_EXTERNAL, buffer_allocator), panel_bpp_(panel_bpp),
+ pattern_type_(pattern_type) {
+}
+
+int HWCDisplayExternalTest::Init() {
+ uint32_t external_width = 0;
+ uint32_t external_height = 0;
+
+ int status = HWCDisplay::Init();
+ if (status) {
+ DLOGE("HWCDisplayExternalTest::Init status = %d ", status);
+ return status;
+ }
+
+ status = CreateLayerStack();
+ if (status) {
+ Deinit();
+ return status;
+ }
+
+ DisplayError error = HWCDisplay::GetMixerResolution(&external_width, &external_height);
+ if (error != kErrorNone) {
+ Deinit();
+ return -EINVAL;
+ }
+
+ status = HWCDisplay::SetFrameBufferResolution(external_width, external_height);
+ if (status) {
+ Deinit();
+ DLOGE("HWCDisplayExternalTest:: set fb resolution status = %d ", status);
+ return status;
+ }
+
+ return status;
+}
+
+int HWCDisplayExternalTest::Deinit() {
+ DestroyLayerStack();
+ return HWCDisplay::Deinit();
+}
+
+
+HWC2::Error HWCDisplayExternalTest::Validate(uint32_t *out_num_types, uint32_t *out_num_requests) {
+ auto status = HWC2::Error::None;
+ if (secure_display_active_) {
+ MarkLayersForGPUBypass();
+ return status;
+ }
+
+ if (layer_set_.empty()) {
+ flush_ = true;
+ return status;
+ }
+
+ if (shutdown_pending_) {
+ return status;
+ }
+ DisplayError error = display_intf_->Prepare(&layer_stack_);
+ if (error != kErrorNone) {
+ if (error == kErrorShutDown) {
+ shutdown_pending_ = true;
+ } else if (error != kErrorPermission) {
+ DLOGE("Prepare failed. Error = %d", error);
+ // To prevent surfaceflinger infinite wait, flush the previous frame during Commit()
+ // so that previous buffer and fences are released, and override the error.
+ flush_ = true;
+ }
+ }
+
+ MarkLayersForGPUBypass();
+
+ return status;
+}
+
+HWC2::Error HWCDisplayExternalTest::Present(int32_t *out_retire_fence) {
+ auto status = HWC2::Error::None;
+
+ if (secure_display_active_) {
+ return status;
+ }
+
+ if (shutdown_pending_) {
+ return status;
+ }
+
+ DumpInputBuffer();
+
+ if (!flush_) {
+ DisplayError error = kErrorUndefined;
+ error = display_intf_->Commit(&layer_stack_);
+ if (error == kErrorNone) {
+ // A commit is successfully submitted, start flushing on failure now onwards.
+ flush_on_error_ = true;
+ } else {
+ if (error == kErrorShutDown) {
+ shutdown_pending_ = true;
+ return status;
+ } else if (error != kErrorPermission) {
+ DLOGE("Commit failed. Error = %d", error);
+ // To prevent surfaceflinger infinite wait, flush the previous frame during Commit()
+ // so that previous buffer and fences are released, and override the error.
+ flush_ = true;
+ }
+ }
+ }
+
+ return PostCommit(out_retire_fence);
+}
+
+void HWCDisplayExternalTest::SetSecureDisplay(bool secure_display_active) {
+ if (secure_display_active_ != secure_display_active) {
+ secure_display_active_ = secure_display_active;
+
+ if (secure_display_active_) {
+ DisplayError error = display_intf_->Flush();
+ if (error != kErrorNone) {
+ DLOGE("Flush failed. Error = %d", error);
+ }
+ }
+ }
+ return;
+}
+
+int HWCDisplayExternalTest::Perform(uint32_t operation, ...) {
+ return 0;
+}
+
+void HWCDisplayExternalTest::DumpInputBuffer() {
+ if (!dump_frame_count_ || flush_ || !dump_input_layers_) {
+ return;
+ }
+
+ const char *dir_path = "/data/vendor/display/frame_dump_external";
+ uint32_t width = buffer_info_.alloc_buffer_info.aligned_width;
+ uint32_t height = buffer_info_.alloc_buffer_info.aligned_height;
+ string format_str = GetFormatString(buffer_info_.buffer_config.format);
+
+ char *buffer = reinterpret_cast<char *>(mmap(NULL, buffer_info_.alloc_buffer_info.size,
+ PROT_READ|PROT_WRITE, MAP_SHARED,
+ buffer_info_.alloc_buffer_info.fd, 0));
+ if (buffer == MAP_FAILED) {
+ DLOGW("mmap failed. err = %d", errno);
+ return;
+ }
+
+ if (mkdir(dir_path, 0777) != 0 && errno != EEXIST) {
+ DLOGW("Failed to create %s directory errno = %d, desc = %s", dir_path, errno, strerror(errno));
+ return;
+ }
+
+ // if directory exists already, need to explicitly change the permission.
+ if (errno == EEXIST && chmod(dir_path, 0777) != 0) {
+ DLOGW("Failed to change permissions on %s directory", dir_path);
+ return;
+ }
+
+ if (buffer) {
+ std::stringstream dump_file_name;
+ dump_file_name << dir_path;
+ dump_file_name << "/input_layer_" << width << "x" << height << "_" << format_str << ".raw";
+
+ std::fstream fs;
+ fs.open(dump_file_name.str().c_str(), std::fstream::in | std::fstream::out | std::fstream::app);
+ if (!fs.is_open()) {
+ DLOGI("File open failed %s", dump_file_name.str().c_str());
+ return;
+ }
+
+ fs.write(buffer, (std::streamsize)buffer_info_.alloc_buffer_info.size);
+ fs.close();
+
+ DLOGI("Frame Dump %s: is successful", dump_file_name.str().c_str());
+ }
+
+ // Dump only once as the content is going to be same for all draw cycles
+ if (dump_frame_count_) {
+ dump_frame_count_ = 0;
+ }
+
+ if (munmap(buffer, buffer_info_.alloc_buffer_info.size) != 0) {
+ DLOGW("munmap failed. err = %d", errno);
+ return;
+ }
+}
+
+void HWCDisplayExternalTest::CalcCRC(uint32_t color_val, std::bitset<16> *crc_data) {
+ std::bitset<16> color = {};
+ std::bitset<16> temp_crc = {};
+
+ switch (panel_bpp_) {
+ case kDisplayBpp18:
+ color = (color_val & 0xFC) << 8;
+ break;
+ case kDisplayBpp24:
+ color = color_val << 8;
+ break;
+ case kDisplayBpp30:
+ color = color_val << 6;
+ break;
+ default:
+ return;
+ }
+
+ temp_crc[15] = (*crc_data)[0] ^ (*crc_data)[1] ^ (*crc_data)[2] ^ (*crc_data)[3] ^
+ (*crc_data)[4] ^ (*crc_data)[5] ^ (*crc_data)[6] ^ (*crc_data)[7] ^
+ (*crc_data)[8] ^ (*crc_data)[9] ^ (*crc_data)[10] ^ (*crc_data)[11] ^
+ (*crc_data)[12] ^ (*crc_data)[14] ^ (*crc_data)[15] ^ color[0] ^ color[1] ^
+ color[2] ^ color[3] ^ color[4] ^ color[5] ^ color[6] ^ color[7] ^ color[8] ^
+ color[9] ^ color[10] ^ color[11] ^ color[12] ^ color[14] ^ color[15];
+
+ temp_crc[14] = (*crc_data)[12] ^ (*crc_data)[13] ^ color[12] ^ color[13];
+ temp_crc[13] = (*crc_data)[11] ^ (*crc_data)[12] ^ color[11] ^ color[12];
+ temp_crc[12] = (*crc_data)[10] ^ (*crc_data)[11] ^ color[10] ^ color[11];
+ temp_crc[11] = (*crc_data)[9] ^ (*crc_data)[10] ^ color[9] ^ color[10];
+ temp_crc[10] = (*crc_data)[8] ^ (*crc_data)[9] ^ color[8] ^ color[9];
+ temp_crc[9] = (*crc_data)[7] ^ (*crc_data)[8] ^ color[7] ^ color[8];
+ temp_crc[8] = (*crc_data)[6] ^ (*crc_data)[7] ^ color[6] ^ color[7];
+ temp_crc[7] = (*crc_data)[5] ^ (*crc_data)[6] ^ color[5] ^ color[6];
+ temp_crc[6] = (*crc_data)[4] ^ (*crc_data)[5] ^ color[4] ^ color[5];
+ temp_crc[5] = (*crc_data)[3] ^ (*crc_data)[4] ^ color[3] ^ color[4];
+ temp_crc[4] = (*crc_data)[2] ^ (*crc_data)[3] ^ color[2] ^ color[3];
+ temp_crc[3] = (*crc_data)[1] ^ (*crc_data)[2] ^ (*crc_data)[15] ^ color[1] ^ color[2] ^ color[15];
+ temp_crc[2] = (*crc_data)[0] ^ (*crc_data)[1] ^ (*crc_data)[14] ^ color[0] ^ color[1] ^ color[14];
+
+ temp_crc[1] = (*crc_data)[1] ^ (*crc_data)[2] ^ (*crc_data)[3] ^ (*crc_data)[4] ^ (*crc_data)[5] ^
+ (*crc_data)[6] ^ (*crc_data)[7] ^ (*crc_data)[8] ^ (*crc_data)[9] ^
+ (*crc_data)[10] ^ (*crc_data)[11] ^ (*crc_data)[12] ^ (*crc_data)[13] ^
+ (*crc_data)[14] ^ color[1] ^ color[2] ^ color[3] ^ color[4] ^ color[5] ^ color[6] ^
+ color[7] ^ color[8] ^ color[9] ^ color[10] ^ color[11] ^ color[12] ^ color[13] ^
+ color[14];
+
+ temp_crc[0] = (*crc_data)[0] ^ (*crc_data)[1] ^ (*crc_data)[2] ^ (*crc_data)[3] ^ (*crc_data)[4] ^
+ (*crc_data)[5] ^ (*crc_data)[6] ^ (*crc_data)[7] ^ (*crc_data)[8] ^ (*crc_data)[9] ^
+ (*crc_data)[10] ^ (*crc_data)[11] ^ (*crc_data)[12] ^ (*crc_data)[13] ^
+ (*crc_data)[15] ^ color[0] ^ color[1] ^ color[2] ^ color[3] ^ color[4] ^ color[5] ^
+ color[6] ^ color[7] ^ color[8] ^ color[9] ^ color[10] ^ color[11] ^ color[12] ^
+ color[13] ^ color[15];
+
+ (*crc_data) = temp_crc;
+}
+
+int HWCDisplayExternalTest::FillBuffer() {
+ uint8_t *buffer = reinterpret_cast<uint8_t *>(mmap(NULL, buffer_info_.alloc_buffer_info.size,
+ PROT_READ|PROT_WRITE, MAP_SHARED,
+ buffer_info_.alloc_buffer_info.fd, 0));
+ if (buffer == MAP_FAILED) {
+ DLOGE("mmap failed. err = %d", errno);
+ return -EFAULT;
+ }
+
+ switch (pattern_type_) {
+ case kPatternColorRamp:
+ GenerateColorRamp(buffer);
+ break;
+ case kPatternBWVertical:
+ GenerateBWVertical(buffer);
+ break;
+ case kPatternColorSquare:
+ GenerateColorSquare(buffer);
+ break;
+ default:
+ DLOGW("Invalid Pattern type %d", pattern_type_);
+ return -EINVAL;
+ }
+
+ if (munmap(buffer, buffer_info_.alloc_buffer_info.size) != 0) {
+ DLOGE("munmap failed. err = %d", errno);
+ return -EFAULT;
+ }
+
+ return 0;
+}
+
+int HWCDisplayExternalTest::GetStride(LayerBufferFormat format, uint32_t width, uint32_t *stride) {
+ switch (format) {
+ case kFormatRGBA8888:
+ case kFormatRGBA1010102:
+ *stride = width * 4;
+ break;
+ case kFormatRGB888:
+ *stride = width * 3;
+ break;
+ default:
+ DLOGE("Unsupported format type %d", format);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+void HWCDisplayExternalTest::PixelCopy(uint32_t red, uint32_t green, uint32_t blue, uint32_t alpha,
+ uint8_t **buffer) {
+ LayerBufferFormat format = buffer_info_.buffer_config.format;
+
+ switch (format) {
+ case kFormatRGBA8888:
+ *(*buffer)++ = UINT8(red & 0xFF);
+ *(*buffer)++ = UINT8(green & 0xFF);
+ *(*buffer)++ = UINT8(blue & 0xFF);
+ *(*buffer)++ = UINT8(alpha & 0xFF);
+ break;
+ case kFormatRGB888:
+ *(*buffer)++ = UINT8(red & 0xFF);
+ *(*buffer)++ = UINT8(green & 0xFF);
+ *(*buffer)++ = UINT8(blue & 0xFF);
+ break;
+ case kFormatRGBA1010102:
+ // Lower 8 bits of red
+ *(*buffer)++ = UINT8(red & 0xFF);
+
+ // Upper 2 bits of Red + Lower 6 bits of green
+ *(*buffer)++ = UINT8(((green & 0x3F) << 2) | ((red >> 0x8) & 0x3));
+
+ // Upper 4 bits of green + Lower 4 bits of blue
+ *(*buffer)++ = UINT8(((blue & 0xF) << 4) | ((green >> 6) & 0xF));
+
+ // Upper 6 bits of blue + Lower 2 bits of alpha
+ *(*buffer)++ = UINT8(((alpha & 0x3) << 6) | ((blue >> 4) & 0x3F));
+ break;
+ default:
+ DLOGW("format not supported format = %d", format);
+ break;
+ }
+}
+
+void HWCDisplayExternalTest::GenerateColorRamp(uint8_t *buffer) {
+ uint32_t width = buffer_info_.buffer_config.width;
+ uint32_t height = buffer_info_.buffer_config.height;
+ LayerBufferFormat format = buffer_info_.buffer_config.format;
+ uint32_t aligned_width = buffer_info_.alloc_buffer_info.aligned_width;
+ uint32_t buffer_stride = 0;
+
+ uint32_t color_ramp = 0;
+ uint32_t start_color_val = 0;
+ uint32_t step_size = 1;
+ uint32_t ramp_width = 0;
+ uint32_t ramp_height = 0;
+ uint32_t shift_by = 0;
+
+ std::bitset<16> crc_red = {};
+ std::bitset<16> crc_green = {};
+ std::bitset<16> crc_blue = {};
+
+ switch (panel_bpp_) {
+ case kDisplayBpp18:
+ ramp_height = 64;
+ ramp_width = 64;
+ shift_by = 2;
+ break;
+ case kDisplayBpp24:
+ ramp_height = 64;
+ ramp_width = 256;
+ break;
+ case kDisplayBpp30:
+ ramp_height = 32;
+ ramp_width = 256;
+ start_color_val = 0x180;
+ break;
+ default:
+ return;
+ }
+
+ GetStride(format, aligned_width, &buffer_stride);
+
+ for (uint32_t loop_height = 0; loop_height < height; loop_height++) {
+ uint32_t color_value = start_color_val;
+ uint8_t *temp = buffer + (loop_height * buffer_stride);
+
+ for (uint32_t loop_width = 0; loop_width < width; loop_width++) {
+ if (color_ramp == kColorRedRamp) {
+ PixelCopy(color_value, 0, 0, 0, &temp);
+ CalcCRC(color_value, &crc_red);
+ CalcCRC(0, &crc_green);
+ CalcCRC(0, &crc_blue);
+ }
+ if (color_ramp == kColorGreenRamp) {
+ PixelCopy(0, color_value, 0, 0, &temp);
+ CalcCRC(0, &crc_red);
+ CalcCRC(color_value, &crc_green);
+ CalcCRC(0, &crc_blue);
+ }
+ if (color_ramp == kColorBlueRamp) {
+ PixelCopy(0, 0, color_value, 0, &temp);
+ CalcCRC(0, &crc_red);
+ CalcCRC(0, &crc_green);
+ CalcCRC(color_value, &crc_blue);
+ }
+ if (color_ramp == kColorWhiteRamp) {
+ PixelCopy(color_value, color_value, color_value, 0, &temp);
+ CalcCRC(color_value, &crc_red);
+ CalcCRC(color_value, &crc_green);
+ CalcCRC(color_value, &crc_blue);
+ }
+
+ color_value = (start_color_val + (((loop_width + 1) % ramp_width) * step_size)) << shift_by;
+ }
+
+ if (panel_bpp_ == kDisplayBpp30 && ((loop_height + 1) % ramp_height) == 0) {
+ if (start_color_val == 0x180) {
+ start_color_val = 0;
+ step_size = 4;
+ } else {
+ start_color_val = 0x180;
+ step_size = 1;
+ color_ramp = (color_ramp + 1) % 4;
+ }
+ continue;
+ }
+
+ if (((loop_height + 1) % ramp_height) == 0) {
+ color_ramp = (color_ramp + 1) % 4;
+ }
+ }
+
+ DLOGI("CRC red %x", crc_red.to_ulong());
+ DLOGI("CRC green %x", crc_green.to_ulong());
+ DLOGI("CRC blue %x", crc_blue.to_ulong());
+}
+
+void HWCDisplayExternalTest::GenerateBWVertical(uint8_t *buffer) {
+ uint32_t width = buffer_info_.buffer_config.width;
+ uint32_t height = buffer_info_.buffer_config.height;
+ LayerBufferFormat format = buffer_info_.buffer_config.format;
+ uint32_t aligned_width = buffer_info_.alloc_buffer_info.aligned_width;
+ uint32_t buffer_stride = 0;
+ uint32_t bits_per_component = panel_bpp_ / 3;
+ uint32_t max_color_val = (1 << bits_per_component) - 1;
+
+ std::bitset<16> crc_red = {};
+ std::bitset<16> crc_green = {};
+ std::bitset<16> crc_blue = {};
+
+ if (panel_bpp_ == kDisplayBpp18) {
+ max_color_val <<= 2;
+ }
+
+ GetStride(format, aligned_width, &buffer_stride);
+
+ for (uint32_t loop_height = 0; loop_height < height; loop_height++) {
+ uint32_t color = 0;
+ uint8_t *temp = buffer + (loop_height * buffer_stride);
+
+ for (uint32_t loop_width = 0; loop_width < width; loop_width++) {
+ if (color == kColorBlack) {
+ PixelCopy(0, 0, 0, 0, &temp);
+ CalcCRC(0, &crc_red);
+ CalcCRC(0, &crc_green);
+ CalcCRC(0, &crc_blue);
+ }
+ if (color == kColorWhite) {
+ PixelCopy(max_color_val, max_color_val, max_color_val, 0, &temp);
+ CalcCRC(max_color_val, &crc_red);
+ CalcCRC(max_color_val, &crc_green);
+ CalcCRC(max_color_val, &crc_blue);
+ }
+
+ color = (color + 1) % 2;
+ }
+ }
+
+ DLOGI("CRC red %x", crc_red.to_ulong());
+ DLOGI("CRC green %x", crc_green.to_ulong());
+ DLOGI("CRC blue %x", crc_blue.to_ulong());
+}
+
+void HWCDisplayExternalTest::GenerateColorSquare(uint8_t *buffer) {
+ uint32_t width = buffer_info_.buffer_config.width;
+ uint32_t height = buffer_info_.buffer_config.height;
+ LayerBufferFormat format = buffer_info_.buffer_config.format;
+ uint32_t aligned_width = buffer_info_.alloc_buffer_info.aligned_width;
+ uint32_t buffer_stride = 0;
+ uint32_t max_color_val = 0;
+ uint32_t min_color_val = 0;
+
+ std::bitset<16> crc_red = {};
+ std::bitset<16> crc_green = {};
+ std::bitset<16> crc_blue = {};
+
+ switch (panel_bpp_) {
+ case kDisplayBpp18:
+ max_color_val = 63 << 2; // CEA Dynamic range for 18bpp 0 - 63
+ min_color_val = 0;
+ break;
+ case kDisplayBpp24:
+ max_color_val = 235; // CEA Dynamic range for 24bpp 16 - 235
+ min_color_val = 16;
+ break;
+ case kDisplayBpp30:
+ max_color_val = 940; // CEA Dynamic range for 30bpp 64 - 940
+ min_color_val = 64;
+ break;
+ default:
+ return;
+ }
+
+ array<array<uint32_t, 3>, 8> colors = {{
+ {{max_color_val, max_color_val, max_color_val}}, // White Color
+ {{max_color_val, max_color_val, min_color_val}}, // Yellow Color
+ {{min_color_val, max_color_val, max_color_val}}, // Cyan Color
+ {{min_color_val, max_color_val, min_color_val}}, // Green Color
+ {{max_color_val, min_color_val, max_color_val}}, // Megenta Color
+ {{max_color_val, min_color_val, min_color_val}}, // Red Color
+ {{min_color_val, min_color_val, max_color_val}}, // Blue Color
+ {{min_color_val, min_color_val, min_color_val}}, // Black Color
+ }};
+
+ GetStride(format, aligned_width, &buffer_stride);
+
+ for (uint32_t loop_height = 0; loop_height < height; loop_height++) {
+ uint32_t color = 0;
+ uint8_t *temp = buffer + (loop_height * buffer_stride);
+
+ for (uint32_t loop_width = 0; loop_width < width; loop_width++) {
+ PixelCopy(colors[color][0], colors[color][1], colors[color][2], 0, &temp);
+ CalcCRC(colors[color][0], &crc_red);
+ CalcCRC(colors[color][1], &crc_green);
+ CalcCRC(colors[color][2], &crc_blue);
+
+ if (((loop_width + 1) % 64) == 0) {
+ color = (color + 1) % colors.size();
+ }
+ }
+
+ if (((loop_height + 1) % 64) == 0) {
+ std::reverse(colors.begin(), (colors.end() - 1));
+ }
+ }
+
+ DLOGI("CRC red %x", crc_red.to_ulong());
+ DLOGI("CRC green %x", crc_green.to_ulong());
+ DLOGI("CRC blue %x", crc_blue.to_ulong());
+}
+
+int HWCDisplayExternalTest::InitLayer(Layer *layer) {
+ uint32_t active_config = 0;
+ DisplayConfigVariableInfo var_info = {};
+
+ GetActiveDisplayConfig(&active_config);
+
+ GetDisplayAttributesForConfig(INT32(active_config), &var_info);
+
+ layer->flags.updating = 1;
+ layer->src_rect = LayerRect(0, 0, var_info.x_pixels, var_info.y_pixels);
+ layer->dst_rect = layer->src_rect;
+ layer->frame_rate = var_info.fps;
+ layer->blending = kBlendingPremultiplied;
+
+ layer->input_buffer.unaligned_width = var_info.x_pixels;
+ layer->input_buffer.unaligned_height = var_info.y_pixels;
+ buffer_info_.buffer_config.format = kFormatRGBA8888;
+
+ if (layer->composition != kCompositionGPUTarget) {
+ buffer_info_.buffer_config.width = var_info.x_pixels;
+ buffer_info_.buffer_config.height = var_info.y_pixels;
+ switch (panel_bpp_) {
+ case kDisplayBpp18:
+ case kDisplayBpp24:
+ buffer_info_.buffer_config.format = kFormatRGB888;
+ break;
+ case kDisplayBpp30:
+ buffer_info_.buffer_config.format = kFormatRGBA1010102;
+ break;
+ default:
+ DLOGW("panel bpp not supported %d", panel_bpp_);
+ return -EINVAL;
+ }
+ buffer_info_.buffer_config.buffer_count = 1;
+
+ int ret = buffer_allocator_->AllocateBuffer(&buffer_info_);
+ if (ret != 0) {
+ DLOGE("Buffer allocation failed. ret: %d", ret);
+ return -ENOMEM;
+ }
+
+ ret = FillBuffer();
+ if (ret != 0) {
+ buffer_allocator_->FreeBuffer(&buffer_info_);
+ return ret;
+ }
+
+ layer->input_buffer.width = buffer_info_.alloc_buffer_info.aligned_width;
+ layer->input_buffer.height = buffer_info_.alloc_buffer_info.aligned_height;
+ layer->input_buffer.size = buffer_info_.alloc_buffer_info.size;
+ layer->input_buffer.planes[0].fd = buffer_info_.alloc_buffer_info.fd;
+ layer->input_buffer.planes[0].stride = buffer_info_.alloc_buffer_info.stride;
+ layer->input_buffer.format = buffer_info_.buffer_config.format;
+
+ DLOGI("Input buffer WxH %dx%d format %s size %d fd %d stride %d", layer->input_buffer.width,
+ layer->input_buffer.height, GetFormatString(layer->input_buffer.format),
+ layer->input_buffer.size, layer->input_buffer.planes[0].fd,
+ layer->input_buffer.planes[0].stride);
+ }
+
+ return 0;
+}
+
+int HWCDisplayExternalTest::DeinitLayer(Layer *layer) {
+ if (layer->composition != kCompositionGPUTarget) {
+ int ret = buffer_allocator_->FreeBuffer(&buffer_info_);
+ if (ret != 0) {
+ DLOGE("Buffer deallocation failed. ret: %d", ret);
+ return -ENOMEM;
+ }
+ }
+
+ return 0;
+}
+
+int HWCDisplayExternalTest::CreateLayerStack() {
+ for (uint32_t i = 0; i < (kTestLayerCnt + 1 /* one dummy gpu_target layer */); i++) {
+ Layer *layer = new Layer();
+
+ if (i == kTestLayerCnt) {
+ layer->composition = kCompositionGPUTarget;
+ }
+ DLOGE("External :: CreateLayerStack %d", i);
+ int ret = InitLayer(layer);
+ if (ret != 0) {
+ delete layer;
+ return ret;
+ }
+ layer_stack_.layers.push_back(layer);
+ }
+
+ return 0;
+}
+
+int HWCDisplayExternalTest::DestroyLayerStack() {
+ for (uint32_t i = 0; i < UINT32(layer_stack_.layers.size()); i++) {
+ Layer *layer = layer_stack_.layers.at(i);
+ int ret = DeinitLayer(layer);
+ if (ret != 0) {
+ return ret;
+ }
+ delete layer;
+ }
+ layer_stack_.layers = {};
+ return 0;
+}
+
+HWC2::Error HWCDisplayExternalTest::PostCommit(int32_t *out_retire_fence) {
+ auto status = HWC2::Error::None;
+ // Do no call flush on errors, if a successful buffer is never submitted.
+ if (flush_ && flush_on_error_) {
+ display_intf_->Flush();
+ }
+ if (!flush_) {
+ for (size_t i = 0; i < layer_stack_.layers.size(); i++) {
+ Layer *layer = layer_stack_.layers.at(i);
+ LayerBuffer &layer_buffer = layer->input_buffer;
+
+ close(layer_buffer.release_fence_fd);
+ layer_buffer.release_fence_fd = -1;
+ }
+ close(layer_stack_.retire_fence_fd);
+ layer_stack_.retire_fence_fd = -1;
+ *out_retire_fence = -1;
+ }
+
+ flush_ = false;
+ return status;
+}
+
+} // namespace sdm
+
diff --git a/msm8909/sdm/libs/hwc2/hwc_display_external_test.h b/msm8909/sdm/libs/hwc2/hwc_display_external_test.h
new file mode 100644
index 00000000..e2c13f58
--- /dev/null
+++ b/msm8909/sdm/libs/hwc2/hwc_display_external_test.h
@@ -0,0 +1,102 @@
+/*
+* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without modification, are permitted
+* provided that the following conditions are met:
+* * Redistributions of source code must retain the above copyright notice, this list of
+* conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright notice, this list of
+* conditions and the following disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its contributors may be used to
+* endorse or promote products derived from this software without specific prior written
+* permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __HWC_DISPLAY_EXTERNAL_TEST_H__
+#define __HWC_DISPLAY_EXTERNAL_TEST_H__
+
+#include<bitset>
+
+#include "hwc_display.h"
+#include "hwc_buffer_allocator.h"
+
+namespace sdm {
+
+class HWCDisplayExternalTest : public HWCDisplay {
+ public:
+ static int Create(CoreInterface *core_intf, HWCBufferAllocator *buffer_allocator,
+ HWCCallbacks *callbacks, qService::QService *qservice,
+ uint32_t panel_bpp, uint32_t pattern_type, HWCDisplay **hwc_display);
+ static void Destroy(HWCDisplay *hwc_display);
+ virtual HWC2::Error Validate(uint32_t *out_num_types, uint32_t *out_num_requests);
+ virtual HWC2::Error Present(int32_t *out_retire_fence);
+ virtual void SetSecureDisplay(bool secure_display_active);
+ virtual int Perform(uint32_t operation, ...);
+
+ protected:
+ BufferInfo buffer_info_ = {};
+ uint32_t panel_bpp_ = 0;
+ uint32_t pattern_type_ = 0;
+
+ enum ColorPatternType {
+ kPatternNone = 0,
+ kPatternColorRamp,
+ kPatternBWVertical,
+ kPatternColorSquare,
+ };
+
+ enum DisplayBpp {
+ kDisplayBpp18 = 18,
+ kDisplayBpp24 = 24,
+ kDisplayBpp30 = 30,
+ };
+
+ enum ColorRamp {
+ kColorRedRamp = 0,
+ kColorGreenRamp = 1,
+ kColorBlueRamp = 2,
+ kColorWhiteRamp = 3,
+ };
+
+ enum Colors {
+ kColorBlack = 0,
+ kColorWhite = 1,
+ };
+
+ private:
+ HWCDisplayExternalTest(CoreInterface *core_intf, HWCBufferAllocator *buffer_allocator,
+ HWCCallbacks *callbacks, qService::QService *qservice,
+ uint32_t panel_bpp, uint32_t pattern_type);
+ int Init();
+ int Deinit();
+ void DumpInputBuffer();
+ void CalcCRC(uint32_t color_value, std::bitset<16> *crc_data);
+ int FillBuffer();
+ int GetStride(LayerBufferFormat format, uint32_t width, uint32_t *stride);
+ void PixelCopy(uint32_t red, uint32_t green, uint32_t blue, uint32_t alpha, uint8_t **buffer);
+ void GenerateColorRamp(uint8_t *buffer);
+ void GenerateBWVertical(uint8_t *buffer);
+ void GenerateColorSquare(uint8_t *buffer);
+ int InitLayer(Layer *layer);
+ int DeinitLayer(Layer *layer);
+ int CreateLayerStack();
+ int DestroyLayerStack();
+ HWC2::Error PostCommit(int32_t *out_retire_fence);
+
+ static const uint32_t kTestLayerCnt = 1;
+};
+
+} // namespace sdm
+
+#endif // __HWC_DISPLAY_EXTERNAL_TEST_H__
+
diff --git a/msm8909/sdm/libs/hwc2/hwc_display_primary.cpp b/msm8909/sdm/libs/hwc2/hwc_display_primary.cpp
new file mode 100644
index 00000000..5a6bddd6
--- /dev/null
+++ b/msm8909/sdm/libs/hwc2/hwc_display_primary.cpp
@@ -0,0 +1,620 @@
+/*
+* Copyright (c) 2014 - 2018, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <cutils/properties.h>
+#include <sync/sync.h>
+#include <utils/constants.h>
+#include <utils/debug.h>
+#include <stdarg.h>
+#include <sys/mman.h>
+
+#include <map>
+#include <string>
+#include <vector>
+
+#include "hwc_display_primary.h"
+#include "hwc_debugger.h"
+
+#define __CLASS__ "HWCDisplayPrimary"
+
+namespace sdm {
+
+int HWCDisplayPrimary::Create(CoreInterface *core_intf, BufferAllocator *buffer_allocator,
+ HWCCallbacks *callbacks, qService::QService *qservice,
+ HWCDisplay **hwc_display) {
+ int status = 0;
+ uint32_t primary_width = 0;
+ uint32_t primary_height = 0;
+
+ HWCDisplay *hwc_display_primary =
+ new HWCDisplayPrimary(core_intf, buffer_allocator, callbacks, qservice);
+ status = hwc_display_primary->Init();
+ if (status) {
+ delete hwc_display_primary;
+ return status;
+ }
+
+ hwc_display_primary->GetMixerResolution(&primary_width, &primary_height);
+ int width = 0, height = 0;
+ HWCDebugHandler::Get()->GetProperty(FB_WIDTH_PROP, &width);
+ HWCDebugHandler::Get()->GetProperty(FB_HEIGHT_PROP, &height);
+ if (width > 0 && height > 0) {
+ primary_width = UINT32(width);
+ primary_height = UINT32(height);
+ }
+
+ status = hwc_display_primary->SetFrameBufferResolution(primary_width, primary_height);
+ if (status) {
+ Destroy(hwc_display_primary);
+ return status;
+ }
+
+ *hwc_display = hwc_display_primary;
+
+ return status;
+}
+
+void HWCDisplayPrimary::Destroy(HWCDisplay *hwc_display) {
+ hwc_display->Deinit();
+ delete hwc_display;
+}
+
+HWCDisplayPrimary::HWCDisplayPrimary(CoreInterface *core_intf, BufferAllocator *buffer_allocator,
+ HWCCallbacks *callbacks, qService::QService *qservice)
+ : HWCDisplay(core_intf, callbacks, kPrimary, HWC_DISPLAY_PRIMARY, true, qservice,
+ DISPLAY_CLASS_PRIMARY, buffer_allocator),
+ buffer_allocator_(buffer_allocator),
+ cpu_hint_(NULL) {
+}
+
+int HWCDisplayPrimary::Init() {
+ cpu_hint_ = new CPUHint();
+ if (cpu_hint_->Init(static_cast<HWCDebugHandler *>(HWCDebugHandler::Get())) != kErrorNone) {
+ delete cpu_hint_;
+ cpu_hint_ = NULL;
+ }
+
+ use_metadata_refresh_rate_ = true;
+ int disable_metadata_dynfps = 0;
+ HWCDebugHandler::Get()->GetProperty(DISABLE_METADATA_DYNAMIC_FPS_PROP, &disable_metadata_dynfps);
+ if (disable_metadata_dynfps) {
+ use_metadata_refresh_rate_ = false;
+ }
+
+ int status = HWCDisplay::Init();
+ if (status) {
+ return status;
+ }
+ color_mode_ = new HWCColorMode(display_intf_);
+ color_mode_->Init();
+ HWCDebugHandler::Get()->GetProperty(ENABLE_DEFAULT_COLOR_MODE, &default_mode_status_);
+
+ return status;
+}
+
+void HWCDisplayPrimary::ProcessBootAnimCompleted() {
+ uint32_t numBootUpLayers = 0;
+ // TODO(user): Remove this hack
+
+ numBootUpLayers = static_cast<uint32_t>(Debug::GetBootAnimLayerCount());
+
+ if (numBootUpLayers == 0) {
+ numBootUpLayers = 2;
+ }
+ /* All other checks namely "init.svc.bootanim" or
+ * HWC_GEOMETRY_CHANGED fail in correctly identifying the
+ * exact bootup transition to homescreen
+ */
+ char property[PROPERTY_VALUE_MAX];
+ bool isEncrypted = false;
+ bool main_class_services_started = false;
+ property_get("ro.crypto.state", property, "unencrypted");
+ if (!strcmp(property, "encrypted")) {
+ property_get("ro.crypto.type", property, "block");
+ if (!strcmp(property, "block")) {
+ isEncrypted = true;
+ property_get("vold.decrypt", property, "");
+ if (!strcmp(property, "trigger_restart_framework")) {
+ main_class_services_started = true;
+ }
+ }
+ }
+
+ if ((!isEncrypted || (isEncrypted && main_class_services_started)) &&
+ (layer_set_.size() > numBootUpLayers)) {
+ DLOGI("Applying default mode");
+ boot_animation_completed_ = true;
+ // Applying default mode after bootanimation is finished And
+ // If Data is Encrypted, it is ready for access.
+ if (display_intf_) {
+ display_intf_->ApplyDefaultDisplayMode();
+ RestoreColorTransform();
+ }
+ }
+}
+
+HWC2::Error HWCDisplayPrimary::Validate(uint32_t *out_num_types, uint32_t *out_num_requests) {
+ auto status = HWC2::Error::None;
+ DisplayError error = kErrorNone;
+
+ if (default_mode_status_ && !boot_animation_completed_) {
+ ProcessBootAnimCompleted();
+ }
+
+ if (display_paused_) {
+ MarkLayersForGPUBypass();
+ return status;
+ }
+
+
+ // Fill in the remaining blanks in the layers and add them to the SDM layerstack
+ BuildLayerStack();
+
+ if (color_tranform_failed_) {
+ // Must fall back to client composition
+ MarkLayersForClientComposition();
+ }
+
+ // Checks and replaces layer stack for solid fill
+ SolidFillPrepare();
+
+ bool pending_output_dump = dump_frame_count_ && dump_output_to_file_;
+
+ if (frame_capture_buffer_queued_ || pending_output_dump) {
+ // RHS values were set in FrameCaptureAsync() called from a binder thread. They are picked up
+ // here in a subsequent draw round.
+ layer_stack_.output_buffer = &output_buffer_;
+ layer_stack_.flags.post_processed_output = post_processed_output_;
+ }
+
+ uint32_t num_updating_layers = GetUpdatingLayersCount();
+ bool one_updating_layer = (num_updating_layers == 1);
+ if (num_updating_layers != 0) {
+ ToggleCPUHint(one_updating_layer);
+ }
+
+ uint32_t refresh_rate = GetOptimalRefreshRate(one_updating_layer);
+ if (current_refresh_rate_ != refresh_rate || handle_idle_timeout_) {
+ error = display_intf_->SetRefreshRate(refresh_rate);
+ }
+
+ if (error == kErrorNone) {
+ // On success, set current refresh rate to new refresh rate
+ current_refresh_rate_ = refresh_rate;
+ }
+
+ if (handle_idle_timeout_) {
+ handle_idle_timeout_ = false;
+ }
+
+ if (layer_set_.empty()) {
+ // Avoid flush for Command mode panel.
+ DisplayConfigFixedInfo display_config;
+ display_intf_->GetConfig(&display_config);
+ flush_ = !display_config.is_cmdmode;
+ return status;
+ }
+
+ status = PrepareLayerStack(out_num_types, out_num_requests);
+ return status;
+}
+
+HWC2::Error HWCDisplayPrimary::Present(int32_t *out_retire_fence) {
+ auto status = HWC2::Error::None;
+ if (display_paused_) {
+ // TODO(user): From old HWC implementation
+ // If we do not handle the frame set retireFenceFd to outbufAcquireFenceFd
+ // Revisit this when validating display_paused
+ DisplayError error = display_intf_->Flush();
+ if (error != kErrorNone) {
+ DLOGE("Flush failed. Error = %d", error);
+ }
+ } else {
+ status = HWCDisplay::CommitLayerStack();
+ if (status == HWC2::Error::None) {
+ HandleFrameOutput();
+ SolidFillCommit();
+ status = HWCDisplay::PostCommitLayerStack(out_retire_fence);
+ }
+ }
+
+ CloseAcquireFds();
+ return status;
+}
+
+HWC2::Error HWCDisplayPrimary::GetColorModes(uint32_t *out_num_modes,
+ android_color_mode_t *out_modes) {
+ if (out_modes == nullptr) {
+ *out_num_modes = color_mode_->GetColorModeCount();
+ } else {
+ color_mode_->GetColorModes(out_num_modes, out_modes);
+ }
+
+ return HWC2::Error::None;
+}
+
+HWC2::Error HWCDisplayPrimary::SetColorMode(android_color_mode_t mode) {
+ auto status = color_mode_->SetColorMode(mode);
+ if (status != HWC2::Error::None) {
+ DLOGE("failed for mode = %d", mode);
+ return status;
+ }
+
+ callbacks_->Refresh(HWC_DISPLAY_PRIMARY);
+ validated_.reset();
+
+ return status;
+}
+
+HWC2::Error HWCDisplayPrimary::RestoreColorTransform() {
+ auto status = color_mode_->RestoreColorTransform();
+ if (status != HWC2::Error::None) {
+ DLOGE("failed to RestoreColorTransform");
+ return status;
+ }
+
+ callbacks_->Refresh(HWC_DISPLAY_PRIMARY);
+
+ return status;
+}
+
+HWC2::Error HWCDisplayPrimary::SetColorTransform(const float *matrix,
+ android_color_transform_t hint) {
+ if (!matrix) {
+ return HWC2::Error::BadParameter;
+ }
+
+ auto status = color_mode_->SetColorTransform(matrix, hint);
+ if ((hint != HAL_COLOR_TRANSFORM_IDENTITY) && (status != HWC2::Error::None)) {
+ DLOGE("failed for hint = %d", hint);
+ color_tranform_failed_ = true;
+ return status;
+ }
+
+ callbacks_->Refresh(HWC_DISPLAY_PRIMARY);
+ color_tranform_failed_ = false;
+ validated_.reset();
+
+ return status;
+}
+
+int HWCDisplayPrimary::Perform(uint32_t operation, ...) {
+ va_list args;
+ va_start(args, operation);
+ int val = 0;
+ LayerRect *rect = NULL;
+
+ switch (operation) {
+ case SET_METADATA_DYN_REFRESH_RATE:
+ val = va_arg(args, int32_t);
+ SetMetaDataRefreshRateFlag(val);
+ break;
+ case SET_BINDER_DYN_REFRESH_RATE:
+ val = va_arg(args, int32_t);
+ ForceRefreshRate(UINT32(val));
+ break;
+ case SET_DISPLAY_MODE:
+ val = va_arg(args, int32_t);
+ SetDisplayMode(UINT32(val));
+ break;
+ case SET_QDCM_SOLID_FILL_INFO:
+ val = va_arg(args, int32_t);
+ SetQDCMSolidFillInfo(true, UINT32(val));
+ break;
+ case UNSET_QDCM_SOLID_FILL_INFO:
+ val = va_arg(args, int32_t);
+ SetQDCMSolidFillInfo(false, UINT32(val));
+ break;
+ case SET_QDCM_SOLID_FILL_RECT:
+ rect = va_arg(args, LayerRect*);
+ solid_fill_rect_ = *rect;
+ break;
+ default:
+ DLOGW("Invalid operation %d", operation);
+ va_end(args);
+ return -EINVAL;
+ }
+ va_end(args);
+ validated_.reset();
+
+ return 0;
+}
+
+DisplayError HWCDisplayPrimary::SetDisplayMode(uint32_t mode) {
+ DisplayError error = kErrorNone;
+
+ if (display_intf_) {
+ error = display_intf_->SetDisplayMode(mode);
+ }
+
+ return error;
+}
+
+void HWCDisplayPrimary::SetMetaDataRefreshRateFlag(bool enable) {
+ int disable_metadata_dynfps = 0;
+
+ HWCDebugHandler::Get()->GetProperty(DISABLE_METADATA_DYNAMIC_FPS_PROP, &disable_metadata_dynfps);
+ if (disable_metadata_dynfps) {
+ return;
+ }
+ use_metadata_refresh_rate_ = enable;
+}
+
+void HWCDisplayPrimary::SetQDCMSolidFillInfo(bool enable, uint32_t color) {
+ solid_fill_enable_ = enable;
+ solid_fill_color_ = color;
+}
+
+void HWCDisplayPrimary::ToggleCPUHint(bool set) {
+ if (!cpu_hint_) {
+ return;
+ }
+
+ if (set) {
+ cpu_hint_->Set();
+ } else {
+ cpu_hint_->Reset();
+ }
+}
+
+void HWCDisplayPrimary::SetSecureDisplay(bool secure_display_active) {
+ if (secure_display_active_ != secure_display_active) {
+ // Skip Prepare and call Flush for null commit
+ DLOGI("SecureDisplay state changed from %d to %d Needs Flush!!", secure_display_active_,
+ secure_display_active);
+ secure_display_active_ = secure_display_active;
+
+ // Avoid flush for Command mode panel.
+ DisplayConfigFixedInfo display_config;
+ display_intf_->GetConfig(&display_config);
+ skip_prepare_ = !display_config.is_cmdmode;
+ }
+}
+
+void HWCDisplayPrimary::ForceRefreshRate(uint32_t refresh_rate) {
+ if ((refresh_rate && (refresh_rate < min_refresh_rate_ || refresh_rate > max_refresh_rate_)) ||
+ force_refresh_rate_ == refresh_rate) {
+ // Cannot honor force refresh rate, as its beyond the range or new request is same
+ return;
+ }
+
+ force_refresh_rate_ = refresh_rate;
+
+ callbacks_->Refresh(HWC_DISPLAY_PRIMARY);
+
+ return;
+}
+
+uint32_t HWCDisplayPrimary::GetOptimalRefreshRate(bool one_updating_layer) {
+ if (force_refresh_rate_) {
+ return force_refresh_rate_;
+ } else if (handle_idle_timeout_) {
+ return min_refresh_rate_;
+ } else if (use_metadata_refresh_rate_ && one_updating_layer && metadata_refresh_rate_) {
+ return metadata_refresh_rate_;
+ }
+
+ return max_refresh_rate_;
+}
+
+DisplayError HWCDisplayPrimary::Refresh() {
+ DisplayError error = kErrorNone;
+
+ callbacks_->Refresh(HWC_DISPLAY_PRIMARY);
+ handle_idle_timeout_ = true;
+
+ return error;
+}
+
+void HWCDisplayPrimary::SetIdleTimeoutMs(uint32_t timeout_ms) {
+ display_intf_->SetIdleTimeoutMs(timeout_ms);
+ validated_.reset();
+}
+
+static void SetLayerBuffer(const BufferInfo &output_buffer_info, LayerBuffer *output_buffer) {
+ const BufferConfig& buffer_config = output_buffer_info.buffer_config;
+ const AllocatedBufferInfo &alloc_buffer_info = output_buffer_info.alloc_buffer_info;
+
+ output_buffer->width = alloc_buffer_info.aligned_width;
+ output_buffer->height = alloc_buffer_info.aligned_height;
+ output_buffer->unaligned_width = buffer_config.width;
+ output_buffer->unaligned_height = buffer_config.height;
+ output_buffer->format = buffer_config.format;
+ output_buffer->planes[0].fd = alloc_buffer_info.fd;
+ output_buffer->planes[0].stride = alloc_buffer_info.stride;
+}
+
+void HWCDisplayPrimary::HandleFrameOutput() {
+ if (frame_capture_buffer_queued_) {
+ HandleFrameCapture();
+ } else if (dump_output_to_file_) {
+ HandleFrameDump();
+ }
+}
+
+void HWCDisplayPrimary::HandleFrameCapture() {
+ if (output_buffer_.release_fence_fd >= 0) {
+ frame_capture_status_ = sync_wait(output_buffer_.release_fence_fd, 1000);
+ ::close(output_buffer_.release_fence_fd);
+ output_buffer_.release_fence_fd = -1;
+ }
+
+ frame_capture_buffer_queued_ = false;
+ post_processed_output_ = false;
+ output_buffer_ = {};
+}
+
+void HWCDisplayPrimary::HandleFrameDump() {
+ if (dump_frame_count_ && output_buffer_.release_fence_fd >= 0) {
+ int ret = sync_wait(output_buffer_.release_fence_fd, 1000);
+ ::close(output_buffer_.release_fence_fd);
+ output_buffer_.release_fence_fd = -1;
+ if (ret < 0) {
+ DLOGE("sync_wait error errno = %d, desc = %s", errno, strerror(errno));
+ } else {
+ DumpOutputBuffer(output_buffer_info_, output_buffer_base_, layer_stack_.retire_fence_fd);
+ }
+ }
+
+ if (0 == dump_frame_count_) {
+ dump_output_to_file_ = false;
+ // Unmap and Free buffer
+ if (munmap(output_buffer_base_, output_buffer_info_.alloc_buffer_info.size) != 0) {
+ DLOGE("unmap failed with err %d", errno);
+ }
+ if (buffer_allocator_->FreeBuffer(&output_buffer_info_) != 0) {
+ DLOGE("FreeBuffer failed");
+ }
+
+ post_processed_output_ = false;
+ output_buffer_ = {};
+ output_buffer_info_ = {};
+ output_buffer_base_ = nullptr;
+ }
+}
+
+void HWCDisplayPrimary::SetFrameDumpConfig(uint32_t count, uint32_t bit_mask_layer_type) {
+ HWCDisplay::SetFrameDumpConfig(count, bit_mask_layer_type);
+ dump_output_to_file_ = bit_mask_layer_type & (1 << OUTPUT_LAYER_DUMP);
+ DLOGI("output_layer_dump_enable %d", dump_output_to_file_);
+
+ if (!count || !dump_output_to_file_) {
+ return;
+ }
+
+ // Allocate and map output buffer
+ output_buffer_info_ = {};
+ // Since we dump DSPP output use Panel resolution.
+ GetPanelResolution(&output_buffer_info_.buffer_config.width,
+ &output_buffer_info_.buffer_config.height);
+ output_buffer_info_.buffer_config.format = kFormatRGB888;
+ output_buffer_info_.buffer_config.buffer_count = 1;
+ if (buffer_allocator_->AllocateBuffer(&output_buffer_info_) != 0) {
+ DLOGE("Buffer allocation failed");
+ output_buffer_info_ = {};
+ return;
+ }
+
+ void *buffer = mmap(NULL, output_buffer_info_.alloc_buffer_info.size, PROT_READ | PROT_WRITE,
+ MAP_SHARED, output_buffer_info_.alloc_buffer_info.fd, 0);
+
+ if (buffer == MAP_FAILED) {
+ DLOGE("mmap failed with err %d", errno);
+ buffer_allocator_->FreeBuffer(&output_buffer_info_);
+ output_buffer_info_ = {};
+ return;
+ }
+
+ output_buffer_base_ = buffer;
+ post_processed_output_ = true;
+ DisablePartialUpdateOneFrame();
+ validated_.reset();
+}
+
+int HWCDisplayPrimary::FrameCaptureAsync(const BufferInfo &output_buffer_info,
+ bool post_processed_output) {
+ // Note: This function is called in context of a binder thread and a lock is already held
+ if (output_buffer_info.alloc_buffer_info.fd < 0) {
+ DLOGE("Invalid fd %d", output_buffer_info.alloc_buffer_info.fd);
+ return -1;
+ }
+
+ auto panel_width = 0u;
+ auto panel_height = 0u;
+ auto fb_width = 0u;
+ auto fb_height = 0u;
+
+ GetPanelResolution(&panel_width, &panel_height);
+ GetFrameBufferResolution(&fb_width, &fb_height);
+
+ if (post_processed_output && (output_buffer_info.buffer_config.width < panel_width ||
+ output_buffer_info.buffer_config.height < panel_height)) {
+ DLOGE("Buffer dimensions should not be less than panel resolution");
+ return -1;
+ } else if (!post_processed_output && (output_buffer_info.buffer_config.width < fb_width ||
+ output_buffer_info.buffer_config.height < fb_height)) {
+ DLOGE("Buffer dimensions should not be less than FB resolution");
+ return -1;
+ }
+
+ SetLayerBuffer(output_buffer_info, &output_buffer_);
+ post_processed_output_ = post_processed_output;
+ frame_capture_buffer_queued_ = true;
+ // Status is only cleared on a new call to dump and remains valid otherwise
+ frame_capture_status_ = -EAGAIN;
+ DisablePartialUpdateOneFrame();
+
+ return 0;
+}
+
+DisplayError HWCDisplayPrimary::SetDetailEnhancerConfig
+ (const DisplayDetailEnhancerData &de_data) {
+ DisplayError error = kErrorNotSupported;
+
+ if (display_intf_) {
+ error = display_intf_->SetDetailEnhancerData(de_data);
+ validated_.reset();
+ }
+ return error;
+}
+
+DisplayError HWCDisplayPrimary::ControlPartialUpdate(bool enable, uint32_t *pending) {
+ DisplayError error = kErrorNone;
+
+ if (display_intf_) {
+ error = display_intf_->ControlPartialUpdate(enable, pending);
+ validated_.reset();
+ }
+
+ return error;
+}
+
+DisplayError HWCDisplayPrimary::DisablePartialUpdateOneFrame() {
+ DisplayError error = kErrorNone;
+
+ if (display_intf_) {
+ error = display_intf_->DisablePartialUpdateOneFrame();
+ validated_.reset();
+ }
+
+ return error;
+}
+
+
+DisplayError HWCDisplayPrimary::SetMixerResolution(uint32_t width, uint32_t height) {
+ DisplayError error = display_intf_->SetMixerResolution(width, height);
+ validated_.reset();
+ return error;
+}
+
+DisplayError HWCDisplayPrimary::GetMixerResolution(uint32_t *width, uint32_t *height) {
+ return display_intf_->GetMixerResolution(width, height);
+}
+
+} // namespace sdm
diff --git a/msm8909/sdm/libs/hwc2/hwc_display_primary.h b/msm8909/sdm/libs/hwc2/hwc_display_primary.h
new file mode 100644
index 00000000..b5a522d3
--- /dev/null
+++ b/msm8909/sdm/libs/hwc2/hwc_display_primary.h
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials provided
+ with the distribution.
+ * Neither the name of The Linux Foundation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __HWC_DISPLAY_PRIMARY_H__
+#define __HWC_DISPLAY_PRIMARY_H__
+
+#include <string>
+
+#include "cpuhint.h"
+#include "hwc_display.h"
+
+namespace sdm {
+
+class HWCDisplayPrimary : public HWCDisplay {
+ public:
+ enum {
+ SET_METADATA_DYN_REFRESH_RATE,
+ SET_BINDER_DYN_REFRESH_RATE,
+ SET_DISPLAY_MODE,
+ SET_QDCM_SOLID_FILL_INFO,
+ UNSET_QDCM_SOLID_FILL_INFO,
+ SET_QDCM_SOLID_FILL_RECT,
+ };
+
+ static int Create(CoreInterface *core_intf, BufferAllocator *buffer_allocator,
+ HWCCallbacks *callbacks, qService::QService *qservice,
+ HWCDisplay **hwc_display);
+ static void Destroy(HWCDisplay *hwc_display);
+ virtual int Init();
+ virtual HWC2::Error Validate(uint32_t *out_num_types, uint32_t *out_num_requests);
+ virtual HWC2::Error Present(int32_t *out_retire_fence);
+ virtual HWC2::Error GetColorModes(uint32_t *out_num_modes, android_color_mode_t *out_modes);
+ virtual HWC2::Error SetColorMode(android_color_mode_t mode);
+ virtual HWC2::Error SetColorTransform(const float *matrix, android_color_transform_t hint);
+ virtual HWC2::Error RestoreColorTransform();
+ virtual int Perform(uint32_t operation, ...);
+ virtual void SetSecureDisplay(bool secure_display_active);
+ virtual DisplayError Refresh();
+ virtual void SetIdleTimeoutMs(uint32_t timeout_ms);
+ virtual void SetFrameDumpConfig(uint32_t count, uint32_t bit_mask_layer_type);
+ virtual int FrameCaptureAsync(const BufferInfo &output_buffer_info, bool post_processed);
+ virtual int GetFrameCaptureStatus() { return frame_capture_status_; }
+ virtual DisplayError SetDetailEnhancerConfig(const DisplayDetailEnhancerData &de_data);
+ virtual DisplayError ControlPartialUpdate(bool enable, uint32_t *pending);
+
+ private:
+ HWCDisplayPrimary(CoreInterface *core_intf, BufferAllocator *buffer_allocator,
+ HWCCallbacks *callbacks, qService::QService *qservice);
+ void SetMetaDataRefreshRateFlag(bool enable);
+ virtual DisplayError SetDisplayMode(uint32_t mode);
+ virtual DisplayError DisablePartialUpdateOneFrame();
+ void ProcessBootAnimCompleted(void);
+ void SetQDCMSolidFillInfo(bool enable, uint32_t color);
+ void ToggleCPUHint(bool set);
+ void ForceRefreshRate(uint32_t refresh_rate);
+ uint32_t GetOptimalRefreshRate(bool one_updating_layer);
+ void HandleFrameOutput();
+ void HandleFrameCapture();
+ void HandleFrameDump();
+ DisplayError SetMixerResolution(uint32_t width, uint32_t height);
+ DisplayError GetMixerResolution(uint32_t *width, uint32_t *height);
+
+ BufferAllocator *buffer_allocator_ = nullptr;
+ CPUHint *cpu_hint_ = nullptr;
+ bool handle_idle_timeout_ = false;
+
+ // Primary output buffer configuration
+ LayerBuffer output_buffer_ = {};
+ bool post_processed_output_ = false;
+
+ // Members for 1 frame capture in a client provided buffer
+ bool frame_capture_buffer_queued_ = false;
+ int frame_capture_status_ = -EAGAIN;
+
+ // Members for N frame output dump to file
+ bool dump_output_to_file_ = false;
+ BufferInfo output_buffer_info_ = {};
+ void *output_buffer_base_ = nullptr;
+ int default_mode_status_ = 0;
+};
+
+} // namespace sdm
+
+#endif // __HWC_DISPLAY_PRIMARY_H__
diff --git a/msm8909/sdm/libs/hwc2/hwc_display_virtual.cpp b/msm8909/sdm/libs/hwc2/hwc_display_virtual.cpp
new file mode 100644
index 00000000..232819ea
--- /dev/null
+++ b/msm8909/sdm/libs/hwc2/hwc_display_virtual.cpp
@@ -0,0 +1,263 @@
+/*
+* Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <utils/constants.h>
+#include <utils/debug.h>
+#include <sync/sync.h>
+#include <stdarg.h>
+#ifndef USE_GRALLOC1
+#include <gr.h>
+#endif
+
+#include "hwc_display_virtual.h"
+#include "hwc_debugger.h"
+
+#define __CLASS__ "HWCDisplayVirtual"
+
+namespace sdm {
+
+int HWCDisplayVirtual::Create(CoreInterface *core_intf, HWCBufferAllocator *buffer_allocator,
+ HWCCallbacks *callbacks, uint32_t width,
+ uint32_t height, int32_t *format, HWCDisplay **hwc_display) {
+ int status = 0;
+ HWCDisplayVirtual *hwc_display_virtual = new HWCDisplayVirtual(core_intf, buffer_allocator,
+ callbacks);
+
+ // TODO(user): Populate format correctly
+ DLOGI("Creating virtual display: w: %d h:%d format:0x%x", width, height, *format);
+
+ status = hwc_display_virtual->Init();
+ if (status) {
+ DLOGW("Failed to initialize virtual display");
+ delete hwc_display_virtual;
+ return status;
+ }
+
+ status = INT32(hwc_display_virtual->SetPowerMode(HWC2::PowerMode::On));
+ if (status) {
+ DLOGW("Failed to set power mode on virtual display");
+ Destroy(hwc_display_virtual);
+ return status;
+ }
+
+ status = hwc_display_virtual->SetConfig(width, height);
+ if (status) {
+ Destroy(hwc_display_virtual);
+ return status;
+ }
+
+ // TODO(user): Validate that we support this width/height
+ status = hwc_display_virtual->SetFrameBufferResolution(width, height);
+
+ if (status) {
+ DLOGW("Failed to set virtual display FB resolution");
+ Destroy(hwc_display_virtual);
+ return status;
+ }
+
+ *hwc_display = static_cast<HWCDisplay *>(hwc_display_virtual);
+
+ return 0;
+}
+
+void HWCDisplayVirtual::Destroy(HWCDisplay *hwc_display) {
+ hwc_display->Deinit();
+ delete hwc_display;
+}
+
+HWCDisplayVirtual::HWCDisplayVirtual(CoreInterface *core_intf, HWCBufferAllocator *buffer_allocator,
+ HWCCallbacks *callbacks)
+ : HWCDisplay(core_intf, callbacks, kVirtual, HWC_DISPLAY_VIRTUAL, false, NULL,
+ DISPLAY_CLASS_VIRTUAL, buffer_allocator) {
+}
+
+int HWCDisplayVirtual::Init() {
+ output_buffer_ = new LayerBuffer();
+ return HWCDisplay::Init();
+}
+
+int HWCDisplayVirtual::Deinit() {
+ int status = 0;
+ if (output_buffer_) {
+ if (output_buffer_->acquire_fence_fd >= 0) {
+ close(output_buffer_->acquire_fence_fd);
+ output_buffer_->acquire_fence_fd = -1;
+ }
+ delete output_buffer_;
+ output_buffer_ = nullptr;
+ }
+ status = HWCDisplay::Deinit();
+
+ return status;
+}
+
+HWC2::Error HWCDisplayVirtual::Validate(uint32_t *out_num_types, uint32_t *out_num_requests) {
+ auto status = HWC2::Error::None;
+
+ if (display_paused_) {
+ MarkLayersForGPUBypass();
+ return status;
+ }
+
+ BuildLayerStack();
+ layer_stack_.output_buffer = output_buffer_;
+
+ if (layer_set_.empty()) {
+ DLOGI("Skipping Validate and Commit");
+ return status;
+ }
+ status = PrepareLayerStack(out_num_types, out_num_requests);
+ return status;
+}
+
+HWC2::Error HWCDisplayVirtual::Present(int32_t *out_retire_fence) {
+ auto status = HWC2::Error::None;
+ if (display_paused_) {
+ DisplayError error = display_intf_->Flush();
+ if (error != kErrorNone) {
+ DLOGE("Flush failed. Error = %d", error);
+ }
+ } else {
+ status = HWCDisplay::CommitLayerStack();
+ if (status == HWC2::Error::None) {
+ if (dump_frame_count_ && !flush_ && dump_output_layer_) {
+ if (output_handle_) {
+ BufferInfo buffer_info;
+ const private_handle_t *output_handle =
+ reinterpret_cast<const private_handle_t *>(output_buffer_->buffer_id);
+ DisplayError error = kErrorNone;
+ if (!output_handle->base) {
+ error = buffer_allocator_->MapBuffer(output_handle, -1);
+ if (error != kErrorNone) {
+ DLOGE("Failed to map output buffer, error = %d", error);
+ return HWC2::Error::BadParameter;
+ }
+ }
+ buffer_info.buffer_config.width = static_cast<uint32_t>(output_handle->width);
+ buffer_info.buffer_config.height = static_cast<uint32_t>(output_handle->height);
+ buffer_info.buffer_config.format =
+ GetSDMFormat(output_handle->format, output_handle->flags);
+ buffer_info.alloc_buffer_info.size = static_cast<uint32_t>(output_handle->size);
+ DumpOutputBuffer(buffer_info, reinterpret_cast<void *>(output_handle->base),
+ layer_stack_.retire_fence_fd);
+
+ int release_fence = -1;
+ error = buffer_allocator_->UnmapBuffer(output_handle, &release_fence);
+ if (error != kErrorNone) {
+ DLOGE("Failed to unmap buffer, error = %d", error);
+ return HWC2::Error::BadParameter;
+ }
+ }
+ }
+
+ status = HWCDisplay::PostCommitLayerStack(out_retire_fence);
+ }
+ }
+ CloseAcquireFds();
+ if (output_buffer_->acquire_fence_fd >= 0) {
+ close(output_buffer_->acquire_fence_fd);
+ output_buffer_->acquire_fence_fd = -1;
+ }
+ return status;
+}
+
+int HWCDisplayVirtual::SetConfig(uint32_t width, uint32_t height) {
+ DisplayConfigVariableInfo variable_info;
+ variable_info.x_pixels = width;
+ variable_info.y_pixels = height;
+ // TODO(user): Need to get the framerate of primary display and update it.
+ variable_info.fps = 60;
+ return display_intf_->SetActiveConfig(&variable_info);
+}
+
+HWC2::Error HWCDisplayVirtual::SetOutputBuffer(buffer_handle_t buf, int32_t release_fence) {
+ if (buf == nullptr || release_fence == 0) {
+ return HWC2::Error::BadParameter;
+ }
+ const private_handle_t *output_handle = static_cast<const private_handle_t *>(buf);
+
+ // Fill output buffer parameters (width, height, format, plane information, fence)
+ output_buffer_->acquire_fence_fd = dup(release_fence);
+
+ if (output_handle) {
+ output_handle_ = output_handle;
+ output_buffer_->buffer_id = reinterpret_cast<uint64_t>(output_handle);
+ int output_handle_format = output_handle->format;
+
+ if (output_handle_format == HAL_PIXEL_FORMAT_RGBA_8888) {
+ output_handle_format = HAL_PIXEL_FORMAT_RGBX_8888;
+ }
+
+ output_buffer_->format = GetSDMFormat(output_handle_format, output_handle->flags);
+
+ if (output_buffer_->format == kFormatInvalid) {
+ return HWC2::Error::BadParameter;
+ }
+
+ int aligned_width, aligned_height;
+#ifdef USE_GRALLOC1
+ buffer_allocator_->GetCustomWidthAndHeight(output_handle, &aligned_width, &aligned_height);
+#else
+ AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(output_handle, aligned_width,
+ aligned_height);
+#endif
+
+ output_buffer_->width = UINT32(aligned_width);
+ output_buffer_->height = UINT32(aligned_height);
+ output_buffer_->unaligned_width = UINT32(output_handle->unaligned_width);
+ output_buffer_->unaligned_height = UINT32(output_handle->unaligned_height);
+ output_buffer_->flags.secure = 0;
+ output_buffer_->flags.video = 0;
+
+ if (sdm::SetCSC(output_handle, &output_buffer_->color_metadata) != kErrorNone) {
+ return HWC2::Error::BadParameter;
+ }
+
+ // TZ Protected Buffer - L1
+ if (output_handle->flags & private_handle_t::PRIV_FLAGS_SECURE_BUFFER) {
+ output_buffer_->flags.secure = 1;
+ }
+
+ // ToDo: Need to extend for non-RGB formats
+ output_buffer_->planes[0].fd = output_handle->fd;
+ output_buffer_->planes[0].offset = output_handle->offset;
+ output_buffer_->planes[0].stride = UINT32(output_handle->width);
+ }
+
+ return HWC2::Error::None;
+}
+
+void HWCDisplayVirtual::SetFrameDumpConfig(uint32_t count, uint32_t bit_mask_layer_type) {
+ HWCDisplay::SetFrameDumpConfig(count, bit_mask_layer_type);
+ dump_output_layer_ = ((bit_mask_layer_type & (1 << OUTPUT_LAYER_DUMP)) != 0);
+
+ DLOGI("output_layer_dump_enable %d", dump_output_layer_);
+}
+
+} // namespace sdm
diff --git a/msm8909/sdm/libs/hwc2/hwc_display_virtual.h b/msm8909/sdm/libs/hwc2/hwc_display_virtual.h
new file mode 100644
index 00000000..36e85091
--- /dev/null
+++ b/msm8909/sdm/libs/hwc2/hwc_display_virtual.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials provided
+ with the distribution.
+ * Neither the name of The Linux Foundation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __HWC_DISPLAY_VIRTUAL_H__
+#define __HWC_DISPLAY_VIRTUAL_H__
+
+#include <qdMetaData.h>
+#include <gralloc_priv.h>
+#include "hwc_display.h"
+
+namespace sdm {
+
+class HWCDisplayVirtual : public HWCDisplay {
+ public:
+ static int Create(CoreInterface *core_intf, HWCBufferAllocator *buffer_allocator,
+ HWCCallbacks *callbacks, uint32_t width,
+ uint32_t height, int32_t *format, HWCDisplay **hwc_display);
+ static void Destroy(HWCDisplay *hwc_display);
+ virtual int Init();
+ virtual int Deinit();
+ virtual HWC2::Error Validate(uint32_t *out_num_types, uint32_t *out_num_requests);
+ virtual HWC2::Error Present(int32_t *out_retire_fence);
+ virtual void SetFrameDumpConfig(uint32_t count, uint32_t bit_mask_layer_type);
+ HWC2::Error SetOutputBuffer(buffer_handle_t buf, int32_t release_fence);
+
+ private:
+ HWCDisplayVirtual(CoreInterface *core_intf, HWCBufferAllocator *buffer_allocator,
+ HWCCallbacks *callbacks);
+ int SetConfig(uint32_t width, uint32_t height);
+
+ bool dump_output_layer_ = false;
+ LayerBuffer *output_buffer_ = NULL;
+ const private_handle_t *output_handle_ = nullptr;
+};
+
+} // namespace sdm
+
+#endif // __HWC_DISPLAY_VIRTUAL_H__
diff --git a/msm8909/sdm/libs/hwc2/hwc_layers.cpp b/msm8909/sdm/libs/hwc2/hwc_layers.cpp
new file mode 100644
index 00000000..23c42aa7
--- /dev/null
+++ b/msm8909/sdm/libs/hwc2/hwc_layers.cpp
@@ -0,0 +1,827 @@
+/*
+ * Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
+ * Not a Contribution.
+ *
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdint.h>
+#include <qdMetaData.h>
+
+#include "hwc_layers.h"
+#ifndef USE_GRALLOC1
+#include <gr.h>
+#endif
+#include <utils/debug.h>
+#include <cmath>
+
+#define __CLASS__ "HWCLayer"
+
+namespace sdm {
+
+std::atomic<hwc2_layer_t> HWCLayer::next_id_(1);
+
+DisplayError SetCSC(const private_handle_t *pvt_handle, ColorMetaData *color_metadata) {
+ if (getMetaData(const_cast<private_handle_t *>(pvt_handle), GET_COLOR_METADATA,
+ color_metadata) != 0) {
+ ColorSpace_t csc = ITU_R_601;
+ if (getMetaData(const_cast<private_handle_t *>(pvt_handle), GET_COLOR_SPACE,
+ &csc) == 0) {
+ if (csc == ITU_R_601_FR || csc == ITU_R_2020_FR) {
+ color_metadata->range = Range_Full;
+ }
+
+ switch (csc) {
+ case ITU_R_601:
+ case ITU_R_601_FR:
+ // video and display driver uses 601_525
+ color_metadata->colorPrimaries = ColorPrimaries_BT601_6_525;
+ break;
+ case ITU_R_709:
+ color_metadata->colorPrimaries = ColorPrimaries_BT709_5;
+ break;
+ case ITU_R_2020:
+ case ITU_R_2020_FR:
+ color_metadata->colorPrimaries = ColorPrimaries_BT2020;
+ break;
+ default:
+ DLOGE("Unsupported CSC: %d", csc);
+ return kErrorNotSupported;
+ }
+ } else {
+ return kErrorNotSupported;
+ }
+ }
+
+ return kErrorNone;
+}
+
+// Returns true when color primary is supported
+bool GetColorPrimary(const int32_t &dataspace, ColorPrimaries *color_primary) {
+ auto standard = dataspace & HAL_DATASPACE_STANDARD_MASK;
+ bool supported_csc = true;
+ switch (standard) {
+ case HAL_DATASPACE_STANDARD_BT709:
+ *color_primary = ColorPrimaries_BT709_5;
+ break;
+ case HAL_DATASPACE_STANDARD_BT601_525:
+ case HAL_DATASPACE_STANDARD_BT601_525_UNADJUSTED:
+ *color_primary = ColorPrimaries_BT601_6_525;
+ break;
+ case HAL_DATASPACE_STANDARD_BT601_625:
+ case HAL_DATASPACE_STANDARD_BT601_625_UNADJUSTED:
+ *color_primary = ColorPrimaries_BT601_6_625;
+ break;
+ case HAL_DATASPACE_STANDARD_DCI_P3:
+ *color_primary = ColorPrimaries_DCIP3;
+ break;
+ case HAL_DATASPACE_STANDARD_BT2020:
+ *color_primary = ColorPrimaries_BT2020;
+ break;
+ default:
+ DLOGV_IF(kTagClient, "Unsupported Standard Request = %d", standard);
+ supported_csc = false;
+ }
+ return supported_csc;
+}
+
+bool GetTransfer(const int32_t &dataspace, GammaTransfer *gamma_transfer) {
+ auto transfer = dataspace & HAL_DATASPACE_TRANSFER_MASK;
+ bool supported_transfer = true;
+ switch (transfer) {
+ case HAL_DATASPACE_TRANSFER_SRGB:
+ *gamma_transfer = Transfer_sRGB;
+ break;
+ case HAL_DATASPACE_TRANSFER_SMPTE_170M:
+ *gamma_transfer = Transfer_SMPTE_170M;
+ break;
+ case HAL_DATASPACE_TRANSFER_ST2084:
+ *gamma_transfer = Transfer_SMPTE_ST2084;
+ break;
+ case HAL_DATASPACE_TRANSFER_HLG:
+ *gamma_transfer = Transfer_HLG;
+ break;
+ case HAL_DATASPACE_TRANSFER_LINEAR:
+ *gamma_transfer = Transfer_Linear;
+ break;
+ case HAL_DATASPACE_TRANSFER_GAMMA2_2:
+ *gamma_transfer = Transfer_Gamma2_2;
+ break;
+ default:
+ DLOGV_IF(kTagClient, "Unsupported Transfer Request = %d", transfer);
+ supported_transfer = false;
+ }
+ return supported_transfer;
+}
+
+void GetRange(const int32_t &dataspace, ColorRange *color_range) {
+ auto range = dataspace & HAL_DATASPACE_RANGE_MASK;
+ switch (range) {
+ case HAL_DATASPACE_RANGE_FULL:
+ *color_range = Range_Full;
+ break;
+ case HAL_DATASPACE_RANGE_LIMITED:
+ *color_range = Range_Limited;
+ break;
+ default:
+ DLOGV_IF(kTagClient, "Unsupported Range Request = %d", range);
+ break;
+ }
+}
+
+bool IsBT2020(const ColorPrimaries &color_primary) {
+ switch (color_primary) {
+ case ColorPrimaries_BT2020:
+ return true;
+ break;
+ default:
+ return false;
+ }
+}
+
+// Retrieve ColorMetaData from android_data_space_t (STANDARD|TRANSFER|RANGE)
+bool GetSDMColorSpace(const int32_t &dataspace, ColorMetaData *color_metadata) {
+ bool valid = false;
+ valid = GetColorPrimary(dataspace, &(color_metadata->colorPrimaries));
+ if (!valid) {
+ return valid;
+ }
+ valid = GetTransfer(dataspace, &(color_metadata->transfer));
+ if (!valid) {
+ return valid;
+ }
+ GetRange(dataspace, &(color_metadata->range));
+
+ return true;
+}
+
+// Layer operations
+HWCLayer::HWCLayer(hwc2_display_t display_id, HWCBufferAllocator *buf_allocator)
+ : id_(next_id_++), display_id_(display_id), buffer_allocator_(buf_allocator) {
+ layer_ = new Layer();
+ // Fences are deferred, so the first time this layer is presented, return -1
+ // TODO(user): Verify that fences are properly obtained on suspend/resume
+ release_fences_.push(-1);
+}
+
+HWCLayer::~HWCLayer() {
+ // Close any fences left for this layer
+ while (!release_fences_.empty()) {
+ close(release_fences_.front());
+ release_fences_.pop();
+ }
+ close(ion_fd_);
+ if (layer_) {
+ delete layer_;
+ }
+}
+
+HWC2::Error HWCLayer::SetLayerBuffer(buffer_handle_t buffer, int32_t acquire_fence) {
+ if (!buffer) {
+ DLOGE("Invalid buffer handle: %p on layer: %d", buffer, id_);
+ return HWC2::Error::BadParameter;
+ }
+
+ if (acquire_fence == 0) {
+ DLOGE("acquire_fence is zero");
+ return HWC2::Error::BadParameter;
+ }
+
+ const private_handle_t *handle = static_cast<const private_handle_t *>(buffer);
+
+ // Validate and dup ion fd from surfaceflinger
+ // This works around bug 30281222
+ if (handle->fd < 0) {
+ return HWC2::Error::BadParameter;
+ } else {
+ close(ion_fd_);
+ ion_fd_ = dup(handle->fd);
+ }
+
+ LayerBuffer *layer_buffer = &layer_->input_buffer;
+ int aligned_width, aligned_height;
+#ifdef USE_GRALLOC1
+ buffer_allocator_->GetCustomWidthAndHeight(handle, &aligned_width, &aligned_height);
+#else
+ AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(handle, aligned_width, aligned_height);
+#endif
+
+ LayerBufferFormat format = GetSDMFormat(handle->format, handle->flags);
+ if ((format != layer_buffer->format) || (UINT32(aligned_width) != layer_buffer->width) ||
+ (UINT32(aligned_height) != layer_buffer->height)) {
+ // Layer buffer geometry has changed.
+ geometry_changes_ |= kBufferGeometry;
+ }
+
+ layer_buffer->format = format;
+ layer_buffer->width = UINT32(aligned_width);
+ layer_buffer->height = UINT32(aligned_height);
+ layer_buffer->unaligned_width = UINT32(handle->unaligned_width);
+ layer_buffer->unaligned_height = UINT32(handle->unaligned_height);
+
+ if (SetMetaData(const_cast<private_handle_t *>(handle), layer_) != kErrorNone) {
+ return HWC2::Error::BadLayer;
+ }
+
+ layer_buffer->flags.video = (handle->buffer_type == BUFFER_TYPE_VIDEO) ? true : false;
+
+ // TZ Protected Buffer - L1
+ bool secure = (handle->flags & private_handle_t::PRIV_FLAGS_SECURE_BUFFER);
+ bool secure_camera = secure && (handle->flags & private_handle_t::PRIV_FLAGS_CAMERA_WRITE);
+ bool secure_display = (handle->flags & private_handle_t::PRIV_FLAGS_SECURE_DISPLAY);
+ if (secure != layer_buffer->flags.secure || secure_camera != layer_buffer->flags.secure_camera ||
+ secure_display != layer_buffer->flags.secure_display) {
+ // Secure attribute of layer buffer has changed.
+ needs_validate_ = true;
+ }
+
+ layer_buffer->flags.secure = secure;
+ layer_buffer->flags.secure_camera = secure_camera;
+ layer_buffer->flags.secure_display = secure_display;
+
+ layer_buffer->planes[0].fd = ion_fd_;
+ layer_buffer->planes[0].offset = handle->offset;
+ layer_buffer->planes[0].stride = UINT32(handle->width);
+ layer_buffer->acquire_fence_fd = acquire_fence;
+ layer_buffer->size = handle->size;
+ layer_buffer->buffer_id = reinterpret_cast<uint64_t>(handle);
+
+ return HWC2::Error::None;
+}
+
+HWC2::Error HWCLayer::SetLayerSurfaceDamage(hwc_region_t damage) {
+ // Check if there is an update in SurfaceDamage rects
+ if (layer_->dirty_regions.size() != damage.numRects) {
+ needs_validate_ = true;
+ } else {
+ for (uint32_t j = 0; j < damage.numRects; j++) {
+ LayerRect damage_rect;
+ SetRect(damage.rects[j], &damage_rect);
+ if (damage_rect != layer_->dirty_regions.at(j)) {
+ needs_validate_ = true;
+ break;
+ }
+ }
+ }
+
+ layer_->dirty_regions.clear();
+ for (uint32_t i = 0; i < damage.numRects; i++) {
+ LayerRect rect;
+ SetRect(damage.rects[i], &rect);
+ layer_->dirty_regions.push_back(rect);
+ }
+ return HWC2::Error::None;
+}
+
+HWC2::Error HWCLayer::SetLayerBlendMode(HWC2::BlendMode mode) {
+ LayerBlending blending = kBlendingPremultiplied;
+ switch (mode) {
+ case HWC2::BlendMode::Coverage:
+ blending = kBlendingCoverage;
+ break;
+ case HWC2::BlendMode::Premultiplied:
+ blending = kBlendingPremultiplied;
+ break;
+ case HWC2::BlendMode::None:
+ blending = kBlendingOpaque;
+ break;
+ default:
+ return HWC2::Error::BadParameter;
+ }
+
+ if (layer_->blending != blending) {
+ geometry_changes_ |= kBlendMode;
+ layer_->blending = blending;
+ }
+ return HWC2::Error::None;
+}
+
+HWC2::Error HWCLayer::SetLayerColor(hwc_color_t color) {
+ if (client_requested_ != HWC2::Composition::SolidColor) {
+ return HWC2::Error::None;
+ }
+ layer_->solid_fill_color = GetUint32Color(color);
+ layer_->input_buffer.format = kFormatARGB8888;
+ DLOGV_IF(kTagClient, "[%" PRIu64 "][%" PRIu64 "] Layer color set to %x", display_id_, id_,
+ layer_->solid_fill_color);
+ return HWC2::Error::None;
+}
+
+HWC2::Error HWCLayer::SetLayerCompositionType(HWC2::Composition type) {
+ client_requested_ = type;
+ switch (type) {
+ case HWC2::Composition::Client:
+ break;
+ case HWC2::Composition::Device:
+ // We try and default to this in SDM
+ break;
+ case HWC2::Composition::SolidColor:
+ break;
+ case HWC2::Composition::Cursor:
+ break;
+ case HWC2::Composition::Invalid:
+ return HWC2::Error::BadParameter;
+ default:
+ return HWC2::Error::Unsupported;
+ }
+
+ return HWC2::Error::None;
+}
+
+HWC2::Error HWCLayer::SetLayerDataspace(int32_t dataspace) {
+ // Map deprecated dataspace values to appropriate
+ // new enums
+ if (dataspace & 0xffff) {
+ switch (dataspace & 0xffff) {
+ case HAL_DATASPACE_SRGB:
+ dataspace = HAL_DATASPACE_V0_SRGB;
+ break;
+ case HAL_DATASPACE_JFIF:
+ dataspace = HAL_DATASPACE_V0_JFIF;
+ break;
+ case HAL_DATASPACE_SRGB_LINEAR:
+ dataspace = HAL_DATASPACE_V0_SRGB_LINEAR;
+ break;
+ case HAL_DATASPACE_BT601_625:
+ dataspace = HAL_DATASPACE_V0_BT601_625;
+ break;
+ case HAL_DATASPACE_BT601_525:
+ dataspace = HAL_DATASPACE_V0_BT601_525;
+ break;
+ case HAL_DATASPACE_BT709:
+ dataspace = HAL_DATASPACE_V0_BT709;
+ break;
+ default:
+ // unknown legacy dataspace
+ DLOGW_IF(kTagClient, "Unsupported dataspace type %d", dataspace);
+ }
+ }
+
+ // cache the dataspace, to be used later to update SDM ColorMetaData
+ if (dataspace_ != dataspace) {
+ geometry_changes_ |= kDataspace;
+ dataspace_ = dataspace;
+ }
+ return HWC2::Error::None;
+}
+
+HWC2::Error HWCLayer::SetLayerDisplayFrame(hwc_rect_t frame) {
+ LayerRect dst_rect = {};
+ SetRect(frame, &dst_rect);
+ if (layer_->dst_rect != dst_rect) {
+ geometry_changes_ |= kDisplayFrame;
+ layer_->dst_rect = dst_rect;
+ }
+ return HWC2::Error::None;
+}
+
+HWC2::Error HWCLayer::SetCursorPosition(int32_t x, int32_t y) {
+ hwc_rect_t frame = {};
+ frame.left = x;
+ frame.top = y;
+ frame.right = x + INT(layer_->dst_rect.right - layer_->dst_rect.left);
+ frame.bottom = y + INT(layer_->dst_rect.bottom - layer_->dst_rect.top);
+ SetLayerDisplayFrame(frame);
+
+ return HWC2::Error::None;
+}
+
+HWC2::Error HWCLayer::SetLayerPlaneAlpha(float alpha) {
+ // Conversion of float alpha in range 0.0 to 1.0 similar to the HWC Adapter
+ uint8_t plane_alpha = static_cast<uint8_t>(std::round(255.0f * alpha));
+ if (layer_->plane_alpha != plane_alpha) {
+ geometry_changes_ |= kPlaneAlpha;
+ layer_->plane_alpha = plane_alpha;
+ }
+
+ return HWC2::Error::None;
+}
+
+HWC2::Error HWCLayer::SetLayerSourceCrop(hwc_frect_t crop) {
+ LayerRect src_rect = {};
+ SetRect(crop, &src_rect);
+ if (layer_->src_rect != src_rect) {
+ geometry_changes_ |= kSourceCrop;
+ layer_->src_rect = src_rect;
+ }
+
+ return HWC2::Error::None;
+}
+
+HWC2::Error HWCLayer::SetLayerTransform(HWC2::Transform transform) {
+ LayerTransform layer_transform = {};
+ switch (transform) {
+ case HWC2::Transform::FlipH:
+ layer_transform.flip_horizontal = true;
+ break;
+ case HWC2::Transform::FlipV:
+ layer_transform.flip_vertical = true;
+ break;
+ case HWC2::Transform::Rotate90:
+ layer_transform.rotation = 90.0f;
+ break;
+ case HWC2::Transform::Rotate180:
+ layer_transform.flip_horizontal = true;
+ layer_transform.flip_vertical = true;
+ break;
+ case HWC2::Transform::Rotate270:
+ layer_transform.rotation = 90.0f;
+ layer_transform.flip_horizontal = true;
+ layer_transform.flip_vertical = true;
+ break;
+ case HWC2::Transform::FlipHRotate90:
+ layer_transform.rotation = 90.0f;
+ layer_transform.flip_horizontal = true;
+ break;
+ case HWC2::Transform::FlipVRotate90:
+ layer_transform.rotation = 90.0f;
+ layer_transform.flip_vertical = true;
+ break;
+ case HWC2::Transform::None:
+ // do nothing
+ break;
+ }
+
+ if (layer_->transform != layer_transform) {
+ geometry_changes_ |= kTransform;
+ layer_->transform = layer_transform;
+ }
+ return HWC2::Error::None;
+}
+
+HWC2::Error HWCLayer::SetLayerVisibleRegion(hwc_region_t visible) {
+ layer_->visible_regions.clear();
+ for (uint32_t i = 0; i < visible.numRects; i++) {
+ LayerRect rect;
+ SetRect(visible.rects[i], &rect);
+ layer_->visible_regions.push_back(rect);
+ }
+
+ return HWC2::Error::None;
+}
+
+HWC2::Error HWCLayer::SetLayerZOrder(uint32_t z) {
+ if (z_ != z) {
+ geometry_changes_ |= kZOrder;
+ z_ = z;
+ }
+ return HWC2::Error::None;
+}
+
+void HWCLayer::SetRect(const hwc_rect_t &source, LayerRect *target) {
+ target->left = FLOAT(source.left);
+ target->top = FLOAT(source.top);
+ target->right = FLOAT(source.right);
+ target->bottom = FLOAT(source.bottom);
+}
+
+void HWCLayer::SetRect(const hwc_frect_t &source, LayerRect *target) {
+ // Recommended way of rounding as in hwcomposer2.h - SetLayerSourceCrop
+ target->left = std::ceil(source.left);
+ target->top = std::ceil(source.top);
+ target->right = std::floor(source.right);
+ target->bottom = std::floor(source.bottom);
+}
+
+uint32_t HWCLayer::GetUint32Color(const hwc_color_t &source) {
+ // Returns 32 bit ARGB
+ uint32_t a = UINT32(source.a) << 24;
+ uint32_t r = UINT32(source.r) << 16;
+ uint32_t g = UINT32(source.g) << 8;
+ uint32_t b = UINT32(source.b);
+ uint32_t color = a | r | g | b;
+ return color;
+}
+
+LayerBufferFormat HWCLayer::GetSDMFormat(const int32_t &source, const int flags) {
+ LayerBufferFormat format = kFormatInvalid;
+ if (flags & private_handle_t::PRIV_FLAGS_UBWC_ALIGNED) {
+ switch (source) {
+ case HAL_PIXEL_FORMAT_RGBA_8888:
+ format = kFormatRGBA8888Ubwc;
+ break;
+ case HAL_PIXEL_FORMAT_RGBX_8888:
+ format = kFormatRGBX8888Ubwc;
+ break;
+ case HAL_PIXEL_FORMAT_BGR_565:
+ format = kFormatBGR565Ubwc;
+ break;
+ case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
+ case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC:
+ case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
+ format = kFormatYCbCr420SPVenusUbwc;
+ break;
+ case HAL_PIXEL_FORMAT_YCbCr_420_TP10_UBWC:
+ format = kFormatYCbCr420TP10Ubwc;
+ break;
+ case HAL_PIXEL_FORMAT_YCbCr_420_P010_UBWC:
+ format = kFormatYCbCr420P010Ubwc;
+ break;
+ default:
+ DLOGE("Unsupported format type for UBWC %d", source);
+ return kFormatInvalid;
+ }
+ return format;
+ }
+
+ switch (source) {
+ case HAL_PIXEL_FORMAT_RGBA_8888:
+ format = kFormatRGBA8888;
+ break;
+ case HAL_PIXEL_FORMAT_RGBA_5551:
+ format = kFormatRGBA5551;
+ break;
+ case HAL_PIXEL_FORMAT_RGBA_4444:
+ format = kFormatRGBA4444;
+ break;
+ case HAL_PIXEL_FORMAT_BGRA_8888:
+ format = kFormatBGRA8888;
+ break;
+ case HAL_PIXEL_FORMAT_RGBX_8888:
+ format = kFormatRGBX8888;
+ break;
+ case HAL_PIXEL_FORMAT_BGRX_8888:
+ format = kFormatBGRX8888;
+ break;
+ case HAL_PIXEL_FORMAT_RGB_888:
+ format = kFormatRGB888;
+ break;
+ case HAL_PIXEL_FORMAT_BGR_888:
+ format = kFormatBGR888;
+ break;
+ case HAL_PIXEL_FORMAT_RGB_565:
+ format = kFormatRGB565;
+ break;
+ case HAL_PIXEL_FORMAT_BGR_565:
+ format = kFormatBGR565;
+ break;
+ case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
+ case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
+ format = kFormatYCbCr420SemiPlanarVenus;
+ break;
+ case HAL_PIXEL_FORMAT_YCrCb_420_SP_VENUS:
+ format = kFormatYCrCb420SemiPlanarVenus;
+ break;
+ case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC:
+ format = kFormatYCbCr420SPVenusUbwc;
+ break;
+ case HAL_PIXEL_FORMAT_YV12:
+ format = kFormatYCrCb420PlanarStride16;
+ break;
+ case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+ format = kFormatYCrCb420SemiPlanar;
+ break;
+ case HAL_PIXEL_FORMAT_YCbCr_420_SP:
+ format = kFormatYCbCr420SemiPlanar;
+ break;
+ case HAL_PIXEL_FORMAT_YCbCr_422_SP:
+ format = kFormatYCbCr422H2V1SemiPlanar;
+ break;
+ case HAL_PIXEL_FORMAT_YCbCr_422_I:
+ format = kFormatYCbCr422H2V1Packed;
+ break;
+ case HAL_PIXEL_FORMAT_CbYCrY_422_I:
+ format = kFormatCbYCrY422H2V1Packed;
+ break;
+ case HAL_PIXEL_FORMAT_RGBA_1010102:
+ format = kFormatRGBA1010102;
+ break;
+ case HAL_PIXEL_FORMAT_ARGB_2101010:
+ format = kFormatARGB2101010;
+ break;
+ case HAL_PIXEL_FORMAT_RGBX_1010102:
+ format = kFormatRGBX1010102;
+ break;
+ case HAL_PIXEL_FORMAT_XRGB_2101010:
+ format = kFormatXRGB2101010;
+ break;
+ case HAL_PIXEL_FORMAT_BGRA_1010102:
+ format = kFormatBGRA1010102;
+ break;
+ case HAL_PIXEL_FORMAT_ABGR_2101010:
+ format = kFormatABGR2101010;
+ break;
+ case HAL_PIXEL_FORMAT_BGRX_1010102:
+ format = kFormatBGRX1010102;
+ break;
+ case HAL_PIXEL_FORMAT_XBGR_2101010:
+ format = kFormatXBGR2101010;
+ break;
+ case HAL_PIXEL_FORMAT_YCbCr_420_P010:
+ format = kFormatYCbCr420P010;
+ break;
+ case HAL_PIXEL_FORMAT_YCbCr_420_TP10_UBWC:
+ format = kFormatYCbCr420TP10Ubwc;
+ break;
+ case HAL_PIXEL_FORMAT_YCbCr_420_P010_UBWC:
+ format = kFormatYCbCr420P010Ubwc;
+ break;
+ default:
+ DLOGW("Unsupported format type = %d", source);
+ return kFormatInvalid;
+ }
+
+ return format;
+}
+
+LayerBufferS3DFormat HWCLayer::GetS3DFormat(uint32_t s3d_format) {
+ LayerBufferS3DFormat sdm_s3d_format = kS3dFormatNone;
+ switch (s3d_format) {
+ case HAL_NO_3D:
+ sdm_s3d_format = kS3dFormatNone;
+ break;
+ case HAL_3D_SIDE_BY_SIDE_L_R:
+ sdm_s3d_format = kS3dFormatLeftRight;
+ break;
+ case HAL_3D_SIDE_BY_SIDE_R_L:
+ sdm_s3d_format = kS3dFormatRightLeft;
+ break;
+ case HAL_3D_TOP_BOTTOM:
+ sdm_s3d_format = kS3dFormatTopBottom;
+ break;
+ default:
+ DLOGW("Invalid S3D format %d", s3d_format);
+ }
+ return sdm_s3d_format;
+}
+
+DisplayError HWCLayer::SetMetaData(const private_handle_t *pvt_handle, Layer *layer) {
+ LayerBuffer *layer_buffer = &layer->input_buffer;
+ private_handle_t *handle = const_cast<private_handle_t *>(pvt_handle);
+ IGC_t igc = {};
+ LayerIGC layer_igc = layer_buffer->igc;
+ if (getMetaData(handle, GET_IGC, &igc) == 0) {
+ if (SetIGC(igc, &layer_igc) != kErrorNone) {
+ return kErrorNotSupported;
+ }
+ }
+
+ float fps = 0;
+ uint32_t frame_rate = layer->frame_rate;
+ if (getMetaData(handle, GET_REFRESH_RATE, &fps) == 0) {
+ frame_rate = RoundToStandardFPS(fps);
+ }
+
+ int32_t interlaced = 0;
+ bool interlace = layer_buffer->flags.interlace;
+ if (getMetaData(handle, GET_PP_PARAM_INTERLACED, &interlaced) == 0) {
+ interlace = interlaced ? true : false;
+ }
+ if (interlace != layer_buffer->flags.interlace) {
+ DLOGI("Layer buffer interlaced metadata has changed. old=%d, new=%d",
+ layer_buffer->flags.interlace, interlace);
+ }
+
+ uint32_t linear_format = 0;
+ if (getMetaData(handle, GET_LINEAR_FORMAT, &linear_format) == 0) {
+ layer_buffer->format = GetSDMFormat(INT32(linear_format), 0);
+ }
+
+ uint32_t s3d = 0;
+ LayerBufferS3DFormat s3d_format = layer_buffer->s3d_format;
+ if (getMetaData(handle, GET_S3D_FORMAT, &s3d) == 0) {
+ s3d_format = GetS3DFormat(s3d);
+ }
+
+ if ((layer_igc != layer_buffer->igc) || (interlace != layer_buffer->flags.interlace) ||
+ (frame_rate != layer->frame_rate) || (s3d_format != layer_buffer->s3d_format)) {
+ // Layer buffer metadata has changed.
+ needs_validate_ = true;
+ layer_buffer->igc = layer_igc;
+ layer->frame_rate = frame_rate;
+ layer_buffer->s3d_format = s3d_format;
+ layer_buffer->flags.interlace = interlace;
+ }
+
+ return kErrorNone;
+}
+
+DisplayError HWCLayer::SetIGC(IGC_t source, LayerIGC *target) {
+ switch (source) {
+ case IGC_NotSpecified:
+ *target = kIGCNotSpecified;
+ break;
+ case IGC_sRGB:
+ *target = kIGCsRGB;
+ break;
+ default:
+ DLOGE("Unsupported IGC: %d", source);
+ return kErrorNotSupported;
+ }
+
+ return kErrorNone;
+}
+
+
+
+bool HWCLayer::SupportLocalConversion(ColorPrimaries working_primaries) {
+ if (layer_->input_buffer.color_metadata.colorPrimaries <= ColorPrimaries_BT601_6_525 &&
+ working_primaries <= ColorPrimaries_BT601_6_525) {
+ return true;
+ }
+ return false;
+}
+
+bool HWCLayer::ValidateAndSetCSC() {
+ if (client_requested_ != HWC2::Composition::Device &&
+ client_requested_ != HWC2::Composition::Cursor) {
+ // Check the layers which are configured to Device
+ return true;
+ }
+
+ LayerBuffer *layer_buffer = &layer_->input_buffer;
+ bool use_color_metadata = true;
+#ifdef FEATURE_WIDE_COLOR
+ ColorMetaData csc = {};
+ if (dataspace_ != HAL_DATASPACE_UNKNOWN) {
+ use_color_metadata = false;
+ bool valid_csc = GetSDMColorSpace(dataspace_, &csc);
+ if (!valid_csc) {
+ return false;
+ }
+ // if we are here here, update the sdm layer csc.
+ layer_buffer->color_metadata.transfer = csc.transfer;
+ layer_buffer->color_metadata.colorPrimaries = csc.colorPrimaries;
+ layer_buffer->color_metadata.range = csc.range;
+ }
+#endif
+
+ if (IsBT2020(layer_buffer->color_metadata.colorPrimaries)) {
+ // android_dataspace_t doesnt support mastering display and light levels
+ // so retrieve it from metadata for BT2020(HDR)
+ use_color_metadata = true;
+ }
+
+ if (use_color_metadata) {
+ const private_handle_t *handle =
+ reinterpret_cast<const private_handle_t *>(layer_buffer->buffer_id);
+ if (sdm::SetCSC(handle, &layer_buffer->color_metadata) != kErrorNone) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+
+uint32_t HWCLayer::RoundToStandardFPS(float fps) {
+ static const uint32_t standard_fps[4] = {24, 30, 48, 60};
+ uint32_t frame_rate = (uint32_t)(fps);
+
+ int count = INT(sizeof(standard_fps) / sizeof(standard_fps[0]));
+ for (int i = 0; i < count; i++) {
+ if ((standard_fps[i] - frame_rate) < 2) {
+ // Most likely used for video, the fps can fluctuate
+ // Ex: b/w 29 and 30 for 30 fps clip
+ return standard_fps[i];
+ }
+ }
+
+ return frame_rate;
+}
+
+void HWCLayer::SetComposition(const LayerComposition &sdm_composition) {
+ auto hwc_composition = HWC2::Composition::Invalid;
+ switch (sdm_composition) {
+ case kCompositionGPU:
+ hwc_composition = HWC2::Composition::Client;
+ break;
+ case kCompositionHWCursor:
+ hwc_composition = HWC2::Composition::Cursor;
+ break;
+ default:
+ hwc_composition = HWC2::Composition::Device;
+ break;
+ }
+ // Update solid fill composition
+ if (sdm_composition == kCompositionSDE && layer_->flags.solid_fill != 0) {
+ hwc_composition = HWC2::Composition::SolidColor;
+ }
+ device_selected_ = hwc_composition;
+
+ return;
+}
+void HWCLayer::PushReleaseFence(int32_t fence) {
+ release_fences_.push(fence);
+}
+int32_t HWCLayer::PopReleaseFence(void) {
+ if (release_fences_.empty())
+ return -1;
+ auto fence = release_fences_.front();
+ release_fences_.pop();
+ return fence;
+}
+
+} // namespace sdm
diff --git a/msm8909/sdm/libs/hwc2/hwc_layers.h b/msm8909/sdm/libs/hwc2/hwc_layers.h
new file mode 100644
index 00000000..1d71ca8c
--- /dev/null
+++ b/msm8909/sdm/libs/hwc2/hwc_layers.h
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
+ * Not a Contribution.
+ *
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __HWC_LAYERS_H__
+#define __HWC_LAYERS_H__
+
+/* This class translates HWC2 Layer functions to the SDM LayerStack
+ */
+
+#include <gralloc_priv.h>
+#include <qdMetaData.h>
+#include <core/layer_stack.h>
+#define HWC2_INCLUDE_STRINGIFICATION
+#define HWC2_USE_CPP11
+#include <hardware/hwcomposer2.h>
+#undef HWC2_INCLUDE_STRINGIFICATION
+#undef HWC2_USE_CPP11
+#include <map>
+#include <queue>
+#include <set>
+#include "core/buffer_allocator.h"
+#include "hwc_buffer_allocator.h"
+
+namespace sdm {
+
+DisplayError SetCSC(const private_handle_t *pvt_handle, ColorMetaData *color_metadata);
+bool GetColorPrimary(const int32_t &dataspace, ColorPrimaries *color_primary);
+bool GetTransfer(const int32_t &dataspace, GammaTransfer *gamma_transfer);
+void GetRange(const int32_t &dataspace, ColorRange *color_range);
+bool GetSDMColorSpace(const int32_t &dataspace, ColorMetaData *color_metadata);
+bool IsBT2020(const ColorPrimaries &color_primary);
+enum GeometryChanges {
+ kNone = 0x000,
+ kBlendMode = 0x001,
+ kDataspace = 0x002,
+ kDisplayFrame = 0x004,
+ kPlaneAlpha = 0x008,
+ kSourceCrop = 0x010,
+ kTransform = 0x020,
+ kZOrder = 0x040,
+ kAdded = 0x080,
+ kRemoved = 0x100,
+ kBufferGeometry = 0x200,
+};
+
+class HWCLayer {
+ public:
+ explicit HWCLayer(hwc2_display_t display_id, HWCBufferAllocator *buf_allocator);
+ ~HWCLayer();
+ uint32_t GetZ() const { return z_; }
+ hwc2_layer_t GetId() const { return id_; }
+ Layer *GetSDMLayer() { return layer_; }
+
+ HWC2::Error SetLayerBlendMode(HWC2::BlendMode mode);
+ HWC2::Error SetLayerBuffer(buffer_handle_t buffer, int32_t acquire_fence);
+ HWC2::Error SetLayerColor(hwc_color_t color);
+ HWC2::Error SetLayerCompositionType(HWC2::Composition type);
+ HWC2::Error SetLayerDataspace(int32_t dataspace);
+ HWC2::Error SetLayerDisplayFrame(hwc_rect_t frame);
+ HWC2::Error SetCursorPosition(int32_t x, int32_t y);
+ HWC2::Error SetLayerPlaneAlpha(float alpha);
+ HWC2::Error SetLayerSourceCrop(hwc_frect_t crop);
+ HWC2::Error SetLayerSurfaceDamage(hwc_region_t damage);
+ HWC2::Error SetLayerTransform(HWC2::Transform transform);
+ HWC2::Error SetLayerVisibleRegion(hwc_region_t visible);
+ HWC2::Error SetLayerZOrder(uint32_t z);
+ void SetComposition(const LayerComposition &sdm_composition);
+ HWC2::Composition GetClientRequestedCompositionType() { return client_requested_; }
+ void UpdateClientCompositionType(HWC2::Composition type) { client_requested_ = type; }
+ HWC2::Composition GetDeviceSelectedCompositionType() { return device_selected_; }
+ int32_t GetLayerDataspace() { return dataspace_; }
+ uint32_t GetGeometryChanges() { return geometry_changes_; }
+ void ResetGeometryChanges() { geometry_changes_ = GeometryChanges::kNone; }
+ void PushReleaseFence(int32_t fence);
+ int32_t PopReleaseFence(void);
+ bool ValidateAndSetCSC();
+ bool SupportLocalConversion(ColorPrimaries working_primaries);
+ void ResetValidation() { needs_validate_ = false; }
+ bool NeedsValidation() { return (needs_validate_ || geometry_changes_); }
+
+ private:
+ Layer *layer_ = nullptr;
+ uint32_t z_ = 0;
+ const hwc2_layer_t id_;
+ const hwc2_display_t display_id_;
+ static std::atomic<hwc2_layer_t> next_id_;
+ std::queue<int32_t> release_fences_;
+ int ion_fd_ = -1;
+ HWCBufferAllocator *buffer_allocator_ = NULL;
+ int32_t dataspace_ = HAL_DATASPACE_UNKNOWN;
+ bool needs_validate_ = true;
+
+ // Composition requested by client(SF)
+ HWC2::Composition client_requested_ = HWC2::Composition::Device;
+ // Composition selected by SDM
+ HWC2::Composition device_selected_ = HWC2::Composition::Device;
+ uint32_t geometry_changes_ = GeometryChanges::kNone;
+
+ void SetRect(const hwc_rect_t &source, LayerRect *target);
+ void SetRect(const hwc_frect_t &source, LayerRect *target);
+ uint32_t GetUint32Color(const hwc_color_t &source);
+ LayerBufferFormat GetSDMFormat(const int32_t &source, const int flags);
+ LayerBufferS3DFormat GetS3DFormat(uint32_t s3d_format);
+ DisplayError SetMetaData(const private_handle_t *pvt_handle, Layer *layer);
+ DisplayError SetIGC(IGC_t source, LayerIGC *target);
+ uint32_t RoundToStandardFPS(float fps);
+};
+
+struct SortLayersByZ {
+ bool operator()(const HWCLayer *lhs, const HWCLayer *rhs) const {
+ return lhs->GetZ() < rhs->GetZ();
+ }
+};
+
+} // namespace sdm
+#endif // __HWC_LAYERS_H__
diff --git a/msm8909/sdm/libs/hwc2/hwc_session.cpp b/msm8909/sdm/libs/hwc2/hwc_session.cpp
new file mode 100644
index 00000000..b78b1a2b
--- /dev/null
+++ b/msm8909/sdm/libs/hwc2/hwc_session.cpp
@@ -0,0 +1,1631 @@
+/*
+ * Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
+ * Not a Contribution.
+ *
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <core/buffer_allocator.h>
+#include <private/color_params.h>
+#include <utils/constants.h>
+#include <utils/String16.h>
+#include <cutils/properties.h>
+#include <hardware_legacy/uevent.h>
+#include <sys/resource.h>
+#include <sys/prctl.h>
+#include <binder/Parcel.h>
+#include <QService.h>
+#include <display_config.h>
+#include <utils/debug.h>
+#include <sync/sync.h>
+#include <profiler.h>
+#include <algorithm>
+#include <string>
+#include <bitset>
+#include <thread>
+#include <memory>
+
+#include "hwc_buffer_allocator.h"
+#include "hwc_buffer_sync_handler.h"
+#include "hwc_session.h"
+#include "hwc_debugger.h"
+#include "hwc_display_primary.h"
+#include "hwc_display_virtual.h"
+#include "hwc_display_external_test.h"
+#include "qd_utils.h"
+
+#define __CLASS__ "HWCSession"
+
+#define HWC_UEVENT_SWITCH_HDMI "change@/devices/virtual/switch/hdmi"
+#define HWC_UEVENT_GRAPHICS_FB0 "change@/devices/virtual/graphics/fb0"
+
+static sdm::HWCSession::HWCModuleMethods g_hwc_module_methods;
+
+hwc_module_t HAL_MODULE_INFO_SYM = {
+ .common = {
+ .tag = HARDWARE_MODULE_TAG,
+ .version_major = 3,
+ .version_minor = 0,
+ .id = HWC_HARDWARE_MODULE_ID,
+ .name = "QTI Hardware Composer Module",
+ .author = "CodeAurora Forum",
+ .methods = &g_hwc_module_methods,
+ .dso = 0,
+ .reserved = {0},
+ }
+};
+
+namespace sdm {
+
+static HWCUEvent g_hwc_uevent_;
+Locker HWCSession::locker_[HWC_NUM_DISPLAY_TYPES];
+bool HWCSession::disable_skip_validate_ = false;
+
+void HWCUEvent::UEventThread(HWCUEvent *hwc_uevent) {
+ const char *uevent_thread_name = "HWC_UeventThread";
+
+ prctl(PR_SET_NAME, uevent_thread_name, 0, 0, 0);
+ setpriority(PRIO_PROCESS, 0, HAL_PRIORITY_URGENT_DISPLAY);
+
+ int status = uevent_init();
+ if (!status) {
+ std::unique_lock<std::mutex> caller_lock(hwc_uevent->mutex_);
+ hwc_uevent->caller_cv_.notify_one();
+ DLOGE("Failed to init uevent with err %d", status);
+ return;
+ }
+
+ {
+ // Signal caller thread that worker thread is ready to listen to events.
+ std::unique_lock<std::mutex> caller_lock(hwc_uevent->mutex_);
+ hwc_uevent->init_done_ = true;
+ hwc_uevent->caller_cv_.notify_one();
+ }
+
+ while (1) {
+ char uevent_data[PAGE_SIZE] = {};
+
+ // keep last 2 zeroes to ensure double 0 termination
+ int length = uevent_next_event(uevent_data, INT32(sizeof(uevent_data)) - 2);
+
+ // scope of lock to this block only, so that caller is free to set event handler to nullptr;
+ {
+ std::lock_guard<std::mutex> guard(hwc_uevent->mutex_);
+ if (hwc_uevent->uevent_listener_) {
+ hwc_uevent->uevent_listener_->UEventHandler(uevent_data, length);
+ } else {
+ DLOGW("UEvent dropped. No uevent listener.");
+ }
+ }
+ }
+}
+
+HWCUEvent::HWCUEvent() {
+ std::unique_lock<std::mutex> caller_lock(mutex_);
+ std::thread thread(HWCUEvent::UEventThread, this);
+ thread.detach();
+ caller_cv_.wait(caller_lock);
+}
+
+void HWCUEvent::Register(HWCUEventListener *uevent_listener) {
+ DLOGI("Set uevent listener = %p", uevent_listener);
+
+ std::lock_guard<std::mutex> obj(mutex_);
+ uevent_listener_ = uevent_listener;
+}
+
+HWCSession::HWCSession(const hw_module_t *module) {
+ hwc2_device_t::common.tag = HARDWARE_DEVICE_TAG;
+ hwc2_device_t::common.version = HWC_DEVICE_API_VERSION_2_0;
+ hwc2_device_t::common.module = const_cast<hw_module_t *>(module);
+ hwc2_device_t::common.close = Close;
+ hwc2_device_t::getCapabilities = GetCapabilities;
+ hwc2_device_t::getFunction = GetFunction;
+}
+
+int HWCSession::Init() {
+ SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
+
+ int status = -EINVAL;
+ const char *qservice_name = "display.qservice";
+
+ if (!g_hwc_uevent_.InitDone()) {
+ return status;
+ }
+
+ // Start QService and connect to it.
+ qService::QService::init();
+ android::sp<qService::IQService> iqservice = android::interface_cast<qService::IQService>(
+ android::defaultServiceManager()->getService(android::String16(qservice_name)));
+
+ if (iqservice.get()) {
+ iqservice->connect(android::sp<qClient::IQClient>(this));
+ qservice_ = reinterpret_cast<qService::QService *>(iqservice.get());
+ } else {
+ ALOGE("%s::%s: Failed to acquire %s", __CLASS__, __FUNCTION__, qservice_name);
+ return -EINVAL;
+ }
+
+ StartServices();
+
+ DisplayError error = buffer_allocator_.Init();
+ if (error != kErrorNone) {
+ ALOGE("%s::%s: Buffer allocaor initialization failed. Error = %d",
+ __CLASS__, __FUNCTION__, error);
+ return -EINVAL;
+ }
+
+ error = CoreInterface::CreateCore(HWCDebugHandler::Get(), &buffer_allocator_,
+ &buffer_sync_handler_, &socket_handler_, &core_intf_);
+ if (error != kErrorNone) {
+ buffer_allocator_.Deinit();
+ ALOGE("%s::%s: Display core initialization failed. Error = %d", __CLASS__, __FUNCTION__, error);
+ return -EINVAL;
+ }
+
+ g_hwc_uevent_.Register(this);
+
+ // If HDMI display is primary display, defer display creation until hotplug event is received.
+ HWDisplayInterfaceInfo hw_disp_info = {};
+ error = core_intf_->GetFirstDisplayInterfaceType(&hw_disp_info);
+ if (error != kErrorNone) {
+ g_hwc_uevent_.Register(nullptr);
+ CoreInterface::DestroyCore();
+ buffer_allocator_.Deinit();
+ DLOGE("Primary display type not recognized. Error = %d", error);
+ return -EINVAL;
+ }
+
+ if (hw_disp_info.type == kHDMI) {
+ status = 0;
+ hdmi_is_primary_ = true;
+ // Create display if it is connected, else wait for hotplug connect event.
+ if (hw_disp_info.is_connected) {
+ status = CreateExternalDisplay(HWC_DISPLAY_PRIMARY);
+ }
+ } else {
+ // Create and power on primary display
+ status = HWCDisplayPrimary::Create(core_intf_, &buffer_allocator_, &callbacks_, qservice_,
+ &hwc_display_[HWC_DISPLAY_PRIMARY]);
+ color_mgr_ = HWCColorManager::CreateColorManager(&buffer_allocator_);
+ if (!color_mgr_) {
+ DLOGW("Failed to load HWCColorManager.");
+ }
+ }
+
+ if (status) {
+ g_hwc_uevent_.Register(nullptr);
+ CoreInterface::DestroyCore();
+ buffer_allocator_.Deinit();
+ return status;
+ }
+
+ struct rlimit fd_limit = {};
+ getrlimit(RLIMIT_NOFILE, &fd_limit);
+ fd_limit.rlim_cur = fd_limit.rlim_cur * 2;
+ if (fd_limit.rlim_cur < fd_limit.rlim_max) {
+ auto err = setrlimit(RLIMIT_NOFILE, &fd_limit);
+ if (err) {
+ DLOGW("Unable to increase fd limit - err:%d, %s", errno, strerror(errno));
+ }
+ }
+
+ return 0;
+}
+
+int HWCSession::Deinit() {
+ Locker::SequenceCancelScopeLock lock_v(locker_[HWC_DISPLAY_VIRTUAL]);
+ Locker::SequenceCancelScopeLock lock_e(locker_[HWC_DISPLAY_EXTERNAL]);
+ Locker::SequenceCancelScopeLock lock_p(locker_[HWC_DISPLAY_PRIMARY]);
+
+ HWCDisplay *primary_display = hwc_display_[HWC_DISPLAY_PRIMARY];
+ if (primary_display) {
+ if (hdmi_is_primary_) {
+ HWCDisplayExternal::Destroy(primary_display);
+ } else {
+ HWCDisplayPrimary::Destroy(primary_display);
+ }
+ }
+ hwc_display_[HWC_DISPLAY_PRIMARY] = nullptr;
+
+ if (color_mgr_) {
+ color_mgr_->DestroyColorManager();
+ }
+
+ g_hwc_uevent_.Register(nullptr);
+
+ DisplayError error = CoreInterface::DestroyCore();
+ if (error != kErrorNone) {
+ ALOGE("Display core de-initialization failed. Error = %d", error);
+ }
+
+ return 0;
+}
+
+int HWCSession::Open(const hw_module_t *module, const char *name, hw_device_t **device) {
+ if (!module || !name || !device) {
+ ALOGE("%s::%s: Invalid parameters.", __CLASS__, __FUNCTION__);
+ return -EINVAL;
+ }
+
+ if (!strcmp(name, HWC_HARDWARE_COMPOSER)) {
+ HWCSession *hwc_session = new HWCSession(module);
+ if (!hwc_session) {
+ return -ENOMEM;
+ }
+
+ int status = hwc_session->Init();
+ if (status != 0) {
+ return status;
+ }
+
+ hwc2_device_t *composer_device = hwc_session;
+ *device = reinterpret_cast<hw_device_t *>(composer_device);
+ }
+
+ return 0;
+}
+
+int HWCSession::Close(hw_device_t *device) {
+ if (!device) {
+ return -EINVAL;
+ }
+
+ hwc2_device_t *composer_device = reinterpret_cast<hwc2_device_t *>(device);
+ HWCSession *hwc_session = static_cast<HWCSession *>(composer_device);
+
+ hwc_session->Deinit();
+
+ return 0;
+}
+
+void HWCSession::GetCapabilities(struct hwc2_device *device, uint32_t *outCount,
+ int32_t *outCapabilities) {
+ if (!outCount) {
+ return;
+ }
+
+ int value = 0;
+ uint32_t count = 0;
+ HWCSession *hwc_session = static_cast<HWCSession *>(device);
+ bool color_transform_supported = hwc_session->core_intf_->IsColorTransformSupported();
+
+ if (Debug::Get()->GetProperty(DISABLE_SKIP_VALIDATE_PROP, &value) == kErrorNone) {
+ disable_skip_validate_ = (value == 1);
+ }
+
+ count += (color_transform_supported) ? 1 : 0;
+ count += (!disable_skip_validate_) ? 1 : 0;
+
+ if (outCapabilities != nullptr && (*outCount >= count)) {
+ int i = 0;
+ if (color_transform_supported) {
+ outCapabilities[i++] = HWC2_CAPABILITY_SKIP_CLIENT_COLOR_TRANSFORM;
+ }
+ if (!disable_skip_validate_) {
+ outCapabilities[i++] = HWC2_CAPABILITY_SKIP_VALIDATE;
+ }
+ }
+ *outCount = count;
+}
+
+template <typename PFN, typename T>
+static hwc2_function_pointer_t AsFP(T function) {
+ static_assert(std::is_same<PFN, T>::value, "Incompatible function pointer");
+ return reinterpret_cast<hwc2_function_pointer_t>(function);
+}
+
+// HWC2 functions returned in GetFunction
+// Defined in the same order as in the HWC2 header
+
+int32_t HWCSession::AcceptDisplayChanges(hwc2_device_t *device, hwc2_display_t display) {
+ return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::AcceptDisplayChanges);
+}
+
+int32_t HWCSession::CreateLayer(hwc2_device_t *device, hwc2_display_t display,
+ hwc2_layer_t *out_layer_id) {
+ if (!out_layer_id) {
+ return HWC2_ERROR_BAD_PARAMETER;
+ }
+
+ return CallDisplayFunction(device, display, &HWCDisplay::CreateLayer, out_layer_id);
+}
+
+int32_t HWCSession::CreateVirtualDisplay(hwc2_device_t *device, uint32_t width, uint32_t height,
+ int32_t *format, hwc2_display_t *out_display_id) {
+ // TODO(user): Handle concurrency with HDMI
+ SCOPE_LOCK(locker_[HWC_DISPLAY_VIRTUAL]);
+ if (!device) {
+ return HWC2_ERROR_BAD_DISPLAY;
+ }
+
+ if (!out_display_id || !width || !height || !format) {
+ return HWC2_ERROR_BAD_PARAMETER;
+ }
+
+ HWCSession *hwc_session = static_cast<HWCSession *>(device);
+ auto status = hwc_session->CreateVirtualDisplayObject(width, height, format);
+ if (status == HWC2::Error::None) {
+ *out_display_id = HWC_DISPLAY_VIRTUAL;
+ DLOGI("Created virtual display id:% " PRIu64 " with res: %dx%d",
+ *out_display_id, width, height);
+ } else {
+ DLOGE("Failed to create virtual display: %s", to_string(status).c_str());
+ }
+ return INT32(status);
+}
+
+int32_t HWCSession::DestroyLayer(hwc2_device_t *device, hwc2_display_t display,
+ hwc2_layer_t layer) {
+ return CallDisplayFunction(device, display, &HWCDisplay::DestroyLayer, layer);
+}
+
+int32_t HWCSession::DestroyVirtualDisplay(hwc2_device_t *device, hwc2_display_t display) {
+ if (!device || display != HWC_DISPLAY_VIRTUAL) {
+ return HWC2_ERROR_BAD_DISPLAY;
+ }
+
+ SCOPE_LOCK(locker_[display]);
+ DLOGI("Destroying virtual display id:%" PRIu64, display);
+ auto *hwc_session = static_cast<HWCSession *>(device);
+
+ if (hwc_session->hwc_display_[display]) {
+ HWCDisplayVirtual::Destroy(hwc_session->hwc_display_[display]);
+ hwc_session->hwc_display_[display] = nullptr;
+ return HWC2_ERROR_NONE;
+ } else {
+ return HWC2_ERROR_BAD_DISPLAY;
+ }
+}
+
+void HWCSession::Dump(hwc2_device_t *device, uint32_t *out_size, char *out_buffer) {
+ if (!device || !out_size) {
+ return;
+ }
+
+ auto *hwc_session = static_cast<HWCSession *>(device);
+ const size_t max_dump_size = 8192;
+
+ if (out_buffer == nullptr) {
+ *out_size = max_dump_size;
+ } else {
+ std::string s {};
+ for (int id = HWC_DISPLAY_PRIMARY; id <= HWC_DISPLAY_VIRTUAL; id++) {
+ SCOPE_LOCK(locker_[id]);
+ if (hwc_session->hwc_display_[id]) {
+ s += hwc_session->hwc_display_[id]->Dump();
+ }
+ }
+ auto copied = s.copy(out_buffer, std::min(s.size(), max_dump_size), 0);
+ *out_size = UINT32(copied);
+ }
+}
+
+static int32_t GetActiveConfig(hwc2_device_t *device, hwc2_display_t display,
+ hwc2_config_t *out_config) {
+ return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::GetActiveConfig, out_config);
+}
+
+static int32_t GetChangedCompositionTypes(hwc2_device_t *device, hwc2_display_t display,
+ uint32_t *out_num_elements, hwc2_layer_t *out_layers,
+ int32_t *out_types) {
+ // null_ptr check only for out_num_elements, as out_layers and out_types can be null.
+ if (!out_num_elements) {
+ return HWC2_ERROR_BAD_PARAMETER;
+ }
+ return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::GetChangedCompositionTypes,
+ out_num_elements, out_layers, out_types);
+}
+
+static int32_t GetClientTargetSupport(hwc2_device_t *device, hwc2_display_t display, uint32_t width,
+ uint32_t height, int32_t format, int32_t dataspace) {
+ return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::GetClientTargetSupport,
+ width, height, format, dataspace);
+}
+
+static int32_t GetColorModes(hwc2_device_t *device, hwc2_display_t display, uint32_t *out_num_modes,
+ int32_t /*android_color_mode_t*/ *int_out_modes) {
+ auto out_modes = reinterpret_cast<android_color_mode_t *>(int_out_modes);
+ return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::GetColorModes, out_num_modes,
+ out_modes);
+}
+
+static int32_t GetDisplayAttribute(hwc2_device_t *device, hwc2_display_t display,
+ hwc2_config_t config, int32_t int_attribute,
+ int32_t *out_value) {
+ auto attribute = static_cast<HWC2::Attribute>(int_attribute);
+ return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::GetDisplayAttribute, config,
+ attribute, out_value);
+}
+
+static int32_t GetDisplayConfigs(hwc2_device_t *device, hwc2_display_t display,
+ uint32_t *out_num_configs, hwc2_config_t *out_configs) {
+ return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::GetDisplayConfigs,
+ out_num_configs, out_configs);
+}
+
+static int32_t GetDisplayName(hwc2_device_t *device, hwc2_display_t display, uint32_t *out_size,
+ char *out_name) {
+ return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::GetDisplayName, out_size,
+ out_name);
+}
+
+static int32_t GetDisplayRequests(hwc2_device_t *device, hwc2_display_t display,
+ int32_t *out_display_requests, uint32_t *out_num_elements,
+ hwc2_layer_t *out_layers, int32_t *out_layer_requests) {
+ return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::GetDisplayRequests,
+ out_display_requests, out_num_elements, out_layers,
+ out_layer_requests);
+}
+
+static int32_t GetDisplayType(hwc2_device_t *device, hwc2_display_t display, int32_t *out_type) {
+ return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::GetDisplayType, out_type);
+}
+
+static int32_t GetDozeSupport(hwc2_device_t *device, hwc2_display_t display, int32_t *out_support) {
+ if (display == HWC_DISPLAY_PRIMARY) {
+ *out_support = 1;
+ } else {
+ // TODO(user): Port over connect_display_ from HWC1
+ // Return no error for connected displays
+ *out_support = 0;
+ return HWC2_ERROR_BAD_DISPLAY;
+ }
+ return HWC2_ERROR_NONE;
+}
+
+static int32_t GetHdrCapabilities(hwc2_device_t* device, hwc2_display_t display,
+ uint32_t* out_num_types, int32_t* out_types,
+ float* out_max_luminance, float* out_max_average_luminance,
+ float* out_min_luminance) {
+ return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::GetHdrCapabilities,
+ out_num_types, out_types, out_max_luminance,
+ out_max_average_luminance, out_min_luminance);
+}
+
+static uint32_t GetMaxVirtualDisplayCount(hwc2_device_t *device) {
+ char property[PROPERTY_VALUE_MAX];
+ property_get(WRITEBACK_SUPPORTED, property, "1");
+ return (uint32_t) atoi(property);
+}
+
+static int32_t GetReleaseFences(hwc2_device_t *device, hwc2_display_t display,
+ uint32_t *out_num_elements, hwc2_layer_t *out_layers,
+ int32_t *out_fences) {
+ return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::GetReleaseFences,
+ out_num_elements, out_layers, out_fences);
+}
+
+int32_t HWCSession::PresentDisplay(hwc2_device_t *device, hwc2_display_t display,
+ int32_t *out_retire_fence) {
+ HWCSession *hwc_session = static_cast<HWCSession *>(device);
+ bool notify_hotplug = false;
+ auto status = HWC2::Error::BadDisplay;
+ DTRACE_SCOPED();
+
+ if (display >= HWC_NUM_DISPLAY_TYPES) {
+ return HWC2_ERROR_BAD_DISPLAY;
+ }
+
+ {
+ SEQUENCE_EXIT_SCOPE_LOCK(locker_[display]);
+ if (!device) {
+ return HWC2_ERROR_BAD_DISPLAY;
+ }
+
+ // TODO(user): Handle virtual display/HDMI concurrency
+ if (hwc_session->hwc_display_[display]) {
+ status = hwc_session->hwc_display_[display]->Present(out_retire_fence);
+ // This is only indicative of how many times SurfaceFlinger posts
+ // frames to the display.
+ CALC_FPS();
+ }
+ }
+
+ if (status != HWC2::Error::None && status != HWC2::Error::NotValidated) {
+ SEQUENCE_CANCEL_SCOPE_LOCK(locker_[display]);
+ }
+
+ // Handle Pending external display connection
+ if (hwc_session->external_pending_connect_ && (display == HWC_DISPLAY_PRIMARY)) {
+ Locker::ScopeLock lock_e(locker_[HWC_DISPLAY_EXTERNAL]);
+ Locker::ScopeLock lock_v(locker_[HWC_DISPLAY_VIRTUAL]);
+
+ if (!hwc_session->hwc_display_[HWC_DISPLAY_VIRTUAL]) {
+ DLOGD("Process pending external display connection");
+ hwc_session->ConnectDisplay(HWC_DISPLAY_EXTERNAL);
+ hwc_session->external_pending_connect_ = false;
+ notify_hotplug = true;
+ }
+ }
+
+ if (notify_hotplug) {
+ hwc_session->HotPlug(HWC_DISPLAY_EXTERNAL, HWC2::Connection::Connected);
+ }
+
+ return INT32(status);
+}
+
+int32_t HWCSession::RegisterCallback(hwc2_device_t *device, int32_t descriptor,
+ hwc2_callback_data_t callback_data,
+ hwc2_function_pointer_t pointer) {
+ if (!device || pointer == nullptr) {
+ return HWC2_ERROR_BAD_PARAMETER;
+ }
+ HWCSession *hwc_session = static_cast<HWCSession *>(device);
+ SCOPE_LOCK(hwc_session->callbacks_lock_);
+ auto desc = static_cast<HWC2::Callback>(descriptor);
+ auto error = hwc_session->callbacks_.Register(desc, callback_data, pointer);
+ DLOGD("Registering callback: %s", to_string(desc).c_str());
+ if (descriptor == HWC2_CALLBACK_HOTPLUG) {
+ if (hwc_session->hwc_display_[HWC_DISPLAY_PRIMARY]) {
+ hwc_session->callbacks_.Hotplug(HWC_DISPLAY_PRIMARY, HWC2::Connection::Connected);
+ }
+ }
+ hwc_session->need_invalidate_ = false;
+ hwc_session->callbacks_lock_.Broadcast();
+ return INT32(error);
+}
+
+static int32_t SetActiveConfig(hwc2_device_t *device, hwc2_display_t display,
+ hwc2_config_t config) {
+ return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::SetActiveConfig, config);
+}
+
+static int32_t SetClientTarget(hwc2_device_t *device, hwc2_display_t display,
+ buffer_handle_t target, int32_t acquire_fence,
+ int32_t dataspace, hwc_region_t damage) {
+ return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::SetClientTarget, target,
+ acquire_fence, dataspace, damage);
+}
+
+int32_t HWCSession::SetColorMode(hwc2_device_t *device, hwc2_display_t display,
+ int32_t /*android_color_mode_t*/ int_mode) {
+ if (int_mode < HAL_COLOR_MODE_NATIVE || int_mode > HAL_COLOR_MODE_DISPLAY_P3) {
+ return HWC2_ERROR_BAD_PARAMETER;
+ }
+ auto mode = static_cast<android_color_mode_t>(int_mode);
+ return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::SetColorMode, mode);
+}
+
+int32_t HWCSession::SetColorTransform(hwc2_device_t *device, hwc2_display_t display,
+ const float *matrix,
+ int32_t /*android_color_transform_t*/ hint) {
+ if (!matrix || hint < HAL_COLOR_TRANSFORM_IDENTITY ||
+ hint > HAL_COLOR_TRANSFORM_CORRECT_TRITANOPIA) {
+ return HWC2_ERROR_BAD_PARAMETER;
+ }
+ android_color_transform_t transform_hint = static_cast<android_color_transform_t>(hint);
+ return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::SetColorTransform, matrix,
+ transform_hint);
+}
+
+static int32_t SetCursorPosition(hwc2_device_t *device, hwc2_display_t display, hwc2_layer_t layer,
+ int32_t x, int32_t y) {
+ auto status = INT32(HWC2::Error::None);
+ status = HWCSession::CallDisplayFunction(device, display, &HWCDisplay::SetCursorPosition,
+ layer, x, y);
+ if (status == INT32(HWC2::Error::None)) {
+ // Update cursor position
+ HWCSession::CallLayerFunction(device, display, layer, &HWCLayer::SetCursorPosition, x, y);
+ }
+ return status;
+}
+
+static int32_t SetLayerBlendMode(hwc2_device_t *device, hwc2_display_t display, hwc2_layer_t layer,
+ int32_t int_mode) {
+ if (int_mode < HWC2_BLEND_MODE_INVALID || int_mode > HWC2_BLEND_MODE_COVERAGE) {
+ return HWC2_ERROR_BAD_PARAMETER;
+ }
+ auto mode = static_cast<HWC2::BlendMode>(int_mode);
+ return HWCSession::CallLayerFunction(device, display, layer, &HWCLayer::SetLayerBlendMode, mode);
+}
+
+static int32_t SetLayerBuffer(hwc2_device_t *device, hwc2_display_t display, hwc2_layer_t layer,
+ buffer_handle_t buffer, int32_t acquire_fence) {
+ return HWCSession::CallLayerFunction(device, display, layer, &HWCLayer::SetLayerBuffer, buffer,
+ acquire_fence);
+}
+
+static int32_t SetLayerColor(hwc2_device_t *device, hwc2_display_t display, hwc2_layer_t layer,
+ hwc_color_t color) {
+ return HWCSession::CallLayerFunction(device, display, layer, &HWCLayer::SetLayerColor, color);
+}
+
+static int32_t SetLayerCompositionType(hwc2_device_t *device, hwc2_display_t display,
+ hwc2_layer_t layer, int32_t int_type) {
+ auto type = static_cast<HWC2::Composition>(int_type);
+ return HWCSession::CallLayerFunction(device, display, layer, &HWCLayer::SetLayerCompositionType,
+ type);
+}
+
+static int32_t SetLayerDataspace(hwc2_device_t *device, hwc2_display_t display, hwc2_layer_t layer,
+ int32_t dataspace) {
+ return HWCSession::CallLayerFunction(device, display, layer, &HWCLayer::SetLayerDataspace,
+ dataspace);
+}
+
+static int32_t SetLayerDisplayFrame(hwc2_device_t *device, hwc2_display_t display,
+ hwc2_layer_t layer, hwc_rect_t frame) {
+ return HWCSession::CallLayerFunction(device, display, layer, &HWCLayer::SetLayerDisplayFrame,
+ frame);
+}
+
+static int32_t SetLayerPlaneAlpha(hwc2_device_t *device, hwc2_display_t display, hwc2_layer_t layer,
+ float alpha) {
+ return HWCSession::CallLayerFunction(device, display, layer, &HWCLayer::SetLayerPlaneAlpha,
+ alpha);
+}
+
+static int32_t SetLayerSourceCrop(hwc2_device_t *device, hwc2_display_t display, hwc2_layer_t layer,
+ hwc_frect_t crop) {
+ return HWCSession::CallLayerFunction(device, display, layer, &HWCLayer::SetLayerSourceCrop, crop);
+}
+
+static int32_t SetLayerSurfaceDamage(hwc2_device_t *device, hwc2_display_t display,
+ hwc2_layer_t layer, hwc_region_t damage) {
+ return HWCSession::CallLayerFunction(device, display, layer, &HWCLayer::SetLayerSurfaceDamage,
+ damage);
+}
+
+static int32_t SetLayerTransform(hwc2_device_t *device, hwc2_display_t display, hwc2_layer_t layer,
+ int32_t int_transform) {
+ auto transform = static_cast<HWC2::Transform>(int_transform);
+ return HWCSession::CallLayerFunction(device, display, layer, &HWCLayer::SetLayerTransform,
+ transform);
+}
+
+static int32_t SetLayerVisibleRegion(hwc2_device_t *device, hwc2_display_t display,
+ hwc2_layer_t layer, hwc_region_t visible) {
+ return HWCSession::CallLayerFunction(device, display, layer, &HWCLayer::SetLayerVisibleRegion,
+ visible);
+}
+
+static int32_t SetLayerZOrder(hwc2_device_t *device, hwc2_display_t display, hwc2_layer_t layer,
+ uint32_t z) {
+ return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::SetLayerZOrder, layer, z);
+}
+
+int32_t HWCSession::SetOutputBuffer(hwc2_device_t *device, hwc2_display_t display,
+ buffer_handle_t buffer, int32_t releaseFence) {
+ if (!device) {
+ return HWC2_ERROR_BAD_DISPLAY;
+ }
+
+ if (display != HWC_DISPLAY_VIRTUAL) {
+ return HWC2_ERROR_UNSUPPORTED;
+ }
+
+ SCOPE_LOCK(locker_[display]);
+ auto *hwc_session = static_cast<HWCSession *>(device);
+ if (hwc_session->hwc_display_[display]) {
+ auto vds = reinterpret_cast<HWCDisplayVirtual *>(hwc_session->hwc_display_[display]);
+ auto status = vds->SetOutputBuffer(buffer, releaseFence);
+ return INT32(status);
+ } else {
+ return HWC2_ERROR_BAD_DISPLAY;
+ }
+}
+
+int32_t HWCSession::SetPowerMode(hwc2_device_t *device, hwc2_display_t display, int32_t int_mode) {
+ auto mode = static_cast<HWC2::PowerMode>(int_mode);
+ return CallDisplayFunction(device, display, &HWCDisplay::SetPowerMode, mode);
+}
+
+static int32_t SetVsyncEnabled(hwc2_device_t *device, hwc2_display_t display, int32_t int_enabled) {
+ auto enabled = static_cast<HWC2::Vsync>(int_enabled);
+ return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::SetVsyncEnabled, enabled);
+}
+
+int32_t HWCSession::ValidateDisplay(hwc2_device_t *device, hwc2_display_t display,
+ uint32_t *out_num_types, uint32_t *out_num_requests) {
+ DTRACE_SCOPED();
+ HWCSession *hwc_session = static_cast<HWCSession *>(device);
+ if (!device) {
+ return HWC2_ERROR_BAD_DISPLAY;
+ }
+
+ // TODO(user): Handle secure session, handle QDCM solid fill
+ // Handle external_pending_connect_ in CreateVirtualDisplay
+ auto status = HWC2::Error::BadDisplay;
+ {
+ SEQUENCE_ENTRY_SCOPE_LOCK(locker_[display]);
+ if (hwc_session->hwc_display_[display]) {
+ if (display == HWC_DISPLAY_PRIMARY) {
+ // TODO(user): This can be moved to HWCDisplayPrimary
+ if (hwc_session->reset_panel_) {
+ DLOGW("panel is in bad state, resetting the panel");
+ hwc_session->ResetPanel();
+ }
+
+ if (hwc_session->need_invalidate_) {
+ hwc_session->Refresh(display);
+ hwc_session->need_invalidate_ = false;
+ }
+
+ if (hwc_session->color_mgr_) {
+ hwc_session->color_mgr_->SetColorModeDetailEnhancer(hwc_session->hwc_display_[display]);
+ }
+ }
+
+ status = hwc_session->hwc_display_[display]->Validate(out_num_types, out_num_requests);
+ }
+ }
+
+ // Sequence locking currently begins on Validate, so cancel the sequence lock on failures
+ if (status != HWC2::Error::None && status != HWC2::Error::HasChanges) {
+ SEQUENCE_CANCEL_SCOPE_LOCK(locker_[display]);
+ }
+
+ return INT32(status);
+}
+
+hwc2_function_pointer_t HWCSession::GetFunction(struct hwc2_device *device,
+ int32_t int_descriptor) {
+ auto descriptor = static_cast<HWC2::FunctionDescriptor>(int_descriptor);
+
+ switch (descriptor) {
+ case HWC2::FunctionDescriptor::AcceptDisplayChanges:
+ return AsFP<HWC2_PFN_ACCEPT_DISPLAY_CHANGES>(HWCSession::AcceptDisplayChanges);
+ case HWC2::FunctionDescriptor::CreateLayer:
+ return AsFP<HWC2_PFN_CREATE_LAYER>(CreateLayer);
+ case HWC2::FunctionDescriptor::CreateVirtualDisplay:
+ return AsFP<HWC2_PFN_CREATE_VIRTUAL_DISPLAY>(HWCSession::CreateVirtualDisplay);
+ case HWC2::FunctionDescriptor::DestroyLayer:
+ return AsFP<HWC2_PFN_DESTROY_LAYER>(DestroyLayer);
+ case HWC2::FunctionDescriptor::DestroyVirtualDisplay:
+ return AsFP<HWC2_PFN_DESTROY_VIRTUAL_DISPLAY>(HWCSession::DestroyVirtualDisplay);
+ case HWC2::FunctionDescriptor::Dump:
+ return AsFP<HWC2_PFN_DUMP>(HWCSession::Dump);
+ case HWC2::FunctionDescriptor::GetActiveConfig:
+ return AsFP<HWC2_PFN_GET_ACTIVE_CONFIG>(GetActiveConfig);
+ case HWC2::FunctionDescriptor::GetChangedCompositionTypes:
+ return AsFP<HWC2_PFN_GET_CHANGED_COMPOSITION_TYPES>(GetChangedCompositionTypes);
+ case HWC2::FunctionDescriptor::GetClientTargetSupport:
+ return AsFP<HWC2_PFN_GET_CLIENT_TARGET_SUPPORT>(GetClientTargetSupport);
+ case HWC2::FunctionDescriptor::GetColorModes:
+ return AsFP<HWC2_PFN_GET_COLOR_MODES>(GetColorModes);
+ case HWC2::FunctionDescriptor::GetDisplayAttribute:
+ return AsFP<HWC2_PFN_GET_DISPLAY_ATTRIBUTE>(GetDisplayAttribute);
+ case HWC2::FunctionDescriptor::GetDisplayConfigs:
+ return AsFP<HWC2_PFN_GET_DISPLAY_CONFIGS>(GetDisplayConfigs);
+ case HWC2::FunctionDescriptor::GetDisplayName:
+ return AsFP<HWC2_PFN_GET_DISPLAY_NAME>(GetDisplayName);
+ case HWC2::FunctionDescriptor::GetDisplayRequests:
+ return AsFP<HWC2_PFN_GET_DISPLAY_REQUESTS>(GetDisplayRequests);
+ case HWC2::FunctionDescriptor::GetDisplayType:
+ return AsFP<HWC2_PFN_GET_DISPLAY_TYPE>(GetDisplayType);
+ case HWC2::FunctionDescriptor::GetHdrCapabilities:
+ return AsFP<HWC2_PFN_GET_HDR_CAPABILITIES>(GetHdrCapabilities);
+ case HWC2::FunctionDescriptor::GetDozeSupport:
+ return AsFP<HWC2_PFN_GET_DOZE_SUPPORT>(GetDozeSupport);
+ case HWC2::FunctionDescriptor::GetMaxVirtualDisplayCount:
+ return AsFP<HWC2_PFN_GET_MAX_VIRTUAL_DISPLAY_COUNT>(GetMaxVirtualDisplayCount);
+ case HWC2::FunctionDescriptor::GetReleaseFences:
+ return AsFP<HWC2_PFN_GET_RELEASE_FENCES>(GetReleaseFences);
+ case HWC2::FunctionDescriptor::PresentDisplay:
+ return AsFP<HWC2_PFN_PRESENT_DISPLAY>(PresentDisplay);
+ case HWC2::FunctionDescriptor::RegisterCallback:
+ return AsFP<HWC2_PFN_REGISTER_CALLBACK>(RegisterCallback);
+ case HWC2::FunctionDescriptor::SetActiveConfig:
+ return AsFP<HWC2_PFN_SET_ACTIVE_CONFIG>(SetActiveConfig);
+ case HWC2::FunctionDescriptor::SetClientTarget:
+ return AsFP<HWC2_PFN_SET_CLIENT_TARGET>(SetClientTarget);
+ case HWC2::FunctionDescriptor::SetColorMode:
+ return AsFP<HWC2_PFN_SET_COLOR_MODE>(SetColorMode);
+ case HWC2::FunctionDescriptor::SetColorTransform:
+ return AsFP<HWC2_PFN_SET_COLOR_TRANSFORM>(SetColorTransform);
+ case HWC2::FunctionDescriptor::SetCursorPosition:
+ return AsFP<HWC2_PFN_SET_CURSOR_POSITION>(SetCursorPosition);
+ case HWC2::FunctionDescriptor::SetLayerBlendMode:
+ return AsFP<HWC2_PFN_SET_LAYER_BLEND_MODE>(SetLayerBlendMode);
+ case HWC2::FunctionDescriptor::SetLayerBuffer:
+ return AsFP<HWC2_PFN_SET_LAYER_BUFFER>(SetLayerBuffer);
+ case HWC2::FunctionDescriptor::SetLayerColor:
+ return AsFP<HWC2_PFN_SET_LAYER_COLOR>(SetLayerColor);
+ case HWC2::FunctionDescriptor::SetLayerCompositionType:
+ return AsFP<HWC2_PFN_SET_LAYER_COMPOSITION_TYPE>(SetLayerCompositionType);
+ case HWC2::FunctionDescriptor::SetLayerDataspace:
+ return AsFP<HWC2_PFN_SET_LAYER_DATASPACE>(SetLayerDataspace);
+ case HWC2::FunctionDescriptor::SetLayerDisplayFrame:
+ return AsFP<HWC2_PFN_SET_LAYER_DISPLAY_FRAME>(SetLayerDisplayFrame);
+ case HWC2::FunctionDescriptor::SetLayerPlaneAlpha:
+ return AsFP<HWC2_PFN_SET_LAYER_PLANE_ALPHA>(SetLayerPlaneAlpha);
+ // Sideband stream is not supported
+ // case HWC2::FunctionDescriptor::SetLayerSidebandStream:
+ case HWC2::FunctionDescriptor::SetLayerSourceCrop:
+ return AsFP<HWC2_PFN_SET_LAYER_SOURCE_CROP>(SetLayerSourceCrop);
+ case HWC2::FunctionDescriptor::SetLayerSurfaceDamage:
+ return AsFP<HWC2_PFN_SET_LAYER_SURFACE_DAMAGE>(SetLayerSurfaceDamage);
+ case HWC2::FunctionDescriptor::SetLayerTransform:
+ return AsFP<HWC2_PFN_SET_LAYER_TRANSFORM>(SetLayerTransform);
+ case HWC2::FunctionDescriptor::SetLayerVisibleRegion:
+ return AsFP<HWC2_PFN_SET_LAYER_VISIBLE_REGION>(SetLayerVisibleRegion);
+ case HWC2::FunctionDescriptor::SetLayerZOrder:
+ return AsFP<HWC2_PFN_SET_LAYER_Z_ORDER>(SetLayerZOrder);
+ case HWC2::FunctionDescriptor::SetOutputBuffer:
+ return AsFP<HWC2_PFN_SET_OUTPUT_BUFFER>(SetOutputBuffer);
+ case HWC2::FunctionDescriptor::SetPowerMode:
+ return AsFP<HWC2_PFN_SET_POWER_MODE>(SetPowerMode);
+ case HWC2::FunctionDescriptor::SetVsyncEnabled:
+ return AsFP<HWC2_PFN_SET_VSYNC_ENABLED>(SetVsyncEnabled);
+ case HWC2::FunctionDescriptor::ValidateDisplay:
+ return AsFP<HWC2_PFN_VALIDATE_DISPLAY>(HWCSession::ValidateDisplay);
+ default:
+ DLOGD("Unknown/Unimplemented function descriptor: %d (%s)", int_descriptor,
+ to_string(descriptor).c_str());
+ return nullptr;
+ }
+ return nullptr;
+}
+
+// TODO(user): handle locking
+
+HWC2::Error HWCSession::CreateVirtualDisplayObject(uint32_t width, uint32_t height,
+ int32_t *format) {
+ if (hwc_display_[HWC_DISPLAY_VIRTUAL]) {
+ return HWC2::Error::NoResources;
+ }
+ auto status = HWCDisplayVirtual::Create(core_intf_, &buffer_allocator_, &callbacks_, width,
+ height, format, &hwc_display_[HWC_DISPLAY_VIRTUAL]);
+ // TODO(user): validate width and height support
+ if (status)
+ return HWC2::Error::Unsupported;
+
+ return HWC2::Error::None;
+}
+
+int32_t HWCSession::ConnectDisplay(int disp) {
+ DLOGI("Display = %d", disp);
+
+ int status = 0;
+ uint32_t primary_width = 0;
+ uint32_t primary_height = 0;
+
+ hwc_display_[HWC_DISPLAY_PRIMARY]->GetFrameBufferResolution(&primary_width, &primary_height);
+
+ if (disp == HWC_DISPLAY_EXTERNAL) {
+ status = CreateExternalDisplay(disp, primary_width, primary_height);
+ } else {
+ DLOGE("Invalid display type");
+ return -1;
+ }
+
+ if (!status) {
+ hwc_display_[disp]->SetSecureDisplay(secure_display_active_);
+ }
+
+ return status;
+}
+
+int HWCSession::DisconnectDisplay(int disp) {
+ DLOGI("Display = %d", disp);
+
+ if (disp == HWC_DISPLAY_EXTERNAL) {
+ HWCDisplayExternal::Destroy(hwc_display_[disp]);
+ } else if (disp == HWC_DISPLAY_VIRTUAL) {
+ HWCDisplayVirtual::Destroy(hwc_display_[disp]);
+ } else {
+ DLOGE("Invalid display type");
+ return -1;
+ }
+
+ hwc_display_[disp] = NULL;
+
+ return 0;
+}
+
+// Qclient methods
+android::status_t HWCSession::notifyCallback(uint32_t command, const android::Parcel *input_parcel,
+ android::Parcel *output_parcel) {
+ android::status_t status = 0;
+
+ switch (command) {
+ case qService::IQService::DYNAMIC_DEBUG:
+ DynamicDebug(input_parcel);
+ break;
+
+ case qService::IQService::SCREEN_REFRESH:
+ refreshScreen();
+ break;
+
+ case qService::IQService::SET_IDLE_TIMEOUT:
+ setIdleTimeout(UINT32(input_parcel->readInt32()));
+ break;
+
+ case qService::IQService::SET_FRAME_DUMP_CONFIG:
+ SetFrameDumpConfig(input_parcel);
+ break;
+
+ case qService::IQService::SET_MAX_PIPES_PER_MIXER:
+ status = SetMaxMixerStages(input_parcel);
+ break;
+
+ case qService::IQService::SET_DISPLAY_MODE:
+ status = SetDisplayMode(input_parcel);
+ break;
+
+ case qService::IQService::SET_SECONDARY_DISPLAY_STATUS: {
+ int disp_id = INT(input_parcel->readInt32());
+ HWCDisplay::DisplayStatus disp_status =
+ static_cast<HWCDisplay::DisplayStatus>(input_parcel->readInt32());
+ status = SetSecondaryDisplayStatus(disp_id, disp_status);
+ output_parcel->writeInt32(status);
+ }
+ break;
+
+ case qService::IQService::CONFIGURE_DYN_REFRESH_RATE:
+ status = ConfigureRefreshRate(input_parcel);
+ break;
+
+ case qService::IQService::SET_VIEW_FRAME:
+ break;
+
+ case qService::IQService::TOGGLE_SCREEN_UPDATES: {
+ int32_t input = input_parcel->readInt32();
+ status = toggleScreenUpdate(input == 1);
+ output_parcel->writeInt32(status);
+ }
+ break;
+
+ case qService::IQService::QDCM_SVC_CMDS:
+ status = QdcmCMDHandler(input_parcel, output_parcel);
+ break;
+
+ case qService::IQService::MIN_HDCP_ENCRYPTION_LEVEL_CHANGED: {
+ int disp_id = input_parcel->readInt32();
+ uint32_t min_enc_level = UINT32(input_parcel->readInt32());
+ status = MinHdcpEncryptionLevelChanged(disp_id, min_enc_level);
+ output_parcel->writeInt32(status);
+ }
+ break;
+
+ case qService::IQService::CONTROL_PARTIAL_UPDATE: {
+ int disp_id = input_parcel->readInt32();
+ uint32_t enable = UINT32(input_parcel->readInt32());
+ status = ControlPartialUpdate(disp_id, enable == 1);
+ output_parcel->writeInt32(status);
+ }
+ break;
+
+ case qService::IQService::SET_ACTIVE_CONFIG: {
+ uint32_t config = UINT32(input_parcel->readInt32());
+ int disp_id = input_parcel->readInt32();
+ status = SetActiveConfigIndex(disp_id, config);
+ }
+ break;
+
+ case qService::IQService::GET_ACTIVE_CONFIG: {
+ int disp_id = input_parcel->readInt32();
+ uint32_t config = 0;
+ status = GetActiveConfigIndex(disp_id, &config);
+ output_parcel->writeInt32(INT(config));
+ }
+ break;
+
+ case qService::IQService::GET_CONFIG_COUNT: {
+ int disp_id = input_parcel->readInt32();
+ uint32_t count = 0;
+ status = GetConfigCount(disp_id, &count);
+ output_parcel->writeInt32(INT(count));
+ }
+ break;
+
+ case qService::IQService::GET_DISPLAY_ATTRIBUTES_FOR_CONFIG:
+ status = HandleGetDisplayAttributesForConfig(input_parcel, output_parcel);
+ break;
+
+ case qService::IQService::GET_PANEL_BRIGHTNESS: {
+ int level = 0;
+ status = GetPanelBrightness(&level);
+ output_parcel->writeInt32(level);
+ }
+ break;
+
+ case qService::IQService::SET_PANEL_BRIGHTNESS: {
+ uint32_t level = UINT32(input_parcel->readInt32());
+ status = setPanelBrightness(level);
+ output_parcel->writeInt32(status);
+ }
+ break;
+
+ case qService::IQService::GET_DISPLAY_VISIBLE_REGION:
+ status = GetVisibleDisplayRect(input_parcel, output_parcel);
+ break;
+
+ case qService::IQService::SET_CAMERA_STATUS: {
+ uint32_t camera_status = UINT32(input_parcel->readInt32());
+ status = setCameraLaunchStatus(camera_status);
+ }
+ break;
+
+ case qService::IQService::GET_BW_TRANSACTION_STATUS: {
+ bool state = true;
+ status = DisplayBWTransactionPending(&state);
+ output_parcel->writeInt32(state);
+ }
+ break;
+
+ case qService::IQService::SET_LAYER_MIXER_RESOLUTION:
+ status = SetMixerResolution(input_parcel);
+ break;
+
+ case qService::IQService::SET_COLOR_MODE:
+ status = SetColorModeOverride(input_parcel);
+ break;
+
+ default:
+ DLOGW("QService command = %d is not supported", command);
+ return -EINVAL;
+ }
+
+ return status;
+}
+
+android::status_t HWCSession::HandleGetDisplayAttributesForConfig(const android::Parcel
+ *input_parcel,
+ android::Parcel *output_parcel) {
+ int config = input_parcel->readInt32();
+ int dpy = input_parcel->readInt32();
+ int error = android::BAD_VALUE;
+ DisplayConfigVariableInfo display_attributes;
+
+ if (dpy < HWC_DISPLAY_PRIMARY || dpy >= HWC_NUM_DISPLAY_TYPES || config < 0) {
+ return android::BAD_VALUE;
+ }
+
+ SEQUENCE_WAIT_SCOPE_LOCK(locker_[dpy]);
+ if (hwc_display_[dpy]) {
+ error = hwc_display_[dpy]->GetDisplayAttributesForConfig(config, &display_attributes);
+ if (error == 0) {
+ output_parcel->writeInt32(INT(display_attributes.vsync_period_ns));
+ output_parcel->writeInt32(INT(display_attributes.x_pixels));
+ output_parcel->writeInt32(INT(display_attributes.y_pixels));
+ output_parcel->writeFloat(display_attributes.x_dpi);
+ output_parcel->writeFloat(display_attributes.y_dpi);
+ output_parcel->writeInt32(0); // Panel type, unsupported.
+ }
+ }
+
+ return error;
+}
+
+android::status_t HWCSession::ConfigureRefreshRate(const android::Parcel *input_parcel) {
+ SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
+
+ uint32_t operation = UINT32(input_parcel->readInt32());
+ HWCDisplay *hwc_display = hwc_display_[HWC_DISPLAY_PRIMARY];
+
+ switch (operation) {
+ case qdutils::DISABLE_METADATA_DYN_REFRESH_RATE:
+ return hwc_display->Perform(HWCDisplayPrimary::SET_METADATA_DYN_REFRESH_RATE, false);
+
+ case qdutils::ENABLE_METADATA_DYN_REFRESH_RATE:
+ return hwc_display->Perform(HWCDisplayPrimary::SET_METADATA_DYN_REFRESH_RATE, true);
+
+ case qdutils::SET_BINDER_DYN_REFRESH_RATE: {
+ uint32_t refresh_rate = UINT32(input_parcel->readInt32());
+ return hwc_display->Perform(HWCDisplayPrimary::SET_BINDER_DYN_REFRESH_RATE, refresh_rate);
+ }
+
+ default:
+ DLOGW("Invalid operation %d", operation);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+android::status_t HWCSession::SetDisplayMode(const android::Parcel *input_parcel) {
+ SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
+
+ uint32_t mode = UINT32(input_parcel->readInt32());
+ return hwc_display_[HWC_DISPLAY_PRIMARY]->Perform(HWCDisplayPrimary::SET_DISPLAY_MODE, mode);
+}
+
+android::status_t HWCSession::SetMaxMixerStages(const android::Parcel *input_parcel) {
+ DisplayError error = kErrorNone;
+ std::bitset<32> bit_mask_display_type = UINT32(input_parcel->readInt32());
+ uint32_t max_mixer_stages = UINT32(input_parcel->readInt32());
+
+ if (bit_mask_display_type[HWC_DISPLAY_PRIMARY]) {
+ SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
+ if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
+ error = hwc_display_[HWC_DISPLAY_PRIMARY]->SetMaxMixerStages(max_mixer_stages);
+ if (error != kErrorNone) {
+ return -EINVAL;
+ }
+ }
+ }
+
+ if (bit_mask_display_type[HWC_DISPLAY_EXTERNAL]) {
+ SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_EXTERNAL]);
+ if (hwc_display_[HWC_DISPLAY_EXTERNAL]) {
+ error = hwc_display_[HWC_DISPLAY_EXTERNAL]->SetMaxMixerStages(max_mixer_stages);
+ if (error != kErrorNone) {
+ return -EINVAL;
+ }
+ }
+ }
+
+ if (bit_mask_display_type[HWC_DISPLAY_VIRTUAL]) {
+ SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_VIRTUAL]);
+ if (hwc_display_[HWC_DISPLAY_VIRTUAL]) {
+ error = hwc_display_[HWC_DISPLAY_VIRTUAL]->SetMaxMixerStages(max_mixer_stages);
+ if (error != kErrorNone) {
+ return -EINVAL;
+ }
+ }
+ }
+
+ return 0;
+}
+
+void HWCSession::SetFrameDumpConfig(const android::Parcel *input_parcel) {
+ uint32_t frame_dump_count = UINT32(input_parcel->readInt32());
+ std::bitset<32> bit_mask_display_type = UINT32(input_parcel->readInt32());
+ uint32_t bit_mask_layer_type = UINT32(input_parcel->readInt32());
+
+ if (bit_mask_display_type[HWC_DISPLAY_PRIMARY]) {
+ SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
+ if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
+ hwc_display_[HWC_DISPLAY_PRIMARY]->SetFrameDumpConfig(frame_dump_count, bit_mask_layer_type);
+ }
+ }
+
+ if (bit_mask_display_type[HWC_DISPLAY_EXTERNAL]) {
+ SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_EXTERNAL]);
+ if (hwc_display_[HWC_DISPLAY_EXTERNAL]) {
+ hwc_display_[HWC_DISPLAY_EXTERNAL]->SetFrameDumpConfig(frame_dump_count, bit_mask_layer_type);
+ }
+ }
+
+ if (bit_mask_display_type[HWC_DISPLAY_VIRTUAL]) {
+ SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_VIRTUAL]);
+ if (hwc_display_[HWC_DISPLAY_VIRTUAL]) {
+ hwc_display_[HWC_DISPLAY_VIRTUAL]->SetFrameDumpConfig(frame_dump_count, bit_mask_layer_type);
+ }
+ }
+}
+
+android::status_t HWCSession::SetMixerResolution(const android::Parcel *input_parcel) {
+ DisplayError error = kErrorNone;
+ uint32_t dpy = UINT32(input_parcel->readInt32());
+
+ if (dpy != HWC_DISPLAY_PRIMARY) {
+ DLOGI("Resoulution change not supported for this display %d", dpy);
+ return -EINVAL;
+ }
+
+ SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
+ if (!hwc_display_[HWC_DISPLAY_PRIMARY]) {
+ DLOGI("Primary display is not initialized");
+ return -EINVAL;
+ }
+
+ uint32_t width = UINT32(input_parcel->readInt32());
+ uint32_t height = UINT32(input_parcel->readInt32());
+
+ error = hwc_display_[HWC_DISPLAY_PRIMARY]->SetMixerResolution(width, height);
+ if (error != kErrorNone) {
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+android::status_t HWCSession::SetColorModeOverride(const android::Parcel *input_parcel) {
+ auto display = static_cast<hwc2_display_t >(input_parcel->readInt32());
+ auto mode = static_cast<android_color_mode_t>(input_parcel->readInt32());
+ auto device = static_cast<hwc2_device_t *>(this);
+
+ if (display >= HWC_NUM_DISPLAY_TYPES) {
+ return -EINVAL;
+ }
+ auto err = CallDisplayFunction(device, display, &HWCDisplay::SetColorMode, mode);
+ if (err != HWC2_ERROR_NONE)
+ return -EINVAL;
+
+ return 0;
+}
+
+void HWCSession::DynamicDebug(const android::Parcel *input_parcel) {
+ // TODO(user): Do we really need a lock here?
+
+ int type = input_parcel->readInt32();
+ bool enable = (input_parcel->readInt32() > 0);
+ DLOGI("type = %d enable = %d", type, enable);
+ int verbose_level = input_parcel->readInt32();
+
+ switch (type) {
+ case qService::IQService::DEBUG_ALL:
+ HWCDebugHandler::DebugAll(enable, verbose_level);
+ break;
+
+ case qService::IQService::DEBUG_MDPCOMP:
+ HWCDebugHandler::DebugStrategy(enable, verbose_level);
+ HWCDebugHandler::DebugCompManager(enable, verbose_level);
+ break;
+
+ case qService::IQService::DEBUG_PIPE_LIFECYCLE:
+ HWCDebugHandler::DebugResources(enable, verbose_level);
+ break;
+
+ case qService::IQService::DEBUG_DRIVER_CONFIG:
+ HWCDebugHandler::DebugDriverConfig(enable, verbose_level);
+ break;
+
+ case qService::IQService::DEBUG_ROTATOR:
+ HWCDebugHandler::DebugResources(enable, verbose_level);
+ HWCDebugHandler::DebugDriverConfig(enable, verbose_level);
+ HWCDebugHandler::DebugRotator(enable, verbose_level);
+ break;
+
+ case qService::IQService::DEBUG_QDCM:
+ HWCDebugHandler::DebugQdcm(enable, verbose_level);
+ break;
+
+ case qService::IQService::DEBUG_SCALAR:
+ HWCDebugHandler::DebugScalar(enable, verbose_level);
+ break;
+
+ case qService::IQService::DEBUG_CLIENT:
+ HWCDebugHandler::DebugClient(enable, verbose_level);
+ break;
+
+ case qService::IQService::DEBUG_DISPLAY:
+ HWCDebugHandler::DebugDisplay(enable, verbose_level);
+ break;
+
+ default:
+ DLOGW("type = %d is not supported", type);
+ }
+}
+
+android::status_t HWCSession::QdcmCMDHandler(const android::Parcel *input_parcel,
+ android::Parcel *output_parcel) {
+ int ret = 0;
+ int32_t *brightness_value = NULL;
+ uint32_t display_id(0);
+ PPPendingParams pending_action;
+ PPDisplayAPIPayload resp_payload, req_payload;
+
+ if (!color_mgr_) {
+ return -1;
+ }
+
+ pending_action.action = kNoAction;
+ pending_action.params = NULL;
+
+ // Read display_id, payload_size and payload from in_parcel.
+ ret = HWCColorManager::CreatePayloadFromParcel(*input_parcel, &display_id, &req_payload);
+ if (!ret) {
+ if (HWC_DISPLAY_PRIMARY == display_id && hwc_display_[HWC_DISPLAY_PRIMARY])
+ ret = hwc_display_[HWC_DISPLAY_PRIMARY]->ColorSVCRequestRoute(req_payload, &resp_payload,
+ &pending_action);
+
+ if (HWC_DISPLAY_EXTERNAL == display_id && hwc_display_[HWC_DISPLAY_EXTERNAL])
+ ret = hwc_display_[HWC_DISPLAY_EXTERNAL]->ColorSVCRequestRoute(req_payload, &resp_payload,
+ &pending_action);
+ }
+
+ if (ret) {
+ output_parcel->writeInt32(ret); // first field in out parcel indicates return code.
+ req_payload.DestroyPayload();
+ resp_payload.DestroyPayload();
+ return ret;
+ }
+
+
+ int32_t action = pending_action.action;
+ int count = -1;
+ bool reset_validate = true;
+ while (action > 0) {
+ count++;
+ int32_t bit = (action & 1);
+ action = action >> 1;
+
+ if (!bit)
+ continue;
+
+ DLOGV_IF(kTagQDCM, "pending action = %d", BITMAP(count));
+ switch (BITMAP(count)) {
+ case kInvalidating:
+ Refresh(HWC_DISPLAY_PRIMARY);
+ reset_validate = !disable_skip_validate_;
+ break;
+ case kEnterQDCMMode:
+ ret = color_mgr_->EnableQDCMMode(true, hwc_display_[HWC_DISPLAY_PRIMARY]);
+ break;
+ case kExitQDCMMode:
+ ret = color_mgr_->EnableQDCMMode(false, hwc_display_[HWC_DISPLAY_PRIMARY]);
+ break;
+ case kApplySolidFill:
+ ret = color_mgr_->SetSolidFill(pending_action.params,
+ true, hwc_display_[HWC_DISPLAY_PRIMARY]);
+ Refresh(HWC_DISPLAY_PRIMARY);
+ break;
+ case kDisableSolidFill:
+ ret = color_mgr_->SetSolidFill(pending_action.params,
+ false, hwc_display_[HWC_DISPLAY_PRIMARY]);
+ Refresh(HWC_DISPLAY_PRIMARY);
+ break;
+ case kSetPanelBrightness:
+ brightness_value = reinterpret_cast<int32_t *>(resp_payload.payload);
+ if (brightness_value == NULL) {
+ DLOGE("Brightness value is Null");
+ return -EINVAL;
+ }
+ if (HWC_DISPLAY_PRIMARY == display_id)
+ ret = hwc_display_[HWC_DISPLAY_PRIMARY]->SetPanelBrightness(*brightness_value);
+ break;
+ case kEnableFrameCapture:
+ ret = color_mgr_->SetFrameCapture(pending_action.params, true,
+ hwc_display_[HWC_DISPLAY_PRIMARY]);
+ Refresh(HWC_DISPLAY_PRIMARY);
+ break;
+ case kDisableFrameCapture:
+ ret = color_mgr_->SetFrameCapture(pending_action.params, false,
+ hwc_display_[HWC_DISPLAY_PRIMARY]);
+ break;
+ case kConfigureDetailedEnhancer:
+ ret = color_mgr_->SetDetailedEnhancer(pending_action.params,
+ hwc_display_[HWC_DISPLAY_PRIMARY]);
+ Refresh(HWC_DISPLAY_PRIMARY);
+ break;
+ case kModeSet:
+ ret = static_cast<int>
+ (hwc_display_[HWC_DISPLAY_PRIMARY]->RestoreColorTransform());
+ Refresh(HWC_DISPLAY_PRIMARY);
+ break;
+ case kNoAction:
+ break;
+ default:
+ DLOGW("Invalid pending action = %d!", pending_action.action);
+ break;
+ }
+ }
+ // for display API getter case, marshall returned params into out_parcel.
+ output_parcel->writeInt32(ret);
+ HWCColorManager::MarshallStructIntoParcel(resp_payload, output_parcel);
+ req_payload.DestroyPayload();
+ resp_payload.DestroyPayload();
+ if (reset_validate) {
+ hwc_display_[display_id]->ResetValidation();
+ }
+
+ return (ret ? -EINVAL : 0);
+}
+
+void HWCSession::UEventHandler(const char *uevent_data, int length) {
+ if (!strcasecmp(uevent_data, HWC_UEVENT_SWITCH_HDMI)) {
+ DLOGI("Uevent HDMI = %s", uevent_data);
+ int connected = GetEventValue(uevent_data, length, "SWITCH_STATE=");
+ if (connected >= 0) {
+ DLOGI("HDMI = %s", connected ? "connected" : "disconnected");
+ if (HotPlugHandler(connected) == -1) {
+ DLOGE("Failed handling Hotplug = %s", connected ? "connected" : "disconnected");
+ }
+ }
+ } else if (!strcasecmp(uevent_data, HWC_UEVENT_GRAPHICS_FB0)) {
+ DLOGI("Uevent FB0 = %s", uevent_data);
+ int panel_reset = GetEventValue(uevent_data, length, "PANEL_ALIVE=");
+ if (panel_reset == 0) {
+ Refresh(0);
+ reset_panel_ = true;
+ }
+ }
+}
+
+int HWCSession::GetEventValue(const char *uevent_data, int length, const char *event_info) {
+ const char *iterator_str = uevent_data;
+ while (((iterator_str - uevent_data) <= length) && (*iterator_str)) {
+ const char *pstr = strstr(iterator_str, event_info);
+ if (pstr != NULL) {
+ return (atoi(iterator_str + strlen(event_info)));
+ }
+ iterator_str += strlen(iterator_str) + 1;
+ }
+
+ return -1;
+}
+
+void HWCSession::ResetPanel() {
+ HWC2::Error status;
+
+ DLOGI("Powering off primary");
+ status = hwc_display_[HWC_DISPLAY_PRIMARY]->SetPowerMode(HWC2::PowerMode::Off);
+ if (status != HWC2::Error::None) {
+ DLOGE("power-off on primary failed with error = %d", status);
+ }
+
+ DLOGI("Restoring power mode on primary");
+ HWC2::PowerMode mode = hwc_display_[HWC_DISPLAY_PRIMARY]->GetLastPowerMode();
+ status = hwc_display_[HWC_DISPLAY_PRIMARY]->SetPowerMode(mode);
+ if (status != HWC2::Error::None) {
+ DLOGE("Setting power mode = %d on primary failed with error = %d", mode, status);
+ }
+
+ status = hwc_display_[HWC_DISPLAY_PRIMARY]->SetVsyncEnabled(HWC2::Vsync::Enable);
+ if (status != HWC2::Error::None) {
+ DLOGE("enabling vsync failed for primary with error = %d", status);
+ }
+
+ reset_panel_ = false;
+}
+
+int HWCSession::HotPlugHandler(bool connected) {
+ int status = 0;
+ bool notify_hotplug = false;
+
+ // To prevent sending events to client while a lock is held, acquire scope locks only within
+ // below scope so that those get automatically unlocked after the scope ends.
+ do {
+ // If HDMI is primary but not created yet (first time), create it and notify surfaceflinger.
+ // if it is already created, but got disconnected/connected again,
+ // just toggle display status and do not notify surfaceflinger.
+ // If HDMI is not primary, create/destroy external display normally.
+ if (hdmi_is_primary_) {
+ SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
+ if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
+ status = hwc_display_[HWC_DISPLAY_PRIMARY]->SetState(connected);
+ } else {
+ status = CreateExternalDisplay(HWC_DISPLAY_PRIMARY);
+ notify_hotplug = true;
+ }
+
+ break;
+ }
+
+ {
+ SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
+ // Primary display must be connected for HDMI as secondary cases.
+ if (!hwc_display_[HWC_DISPLAY_PRIMARY]) {
+ DLOGE("Primary display is not connected.");
+ return -1;
+ }
+ }
+
+ if (connected) {
+ SCOPE_LOCK(locker_[HWC_DISPLAY_EXTERNAL]);
+ Locker::ScopeLock lock_v(locker_[HWC_DISPLAY_VIRTUAL]);
+ // Connect external display if virtual display is not connected.
+ // Else, defer external display connection and process it when virtual display
+ // tears down; Do not notify SurfaceFlinger since connection is deferred now.
+ if (!hwc_display_[HWC_DISPLAY_VIRTUAL]) {
+ status = ConnectDisplay(HWC_DISPLAY_EXTERNAL);
+ if (status) {
+ return status;
+ }
+ notify_hotplug = true;
+ } else {
+ DLOGI("Virtual display is connected, pending connection");
+ external_pending_connect_ = true;
+ }
+ } else {
+ SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_EXTERNAL]);
+ // Do not return error if external display is not in connected status.
+ // Due to virtual display concurrency, external display connection might be still pending
+ // but hdmi got disconnected before pending connection could be processed.
+ if (hwc_display_[HWC_DISPLAY_EXTERNAL]) {
+ status = DisconnectDisplay(HWC_DISPLAY_EXTERNAL);
+ notify_hotplug = true;
+ }
+ external_pending_connect_ = false;
+ }
+ } while (0);
+
+ if (connected) {
+ Refresh(0);
+
+ if (!hdmi_is_primary_) {
+ // wait for sufficient time to ensure sufficient resources are available to process new
+ // new display connection.
+ uint32_t vsync_period = UINT32(GetVsyncPeriod(HWC_DISPLAY_PRIMARY));
+ usleep(vsync_period * 2 / 1000);
+ }
+ }
+
+ // notify client
+ if (notify_hotplug) {
+ HotPlug(hdmi_is_primary_ ? HWC_DISPLAY_PRIMARY : HWC_DISPLAY_EXTERNAL,
+ connected ? HWC2::Connection::Connected : HWC2::Connection::Disconnected);
+ }
+
+ qservice_->onHdmiHotplug(INT(connected));
+
+ return 0;
+}
+
+int HWCSession::GetVsyncPeriod(int disp) {
+ SCOPE_LOCK(locker_[disp]);
+ // default value
+ int32_t vsync_period = 1000000000l / 60;
+ auto attribute = HWC2::Attribute::VsyncPeriod;
+
+ if (hwc_display_[disp]) {
+ hwc_display_[disp]->GetDisplayAttribute(0, attribute, &vsync_period);
+ }
+
+ return vsync_period;
+}
+
+android::status_t HWCSession::GetVisibleDisplayRect(const android::Parcel *input_parcel,
+ android::Parcel *output_parcel) {
+ int dpy = input_parcel->readInt32();
+ if (dpy < HWC_DISPLAY_PRIMARY || dpy >= HWC_NUM_DISPLAY_TYPES) {
+ return android::BAD_VALUE;
+ }
+
+ SEQUENCE_WAIT_SCOPE_LOCK(locker_[dpy]);
+ if (!hwc_display_[dpy]) {
+ return android::NO_INIT;
+ }
+
+ hwc_rect_t visible_rect = {0, 0, 0, 0};
+ int error = hwc_display_[dpy]->GetVisibleDisplayRect(&visible_rect);
+ if (error < 0) {
+ return error;
+ }
+
+ output_parcel->writeInt32(visible_rect.left);
+ output_parcel->writeInt32(visible_rect.top);
+ output_parcel->writeInt32(visible_rect.right);
+ output_parcel->writeInt32(visible_rect.bottom);
+
+ return android::NO_ERROR;
+}
+
+void HWCSession::Refresh(hwc2_display_t display) {
+ SCOPE_LOCK(callbacks_lock_);
+ HWC2::Error err = callbacks_.Refresh(display);
+ while (err != HWC2::Error::None) {
+ callbacks_lock_.Wait();
+ err = callbacks_.Refresh(display);
+ }
+}
+
+void HWCSession::HotPlug(hwc2_display_t display, HWC2::Connection state) {
+ SCOPE_LOCK(callbacks_lock_);
+ HWC2::Error err = callbacks_.Hotplug(display, state);
+ while (err != HWC2::Error::None) {
+ callbacks_lock_.Wait();
+ err = callbacks_.Hotplug(display, state);
+ }
+}
+
+int HWCSession::CreateExternalDisplay(int disp, uint32_t primary_width,
+ uint32_t primary_height, bool use_primary_res) {
+ uint32_t panel_bpp = 0;
+ uint32_t pattern_type = 0;
+ if (qdutils::isDPConnected()) {
+ qdutils::getDPTestConfig(&panel_bpp, &pattern_type);
+ }
+ if (panel_bpp && pattern_type) {
+ return HWCDisplayExternalTest::Create(core_intf_, &buffer_allocator_, &callbacks_,
+ qservice_, panel_bpp,
+ pattern_type, &hwc_display_[disp]);
+ }
+ if (use_primary_res) {
+ return HWCDisplayExternal::Create(core_intf_, &buffer_allocator_, &callbacks_,
+ primary_width, primary_height, qservice_,
+ use_primary_res, &hwc_display_[disp]);
+ } else {
+ return HWCDisplayExternal::Create(core_intf_, &buffer_allocator_, &callbacks_,
+ qservice_, &hwc_display_[disp]);
+ }
+}
+
+} // namespace sdm
diff --git a/msm8909/sdm/libs/hwc2/hwc_session.h b/msm8909/sdm/libs/hwc2/hwc_session.h
new file mode 100644
index 00000000..c7941762
--- /dev/null
+++ b/msm8909/sdm/libs/hwc2/hwc_session.h
@@ -0,0 +1,264 @@
+/*
+ * Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
+ * Not a Contribution.
+ *
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __HWC_SESSION_H__
+#define __HWC_SESSION_H__
+
+#ifdef DISPLAY_CONFIG_1_1
+#include <vendor/display/config/1.1/IDisplayConfig.h>
+#else
+#include <vendor/display/config/1.0/IDisplayConfig.h>
+#endif
+
+#include <core/core_interface.h>
+#include <utils/locker.h>
+
+#include "hwc_callbacks.h"
+#include "hwc_layers.h"
+#include "hwc_display.h"
+#include "hwc_display_primary.h"
+#include "hwc_display_external.h"
+#include "hwc_display_virtual.h"
+#include "hwc_color_manager.h"
+#include "hwc_socket_handler.h"
+
+namespace sdm {
+
+#ifdef DISPLAY_CONFIG_1_1
+using vendor::display::config::V1_1::IDisplayConfig;
+#else
+using ::vendor::display::config::V1_0::IDisplayConfig;
+#endif
+using ::android::hardware::Return;
+
+// Create a singleton uevent listener thread valid for life of hardware composer process.
+// This thread blocks on uevents poll inside uevent library implementation. This poll exits
+// only when there is a valid uevent, it can not be interrupted otherwise. Tieing life cycle
+// of this thread with HWC session cause HWC deinitialization to wait infinitely for the
+// thread to exit.
+class HWCUEventListener {
+ public:
+ virtual ~HWCUEventListener() {}
+ virtual void UEventHandler(const char *uevent_data, int length) = 0;
+};
+
+class HWCUEvent {
+ public:
+ HWCUEvent();
+ static void UEventThread(HWCUEvent *hwc_event);
+ void Register(HWCUEventListener *uevent_listener);
+ inline bool InitDone() { return init_done_; }
+
+ private:
+ std::mutex mutex_;
+ std::condition_variable caller_cv_;
+ HWCUEventListener *uevent_listener_ = nullptr;
+ bool init_done_ = false;
+};
+
+class HWCSession : hwc2_device_t, HWCUEventListener, IDisplayConfig, public qClient::BnQClient {
+ public:
+ struct HWCModuleMethods : public hw_module_methods_t {
+ HWCModuleMethods() { hw_module_methods_t::open = HWCSession::Open; }
+ };
+
+ explicit HWCSession(const hw_module_t *module);
+ int Init();
+ int Deinit();
+ HWC2::Error CreateVirtualDisplayObject(uint32_t width, uint32_t height, int32_t *format);
+
+ template <typename... Args>
+ static int32_t CallDisplayFunction(hwc2_device_t *device, hwc2_display_t display,
+ HWC2::Error (HWCDisplay::*member)(Args...), Args... args) {
+ if (!device) {
+ return HWC2_ERROR_BAD_PARAMETER;
+ }
+
+ if (display >= HWC_NUM_DISPLAY_TYPES) {
+ return HWC2_ERROR_BAD_DISPLAY;
+ }
+
+ SCOPE_LOCK(locker_[display]);
+ HWCSession *hwc_session = static_cast<HWCSession *>(device);
+ auto status = HWC2::Error::BadDisplay;
+ if (hwc_session->hwc_display_[display]) {
+ auto hwc_display = hwc_session->hwc_display_[display];
+ status = (hwc_display->*member)(std::forward<Args>(args)...);
+ }
+ return INT32(status);
+ }
+
+ template <typename... Args>
+ static int32_t CallLayerFunction(hwc2_device_t *device, hwc2_display_t display,
+ hwc2_layer_t layer, HWC2::Error (HWCLayer::*member)(Args...),
+ Args... args) {
+ if (!device) {
+ return HWC2_ERROR_BAD_DISPLAY;
+ }
+
+ SCOPE_LOCK(locker_[display]);
+ HWCSession *hwc_session = static_cast<HWCSession *>(device);
+ auto status = HWC2::Error::BadDisplay;
+ if (hwc_session->hwc_display_[display]) {
+ status = HWC2::Error::BadLayer;
+ auto hwc_layer = hwc_session->hwc_display_[display]->GetHWCLayer(layer);
+ if (hwc_layer != nullptr) {
+ status = (hwc_layer->*member)(std::forward<Args>(args)...);
+ if (hwc_session->hwc_display_[display]->GetGeometryChanges()) {
+ hwc_session->hwc_display_[display]->ResetValidation();
+ }
+ }
+ }
+ return INT32(status);
+ }
+
+ // HWC2 Functions that require a concrete implementation in hwc session
+ // and hence need to be member functions
+ static int32_t AcceptDisplayChanges(hwc2_device_t *device, hwc2_display_t display);
+ static int32_t CreateLayer(hwc2_device_t *device, hwc2_display_t display,
+ hwc2_layer_t *out_layer_id);
+ static int32_t CreateVirtualDisplay(hwc2_device_t *device, uint32_t width, uint32_t height,
+ int32_t *format, hwc2_display_t *out_display_id);
+ static int32_t DestroyLayer(hwc2_device_t *device, hwc2_display_t display, hwc2_layer_t layer);
+ static int32_t DestroyVirtualDisplay(hwc2_device_t *device, hwc2_display_t display);
+ static void Dump(hwc2_device_t *device, uint32_t *out_size, char *out_buffer);
+ static int32_t PresentDisplay(hwc2_device_t *device, hwc2_display_t display,
+ int32_t *out_retire_fence);
+ static int32_t RegisterCallback(hwc2_device_t *device, int32_t descriptor,
+ hwc2_callback_data_t callback_data,
+ hwc2_function_pointer_t pointer);
+ static int32_t SetOutputBuffer(hwc2_device_t *device, hwc2_display_t display,
+ buffer_handle_t buffer, int32_t releaseFence);
+ static int32_t SetPowerMode(hwc2_device_t *device, hwc2_display_t display, int32_t int_mode);
+ static int32_t ValidateDisplay(hwc2_device_t *device, hwc2_display_t display,
+ uint32_t *out_num_types, uint32_t *out_num_requests);
+ static int32_t SetColorMode(hwc2_device_t *device, hwc2_display_t display,
+ int32_t /*android_color_mode_t*/ int_mode);
+ static int32_t SetColorTransform(hwc2_device_t *device, hwc2_display_t display,
+ const float *matrix, int32_t /*android_color_transform_t*/ hint);
+
+ private:
+ static const int kExternalConnectionTimeoutMs = 500;
+ static const int kPartialUpdateControlTimeoutMs = 100;
+ static bool disable_skip_validate_;
+
+ // hwc methods
+ static int Open(const hw_module_t *module, const char *name, hw_device_t **device);
+ static int Close(hw_device_t *device);
+ static void GetCapabilities(struct hwc2_device *device, uint32_t *outCount,
+ int32_t *outCapabilities);
+ static hwc2_function_pointer_t GetFunction(struct hwc2_device *device, int32_t descriptor);
+
+ // Uevent handler
+ virtual void UEventHandler(const char *uevent_data, int length);
+ int GetEventValue(const char *uevent_data, int length, const char *event_info);
+ int HotPlugHandler(bool connected);
+ void ResetPanel();
+ int32_t ConnectDisplay(int disp);
+ int DisconnectDisplay(int disp);
+ int GetVsyncPeriod(int disp);
+ int32_t GetConfigCount(int disp_id, uint32_t *count);
+ int32_t GetActiveConfigIndex(int disp_id, uint32_t *config);
+ int32_t SetActiveConfigIndex(int disp_id, uint32_t config);
+ int32_t ControlPartialUpdate(int dpy, bool enable);
+ int32_t DisplayBWTransactionPending(bool *status);
+ int32_t SetSecondaryDisplayStatus(int disp_id, HWCDisplay::DisplayStatus status);
+ int32_t GetPanelBrightness(int *level);
+ int32_t MinHdcpEncryptionLevelChanged(int disp_id, uint32_t min_enc_level);
+ int32_t CreateExternalDisplay(int disp, uint32_t primary_width = 0,
+ uint32_t primary_height = 0,
+ bool use_primary_res = false);
+
+ // service methods
+ void StartServices();
+
+ // Methods from ::android::hardware::display::config::V1_0::IDisplayConfig follow.
+ Return<void> isDisplayConnected(IDisplayConfig::DisplayType dpy,
+ isDisplayConnected_cb _hidl_cb) override;
+ Return<int32_t> setSecondayDisplayStatus(IDisplayConfig::DisplayType dpy,
+ IDisplayConfig::DisplayExternalStatus status) override;
+ Return<int32_t> configureDynRefeshRate(IDisplayConfig::DisplayDynRefreshRateOp op,
+ uint32_t refreshRate) override;
+ Return<void> getConfigCount(IDisplayConfig::DisplayType dpy,
+ getConfigCount_cb _hidl_cb) override;
+ Return<void> getActiveConfig(IDisplayConfig::DisplayType dpy,
+ getActiveConfig_cb _hidl_cb) override;
+ Return<int32_t> setActiveConfig(IDisplayConfig::DisplayType dpy, uint32_t config) override;
+ Return<void> getDisplayAttributes(uint32_t configIndex, IDisplayConfig::DisplayType dpy,
+ getDisplayAttributes_cb _hidl_cb) override;
+ Return<int32_t> setPanelBrightness(uint32_t level) override;
+ Return<void> getPanelBrightness(getPanelBrightness_cb _hidl_cb) override;
+ Return<int32_t> minHdcpEncryptionLevelChanged(IDisplayConfig::DisplayType dpy,
+ uint32_t min_enc_level) override;
+ Return<int32_t> refreshScreen() override;
+ Return<int32_t> controlPartialUpdate(IDisplayConfig::DisplayType dpy, bool enable) override;
+ Return<int32_t> toggleScreenUpdate(bool on) override;
+ Return<int32_t> setIdleTimeout(uint32_t value) override;
+ Return<void> getHDRCapabilities(IDisplayConfig::DisplayType dpy,
+ getHDRCapabilities_cb _hidl_cb) override;
+ Return<int32_t> setCameraLaunchStatus(uint32_t on) override;
+ Return<void> displayBWTransactionPending(displayBWTransactionPending_cb _hidl_cb) override;
+
+ // Methods from ::android::hardware::display::config::V1_1::IDisplayConfig follow.
+#ifdef DISPLAY_CONFIG_1_1
+ Return<int32_t> setDisplayAnimating(uint64_t display_id, bool animating) override;
+#endif
+
+ // QClient methods
+ virtual android::status_t notifyCallback(uint32_t command, const android::Parcel *input_parcel,
+ android::Parcel *output_parcel);
+ void DynamicDebug(const android::Parcel *input_parcel);
+ void SetFrameDumpConfig(const android::Parcel *input_parcel);
+ android::status_t SetMaxMixerStages(const android::Parcel *input_parcel);
+ android::status_t SetDisplayMode(const android::Parcel *input_parcel);
+ android::status_t ConfigureRefreshRate(const android::Parcel *input_parcel);
+ android::status_t QdcmCMDHandler(const android::Parcel *input_parcel,
+ android::Parcel *output_parcel);
+ android::status_t HandleGetDisplayAttributesForConfig(const android::Parcel *input_parcel,
+ android::Parcel *output_parcel);
+ android::status_t GetVisibleDisplayRect(const android::Parcel *input_parcel,
+ android::Parcel *output_parcel);
+ android::status_t SetMixerResolution(const android::Parcel *input_parcel);
+ android::status_t SetColorModeOverride(const android::Parcel *input_parcel);
+
+ void Refresh(hwc2_display_t display);
+ void HotPlug(hwc2_display_t display, HWC2::Connection state);
+
+ static Locker locker_[HWC_NUM_DISPLAY_TYPES];
+ CoreInterface *core_intf_ = nullptr;
+ HWCDisplay *hwc_display_[HWC_NUM_DISPLAY_TYPES] = {nullptr};
+ HWCCallbacks callbacks_;
+ HWCBufferAllocator buffer_allocator_;
+ HWCBufferSyncHandler buffer_sync_handler_;
+ HWCColorManager *color_mgr_ = nullptr;
+ bool reset_panel_ = false;
+ bool secure_display_active_ = false;
+ bool external_pending_connect_ = false;
+ bool new_bw_mode_ = false;
+ bool need_invalidate_ = false;
+ int bw_mode_release_fd_ = -1;
+ qService::QService *qservice_ = nullptr;
+ HWCSocketHandler socket_handler_;
+ bool hdmi_is_primary_ = false;
+ Locker callbacks_lock_;
+};
+
+} // namespace sdm
+
+#endif // __HWC_SESSION_H__
diff --git a/msm8909/sdm/libs/hwc2/hwc_session_services.cpp b/msm8909/sdm/libs/hwc2/hwc_session_services.cpp
new file mode 100644
index 00000000..e8df03e0
--- /dev/null
+++ b/msm8909/sdm/libs/hwc2/hwc_session_services.cpp
@@ -0,0 +1,494 @@
+/*
+* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation. nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <core/buffer_allocator.h>
+#include <utils/debug.h>
+#include <sync/sync.h>
+#include <profiler.h>
+
+#include "hwc_buffer_sync_handler.h"
+#include "hwc_session.h"
+
+#define __CLASS__ "HWCSession"
+
+namespace sdm {
+
+using ::android::hardware::Void;
+
+void HWCSession::StartServices() {
+ status_t status = IDisplayConfig::registerAsService();
+ if (status != OK) {
+ ALOGW("%s::%s: Could not register IDisplayConfig as service (%d).",
+ __CLASS__, __FUNCTION__, status);
+ } else {
+ ALOGI("%s::%s: IDisplayConfig service registration completed.", __CLASS__, __FUNCTION__);
+ }
+}
+
+int MapDisplayType(IDisplayConfig::DisplayType dpy) {
+ switch (dpy) {
+ case IDisplayConfig::DisplayType::DISPLAY_PRIMARY:
+ return HWC_DISPLAY_PRIMARY;
+
+ case IDisplayConfig::DisplayType::DISPLAY_EXTERNAL:
+ return HWC_DISPLAY_EXTERNAL;
+
+ case IDisplayConfig::DisplayType::DISPLAY_VIRTUAL:
+ return HWC_DISPLAY_VIRTUAL;
+
+ default:
+ break;
+ }
+
+ return -EINVAL;
+}
+
+HWCDisplay::DisplayStatus MapExternalStatus(IDisplayConfig::DisplayExternalStatus status) {
+ switch (status) {
+ case IDisplayConfig::DisplayExternalStatus::EXTERNAL_OFFLINE:
+ return HWCDisplay::kDisplayStatusOffline;
+
+ case IDisplayConfig::DisplayExternalStatus::EXTERNAL_ONLINE:
+ return HWCDisplay::kDisplayStatusOnline;
+
+ case IDisplayConfig::DisplayExternalStatus::EXTERNAL_PAUSE:
+ return HWCDisplay::kDisplayStatusPause;
+
+ case IDisplayConfig::DisplayExternalStatus::EXTERNAL_RESUME:
+ return HWCDisplay::kDisplayStatusResume;
+
+ default:
+ break;
+ }
+
+ return HWCDisplay::kDisplayStatusInvalid;
+}
+
+// Methods from ::vendor::hardware::display::config::V1_0::IDisplayConfig follow.
+Return<void> HWCSession::isDisplayConnected(IDisplayConfig::DisplayType dpy,
+ isDisplayConnected_cb _hidl_cb) {
+ int32_t error = -EINVAL;
+ bool connected = false;
+
+ int disp_id = MapDisplayType(dpy);
+ SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_id]);
+
+ if (disp_id >= 0) {
+ connected = hwc_display_[disp_id];
+ error = 0;
+ }
+
+ _hidl_cb(error, connected);
+
+ return Void();
+}
+
+int32_t HWCSession::SetSecondaryDisplayStatus(int disp_id, HWCDisplay::DisplayStatus status) {
+ if (disp_id < 0) {
+ return -EINVAL;
+ }
+
+ SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_id]);
+ DLOGI("Display = %d, Status = %d", disp_id, status);
+
+ if (disp_id == HWC_DISPLAY_PRIMARY) {
+ DLOGE("Not supported for this display");
+ } else if (!hwc_display_[disp_id]) {
+ DLOGW("Display is not connected");
+ } else {
+ return hwc_display_[disp_id]->SetDisplayStatus(status);
+ }
+
+ return -EINVAL;
+}
+
+Return<int32_t> HWCSession::setSecondayDisplayStatus(IDisplayConfig::DisplayType dpy,
+ IDisplayConfig::DisplayExternalStatus status) {
+ return SetSecondaryDisplayStatus(MapDisplayType(dpy), MapExternalStatus(status));
+}
+
+Return<int32_t> HWCSession::configureDynRefeshRate(IDisplayConfig::DisplayDynRefreshRateOp op,
+ uint32_t refreshRate) {
+ SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
+ HWCDisplay *hwc_display = hwc_display_[HWC_DISPLAY_PRIMARY];
+
+ switch (op) {
+ case IDisplayConfig::DisplayDynRefreshRateOp::DISABLE_METADATA_DYN_REFRESH_RATE:
+ return hwc_display->Perform(HWCDisplayPrimary::SET_METADATA_DYN_REFRESH_RATE, false);
+
+ case IDisplayConfig::DisplayDynRefreshRateOp::ENABLE_METADATA_DYN_REFRESH_RATE:
+ return hwc_display->Perform(HWCDisplayPrimary::SET_METADATA_DYN_REFRESH_RATE, true);
+
+ case IDisplayConfig::DisplayDynRefreshRateOp::SET_BINDER_DYN_REFRESH_RATE:
+ return hwc_display->Perform(HWCDisplayPrimary::SET_BINDER_DYN_REFRESH_RATE, refreshRate);
+
+ default:
+ DLOGW("Invalid operation %d", op);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+int32_t HWCSession::GetConfigCount(int disp_id, uint32_t *count) {
+ if (disp_id < 0) {
+ return -EINVAL;
+ }
+
+ SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_id]);
+
+ if (hwc_display_[disp_id]) {
+ return hwc_display_[disp_id]->GetDisplayConfigCount(count);
+ }
+
+ return -EINVAL;
+}
+
+Return<void> HWCSession::getConfigCount(IDisplayConfig::DisplayType dpy,
+ getConfigCount_cb _hidl_cb) {
+ uint32_t count = 0;
+ int32_t error = GetConfigCount(MapDisplayType(dpy), &count);
+
+ _hidl_cb(error, count);
+
+ return Void();
+}
+
+int32_t HWCSession::GetActiveConfigIndex(int disp_id, uint32_t *config) {
+ if (disp_id < 0) {
+ return -EINVAL;
+ }
+
+ SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_id]);
+
+ if (hwc_display_[disp_id]) {
+ return hwc_display_[disp_id]->GetActiveDisplayConfig(config);
+ }
+
+ return -EINVAL;
+}
+
+Return<void> HWCSession::getActiveConfig(IDisplayConfig::DisplayType dpy,
+ getActiveConfig_cb _hidl_cb) {
+ uint32_t config = 0;
+ int32_t error = GetActiveConfigIndex(MapDisplayType(dpy), &config);
+
+ _hidl_cb(error, config);
+
+ return Void();
+}
+
+int32_t HWCSession::SetActiveConfigIndex(int disp_id, uint32_t config) {
+ if (disp_id < 0) {
+ return -EINVAL;
+ }
+
+ SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_id]);
+ int32_t error = -EINVAL;
+ if (hwc_display_[disp_id]) {
+ error = hwc_display_[disp_id]->SetActiveDisplayConfig(config);
+ if (!error) {
+ Refresh(0);
+ }
+ }
+
+ return error;
+}
+
+Return<int32_t> HWCSession::setActiveConfig(IDisplayConfig::DisplayType dpy, uint32_t config) {
+ return SetActiveConfigIndex(MapDisplayType(dpy), config);
+}
+
+Return<void> HWCSession::getDisplayAttributes(uint32_t configIndex,
+ IDisplayConfig::DisplayType dpy,
+ getDisplayAttributes_cb _hidl_cb) {
+ int32_t error = -EINVAL;
+ IDisplayConfig::DisplayAttributes display_attributes = {};
+ int disp_id = MapDisplayType(dpy);
+
+ SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_id]);
+ if (disp_id >= 0 && hwc_display_[disp_id]) {
+ DisplayConfigVariableInfo hwc_display_attributes;
+ error = hwc_display_[disp_id]->GetDisplayAttributesForConfig(static_cast<int>(configIndex),
+ &hwc_display_attributes);
+ if (!error) {
+ display_attributes.vsyncPeriod = hwc_display_attributes.vsync_period_ns;
+ display_attributes.xRes = hwc_display_attributes.x_pixels;
+ display_attributes.yRes = hwc_display_attributes.y_pixels;
+ display_attributes.xDpi = hwc_display_attributes.x_dpi;
+ display_attributes.yDpi = hwc_display_attributes.y_dpi;
+ display_attributes.panelType = IDisplayConfig::DisplayPortType::DISPLAY_PORT_DEFAULT;
+ display_attributes.isYuv = hwc_display_attributes.is_yuv;
+ }
+ }
+
+ return Void();
+}
+
+Return<int32_t> HWCSession::setPanelBrightness(uint32_t level) {
+ SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
+ int32_t error = -EINVAL;
+
+ if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
+ error = hwc_display_[HWC_DISPLAY_PRIMARY]->SetPanelBrightness(static_cast<int>(level));
+ if (error) {
+ DLOGE("Failed to set the panel brightness = %d. Error = %d", level, error);
+ }
+ }
+
+ return error;
+}
+
+int32_t HWCSession::GetPanelBrightness(int *level) {
+ SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
+ int32_t error = -EINVAL;
+
+ if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
+ error = hwc_display_[HWC_DISPLAY_PRIMARY]->GetPanelBrightness(level);
+ if (error) {
+ DLOGE("Failed to get the panel brightness. Error = %d", error);
+ }
+ }
+
+ return error;
+}
+
+Return<void> HWCSession::getPanelBrightness(getPanelBrightness_cb _hidl_cb) {
+ int level = 0;
+ int32_t error = GetPanelBrightness(&level);
+
+ _hidl_cb(error, static_cast<uint32_t>(level));
+
+ return Void();
+}
+
+int32_t HWCSession::MinHdcpEncryptionLevelChanged(int disp_id, uint32_t min_enc_level) {
+ DLOGI("Display %d", disp_id);
+
+ if (disp_id < 0) {
+ return -EINVAL;
+ }
+
+ SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_id]);
+ if (disp_id != HWC_DISPLAY_EXTERNAL) {
+ DLOGE("Not supported for display");
+ } else if (!hwc_display_[disp_id]) {
+ DLOGW("Display is not connected");
+ } else {
+ return hwc_display_[disp_id]->OnMinHdcpEncryptionLevelChange(min_enc_level);
+ }
+
+ return -EINVAL;
+}
+
+Return<int32_t> HWCSession::minHdcpEncryptionLevelChanged(IDisplayConfig::DisplayType dpy,
+ uint32_t min_enc_level) {
+ return MinHdcpEncryptionLevelChanged(MapDisplayType(dpy), min_enc_level);
+}
+
+Return<int32_t> HWCSession::refreshScreen() {
+ SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
+ Refresh(HWC_DISPLAY_PRIMARY);
+
+ return 0;
+}
+
+int32_t HWCSession::ControlPartialUpdate(int disp_id, bool enable) {
+ if (disp_id < 0) {
+ return -EINVAL;
+ }
+
+ if (disp_id != HWC_DISPLAY_PRIMARY) {
+ DLOGW("CONTROL_PARTIAL_UPDATE is not applicable for display = %d", disp_id);
+ return -EINVAL;
+ }
+
+ SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_id]);
+ HWCDisplay *hwc_display = hwc_display_[HWC_DISPLAY_PRIMARY];
+ if (!hwc_display) {
+ DLOGE("primary display object is not instantiated");
+ return -EINVAL;
+ }
+
+ uint32_t pending = 0;
+ DisplayError hwc_error = hwc_display->ControlPartialUpdate(enable, &pending);
+
+ if (hwc_error == kErrorNone) {
+ if (!pending) {
+ return 0;
+ }
+ } else if (hwc_error == kErrorNotSupported) {
+ return 0;
+ } else {
+ return -EINVAL;
+ }
+
+ // Todo(user): Unlock it before sending events to client. It may cause deadlocks in future.
+ Refresh(HWC_DISPLAY_PRIMARY);
+
+ // Wait until partial update control is complete
+ int32_t error = locker_[disp_id].WaitFinite(kPartialUpdateControlTimeoutMs);
+
+ return error;
+}
+
+Return<int32_t> HWCSession::controlPartialUpdate(IDisplayConfig::DisplayType dpy, bool enable) {
+ return ControlPartialUpdate(MapDisplayType(dpy), enable);
+}
+
+Return<int32_t> HWCSession::toggleScreenUpdate(bool on) {
+ SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
+
+ int32_t error = -EINVAL;
+ if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
+ error = hwc_display_[HWC_DISPLAY_PRIMARY]->ToggleScreenUpdates(on);
+ if (error) {
+ DLOGE("Failed to toggle screen updates = %d. Error = %d", on, error);
+ }
+ }
+
+ return error;
+}
+
+Return<int32_t> HWCSession::setIdleTimeout(uint32_t value) {
+ SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
+
+ if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
+ hwc_display_[HWC_DISPLAY_PRIMARY]->SetIdleTimeoutMs(value);
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+Return<void> HWCSession::getHDRCapabilities(IDisplayConfig::DisplayType dpy,
+ getHDRCapabilities_cb _hidl_cb) {
+ int32_t error = -EINVAL;
+ IDisplayConfig::DisplayHDRCapabilities hdr_caps = {};
+
+ do {
+ int disp_id = MapDisplayType(dpy);
+ if (disp_id < 0) {
+ DLOGE("Invalid display id = %d", disp_id);
+ break;
+ }
+
+ SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_id]);
+ HWCDisplay *hwc_display = hwc_display_[disp_id];
+ if (!hwc_display) {
+ DLOGE("Display = %d is not connected.", disp_id);
+ break;
+ }
+
+ // query number of hdr types
+ uint32_t out_num_types = 0;
+ if (hwc_display->GetHdrCapabilities(&out_num_types, nullptr, nullptr, nullptr, nullptr)
+ != HWC2::Error::None) {
+ break;
+ }
+
+ if (!out_num_types) {
+ error = 0;
+ break;
+ }
+
+ // query hdr caps
+ hdr_caps.supportedHdrTypes.resize(out_num_types);
+
+ float out_max_luminance = 0.0f;
+ float out_max_average_luminance = 0.0f;
+ float out_min_luminance = 0.0f;
+ if (hwc_display->GetHdrCapabilities(&out_num_types, hdr_caps.supportedHdrTypes.data(),
+ &out_max_luminance, &out_max_average_luminance,
+ &out_min_luminance)
+ == HWC2::Error::None) {
+ error = 0;
+ }
+ } while (false);
+
+ _hidl_cb(error, hdr_caps);
+
+ return Void();
+}
+
+Return<int32_t> HWCSession::setCameraLaunchStatus(uint32_t on) {
+ SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
+
+ HWBwModes mode = on > 0 ? kBwCamera : kBwDefault;
+
+ // trigger invalidate to apply new bw caps.
+ Refresh(HWC_DISPLAY_PRIMARY);
+
+ if (core_intf_->SetMaxBandwidthMode(mode) != kErrorNone) {
+ return -EINVAL;
+ }
+
+ new_bw_mode_ = true;
+ need_invalidate_ = true;
+ hwc_display_[HWC_DISPLAY_PRIMARY]->ResetValidation();
+
+ return 0;
+}
+
+int32_t HWCSession::DisplayBWTransactionPending(bool *status) {
+ SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
+
+ if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
+ if (sync_wait(bw_mode_release_fd_, 0) < 0) {
+ DLOGI("bw_transaction_release_fd is not yet signaled: err= %s", strerror(errno));
+ *status = false;
+ }
+
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+Return<void> HWCSession::displayBWTransactionPending(displayBWTransactionPending_cb _hidl_cb) {
+ bool status = true;
+
+ int32_t error = DisplayBWTransactionPending(&status);
+
+ _hidl_cb(error, status);
+
+ return Void();
+}
+
+#ifdef DISPLAY_CONFIG_1_1
+// Methods from ::vendor::hardware::display::config::V1_1::IDisplayConfig follow.
+Return<int32_t> HWCSession::setDisplayAnimating(uint64_t display_id, bool animating ) {
+ SEQUENCE_WAIT_SCOPE_LOCK(locker_[display_id]);
+ return CallDisplayFunction(static_cast<hwc2_device_t *>(this), display_id,
+ &HWCDisplay::SetDisplayAnimating, animating);
+}
+#endif
+
+
+} // namespace sdm
diff --git a/msm8909/sdm/libs/hwc2/hwc_tonemapper.cpp b/msm8909/sdm/libs/hwc2/hwc_tonemapper.cpp
new file mode 100644
index 00000000..e68741e6
--- /dev/null
+++ b/msm8909/sdm/libs/hwc2/hwc_tonemapper.cpp
@@ -0,0 +1,386 @@
+/*
+* Copyright (c) 2016 - 2018, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <gralloc_priv.h>
+#include <sync/sync.h>
+
+#include <TonemapFactory.h>
+
+#include <core/buffer_allocator.h>
+
+#include <utils/constants.h>
+#include <utils/debug.h>
+#include <utils/formats.h>
+#include <utils/rect.h>
+#include <utils/utils.h>
+
+#include <vector>
+
+#include "hwc_debugger.h"
+#include "hwc_tonemapper.h"
+
+#define __CLASS__ "HWCToneMapper"
+
+namespace sdm {
+
+ToneMapSession::ToneMapSession(HWCBufferAllocator *buffer_allocator)
+ : tone_map_task_(*this), buffer_allocator_(buffer_allocator) {
+ buffer_info_.resize(kNumIntermediateBuffers);
+}
+
+ToneMapSession::~ToneMapSession() {
+ tone_map_task_.PerformTask(ToneMapTaskCode::kCodeDestroy, nullptr);
+ FreeIntermediateBuffers();
+ buffer_info_.clear();
+}
+
+void ToneMapSession::OnTask(const ToneMapTaskCode &task_code,
+ SyncTask<ToneMapTaskCode>::TaskContext *task_context) {
+ switch (task_code) {
+ case ToneMapTaskCode::kCodeGetInstance: {
+ ToneMapGetInstanceContext *ctx = static_cast<ToneMapGetInstanceContext *>(task_context);
+ Lut3d &lut_3d = ctx->layer->lut_3d;
+ Color10Bit *grid_entries = NULL;
+ int grid_size = 0;
+ if (lut_3d.validGridEntries) {
+ grid_entries = lut_3d.gridEntries;
+ grid_size = INT(lut_3d.gridSize);
+ }
+ gpu_tone_mapper_ = TonemapperFactory_GetInstance(tone_map_config_.type,
+ lut_3d.lutEntries, lut_3d.dim,
+ grid_entries, grid_size,
+ tone_map_config_.secure);
+ }
+ break;
+
+ case ToneMapTaskCode::kCodeBlit: {
+ ToneMapBlitContext *ctx = static_cast<ToneMapBlitContext *>(task_context);
+ uint8_t buffer_index = current_buffer_index_;
+ const void *dst_hnd = reinterpret_cast<const void *>
+ (buffer_info_[buffer_index].private_data);
+ const void *src_hnd = reinterpret_cast<const void *>
+ (ctx->layer->input_buffer.buffer_id);
+ ctx->fence_fd = gpu_tone_mapper_->blit(dst_hnd, src_hnd, ctx->merged_fd);
+ }
+ break;
+
+ case ToneMapTaskCode::kCodeDestroy: {
+ delete gpu_tone_mapper_;
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
+DisplayError ToneMapSession::AllocateIntermediateBuffers(const Layer *layer) {
+ DisplayError error = kErrorNone;
+ for (uint8_t i = 0; i < kNumIntermediateBuffers; i++) {
+ BufferInfo &buffer_info = buffer_info_[i];
+ buffer_info.buffer_config.width = layer->request.width;
+ buffer_info.buffer_config.height = layer->request.height;
+ buffer_info.buffer_config.format = layer->request.format;
+ buffer_info.buffer_config.secure = layer->request.flags.secure;
+ buffer_info.buffer_config.gfx_client = true;
+ error = buffer_allocator_->AllocateBuffer(&buffer_info);
+ if (error != kErrorNone) {
+ FreeIntermediateBuffers();
+ return error;
+ }
+ }
+
+ return kErrorNone;
+}
+
+void ToneMapSession::FreeIntermediateBuffers() {
+ for (uint8_t i = 0; i < kNumIntermediateBuffers; i++) {
+ // Free the valid fence
+ if (release_fence_fd_[i] >= 0) {
+ CloseFd(&release_fence_fd_[i]);
+ }
+ BufferInfo &buffer_info = buffer_info_[i];
+ if (buffer_info.private_data) {
+ buffer_allocator_->FreeBuffer(&buffer_info);
+ }
+ }
+}
+
+void ToneMapSession::UpdateBuffer(int acquire_fence, LayerBuffer *buffer) {
+ // Acquire fence will be closed by HWC Display.
+ // Fence returned by GPU will be closed in PostCommit.
+ buffer->acquire_fence_fd = acquire_fence;
+ buffer->size = buffer_info_[current_buffer_index_].alloc_buffer_info.size;
+ buffer->planes[0].fd = buffer_info_[current_buffer_index_].alloc_buffer_info.fd;
+}
+
+void ToneMapSession::SetReleaseFence(int fd) {
+ CloseFd(&release_fence_fd_[current_buffer_index_]);
+ // Used to give to GPU tonemapper along with input layer fd
+ release_fence_fd_[current_buffer_index_] = dup(fd);
+}
+
+void ToneMapSession::SetToneMapConfig(Layer *layer) {
+ // HDR -> SDR is FORWARD and SDR - > HDR is INVERSE
+ tone_map_config_.type = layer->input_buffer.flags.hdr ? TONEMAP_FORWARD : TONEMAP_INVERSE;
+ tone_map_config_.colorPrimaries = layer->input_buffer.color_metadata.colorPrimaries;
+ tone_map_config_.transfer = layer->input_buffer.color_metadata.transfer;
+ tone_map_config_.secure = layer->request.flags.secure;
+ tone_map_config_.format = layer->request.format;
+}
+
+bool ToneMapSession::IsSameToneMapConfig(Layer *layer) {
+ LayerBuffer& buffer = layer->input_buffer;
+ private_handle_t *handle = static_cast<private_handle_t *>(buffer_info_[0].private_data);
+ int tonemap_type = buffer.flags.hdr ? TONEMAP_FORWARD : TONEMAP_INVERSE;
+
+ return ((tonemap_type == tone_map_config_.type) &&
+ (buffer.color_metadata.colorPrimaries == tone_map_config_.colorPrimaries) &&
+ (buffer.color_metadata.transfer == tone_map_config_.transfer) &&
+ (layer->request.flags.secure == tone_map_config_.secure) &&
+ (layer->request.format == tone_map_config_.format) &&
+ (layer->request.width == UINT32(handle->unaligned_width)) &&
+ (layer->request.height == UINT32(handle->unaligned_height)));
+}
+
+int HWCToneMapper::HandleToneMap(LayerStack *layer_stack) {
+ uint32_t gpu_count = 0;
+ DisplayError error = kErrorNone;
+
+ for (uint32_t i = 0; i < layer_stack->layers.size(); i++) {
+ uint32_t session_index = 0;
+ Layer *layer = layer_stack->layers.at(i);
+ if (layer->composition == kCompositionGPU) {
+ gpu_count++;
+ }
+
+ if (layer->request.flags.tone_map) {
+ DLOGV_IF(kTagClient, "Tonemapping for layer at index %d", i);
+ switch (layer->composition) {
+ case kCompositionGPUTarget:
+ if (!gpu_count) {
+ // When all layers are on FrameBuffer and if they do not update in the next draw cycle,
+ // then SDM marks them for SDE Composition because the cached FB layer gets displayed.
+ // GPU count will be 0 in this case. Try to use the existing tone-mapped frame buffer.
+ // No ToneMap/Blit is required. Just update the buffer & acquire fence fd of FB layer.
+ if (!tone_map_sessions_.empty() && (fb_session_index_ >= 0)) {
+ ToneMapSession *fb_tone_map_session = tone_map_sessions_.at(UINT32(fb_session_index_));
+ fb_tone_map_session->UpdateBuffer(-1 /* acquire_fence */, &layer->input_buffer);
+ fb_tone_map_session->layer_index_ = INT(i);
+ fb_tone_map_session->acquired_ = true;
+ return 0;
+ }
+ }
+ error = AcquireToneMapSession(layer, &session_index);
+ fb_session_index_ = INT(session_index);
+ break;
+ default:
+ error = AcquireToneMapSession(layer, &session_index);
+ break;
+ }
+
+ if (error != kErrorNone) {
+ Terminate();
+ return -1;
+ }
+
+ ToneMapSession *session = tone_map_sessions_.at(session_index);
+ ToneMap(layer, session);
+ DLOGI_IF(kTagClient, "Layer %d associated with session index %d", i, session_index);
+ session->layer_index_ = INT(i);
+ }
+ }
+
+ return 0;
+}
+
+void HWCToneMapper::ToneMap(Layer* layer, ToneMapSession *session) {
+ ToneMapBlitContext ctx = {};
+ ctx.layer = layer;
+
+ uint8_t buffer_index = session->current_buffer_index_;
+ int &release_fence_fd = session->release_fence_fd_[buffer_index];
+
+ // use and close the layer->input_buffer acquire fence fd.
+ int acquire_fd = layer->input_buffer.acquire_fence_fd;
+ buffer_sync_handler_.SyncMerge(release_fence_fd, acquire_fd, &ctx.merged_fd);
+
+ if (acquire_fd >= 0) {
+ CloseFd(&acquire_fd);
+ }
+
+ if (release_fence_fd >= 0) {
+ CloseFd(&release_fence_fd);
+ }
+
+ DTRACE_BEGIN("GPU_TM_BLIT");
+ session->tone_map_task_.PerformTask(ToneMapTaskCode::kCodeBlit, &ctx);
+ DTRACE_END();
+
+ DumpToneMapOutput(session, &ctx.fence_fd);
+ session->UpdateBuffer(ctx.fence_fd, &layer->input_buffer);
+}
+
+void HWCToneMapper::PostCommit(LayerStack *layer_stack) {
+ auto it = tone_map_sessions_.begin();
+ while (it != tone_map_sessions_.end()) {
+ uint32_t session_index = UINT32(std::distance(tone_map_sessions_.begin(), it));
+ ToneMapSession *session = tone_map_sessions_.at(session_index);
+ if (session->acquired_) {
+ Layer *layer = layer_stack->layers.at(UINT32(session->layer_index_));
+ // Close the fd returned by GPU ToneMapper and set release fence.
+ LayerBuffer &layer_buffer = layer->input_buffer;
+ CloseFd(&layer_buffer.acquire_fence_fd);
+ session->SetReleaseFence(layer_buffer.release_fence_fd);
+ session->acquired_ = false;
+ it++;
+ } else {
+ DLOGI_IF(kTagClient, "Tone map session %d closed.", session_index);
+ delete session;
+ it = tone_map_sessions_.erase(it);
+ int deleted_session = INT(session_index);
+ // If FB tonemap session gets deleted, reset fb_session_index_, else update it.
+ if (deleted_session == fb_session_index_) {
+ fb_session_index_ = -1;
+ } else if (deleted_session < fb_session_index_) {
+ fb_session_index_--;
+ }
+ }
+ }
+}
+
+void HWCToneMapper::Terminate() {
+ if (tone_map_sessions_.size()) {
+ while (!tone_map_sessions_.empty()) {
+ delete tone_map_sessions_.back();
+ tone_map_sessions_.pop_back();
+ }
+ fb_session_index_ = -1;
+ }
+}
+
+void HWCToneMapper::SetFrameDumpConfig(uint32_t count) {
+ DLOGI("Dump FrameConfig count = %d", count);
+ dump_frame_count_ = count;
+ dump_frame_index_ = 0;
+}
+
+void HWCToneMapper::DumpToneMapOutput(ToneMapSession *session, int *acquire_fd) {
+ DisplayError error = kErrorNone;
+ if (!dump_frame_count_) {
+ return;
+ }
+
+ BufferInfo &buffer_info = session->buffer_info_[session->current_buffer_index_];
+ private_handle_t *target_buffer = static_cast<private_handle_t *>(buffer_info.private_data);
+
+ if (*acquire_fd >= 0) {
+ int error = sync_wait(*acquire_fd, 1000);
+ if (error < 0) {
+ DLOGW("sync_wait error errno = %d, desc = %s", errno, strerror(errno));
+ return;
+ }
+ }
+
+ error = buffer_allocator_->MapBuffer(target_buffer, *acquire_fd);
+ if (error != kErrorNone) {
+ DLOGE("MapBuffer failed, base addr = %x", target_buffer->base);
+ return;
+ }
+
+ size_t result = 0;
+ char dump_file_name[PATH_MAX];
+ snprintf(dump_file_name, sizeof(dump_file_name), "%s/frame_dump_primary"
+ "/tonemap_%dx%d_frame%d.raw", HWCDebugHandler::DumpDir(), target_buffer->width,
+ target_buffer->height, dump_frame_index_);
+
+ FILE* fp = fopen(dump_file_name, "w+");
+ if (fp) {
+ DLOGI("base addr = %x", target_buffer->base);
+ result = fwrite(reinterpret_cast<void *>(target_buffer->base), target_buffer->size, 1, fp);
+ fclose(fp);
+ }
+ dump_frame_count_--;
+ dump_frame_index_++;
+ CloseFd(acquire_fd);
+}
+
+DisplayError HWCToneMapper::AcquireToneMapSession(Layer *layer, uint32_t *session_index) {
+ // When the property vendor.display.disable_hdr_lut_gen is set, the lutEntries and gridEntries in
+ // the Lut3d will be NULL, clients needs to allocate the memory and set correct 3D Lut
+ // for Tonemapping.
+ if (!layer->lut_3d.lutEntries || !layer->lut_3d.dim) {
+ // Atleast lutEntries must be valid for GPU Tonemapper.
+ DLOGE("Invalid Lut Entries or lut dimension = %d", layer->lut_3d.dim);
+ return kErrorParameters;
+ }
+
+ // Check if we can re-use an existing tone map session.
+ for (uint32_t i = 0; i < tone_map_sessions_.size(); i++) {
+ ToneMapSession *tonemap_session = tone_map_sessions_.at(i);
+ if (!tonemap_session->acquired_ && tonemap_session->IsSameToneMapConfig(layer)) {
+ tonemap_session->current_buffer_index_ = (tonemap_session->current_buffer_index_ + 1) %
+ ToneMapSession::kNumIntermediateBuffers;
+ tonemap_session->acquired_ = true;
+ *session_index = i;
+ return kErrorNone;
+ }
+ }
+
+ ToneMapSession *session = new ToneMapSession(buffer_allocator_);
+ if (!session) {
+ return kErrorMemory;
+ }
+
+ session->SetToneMapConfig(layer);
+
+ ToneMapGetInstanceContext ctx;
+ ctx.layer = layer;
+ session->tone_map_task_.PerformTask(ToneMapTaskCode::kCodeGetInstance, &ctx);
+
+ if (session->gpu_tone_mapper_ == NULL) {
+ DLOGE("Get Tonemapper failed!");
+ delete session;
+ return kErrorNotSupported;
+ }
+ DisplayError error = session->AllocateIntermediateBuffers(layer);
+ if (error != kErrorNone) {
+ DLOGE("Allocation of Intermediate Buffers failed!");
+ delete session;
+ return error;
+ }
+
+ session->acquired_ = true;
+ tone_map_sessions_.push_back(session);
+ *session_index = UINT32(tone_map_sessions_.size() - 1);
+
+ return kErrorNone;
+}
+
+} // namespace sdm
diff --git a/msm8909/sdm/libs/hwc2/hwc_tonemapper.h b/msm8909/sdm/libs/hwc2/hwc_tonemapper.h
new file mode 100644
index 00000000..8bef3b1f
--- /dev/null
+++ b/msm8909/sdm/libs/hwc2/hwc_tonemapper.h
@@ -0,0 +1,125 @@
+/*
+* Copyright (c) 2016 - 2017, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __HWC_TONEMAPPER_H__
+#define __HWC_TONEMAPPER_H__
+
+#include <fcntl.h>
+#include <sys/mman.h>
+
+#include <hardware/hwcomposer.h>
+
+#include <core/layer_stack.h>
+#include <utils/sys.h>
+#include <utils/sync_task.h>
+#include <vector>
+#include "hwc_buffer_sync_handler.h"
+#include "hwc_buffer_allocator.h"
+
+class Tonemapper;
+
+namespace sdm {
+
+enum class ToneMapTaskCode : int32_t {
+ kCodeGetInstance,
+ kCodeBlit,
+ kCodeDestroy,
+};
+
+struct ToneMapGetInstanceContext : public SyncTask<ToneMapTaskCode>::TaskContext {
+ Layer *layer = nullptr;
+};
+
+struct ToneMapBlitContext : public SyncTask<ToneMapTaskCode>::TaskContext {
+ Layer *layer = nullptr;
+ int merged_fd = -1;
+ int fence_fd = -1;
+};
+
+struct ToneMapConfig {
+ int type = 0;
+ ColorPrimaries colorPrimaries = ColorPrimaries_Max;
+ GammaTransfer transfer = Transfer_Max;
+ LayerBufferFormat format = kFormatRGBA8888;
+ bool secure = false;
+};
+
+class ToneMapSession : public SyncTask<ToneMapTaskCode>::TaskHandler {
+ public:
+ explicit ToneMapSession(HWCBufferAllocator *buffer_allocator);
+ ~ToneMapSession();
+ DisplayError AllocateIntermediateBuffers(const Layer *layer);
+ void FreeIntermediateBuffers();
+ void UpdateBuffer(int acquire_fence, LayerBuffer *buffer);
+ void SetReleaseFence(int fd);
+ void SetToneMapConfig(Layer *layer);
+ bool IsSameToneMapConfig(Layer *layer);
+
+ // TaskHandler methods implementation.
+ virtual void OnTask(const ToneMapTaskCode &task_code,
+ SyncTask<ToneMapTaskCode>::TaskContext *task_context);
+
+ static const uint8_t kNumIntermediateBuffers = 2;
+ SyncTask<ToneMapTaskCode> tone_map_task_;
+ Tonemapper *gpu_tone_mapper_ = nullptr;
+ HWCBufferAllocator *buffer_allocator_ = nullptr;
+ ToneMapConfig tone_map_config_ = {};
+ uint8_t current_buffer_index_ = 0;
+ std::vector<BufferInfo> buffer_info_ = {};
+ int release_fence_fd_[kNumIntermediateBuffers] = {-1, -1};
+ bool acquired_ = false;
+ int layer_index_ = -1;
+};
+
+class HWCToneMapper {
+ public:
+ explicit HWCToneMapper(HWCBufferAllocator *allocator) : buffer_allocator_(allocator) {}
+ ~HWCToneMapper() {}
+
+ int HandleToneMap(LayerStack *layer_stack);
+ bool IsActive() { return !tone_map_sessions_.empty(); }
+ void PostCommit(LayerStack *layer_stack);
+ void SetFrameDumpConfig(uint32_t count);
+ void Terminate();
+
+ private:
+ void ToneMap(Layer *layer, ToneMapSession *session);
+ DisplayError AcquireToneMapSession(Layer *layer, uint32_t *session_index);
+ void DumpToneMapOutput(ToneMapSession *session, int *acquire_fence);
+
+ std::vector<ToneMapSession*> tone_map_sessions_;
+ HWCBufferSyncHandler buffer_sync_handler_ = {};
+ HWCBufferAllocator *buffer_allocator_ = nullptr;
+ uint32_t dump_frame_count_ = 0;
+ uint32_t dump_frame_index_ = 0;
+ int fb_session_index_ = -1;
+};
+
+} // namespace sdm
+#endif // __HWC_TONEMAPPER_H__
diff --git a/msm8909/sdm/libs/utils/Android.mk b/msm8909/sdm/libs/utils/Android.mk
new file mode 100644
index 00000000..09e14146
--- /dev/null
+++ b/msm8909/sdm/libs/utils/Android.mk
@@ -0,0 +1,32 @@
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+include $(LOCAL_PATH)/../../../common.mk
+
+LOCAL_MODULE := libsdmutils
+LOCAL_VENDOR_MODULE := true
+LOCAL_MODULE_TAGS := optional
+LOCAL_C_INCLUDES := $(common_includes)
+LOCAL_HEADER_LIBRARIES := display_headers
+LOCAL_CFLAGS := -DLOG_TAG=\"SDM\" $(common_flags)
+LOCAL_SRC_FILES := debug.cpp \
+ rect.cpp \
+ sys.cpp \
+ formats.cpp \
+ utils.cpp
+
+include $(BUILD_SHARED_LIBRARY)
+
+SDM_HEADER_PATH := ../../include
+include $(CLEAR_VARS)
+LOCAL_COPY_HEADERS_TO := $(common_header_export_path)/sdm/utils
+LOCAL_COPY_HEADERS = $(SDM_HEADER_PATH)/utils/constants.h \
+ $(SDM_HEADER_PATH)/utils/debug.h \
+ $(SDM_HEADER_PATH)/utils/formats.h \
+ $(SDM_HEADER_PATH)/utils/locker.h \
+ $(SDM_HEADER_PATH)/utils/rect.h \
+ $(SDM_HEADER_PATH)/utils/sys.h \
+ $(SDM_HEADER_PATH)/utils/sync_task.h \
+ $(SDM_HEADER_PATH)/utils/utils.h \
+ $(SDM_HEADER_PATH)/utils/factory.h
+
+include $(BUILD_COPY_HEADERS)
diff --git a/msm8909/sdm/libs/utils/Makefile.am b/msm8909/sdm/libs/utils/Makefile.am
new file mode 100644
index 00000000..d8d8dc5a
--- /dev/null
+++ b/msm8909/sdm/libs/utils/Makefile.am
@@ -0,0 +1,12 @@
+cpp_sources = debug.cpp \
+ rect.cpp \
+ sys.cpp \
+ formats.cpp \
+ utils.cpp
+
+lib_LTLIBRARIES = libsdmutils.la
+libsdmutils_la_CC = @CC@
+libsdmutils_la_SOURCES = $(cpp_sources)
+libsdmutils_la_CFLAGS = $(COMMON_CFLAGS) -DLOG_TAG=\"SDM\"
+libsdmutils_la_CPPFLAGS = $(AM_CPPFLAGS)
+libsdmutils_la_LDFLAGS = -shared -avoid-version
diff --git a/msm8909/sdm/libs/utils/debug.cpp b/msm8909/sdm/libs/utils/debug.cpp
new file mode 100644
index 00000000..a012ab4e
--- /dev/null
+++ b/msm8909/sdm/libs/utils/debug.cpp
@@ -0,0 +1,216 @@
+/*
+* Copyright (c) 2014 - 2018, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <stdlib.h>
+#include <utils/debug.h>
+#include <utils/constants.h>
+#include <string>
+#include <algorithm>
+
+namespace sdm {
+
+Debug Debug::debug_;
+
+Debug::Debug() : debug_handler_(&default_debug_handler_) {
+}
+
+int Debug::GetSimulationFlag() {
+ int value = 0;
+ debug_.debug_handler_->GetProperty(COMPOSITION_MASK_PROP, &value);
+
+ return value;
+}
+
+int Debug::GetHDMIResolution() {
+ int value = 0;
+ debug_.debug_handler_->GetProperty(HDMI_CONFIG_INDEX_PROP, &value);
+ return value;
+}
+
+void Debug::GetIdleTimeoutMs(uint32_t *active_ms, uint32_t *inactive_ms) {
+ int active_val = IDLE_TIMEOUT_ACTIVE_MS;
+ int inactive_val = IDLE_TIMEOUT_INACTIVE_MS;
+
+ debug_.debug_handler_->GetProperty(IDLE_TIME_PROP, &active_val);
+ debug_.debug_handler_->GetProperty(IDLE_TIME_INACTIVE_PROP, &inactive_val);
+
+ *active_ms = UINT32(active_val);
+ *inactive_ms = UINT32(inactive_val);
+}
+
+int Debug::GetBootAnimLayerCount() {
+ int value = 0;
+ debug_.debug_handler_->GetProperty(BOOT_ANIMATION_LAYER_COUNT_PROP, &value);
+
+ return value;
+}
+
+bool Debug::IsRotatorDownScaleDisabled() {
+ int value = 0;
+ debug_.debug_handler_->GetProperty(DISABLE_ROTATOR_DOWNSCALE_PROP, &value);
+
+ return (value == 1);
+}
+
+bool Debug::IsDecimationDisabled() {
+ int value = 0;
+ debug_.debug_handler_->GetProperty(DISABLE_DECIMATION_PROP, &value);
+
+ return (value == 1);
+}
+
+int Debug::GetMaxPipesPerMixer(DisplayType display_type) {
+ int value = -1;
+ switch (display_type) {
+ case kPrimary:
+ debug_.debug_handler_->GetProperty(PRIMARY_MIXER_STAGES_PROP, &value);
+ break;
+ case kHDMI:
+ debug_.debug_handler_->GetProperty(EXTERNAL_MIXER_STAGES_PROP, &value);
+ break;
+ case kVirtual:
+ debug_.debug_handler_->GetProperty(VIRTUAL_MIXER_STAGES_PROP, &value);
+ break;
+ default:
+ break;
+ }
+
+ return value;
+}
+
+int Debug::GetMaxUpscale() {
+ int value = 0;
+ debug_.debug_handler_->GetProperty(MAX_UPSCALE_PROP, &value);
+
+ return value;
+}
+
+bool Debug::IsVideoModeEnabled() {
+ int value = 0;
+ debug_.debug_handler_->GetProperty(VIDEO_MODE_PANEL_PROP, &value);
+
+ return (value == 1);
+}
+
+bool Debug::IsRotatorUbwcDisabled() {
+ int value = 0;
+ debug_.debug_handler_->GetProperty(DISABLE_ROTATOR_UBWC_PROP, &value);
+
+ return (value == 1);
+}
+
+bool Debug::IsRotatorSplitDisabled() {
+ int value = 0;
+ debug_.debug_handler_->GetProperty(DISABLE_ROTATOR_SPLIT_PROP, &value);
+
+ return (value == 1);
+}
+
+bool Debug::IsScalarDisabled() {
+ int value = 0;
+ debug_.debug_handler_->GetProperty(DISABLE_SCALER_PROP, &value);
+
+ return (value == 1);
+}
+
+bool Debug::IsUbwcTiledFrameBuffer() {
+ int ubwc_disabled = 0;
+ int ubwc_framebuffer = 0;
+
+ debug_.debug_handler_->GetProperty(DISABLE_UBWC_PROP, &ubwc_disabled);
+
+ if (!ubwc_disabled) {
+ debug_.debug_handler_->GetProperty(ENABLE_FB_UBWC_PROP, &ubwc_framebuffer);
+ }
+
+ return (ubwc_framebuffer == 1);
+}
+
+bool Debug::IsAVRDisabled() {
+ int value = 0;
+ debug_.debug_handler_->GetProperty(DISABLE_AVR_PROP, &value);
+
+ return (value == 1);
+}
+
+bool Debug::IsExtAnimDisabled() {
+ int value = 0;
+ debug_.debug_handler_->GetProperty(DISABLE_EXTERNAL_ANIMATION_PROP, &value);
+
+ return (value == 1);
+}
+
+bool Debug::IsPartialSplitDisabled() {
+ int value = 0;
+ debug_.debug_handler_->GetProperty(DISABLE_PARTIAL_SPLIT_PROP, &value);
+
+ return (value == 1);
+}
+
+DisplayError Debug::GetMixerResolution(uint32_t *width, uint32_t *height) {
+ char value[64] = {};
+
+ DisplayError error = debug_.debug_handler_->GetProperty(MIXER_RESOLUTION_PROP, value);
+ if (error !=kErrorNone) {
+ return error;
+ }
+
+ std::string str(value);
+
+ *width = UINT32(stoi(str));
+ *height = UINT32(stoi(str.substr(str.find('x') + 1)));
+
+ return kErrorNone;
+}
+
+int Debug::GetExtMaxlayers() {
+ int max_external_layers = 0;
+ debug_.debug_handler_->GetProperty(MAX_EXTERNAL_LAYERS_PROP, &max_external_layers);
+
+ return std::max(max_external_layers, 2);
+}
+
+bool Debug::GetProperty(const char* property_name, char* value) {
+ if (debug_.debug_handler_->GetProperty(property_name, value) != kErrorNone) {
+ return false;
+ }
+
+ return true;
+}
+
+bool Debug::SetProperty(const char* property_name, const char* value) {
+ if (debug_.debug_handler_->SetProperty(property_name, value) != kErrorNone) {
+ return false;
+ }
+
+ return true;
+}
+
+} // namespace sdm
+
diff --git a/msm8909/sdm/libs/utils/formats.cpp b/msm8909/sdm/libs/utils/formats.cpp
new file mode 100644
index 00000000..b7deb183
--- /dev/null
+++ b/msm8909/sdm/libs/utils/formats.cpp
@@ -0,0 +1,131 @@
+/*
+* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <utils/formats.h>
+
+#define __CLASS__ "FormatsUtils"
+
+namespace sdm {
+
+bool IsUBWCFormat(LayerBufferFormat format) {
+ switch (format) {
+ case kFormatRGBA8888Ubwc:
+ case kFormatRGBX8888Ubwc:
+ case kFormatBGR565Ubwc:
+ case kFormatYCbCr420SPVenusUbwc:
+ case kFormatRGBA1010102Ubwc:
+ case kFormatRGBX1010102Ubwc:
+ case kFormatYCbCr420TP10Ubwc:
+ case kFormatYCbCr420P010Ubwc:
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool Is10BitFormat(LayerBufferFormat format) {
+ switch (format) {
+ case kFormatRGBA1010102:
+ case kFormatARGB2101010:
+ case kFormatRGBX1010102:
+ case kFormatXRGB2101010:
+ case kFormatBGRA1010102:
+ case kFormatABGR2101010:
+ case kFormatBGRX1010102:
+ case kFormatXBGR2101010:
+ case kFormatRGBA1010102Ubwc:
+ case kFormatRGBX1010102Ubwc:
+ case kFormatYCbCr420P010:
+ case kFormatYCbCr420TP10Ubwc:
+ case kFormatYCbCr420P010Ubwc:
+ return true;
+ default:
+ return false;
+ }
+}
+
+const char *GetFormatString(const LayerBufferFormat &format) {
+ switch (format) {
+ case kFormatARGB8888: return "ARGB_8888";
+ case kFormatRGBA8888: return "RGBA_8888";
+ case kFormatBGRA8888: return "BGRA_8888";
+ case kFormatXRGB8888: return "XRGB_8888";
+ case kFormatRGBX8888: return "RGBX_8888";
+ case kFormatBGRX8888: return "BGRX_8888";
+ case kFormatRGBA5551: return "RGBA_5551";
+ case kFormatRGBA4444: return "RGBA_4444";
+ case kFormatRGB888: return "RGB_888";
+ case kFormatBGR888: return "BGR_888";
+ case kFormatRGB565: return "RGB_565";
+ case kFormatBGR565: return "BGR_565";
+ case kFormatRGBA8888Ubwc: return "RGBA_8888_UBWC";
+ case kFormatRGBX8888Ubwc: return "RGBX_8888_UBWC";
+ case kFormatBGR565Ubwc: return "BGR_565_UBWC";
+ case kFormatYCbCr420Planar: return "Y_CB_CR_420";
+ case kFormatYCrCb420Planar: return "Y_CR_CB_420";
+ case kFormatYCrCb420PlanarStride16: return "Y_CR_CB_420_STRIDE16";
+ case kFormatYCbCr420SemiPlanar: return "Y_CBCR_420";
+ case kFormatYCrCb420SemiPlanar: return "Y_CRCB_420";
+ case kFormatYCbCr420SemiPlanarVenus: return "Y_CBCR_420_VENUS";
+ case kFormatYCrCb420SemiPlanarVenus: return "Y_CRCB_420_VENUS";
+ case kFormatYCbCr422H1V2SemiPlanar: return "Y_CBCR_422_H1V2";
+ case kFormatYCrCb422H1V2SemiPlanar: return "Y_CRCB_422_H1V2";
+ case kFormatYCbCr422H2V1SemiPlanar: return "Y_CBCR_422_H2V1";
+ case kFormatYCrCb422H2V1SemiPlanar: return "Y_CRCB_422_H2V2";
+ case kFormatYCbCr420SPVenusUbwc: return "Y_CBCR_420_VENUS_UBWC";
+ case kFormatYCbCr422H2V1Packed: return "YCBYCR_422_H2V1";
+ case kFormatCbYCrY422H2V1Packed: return "CBYCRY_422_H2V1";
+ case kFormatRGBA1010102: return "RGBA_1010102";
+ case kFormatARGB2101010: return "ARGB_2101010";
+ case kFormatRGBX1010102: return "RGBX_1010102";
+ case kFormatXRGB2101010: return "XRGB_2101010";
+ case kFormatBGRA1010102: return "BGRA_1010102";
+ case kFormatABGR2101010: return "ABGR_2101010";
+ case kFormatBGRX1010102: return "BGRX_1010102";
+ case kFormatXBGR2101010: return "XBGR_2101010";
+ case kFormatRGBA1010102Ubwc: return "RGBA_1010102_UBWC";
+ case kFormatRGBX1010102Ubwc: return "RGBX_1010102_UBWC";
+ case kFormatYCbCr420P010: return "Y_CBCR_420_P010";
+ case kFormatYCbCr420TP10Ubwc: return "Y_CBCR_420_TP10_UBWC";
+ case kFormatYCbCr420P010Ubwc: return "Y_CBCR_420_P010_UBWC";
+ default: return "UNKNOWN";
+ }
+}
+
+BufferLayout GetBufferLayout(LayerBufferFormat format) {
+ switch (format) {
+ case kFormatYCbCr420TP10Ubwc:
+ return kTPTiled;
+ default:
+ return (IsUBWCFormat(format) ? kUBWC : kLinear);
+ }
+}
+
+} // namespace sdm
+
diff --git a/msm8909/sdm/libs/utils/rect.cpp b/msm8909/sdm/libs/utils/rect.cpp
new file mode 100644
index 00000000..84132574
--- /dev/null
+++ b/msm8909/sdm/libs/utils/rect.cpp
@@ -0,0 +1,270 @@
+/*
+* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <math.h>
+#include <utils/rect.h>
+#include <utils/constants.h>
+#include <algorithm>
+
+#define __CLASS__ "RectUtils"
+
+namespace sdm {
+
+bool IsValid(const LayerRect &rect) {
+ return ((rect.bottom > rect.top) && (rect.right > rect.left));
+}
+
+bool IsCongruent(const LayerRect &rect1, const LayerRect &rect2) {
+ return ((rect1.left == rect2.left) &&
+ (rect1.top == rect2.top) &&
+ (rect1.right == rect2.right) &&
+ (rect1.bottom == rect2.bottom));
+}
+
+void LogI(DebugTag debug_tag, const char *prefix, const LayerRect &roi) {
+ DLOGI_IF(debug_tag, "%s: left = %.0f, top = %.0f, right = %.0f, bottom = %.0f",
+ prefix, roi.left, roi.top, roi.right, roi.bottom);
+}
+
+void Log(DebugTag debug_tag, const char *prefix, const LayerRect &roi) {
+ DLOGV_IF(debug_tag, "%s: left = %.0f, top = %.0f, right = %.0f, bottom = %.0f",
+ prefix, roi.left, roi.top, roi.right, roi.bottom);
+}
+
+void Normalize(const uint32_t &align_x, const uint32_t &align_y, LayerRect *rect) {
+ rect->left = ROUND_UP_ALIGN_UP(rect->left, align_x);
+ rect->right = ROUND_UP_ALIGN_DOWN(rect->right, align_x);
+ rect->top = ROUND_UP_ALIGN_UP(rect->top, align_y);
+ rect->bottom = ROUND_UP_ALIGN_DOWN(rect->bottom, align_y);
+}
+
+LayerRect Intersection(const LayerRect &rect1, const LayerRect &rect2) {
+ LayerRect res;
+
+ if (!IsValid(rect1) || !IsValid(rect2)) {
+ return LayerRect();
+ }
+
+ res.left = std::max(rect1.left, rect2.left);
+ res.top = std::max(rect1.top, rect2.top);
+ res.right = std::min(rect1.right, rect2.right);
+ res.bottom = std::min(rect1.bottom, rect2.bottom);
+
+ if (!IsValid(res)) {
+ return LayerRect();
+ }
+
+ return res;
+}
+
+LayerRect Reposition(const LayerRect &rect, const int &x_offset, const int &y_offset) {
+ LayerRect res;
+
+ if (!IsValid(rect)) {
+ return LayerRect();
+ }
+
+ res.left = rect.left + FLOAT(x_offset);
+ res.top = rect.top + FLOAT(y_offset);
+ res.right = rect.right + FLOAT(x_offset);
+ res.bottom = rect.bottom + FLOAT(y_offset);
+
+ return res;
+}
+
+// Not a geometrical rect deduction. Deducts rect2 from rect1 only if it results a single rect
+LayerRect Subtract(const LayerRect &rect1, const LayerRect &rect2) {
+ LayerRect res;
+
+ res = rect1;
+
+ if ((rect1.left == rect2.left) && (rect1.right == rect2.right)) {
+ if ((rect1.top == rect2.top) && (rect2.bottom <= rect1.bottom)) {
+ res.top = rect2.bottom;
+ } else if ((rect1.bottom == rect2.bottom) && (rect2.top >= rect1.top)) {
+ res.bottom = rect2.top;
+ }
+ } else if ((rect1.top == rect2.top) && (rect1.bottom == rect2.bottom)) {
+ if ((rect1.left == rect2.left) && (rect2.right <= rect1.right)) {
+ res.left = rect2.right;
+ } else if ((rect1.right == rect2.right) && (rect2.left >= rect1.left)) {
+ res.right = rect2.left;
+ }
+ }
+
+ return res;
+}
+
+LayerRect Union(const LayerRect &rect1, const LayerRect &rect2) {
+ LayerRect res;
+
+ if (!IsValid(rect1) && !IsValid(rect2)) {
+ return LayerRect();
+ }
+
+ if (!IsValid(rect1)) {
+ return rect2;
+ }
+
+ if (!IsValid(rect2)) {
+ return rect1;
+ }
+
+ res.left = std::min(rect1.left, rect2.left);
+ res.top = std::min(rect1.top, rect2.top);
+ res.right = std::max(rect1.right, rect2.right);
+ res.bottom = std::max(rect1.bottom, rect2.bottom);
+
+ return res;
+}
+
+void SplitLeftRight(const LayerRect &in_rect, uint32_t split_count, uint32_t align_x,
+ bool flip_horizontal, LayerRect *out_rects) {
+ LayerRect rect_temp = in_rect;
+
+ uint32_t split_width = UINT32(rect_temp.right - rect_temp.left) / split_count;
+ float aligned_width = FLOAT(CeilToMultipleOf(split_width, align_x));
+
+ for (uint32_t count = 0; count < split_count; count++) {
+ float aligned_right = rect_temp.left + aligned_width;
+ out_rects[count].left = rect_temp.left;
+ out_rects[count].right = std::min(rect_temp.right, aligned_right);
+ out_rects[count].top = rect_temp.top;
+ out_rects[count].bottom = rect_temp.bottom;
+
+ rect_temp.left = out_rects[count].right;
+
+ Log(kTagRotator, "SplitLeftRight", out_rects[count]);
+ }
+
+ // If we have a horizontal flip, then we should be splitting the source from right to left
+ // to ensure that the right split will have an aligned width that matches the alignment on the
+ // destination.
+ if (flip_horizontal && split_count > 1) {
+ out_rects[0].right = out_rects[0].left + (out_rects[1].right - out_rects[1].left);
+ out_rects[1].left = out_rects[0].right;
+ Log(kTagRotator, "Adjusted Left", out_rects[0]);
+ Log(kTagRotator, "Adjusted Right", out_rects[1]);
+ }
+}
+
+void SplitTopBottom(const LayerRect &in_rect, uint32_t split_count, uint32_t align_y,
+ bool flip_horizontal, LayerRect *out_rects) {
+ LayerRect rect_temp = in_rect;
+
+ uint32_t split_height = UINT32(rect_temp.bottom - rect_temp.top) / split_count;
+ float aligned_height = FLOAT(CeilToMultipleOf(split_height, align_y));
+
+ for (uint32_t count = 0; count < split_count; count++) {
+ float aligned_bottom = rect_temp.top + aligned_height;
+ out_rects[count].top = rect_temp.top;
+ out_rects[count].bottom = std::min(rect_temp.bottom, aligned_bottom);
+ out_rects[count].left = rect_temp.left;
+ out_rects[count].right = rect_temp.right;
+
+ rect_temp.top = out_rects[count].bottom;
+
+ Log(kTagRotator, "SplitTopBottom", out_rects[count]);
+ }
+
+ // If we have a horizontal flip, then we should be splitting the destination from bottom to top
+ // to ensure that the bottom split's y-offset is aligned correctly after we swap the destinations
+ // while accounting for the flip.
+ if (flip_horizontal && split_count > 1) {
+ out_rects[0].bottom = out_rects[0].top + (out_rects[1].bottom - out_rects[1].top);
+ out_rects[1].top = out_rects[0].bottom;
+ Log(kTagRotator, "Adjusted Top", out_rects[0]);
+ Log(kTagRotator, "Adjusted Bottom", out_rects[1]);
+ }
+}
+
+void MapRect(const LayerRect &src_domain, const LayerRect &dst_domain, const LayerRect &in_rect,
+ LayerRect *out_rect) {
+ if (!IsValid(src_domain) || !IsValid(dst_domain) || !IsValid(in_rect)) {
+ return;
+ }
+
+ int x_offset = INT(src_domain.left);
+ int y_offset = INT(src_domain.top);
+
+ LayerRect modified_in_rect = Reposition(in_rect, -x_offset, -y_offset);
+ float src_domain_width = src_domain.right - src_domain.left;
+ float src_domain_height = src_domain.bottom - src_domain.top;
+ float dst_domain_width = dst_domain.right - dst_domain.left;
+ float dst_domain_height = dst_domain.bottom - dst_domain.top;
+
+ float width_ratio = dst_domain_width / src_domain_width;
+ float height_ratio = dst_domain_height / src_domain_height;
+
+ out_rect->left = dst_domain.left + (width_ratio * modified_in_rect.left);
+ out_rect->top = dst_domain.top + (height_ratio * modified_in_rect.top);
+ out_rect->right = dst_domain.left + (width_ratio * modified_in_rect.right);
+ out_rect->bottom = dst_domain.top + (height_ratio * modified_in_rect.bottom);
+}
+
+void TransformHV(const LayerRect &src_domain, const LayerRect &in_rect,
+ const LayerTransform &transform, LayerRect *out_rect) {
+ if (!IsValid(src_domain) || !IsValid(in_rect)) {
+ return;
+ }
+
+ float in_width = in_rect.right - in_rect.left;
+ float in_height = in_rect.bottom - in_rect.top;
+ float x_offset = in_rect.left - src_domain.left;
+ float y_offset = in_rect.top - src_domain.top;
+ *out_rect = in_rect;
+
+ if (transform.flip_horizontal) {
+ out_rect->right = src_domain.right - x_offset;
+ out_rect->left = out_rect->right - in_width;
+ }
+
+ if (transform.flip_vertical) {
+ out_rect->bottom = src_domain.bottom - y_offset;
+ out_rect->top = out_rect->bottom - in_height;
+ }
+}
+
+RectOrientation GetOrientation(const LayerRect &in_rect) {
+ if (!IsValid(in_rect)) {
+ return kOrientationUnknown;
+ }
+
+ float input_width = in_rect.right - in_rect.left;
+ float input_height = in_rect.bottom - in_rect.top;
+
+ if (input_width < input_height) {
+ return kOrientationPortrait;
+ }
+
+ return kOrientationLandscape;
+}
+
+} // namespace sdm
+
diff --git a/msm8909/sdm/libs/utils/sys.cpp b/msm8909/sdm/libs/utils/sys.cpp
new file mode 100644
index 00000000..f5e0f291
--- /dev/null
+++ b/msm8909/sdm/libs/utils/sys.cpp
@@ -0,0 +1,95 @@
+/*
+* Copyright (c) 2015, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <utils/sys.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string>
+
+#define __CLASS__ "Sys"
+
+namespace sdm {
+
+#ifndef SDM_VIRTUAL_DRIVER
+
+int PthreadCancel(pthread_t /* thread */) {
+ return 0;
+}
+
+// Pointer to actual driver interfaces.
+Sys::ioctl Sys::ioctl_ = ::ioctl;
+Sys::access Sys::access_ = ::access;
+Sys::open Sys::open_ = ::open;
+Sys::close Sys::close_ = ::close;
+Sys::poll Sys::poll_ = ::poll;
+Sys::pread Sys::pread_ = ::pread;
+Sys::pwrite Sys::pwrite_ = ::pwrite;
+Sys::pthread_cancel Sys::pthread_cancel_ = PthreadCancel;
+Sys::dup Sys::dup_ = ::dup;
+Sys::read Sys::read_ = ::read;
+Sys::write Sys::write_ = ::write;
+Sys::eventfd Sys::eventfd_ = ::eventfd;
+
+bool Sys::getline_(fstream &fs, std::string &line) {
+ return std::getline(fs, line) ? true : false;
+}
+
+#endif // SDM_VIRTUAL_DRIVER
+
+DynLib::~DynLib() {
+ Close();
+}
+
+bool DynLib::Open(const char *lib_name) {
+ Close();
+ lib_ = ::dlopen(lib_name, RTLD_NOW);
+
+ return (lib_ != NULL);
+}
+
+bool DynLib::Sym(const char *func_name, void **func_ptr) {
+ if (lib_) {
+ *func_ptr = ::dlsym(lib_, func_name);
+ } else {
+ *func_ptr = NULL;
+ }
+
+ return (*func_ptr != NULL);
+}
+
+void DynLib::Close() {
+ if (lib_) {
+ ::dlclose(lib_);
+ lib_ = NULL;
+ }
+}
+
+} // namespace sdm
+
diff --git a/msm8909/sdm/libs/utils/utils.cpp b/msm8909/sdm/libs/utils/utils.cpp
new file mode 100644
index 00000000..07211a1a
--- /dev/null
+++ b/msm8909/sdm/libs/utils/utils.cpp
@@ -0,0 +1,71 @@
+/*
+* Copyright (c) 2016 - 2017, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <unistd.h>
+#include <math.h>
+#include <utils/sys.h>
+#include <utils/utils.h>
+
+#include <algorithm>
+
+#define __CLASS__ "Utils"
+
+namespace sdm {
+
+float gcd(float a, float b) {
+ if (a < b) {
+ std::swap(a, b);
+ }
+
+ while (b != 0) {
+ float tmp = b;
+ b = fmodf(a, b);
+ a = tmp;
+ }
+
+ return a;
+}
+
+float lcm(float a, float b) {
+ return (a * b) / gcd(a, b);
+}
+
+void CloseFd(int *fd) {
+ if (*fd >= 0) {
+ Sys::close_(*fd);
+ *fd = -1;
+ }
+}
+
+DriverType GetDriverType() {
+ const char *fb_caps = "/sys/devices/virtual/graphics/fb0/mdp/caps";
+ // 0 - File exists
+ return Sys::access_(fb_caps, F_OK) ? DriverType::DRM : DriverType::FB;
+}
+} // namespace sdm