static void svga_set_polygon_stipple(struct pipe_context *pipe, const struct pipe_poly_stipple *stipple) { struct svga_context *svga = svga_context(pipe); /* release old texture */ pipe_resource_reference(&svga->polygon_stipple.texture, NULL); /* release old sampler view */ if (svga->polygon_stipple.sampler_view) { pipe->sampler_view_destroy(pipe, &svga->polygon_stipple.sampler_view->base); } /* create new stipple texture */ svga->polygon_stipple.texture = util_pstipple_create_stipple_texture(pipe, stipple->stipple); /* create new sampler view */ svga->polygon_stipple.sampler_view = (struct svga_pipe_sampler_view *) util_pstipple_create_sampler_view(pipe, svga->polygon_stipple.texture); /* allocate sampler state, if first time */ if (!svga->polygon_stipple.sampler) { svga->polygon_stipple.sampler = util_pstipple_create_sampler(pipe); } svga->dirty |= SVGA_NEW_STIPPLE; }
static void svga_destroy( struct pipe_context *pipe ) { struct svga_context *svga = svga_context( pipe ); unsigned shader; svga_cleanup_framebuffer( svga ); svga_cleanup_tss_binding( svga ); svga_hwtnl_destroy( svga->hwtnl ); svga_cleanup_vertex_state(svga); svga->swc->destroy(svga->swc); svga_destroy_swtnl( svga ); u_upload_destroy( svga->upload_vb ); u_upload_destroy( svga->upload_ib ); util_bitmask_destroy( svga->vs_bm ); util_bitmask_destroy( svga->fs_bm ); for(shader = 0; shader < PIPE_SHADER_TYPES; ++shader) pipe_resource_reference( &svga->curr.cb[shader], NULL ); FREE( svga ); }
static void * svga_create_fs_state(struct pipe_context *pipe, const struct pipe_shader_state *templ) { struct svga_context *svga = svga_context(pipe); struct svga_screen *svgascreen = svga_screen(pipe->screen); struct svga_fragment_shader *fs; fs = CALLOC_STRUCT(svga_fragment_shader); if (!fs) return NULL; fs->base.tokens = tgsi_dup_tokens(templ->tokens); /* Collect basic info that we'll need later: */ tgsi_scan_shader(fs->base.tokens, &fs->base.info); fs->base.id = svga->debug.shader_id++; fs->base.use_sm30 = svgascreen->use_ps30; if (SVGA_DEBUG & DEBUG_TGSI || 0) { debug_printf("%s id: %u, inputs: %u, outputs: %u\n", __FUNCTION__, fs->base.id, fs->base.info.num_inputs, fs->base.info.num_outputs); } return fs; }
/** * Clear the given surface to the specified value. * No masking, no scissor (clear entire buffer). */ void svga_clear(struct pipe_context *pipe, unsigned buffers, const float *rgba, double depth, unsigned stencil) { struct svga_context *svga = svga_context( pipe ); int ret; if (buffers & PIPE_CLEAR_COLOR) SVGA_DBG(DEBUG_DMA, "clear sid %p\n", svga_surface(svga->curr.framebuffer.cbufs[0])->handle); ret = try_clear( svga, buffers, rgba, depth, stencil ); if (ret == PIPE_ERROR_OUT_OF_MEMORY) { /* Flush command buffer and retry: */ svga_context_flush( svga, NULL ); ret = try_clear( svga, buffers, rgba, depth, stencil ); } /* * Mark target surfaces as dirty * TODO Mark only cleared surfaces. */ svga_mark_surfaces_dirty(svga); assert (ret == PIPE_OK); }
static void * svga_create_gs_state(struct pipe_context *pipe, const struct pipe_shader_state *templ) { struct svga_context *svga = svga_context(pipe); struct svga_geometry_shader *gs = CALLOC_STRUCT(svga_geometry_shader); if (!gs) return NULL; SVGA_STATS_TIME_PUSH(svga_sws(svga), SVGA_STATS_TIME_CREATEGS); gs->base.tokens = tgsi_dup_tokens(templ->tokens); /* Collect basic info that we'll need later: */ tgsi_scan_shader(gs->base.tokens, &gs->base.info); gs->draw_shader = draw_create_geometry_shader(svga->swtnl.draw, templ); gs->base.id = svga->debug.shader_id++; gs->generic_outputs = svga_get_generic_outputs_mask(&gs->base.info); /* check for any stream output declarations */ if (templ->stream_output.num_outputs) { gs->base.stream_output = svga_create_stream_output(svga, &gs->base, &templ->stream_output); } SVGA_STATS_TIME_POP(svga_sws(svga)); return gs; }
static void svga_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index, struct pipe_constant_buffer *cb) { struct svga_context *svga = svga_context(pipe); struct pipe_resource *buf = cb ? cb->buffer : NULL; if (cb && cb->user_buffer) { buf = svga_user_buffer_create(pipe->screen, (void *) cb->user_buffer, cb->buffer_size, PIPE_BIND_CONSTANT_BUFFER); } assert(shader < PIPE_SHADER_TYPES); assert(index == 0); pipe_resource_reference( &svga->curr.cb[shader], buf ); if (shader == PIPE_SHADER_FRAGMENT) svga->dirty |= SVGA_NEW_FS_CONST_BUFFER; else svga->dirty |= SVGA_NEW_VS_CONST_BUFFER; if (cb && cb->user_buffer) { pipe_resource_reference(&buf, NULL); } }
static void * svga_create_vertex_elements_state(struct pipe_context *pipe, unsigned count, const struct pipe_vertex_element *attribs) { struct svga_context *svga = svga_context(pipe); struct svga_velems_state *velems; assert(count <= PIPE_MAX_ATTRIBS); velems = (struct svga_velems_state *) MALLOC(sizeof(struct svga_velems_state)); if (velems) { velems->count = count; memcpy(velems->velem, attribs, sizeof(*attribs) * count); velems->need_swvfetch = FALSE; velems->adjust_attrib_range = 0x0; velems->attrib_is_pure_int = 0x0; velems->adjust_attrib_w_1 = 0x0; velems->adjust_attrib_itof = 0x0; velems->adjust_attrib_utof = 0x0; velems->attrib_is_bgra = 0x0; velems->attrib_puint_to_snorm = 0x0; velems->attrib_puint_to_uscaled = 0x0; velems->attrib_puint_to_sscaled = 0x0; if (svga_have_vgpu10(svga)) { define_input_element_object(svga, velems); } else { translate_vertex_decls(svga, velems); } } return velems; }
/** * \brief Clear render target pipe callback * * \param pipe[in] The pipe context * \param dst[in] The surface to clear * \param color[in] Clear color * \param dstx[in] Clear region left * \param dsty[in] Clear region top * \param width[in] Clear region width * \param height[in] Clear region height * \param render_condition_enabled[in] Whether to use conditional rendering * to clear (if elsewhere enabled). */ static void svga_clear_render_target(struct pipe_context *pipe, struct pipe_surface *dst, const union pipe_color_union *color, unsigned dstx, unsigned dsty, unsigned width, unsigned height, bool render_condition_enabled) { struct svga_context *svga = svga_context( pipe ); svga_toggle_render_condition(svga, render_condition_enabled, FALSE); if (!svga_have_vgpu10(svga) || dstx != 0 || dsty != 0 || width != dst->width || height != dst->height) { svga_blitter_clear_render_target(svga, dst, color, dstx, dsty, width, height); } else { enum pipe_error ret; ret = svga_try_clear_render_target(svga, dst, color); if (ret == PIPE_ERROR_OUT_OF_MEMORY) { svga_context_flush( svga, NULL ); ret = svga_try_clear_render_target(svga, dst, color); } assert (ret == PIPE_OK); } svga_toggle_render_condition(svga, render_condition_enabled, TRUE); }
static void svga_delete_vertex_elements_state(struct pipe_context *pipe, void *state) { struct svga_context *svga = svga_context(pipe); struct svga_velems_state *velems = (struct svga_velems_state *) state; if (svga_have_vgpu10(svga)) { enum pipe_error ret; svga_hwtnl_flush_retry(svga); ret = SVGA3D_vgpu10_DestroyElementLayout(svga->swc, velems->id); if (ret != PIPE_OK) { svga_context_flush(svga, NULL); ret = SVGA3D_vgpu10_DestroyElementLayout(svga->swc, velems->id); assert(ret == PIPE_OK); } if (velems->id == svga->state.hw_draw.layout_id) svga->state.hw_draw.layout_id = SVGA3D_INVALID_ID; util_bitmask_clear(svga->input_element_object_id_bm, velems->id); velems->id = SVGA3D_INVALID_ID; } FREE(velems); }
static void svga_set_index_buffer(struct pipe_context *pipe, const struct pipe_index_buffer *ib) { struct svga_context *svga = svga_context(pipe); util_set_index_buffer(&svga->curr.ib, ib); }
static void svga_clear_depth_stencil(struct pipe_context *pipe, struct pipe_surface *dst, unsigned clear_flags, double depth, unsigned stencil, unsigned dstx, unsigned dsty, unsigned width, unsigned height, bool render_condition_enabled) { struct svga_context *svga = svga_context( pipe ); svga_toggle_render_condition(svga, render_condition_enabled, FALSE); /* Use software fallback */ begin_blit(svga); util_blitter_save_framebuffer(svga->blitter, &svga->curr.framebuffer); util_blitter_clear_depth_stencil(svga->blitter, dst, clear_flags, depth, stencil, dstx, dsty, width, height); svga_toggle_render_condition(svga, render_condition_enabled, TRUE); }
/** * Clear the given surface to the specified value. * No masking, no scissor (clear entire buffer). */ void svga_clear(struct pipe_context *pipe, unsigned buffers, const union pipe_color_union *color, double depth, unsigned stencil) { struct svga_context *svga = svga_context( pipe ); enum pipe_error ret; if (buffers & PIPE_CLEAR_COLOR) SVGA_DBG(DEBUG_DMA, "clear sid %p\n", svga_surface(svga->curr.framebuffer.cbufs[0])->handle); /* flush any queued prims (don't want them to appear after the clear!) */ svga_hwtnl_flush_retry(svga); ret = try_clear( svga, buffers, color, depth, stencil ); if (ret == PIPE_ERROR_OUT_OF_MEMORY) { /* Flush command buffer and retry: */ svga_context_flush( svga, NULL ); ret = try_clear( svga, buffers, color, depth, stencil ); } /* * Mark target surfaces as dirty * TODO Mark only cleared surfaces. */ svga_mark_surfaces_dirty(svga); assert (ret == PIPE_OK); }
static void svga_texture_transfer_destroy(struct pipe_context *pipe, struct pipe_transfer *transfer) { struct svga_context *svga = svga_context(pipe); struct svga_texture *tex = svga_texture(transfer->resource); struct svga_screen *ss = svga_screen(pipe->screen); struct svga_winsys_screen *sws = ss->sws; struct svga_transfer *st = svga_transfer(transfer); if (st->base.usage & PIPE_TRANSFER_WRITE) { SVGA3dSurfaceDMAFlags flags; memset(&flags, 0, sizeof flags); if (transfer->usage & PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE) { flags.discard = TRUE; } if (transfer->usage & PIPE_TRANSFER_UNSYNCHRONIZED) { flags.unsynchronized = TRUE; } svga_transfer_dma(svga, st, SVGA3D_WRITE_HOST_VRAM, flags); ss->texture_timestamp++; tex->view_age[transfer->level] = ++(tex->age); if (transfer->resource->target == PIPE_TEXTURE_CUBE) tex->defined[transfer->box.z][transfer->level] = TRUE; else tex->defined[0][transfer->level] = TRUE; } pipe_resource_reference(&st->base.resource, NULL); FREE(st->swbuf); sws->buffer_destroy(sws, st->hwbuf); FREE(st); }
static void * svga_create_fs_state(struct pipe_context *pipe, const struct pipe_shader_state *templ) { struct svga_context *svga = svga_context(pipe); struct svga_fragment_shader *fs; fs = CALLOC_STRUCT(svga_fragment_shader); if (!fs) return NULL; fs->base.tokens = tgsi_dup_tokens(templ->tokens); /* Collect basic info that we'll need later: */ tgsi_scan_shader(fs->base.tokens, &fs->base.info); fs->base.id = svga->debug.shader_id++; fs->generic_inputs = svga_get_generic_inputs_mask(&fs->base.info); svga_remap_generics(fs->generic_inputs, fs->generic_remap_table); fs->draw_shader = draw_create_fragment_shader(svga->swtnl.draw, templ); if (SVGA_DEBUG & DEBUG_TGSI || 0) { debug_printf("%s id: %u, inputs: %u, outputs: %u\n", __FUNCTION__, fs->base.id, fs->base.info.num_inputs, fs->base.info.num_outputs); } return fs; }
static void svga_blit(struct pipe_context *pipe, const struct pipe_blit_info *blit_info) { struct svga_context *svga = svga_context(pipe); struct pipe_blit_info info = *blit_info; if (info.src.resource->nr_samples > 1 && info.dst.resource->nr_samples <= 1 && !util_format_is_depth_or_stencil(info.src.resource->format) && !util_format_is_pure_integer(info.src.resource->format)) { debug_printf("svga: color resolve unimplemented\n"); return; } if (util_try_blit_via_copy_region(pipe, &info)) { return; /* done */ } if (info.mask & PIPE_MASK_S) { debug_printf("svga: cannot blit stencil, skipping\n"); info.mask &= ~PIPE_MASK_S; } if (!util_blitter_is_blit_supported(svga->blitter, &info)) { debug_printf("svga: blit unsupported %s -> %s\n", util_format_short_name(info.src.resource->format), util_format_short_name(info.dst.resource->format)); return; } /* XXX turn off occlusion and streamout queries */ util_blitter_save_vertex_buffers(svga->blitter, svga->curr.num_vertex_buffers, svga->curr.vb); util_blitter_save_vertex_elements(svga->blitter, (void*)svga->curr.velems); util_blitter_save_vertex_shader(svga->blitter, svga->curr.vs); /*util_blitter_save_geometry_shader(svga->blitter, svga->curr.gs);*/ /*util_blitter_save_so_targets(svga->blitter, svga->num_so_targets, (struct pipe_stream_output_target**)svga->so_targets);*/ util_blitter_save_rasterizer(svga->blitter, (void*)svga->curr.rast); util_blitter_save_viewport(svga->blitter, &svga->curr.viewport); util_blitter_save_scissor(svga->blitter, &svga->curr.scissor); util_blitter_save_fragment_shader(svga->blitter, svga->curr.fs); util_blitter_save_blend(svga->blitter, (void*)svga->curr.blend); util_blitter_save_depth_stencil_alpha(svga->blitter, (void*)svga->curr.depth); util_blitter_save_stencil_ref(svga->blitter, &svga->curr.stencil_ref); /*util_blitter_save_sample_mask(svga->blitter, svga->sample_mask);*/ util_blitter_save_framebuffer(svga->blitter, &svga->curr.framebuffer); util_blitter_save_fragment_sampler_states(svga->blitter, svga->curr.num_samplers, (void**)svga->curr.sampler); util_blitter_save_fragment_sampler_views(svga->blitter, svga->curr.num_sampler_views, svga->curr.sampler_views); /*util_blitter_save_render_condition(svga->blitter, svga->render_cond_query, svga->render_cond_mode);*/ util_blitter_blit(svga->blitter, &info); }
static struct pipe_stream_output_target * svga_create_stream_output_target(struct pipe_context *pipe, struct pipe_resource *buffer, unsigned buffer_offset, unsigned buffer_size) { struct svga_context *svga = svga_context(pipe); struct svga_stream_output_target *sot; SVGA_DBG(DEBUG_STREAMOUT, "%s offset=%d size=%d\n", __FUNCTION__, buffer_offset, buffer_size); assert(svga_have_vgpu10(svga)); (void) svga; sot = CALLOC_STRUCT(svga_stream_output_target); if (!sot) return NULL; pipe_reference_init(&sot->base.reference, 1); pipe_resource_reference(&sot->base.buffer, buffer); sot->base.context = pipe; sot->base.buffer = buffer; sot->base.buffer_offset = buffer_offset; sot->base.buffer_size = buffer_size; return &sot->base; }
static void svga_delete_vs_state(struct pipe_context *pipe, void *shader) { struct svga_context *svga = svga_context(pipe); struct svga_vertex_shader *vs = (struct svga_vertex_shader *)shader; struct svga_shader_result *result, *tmp; enum pipe_error ret; svga_hwtnl_flush_retry( svga ); draw_delete_vertex_shader(svga->swtnl.draw, vs->draw_shader); for (result = vs->base.results; result; result = tmp ) { tmp = result->next; ret = SVGA3D_DestroyShader(svga->swc, result->id, SVGA3D_SHADERTYPE_VS ); if(ret != PIPE_OK) { svga_context_flush(svga, NULL); ret = SVGA3D_DestroyShader(svga->swc, result->id, SVGA3D_SHADERTYPE_VS ); assert(ret == PIPE_OK); } svga_destroy_shader_result( result ); } FREE((void *)vs->base.tokens); FREE(vs); }
static void svga_set_vertex_buffers(struct pipe_context *pipe, unsigned count, const struct pipe_vertex_buffer *buffers) { struct svga_context *svga = svga_context(pipe); unsigned i; boolean any_user_buffer = FALSE; /* Check for no change */ if (count == svga->curr.num_vertex_buffers && memcmp(svga->curr.vb, buffers, count * sizeof buffers[0]) == 0) return; /* Adjust refcounts */ for (i = 0; i < count; i++) { pipe_resource_reference(&svga->curr.vb[i].buffer, buffers[i].buffer); if (svga_buffer_is_user_buffer(buffers[i].buffer)) any_user_buffer = TRUE; } for ( ; i < svga->curr.num_vertex_buffers; i++) pipe_resource_reference(&svga->curr.vb[i].buffer, NULL); /* Copy remaining data */ memcpy(svga->curr.vb, buffers, count * sizeof buffers[0]); svga->curr.num_vertex_buffers = count; svga->curr.any_user_vertex_buffers = any_user_buffer; svga->dirty |= SVGA_NEW_VBUFFER; }
static void svga_end_query(struct pipe_context *pipe, struct pipe_query *q) { struct svga_context *svga = svga_context( pipe ); struct svga_query *sq = svga_query( q ); enum pipe_error ret; SVGA_DBG(DEBUG_QUERY, "%s\n", __FUNCTION__); assert(svga->sq == sq); svga_hwtnl_flush_retry(svga); /* Set to PENDING before sending EndQuery. */ sq->queryResult->state = SVGA3D_QUERYSTATE_PENDING; ret = SVGA3D_EndQuery( svga->swc, sq->type, sq->hwbuf); if(ret != PIPE_OK) { svga_context_flush(svga, NULL); ret = SVGA3D_EndQuery( svga->swc, sq->type, sq->hwbuf); assert(ret == PIPE_OK); } /* TODO: Delay flushing. We don't really need to flush here, just ensure * that there is one flush before svga_get_query_result attempts to get the * result */ svga_context_flush(svga, NULL); svga->sq = NULL; }
static void svga_bind_depth_stencil_state(struct pipe_context *pipe, void *depth_stencil) { struct svga_context *svga = svga_context(pipe); svga->curr.depth = (const struct svga_depth_stencil_state *)depth_stencil; svga->dirty |= SVGA_NEW_DEPTH_STENCIL; }
static void svga_set_scissor_state( struct pipe_context *pipe, const struct pipe_scissor_state *scissor ) { struct svga_context *svga = svga_context(pipe); memcpy( &svga->curr.scissor, scissor, sizeof(*scissor) ); svga->dirty |= SVGA_NEW_SCISSOR; }
static void svga_bind_blend_state(struct pipe_context *pipe, void *blend) { struct svga_context *svga = svga_context(pipe); svga->curr.blend = (struct svga_blend_state*)blend; svga->dirty |= SVGA_NEW_BLEND; }
static void svga_bind_vs_state(struct pipe_context *pipe, void *shader) { struct svga_vertex_shader *vs = (struct svga_vertex_shader *)shader; struct svga_context *svga = svga_context(pipe); svga->curr.vs = vs; svga->dirty |= SVGA_NEW_VS; }
static void svga_bind_gs_state(struct pipe_context *pipe, void *shader) { struct svga_geometry_shader *gs = (struct svga_geometry_shader *)shader; struct svga_context *svga = svga_context(pipe); svga->curr.user_gs = gs; svga->dirty |= SVGA_NEW_GS; }
static void svga_set_stencil_ref( struct pipe_context *pipe, const struct pipe_stencil_ref *stencil_ref ) { struct svga_context *svga = svga_context(pipe); svga->curr.stencil_ref = *stencil_ref; svga->dirty |= SVGA_NEW_STENCIL_REF; }
/** * svga_fence_server_sync * * This function imports a fence from another process/device into the current * software context so that SVGA can synchronize with it. */ static void svga_fence_server_sync(struct pipe_context *pipe, struct pipe_fence_handle *fence) { struct svga_winsys_screen *sws = svga_winsys_screen(pipe->screen); struct svga_context *svga = svga_context(pipe); sws->fence_server_sync(sws, &svga->swc->imported_fence_fd, fence); }
static void svga_bind_fs_state(struct pipe_context *pipe, void *shader) { struct svga_fragment_shader *fs = (struct svga_fragment_shader *) shader; struct svga_context *svga = svga_context(pipe); svga->curr.fs = fs; svga->dirty |= SVGA_NEW_FS; }
static void svga_set_clip_state( struct pipe_context *pipe, const struct pipe_clip_state *clip ) { struct svga_context *svga = svga_context(pipe); svga->curr.clip = *clip; /* struct copy */ svga->dirty |= SVGA_NEW_CLIP; }
static void svga_set_blend_color( struct pipe_context *pipe, const struct pipe_blend_color *blend_color ) { struct svga_context *svga = svga_context(pipe); svga->curr.blend_color = *blend_color; svga->dirty |= SVGA_NEW_BLEND; }
static void svga_bind_vertex_elements_state(struct pipe_context *pipe, void *velems) { struct svga_context *svga = svga_context(pipe); struct svga_velems_state *svga_velems = (struct svga_velems_state *) velems; svga->curr.velems = svga_velems; svga->dirty |= SVGA_NEW_VELEMENT; }