cell: send rasterizer state to SPUs in proper way, remove front_winding hack
[mesa.git] / src / gallium / drivers / cell / spu / spu_command.c
1 /**************************************************************************
2 *
3 * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
4 * All Rights Reserved.
5 *
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:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
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.
25 *
26 **************************************************************************/
27
28
29 /**
30 * SPU command processing code
31 */
32
33
34 #include <stdio.h>
35 #include <libmisc.h>
36
37 #include "pipe/p_defines.h"
38
39 #include "spu_command.h"
40 #include "spu_main.h"
41 #include "spu_render.h"
42 #include "spu_per_fragment_op.h"
43 #include "spu_texture.h"
44 #include "spu_tile.h"
45 #include "spu_vertex_shader.h"
46 #include "spu_dcache.h"
47 #include "cell/common.h"
48
49
50 struct spu_vs_context draw;
51
52
53 /**
54 * Buffers containing dynamically generated SPU code:
55 */
56 static unsigned char attribute_fetch_code_buffer[136 * PIPE_MAX_ATTRIBS]
57 ALIGN16_ATTRIB;
58
59
60
61 static INLINE int
62 align(int value, int alignment)
63 {
64 return (value + alignment - 1) & ~(alignment - 1);
65 }
66
67
68
69 /**
70 * Tell the PPU that this SPU has finished copying a buffer to
71 * local store and that it may be reused by the PPU.
72 * This is done by writting a 16-byte batch-buffer-status block back into
73 * main memory (in cell_context->buffer_status[]).
74 */
75 static void
76 release_buffer(uint buffer)
77 {
78 /* Evidently, using less than a 16-byte status doesn't work reliably */
79 static const uint status[4] ALIGN16_ATTRIB
80 = {CELL_BUFFER_STATUS_FREE, 0, 0, 0};
81
82 const uint index = 4 * (spu.init.id * CELL_NUM_BUFFERS + buffer);
83 uint *dst = spu.init.buffer_status + index;
84
85 ASSERT(buffer < CELL_NUM_BUFFERS);
86
87 mfc_put((void *) &status, /* src in local memory */
88 (unsigned int) dst, /* dst in main memory */
89 sizeof(status), /* size */
90 TAG_MISC, /* tag is unimportant */
91 0, /* tid */
92 0 /* rid */);
93 }
94
95
96 static void
97 cmd_clear_surface(const struct cell_command_clear_surface *clear)
98 {
99 D_PRINTF(CELL_DEBUG_CMD, "CLEAR SURF %u to 0x%08x\n", clear->surface, clear->value);
100
101 if (clear->surface == 0) {
102 spu.fb.color_clear_value = clear->value;
103 if (spu.init.debug_flags & CELL_DEBUG_CHECKER) {
104 uint x = (spu.init.id << 4) | (spu.init.id << 12) |
105 (spu.init.id << 20) | (spu.init.id << 28);
106 spu.fb.color_clear_value ^= x;
107 }
108 }
109 else {
110 spu.fb.depth_clear_value = clear->value;
111 }
112
113 #define CLEAR_OPT 1
114 #if CLEAR_OPT
115
116 /* Simply set all tiles' status to CLEAR.
117 * When we actually begin rendering into a tile, we'll initialize it to
118 * the clear value. If any tiles go untouched during the frame,
119 * really_clear_tiles() will set them to the clear value.
120 */
121 if (clear->surface == 0) {
122 memset(spu.ctile_status, TILE_STATUS_CLEAR, sizeof(spu.ctile_status));
123 }
124 else {
125 memset(spu.ztile_status, TILE_STATUS_CLEAR, sizeof(spu.ztile_status));
126 }
127
128 #else
129
130 /*
131 * This path clears the whole framebuffer to the clear color right now.
132 */
133
134 /*
135 printf("SPU: %s num=%d w=%d h=%d\n",
136 __FUNCTION__, num_tiles, spu.fb.width_tiles, spu.fb.height_tiles);
137 */
138
139 /* init a single tile to the clear value */
140 if (clear->surface == 0) {
141 clear_c_tile(&spu.ctile);
142 }
143 else {
144 clear_z_tile(&spu.ztile);
145 }
146
147 /* walk over my tiles, writing the 'clear' tile's data */
148 {
149 const uint num_tiles = spu.fb.width_tiles * spu.fb.height_tiles;
150 uint i;
151 for (i = spu.init.id; i < num_tiles; i += spu.init.num_spus) {
152 uint tx = i % spu.fb.width_tiles;
153 uint ty = i / spu.fb.width_tiles;
154 if (clear->surface == 0)
155 put_tile(tx, ty, &spu.ctile, TAG_SURFACE_CLEAR, 0);
156 else
157 put_tile(tx, ty, &spu.ztile, TAG_SURFACE_CLEAR, 1);
158 }
159 }
160
161 if (spu.init.debug_flags & CELL_DEBUG_SYNC) {
162 wait_on_mask(1 << TAG_SURFACE_CLEAR);
163 }
164
165 #endif /* CLEAR_OPT */
166
167 D_PRINTF(CELL_DEBUG_CMD, "CLEAR SURF done\n");
168 }
169
170
171 static void
172 cmd_release_verts(const struct cell_command_release_verts *release)
173 {
174 D_PRINTF(CELL_DEBUG_CMD, "RELEASE VERTS %u\n", release->vertex_buf);
175 ASSERT(release->vertex_buf != ~0U);
176 release_buffer(release->vertex_buf);
177 }
178
179
180 /**
181 * Process a CELL_CMD_STATE_FRAGMENT_OPS command.
182 * This involves installing new fragment ops SPU code.
183 * If this function is never called, we'll use a regular C fallback function
184 * for fragment processing.
185 */
186 static void
187 cmd_state_fragment_ops(const struct cell_command_fragment_ops *fops)
188 {
189 static int warned = 0;
190
191 D_PRINTF(CELL_DEBUG_CMD, "CMD_STATE_FRAGMENT_OPS\n");
192 /* Copy SPU code from batch buffer to spu buffer */
193 memcpy(spu.fragment_ops_code, fops->code, SPU_MAX_FRAGMENT_OPS_INSTS * 4);
194 /* Copy state info (for fallback case only) */
195 memcpy(&spu.depth_stencil_alpha, &fops->dsa, sizeof(fops->dsa));
196 memcpy(&spu.blend, &fops->blend, sizeof(fops->blend));
197 memcpy(&spu.blend_color, &fops->blend_color, sizeof(fops->blend_color));
198
199 /* Parity twist! For now, always use the fallback code by default,
200 * only switching to codegen when specifically requested. This
201 * allows us to develop freely without risking taking down the
202 * branch.
203 *
204 * Later, the parity of this check will be reversed, so that
205 * codegen is *always* used, unless we specifically indicate that
206 * we don't want it.
207 *
208 * Eventually, the option will be removed completely, because in
209 * final code we'll always use codegen and won't even provide the
210 * raw state records that the fallback code requires.
211 */
212 if ((spu.init.debug_flags & CELL_DEBUG_FRAGMENT_OP_FALLBACK) == 0) {
213 spu.fragment_ops = (spu_fragment_ops_func) spu.fragment_ops_code;
214 }
215 else {
216 /* otherwise, the default fallback code remains in place */
217 if (!warned) {
218 fprintf(stderr, "Cell Warning: using fallback per-fragment code\n");
219 warned = 1;
220 }
221 }
222
223 spu.read_depth = spu.depth_stencil_alpha.depth.enabled;
224 spu.read_stencil = spu.depth_stencil_alpha.stencil[0].enabled;
225 }
226
227
228 static void
229 cmd_state_fragment_program(const struct cell_command_fragment_program *fp)
230 {
231 D_PRINTF(CELL_DEBUG_CMD, "CMD_STATE_FRAGMENT_PROGRAM\n");
232 /* Copy SPU code from batch buffer to spu buffer */
233 memcpy(spu.fragment_program_code, fp->code,
234 SPU_MAX_FRAGMENT_PROGRAM_INSTS * 4);
235 #if 01
236 /* Point function pointer at new code */
237 spu.fragment_program = (spu_fragment_program_func)spu.fragment_program_code;
238 #endif
239 }
240
241
242 static uint
243 cmd_state_fs_constants(const uint64_t *buffer, uint pos)
244 {
245 const uint num_const = buffer[pos + 1];
246 const float *constants = (const float *) &buffer[pos + 2];
247 uint i;
248
249 D_PRINTF(CELL_DEBUG_CMD, "CMD_STATE_FS_CONSTANTS (%u)\n", num_const);
250
251 /* Expand each float to float[4] for SOA execution */
252 for (i = 0; i < num_const; i++) {
253 D_PRINTF(CELL_DEBUG_CMD, " const[%u] = %f\n", i, constants[i]);
254 spu.constants[i] = spu_splats(constants[i]);
255 }
256
257 /* return new buffer pos (in 8-byte words) */
258 return pos + 2 + num_const / 2;
259 }
260
261
262 static void
263 cmd_state_framebuffer(const struct cell_command_framebuffer *cmd)
264 {
265 D_PRINTF(CELL_DEBUG_CMD, "FRAMEBUFFER: %d x %d at %p, cformat 0x%x zformat 0x%x\n",
266 cmd->width,
267 cmd->height,
268 cmd->color_start,
269 cmd->color_format,
270 cmd->depth_format);
271
272 ASSERT_ALIGN16(cmd->color_start);
273 ASSERT_ALIGN16(cmd->depth_start);
274
275 spu.fb.color_start = cmd->color_start;
276 spu.fb.depth_start = cmd->depth_start;
277 spu.fb.color_format = cmd->color_format;
278 spu.fb.depth_format = cmd->depth_format;
279 spu.fb.width = cmd->width;
280 spu.fb.height = cmd->height;
281 spu.fb.width_tiles = (spu.fb.width + TILE_SIZE - 1) / TILE_SIZE;
282 spu.fb.height_tiles = (spu.fb.height + TILE_SIZE - 1) / TILE_SIZE;
283
284 switch (spu.fb.depth_format) {
285 case PIPE_FORMAT_Z32_UNORM:
286 spu.fb.zsize = 4;
287 spu.fb.zscale = (float) 0xffffffffu;
288 break;
289 case PIPE_FORMAT_Z24S8_UNORM:
290 case PIPE_FORMAT_S8Z24_UNORM:
291 case PIPE_FORMAT_Z24X8_UNORM:
292 case PIPE_FORMAT_X8Z24_UNORM:
293 spu.fb.zsize = 4;
294 spu.fb.zscale = (float) 0x00ffffffu;
295 break;
296 case PIPE_FORMAT_Z16_UNORM:
297 spu.fb.zsize = 2;
298 spu.fb.zscale = (float) 0xffffu;
299 break;
300 default:
301 spu.fb.zsize = 0;
302 break;
303 }
304 }
305
306
307 /**
308 * Tex texture mask_s/t and scale_s/t fields depend on the texture size and
309 * sampler wrap modes.
310 */
311 static void
312 update_tex_masks(struct spu_texture *texture,
313 const struct pipe_sampler_state *sampler,
314 uint unit)
315 {
316 uint i;
317
318 for (i = 0; i < CELL_MAX_TEXTURE_LEVELS; i++) {
319 int width = texture->level[i].width;
320 int height = texture->level[i].height;
321
322 if (sampler->wrap_s == PIPE_TEX_WRAP_REPEAT)
323 texture->level[i].mask_s = spu_splats(width - 1);
324 else
325 texture->level[i].mask_s = spu_splats(~0);
326
327 if (sampler->wrap_t == PIPE_TEX_WRAP_REPEAT)
328 texture->level[i].mask_t = spu_splats(height - 1);
329 else
330 texture->level[i].mask_t = spu_splats(~0);
331
332 if (sampler->normalized_coords) {
333 texture->level[i].scale_s = spu_splats((float) width);
334 texture->level[i].scale_t = spu_splats((float) height);
335 }
336 else {
337 texture->level[i].scale_s = spu_splats(1.0f);
338 texture->level[i].scale_t = spu_splats(1.0f);
339 }
340 }
341
342 /* XXX temporary hack */
343 if (texture->target == PIPE_TEXTURE_CUBE) {
344 spu.sample_texture4[unit] = sample_texture4_cube;
345 }
346 }
347
348
349 static void
350 cmd_state_sampler(const struct cell_command_sampler *sampler)
351 {
352 uint unit = sampler->unit;
353
354 D_PRINTF(CELL_DEBUG_CMD, "SAMPLER [%u]\n", unit);
355
356 spu.sampler[unit] = sampler->state;
357
358 switch (spu.sampler[unit].min_img_filter) {
359 case PIPE_TEX_FILTER_LINEAR:
360 spu.min_sample_texture4[unit] = sample_texture4_bilinear;
361 break;
362 case PIPE_TEX_FILTER_ANISO:
363 /* fall-through, for now */
364 case PIPE_TEX_FILTER_NEAREST:
365 spu.min_sample_texture4[unit] = sample_texture4_nearest;
366 break;
367 default:
368 ASSERT(0);
369 }
370
371 switch (spu.sampler[sampler->unit].mag_img_filter) {
372 case PIPE_TEX_FILTER_LINEAR:
373 spu.mag_sample_texture4[unit] = sample_texture4_bilinear;
374 break;
375 case PIPE_TEX_FILTER_ANISO:
376 /* fall-through, for now */
377 case PIPE_TEX_FILTER_NEAREST:
378 spu.mag_sample_texture4[unit] = sample_texture4_nearest;
379 break;
380 default:
381 ASSERT(0);
382 }
383
384 switch (spu.sampler[sampler->unit].min_mip_filter) {
385 case PIPE_TEX_MIPFILTER_NEAREST:
386 case PIPE_TEX_MIPFILTER_LINEAR:
387 spu.sample_texture4[unit] = sample_texture4_lod;
388 break;
389 case PIPE_TEX_MIPFILTER_NONE:
390 spu.sample_texture4[unit] = spu.mag_sample_texture4[unit];
391 break;
392 default:
393 ASSERT(0);
394 }
395
396 update_tex_masks(&spu.texture[unit], &spu.sampler[unit], unit);
397 }
398
399
400 static void
401 cmd_state_texture(const struct cell_command_texture *texture)
402 {
403 const uint unit = texture->unit;
404 uint i;
405
406 D_PRINTF(CELL_DEBUG_CMD, "TEXTURE [%u]\n", texture->unit);
407
408 spu.texture[unit].max_level = 0;
409 spu.texture[unit].target = texture->target;
410
411 for (i = 0; i < CELL_MAX_TEXTURE_LEVELS; i++) {
412 uint width = texture->width[i];
413 uint height = texture->height[i];
414 uint depth = texture->depth[i];
415
416 D_PRINTF(CELL_DEBUG_CMD, " LEVEL %u: at %p size[0] %u x %u\n", i,
417 texture->start[i], texture->width[i], texture->height[i]);
418
419 spu.texture[unit].level[i].start = texture->start[i];
420 spu.texture[unit].level[i].width = width;
421 spu.texture[unit].level[i].height = height;
422 spu.texture[unit].level[i].depth = depth;
423
424 spu.texture[unit].level[i].tiles_per_row =
425 (width + TILE_SIZE - 1) / TILE_SIZE;
426
427 spu.texture[unit].level[i].bytes_per_image =
428 4 * align(width, TILE_SIZE) * align(height, TILE_SIZE) * depth;
429
430 spu.texture[unit].level[i].max_s = spu_splats((int) width - 1);
431 spu.texture[unit].level[i].max_t = spu_splats((int) height - 1);
432
433 if (texture->start[i])
434 spu.texture[unit].max_level = i;
435 }
436
437 update_tex_masks(&spu.texture[unit], &spu.sampler[unit], unit);
438 }
439
440
441 static void
442 cmd_state_vertex_info(const struct vertex_info *vinfo)
443 {
444 D_PRINTF(CELL_DEBUG_CMD, "VERTEX_INFO num_attribs=%u\n", vinfo->num_attribs);
445 ASSERT(vinfo->num_attribs >= 1);
446 ASSERT(vinfo->num_attribs <= 8);
447 memcpy(&spu.vertex_info, vinfo, sizeof(*vinfo));
448 }
449
450
451 static void
452 cmd_state_vs_array_info(const struct cell_array_info *vs_info)
453 {
454 const unsigned attr = vs_info->attr;
455
456 ASSERT(attr < PIPE_MAX_ATTRIBS);
457 draw.vertex_fetch.src_ptr[attr] = vs_info->base;
458 draw.vertex_fetch.pitch[attr] = vs_info->pitch;
459 draw.vertex_fetch.size[attr] = vs_info->size;
460 draw.vertex_fetch.code_offset[attr] = vs_info->function_offset;
461 draw.vertex_fetch.dirty = 1;
462 }
463
464
465 static void
466 cmd_state_attrib_fetch(const struct cell_attribute_fetch_code *code)
467 {
468 mfc_get(attribute_fetch_code_buffer,
469 (unsigned int) code->base, /* src */
470 code->size,
471 TAG_BATCH_BUFFER,
472 0, /* tid */
473 0 /* rid */);
474 wait_on_mask(1 << TAG_BATCH_BUFFER);
475
476 draw.vertex_fetch.code = attribute_fetch_code_buffer;
477 }
478
479
480 static void
481 cmd_finish(void)
482 {
483 D_PRINTF(CELL_DEBUG_CMD, "FINISH\n");
484 really_clear_tiles(0);
485 /* wait for all outstanding DMAs to finish */
486 mfc_write_tag_mask(~0);
487 mfc_read_tag_status_all();
488 /* send mbox message to PPU */
489 spu_write_out_mbox(CELL_CMD_FINISH);
490 }
491
492
493 /**
494 * Execute a batch of commands which was sent to us by the PPU.
495 * See the cell_emit_state.c code to see where the commands come from.
496 *
497 * The opcode param encodes the location of the buffer and its size.
498 */
499 static void
500 cmd_batch(uint opcode)
501 {
502 const uint buf = (opcode >> 8) & 0xff;
503 uint size = (opcode >> 16);
504 uint64_t buffer[CELL_BUFFER_SIZE / 8] ALIGN16_ATTRIB;
505 const unsigned usize = size / sizeof(buffer[0]);
506 uint pos;
507
508 D_PRINTF(CELL_DEBUG_CMD, "BATCH buffer %u, len %u, from %p\n",
509 buf, size, spu.init.buffers[buf]);
510
511 ASSERT((opcode & CELL_CMD_OPCODE_MASK) == CELL_CMD_BATCH);
512
513 ASSERT_ALIGN16(spu.init.buffers[buf]);
514
515 size = ROUNDUP16(size);
516
517 ASSERT_ALIGN16(spu.init.buffers[buf]);
518
519 mfc_get(buffer, /* dest */
520 (unsigned int) spu.init.buffers[buf], /* src */
521 size,
522 TAG_BATCH_BUFFER,
523 0, /* tid */
524 0 /* rid */);
525 wait_on_mask(1 << TAG_BATCH_BUFFER);
526
527 /* Tell PPU we're done copying the buffer to local store */
528 D_PRINTF(CELL_DEBUG_CMD, "release batch buf %u\n", buf);
529 release_buffer(buf);
530
531 /*
532 * Loop over commands in the batch buffer
533 */
534 for (pos = 0; pos < usize; /* no incr */) {
535 switch (buffer[pos]) {
536 /*
537 * rendering commands
538 */
539 case CELL_CMD_CLEAR_SURFACE:
540 {
541 struct cell_command_clear_surface *clr
542 = (struct cell_command_clear_surface *) &buffer[pos];
543 cmd_clear_surface(clr);
544 pos += sizeof(*clr) / 8;
545 }
546 break;
547 case CELL_CMD_RENDER:
548 {
549 struct cell_command_render *render
550 = (struct cell_command_render *) &buffer[pos];
551 uint pos_incr;
552 cmd_render(render, &pos_incr);
553 pos += pos_incr;
554 }
555 break;
556 /*
557 * state-update commands
558 */
559 case CELL_CMD_STATE_FRAMEBUFFER:
560 {
561 struct cell_command_framebuffer *fb
562 = (struct cell_command_framebuffer *) &buffer[pos];
563 cmd_state_framebuffer(fb);
564 pos += sizeof(*fb) / 8;
565 }
566 break;
567 case CELL_CMD_STATE_FRAGMENT_OPS:
568 {
569 struct cell_command_fragment_ops *fops
570 = (struct cell_command_fragment_ops *) &buffer[pos];
571 cmd_state_fragment_ops(fops);
572 pos += sizeof(*fops) / 8;
573 }
574 break;
575 case CELL_CMD_STATE_FRAGMENT_PROGRAM:
576 {
577 struct cell_command_fragment_program *fp
578 = (struct cell_command_fragment_program *) &buffer[pos];
579 cmd_state_fragment_program(fp);
580 pos += sizeof(*fp) / 8;
581 }
582 break;
583 case CELL_CMD_STATE_FS_CONSTANTS:
584 pos = cmd_state_fs_constants(buffer, pos);
585 break;
586 case CELL_CMD_STATE_RASTERIZER:
587 {
588 struct cell_command_rasterizer *rast =
589 (struct cell_command_rasterizer *) &buffer[pos];
590 spu.rasterizer = rast->rasterizer;
591 pos += sizeof(*rast) / 8;
592 }
593 break;
594 case CELL_CMD_STATE_SAMPLER:
595 {
596 struct cell_command_sampler *sampler
597 = (struct cell_command_sampler *) &buffer[pos];
598 cmd_state_sampler(sampler);
599 pos += sizeof(*sampler) / 8;
600 }
601 break;
602 case CELL_CMD_STATE_TEXTURE:
603 {
604 struct cell_command_texture *texture
605 = (struct cell_command_texture *) &buffer[pos];
606 cmd_state_texture(texture);
607 pos += sizeof(*texture) / 8;
608 }
609 break;
610 case CELL_CMD_STATE_VERTEX_INFO:
611 cmd_state_vertex_info((struct vertex_info *) &buffer[pos+1]);
612 pos += (1 + ROUNDUP8(sizeof(struct vertex_info)) / 8);
613 break;
614 case CELL_CMD_STATE_VIEWPORT:
615 (void) memcpy(& draw.viewport, &buffer[pos+1],
616 sizeof(struct pipe_viewport_state));
617 pos += (1 + ROUNDUP8(sizeof(struct pipe_viewport_state)) / 8);
618 break;
619 case CELL_CMD_STATE_UNIFORMS:
620 draw.constants = (const float (*)[4]) (uintptr_t) buffer[pos + 1];
621 pos += 2;
622 break;
623 case CELL_CMD_STATE_VS_ARRAY_INFO:
624 cmd_state_vs_array_info((struct cell_array_info *) &buffer[pos+1]);
625 pos += (1 + ROUNDUP8(sizeof(struct cell_array_info)) / 8);
626 break;
627 case CELL_CMD_STATE_BIND_VS:
628 #if 0
629 spu_bind_vertex_shader(&draw,
630 (struct cell_shader_info *) &buffer[pos+1]);
631 #endif
632 pos += (1 + ROUNDUP8(sizeof(struct cell_shader_info)) / 8);
633 break;
634 case CELL_CMD_STATE_ATTRIB_FETCH:
635 cmd_state_attrib_fetch((struct cell_attribute_fetch_code *)
636 &buffer[pos+1]);
637 pos += (1 + ROUNDUP8(sizeof(struct cell_attribute_fetch_code)) / 8);
638 break;
639 /*
640 * misc commands
641 */
642 case CELL_CMD_FINISH:
643 cmd_finish();
644 pos += 1;
645 break;
646 case CELL_CMD_RELEASE_VERTS:
647 {
648 struct cell_command_release_verts *release
649 = (struct cell_command_release_verts *) &buffer[pos];
650 cmd_release_verts(release);
651 pos += sizeof(*release) / 8;
652 }
653 break;
654 case CELL_CMD_FLUSH_BUFFER_RANGE: {
655 struct cell_buffer_range *br = (struct cell_buffer_range *)
656 &buffer[pos+1];
657
658 spu_dcache_mark_dirty((unsigned) br->base, br->size);
659 pos += (1 + ROUNDUP8(sizeof(struct cell_buffer_range)) / 8);
660 break;
661 }
662 default:
663 printf("SPU %u: bad opcode: 0x%llx\n", spu.init.id, buffer[pos]);
664 ASSERT(0);
665 break;
666 }
667 }
668
669 D_PRINTF(CELL_DEBUG_CMD, "BATCH complete\n");
670 }
671
672
673
674 /**
675 * Main loop for SPEs: Get a command, execute it, repeat.
676 */
677 void
678 command_loop(void)
679 {
680 int exitFlag = 0;
681
682 D_PRINTF(CELL_DEBUG_CMD, "Enter command loop\n");
683
684 while (!exitFlag) {
685 unsigned opcode;
686
687 D_PRINTF(CELL_DEBUG_CMD, "Wait for cmd...\n");
688
689 /* read/wait from mailbox */
690 opcode = (unsigned int) spu_read_in_mbox();
691 D_PRINTF(CELL_DEBUG_CMD, "got cmd 0x%x\n", opcode);
692
693 switch (opcode & CELL_CMD_OPCODE_MASK) {
694 case CELL_CMD_EXIT:
695 D_PRINTF(CELL_DEBUG_CMD, "EXIT\n");
696 exitFlag = 1;
697 break;
698 case CELL_CMD_VS_EXECUTE:
699 #if 0
700 spu_execute_vertex_shader(&draw, &cmd.vs);
701 #endif
702 break;
703 case CELL_CMD_BATCH:
704 cmd_batch(opcode);
705 break;
706 default:
707 printf("Bad opcode 0x%x!\n", opcode & CELL_CMD_OPCODE_MASK);
708 }
709
710 }
711
712 D_PRINTF(CELL_DEBUG_CMD, "Exit command loop\n");
713
714 spu_dcache_report();
715 }