diff --git a/src/gallium/drivers/iris/iris_context.h b/src/gallium/drivers/iris/iris_context.h index 17843dd80c2..004b7fbd061 100644 --- a/src/gallium/drivers/iris/iris_context.h +++ b/src/gallium/drivers/iris/iris_context.h @@ -1014,6 +1014,8 @@ struct iris_context { struct pipe_stencil_ref stencil_ref; struct pipe_framebuffer_state framebuffer; struct pipe_clip_state clip_planes; + /* width and height treated like x2 and y2 */ + struct pipe_box render_area; float default_outer_level[4]; float default_inner_level[2]; diff --git a/src/gallium/drivers/iris/iris_resource.h b/src/gallium/drivers/iris/iris_resource.h index 229c9b9d36c..4b946242636 100644 --- a/src/gallium/drivers/iris/iris_resource.h +++ b/src/gallium/drivers/iris/iris_resource.h @@ -167,6 +167,10 @@ struct iris_resource { * The screen the resource was originally created with, stored for refcounting. */ struct pipe_screen *orig_screen; + + /* width and height treated like x2 and y2 */ + struct pipe_box damage; + bool use_damage; }; /** diff --git a/src/gallium/drivers/iris/iris_screen.c b/src/gallium/drivers/iris/iris_screen.c index 8e7a496ec39..a22a3d64333 100644 --- a/src/gallium/drivers/iris/iris_screen.c +++ b/src/gallium/drivers/iris/iris_screen.c @@ -753,6 +753,40 @@ iris_screen_get_fd(struct pipe_screen *pscreen) return screen->winsys_fd; } +static void +iris_set_damage_region(struct pipe_screen *pscreen, struct pipe_resource *pres, + unsigned int nrects, const struct pipe_box *rects) +{ + struct iris_resource *res = (struct iris_resource *)pres; + + res->use_damage = nrects > 0; + if (!res->use_damage) + return; + + res->damage.x = INT32_MAX; + res->damage.y = INT32_MAX; + res->damage.width = 0; + res->damage.height = 0; + + for (unsigned i = 0; i < nrects; i++) { + res->damage.x = MIN2(res->damage.x, rects[i].x); + res->damage.y = MIN2(res->damage.y, rects[i].y); + res->damage.width = MAX2(res->damage.width, rects[i].width + rects[i].x); + res->damage.height = MAX2(res->damage.height, rects[i].height + rects[i].y); + + if (unlikely(res->damage.x == 0 && + res->damage.y == 0 && + res->damage.width == res->base.b.width0 && + res->damage.height == res->base.b.height0)) + break; + } + + res->damage.x = MAX2(res->damage.x, 0); + res->damage.y = MAX2(res->damage.y, 0); + res->damage.width = MIN2(res->damage.width, res->base.b.width0); + res->damage.height = MIN2(res->damage.height, res->base.b.height0); +} + struct pipe_screen * iris_screen_create(int fd, const struct pipe_screen_config *config) { @@ -881,6 +915,7 @@ iris_screen_create(int fd, const struct pipe_screen_config *config) pscreen->query_memory_info = iris_query_memory_info; pscreen->get_driver_query_group_info = iris_get_monitor_group_info; pscreen->get_driver_query_info = iris_get_monitor_info; + pscreen->set_damage_region = iris_set_damage_region; iris_init_screen_program_functions(pscreen); genX_call(screen->devinfo, init_screen_state, screen); diff --git a/src/gallium/drivers/iris/iris_state.c b/src/gallium/drivers/iris/iris_state.c index 27750d88ff8..36b61761880 100644 --- a/src/gallium/drivers/iris/iris_state.c +++ b/src/gallium/drivers/iris/iris_state.c @@ -3765,6 +3765,8 @@ iris_set_framebuffer_state(struct pipe_context *ctx, struct pipe_framebuffer_state *cso = &ice->state.framebuffer; struct iris_resource *zres; struct iris_resource *stencil_res; + struct iris_resource *new_res = NULL; + struct pipe_box new_render_area; unsigned samples = util_framebuffer_get_num_samples(state); unsigned layers = util_framebuffer_get_num_layers(state); @@ -3795,8 +3797,21 @@ iris_set_framebuffer_state(struct pipe_context *ctx, ice->state.dirty |= IRIS_DIRTY_CLIP; } - if (cso->width != state->width || cso->height != state->height) { + if (state->nr_cbufs > 0 && state->cbufs[0]) + new_res = (struct iris_resource *)state->cbufs[0]->texture; + + if (new_res && new_res->use_damage) { + new_render_area = new_res->damage; + } else { + new_render_area.x = 0; + new_render_area.y = 0; + new_render_area.width = state->width; + new_render_area.height = state->height; + } + + if (memcmp(&ice->state.render_area, &new_render_area, sizeof(new_render_area))) { ice->state.dirty |= IRIS_DIRTY_SF_CL_VIEWPORT; + ice->state.render_area = new_render_area; } if (cso->zsbuf || state->zsbuf) { @@ -6928,6 +6943,7 @@ iris_upload_dirty_render_state(struct iris_context *ice, if (dirty & IRIS_DIRTY_SF_CL_VIEWPORT) { struct pipe_framebuffer_state *cso_fb = &ice->state.framebuffer; + int32_t x_min, y_min, x_max, y_max; uint32_t sf_cl_vp_address; uint32_t *vp_map = stream_state(batch, ice->state.dynamic_uploader, @@ -6935,6 +6951,11 @@ iris_upload_dirty_render_state(struct iris_context *ice, 4 * ice->state.num_viewports * GENX(SF_CLIP_VIEWPORT_length), 64, &sf_cl_vp_address); + x_min = ice->state.render_area.x; + y_min = ice->state.render_area.y; + x_max = ice->state.render_area.width; + y_max = ice->state.render_area.height; + for (unsigned i = 0; i < ice->state.num_viewports; i++) { const struct pipe_viewport_state *state = &ice->state.viewports[i]; float gb_xmin, gb_xmax, gb_ymin, gb_ymax; @@ -6944,7 +6965,7 @@ iris_upload_dirty_render_state(struct iris_context *ice, float vp_ymin = viewport_extent(state, 1, -1.0f); float vp_ymax = viewport_extent(state, 1, 1.0f); - intel_calculate_guardband_size(0, cso_fb->width, 0, cso_fb->height, + intel_calculate_guardband_size(x_min, x_max, y_min, y_max, state->scale[0], state->scale[1], state->translate[0], state->translate[1], &gb_xmin, &gb_xmax, &gb_ymin, &gb_ymax);