cell_vbuf.c

Go to the documentation of this file.
00001 /**************************************************************************
00002  * 
00003  * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
00004  * All Rights Reserved.
00005  * 
00006  * Permission is hereby granted, free of charge, to any person obtaining a
00007  * copy of this software and associated documentation files (the
00008  * "Software"), to deal in the Software without restriction, including
00009  * without limitation the rights to use, copy, modify, merge, publish,
00010  * distribute, sub license, and/or sell copies of the Software, and to
00011  * permit persons to whom the Software is furnished to do so, subject to
00012  * the following conditions:
00013  * 
00014  * The above copyright notice and this permission notice (including the
00015  * next paragraph) shall be included in all copies or substantial portions
00016  * of the Software.
00017  * 
00018  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
00019  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00020  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
00021  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
00022  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
00023  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
00024  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
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    /*printf("Alloc verts %u * %u\n", vertex_size, nr_vertices);*/
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    printf("%s vertex_buf = %u  count = %u\n",
00108           __FUNCTION__, cvbr->vertex_buf, vertices_used);
00109    */
00110 
00111    /* Tell SPUs they can release the vert buf */
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    /*printf("cell_set_prim %u\n", prim);*/
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    /*if (min_index > 0)*/
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    /* compute x/y bounding box */
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; /* only render tris for now */
00204 
00205    /* build/insert batch RENDER command */
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       /* append indices after render command */
00222       memcpy(render + 1, indices, nr_indices * 2);
00223 
00224       /* if there's room, append vertices after the indices, else leave
00225        * vertices in the original/separate buffer.
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          /* vertex data inlined, after indices, at 16-byte boundary */
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          /* vertex data in separate buffer */
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    /* helpful for debug */
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    /* The max number of indexes is what can fix into a batch buffer,
00279     * minus the render and release-verts commands.
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 }

Generated on Tue Sep 29 06:25:16 2009 for Gallium3D by  doxygen 1.5.4