static void cell_set_framebuffer_state(struct pipe_context *pipe, const struct pipe_framebuffer_state *fb) { struct cell_context *cell = cell_context(pipe); if (1 /*memcmp(&cell->framebuffer, fb, sizeof(*fb))*/) { uint i; /* unmap old surfaces */ cell_unmap_surfaces(cell); /* Finish any pending rendering to the current surface before * installing a new surface! */ cell_flush_int(cell, CELL_FLUSH_WAIT); /* update my state * (this is also where old surfaces will finally get freed) */ cell->framebuffer.width = fb->width; cell->framebuffer.height = fb->height; cell->framebuffer.nr_cbufs = fb->nr_cbufs; for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) { pipe_surface_reference(&cell->framebuffer.cbufs[i], fb->cbufs[i]); } pipe_surface_reference(&cell->framebuffer.zsbuf, fb->zsbuf); /* map new surfaces */ cell_map_surfaces(cell); cell->dirty |= CELL_NEW_FRAMEBUFFER; } }
/** * Create vertex shader state. * Called via pipe->create_vs_state() */ static void * cell_create_vs_state(struct pipe_context *pipe, const struct pipe_shader_state *templ) { struct cell_context *cell = cell_context(pipe); struct cell_vertex_shader_state *cvs; cvs = CALLOC_STRUCT(cell_vertex_shader_state); if (!cvs) return NULL; cvs->shader.tokens = tgsi_dup_tokens(templ->tokens); if (!cvs->shader.tokens) { FREE(cvs); return NULL; } tgsi_scan_shader(templ->tokens, &cvs->info); cvs->draw_data = draw_create_vertex_shader(cell->draw, &cvs->shader); if (cvs->draw_data == NULL) { FREE( (void *) cvs->shader.tokens ); FREE( cvs ); return NULL; } return cvs; }
static void cell_set_sampler_textures(struct pipe_context *pipe, unsigned num, struct pipe_texture **texture) { struct cell_context *cell = cell_context(pipe); uint i, changed = 0x0; assert(num <= CELL_MAX_SAMPLERS); for (i = 0; i < CELL_MAX_SAMPLERS; i++) { struct cell_texture *new_tex = cell_texture(i < num ? texture[i] : NULL); struct cell_texture *old_tex = cell->texture[i]; if (old_tex != new_tex) { pipe_texture_reference((struct pipe_texture **) &cell->texture[i], (struct pipe_texture *) new_tex); changed |= (1 << i); } } cell->num_textures = num; if (changed) { cell->dirty |= CELL_NEW_TEXTURE; cell->dirty_textures |= changed; } }
static void cell_set_polygon_stipple( struct pipe_context *pipe, const struct pipe_poly_stipple *stipple ) { struct cell_context *cell = cell_context(pipe); memcpy( &cell->poly_stipple, stipple, sizeof(*stipple) ); cell->dirty |= CELL_NEW_STIPPLE; }
static void cell_set_scissor_state( struct pipe_context *pipe, const struct pipe_scissor_state *scissor ) { struct cell_context *cell = cell_context(pipe); memcpy( &cell->scissor, scissor, sizeof(*scissor) ); cell->dirty |= CELL_NEW_SCISSOR; }
static void cell_set_clip_state(struct pipe_context *pipe, const struct pipe_clip_state *clip) { struct cell_context *cell = cell_context(pipe); /* pass the clip state to the draw module */ draw_set_clip_state(cell->draw, clip); }
/** * Called via pipe->bind_fs_state() */ static void cell_bind_fs_state(struct pipe_context *pipe, void *fs) { struct cell_context *cell = cell_context(pipe); cell->fs = cell_fragment_shader_state(fs); cell->dirty |= CELL_NEW_FS; }
/** * Called via pipe->delete_vs_state() */ static void cell_delete_vs_state(struct pipe_context *pipe, void *vs) { struct cell_context *cell = cell_context(pipe); struct cell_vertex_shader_state *cvs = cell_vertex_shader_state(vs); draw_delete_vertex_shader(cell->draw, cvs->draw_data); FREE( (void *) cvs->shader.tokens ); FREE( cvs ); }
static void cell_bind_blend_state(struct pipe_context *pipe, void *blend) { struct cell_context *cell = cell_context(pipe); draw_flush(cell->draw); cell->blend = (struct pipe_blend_state *) blend; cell->dirty |= CELL_NEW_BLEND; }
static void cell_bind_depth_stencil_alpha_state(struct pipe_context *pipe, void *dsa) { struct cell_context *cell = cell_context(pipe); draw_flush(cell->draw); cell->depth_stencil = (struct pipe_depth_stencil_alpha_state *) dsa; cell->dirty |= CELL_NEW_DEPTH_STENCIL; }
static void cell_set_blend_color(struct pipe_context *pipe, const struct pipe_blend_color *blend_color) { struct cell_context *cell = cell_context(pipe); draw_flush(cell->draw); cell->blend_color = *blend_color; cell->dirty |= CELL_NEW_BLEND; }
/** * Called via pipe->bind_vs_state() */ static void cell_bind_vs_state(struct pipe_context *pipe, void *vs) { struct cell_context *cell = cell_context(pipe); cell->vs = cell_vertex_shader_state(vs); draw_bind_vertex_shader(cell->draw, (cell->vs ? cell->vs->draw_data : NULL)); cell->dirty |= CELL_NEW_VS; }
static void cell_bind_rasterizer_state(struct pipe_context *pipe, void *rast) { struct pipe_rasterizer_state *rasterizer = (struct pipe_rasterizer_state *) rast; struct cell_context *cell = cell_context(pipe); /* pass-through to draw module */ draw_set_rasterizer_state(cell->draw, rasterizer); cell->rasterizer = rasterizer; cell->dirty |= CELL_NEW_RASTERIZER; }
/** * Called via pipe->flush() */ void cell_flush(struct pipe_context *pipe, struct pipe_fence_handle **fence) { struct cell_context *cell = cell_context(pipe); if (fence) { *fence = NULL; } flags |= CELL_FLUSH_WAIT; draw_flush( cell->draw ); cell_flush_int(cell, flags); }
/** * Draw vertex arrays, with optional indexing. * Basically, map the vertex buffers (and drawing surfaces), then hand off * the drawing to the 'draw' module. * * XXX should the element buffer be specified/bound with a separate function? */ static void cell_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info) { struct cell_context *cell = cell_context(pipe); struct draw_context *draw = cell->draw; void *mapped_indices = NULL; unsigned i; if (cell->dirty) cell_update_derived( cell ); #if 0 cell_map_surfaces(cell); #endif /* * Map vertex buffers */ for (i = 0; i < cell->num_vertex_buffers; i++) { void *buf = cell_resource(cell->vertex_buffer[i].buffer)->data; draw_set_mapped_vertex_buffer(draw, i, buf); } /* Map index buffer, if present */ if (info->indexed && cell->index_buffer.buffer) mapped_indices = cell_resource(cell->index_buffer.buffer)->data; draw_set_mapped_index_buffer(draw, mapped_indices); /* draw! */ draw_vbo(draw, info); /* * unmap vertex/index buffers - will cause draw module to flush */ for (i = 0; i < cell->num_vertex_buffers; i++) { draw_set_mapped_vertex_buffer(draw, i, NULL); } if (mapped_indices) { draw_set_mapped_index_buffer(draw, NULL); } /* * TODO: Flush only when a user vertex/index buffer is present * (or even better, modify draw module to do this * internally when this condition is seen?) */ draw_flush(draw); }
/* Called when driver state tracker notices changes to the viewport * matrix: */ static void cell_set_viewport_state( struct pipe_context *pipe, const struct pipe_viewport_state *viewport ) { struct cell_context *cell = cell_context(pipe); cell->viewport = *viewport; /* struct copy */ cell->dirty |= CELL_NEW_VIEWPORT; /* pass the viewport info to the draw module */ draw_set_viewport_state(cell->draw, viewport); /* Using tnl/ and vf/ modules is temporary while getting started. * Full pipe will have vertex shader, vertex fetch of its own. */ }
static void cell_set_vertex_buffers(struct pipe_context *pipe, unsigned count, const struct pipe_vertex_buffer *buffers) { struct cell_context *cell = cell_context(pipe); assert(count <= PIPE_MAX_ATTRIBS); memcpy(cell->vertex_buffer, buffers, count * sizeof(buffers[0])); cell->num_vertex_buffers = count; cell->dirty |= CELL_NEW_VERTEX; draw_set_vertex_buffers(cell->draw, count, buffers); }
static void cell_destroy_context( struct pipe_context *pipe ) { struct cell_context *cell = cell_context(pipe); unsigned i; for (i = 0; i < cell->num_vertex_buffers; i++) { pipe_resource_reference(&cell->vertex_buffer[i].buffer, NULL); } util_delete_keymap(cell->fragment_ops_cache, NULL); cell_spu_exit(cell); align_free(cell); }
/** * Called via pipe->set_constant_buffer() */ static void cell_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index, const struct pipe_constant_buffer *buf) { struct cell_context *cell = cell_context(pipe); assert(shader < PIPE_SHADER_TYPES); assert(index == 0); draw_flush(cell->draw); /* note: reference counting */ pipe_buffer_reference(&cell->constants[shader].buffer, buf->buffer); if (shader == PIPE_SHADER_VERTEX) cell->dirty |= CELL_NEW_VS_CONSTANTS; else if (shader == PIPE_SHADER_FRAGMENT) cell->dirty |= CELL_NEW_FS_CONSTANTS; }
/** * Create fragment shader state. * Called via pipe->create_fs_state() */ static void * cell_create_fs_state(struct pipe_context *pipe, const struct pipe_shader_state *templ) { struct cell_context *cell = cell_context(pipe); struct cell_fragment_shader_state *cfs; cfs = CALLOC_STRUCT(cell_fragment_shader_state); if (!cfs) return NULL; cfs->shader.tokens = tgsi_dup_tokens(templ->tokens); if (!cfs->shader.tokens) { FREE(cfs); return NULL; } tgsi_scan_shader(templ->tokens, &cfs->info); cell_gen_fragment_program(cell, cfs->shader.tokens, &cfs->code); return cfs; }
static void cell_bind_sampler_states(struct pipe_context *pipe, unsigned num, void **samplers) { struct cell_context *cell = cell_context(pipe); uint i, changed = 0x0; assert(num <= CELL_MAX_SAMPLERS); draw_flush(cell->draw); for (i = 0; i < CELL_MAX_SAMPLERS; i++) { struct pipe_sampler_state *new_samp = i < num ? samplers[i] : NULL; if (cell->sampler[i] != new_samp) { cell->sampler[i] = new_samp; changed |= (1 << i); } } if (changed) { cell->dirty |= CELL_NEW_SAMPLER; cell->dirty_samplers |= changed; } }
static void cell_set_edgeflags(struct pipe_context *pipe, const unsigned *edgeflags) { struct cell_context *cell = cell_context(pipe); draw_set_edgeflags(cell->draw, edgeflags); }
/** * Draw vertex arrays, with optional indexing. * Basically, map the vertex buffers (and drawing surfaces), then hand off * the drawing to the 'draw' module. * * XXX should the element buffer be specified/bound with a separate function? */ static boolean cell_draw_range_elements(struct pipe_context *pipe, struct pipe_buffer *indexBuffer, unsigned indexSize, unsigned min_index, unsigned max_index, unsigned mode, unsigned start, unsigned count) { struct cell_context *sp = cell_context(pipe); struct draw_context *draw = sp->draw; unsigned i; if (sp->dirty) cell_update_derived( sp ); #if 0 cell_map_surfaces(sp); #endif cell_map_constant_buffers(sp); /* * Map vertex buffers */ for (i = 0; i < sp->num_vertex_buffers; i++) { void *buf = pipe_buffer_map(pipe->screen, sp->vertex_buffer[i].buffer, PIPE_BUFFER_USAGE_CPU_READ); cell_flush_buffer_range(sp, buf, sp->vertex_buffer[i].buffer->size); draw_set_mapped_vertex_buffer(draw, i, buf); } /* Map index buffer, if present */ if (indexBuffer) { void *mapped_indexes = pipe_buffer_map(pipe->screen, indexBuffer, PIPE_BUFFER_USAGE_CPU_READ); draw_set_mapped_element_buffer(draw, indexSize, mapped_indexes); } else { /* no index/element buffer */ draw_set_mapped_element_buffer(draw, 0, NULL); } /* draw! */ draw_arrays(draw, mode, start, count); /* * unmap vertex/index buffers - will cause draw module to flush */ for (i = 0; i < sp->num_vertex_buffers; i++) { draw_set_mapped_vertex_buffer(draw, i, NULL); pipe_buffer_unmap(pipe->screen, sp->vertex_buffer[i].buffer); } if (indexBuffer) { draw_set_mapped_element_buffer(draw, 0, NULL); pipe_buffer_unmap(pipe->screen, indexBuffer); } /* Note: leave drawing surfaces mapped */ cell_unmap_constant_buffers(sp); return TRUE; }