spu_main.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 
00028 
00029 /* main() for Cell SPU code */
00030 
00031 
00032 #include <stdio.h>
00033 #include <libmisc.h>
00034 
00035 #include "spu_main.h"
00036 #include "spu_render.h"
00037 #include "spu_per_fragment_op.h"
00038 #include "spu_texture.h"
00039 #include "spu_tile.h"
00040 //#include "spu_test.h"
00041 #include "spu_vertex_shader.h"
00042 #include "spu_dcache.h"
00043 #include "cell/common.h"
00044 #include "pipe/p_defines.h"
00045 
00046 
00047 /*
00048 helpful headers:
00049 /usr/lib/gcc/spu/4.1.1/include/spu_mfcio.h
00050 /opt/cell/sdk/usr/include/libmisc.h
00051 */
00052 
00053 boolean Debug = FALSE;
00054 
00055 struct spu_global spu;
00056 
00057 struct spu_vs_context draw;
00058 
00059 
00063 static unsigned char attribute_fetch_code_buffer[136 * PIPE_MAX_ATTRIBS]
00064     ALIGN16_ATTRIB;
00065 
00066 
00067 
00074 static void
00075 release_buffer(uint buffer)
00076 {
00077    /* Evidently, using less than a 16-byte status doesn't work reliably */
00078    static const uint status[4] ALIGN16_ATTRIB
00079       = {CELL_BUFFER_STATUS_FREE, 0, 0, 0};
00080 
00081    const uint index = 4 * (spu.init.id * CELL_NUM_BUFFERS + buffer);
00082    uint *dst = spu.init.buffer_status + index;
00083 
00084    ASSERT(buffer < CELL_NUM_BUFFERS);
00085 
00086    mfc_put((void *) &status,    /* src in local memory */
00087            (unsigned int) dst,  /* dst in main memory */
00088            sizeof(status),      /* size */
00089            TAG_MISC,            /* tag is unimportant */
00090            0, /* tid */
00091            0  /* rid */);
00092 }
00093 
00094 
00099 static void
00100 really_clear_tiles(uint surfaceIndex)
00101 {
00102    const uint num_tiles = spu.fb.width_tiles * spu.fb.height_tiles;
00103    uint i;
00104 
00105    if (surfaceIndex == 0) {
00106       clear_c_tile(&spu.ctile);
00107 
00108       for (i = spu.init.id; i < num_tiles; i += spu.init.num_spus) {
00109          uint tx = i % spu.fb.width_tiles;
00110          uint ty = i / spu.fb.width_tiles;
00111          if (spu.ctile_status[ty][tx] == TILE_STATUS_CLEAR) {
00112             put_tile(tx, ty, &spu.ctile, TAG_SURFACE_CLEAR, 0);
00113          }
00114       }
00115    }
00116    else {
00117       clear_z_tile(&spu.ztile);
00118 
00119       for (i = spu.init.id; i < num_tiles; i += spu.init.num_spus) {
00120          uint tx = i % spu.fb.width_tiles;
00121          uint ty = i / spu.fb.width_tiles;
00122          if (spu.ztile_status[ty][tx] == TILE_STATUS_CLEAR)
00123             put_tile(tx, ty, &spu.ctile, TAG_SURFACE_CLEAR, 1);
00124       }
00125    }
00126 
00127 #if 0
00128    wait_on_mask(1 << TAG_SURFACE_CLEAR);
00129 #endif
00130 }
00131 
00132 
00133 static void
00134 cmd_clear_surface(const struct cell_command_clear_surface *clear)
00135 {
00136    if (Debug)
00137       printf("SPU %u: CLEAR SURF %u to 0x%08x\n", spu.init.id,
00138              clear->surface, clear->value);
00139 
00140    if (clear->surface == 0) {
00141       spu.fb.color_clear_value = clear->value;
00142       if (spu.init.debug_flags & CELL_DEBUG_CHECKER) {
00143          uint x = (spu.init.id << 4) | (spu.init.id << 12) |
00144             (spu.init.id << 20) | (spu.init.id << 28);
00145          spu.fb.color_clear_value ^= x;
00146       }
00147    }
00148    else {
00149       spu.fb.depth_clear_value = clear->value;
00150    }
00151 
00152 #define CLEAR_OPT 1
00153 #if CLEAR_OPT
00154 
00155    /* Simply set all tiles' status to CLEAR.
00156     * When we actually begin rendering into a tile, we'll initialize it to
00157     * the clear value.  If any tiles go untouched during the frame,
00158     * really_clear_tiles() will set them to the clear value.
00159     */
00160    if (clear->surface == 0) {
00161       memset(spu.ctile_status, TILE_STATUS_CLEAR, sizeof(spu.ctile_status));
00162    }
00163    else {
00164       memset(spu.ztile_status, TILE_STATUS_CLEAR, sizeof(spu.ztile_status));
00165    }
00166 
00167 #else
00168 
00169    /*
00170     * This path clears the whole framebuffer to the clear color right now.
00171     */
00172 
00173    /*
00174    printf("SPU: %s num=%d w=%d h=%d\n",
00175           __FUNCTION__, num_tiles, spu.fb.width_tiles, spu.fb.height_tiles);
00176    */
00177 
00178    /* init a single tile to the clear value */
00179    if (clear->surface == 0) {
00180       clear_c_tile(&spu.ctile);
00181    }
00182    else {
00183       clear_z_tile(&spu.ztile);
00184    }
00185 
00186    /* walk over my tiles, writing the 'clear' tile's data */
00187    {
00188       const uint num_tiles = spu.fb.width_tiles * spu.fb.height_tiles;
00189       uint i;
00190       for (i = spu.init.id; i < num_tiles; i += spu.init.num_spus) {
00191          uint tx = i % spu.fb.width_tiles;
00192          uint ty = i / spu.fb.width_tiles;
00193          if (clear->surface == 0)
00194             put_tile(tx, ty, &spu.ctile, TAG_SURFACE_CLEAR, 0);
00195          else
00196             put_tile(tx, ty, &spu.ztile, TAG_SURFACE_CLEAR, 1);
00197       }
00198    }
00199 
00200    if (spu.init.debug_flags & CELL_DEBUG_SYNC) {
00201       wait_on_mask(1 << TAG_SURFACE_CLEAR);
00202    }
00203 
00204 #endif /* CLEAR_OPT */
00205 
00206    if (Debug)
00207       printf("SPU %u: CLEAR SURF done\n", spu.init.id);
00208 }
00209 
00210 
00211 static void
00212 cmd_release_verts(const struct cell_command_release_verts *release)
00213 {
00214    if (Debug)
00215       printf("SPU %u: RELEASE VERTS %u\n",
00216              spu.init.id, release->vertex_buf);
00217    ASSERT(release->vertex_buf != ~0U);
00218    release_buffer(release->vertex_buf);
00219 }
00220 
00221 
00228 static void
00229 cmd_state_fragment_ops(const struct cell_command_fragment_ops *fops)
00230 {
00231    if (Debug)
00232       printf("SPU %u: CMD_STATE_FRAGMENT_OPS\n", spu.init.id);
00233    /* Copy SPU code from batch buffer to spu buffer */
00234    memcpy(spu.fragment_ops_code, fops->code, SPU_MAX_FRAGMENT_OPS_INSTS * 4);
00235    /* Copy state info (for fallback case only) */
00236    memcpy(&spu.depth_stencil_alpha, &fops->dsa, sizeof(fops->dsa));
00237    memcpy(&spu.blend, &fops->blend, sizeof(fops->blend));
00238 
00239    /* Point function pointer at new code */
00240    spu.fragment_ops = (spu_fragment_ops_func) spu.fragment_ops_code;
00241 
00242    spu.read_depth = spu.depth_stencil_alpha.depth.enabled;
00243    spu.read_stencil = spu.depth_stencil_alpha.stencil[0].enabled;
00244 }
00245 
00246 
00247 static void
00248 cmd_state_fragment_program(const struct cell_command_fragment_program *fp)
00249 {
00250    if (Debug)
00251       printf("SPU %u: CMD_STATE_FRAGMENT_PROGRAM\n", spu.init.id);
00252    /* Copy SPU code from batch buffer to spu buffer */
00253    memcpy(spu.fragment_program_code, fp->code,
00254           SPU_MAX_FRAGMENT_PROGRAM_INSTS * 4);
00255 #if 01
00256    /* Point function pointer at new code */
00257    spu.fragment_program = (spu_fragment_program_func)spu.fragment_program_code;
00258 #endif
00259 }
00260 
00261 
00262 static void
00263 cmd_state_framebuffer(const struct cell_command_framebuffer *cmd)
00264 {
00265    if (Debug)
00266       printf("SPU %u: FRAMEBUFFER: %d x %d at %p, cformat 0x%x  zformat 0x%x\n",
00267              spu.init.id,
00268              cmd->width,
00269              cmd->height,
00270              cmd->color_start,
00271              cmd->color_format,
00272              cmd->depth_format);
00273 
00274    ASSERT_ALIGN16(cmd->color_start);
00275    ASSERT_ALIGN16(cmd->depth_start);
00276 
00277    spu.fb.color_start = cmd->color_start;
00278    spu.fb.depth_start = cmd->depth_start;
00279    spu.fb.color_format = cmd->color_format;
00280    spu.fb.depth_format = cmd->depth_format;
00281    spu.fb.width = cmd->width;
00282    spu.fb.height = cmd->height;
00283    spu.fb.width_tiles = (spu.fb.width + TILE_SIZE - 1) / TILE_SIZE;
00284    spu.fb.height_tiles = (spu.fb.height + TILE_SIZE - 1) / TILE_SIZE;
00285 
00286    switch (spu.fb.depth_format) {
00287    case PIPE_FORMAT_Z32_UNORM:
00288       spu.fb.zsize = 4;
00289       spu.fb.zscale = (float) 0xffffffffu;
00290       break;
00291    case PIPE_FORMAT_Z24S8_UNORM:
00292    case PIPE_FORMAT_S8Z24_UNORM:
00293    case PIPE_FORMAT_Z24X8_UNORM:
00294    case PIPE_FORMAT_X8Z24_UNORM:
00295       spu.fb.zsize = 4;
00296       spu.fb.zscale = (float) 0x00ffffffu;
00297       break;
00298    case PIPE_FORMAT_Z16_UNORM:
00299       spu.fb.zsize = 2;
00300       spu.fb.zscale = (float) 0xffffu;
00301       break;
00302    default:
00303       spu.fb.zsize = 0;
00304       break;
00305    }
00306 }
00307 
00308 
00309 static void
00310 cmd_state_sampler(const struct cell_command_sampler *sampler)
00311 {
00312    if (Debug)
00313       printf("SPU %u: SAMPLER [%u]\n",
00314              spu.init.id, sampler->unit);
00315 
00316    spu.sampler[sampler->unit] = sampler->state;
00317    if (spu.sampler[sampler->unit].min_img_filter == PIPE_TEX_FILTER_LINEAR)
00318       spu.sample_texture[sampler->unit] = sample_texture_bilinear;
00319    else
00320       spu.sample_texture[sampler->unit] = sample_texture_nearest;
00321 }
00322 
00323 
00324 static void
00325 cmd_state_texture(const struct cell_command_texture *texture)
00326 {
00327    const uint unit = texture->unit;
00328    const uint width = texture->width;
00329    const uint height = texture->height;
00330 
00331    if (Debug) {
00332       printf("SPU %u: TEXTURE [%u] at %p  size %u x %u\n", spu.init.id,
00333              texture->unit, texture->start,
00334              texture->width, texture->height);
00335    }
00336 
00337    spu.texture[unit].start = texture->start;
00338    spu.texture[unit].width = width;
00339    spu.texture[unit].height = height;
00340 
00341    spu.texture[unit].tiles_per_row = width / TILE_SIZE;
00342 
00343    spu.texture[unit].tex_size = (vector float) { width, height, 0.0, 0.0};
00344    spu.texture[unit].tex_size_mask = (vector unsigned int)
00345          { width - 1, height - 1, 0, 0 };
00346    spu.texture[unit].tex_size_x_mask = spu_splats(width - 1);
00347    spu.texture[unit].tex_size_y_mask = spu_splats(height - 1);
00348 }
00349 
00350 
00351 static void
00352 cmd_state_vertex_info(const struct vertex_info *vinfo)
00353 {
00354    if (Debug) {
00355       printf("SPU %u: VERTEX_INFO num_attribs=%u\n", spu.init.id,
00356              vinfo->num_attribs);
00357    }
00358    ASSERT(vinfo->num_attribs >= 1);
00359    ASSERT(vinfo->num_attribs <= 8);
00360    memcpy(&spu.vertex_info, vinfo, sizeof(*vinfo));
00361 }
00362 
00363 
00364 static void
00365 cmd_state_vs_array_info(const struct cell_array_info *vs_info)
00366 {
00367    const unsigned attr = vs_info->attr;
00368 
00369    ASSERT(attr < PIPE_MAX_ATTRIBS);
00370    draw.vertex_fetch.src_ptr[attr] = vs_info->base;
00371    draw.vertex_fetch.pitch[attr] = vs_info->pitch;
00372    draw.vertex_fetch.size[attr] = vs_info->size;
00373    draw.vertex_fetch.code_offset[attr] = vs_info->function_offset;
00374    draw.vertex_fetch.dirty = 1;
00375 }
00376 
00377 
00378 static void
00379 cmd_state_attrib_fetch(const struct cell_attribute_fetch_code *code)
00380 {
00381    mfc_get(attribute_fetch_code_buffer,
00382            (unsigned int) code->base,  /* src */
00383            code->size,
00384            TAG_BATCH_BUFFER,
00385            0, /* tid */
00386            0  /* rid */);
00387    wait_on_mask(1 << TAG_BATCH_BUFFER);
00388 
00389    draw.vertex_fetch.code = attribute_fetch_code_buffer;
00390 }
00391 
00392 
00393 static void
00394 cmd_finish(void)
00395 {
00396    if (Debug)
00397       printf("SPU %u: FINISH\n", spu.init.id);
00398    really_clear_tiles(0);
00399    /* wait for all outstanding DMAs to finish */
00400    mfc_write_tag_mask(~0);
00401    mfc_read_tag_status_all();
00402    /* send mbox message to PPU */
00403    spu_write_out_mbox(CELL_CMD_FINISH);
00404 }
00405 
00406 
00413 static void
00414 cmd_batch(uint opcode)
00415 {
00416    const uint buf = (opcode >> 8) & 0xff;
00417    uint size = (opcode >> 16);
00418    uint64_t buffer[CELL_BUFFER_SIZE / 8] ALIGN16_ATTRIB;
00419    const unsigned usize = size / sizeof(buffer[0]);
00420    uint pos;
00421 
00422    if (Debug)
00423       printf("SPU %u: BATCH buffer %u, len %u, from %p\n",
00424              spu.init.id, buf, size, spu.init.buffers[buf]);
00425 
00426    ASSERT((opcode & CELL_CMD_OPCODE_MASK) == CELL_CMD_BATCH);
00427 
00428    ASSERT_ALIGN16(spu.init.buffers[buf]);
00429 
00430    size = ROUNDUP16(size);
00431 
00432    ASSERT_ALIGN16(spu.init.buffers[buf]);
00433 
00434    mfc_get(buffer,  /* dest */
00435            (unsigned int) spu.init.buffers[buf],  /* src */
00436            size,
00437            TAG_BATCH_BUFFER,
00438            0, /* tid */
00439            0  /* rid */);
00440    wait_on_mask(1 << TAG_BATCH_BUFFER);
00441 
00442    /* Tell PPU we're done copying the buffer to local store */
00443    if (Debug)
00444       printf("SPU %u: release batch buf %u\n", spu.init.id, buf);
00445    release_buffer(buf);
00446 
00447    /*
00448     * Loop over commands in the batch buffer
00449     */
00450    for (pos = 0; pos < usize; /* no incr */) {
00451       switch (buffer[pos]) {
00452       /*
00453        * rendering commands
00454        */
00455       case CELL_CMD_CLEAR_SURFACE:
00456          {
00457             struct cell_command_clear_surface *clr
00458                = (struct cell_command_clear_surface *) &buffer[pos];
00459             cmd_clear_surface(clr);
00460             pos += sizeof(*clr) / 8;
00461          }
00462          break;
00463       case CELL_CMD_RENDER:
00464          {
00465             struct cell_command_render *render
00466                = (struct cell_command_render *) &buffer[pos];
00467             uint pos_incr;
00468             cmd_render(render, &pos_incr);
00469             pos += pos_incr;
00470          }
00471          break;
00472       /*
00473        * state-update commands
00474        */
00475       case CELL_CMD_STATE_FRAMEBUFFER:
00476          {
00477             struct cell_command_framebuffer *fb
00478                = (struct cell_command_framebuffer *) &buffer[pos];
00479             cmd_state_framebuffer(fb);
00480             pos += sizeof(*fb) / 8;
00481          }
00482          break;
00483       case CELL_CMD_STATE_FRAGMENT_OPS:
00484          {
00485             struct cell_command_fragment_ops *fops
00486                = (struct cell_command_fragment_ops *) &buffer[pos];
00487             cmd_state_fragment_ops(fops);
00488             pos += sizeof(*fops) / 8;
00489          }
00490          break;
00491       case CELL_CMD_STATE_FRAGMENT_PROGRAM:
00492          {
00493             struct cell_command_fragment_program *fp
00494                = (struct cell_command_fragment_program *) &buffer[pos];
00495             cmd_state_fragment_program(fp);
00496             pos += sizeof(*fp) / 8;
00497          }
00498          break;
00499       case CELL_CMD_STATE_SAMPLER:
00500          {
00501             struct cell_command_sampler *sampler
00502                = (struct cell_command_sampler *) &buffer[pos];
00503             cmd_state_sampler(sampler);
00504             pos += sizeof(*sampler) / 8;
00505          }
00506          break;
00507       case CELL_CMD_STATE_TEXTURE:
00508          {
00509             struct cell_command_texture *texture
00510                = (struct cell_command_texture *) &buffer[pos];
00511             cmd_state_texture(texture);
00512             pos += sizeof(*texture) / 8;
00513          }
00514          break;
00515       case CELL_CMD_STATE_VERTEX_INFO:
00516          cmd_state_vertex_info((struct vertex_info *) &buffer[pos+1]);
00517          pos += (1 + ROUNDUP8(sizeof(struct vertex_info)) / 8);
00518          break;
00519       case CELL_CMD_STATE_VIEWPORT:
00520          (void) memcpy(& draw.viewport, &buffer[pos+1],
00521                        sizeof(struct pipe_viewport_state));
00522          pos += (1 + ROUNDUP8(sizeof(struct pipe_viewport_state)) / 8);
00523          break;
00524       case CELL_CMD_STATE_UNIFORMS:
00525          draw.constants = (const float (*)[4]) (uintptr_t) buffer[pos + 1];
00526          pos += 2;
00527          break;
00528       case CELL_CMD_STATE_VS_ARRAY_INFO:
00529          cmd_state_vs_array_info((struct cell_array_info *) &buffer[pos+1]);
00530          pos += (1 + ROUNDUP8(sizeof(struct cell_array_info)) / 8);
00531          break;
00532       case CELL_CMD_STATE_BIND_VS:
00533 #if 0
00534          spu_bind_vertex_shader(&draw,
00535                                 (struct cell_shader_info *) &buffer[pos+1]);
00536 #endif
00537          pos += (1 + ROUNDUP8(sizeof(struct cell_shader_info)) / 8);
00538          break;
00539       case CELL_CMD_STATE_ATTRIB_FETCH:
00540          cmd_state_attrib_fetch((struct cell_attribute_fetch_code *)
00541                                 &buffer[pos+1]);
00542          pos += (1 + ROUNDUP8(sizeof(struct cell_attribute_fetch_code)) / 8);
00543          break;
00544       /*
00545        * misc commands
00546        */
00547       case CELL_CMD_FINISH:
00548          cmd_finish();
00549          pos += 1;
00550          break;
00551       case CELL_CMD_RELEASE_VERTS:
00552          {
00553             struct cell_command_release_verts *release
00554                = (struct cell_command_release_verts *) &buffer[pos];
00555             cmd_release_verts(release);
00556             pos += sizeof(*release) / 8;
00557          }
00558          break;
00559       case CELL_CMD_FLUSH_BUFFER_RANGE: {
00560          struct cell_buffer_range *br = (struct cell_buffer_range *)
00561              &buffer[pos+1];
00562 
00563          spu_dcache_mark_dirty((unsigned) br->base, br->size);
00564          pos += (1 + ROUNDUP8(sizeof(struct cell_buffer_range)) / 8);
00565          break;
00566       }
00567       default:
00568          printf("SPU %u: bad opcode: 0x%llx\n", spu.init.id, buffer[pos]);
00569          ASSERT(0);
00570          break;
00571       }
00572    }
00573 
00574    if (Debug)
00575       printf("SPU %u: BATCH complete\n", spu.init.id);
00576 }
00577 
00578 
00582 static void
00583 main_loop(void)
00584 {
00585    struct cell_command cmd;
00586    int exitFlag = 0;
00587 
00588    if (Debug)
00589       printf("SPU %u: Enter main loop\n", spu.init.id);
00590 
00591    ASSERT((sizeof(struct cell_command) & 0xf) == 0);
00592    ASSERT_ALIGN16(&cmd);
00593 
00594    while (!exitFlag) {
00595       unsigned opcode;
00596       int tag = 0;
00597 
00598       if (Debug)
00599          printf("SPU %u: Wait for cmd...\n", spu.init.id);
00600 
00601       /* read/wait from mailbox */
00602       opcode = (unsigned int) spu_read_in_mbox();
00603 
00604       if (Debug)
00605          printf("SPU %u: got cmd 0x%x\n", spu.init.id, opcode);
00606 
00607       /* command payload */
00608       mfc_get(&cmd,  /* dest */
00609               (unsigned int) spu.init.cmd, /* src */
00610               sizeof(struct cell_command), /* bytes */
00611               tag,
00612               0, /* tid */
00613               0  /* rid */);
00614       wait_on_mask( 1 << tag );
00615 
00616       /*
00617        * NOTE: most commands should be contained in a batch buffer
00618        */
00619 
00620       switch (opcode & CELL_CMD_OPCODE_MASK) {
00621       case CELL_CMD_EXIT:
00622          if (Debug)
00623             printf("SPU %u: EXIT\n", spu.init.id);
00624          exitFlag = 1;
00625          break;
00626       case CELL_CMD_VS_EXECUTE:
00627 #if 0
00628          spu_execute_vertex_shader(&draw, &cmd.vs);
00629 #endif
00630          break;
00631       case CELL_CMD_BATCH:
00632          cmd_batch(opcode);
00633          break;
00634       default:
00635          printf("Bad opcode!\n");
00636       }
00637 
00638    }
00639 
00640    if (Debug)
00641       printf("SPU %u: Exit main loop\n", spu.init.id);
00642 
00643    spu_dcache_report();
00644 }
00645 
00646 
00647 
00648 static void
00649 one_time_init(void)
00650 {
00651    memset(spu.ctile_status, TILE_STATUS_DEFINED, sizeof(spu.ctile_status));
00652    memset(spu.ztile_status, TILE_STATUS_DEFINED, sizeof(spu.ztile_status));
00653    invalidate_tex_cache();
00654 
00655    /* Install default/fallback fragment processing function.
00656     * This will normally be overriden by a code-gen'd function.
00657     */
00658    spu.fragment_ops = spu_fallback_fragment_ops;
00659 }
00660 
00661 
00662 
00663 /* In some versions of the SDK the SPE main takes 'unsigned long' as a
00664  * parameter.  In others it takes 'unsigned long long'.  Use a define to
00665  * select between the two.
00666  */
00667 #ifdef SPU_MAIN_PARAM_LONG_LONG
00668 typedef unsigned long long main_param_t;
00669 #else
00670 typedef unsigned long main_param_t;
00671 #endif
00672 
00676 int
00677 main(main_param_t speid, main_param_t argp)
00678 {
00679    int tag = 0;
00680 
00681    (void) speid;
00682 
00683    ASSERT(sizeof(tile_t) == TILE_SIZE * TILE_SIZE * 4);
00684    ASSERT(sizeof(struct cell_command_render) % 8 == 0);
00685 
00686    one_time_init();
00687 
00688    if (Debug)
00689       printf("SPU: main() speid=%lu\n", (unsigned long) speid);
00690 
00691    mfc_get(&spu.init,  /* dest */
00692            (unsigned int) argp, /* src */
00693            sizeof(struct cell_init_info), /* bytes */
00694            tag,
00695            0, /* tid */
00696            0  /* rid */);
00697    wait_on_mask( 1 << tag );
00698 
00699 #if 0
00700    if (spu.init.id==0)
00701       spu_test_misc();
00702 #endif
00703 
00704    main_loop();
00705 
00706    return 0;
00707 }

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