We rename do_blorp_blit() to try_blorp_blit(), and add a return error if the surface size for the blit is too large. Now, do_blorp_blit() is rewritten to try to split the blit into smaller operations if try_blorp_blit() fails.
Note: In this commit, try_blorp_blit() will always attempt to blit and never return an error, which matches the previous behavior. We will enable the size checking and splitting in a future commit. The motivation for this splitting is that in some cases when we flatten an image, it's dimensions grow, and this can then exceed the programmable hardware limits. An example is w-tiled+MSAA blits. Signed-off-by: Jordan Justen <jordan.l.jus...@intel.com> --- src/intel/blorp/blorp_blit.c | 93 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 87 insertions(+), 6 deletions(-) diff --git a/src/intel/blorp/blorp_blit.c b/src/intel/blorp/blorp_blit.c index 24c4fd6..caa3e33 100644 --- a/src/intel/blorp/blorp_blit.c +++ b/src/intel/blorp/blorp_blit.c @@ -1530,11 +1530,18 @@ struct blt_coords { struct blt_axis x, y; }; -static void -do_blorp_blit(struct blorp_batch *batch, - struct blorp_params *params, - struct brw_blorp_blit_prog_key *wm_prog_key, - const struct blt_coords *coords) +#define BLIT_WIDTH_TOO_LARGE 1 +#define BLIT_HEIGHT_TOO_LARGE 2 + +/* Try to blit. If the surface parameters exceed the size allowed by hardware, + * then a bitmask of BLIT_WIDTH_TOO_LARGE and BLIT_HEIGHT_TOO_LARGE will be + * returned. If 0 is returned, then the blit was successful. + */ +static unsigned +try_blorp_blit(struct blorp_batch *batch, + struct blorp_params *params, + struct brw_blorp_blit_prog_key *wm_prog_key, + const struct blt_coords *coords) { const struct gen_device_info *devinfo = batch->blorp->isl_dev->info; @@ -1737,7 +1744,81 @@ do_blorp_blit(struct blorp_batch *batch, brw_blorp_get_blit_kernel(batch->blorp, params, wm_prog_key); - batch->blorp->exec(batch, params); + unsigned result = 0; + + if (result == 0) { + batch->blorp->exec(batch, params); + } + + return result; +} + +/* Adjust split blit source coordinates for the current destination + * coordinates. + */ +static void +adjust_split_coords(const struct blt_axis *orig, + struct blt_axis *split_coords, + float scale) +{ + float delta0 = scale * (split_coords->dst0 - orig->dst0); + float delta1 = scale * (split_coords->dst1 - orig->dst1); + split_coords->src0 = orig->src0 + (scale >= 0.0 ? delta0 : delta1); + split_coords->src1 = orig->src1 + (scale >= 0.0 ? delta1 : delta0); +} + +static void +do_blorp_blit(struct blorp_batch *batch, + struct blorp_params *params, + struct brw_blorp_blit_prog_key *wm_prog_key, + const struct blt_coords *orig) +{ + struct blt_coords split_coords = *orig; + float w = orig->x.dst1 - orig->x.dst0; + float h = orig->y.dst1 - orig->y.dst0; + float x_scale = (orig->x.src1 - orig->x.src0) / w; + float y_scale = (orig->y.src1 - orig->y.src0) / h; + if (orig->x.mirror) + x_scale = -x_scale; + if (orig->y.mirror) + y_scale = -y_scale; + + bool x_done, y_done; + do { + unsigned result = + try_blorp_blit(batch, params, wm_prog_key, &split_coords); + + if (result & BLIT_WIDTH_TOO_LARGE) { + w /= 2.0; + assert(w >= 1.0); + split_coords.x.dst1 = MIN2(split_coords.x.dst0 + w, orig->x.dst1); + adjust_split_coords(&orig->x, &split_coords.x, x_scale); + } + if (result & BLIT_HEIGHT_TOO_LARGE) { + h /= 2.0; + assert(h >= 1.0); + split_coords.y.dst1 = MIN2(split_coords.y.dst0 + h, orig->y.dst1); + adjust_split_coords(&orig->y, &split_coords.y, y_scale); + } + + if (result != 0) + continue; + + y_done = (orig->y.dst1 - split_coords.y.dst1 < 0.5); + x_done = y_done && (orig->x.dst1 - split_coords.x.dst1 < 0.5); + if (x_done) { + break; + } else if (y_done) { + split_coords.x.dst0 += w; + split_coords.x.dst1 = MIN2(split_coords.x.dst0 + w, orig->x.dst1); + split_coords.y.dst0 = orig->y.dst0; + adjust_split_coords(&orig->x, &split_coords.x, x_scale); + } else { + split_coords.y.dst0 += h; + split_coords.y.dst1 = MIN2(split_coords.y.dst0 + h, orig->y.dst1); + adjust_split_coords(&orig->y, &split_coords.y, y_scale); + } + } while (true); } void -- 2.10.2 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev