1 /* 2 * Copyright (c) 2016 - 2017, The Linux Foundation. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are 6 * met: 7 * * Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * * Redistributions in binary form must reproduce the above 10 * copyright notice, this list of conditions and the following 11 * disclaimer in the documentation and/or other materials provided 12 * with the distribution. 13 * * Neither the name of The Linux Foundation nor the names of its 14 * contributors may be used to endorse or promote products derived 15 * from this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED 18 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 21 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 24 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 25 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 26 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 27 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30 #include <alloc_controller.h> 31 #include <gr.h> 32 #include <gralloc_priv.h> 33 #include <memalloc.h> 34 #include <sync/sync.h> 35 36 #include <TonemapFactory.h> 37 38 #include <core/buffer_allocator.h> 39 40 #include <utils/constants.h> 41 #include <utils/debug.h> 42 #include <utils/formats.h> 43 #include <utils/rect.h> 44 #include <utils/utils.h> 45 46 #include <vector> 47 48 #include "hwc_debugger.h" 49 #include "hwc_tonemapper.h" 50 51 #define __CLASS__ "HWCToneMapper" 52 53 namespace sdm { 54 55 ToneMapSession::~ToneMapSession() { 56 delete gpu_tone_mapper_; 57 gpu_tone_mapper_ = NULL; 58 FreeIntermediateBuffers(); 59 } 60 61 DisplayError ToneMapSession::AllocateIntermediateBuffers(int w, int h, int format, int usage) { 62 for (uint8_t i = 0; i < kNumIntermediateBuffers; i++) { 63 int status = alloc_buffer(&intermediate_buffer_[i], w, h, format, usage); 64 if (status < 0) { 65 FreeIntermediateBuffers(); 66 return kErrorMemory; 67 } 68 } 69 70 return kErrorNone; 71 } 72 73 void ToneMapSession::FreeIntermediateBuffers() { 74 for (uint8_t i = 0; i < kNumIntermediateBuffers; i++) { 75 private_handle_t *buffer = intermediate_buffer_[i]; 76 if (buffer) { 77 // Free the valid fence 78 if (release_fence_fd_[i] >= 0) { 79 CloseFd(&release_fence_fd_[i]); 80 } 81 free_buffer(buffer); 82 intermediate_buffer_[i] = NULL; 83 } 84 } 85 } 86 87 void ToneMapSession::UpdateBuffer(int acquire_fence, LayerBuffer *buffer) { 88 // Acquire fence will be closed by HWC Display. 89 // Fence returned by GPU will be closed in PostCommit. 90 buffer->acquire_fence_fd = acquire_fence; 91 buffer->size = intermediate_buffer_[current_buffer_index_]->size; 92 buffer->planes[0].fd = intermediate_buffer_[current_buffer_index_]->fd; 93 } 94 95 void ToneMapSession::SetReleaseFence(int fd) { 96 CloseFd(&release_fence_fd_[current_buffer_index_]); 97 // Used to give to GPU tonemapper along with input layer fd 98 release_fence_fd_[current_buffer_index_] = dup(fd); 99 } 100 101 void ToneMapSession::SetToneMapConfig(Layer *layer) { 102 // HDR -> SDR is FORWARD and SDR - > HDR is INVERSE 103 tone_map_config_.type = layer->input_buffer.flags.hdr ? TONEMAP_FORWARD : TONEMAP_INVERSE; 104 tone_map_config_.colorPrimaries = layer->input_buffer.color_metadata.colorPrimaries; 105 tone_map_config_.transfer = layer->input_buffer.color_metadata.transfer; 106 tone_map_config_.secure = layer->request.flags.secure; 107 tone_map_config_.format = layer->request.format; 108 } 109 110 bool ToneMapSession::IsSameToneMapConfig(Layer *layer) { 111 LayerBuffer& buffer = layer->input_buffer; 112 private_handle_t *handle = intermediate_buffer_[0]; 113 int tonemap_type = buffer.flags.hdr ? TONEMAP_FORWARD : TONEMAP_INVERSE; 114 115 return ((tonemap_type == tone_map_config_.type) && 116 (buffer.color_metadata.colorPrimaries == tone_map_config_.colorPrimaries) && 117 (buffer.color_metadata.transfer == tone_map_config_.transfer) && 118 (layer->request.flags.secure == tone_map_config_.secure) && 119 (layer->request.format == tone_map_config_.format) && 120 (layer->request.width == UINT32(handle->unaligned_width)) && 121 (layer->request.height == UINT32(handle->unaligned_height))); 122 } 123 124 int HWCToneMapper::HandleToneMap(hwc_display_contents_1_t *content_list, LayerStack *layer_stack) { 125 uint32_t gpu_count = 0; 126 DisplayError error = kErrorNone; 127 128 for (uint32_t i = 0; i < layer_stack->layers.size(); i++) { 129 uint32_t session_index = 0; 130 Layer *layer = layer_stack->layers.at(i); 131 if (layer->composition == kCompositionGPU) { 132 gpu_count++; 133 } 134 135 if (layer->request.flags.tone_map) { 136 switch (layer->composition) { 137 case kCompositionGPUTarget: 138 if (!gpu_count) { 139 // When all layers are on FrameBuffer and if they do not update in the next draw cycle, 140 // then SDM marks them for SDE Composition because the cached FB layer gets displayed. 141 // GPU count will be 0 in this case. Try to use the existing tone-mapped frame buffer. 142 // No ToneMap/Blit is required. Just update the buffer & acquire fence fd of FB layer. 143 if (!tone_map_sessions_.empty()) { 144 ToneMapSession *fb_tone_map_session = tone_map_sessions_.at(fb_session_index_); 145 fb_tone_map_session->UpdateBuffer(-1 /* acquire_fence */, &layer->input_buffer); 146 fb_tone_map_session->layer_index_ = INT(i); 147 fb_tone_map_session->acquired_ = true; 148 return 0; 149 } 150 } 151 error = AcquireToneMapSession(layer, &session_index); 152 fb_session_index_ = session_index; 153 break; 154 default: 155 error = AcquireToneMapSession(layer, &session_index); 156 break; 157 } 158 159 if (error != kErrorNone) { 160 Terminate(); 161 return -1; 162 } 163 164 ToneMapSession *session = tone_map_sessions_.at(session_index); 165 ToneMap(&content_list->hwLayers[i], layer, session); 166 session->layer_index_ = INT(i); 167 } 168 } 169 170 return 0; 171 } 172 173 void HWCToneMapper::ToneMap(hwc_layer_1_t *hwc_layer, Layer* layer, ToneMapSession *session) { 174 int fence_fd = -1; 175 int acquire_fd = -1; 176 int merged_fd = -1; 177 178 uint8_t buffer_index = session->current_buffer_index_; 179 const private_handle_t *dst_hnd = session->intermediate_buffer_[buffer_index]; 180 const private_handle_t *src_hnd = static_cast<const private_handle_t *>(hwc_layer->handle); 181 182 acquire_fd = dup(layer->input_buffer.acquire_fence_fd); 183 buffer_sync_handler_.SyncMerge(session->release_fence_fd_[buffer_index], acquire_fd, &merged_fd); 184 185 if (acquire_fd >= 0) { 186 CloseFd(&acquire_fd); 187 } 188 189 if (session->release_fence_fd_[buffer_index] >= 0) { 190 CloseFd(&session->release_fence_fd_[buffer_index]); 191 } 192 193 DTRACE_BEGIN("GPU_TM_BLIT"); 194 fence_fd = session->gpu_tone_mapper_->blit(reinterpret_cast<const void *>(dst_hnd), 195 reinterpret_cast<const void *>(src_hnd), merged_fd); 196 DTRACE_END(); 197 198 DumpToneMapOutput(session, &fence_fd); 199 session->UpdateBuffer(fence_fd, &layer->input_buffer); 200 } 201 202 void HWCToneMapper::PostCommit(LayerStack *layer_stack) { 203 auto it = tone_map_sessions_.begin(); 204 while (it != tone_map_sessions_.end()) { 205 uint32_t session_index = UINT32(std::distance(tone_map_sessions_.begin(), it)); 206 ToneMapSession *session = tone_map_sessions_.at(session_index); 207 Layer *layer = layer_stack->layers.at(UINT32(session->layer_index_)); 208 if (session->acquired_) { 209 // Close the fd returned by GPU ToneMapper and set release fence. 210 LayerBuffer &layer_buffer = layer->input_buffer; 211 CloseFd(&layer_buffer.acquire_fence_fd); 212 session->SetReleaseFence(layer_buffer.release_fence_fd); 213 session->acquired_ = false; 214 it++; 215 } else { 216 delete session; 217 it = tone_map_sessions_.erase(it); 218 } 219 } 220 } 221 222 void HWCToneMapper::Terminate() { 223 if (tone_map_sessions_.size()) { 224 while (!tone_map_sessions_.empty()) { 225 delete tone_map_sessions_.back(); 226 tone_map_sessions_.pop_back(); 227 } 228 fb_session_index_ = 0; 229 } 230 } 231 232 void HWCToneMapper::SetFrameDumpConfig(uint32_t count) { 233 DLOGI("Dump FrameConfig count = %d", count); 234 dump_frame_count_ = count; 235 dump_frame_index_ = 0; 236 } 237 238 void HWCToneMapper::DumpToneMapOutput(ToneMapSession *session, int *acquire_fd) { 239 if (!dump_frame_count_) { 240 return; 241 } 242 243 private_handle_t *target_buffer = session->intermediate_buffer_[session->current_buffer_index_]; 244 245 if (*acquire_fd >= 0) { 246 int error = sync_wait(*acquire_fd, 1000); 247 if (error < 0) { 248 DLOGW("sync_wait error errno = %d, desc = %s", errno, strerror(errno)); 249 return; 250 } 251 } 252 253 size_t result = 0; 254 char dump_file_name[PATH_MAX]; 255 snprintf(dump_file_name, sizeof(dump_file_name), "/data/misc/display/frame_dump_primary" 256 "/tonemap_%dx%d_frame%d.raw", target_buffer->width, target_buffer->height, 257 dump_frame_index_); 258 259 FILE* fp = fopen(dump_file_name, "w+"); 260 if (fp) { 261 DLOGI("base addr = %x", target_buffer->base); 262 result = fwrite(reinterpret_cast<void *>(target_buffer->base), target_buffer->size, 1, fp); 263 fclose(fp); 264 } 265 dump_frame_count_--; 266 dump_frame_index_++; 267 CloseFd(acquire_fd); 268 } 269 270 DisplayError HWCToneMapper::AcquireToneMapSession(Layer *layer, uint32_t *session_index) { 271 Color10Bit *grid_entries = NULL; 272 int grid_size = 0; 273 274 if (layer->lut_3d.validGridEntries) { 275 grid_entries = layer->lut_3d.gridEntries; 276 grid_size = INT(layer->lut_3d.gridSize); 277 } 278 279 // When the property sdm.disable_hdr_lut_gen is set, the lutEntries and gridEntries in 280 // the Lut3d will be NULL, clients needs to allocate the memory and set correct 3D Lut 281 // for Tonemapping. 282 if (!layer->lut_3d.lutEntries || !layer->lut_3d.dim) { 283 // Atleast lutEntries must be valid for GPU Tonemapper. 284 DLOGE("Invalid Lut Entries or lut dimension = %d", layer->lut_3d.dim); 285 return kErrorParameters; 286 } 287 288 // Check if we can re-use an existing tone map session. 289 for (uint32_t i = 0; i < tone_map_sessions_.size(); i++) { 290 ToneMapSession *tonemap_session = tone_map_sessions_.at(i); 291 if (!tonemap_session->acquired_ && tonemap_session->IsSameToneMapConfig(layer)) { 292 tonemap_session->current_buffer_index_ = (tonemap_session->current_buffer_index_ + 1) % 293 ToneMapSession::kNumIntermediateBuffers; 294 tonemap_session->acquired_ = true; 295 *session_index = i; 296 return kErrorNone; 297 } 298 } 299 300 ToneMapSession *session = new ToneMapSession(); 301 302 session->SetToneMapConfig(layer); 303 session->gpu_tone_mapper_ = TonemapperFactory_GetInstance(session->tone_map_config_.type, 304 layer->lut_3d.lutEntries, 305 layer->lut_3d.dim, 306 grid_entries, grid_size, 307 session->tone_map_config_.secure); 308 309 if (session->gpu_tone_mapper_ == NULL) { 310 DLOGE("Get Tonemapper failed!"); 311 delete session; 312 return kErrorNotSupported; 313 } 314 315 int status, format; 316 DisplayError error = kErrorNone; 317 int usage = INT(GRALLOC_USAGE_PRIVATE_IOMMU_HEAP | GRALLOC_USAGE_HW_TEXTURE); 318 319 if (layer->request.flags.secure) { 320 usage = INT(GRALLOC_USAGE_PRIVATE_MM_HEAP); 321 usage |= INT(GRALLOC_USAGE_PROTECTED); 322 } 323 324 status = buffer_allocator_.SetBufferInfo(layer->request.format, &format, &usage); 325 error = session->AllocateIntermediateBuffers(INT(layer->request.width), 326 INT(layer->request.height), format, usage); 327 328 if (error != kErrorNone) { 329 DLOGE("Allocation of Intermediate Buffers failed!"); 330 delete session; 331 return error; 332 } 333 334 session->acquired_ = true; 335 tone_map_sessions_.push_back(session); 336 *session_index = UINT32(tone_map_sessions_.size() - 1); 337 338 return kErrorNone; 339 } 340 341 } // namespace sdm 342