Home | History | Annotate | Download | only in hwc
      1 /*
      2 * Copyright (c) 2014 - 2016, 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 <utils/constants.h>
     31 #include <utils/debug.h>
     32 #include <sync/sync.h>
     33 #include <stdarg.h>
     34 #include <gr.h>
     35 
     36 #include "hwc_display_virtual.h"
     37 #include "hwc_debugger.h"
     38 
     39 #define __CLASS__ "HWCDisplayVirtual"
     40 
     41 namespace sdm {
     42 
     43 int HWCDisplayVirtual::Create(CoreInterface *core_intf, hwc_procs_t const **hwc_procs,
     44                               uint32_t primary_width, uint32_t primary_height,
     45                               hwc_display_contents_1_t *content_list,
     46                               HWCDisplay **hwc_display) {
     47   int status = 0;
     48   HWCDisplayVirtual *hwc_display_virtual = new HWCDisplayVirtual(core_intf, hwc_procs);
     49   uint32_t virtual_width = 0, virtual_height = 0;
     50 
     51   status = hwc_display_virtual->Init();
     52   if (status) {
     53     delete hwc_display_virtual;
     54     return status;
     55   }
     56 
     57   status = hwc_display_virtual->SetPowerMode(HWC_POWER_MODE_NORMAL);
     58   if (status) {
     59     Destroy(hwc_display_virtual);
     60     return status;
     61   }
     62 
     63   // TODO(user): Need to update resolution(and not aligned resolution) on writeback.
     64   status = hwc_display_virtual->SetOutputSliceFromMetadata(content_list);
     65   if (status) {
     66     Destroy(hwc_display_virtual);
     67     return status;
     68   }
     69 
     70   hwc_display_virtual->GetPanelResolution(&virtual_width, &virtual_height);
     71 
     72   if (content_list->numHwLayers < 1) {
     73     Destroy(hwc_display_virtual);
     74     return -1;
     75   }
     76 
     77   hwc_layer_1_t &fb_layer = content_list->hwLayers[content_list->numHwLayers-1];
     78   int fb_width = fb_layer.displayFrame.right - fb_layer.displayFrame.left;
     79   int fb_height = fb_layer.displayFrame.bottom - fb_layer.displayFrame.top;
     80 
     81   status = hwc_display_virtual->SetFrameBufferResolution(UINT32(fb_width), UINT32(fb_height));
     82 
     83   if (status) {
     84     Destroy(hwc_display_virtual);
     85     return status;
     86   }
     87 
     88   *hwc_display = static_cast<HWCDisplay *>(hwc_display_virtual);
     89 
     90   return 0;
     91 }
     92 
     93 void HWCDisplayVirtual::Destroy(HWCDisplay *hwc_display) {
     94   hwc_display->Deinit();
     95   delete hwc_display;
     96 }
     97 
     98 HWCDisplayVirtual::HWCDisplayVirtual(CoreInterface *core_intf, hwc_procs_t const **hwc_procs)
     99   : HWCDisplay(core_intf, hwc_procs, kVirtual, HWC_DISPLAY_VIRTUAL, false),
    100     dump_output_layer_(false), output_buffer_(NULL) {
    101 }
    102 
    103 int HWCDisplayVirtual::Init() {
    104   output_buffer_ = new LayerBuffer();
    105   if (!output_buffer_) {
    106     return -ENOMEM;
    107   }
    108 
    109   return HWCDisplay::Init();
    110 }
    111 
    112 int HWCDisplayVirtual::Deinit() {
    113   int status = 0;
    114 
    115   status = HWCDisplay::Deinit();
    116   if (status) {
    117     return status;
    118   }
    119 
    120   if (output_buffer_) {
    121     delete output_buffer_;
    122   }
    123 
    124   return status;
    125 }
    126 
    127 int HWCDisplayVirtual::Prepare(hwc_display_contents_1_t *content_list) {
    128   int status = 0;
    129 
    130   status = SetOutputSliceFromMetadata(content_list);
    131   if (status) {
    132     return status;
    133   }
    134 
    135   if (display_paused_) {
    136     MarkLayersForGPUBypass(content_list);
    137     return status;
    138   }
    139 
    140   status = AllocateLayerStack(content_list);
    141   if (status) {
    142     return status;
    143   }
    144 
    145   status = SetOutputBuffer(content_list);
    146   if (status) {
    147     return status;
    148   }
    149 
    150   status = PrePrepareLayerStack(content_list);
    151   if (status) {
    152     return status;
    153   }
    154 
    155   status = PrepareLayerStack(content_list);
    156   if (status) {
    157     return status;
    158   }
    159 
    160   return 0;
    161 }
    162 
    163 int HWCDisplayVirtual::Commit(hwc_display_contents_1_t *content_list) {
    164   int status = 0;
    165   if (display_paused_) {
    166     DisplayError error = display_intf_->Flush();
    167     if (error != kErrorNone) {
    168       DLOGE("Flush failed. Error = %d", error);
    169     }
    170     return status;
    171   }
    172 
    173   status = HWCDisplay::CommitLayerStack(content_list);
    174   if (status) {
    175     return status;
    176   }
    177 
    178   DumpOutputBuffer(content_list);
    179 
    180   status = HWCDisplay::PostCommitLayerStack(content_list);
    181   if (status) {
    182     return status;
    183   }
    184 
    185   return 0;
    186 }
    187 
    188 int HWCDisplayVirtual::SetOutputSliceFromMetadata(hwc_display_contents_1_t *content_list) {
    189   const private_handle_t *output_handle =
    190         static_cast<const private_handle_t *>(content_list->outbuf);
    191   DisplayError error = kErrorNone;
    192   int status = 0;
    193 
    194   if (output_handle) {
    195     int output_handle_format = output_handle->format;
    196     if (output_handle_format == HAL_PIXEL_FORMAT_RGBA_8888) {
    197       output_handle_format = HAL_PIXEL_FORMAT_RGBX_8888;
    198     }
    199 
    200     LayerBufferFormat format = GetSDMFormat(output_handle_format, output_handle->flags);
    201     if (format == kFormatInvalid) {
    202       return -EINVAL;
    203     }
    204 
    205     int active_width;
    206     int active_height;
    207 
    208     AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(output_handle, active_width,
    209                                                           active_height);
    210 
    211     if ((active_width != INT(output_buffer_->width)) ||
    212         (active_height!= INT(output_buffer_->height)) ||
    213         (format != output_buffer_->format)) {
    214       // Populate virtual display attributes based on displayFrame of FBT.
    215       // For DRC, use width and height populated in metadata (unaligned values)
    216       // for setting attributes of virtual display. This is needed because if
    217       // we use aligned width and height, scaling will be required for FBT layer.
    218       DisplayConfigVariableInfo variable_info;
    219       hwc_layer_1_t &fbt_layer = content_list->hwLayers[content_list->numHwLayers-1];
    220       hwc_rect_t &frame = fbt_layer.displayFrame;
    221       int fbt_width = frame.right - frame.left;
    222       int fbt_height = frame.bottom - frame.top;
    223       const MetaData_t *meta_data = reinterpret_cast<MetaData_t *>(output_handle->base_metadata);
    224       if (meta_data && meta_data->operation & UPDATE_BUFFER_GEOMETRY) {
    225         variable_info.x_pixels = UINT32(meta_data->bufferDim.sliceWidth);
    226         variable_info.y_pixels = UINT32(meta_data->bufferDim.sliceHeight);
    227       } else {
    228         variable_info.x_pixels = UINT32(fbt_width);
    229         variable_info.y_pixels = UINT32(fbt_height);
    230       }
    231       // TODO(user): Need to get the framerate of primary display and update it.
    232       variable_info.fps = 60;
    233 
    234       error = display_intf_->SetActiveConfig(&variable_info);
    235       if (error != kErrorNone) {
    236         return -EINVAL;
    237       }
    238 
    239       status = SetOutputBuffer(content_list);
    240       if (status) {
    241         return status;
    242       }
    243     }
    244   }
    245 
    246   return 0;
    247 }
    248 
    249 int HWCDisplayVirtual::SetOutputBuffer(hwc_display_contents_1_t *content_list) {
    250   int status = 0;
    251 
    252   const private_handle_t *output_handle =
    253         static_cast<const private_handle_t *>(content_list->outbuf);
    254 
    255   // Fill output buffer parameters (width, height, format, plane information, fence)
    256   output_buffer_->acquire_fence_fd = content_list->outbufAcquireFenceFd;
    257 
    258   if (output_handle) {
    259     int output_handle_format = output_handle->format;
    260 
    261     if (output_handle_format == HAL_PIXEL_FORMAT_RGBA_8888) {
    262       output_handle_format = HAL_PIXEL_FORMAT_RGBX_8888;
    263     }
    264 
    265     output_buffer_->format = GetSDMFormat(output_handle_format, output_handle->flags);
    266 
    267     if (output_buffer_->format == kFormatInvalid) {
    268       return -EINVAL;
    269     }
    270 
    271     int output_buffer_width, output_buffer_height;
    272     AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(output_handle, output_buffer_width,
    273                                                           output_buffer_height);
    274 
    275     output_buffer_->width = UINT32(output_buffer_width);
    276     output_buffer_->height = UINT32(output_buffer_height);
    277     output_buffer_->flags.secure = 0;
    278     output_buffer_->flags.video = 0;
    279 
    280     // TZ Protected Buffer - L1
    281     if (output_handle->flags & private_handle_t::PRIV_FLAGS_SECURE_BUFFER) {
    282       output_buffer_->flags.secure = 1;
    283     }
    284 
    285     // ToDo: Need to extend for non-RGB formats
    286     output_buffer_->planes[0].fd = output_handle->fd;
    287     output_buffer_->planes[0].offset = output_handle->offset;
    288     output_buffer_->planes[0].stride = UINT32(output_handle->width);
    289   }
    290 
    291   layer_stack_.output_buffer = output_buffer_;
    292 
    293   return status;
    294 }
    295 
    296 void HWCDisplayVirtual::DumpOutputBuffer(hwc_display_contents_1_t *content_list) {
    297   const private_handle_t *output_handle = (const private_handle_t *)(content_list->outbuf);
    298   char dir_path[PATH_MAX];
    299 
    300   if (!dump_frame_count_ || flush_ || !dump_output_layer_) {
    301     return;
    302   }
    303 
    304   snprintf(dir_path, sizeof(dir_path), "/data/misc/display/frame_dump_%s", GetDisplayString());
    305 
    306   if (mkdir(dir_path, 777) != 0 && errno != EEXIST) {
    307     DLOGW("Failed to create %s directory errno = %d, desc = %s", dir_path, errno, strerror(errno));
    308     return;
    309   }
    310 
    311   // if directory exists already, need to explicitly change the permission.
    312   if (errno == EEXIST && chmod(dir_path, 0777) != 0) {
    313     DLOGW("Failed to change permissions on %s directory", dir_path);
    314     return;
    315   }
    316 
    317   if (output_handle && output_handle->base) {
    318     char dump_file_name[PATH_MAX];
    319     size_t result = 0;
    320 
    321     if (content_list->outbufAcquireFenceFd >= 0) {
    322       int error = sync_wait(content_list->outbufAcquireFenceFd, 1000);
    323       if (error < 0) {
    324         DLOGW("sync_wait error errno = %d, desc = %s", errno,  strerror(errno));
    325         return;
    326       }
    327     }
    328 
    329     snprintf(dump_file_name, sizeof(dump_file_name), "%s/output_layer_%dx%d_%s_frame%d.raw",
    330              dir_path, output_handle->width, output_handle->height,
    331              GetHALPixelFormatString(output_handle->format), dump_frame_index_);
    332 
    333     FILE* fp = fopen(dump_file_name, "w+");
    334     if (fp) {
    335       result = fwrite(reinterpret_cast<void *>(output_handle->base), output_handle->size, 1, fp);
    336       fclose(fp);
    337     }
    338 
    339     DLOGI("Frame Dump of %s is %s", dump_file_name, result ? "Successful" : "Failed");
    340   }
    341 }
    342 
    343 void HWCDisplayVirtual::SetFrameDumpConfig(uint32_t count, uint32_t bit_mask_layer_type) {
    344   HWCDisplay::SetFrameDumpConfig(count, bit_mask_layer_type);
    345   dump_output_layer_ = ((bit_mask_layer_type & (1 << OUTPUT_LAYER_DUMP)) != 0);
    346 
    347   DLOGI("output_layer_dump_enable %d", dump_output_layer_);
    348 }
    349 
    350 }  // namespace sdm
    351 
    352