static bool dc_state_untrack_phantom_stream(struct dc_state *state, struct dc_stream_state *phantom_stream)
{
bool res = false;
int i;
/* first find phantom stream in the dc_state */ for (i = 0; i < state->phantom_stream_count; i++) { if (state->phantom_streams[i] == phantom_stream) {
state->phantom_streams[i] = NULL;
res = true;
break;
}
}
/* failed to find stream in state */ if (!res)
return res;
/* trim back phantom streams */
state->phantom_stream_count--; for (; i < state->phantom_stream_count; i++)
state->phantom_streams[i] = state->phantom_streams[i + 1];
static bool dc_state_untrack_phantom_plane(struct dc_state *state, struct dc_plane_state *phantom_plane)
{
bool res = false;
int i;
/* first find phantom plane in the dc_state */ for (i = 0; i < state->phantom_plane_count; i++) { if (state->phantom_planes[i] == phantom_plane) {
state->phantom_planes[i] = NULL;
res = true;
break;
}
}
/* failed to find plane in state */ if (!res)
return res;
/* trim back phantom planes */
state->phantom_plane_count--; for (; i < state->phantom_plane_count; i++)
state->phantom_planes[i] = state->phantom_planes[i + 1];
for (i = 0; i < MAX_PIPES; i++) {
struct pipe_ctx *cur_pipe = &dst_state->res_ctx.pipe_ctx[i];
if (cur_pipe->top_pipe)
cur_pipe->top_pipe = &dst_state->res_ctx.pipe_ctx[cur_pipe->top_pipe->pipe_idx];
if (cur_pipe->bottom_pipe)
cur_pipe->bottom_pipe = &dst_state->res_ctx.pipe_ctx[cur_pipe->bottom_pipe->pipe_idx];
if (cur_pipe->prev_odm_pipe)
cur_pipe->prev_odm_pipe = &dst_state->res_ctx.pipe_ctx[cur_pipe->prev_odm_pipe->pipe_idx];
if (cur_pipe->next_odm_pipe)
cur_pipe->next_odm_pipe = &dst_state->res_ctx.pipe_ctx[cur_pipe->next_odm_pipe->pipe_idx];
}
/* retain phantoms */ for (i = 0; i < dst_state->phantom_stream_count; i++)
dc_stream_retain(dst_state->phantom_streams[i]);
for (i = 0; i < dst_state->phantom_plane_count; i++)
dc_plane_state_retain(dst_state->phantom_planes[i]);
/* retain streams and planes */ for (i = 0; i < dst_state->stream_count; i++) {
dc_stream_retain(dst_state->streams[i]); for (j = 0; j < dst_state->stream_status[i].plane_count; j++)
dc_plane_state_retain(
dst_state->stream_status[i].plane_states[j]);
}
}
static void init_state(struct dc *dc, struct dc_state *state)
{
/* Each context must have their own instance of VBA and in order to
* initialize and obtain IP and SOC the base DML instance from DC is
* initially copied into every context
*/
memcpy(&state->bw_ctx.dml, &dc->dml, sizeof(struct display_mode_lib));
}
/* Public dc_state functions */
struct dc_state *dc_state_create(struct dc *dc, struct dc_state_create_params *params)
{
struct dc_state *state;
state = kvzalloc(sizeof(struct dc_state), GFP_KERNEL);
/* Initialise DIG link encoder resource tracking variables. */ if (dc->res_pool)
link_enc_cfg_init(dc, state);
}
void dc_state_destruct(struct dc_state *state)
{
int i, j;
for (i = 0; i < state->stream_count; i++) { for (j = 0; j < state->stream_status[i].plane_count; j++)
dc_plane_state_release(
state->stream_status[i].plane_states[j]);
static void remove_mpc_combine_for_stream(const struct dc *dc,
struct dc_state *new_ctx,
const struct dc_state *cur_ctx,
struct dc_stream_status *status)
{
int i;
for (i = 0; i < status->plane_count; i++)
resource_update_pipes_for_plane_with_slice_count(
new_ctx, cur_ctx, dc->res_pool,
status->plane_states[i], 1);
}
stream_status = dc_state_get_stream_status(state, stream);
otg_master_pipe = resource_get_otg_master_for_stream(
&state->res_ctx, stream); if (stream_status == NULL) {
dm_error("Existing stream not found; failed to attach surface!\n");
goto out;
} elseif (stream_status->plane_count == MAX_SURFACES) {
dm_error("Surface: can not attach plane_state %p! Maximum is: %d\n",
plane_state, MAX_SURFACES);
goto out;
} elseif (!otg_master_pipe) {
goto out;
}
added = resource_append_dpp_pipes_for_plane_composition(state,
dc->current_state, pool, otg_master_pipe, plane_state);
if (!added) {
/* try to remove MPC combine to free up pipes */ for (i = 0; i < state->stream_count; i++)
remove_mpc_combine_for_stream(dc, state,
dc->current_state,
&state->stream_status[i]);
added = resource_append_dpp_pipes_for_plane_composition(state,
dc->current_state, pool,
otg_master_pipe, plane_state);
}
if (!added) {
/* try to decrease ODM slice count gradually to free up pipes */
odm_slice_count = resource_get_odm_slice_count(otg_master_pipe); for (i = odm_slice_count - 1; i > 0; i--) {
resource_update_pipes_for_stream_with_slice_count(state,
dc->current_state, dc->res_pool, stream,
i);
added = resource_append_dpp_pipes_for_plane_composition(
state,
dc->current_state, pool,
otg_master_pipe, plane_state); if (added)
break;
}
}
if (added) {
stream_status->plane_states[stream_status->plane_count] =
plane_state;
stream_status->plane_count++;
dc_plane_state_retain(plane_state);
}
for (i = 0; i < state->stream_count; i++) if (state->streams[i] == stream) {
stream_status = &state->stream_status[i];
break;
}
if (stream_status == NULL) {
dm_error("Existing stream not found; failed to remove plane.\n");
return false;
}
resource_remove_dpp_pipes_for_plane_composition(
state, pool, plane_state);
for (i = 0; i < stream_status->plane_count; i++) { if (stream_status->plane_states[i] == plane_state) {
dc_plane_state_release(stream_status->plane_states[i]);
break;
}
}
if (i == stream_status->plane_count) {
dm_error("Existing plane_state not found; failed to detach it!\n");
return false;
}
stream_status->plane_count--;
/* Start at the plane we've just released, and move all the planes one index forward to "trim" the array */ for (; i < stream_status->plane_count; i++)
stream_status->plane_states[i] = stream_status->plane_states[i + 1];
/**
* dc_state_rem_all_planes_for_stream - Remove planes attached to the target stream.
*
* @dc: Current dc state.
* @stream: Target stream, which we want to remove the attached plans.
* @state: context from which the planes are to be removed.
*
* Return:
* Return true if DC was able to remove all planes from the target
* stream, otherwise, return false.
*/
bool dc_state_rem_all_planes_for_stream(
const struct dc *dc,
struct dc_stream_state *stream,
struct dc_state *state)
{
int i, old_plane_count;
struct dc_stream_status *stream_status = NULL;
struct dc_plane_state *del_planes[MAX_SURFACES] = { 0 };
for (i = 0; i < state->stream_count; i++) if (state->streams[i] == stream) {
stream_status = &state->stream_status[i];
break;
}
if (stream_status == NULL) {
dm_error("Existing stream %p not found!\n", stream);
return false;
}
old_plane_count = stream_status->plane_count;
for (i = 0; i < old_plane_count; i++)
del_planes[i] = stream_status->plane_states[i];
for (i = 0; i < old_plane_count; i++) if (!dc_state_remove_plane(dc, stream, del_planes[i], state))
return false;
return true;
}
bool dc_state_add_all_planes_for_stream(
const struct dc *dc,
struct dc_stream_state *stream,
struct dc_plane_state * const *plane_states,
int plane_count,
struct dc_state *state)
{
int i;
bool result = true;
for (i = 0; i < plane_count; i++) if (!dc_state_add_plane(dc, stream, plane_states[i], state)) {
result = false;
break;
}
return result;
}
/* Private dc_state functions */
/**
* dc_state_get_stream_status - Get stream status from given dc state
* @state: DC state to find the stream status in
* @stream: The stream to get the stream status for
*
* The given stream is expected to exist in the given dc state. Otherwise, NULL
* will be returned.
*/
struct dc_stream_status *dc_state_get_stream_status(
struct dc_state *state,
const struct dc_stream_state *stream)
{
uint8_t i;
if (state == NULL)
return NULL;
for (i = 0; i < state->stream_count; i++) { if (stream == state->streams[i])
return &state->stream_status[i];
}
for (i = 0; i < state->stream_count; i++) { if (state->streams[i] == stream) {
paired_stream = state->stream_status[i].mall_stream_config.paired_stream;
break;
}
}
if (!dc_state_untrack_phantom_stream(state, phantom_stream)) {
DC_LOG_ERROR("Failed to free phantom stream %p in dc state %p.\n", phantom_stream, state);
return;
}
if (!dc_state_untrack_phantom_plane(state, phantom_plane)) {
DC_LOG_ERROR("Failed to free phantom plane %p in dc state %p.\n", phantom_plane, state);
return;
}
dc_plane_state_release(phantom_plane);
}
/* add phantom streams to context and generate correct meta inside dc_state */
enum dc_status dc_state_add_phantom_stream(const struct dc *dc,
struct dc_state *state,
struct dc_stream_state *phantom_stream,
struct dc_stream_state *main_stream)
{
struct dc_stream_status *main_stream_status;
struct dc_stream_status *phantom_stream_status;
enum dc_status res = dc_state_add_stream(dc, state, phantom_stream);
/* check if stream is tracked */ if (res == DC_OK && !dc_state_is_phantom_stream_tracked(state, phantom_stream)) {
/* stream must be tracked if added to state */
dc_state_track_phantom_stream(state, phantom_stream);
}
/* setup subvp meta */
main_stream_status = dc_state_get_stream_status(state, main_stream); if (main_stream_status) {
main_stream_status->mall_stream_config.type = SUBVP_MAIN;
main_stream_status->mall_stream_config.paired_stream = phantom_stream;
}
/* check if stream is tracked */ if (res && !dc_state_is_phantom_plane_tracked(state, phantom_plane)) {
/* stream must be tracked if added to state */
dc_state_track_phantom_plane(state, phantom_plane);
}
bool dc_state_rem_all_phantom_planes_for_stream(
const struct dc *dc,
struct dc_stream_state *phantom_stream,
struct dc_state *state,
bool should_release_planes)
{
int i, old_plane_count;
struct dc_stream_status *stream_status = NULL;
struct dc_plane_state *del_planes[MAX_SURFACES] = { 0 };
for (i = 0; i < state->stream_count; i++) if (state->streams[i] == phantom_stream) {
stream_status = &state->stream_status[i];
break;
}
if (stream_status == NULL) {
dm_error("Existing stream %p not found!\n", phantom_stream);
return false;
}
old_plane_count = stream_status->plane_count;
for (i = 0; i < old_plane_count; i++)
del_planes[i] = stream_status->plane_states[i];
for (i = 0; i < old_plane_count; i++) { if (!dc_state_remove_plane(dc, phantom_stream, del_planes[i], state))
return false; if (should_release_planes)
dc_state_release_phantom_plane(dc, state, del_planes[i]);
}
for (i = 0; i < state->stream_count; i++) { if (dc_state_get_stream_subvp_type(state, state->streams[i]) != SUBVP_NONE)
return true;
}
return false;
}
Messung V0.5 in Prozent
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.10Bemerkung:
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.