diff options
-rw-r--r-- | src/gallium/drivers/ilo/ilo_blit.c | 262 | ||||
-rw-r--r-- | src/gallium/drivers/ilo/ilo_context.c | 10 | ||||
-rw-r--r-- | src/gallium/drivers/ilo/ilo_context.h | 2 |
3 files changed, 269 insertions, 5 deletions
diff --git a/src/gallium/drivers/ilo/ilo_blit.c b/src/gallium/drivers/ilo/ilo_blit.c index ce4801d46b6..20e09ae340b 100644 --- a/src/gallium/drivers/ilo/ilo_blit.c +++ b/src/gallium/drivers/ilo/ilo_blit.c @@ -25,19 +25,271 @@ * Chia-I Wu <[email protected]> */ +#include "util/u_blitter.h" +#include "util/u_clear.h" +#include "util/u_pack_color.h" +#include "util/u_surface.h" +#include "intel_reg.h" + #include "ilo_context.h" +#include "ilo_cp.h" +#include "ilo_resource.h" +#include "ilo_screen.h" #include "ilo_blit.h" +static bool +blitter_xy_color_blt(struct pipe_context *pipe, + struct pipe_resource *r, + int16_t x1, int16_t y1, + int16_t x2, int16_t y2, + uint32_t color) +{ + const int cmd_len = 6; + struct ilo_context *ilo = ilo_context(pipe); + struct ilo_resource *res = ilo_resource(r); + uint32_t cmd, br13; + int cpp, stride; + struct intel_bo *bo_check[2]; + + /* how to support Y-tiling? */ + if (res->tiling == INTEL_TILING_Y) + return false; + + /* nothing to clear */ + if (x1 >= x2 || y1 >= y2) + return true; + + cmd = XY_COLOR_BLT_CMD | (cmd_len - 2); + br13 = 0xf0 << 16; + + cpp = util_format_get_blocksize(res->base.format); + switch (cpp) { + case 4: + cmd |= XY_BLT_WRITE_ALPHA | XY_BLT_WRITE_RGB; + br13 |= BR13_8888; + break; + case 2: + br13 |= BR13_565; + break; + case 1: + br13 |= BR13_8; + break; + default: + return false; + break; + } + + stride = res->bo_stride; + if (res->tiling != INTEL_TILING_NONE) { + assert(res->tiling == INTEL_TILING_X); + + cmd |= XY_DST_TILED; + /* in dwords */ + stride /= 4; + } + + /* make room if necessary */ + bo_check[0] = ilo->cp->bo; + bo_check[1] = res->bo; + if (ilo->winsys->check_aperture_space(ilo->winsys, bo_check, 2)) + ilo_cp_flush(ilo->cp); + + ilo_cp_set_ring(ilo->cp, ILO_CP_RING_BLT); + + ilo_cp_begin(ilo->cp, cmd_len); + ilo_cp_write(ilo->cp, cmd); + ilo_cp_write(ilo->cp, br13 | stride); + ilo_cp_write(ilo->cp, (y1 << 16) | x1); + ilo_cp_write(ilo->cp, (y2 << 16) | x2); + ilo_cp_write_bo(ilo->cp, 0, res->bo, + INTEL_DOMAIN_RENDER, + INTEL_DOMAIN_RENDER); + ilo_cp_write(ilo->cp, color); + ilo_cp_end(ilo->cp); + + return true; +} + +enum ilo_blitter_op { + ILO_BLITTER_CLEAR, + ILO_BLITTER_CLEAR_SURFACE, + ILO_BLITTER_BLIT, +}; + +static void +ilo_blitter_begin(struct ilo_context *ilo, enum ilo_blitter_op op) +{ + /* as documented in util/u_blitter.h */ + util_blitter_save_vertex_buffer_slot(ilo->blitter, + ilo->vertex_buffers.buffers); + util_blitter_save_vertex_elements(ilo->blitter, ilo->vertex_elements); + util_blitter_save_vertex_shader(ilo->blitter, ilo->vs); + util_blitter_save_geometry_shader(ilo->blitter, ilo->gs); + util_blitter_save_so_targets(ilo->blitter, + ilo->stream_output_targets.num_targets, + ilo->stream_output_targets.targets); + + util_blitter_save_fragment_shader(ilo->blitter, ilo->fs); + util_blitter_save_depth_stencil_alpha(ilo->blitter, + ilo->depth_stencil_alpha); + util_blitter_save_blend(ilo->blitter, ilo->blend); + + /* undocumented? */ + util_blitter_save_viewport(ilo->blitter, &ilo->viewport); + util_blitter_save_stencil_ref(ilo->blitter, &ilo->stencil_ref); + util_blitter_save_sample_mask(ilo->blitter, ilo->sample_mask); + + switch (op) { + case ILO_BLITTER_CLEAR: + util_blitter_save_rasterizer(ilo->blitter, ilo->rasterizer); + break; + case ILO_BLITTER_CLEAR_SURFACE: + util_blitter_save_framebuffer(ilo->blitter, &ilo->framebuffer); + break; + case ILO_BLITTER_BLIT: + util_blitter_save_rasterizer(ilo->blitter, ilo->rasterizer); + util_blitter_save_framebuffer(ilo->blitter, &ilo->framebuffer); + + util_blitter_save_fragment_sampler_states(ilo->blitter, + ilo->samplers[PIPE_SHADER_FRAGMENT].num_samplers, + (void **) ilo->samplers[PIPE_SHADER_FRAGMENT].samplers); + + util_blitter_save_fragment_sampler_views(ilo->blitter, + ilo->sampler_views[PIPE_SHADER_FRAGMENT].num_views, + ilo->sampler_views[PIPE_SHADER_FRAGMENT].views); + + /* disable render condition? */ + break; + default: + break; + } +} + +static void +ilo_blitter_end(struct ilo_context *ilo) +{ +} + +static void +ilo_clear(struct pipe_context *pipe, + unsigned buffers, + const union pipe_color_union *color, + double depth, + unsigned stencil) +{ + struct ilo_context *ilo = ilo_context(pipe); + + /* TODO we should pause/resume some queries */ + ilo_blitter_begin(ilo, ILO_BLITTER_CLEAR); + + util_blitter_clear(ilo->blitter, + ilo->framebuffer.width, ilo->framebuffer.height, + ilo->framebuffer.nr_cbufs, buffers, + (ilo->framebuffer.nr_cbufs) ? ilo->framebuffer.cbufs[0]->format : + PIPE_FORMAT_NONE, + color, depth, stencil); + + ilo_blitter_end(ilo); +} + +static void +ilo_clear_render_target(struct pipe_context *pipe, + struct pipe_surface *dst, + const union pipe_color_union *color, + unsigned dstx, unsigned dsty, + unsigned width, unsigned height) +{ + struct ilo_context *ilo = ilo_context(pipe); + union util_color packed; + + if (!width || !height || dstx >= dst->width || dsty >= dst->height) + return; + + if (dstx + width > dst->width) + width = dst->width - dstx; + if (dsty + height > dst->height) + height = dst->height - dsty; + + util_pack_color(color->f, dst->format, &packed); + + /* try HW blit first */ + if (blitter_xy_color_blt(pipe, dst->texture, + dstx, dsty, + dstx + width, dsty + height, + packed.ui)) + return; + + ilo_blitter_begin(ilo, ILO_BLITTER_CLEAR_SURFACE); + util_blitter_clear_render_target(ilo->blitter, + dst, color, dstx, dsty, width, height); + ilo_blitter_end(ilo); +} + +static void +ilo_clear_depth_stencil(struct pipe_context *pipe, + struct pipe_surface *dst, + unsigned clear_flags, + double depth, + unsigned stencil, + unsigned dstx, unsigned dsty, + unsigned width, unsigned height) +{ + struct ilo_context *ilo = ilo_context(pipe); + + /* + * The PRM claims that HW blit supports Y-tiling since GEN6, but it does + * not tell us how to program it. Since depth buffers are always Y-tiled, + * HW blit will not work. + */ + ilo_blitter_begin(ilo, ILO_BLITTER_CLEAR_SURFACE); + util_blitter_clear_depth_stencil(ilo->blitter, + dst, clear_flags, depth, stencil, dstx, dsty, width, height); + ilo_blitter_end(ilo); +} + +static void +ilo_blit(struct pipe_context *pipe, const struct pipe_blit_info *info) +{ + struct ilo_context *ilo = ilo_context(pipe); + struct pipe_blit_info skip_stencil; + + if (util_try_blit_via_copy_region(pipe, info)) + return; + + if (!util_blitter_is_blit_supported(ilo->blitter, info)) { + /* try without stencil */ + if (info->mask & PIPE_MASK_S) { + skip_stencil = *info; + skip_stencil.mask = info->mask & ~PIPE_MASK_S; + + if (util_blitter_is_blit_supported(ilo->blitter, &skip_stencil)) + info = &skip_stencil; + } + + if (info == &skip_stencil) { + ilo_warn("ignore stencil buffer blitting\n"); + } + else { + ilo_warn("failed to blit with the generic blitter\n"); + return; + } + } + + ilo_blitter_begin(ilo, ILO_BLITTER_BLIT); + util_blitter_blit(ilo->blitter, info); + ilo_blitter_end(ilo); +} + /** * Initialize blit-related functions. */ void ilo_init_blit_functions(struct ilo_context *ilo) { - ilo->base.resource_copy_region = NULL; - ilo->base.blit = NULL; + ilo->base.resource_copy_region = util_resource_copy_region; + ilo->base.blit = ilo_blit; - ilo->base.clear = NULL; - ilo->base.clear_render_target = NULL; - ilo->base.clear_depth_stencil = NULL; + ilo->base.clear = ilo_clear; + ilo->base.clear_render_target = ilo_clear_render_target; + ilo->base.clear_depth_stencil = ilo_clear_depth_stencil; } diff --git a/src/gallium/drivers/ilo/ilo_context.c b/src/gallium/drivers/ilo/ilo_context.c index d92b07811ea..82da56e7196 100644 --- a/src/gallium/drivers/ilo/ilo_context.c +++ b/src/gallium/drivers/ilo/ilo_context.c @@ -25,6 +25,7 @@ * Chia-I Wu <[email protected]> */ +#include "util/u_blitter.h" #include "intel_chipset.h" #include "ilo_3d.h" @@ -100,6 +101,8 @@ ilo_context_destroy(struct pipe_context *pipe) if (ilo->last_cp_bo) ilo->last_cp_bo->unreference(ilo->last_cp_bo); + if (ilo->blitter) + util_blitter_destroy(ilo->blitter); if (ilo->shader_cache) ilo_shader_cache_destroy(ilo->shader_cache); if (ilo->cp) @@ -203,6 +206,13 @@ ilo_context_create(struct pipe_screen *screen, void *priv) ilo_init_video_functions(ilo); ilo_init_gpgpu_functions(ilo); + /* this must be called last as u_blitter is a client of the pipe context */ + ilo->blitter = util_blitter_create(&ilo->base); + if (!ilo->blitter) { + ilo_context_destroy(&ilo->base); + return NULL; + } + return &ilo->base; } diff --git a/src/gallium/drivers/ilo/ilo_context.h b/src/gallium/drivers/ilo/ilo_context.h index 107961d57c6..58fee1f1821 100644 --- a/src/gallium/drivers/ilo/ilo_context.h +++ b/src/gallium/drivers/ilo/ilo_context.h @@ -54,6 +54,7 @@ #define ILO_WM_CONST_SURFACE(i) (ILO_MAX_DRAW_BUFFERS + i) #define ILO_WM_TEXTURE_SURFACE(i) (ILO_MAX_DRAW_BUFFERS + ILO_MAX_CONST_BUFFERS + i) +struct blitter_context; struct intel_winsys; struct intel_bo; struct ilo_cp; @@ -86,6 +87,7 @@ struct ilo_context { struct intel_bo *last_cp_bo; struct ilo_shader_cache *shader_cache; + struct blitter_context *blitter; uint32_t dirty; |