sde: Make validate and commit ioctl calls on driver.

1. Update hw framebuffer implementation to compose layers for
   validation with driver.
2. Use atomic commit ioctl to send layers for validation
   and commit on driver.
3. Add different buffer formats handling in hw framebuffer.

Change-Id: I13f9c245c14859c8e2680ef724cfebb59a0d990e
This commit is contained in:
Dileep Marchya
2014-11-04 17:04:50 -08:00
parent f4b46aeb5f
commit aef83adb7e
12 changed files with 308 additions and 253 deletions

View File

@@ -1,14 +1,13 @@
# This flag will be set to true during migration to Snapdragon Display Engine.
TARGET_USES_SDE = false
display-hals := libgralloc libcopybit liblight libmemtrack
display-hals := libgralloc libcopybit liblight libmemtrack libqservice
ifeq ($(TARGET_USES_SDE), true)
sde-libs := displayengine/libs
display-hals += $(sde-libs)/utils $(sde-libs)/core $(sde-libs)/hwc
else
display-hals += libgenlock libhwcomposer liboverlay libqdutils libhdmi
display-hals += libqservice
endif
ifeq ($(call is-vendor-board-platform,QCOM),true)

View File

@@ -76,6 +76,10 @@ enum LayerBufferFormat {
//!< 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)
/* All YUV-Packed formats, Any new format will be added towards end of this group to maintain
backward compatibility.
*/

View File

@@ -43,7 +43,7 @@ namespace sde {
@sa Layer
*/
enum LayerBlending {
kBlendingNone = 0, //!< Blend operation is not specified.
kBlendingNone, //!< Blend operation is not specified.
kBlendingOpaque, //!< Pixel color is expressed using straight alpha in color tuples. It
//!< is constant blend operation. The layer would appear opaque if plane
@@ -217,7 +217,7 @@ struct LayerStack {
uint32_t layer_count; //!< Total number of layers.
LayerStackFlags flags; //!< Flags associated with this layer set.
LayerStack() : output_buffer(NULL) { }
LayerStack() : output_buffer(NULL), layers(NULL), layer_count(0) { }
};
} // namespace sde

View File

@@ -233,6 +233,7 @@ DisplayError DisplayBase::SetDisplayState(DisplayState state) {
switch (state) {
case kStateOff:
hw_layers_.info.count = 0;
comp_manager_->Purge(display_comp_ctx_);
error = hw_intf_->PowerOff(hw_device_);
break;

View File

@@ -53,8 +53,6 @@ extern ssize_t virtual_pread(int fd, void *data, size_t count, off_t offset);
extern FILE* virtual_fopen(const char *fname, const char *mode);
extern int virtual_fclose(FILE* fileptr);
extern ssize_t virtual_getline(char **lineptr, size_t *linelen, FILE *stream);
#endif
namespace sde {
@@ -325,28 +323,18 @@ DisplayError HWFrameBuffer::SetVSyncState(Handle device, bool enable) {
}
DisplayError HWFrameBuffer::Validate(Handle device, HWLayers *hw_layers) {
DisplayError error = kErrorNone;
HWContext *hw_context = reinterpret_cast<HWContext *>(device);
return kErrorNone;
}
DisplayError HWFrameBuffer::Commit(Handle device, HWLayers *hw_layers) {
HWContext *hw_context = reinterpret_cast<HWContext *>(device);
hw_context->ResetMDPCommit();
HWLayersInfo &hw_layer_info = hw_layers->info;
// Assuming left & right both pipe are required, maximum possible number of overlays.
uint32_t max_overlay_count = hw_layer_info.count * 2;
int acquire_fences[hw_layer_info.count]; // NOLINT
int release_fence = -1;
int retire_fence = -1;
uint32_t acquire_fence_count = 0;
STRUCT_VAR_ARRAY(mdp_overlay, overlay_array, max_overlay_count);
STRUCT_VAR_ARRAY(msmfb_overlay_data, data_array, max_overlay_count);
LayerStack *stack = hw_layer_info.stack;
uint32_t num_overlays = 0;
mdp_layer_commit_v1 &mdp_commit = hw_context->mdp_commit.commit_v1;
mdp_input_layer *mdp_layers = hw_context->mdp_layers;
uint32_t &mdp_layer_count = mdp_commit.input_layer_cnt;
for (uint32_t i = 0; i < hw_layer_info.count; i++) {
uint32_t layer_index = hw_layer_info.index[i];
Layer &layer = stack->layers[layer_index];
@@ -355,110 +343,135 @@ DisplayError HWFrameBuffer::Commit(Handle device, HWLayers *hw_layers) {
HWPipeInfo &left_pipe = config.left_pipe;
// Configure left pipe
mdp_overlay &left_overlay = overlay_array[num_overlays];
msmfb_overlay_data &left_data = data_array[num_overlays];
mdp_input_layer &mdp_layer_left = mdp_layers[mdp_layer_count];
mdp_layer_left.alpha = layer.plane_alpha;
mdp_layer_left.z_order = static_cast<uint16_t>(i);
mdp_layer_left.transp_mask = 0xffffffff;
SetBlending(layer.blending, &mdp_layer_left.blend_op);
SetRect(left_pipe.src_roi, &mdp_layer_left.src_rect);
SetRect(left_pipe.dst_roi, &mdp_layer_left.dst_rect);
mdp_layer_left.pipe_ndx = left_pipe.pipe_id;
left_overlay.id = left_pipe.pipe_id;
left_overlay.flags |= MDP_BLEND_FG_PREMULT;
left_overlay.transp_mask = 0xffffffff;
left_overlay.z_order = i;
left_overlay.alpha = layer.plane_alpha;
left_overlay.src.width = input_buffer->planes[0].stride;
left_overlay.src.height = input_buffer->height;
SetBlending(&left_overlay.blend_op, layer.blending);
SetFormat(&left_overlay.src.format, layer.input_buffer->format);
SetRect(&left_overlay.src_rect, left_pipe.src_roi);
SetRect(&left_overlay.dst_rect, left_pipe.dst_roi);
left_data.id = left_pipe.pipe_id;
left_data.data.memory_id = input_buffer->planes[0].fd;
left_data.data.offset = input_buffer->planes[0].offset;
mdp_layer_buffer &mdp_buffer_left = mdp_layer_left.buffer;
mdp_buffer_left.width = input_buffer->width;
mdp_buffer_left.height = input_buffer->height;
num_overlays++;
error = SetFormat(layer.input_buffer->format, &mdp_buffer_left.format);
if (error != kErrorNone) {
return error;
}
mdp_layer_count++;
// Configure right pipe
if (config.is_right_pipe) {
HWPipeInfo &right_pipe = config.right_pipe;
mdp_overlay &right_overlay = overlay_array[num_overlays];
msmfb_overlay_data &right_data = data_array[num_overlays];
mdp_input_layer &mdp_layer_right = mdp_layers[mdp_layer_count];
right_overlay = left_overlay;
right_data = left_data;
right_overlay.id = right_pipe.pipe_id;
right_data.id = right_pipe.pipe_id;
SetRect(&right_overlay.src_rect, right_pipe.src_roi);
SetRect(&right_overlay.dst_rect, right_pipe.dst_roi);
mdp_layer_right = mdp_layer_left;
num_overlays++;
}
mdp_layer_right.pipe_ndx = right_pipe.pipe_id;
SetRect(right_pipe.src_roi, &mdp_layer_right.src_rect);
SetRect(right_pipe.dst_roi, &mdp_layer_right.dst_rect);
if (input_buffer->acquire_fence_fd >= 0) {
acquire_fences[acquire_fence_count] = input_buffer->acquire_fence_fd;
acquire_fence_count++;
mdp_layer_count++;
}
}
mdp_overlay *overlay_list[num_overlays];
msmfb_overlay_data *data_list[num_overlays];
for (uint32_t i = 0; i < num_overlays; i++) {
overlay_list[i] = &overlay_array[i];
data_list[i] = &data_array[i];
mdp_commit.flags |= MDP_VALIDATE_LAYER;
if (ioctl_(hw_context->device_fd, MSMFB_ATOMIC_COMMIT, &hw_context->mdp_commit) == -1) {
IOCTL_LOGE("validate:"MSMFB_ATOMIC_COMMIT);
return kErrorHardware;
}
// TODO(user): Replace with Atomic commit call.
STRUCT_VAR(mdp_atomic_commit, atomic_commit);
atomic_commit.overlay_list = overlay_list;
atomic_commit.data_list = data_list;
atomic_commit.num_overlays = num_overlays;
atomic_commit.buf_sync.acq_fen_fd = acquire_fences;
atomic_commit.buf_sync.acq_fen_fd_cnt = acquire_fence_count;
atomic_commit.buf_sync.rel_fen_fd = &release_fence;
atomic_commit.buf_sync.retire_fen_fd = &retire_fence;
atomic_commit.buf_sync.flags = MDP_BUF_SYNC_FLAG_RETIRE_FENCE;
return kErrorNone;
}
if (UNLIKELY(ioctl_(hw_context->device_fd, MSMFB_ATOMIC_COMMIT, &atomic_commit) == -1)) {
IOCTL_LOGE(MSMFB_ATOMIC_COMMIT);
DisplayError HWFrameBuffer::Commit(Handle device, HWLayers *hw_layers) {
HWContext *hw_context = reinterpret_cast<HWContext *>(device);
HWLayersInfo &hw_layer_info = hw_layers->info;
LayerStack *stack = hw_layer_info.stack;
mdp_layer_commit_v1 &mdp_commit = hw_context->mdp_commit.commit_v1;
mdp_input_layer *mdp_layers = hw_context->mdp_layers;
uint32_t mdp_layer_index = 0;
for (uint32_t i = 0; i < hw_layer_info.count; i++) {
uint32_t layer_index = hw_layer_info.index[i];
LayerBuffer *input_buffer = stack->layers[layer_index].input_buffer;
uint32_t split_count = hw_layers->config[i].is_right_pipe ? 2 : 1;
for (uint32_t j = 0; j < split_count; j++) {
mdp_layer_buffer &mdp_buffer = mdp_layers[mdp_layer_index].buffer;
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;
mdp_buffer.planes[0].stride = input_buffer->planes[0].stride;
} else {
DLOGW("Invalid buffer fd, setting plane count to 0");
mdp_buffer.plane_count = 0;
}
mdp_buffer.fence = input_buffer->acquire_fence_fd;
mdp_layer_index++;
}
}
mdp_commit.flags |= MDP_COMMIT_RETIRE_FENCE;
mdp_commit.flags &= ~MDP_VALIDATE_LAYER;
if (ioctl_(hw_context->device_fd, MSMFB_ATOMIC_COMMIT, &hw_context->mdp_commit) == -1) {
IOCTL_LOGE("commit:"MSMFB_ATOMIC_COMMIT);
return kErrorHardware;
}
// MDP returns only one release fence for the entire layer stack. Duplicate this fence into all
// layers being composed by MDP.
stack->retire_fence_fd = retire_fence;
stack->retire_fence_fd = mdp_commit.retire_fence;
for (uint32_t i = 0; i < hw_layer_info.count; i++) {
uint32_t layer_index = hw_layer_info.index[i];
Layer &layer = stack->layers[layer_index];
LayerBuffer *input_buffer = layer.input_buffer;
input_buffer->release_fence_fd = dup(release_fence);
LayerBuffer *input_buffer = stack->layers[layer_index].input_buffer;
input_buffer->release_fence_fd = dup(mdp_commit.release_fence);
}
close(release_fence);
close(mdp_commit.release_fence);
return kErrorNone;
}
void HWFrameBuffer::SetFormat(uint32_t *target, const LayerBufferFormat &source) {
DisplayError HWFrameBuffer::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 kFormatRGB888: *target = MDP_RGB_888; break;
case kFormatRGB565: *target = MDP_RGB_565; break;
case kFormatYCbCr420Planar: *target = MDP_Y_CB_CR_H2V2; break;
case kFormatYCrCb420Planar: *target = MDP_Y_CR_CB_H2V2; break;
case kFormatYCbCr420SemiPlanar: *target = MDP_Y_CBCR_H2V2; break;
case kFormatYCrCb420SemiPlanar: *target = MDP_Y_CRCB_H2V2; break;
case kFormatYCbCr422Packed: *target = MDP_YCBYCR_H2V1; break;
case kFormatYCbCr420SemiPlanarVenus: *target = MDP_Y_CBCR_H2V2_VENUS; break;
default:
*target = MDP_RGBA_8888;
break;
DLOGE("Unsupported format type %d", source);
return kErrorParameters;
}
return kErrorNone;
}
void HWFrameBuffer::SetBlending(const LayerBlending &source, mdss_mdp_blend_op *target) {
switch (source) {
case kBlendingPremultiplied: *target = BLEND_OP_PREMULTIPLIED; break;
case kBlendingCoverage: *target = BLEND_OP_COVERAGE; break;
default: *target = BLEND_OP_NOT_DEFINED; break;
}
}
void HWFrameBuffer::SetBlending(uint32_t *target, const LayerBlending &source) {
switch (source) {
case kBlendingPremultiplied:
*target = BLEND_OP_PREMULTIPLIED;
break;
case kBlendingCoverage:
*target = BLEND_OP_COVERAGE;
break;
default:
*target = BLEND_OP_NOT_DEFINED;
break;
}
}
void HWFrameBuffer::SetRect(mdp_rect *target, const LayerRect &source) {
void HWFrameBuffer::SetRect(const LayerRect &source, mdp_rect *target) {
target->x = INT(ceilf(source.left));
target->y = INT(ceilf(source.top));
target->w = INT(floorf(source.right)) - target->x;
@@ -498,7 +511,7 @@ void* HWFrameBuffer::DisplayEventThreadHandler() {
pthread_exit(0);
}
typedef void (HWFrameBuffer::*EventHandler)(int, char*);
typedef void (HWFrameBuffer::*EventHandler)(int, char *);
EventHandler event_handler[kNumDisplayEvents] = { &HWFrameBuffer::HandleVSync,
&HWFrameBuffer::HandleBlank };
@@ -538,13 +551,10 @@ void HWFrameBuffer::HandleVSync(int display_id, char *data) {
timestamp = strtoull(data + strlen("VSYNC="), NULL, 0);
}
event_handler_[display_id]->VSync(timestamp);
return;
}
void HWFrameBuffer::HandleBlank(int display_id, char* data) {
void HWFrameBuffer::HandleBlank(int display_id, char *data) {
// TODO(user): Need to send blank Event
return;
}
void HWFrameBuffer::PopulateFBNodeIndex() {

View File

@@ -27,7 +27,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <linux/msm_mdp.h>
#include <linux/msm_mdp_ext.h>
#include <poll.h>
#include <pthread.h>
@@ -58,6 +58,19 @@ class HWFrameBuffer : public HWInterface {
struct HWContext {
HWBlockType type;
int device_fd;
mdp_layer_commit mdp_commit;
mdp_input_layer mdp_layers[kMaxSDELayers * 2]; // split panel (left + right) for worst case
HWContext() : type(kHWBlockMax), device_fd(-1) {
ResetMDPCommit();
}
void ResetMDPCommit() {
memset(&mdp_commit, 0, sizeof(mdp_commit));
memset(&mdp_layers, 0, sizeof(mdp_layers));
mdp_commit.version = MDP_COMMIT_VERSION_1_0;
mdp_commit.commit_v1.input_layers = mdp_layers;
}
};
enum PanelType {
@@ -100,9 +113,9 @@ class HWFrameBuffer : public HWInterface {
static const int kNumDisplayEvents = 2;
static const int kHWMdssVersion5 = 500; // MDSS_V5
inline void SetFormat(uint32_t *target, const LayerBufferFormat &source);
inline void SetBlending(uint32_t *target, const LayerBlending &source);
inline void SetRect(mdp_rect *target, const LayerRect &source);
inline DisplayError SetFormat(const LayerBufferFormat &source, uint32_t *target);
inline void SetBlending(const LayerBlending &source, mdss_mdp_blend_op *target);
inline void SetRect(const LayerRect &source, mdp_rect *target);
// Event Thread to receive vsync/blank events
static void* DisplayEventThread(void *context);

View File

@@ -64,7 +64,7 @@ DisplayError ResManager::Config(DisplayResourceContext *display_resource_ctx, HW
pipe_info = &hw_layers->config[i].right_pipe;
if ((dstRight.right - dstRight.left) > kMaxInterfaceWidth ||
crop_width > kMaxInterfaceWidth ||
((hw_block_id == kHWPrimary) && hw_res_info_.is_src_split &&
((hw_block_id == kHWPrimary) &&
(crop_width > display_attributes.split_left))) {
scissor.left = FLOAT(display_attributes.split_left);
scissor.top = 0.0f;

View File

@@ -195,10 +195,6 @@ DisplayError ResManager::Acquire(Handle display_ctx, HWLayers *hw_layers) {
DisplayError error = kErrorNone;
const struct HWLayersInfo &layer_info = hw_layers->info;
if (UNLIKELY(!layer_info.count)) {
return kErrorNone;
}
if (UNLIKELY(layer_info.count > num_pipe_)) {
return kErrorResources;
}

View File

@@ -56,8 +56,8 @@ int HWCDisplay::Deinit() {
return -EINVAL;
}
if (LIKELY(layer_stack_.raw)) {
delete[] layer_stack_.raw;
if (LIKELY(layer_stack_memory_.raw)) {
delete[] layer_stack_memory_.raw;
}
return 0;
@@ -174,27 +174,28 @@ int HWCDisplay::AllocateLayerStack(hwc_display_contents_1_t *content_list) {
// Layer array may be large enough to hold current number of layers.
// If not, re-allocate it now.
if (UNLIKELY(layer_stack_.size < required_size)) {
if (LIKELY(layer_stack_.raw)) {
delete[] layer_stack_.raw;
layer_stack_.size = 0;
if (UNLIKELY(layer_stack_memory_.size < required_size)) {
if (LIKELY(layer_stack_memory_.raw)) {
delete[] layer_stack_memory_.raw;
layer_stack_memory_.size = 0;
}
// Allocate in multiple of kSizeSteps.
required_size = ROUND_UP(required_size, layer_stack_.kSizeSteps);
required_size = ROUND_UP(required_size, layer_stack_memory_.kSizeSteps);
layer_stack_.raw = new uint8_t[required_size];
if (UNLIKELY(!layer_stack_.raw)) {
layer_stack_memory_.raw = new uint8_t[required_size];
if (UNLIKELY(!layer_stack_memory_.raw)) {
return -ENOMEM;
}
layer_stack_.size = required_size;
layer_stack_memory_.size = required_size;
}
// Assign memory addresses now.
uint8_t *current_address = layer_stack_.raw;
uint8_t *current_address = layer_stack_memory_.raw;
// Layer array address
layer_stack_ = LayerStack();
layer_stack_.layers = reinterpret_cast<Layer *>(current_address);
layer_stack_.layer_count = static_cast<uint32_t>(num_hw_layers);
current_address += num_hw_layers * sizeof(Layer);
@@ -202,19 +203,25 @@ int HWCDisplay::AllocateLayerStack(hwc_display_contents_1_t *content_list) {
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[i];
layer = Layer();
// Layer buffer handle address
layer.input_buffer = reinterpret_cast<LayerBuffer *>(current_address);
*layer.input_buffer = LayerBuffer();
current_address += sizeof(LayerBuffer);
// Visible rectangle address
layer.visible_regions.rect = reinterpret_cast<LayerRect *>(current_address);
layer.visible_regions.count = static_cast<uint32_t>(hwc_layer.visibleRegionScreen.numRects);
for (size_t i = 0; i < layer.visible_regions.count; i++) {
*layer.visible_regions.rect = LayerRect();
}
current_address += hwc_layer.visibleRegionScreen.numRects * sizeof(LayerRect);
// Dirty rectangle address
layer.dirty_regions.rect = reinterpret_cast<LayerRect *>(current_address);
layer.dirty_regions.count = 1;
*layer.dirty_regions.rect = LayerRect();
current_address += sizeof(LayerRect);
}
@@ -223,13 +230,10 @@ int HWCDisplay::AllocateLayerStack(hwc_display_contents_1_t *content_list) {
int HWCDisplay::PrepareLayerStack(hwc_display_contents_1_t *content_list) {
size_t num_hw_layers = content_list->numHwLayers;
if (UNLIKELY(num_hw_layers <= 1)) {
if (num_hw_layers <= 1) {
return 0;
}
// Reset Layer stack flags
layer_stack_.flags = LayerStackFlags();
// Configure each layer
for (size_t i = 0; i < num_hw_layers; i++) {
hwc_layer_1_t &hwc_layer = content_list->hwLayers[i];
@@ -239,15 +243,12 @@ int HWCDisplay::PrepareLayerStack(hwc_display_contents_1_t *content_list) {
LayerBuffer *layer_buffer = layer.input_buffer;
if (pvt_handle) {
if (UNLIKELY(SetFormat(&layer_buffer->format, pvt_handle->format))) {
if (SetFormat(pvt_handle->format, &layer_buffer->format)) {
return -EINVAL;
}
layer_buffer->width = pvt_handle->width;
layer_buffer->height = pvt_handle->height;
layer_buffer->planes[0].fd = pvt_handle->fd;
layer_buffer->planes[0].offset = pvt_handle->offset;
layer_buffer->planes[0].stride = pvt_handle->width;
if (pvt_handle->bufferType == BUFFER_TYPE_VIDEO) {
layer_stack_.flags.video_present = true;
}
@@ -256,20 +257,20 @@ int HWCDisplay::PrepareLayerStack(hwc_display_contents_1_t *content_list) {
}
}
SetRect(&layer.dst_rect, hwc_layer.displayFrame);
SetRect(&layer.src_rect, hwc_layer.sourceCropf);
SetRect(hwc_layer.displayFrame, &layer.dst_rect);
SetRect(hwc_layer.sourceCropf, &layer.src_rect);
for (size_t j = 0; j < hwc_layer.visibleRegionScreen.numRects; j++) {
SetRect(&layer.visible_regions.rect[j], hwc_layer.visibleRegionScreen.rects[j]);
SetRect(hwc_layer.visibleRegionScreen.rects[j], &layer.visible_regions.rect[j]);
}
SetRect(&layer.dirty_regions.rect[0], hwc_layer.dirtyRect);
SetComposition(&layer.composition, hwc_layer.compositionType);
SetBlending(&layer.blending, hwc_layer.blending);
SetRect(hwc_layer.dirtyRect, &layer.dirty_regions.rect[0]);
SetComposition(hwc_layer.compositionType, &layer.composition);
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);
layer_transform.rotation = ((hwc_transform & HWC_TRANSFORM_ROT_90) ? 90.0f : 0.0f);
layer.plane_alpha = hwc_layer.planeAlpha;
layer.flags.skip = ((hwc_layer.flags & HWC_SKIP_LAYER) > 0);
@@ -294,10 +295,16 @@ int HWCDisplay::PrepareLayerStack(hwc_display_contents_1_t *content_list) {
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[i];
// if current frame does not need frame buffer redraw, then mark them for HWC_OVERLAY
LayerComposition composition = needs_fb_refresh ? layer.composition : kCompositionSDE;
SetComposition(&hwc_layer.compositionType, composition);
LayerComposition composition = layer.composition;
// If current layer does not need frame buffer redraw, then mark it as HWC_OVERLAY
if (!needs_fb_refresh && (composition != kCompositionGPUTarget)) {
composition = kCompositionSDE;
}
SetComposition(composition, &hwc_layer.compositionType);
}
// Cache the current layer stack information like layer_count, composition type and layer handle
// for the future.
CacheLayerStackInfo(content_list);
@@ -305,55 +312,33 @@ int HWCDisplay::PrepareLayerStack(hwc_display_contents_1_t *content_list) {
return 0;
}
void HWCDisplay::CacheLayerStackInfo(hwc_display_contents_1_t *content_list) {
uint32_t layer_count = layer_stack_.layer_count;
for (size_t i = 0; i < layer_count; i++) {
Layer &layer = layer_stack_.layers[i];
layer_stack_cache_.layer_cache[i].handle = content_list->hwLayers[i].handle;
layer_stack_cache_.layer_cache[i].composition = layer.composition;
}
layer_stack_cache_.layer_count = layer_count;
}
bool HWCDisplay::NeedsFrameBufferRefresh(hwc_display_contents_1_t *content_list) {
uint32_t layer_count = layer_stack_.layer_count;
// Frame buffer needs to be refreshed for the following reasons:
// 1. Any layer is marked skip in the current layer stack.
// 2. Any layer is added/removed/layer properties changes in the current layer stack.
// 3. Any layer handle is changed and it is marked for GPU composition
// 4. Any layer's current composition is different from previous composition.
if ((layer_stack_cache_.layer_count != layer_count) || layer_stack_.flags.skip_present ||
layer_stack_.flags.geometry_changed) {
return true;
}
for (size_t i = 0; i < layer_count; i++) {
hwc_layer_1_t &hwc_layer = content_list->hwLayers[i];
Layer &layer = layer_stack_.layers[i];
LayerCache &layer_cache = layer_stack_cache_.layer_cache[i];
if (layer_cache.composition != layer.composition) {
return true;
}
if ((layer.composition == kCompositionGPU) && (layer_cache.handle != hwc_layer.handle)) {
return true;
}
}
return false;
}
int HWCDisplay::CommitLayerStack(hwc_display_contents_1_t *content_list) {
size_t num_hw_layers = content_list->numHwLayers;
if (UNLIKELY(num_hw_layers <= 1)) {
if (num_hw_layers <= 1) {
if (!num_hw_layers) {
return 0;
}
// TODO(user): handle if only 1 layer(fb target) is received.
int &acquireFenceFd = content_list->hwLayers[0].acquireFenceFd;
if (acquireFenceFd >= 0) {
close(acquireFenceFd);
}
return 0;
}
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);
LayerBuffer *layer_buffer = layer_stack_.layers[i].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 = pvt_handle->width;
}
layer_buffer->acquire_fence_fd = hwc_layer.acquireFenceFd;
}
@@ -380,79 +365,103 @@ int HWCDisplay::CommitLayerStack(hwc_display_contents_1_t *content_list) {
return 0;
}
void HWCDisplay::SetRect(LayerRect *target, const hwc_rect_t &source) {
bool HWCDisplay::NeedsFrameBufferRefresh(hwc_display_contents_1_t *content_list) {
uint32_t layer_count = layer_stack_.layer_count;
// Frame buffer needs to be refreshed for the following reasons:
// 1. Any layer is marked skip in the current layer stack.
// 2. Any layer is added/removed/layer properties changes in the current layer stack.
// 3. Any layer handle is changed and it is marked for GPU composition
// 4. Any layer's current composition is different from previous composition.
if ((layer_stack_cache_.layer_count != layer_count) || layer_stack_.flags.skip_present ||
layer_stack_.flags.geometry_changed) {
return true;
}
for (uint32_t i = 0; i < layer_count; i++) {
hwc_layer_1_t &hwc_layer = content_list->hwLayers[i];
Layer &layer = layer_stack_.layers[i];
LayerCache &layer_cache = layer_stack_cache_.layer_cache[i];
if (layer.composition == kCompositionGPUTarget) {
continue;
}
if (layer_cache.composition != layer.composition) {
return true;
}
if ((layer.composition == kCompositionGPU) && (layer_cache.handle != hwc_layer.handle)) {
return true;
}
}
return false;
}
void HWCDisplay::CacheLayerStackInfo(hwc_display_contents_1_t *content_list) {
uint32_t layer_count = layer_stack_.layer_count;
for (uint32_t i = 0; i < layer_count; i++) {
Layer &layer = layer_stack_.layers[i];
if (layer.composition == kCompositionGPUTarget) {
continue;
}
layer_stack_cache_.layer_cache[i].handle = content_list->hwLayers[i].handle;
layer_stack_cache_.layer_cache[i].composition = layer.composition;
}
layer_stack_cache_.layer_count = layer_count;
}
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(LayerRect *target, const hwc_frect_t &source) {
void HWCDisplay::SetRect(const hwc_frect_t &source, LayerRect *target) {
target->left = source.left;
target->top = source.top;
target->right = source.right;
target->bottom = source.bottom;
}
void HWCDisplay::SetComposition(LayerComposition *target, const int32_t &source) {
void HWCDisplay::SetComposition(const int32_t &source, LayerComposition *target) {
switch (source) {
case HWC_FRAMEBUFFER_TARGET:
*target = kCompositionGPUTarget;
break;
default:
*target = kCompositionSDE;
break;
case HWC_FRAMEBUFFER_TARGET: *target = kCompositionGPUTarget; break;
default: *target = kCompositionSDE; break;
}
}
void HWCDisplay::SetComposition(int32_t *target, const LayerComposition &source) {
void HWCDisplay::SetComposition(const int32_t &source, int32_t *target) {
switch (source) {
case kCompositionGPUTarget:
*target = HWC_FRAMEBUFFER_TARGET;
break;
case kCompositionSDE:
*target = HWC_OVERLAY;
break;
default:
*target = HWC_FRAMEBUFFER;
break;
case kCompositionGPUTarget: *target = HWC_FRAMEBUFFER_TARGET; break;
case kCompositionSDE: *target = HWC_OVERLAY; break;
default: *target = HWC_FRAMEBUFFER; break;
}
}
void HWCDisplay::SetBlending(LayerBlending *target, const int32_t &source) {
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 = kBlendingNone;
break;
case HWC_BLENDING_PREMULT: *target = kBlendingPremultiplied; break;
case HWC_BLENDING_COVERAGE: *target = kBlendingCoverage; break;
default: *target = kBlendingNone; break;
}
}
int HWCDisplay::SetFormat(LayerBufferFormat *target, const int &source) {
int HWCDisplay::SetFormat(const int32_t &source, LayerBufferFormat *target) {
switch (source) {
case HAL_PIXEL_FORMAT_RGBA_8888:
*target = kFormatRGBA8888;
break;
case HAL_PIXEL_FORMAT_BGRA_8888:
*target = kFormatBGRA8888;
break;
case HAL_PIXEL_FORMAT_RGBX_8888:
*target = kFormatRGBX8888;
break;
case HAL_PIXEL_FORMAT_BGRX_8888:
*target = kFormatBGRX8888;
break;
case HAL_PIXEL_FORMAT_RGB_888:
*target = kFormatRGB888;
break;
case HAL_PIXEL_FORMAT_RGB_565:
*target = kFormatRGB565;
break;
case HAL_PIXEL_FORMAT_RGBA_8888: *target = kFormatRGBA8888; break;
case HAL_PIXEL_FORMAT_BGRA_8888: *target = kFormatBGRA8888; break;
case HAL_PIXEL_FORMAT_RGBX_8888: *target = kFormatRGBX8888; break;
case HAL_PIXEL_FORMAT_BGRX_8888: *target = kFormatBGRX8888; break;
case HAL_PIXEL_FORMAT_RGB_888: *target = kFormatRGB888; break;
case HAL_PIXEL_FORMAT_RGB_565: *target = kFormatRGB565; break;
case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS: *target = kFormatYCbCr420SemiPlanarVenus; break;
default:
DLOGE("Unsupported format type %d", source);
return -EINVAL;

View File

@@ -47,39 +47,14 @@ class HWCDisplay : public DisplayEventHandler {
static const uint32_t kMaxLayerCount = 32;
// Structure to track memory allocation for layer stack (layers, rectangles) object.
struct LayerStackMemory : LayerStack {
static const size_t kSizeSteps = 4096; // Default memory allocation.
struct LayerStackMemory {
static const size_t kSizeSteps = 1024; // Default memory allocation.
uint8_t *raw; // Pointer to byte array.
size_t size; // Current number of allocated bytes.
LayerStackMemory() : raw(NULL), size(0) { }
};
HWCDisplay(CoreInterface *core_intf, hwc_procs_t const **hwc_procs, DisplayType type, int id);
virtual ~HWCDisplay() { }
// DisplayEventHandler methods
virtual DisplayError VSync(const DisplayEventVSync &vsync);
virtual DisplayError Refresh();
virtual int AllocateLayerStack(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);
inline void SetRect(LayerRect *target, const hwc_rect_t &source);
inline void SetRect(LayerRect *target, const hwc_frect_t &source);
inline void SetComposition(LayerComposition *target, const int32_t &source);
inline void SetComposition(int32_t *target, const LayerComposition &source);
inline void SetBlending(LayerBlending *target, const int32_t &source);
inline int SetFormat(LayerBufferFormat *target, const int &source);
LayerStackMemory layer_stack_;
CoreInterface *core_intf_;
hwc_procs_t const **hwc_procs_;
DisplayType type_;
int id_;
DisplayInterface *display_intf_;
private:
struct LayerCache {
buffer_handle_t handle;
LayerComposition composition;
@@ -94,10 +69,33 @@ class HWCDisplay : public DisplayEventHandler {
LayerStackCache() : layer_count(0) { }
};
HWCDisplay(CoreInterface *core_intf, hwc_procs_t const **hwc_procs, DisplayType type, int id);
virtual ~HWCDisplay() { }
// DisplayEventHandler methods
virtual DisplayError VSync(const DisplayEventVSync &vsync);
virtual DisplayError Refresh();
virtual int AllocateLayerStack(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);
bool NeedsFrameBufferRefresh(hwc_display_contents_1_t *content_list);
void CacheLayerStackInfo(hwc_display_contents_1_t *content_list);
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 int32_t &source, int32_t *target);
inline void SetBlending(const int32_t &source, LayerBlending *target);
inline int SetFormat(const int32_t &source, LayerBufferFormat *target);
LayerStackMemory layer_stack_memory_;
LayerStack layer_stack_;
LayerStackCache layer_stack_cache_;
CoreInterface *core_intf_;
hwc_procs_t const **hwc_procs_;
DisplayType type_;
int id_;
DisplayInterface *display_intf_;
};
} // namespace sde

View File

@@ -45,10 +45,33 @@ int HWCDisplayExternal::Deinit() {
}
int HWCDisplayExternal::Prepare(hwc_display_contents_1_t *content_list) {
int status = 0;
status = AllocateLayerStack(content_list);
if (UNLIKELY(status)) {
return status;
}
layer_stack_.retire_fence_fd = -1;
status = PrepareLayerStack(content_list);
if (UNLIKELY(status)) {
return status;
}
return 0;
}
int HWCDisplayExternal::Commit(hwc_display_contents_1_t *content_list) {
int status = 0;
status = HWCDisplay::CommitLayerStack(content_list);
if (UNLIKELY(status)) {
return status;
}
content_list->retireFenceFd = layer_stack_.retire_fence_fd;
return 0;
}

View File

@@ -52,6 +52,8 @@ int HWCDisplayPrimary::Prepare(hwc_display_contents_1_t *content_list) {
return status;
}
layer_stack_.retire_fence_fd = -1;
status = PrepareLayerStack(content_list);
if (UNLIKELY(status)) {
return status;