00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #include <stdio.h>
00030 #include <libmisc.h>
00031 #include <spu_mfcio.h>
00032
00033 #include "spu_main.h"
00034 #include "spu_render.h"
00035 #include "spu_tri.h"
00036 #include "spu_tile.h"
00037 #include "cell/common.h"
00038 #include "util/u_memory.h"
00039
00040
00045 static INLINE void
00046 tile_bounding_box(const struct cell_command_render *render,
00047 uint *txmin, uint *tymin,
00048 uint *box_num_tiles, uint *box_width_tiles)
00049 {
00050 #if 0
00051
00052 uint txmax = spu.fb.width_tiles - 1;
00053 uint tymax = spu.fb.height_tiles - 1;
00054 *txmin = 0;
00055 *tymin = 0;
00056 *box_num_tiles = spu.fb.width_tiles * spu.fb.height_tiles;
00057 *box_width_tiles = spu.fb.width_tiles;
00058 (void) render;
00059 (void) txmax;
00060 (void) tymax;
00061 #else
00062 uint txmax, tymax, box_height_tiles;
00063
00064 *txmin = (uint) render->xmin / TILE_SIZE;
00065 *tymin = (uint) render->ymin / TILE_SIZE;
00066 txmax = (uint) render->xmax / TILE_SIZE;
00067 tymax = (uint) render->ymax / TILE_SIZE;
00068 if (txmax >= spu.fb.width_tiles)
00069 txmax = spu.fb.width_tiles-1;
00070 if (tymax >= spu.fb.height_tiles)
00071 tymax = spu.fb.height_tiles-1;
00072 *box_width_tiles = txmax - *txmin + 1;
00073 box_height_tiles = tymax - *tymin + 1;
00074 *box_num_tiles = *box_width_tiles * box_height_tiles;
00075 #endif
00076 #if 0
00077 printf("SPU %u: bounds: %g, %g ... %g, %g\n", spu.init.id,
00078 render->xmin, render->ymin, render->xmax, render->ymax);
00079 printf("SPU %u: tiles: %u, %u .. %u, %u\n",
00080 spu.init.id, *txmin, *tymin, txmax, tymax);
00081 ASSERT(render->xmin <= render->xmax);
00082 ASSERT(render->ymin <= render->ymax);
00083 #endif
00084 }
00085
00086
00088 static INLINE boolean
00089 my_tile(uint tx, uint ty)
00090 {
00091 return (spu.fb.width_tiles * ty + tx) % spu.init.num_spus == spu.init.id;
00092 }
00093
00094
00098 static INLINE void
00099 get_cz_tiles(uint tx, uint ty)
00100 {
00101 if (spu.read_depth) {
00102 if (spu.cur_ztile_status != TILE_STATUS_CLEAR) {
00103
00104 get_tile(tx, ty, &spu.ztile, TAG_READ_TILE_Z, 1);
00105 spu.cur_ztile_status = TILE_STATUS_GETTING;
00106 }
00107 }
00108
00109 if (spu.cur_ctile_status != TILE_STATUS_CLEAR) {
00110
00111 get_tile(tx, ty, &spu.ctile, TAG_READ_TILE_COLOR, 0);
00112 spu.cur_ctile_status = TILE_STATUS_GETTING;
00113 }
00114 }
00115
00116
00120 static INLINE void
00121 put_cz_tiles(uint tx, uint ty)
00122 {
00123 if (spu.cur_ztile_status == TILE_STATUS_DIRTY) {
00124
00125
00126 put_tile(tx, ty, &spu.ztile, TAG_WRITE_TILE_Z, 1);
00127 spu.cur_ztile_status = TILE_STATUS_DEFINED;
00128 }
00129 else if (spu.cur_ztile_status == TILE_STATUS_GETTING) {
00130
00131 spu.cur_ztile_status = TILE_STATUS_DEFINED;
00132
00133 }
00134
00135 if (spu.cur_ctile_status == TILE_STATUS_DIRTY) {
00136
00137
00138 put_tile(tx, ty, &spu.ctile, TAG_WRITE_TILE_COLOR, 0);
00139 spu.cur_ctile_status = TILE_STATUS_DEFINED;
00140 }
00141 else if (spu.cur_ctile_status == TILE_STATUS_GETTING) {
00142
00143 spu.cur_ctile_status = TILE_STATUS_DEFINED;
00144
00145 }
00146 }
00147
00148
00152 static INLINE void
00153 wait_put_cz_tiles(void)
00154 {
00155 wait_on_mask(1 << TAG_WRITE_TILE_COLOR);
00156 if (spu.read_depth) {
00157 wait_on_mask(1 << TAG_WRITE_TILE_Z);
00158 }
00159 }
00160
00161
00167 void
00168 cmd_render(const struct cell_command_render *render, uint *pos_incr)
00169 {
00170
00171 ubyte vertex_data[CELL_BUFFER_SIZE] ALIGN16_ATTRIB;
00172 const uint vertex_size = render->vertex_size;
00173 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
00191
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
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
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
00216 ubyte *src = spu.init.buffers[render->vertex_buf];
00217 ubyte *dest = vertex_data;
00218
00219
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,
00230 (unsigned int) src,
00231 total_vertex_bytes,
00232 TAG_VERTEX_BUFFER,
00233 0,
00234 0 );
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
00251 wait_on_mask(1 << TAG_SURFACE_CLEAR);
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
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
00286
00287
00288 put_cz_tiles(tx, ty);
00289
00290 wait_put_cz_tiles();
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 }
00300
00301