Go to the source code of this file.
Functions | |
void | cmd_render (const struct cell_command_render *render, uint *pos_incr) |
Render primitives. |
void cmd_render | ( | const struct cell_command_render * | render, | |
uint * | pos_incr | |||
) |
Render primitives.
pos_incr | returns value indicating how may words to skip after this command in the batch buffer |
find tiles which intersect the prim bounding box
loop over tiles, rendering tris
Definition at line 168 of file spu_render.c.
References ALIGN16_ATTRIB, align_pointer(), ASSERT, ASSERT_ALIGN16, cell_init_info::buffers, CELL_BUFFER_SIZE, spu_global::cur_ctile_status, spu_global::cur_ztile_status, Debug, spu_global::fb, get_cz_tiles(), spu_framebuffer::height_tiles, cell_init_info::id, spu_global::init, cell_command_render::inline_verts, cell_command_render::min_index, my_tile(), cell_command_render::num_indexes, cell_command_render::num_verts, PIPE_PRIM_TRIANGLES, cell_command_render::prim_type, put_cz_tiles(), ROUNDUP8, spu, TAG_SURFACE_CLEAR, TAG_VERTEX_BUFFER, tile_bounding_box(), tri_draw(), cell_command_render::vertex_buf, cell_command_render::vertex_size, wait_on_mask(), wait_put_cz_tiles(), and spu_framebuffer::width_tiles.
00169 { 00170 /* we'll DMA into these buffers */ 00171 ubyte vertex_data[CELL_BUFFER_SIZE] ALIGN16_ATTRIB; 00172 const uint vertex_size = render->vertex_size; /* in bytes */ 00173 /*const*/ uint total_vertex_bytes = render->num_verts * vertex_size; 00174 uint index_bytes; 00175 const ubyte *vertices; 00176 const ushort *indexes; 00177 uint i, j; 00178 00179 00180 if (Debug) { 00181 printf("SPU %u: RENDER prim %u, num_vert=%u num_ind=%u " 00182 "inline_vert=%u\n", 00183 spu.init.id, 00184 render->prim_type, 00185 render->num_verts, 00186 render->num_indexes, 00187 render->inline_verts); 00188 00189 /* 00190 printf(" bound: %g, %g .. %g, %g\n", 00191 render->xmin, render->ymin, render->xmax, render->ymax); 00192 */ 00193 } 00194 00195 ASSERT(sizeof(*render) % 4 == 0); 00196 ASSERT(total_vertex_bytes % 16 == 0); 00197 ASSERT(render->prim_type == PIPE_PRIM_TRIANGLES); 00198 ASSERT(render->num_indexes % 3 == 0); 00199 00200 00201 /* indexes are right after the render command in the batch buffer */ 00202 indexes = (const ushort *) (render + 1); 00203 index_bytes = ROUNDUP8(render->num_indexes * 2); 00204 *pos_incr = index_bytes / 8 + sizeof(*render) / 8; 00205 00206 00207 if (render->inline_verts) { 00208 /* Vertices are after indexes in batch buffer at next 16-byte addr */ 00209 vertices = (const ubyte *) render + (*pos_incr * 8); 00210 vertices = (const ubyte *) align_pointer((void *) vertices, 16); 00211 ASSERT_ALIGN16(vertices); 00212 *pos_incr = ((vertices + total_vertex_bytes) - (ubyte *) render) / 8; 00213 } 00214 else { 00215 /* Begin DMA fetch of vertex buffer */ 00216 ubyte *src = spu.init.buffers[render->vertex_buf]; 00217 ubyte *dest = vertex_data; 00218 00219 /* skip vertex data we won't use */ 00220 #if 01 00221 src += render->min_index * vertex_size; 00222 dest += render->min_index * vertex_size; 00223 total_vertex_bytes -= render->min_index * vertex_size; 00224 #endif 00225 ASSERT(total_vertex_bytes % 16 == 0); 00226 ASSERT_ALIGN16(dest); 00227 ASSERT_ALIGN16(src); 00228 00229 mfc_get(dest, /* in vertex_data[] array */ 00230 (unsigned int) src, /* src in main memory */ 00231 total_vertex_bytes, /* size */ 00232 TAG_VERTEX_BUFFER, 00233 0, /* tid */ 00234 0 /* rid */); 00235 00236 vertices = vertex_data; 00237 00238 wait_on_mask(1 << TAG_VERTEX_BUFFER); 00239 } 00240 00241 00245 uint txmin, tymin, box_width_tiles, box_num_tiles; 00246 tile_bounding_box(render, &txmin, &tymin, 00247 &box_num_tiles, &box_width_tiles); 00248 00249 00250 /* make sure any pending clears have completed */ 00251 wait_on_mask(1 << TAG_SURFACE_CLEAR); /* XXX temporary */ 00252 00253 00257 for (i = 0; i < box_num_tiles; i++) { 00258 const uint tx = txmin + i % box_width_tiles; 00259 const uint ty = tymin + i / box_width_tiles; 00260 00261 ASSERT(tx < spu.fb.width_tiles); 00262 ASSERT(ty < spu.fb.height_tiles); 00263 00264 if (!my_tile(tx, ty)) 00265 continue; 00266 00267 spu.cur_ctile_status = spu.ctile_status[ty][tx]; 00268 spu.cur_ztile_status = spu.ztile_status[ty][tx]; 00269 00270 get_cz_tiles(tx, ty); 00271 00272 uint drawn = 0; 00273 00274 /* loop over tris */ 00275 for (j = 0; j < render->num_indexes; j += 3) { 00276 const float *v0, *v1, *v2; 00277 00278 v0 = (const float *) (vertices + indexes[j+0] * vertex_size); 00279 v1 = (const float *) (vertices + indexes[j+1] * vertex_size); 00280 v2 = (const float *) (vertices + indexes[j+2] * vertex_size); 00281 00282 drawn += tri_draw(v0, v1, v2, tx, ty); 00283 } 00284 00285 //printf("SPU %u: drew %u of %u\n", spu.init.id, drawn, render->num_indexes/3); 00286 00287 /* write color/z tiles back to main framebuffer, if dirtied */ 00288 put_cz_tiles(tx, ty); 00289 00290 wait_put_cz_tiles(); /* XXX seems unnecessary... */ 00291 00292 spu.ctile_status[ty][tx] = spu.cur_ctile_status; 00293 spu.ztile_status[ty][tx] = spu.cur_ztile_status; 00294 } 00295 00296 if (Debug) 00297 printf("SPU %u: RENDER done\n", 00298 spu.init.id); 00299 }