5515bb55c955ae4b91ee599b3ff4f9b52ab128b5
1 /**************************************************************************
3 * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 **************************************************************************/
31 #include <spu_mfcio.h>
34 #include "spu_render.h"
37 #include "cell/common.h"
38 #include "util/u_memory.h"
42 * Given a rendering command's bounding box (in pixels) compute the
43 * location of the corresponding screen tile bounding box.
46 tile_bounding_box(const struct cell_command_render
*render
,
47 uint
*txmin
, uint
*tymin
,
48 uint
*box_num_tiles
, uint
*box_width_tiles
)
51 /* Debug: full-window bounding box */
52 uint txmax
= spu
.fb
.width_tiles
- 1;
53 uint tymax
= spu
.fb
.height_tiles
- 1;
56 *box_num_tiles
= spu
.fb
.width_tiles
* spu
.fb
.height_tiles
;
57 *box_width_tiles
= spu
.fb
.width_tiles
;
62 uint txmax
, tymax
, box_height_tiles
;
64 *txmin
= (uint
) render
->xmin
/ TILE_SIZE
;
65 *tymin
= (uint
) render
->ymin
/ TILE_SIZE
;
66 txmax
= (uint
) render
->xmax
/ TILE_SIZE
;
67 tymax
= (uint
) render
->ymax
/ TILE_SIZE
;
68 if (txmax
>= spu
.fb
.width_tiles
)
69 txmax
= spu
.fb
.width_tiles
-1;
70 if (tymax
>= spu
.fb
.height_tiles
)
71 tymax
= spu
.fb
.height_tiles
-1;
72 *box_width_tiles
= txmax
- *txmin
+ 1;
73 box_height_tiles
= tymax
- *tymin
+ 1;
74 *box_num_tiles
= *box_width_tiles
* box_height_tiles
;
77 printf("SPU %u: bounds: %g, %g ... %g, %g\n", spu
.init
.id
,
78 render
->xmin
, render
->ymin
, render
->xmax
, render
->ymax
);
79 printf("SPU %u: tiles: %u, %u .. %u, %u\n",
80 spu
.init
.id
, *txmin
, *tymin
, txmax
, tymax
);
81 ASSERT(render
->xmin
<= render
->xmax
);
82 ASSERT(render
->ymin
<= render
->ymax
);
87 /** Check if the tile at (tx,ty) belongs to this SPU */
89 my_tile(uint tx
, uint ty
)
91 return (spu
.fb
.width_tiles
* ty
+ tx
) % spu
.init
.num_spus
== spu
.init
.id
;
96 * Start fetching non-clear color/Z tiles from main memory
99 get_cz_tiles(uint tx
, uint ty
)
101 if (spu
.read_depth
) {
102 if (spu
.cur_ztile_status
!= TILE_STATUS_CLEAR
) {
103 //printf("SPU %u: getting Z tile %u, %u\n", spu.init.id, tx, ty);
104 get_tile(tx
, ty
, &spu
.ztile
, TAG_READ_TILE_Z
, 1);
105 spu
.cur_ztile_status
= TILE_STATUS_GETTING
;
109 if (spu
.cur_ctile_status
!= TILE_STATUS_CLEAR
) {
110 //printf("SPU %u: getting C tile %u, %u\n", spu.init.id, tx, ty);
111 get_tile(tx
, ty
, &spu
.ctile
, TAG_READ_TILE_COLOR
, 0);
112 spu
.cur_ctile_status
= TILE_STATUS_GETTING
;
118 * Start putting dirty color/Z tiles back to main memory
121 put_cz_tiles(uint tx
, uint ty
)
123 if (spu
.cur_ztile_status
== TILE_STATUS_DIRTY
) {
124 /* tile was modified and needs to be written back */
125 //printf("SPU %u: put dirty Z tile %u, %u\n", spu.init.id, tx, ty);
126 put_tile(tx
, ty
, &spu
.ztile
, TAG_WRITE_TILE_Z
, 1);
127 spu
.cur_ztile_status
= TILE_STATUS_DEFINED
;
129 else if (spu
.cur_ztile_status
== TILE_STATUS_GETTING
) {
130 /* tile was never used */
131 spu
.cur_ztile_status
= TILE_STATUS_DEFINED
;
132 //printf("SPU %u: put getting Z tile %u, %u\n", spu.init.id, tx, ty);
135 if (spu
.cur_ctile_status
== TILE_STATUS_DIRTY
) {
136 /* tile was modified and needs to be written back */
137 //printf("SPU %u: put dirty C tile %u, %u\n", spu.init.id, tx, ty);
138 put_tile(tx
, ty
, &spu
.ctile
, TAG_WRITE_TILE_COLOR
, 0);
139 spu
.cur_ctile_status
= TILE_STATUS_DEFINED
;
141 else if (spu
.cur_ctile_status
== TILE_STATUS_GETTING
) {
142 /* tile was never used */
143 spu
.cur_ctile_status
= TILE_STATUS_DEFINED
;
144 //printf("SPU %u: put getting C tile %u, %u\n", spu.init.id, tx, ty);
150 * Wait for 'put' of color/z tiles to complete.
153 wait_put_cz_tiles(void)
155 wait_on_mask(1 << TAG_WRITE_TILE_COLOR
);
156 if (spu
.read_depth
) {
157 wait_on_mask(1 << TAG_WRITE_TILE_Z
);
164 * \param pos_incr returns value indicating how may words to skip after
165 * this command in the batch buffer
168 cmd_render(const struct cell_command_render
*render
, uint
*pos_incr
)
170 /* we'll DMA into these buffers */
171 ubyte vertex_data
[CELL_BUFFER_SIZE
] ALIGN16_ATTRIB
;
172 const uint vertex_size
= render
->vertex_size
; /* in bytes */
173 /*const*/ uint total_vertex_bytes
= render
->num_verts
* vertex_size
;
175 const ubyte
*vertices
;
176 const ushort
*indexes
;
180 D_PRINTF(CELL_DEBUG_CMD
,
181 "RENDER prim=%u num_vert=%u num_ind=%u inline_vert=%u\n",
185 render
->inline_verts
);
187 ASSERT(sizeof(*render
) % 4 == 0);
188 ASSERT(total_vertex_bytes
% 16 == 0);
189 ASSERT(render
->prim_type
== PIPE_PRIM_TRIANGLES
);
190 ASSERT(render
->num_indexes
% 3 == 0);
193 /* indexes are right after the render command in the batch buffer */
194 indexes
= (const ushort
*) (render
+ 1);
195 index_bytes
= ROUNDUP8(render
->num_indexes
* 2);
196 *pos_incr
= index_bytes
/ 8 + sizeof(*render
) / 8;
199 if (render
->inline_verts
) {
200 /* Vertices are after indexes in batch buffer at next 16-byte addr */
201 vertices
= (const ubyte
*) render
+ (*pos_incr
* 8);
202 vertices
= (const ubyte
*) align_pointer((void *) vertices
, 16);
203 ASSERT_ALIGN16(vertices
);
204 *pos_incr
= ((vertices
+ total_vertex_bytes
) - (ubyte
*) render
) / 8;
207 /* Begin DMA fetch of vertex buffer */
208 ubyte
*src
= spu
.init
.buffers
[render
->vertex_buf
];
209 ubyte
*dest
= vertex_data
;
211 /* skip vertex data we won't use */
213 src
+= render
->min_index
* vertex_size
;
214 dest
+= render
->min_index
* vertex_size
;
215 total_vertex_bytes
-= render
->min_index
* vertex_size
;
217 ASSERT(total_vertex_bytes
% 16 == 0);
218 ASSERT_ALIGN16(dest
);
221 mfc_get(dest
, /* in vertex_data[] array */
222 (unsigned int) src
, /* src in main memory */
223 total_vertex_bytes
, /* size */
228 vertices
= vertex_data
;
230 wait_on_mask(1 << TAG_VERTEX_BUFFER
);
235 ** find tiles which intersect the prim bounding box
237 uint txmin
, tymin
, box_width_tiles
, box_num_tiles
;
238 tile_bounding_box(render
, &txmin
, &tymin
,
239 &box_num_tiles
, &box_width_tiles
);
242 /* make sure any pending clears have completed */
243 wait_on_mask(1 << TAG_SURFACE_CLEAR
); /* XXX temporary */
249 ** loop over tiles, rendering tris
251 for (i
= 0; i
< box_num_tiles
; i
++) {
252 const uint tx
= txmin
+ i
% box_width_tiles
;
253 const uint ty
= tymin
+ i
/ box_width_tiles
;
255 ASSERT(tx
< spu
.fb
.width_tiles
);
256 ASSERT(ty
< spu
.fb
.height_tiles
);
258 if (!my_tile(tx
, ty
))
263 spu
.cur_ctile_status
= spu
.ctile_status
[ty
][tx
];
264 spu
.cur_ztile_status
= spu
.ztile_status
[ty
][tx
];
266 get_cz_tiles(tx
, ty
);
271 for (j
= 0; j
< render
->num_indexes
; j
+= 3) {
272 const float *v0
, *v1
, *v2
;
274 v0
= (const float *) (vertices
+ indexes
[j
+0] * vertex_size
);
275 v1
= (const float *) (vertices
+ indexes
[j
+1] * vertex_size
);
276 v2
= (const float *) (vertices
+ indexes
[j
+2] * vertex_size
);
278 drawn
+= tri_draw(v0
, v1
, v2
, tx
, ty
);
281 //printf("SPU %u: drew %u of %u\n", spu.init.id, drawn, render->num_indexes/3);
283 /* write color/z tiles back to main framebuffer, if dirtied */
284 put_cz_tiles(tx
, ty
);
286 wait_put_cz_tiles(); /* XXX seems unnecessary... */
288 spu
.ctile_status
[ty
][tx
] = spu
.cur_ctile_status
;
289 spu
.ztile_status
[ty
][tx
] = spu
.cur_ztile_status
;
292 D_PRINTF(CELL_DEBUG_CMD
,
293 "RENDER done (%u tiles hit)\n",