Path: blob/21.2-virgl/src/gallium/auxiliary/cso_cache/cso_context.c
4565 views
/**************************************************************************1*2* Copyright 2007 VMware, Inc.3* All Rights Reserved.4*5* Permission is hereby granted, free of charge, to any person obtaining a6* copy of this software and associated documentation files (the7* "Software"), to deal in the Software without restriction, including8* without limitation the rights to use, copy, modify, merge, publish,9* distribute, sub license, and/or sell copies of the Software, and to10* permit persons to whom the Software is furnished to do so, subject to11* the following conditions:12*13* The above copyright notice and this permission notice (including the14* next paragraph) shall be included in all copies or substantial portions15* of the Software.16*17* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS18* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF19* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.20* IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR21* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,22* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE23* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.24*25**************************************************************************/2627/**28* @file29*30* Wrap the cso cache & hash mechanisms in a simplified31* pipe-driver-specific interface.32*33* @author Zack Rusin <[email protected]>34* @author Keith Whitwell <[email protected]>35*/3637#include "pipe/p_state.h"38#include "util/u_draw.h"39#include "util/u_framebuffer.h"40#include "util/u_inlines.h"41#include "util/u_math.h"42#include "util/u_memory.h"43#include "util/u_vbuf.h"44#include "tgsi/tgsi_parse.h"4546#include "cso_cache/cso_context.h"47#include "cso_cache/cso_cache.h"48#include "cso_cache/cso_hash.h"49#include "cso_context.h"505152/**53* Per-shader sampler information.54*/55struct sampler_info56{57struct cso_sampler *cso_samplers[PIPE_MAX_SAMPLERS];58void *samplers[PIPE_MAX_SAMPLERS];59};60616263struct cso_context {64struct pipe_context *pipe;6566struct u_vbuf *vbuf;67struct u_vbuf *vbuf_current;68bool always_use_vbuf;6970boolean has_geometry_shader;71boolean has_tessellation;72boolean has_compute_shader;73boolean has_streamout;7475unsigned saved_state; /**< bitmask of CSO_BIT_x flags */76unsigned saved_compute_state; /**< bitmask of CSO_BIT_COMPUTE_x flags */7778struct sampler_info fragment_samplers_saved;79struct sampler_info compute_samplers_saved;80struct sampler_info samplers[PIPE_SHADER_TYPES];8182/* Temporary number until cso_single_sampler_done is called.83* It tracks the highest sampler seen in cso_single_sampler.84*/85int max_sampler_seen;8687unsigned nr_so_targets;88struct pipe_stream_output_target *so_targets[PIPE_MAX_SO_BUFFERS];8990unsigned nr_so_targets_saved;91struct pipe_stream_output_target *so_targets_saved[PIPE_MAX_SO_BUFFERS];9293/** Current and saved state.94* The saved state is used as a 1-deep stack.95*/96void *blend, *blend_saved;97void *depth_stencil, *depth_stencil_saved;98void *rasterizer, *rasterizer_saved;99void *fragment_shader, *fragment_shader_saved;100void *vertex_shader, *vertex_shader_saved;101void *geometry_shader, *geometry_shader_saved;102void *tessctrl_shader, *tessctrl_shader_saved;103void *tesseval_shader, *tesseval_shader_saved;104void *compute_shader, *compute_shader_saved;105void *velements, *velements_saved;106struct pipe_query *render_condition, *render_condition_saved;107uint render_condition_mode, render_condition_mode_saved;108boolean render_condition_cond, render_condition_cond_saved;109bool flatshade_first, flatshade_first_saved;110111struct pipe_framebuffer_state fb, fb_saved;112struct pipe_viewport_state vp, vp_saved;113unsigned sample_mask, sample_mask_saved;114unsigned min_samples, min_samples_saved;115struct pipe_stencil_ref stencil_ref, stencil_ref_saved;116117/* This should be last to keep all of the above together in memory. */118struct cso_cache cache;119};120121struct pipe_context *cso_get_pipe_context(struct cso_context *cso)122{123return cso->pipe;124}125126static inline boolean delete_cso(struct cso_context *ctx,127void *state, enum cso_cache_type type)128{129switch (type) {130case CSO_BLEND:131if (ctx->blend == ((struct cso_blend*)state)->data)132return false;133break;134case CSO_DEPTH_STENCIL_ALPHA:135if (ctx->depth_stencil == ((struct cso_depth_stencil_alpha*)state)->data)136return false;137break;138case CSO_RASTERIZER:139if (ctx->rasterizer == ((struct cso_rasterizer*)state)->data)140return false;141break;142case CSO_VELEMENTS:143if (ctx->velements == ((struct cso_velements*)state)->data)144return false;145break;146case CSO_SAMPLER:147/* nothing to do for samplers */148break;149default:150assert(0);151}152153cso_delete_state(ctx->pipe, state, type);154return true;155}156157static inline void158sanitize_hash(struct cso_hash *hash, enum cso_cache_type type,159int max_size, void *user_data)160{161struct cso_context *ctx = (struct cso_context *)user_data;162/* if we're approach the maximum size, remove fourth of the entries163* otherwise every subsequent call will go through the same */164int hash_size = cso_hash_size(hash);165int max_entries = (max_size > hash_size) ? max_size : hash_size;166int to_remove = (max_size < max_entries) * max_entries/4;167struct cso_hash_iter iter;168struct cso_sampler **samplers_to_restore = NULL;169unsigned to_restore = 0;170171if (hash_size > max_size)172to_remove += hash_size - max_size;173174if (to_remove == 0)175return;176177if (type == CSO_SAMPLER) {178int i, j;179180samplers_to_restore = MALLOC(PIPE_SHADER_TYPES * PIPE_MAX_SAMPLERS *181sizeof(*samplers_to_restore));182183/* Temporarily remove currently bound sampler states from the hash184* table, to prevent them from being deleted185*/186for (i = 0; i < PIPE_SHADER_TYPES; i++) {187for (j = 0; j < PIPE_MAX_SAMPLERS; j++) {188struct cso_sampler *sampler = ctx->samplers[i].cso_samplers[j];189190if (sampler && cso_hash_take(hash, sampler->hash_key))191samplers_to_restore[to_restore++] = sampler;192}193}194}195196iter = cso_hash_first_node(hash);197while (to_remove) {198/*remove elements until we're good */199/*fixme: currently we pick the nodes to remove at random*/200void *cso = cso_hash_iter_data(iter);201202if (!cso)203break;204205if (delete_cso(ctx, cso, type)) {206iter = cso_hash_erase(hash, iter);207--to_remove;208} else209iter = cso_hash_iter_next(iter);210}211212if (type == CSO_SAMPLER) {213/* Put currently bound sampler states back into the hash table */214while (to_restore--) {215struct cso_sampler *sampler = samplers_to_restore[to_restore];216217cso_hash_insert(hash, sampler->hash_key, sampler);218}219220FREE(samplers_to_restore);221}222}223224static void cso_init_vbuf(struct cso_context *cso, unsigned flags)225{226struct u_vbuf_caps caps;227bool uses_user_vertex_buffers = !(flags & CSO_NO_USER_VERTEX_BUFFERS);228bool needs64b = !(flags & CSO_NO_64B_VERTEX_BUFFERS);229230u_vbuf_get_caps(cso->pipe->screen, &caps, needs64b);231232/* Enable u_vbuf if needed. */233if (caps.fallback_always ||234(uses_user_vertex_buffers &&235caps.fallback_only_for_user_vbuffers)) {236cso->vbuf = u_vbuf_create(cso->pipe, &caps);237cso->vbuf_current = cso->vbuf;238cso->always_use_vbuf = caps.fallback_always;239}240}241242struct cso_context *243cso_create_context(struct pipe_context *pipe, unsigned flags)244{245struct cso_context *ctx = CALLOC_STRUCT(cso_context);246if (!ctx)247return NULL;248249cso_cache_init(&ctx->cache, pipe);250cso_cache_set_sanitize_callback(&ctx->cache, sanitize_hash, ctx);251252ctx->pipe = pipe;253ctx->sample_mask = ~0;254255if (!(flags & CSO_NO_VBUF))256cso_init_vbuf(ctx, flags);257258/* Enable for testing: */259if (0) cso_set_maximum_cache_size(&ctx->cache, 4);260261if (pipe->screen->get_shader_param(pipe->screen, PIPE_SHADER_GEOMETRY,262PIPE_SHADER_CAP_MAX_INSTRUCTIONS) > 0) {263ctx->has_geometry_shader = TRUE;264}265if (pipe->screen->get_shader_param(pipe->screen, PIPE_SHADER_TESS_CTRL,266PIPE_SHADER_CAP_MAX_INSTRUCTIONS) > 0) {267ctx->has_tessellation = TRUE;268}269if (pipe->screen->get_shader_param(pipe->screen, PIPE_SHADER_COMPUTE,270PIPE_SHADER_CAP_MAX_INSTRUCTIONS) > 0) {271int supported_irs =272pipe->screen->get_shader_param(pipe->screen, PIPE_SHADER_COMPUTE,273PIPE_SHADER_CAP_SUPPORTED_IRS);274if (supported_irs & ((1 << PIPE_SHADER_IR_TGSI) |275(1 << PIPE_SHADER_IR_NIR))) {276ctx->has_compute_shader = TRUE;277}278}279if (pipe->screen->get_param(pipe->screen,280PIPE_CAP_MAX_STREAM_OUTPUT_BUFFERS) != 0) {281ctx->has_streamout = TRUE;282}283284ctx->max_sampler_seen = -1;285return ctx;286}287288void cso_unbind_context(struct cso_context *ctx)289{290unsigned i;291292if (ctx->pipe) {293ctx->pipe->bind_blend_state( ctx->pipe, NULL );294ctx->pipe->bind_rasterizer_state( ctx->pipe, NULL );295296{297static struct pipe_sampler_view *views[PIPE_MAX_SHADER_SAMPLER_VIEWS] = { NULL };298static struct pipe_shader_buffer ssbos[PIPE_MAX_SHADER_BUFFERS] = { 0 };299static void *zeros[PIPE_MAX_SAMPLERS] = { NULL };300struct pipe_screen *scr = ctx->pipe->screen;301enum pipe_shader_type sh;302for (sh = 0; sh < PIPE_SHADER_TYPES; sh++) {303switch (sh) {304case PIPE_SHADER_GEOMETRY:305if (!ctx->has_geometry_shader)306continue;307break;308case PIPE_SHADER_TESS_CTRL:309case PIPE_SHADER_TESS_EVAL:310if (!ctx->has_tessellation)311continue;312break;313case PIPE_SHADER_COMPUTE:314if (!ctx->has_compute_shader)315continue;316break;317default:318break;319}320321int maxsam = scr->get_shader_param(scr, sh,322PIPE_SHADER_CAP_MAX_TEXTURE_SAMPLERS);323int maxview = scr->get_shader_param(scr, sh,324PIPE_SHADER_CAP_MAX_SAMPLER_VIEWS);325int maxssbo = scr->get_shader_param(scr, sh,326PIPE_SHADER_CAP_MAX_SHADER_BUFFERS);327int maxcb = scr->get_shader_param(scr, sh,328PIPE_SHADER_CAP_MAX_CONST_BUFFERS);329int maximg = scr->get_shader_param(scr, sh,330PIPE_SHADER_CAP_MAX_SHADER_IMAGES);331assert(maxsam <= PIPE_MAX_SAMPLERS);332assert(maxview <= PIPE_MAX_SHADER_SAMPLER_VIEWS);333assert(maxssbo <= PIPE_MAX_SHADER_BUFFERS);334assert(maxcb <= PIPE_MAX_CONSTANT_BUFFERS);335assert(maximg <= PIPE_MAX_SHADER_IMAGES);336if (maxsam > 0) {337ctx->pipe->bind_sampler_states(ctx->pipe, sh, 0, maxsam, zeros);338}339if (maxview > 0) {340ctx->pipe->set_sampler_views(ctx->pipe, sh, 0, maxview, 0, views);341}342if (maxssbo > 0) {343ctx->pipe->set_shader_buffers(ctx->pipe, sh, 0, maxssbo, ssbos, 0);344}345if (maximg > 0) {346ctx->pipe->set_shader_images(ctx->pipe, sh, 0, 0, maximg, NULL);347}348for (int i = 0; i < maxcb; i++) {349ctx->pipe->set_constant_buffer(ctx->pipe, sh, i, false, NULL);350}351}352}353354ctx->pipe->bind_depth_stencil_alpha_state( ctx->pipe, NULL );355struct pipe_stencil_ref sr = {0};356ctx->pipe->set_stencil_ref(ctx->pipe, sr);357ctx->pipe->bind_fs_state( ctx->pipe, NULL );358ctx->pipe->set_constant_buffer(ctx->pipe, PIPE_SHADER_FRAGMENT, 0, false, NULL);359ctx->pipe->bind_vs_state( ctx->pipe, NULL );360ctx->pipe->set_constant_buffer(ctx->pipe, PIPE_SHADER_VERTEX, 0, false, NULL);361if (ctx->has_geometry_shader) {362ctx->pipe->bind_gs_state(ctx->pipe, NULL);363}364if (ctx->has_tessellation) {365ctx->pipe->bind_tcs_state(ctx->pipe, NULL);366ctx->pipe->bind_tes_state(ctx->pipe, NULL);367}368if (ctx->has_compute_shader) {369ctx->pipe->bind_compute_state(ctx->pipe, NULL);370}371ctx->pipe->bind_vertex_elements_state( ctx->pipe, NULL );372373if (ctx->has_streamout)374ctx->pipe->set_stream_output_targets(ctx->pipe, 0, NULL, NULL);375}376377util_unreference_framebuffer_state(&ctx->fb);378util_unreference_framebuffer_state(&ctx->fb_saved);379380for (i = 0; i < PIPE_MAX_SO_BUFFERS; i++) {381pipe_so_target_reference(&ctx->so_targets[i], NULL);382pipe_so_target_reference(&ctx->so_targets_saved[i], NULL);383}384385memset(&ctx->samplers, 0, sizeof(ctx->samplers));386memset(&ctx->nr_so_targets, 0, offsetof(struct cso_context, cache) - offsetof(struct cso_context, nr_so_targets));387ctx->sample_mask = ~0;388/*389* If the cso context is reused (with the same pipe context),390* need to really make sure the context state doesn't get out of sync.391*/392ctx->pipe->set_sample_mask(ctx->pipe, ctx->sample_mask);393if (ctx->pipe->set_min_samples)394ctx->pipe->set_min_samples(ctx->pipe, ctx->min_samples);395}396397/**398* Free the CSO context.399*/400void cso_destroy_context( struct cso_context *ctx )401{402cso_unbind_context(ctx);403cso_cache_delete(&ctx->cache);404405if (ctx->vbuf)406u_vbuf_destroy(ctx->vbuf);407FREE( ctx );408}409410411/* Those function will either find the state of the given template412* in the cache or they will create a new state from the given413* template, insert it in the cache and return it.414*/415416/*417* If the driver returns 0 from the create method then they will assign418* the data member of the cso to be the template itself.419*/420421enum pipe_error cso_set_blend(struct cso_context *ctx,422const struct pipe_blend_state *templ)423{424unsigned key_size, hash_key;425struct cso_hash_iter iter;426void *handle;427428key_size = templ->independent_blend_enable ?429sizeof(struct pipe_blend_state) :430(char *)&(templ->rt[1]) - (char *)templ;431hash_key = cso_construct_key((void*)templ, key_size);432iter = cso_find_state_template(&ctx->cache, hash_key, CSO_BLEND,433(void*)templ, key_size);434435if (cso_hash_iter_is_null(iter)) {436struct cso_blend *cso = MALLOC(sizeof(struct cso_blend));437if (!cso)438return PIPE_ERROR_OUT_OF_MEMORY;439440memset(&cso->state, 0, sizeof cso->state);441memcpy(&cso->state, templ, key_size);442cso->data = ctx->pipe->create_blend_state(ctx->pipe, &cso->state);443444iter = cso_insert_state(&ctx->cache, hash_key, CSO_BLEND, cso);445if (cso_hash_iter_is_null(iter)) {446FREE(cso);447return PIPE_ERROR_OUT_OF_MEMORY;448}449450handle = cso->data;451}452else {453handle = ((struct cso_blend *)cso_hash_iter_data(iter))->data;454}455456if (ctx->blend != handle) {457ctx->blend = handle;458ctx->pipe->bind_blend_state(ctx->pipe, handle);459}460return PIPE_OK;461}462463static void464cso_save_blend(struct cso_context *ctx)465{466assert(!ctx->blend_saved);467ctx->blend_saved = ctx->blend;468}469470static void471cso_restore_blend(struct cso_context *ctx)472{473if (ctx->blend != ctx->blend_saved) {474ctx->blend = ctx->blend_saved;475ctx->pipe->bind_blend_state(ctx->pipe, ctx->blend_saved);476}477ctx->blend_saved = NULL;478}479480481482enum pipe_error483cso_set_depth_stencil_alpha(struct cso_context *ctx,484const struct pipe_depth_stencil_alpha_state *templ)485{486unsigned key_size = sizeof(struct pipe_depth_stencil_alpha_state);487unsigned hash_key = cso_construct_key((void*)templ, key_size);488struct cso_hash_iter iter = cso_find_state_template(&ctx->cache,489hash_key,490CSO_DEPTH_STENCIL_ALPHA,491(void*)templ, key_size);492void *handle;493494if (cso_hash_iter_is_null(iter)) {495struct cso_depth_stencil_alpha *cso =496MALLOC(sizeof(struct cso_depth_stencil_alpha));497if (!cso)498return PIPE_ERROR_OUT_OF_MEMORY;499500memcpy(&cso->state, templ, sizeof(*templ));501cso->data = ctx->pipe->create_depth_stencil_alpha_state(ctx->pipe,502&cso->state);503504iter = cso_insert_state(&ctx->cache, hash_key,505CSO_DEPTH_STENCIL_ALPHA, cso);506if (cso_hash_iter_is_null(iter)) {507FREE(cso);508return PIPE_ERROR_OUT_OF_MEMORY;509}510511handle = cso->data;512}513else {514handle = ((struct cso_depth_stencil_alpha *)515cso_hash_iter_data(iter))->data;516}517518if (ctx->depth_stencil != handle) {519ctx->depth_stencil = handle;520ctx->pipe->bind_depth_stencil_alpha_state(ctx->pipe, handle);521}522return PIPE_OK;523}524525static void526cso_save_depth_stencil_alpha(struct cso_context *ctx)527{528assert(!ctx->depth_stencil_saved);529ctx->depth_stencil_saved = ctx->depth_stencil;530}531532static void533cso_restore_depth_stencil_alpha(struct cso_context *ctx)534{535if (ctx->depth_stencil != ctx->depth_stencil_saved) {536ctx->depth_stencil = ctx->depth_stencil_saved;537ctx->pipe->bind_depth_stencil_alpha_state(ctx->pipe,538ctx->depth_stencil_saved);539}540ctx->depth_stencil_saved = NULL;541}542543544545enum pipe_error cso_set_rasterizer(struct cso_context *ctx,546const struct pipe_rasterizer_state *templ)547{548unsigned key_size = sizeof(struct pipe_rasterizer_state);549unsigned hash_key = cso_construct_key((void*)templ, key_size);550struct cso_hash_iter iter = cso_find_state_template(&ctx->cache,551hash_key,552CSO_RASTERIZER,553(void*)templ, key_size);554void *handle = NULL;555556/* We can't have both point_quad_rasterization (sprites) and point_smooth557* (round AA points) enabled at the same time.558*/559assert(!(templ->point_quad_rasterization && templ->point_smooth));560561if (cso_hash_iter_is_null(iter)) {562struct cso_rasterizer *cso = MALLOC(sizeof(struct cso_rasterizer));563if (!cso)564return PIPE_ERROR_OUT_OF_MEMORY;565566memcpy(&cso->state, templ, sizeof(*templ));567cso->data = ctx->pipe->create_rasterizer_state(ctx->pipe, &cso->state);568569iter = cso_insert_state(&ctx->cache, hash_key, CSO_RASTERIZER, cso);570if (cso_hash_iter_is_null(iter)) {571FREE(cso);572return PIPE_ERROR_OUT_OF_MEMORY;573}574575handle = cso->data;576}577else {578handle = ((struct cso_rasterizer *)cso_hash_iter_data(iter))->data;579}580581if (ctx->rasterizer != handle) {582ctx->rasterizer = handle;583ctx->flatshade_first = templ->flatshade_first;584if (ctx->vbuf)585u_vbuf_set_flatshade_first(ctx->vbuf, ctx->flatshade_first);586ctx->pipe->bind_rasterizer_state(ctx->pipe, handle);587}588return PIPE_OK;589}590591static void592cso_save_rasterizer(struct cso_context *ctx)593{594assert(!ctx->rasterizer_saved);595ctx->rasterizer_saved = ctx->rasterizer;596ctx->flatshade_first_saved = ctx->flatshade_first;597}598599static void600cso_restore_rasterizer(struct cso_context *ctx)601{602if (ctx->rasterizer != ctx->rasterizer_saved) {603ctx->rasterizer = ctx->rasterizer_saved;604ctx->flatshade_first = ctx->flatshade_first_saved;605if (ctx->vbuf)606u_vbuf_set_flatshade_first(ctx->vbuf, ctx->flatshade_first);607ctx->pipe->bind_rasterizer_state(ctx->pipe, ctx->rasterizer_saved);608}609ctx->rasterizer_saved = NULL;610}611612613void cso_set_fragment_shader_handle(struct cso_context *ctx, void *handle )614{615if (ctx->fragment_shader != handle) {616ctx->fragment_shader = handle;617ctx->pipe->bind_fs_state(ctx->pipe, handle);618}619}620621static void622cso_save_fragment_shader(struct cso_context *ctx)623{624assert(!ctx->fragment_shader_saved);625ctx->fragment_shader_saved = ctx->fragment_shader;626}627628static void629cso_restore_fragment_shader(struct cso_context *ctx)630{631if (ctx->fragment_shader_saved != ctx->fragment_shader) {632ctx->pipe->bind_fs_state(ctx->pipe, ctx->fragment_shader_saved);633ctx->fragment_shader = ctx->fragment_shader_saved;634}635ctx->fragment_shader_saved = NULL;636}637638639void cso_set_vertex_shader_handle(struct cso_context *ctx, void *handle)640{641if (ctx->vertex_shader != handle) {642ctx->vertex_shader = handle;643ctx->pipe->bind_vs_state(ctx->pipe, handle);644}645}646647static void648cso_save_vertex_shader(struct cso_context *ctx)649{650assert(!ctx->vertex_shader_saved);651ctx->vertex_shader_saved = ctx->vertex_shader;652}653654static void655cso_restore_vertex_shader(struct cso_context *ctx)656{657if (ctx->vertex_shader_saved != ctx->vertex_shader) {658ctx->pipe->bind_vs_state(ctx->pipe, ctx->vertex_shader_saved);659ctx->vertex_shader = ctx->vertex_shader_saved;660}661ctx->vertex_shader_saved = NULL;662}663664665void cso_set_framebuffer(struct cso_context *ctx,666const struct pipe_framebuffer_state *fb)667{668if (memcmp(&ctx->fb, fb, sizeof(*fb)) != 0) {669util_copy_framebuffer_state(&ctx->fb, fb);670ctx->pipe->set_framebuffer_state(ctx->pipe, fb);671}672}673674static void675cso_save_framebuffer(struct cso_context *ctx)676{677util_copy_framebuffer_state(&ctx->fb_saved, &ctx->fb);678}679680static void681cso_restore_framebuffer(struct cso_context *ctx)682{683if (memcmp(&ctx->fb, &ctx->fb_saved, sizeof(ctx->fb))) {684util_copy_framebuffer_state(&ctx->fb, &ctx->fb_saved);685ctx->pipe->set_framebuffer_state(ctx->pipe, &ctx->fb);686util_unreference_framebuffer_state(&ctx->fb_saved);687}688}689690691void cso_set_viewport(struct cso_context *ctx,692const struct pipe_viewport_state *vp)693{694if (memcmp(&ctx->vp, vp, sizeof(*vp))) {695ctx->vp = *vp;696ctx->pipe->set_viewport_states(ctx->pipe, 0, 1, vp);697}698}699700/**701* Setup viewport state for given width and height (position is always (0,0)).702* Invert the Y axis if 'invert' is true.703*/704void705cso_set_viewport_dims(struct cso_context *ctx,706float width, float height, boolean invert)707{708struct pipe_viewport_state vp;709vp.scale[0] = width * 0.5f;710vp.scale[1] = height * (invert ? -0.5f : 0.5f);711vp.scale[2] = 0.5f;712vp.translate[0] = 0.5f * width;713vp.translate[1] = 0.5f * height;714vp.translate[2] = 0.5f;715vp.swizzle_x = PIPE_VIEWPORT_SWIZZLE_POSITIVE_X;716vp.swizzle_y = PIPE_VIEWPORT_SWIZZLE_POSITIVE_Y;717vp.swizzle_z = PIPE_VIEWPORT_SWIZZLE_POSITIVE_Z;718vp.swizzle_w = PIPE_VIEWPORT_SWIZZLE_POSITIVE_W;719cso_set_viewport(ctx, &vp);720}721722static void723cso_save_viewport(struct cso_context *ctx)724{725ctx->vp_saved = ctx->vp;726}727728729static void730cso_restore_viewport(struct cso_context *ctx)731{732if (memcmp(&ctx->vp, &ctx->vp_saved, sizeof(ctx->vp))) {733ctx->vp = ctx->vp_saved;734ctx->pipe->set_viewport_states(ctx->pipe, 0, 1, &ctx->vp);735}736}737738void cso_set_sample_mask(struct cso_context *ctx, unsigned sample_mask)739{740if (ctx->sample_mask != sample_mask) {741ctx->sample_mask = sample_mask;742ctx->pipe->set_sample_mask(ctx->pipe, sample_mask);743}744}745746static void747cso_save_sample_mask(struct cso_context *ctx)748{749ctx->sample_mask_saved = ctx->sample_mask;750}751752static void753cso_restore_sample_mask(struct cso_context *ctx)754{755cso_set_sample_mask(ctx, ctx->sample_mask_saved);756}757758void cso_set_min_samples(struct cso_context *ctx, unsigned min_samples)759{760if (ctx->min_samples != min_samples && ctx->pipe->set_min_samples) {761ctx->min_samples = min_samples;762ctx->pipe->set_min_samples(ctx->pipe, min_samples);763}764}765766static void767cso_save_min_samples(struct cso_context *ctx)768{769ctx->min_samples_saved = ctx->min_samples;770}771772static void773cso_restore_min_samples(struct cso_context *ctx)774{775cso_set_min_samples(ctx, ctx->min_samples_saved);776}777778void cso_set_stencil_ref(struct cso_context *ctx,779const struct pipe_stencil_ref sr)780{781if (memcmp(&ctx->stencil_ref, &sr, sizeof(ctx->stencil_ref))) {782ctx->stencil_ref = sr;783ctx->pipe->set_stencil_ref(ctx->pipe, sr);784}785}786787static void788cso_save_stencil_ref(struct cso_context *ctx)789{790ctx->stencil_ref_saved = ctx->stencil_ref;791}792793794static void795cso_restore_stencil_ref(struct cso_context *ctx)796{797if (memcmp(&ctx->stencil_ref, &ctx->stencil_ref_saved,798sizeof(ctx->stencil_ref))) {799ctx->stencil_ref = ctx->stencil_ref_saved;800ctx->pipe->set_stencil_ref(ctx->pipe, ctx->stencil_ref);801}802}803804void cso_set_render_condition(struct cso_context *ctx,805struct pipe_query *query,806boolean condition,807enum pipe_render_cond_flag mode)808{809struct pipe_context *pipe = ctx->pipe;810811if (ctx->render_condition != query ||812ctx->render_condition_mode != mode ||813ctx->render_condition_cond != condition) {814pipe->render_condition(pipe, query, condition, mode);815ctx->render_condition = query;816ctx->render_condition_cond = condition;817ctx->render_condition_mode = mode;818}819}820821static void822cso_save_render_condition(struct cso_context *ctx)823{824ctx->render_condition_saved = ctx->render_condition;825ctx->render_condition_cond_saved = ctx->render_condition_cond;826ctx->render_condition_mode_saved = ctx->render_condition_mode;827}828829static void830cso_restore_render_condition(struct cso_context *ctx)831{832cso_set_render_condition(ctx, ctx->render_condition_saved,833ctx->render_condition_cond_saved,834ctx->render_condition_mode_saved);835}836837void cso_set_geometry_shader_handle(struct cso_context *ctx, void *handle)838{839assert(ctx->has_geometry_shader || !handle);840841if (ctx->has_geometry_shader && ctx->geometry_shader != handle) {842ctx->geometry_shader = handle;843ctx->pipe->bind_gs_state(ctx->pipe, handle);844}845}846847static void848cso_save_geometry_shader(struct cso_context *ctx)849{850if (!ctx->has_geometry_shader) {851return;852}853854assert(!ctx->geometry_shader_saved);855ctx->geometry_shader_saved = ctx->geometry_shader;856}857858static void859cso_restore_geometry_shader(struct cso_context *ctx)860{861if (!ctx->has_geometry_shader) {862return;863}864865if (ctx->geometry_shader_saved != ctx->geometry_shader) {866ctx->pipe->bind_gs_state(ctx->pipe, ctx->geometry_shader_saved);867ctx->geometry_shader = ctx->geometry_shader_saved;868}869ctx->geometry_shader_saved = NULL;870}871872void cso_set_tessctrl_shader_handle(struct cso_context *ctx, void *handle)873{874assert(ctx->has_tessellation || !handle);875876if (ctx->has_tessellation && ctx->tessctrl_shader != handle) {877ctx->tessctrl_shader = handle;878ctx->pipe->bind_tcs_state(ctx->pipe, handle);879}880}881882static void883cso_save_tessctrl_shader(struct cso_context *ctx)884{885if (!ctx->has_tessellation) {886return;887}888889assert(!ctx->tessctrl_shader_saved);890ctx->tessctrl_shader_saved = ctx->tessctrl_shader;891}892893static void894cso_restore_tessctrl_shader(struct cso_context *ctx)895{896if (!ctx->has_tessellation) {897return;898}899900if (ctx->tessctrl_shader_saved != ctx->tessctrl_shader) {901ctx->pipe->bind_tcs_state(ctx->pipe, ctx->tessctrl_shader_saved);902ctx->tessctrl_shader = ctx->tessctrl_shader_saved;903}904ctx->tessctrl_shader_saved = NULL;905}906907void cso_set_tesseval_shader_handle(struct cso_context *ctx, void *handle)908{909assert(ctx->has_tessellation || !handle);910911if (ctx->has_tessellation && ctx->tesseval_shader != handle) {912ctx->tesseval_shader = handle;913ctx->pipe->bind_tes_state(ctx->pipe, handle);914}915}916917static void918cso_save_tesseval_shader(struct cso_context *ctx)919{920if (!ctx->has_tessellation) {921return;922}923924assert(!ctx->tesseval_shader_saved);925ctx->tesseval_shader_saved = ctx->tesseval_shader;926}927928static void929cso_restore_tesseval_shader(struct cso_context *ctx)930{931if (!ctx->has_tessellation) {932return;933}934935if (ctx->tesseval_shader_saved != ctx->tesseval_shader) {936ctx->pipe->bind_tes_state(ctx->pipe, ctx->tesseval_shader_saved);937ctx->tesseval_shader = ctx->tesseval_shader_saved;938}939ctx->tesseval_shader_saved = NULL;940}941942void cso_set_compute_shader_handle(struct cso_context *ctx, void *handle)943{944assert(ctx->has_compute_shader || !handle);945946if (ctx->has_compute_shader && ctx->compute_shader != handle) {947ctx->compute_shader = handle;948ctx->pipe->bind_compute_state(ctx->pipe, handle);949}950}951952static void953cso_save_compute_shader(struct cso_context *ctx)954{955if (!ctx->has_compute_shader) {956return;957}958959assert(!ctx->compute_shader_saved);960ctx->compute_shader_saved = ctx->compute_shader;961}962963static void964cso_restore_compute_shader(struct cso_context *ctx)965{966if (!ctx->has_compute_shader) {967return;968}969970if (ctx->compute_shader_saved != ctx->compute_shader) {971ctx->pipe->bind_compute_state(ctx->pipe, ctx->compute_shader_saved);972ctx->compute_shader = ctx->compute_shader_saved;973}974ctx->compute_shader_saved = NULL;975}976977978static void979cso_save_compute_samplers(struct cso_context *ctx)980{981struct sampler_info *info = &ctx->samplers[PIPE_SHADER_COMPUTE];982struct sampler_info *saved = &ctx->compute_samplers_saved;983984memcpy(saved->cso_samplers, info->cso_samplers,985sizeof(info->cso_samplers));986memcpy(saved->samplers, info->samplers, sizeof(info->samplers));987}988989990static void991cso_restore_compute_samplers(struct cso_context *ctx)992{993struct sampler_info *info = &ctx->samplers[PIPE_SHADER_COMPUTE];994struct sampler_info *saved = &ctx->compute_samplers_saved;995996memcpy(info->cso_samplers, saved->cso_samplers,997sizeof(info->cso_samplers));998memcpy(info->samplers, saved->samplers, sizeof(info->samplers));9991000for (int i = PIPE_MAX_SAMPLERS - 1; i >= 0; i--) {1001if (info->samplers[i]) {1002ctx->max_sampler_seen = i;1003break;1004}1005}10061007cso_single_sampler_done(ctx, PIPE_SHADER_COMPUTE);1008}100910101011static void1012cso_set_vertex_elements_direct(struct cso_context *ctx,1013const struct cso_velems_state *velems)1014{1015unsigned key_size, hash_key;1016struct cso_hash_iter iter;1017void *handle;10181019/* Need to include the count into the stored state data too.1020* Otherwise first few count pipe_vertex_elements could be identical1021* even if count is different, and there's no guarantee the hash would1022* be different in that case neither.1023*/1024key_size = sizeof(struct pipe_vertex_element) * velems->count +1025sizeof(unsigned);1026hash_key = cso_construct_key((void*)velems, key_size);1027iter = cso_find_state_template(&ctx->cache, hash_key, CSO_VELEMENTS,1028(void*)velems, key_size);10291030if (cso_hash_iter_is_null(iter)) {1031struct cso_velements *cso = MALLOC(sizeof(struct cso_velements));1032if (!cso)1033return;10341035memcpy(&cso->state, velems, key_size);1036cso->data = ctx->pipe->create_vertex_elements_state(ctx->pipe,1037velems->count,1038&cso->state.velems[0]);10391040iter = cso_insert_state(&ctx->cache, hash_key, CSO_VELEMENTS, cso);1041if (cso_hash_iter_is_null(iter)) {1042FREE(cso);1043return;1044}10451046handle = cso->data;1047}1048else {1049handle = ((struct cso_velements *)cso_hash_iter_data(iter))->data;1050}10511052if (ctx->velements != handle) {1053ctx->velements = handle;1054ctx->pipe->bind_vertex_elements_state(ctx->pipe, handle);1055}1056}10571058enum pipe_error1059cso_set_vertex_elements(struct cso_context *ctx,1060const struct cso_velems_state *velems)1061{1062struct u_vbuf *vbuf = ctx->vbuf_current;10631064if (vbuf) {1065u_vbuf_set_vertex_elements(vbuf, velems);1066return PIPE_OK;1067}10681069cso_set_vertex_elements_direct(ctx, velems);1070return PIPE_OK;1071}10721073static void1074cso_save_vertex_elements(struct cso_context *ctx)1075{1076struct u_vbuf *vbuf = ctx->vbuf_current;10771078if (vbuf) {1079u_vbuf_save_vertex_elements(vbuf);1080return;1081}10821083assert(!ctx->velements_saved);1084ctx->velements_saved = ctx->velements;1085}10861087static void1088cso_restore_vertex_elements(struct cso_context *ctx)1089{1090struct u_vbuf *vbuf = ctx->vbuf_current;10911092if (vbuf) {1093u_vbuf_restore_vertex_elements(vbuf);1094return;1095}10961097if (ctx->velements != ctx->velements_saved) {1098ctx->velements = ctx->velements_saved;1099ctx->pipe->bind_vertex_elements_state(ctx->pipe, ctx->velements_saved);1100}1101ctx->velements_saved = NULL;1102}11031104/* vertex buffers */11051106void cso_set_vertex_buffers(struct cso_context *ctx,1107unsigned start_slot, unsigned count,1108const struct pipe_vertex_buffer *buffers)1109{1110struct u_vbuf *vbuf = ctx->vbuf_current;11111112if (!count)1113return;11141115if (vbuf) {1116u_vbuf_set_vertex_buffers(vbuf, start_slot, count, 0, false, buffers);1117return;1118}11191120struct pipe_context *pipe = ctx->pipe;1121pipe->set_vertex_buffers(pipe, start_slot, count, 0, false, buffers);1122}11231124/**1125* Set vertex buffers and vertex elements. Skip u_vbuf if it's only needed1126* for user vertex buffers and user vertex buffers are not set by this call.1127* u_vbuf will be disabled. To re-enable u_vbuf, call this function again.1128*1129* Skipping u_vbuf decreases CPU overhead for draw calls that don't need it,1130* such as VBOs, glBegin/End, and display lists.1131*1132* Internal operations that do "save states, draw, restore states" shouldn't1133* use this, because the states are only saved in either cso_context or1134* u_vbuf, not both.1135*/1136void1137cso_set_vertex_buffers_and_elements(struct cso_context *ctx,1138const struct cso_velems_state *velems,1139unsigned vb_count,1140unsigned unbind_trailing_vb_count,1141bool take_ownership,1142bool uses_user_vertex_buffers,1143const struct pipe_vertex_buffer *vbuffers)1144{1145struct u_vbuf *vbuf = ctx->vbuf;1146struct pipe_context *pipe = ctx->pipe;11471148if (vbuf && (ctx->always_use_vbuf || uses_user_vertex_buffers)) {1149if (!ctx->vbuf_current) {1150/* Unbind all buffers in cso_context, because we'll use u_vbuf. */1151unsigned unbind_vb_count = vb_count + unbind_trailing_vb_count;1152if (unbind_vb_count)1153pipe->set_vertex_buffers(pipe, 0, 0, unbind_vb_count, false, NULL);11541155/* Unset this to make sure the CSO is re-bound on the next use. */1156ctx->velements = NULL;1157ctx->vbuf_current = vbuf;1158unbind_trailing_vb_count = 0;1159}11601161if (vb_count || unbind_trailing_vb_count) {1162u_vbuf_set_vertex_buffers(vbuf, 0, vb_count,1163unbind_trailing_vb_count,1164take_ownership, vbuffers);1165}1166u_vbuf_set_vertex_elements(vbuf, velems);1167return;1168}11691170if (ctx->vbuf_current) {1171/* Unbind all buffers in u_vbuf, because we'll use cso_context. */1172unsigned unbind_vb_count = vb_count + unbind_trailing_vb_count;1173if (unbind_vb_count)1174u_vbuf_set_vertex_buffers(vbuf, 0, 0, unbind_vb_count, false, NULL);11751176/* Unset this to make sure the CSO is re-bound on the next use. */1177u_vbuf_unset_vertex_elements(vbuf);1178ctx->vbuf_current = NULL;1179unbind_trailing_vb_count = 0;1180}11811182if (vb_count || unbind_trailing_vb_count) {1183pipe->set_vertex_buffers(pipe, 0, vb_count, unbind_trailing_vb_count,1184take_ownership, vbuffers);1185}1186cso_set_vertex_elements_direct(ctx, velems);1187}11881189static bool1190cso_set_sampler(struct cso_context *ctx, enum pipe_shader_type shader_stage,1191unsigned idx, const struct pipe_sampler_state *templ)1192{1193unsigned key_size = sizeof(struct pipe_sampler_state);1194unsigned hash_key = cso_construct_key((void*)templ, key_size);1195struct cso_sampler *cso;1196struct cso_hash_iter iter =1197cso_find_state_template(&ctx->cache,1198hash_key, CSO_SAMPLER,1199(void *) templ, key_size);12001201if (cso_hash_iter_is_null(iter)) {1202cso = MALLOC(sizeof(struct cso_sampler));1203if (!cso)1204return false;12051206memcpy(&cso->state, templ, sizeof(*templ));1207cso->data = ctx->pipe->create_sampler_state(ctx->pipe, &cso->state);1208cso->hash_key = hash_key;12091210iter = cso_insert_state(&ctx->cache, hash_key, CSO_SAMPLER, cso);1211if (cso_hash_iter_is_null(iter)) {1212FREE(cso);1213return false;1214}1215} else {1216cso = cso_hash_iter_data(iter);1217}12181219ctx->samplers[shader_stage].cso_samplers[idx] = cso;1220ctx->samplers[shader_stage].samplers[idx] = cso->data;1221return true;1222}12231224void1225cso_single_sampler(struct cso_context *ctx, enum pipe_shader_type shader_stage,1226unsigned idx, const struct pipe_sampler_state *templ)1227{1228if (cso_set_sampler(ctx, shader_stage, idx, templ))1229ctx->max_sampler_seen = MAX2(ctx->max_sampler_seen, (int)idx);1230}12311232/**1233* Send staged sampler state to the driver.1234*/1235void1236cso_single_sampler_done(struct cso_context *ctx,1237enum pipe_shader_type shader_stage)1238{1239struct sampler_info *info = &ctx->samplers[shader_stage];12401241if (ctx->max_sampler_seen == -1)1242return;12431244ctx->pipe->bind_sampler_states(ctx->pipe, shader_stage, 0,1245ctx->max_sampler_seen + 1,1246info->samplers);1247ctx->max_sampler_seen = -1;1248}124912501251/*1252* If the function encouters any errors it will return the1253* last one. Done to always try to set as many samplers1254* as possible.1255*/1256void1257cso_set_samplers(struct cso_context *ctx,1258enum pipe_shader_type shader_stage,1259unsigned nr,1260const struct pipe_sampler_state **templates)1261{1262int last = -1;12631264for (unsigned i = 0; i < nr; i++) {1265if (!templates[i])1266continue;12671268/* Reuse the same sampler state CSO if 2 consecutive sampler states1269* are identical.1270*1271* The trivial case where both pointers are equal doesn't occur in1272* frequented codepaths.1273*1274* Reuse rate:1275* - Borderlands 2: 55%1276* - Hitman: 65%1277* - Rocket League: 75%1278* - Tomb Raider: 50-65%1279* - XCOM 2: 55%1280*/1281if (last >= 0 &&1282!memcmp(templates[i], templates[last],1283sizeof(struct pipe_sampler_state))) {1284ctx->samplers[shader_stage].cso_samplers[i] =1285ctx->samplers[shader_stage].cso_samplers[last];1286ctx->samplers[shader_stage].samplers[i] =1287ctx->samplers[shader_stage].samplers[last];1288} else {1289/* Look up the sampler state CSO. */1290cso_set_sampler(ctx, shader_stage, i, templates[i]);1291}12921293last = i;1294}12951296ctx->max_sampler_seen = MAX2(ctx->max_sampler_seen, last);1297cso_single_sampler_done(ctx, shader_stage);1298}12991300static void1301cso_save_fragment_samplers(struct cso_context *ctx)1302{1303struct sampler_info *info = &ctx->samplers[PIPE_SHADER_FRAGMENT];1304struct sampler_info *saved = &ctx->fragment_samplers_saved;13051306memcpy(saved->cso_samplers, info->cso_samplers,1307sizeof(info->cso_samplers));1308memcpy(saved->samplers, info->samplers, sizeof(info->samplers));1309}131013111312static void1313cso_restore_fragment_samplers(struct cso_context *ctx)1314{1315struct sampler_info *info = &ctx->samplers[PIPE_SHADER_FRAGMENT];1316struct sampler_info *saved = &ctx->fragment_samplers_saved;13171318memcpy(info->cso_samplers, saved->cso_samplers,1319sizeof(info->cso_samplers));1320memcpy(info->samplers, saved->samplers, sizeof(info->samplers));13211322for (int i = PIPE_MAX_SAMPLERS - 1; i >= 0; i--) {1323if (info->samplers[i]) {1324ctx->max_sampler_seen = i;1325break;1326}1327}13281329cso_single_sampler_done(ctx, PIPE_SHADER_FRAGMENT);1330}133113321333void1334cso_set_stream_outputs(struct cso_context *ctx,1335unsigned num_targets,1336struct pipe_stream_output_target **targets,1337const unsigned *offsets)1338{1339struct pipe_context *pipe = ctx->pipe;1340uint i;13411342if (!ctx->has_streamout) {1343assert(num_targets == 0);1344return;1345}13461347if (ctx->nr_so_targets == 0 && num_targets == 0) {1348/* Nothing to do. */1349return;1350}13511352/* reference new targets */1353for (i = 0; i < num_targets; i++) {1354pipe_so_target_reference(&ctx->so_targets[i], targets[i]);1355}1356/* unref extra old targets, if any */1357for (; i < ctx->nr_so_targets; i++) {1358pipe_so_target_reference(&ctx->so_targets[i], NULL);1359}13601361pipe->set_stream_output_targets(pipe, num_targets, targets,1362offsets);1363ctx->nr_so_targets = num_targets;1364}13651366static void1367cso_save_stream_outputs(struct cso_context *ctx)1368{1369uint i;13701371if (!ctx->has_streamout) {1372return;1373}13741375ctx->nr_so_targets_saved = ctx->nr_so_targets;13761377for (i = 0; i < ctx->nr_so_targets; i++) {1378assert(!ctx->so_targets_saved[i]);1379pipe_so_target_reference(&ctx->so_targets_saved[i], ctx->so_targets[i]);1380}1381}13821383static void1384cso_restore_stream_outputs(struct cso_context *ctx)1385{1386struct pipe_context *pipe = ctx->pipe;1387uint i;1388unsigned offset[PIPE_MAX_SO_BUFFERS];13891390if (!ctx->has_streamout) {1391return;1392}13931394if (ctx->nr_so_targets == 0 && ctx->nr_so_targets_saved == 0) {1395/* Nothing to do. */1396return;1397}13981399assert(ctx->nr_so_targets_saved <= PIPE_MAX_SO_BUFFERS);1400for (i = 0; i < ctx->nr_so_targets_saved; i++) {1401pipe_so_target_reference(&ctx->so_targets[i], NULL);1402/* move the reference from one pointer to another */1403ctx->so_targets[i] = ctx->so_targets_saved[i];1404ctx->so_targets_saved[i] = NULL;1405/* -1 means append */1406offset[i] = (unsigned)-1;1407}1408for (; i < ctx->nr_so_targets; i++) {1409pipe_so_target_reference(&ctx->so_targets[i], NULL);1410}14111412pipe->set_stream_output_targets(pipe, ctx->nr_so_targets_saved,1413ctx->so_targets, offset);14141415ctx->nr_so_targets = ctx->nr_so_targets_saved;1416ctx->nr_so_targets_saved = 0;1417}141814191420/**1421* Save all the CSO state items specified by the state_mask bitmask1422* of CSO_BIT_x flags.1423*/1424void1425cso_save_state(struct cso_context *cso, unsigned state_mask)1426{1427assert(cso->saved_state == 0);14281429cso->saved_state = state_mask;14301431if (state_mask & CSO_BIT_BLEND)1432cso_save_blend(cso);1433if (state_mask & CSO_BIT_DEPTH_STENCIL_ALPHA)1434cso_save_depth_stencil_alpha(cso);1435if (state_mask & CSO_BIT_FRAGMENT_SAMPLERS)1436cso_save_fragment_samplers(cso);1437if (state_mask & CSO_BIT_FRAGMENT_SHADER)1438cso_save_fragment_shader(cso);1439if (state_mask & CSO_BIT_FRAMEBUFFER)1440cso_save_framebuffer(cso);1441if (state_mask & CSO_BIT_GEOMETRY_SHADER)1442cso_save_geometry_shader(cso);1443if (state_mask & CSO_BIT_MIN_SAMPLES)1444cso_save_min_samples(cso);1445if (state_mask & CSO_BIT_RASTERIZER)1446cso_save_rasterizer(cso);1447if (state_mask & CSO_BIT_RENDER_CONDITION)1448cso_save_render_condition(cso);1449if (state_mask & CSO_BIT_SAMPLE_MASK)1450cso_save_sample_mask(cso);1451if (state_mask & CSO_BIT_STENCIL_REF)1452cso_save_stencil_ref(cso);1453if (state_mask & CSO_BIT_STREAM_OUTPUTS)1454cso_save_stream_outputs(cso);1455if (state_mask & CSO_BIT_TESSCTRL_SHADER)1456cso_save_tessctrl_shader(cso);1457if (state_mask & CSO_BIT_TESSEVAL_SHADER)1458cso_save_tesseval_shader(cso);1459if (state_mask & CSO_BIT_VERTEX_ELEMENTS)1460cso_save_vertex_elements(cso);1461if (state_mask & CSO_BIT_VERTEX_SHADER)1462cso_save_vertex_shader(cso);1463if (state_mask & CSO_BIT_VIEWPORT)1464cso_save_viewport(cso);1465if (state_mask & CSO_BIT_PAUSE_QUERIES)1466cso->pipe->set_active_query_state(cso->pipe, false);1467}146814691470/**1471* Restore the state which was saved by cso_save_state().1472*/1473void1474cso_restore_state(struct cso_context *cso)1475{1476unsigned state_mask = cso->saved_state;14771478assert(state_mask);14791480if (state_mask & CSO_BIT_BLEND)1481cso_restore_blend(cso);1482if (state_mask & CSO_BIT_DEPTH_STENCIL_ALPHA)1483cso_restore_depth_stencil_alpha(cso);1484if (state_mask & CSO_BIT_FRAGMENT_SAMPLERS)1485cso_restore_fragment_samplers(cso);1486if (state_mask & CSO_BIT_FRAGMENT_SHADER)1487cso_restore_fragment_shader(cso);1488if (state_mask & CSO_BIT_FRAMEBUFFER)1489cso_restore_framebuffer(cso);1490if (state_mask & CSO_BIT_GEOMETRY_SHADER)1491cso_restore_geometry_shader(cso);1492if (state_mask & CSO_BIT_MIN_SAMPLES)1493cso_restore_min_samples(cso);1494if (state_mask & CSO_BIT_RASTERIZER)1495cso_restore_rasterizer(cso);1496if (state_mask & CSO_BIT_RENDER_CONDITION)1497cso_restore_render_condition(cso);1498if (state_mask & CSO_BIT_SAMPLE_MASK)1499cso_restore_sample_mask(cso);1500if (state_mask & CSO_BIT_STENCIL_REF)1501cso_restore_stencil_ref(cso);1502if (state_mask & CSO_BIT_STREAM_OUTPUTS)1503cso_restore_stream_outputs(cso);1504if (state_mask & CSO_BIT_TESSCTRL_SHADER)1505cso_restore_tessctrl_shader(cso);1506if (state_mask & CSO_BIT_TESSEVAL_SHADER)1507cso_restore_tesseval_shader(cso);1508if (state_mask & CSO_BIT_VERTEX_ELEMENTS)1509cso_restore_vertex_elements(cso);1510if (state_mask & CSO_BIT_VERTEX_SHADER)1511cso_restore_vertex_shader(cso);1512if (state_mask & CSO_BIT_VIEWPORT)1513cso_restore_viewport(cso);1514if (state_mask & CSO_BIT_PAUSE_QUERIES)1515cso->pipe->set_active_query_state(cso->pipe, true);15161517cso->saved_state = 0;1518}15191520/**1521* Save all the CSO state items specified by the state_mask bitmask1522* of CSO_BIT_COMPUTE_x flags.1523*/1524void1525cso_save_compute_state(struct cso_context *cso, unsigned state_mask)1526{1527assert(cso->saved_compute_state == 0);15281529cso->saved_compute_state = state_mask;15301531if (state_mask & CSO_BIT_COMPUTE_SHADER)1532cso_save_compute_shader(cso);15331534if (state_mask & CSO_BIT_COMPUTE_SAMPLERS)1535cso_save_compute_samplers(cso);1536}153715381539/**1540* Restore the state which was saved by cso_save_compute_state().1541*/1542void1543cso_restore_compute_state(struct cso_context *cso)1544{1545unsigned state_mask = cso->saved_compute_state;15461547assert(state_mask);15481549if (state_mask & CSO_BIT_COMPUTE_SHADER)1550cso_restore_compute_shader(cso);15511552if (state_mask & CSO_BIT_COMPUTE_SAMPLERS)1553cso_restore_compute_samplers(cso);15541555cso->saved_compute_state = 0;1556}1557155815591560/* drawing */15611562void1563cso_draw_vbo(struct cso_context *cso,1564const struct pipe_draw_info *info,1565unsigned drawid_offset,1566const struct pipe_draw_indirect_info *indirect,1567const struct pipe_draw_start_count_bias draw)1568{1569struct u_vbuf *vbuf = cso->vbuf_current;15701571/* We can't have both indirect drawing and SO-vertex-count drawing */1572assert(!indirect ||1573indirect->buffer == NULL ||1574indirect->count_from_stream_output == NULL);15751576/* We can't have SO-vertex-count drawing with an index buffer */1577assert(info->index_size == 0 ||1578!indirect ||1579indirect->count_from_stream_output == NULL);15801581if (vbuf) {1582u_vbuf_draw_vbo(vbuf, info, drawid_offset, indirect, draw);1583} else {1584struct pipe_context *pipe = cso->pipe;1585pipe->draw_vbo(pipe, info, drawid_offset, indirect, &draw, 1);1586}1587}15881589/* info->draw_id can be changed by the callee if increment_draw_id is true. */1590void1591cso_multi_draw(struct cso_context *cso,1592struct pipe_draw_info *info,1593unsigned drawid_offset,1594const struct pipe_draw_start_count_bias *draws,1595unsigned num_draws)1596{1597struct u_vbuf *vbuf = cso->vbuf_current;15981599if (vbuf) {1600/* Increase refcount to be able to use take_index_buffer_ownership with1601* all draws.1602*/1603if (num_draws > 1 && info->take_index_buffer_ownership)1604p_atomic_add(&info->index.resource->reference.count, num_draws - 1);16051606unsigned drawid = drawid_offset;1607for (unsigned i = 0; i < num_draws; i++) {1608u_vbuf_draw_vbo(vbuf, info, drawid, NULL, draws[i]);16091610if (info->increment_draw_id)1611drawid++;1612}1613} else {1614struct pipe_context *pipe = cso->pipe;16151616pipe->draw_vbo(pipe, info, drawid_offset, NULL, draws, num_draws);1617}1618}16191620void1621cso_draw_arrays(struct cso_context *cso, uint mode, uint start, uint count)1622{1623struct pipe_draw_info info;1624struct pipe_draw_start_count_bias draw;16251626util_draw_init_info(&info);16271628info.mode = mode;1629info.index_bounds_valid = true;1630info.min_index = start;1631info.max_index = start + count - 1;16321633draw.start = start;1634draw.count = count;1635draw.index_bias = 0;16361637cso_draw_vbo(cso, &info, 0, NULL, draw);1638}16391640void1641cso_draw_arrays_instanced(struct cso_context *cso, uint mode,1642uint start, uint count,1643uint start_instance, uint instance_count)1644{1645struct pipe_draw_info info;1646struct pipe_draw_start_count_bias draw;16471648util_draw_init_info(&info);16491650info.mode = mode;1651info.index_bounds_valid = true;1652info.min_index = start;1653info.max_index = start + count - 1;1654info.start_instance = start_instance;1655info.instance_count = instance_count;16561657draw.start = start;1658draw.count = count;1659draw.index_bias = 0;16601661cso_draw_vbo(cso, &info, 0, NULL, draw);1662}166316641665