diff --git a/common/compositor/compositor.cpp b/common/compositor/compositor.cpp index e9ff51d90..784686ab3 100644 --- a/common/compositor/compositor.cpp +++ b/common/compositor/compositor.cpp @@ -74,9 +74,6 @@ bool Compositor::Draw(DisplayPlaneStateList &comp_planes, plane.GetSourceLayers().end()); } } else if (plane.IsVideoPlane()) { - dedicated_layers.insert(dedicated_layers.end(), - plane.GetSourceLayers().begin(), - plane.GetSourceLayers().end()); media_state.emplace_back(); plane.SwapSurfaceIfNeeded(); DrawState &state = media_state.back(); @@ -87,56 +84,89 @@ bool Compositor::Draw(DisplayPlaneStateList &comp_planes, media_state.scaling_mode_ = scaling_mode_; media_state.deinterlace_ = deinterlace_; lock_.unlock(); - const OverlayLayer &layer = layers[plane.GetSourceLayers().at(0)]; - media_state.layer_ = &layer; + OverlayLayer* layer = &(layers[plane.GetSourceLayers().at(0)]); + media_state.layers_.emplace_back(layer); } else if (plane.NeedsOffScreenComposition()) { - comp = &plane; - plane.SwapSurfaceIfNeeded(); - std::vector &comp_regions = - plane.GetCompositionRegion(); - bool regions_empty = comp_regions.empty(); - NativeSurface *surface = plane.GetOffScreenTarget(); - if (surface == NULL) { - ETRACE("GetOffScreenTarget() returned NULL pointer 'surface'."); - return false; - } - if (!regions_empty && - (surface->ClearSurface() || surface->IsPartialClear() || - surface->IsSurfaceDamageChanged())) { - plane.ResetCompositionRegion(); - regions_empty = true; - } - - if (surface->ClearSurface()) { - plane.UpdateDamage(plane.GetDisplayFrame()); - } - - if (regions_empty) { - SeparateLayers(dedicated_layers, comp->GetSourceLayers(), display_frame, - surface->GetSurfaceDamage(), comp_regions); + bool content_protected = false; + + // If we have a video layer along with other layers then check + // if any of the layers contain protected content. + if (plane.HasVideoLayer()) { + for (size_t l : plane.GetSourceLayers()) { + OverlayLayer& layer = layers.at(l); + if (layer.IsProtected()) { + content_protected = true; + break; + } + } } - std::vector().swap(dedicated_layers); - if (comp_regions.empty()) - continue; - - draw_state.emplace_back(); - DrawState &state = draw_state.back(); - state.surface_ = surface; - size_t num_regions = comp_regions.size(); - state.states_.reserve(num_regions); - bool use_plane_transform = false; - if (plane.GetRotationType() == - DisplayPlaneState::RotationType::kGPURotation) { - use_plane_transform = true; - } - - CalculateRenderState(layers, comp_regions, state, - plane.GetDownScalingFactor(), - plane.IsUsingPlaneScalar(), use_plane_transform); - - if (state.states_.empty()) { - draw_state.pop_back(); + if (content_protected) { + // if we have protected content along with other layers, then we + // need to use libva for the blending of the layers. + media_state.emplace_back(); + plane.SwapSurfaceIfNeeded(); + DrawState &state = media_state.back(); + state.surface_ = plane.GetOffScreenTarget(); + MediaState &media_state = state.media_state_; + lock_.lock(); + media_state.colors_ = colors_; + media_state.scaling_mode_ = scaling_mode_; + media_state.deinterlace_ = deinterlace_; + lock_.unlock(); + for (auto layer_id : plane.GetSourceLayers()) { + OverlayLayer *layer = &(layers.at(layer_id)); + media_state.layers_.emplace_back(layer); + } + } else { + comp = &plane; + plane.SwapSurfaceIfNeeded(); + std::vector &comp_regions = + plane.GetCompositionRegion(); + bool regions_empty = comp_regions.empty(); + NativeSurface *surface = plane.GetOffScreenTarget(); + if (surface == NULL) { + ETRACE("GetOffScreenTarget() returned NULL pointer 'surface'."); + return false; + } + if (!regions_empty && + (surface->ClearSurface() || surface->IsPartialClear() || + surface->IsSurfaceDamageChanged())) { + plane.ResetCompositionRegion(); + regions_empty = true; + } + + if (surface->ClearSurface()) { + plane.UpdateDamage(plane.GetDisplayFrame()); + } + + if (regions_empty) { + SeparateLayers(dedicated_layers, comp->GetSourceLayers(), display_frame, + surface->GetSurfaceDamage(), comp_regions); + } + + std::vector().swap(dedicated_layers); + if (comp_regions.empty()) + continue; + + draw_state.emplace_back(); + DrawState &state = draw_state.back(); + state.surface_ = surface; + size_t num_regions = comp_regions.size(); + state.states_.reserve(num_regions); + bool use_plane_transform = false; + if (plane.GetRotationType() == + DisplayPlaneState::RotationType::kGPURotation) { + use_plane_transform = true; + } + + CalculateRenderState(layers, comp_regions, state, + plane.GetDownScalingFactor(), + plane.IsUsingPlaneScalar(), use_plane_transform); + + if (state.states_.empty()) { + draw_state.pop_back(); + } } } } diff --git a/common/compositor/renderstate.h b/common/compositor/renderstate.h index 7ab7b9c57..106fc6e44 100644 --- a/common/compositor/renderstate.h +++ b/common/compositor/renderstate.h @@ -60,7 +60,7 @@ struct RenderState { }; struct MediaState { - const OverlayLayer *layer_; + std::vector layers_; HWCColorMap colors_; HWCDeinterlaceProp deinterlace_; uint32_t scaling_mode_; diff --git a/common/compositor/va/varenderer.cpp b/common/compositor/va/varenderer.cpp index 1afca77b4..624599cfd 100644 --- a/common/compositor/va/varenderer.cpp +++ b/common/compositor/va/varenderer.cpp @@ -21,6 +21,7 @@ #include #include +#include "hwcutils.h" #include "hwctrace.h" #include "nativesurface.h" #include "overlaybuffer.h" @@ -243,107 +244,127 @@ bool VARenderer::Draw(const MediaState& state, NativeSurface* surface) { } } - // Get Input Surface. - OverlayBuffer* buffer_in = state.layer_->GetBuffer(); - const MediaResourceHandle& resource = buffer_in->GetMediaResource( - va_display_, state.layer_->GetSourceCropWidth(), - state.layer_->GetSourceCropHeight()); - VASurfaceID surface_in = resource.surface_; - if (surface_in == VA_INVALID_ID) { - ETRACE("Failed to create Va Input Surface. \n"); - return false; - } - // Get Output Surface. OverlayLayer* layer_out = surface->GetLayer(); + HwcRect layer_out_disp_frame = layer_out->GetDisplayFrame(); + int xtranslation = layer_out_disp_frame.left; + int ytranslation = layer_out_disp_frame.top; + const MediaResourceHandle& out_resource = - layer_out->GetBuffer()->GetMediaResource( - va_display_, layer_out->GetSourceCropWidth(), - layer_out->GetSourceCropHeight()); + layer_out->GetBuffer()->GetMediaResource( + va_display_, layer_out->GetDisplayFrameWidth(), + layer_out->GetDisplayFrameWidth()); VASurfaceID surface_out = out_resource.surface_; if (surface_out == VA_INVALID_ID) { ETRACE("Failed to create Va Output Surface. \n"); return false; } - // Set the protected status to output layer if input layer is protected - if (state.layer_->IsProtected()) { - layer_out->SetProtected(true); - } else { - layer_out->SetProtected(false); - } + layer_out->SetProtected(false); - VARectangle surface_region; - const OverlayLayer* layer_in = state.layer_; - const HwcRect& source_crop = layer_in->GetSourceCrop(); - surface_region.x = static_cast(source_crop.left); - surface_region.y = static_cast(source_crop.top); - surface_region.width = layer_in->GetSourceCropWidth(); - surface_region.height = layer_in->GetSourceCropHeight(); - - VARectangle output_region; - const HwcRect& source_crop_out = layer_out->GetSourceCrop(); - output_region.x = static_cast(source_crop_out.left); - output_region.y = static_cast(source_crop_out.top); - output_region.width = layer_out->GetSourceCropWidth(); - output_region.height = layer_out->GetSourceCropHeight(); - - VAProcPipelineParameterBuffer pipe_param = {}; - pipe_param.surface = surface_in; - pipe_param.surface_region = &surface_region; - pipe_param.surface_color_standard = VAProcColorStandardBT601; - pipe_param.output_region = &output_region; - pipe_param.output_color_standard = VAProcColorStandardBT601; - - DUMPTRACE("surface_region: (%d, %d, %d, %d)\n", surface_region.x, - surface_region.y, surface_region.width, surface_region.height); - DUMPTRACE("Layer DisplayFrame:(%d,%d,%d,%d)\n", output_region.x, - output_region.y, output_region.width, output_region.height); - - for (auto itr = state.colors_.begin(); itr != state.colors_.end(); itr++) { - SetVAProcFilterColorValue(itr->first, itr->second); - } + VAStatus ret = VA_STATUS_SUCCESS; + ret = vaBeginPicture(va_display_, va_context_, surface_out); - SetVAProcFilterDeinterlaceMode(state.deinterlace_, buffer_in); + OverlayLayer* layer_in = NULL; + uint32_t total_layers = state.layers_.size(); + std::vector pipeline_buffers(total_layers, va_display_); + + for (uint32_t i = 0; i < total_layers; i++) { + layer_in = state.layers_.at(i); + ScopedVABufferID& pipeline_buffer = pipeline_buffers.at(i); + // Get Input Surface. + OverlayBuffer* buffer_in = layer_in->GetBuffer(); + const MediaResourceHandle& resource = buffer_in->GetMediaResource( + va_display_, layer_in->GetSourceCropWidth(), + layer_in->GetSourceCropHeight()); + VASurfaceID surface_in = resource.surface_; + if (surface_in == VA_INVALID_ID) { + ETRACE("Failed to create Va Input Surface. \n"); + return false; + } - if (!UpdateCaps()) { - ETRACE("Failed to update capabailities. \n"); - return false; - } + // Set the protected status to output layer if input layer is protected + if (layer_in->IsProtected()) { + layer_out->SetProtected(true); + } - pipe_param.filter_flags = GetVAProcFilterScalingMode(state.scaling_mode_); - if (filters_.size()) { - pipe_param.filters = filters_.data(); - } - pipe_param.num_filters = static_cast(filters_.size()); + + VARectangle surface_region; + const HwcRect& source_crop = layer_in->GetSourceCrop(); + surface_region.x = static_cast(source_crop.left); + surface_region.y = static_cast(source_crop.top); + surface_region.width = layer_in->GetSourceCropWidth(); + surface_region.height = layer_in->GetSourceCropHeight(); + + VARectangle output_region; + HwcRect display_frame = layer_in->GetDisplayFrame(); + display_frame = TranslateRect(display_frame, -xtranslation, -ytranslation); + output_region.x = display_frame.left; + output_region.y = display_frame.top; + output_region.width = layer_in->GetDisplayFrameWidth(); + output_region.height = layer_in->GetDisplayFrameHeight(); + + + VABlendState bs = {}; + bs.flags = VA_BLEND_PREMULTIPLIED_ALPHA; + + VAProcPipelineParameterBuffer pipe_param = {}; + pipe_param.surface = surface_in; + pipe_param.surface_region = &surface_region; + pipe_param.surface_color_standard = VAProcColorStandardBT601; + pipe_param.output_region = &output_region; + pipe_param.output_color_standard = VAProcColorStandardBT601; + pipe_param.blend_state = &bs; + + DUMPTRACE("surface_region: (%d, %d, %d, %d)\n", surface_region.x, + surface_region.y, surface_region.width, surface_region.height); + DUMPTRACE("Layer DisplayFrame:(%d,%d,%d,%d)\n", output_region.x, + output_region.y, output_region.width, output_region.height); #if VA_MAJOR_VERSION >= 1 - // currently rotation is only supported by VA on Android. - uint32_t rotation = 0, mirror = 0; - HWCTransformToVA(state.layer_->GetTransform(), rotation, mirror); - pipe_param.rotation_state = rotation; - pipe_param.mirror_state = mirror; + // currently rotation is only supported by VA on Android. + uint32_t rotation = 0, mirror = 0; + HWCTransformToVA(layer_in->GetTransform(), rotation, mirror); + pipe_param.rotation_state = rotation; + pipe_param.mirror_state = mirror; #endif - ScopedVABufferID pipeline_buffer(va_display_); - if (!pipeline_buffer.CreateBuffer( + for (auto itr = state.colors_.begin(); itr != state.colors_.end(); itr++) { + SetVAProcFilterColorValue(itr->first, itr->second); + } + SetVAProcFilterDeinterlaceMode(state.deinterlace_, buffer_in); + + if (!UpdateCaps()) { + ETRACE("Failed to update capabailities. \n"); + return false; + } + + pipe_param.filter_flags = GetVAProcFilterScalingMode(state.scaling_mode_); + if (filters_.size()) { + pipe_param.filters = filters_.data(); + } + pipe_param.num_filters = static_cast(filters_.size()); + + if (!pipeline_buffer.CreateBuffer( va_context_, VAProcPipelineParameterBufferType, sizeof(VAProcPipelineParameterBuffer), 1, &pipe_param)) { - return false; - } + return false; + } - VAStatus ret = VA_STATUS_SUCCESS; - ret = vaBeginPicture(va_display_, va_context_, surface_out); - ret |= + ret |= vaRenderPicture(va_display_, va_context_, &pipeline_buffer.buffer(), 1); - ret |= vaEndPicture(va_display_, va_context_); - if (surface_region.width == 1920 && surface_region.height == 1080) { - // FIXME: WA for OAM-63127. Not sure why this is needed but seems - // to ensure we have consistent 60 fps. - vaSyncSurface(va_display_, surface_out); } + ret |= vaEndPicture(va_display_, va_context_); + + // reviewer: How to resolve this? + // if (surface_region.width == 1920 && surface_region.height == 1080) { + // // FIXME: WA for OAM-63127. Not sure why this is needed but seems + // // to ensure we have consistent 60 fps. + // vaSyncSurface(va_display_, surface_out); + // } + surface->ResetDamage(); return ret == VA_STATUS_SUCCESS ? true : false; diff --git a/common/compositor/va/vautils.cpp b/common/compositor/va/vautils.cpp index fae53066c..c08856519 100644 --- a/common/compositor/va/vautils.cpp +++ b/common/compositor/va/vautils.cpp @@ -42,6 +42,13 @@ int DrmFormatToVAFormat(int format) { return VA_FOURCC_YUY2; case DRM_FORMAT_P010: return VA_FOURCC_P010; + // reviewer: please check this + case DRM_FORMAT_ABGR8888: + return VA_FOURCC_RGBA; + case DRM_FORMAT_XBGR8888: + return VA_FOURCC_RGBX; + case DRM_FORMAT_ARGB8888: + return VA_FOURCC_ABGR; case DRM_FORMAT_YVYU: case DRM_FORMAT_VYUY: case DRM_FORMAT_YUV444: @@ -69,6 +76,13 @@ int DrmFormatToRTFormat(int format) { return VA_RT_FORMAT_YUV444; case DRM_FORMAT_P010: return VA_RT_FORMAT_YUV420_10BPP; + // reviewer: please check this + case DRM_FORMAT_ABGR8888: + return VA_RT_FORMAT_RGB32; + case DRM_FORMAT_XBGR8888: + return VA_RT_FORMAT_RGB32; + case DRM_FORMAT_ARGB8888: + return VA_RT_FORMAT_RGB32; default: ETRACE("Unable to convert to RTFormat from format %x", format); break; diff --git a/common/display/displayplanemanager.cpp b/common/display/displayplanemanager.cpp index d1ecefb6c..243b29e13 100644 --- a/common/display/displayplanemanager.cpp +++ b/common/display/displayplanemanager.cpp @@ -234,6 +234,9 @@ bool DisplayPlaneManager::ValidateLayers( validate_final_layers); #endif DisplayPlaneState &last_plane = composition.back(); + if (layer->IsVideoLayer()) { + last_plane.SetVideoPlane(true); + } ResetPlaneTarget(last_plane, commit_planes.back()); validate_final_layers = true; if (display_transform_ != kIdentity) { @@ -272,6 +275,9 @@ bool DisplayPlaneManager::ValidateLayers( } DisplayPlaneState &last_plane = composition.back(); + if (layer->IsVideoLayer()) { + last_plane.SetVideoPlane(true); + } if (!validate_final_layers) validate_final_layers = !(last_plane.GetOffScreenTarget()); ResetPlaneTarget(last_plane, commit_planes.back()); @@ -720,7 +726,7 @@ void DisplayPlaneManager::SetDisplayTransform(uint32_t transform) { void DisplayPlaneManager::EnsureOffScreenTarget(DisplayPlaneState &plane) { NativeSurface *surface = NULL; - bool video_separate = plane.IsVideoPlane(); + bool video_separate = plane.IsVideoPlane() && (plane.GetSourceLayers().size() == 1); uint32_t preferred_format = 0; uint32_t usage = hwcomposer::kLayerNormal; if (video_separate) { diff --git a/common/display/displayplanestate.cpp b/common/display/displayplanestate.cpp index 4831b6701..096c9229e 100644 --- a/common/display/displayplanestate.cpp +++ b/common/display/displayplanestate.cpp @@ -481,9 +481,15 @@ bool DisplayPlaneState::HasCursorLayer() const { } bool DisplayPlaneState::IsVideoPlane() const { - return private_data_->type_ == DisplayPlanePrivateState::PlaneType::kVideo; + bool is_video = private_data_->type_ == DisplayPlanePrivateState::PlaneType::kVideo; + bool single_layer = private_data_->source_layers_.size() == 1; + return is_video && single_layer; } + bool DisplayPlaneState::HasVideoLayer() const { + return private_data_->type_ == DisplayPlanePrivateState::PlaneType::kVideo; + } + void DisplayPlaneState::SetVideoPlane(bool enable_video) { #ifndef DISABLE_VA if (enable_video) { diff --git a/common/display/displayplanestate.h b/common/display/displayplanestate.h index 13014cefc..08830e977 100644 --- a/common/display/displayplanestate.h +++ b/common/display/displayplanestate.h @@ -130,6 +130,8 @@ class DisplayPlaneState { bool IsVideoPlane() const; + bool HasVideoLayer() const; + // Set true if this Plane State is handling Video layer and // needs to go through the Media Compositor for any // offscreen composition usage. diff --git a/common/display/displayqueue.cpp b/common/display/displayqueue.cpp index 75ee7df6e..14ba444e4 100644 --- a/common/display/displayqueue.cpp +++ b/common/display/displayqueue.cpp @@ -752,7 +752,7 @@ bool DisplayQueue::QueueUpdate(std::vector& source_layers, } bool composition_passed = true; - bool disable_ovelays = state_ & kDisableOverlayUsage; + bool disable_ovelays = true; //state_ & kDisableOverlayUsage; if (!validate_layers && tracker.RevalidateLayers()) { validate_layers = true; }