Path: blob/21.2-virgl/src/gallium/auxiliary/util/u_blitter.c
4561 views
/**************************************************************************1*2* Copyright 2009 Marek Olšák <[email protected]>3*4* Permission is hereby granted, free of charge, to any person obtaining a5* copy of this software and associated documentation files (the6* "Software"), to deal in the Software without restriction, including7* without limitation the rights to use, copy, modify, merge, publish,8* distribute, sub license, and/or sell copies of the Software, and to9* permit persons to whom the Software is furnished to do so, subject to10* the following conditions:11*12* The above copyright notice and this permission notice (including the13* next paragraph) shall be included in all copies or substantial portions14* of the Software.15*16* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS17* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF18* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.19* IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR20* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,21* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE22* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.23*24**************************************************************************/2526/**27* @file28* Blitter utility to facilitate acceleration of the clear, clear_render_target,29* clear_depth_stencil, resource_copy_region, and blit functions.30*31* @author Marek Olšák32*/3334#include "pipe/p_context.h"35#include "pipe/p_defines.h"36#include "util/u_inlines.h"37#include "pipe/p_shader_tokens.h"38#include "pipe/p_state.h"3940#include "util/format/u_format.h"41#include "util/u_memory.h"42#include "util/u_math.h"43#include "util/u_blitter.h"44#include "util/u_draw_quad.h"45#include "util/u_sampler.h"46#include "util/u_simple_shaders.h"47#include "util/u_surface.h"48#include "util/u_texture.h"49#include "util/u_upload_mgr.h"5051#define INVALID_PTR ((void*)~0)5253#define GET_CLEAR_BLEND_STATE_IDX(clear_buffers) \54((clear_buffers) / PIPE_CLEAR_COLOR0)5556#define NUM_RESOLVE_FRAG_SHADERS 5 /* MSAA 2x, 4x, 8x, 16x, 32x */57#define GET_MSAA_RESOLVE_FS_IDX(nr_samples) (util_logbase2(nr_samples)-1)5859struct blitter_context_priv60{61struct blitter_context base;6263float vertices[4][2][4]; /**< {pos, color} or {pos, texcoord} */6465/* Templates for various state objects. */6667/* Constant state objects. */68/* Vertex shaders. */69void *vs; /**< Vertex shader which passes {pos, generic} to the output.*/70void *vs_nogeneric;71void *vs_pos_only[4]; /**< Vertex shader which passes pos to the output72for clear_buffer/copy_buffer.*/73void *vs_layered; /**< Vertex shader which sets LAYER = INSTANCEID. */7475/* Fragment shaders. */76void *fs_empty;77void *fs_write_one_cbuf;78void *fs_write_all_cbufs;7980/* FS which outputs a color from a texture where81* the 1st index indicates the texture type / destination type,82* the 2nd index is the PIPE_TEXTURE_* to be sampled,83* the 3rd index is 0 = use TEX, 1 = use TXF.84*/85void *fs_texfetch_col[5][PIPE_MAX_TEXTURE_TYPES][2];8687/* FS which outputs a depth from a texture, where88* the 1st index is the PIPE_TEXTURE_* to be sampled,89* the 2nd index is 0 = use TEX, 1 = use TXF.90*/91void *fs_texfetch_depth[PIPE_MAX_TEXTURE_TYPES][2];92void *fs_texfetch_depthstencil[PIPE_MAX_TEXTURE_TYPES][2];93void *fs_texfetch_stencil[PIPE_MAX_TEXTURE_TYPES][2];9495/* FS which outputs one sample from a multisample texture. */96void *fs_texfetch_col_msaa[5][PIPE_MAX_TEXTURE_TYPES];97void *fs_texfetch_depth_msaa[PIPE_MAX_TEXTURE_TYPES];98void *fs_texfetch_depthstencil_msaa[PIPE_MAX_TEXTURE_TYPES];99void *fs_texfetch_stencil_msaa[PIPE_MAX_TEXTURE_TYPES];100101/* FS which outputs an average of all samples. */102void *fs_resolve[PIPE_MAX_TEXTURE_TYPES][NUM_RESOLVE_FRAG_SHADERS][2];103104/* FS which unpacks color to ZS or packs ZS to color, matching105* the ZS format. See util_blitter_get_color_format_for_zs().106*/107void *fs_pack_color_zs[TGSI_TEXTURE_COUNT][10];108109/* FS which is meant for replicating indevidual stencil-buffer bits */110void *fs_stencil_blit_fallback[2];111112/* Blend state. */113void *blend[PIPE_MASK_RGBA+1][2]; /**< blend state with writemask */114void *blend_clear[GET_CLEAR_BLEND_STATE_IDX(PIPE_CLEAR_COLOR)+1];115116/* Depth stencil alpha state. */117void *dsa_write_depth_stencil;118void *dsa_write_depth_keep_stencil;119void *dsa_keep_depth_stencil;120void *dsa_keep_depth_write_stencil;121void *dsa_replicate_stencil_bit[8];122123/* Vertex elements states. */124void *velem_state;125void *velem_state_readbuf[4]; /**< X, XY, XYZ, XYZW */126127/* Sampler state. */128void *sampler_state;129void *sampler_state_linear;130void *sampler_state_rect;131void *sampler_state_rect_linear;132133/* Rasterizer state. */134void *rs_state[2][2]; /**< [scissor][msaa] */135void *rs_discard_state;136137/* Destination surface dimensions. */138unsigned dst_width;139unsigned dst_height;140141void *custom_vs;142143bool has_geometry_shader;144bool has_tessellation;145bool has_layered;146bool has_stream_out;147bool has_stencil_export;148bool has_texture_multisample;149bool has_tex_lz;150bool has_txf;151bool cube_as_2darray;152bool cached_all_shaders;153154/* The Draw module overrides these functions.155* Always create the blitter before Draw. */156void (*bind_fs_state)(struct pipe_context *, void *);157void (*delete_fs_state)(struct pipe_context *, void *);158};159160struct blitter_context *util_blitter_create(struct pipe_context *pipe)161{162struct blitter_context_priv *ctx;163struct pipe_blend_state blend;164struct pipe_depth_stencil_alpha_state dsa;165struct pipe_rasterizer_state rs_state;166struct pipe_sampler_state sampler_state;167struct pipe_vertex_element velem[2];168unsigned i, j;169170ctx = CALLOC_STRUCT(blitter_context_priv);171if (!ctx)172return NULL;173174ctx->base.pipe = pipe;175ctx->base.draw_rectangle = util_blitter_draw_rectangle;176177ctx->bind_fs_state = pipe->bind_fs_state;178ctx->delete_fs_state = pipe->delete_fs_state;179180/* init state objects for them to be considered invalid */181ctx->base.saved_blend_state = INVALID_PTR;182ctx->base.saved_dsa_state = INVALID_PTR;183ctx->base.saved_rs_state = INVALID_PTR;184ctx->base.saved_fs = INVALID_PTR;185ctx->base.saved_vs = INVALID_PTR;186ctx->base.saved_gs = INVALID_PTR;187ctx->base.saved_velem_state = INVALID_PTR;188ctx->base.saved_fb_state.nr_cbufs = ~0;189ctx->base.saved_num_sampler_views = ~0;190ctx->base.saved_num_sampler_states = ~0;191ctx->base.saved_num_so_targets = ~0;192193ctx->has_geometry_shader =194pipe->screen->get_shader_param(pipe->screen, PIPE_SHADER_GEOMETRY,195PIPE_SHADER_CAP_MAX_INSTRUCTIONS) > 0;196197ctx->has_tessellation =198pipe->screen->get_shader_param(pipe->screen, PIPE_SHADER_TESS_CTRL,199PIPE_SHADER_CAP_MAX_INSTRUCTIONS) > 0;200201ctx->has_stream_out =202pipe->screen->get_param(pipe->screen,203PIPE_CAP_MAX_STREAM_OUTPUT_BUFFERS) != 0;204205ctx->has_stencil_export =206pipe->screen->get_param(pipe->screen,207PIPE_CAP_SHADER_STENCIL_EXPORT);208209ctx->has_texture_multisample =210pipe->screen->get_param(pipe->screen, PIPE_CAP_TEXTURE_MULTISAMPLE);211212ctx->has_tex_lz = pipe->screen->get_param(pipe->screen,213PIPE_CAP_TGSI_TEX_TXF_LZ);214ctx->has_txf = pipe->screen->get_param(pipe->screen,215PIPE_CAP_GLSL_FEATURE_LEVEL) > 130;216ctx->cube_as_2darray = pipe->screen->get_param(pipe->screen,217PIPE_CAP_SAMPLER_VIEW_TARGET);218219/* blend state objects */220memset(&blend, 0, sizeof(blend));221222for (i = 0; i <= PIPE_MASK_RGBA; i++) {223for (j = 0; j < 2; j++) {224memset(&blend.rt[0], 0, sizeof(blend.rt[0]));225blend.rt[0].colormask = i;226if (j) {227blend.rt[0].blend_enable = 1;228blend.rt[0].rgb_func = PIPE_BLEND_ADD;229blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_SRC_ALPHA;230blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_INV_SRC_ALPHA;231blend.rt[0].alpha_func = PIPE_BLEND_ADD;232blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_SRC_ALPHA;233blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_INV_SRC_ALPHA;234}235ctx->blend[i][j] = pipe->create_blend_state(pipe, &blend);236}237}238239/* depth stencil alpha state objects */240memset(&dsa, 0, sizeof(dsa));241ctx->dsa_keep_depth_stencil =242pipe->create_depth_stencil_alpha_state(pipe, &dsa);243244dsa.depth_enabled = 1;245dsa.depth_writemask = 1;246dsa.depth_func = PIPE_FUNC_ALWAYS;247ctx->dsa_write_depth_keep_stencil =248pipe->create_depth_stencil_alpha_state(pipe, &dsa);249250dsa.stencil[0].enabled = 1;251dsa.stencil[0].func = PIPE_FUNC_ALWAYS;252dsa.stencil[0].fail_op = PIPE_STENCIL_OP_REPLACE;253dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_REPLACE;254dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_REPLACE;255dsa.stencil[0].valuemask = 0xff;256dsa.stencil[0].writemask = 0xff;257ctx->dsa_write_depth_stencil =258pipe->create_depth_stencil_alpha_state(pipe, &dsa);259260dsa.depth_enabled = 0;261dsa.depth_writemask = 0;262ctx->dsa_keep_depth_write_stencil =263pipe->create_depth_stencil_alpha_state(pipe, &dsa);264265/* sampler state */266memset(&sampler_state, 0, sizeof(sampler_state));267sampler_state.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;268sampler_state.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;269sampler_state.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;270sampler_state.normalized_coords = 1;271ctx->sampler_state = pipe->create_sampler_state(pipe, &sampler_state);272sampler_state.normalized_coords = 0;273ctx->sampler_state_rect = pipe->create_sampler_state(pipe, &sampler_state);274275sampler_state.min_img_filter = PIPE_TEX_FILTER_LINEAR;276sampler_state.mag_img_filter = PIPE_TEX_FILTER_LINEAR;277sampler_state.normalized_coords = 1;278ctx->sampler_state_linear = pipe->create_sampler_state(pipe, &sampler_state);279sampler_state.normalized_coords = 0;280ctx->sampler_state_rect_linear = pipe->create_sampler_state(pipe, &sampler_state);281282/* rasterizer state */283memset(&rs_state, 0, sizeof(rs_state));284rs_state.cull_face = PIPE_FACE_NONE;285rs_state.half_pixel_center = 1;286rs_state.bottom_edge_rule = 1;287rs_state.flatshade = 1;288rs_state.depth_clip_near = 1;289rs_state.depth_clip_far = 1;290291unsigned scissor, msaa;292for (scissor = 0; scissor < 2; scissor++) {293for (msaa = 0; msaa < 2; msaa++) {294rs_state.scissor = scissor;295rs_state.multisample = msaa;296ctx->rs_state[scissor][msaa] =297pipe->create_rasterizer_state(pipe, &rs_state);298}299}300301if (ctx->has_stream_out) {302rs_state.scissor = rs_state.multisample = 0;303rs_state.rasterizer_discard = 1;304ctx->rs_discard_state = pipe->create_rasterizer_state(pipe, &rs_state);305}306307ctx->base.cb_slot = 0; /* 0 for now */308ctx->base.vb_slot = 0; /* 0 for now */309310/* vertex elements states */311memset(&velem[0], 0, sizeof(velem[0]) * 2);312for (i = 0; i < 2; i++) {313velem[i].src_offset = i * 4 * sizeof(float);314velem[i].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;315velem[i].vertex_buffer_index = ctx->base.vb_slot;316}317ctx->velem_state = pipe->create_vertex_elements_state(pipe, 2, &velem[0]);318319if (ctx->has_stream_out) {320static enum pipe_format formats[4] = {321PIPE_FORMAT_R32_UINT,322PIPE_FORMAT_R32G32_UINT,323PIPE_FORMAT_R32G32B32_UINT,324PIPE_FORMAT_R32G32B32A32_UINT325};326327for (i = 0; i < 4; i++) {328velem[0].src_format = formats[i];329velem[0].vertex_buffer_index = ctx->base.vb_slot;330ctx->velem_state_readbuf[i] =331pipe->create_vertex_elements_state(pipe, 1, &velem[0]);332}333}334335ctx->has_layered =336pipe->screen->get_param(pipe->screen, PIPE_CAP_TGSI_INSTANCEID) &&337pipe->screen->get_param(pipe->screen, PIPE_CAP_TGSI_VS_LAYER_VIEWPORT);338339/* set invariant vertex coordinates */340for (i = 0; i < 4; i++) {341ctx->vertices[i][0][2] = 0; /*v.z*/342ctx->vertices[i][0][3] = 1; /*v.w*/343}344345return &ctx->base;346}347348void *util_blitter_get_noop_blend_state(struct blitter_context *blitter)349{350struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;351352return ctx->blend[0][0];353}354355void *util_blitter_get_noop_dsa_state(struct blitter_context *blitter)356{357struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;358359return ctx->dsa_keep_depth_stencil;360}361362void *util_blitter_get_discard_rasterizer_state(struct blitter_context *blitter)363{364struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;365366return ctx->rs_discard_state;367}368369static void bind_vs_pos_only(struct blitter_context_priv *ctx,370unsigned num_so_channels)371{372struct pipe_context *pipe = ctx->base.pipe;373int index = num_so_channels ? num_so_channels - 1 : 0;374375if (!ctx->vs_pos_only[index]) {376struct pipe_stream_output_info so;377static const enum tgsi_semantic semantic_names[] =378{ TGSI_SEMANTIC_POSITION };379const uint semantic_indices[] = { 0 };380381memset(&so, 0, sizeof(so));382so.num_outputs = 1;383so.output[0].num_components = num_so_channels;384so.stride[0] = num_so_channels;385386ctx->vs_pos_only[index] =387util_make_vertex_passthrough_shader_with_so(pipe, 1, semantic_names,388semantic_indices, false,389false, &so);390}391392pipe->bind_vs_state(pipe, ctx->vs_pos_only[index]);393}394395static void *get_vs_passthrough_pos_generic(struct blitter_context *blitter)396{397struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;398struct pipe_context *pipe = ctx->base.pipe;399400if (!ctx->vs) {401static const enum tgsi_semantic semantic_names[] =402{ TGSI_SEMANTIC_POSITION, TGSI_SEMANTIC_GENERIC };403const uint semantic_indices[] = { 0, 0 };404ctx->vs =405util_make_vertex_passthrough_shader(pipe, 2, semantic_names,406semantic_indices, false);407}408return ctx->vs;409}410411static void *get_vs_passthrough_pos(struct blitter_context *blitter)412{413struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;414struct pipe_context *pipe = ctx->base.pipe;415416if (!ctx->vs_nogeneric) {417static const enum tgsi_semantic semantic_names[] =418{ TGSI_SEMANTIC_POSITION };419const uint semantic_indices[] = { 0 };420421ctx->vs_nogeneric =422util_make_vertex_passthrough_shader(pipe, 1,423semantic_names,424semantic_indices, false);425}426return ctx->vs_nogeneric;427}428429static void *get_vs_layered(struct blitter_context *blitter)430{431struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;432struct pipe_context *pipe = ctx->base.pipe;433434if (!ctx->vs_layered) {435ctx->vs_layered = util_make_layered_clear_vertex_shader(pipe);436}437return ctx->vs_layered;438}439440static void bind_fs_empty(struct blitter_context_priv *ctx)441{442struct pipe_context *pipe = ctx->base.pipe;443444if (!ctx->fs_empty) {445assert(!ctx->cached_all_shaders);446ctx->fs_empty = util_make_empty_fragment_shader(pipe);447}448449ctx->bind_fs_state(pipe, ctx->fs_empty);450}451452static void bind_fs_write_one_cbuf(struct blitter_context_priv *ctx)453{454struct pipe_context *pipe = ctx->base.pipe;455456if (!ctx->fs_write_one_cbuf) {457assert(!ctx->cached_all_shaders);458ctx->fs_write_one_cbuf =459util_make_fragment_passthrough_shader(pipe, TGSI_SEMANTIC_GENERIC,460TGSI_INTERPOLATE_CONSTANT, false);461}462463ctx->bind_fs_state(pipe, ctx->fs_write_one_cbuf);464}465466static void bind_fs_write_all_cbufs(struct blitter_context_priv *ctx)467{468struct pipe_context *pipe = ctx->base.pipe;469470if (!ctx->fs_write_all_cbufs) {471assert(!ctx->cached_all_shaders);472ctx->fs_write_all_cbufs =473util_make_fragment_passthrough_shader(pipe, TGSI_SEMANTIC_GENERIC,474TGSI_INTERPOLATE_CONSTANT, true);475}476477ctx->bind_fs_state(pipe, ctx->fs_write_all_cbufs);478}479480void util_blitter_destroy(struct blitter_context *blitter)481{482struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;483struct pipe_context *pipe = blitter->pipe;484unsigned i, j, f;485486for (i = 0; i <= PIPE_MASK_RGBA; i++)487for (j = 0; j < 2; j++)488pipe->delete_blend_state(pipe, ctx->blend[i][j]);489490for (i = 0; i < ARRAY_SIZE(ctx->blend_clear); i++) {491if (ctx->blend_clear[i])492pipe->delete_blend_state(pipe, ctx->blend_clear[i]);493}494pipe->delete_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil);495pipe->delete_depth_stencil_alpha_state(pipe,496ctx->dsa_write_depth_keep_stencil);497pipe->delete_depth_stencil_alpha_state(pipe, ctx->dsa_write_depth_stencil);498pipe->delete_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_write_stencil);499500for (i = 0; i < ARRAY_SIZE(ctx->dsa_replicate_stencil_bit); i++) {501if (ctx->dsa_replicate_stencil_bit[i])502pipe->delete_depth_stencil_alpha_state(pipe, ctx->dsa_replicate_stencil_bit[i]);503}504505unsigned scissor, msaa;506for (scissor = 0; scissor < 2; scissor++) {507for (msaa = 0; msaa < 2; msaa++) {508pipe->delete_rasterizer_state(pipe, ctx->rs_state[scissor][msaa]);509}510}511512if (ctx->rs_discard_state)513pipe->delete_rasterizer_state(pipe, ctx->rs_discard_state);514if (ctx->vs)515pipe->delete_vs_state(pipe, ctx->vs);516if (ctx->vs_nogeneric)517pipe->delete_vs_state(pipe, ctx->vs_nogeneric);518for (i = 0; i < 4; i++)519if (ctx->vs_pos_only[i])520pipe->delete_vs_state(pipe, ctx->vs_pos_only[i]);521if (ctx->vs_layered)522pipe->delete_vs_state(pipe, ctx->vs_layered);523pipe->delete_vertex_elements_state(pipe, ctx->velem_state);524for (i = 0; i < 4; i++) {525if (ctx->velem_state_readbuf[i]) {526pipe->delete_vertex_elements_state(pipe, ctx->velem_state_readbuf[i]);527}528}529530for (i = 0; i < PIPE_MAX_TEXTURE_TYPES; i++) {531for (unsigned type = 0; type < ARRAY_SIZE(ctx->fs_texfetch_col); ++type) {532for (unsigned inst = 0; inst < 2; inst++) {533if (ctx->fs_texfetch_col[type][i][inst])534ctx->delete_fs_state(pipe, ctx->fs_texfetch_col[type][i][inst]);535}536if (ctx->fs_texfetch_col_msaa[type][i])537ctx->delete_fs_state(pipe, ctx->fs_texfetch_col_msaa[type][i]);538}539540for (unsigned inst = 0; inst < 2; inst++) {541if (ctx->fs_texfetch_depth[i][inst])542ctx->delete_fs_state(pipe, ctx->fs_texfetch_depth[i][inst]);543if (ctx->fs_texfetch_depthstencil[i][inst])544ctx->delete_fs_state(pipe, ctx->fs_texfetch_depthstencil[i][inst]);545if (ctx->fs_texfetch_stencil[i][inst])546ctx->delete_fs_state(pipe, ctx->fs_texfetch_stencil[i][inst]);547}548549if (ctx->fs_texfetch_depth_msaa[i])550ctx->delete_fs_state(pipe, ctx->fs_texfetch_depth_msaa[i]);551if (ctx->fs_texfetch_depthstencil_msaa[i])552ctx->delete_fs_state(pipe, ctx->fs_texfetch_depthstencil_msaa[i]);553if (ctx->fs_texfetch_stencil_msaa[i])554ctx->delete_fs_state(pipe, ctx->fs_texfetch_stencil_msaa[i]);555556for (j = 0; j< ARRAY_SIZE(ctx->fs_resolve[i]); j++)557for (f = 0; f < 2; f++)558if (ctx->fs_resolve[i][j][f])559ctx->delete_fs_state(pipe, ctx->fs_resolve[i][j][f]);560}561562for (i = 0; i < ARRAY_SIZE(ctx->fs_pack_color_zs); i++) {563for (j = 0; j < ARRAY_SIZE(ctx->fs_pack_color_zs[0]); j++) {564if (ctx->fs_pack_color_zs[i][j])565ctx->delete_fs_state(pipe, ctx->fs_pack_color_zs[i][j]);566}567}568569if (ctx->fs_empty)570ctx->delete_fs_state(pipe, ctx->fs_empty);571if (ctx->fs_write_one_cbuf)572ctx->delete_fs_state(pipe, ctx->fs_write_one_cbuf);573if (ctx->fs_write_all_cbufs)574ctx->delete_fs_state(pipe, ctx->fs_write_all_cbufs);575576for (i = 0; i < ARRAY_SIZE(ctx->fs_stencil_blit_fallback); ++i)577if (ctx->fs_stencil_blit_fallback[i])578ctx->delete_fs_state(pipe, ctx->fs_stencil_blit_fallback[i]);579580pipe->delete_sampler_state(pipe, ctx->sampler_state_rect_linear);581pipe->delete_sampler_state(pipe, ctx->sampler_state_rect);582pipe->delete_sampler_state(pipe, ctx->sampler_state_linear);583pipe->delete_sampler_state(pipe, ctx->sampler_state);584FREE(ctx);585}586587void util_blitter_set_texture_multisample(struct blitter_context *blitter,588bool supported)589{590struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;591592ctx->has_texture_multisample = supported;593}594595void util_blitter_set_running_flag(struct blitter_context *blitter)596{597if (blitter->running) {598_debug_printf("u_blitter:%i: Caught recursion. This is a driver bug.\n",599__LINE__);600}601blitter->running = true;602603blitter->pipe->set_active_query_state(blitter->pipe, false);604}605606void util_blitter_unset_running_flag(struct blitter_context *blitter)607{608if (!blitter->running) {609_debug_printf("u_blitter:%i: Caught recursion. This is a driver bug.\n",610__LINE__);611}612blitter->running = false;613614blitter->pipe->set_active_query_state(blitter->pipe, true);615}616617static void blitter_check_saved_vertex_states(ASSERTED struct blitter_context_priv *ctx)618{619assert(ctx->base.saved_vs != INVALID_PTR);620assert(!ctx->has_geometry_shader || ctx->base.saved_gs != INVALID_PTR);621assert(!ctx->has_tessellation || ctx->base.saved_tcs != INVALID_PTR);622assert(!ctx->has_tessellation || ctx->base.saved_tes != INVALID_PTR);623assert(!ctx->has_stream_out || ctx->base.saved_num_so_targets != ~0u);624assert(ctx->base.saved_rs_state != INVALID_PTR);625}626627void util_blitter_restore_vertex_states(struct blitter_context *blitter)628{629struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;630struct pipe_context *pipe = ctx->base.pipe;631unsigned i;632633/* Vertex buffer. */634if (ctx->base.saved_vertex_buffer.buffer.resource) {635pipe->set_vertex_buffers(pipe, ctx->base.vb_slot, 1, 0, true,636&ctx->base.saved_vertex_buffer);637ctx->base.saved_vertex_buffer.buffer.resource = NULL;638}639640/* Vertex elements. */641if (ctx->base.saved_velem_state != INVALID_PTR) {642pipe->bind_vertex_elements_state(pipe, ctx->base.saved_velem_state);643ctx->base.saved_velem_state = INVALID_PTR;644}645646/* Vertex shader. */647pipe->bind_vs_state(pipe, ctx->base.saved_vs);648ctx->base.saved_vs = INVALID_PTR;649650/* Geometry shader. */651if (ctx->has_geometry_shader) {652pipe->bind_gs_state(pipe, ctx->base.saved_gs);653ctx->base.saved_gs = INVALID_PTR;654}655656if (ctx->has_tessellation) {657pipe->bind_tcs_state(pipe, ctx->base.saved_tcs);658pipe->bind_tes_state(pipe, ctx->base.saved_tes);659ctx->base.saved_tcs = INVALID_PTR;660ctx->base.saved_tes = INVALID_PTR;661}662663/* Stream outputs. */664if (ctx->has_stream_out) {665unsigned offsets[PIPE_MAX_SO_BUFFERS];666for (i = 0; i < ctx->base.saved_num_so_targets; i++)667offsets[i] = (unsigned)-1;668pipe->set_stream_output_targets(pipe,669ctx->base.saved_num_so_targets,670ctx->base.saved_so_targets, offsets);671672for (i = 0; i < ctx->base.saved_num_so_targets; i++)673pipe_so_target_reference(&ctx->base.saved_so_targets[i], NULL);674675ctx->base.saved_num_so_targets = ~0;676}677678/* Rasterizer. */679pipe->bind_rasterizer_state(pipe, ctx->base.saved_rs_state);680ctx->base.saved_rs_state = INVALID_PTR;681}682683static void blitter_check_saved_fragment_states(ASSERTED struct blitter_context_priv *ctx)684{685assert(ctx->base.saved_fs != INVALID_PTR);686assert(ctx->base.saved_dsa_state != INVALID_PTR);687assert(ctx->base.saved_blend_state != INVALID_PTR);688}689690void util_blitter_restore_fragment_states(struct blitter_context *blitter)691{692struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;693struct pipe_context *pipe = ctx->base.pipe;694695/* Fragment shader. */696ctx->bind_fs_state(pipe, ctx->base.saved_fs);697ctx->base.saved_fs = INVALID_PTR;698699/* Depth, stencil, alpha. */700pipe->bind_depth_stencil_alpha_state(pipe, ctx->base.saved_dsa_state);701ctx->base.saved_dsa_state = INVALID_PTR;702703/* Blend state. */704pipe->bind_blend_state(pipe, ctx->base.saved_blend_state);705ctx->base.saved_blend_state = INVALID_PTR;706707/* Sample mask. */708if (ctx->base.is_sample_mask_saved) {709pipe->set_sample_mask(pipe, ctx->base.saved_sample_mask);710ctx->base.is_sample_mask_saved = false;711}712713/* Miscellaneous states. */714/* XXX check whether these are saved and whether they need to be restored715* (depending on the operation) */716pipe->set_stencil_ref(pipe, ctx->base.saved_stencil_ref);717718if (!blitter->skip_viewport_restore)719pipe->set_viewport_states(pipe, 0, 1, &ctx->base.saved_viewport);720721if (blitter->saved_num_window_rectangles) {722pipe->set_window_rectangles(pipe,723blitter->saved_window_rectangles_include,724blitter->saved_num_window_rectangles,725blitter->saved_window_rectangles);726}727}728729static void blitter_check_saved_fb_state(ASSERTED struct blitter_context_priv *ctx)730{731assert(ctx->base.saved_fb_state.nr_cbufs != (ubyte) ~0);732}733734static void blitter_disable_render_cond(struct blitter_context_priv *ctx)735{736struct pipe_context *pipe = ctx->base.pipe;737738if (ctx->base.saved_render_cond_query) {739pipe->render_condition(pipe, NULL, false, 0);740}741}742743void util_blitter_restore_render_cond(struct blitter_context *blitter)744{745struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;746struct pipe_context *pipe = ctx->base.pipe;747748if (ctx->base.saved_render_cond_query) {749pipe->render_condition(pipe, ctx->base.saved_render_cond_query,750ctx->base.saved_render_cond_cond,751ctx->base.saved_render_cond_mode);752ctx->base.saved_render_cond_query = NULL;753}754}755756void util_blitter_restore_fb_state(struct blitter_context *blitter)757{758struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;759struct pipe_context *pipe = ctx->base.pipe;760761pipe->set_framebuffer_state(pipe, &ctx->base.saved_fb_state);762util_unreference_framebuffer_state(&ctx->base.saved_fb_state);763}764765static void blitter_check_saved_textures(ASSERTED struct blitter_context_priv *ctx)766{767assert(ctx->base.saved_num_sampler_states != ~0u);768assert(ctx->base.saved_num_sampler_views != ~0u);769}770771void util_blitter_restore_textures(struct blitter_context *blitter)772{773struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;774struct pipe_context *pipe = ctx->base.pipe;775unsigned i;776777/* Fragment sampler states. */778pipe->bind_sampler_states(pipe, PIPE_SHADER_FRAGMENT, 0,779ctx->base.saved_num_sampler_states,780ctx->base.saved_sampler_states);781782ctx->base.saved_num_sampler_states = ~0;783784/* Fragment sampler views. */785pipe->set_sampler_views(pipe, PIPE_SHADER_FRAGMENT, 0,786ctx->base.saved_num_sampler_views, 0,787ctx->base.saved_sampler_views);788789for (i = 0; i < ctx->base.saved_num_sampler_views; i++)790pipe_sampler_view_reference(&ctx->base.saved_sampler_views[i], NULL);791792ctx->base.saved_num_sampler_views = ~0;793}794795void util_blitter_restore_constant_buffer_state(struct blitter_context *blitter)796{797struct pipe_context *pipe = blitter->pipe;798799pipe->set_constant_buffer(pipe, PIPE_SHADER_FRAGMENT, blitter->cb_slot,800true, &blitter->saved_fs_constant_buffer);801blitter->saved_fs_constant_buffer.buffer = NULL;802}803804static void blitter_set_rectangle(struct blitter_context_priv *ctx,805int x1, int y1, int x2, int y2,806float depth)807{808/* set vertex positions */809ctx->vertices[0][0][0] = (float)x1 / ctx->dst_width * 2.0f - 1.0f; /*v0.x*/810ctx->vertices[0][0][1] = (float)y1 / ctx->dst_height * 2.0f - 1.0f; /*v0.y*/811812ctx->vertices[1][0][0] = (float)x2 / ctx->dst_width * 2.0f - 1.0f; /*v1.x*/813ctx->vertices[1][0][1] = (float)y1 / ctx->dst_height * 2.0f - 1.0f; /*v1.y*/814815ctx->vertices[2][0][0] = (float)x2 / ctx->dst_width * 2.0f - 1.0f; /*v2.x*/816ctx->vertices[2][0][1] = (float)y2 / ctx->dst_height * 2.0f - 1.0f; /*v2.y*/817818ctx->vertices[3][0][0] = (float)x1 / ctx->dst_width * 2.0f - 1.0f; /*v3.x*/819ctx->vertices[3][0][1] = (float)y2 / ctx->dst_height * 2.0f - 1.0f; /*v3.y*/820821/* viewport */822struct pipe_viewport_state viewport;823viewport.scale[0] = 0.5f * ctx->dst_width;824viewport.scale[1] = 0.5f * ctx->dst_height;825viewport.scale[2] = 0.0f;826viewport.translate[0] = 0.5f * ctx->dst_width;827viewport.translate[1] = 0.5f * ctx->dst_height;828viewport.translate[2] = depth;829viewport.swizzle_x = PIPE_VIEWPORT_SWIZZLE_POSITIVE_X;830viewport.swizzle_y = PIPE_VIEWPORT_SWIZZLE_POSITIVE_Y;831viewport.swizzle_z = PIPE_VIEWPORT_SWIZZLE_POSITIVE_Z;832viewport.swizzle_w = PIPE_VIEWPORT_SWIZZLE_POSITIVE_W;833ctx->base.pipe->set_viewport_states(ctx->base.pipe, 0, 1, &viewport);834}835836static void blitter_set_clear_color(struct blitter_context_priv *ctx,837const float color[4])838{839int i;840841if (color) {842for (i = 0; i < 4; i++)843memcpy(&ctx->vertices[i][1][0], color, sizeof(uint32_t) * 4);844} else {845for (i = 0; i < 4; i++)846memset(&ctx->vertices[i][1][0], 0, sizeof(uint32_t) * 4);847}848}849850static void get_texcoords(struct pipe_sampler_view *src,851unsigned src_width0, unsigned src_height0,852int x1, int y1, int x2, int y2,853float layer, unsigned sample,854bool uses_txf, union blitter_attrib *out)855{856unsigned level = src->u.tex.first_level;857bool normalized = !uses_txf &&858src->target != PIPE_TEXTURE_RECT &&859src->texture->nr_samples <= 1;860861if (normalized) {862out->texcoord.x1 = x1 / (float)u_minify(src_width0, level);863out->texcoord.y1 = y1 / (float)u_minify(src_height0, level);864out->texcoord.x2 = x2 / (float)u_minify(src_width0, level);865out->texcoord.y2 = y2 / (float)u_minify(src_height0, level);866} else {867out->texcoord.x1 = x1;868out->texcoord.y1 = y1;869out->texcoord.x2 = x2;870out->texcoord.y2 = y2;871}872873out->texcoord.z = 0;874out->texcoord.w = 0;875876/* Set the layer. */877switch (src->target) {878case PIPE_TEXTURE_3D:879{880float r = layer;881882if (!uses_txf)883r /= u_minify(src->texture->depth0, src->u.tex.first_level);884885out->texcoord.z = r;886}887break;888889case PIPE_TEXTURE_1D_ARRAY:890out->texcoord.y1 = out->texcoord.y2 = layer;891break;892893case PIPE_TEXTURE_2D_ARRAY:894out->texcoord.z = layer;895out->texcoord.w = sample;896break;897898case PIPE_TEXTURE_CUBE_ARRAY:899out->texcoord.w = (unsigned)layer / 6;900break;901902case PIPE_TEXTURE_2D:903out->texcoord.w = sample;904break;905906default:;907}908}909910static void blitter_set_dst_dimensions(struct blitter_context_priv *ctx,911unsigned width, unsigned height)912{913ctx->dst_width = width;914ctx->dst_height = height;915}916917static void set_texcoords_in_vertices(const union blitter_attrib *attrib,918float *out, unsigned stride)919{920out[0] = attrib->texcoord.x1;921out[1] = attrib->texcoord.y1;922out += stride;923out[0] = attrib->texcoord.x2;924out[1] = attrib->texcoord.y1;925out += stride;926out[0] = attrib->texcoord.x2;927out[1] = attrib->texcoord.y2;928out += stride;929out[0] = attrib->texcoord.x1;930out[1] = attrib->texcoord.y2;931}932933static void *blitter_get_fs_texfetch_col(struct blitter_context_priv *ctx,934enum pipe_format src_format,935enum pipe_format dst_format,936enum pipe_texture_target target,937unsigned src_nr_samples,938unsigned dst_nr_samples,939unsigned filter,940bool use_txf)941{942struct pipe_context *pipe = ctx->base.pipe;943enum tgsi_texture_type tgsi_tex =944util_pipe_tex_to_tgsi_tex(target, src_nr_samples);945enum tgsi_return_type stype;946enum tgsi_return_type dtype;947unsigned type;948949assert(target < PIPE_MAX_TEXTURE_TYPES);950951if (util_format_is_pure_uint(src_format)) {952stype = TGSI_RETURN_TYPE_UINT;953if (util_format_is_pure_uint(dst_format)) {954dtype = TGSI_RETURN_TYPE_UINT;955type = 0;956} else {957assert(util_format_is_pure_sint(dst_format));958dtype = TGSI_RETURN_TYPE_SINT;959type = 1;960}961} else if (util_format_is_pure_sint(src_format)) {962stype = TGSI_RETURN_TYPE_SINT;963if (util_format_is_pure_sint(dst_format)) {964dtype = TGSI_RETURN_TYPE_SINT;965type = 2;966} else {967assert(util_format_is_pure_uint(dst_format));968dtype = TGSI_RETURN_TYPE_UINT;969type = 3;970}971} else {972assert(!util_format_is_pure_uint(dst_format) &&973!util_format_is_pure_sint(dst_format));974dtype = stype = TGSI_RETURN_TYPE_FLOAT;975type = 4;976}977978if (src_nr_samples > 1) {979void **shader;980981/* OpenGL requires that integer textures just copy 1 sample instead982* of averaging.983*/984if (dst_nr_samples <= 1 &&985stype != TGSI_RETURN_TYPE_UINT &&986stype != TGSI_RETURN_TYPE_SINT) {987/* The destination has one sample, so we'll do color resolve. */988unsigned index = GET_MSAA_RESOLVE_FS_IDX(src_nr_samples);989990assert(filter < 2);991992shader = &ctx->fs_resolve[target][index][filter];993994if (!*shader) {995assert(!ctx->cached_all_shaders);996if (filter == PIPE_TEX_FILTER_LINEAR) {997*shader = util_make_fs_msaa_resolve_bilinear(pipe, tgsi_tex,998src_nr_samples,999stype);1000}1001else {1002*shader = util_make_fs_msaa_resolve(pipe, tgsi_tex,1003src_nr_samples,1004stype);1005}1006}1007}1008else {1009/* The destination has multiple samples, we'll do1010* an MSAA->MSAA copy.1011*/1012shader = &ctx->fs_texfetch_col_msaa[type][target];10131014/* Create the fragment shader on-demand. */1015if (!*shader) {1016assert(!ctx->cached_all_shaders);1017*shader = util_make_fs_blit_msaa_color(pipe, tgsi_tex, stype, dtype);1018}1019}10201021return *shader;1022} else {1023void **shader;10241025if (use_txf)1026shader = &ctx->fs_texfetch_col[type][target][1];1027else1028shader = &ctx->fs_texfetch_col[type][target][0];10291030/* Create the fragment shader on-demand. */1031if (!*shader) {1032assert(!ctx->cached_all_shaders);1033*shader = util_make_fragment_tex_shader(pipe, tgsi_tex,1034TGSI_INTERPOLATE_LINEAR,1035stype, dtype,1036ctx->has_tex_lz, use_txf);1037}10381039return *shader;1040}1041}10421043static inline1044void *blitter_get_fs_pack_color_zs(struct blitter_context_priv *ctx,1045enum pipe_texture_target target,1046unsigned nr_samples,1047enum pipe_format zs_format,1048bool dst_is_color)1049{1050struct pipe_context *pipe = ctx->base.pipe;1051enum tgsi_texture_type tgsi_tex =1052util_pipe_tex_to_tgsi_tex(target, nr_samples);1053int format_index = zs_format == PIPE_FORMAT_Z24_UNORM_S8_UINT ? 0 :1054zs_format == PIPE_FORMAT_S8_UINT_Z24_UNORM ? 1 :1055zs_format == PIPE_FORMAT_Z32_FLOAT_S8X24_UINT ? 2 :1056zs_format == PIPE_FORMAT_Z24X8_UNORM ? 3 :1057zs_format == PIPE_FORMAT_X8Z24_UNORM ? 4 : -1;10581059if (format_index == -1) {1060assert(0);1061return NULL;1062}10631064/* The first 5 shaders pack ZS to color, the last 5 shaders unpack color1065* to ZS.1066*/1067if (dst_is_color)1068format_index += 5;10691070void **shader = &ctx->fs_pack_color_zs[tgsi_tex][format_index];10711072/* Create the fragment shader on-demand. */1073if (!*shader) {1074assert(!ctx->cached_all_shaders);1075*shader = util_make_fs_pack_color_zs(pipe, tgsi_tex, zs_format,1076dst_is_color);1077}1078return *shader;1079}10801081static inline1082void *blitter_get_fs_texfetch_depth(struct blitter_context_priv *ctx,1083enum pipe_texture_target target,1084unsigned nr_samples,1085bool use_txf)1086{1087struct pipe_context *pipe = ctx->base.pipe;10881089assert(target < PIPE_MAX_TEXTURE_TYPES);10901091if (nr_samples > 1) {1092void **shader = &ctx->fs_texfetch_depth_msaa[target];10931094/* Create the fragment shader on-demand. */1095if (!*shader) {1096enum tgsi_texture_type tgsi_tex;1097assert(!ctx->cached_all_shaders);1098tgsi_tex = util_pipe_tex_to_tgsi_tex(target, nr_samples);1099*shader = util_make_fs_blit_msaa_depth(pipe, tgsi_tex);1100}11011102return *shader;1103} else {1104void **shader;11051106if (use_txf)1107shader = &ctx->fs_texfetch_depth[target][1];1108else1109shader = &ctx->fs_texfetch_depth[target][0];11101111/* Create the fragment shader on-demand. */1112if (!*shader) {1113enum tgsi_texture_type tgsi_tex;1114assert(!ctx->cached_all_shaders);1115tgsi_tex = util_pipe_tex_to_tgsi_tex(target, 0);1116*shader = util_make_fs_blit_zs(pipe, PIPE_MASK_Z, tgsi_tex,1117ctx->has_tex_lz, use_txf);1118}11191120return *shader;1121}1122}11231124static inline1125void *blitter_get_fs_texfetch_depthstencil(struct blitter_context_priv *ctx,1126enum pipe_texture_target target,1127unsigned nr_samples,1128bool use_txf)1129{1130struct pipe_context *pipe = ctx->base.pipe;11311132assert(target < PIPE_MAX_TEXTURE_TYPES);11331134if (nr_samples > 1) {1135void **shader = &ctx->fs_texfetch_depthstencil_msaa[target];11361137/* Create the fragment shader on-demand. */1138if (!*shader) {1139enum tgsi_texture_type tgsi_tex;1140assert(!ctx->cached_all_shaders);1141tgsi_tex = util_pipe_tex_to_tgsi_tex(target, nr_samples);1142*shader = util_make_fs_blit_msaa_depthstencil(pipe, tgsi_tex);1143}11441145return *shader;1146} else {1147void **shader;11481149if (use_txf)1150shader = &ctx->fs_texfetch_depthstencil[target][1];1151else1152shader = &ctx->fs_texfetch_depthstencil[target][0];11531154/* Create the fragment shader on-demand. */1155if (!*shader) {1156enum tgsi_texture_type tgsi_tex;1157assert(!ctx->cached_all_shaders);1158tgsi_tex = util_pipe_tex_to_tgsi_tex(target, 0);1159*shader = util_make_fs_blit_zs(pipe, PIPE_MASK_ZS, tgsi_tex,1160ctx->has_tex_lz, use_txf);1161}11621163return *shader;1164}1165}11661167static inline1168void *blitter_get_fs_texfetch_stencil(struct blitter_context_priv *ctx,1169enum pipe_texture_target target,1170unsigned nr_samples,1171bool use_txf)1172{1173struct pipe_context *pipe = ctx->base.pipe;11741175assert(target < PIPE_MAX_TEXTURE_TYPES);11761177if (nr_samples > 1) {1178void **shader = &ctx->fs_texfetch_stencil_msaa[target];11791180/* Create the fragment shader on-demand. */1181if (!*shader) {1182enum tgsi_texture_type tgsi_tex;1183assert(!ctx->cached_all_shaders);1184tgsi_tex = util_pipe_tex_to_tgsi_tex(target, nr_samples);1185*shader = util_make_fs_blit_msaa_stencil(pipe, tgsi_tex);1186}11871188return *shader;1189} else {1190void **shader;11911192if (use_txf)1193shader = &ctx->fs_texfetch_stencil[target][1];1194else1195shader = &ctx->fs_texfetch_stencil[target][0];11961197/* Create the fragment shader on-demand. */1198if (!*shader) {1199enum tgsi_texture_type tgsi_tex;1200assert(!ctx->cached_all_shaders);1201tgsi_tex = util_pipe_tex_to_tgsi_tex(target, 0);1202*shader = util_make_fs_blit_zs(pipe, PIPE_MASK_S, tgsi_tex,1203ctx->has_tex_lz, use_txf);1204}12051206return *shader;1207}1208}120912101211/**1212* Generate and save all fragment shaders that we will ever need for1213* blitting. Drivers which use the 'draw' fallbacks will typically use1214* this to make sure we generate/use shaders that don't go through the1215* draw module's wrapper functions.1216*/1217void util_blitter_cache_all_shaders(struct blitter_context *blitter)1218{1219struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;1220struct pipe_context *pipe = blitter->pipe;1221struct pipe_screen *screen = pipe->screen;1222unsigned samples, j, f, target, max_samples, use_txf;1223bool has_arraytex, has_cubearraytex;12241225max_samples = ctx->has_texture_multisample ? 2 : 1;1226has_arraytex = screen->get_param(screen,1227PIPE_CAP_MAX_TEXTURE_ARRAY_LAYERS) != 0;1228has_cubearraytex = screen->get_param(screen,1229PIPE_CAP_CUBE_MAP_ARRAY) != 0;12301231/* It only matters if i <= 1 or > 1. */1232for (samples = 1; samples <= max_samples; samples++) {1233for (target = PIPE_TEXTURE_1D; target < PIPE_MAX_TEXTURE_TYPES; target++) {1234for (use_txf = 0; use_txf <= ctx->has_txf; use_txf++) {1235if (!has_arraytex &&1236(target == PIPE_TEXTURE_1D_ARRAY ||1237target == PIPE_TEXTURE_2D_ARRAY)) {1238continue;1239}1240if (!has_cubearraytex &&1241(target == PIPE_TEXTURE_CUBE_ARRAY))1242continue;12431244if (samples > 1 &&1245(target != PIPE_TEXTURE_2D &&1246target != PIPE_TEXTURE_2D_ARRAY))1247continue;12481249if (samples > 1 && use_txf)1250continue; /* TXF is the only option, use_txf has no effect */12511252/* If samples == 1, the shaders read one texel. If samples >= 1,1253* they read one sample.1254*/1255blitter_get_fs_texfetch_col(ctx, PIPE_FORMAT_R32_FLOAT,1256PIPE_FORMAT_R32_FLOAT, target,1257samples, samples, 0, use_txf);1258blitter_get_fs_texfetch_col(ctx, PIPE_FORMAT_R32_UINT,1259PIPE_FORMAT_R32_UINT, target,1260samples, samples, 0, use_txf);1261blitter_get_fs_texfetch_col(ctx, PIPE_FORMAT_R32_UINT,1262PIPE_FORMAT_R32_SINT, target,1263samples, samples, 0, use_txf);1264blitter_get_fs_texfetch_col(ctx, PIPE_FORMAT_R32_SINT,1265PIPE_FORMAT_R32_SINT, target,1266samples, samples, 0, use_txf);1267blitter_get_fs_texfetch_col(ctx, PIPE_FORMAT_R32_SINT,1268PIPE_FORMAT_R32_UINT, target,1269samples, samples, 0, use_txf);1270blitter_get_fs_texfetch_depth(ctx, target, samples, use_txf);1271if (ctx->has_stencil_export) {1272blitter_get_fs_texfetch_depthstencil(ctx, target, samples, use_txf);1273blitter_get_fs_texfetch_stencil(ctx, target, samples, use_txf);1274}12751276if (samples == 1)1277continue;12781279/* MSAA resolve shaders. */1280for (j = 2; j < 32; j++) {1281if (!screen->is_format_supported(screen, PIPE_FORMAT_R32_FLOAT,1282target, j, j,1283PIPE_BIND_SAMPLER_VIEW)) {1284continue;1285}12861287for (f = 0; f < 2; f++) {1288if (f != PIPE_TEX_FILTER_NEAREST && use_txf)1289continue;12901291blitter_get_fs_texfetch_col(ctx, PIPE_FORMAT_R32_FLOAT,1292PIPE_FORMAT_R32_FLOAT, target,1293j, 1, f, use_txf);1294blitter_get_fs_texfetch_col(ctx, PIPE_FORMAT_R32_UINT,1295PIPE_FORMAT_R32_UINT, target,1296j, 1, f, use_txf);1297blitter_get_fs_texfetch_col(ctx, PIPE_FORMAT_R32_SINT,1298PIPE_FORMAT_R32_SINT, target,1299j, 1, f, use_txf);1300}1301}1302}1303}1304}13051306ctx->fs_empty = util_make_empty_fragment_shader(pipe);13071308ctx->fs_write_one_cbuf =1309util_make_fragment_passthrough_shader(pipe, TGSI_SEMANTIC_GENERIC,1310TGSI_INTERPOLATE_CONSTANT, false);13111312ctx->fs_write_all_cbufs =1313util_make_fragment_passthrough_shader(pipe, TGSI_SEMANTIC_GENERIC,1314TGSI_INTERPOLATE_CONSTANT, true);13151316ctx->cached_all_shaders = true;1317}13181319static void blitter_set_common_draw_rect_state(struct blitter_context_priv *ctx,1320bool scissor, bool msaa)1321{1322struct pipe_context *pipe = ctx->base.pipe;13231324if (ctx->base.saved_num_window_rectangles)1325pipe->set_window_rectangles(pipe, false, 0, NULL);13261327pipe->bind_rasterizer_state(pipe, ctx->rs_state[scissor][msaa]);13281329if (ctx->has_geometry_shader)1330pipe->bind_gs_state(pipe, NULL);1331if (ctx->has_tessellation) {1332pipe->bind_tcs_state(pipe, NULL);1333pipe->bind_tes_state(pipe, NULL);1334}1335if (ctx->has_stream_out)1336pipe->set_stream_output_targets(pipe, 0, NULL, NULL);1337}13381339static void blitter_draw(struct blitter_context_priv *ctx,1340void *vertex_elements_cso,1341blitter_get_vs_func get_vs,1342int x1, int y1, int x2, int y2, float depth,1343unsigned num_instances)1344{1345struct pipe_context *pipe = ctx->base.pipe;1346struct pipe_vertex_buffer vb = {0};13471348blitter_set_rectangle(ctx, x1, y1, x2, y2, depth);13491350vb.stride = 8 * sizeof(float);13511352u_upload_data(pipe->stream_uploader, 0, sizeof(ctx->vertices), 4, ctx->vertices,1353&vb.buffer_offset, &vb.buffer.resource);1354if (!vb.buffer.resource)1355return;1356u_upload_unmap(pipe->stream_uploader);13571358pipe->set_vertex_buffers(pipe, ctx->base.vb_slot, 1, 0, false, &vb);1359pipe->bind_vertex_elements_state(pipe, vertex_elements_cso);1360pipe->bind_vs_state(pipe, get_vs(&ctx->base));13611362if (ctx->base.use_index_buffer) {1363/* Note that for V3D,1364* dEQP-GLES3.functional.fbo.blit.rect.nearest_consistency_* require1365* that the last vert of the two tris be the same.1366*/1367static uint8_t indices[6] = { 0, 1, 2, 0, 3, 2 };1368util_draw_elements_instanced(pipe, indices, 1, 0,1369PIPE_PRIM_TRIANGLES, 0, 6,13700, num_instances);1371} else {1372util_draw_arrays_instanced(pipe, PIPE_PRIM_TRIANGLE_FAN, 0, 4,13730, num_instances);1374}1375pipe_resource_reference(&vb.buffer.resource, NULL);1376}13771378void util_blitter_draw_rectangle(struct blitter_context *blitter,1379void *vertex_elements_cso,1380blitter_get_vs_func get_vs,1381int x1, int y1, int x2, int y2,1382float depth, unsigned num_instances,1383enum blitter_attrib_type type,1384const union blitter_attrib *attrib)1385{1386struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;1387unsigned i;13881389switch (type) {1390case UTIL_BLITTER_ATTRIB_COLOR:1391blitter_set_clear_color(ctx, attrib->color);1392break;13931394case UTIL_BLITTER_ATTRIB_TEXCOORD_XYZW:1395for (i = 0; i < 4; i++) {1396ctx->vertices[i][1][2] = attrib->texcoord.z;1397ctx->vertices[i][1][3] = attrib->texcoord.w;1398}1399FALLTHROUGH;1400case UTIL_BLITTER_ATTRIB_TEXCOORD_XY:1401set_texcoords_in_vertices(attrib, &ctx->vertices[0][1][0], 8);1402break;14031404default:;1405}14061407blitter_draw(ctx, vertex_elements_cso, get_vs, x1, y1, x2, y2, depth,1408num_instances);1409}14101411static void *get_clear_blend_state(struct blitter_context_priv *ctx,1412unsigned clear_buffers)1413{1414struct pipe_context *pipe = ctx->base.pipe;1415int index;14161417clear_buffers &= PIPE_CLEAR_COLOR;14181419/* Return an existing blend state. */1420if (!clear_buffers)1421return ctx->blend[0][0];14221423index = GET_CLEAR_BLEND_STATE_IDX(clear_buffers);14241425if (ctx->blend_clear[index])1426return ctx->blend_clear[index];14271428/* Create a new one. */1429{1430struct pipe_blend_state blend = {0};1431unsigned i;14321433blend.independent_blend_enable = 1;14341435for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) {1436if (clear_buffers & (PIPE_CLEAR_COLOR0 << i)) {1437blend.rt[i].colormask = PIPE_MASK_RGBA;1438blend.max_rt = i;1439}1440}14411442ctx->blend_clear[index] = pipe->create_blend_state(pipe, &blend);1443}1444return ctx->blend_clear[index];1445}14461447void util_blitter_common_clear_setup(struct blitter_context *blitter,1448unsigned width, unsigned height,1449unsigned clear_buffers,1450void *custom_blend, void *custom_dsa)1451{1452struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;1453struct pipe_context *pipe = ctx->base.pipe;14541455util_blitter_set_running_flag(blitter);1456blitter_check_saved_vertex_states(ctx);1457blitter_check_saved_fragment_states(ctx);1458blitter_disable_render_cond(ctx);14591460/* bind states */1461if (custom_blend) {1462pipe->bind_blend_state(pipe, custom_blend);1463} else {1464pipe->bind_blend_state(pipe, get_clear_blend_state(ctx, clear_buffers));1465}14661467if (custom_dsa) {1468pipe->bind_depth_stencil_alpha_state(pipe, custom_dsa);1469} else if ((clear_buffers & PIPE_CLEAR_DEPTHSTENCIL) == PIPE_CLEAR_DEPTHSTENCIL) {1470pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_write_depth_stencil);1471} else if (clear_buffers & PIPE_CLEAR_DEPTH) {1472pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_write_depth_keep_stencil);1473} else if (clear_buffers & PIPE_CLEAR_STENCIL) {1474pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_write_stencil);1475} else {1476pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil);1477}14781479pipe->set_sample_mask(pipe, ~0);1480blitter_set_dst_dimensions(ctx, width, height);1481}14821483static void util_blitter_clear_custom(struct blitter_context *blitter,1484unsigned width, unsigned height,1485unsigned num_layers,1486unsigned clear_buffers,1487const union pipe_color_union *color,1488double depth, unsigned stencil,1489void *custom_blend, void *custom_dsa,1490bool msaa)1491{1492struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;1493struct pipe_context *pipe = ctx->base.pipe;1494struct pipe_stencil_ref sr = { { 0 } };14951496assert(ctx->has_layered || num_layers <= 1);14971498util_blitter_common_clear_setup(blitter, width, height, clear_buffers,1499custom_blend, custom_dsa);15001501sr.ref_value[0] = stencil & 0xff;1502pipe->set_stencil_ref(pipe, sr);15031504union blitter_attrib attrib;1505memcpy(attrib.color, color->ui, sizeof(color->ui));15061507bool pass_generic = (clear_buffers & PIPE_CLEAR_COLOR) != 0;1508enum blitter_attrib_type type = pass_generic ? UTIL_BLITTER_ATTRIB_COLOR :1509UTIL_BLITTER_ATTRIB_NONE;15101511if (pass_generic)1512bind_fs_write_all_cbufs(ctx);1513else1514bind_fs_empty(ctx);15151516if (num_layers > 1 && ctx->has_layered) {1517blitter_get_vs_func get_vs = get_vs_layered;15181519blitter_set_common_draw_rect_state(ctx, false, msaa);1520blitter->draw_rectangle(blitter, ctx->velem_state, get_vs,15210, 0, width, height,1522(float) depth, num_layers, type, &attrib);1523} else {1524blitter_get_vs_func get_vs;15251526if (pass_generic)1527get_vs = get_vs_passthrough_pos_generic;1528else1529get_vs = get_vs_passthrough_pos;15301531blitter_set_common_draw_rect_state(ctx, false, msaa);1532blitter->draw_rectangle(blitter, ctx->velem_state, get_vs,15330, 0, width, height,1534(float) depth, 1, type, &attrib);1535}15361537util_blitter_restore_vertex_states(blitter);1538util_blitter_restore_fragment_states(blitter);1539util_blitter_restore_render_cond(blitter);1540util_blitter_unset_running_flag(blitter);1541}15421543void util_blitter_clear(struct blitter_context *blitter,1544unsigned width, unsigned height, unsigned num_layers,1545unsigned clear_buffers,1546const union pipe_color_union *color,1547double depth, unsigned stencil,1548bool msaa)1549{1550util_blitter_clear_custom(blitter, width, height, num_layers,1551clear_buffers, color, depth, stencil,1552NULL, NULL, msaa);1553}15541555void util_blitter_custom_clear_depth(struct blitter_context *blitter,1556unsigned width, unsigned height,1557double depth, void *custom_dsa)1558{1559static const union pipe_color_union color;1560util_blitter_clear_custom(blitter, width, height, 0, 0, &color, depth, 0,1561NULL, custom_dsa, false);1562}15631564void util_blitter_default_dst_texture(struct pipe_surface *dst_templ,1565struct pipe_resource *dst,1566unsigned dstlevel,1567unsigned dstz)1568{1569memset(dst_templ, 0, sizeof(*dst_templ));1570dst_templ->format = util_format_linear(dst->format);1571dst_templ->u.tex.level = dstlevel;1572dst_templ->u.tex.first_layer = dstz;1573dst_templ->u.tex.last_layer = dstz;1574}15751576static struct pipe_surface *1577util_blitter_get_next_surface_layer(struct pipe_context *pipe,1578struct pipe_surface *surf)1579{1580struct pipe_surface dst_templ;15811582memset(&dst_templ, 0, sizeof(dst_templ));1583dst_templ.format = surf->format;1584dst_templ.u.tex.level = surf->u.tex.level;1585dst_templ.u.tex.first_layer = surf->u.tex.first_layer + 1;1586dst_templ.u.tex.last_layer = surf->u.tex.last_layer + 1;15871588return pipe->create_surface(pipe, surf->texture, &dst_templ);1589}15901591void util_blitter_default_src_texture(struct blitter_context *blitter,1592struct pipe_sampler_view *src_templ,1593struct pipe_resource *src,1594unsigned srclevel)1595{1596struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;15971598memset(src_templ, 0, sizeof(*src_templ));15991600if (ctx->cube_as_2darray &&1601(src->target == PIPE_TEXTURE_CUBE ||1602src->target == PIPE_TEXTURE_CUBE_ARRAY))1603src_templ->target = PIPE_TEXTURE_2D_ARRAY;1604else1605src_templ->target = src->target;16061607src_templ->format = util_format_linear(src->format);1608src_templ->u.tex.first_level = srclevel;1609src_templ->u.tex.last_level = srclevel;1610src_templ->u.tex.first_layer = 0;1611src_templ->u.tex.last_layer =1612src->target == PIPE_TEXTURE_3D ? u_minify(src->depth0, srclevel) - 11613: (unsigned)(src->array_size - 1);1614src_templ->swizzle_r = PIPE_SWIZZLE_X;1615src_templ->swizzle_g = PIPE_SWIZZLE_Y;1616src_templ->swizzle_b = PIPE_SWIZZLE_Z;1617src_templ->swizzle_a = PIPE_SWIZZLE_W;1618}16191620static bool is_blit_generic_supported(struct blitter_context *blitter,1621const struct pipe_resource *dst,1622enum pipe_format dst_format,1623const struct pipe_resource *src,1624enum pipe_format src_format,1625unsigned mask)1626{1627struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;1628struct pipe_screen *screen = ctx->base.pipe->screen;16291630if (dst) {1631unsigned bind;1632const struct util_format_description *desc =1633util_format_description(dst_format);1634bool dst_has_stencil = util_format_has_stencil(desc);16351636/* Stencil export must be supported for stencil copy. */1637if ((mask & PIPE_MASK_S) && dst_has_stencil &&1638!ctx->has_stencil_export) {1639return false;1640}16411642if (dst_has_stencil || util_format_has_depth(desc))1643bind = PIPE_BIND_DEPTH_STENCIL;1644else1645bind = PIPE_BIND_RENDER_TARGET;16461647if (!screen->is_format_supported(screen, dst_format, dst->target,1648dst->nr_samples, dst->nr_storage_samples,1649bind)) {1650return false;1651}1652}16531654if (src) {1655if (src->nr_samples > 1 && !ctx->has_texture_multisample) {1656return false;1657}16581659if (!screen->is_format_supported(screen, src_format, src->target,1660src->nr_samples, src->nr_storage_samples,1661PIPE_BIND_SAMPLER_VIEW)) {1662return false;1663}16641665/* Check stencil sampler support for stencil copy. */1666if (mask & PIPE_MASK_S) {1667if (util_format_has_stencil(util_format_description(src_format))) {1668enum pipe_format stencil_format =1669util_format_stencil_only(src_format);1670assert(stencil_format != PIPE_FORMAT_NONE);16711672if (stencil_format != src_format &&1673!screen->is_format_supported(screen, stencil_format,1674src->target, src->nr_samples,1675src->nr_storage_samples,1676PIPE_BIND_SAMPLER_VIEW)) {1677return false;1678}1679}1680}1681}16821683return true;1684}16851686bool util_blitter_is_copy_supported(struct blitter_context *blitter,1687const struct pipe_resource *dst,1688const struct pipe_resource *src)1689{1690return is_blit_generic_supported(blitter, dst, dst->format,1691src, src->format, PIPE_MASK_RGBAZS);1692}16931694bool util_blitter_is_blit_supported(struct blitter_context *blitter,1695const struct pipe_blit_info *info)1696{1697return is_blit_generic_supported(blitter,1698info->dst.resource, info->dst.format,1699info->src.resource, info->src.format,1700info->mask);1701}17021703void util_blitter_copy_texture(struct blitter_context *blitter,1704struct pipe_resource *dst,1705unsigned dst_level,1706unsigned dstx, unsigned dsty, unsigned dstz,1707struct pipe_resource *src,1708unsigned src_level,1709const struct pipe_box *srcbox)1710{1711struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;1712struct pipe_context *pipe = ctx->base.pipe;1713struct pipe_surface *dst_view, dst_templ;1714struct pipe_sampler_view src_templ, *src_view;1715struct pipe_box dstbox;17161717assert(dst && src);1718assert(src->target < PIPE_MAX_TEXTURE_TYPES);17191720u_box_3d(dstx, dsty, dstz, abs(srcbox->width), abs(srcbox->height),1721abs(srcbox->depth), &dstbox);17221723/* Initialize the surface. */1724util_blitter_default_dst_texture(&dst_templ, dst, dst_level, dstz);1725dst_view = pipe->create_surface(pipe, dst, &dst_templ);17261727/* Initialize the sampler view. */1728util_blitter_default_src_texture(blitter, &src_templ, src, src_level);1729src_view = pipe->create_sampler_view(pipe, src, &src_templ);17301731/* Copy. */1732util_blitter_blit_generic(blitter, dst_view, &dstbox,1733src_view, srcbox, src->width0, src->height0,1734PIPE_MASK_RGBAZS, PIPE_TEX_FILTER_NEAREST, NULL,1735false);17361737pipe_surface_reference(&dst_view, NULL);1738pipe_sampler_view_reference(&src_view, NULL);1739}17401741static void1742blitter_draw_tex(struct blitter_context_priv *ctx,1743int dst_x1, int dst_y1, int dst_x2, int dst_y2,1744struct pipe_sampler_view *src,1745unsigned src_width0, unsigned src_height0,1746int src_x1, int src_y1, int src_x2, int src_y2,1747float layer, unsigned sample,1748bool uses_txf, enum blitter_attrib_type type)1749{1750union blitter_attrib coord;1751blitter_get_vs_func get_vs = get_vs_passthrough_pos_generic;17521753get_texcoords(src, src_width0, src_height0,1754src_x1, src_y1, src_x2, src_y2, layer, sample,1755uses_txf, &coord);17561757if (src->target == PIPE_TEXTURE_CUBE ||1758src->target == PIPE_TEXTURE_CUBE_ARRAY) {1759float face_coord[4][2];17601761set_texcoords_in_vertices(&coord, &face_coord[0][0], 2);1762util_map_texcoords2d_onto_cubemap((unsigned)layer % 6,1763/* pointer, stride in floats */1764&face_coord[0][0], 2,1765&ctx->vertices[0][1][0], 8,1766false);1767for (unsigned i = 0; i < 4; i++)1768ctx->vertices[i][1][3] = coord.texcoord.w;17691770/* Cubemaps don't use draw_rectangle. */1771blitter_draw(ctx, ctx->velem_state, get_vs,1772dst_x1, dst_y1, dst_x2, dst_y2, 0, 1);1773} else {1774ctx->base.draw_rectangle(&ctx->base, ctx->velem_state, get_vs,1775dst_x1, dst_y1, dst_x2, dst_y2,17760, 1, type, &coord);1777}1778}17791780static void do_blits(struct blitter_context_priv *ctx,1781struct pipe_surface *dst,1782const struct pipe_box *dstbox,1783struct pipe_sampler_view *src,1784unsigned src_width0,1785unsigned src_height0,1786const struct pipe_box *srcbox,1787bool is_zsbuf,1788bool uses_txf)1789{1790struct pipe_context *pipe = ctx->base.pipe;1791unsigned src_samples = src->texture->nr_samples;1792unsigned dst_samples = dst->texture->nr_samples;1793enum pipe_texture_target src_target = src->target;1794struct pipe_framebuffer_state fb_state = {0};17951796/* Initialize framebuffer state. */1797fb_state.width = dst->width;1798fb_state.height = dst->height;1799fb_state.nr_cbufs = is_zsbuf ? 0 : 1;18001801blitter_set_dst_dimensions(ctx, fb_state.width, fb_state.height);18021803if ((src_target == PIPE_TEXTURE_1D ||1804src_target == PIPE_TEXTURE_2D ||1805src_target == PIPE_TEXTURE_RECT) &&1806src_samples <= 1) {1807/* Set framebuffer state. */1808if (is_zsbuf) {1809fb_state.zsbuf = dst;1810} else {1811fb_state.cbufs[0] = dst;1812}1813pipe->set_framebuffer_state(pipe, &fb_state);18141815/* Draw. */1816pipe->set_sample_mask(pipe, ~0);1817blitter_draw_tex(ctx, dstbox->x, dstbox->y,1818dstbox->x + dstbox->width,1819dstbox->y + dstbox->height,1820src, src_width0, src_height0, srcbox->x, srcbox->y,1821srcbox->x + srcbox->width, srcbox->y + srcbox->height,18220, 0, uses_txf, UTIL_BLITTER_ATTRIB_TEXCOORD_XY);1823} else {1824/* Draw the quad with the generic codepath. */1825int dst_z;1826for (dst_z = 0; dst_z < dstbox->depth; dst_z++) {1827struct pipe_surface *old;1828bool flipped = (srcbox->depth < 0);1829float depth_center_offset = 0.0;1830int src_depth = abs(srcbox->depth);1831float src_z_step = src_depth / (float)dstbox->depth;18321833/* Scale Z properly if the blit is scaled.1834*1835* When downscaling, we want the coordinates centered, so that1836* mipmapping works for 3D textures. For example, when generating1837* a 4x4x4 level, this wouldn't average the pixels:1838*1839* src Z: 0 1 2 3 4 5 6 71840* dst Z: 0 1 2 31841*1842* Because the pixels are not centered below the pixels of the higher1843* level. Therefore, we want this:1844* src Z: 0 1 2 3 4 5 6 71845* dst Z: 0 1 2 31846*1847* This calculation is taken from the radv driver.1848*/1849if (src_target == PIPE_TEXTURE_3D)1850depth_center_offset = 0.5 / dstbox->depth * src_depth;18511852if (flipped) {1853src_z_step *= - 1;1854depth_center_offset *= -1;1855}18561857float src_z = dst_z * src_z_step + depth_center_offset;18581859/* Set framebuffer state. */1860if (is_zsbuf) {1861fb_state.zsbuf = dst;1862} else {1863fb_state.cbufs[0] = dst;1864}1865pipe->set_framebuffer_state(pipe, &fb_state);18661867/* See if we need to blit a multisample or singlesample buffer. */1868if (src_samples == dst_samples && dst_samples > 1) {1869/* MSAA copy. */1870unsigned i, max_sample = dst_samples - 1;18711872for (i = 0; i <= max_sample; i++) {1873pipe->set_sample_mask(pipe, 1 << i);1874blitter_draw_tex(ctx, dstbox->x, dstbox->y,1875dstbox->x + dstbox->width,1876dstbox->y + dstbox->height,1877src, src_width0, src_height0,1878srcbox->x, srcbox->y,1879srcbox->x + srcbox->width,1880srcbox->y + srcbox->height,1881srcbox->z + src_z, i, uses_txf,1882UTIL_BLITTER_ATTRIB_TEXCOORD_XYZW);1883}1884} else {1885/* Normal copy, MSAA upsampling, or MSAA resolve. */1886pipe->set_sample_mask(pipe, ~0);1887blitter_draw_tex(ctx, dstbox->x, dstbox->y,1888dstbox->x + dstbox->width,1889dstbox->y + dstbox->height,1890src, src_width0, src_height0,1891srcbox->x, srcbox->y,1892srcbox->x + srcbox->width,1893srcbox->y + srcbox->height,1894srcbox->z + src_z, 0, uses_txf,1895UTIL_BLITTER_ATTRIB_TEXCOORD_XYZW);1896}18971898/* Get the next surface or (if this is the last iteration)1899* just unreference the last one. */1900old = dst;1901if (dst_z < dstbox->depth-1) {1902dst = util_blitter_get_next_surface_layer(ctx->base.pipe, dst);1903}1904if (dst_z) {1905pipe_surface_reference(&old, NULL);1906}1907}1908}1909}19101911void util_blitter_blit_generic(struct blitter_context *blitter,1912struct pipe_surface *dst,1913const struct pipe_box *dstbox,1914struct pipe_sampler_view *src,1915const struct pipe_box *srcbox,1916unsigned src_width0, unsigned src_height0,1917unsigned mask, unsigned filter,1918const struct pipe_scissor_state *scissor,1919bool alpha_blend)1920{1921struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;1922struct pipe_context *pipe = ctx->base.pipe;1923enum pipe_texture_target src_target = src->target;1924unsigned src_samples = src->texture->nr_samples;1925unsigned dst_samples = dst->texture->nr_samples;1926void *sampler_state;1927const struct util_format_description *src_desc =1928util_format_description(src->format);1929const struct util_format_description *dst_desc =1930util_format_description(dst->format);19311932bool src_has_color = src_desc->colorspace != UTIL_FORMAT_COLORSPACE_ZS;1933bool src_has_depth = util_format_has_depth(src_desc);1934bool src_has_stencil = util_format_has_stencil(src_desc);19351936bool dst_has_color = mask & PIPE_MASK_RGBA &&1937dst_desc->colorspace != UTIL_FORMAT_COLORSPACE_ZS;1938bool dst_has_depth = mask & PIPE_MASK_Z &&1939util_format_has_depth(dst_desc);1940bool dst_has_stencil = ctx->has_stencil_export &&1941mask & PIPE_MASK_S &&1942util_format_has_stencil(dst_desc);19431944/* Return if there is nothing to do. */1945if (!dst_has_color && !dst_has_depth && !dst_has_stencil) {1946return;1947}19481949bool is_scaled = dstbox->width != abs(srcbox->width) ||1950dstbox->height != abs(srcbox->height);19511952if (src_has_stencil || !is_scaled)1953filter = PIPE_TEX_FILTER_NEAREST;19541955bool use_txf = false;19561957/* Don't support scaled blits. The TXF shader uses F2I for rounding. */1958if (ctx->has_txf &&1959!is_scaled &&1960filter == PIPE_TEX_FILTER_NEAREST &&1961src->target != PIPE_TEXTURE_CUBE &&1962src->target != PIPE_TEXTURE_CUBE_ARRAY) {1963int src_width = u_minify(src_width0, src->u.tex.first_level);1964int src_height = u_minify(src_height0, src->u.tex.first_level);1965int src_depth = src->u.tex.last_layer + 1;1966struct pipe_box box = *srcbox;19671968/* Eliminate negative width/height/depth. */1969if (box.width < 0) {1970box.x += box.width;1971box.width *= -1;1972}1973if (box.height < 0) {1974box.y += box.height;1975box.height *= -1;1976}1977if (box.depth < 0) {1978box.z += box.depth;1979box.depth *= -1;1980}19811982/* See if srcbox is in bounds. TXF doesn't clamp the coordinates. */1983use_txf =1984box.x >= 0 && box.x < src_width &&1985box.y >= 0 && box.y < src_height &&1986box.z >= 0 && box.z < src_depth &&1987box.x + box.width > 0 && box.x + box.width <= src_width &&1988box.y + box.height > 0 && box.y + box.height <= src_height &&1989box.z + box.depth > 0 && box.z + box.depth <= src_depth;1990}19911992/* Check whether the states are properly saved. */1993util_blitter_set_running_flag(blitter);1994blitter_check_saved_vertex_states(ctx);1995blitter_check_saved_fragment_states(ctx);1996blitter_check_saved_textures(ctx);1997blitter_check_saved_fb_state(ctx);1998blitter_disable_render_cond(ctx);19992000/* Blend, DSA, fragment shader. */2001if (dst_has_depth && dst_has_stencil) {2002pipe->bind_blend_state(pipe, ctx->blend[0][0]);2003pipe->bind_depth_stencil_alpha_state(pipe,2004ctx->dsa_write_depth_stencil);2005if (src_has_color) {2006assert(use_txf);2007ctx->bind_fs_state(pipe,2008blitter_get_fs_pack_color_zs(ctx, src_target,2009src_samples, dst->format, false));2010} else {2011ctx->bind_fs_state(pipe,2012blitter_get_fs_texfetch_depthstencil(ctx, src_target,2013src_samples, use_txf));2014}2015} else if (dst_has_depth) {2016pipe->bind_blend_state(pipe, ctx->blend[0][0]);2017pipe->bind_depth_stencil_alpha_state(pipe,2018ctx->dsa_write_depth_keep_stencil);2019if (src_has_color &&2020(src->format == PIPE_FORMAT_R32_UINT ||2021src->format == PIPE_FORMAT_R32G32_UINT)) {2022assert(use_txf);2023ctx->bind_fs_state(pipe,2024blitter_get_fs_pack_color_zs(ctx, src_target,2025src_samples, dst->format, false));2026} else {2027ctx->bind_fs_state(pipe,2028blitter_get_fs_texfetch_depth(ctx, src_target,2029src_samples, use_txf));2030}2031} else if (dst_has_stencil) {2032pipe->bind_blend_state(pipe, ctx->blend[0][0]);2033pipe->bind_depth_stencil_alpha_state(pipe,2034ctx->dsa_keep_depth_write_stencil);20352036assert(src_has_stencil); /* unpacking from color is unsupported */2037ctx->bind_fs_state(pipe,2038blitter_get_fs_texfetch_stencil(ctx, src_target,2039src_samples, use_txf));2040} else {2041unsigned colormask = mask & PIPE_MASK_RGBA;20422043pipe->bind_blend_state(pipe, ctx->blend[colormask][alpha_blend]);2044pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil);20452046if (src_has_depth &&2047(dst->format == PIPE_FORMAT_R32_UINT ||2048dst->format == PIPE_FORMAT_R32G32_UINT)) {2049assert(use_txf);2050ctx->bind_fs_state(pipe,2051blitter_get_fs_pack_color_zs(ctx, src_target,2052src_samples, src->format, true));2053} else {2054ctx->bind_fs_state(pipe,2055blitter_get_fs_texfetch_col(ctx, src->format, dst->format, src_target,2056src_samples, dst_samples, filter,2057use_txf));2058}2059}20602061/* Set the linear filter only for scaled color non-MSAA blits. */2062if (filter == PIPE_TEX_FILTER_LINEAR) {2063if (src_target == PIPE_TEXTURE_RECT) {2064sampler_state = ctx->sampler_state_rect_linear;2065} else {2066sampler_state = ctx->sampler_state_linear;2067}2068} else {2069if (src_target == PIPE_TEXTURE_RECT) {2070sampler_state = ctx->sampler_state_rect;2071} else {2072sampler_state = ctx->sampler_state;2073}2074}20752076/* Set samplers. */2077if (src_has_depth && src_has_stencil &&2078(dst_has_color || (dst_has_depth && dst_has_stencil))) {2079/* Setup two samplers, one for depth and the other one for stencil. */2080struct pipe_sampler_view templ;2081struct pipe_sampler_view *views[2];2082void *samplers[2] = {sampler_state, sampler_state};20832084templ = *src;2085templ.format = util_format_stencil_only(templ.format);2086assert(templ.format != PIPE_FORMAT_NONE);20872088views[0] = src;2089views[1] = pipe->create_sampler_view(pipe, src->texture, &templ);20902091pipe->set_sampler_views(pipe, PIPE_SHADER_FRAGMENT, 0, 2, 0, views);2092pipe->bind_sampler_states(pipe, PIPE_SHADER_FRAGMENT, 0, 2, samplers);20932094pipe_sampler_view_reference(&views[1], NULL);2095} else if (src_has_stencil && dst_has_stencil) {2096/* Set a stencil-only sampler view for it not to sample depth instead. */2097struct pipe_sampler_view templ;2098struct pipe_sampler_view *view;20992100templ = *src;2101templ.format = util_format_stencil_only(templ.format);2102assert(templ.format != PIPE_FORMAT_NONE);21032104view = pipe->create_sampler_view(pipe, src->texture, &templ);21052106pipe->set_sampler_views(pipe, PIPE_SHADER_FRAGMENT, 0, 1, 0, &view);2107pipe->bind_sampler_states(pipe, PIPE_SHADER_FRAGMENT,21080, 1, &sampler_state);21092110pipe_sampler_view_reference(&view, NULL);2111} else {2112pipe->set_sampler_views(pipe, PIPE_SHADER_FRAGMENT, 0, 1, 0, &src);2113pipe->bind_sampler_states(pipe, PIPE_SHADER_FRAGMENT,21140, 1, &sampler_state);2115}21162117if (scissor) {2118pipe->set_scissor_states(pipe, 0, 1, scissor);2119}21202121blitter_set_common_draw_rect_state(ctx, scissor != NULL, dst_samples > 1);21222123do_blits(ctx, dst, dstbox, src, src_width0, src_height0,2124srcbox, dst_has_depth || dst_has_stencil, use_txf);21252126util_blitter_restore_vertex_states(blitter);2127util_blitter_restore_fragment_states(blitter);2128util_blitter_restore_textures(blitter);2129util_blitter_restore_fb_state(blitter);2130if (scissor) {2131pipe->set_scissor_states(pipe, 0, 1, &ctx->base.saved_scissor);2132}2133util_blitter_restore_render_cond(blitter);2134util_blitter_unset_running_flag(blitter);2135}21362137void2138util_blitter_blit(struct blitter_context *blitter,2139const struct pipe_blit_info *info)2140{2141struct pipe_resource *dst = info->dst.resource;2142struct pipe_resource *src = info->src.resource;2143struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;2144struct pipe_context *pipe = ctx->base.pipe;2145struct pipe_surface *dst_view, dst_templ;2146struct pipe_sampler_view src_templ, *src_view;21472148/* Initialize the surface. */2149util_blitter_default_dst_texture(&dst_templ, dst, info->dst.level,2150info->dst.box.z);2151dst_templ.format = info->dst.format;2152dst_view = pipe->create_surface(pipe, dst, &dst_templ);21532154/* Initialize the sampler view. */2155util_blitter_default_src_texture(blitter, &src_templ, src, info->src.level);2156src_templ.format = info->src.format;2157src_view = pipe->create_sampler_view(pipe, src, &src_templ);21582159/* Copy. */2160util_blitter_blit_generic(blitter, dst_view, &info->dst.box,2161src_view, &info->src.box, src->width0, src->height0,2162info->mask, info->filter,2163info->scissor_enable ? &info->scissor : NULL,2164info->alpha_blend);21652166pipe_surface_reference(&dst_view, NULL);2167pipe_sampler_view_reference(&src_view, NULL);2168}21692170void util_blitter_generate_mipmap(struct blitter_context *blitter,2171struct pipe_resource *tex,2172enum pipe_format format,2173unsigned base_level, unsigned last_level,2174unsigned first_layer, unsigned last_layer)2175{2176struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;2177struct pipe_context *pipe = ctx->base.pipe;2178struct pipe_surface dst_templ, *dst_view;2179struct pipe_sampler_view src_templ, *src_view;2180bool is_depth;2181void *sampler_state;2182const struct util_format_description *desc =2183util_format_description(format);2184unsigned src_level;2185unsigned target = tex->target;21862187if (ctx->cube_as_2darray &&2188(target == PIPE_TEXTURE_CUBE || target == PIPE_TEXTURE_CUBE_ARRAY))2189target = PIPE_TEXTURE_2D_ARRAY;21902191assert(tex->nr_samples <= 1);2192/* Disallow stencil formats without depth. */2193assert(!util_format_has_stencil(desc) || util_format_has_depth(desc));21942195is_depth = desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS;21962197/* Check whether the states are properly saved. */2198util_blitter_set_running_flag(blitter);2199blitter_check_saved_vertex_states(ctx);2200blitter_check_saved_fragment_states(ctx);2201blitter_check_saved_textures(ctx);2202blitter_check_saved_fb_state(ctx);2203blitter_disable_render_cond(ctx);22042205/* Set states. */2206if (is_depth) {2207pipe->bind_blend_state(pipe, ctx->blend[0][0]);2208pipe->bind_depth_stencil_alpha_state(pipe,2209ctx->dsa_write_depth_keep_stencil);2210ctx->bind_fs_state(pipe,2211blitter_get_fs_texfetch_depth(ctx, target, 1, false));2212} else {2213pipe->bind_blend_state(pipe, ctx->blend[PIPE_MASK_RGBA][0]);2214pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil);2215ctx->bind_fs_state(pipe,2216blitter_get_fs_texfetch_col(ctx, tex->format, tex->format, target,22171, 1, PIPE_TEX_FILTER_LINEAR, false));2218}22192220if (target == PIPE_TEXTURE_RECT) {2221sampler_state = ctx->sampler_state_rect_linear;2222} else {2223sampler_state = ctx->sampler_state_linear;2224}2225pipe->bind_sampler_states(pipe, PIPE_SHADER_FRAGMENT,22260, 1, &sampler_state);22272228blitter_set_common_draw_rect_state(ctx, false, false);22292230for (src_level = base_level; src_level < last_level; src_level++) {2231struct pipe_box dstbox = {0}, srcbox = {0};2232unsigned dst_level = src_level + 1;22332234dstbox.width = u_minify(tex->width0, dst_level);2235dstbox.height = u_minify(tex->height0, dst_level);22362237srcbox.width = u_minify(tex->width0, src_level);2238srcbox.height = u_minify(tex->height0, src_level);22392240if (target == PIPE_TEXTURE_3D) {2241dstbox.depth = util_num_layers(tex, dst_level);2242srcbox.depth = util_num_layers(tex, src_level);2243} else {2244dstbox.z = srcbox.z = first_layer;2245dstbox.depth = srcbox.depth = last_layer - first_layer + 1;2246}22472248/* Initialize the surface. */2249util_blitter_default_dst_texture(&dst_templ, tex, dst_level,2250first_layer);2251dst_templ.format = format;2252dst_view = pipe->create_surface(pipe, tex, &dst_templ);22532254/* Initialize the sampler view. */2255util_blitter_default_src_texture(blitter, &src_templ, tex, src_level);2256src_templ.format = format;2257src_view = pipe->create_sampler_view(pipe, tex, &src_templ);22582259pipe->set_sampler_views(pipe, PIPE_SHADER_FRAGMENT, 0, 1, 0, &src_view);22602261do_blits(ctx, dst_view, &dstbox, src_view, tex->width0, tex->height0,2262&srcbox, is_depth, false);22632264pipe_surface_reference(&dst_view, NULL);2265pipe_sampler_view_reference(&src_view, NULL);2266}22672268util_blitter_restore_vertex_states(blitter);2269util_blitter_restore_fragment_states(blitter);2270util_blitter_restore_textures(blitter);2271util_blitter_restore_fb_state(blitter);2272util_blitter_restore_render_cond(blitter);2273util_blitter_unset_running_flag(blitter);2274}22752276/* Clear a region of a color surface to a constant value. */2277void util_blitter_clear_render_target(struct blitter_context *blitter,2278struct pipe_surface *dstsurf,2279const union pipe_color_union *color,2280unsigned dstx, unsigned dsty,2281unsigned width, unsigned height)2282{2283struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;2284struct pipe_context *pipe = ctx->base.pipe;2285struct pipe_framebuffer_state fb_state;2286bool msaa;2287unsigned num_layers;22882289assert(dstsurf->texture);2290if (!dstsurf->texture)2291return;22922293/* check the saved state */2294util_blitter_set_running_flag(blitter);2295blitter_check_saved_vertex_states(ctx);2296blitter_check_saved_fragment_states(ctx);2297blitter_check_saved_fb_state(ctx);2298blitter_disable_render_cond(ctx);22992300/* bind states */2301pipe->bind_blend_state(pipe, ctx->blend[PIPE_MASK_RGBA][0]);2302pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil);2303bind_fs_write_one_cbuf(ctx);23042305/* set a framebuffer state */2306fb_state.width = dstsurf->width;2307fb_state.height = dstsurf->height;2308fb_state.nr_cbufs = 1;2309fb_state.cbufs[0] = dstsurf;2310fb_state.zsbuf = 0;2311pipe->set_framebuffer_state(pipe, &fb_state);2312pipe->set_sample_mask(pipe, ~0);2313msaa = util_framebuffer_get_num_samples(&fb_state) > 1;23142315blitter_set_dst_dimensions(ctx, dstsurf->width, dstsurf->height);23162317union blitter_attrib attrib;2318memcpy(attrib.color, color->ui, sizeof(color->ui));23192320num_layers = dstsurf->u.tex.last_layer - dstsurf->u.tex.first_layer + 1;2321if (num_layers > 1 && ctx->has_layered) {2322blitter_set_common_draw_rect_state(ctx, false, msaa);2323blitter->draw_rectangle(blitter, ctx->velem_state, get_vs_layered,2324dstx, dsty, dstx+width, dsty+height, 0,2325num_layers, UTIL_BLITTER_ATTRIB_COLOR, &attrib);2326} else {2327blitter_set_common_draw_rect_state(ctx, false, msaa);2328blitter->draw_rectangle(blitter, ctx->velem_state,2329get_vs_passthrough_pos_generic,2330dstx, dsty, dstx+width, dsty+height, 0,23311, UTIL_BLITTER_ATTRIB_COLOR, &attrib);2332}23332334util_blitter_restore_vertex_states(blitter);2335util_blitter_restore_fragment_states(blitter);2336util_blitter_restore_fb_state(blitter);2337util_blitter_restore_render_cond(blitter);2338util_blitter_unset_running_flag(blitter);2339}23402341/* Clear a region of a depth stencil surface. */2342void util_blitter_clear_depth_stencil(struct blitter_context *blitter,2343struct pipe_surface *dstsurf,2344unsigned clear_flags,2345double depth,2346unsigned stencil,2347unsigned dstx, unsigned dsty,2348unsigned width, unsigned height)2349{2350struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;2351struct pipe_context *pipe = ctx->base.pipe;2352struct pipe_framebuffer_state fb_state;2353struct pipe_stencil_ref sr = { { 0 } };2354unsigned num_layers;23552356assert(dstsurf->texture);2357if (!dstsurf->texture)2358return;23592360/* check the saved state */2361util_blitter_set_running_flag(blitter);2362blitter_check_saved_vertex_states(ctx);2363blitter_check_saved_fragment_states(ctx);2364blitter_check_saved_fb_state(ctx);2365blitter_disable_render_cond(ctx);23662367/* bind states */2368pipe->bind_blend_state(pipe, ctx->blend[0][0]);2369if ((clear_flags & PIPE_CLEAR_DEPTHSTENCIL) == PIPE_CLEAR_DEPTHSTENCIL) {2370sr.ref_value[0] = stencil & 0xff;2371pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_write_depth_stencil);2372pipe->set_stencil_ref(pipe, sr);2373}2374else if (clear_flags & PIPE_CLEAR_DEPTH) {2375pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_write_depth_keep_stencil);2376}2377else if (clear_flags & PIPE_CLEAR_STENCIL) {2378sr.ref_value[0] = stencil & 0xff;2379pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_write_stencil);2380pipe->set_stencil_ref(pipe, sr);2381}2382else2383/* hmm that should be illegal probably, or make it a no-op somewhere */2384pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil);23852386bind_fs_empty(ctx);23872388/* set a framebuffer state */2389fb_state.width = dstsurf->width;2390fb_state.height = dstsurf->height;2391fb_state.nr_cbufs = 0;2392fb_state.cbufs[0] = 0;2393fb_state.zsbuf = dstsurf;2394pipe->set_framebuffer_state(pipe, &fb_state);2395pipe->set_sample_mask(pipe, ~0);23962397blitter_set_dst_dimensions(ctx, dstsurf->width, dstsurf->height);23982399num_layers = dstsurf->u.tex.last_layer - dstsurf->u.tex.first_layer + 1;2400if (num_layers > 1 && ctx->has_layered) {2401blitter_set_common_draw_rect_state(ctx, false, false);2402blitter->draw_rectangle(blitter, ctx->velem_state, get_vs_layered,2403dstx, dsty, dstx+width, dsty+height, depth,2404num_layers, UTIL_BLITTER_ATTRIB_NONE, NULL);2405} else {2406blitter_set_common_draw_rect_state(ctx, false, false);2407blitter->draw_rectangle(blitter, ctx->velem_state,2408get_vs_passthrough_pos,2409dstx, dsty, dstx+width, dsty+height, depth, 1,2410UTIL_BLITTER_ATTRIB_NONE, NULL);2411}24122413util_blitter_restore_vertex_states(blitter);2414util_blitter_restore_fragment_states(blitter);2415util_blitter_restore_fb_state(blitter);2416util_blitter_restore_render_cond(blitter);2417util_blitter_unset_running_flag(blitter);2418}24192420/* draw a rectangle across a region using a custom dsa stage - for r600g */2421void util_blitter_custom_depth_stencil(struct blitter_context *blitter,2422struct pipe_surface *zsurf,2423struct pipe_surface *cbsurf,2424unsigned sample_mask,2425void *dsa_stage, float depth)2426{2427struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;2428struct pipe_context *pipe = ctx->base.pipe;2429struct pipe_framebuffer_state fb_state;24302431assert(zsurf->texture);2432if (!zsurf->texture)2433return;24342435/* check the saved state */2436util_blitter_set_running_flag(blitter);2437blitter_check_saved_vertex_states(ctx);2438blitter_check_saved_fragment_states(ctx);2439blitter_check_saved_fb_state(ctx);2440blitter_disable_render_cond(ctx);24412442/* bind states */2443pipe->bind_blend_state(pipe, cbsurf ? ctx->blend[PIPE_MASK_RGBA][0] :2444ctx->blend[0][0]);2445pipe->bind_depth_stencil_alpha_state(pipe, dsa_stage);2446if (cbsurf)2447bind_fs_write_one_cbuf(ctx);2448else2449bind_fs_empty(ctx);24502451/* set a framebuffer state */2452fb_state.width = zsurf->width;2453fb_state.height = zsurf->height;2454fb_state.nr_cbufs = 1;2455if (cbsurf) {2456fb_state.cbufs[0] = cbsurf;2457fb_state.nr_cbufs = 1;2458} else {2459fb_state.cbufs[0] = NULL;2460fb_state.nr_cbufs = 0;2461}2462fb_state.zsbuf = zsurf;2463pipe->set_framebuffer_state(pipe, &fb_state);2464pipe->set_sample_mask(pipe, sample_mask);24652466blitter_set_common_draw_rect_state(ctx, false,2467util_framebuffer_get_num_samples(&fb_state) > 1);2468blitter_set_dst_dimensions(ctx, zsurf->width, zsurf->height);2469blitter->draw_rectangle(blitter, ctx->velem_state, get_vs_passthrough_pos,24700, 0, zsurf->width, zsurf->height, depth,24711, UTIL_BLITTER_ATTRIB_NONE, NULL);24722473util_blitter_restore_vertex_states(blitter);2474util_blitter_restore_fragment_states(blitter);2475util_blitter_restore_fb_state(blitter);2476util_blitter_restore_render_cond(blitter);2477util_blitter_unset_running_flag(blitter);2478}24792480void util_blitter_copy_buffer(struct blitter_context *blitter,2481struct pipe_resource *dst,2482unsigned dstx,2483struct pipe_resource *src,2484unsigned srcx,2485unsigned size)2486{2487struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;2488struct pipe_context *pipe = ctx->base.pipe;2489struct pipe_vertex_buffer vb;2490struct pipe_stream_output_target *so_target;2491unsigned offsets[PIPE_MAX_SO_BUFFERS] = {0};24922493if (srcx >= src->width0 ||2494dstx >= dst->width0) {2495return;2496}2497if (srcx + size > src->width0) {2498size = src->width0 - srcx;2499}2500if (dstx + size > dst->width0) {2501size = dst->width0 - dstx;2502}25032504/* Drivers not capable of Stream Out should not call this function2505* in the first place. */2506assert(ctx->has_stream_out);25072508/* Some alignment is required. */2509if (srcx % 4 != 0 || dstx % 4 != 0 || size % 4 != 0 ||2510!ctx->has_stream_out) {2511struct pipe_box box;2512u_box_1d(srcx, size, &box);2513util_resource_copy_region(pipe, dst, 0, dstx, 0, 0, src, 0, &box);2514return;2515}25162517util_blitter_set_running_flag(blitter);2518blitter_check_saved_vertex_states(ctx);2519blitter_disable_render_cond(ctx);25202521vb.is_user_buffer = false;2522vb.buffer.resource = src;2523vb.buffer_offset = srcx;2524vb.stride = 4;25252526pipe->set_vertex_buffers(pipe, ctx->base.vb_slot, 1, 0, false, &vb);2527pipe->bind_vertex_elements_state(pipe, ctx->velem_state_readbuf[0]);2528bind_vs_pos_only(ctx, 1);2529if (ctx->has_geometry_shader)2530pipe->bind_gs_state(pipe, NULL);2531if (ctx->has_tessellation) {2532pipe->bind_tcs_state(pipe, NULL);2533pipe->bind_tes_state(pipe, NULL);2534}2535pipe->bind_rasterizer_state(pipe, ctx->rs_discard_state);25362537so_target = pipe->create_stream_output_target(pipe, dst, dstx, size);2538pipe->set_stream_output_targets(pipe, 1, &so_target, offsets);25392540util_draw_arrays(pipe, PIPE_PRIM_POINTS, 0, size / 4);25412542util_blitter_restore_vertex_states(blitter);2543util_blitter_restore_render_cond(blitter);2544util_blitter_unset_running_flag(blitter);2545pipe_so_target_reference(&so_target, NULL);2546}25472548void util_blitter_clear_buffer(struct blitter_context *blitter,2549struct pipe_resource *dst,2550unsigned offset, unsigned size,2551unsigned num_channels,2552const union pipe_color_union *clear_value)2553{2554struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;2555struct pipe_context *pipe = ctx->base.pipe;2556struct pipe_vertex_buffer vb = {0};2557struct pipe_stream_output_target *so_target = NULL;2558unsigned offsets[PIPE_MAX_SO_BUFFERS] = {0};25592560assert(num_channels >= 1);2561assert(num_channels <= 4);25622563/* IMPORTANT: DON'T DO ANY BOUNDS CHECKING HERE!2564*2565* R600 uses this to initialize texture resources, so width0 might not be2566* what you think it is.2567*/25682569/* Streamout is required. */2570if (!ctx->has_stream_out) {2571assert(!"Streamout unsupported in util_blitter_clear_buffer()");2572return;2573}25742575/* Some alignment is required. */2576if (offset % 4 != 0 || size % 4 != 0) {2577assert(!"Bad alignment in util_blitter_clear_buffer()");2578return;2579}25802581u_upload_data(pipe->stream_uploader, 0, num_channels*4, 4, clear_value,2582&vb.buffer_offset, &vb.buffer.resource);2583if (!vb.buffer.resource)2584goto out;25852586vb.stride = 0;25872588util_blitter_set_running_flag(blitter);2589blitter_check_saved_vertex_states(ctx);2590blitter_disable_render_cond(ctx);25912592pipe->set_vertex_buffers(pipe, ctx->base.vb_slot, 1, 0, false, &vb);2593pipe->bind_vertex_elements_state(pipe,2594ctx->velem_state_readbuf[num_channels-1]);2595bind_vs_pos_only(ctx, num_channels);2596if (ctx->has_geometry_shader)2597pipe->bind_gs_state(pipe, NULL);2598if (ctx->has_tessellation) {2599pipe->bind_tcs_state(pipe, NULL);2600pipe->bind_tes_state(pipe, NULL);2601}2602pipe->bind_rasterizer_state(pipe, ctx->rs_discard_state);26032604so_target = pipe->create_stream_output_target(pipe, dst, offset, size);2605pipe->set_stream_output_targets(pipe, 1, &so_target, offsets);26062607util_draw_arrays(pipe, PIPE_PRIM_POINTS, 0, size / 4);26082609out:2610util_blitter_restore_vertex_states(blitter);2611util_blitter_restore_render_cond(blitter);2612util_blitter_unset_running_flag(blitter);2613pipe_so_target_reference(&so_target, NULL);2614pipe_resource_reference(&vb.buffer.resource, NULL);2615}26162617/* probably radeon specific */2618void util_blitter_custom_resolve_color(struct blitter_context *blitter,2619struct pipe_resource *dst,2620unsigned dst_level,2621unsigned dst_layer,2622struct pipe_resource *src,2623unsigned src_layer,2624unsigned sample_mask,2625void *custom_blend,2626enum pipe_format format)2627{2628struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;2629struct pipe_context *pipe = ctx->base.pipe;2630struct pipe_framebuffer_state fb_state;2631struct pipe_surface *srcsurf, *dstsurf, surf_tmpl;26322633util_blitter_set_running_flag(blitter);2634blitter_check_saved_vertex_states(ctx);2635blitter_check_saved_fragment_states(ctx);2636blitter_disable_render_cond(ctx);26372638/* bind states */2639pipe->bind_blend_state(pipe, custom_blend);2640pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil);2641bind_fs_write_one_cbuf(ctx);2642pipe->set_sample_mask(pipe, sample_mask);26432644memset(&surf_tmpl, 0, sizeof(surf_tmpl));2645surf_tmpl.format = format;2646surf_tmpl.u.tex.level = dst_level;2647surf_tmpl.u.tex.first_layer = dst_layer;2648surf_tmpl.u.tex.last_layer = dst_layer;26492650dstsurf = pipe->create_surface(pipe, dst, &surf_tmpl);26512652surf_tmpl.u.tex.level = 0;2653surf_tmpl.u.tex.first_layer = src_layer;2654surf_tmpl.u.tex.last_layer = src_layer;26552656srcsurf = pipe->create_surface(pipe, src, &surf_tmpl);26572658/* set a framebuffer state */2659fb_state.width = src->width0;2660fb_state.height = src->height0;2661fb_state.nr_cbufs = 2;2662fb_state.cbufs[0] = srcsurf;2663fb_state.cbufs[1] = dstsurf;2664fb_state.zsbuf = NULL;2665pipe->set_framebuffer_state(pipe, &fb_state);26662667blitter_set_common_draw_rect_state(ctx, false,2668util_framebuffer_get_num_samples(&fb_state) > 1);2669blitter_set_dst_dimensions(ctx, src->width0, src->height0);2670blitter->draw_rectangle(blitter, ctx->velem_state, get_vs_passthrough_pos,26710, 0, src->width0, src->height0,26720, 1, UTIL_BLITTER_ATTRIB_NONE, NULL);2673util_blitter_restore_fb_state(blitter);2674util_blitter_restore_vertex_states(blitter);2675util_blitter_restore_fragment_states(blitter);2676util_blitter_restore_render_cond(blitter);2677util_blitter_unset_running_flag(blitter);26782679pipe_surface_reference(&srcsurf, NULL);2680pipe_surface_reference(&dstsurf, NULL);2681}26822683void util_blitter_custom_color(struct blitter_context *blitter,2684struct pipe_surface *dstsurf,2685void *custom_blend)2686{2687struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;2688struct pipe_context *pipe = ctx->base.pipe;2689struct pipe_framebuffer_state fb_state;26902691assert(dstsurf->texture);2692if (!dstsurf->texture)2693return;26942695/* check the saved state */2696util_blitter_set_running_flag(blitter);2697blitter_check_saved_vertex_states(ctx);2698blitter_check_saved_fragment_states(ctx);2699blitter_check_saved_fb_state(ctx);2700blitter_disable_render_cond(ctx);27012702/* bind states */2703pipe->bind_blend_state(pipe, custom_blend ? custom_blend2704: ctx->blend[PIPE_MASK_RGBA][0]);2705pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil);2706bind_fs_write_one_cbuf(ctx);27072708/* set a framebuffer state */2709fb_state.width = dstsurf->width;2710fb_state.height = dstsurf->height;2711fb_state.nr_cbufs = 1;2712fb_state.cbufs[0] = dstsurf;2713fb_state.zsbuf = 0;2714pipe->set_framebuffer_state(pipe, &fb_state);2715pipe->set_sample_mask(pipe, ~0);27162717blitter_set_common_draw_rect_state(ctx, false,2718util_framebuffer_get_num_samples(&fb_state) > 1);2719blitter_set_dst_dimensions(ctx, dstsurf->width, dstsurf->height);2720blitter->draw_rectangle(blitter, ctx->velem_state, get_vs_passthrough_pos,27210, 0, dstsurf->width, dstsurf->height,27220, 1, UTIL_BLITTER_ATTRIB_NONE, NULL);27232724util_blitter_restore_vertex_states(blitter);2725util_blitter_restore_fragment_states(blitter);2726util_blitter_restore_fb_state(blitter);2727util_blitter_restore_render_cond(blitter);2728util_blitter_unset_running_flag(blitter);2729}27302731static void *get_custom_vs(struct blitter_context *blitter)2732{2733struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;27342735return ctx->custom_vs;2736}27372738/**2739* Performs a custom blit to the destination surface, using the VS and FS2740* provided.2741*2742* Used by vc4 for the 8-bit linear-to-tiled blit.2743*/2744void util_blitter_custom_shader(struct blitter_context *blitter,2745struct pipe_surface *dstsurf,2746void *custom_vs, void *custom_fs)2747{2748struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;2749struct pipe_context *pipe = ctx->base.pipe;2750struct pipe_framebuffer_state fb_state = { 0 };27512752ctx->custom_vs = custom_vs;27532754assert(dstsurf->texture);2755if (!dstsurf->texture)2756return;27572758/* check the saved state */2759util_blitter_set_running_flag(blitter);2760blitter_check_saved_vertex_states(ctx);2761blitter_check_saved_fragment_states(ctx);2762blitter_check_saved_fb_state(ctx);2763blitter_disable_render_cond(ctx);27642765/* bind states */2766pipe->bind_blend_state(pipe, ctx->blend[PIPE_MASK_RGBA][0]);2767pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil);2768pipe->bind_fs_state(pipe, custom_fs);27692770/* set a framebuffer state */2771fb_state.width = dstsurf->width;2772fb_state.height = dstsurf->height;2773fb_state.nr_cbufs = 1;2774fb_state.cbufs[0] = dstsurf;2775pipe->set_framebuffer_state(pipe, &fb_state);2776pipe->set_sample_mask(pipe, ~0);27772778blitter_set_common_draw_rect_state(ctx, false,2779util_framebuffer_get_num_samples(&fb_state) > 1);2780blitter_set_dst_dimensions(ctx, dstsurf->width, dstsurf->height);2781blitter->draw_rectangle(blitter, ctx->velem_state, get_custom_vs,27820, 0, dstsurf->width, dstsurf->height,27830, 1, UTIL_BLITTER_ATTRIB_NONE, NULL);27842785util_blitter_restore_vertex_states(blitter);2786util_blitter_restore_fragment_states(blitter);2787util_blitter_restore_fb_state(blitter);2788util_blitter_restore_render_cond(blitter);2789util_blitter_unset_running_flag(blitter);2790}27912792static void *2793get_stencil_blit_fallback_fs(struct blitter_context_priv *ctx, bool msaa_src)2794{2795if (!ctx->fs_stencil_blit_fallback[msaa_src]) {2796ctx->fs_stencil_blit_fallback[msaa_src] =2797util_make_fs_stencil_blit(ctx->base.pipe, msaa_src);2798}27992800return ctx->fs_stencil_blit_fallback[msaa_src];2801}28022803static void *2804get_stencil_blit_fallback_dsa(struct blitter_context_priv *ctx, unsigned i)2805{2806assert(i < ARRAY_SIZE(ctx->dsa_replicate_stencil_bit));2807if (!ctx->dsa_replicate_stencil_bit[i]) {2808struct pipe_depth_stencil_alpha_state dsa = { 0 };2809dsa.depth_func = PIPE_FUNC_ALWAYS;2810dsa.stencil[0].enabled = 1;2811dsa.stencil[0].func = PIPE_FUNC_ALWAYS;2812dsa.stencil[0].fail_op = PIPE_STENCIL_OP_REPLACE;2813dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_REPLACE;2814dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_REPLACE;2815dsa.stencil[0].valuemask = 0xff;2816dsa.stencil[0].writemask = 1u << i;28172818ctx->dsa_replicate_stencil_bit[i] =2819ctx->base.pipe->create_depth_stencil_alpha_state(ctx->base.pipe, &dsa);2820}2821return ctx->dsa_replicate_stencil_bit[i];2822}28232824/**2825* Performs a series of draws to implement stencil blits texture without2826* requiring stencil writes, updating a single bit per pixel at the time.2827*/2828void2829util_blitter_stencil_fallback(struct blitter_context *blitter,2830struct pipe_resource *dst,2831unsigned dst_level,2832const struct pipe_box *dstbox,2833struct pipe_resource *src,2834unsigned src_level,2835const struct pipe_box *srcbox,2836const struct pipe_scissor_state *scissor)2837{2838struct blitter_context_priv *ctx = (struct blitter_context_priv *)blitter;2839struct pipe_context *pipe = ctx->base.pipe;28402841/* check the saved state */2842util_blitter_set_running_flag(blitter);2843blitter_check_saved_vertex_states(ctx);2844blitter_check_saved_fragment_states(ctx);2845blitter_check_saved_fb_state(ctx);2846blitter_disable_render_cond(ctx);28472848/* Initialize the surface. */2849struct pipe_surface *dst_view, dst_templ;2850util_blitter_default_dst_texture(&dst_templ, dst, dst_level, dstbox->z);2851dst_view = pipe->create_surface(pipe, dst, &dst_templ);28522853/* Initialize the sampler view. */2854struct pipe_sampler_view src_templ, *src_view;2855util_blitter_default_src_texture(blitter, &src_templ, src, src_level);2856src_templ.format = util_format_stencil_only(src_templ.format);2857src_view = pipe->create_sampler_view(pipe, src, &src_templ);28582859/* bind states */2860pipe->bind_blend_state(pipe, ctx->blend[PIPE_MASK_RGBA][0]);2861pipe->bind_fs_state(pipe,2862get_stencil_blit_fallback_fs(ctx, src->nr_samples > 1));28632864/* set a framebuffer state */2865struct pipe_framebuffer_state fb_state = { 0 };2866fb_state.width = dstbox->width;2867fb_state.height = dstbox->height;2868fb_state.zsbuf = dst_view;2869pipe->set_framebuffer_state(pipe, &fb_state);2870pipe->set_sample_mask(pipe, ~0);28712872blitter_set_common_draw_rect_state(ctx, scissor != NULL,2873util_framebuffer_get_num_samples(&fb_state) > 1);2874blitter_set_dst_dimensions(ctx, dst_view->width, dst_view->height);28752876if (scissor) {2877pipe->clear_depth_stencil(pipe, dst_view, PIPE_CLEAR_STENCIL, 0.0, 0,2878MAX2(dstbox->x, scissor->minx),2879MAX2(dstbox->y, scissor->miny),2880MIN2(dstbox->x + dstbox->width, scissor->maxx) - dstbox->x,2881MIN2(dstbox->y + dstbox->height, scissor->maxy) - dstbox->y,2882true);2883pipe->set_scissor_states(pipe, 0, 1, scissor);2884} else {2885pipe->clear_depth_stencil(pipe, dst_view, PIPE_CLEAR_STENCIL, 0.0, 0,2886dstbox->x, dstbox->y,2887dstbox->width, dstbox->height,2888true);2889}28902891pipe->set_sampler_views(pipe, PIPE_SHADER_FRAGMENT, 0, 1, 0, &src_view);2892pipe->bind_sampler_states(pipe, PIPE_SHADER_FRAGMENT, 0, 1, &ctx->sampler_state);28932894unsigned stencil_bits =2895util_format_get_component_bits(dst->format,2896UTIL_FORMAT_COLORSPACE_ZS, 1);28972898struct pipe_stencil_ref sr = { { (1u << stencil_bits) - 1 } };2899pipe->set_stencil_ref(pipe, sr);29002901union blitter_attrib coord;2902get_texcoords(src_view, src->width0, src->height0,2903srcbox->x, srcbox->y,2904srcbox->x + srcbox->width, srcbox->y + srcbox->height,2905srcbox->z, 0, true,2906&coord);29072908for (int i = 0; i < stencil_bits; ++i) {2909uint32_t mask = 1 << i;2910struct pipe_constant_buffer cb = {2911.user_buffer = &mask,2912.buffer_size = sizeof(mask),2913};2914pipe->set_constant_buffer(pipe, PIPE_SHADER_FRAGMENT, blitter->cb_slot,2915false, &cb);29162917pipe->bind_depth_stencil_alpha_state(pipe,2918get_stencil_blit_fallback_dsa(ctx, i));29192920blitter->draw_rectangle(blitter, ctx->velem_state,2921get_vs_passthrough_pos_generic,2922dstbox->x, dstbox->y,2923dstbox->x + dstbox->width,2924dstbox->y + dstbox->height,29250, 1,2926UTIL_BLITTER_ATTRIB_TEXCOORD_XYZW,2927&coord);2928}29292930if (scissor)2931pipe->set_scissor_states(pipe, 0, 1, &ctx->base.saved_scissor);29322933util_blitter_restore_vertex_states(blitter);2934util_blitter_restore_fragment_states(blitter);2935util_blitter_restore_textures(blitter);2936util_blitter_restore_fb_state(blitter);2937util_blitter_restore_render_cond(blitter);2938util_blitter_restore_constant_buffer_state(blitter);2939util_blitter_unset_running_flag(blitter);29402941pipe_surface_reference(&dst_view, NULL);2942pipe_sampler_view_reference(&src_view, NULL);2943}294429452946