blob: e600b799eb26acd169abd60bbeb6dcb7ca58f108 [file] [log] [blame]
/*
* 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 <dlfcn.h>
#include <utils/debug.h>
#include "scalar_helper.h"
#define __CLASS__ "ScalarHelper"
namespace sde {
#ifdef USES_SCALAR
ScalarHelper::ScalarHelper()
: scalar_library_name_("libscalar.so"), configure_scale_api_("configureScale"),
lib_scalar_(NULL), configure_scale_(NULL) {
}
DisplayError ScalarHelper::Init() {
lib_scalar_ = dlopen(scalar_library_name_, RTLD_NOW);
if (lib_scalar_) {
void **scalar_func = reinterpret_cast<void **>(&configure_scale_);
*scalar_func = ::dlsym(lib_scalar_, configure_scale_api_);
if (!configure_scale_) {
DLOGE("Unable to find symbol for %s API!", configure_scale_api_);
dlclose(lib_scalar_);
return kErrorUndefined;
}
} else {
DLOGW("Unable to load %s !", scalar_library_name_);
return kErrorNotSupported;
}
return kErrorNone;
}
void ScalarHelper::Deinit() {
if (lib_scalar_) {
dlclose(lib_scalar_);
}
}
// Helper functions
void ScalarHelper::SetPipeInfo(const HWPipeInfo &hw_pipe, scalar::PipeInfo *pipe) {
pipe->id = hw_pipe.pipe_id;
pipe->horz_deci = hw_pipe.horizontal_decimation;
pipe->vert_deci = hw_pipe.vertical_decimation;
pipe->src_rect.x = UINT32(hw_pipe.src_roi.left);
pipe->src_rect.y = UINT32(hw_pipe.src_roi.top);
pipe->src_rect.w = UINT32(hw_pipe.src_roi.right) - pipe->src_rect.x;
pipe->src_rect.h = UINT32(hw_pipe.src_roi.bottom) - pipe->src_rect.y;
pipe->dst_rect.x = UINT32(hw_pipe.dst_roi.left);
pipe->dst_rect.y = UINT32(hw_pipe.dst_roi.top);
pipe->dst_rect.w = UINT32(hw_pipe.dst_roi.right) - pipe->dst_rect.x;
pipe->dst_rect.h = UINT32(hw_pipe.dst_roi.bottom) - pipe->dst_rect.y;
}
void ScalarHelper::UpdateSrcRoi(const scalar::PipeInfo &pipe, HWPipeInfo *hw_pipe) {
hw_pipe->src_roi.left = FLOAT(pipe.src_rect.x);
hw_pipe->src_roi.top = FLOAT(pipe.src_rect.y);
hw_pipe->src_roi.right = FLOAT(pipe.src_rect.x + pipe.src_rect.w);
hw_pipe->src_roi.bottom = FLOAT(pipe.src_rect.y + pipe.src_rect.h);
}
void ScalarHelper::SetScaleData(const scalar::PipeInfo &pipe, ScaleData *scale_data) {
scalar::Scale *scale = pipe.scale_data;
scale_data->src_width = pipe.src_width;
scale_data->src_height = pipe.src_height;
scale_data->enable_pixel_ext = scale->enable_pxl_ext;
for (int i = 0; i < 4; i++) {
HWPlane &plane = scale_data->plane[i];
plane.init_phase_x = scale->init_phase_x[i];
plane.phase_step_x = scale->phase_step_x[i];
plane.init_phase_y = scale->init_phase_y[i];
plane.phase_step_y = scale->phase_step_y[i];
plane.left.extension = scale->left.extension[i];
plane.left.overfetch = scale->left.overfetch[i];
plane.left.repeat = scale->left.repeat[i];
plane.top.extension = scale->top.extension[i];
plane.top.overfetch = scale->top.overfetch[i];
plane.top.repeat = scale->top.repeat[i];
plane.right.extension = scale->right.extension[i];
plane.right.overfetch = scale->right.overfetch[i];
plane.right.repeat = scale->right.repeat[i];
plane.bottom.extension = scale->bottom.extension[i];
plane.bottom.overfetch = scale->bottom.overfetch[i];
plane.bottom.repeat = scale->bottom.repeat[i];
plane.roi_width = scale->roi_width[i];
}
}
uint32_t ScalarHelper::GetScalarFormat(LayerBufferFormat source) {
uint32_t format = scalar::UNKNOWN_FORMAT;
switch (source) {
case kFormatARGB8888: format = scalar::ARGB_8888; break;
case kFormatRGBA8888: format = scalar::RGBA_8888; break;
case kFormatBGRA8888: format = scalar::BGRA_8888; break;
case kFormatXRGB8888: format = scalar::XRGB_8888; break;
case kFormatRGBX8888: format = scalar::RGBX_8888; break;
case kFormatBGRX8888: format = scalar::BGRX_8888; break;
case kFormatRGBA5551: format = scalar::RGBA_5551; break;
case kFormatRGBA4444: format = scalar::RGBA_4444; break;
case kFormatRGB888: format = scalar::RGB_888; break;
case kFormatBGR888: format = scalar::BGR_888; break;
case kFormatRGB565: format = scalar::RGB_565; break;
case kFormatYCbCr420Planar: format = scalar::Y_CB_CR_H2V2; break;
case kFormatYCrCb420Planar: format = scalar::Y_CR_CB_H2V2; break;
case kFormatYCbCr420SemiPlanar: format = scalar::Y_CBCR_H2V2; break;
case kFormatYCrCb420SemiPlanar: format = scalar::Y_CRCB_H2V2; break;
case kFormatYCbCr422H1V2SemiPlanar: format = scalar::Y_CBCR_H1V2; break;
case kFormatYCrCb422H1V2SemiPlanar: format = scalar::Y_CRCB_H1V2; break;
case kFormatYCbCr422H2V1SemiPlanar: format = scalar::Y_CBCR_H2V1; break;
case kFormatYCrCb422H2V1SemiPlanar: format = scalar::Y_CRCB_H2V1; break;
case kFormatYCbCr422H2V1Packed: format = scalar::YCBYCR_H2V1; break;
case kFormatYCbCr420SemiPlanarVenus: format = scalar::Y_CBCR_H2V2_VENUS; break;
case kFormatRGBA8888Ubwc: format = scalar::RGBA_8888_UBWC; break;
case kFormatRGBX8888Ubwc: format = scalar::RGBX_8888_UBWC; break;
case kFormatRGB565Ubwc: format = scalar::RGB_565_UBWC; break;
case kFormatYCbCr420SPVenusUbwc: format = scalar::Y_CBCR_H2V2_UBWC; break;
default:
DLOGE("Unsupported source format: %x", source);
break;
}
return format;
}
DisplayError ScalarHelper::ConfigureScale(HWLayers *hw_layers) {
HWLayersInfo &hw_layer_info = hw_layers->info;
for (uint32_t i = 0; i < hw_layer_info.count; i++) {
Layer &layer = hw_layer_info.stack->layers[hw_layer_info.index[i]];
uint32_t width = layer.input_buffer->width;
uint32_t height = layer.input_buffer->height;
LayerBufferFormat format = layer.input_buffer->format;
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;
// Reset scale data
memset(&left_pipe.scale_data, 0, sizeof(ScaleData));
memset(&right_pipe.scale_data, 0, sizeof(ScaleData));
// Prepare data structure for lib scalar
uint32_t flags = 0;
struct scalar::LayerInfo layer_info;
struct scalar::Scale left_scale, right_scale;
if (layer.transform.rotation == 90.0f) {
// Flips will be taken care by rotator, if layer requires 90 rotation
flags |= scalar::SCALAR_SOURCE_ROTATED_90;
} else {
flags |= layer.transform.flip_vertical ? scalar::SCALAR_FLIP_UD : 0;
flags |= layer.transform.flip_horizontal ? scalar::SCALAR_FLIP_LR : 0;
}
for (uint32_t count = 0; count < 2; count++) {
const HWPipeInfo &hw_pipe = (count == 0) ? left_pipe : right_pipe;
HWRotateInfo* hw_rotate_info = &hw_rotator_session->hw_rotate_info[count];
scalar::PipeInfo* pipe = (count == 0) ? &layer_info.left_pipe : &layer_info.right_pipe;
if (hw_rotate_info->valid) {
width = UINT32(hw_rotate_info->dst_roi.right - hw_rotate_info->dst_roi.left);
height = UINT32(hw_rotate_info->dst_roi.bottom - hw_rotate_info->dst_roi.top);
format = hw_rotator_session->output_buffer.format;
}
pipe->flags = flags;
pipe->scale_data = (count == 0) ? &left_scale : &right_scale;
pipe->src_width = width;
pipe->src_height = height;
SetPipeInfo(hw_pipe, pipe);
}
layer_info.src_format = GetScalarFormat(format);
DLOGV_IF(kTagScalar, "Scalar Input[%d] flags=%x format=%x", i, flags, layer_info.src_format);
DLOGV_IF(kTagScalar, "Left: id=%d hD=%d vD=%d srcRect=[%d %d %d %d] dstRect=[%d %d %d %d]",
layer_info.left_pipe.id, layer_info.left_pipe.horz_deci, layer_info.left_pipe.vert_deci,
layer_info.left_pipe.src_rect.x, layer_info.left_pipe.src_rect.y,
layer_info.left_pipe.src_rect.w, layer_info.left_pipe.src_rect.h,
layer_info.left_pipe.dst_rect.x, layer_info.left_pipe.dst_rect.y,
layer_info.left_pipe.dst_rect.w, layer_info.left_pipe.dst_rect.h);
DLOGV_IF(kTagScalar, "Right: id=%d hD=%d vD=%d srcRect=[%d %d %d %d] dstRect=[%d %d %d %d]",
layer_info.right_pipe.id, layer_info.right_pipe.horz_deci, layer_info.right_pipe.vert_deci,
layer_info.right_pipe.src_rect.x, layer_info.right_pipe.src_rect.y,
layer_info.right_pipe.src_rect.w, layer_info.right_pipe.src_rect.h,
layer_info.right_pipe.dst_rect.x, layer_info.right_pipe.dst_rect.y,
layer_info.right_pipe.dst_rect.w, layer_info.right_pipe.dst_rect.h);
// Configure scale data structure
if (configure_scale_(&layer_info) < 0) {
DLOGE("Scalar library failed to configure scale data!");
return kErrorParameters;
}
// Set ScaleData and update SrcRoi in HWPipeInfo
if (left_scale.enable_pxl_ext) {
SetScaleData(layer_info.left_pipe, &left_pipe.scale_data);
UpdateSrcRoi(layer_info.left_pipe, &left_pipe);
}
if (right_scale.enable_pxl_ext) {
SetScaleData(layer_info.right_pipe, &right_pipe.scale_data);
UpdateSrcRoi(layer_info.right_pipe, &right_pipe);
}
}
return kErrorNone;
}
#endif
DisplayError Scalar::CreateScalar(Scalar **scalar) {
Scalar *scalar_obj = NULL;
#ifdef USES_SCALAR
scalar_obj = new ScalarHelper();
if (scalar_obj) {
if (scalar_obj->Init() == kErrorNone) {
goto OnSuccess;
} else {
delete scalar_obj;
}
}
#endif
scalar_obj = new Scalar();
if (!scalar_obj) {
return kErrorMemory;
}
OnSuccess:
*scalar = scalar_obj;
return kErrorNone;
}
void Scalar::Destroy(Scalar *scalar) {
scalar->Deinit();
}
} // namespace sde