1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright (C) 2012 Rob Clark <robclark@freedesktop.org> 3bf215546Sopenharmony_ci * 4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 10bf215546Sopenharmony_ci * 11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next 12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 13bf215546Sopenharmony_ci * Software. 14bf215546Sopenharmony_ci * 15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20bf215546Sopenharmony_ci * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21bf215546Sopenharmony_ci * SOFTWARE. 22bf215546Sopenharmony_ci * 23bf215546Sopenharmony_ci * Authors: 24bf215546Sopenharmony_ci * Rob Clark <robclark@freedesktop.org> 25bf215546Sopenharmony_ci */ 26bf215546Sopenharmony_ci 27bf215546Sopenharmony_ci#include "pipe/p_state.h" 28bf215546Sopenharmony_ci#include "util/u_dual_blend.h" 29bf215546Sopenharmony_ci#include "util/u_helpers.h" 30bf215546Sopenharmony_ci#include "util/u_memory.h" 31bf215546Sopenharmony_ci#include "util/u_string.h" 32bf215546Sopenharmony_ci 33bf215546Sopenharmony_ci#include "freedreno_context.h" 34bf215546Sopenharmony_ci#include "freedreno_gmem.h" 35bf215546Sopenharmony_ci#include "freedreno_query_hw.h" 36bf215546Sopenharmony_ci#include "freedreno_resource.h" 37bf215546Sopenharmony_ci#include "freedreno_state.h" 38bf215546Sopenharmony_ci#include "freedreno_texture.h" 39bf215546Sopenharmony_ci#include "freedreno_util.h" 40bf215546Sopenharmony_ci 41bf215546Sopenharmony_ci#define get_safe(ptr, field) ((ptr) ? (ptr)->field : 0) 42bf215546Sopenharmony_ci 43bf215546Sopenharmony_ci/* All the generic state handling.. In case of CSO's that are specific 44bf215546Sopenharmony_ci * to the GPU version, when the bind and the delete are common they can 45bf215546Sopenharmony_ci * go in here. 46bf215546Sopenharmony_ci */ 47bf215546Sopenharmony_ci 48bf215546Sopenharmony_cistatic void 49bf215546Sopenharmony_ciupdate_draw_cost(struct fd_context *ctx) assert_dt 50bf215546Sopenharmony_ci{ 51bf215546Sopenharmony_ci struct pipe_framebuffer_state *pfb = &ctx->framebuffer; 52bf215546Sopenharmony_ci 53bf215546Sopenharmony_ci ctx->draw_cost = pfb->nr_cbufs; 54bf215546Sopenharmony_ci for (unsigned i = 0; i < pfb->nr_cbufs; i++) 55bf215546Sopenharmony_ci if (fd_blend_enabled(ctx, i)) 56bf215546Sopenharmony_ci ctx->draw_cost++; 57bf215546Sopenharmony_ci if (fd_depth_enabled(ctx)) 58bf215546Sopenharmony_ci ctx->draw_cost++; 59bf215546Sopenharmony_ci if (fd_depth_write_enabled(ctx)) 60bf215546Sopenharmony_ci ctx->draw_cost++; 61bf215546Sopenharmony_ci} 62bf215546Sopenharmony_ci 63bf215546Sopenharmony_cistatic void 64bf215546Sopenharmony_cifd_set_blend_color(struct pipe_context *pctx, 65bf215546Sopenharmony_ci const struct pipe_blend_color *blend_color) in_dt 66bf215546Sopenharmony_ci{ 67bf215546Sopenharmony_ci struct fd_context *ctx = fd_context(pctx); 68bf215546Sopenharmony_ci ctx->blend_color = *blend_color; 69bf215546Sopenharmony_ci fd_context_dirty(ctx, FD_DIRTY_BLEND_COLOR); 70bf215546Sopenharmony_ci} 71bf215546Sopenharmony_ci 72bf215546Sopenharmony_cistatic void 73bf215546Sopenharmony_cifd_set_stencil_ref(struct pipe_context *pctx, 74bf215546Sopenharmony_ci const struct pipe_stencil_ref stencil_ref) in_dt 75bf215546Sopenharmony_ci{ 76bf215546Sopenharmony_ci struct fd_context *ctx = fd_context(pctx); 77bf215546Sopenharmony_ci ctx->stencil_ref = stencil_ref; 78bf215546Sopenharmony_ci fd_context_dirty(ctx, FD_DIRTY_STENCIL_REF); 79bf215546Sopenharmony_ci} 80bf215546Sopenharmony_ci 81bf215546Sopenharmony_cistatic void 82bf215546Sopenharmony_cifd_set_clip_state(struct pipe_context *pctx, 83bf215546Sopenharmony_ci const struct pipe_clip_state *clip) in_dt 84bf215546Sopenharmony_ci{ 85bf215546Sopenharmony_ci struct fd_context *ctx = fd_context(pctx); 86bf215546Sopenharmony_ci ctx->ucp = *clip; 87bf215546Sopenharmony_ci fd_context_dirty(ctx, FD_DIRTY_UCP); 88bf215546Sopenharmony_ci} 89bf215546Sopenharmony_ci 90bf215546Sopenharmony_cistatic void 91bf215546Sopenharmony_cifd_set_sample_mask(struct pipe_context *pctx, unsigned sample_mask) in_dt 92bf215546Sopenharmony_ci{ 93bf215546Sopenharmony_ci struct fd_context *ctx = fd_context(pctx); 94bf215546Sopenharmony_ci ctx->sample_mask = (uint16_t)sample_mask; 95bf215546Sopenharmony_ci fd_context_dirty(ctx, FD_DIRTY_SAMPLE_MASK); 96bf215546Sopenharmony_ci} 97bf215546Sopenharmony_ci 98bf215546Sopenharmony_cistatic void 99bf215546Sopenharmony_cifd_set_min_samples(struct pipe_context *pctx, unsigned min_samples) in_dt 100bf215546Sopenharmony_ci{ 101bf215546Sopenharmony_ci struct fd_context *ctx = fd_context(pctx); 102bf215546Sopenharmony_ci ctx->min_samples = min_samples; 103bf215546Sopenharmony_ci fd_context_dirty(ctx, FD_DIRTY_MIN_SAMPLES); 104bf215546Sopenharmony_ci} 105bf215546Sopenharmony_ci 106bf215546Sopenharmony_ci/* notes from calim on #dri-devel: 107bf215546Sopenharmony_ci * index==0 will be non-UBO (ie. glUniformXYZ()) all packed together padded 108bf215546Sopenharmony_ci * out to vec4's 109bf215546Sopenharmony_ci * I should be able to consider that I own the user_ptr until the next 110bf215546Sopenharmony_ci * set_constant_buffer() call, at which point I don't really care about the 111bf215546Sopenharmony_ci * previous values. 112bf215546Sopenharmony_ci * index>0 will be UBO's.. well, I'll worry about that later 113bf215546Sopenharmony_ci */ 114bf215546Sopenharmony_cistatic void 115bf215546Sopenharmony_cifd_set_constant_buffer(struct pipe_context *pctx, enum pipe_shader_type shader, 116bf215546Sopenharmony_ci uint index, bool take_ownership, 117bf215546Sopenharmony_ci const struct pipe_constant_buffer *cb) in_dt 118bf215546Sopenharmony_ci{ 119bf215546Sopenharmony_ci struct fd_context *ctx = fd_context(pctx); 120bf215546Sopenharmony_ci struct fd_constbuf_stateobj *so = &ctx->constbuf[shader]; 121bf215546Sopenharmony_ci 122bf215546Sopenharmony_ci util_copy_constant_buffer(&so->cb[index], cb, take_ownership); 123bf215546Sopenharmony_ci 124bf215546Sopenharmony_ci /* Note that gallium frontends can unbind constant buffers by 125bf215546Sopenharmony_ci * passing NULL here. 126bf215546Sopenharmony_ci */ 127bf215546Sopenharmony_ci if (unlikely(!cb)) { 128bf215546Sopenharmony_ci so->enabled_mask &= ~(1 << index); 129bf215546Sopenharmony_ci return; 130bf215546Sopenharmony_ci } 131bf215546Sopenharmony_ci 132bf215546Sopenharmony_ci so->enabled_mask |= 1 << index; 133bf215546Sopenharmony_ci 134bf215546Sopenharmony_ci fd_context_dirty_shader(ctx, shader, FD_DIRTY_SHADER_CONST); 135bf215546Sopenharmony_ci fd_resource_set_usage(cb->buffer, FD_DIRTY_CONST); 136bf215546Sopenharmony_ci 137bf215546Sopenharmony_ci if (index > 0) { 138bf215546Sopenharmony_ci assert(!cb->user_buffer); 139bf215546Sopenharmony_ci ctx->dirty |= FD_DIRTY_RESOURCE; 140bf215546Sopenharmony_ci } 141bf215546Sopenharmony_ci} 142bf215546Sopenharmony_ci 143bf215546Sopenharmony_cistatic void 144bf215546Sopenharmony_cifd_set_shader_buffers(struct pipe_context *pctx, enum pipe_shader_type shader, 145bf215546Sopenharmony_ci unsigned start, unsigned count, 146bf215546Sopenharmony_ci const struct pipe_shader_buffer *buffers, 147bf215546Sopenharmony_ci unsigned writable_bitmask) in_dt 148bf215546Sopenharmony_ci{ 149bf215546Sopenharmony_ci struct fd_context *ctx = fd_context(pctx); 150bf215546Sopenharmony_ci struct fd_shaderbuf_stateobj *so = &ctx->shaderbuf[shader]; 151bf215546Sopenharmony_ci const unsigned modified_bits = u_bit_consecutive(start, count); 152bf215546Sopenharmony_ci 153bf215546Sopenharmony_ci so->enabled_mask &= ~modified_bits; 154bf215546Sopenharmony_ci so->writable_mask &= ~modified_bits; 155bf215546Sopenharmony_ci so->writable_mask |= writable_bitmask << start; 156bf215546Sopenharmony_ci 157bf215546Sopenharmony_ci for (unsigned i = 0; i < count; i++) { 158bf215546Sopenharmony_ci unsigned n = i + start; 159bf215546Sopenharmony_ci struct pipe_shader_buffer *buf = &so->sb[n]; 160bf215546Sopenharmony_ci 161bf215546Sopenharmony_ci if (buffers && buffers[i].buffer) { 162bf215546Sopenharmony_ci if ((buf->buffer == buffers[i].buffer) && 163bf215546Sopenharmony_ci (buf->buffer_offset == buffers[i].buffer_offset) && 164bf215546Sopenharmony_ci (buf->buffer_size == buffers[i].buffer_size)) 165bf215546Sopenharmony_ci continue; 166bf215546Sopenharmony_ci 167bf215546Sopenharmony_ci buf->buffer_offset = buffers[i].buffer_offset; 168bf215546Sopenharmony_ci buf->buffer_size = buffers[i].buffer_size; 169bf215546Sopenharmony_ci pipe_resource_reference(&buf->buffer, buffers[i].buffer); 170bf215546Sopenharmony_ci 171bf215546Sopenharmony_ci fd_resource_set_usage(buffers[i].buffer, FD_DIRTY_SSBO); 172bf215546Sopenharmony_ci 173bf215546Sopenharmony_ci so->enabled_mask |= BIT(n); 174bf215546Sopenharmony_ci 175bf215546Sopenharmony_ci if (writable_bitmask & BIT(i)) { 176bf215546Sopenharmony_ci struct fd_resource *rsc = fd_resource(buf->buffer); 177bf215546Sopenharmony_ci util_range_add(&rsc->b.b, &rsc->valid_buffer_range, 178bf215546Sopenharmony_ci buf->buffer_offset, 179bf215546Sopenharmony_ci buf->buffer_offset + buf->buffer_size); 180bf215546Sopenharmony_ci } 181bf215546Sopenharmony_ci } else { 182bf215546Sopenharmony_ci pipe_resource_reference(&buf->buffer, NULL); 183bf215546Sopenharmony_ci } 184bf215546Sopenharmony_ci } 185bf215546Sopenharmony_ci 186bf215546Sopenharmony_ci fd_context_dirty_shader(ctx, shader, FD_DIRTY_SHADER_SSBO); 187bf215546Sopenharmony_ci} 188bf215546Sopenharmony_ci 189bf215546Sopenharmony_civoid 190bf215546Sopenharmony_cifd_set_shader_images(struct pipe_context *pctx, enum pipe_shader_type shader, 191bf215546Sopenharmony_ci unsigned start, unsigned count, 192bf215546Sopenharmony_ci unsigned unbind_num_trailing_slots, 193bf215546Sopenharmony_ci const struct pipe_image_view *images) in_dt 194bf215546Sopenharmony_ci{ 195bf215546Sopenharmony_ci struct fd_context *ctx = fd_context(pctx); 196bf215546Sopenharmony_ci struct fd_shaderimg_stateobj *so = &ctx->shaderimg[shader]; 197bf215546Sopenharmony_ci 198bf215546Sopenharmony_ci unsigned mask = 0; 199bf215546Sopenharmony_ci 200bf215546Sopenharmony_ci if (images) { 201bf215546Sopenharmony_ci for (unsigned i = 0; i < count; i++) { 202bf215546Sopenharmony_ci unsigned n = i + start; 203bf215546Sopenharmony_ci struct pipe_image_view *buf = &so->si[n]; 204bf215546Sopenharmony_ci 205bf215546Sopenharmony_ci if ((buf->resource == images[i].resource) && 206bf215546Sopenharmony_ci (buf->format == images[i].format) && 207bf215546Sopenharmony_ci (buf->access == images[i].access) && 208bf215546Sopenharmony_ci !memcmp(&buf->u, &images[i].u, sizeof(buf->u))) 209bf215546Sopenharmony_ci continue; 210bf215546Sopenharmony_ci 211bf215546Sopenharmony_ci mask |= BIT(n); 212bf215546Sopenharmony_ci util_copy_image_view(buf, &images[i]); 213bf215546Sopenharmony_ci 214bf215546Sopenharmony_ci if (buf->resource) { 215bf215546Sopenharmony_ci fd_resource_set_usage(buf->resource, FD_DIRTY_IMAGE); 216bf215546Sopenharmony_ci so->enabled_mask |= BIT(n); 217bf215546Sopenharmony_ci 218bf215546Sopenharmony_ci if ((buf->access & PIPE_IMAGE_ACCESS_WRITE) && 219bf215546Sopenharmony_ci (buf->resource->target == PIPE_BUFFER)) { 220bf215546Sopenharmony_ci 221bf215546Sopenharmony_ci struct fd_resource *rsc = fd_resource(buf->resource); 222bf215546Sopenharmony_ci util_range_add(&rsc->b.b, &rsc->valid_buffer_range, 223bf215546Sopenharmony_ci buf->u.buf.offset, 224bf215546Sopenharmony_ci buf->u.buf.offset + buf->u.buf.size); 225bf215546Sopenharmony_ci } 226bf215546Sopenharmony_ci } else { 227bf215546Sopenharmony_ci so->enabled_mask &= ~BIT(n); 228bf215546Sopenharmony_ci } 229bf215546Sopenharmony_ci } 230bf215546Sopenharmony_ci } else { 231bf215546Sopenharmony_ci mask = (BIT(count) - 1) << start; 232bf215546Sopenharmony_ci 233bf215546Sopenharmony_ci for (unsigned i = 0; i < count; i++) { 234bf215546Sopenharmony_ci unsigned n = i + start; 235bf215546Sopenharmony_ci struct pipe_image_view *img = &so->si[n]; 236bf215546Sopenharmony_ci 237bf215546Sopenharmony_ci pipe_resource_reference(&img->resource, NULL); 238bf215546Sopenharmony_ci } 239bf215546Sopenharmony_ci 240bf215546Sopenharmony_ci so->enabled_mask &= ~mask; 241bf215546Sopenharmony_ci } 242bf215546Sopenharmony_ci 243bf215546Sopenharmony_ci for (unsigned i = 0; i < unbind_num_trailing_slots; i++) 244bf215546Sopenharmony_ci pipe_resource_reference(&so->si[i + start + count].resource, NULL); 245bf215546Sopenharmony_ci 246bf215546Sopenharmony_ci so->enabled_mask &= 247bf215546Sopenharmony_ci ~(BITFIELD_MASK(unbind_num_trailing_slots) << (start + count)); 248bf215546Sopenharmony_ci 249bf215546Sopenharmony_ci fd_context_dirty_shader(ctx, shader, FD_DIRTY_SHADER_IMAGE); 250bf215546Sopenharmony_ci} 251bf215546Sopenharmony_ci 252bf215546Sopenharmony_civoid 253bf215546Sopenharmony_cifd_set_framebuffer_state(struct pipe_context *pctx, 254bf215546Sopenharmony_ci const struct pipe_framebuffer_state *framebuffer) 255bf215546Sopenharmony_ci{ 256bf215546Sopenharmony_ci struct fd_context *ctx = fd_context(pctx); 257bf215546Sopenharmony_ci struct pipe_framebuffer_state *cso; 258bf215546Sopenharmony_ci 259bf215546Sopenharmony_ci DBG("%ux%u, %u layers, %u samples", framebuffer->width, framebuffer->height, 260bf215546Sopenharmony_ci framebuffer->layers, framebuffer->samples); 261bf215546Sopenharmony_ci 262bf215546Sopenharmony_ci cso = &ctx->framebuffer; 263bf215546Sopenharmony_ci 264bf215546Sopenharmony_ci if (util_framebuffer_state_equal(cso, framebuffer)) 265bf215546Sopenharmony_ci return; 266bf215546Sopenharmony_ci 267bf215546Sopenharmony_ci /* Do this *after* checking that the framebuffer state is actually 268bf215546Sopenharmony_ci * changing. In the fd_blitter_clear() path, we get a pfb update 269bf215546Sopenharmony_ci * to restore the current pfb state, which should not trigger us 270bf215546Sopenharmony_ci * to flush (as that can cause the batch to be freed at a point 271bf215546Sopenharmony_ci * before fd_clear() returns, but after the point where it expects 272bf215546Sopenharmony_ci * flushes to potentially happen. 273bf215546Sopenharmony_ci */ 274bf215546Sopenharmony_ci fd_context_switch_from(ctx); 275bf215546Sopenharmony_ci 276bf215546Sopenharmony_ci util_copy_framebuffer_state(cso, framebuffer); 277bf215546Sopenharmony_ci 278bf215546Sopenharmony_ci cso->samples = util_framebuffer_get_num_samples(cso); 279bf215546Sopenharmony_ci 280bf215546Sopenharmony_ci if (ctx->screen->reorder) { 281bf215546Sopenharmony_ci struct fd_batch *old_batch = NULL; 282bf215546Sopenharmony_ci 283bf215546Sopenharmony_ci fd_batch_reference(&old_batch, ctx->batch); 284bf215546Sopenharmony_ci 285bf215546Sopenharmony_ci if (likely(old_batch)) 286bf215546Sopenharmony_ci fd_batch_finish_queries(old_batch); 287bf215546Sopenharmony_ci 288bf215546Sopenharmony_ci fd_batch_reference(&ctx->batch, NULL); 289bf215546Sopenharmony_ci fd_context_all_dirty(ctx); 290bf215546Sopenharmony_ci ctx->update_active_queries = true; 291bf215546Sopenharmony_ci 292bf215546Sopenharmony_ci fd_batch_reference(&old_batch, NULL); 293bf215546Sopenharmony_ci } else if (ctx->batch) { 294bf215546Sopenharmony_ci DBG("%d: cbufs[0]=%p, zsbuf=%p", ctx->batch->needs_flush, 295bf215546Sopenharmony_ci framebuffer->cbufs[0], framebuffer->zsbuf); 296bf215546Sopenharmony_ci fd_batch_flush(ctx->batch); 297bf215546Sopenharmony_ci } 298bf215546Sopenharmony_ci 299bf215546Sopenharmony_ci fd_context_dirty(ctx, FD_DIRTY_FRAMEBUFFER); 300bf215546Sopenharmony_ci 301bf215546Sopenharmony_ci ctx->disabled_scissor.minx = 0; 302bf215546Sopenharmony_ci ctx->disabled_scissor.miny = 0; 303bf215546Sopenharmony_ci ctx->disabled_scissor.maxx = cso->width; 304bf215546Sopenharmony_ci ctx->disabled_scissor.maxy = cso->height; 305bf215546Sopenharmony_ci 306bf215546Sopenharmony_ci fd_context_dirty(ctx, FD_DIRTY_SCISSOR); 307bf215546Sopenharmony_ci update_draw_cost(ctx); 308bf215546Sopenharmony_ci} 309bf215546Sopenharmony_ci 310bf215546Sopenharmony_cistatic void 311bf215546Sopenharmony_cifd_set_polygon_stipple(struct pipe_context *pctx, 312bf215546Sopenharmony_ci const struct pipe_poly_stipple *stipple) in_dt 313bf215546Sopenharmony_ci{ 314bf215546Sopenharmony_ci struct fd_context *ctx = fd_context(pctx); 315bf215546Sopenharmony_ci ctx->stipple = *stipple; 316bf215546Sopenharmony_ci fd_context_dirty(ctx, FD_DIRTY_STIPPLE); 317bf215546Sopenharmony_ci} 318bf215546Sopenharmony_ci 319bf215546Sopenharmony_cistatic void 320bf215546Sopenharmony_cifd_set_scissor_states(struct pipe_context *pctx, unsigned start_slot, 321bf215546Sopenharmony_ci unsigned num_scissors, 322bf215546Sopenharmony_ci const struct pipe_scissor_state *scissor) in_dt 323bf215546Sopenharmony_ci{ 324bf215546Sopenharmony_ci struct fd_context *ctx = fd_context(pctx); 325bf215546Sopenharmony_ci 326bf215546Sopenharmony_ci ctx->scissor = *scissor; 327bf215546Sopenharmony_ci fd_context_dirty(ctx, FD_DIRTY_SCISSOR); 328bf215546Sopenharmony_ci} 329bf215546Sopenharmony_ci 330bf215546Sopenharmony_cistatic void 331bf215546Sopenharmony_cifd_set_viewport_states(struct pipe_context *pctx, unsigned start_slot, 332bf215546Sopenharmony_ci unsigned num_viewports, 333bf215546Sopenharmony_ci const struct pipe_viewport_state *viewport) in_dt 334bf215546Sopenharmony_ci{ 335bf215546Sopenharmony_ci struct fd_context *ctx = fd_context(pctx); 336bf215546Sopenharmony_ci struct pipe_scissor_state *scissor = &ctx->viewport_scissor; 337bf215546Sopenharmony_ci float minx, miny, maxx, maxy; 338bf215546Sopenharmony_ci 339bf215546Sopenharmony_ci ctx->viewport = *viewport; 340bf215546Sopenharmony_ci 341bf215546Sopenharmony_ci /* see si_get_scissor_from_viewport(): */ 342bf215546Sopenharmony_ci 343bf215546Sopenharmony_ci /* Convert (-1, -1) and (1, 1) from clip space into window space. */ 344bf215546Sopenharmony_ci minx = -viewport->scale[0] + viewport->translate[0]; 345bf215546Sopenharmony_ci miny = -viewport->scale[1] + viewport->translate[1]; 346bf215546Sopenharmony_ci maxx = viewport->scale[0] + viewport->translate[0]; 347bf215546Sopenharmony_ci maxy = viewport->scale[1] + viewport->translate[1]; 348bf215546Sopenharmony_ci 349bf215546Sopenharmony_ci /* Handle inverted viewports. */ 350bf215546Sopenharmony_ci if (minx > maxx) { 351bf215546Sopenharmony_ci swap(minx, maxx); 352bf215546Sopenharmony_ci } 353bf215546Sopenharmony_ci if (miny > maxy) { 354bf215546Sopenharmony_ci swap(miny, maxy); 355bf215546Sopenharmony_ci } 356bf215546Sopenharmony_ci 357bf215546Sopenharmony_ci const float max_dims = ctx->screen->gen >= 4 ? 16384.f : 4096.f; 358bf215546Sopenharmony_ci 359bf215546Sopenharmony_ci /* Clamp, convert to integer and round up the max bounds. */ 360bf215546Sopenharmony_ci scissor->minx = CLAMP(minx, 0.f, max_dims); 361bf215546Sopenharmony_ci scissor->miny = CLAMP(miny, 0.f, max_dims); 362bf215546Sopenharmony_ci scissor->maxx = CLAMP(ceilf(maxx), 0.f, max_dims); 363bf215546Sopenharmony_ci scissor->maxy = CLAMP(ceilf(maxy), 0.f, max_dims); 364bf215546Sopenharmony_ci 365bf215546Sopenharmony_ci fd_context_dirty(ctx, FD_DIRTY_VIEWPORT); 366bf215546Sopenharmony_ci} 367bf215546Sopenharmony_ci 368bf215546Sopenharmony_cistatic void 369bf215546Sopenharmony_cifd_set_vertex_buffers(struct pipe_context *pctx, unsigned start_slot, 370bf215546Sopenharmony_ci unsigned count, unsigned unbind_num_trailing_slots, 371bf215546Sopenharmony_ci bool take_ownership, 372bf215546Sopenharmony_ci const struct pipe_vertex_buffer *vb) in_dt 373bf215546Sopenharmony_ci{ 374bf215546Sopenharmony_ci struct fd_context *ctx = fd_context(pctx); 375bf215546Sopenharmony_ci struct fd_vertexbuf_stateobj *so = &ctx->vtx.vertexbuf; 376bf215546Sopenharmony_ci int i; 377bf215546Sopenharmony_ci 378bf215546Sopenharmony_ci /* on a2xx, pitch is encoded in the vtx fetch instruction, so 379bf215546Sopenharmony_ci * we need to mark VTXSTATE as dirty as well to trigger patching 380bf215546Sopenharmony_ci * and re-emitting the vtx shader: 381bf215546Sopenharmony_ci */ 382bf215546Sopenharmony_ci if (ctx->screen->gen < 3) { 383bf215546Sopenharmony_ci for (i = 0; i < count; i++) { 384bf215546Sopenharmony_ci bool new_enabled = vb && vb[i].buffer.resource; 385bf215546Sopenharmony_ci bool old_enabled = so->vb[start_slot + i].buffer.resource != NULL; 386bf215546Sopenharmony_ci uint32_t new_stride = vb ? vb[i].stride : 0; 387bf215546Sopenharmony_ci uint32_t old_stride = so->vb[start_slot + i].stride; 388bf215546Sopenharmony_ci if ((new_enabled != old_enabled) || (new_stride != old_stride)) { 389bf215546Sopenharmony_ci fd_context_dirty(ctx, FD_DIRTY_VTXSTATE); 390bf215546Sopenharmony_ci break; 391bf215546Sopenharmony_ci } 392bf215546Sopenharmony_ci } 393bf215546Sopenharmony_ci } 394bf215546Sopenharmony_ci 395bf215546Sopenharmony_ci util_set_vertex_buffers_mask(so->vb, &so->enabled_mask, vb, start_slot, 396bf215546Sopenharmony_ci count, unbind_num_trailing_slots, 397bf215546Sopenharmony_ci take_ownership); 398bf215546Sopenharmony_ci so->count = util_last_bit(so->enabled_mask); 399bf215546Sopenharmony_ci 400bf215546Sopenharmony_ci if (!vb) 401bf215546Sopenharmony_ci return; 402bf215546Sopenharmony_ci 403bf215546Sopenharmony_ci fd_context_dirty(ctx, FD_DIRTY_VTXBUF); 404bf215546Sopenharmony_ci 405bf215546Sopenharmony_ci for (unsigned i = 0; i < count; i++) { 406bf215546Sopenharmony_ci assert(!vb[i].is_user_buffer); 407bf215546Sopenharmony_ci fd_resource_set_usage(vb[i].buffer.resource, FD_DIRTY_VTXBUF); 408bf215546Sopenharmony_ci 409bf215546Sopenharmony_ci /* Robust buffer access: Return undefined data (the start of the buffer) 410bf215546Sopenharmony_ci * instead of process termination or a GPU hang in case of overflow. 411bf215546Sopenharmony_ci */ 412bf215546Sopenharmony_ci if (vb[i].buffer.resource && 413bf215546Sopenharmony_ci unlikely(vb[i].buffer_offset >= vb[i].buffer.resource->width0)) { 414bf215546Sopenharmony_ci so->vb[start_slot + i].buffer_offset = 0; 415bf215546Sopenharmony_ci } 416bf215546Sopenharmony_ci } 417bf215546Sopenharmony_ci} 418bf215546Sopenharmony_ci 419bf215546Sopenharmony_cistatic void 420bf215546Sopenharmony_cifd_blend_state_bind(struct pipe_context *pctx, void *hwcso) in_dt 421bf215546Sopenharmony_ci{ 422bf215546Sopenharmony_ci struct fd_context *ctx = fd_context(pctx); 423bf215546Sopenharmony_ci struct pipe_blend_state *cso = hwcso; 424bf215546Sopenharmony_ci bool old_is_dual = ctx->blend ? ctx->blend->rt[0].blend_enable && 425bf215546Sopenharmony_ci util_blend_state_is_dual(ctx->blend, 0) 426bf215546Sopenharmony_ci : false; 427bf215546Sopenharmony_ci bool new_is_dual = 428bf215546Sopenharmony_ci cso ? cso->rt[0].blend_enable && util_blend_state_is_dual(cso, 0) : false; 429bf215546Sopenharmony_ci ctx->blend = hwcso; 430bf215546Sopenharmony_ci fd_context_dirty(ctx, FD_DIRTY_BLEND); 431bf215546Sopenharmony_ci if (old_is_dual != new_is_dual) 432bf215546Sopenharmony_ci fd_context_dirty(ctx, FD_DIRTY_BLEND_DUAL); 433bf215546Sopenharmony_ci update_draw_cost(ctx); 434bf215546Sopenharmony_ci} 435bf215546Sopenharmony_ci 436bf215546Sopenharmony_cistatic void 437bf215546Sopenharmony_cifd_blend_state_delete(struct pipe_context *pctx, void *hwcso) in_dt 438bf215546Sopenharmony_ci{ 439bf215546Sopenharmony_ci FREE(hwcso); 440bf215546Sopenharmony_ci} 441bf215546Sopenharmony_ci 442bf215546Sopenharmony_cistatic void 443bf215546Sopenharmony_cifd_rasterizer_state_bind(struct pipe_context *pctx, void *hwcso) in_dt 444bf215546Sopenharmony_ci{ 445bf215546Sopenharmony_ci struct fd_context *ctx = fd_context(pctx); 446bf215546Sopenharmony_ci struct pipe_scissor_state *old_scissor = fd_context_get_scissor(ctx); 447bf215546Sopenharmony_ci bool discard = get_safe(ctx->rasterizer, rasterizer_discard); 448bf215546Sopenharmony_ci unsigned clip_plane_enable = get_safe(ctx->rasterizer, clip_plane_enable); 449bf215546Sopenharmony_ci 450bf215546Sopenharmony_ci ctx->rasterizer = hwcso; 451bf215546Sopenharmony_ci fd_context_dirty(ctx, FD_DIRTY_RASTERIZER); 452bf215546Sopenharmony_ci 453bf215546Sopenharmony_ci if (ctx->rasterizer && ctx->rasterizer->scissor) { 454bf215546Sopenharmony_ci ctx->current_scissor = &ctx->scissor; 455bf215546Sopenharmony_ci } else { 456bf215546Sopenharmony_ci ctx->current_scissor = &ctx->disabled_scissor; 457bf215546Sopenharmony_ci } 458bf215546Sopenharmony_ci 459bf215546Sopenharmony_ci /* if scissor enable bit changed we need to mark scissor 460bf215546Sopenharmony_ci * state as dirty as well: 461bf215546Sopenharmony_ci * NOTE: we can do a shallow compare, since we only care 462bf215546Sopenharmony_ci * if it changed to/from &ctx->disable_scissor 463bf215546Sopenharmony_ci */ 464bf215546Sopenharmony_ci if (old_scissor != fd_context_get_scissor(ctx)) 465bf215546Sopenharmony_ci fd_context_dirty(ctx, FD_DIRTY_SCISSOR); 466bf215546Sopenharmony_ci 467bf215546Sopenharmony_ci if (discard != get_safe(ctx->rasterizer, rasterizer_discard)) 468bf215546Sopenharmony_ci fd_context_dirty(ctx, FD_DIRTY_RASTERIZER_DISCARD); 469bf215546Sopenharmony_ci 470bf215546Sopenharmony_ci if (clip_plane_enable != get_safe(ctx->rasterizer, clip_plane_enable)) 471bf215546Sopenharmony_ci fd_context_dirty(ctx, FD_DIRTY_RASTERIZER_CLIP_PLANE_ENABLE); 472bf215546Sopenharmony_ci} 473bf215546Sopenharmony_ci 474bf215546Sopenharmony_cistatic void 475bf215546Sopenharmony_cifd_rasterizer_state_delete(struct pipe_context *pctx, void *hwcso) in_dt 476bf215546Sopenharmony_ci{ 477bf215546Sopenharmony_ci FREE(hwcso); 478bf215546Sopenharmony_ci} 479bf215546Sopenharmony_ci 480bf215546Sopenharmony_cistatic void 481bf215546Sopenharmony_cifd_zsa_state_bind(struct pipe_context *pctx, void *hwcso) in_dt 482bf215546Sopenharmony_ci{ 483bf215546Sopenharmony_ci struct fd_context *ctx = fd_context(pctx); 484bf215546Sopenharmony_ci ctx->zsa = hwcso; 485bf215546Sopenharmony_ci fd_context_dirty(ctx, FD_DIRTY_ZSA); 486bf215546Sopenharmony_ci update_draw_cost(ctx); 487bf215546Sopenharmony_ci} 488bf215546Sopenharmony_ci 489bf215546Sopenharmony_cistatic void 490bf215546Sopenharmony_cifd_zsa_state_delete(struct pipe_context *pctx, void *hwcso) in_dt 491bf215546Sopenharmony_ci{ 492bf215546Sopenharmony_ci FREE(hwcso); 493bf215546Sopenharmony_ci} 494bf215546Sopenharmony_ci 495bf215546Sopenharmony_cistatic void * 496bf215546Sopenharmony_cifd_vertex_state_create(struct pipe_context *pctx, unsigned num_elements, 497bf215546Sopenharmony_ci const struct pipe_vertex_element *elements) 498bf215546Sopenharmony_ci{ 499bf215546Sopenharmony_ci struct fd_vertex_stateobj *so = CALLOC_STRUCT(fd_vertex_stateobj); 500bf215546Sopenharmony_ci 501bf215546Sopenharmony_ci if (!so) 502bf215546Sopenharmony_ci return NULL; 503bf215546Sopenharmony_ci 504bf215546Sopenharmony_ci memcpy(so->pipe, elements, sizeof(*elements) * num_elements); 505bf215546Sopenharmony_ci so->num_elements = num_elements; 506bf215546Sopenharmony_ci 507bf215546Sopenharmony_ci return so; 508bf215546Sopenharmony_ci} 509bf215546Sopenharmony_ci 510bf215546Sopenharmony_cistatic void 511bf215546Sopenharmony_cifd_vertex_state_delete(struct pipe_context *pctx, void *hwcso) in_dt 512bf215546Sopenharmony_ci{ 513bf215546Sopenharmony_ci FREE(hwcso); 514bf215546Sopenharmony_ci} 515bf215546Sopenharmony_ci 516bf215546Sopenharmony_cistatic void 517bf215546Sopenharmony_cifd_vertex_state_bind(struct pipe_context *pctx, void *hwcso) in_dt 518bf215546Sopenharmony_ci{ 519bf215546Sopenharmony_ci struct fd_context *ctx = fd_context(pctx); 520bf215546Sopenharmony_ci ctx->vtx.vtx = hwcso; 521bf215546Sopenharmony_ci fd_context_dirty(ctx, FD_DIRTY_VTXSTATE); 522bf215546Sopenharmony_ci} 523bf215546Sopenharmony_ci 524bf215546Sopenharmony_cistatic struct pipe_stream_output_target * 525bf215546Sopenharmony_cifd_create_stream_output_target(struct pipe_context *pctx, 526bf215546Sopenharmony_ci struct pipe_resource *prsc, 527bf215546Sopenharmony_ci unsigned buffer_offset, unsigned buffer_size) 528bf215546Sopenharmony_ci{ 529bf215546Sopenharmony_ci struct fd_stream_output_target *target; 530bf215546Sopenharmony_ci struct fd_resource *rsc = fd_resource(prsc); 531bf215546Sopenharmony_ci 532bf215546Sopenharmony_ci target = CALLOC_STRUCT(fd_stream_output_target); 533bf215546Sopenharmony_ci if (!target) 534bf215546Sopenharmony_ci return NULL; 535bf215546Sopenharmony_ci 536bf215546Sopenharmony_ci pipe_reference_init(&target->base.reference, 1); 537bf215546Sopenharmony_ci pipe_resource_reference(&target->base.buffer, prsc); 538bf215546Sopenharmony_ci 539bf215546Sopenharmony_ci target->base.context = pctx; 540bf215546Sopenharmony_ci target->base.buffer_offset = buffer_offset; 541bf215546Sopenharmony_ci target->base.buffer_size = buffer_size; 542bf215546Sopenharmony_ci 543bf215546Sopenharmony_ci target->offset_buf = pipe_buffer_create( 544bf215546Sopenharmony_ci pctx->screen, PIPE_BIND_CUSTOM, PIPE_USAGE_IMMUTABLE, sizeof(uint32_t)); 545bf215546Sopenharmony_ci 546bf215546Sopenharmony_ci assert(rsc->b.b.target == PIPE_BUFFER); 547bf215546Sopenharmony_ci util_range_add(&rsc->b.b, &rsc->valid_buffer_range, buffer_offset, 548bf215546Sopenharmony_ci buffer_offset + buffer_size); 549bf215546Sopenharmony_ci 550bf215546Sopenharmony_ci return &target->base; 551bf215546Sopenharmony_ci} 552bf215546Sopenharmony_ci 553bf215546Sopenharmony_cistatic void 554bf215546Sopenharmony_cifd_stream_output_target_destroy(struct pipe_context *pctx, 555bf215546Sopenharmony_ci struct pipe_stream_output_target *target) 556bf215546Sopenharmony_ci{ 557bf215546Sopenharmony_ci struct fd_stream_output_target *cso = fd_stream_output_target(target); 558bf215546Sopenharmony_ci 559bf215546Sopenharmony_ci pipe_resource_reference(&cso->base.buffer, NULL); 560bf215546Sopenharmony_ci pipe_resource_reference(&cso->offset_buf, NULL); 561bf215546Sopenharmony_ci 562bf215546Sopenharmony_ci FREE(target); 563bf215546Sopenharmony_ci} 564bf215546Sopenharmony_ci 565bf215546Sopenharmony_cistatic void 566bf215546Sopenharmony_cifd_set_stream_output_targets(struct pipe_context *pctx, unsigned num_targets, 567bf215546Sopenharmony_ci struct pipe_stream_output_target **targets, 568bf215546Sopenharmony_ci const unsigned *offsets) in_dt 569bf215546Sopenharmony_ci{ 570bf215546Sopenharmony_ci struct fd_context *ctx = fd_context(pctx); 571bf215546Sopenharmony_ci struct fd_streamout_stateobj *so = &ctx->streamout; 572bf215546Sopenharmony_ci unsigned i; 573bf215546Sopenharmony_ci 574bf215546Sopenharmony_ci assert(num_targets <= ARRAY_SIZE(so->targets)); 575bf215546Sopenharmony_ci 576bf215546Sopenharmony_ci /* Older targets need sw stats enabled for streamout emulation in VS: */ 577bf215546Sopenharmony_ci if (ctx->screen->gen < 5) { 578bf215546Sopenharmony_ci if (num_targets && !so->num_targets) { 579bf215546Sopenharmony_ci ctx->stats_users++; 580bf215546Sopenharmony_ci } else if (so->num_targets && !num_targets) { 581bf215546Sopenharmony_ci ctx->stats_users--; 582bf215546Sopenharmony_ci } 583bf215546Sopenharmony_ci } 584bf215546Sopenharmony_ci 585bf215546Sopenharmony_ci for (i = 0; i < num_targets; i++) { 586bf215546Sopenharmony_ci boolean changed = targets[i] != so->targets[i]; 587bf215546Sopenharmony_ci boolean reset = (offsets[i] != (unsigned)-1); 588bf215546Sopenharmony_ci 589bf215546Sopenharmony_ci so->reset |= (reset << i); 590bf215546Sopenharmony_ci 591bf215546Sopenharmony_ci if (!changed && !reset) 592bf215546Sopenharmony_ci continue; 593bf215546Sopenharmony_ci 594bf215546Sopenharmony_ci /* Note that all SO targets will be reset at once at a 595bf215546Sopenharmony_ci * BeginTransformFeedback(). 596bf215546Sopenharmony_ci */ 597bf215546Sopenharmony_ci if (reset) { 598bf215546Sopenharmony_ci so->offsets[i] = offsets[i]; 599bf215546Sopenharmony_ci ctx->streamout.verts_written = 0; 600bf215546Sopenharmony_ci } 601bf215546Sopenharmony_ci 602bf215546Sopenharmony_ci pipe_so_target_reference(&so->targets[i], targets[i]); 603bf215546Sopenharmony_ci } 604bf215546Sopenharmony_ci 605bf215546Sopenharmony_ci for (; i < so->num_targets; i++) { 606bf215546Sopenharmony_ci pipe_so_target_reference(&so->targets[i], NULL); 607bf215546Sopenharmony_ci } 608bf215546Sopenharmony_ci 609bf215546Sopenharmony_ci so->num_targets = num_targets; 610bf215546Sopenharmony_ci 611bf215546Sopenharmony_ci fd_context_dirty(ctx, FD_DIRTY_STREAMOUT); 612bf215546Sopenharmony_ci} 613bf215546Sopenharmony_ci 614bf215546Sopenharmony_cistatic void 615bf215546Sopenharmony_cifd_bind_compute_state(struct pipe_context *pctx, void *state) in_dt 616bf215546Sopenharmony_ci{ 617bf215546Sopenharmony_ci struct fd_context *ctx = fd_context(pctx); 618bf215546Sopenharmony_ci ctx->compute = state; 619bf215546Sopenharmony_ci /* NOTE: Don't mark FD_DIRTY_PROG for compute specific state */ 620bf215546Sopenharmony_ci ctx->dirty_shader[PIPE_SHADER_COMPUTE] |= FD_DIRTY_SHADER_PROG; 621bf215546Sopenharmony_ci} 622bf215546Sopenharmony_ci 623bf215546Sopenharmony_ci/* TODO pipe_context::set_compute_resources() should DIAF and clover 624bf215546Sopenharmony_ci * should be updated to use pipe_context::set_constant_buffer() and 625bf215546Sopenharmony_ci * pipe_context::set_shader_images(). Until then just directly frob 626bf215546Sopenharmony_ci * the UBO/image state to avoid the rest of the driver needing to 627bf215546Sopenharmony_ci * know about this bastard api.. 628bf215546Sopenharmony_ci */ 629bf215546Sopenharmony_cistatic void 630bf215546Sopenharmony_cifd_set_compute_resources(struct pipe_context *pctx, unsigned start, 631bf215546Sopenharmony_ci unsigned count, struct pipe_surface **prscs) in_dt 632bf215546Sopenharmony_ci{ 633bf215546Sopenharmony_ci struct fd_context *ctx = fd_context(pctx); 634bf215546Sopenharmony_ci struct fd_constbuf_stateobj *so = &ctx->constbuf[PIPE_SHADER_COMPUTE]; 635bf215546Sopenharmony_ci 636bf215546Sopenharmony_ci for (unsigned i = 0; i < count; i++) { 637bf215546Sopenharmony_ci const uint32_t index = i + start + 1; /* UBOs start at index 1 */ 638bf215546Sopenharmony_ci 639bf215546Sopenharmony_ci if (!prscs) { 640bf215546Sopenharmony_ci util_copy_constant_buffer(&so->cb[index], NULL, false); 641bf215546Sopenharmony_ci so->enabled_mask &= ~(1 << index); 642bf215546Sopenharmony_ci } else if (prscs[i]->format == PIPE_FORMAT_NONE) { 643bf215546Sopenharmony_ci struct pipe_constant_buffer cb = { 644bf215546Sopenharmony_ci .buffer = prscs[i]->texture, 645bf215546Sopenharmony_ci }; 646bf215546Sopenharmony_ci util_copy_constant_buffer(&so->cb[index], &cb, false); 647bf215546Sopenharmony_ci so->enabled_mask |= (1 << index); 648bf215546Sopenharmony_ci } else { 649bf215546Sopenharmony_ci // TODO images 650bf215546Sopenharmony_ci unreachable("finishme"); 651bf215546Sopenharmony_ci } 652bf215546Sopenharmony_ci } 653bf215546Sopenharmony_ci} 654bf215546Sopenharmony_ci 655bf215546Sopenharmony_ci/* used by clover to bind global objects, returning the bo address 656bf215546Sopenharmony_ci * via handles[n] 657bf215546Sopenharmony_ci */ 658bf215546Sopenharmony_cistatic void 659bf215546Sopenharmony_cifd_set_global_binding(struct pipe_context *pctx, unsigned first, unsigned count, 660bf215546Sopenharmony_ci struct pipe_resource **prscs, uint32_t **handles) in_dt 661bf215546Sopenharmony_ci{ 662bf215546Sopenharmony_ci struct fd_context *ctx = fd_context(pctx); 663bf215546Sopenharmony_ci struct fd_global_bindings_stateobj *so = &ctx->global_bindings; 664bf215546Sopenharmony_ci unsigned mask = 0; 665bf215546Sopenharmony_ci 666bf215546Sopenharmony_ci if (prscs) { 667bf215546Sopenharmony_ci for (unsigned i = 0; i < count; i++) { 668bf215546Sopenharmony_ci unsigned n = i + first; 669bf215546Sopenharmony_ci 670bf215546Sopenharmony_ci mask |= BIT(n); 671bf215546Sopenharmony_ci 672bf215546Sopenharmony_ci pipe_resource_reference(&so->buf[n], prscs[i]); 673bf215546Sopenharmony_ci 674bf215546Sopenharmony_ci if (so->buf[n]) { 675bf215546Sopenharmony_ci struct fd_resource *rsc = fd_resource(so->buf[n]); 676bf215546Sopenharmony_ci uint32_t offset = *handles[i]; 677bf215546Sopenharmony_ci uint64_t iova = fd_bo_get_iova(rsc->bo) + offset; 678bf215546Sopenharmony_ci 679bf215546Sopenharmony_ci /* Yes, really, despite what the type implies: */ 680bf215546Sopenharmony_ci memcpy(handles[i], &iova, sizeof(iova)); 681bf215546Sopenharmony_ci } 682bf215546Sopenharmony_ci 683bf215546Sopenharmony_ci if (prscs[i]) 684bf215546Sopenharmony_ci so->enabled_mask |= BIT(n); 685bf215546Sopenharmony_ci else 686bf215546Sopenharmony_ci so->enabled_mask &= ~BIT(n); 687bf215546Sopenharmony_ci } 688bf215546Sopenharmony_ci } else { 689bf215546Sopenharmony_ci mask = (BIT(count) - 1) << first; 690bf215546Sopenharmony_ci 691bf215546Sopenharmony_ci for (unsigned i = 0; i < count; i++) { 692bf215546Sopenharmony_ci unsigned n = i + first; 693bf215546Sopenharmony_ci pipe_resource_reference(&so->buf[n], NULL); 694bf215546Sopenharmony_ci } 695bf215546Sopenharmony_ci 696bf215546Sopenharmony_ci so->enabled_mask &= ~mask; 697bf215546Sopenharmony_ci } 698bf215546Sopenharmony_ci} 699bf215546Sopenharmony_ci 700bf215546Sopenharmony_civoid 701bf215546Sopenharmony_cifd_state_init(struct pipe_context *pctx) 702bf215546Sopenharmony_ci{ 703bf215546Sopenharmony_ci pctx->set_blend_color = fd_set_blend_color; 704bf215546Sopenharmony_ci pctx->set_stencil_ref = fd_set_stencil_ref; 705bf215546Sopenharmony_ci pctx->set_clip_state = fd_set_clip_state; 706bf215546Sopenharmony_ci pctx->set_sample_mask = fd_set_sample_mask; 707bf215546Sopenharmony_ci pctx->set_min_samples = fd_set_min_samples; 708bf215546Sopenharmony_ci pctx->set_constant_buffer = fd_set_constant_buffer; 709bf215546Sopenharmony_ci pctx->set_shader_buffers = fd_set_shader_buffers; 710bf215546Sopenharmony_ci pctx->set_shader_images = fd_set_shader_images; 711bf215546Sopenharmony_ci pctx->set_framebuffer_state = fd_set_framebuffer_state; 712bf215546Sopenharmony_ci pctx->set_polygon_stipple = fd_set_polygon_stipple; 713bf215546Sopenharmony_ci pctx->set_scissor_states = fd_set_scissor_states; 714bf215546Sopenharmony_ci pctx->set_viewport_states = fd_set_viewport_states; 715bf215546Sopenharmony_ci 716bf215546Sopenharmony_ci pctx->set_vertex_buffers = fd_set_vertex_buffers; 717bf215546Sopenharmony_ci 718bf215546Sopenharmony_ci pctx->bind_blend_state = fd_blend_state_bind; 719bf215546Sopenharmony_ci pctx->delete_blend_state = fd_blend_state_delete; 720bf215546Sopenharmony_ci 721bf215546Sopenharmony_ci pctx->bind_rasterizer_state = fd_rasterizer_state_bind; 722bf215546Sopenharmony_ci pctx->delete_rasterizer_state = fd_rasterizer_state_delete; 723bf215546Sopenharmony_ci 724bf215546Sopenharmony_ci pctx->bind_depth_stencil_alpha_state = fd_zsa_state_bind; 725bf215546Sopenharmony_ci pctx->delete_depth_stencil_alpha_state = fd_zsa_state_delete; 726bf215546Sopenharmony_ci 727bf215546Sopenharmony_ci if (!pctx->create_vertex_elements_state) 728bf215546Sopenharmony_ci pctx->create_vertex_elements_state = fd_vertex_state_create; 729bf215546Sopenharmony_ci pctx->delete_vertex_elements_state = fd_vertex_state_delete; 730bf215546Sopenharmony_ci pctx->bind_vertex_elements_state = fd_vertex_state_bind; 731bf215546Sopenharmony_ci 732bf215546Sopenharmony_ci pctx->create_stream_output_target = fd_create_stream_output_target; 733bf215546Sopenharmony_ci pctx->stream_output_target_destroy = fd_stream_output_target_destroy; 734bf215546Sopenharmony_ci pctx->set_stream_output_targets = fd_set_stream_output_targets; 735bf215546Sopenharmony_ci 736bf215546Sopenharmony_ci if (has_compute(fd_screen(pctx->screen))) { 737bf215546Sopenharmony_ci pctx->bind_compute_state = fd_bind_compute_state; 738bf215546Sopenharmony_ci pctx->set_compute_resources = fd_set_compute_resources; 739bf215546Sopenharmony_ci pctx->set_global_binding = fd_set_global_binding; 740bf215546Sopenharmony_ci } 741bf215546Sopenharmony_ci} 742