/** * Clear the given buffers to the specified values. * No masking, no scissor (clear entire buffer). */ void softpipe_clear(struct pipe_context *pipe, unsigned buffers, const union pipe_color_union *color, double depth, unsigned stencil) { struct softpipe_context *softpipe = softpipe_context(pipe); uint64_t cv; uint i; if (softpipe->no_rast) return; if (!softpipe_check_render_cond(softpipe)) return; #if 0 softpipe_update_derived(softpipe, PIPE_PRIM_TRIANGLES); /* not needed?? */ #endif if (buffers & PIPE_CLEAR_COLOR) { for (i = 0; i < softpipe->framebuffer.nr_cbufs; i++) { sp_tile_cache_clear(softpipe->cbuf_cache[i], color, 0); } } if (buffers & PIPE_CLEAR_DEPTHSTENCIL) { static const union pipe_color_union zero; struct pipe_surface *ps = softpipe->framebuffer.zsbuf; cv = util_pack64_z_stencil(ps->format, depth, stencil); sp_tile_cache_clear(softpipe->zsbuf_cache, &zero, cv); } softpipe->dirty_render_cache = TRUE; }
void softpipe_set_vertex_sampler_textures(struct pipe_context *pipe, unsigned num_textures, struct pipe_texture **textures) { struct softpipe_context *softpipe = softpipe_context(pipe); uint i; assert(num_textures <= PIPE_MAX_VERTEX_SAMPLERS); /* Check for no-op */ if (num_textures == softpipe->num_vertex_textures && !memcmp(softpipe->vertex_textures, textures, num_textures * sizeof(struct pipe_texture *))) { return; } draw_flush(softpipe->draw); for (i = 0; i < PIPE_MAX_VERTEX_SAMPLERS; i++) { struct pipe_texture *tex = i < num_textures ? textures[i] : NULL; pipe_texture_reference(&softpipe->vertex_textures[i], tex); sp_tex_tile_cache_set_texture(softpipe->vertex_tex_cache[i], tex); } softpipe->num_vertex_textures = num_textures; softpipe->dirty |= SP_NEW_TEXTURE; }
void softpipe_bind_vertex_sampler_states(struct pipe_context *pipe, unsigned num_samplers, void **samplers) { struct softpipe_context *softpipe = softpipe_context(pipe); unsigned i; assert(num_samplers <= PIPE_MAX_VERTEX_SAMPLERS); /* Check for no-op */ if (num_samplers == softpipe->num_vertex_samplers && !memcmp(softpipe->vertex_samplers, samplers, num_samplers * sizeof(void *))) return; draw_flush(softpipe->draw); for (i = 0; i < num_samplers; ++i) softpipe->vertex_samplers[i] = samplers[i]; for (i = num_samplers; i < PIPE_MAX_VERTEX_SAMPLERS; ++i) softpipe->vertex_samplers[i] = NULL; softpipe->num_vertex_samplers = num_samplers; softpipe->dirty |= SP_NEW_SAMPLER; }
static void softpipe_destroy( struct pipe_context *pipe ) { struct softpipe_context *softpipe = softpipe_context( pipe ); uint i, sh; #if DO_PSTIPPLE_IN_HELPER_MODULE if (softpipe->pstipple.sampler) pipe->delete_sampler_state(pipe, softpipe->pstipple.sampler); pipe_resource_reference(&softpipe->pstipple.texture, NULL); pipe_sampler_view_reference(&softpipe->pstipple.sampler_view, NULL); #endif if (softpipe->draw) draw_destroy( softpipe->draw ); if (softpipe->quad.shade) softpipe->quad.shade->destroy( softpipe->quad.shade ); if (softpipe->quad.depth_test) softpipe->quad.depth_test->destroy( softpipe->quad.depth_test ); if (softpipe->quad.blend) softpipe->quad.blend->destroy( softpipe->quad.blend ); if (softpipe->quad.pstipple) softpipe->quad.pstipple->destroy( softpipe->quad.pstipple ); for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) { sp_destroy_tile_cache(softpipe->cbuf_cache[i]); pipe_surface_reference(&softpipe->framebuffer.cbufs[i], NULL); } sp_destroy_tile_cache(softpipe->zsbuf_cache); pipe_surface_reference(&softpipe->framebuffer.zsbuf, NULL); for (sh = 0; sh < Elements(softpipe->tex_cache); sh++) { for (i = 0; i < Elements(softpipe->tex_cache[0]); i++) { sp_destroy_tex_tile_cache(softpipe->tex_cache[sh][i]); pipe_sampler_view_reference(&softpipe->sampler_views[sh][i], NULL); } } for (sh = 0; sh < Elements(softpipe->constants); sh++) { for (i = 0; i < Elements(softpipe->constants[0]); i++) { if (softpipe->constants[sh][i]) { pipe_resource_reference(&softpipe->constants[sh][i], NULL); } } } for (i = 0; i < softpipe->num_vertex_buffers; i++) { pipe_resource_reference(&softpipe->vertex_buffer[i].buffer, NULL); } tgsi_exec_machine_destroy(softpipe->fs_machine); FREE( softpipe ); }
static void softpipe_begin_query(struct pipe_context *pipe, struct pipe_query *q) { struct softpipe_context *softpipe = softpipe_context( pipe ); struct softpipe_query *sq = softpipe_query(q); switch (sq->type) { case PIPE_QUERY_OCCLUSION_COUNTER: sq->start = softpipe->occlusion_count; break; case PIPE_QUERY_TIMESTAMP_DISJOINT: case PIPE_QUERY_TIME_ELAPSED: sq->start = 1000*os_time_get(); break; case PIPE_QUERY_SO_STATISTICS: sq->so.primitives_storage_needed = 0; case PIPE_QUERY_PRIMITIVES_EMITTED: sq->so.num_primitives_written = 0; softpipe->so_stats.num_primitives_written = 0; break; case PIPE_QUERY_PRIMITIVES_GENERATED: sq->num_primitives_generated = 0; softpipe->num_primitives_generated = 0; break; case PIPE_QUERY_TIMESTAMP: case PIPE_QUERY_GPU_FINISHED: break; default: assert(0); break; } softpipe->active_query_count++; softpipe->dirty |= SP_NEW_QUERY; }
static void softpipe_end_query(struct pipe_context *pipe, struct pipe_query *q) { struct softpipe_context *softpipe = softpipe_context( pipe ); struct softpipe_query *sq = softpipe_query(q); sq->end = softpipe->occlusion_count; }
void softpipe_set_clip_state( struct pipe_context *pipe, const struct pipe_clip_state *clip ) { struct softpipe_context *softpipe = softpipe_context(pipe); /* pass the clip state to the draw module */ draw_set_clip_state(softpipe->draw, clip); }
void softpipe_set_sampler_views(struct pipe_context *pipe, unsigned shader, unsigned start, unsigned num, struct pipe_sampler_view **views) { struct softpipe_context *softpipe = softpipe_context(pipe); uint i; assert(shader < PIPE_SHADER_TYPES); assert(start + num <= ARRAY_SIZE(softpipe->sampler_views[shader])); draw_flush(softpipe->draw); /* set the new sampler views */ for (i = 0; i < num; i++) { struct sp_sampler_view *sp_sviewsrc; struct sp_sampler_view *sp_sviewdst = &softpipe->tgsi.sampler[shader]->sp_sview[start + i]; struct pipe_sampler_view **pview = &softpipe->sampler_views[shader][start + i]; pipe_sampler_view_reference(pview, views[i]); sp_tex_tile_cache_set_sampler_view(softpipe->tex_cache[shader][start + i], views[i]); /* * We don't really have variants, however some bits are different per shader, * so just copy? */ sp_sviewsrc = (struct sp_sampler_view *)*pview; if (sp_sviewsrc) { memcpy(sp_sviewdst, sp_sviewsrc, sizeof(*sp_sviewsrc)); sp_sviewdst->compute_lambda = softpipe_get_lambda_func(&sp_sviewdst->base, shader); sp_sviewdst->cache = softpipe->tex_cache[shader][start + i]; } else { memset(sp_sviewdst, 0, sizeof(*sp_sviewsrc)); } } /* find highest non-null sampler_views[] entry */ { unsigned j = MAX2(softpipe->num_sampler_views[shader], start + num); while (j > 0 && softpipe->sampler_views[shader][j - 1] == NULL) j--; softpipe->num_sampler_views[shader] = j; } if (shader == PIPE_SHADER_VERTEX || shader == PIPE_SHADER_GEOMETRY) { draw_set_sampler_views(softpipe->draw, shader, softpipe->sampler_views[shader], softpipe->num_sampler_views[shader]); } softpipe->dirty |= SP_NEW_TEXTURE; }
void softpipe_set_stencil_ref( struct pipe_context *pipe, const struct pipe_stencil_ref *stencil_ref ) { struct softpipe_context *softpipe = softpipe_context(pipe); softpipe->stencil_ref = *stencil_ref; softpipe->dirty |= SP_NEW_DEPTH_STENCIL_ALPHA; }
void softpipe_set_blend_color( struct pipe_context *pipe, const struct pipe_blend_color *blend_color ) { struct softpipe_context *softpipe = softpipe_context(pipe); softpipe->blend_color = *blend_color; softpipe->dirty |= SP_NEW_BLEND; }
void softpipe_bind_blend_state( struct pipe_context *pipe, void *blend ) { struct softpipe_context *softpipe = softpipe_context(pipe); softpipe->blend = (const struct pipe_blend_state *)blend; softpipe->dirty |= SP_NEW_BLEND; }
void softpipe_bind_depth_stencil_state(struct pipe_context *pipe, void *depth_stencil) { struct softpipe_context *softpipe = softpipe_context(pipe); softpipe->depth_stencil = (struct pipe_depth_stencil_alpha_state *)depth_stencil; softpipe->dirty |= SP_NEW_DEPTH_STENCIL_ALPHA; }
static void softpipe_render_condition( struct pipe_context *pipe, struct pipe_query *query, uint mode ) { struct softpipe_context *softpipe = softpipe_context( pipe ); softpipe->render_cond_query = query; softpipe->render_cond_mode = mode; }
void softpipe_set_polygon_stipple( struct pipe_context *pipe, const struct pipe_poly_stipple *stipple ) { struct softpipe_context *softpipe = softpipe_context(pipe); draw_flush(softpipe->draw); softpipe->poly_stipple = *stipple; /* struct copy */ softpipe->dirty |= SP_NEW_STIPPLE; }
void softpipe_set_scissor_state( struct pipe_context *pipe, const struct pipe_scissor_state *scissor ) { struct softpipe_context *softpipe = softpipe_context(pipe); draw_flush(softpipe->draw); softpipe->scissor = *scissor; /* struct copy */ softpipe->dirty |= SP_NEW_SCISSOR; }
/** * XXX this might get moved someday * Set the framebuffer surface info: color buffers, zbuffer, stencil buffer. * Here, we flush the old surfaces and update the tile cache to point to the new * surfaces. */ void softpipe_set_framebuffer_state(struct pipe_context *pipe, const struct pipe_framebuffer_state *fb) { struct softpipe_context *sp = softpipe_context(pipe); uint i; draw_flush(sp->draw); for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) { struct pipe_surface *cb = i < fb->nr_cbufs ? fb->cbufs[i] : NULL; /* check if changing cbuf */ if (sp->framebuffer.cbufs[i] != cb) { /* flush old */ sp_flush_tile_cache(sp->cbuf_cache[i]); /* assign new */ pipe_surface_reference(&sp->framebuffer.cbufs[i], cb); /* update cache */ sp_tile_cache_set_surface(sp->cbuf_cache[i], cb); } } sp->framebuffer.nr_cbufs = fb->nr_cbufs; /* zbuf changing? */ if (sp->framebuffer.zsbuf != fb->zsbuf) { /* flush old */ sp_flush_tile_cache(sp->zsbuf_cache); /* assign new */ pipe_surface_reference(&sp->framebuffer.zsbuf, fb->zsbuf); /* update cache */ sp_tile_cache_set_surface(sp->zsbuf_cache, fb->zsbuf); /* Tell draw module how deep the Z/depth buffer is * * If no depth buffer is bound, send the utility function the * format for no bound depth (PIPE_FORMAT_NONE). */ draw_set_zs_format(sp->draw, (sp->framebuffer.zsbuf) ? sp->framebuffer.zsbuf->format : PIPE_FORMAT_NONE); } sp->framebuffer.width = fb->width; sp->framebuffer.height = fb->height; sp->framebuffer.samples = fb->samples; sp->framebuffer.layers = fb->layers; sp->dirty |= SP_NEW_FRAMEBUFFER; }
void softpipe_set_viewport_state( struct pipe_context *pipe, const struct pipe_viewport_state *viewport ) { struct softpipe_context *softpipe = softpipe_context(pipe); /* pass the viewport info to the draw module */ draw_set_viewport_state(softpipe->draw, viewport); softpipe->viewport = *viewport; /* struct copy */ softpipe->dirty |= SP_NEW_VIEWPORT; }
static void softpipe_set_index_buffer(struct pipe_context *pipe, const struct pipe_index_buffer *ib) { struct softpipe_context *softpipe = softpipe_context(pipe); if (ib) memcpy(&softpipe->index_buffer, ib, sizeof(softpipe->index_buffer)); else memset(&softpipe->index_buffer, 0, sizeof(softpipe->index_buffer)); }
static void sp_blit(struct pipe_context *pipe, const struct pipe_blit_info *info) { struct softpipe_context *sp = softpipe_context(pipe); if (info->render_condition_enable && !softpipe_check_render_cond(sp)) return; 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("softpipe: color resolve unimplemented\n"); return; } if (util_try_blit_via_copy_region(pipe, info)) { return; /* done */ } if (!util_blitter_is_blit_supported(sp->blitter, info)) { debug_printf("softpipe: 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_buffer_slot(sp->blitter, sp->vertex_buffer); util_blitter_save_vertex_elements(sp->blitter, sp->velems); util_blitter_save_vertex_shader(sp->blitter, sp->vs); util_blitter_save_geometry_shader(sp->blitter, sp->gs); util_blitter_save_so_targets(sp->blitter, sp->num_so_targets, (struct pipe_stream_output_target**)sp->so_targets); util_blitter_save_rasterizer(sp->blitter, sp->rasterizer); util_blitter_save_viewport(sp->blitter, &sp->viewports[0]); util_blitter_save_scissor(sp->blitter, &sp->scissors[0]); util_blitter_save_fragment_shader(sp->blitter, sp->fs); util_blitter_save_blend(sp->blitter, sp->blend); util_blitter_save_depth_stencil_alpha(sp->blitter, sp->depth_stencil); util_blitter_save_stencil_ref(sp->blitter, &sp->stencil_ref); /*util_blitter_save_sample_mask(sp->blitter, sp->sample_mask);*/ util_blitter_save_framebuffer(sp->blitter, &sp->framebuffer); util_blitter_save_fragment_sampler_states(sp->blitter, sp->num_samplers[PIPE_SHADER_FRAGMENT], (void**)sp->samplers[PIPE_SHADER_FRAGMENT]); util_blitter_save_fragment_sampler_views(sp->blitter, sp->num_sampler_views[PIPE_SHADER_FRAGMENT], sp->sampler_views[PIPE_SHADER_FRAGMENT]); util_blitter_save_render_condition(sp->blitter, sp->render_cond_query, sp->render_cond_cond, sp->render_cond_mode); util_blitter_blit(sp->blitter, info); }
void softpipe_bind_rasterizer_state(struct pipe_context *pipe, void *setup) { struct softpipe_context *softpipe = softpipe_context(pipe); /* pass-through to draw module */ draw_set_rasterizer_state(softpipe->draw, setup); softpipe->rasterizer = (struct pipe_rasterizer_state *)setup; softpipe->dirty |= SP_NEW_RASTERIZER; }
static void softpipe_bind_blend_state(struct pipe_context *pipe, void *blend) { struct softpipe_context *softpipe = softpipe_context(pipe); draw_flush(softpipe->draw); softpipe->blend = (struct pipe_blend_state *)blend; softpipe->dirty |= SP_NEW_BLEND; }
void softpipe_flush( struct pipe_context *pipe, unsigned flags, struct pipe_fence_handle **fence ) { struct softpipe_context *softpipe = softpipe_context(pipe); uint i; draw_flush(softpipe->draw); if (flags & SP_FLUSH_TEXTURE_CACHE) { unsigned sh; for (sh = 0; sh < Elements(softpipe->tex_cache); sh++) { for (i = 0; i < softpipe->num_sampler_views[sh]; i++) { sp_flush_tex_tile_cache(softpipe->tex_cache[sh][i]); } } } /* If this is a swapbuffers, just flush color buffers. * * The zbuffer changes are not discarded, but held in the cache * in the hope that a later clear will wipe them out. */ for (i = 0; i < softpipe->framebuffer.nr_cbufs; i++) if (softpipe->cbuf_cache[i]) sp_flush_tile_cache(softpipe->cbuf_cache[i]); if (softpipe->zsbuf_cache) sp_flush_tile_cache(softpipe->zsbuf_cache); softpipe->dirty_render_cache = FALSE; /* Enable to dump BMPs of the color/depth buffers each frame */ #if 0 if (flags & PIPE_FLUSH_END_OF_FRAME) { static unsigned frame_no = 1; static char filename[256]; util_snprintf(filename, sizeof(filename), "cbuf_%u.bmp", frame_no); debug_dump_surface_bmp(pipe, filename, softpipe->framebuffer.cbufs[0]); util_snprintf(filename, sizeof(filename), "zsbuf_%u.bmp", frame_no); debug_dump_surface_bmp(pipe, filename, softpipe->framebuffer.zsbuf); ++frame_no; } #endif if (fence) *fence = (void*)(intptr_t)1; }
static void softpipe_bind_vertex_elements_state(struct pipe_context *pipe, void *velems) { struct softpipe_context *softpipe = softpipe_context(pipe); struct sp_velems_state *sp_velems = (struct sp_velems_state *) velems; softpipe->velems = sp_velems; softpipe->dirty |= SP_NEW_VERTEX; if (sp_velems) draw_set_vertex_elements(softpipe->draw, sp_velems->count, sp_velems->velem); }
static boolean softpipe_begin_query(struct pipe_context *pipe, struct pipe_query *q) { struct softpipe_context *softpipe = softpipe_context( pipe ); struct softpipe_query *sq = softpipe_query(q); switch (sq->type) { case PIPE_QUERY_OCCLUSION_COUNTER: case PIPE_QUERY_OCCLUSION_PREDICATE: sq->start = softpipe->occlusion_count; break; case PIPE_QUERY_TIME_ELAPSED: sq->start = os_time_get_nano(); break; case PIPE_QUERY_SO_STATISTICS: sq->so.num_primitives_written = softpipe->so_stats.num_primitives_written; sq->so.primitives_storage_needed = softpipe->so_stats.primitives_storage_needed; break; case PIPE_QUERY_SO_OVERFLOW_PREDICATE: sq->end = FALSE; break; case PIPE_QUERY_PRIMITIVES_EMITTED: sq->so.num_primitives_written = softpipe->so_stats.num_primitives_written; break; case PIPE_QUERY_PRIMITIVES_GENERATED: sq->so.primitives_storage_needed = softpipe->so_stats.primitives_storage_needed; break; case PIPE_QUERY_TIMESTAMP: case PIPE_QUERY_GPU_FINISHED: case PIPE_QUERY_TIMESTAMP_DISJOINT: break; case PIPE_QUERY_PIPELINE_STATISTICS: /* reset our cache */ if (softpipe->active_statistics_queries == 0) { memset(&softpipe->pipeline_statistics, 0, sizeof(softpipe->pipeline_statistics)); } memcpy(&sq->stats, &softpipe->pipeline_statistics, sizeof(sq->stats)); softpipe->active_statistics_queries++; break; default: assert(0); break; } softpipe->active_query_count++; softpipe->dirty |= SP_NEW_QUERY; return true; }
void softpipe_bind_rasterizer_state(struct pipe_context *pipe, void *rasterizer) { struct softpipe_context *softpipe = softpipe_context(pipe); if (softpipe->rasterizer == rasterizer) return; /* pass-through to draw module */ draw_set_rasterizer_state(softpipe->draw, rasterizer); softpipe->rasterizer = rasterizer; softpipe->dirty |= SP_NEW_RASTERIZER; }
static void softpipe_clear_render_target(struct pipe_context *pipe, struct pipe_surface *dst, const union pipe_color_union *color, unsigned dstx, unsigned dsty, unsigned width, unsigned height) { struct softpipe_context *softpipe = softpipe_context(pipe); if (!softpipe_check_render_cond(softpipe)) return; util_clear_render_target(pipe, dst, color, dstx, dsty, width, height); }
static void softpipe_set_viewport_states(struct pipe_context *pipe, unsigned start_slot, unsigned num_viewports, const struct pipe_viewport_state *viewports) { struct softpipe_context *softpipe = softpipe_context(pipe); /* pass the viewport info to the draw module */ draw_set_viewport_states(softpipe->draw, start_slot, num_viewports, viewports); memcpy(softpipe->viewports + start_slot, viewports, sizeof(struct pipe_viewport_state) * num_viewports); softpipe->dirty |= SP_NEW_VIEWPORT; }
void softpipe_set_vertex_buffers(struct pipe_context *pipe, unsigned count, const struct pipe_vertex_buffer *buffers) { struct softpipe_context *softpipe = softpipe_context(pipe); assert(count <= PIPE_MAX_ATTRIBS); memcpy(softpipe->vertex_buffer, buffers, count * sizeof(buffers[0])); softpipe->num_vertex_buffers = count; softpipe->dirty |= SP_NEW_VERTEX; draw_set_vertex_buffers(softpipe->draw, count, buffers); }
static void softpipe_set_sampler_views(struct pipe_context *pipe, unsigned shader, unsigned start, unsigned num, struct pipe_sampler_view **views) { struct softpipe_context *softpipe = softpipe_context(pipe); uint i; assert(shader < PIPE_SHADER_TYPES); assert(start + num <= Elements(softpipe->sampler_views[shader])); /* Check for no-op */ if (start + num <= softpipe->num_sampler_views[shader] && !memcmp(softpipe->sampler_views[shader] + start, views, num * sizeof(struct pipe_sampler_view *))) { return; } draw_flush(softpipe->draw); /* set the new sampler views */ for (i = 0; i < num; i++) { pipe_sampler_view_reference(&softpipe->sampler_views[shader][start + i], views[i]); sp_tex_tile_cache_set_sampler_view(softpipe->tex_cache[shader][start + i], views[i]); } /* find highest non-null sampler_views[] entry */ { unsigned j = MAX2(softpipe->num_sampler_views[shader], start + num); while (j > 0 && softpipe->sampler_views[shader][j - 1] == NULL) j--; softpipe->num_sampler_views[shader] = j; } if (shader == PIPE_SHADER_VERTEX || shader == PIPE_SHADER_GEOMETRY) { draw_set_sampler_views(softpipe->draw, shader, softpipe->sampler_views[shader], softpipe->num_sampler_views[shader]); } softpipe->dirty |= SP_NEW_TEXTURE; }
static void softpipe_set_vertex_buffers(struct pipe_context *pipe, unsigned count, const struct pipe_vertex_buffer *buffers) { struct softpipe_context *softpipe = softpipe_context(pipe); assert(count <= PIPE_MAX_ATTRIBS); util_copy_vertex_buffers(softpipe->vertex_buffer, &softpipe->num_vertex_buffers, buffers, count); softpipe->dirty |= SP_NEW_VERTEX; draw_set_vertex_buffers(softpipe->draw, count, buffers); }