blob: ba30d020365ea11afe324526880d0ad8f60a3180 [file] [log] [blame]
/*
* Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <cassert>
#include "hwc2.h"
hwc2_window::hwc2_window()
: content(HWC2_WINDOW_CONTENT_EMPTY),
z_order(0),
lyr_id(0) { }
void hwc2_window::clear()
{
content = HWC2_WINDOW_CONTENT_EMPTY;
}
hwc2_error_t hwc2_window::assign_client_target(uint32_t z_order)
{
/* The client target will never rotate, scale or flip. Its buffer layout
* could be changed before present display, so the window must support all
* layouts. */
if (!is_empty() || !has_requirements(HWC2_WINDOW_CAP_LAYOUTS))
return HWC2_ERROR_UNSUPPORTED;
content = HWC2_WINDOW_CONTENT_CLIENT_TARGET;
this->z_order = z_order;
return HWC2_ERROR_NONE;
}
hwc2_error_t hwc2_window::assign_layer(uint32_t z_order, const hwc2_layer &lyr)
{
if (!is_empty() || !has_layer_requirements(lyr))
return HWC2_ERROR_UNSUPPORTED;
content = HWC2_WINDOW_CONTENT_LAYER;
this->z_order = z_order;
this->lyr_id = lyr.get_id();
return HWC2_ERROR_NONE;
}
bool hwc2_window::is_empty() const
{
return content == HWC2_WINDOW_CONTENT_EMPTY;
}
bool hwc2_window::contains_client_target() const
{
return content == HWC2_WINDOW_CONTENT_CLIENT_TARGET;
}
bool hwc2_window::contains_layer() const
{
return content == HWC2_WINDOW_CONTENT_LAYER;
}
bool hwc2_window::has_layer_requirements(const hwc2_layer &lyr) const
{
hwc_transform_t transform = lyr.get_transform();
uint32_t reqs = 0;
int32_t layout;
layout = lyr.get_layout();
if (layout < 0)
return false;
reqs |= layout;
if (transform & HWC_TRANSFORM_ROT_90) {
const void *surf;
size_t surf_cnt;
lyr.get_surfaces(&surf, &surf_cnt);
if (surf_cnt > 1)
reqs |= HWC2_WINDOW_CAP_ROTATE_PLANAR;
else
reqs |= HWC2_WINDOW_CAP_ROTATE_PACKED;
}
if (transform & (HWC_TRANSFORM_FLIP_H | HWC_TRANSFORM_FLIP_V))
reqs |= HWC2_WINDOW_CAP_FLIP;
if (lyr.get_scale_width() != 1 || lyr.get_scale_height() != 1)
reqs |= HWC2_WINDOW_CAP_SCALE;
if (lyr.is_yuv())
reqs |= HWC2_WINDOW_CAP_YUV;
return has_requirements(reqs);
}
bool hwc2_window::has_requirements(uint32_t requirements) const
{
return (requirements & capabilities) == requirements;
}
void hwc2_window::set_capabilities(uint32_t capabilities)
{
this->capabilities = capabilities;
}
bool hwc2_window::is_supported(const hwc2_layer &lyr)
{
float source_crop_height = lyr.get_source_crop_height();
float scale_width = lyr.get_scale_width();
float scale_height = lyr.get_scale_height();
if (!lyr.get_buffer_handle())
return false;
if (!lyr.get_adf_buffer_format())
return false;
if (lyr.is_stereo())
return false;
if (lyr.is_overlapped())
return false;
if (lyr.get_display_frame_width() < HWC2_WINDOW_MIN_DISPLAY_FRAME_WIDTH
|| lyr.get_display_frame_height() < HWC2_WINDOW_MIN_DISPLAY_FRAME_HEIGHT)
return false;
if (lyr.get_source_crop_width() < HWC2_WINDOW_MIN_SOURCE_CROP_WIDTH
|| source_crop_height < HWC2_WINDOW_MIN_SOURCE_CROP_HEIGHT)
return false;
if (scale_width < HWC2_WINDOW_MIN_DISPLAY_FRAME_SCALE
|| scale_height < HWC2_WINDOW_MIN_DISPLAY_FRAME_SCALE)
return false;
const void *surf;
size_t surf_cnt;
lyr.get_surfaces(&surf, &surf_cnt);
if (lyr.get_transform() & HWC_TRANSFORM_ROT_90) {
if (surf_cnt == 1 && scale_width == 1 && scale_height == 1
&& source_crop_height > HWC2_WINDOW_MAX_ROT_SRC_HEIGHT_NO_SCALE)
return false;
else if (source_crop_height > HWC2_WINDOW_MAX_ROT_SRC_HEIGHT)
return false;
}
if (!lyr.is_source_crop_int_aligned())
return false;
return true;
}