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
00039 #include "cell_batch.h"
00040 #include "cell_context.h"
00041 #include "cell_flush.h"
00042 #include "cell_spu.h"
00043 #include "cell_vbuf.h"
00044 #include "draw/draw_vbuf.h"
00045 #include "util/u_memory.h"
00046
00047
00049 #define ALLOW_INLINE_VERTS 1
00050
00051
00056 struct cell_vbuf_render
00057 {
00058 struct vbuf_render base;
00059 struct cell_context *cell;
00060 uint prim;
00061 uint vertex_size;
00062 void *vertex_buffer;
00063 uint vertex_buf;
00064 };
00065
00066
00068 static struct cell_vbuf_render *
00069 cell_vbuf_render(struct vbuf_render *vbr)
00070 {
00071 return (struct cell_vbuf_render *) vbr;
00072 }
00073
00074
00075
00076 static const struct vertex_info *
00077 cell_vbuf_get_vertex_info(struct vbuf_render *vbr)
00078 {
00079 struct cell_vbuf_render *cvbr = cell_vbuf_render(vbr);
00080 return &cvbr->cell->vertex_info;
00081 }
00082
00083
00084 static void *
00085 cell_vbuf_allocate_vertices(struct vbuf_render *vbr,
00086 ushort vertex_size, ushort nr_vertices)
00087 {
00088 struct cell_vbuf_render *cvbr = cell_vbuf_render(vbr);
00089
00090
00091 assert(cvbr->vertex_buf == ~0);
00092 cvbr->vertex_buf = cell_get_empty_buffer(cvbr->cell);
00093 cvbr->vertex_buffer = cvbr->cell->buffer[cvbr->vertex_buf];
00094 cvbr->vertex_size = vertex_size;
00095 return cvbr->vertex_buffer;
00096 }
00097
00098
00099 static void
00100 cell_vbuf_release_vertices(struct vbuf_render *vbr, void *vertices,
00101 unsigned vertex_size, unsigned vertices_used)
00102 {
00103 struct cell_vbuf_render *cvbr = cell_vbuf_render(vbr);
00104 struct cell_context *cell = cvbr->cell;
00105
00106
00107
00108
00109
00110
00111
00112 if (cvbr->vertex_buf != ~0U) {
00113 struct cell_command_release_verts *release
00114 = (struct cell_command_release_verts *)
00115 cell_batch_alloc(cell, sizeof(struct cell_command_release_verts));
00116 release->opcode = CELL_CMD_RELEASE_VERTS;
00117 release->vertex_buf = cvbr->vertex_buf;
00118 }
00119
00120 cvbr->vertex_buf = ~0;
00121 cell_flush_int(cell, 0x0);
00122
00123 assert(vertices == cvbr->vertex_buffer);
00124 cvbr->vertex_buffer = NULL;
00125 }
00126
00127
00128
00129 static boolean
00130 cell_vbuf_set_primitive(struct vbuf_render *vbr, unsigned prim)
00131 {
00132 struct cell_vbuf_render *cvbr = cell_vbuf_render(vbr);
00133 cvbr->prim = prim;
00134
00135 return TRUE;
00136 }
00137
00138
00139 static void
00140 cell_vbuf_draw(struct vbuf_render *vbr,
00141 const ushort *indices,
00142 uint nr_indices)
00143 {
00144 struct cell_vbuf_render *cvbr = cell_vbuf_render(vbr);
00145 struct cell_context *cell = cvbr->cell;
00146 float xmin, ymin, xmax, ymax;
00147 uint i;
00148 uint nr_vertices = 0, min_index = ~0;
00149 const void *vertices = cvbr->vertex_buffer;
00150 const uint vertex_size = cvbr->vertex_size;
00151
00152 for (i = 0; i < nr_indices; i++) {
00153 if (indices[i] > nr_vertices)
00154 nr_vertices = indices[i];
00155 if (indices[i] < min_index)
00156 min_index = indices[i];
00157 }
00158 nr_vertices++;
00159
00160 #if 0
00161
00162 printf("%s min_index = %u\n", __FUNCTION__, min_index);
00163 #endif
00164
00165 #if 0
00166 printf("cell_vbuf_draw() nr_indices = %u nr_verts = %u\n",
00167 nr_indices, nr_vertices);
00168 printf(" ");
00169 for (i = 0; i < nr_indices; i += 3) {
00170 printf("%u %u %u, ", indices[i+0], indices[i+1], indices[i+2]);
00171 }
00172 printf("\n");
00173 #elif 0
00174 printf("cell_vbuf_draw() nr_indices = %u nr_verts = %u indexes = [%u %u %u ...]\n",
00175 nr_indices, nr_vertices,
00176 indices[0], indices[1], indices[2]);
00177 printf("ind space = %u, vert space = %u, space = %u\n",
00178 nr_indices * 2,
00179 nr_vertices * 4 * cell->vertex_info.size,
00180 cell_batch_free_space(cell));
00181 #endif
00182
00183
00184 xmin = ymin = 1e50;
00185 xmax = ymax = -1e50;
00186 for (i = min_index; i < nr_vertices; i++) {
00187 const float *v = (float *) ((ubyte *) vertices + i * vertex_size);
00188 if (v[0] < xmin)
00189 xmin = v[0];
00190 if (v[0] > xmax)
00191 xmax = v[0];
00192 if (v[1] < ymin)
00193 ymin = v[1];
00194 if (v[1] > ymax)
00195 ymax = v[1];
00196 }
00197 #if 0
00198 printf("PPU Bounds %g, %g .. %g, %g\n", xmin, ymin, xmax, ymax);
00199 fflush(stdout);
00200 #endif
00201
00202 if (cvbr->prim != PIPE_PRIM_TRIANGLES)
00203 return;
00204
00205
00206 {
00207 const uint index_bytes = ROUNDUP8(nr_indices * 2);
00208 const uint vertex_bytes = nr_vertices * 4 * cell->vertex_info.size;
00209 const uint batch_size = sizeof(struct cell_command_render) + index_bytes;
00210
00211 struct cell_command_render *render
00212 = (struct cell_command_render *)
00213 cell_batch_alloc(cell, batch_size);
00214
00215 render->opcode = CELL_CMD_RENDER;
00216 render->prim_type = cvbr->prim;
00217
00218 render->num_indexes = nr_indices;
00219 render->min_index = min_index;
00220
00221
00222 memcpy(render + 1, indices, nr_indices * 2);
00223
00224
00225
00226
00227 render->vertex_size = 4 * cell->vertex_info.size;
00228 render->num_verts = nr_vertices;
00229 if (ALLOW_INLINE_VERTS &&
00230 min_index == 0 &&
00231 vertex_bytes + 16 <= cell_batch_free_space(cell)) {
00232
00233 void *dst = cell_batch_alloc_aligned(cell, vertex_bytes, 16);
00234 memcpy(dst, vertices, vertex_bytes);
00235 render->inline_verts = TRUE;
00236 render->vertex_buf = ~0;
00237 }
00238 else {
00239
00240 render->inline_verts = FALSE;
00241 ASSERT(cvbr->vertex_buf >= 0);
00242 render->vertex_buf = cvbr->vertex_buf;
00243 }
00244
00245 render->xmin = xmin;
00246 render->ymin = ymin;
00247 render->xmax = xmax;
00248 render->ymax = ymax;
00249 }
00250
00251 #if 0
00252
00253 cell_flush_int(cell, CELL_FLUSH_WAIT);
00254 #endif
00255 }
00256
00257
00258 static void
00259 cell_vbuf_destroy(struct vbuf_render *vbr)
00260 {
00261 struct cell_vbuf_render *cvbr = cell_vbuf_render(vbr);
00262 cvbr->cell->vbuf_render = NULL;
00263 FREE(cvbr);
00264 }
00265
00266
00271 void
00272 cell_init_vbuf(struct cell_context *cell)
00273 {
00274 assert(cell->draw);
00275
00276 cell->vbuf_render = CALLOC_STRUCT(cell_vbuf_render);
00277
00278
00279
00280
00281 cell->vbuf_render->base.max_indices
00282 = (CELL_BUFFER_SIZE
00283 - sizeof(struct cell_command_render)
00284 - sizeof(struct cell_command_release_verts))
00285 / sizeof(ushort);
00286 cell->vbuf_render->base.max_vertex_buffer_bytes = CELL_BUFFER_SIZE;
00287
00288 cell->vbuf_render->base.get_vertex_info = cell_vbuf_get_vertex_info;
00289 cell->vbuf_render->base.allocate_vertices = cell_vbuf_allocate_vertices;
00290 cell->vbuf_render->base.set_primitive = cell_vbuf_set_primitive;
00291 cell->vbuf_render->base.draw = cell_vbuf_draw;
00292 cell->vbuf_render->base.release_vertices = cell_vbuf_release_vertices;
00293 cell->vbuf_render->base.destroy = cell_vbuf_destroy;
00294
00295 cell->vbuf_render->cell = cell;
00296 #if 1
00297 cell->vbuf_render->vertex_buf = ~0;
00298 #endif
00299
00300 cell->vbuf = draw_vbuf_stage(cell->draw, &cell->vbuf_render->base);
00301 }