Skip to content

Commit

Permalink
more work
Browse files Browse the repository at this point in the history
  • Loading branch information
ammen99 committed Feb 10, 2024
1 parent c764260 commit 1990449
Showing 1 changed file with 85 additions and 38 deletions.
123 changes: 85 additions & 38 deletions plugins/common/wayfire/plugins/common/workspace-wall.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,18 @@ class workspace_wall_t : public wf::signal::provider_t
}
}

void consider_rescale_workspace_buffer(int i, int j)
static int damage_sum_area(const wf::region_t& damage)
{
int sum = 0;
for (const auto& rect : damage)
{
sum += (rect.y2 - rect.y1) * (rect.x2 - rect.x1);
}

return sum;
}

bool consider_rescale_workspace_buffer(int i, int j, wf::region_t& visible_damage)
{
// In general, when rendering the auxilliary buffers for each workspace, we can render the
// workspace thumbnails in a lower resolution, because at the end they are shown scaled.
Expand All @@ -311,19 +322,16 @@ class workspace_wall_t : public wf::signal::provider_t
// Avoid keeping a low resolution if we are going up in the scale (for example, expo exit
// animation) and we're close to the 1.0 scale. Otherwise, we risk popping artifacts as we
// suddenly switch from low to high resolution.
const bool scale_nearly_1 = (render_scale > 0.9) && (render_scale > current_scale);
const bool rescale_magnification = (render_scale > 0.5) && (render_scale > current_scale * 1.1);

// In general, it is worth changing the buffer scale if we have a lot of damage to the old
// buffer, so that for ex. a full re-scale is actually cheaper than repaiting the old buffer.
// This could easily happen for example if we have a video player during Expo start animation.
const auto damage_extents = self->aux_buffer_damage[i][j].get_extents();
const int repaint_cost_current_scale =
((damage_extents.x2 - damage_extents.x1) * (damage_extents.y2 - damage_extents.y1)) *
(current_scale * current_scale);

damage_sum_area(visible_damage) * (current_scale * current_scale);
const int repaint_rescale_cost = (bbox.width * bbox.height) * (render_scale * render_scale);

if ((repaint_cost_current_scale > repaint_rescale_cost) || scale_nearly_1)
if ((repaint_cost_current_scale > repaint_rescale_cost) || rescale_magnification)
{
self->aux_buffer_current_scale[i][j] = render_scale;
self->aux_buffers[i][j].subbuffer = wf::geometry_t{
Expand All @@ -333,29 +341,44 @@ class workspace_wall_t : public wf::signal::provider_t
};

self->aux_buffer_damage[i][j] |= self->workspaces[i][j]->get_bounding_box();
LOGI("Switch scale for ", i, "x", j, " from ", current_scale, " to ", render_scale);
return true;
}

return false;
}

void schedule_instructions(
std::vector<scene::render_instruction_t>& instructions,
const wf::render_target_t& target, wf::region_t& damage) override
{
// Instructions for updating the contents of the workspaces
// Update workspaces in a render pass
for (int i = 0; i < (int)self->workspaces.size(); i++)
{
for (int j = 0; j < (int)self->workspaces[i].size(); j++)
{
consider_rescale_workspace_buffer(i, j);
for (auto& instance : instances[i][j])
const auto ws_bbox = self->wall->get_workspace_rectangle({i, j});
const auto visible_box =
geometry_intersection(self->wall->viewport, ws_bbox) - wf::origin(ws_bbox);
wf::region_t visible_damage = self->aux_buffer_damage[i][j] & visible_box;
if (consider_rescale_workspace_buffer(i, j, visible_damage))
{
visible_damage |= visible_box;
}

if (!visible_damage.empty())
{
instance->schedule_instructions(instructions,
self->aux_buffers[i][j], self->aux_buffer_damage[i][j]);
self->aux_buffer_damage[i][j].clear();
scene::render_pass_params_t params;
params.instances = &instances[i][j];
params.damage = std::move(visible_damage);
params.reference_output = self->wall->output;
params.target = self->aux_buffers[i][j];
scene::run_render_pass(params, scene::RPASS_EMIT_SIGNALS);
self->aux_buffer_damage[i][j] ^= visible_damage;
}
}
}

// Render the wall
instructions.push_back(scene::render_instruction_t{
.instance = this,
.target = target,
Expand All @@ -365,6 +388,20 @@ class workspace_wall_t : public wf::signal::provider_t
damage ^= self->get_bounding_box();
}

static gl_geometry scale_fbox( wf::geometry_t A, wf::geometry_t B, wf::geometry_t box)
{
const float px = 1.0 * (box.x - A.x) / A.width;
const float py = 1.0 * (box.y - A.y) / A.height;
const float px2 = 1.0 * (box.x + box.width - A.x) / A.width;
const float py2 = 1.0 * (box.y + box.height - A.y) / A.height;
return gl_geometry {
B.x + B.width * px,
B.y + B.height * py,
B.x + B.width * px2,
B.y + B.height * py2,
};
}

void render(const wf::render_target_t& target, const wf::region_t& region) override
{
OpenGL::render_begin(target);
Expand All @@ -379,34 +416,31 @@ class workspace_wall_t : public wf::signal::provider_t
auto box = get_workspace_rect({i, j});
auto A = self->wall->viewport;
auto B = self->get_bounding_box();
box = scale_box(A, B, box);

gl_geometry render_geometry = scale_fbox(A, B, box);
auto& buffer = self->aux_buffers[i][j];

float dim = self->wall->get_color_for_workspace({i, j});
const glm::vec4 color = glm::vec4(dim, dim, dim, 1.0);

if (!buffer.subbuffer.has_value())
{
OpenGL::render_transformed_texture(
{buffer.tex}, box, target.get_orthographic_projection());
continue;
OpenGL::render_transformed_texture({buffer.tex},
render_geometry, {}, target.get_orthographic_projection(), color);
} else
{
// The 0.999f come from trying to avoid floating-point artifacts
const gl_geometry tex_geometry = {
0.0f,
1.0f - 0.999f * buffer.subbuffer->height / buffer.viewport_height,
0.999f * buffer.subbuffer->width / buffer.viewport_width,
1.0f,
};

OpenGL::render_transformed_texture({buffer.tex},
render_geometry, tex_geometry,
target.get_orthographic_projection(),
color, OpenGL::TEXTURE_USE_TEX_GEOMETRY);
}

const gl_geometry render_geometry = {
1.0f * box.x,
1.0f * box.y,
1.0f * box.x + box.width,
1.0f * box.y + box.height,
};

const gl_geometry tex_geometry = {
0.0f,
1.0f - 1.0f * buffer.subbuffer->height / buffer.viewport_height,
1.0f * buffer.subbuffer->width / buffer.viewport_width,
1.0f,
};

OpenGL::render_transformed_texture({buffer.tex},
render_geometry, tex_geometry,
target.get_orthographic_projection(),
glm::vec4(1.0), OpenGL::TEXTURE_USE_TEX_GEOMETRY);
}
}
}
Expand Down Expand Up @@ -463,6 +497,19 @@ class workspace_wall_t : public wf::signal::provider_t
}
}

~workspace_wall_node_t()
{
OpenGL::render_begin();
for (auto& [_, buffers] : aux_buffers)
{
for (auto& [_, buffer] : buffers)
{
buffer.release();
}
}
OpenGL::render_end();
}

virtual void gen_render_instances(
std::vector<scene::render_instance_uptr>& instances,
scene::damage_callback push_damage, wf::output_t *shown_on) override
Expand Down

0 comments on commit 1990449

Please sign in to comment.