static void BackgroundCorrectGetMatrices(IceTDouble *projection_matrix,
                                         IceTDouble *modelview_matrix)
{
    IceTDouble scale_matrix[16];
    IceTDouble transform_matrix[16];
    IceTInt num_proc;
    IceTInt rank;

    icetGetIntegerv(ICET_NUM_PROCESSES, &num_proc);
    icetGetIntegerv(ICET_RANK, &rank);

    /* Make the projection really project pixel positions to normalized clipping
       coordinates. */
    icetMatrixScale(2.0/PROC_REGION_WIDTH,
                    2.0/(PROC_REGION_HEIGHT*(num_proc+1)),
                    2.0,
                    scale_matrix);
    icetMatrixTranslate(-1.0, -1.0, -1.0, transform_matrix);
    icetMatrixMultiply(projection_matrix, transform_matrix, scale_matrix);

    /* The modelview just passes pixel positions. */
    icetMatrixIdentity(modelview_matrix);

    /* Based on these matrices, set the region we want the local process to draw
       pixels.  The region is defined in pixels.  The previous matrices
       transform the pixels to screen coordinates, which should then implicitly
       be transformed back to pixel coordinates in the draw function. */
    icetBoundingBoxd(0.0,
                     (IceTDouble)PROC_REGION_WIDTH,
                     (IceTDouble)rank*PROC_REGION_HEIGHT,
                     (IceTDouble)(rank+1)*PROC_REGION_HEIGHT,
                     0.0,
                     1.0);
}
static int BackgroundCorrectCheckImage(const IceTImage image)
{
    IceTInt rank;

    icetGetIntegerv(ICET_RANK, &rank);
    if (rank == 0) {
        IceTInt num_proc;
        IceTInt proc;
        const IceTFloat *pixel;

        icetGetIntegerv(ICET_NUM_PROCESSES, &num_proc);

        pixel = icetImageGetColorcf(image);

        for (proc = 0; proc < num_proc; proc++) {
            if (!BackgroundCorrectCheckImageRegion(&pixel, g_blended_color)) {
                printrank("For process %d\n", proc);
                if (ColorsEqual(pixel, g_foreground_color)) {
                    printrank("Pixel never blended with background.\n");
                }
                return TEST_FAILED;
            }
        }

        /* Also check a final patch on top that should be background. */
        if (!BackgroundCorrectCheckImageRegion(&pixel, g_background_color)) {
            printrank("For background area\n");
            return TEST_FAILED;
        }
    }

    return TEST_PASSED;
}
Beispiel #3
0
static IceTImage drawInvokeStrategy(void)
{
    IceTImage image;
    IceTVoid *value;
    IceTEnum strategy;
    IceTInt display_tile;
    IceTInt valid_tile;

    icetGetPointerv(ICET_DRAW_FUNCTION, &value);
    if (value == NULL) {
        icetRaiseError("Drawing function not set.  Call icetDrawCallback.",
                       ICET_INVALID_OPERATION);
        return icetImageNull();
    }

    icetRaiseDebug("Calling strategy");
    icetStateSetBoolean(ICET_IS_DRAWING_FRAME, 1);
    icetGetEnumv(ICET_STRATEGY, &strategy);
    image = icetInvokeStrategy(strategy);

    icetStateSetBoolean(ICET_IS_DRAWING_FRAME, 0);

    /* Ensure that the returned image is the expected size. */
    icetGetIntegerv(ICET_VALID_PIXELS_TILE, &valid_tile);
    icetGetIntegerv(ICET_TILE_DISPLAYED, &display_tile);
    if ((valid_tile != display_tile) && icetIsEnabled(ICET_COLLECT_IMAGES)) {
        icetRaiseDebug2("Display tile: %d, valid tile: %d",
                        display_tile, valid_tile);
        icetRaiseError("Got unexpected tile from strategy.",
                       ICET_SANITY_CHECK_FAIL);
    }
    if (valid_tile >= 0) {
        const IceTInt *valid_tile_viewport
            = icetUnsafeStateGetInteger(ICET_TILE_VIEWPORTS) + 4*valid_tile;
        if (   (valid_tile_viewport[2] != icetImageGetWidth(image))
            || (valid_tile_viewport[3] != icetImageGetHeight(image)) ) {
            IceTInt valid_offset;
            IceTInt valid_num;
            icetRaiseDebug1("Tile returned from strategy: %d\n", valid_tile);
            icetRaiseDebug4("Expected size: %d %d.  Returned size: %d %d",
                            valid_tile_viewport[2], valid_tile_viewport[3],
                            (int)icetImageGetWidth(image),
                            (int)icetImageGetHeight(image));
            icetGetIntegerv(ICET_VALID_PIXELS_OFFSET, &valid_offset);
            icetGetIntegerv(ICET_VALID_PIXELS_NUM, &valid_num);
            icetRaiseDebug2("Reported pixel offset: %d.  Reported pixel count: %d",
                            valid_offset, valid_num);
            icetRaiseError("Got unexpected image size from strategy.",
                           ICET_SANITY_CHECK_FAIL);
        }
    }

    icetStateCheckMemory();

    return image;
}
Beispiel #4
0
void icetProjectTile(IceTInt tile, IceTDouble *mat_out)
{
    IceTInt num_tiles;
    const IceTInt *viewports;
    const IceTDouble *tile_projections;
    IceTInt tile_width, tile_height;
    IceTInt renderable_width, renderable_height;
    const IceTDouble *tile_proj;
    IceTDouble tile_viewport_proj[16];
    const IceTDouble *global_proj;

  /* Update tile projections. */
    update_tile_projections();

    icetGetIntegerv(ICET_NUM_TILES, &num_tiles);
    if ((tile < 0) || (tile >= num_tiles)) {
        icetRaiseError("Bad tile passed to icetProjectTile.",
                       ICET_INVALID_VALUE);
        return;
    }

    viewports = icetUnsafeStateGetInteger(ICET_TILE_VIEWPORTS);
    tile_width = viewports[tile*4+2];
    tile_height = viewports[tile*4+3];
    icetGetIntegerv(ICET_PHYSICAL_RENDER_WIDTH, &renderable_width);
    icetGetIntegerv(ICET_PHYSICAL_RENDER_HEIGHT, &renderable_height);
    tile_projections = icetUnsafeStateGetDouble(ICET_TILE_PROJECTIONS);

    tile_proj = tile_projections + 16*tile;

    if ((renderable_width != tile_width) || (renderable_height != tile_height)){
      /* Compensate for fact that tile is smaller than actual window.
         Use an orthographic projection to place the tile in the lower left
         corner of the tile. */
        IceTDouble viewport_proj[16];
        icetMatrixOrtho(-1.0, 2.0*renderable_width/tile_width - 1.0,
                        -1.0, 2.0*renderable_height/tile_height - 1.0,
                        1.0, -1.0, viewport_proj);

        icetMatrixMultiply(tile_viewport_proj,
                           (const IceTDouble *)viewport_proj,
                           (const IceTDouble *)tile_proj);
    } else {
        memcpy(tile_viewport_proj, (const IceTDouble*)tile_proj,
               16*sizeof(IceTDouble));
    }

  /* Project the user requested view to the tile projection. */
    global_proj = icetUnsafeStateGetDouble(ICET_PROJECTION_MATRIX);
    icetMatrixMultiply(mat_out,
                       (const IceTDouble *)tile_viewport_proj,
                       (const IceTDouble *)global_proj);
}
Beispiel #5
0
void icetDataReplicationGroupColor(IceTInt color)
{
    IceTInt *allcolors;
    IceTInt *mygroup;
    IceTInt num_proc;
    IceTInt i;
    IceTInt size;

    icetGetIntegerv(ICET_NUM_PROCESSES, &num_proc);

    /* Just grab two buffers that should be not be used now.  We will be
       done with them by the time we return from this function. */
    allcolors = icetGetStateBuffer(ICET_STRATEGY_BUFFER_0,
                                   sizeof(IceTInt)*num_proc);
    mygroup = icetGetStateBuffer(ICET_STRATEGY_BUFFER_1,
                                 sizeof(IceTInt)*num_proc);

    icetCommAllgather(&color, 1, ICET_INT, allcolors);

    size = 0;
    for (i = 0; i < num_proc; i++) {
        if (allcolors[i] == color) {
            mygroup[size] = i;
            size++;
        }
    }

    icetDataReplicationGroup(size, mygroup);
}
Beispiel #6
0
static void drawDetermineContainedTiles(const IceTInt contained_viewport[4],
                                        IceTDouble znear, IceTDouble zfar,
                                        IceTInt *contained_list,
                                        IceTBoolean *contained_mask,
                                        IceTInt *num_contained_p)
{
    const IceTInt *tile_viewports;
    IceTInt num_tiles;
    int i;

    tile_viewports = icetUnsafeStateGetInteger(ICET_TILE_VIEWPORTS);
    icetGetIntegerv(ICET_NUM_TILES, &num_tiles);

    *num_contained_p = 0;
    memset(contained_mask, 0, sizeof(IceTBoolean)*num_tiles);
    for (i = 0; i < num_tiles; i++) {
        if (   (znear  <= 1.0)
            && (zfar   >= -1.0)
            && (  contained_viewport[0]
                < tile_viewports[i*4+0] + tile_viewports[i*4+2])
            && (  contained_viewport[0] + contained_viewport[2]
                > tile_viewports[i*4+0])
            && (  contained_viewport[1]
                < tile_viewports[i*4+1] + tile_viewports[i*4+3])
            && (  contained_viewport[1] + contained_viewport[3]
                > tile_viewports[i*4+1]) ) {
            contained_list[*num_contained_p] = i;
            contained_mask[i] = 1;
            (*num_contained_p)++;
        }
    }
}
static int DisplayNoDrawRun(void)
{
    int strategy_index;

    icetGetIntegerv(ICET_RANK, &global_rank);
    icetGetIntegerv(ICET_NUM_PROCESSES, &global_num_proc);

    printf("Starting DisplayNoDraw.\n");

    global_result = TEST_PASSED;

    DisplayNoDrawInit();

    for (strategy_index = 0;
         strategy_index < STRATEGY_LIST_SIZE; strategy_index++) {
        IceTEnum strategy = strategy_list[strategy_index];
        int single_image_strategy_index;
        int num_single_image_strategy;

        icetStrategy(strategy);
        printf("\n\nUsing %s strategy.\n", icetGetStrategyName());

        if (strategy_uses_single_image_strategy(strategy)) {
            num_single_image_strategy = SINGLE_IMAGE_STRATEGY_LIST_SIZE;
        } else {
          /* Set to one since single image strategy does not matter. */
            num_single_image_strategy = 1;
        }

        for (single_image_strategy_index = 0;
             single_image_strategy_index < num_single_image_strategy;
             single_image_strategy_index++) {
            IceTEnum single_image_strategy
                = single_image_strategy_list[single_image_strategy_index];

            icetSingleImageStrategy(single_image_strategy);
            printf("Using %s single image sub-strategy.\n",
                   icetGetSingleImageStrategyName());

            DisplayNoDrawDoTest();
        }
    }

    return global_result;
}
Beispiel #8
0
static void drawCollectTileInformation(void)
{
    IceTBoolean *all_contained_masks;
    IceTInt num_proc;
    IceTInt num_tiles;

    icetGetIntegerv(ICET_NUM_PROCESSES, &num_proc);
    icetGetIntegerv(ICET_NUM_TILES, &num_tiles);

    all_contained_masks
        = icetStateAllocateBoolean(ICET_ALL_CONTAINED_TILES_MASKS,
                                   num_tiles*num_proc);

    icetRaiseDebug("Gathering rendering information.");
    {
        const IceTBoolean *contained_mask;

        contained_mask = icetUnsafeStateGetBoolean(ICET_CONTAINED_TILES_MASK);

        icetCommAllgather(contained_mask, num_tiles, ICET_BYTE,
                          all_contained_masks);
    }

    {
        IceTInt *contrib_counts;
        IceTInt total_image_count;
        IceTInt tile_id;

        contrib_counts
            = icetStateAllocateInteger(ICET_TILE_CONTRIB_COUNTS, num_tiles);
        total_image_count = 0;
        for (tile_id = 0; tile_id < num_tiles; tile_id++) {
            IceTInt proc_id;
            contrib_counts[tile_id] = 0;
            for (proc_id = 0; proc_id < num_proc; proc_id++) {
                if (all_contained_masks[proc_id*num_tiles + tile_id]) {
                    contrib_counts[tile_id]++;
                }
            }
            total_image_count += contrib_counts[tile_id];
        }
        icetStateSetIntegerv(ICET_TOTAL_IMAGE_COUNT, 1, &total_image_count);
    }
}
Beispiel #9
0
void icetRenderTransferSparseImages(IceTSparseImage compositeImage1,
                                    IceTSparseImage compositeImage2,
                                    IceTVoid *inImageBuffer,
                                    IceTSparseImage outSparseImage,
                                    IceTInt *tile_image_dest,
                                    IceTSparseImage *resultImage)
{
    IceTInt num_sending;
    const IceTInt *tile_list;
    IceTInt num_tiles;
    IceTInt width, height;
    IceTInt *imageDestinations;

    IceTInt i;

    rtsi_workingImage = compositeImage1;
    rtsi_availableImage = compositeImage2;
    rtsi_outSparseImage = outSparseImage;
    rtsi_first = ICET_TRUE;

    icetGetIntegerv(ICET_NUM_CONTAINED_TILES, &num_sending);
    tile_list = icetUnsafeStateGetInteger(ICET_CONTAINED_TILES_LIST);
    icetGetIntegerv(ICET_TILE_MAX_WIDTH, &width);
    icetGetIntegerv(ICET_TILE_MAX_HEIGHT, &height);
    icetGetIntegerv(ICET_NUM_TILES, &num_tiles);

    imageDestinations = malloc(num_tiles * sizeof(IceTInt));

  /* Make each element imageDestinations point to the processor to send the
     corresponding image in tile_list. */
    for (i = 0; i < num_sending; i++) {
        imageDestinations[i] = tile_image_dest[tile_list[i]];
    }

    icetSendRecvLargeMessages(num_sending, imageDestinations,
                              icetIsEnabled(ICET_ORDERED_COMPOSITE),
                              rtsi_generateDataFunc, rtsi_handleDataFunc,
                              inImageBuffer,
                              icetSparseImageBufferSize(width, height));

    *resultImage = rtsi_workingImage;

    free(imageDestinations);
}
// ****************************************************************************
//  Function: SendImageToRenderNodes
//
//  Purpose: IceT distinguishes between `tile nodes' and `render nodes'.  All
//           nodes assist in image composition, but final images are only
//           collected on tile nodes.
//           Unfortunately various post-rendering algorithms in VisIt do not
//           make this distinction, which in IceT parlance means we assume all
//           nodes are tile nodes.  This method should send out the image to
//           all other nodes, so we can still utilize IceT by blurring that
//           distinction so that the rest of VisIt never knows.
//
//  Programmer: Tom Fogal
//  Creation:   August 7, 2008
//
// ****************************************************************************
static void
SendImageToRenderNodes(int width, int height, bool Z,
                       GLubyte * const pixels,
                       GLuint * const depth)
{
    GLint n_tiles, n_procs, rank;
    GLboolean have_image;

    ICET(icetGetIntegerv(ICET_NUM_TILES, &n_tiles));
    ICET(icetGetIntegerv(ICET_NUM_PROCESSES, &n_procs));
    ICET(icetGetIntegerv(ICET_RANK, &rank));
    ICET(icetGetBooleanv(ICET_COLOR_BUFFER_VALID, &have_image));

    //              4: assuming GL_RGBA.
    MPI_Bcast(pixels, 4*width*height, MPI_BYTE, 0, VISIT_MPI_COMM);
    if(Z) {
        MPI_Bcast(depth, width*height, MPI_UNSIGNED, 0, VISIT_MPI_COMM);
    }
}
Beispiel #11
0
static void update_tile_projections(void)
{
    GLint *viewports;
    int i;

    icetGetIntegerv(ICET_NUM_TILES, &num_tiles);
    free(tile_projections);
    tile_projections = malloc(num_tiles*16*sizeof(GLdouble));
    viewports = icetUnsafeStateGet(ICET_TILE_VIEWPORTS);

    for (i = 0; i < num_tiles; i++) {
        icetGetViewportProject(viewports[i*4+0], viewports[i*4+1],
                               viewports[i*4+2], viewports[i*4+3],
                               tile_projections + 16*i);
    }
}
Beispiel #12
0
void gl_destroy(void)
{
    IceTInt icet_texture;
    GLuint gl_texture;

    icetRaiseDebug("In OpenGL layer destructor.");

    icetGetIntegerv(ICET_GL_INFLATE_TEXTURE, &icet_texture);
    gl_texture = icet_texture;

    if (gl_texture != 0) {
        glDeleteTextures(1, &gl_texture);
    }

    icetStateSetInteger(ICET_GL_INFLATE_TEXTURE, 0);
}
static void BackgroundCorrectSetupRender()
{
    IceTInt num_proc;

    icetGetIntegerv(ICET_NUM_PROCESSES, &num_proc);

    icetCompositeMode(ICET_COMPOSITE_MODE_BLEND);
    icetSetColorFormat(ICET_IMAGE_COLOR_RGBA_FLOAT);
    icetSetDepthFormat(ICET_IMAGE_DEPTH_NONE);
    icetDisable(ICET_ORDERED_COMPOSITE);
    icetEnable(ICET_CORRECT_COLORED_BACKGROUND);

    icetDrawCallback(BackgroundCorrectDraw);

    icetResetTiles();
    icetAddTile(0, 0, PROC_REGION_WIDTH, PROC_REGION_HEIGHT*(num_proc+1), 0);
}
// ****************************************************************************
//  Method: utofv
//
//  Purpose: Converts a vector of unsigned integers to a vector of floats.  The
//           returned buffer is dynamically allocated, and should be delete[]d
//           by the caller.
//
//  Programmer: Tom Fogal
//  Creation:   July 2, 2008
//
//  Modifications:
//
//    Tom Fogal, Thu Jul 17 10:27:43 EDT 2008
//    lerp the IceT buffer onto the range [0,1] as we convert.  This seems to
//    be what the rest of VisIt expects.
//
//    Tom Fogal, Fri May 29 20:32:50 MDT 2009
//    Query the correct depth max from IceT.
//
// ****************************************************************************
static float *
utofv(const unsigned int * const src, size_t n_elem)
{
    float *res = new float[n_elem];
    unsigned int depth_max;
    {
      // IceT gives an unsigned int, but the accessor function only accepts
      // GLint.  We'll grab the latter and rely on a conversion to get the
      // correct type.
      GLint far_depth;
      icetGetIntegerv(ICET_ABSOLUTE_FAR_DEPTH, &far_depth);
      depth_max = far_depth;
    }
    for(size_t i=0; i < n_elem; ++i) {
        res[i] = lerp(src[i], 0U,depth_max, 0.0f,1.0f);
    }
    return res;
}
// ****************************************************************************
//  Method: VerifyColorFormat
//
//  Purpose: We currently expect GL_RGBA from IceT.  If it gives us something
//           different, we should bail out.
//
//  Programmer: Tom Fogal
//  Creation:   July 1, 2008
//
// ****************************************************************************
void
IceTNetworkManager::VerifyColorFormat() const
{
    GLint color_format;
    ICET(icetGetIntegerv(ICET_COLOR_FORMAT, &color_format));
    if(color_format != GL_RGBA)
    {
        const char *str;
        switch(color_format)
        {
            case GL_RGB: str = "GL_RGB"; break;
            case GL_BGR: str = "GL_BGR"; break;
            case GL_BGRA: str = "GL_BGRA"; break;
            default: str = "unexpected error case"; break;
        }
        EXCEPTION2(UnexpectedValueException, "GL_RGBA", std::string(str));
    }
}
Beispiel #16
0
static IceTVoid *rtfi_generateDataFunc(IceTInt id, IceTInt dest,
                                       IceTSizeType *size) {
    IceTInt rank;
    const IceTInt *tile_list
        = icetUnsafeStateGetInteger(ICET_CONTAINED_TILES_LIST);
    IceTVoid *outBuffer;

    icetGetIntegerv(ICET_RANK, &rank);
    if (dest == rank) {
      /* Special case: sending to myself.
         Just get directly to color and depth buffers. */
        icetGetTileImage(tile_list[id], rtfi_image);
        *size = 0;
        return NULL;
    }
    icetGetCompressedTileImage(tile_list[id], rtfi_outSparseImage);
    icetSparseImagePackageForSend(rtfi_outSparseImage, &outBuffer, size);
    return outBuffer;
}
Beispiel #17
0
static void rtsi_handleDataFunc(void *inSparseImageBuffer, IceTInt src) {
    if (inSparseImageBuffer == NULL) {
      /* Superfluous call from send to self. */
        if (!rtsi_first) {
            icetRaiseError("Unexpected callback order"
                           " in icetRenderTransferSparseImages.",
                           ICET_SANITY_CHECK_FAIL);
        }
    } else {
        IceTSparseImage inSparseImage
            = icetSparseImageUnpackageFromReceive(inSparseImageBuffer);
        if (rtsi_first) {
            IceTSizeType num_pixels
                = icetSparseImageGetNumPixels(inSparseImage);
            icetSparseImageCopyPixels(inSparseImage,
                                      0,
                                      num_pixels,
                                      rtsi_workingImage);
        } else {
            IceTInt rank;
            const IceTInt *process_orders;
            IceTSparseImage old_workingImage;

            icetGetIntegerv(ICET_RANK, &rank);
            process_orders = icetUnsafeStateGetInteger(ICET_PROCESS_ORDERS);
            if (process_orders[src] < process_orders[rank]) {
                icetCompressedCompressedComposite(inSparseImage,
                                                  rtsi_workingImage,
                                                  rtsi_availableImage);
            } else {
                icetCompressedCompressedComposite(rtsi_workingImage,
                                                  inSparseImage,
                                                  rtsi_availableImage);
            }

            old_workingImage = rtsi_workingImage;
            rtsi_workingImage = rtsi_availableImage;
            rtsi_availableImage = old_workingImage;
        }
    }
    rtsi_first = ICET_FALSE;
}
void write_ppm(const char *filename,
	       const GLubyte *image,
	       int width, int height)
{
    FILE *fd;
    int x, y;
    const unsigned char *color;
    GLint color_format;

    icetGetIntegerv(ICET_COLOR_FORMAT, &color_format);

    fd = fopen(filename, "wb");

    fprintf(fd, "P6\n");
    fprintf(fd, "# %s generated by ICE-T test suite.\n", filename);
    fprintf(fd, "%d %d\n", width, height);
    fprintf(fd, "255\n");

    for (y = height-1; y >= 0; y--) {
	color = image + y*width*4;
	for (x = 0; x < width; x++) {
	    switch (color_format) {
	      case GL_RGBA:
		  fwrite(color, 1, 3, fd);
		  break;
#ifdef GL_BGRA_EXT
	      case GL_BGRA_EXT:
		  fwrite(color+2, 1, 1, fd);
		  fwrite(color+1, 1, 1, fd);
		  fwrite(color+0, 1, 1, fd);
		  break;
#endif
	      default:
		  printf("Bad color format.\n");
		  return;
	    }
	    color += 4;
	}
    }

    fclose(fd);
}
Beispiel #19
0
void icetCompositeOrder(const IceTInt *process_ranks)
{
    IceTInt num_proc;
    IceTInt i;
    IceTInt *process_orders;

    icetGetIntegerv(ICET_NUM_PROCESSES, &num_proc);
    process_orders = icetStateAllocateInteger(ICET_PROCESS_ORDERS, num_proc);
    for (i = 0; i < num_proc; i++) {
        process_orders[i] = -1;
    }
    for (i = 0; i < num_proc; i++) {
        process_orders[process_ranks[i]] = i;
    }
    for (i = 0; i < num_proc; i++) {
        if (process_orders[i] == -1) {
            icetRaiseError("Invalid composite order.", ICET_INVALID_VALUE);
            return;
        }
    }
    icetStateSetIntegerv(ICET_COMPOSITE_ORDER, num_proc, process_ranks);
}
Beispiel #20
0
static void drawUseBackgroundColor(const IceTFloat *background_color)
{
    IceTUInt background_color_word;
    IceTBoolean use_color_blending
        = (IceTBoolean)(   *(icetUnsafeStateGetInteger(ICET_COMPOSITE_MODE))
                        == ICET_COMPOSITE_MODE_BLEND);

    ((IceTUByte *)&background_color_word)[0]
        = (IceTUByte)(255*background_color[0]);
    ((IceTUByte *)&background_color_word)[1]
        = (IceTUByte)(255*background_color[1]);
    ((IceTUByte *)&background_color_word)[2]
        = (IceTUByte)(255*background_color[2]);
    ((IceTUByte *)&background_color_word)[3]
        = (IceTUByte)(255*background_color[3]);

    icetStateSetFloatv(ICET_TRUE_BACKGROUND_COLOR, 4, background_color);
    icetStateSetInteger(ICET_TRUE_BACKGROUND_COLOR_WORD, background_color_word);

    if (use_color_blending) {
        IceTInt display_tile;
      /* We need to correct the background color by zeroing it out at
       * blending it back at the end. */
        icetStateSetFloatv(ICET_BACKGROUND_COLOR, 4, black);
        icetStateSetInteger(ICET_BACKGROUND_COLOR_WORD, 0);

        icetGetIntegerv(ICET_TILE_DISPLAYED, &display_tile);
        if (   (background_color_word != 0)
            && icetIsEnabled(ICET_CORRECT_COLORED_BACKGROUND) ) {
            icetStateSetBoolean(ICET_NEED_BACKGROUND_CORRECTION, ICET_TRUE);
        } else {
            icetStateSetBoolean(ICET_NEED_BACKGROUND_CORRECTION, ICET_FALSE);
        }
    } else {
        icetStateSetFloatv(ICET_BACKGROUND_COLOR, 4, background_color);
        icetStateSetInteger(ICET_BACKGROUND_COLOR_WORD, background_color_word);
        icetStateSetBoolean(ICET_NEED_BACKGROUND_CORRECTION, ICET_FALSE);
    }
}
Beispiel #21
0
static void icetSendRecvLargeBuildMessageMasks(
                                             IceTInt numMessagesSending,
                                             const IceTInt *messageDestinations,
                                             IceTInt **sendIds_p,
                                             IceTBoolean **myDestMask_p,
                                             IceTBoolean **mySrcMask_p)
{
    IceTInt comm_size;

    IceTInt *sendIds;
    IceTBoolean *myDestMask;
    IceTBoolean *mySrcMask;

    icetGetIntegerv(ICET_NUM_PROCESSES, &comm_size);

    sendIds = icetGetStateBuffer(ICET_SEND_RECV_LARGE_SEND_IDS_BUF,
                                 comm_size * sizeof(IceTInt));
    myDestMask = icetGetStateBuffer(ICET_SEND_RECV_LARGE_DEST_MASK_BUF,
                                    comm_size * sizeof(IceTBoolean));
    mySrcMask = icetGetStateBuffer(ICET_SEND_RECV_LARGE_SRC_MASK_BUF,
                                   comm_size * sizeof(IceTBoolean));

    /* Convert array of ranks to a mask of ranks. */ {
        IceTInt message_id;
        memset(myDestMask, 0, comm_size * sizeof(IceTBoolean));
        for (message_id = 0; message_id < numMessagesSending; message_id++) {
            myDestMask[messageDestinations[message_id]] = ICET_TRUE;
            sendIds[messageDestinations[message_id]] = message_id;
        }
    }

    /* Transpose myDestMask array to get mask of srcs on each process. */
    icetCommAlltoall(myDestMask, 1, ICET_BOOLEAN, mySrcMask);

    *sendIds_p = sendIds;
    *myDestMask_p = myDestMask;
    *mySrcMask_p = mySrcMask;
}
Beispiel #22
0
void icetDataReplicationGroup(IceTInt size, const IceTInt *processes)
{
    IceTInt rank;
    IceTBoolean found_myself = ICET_FALSE;
    IceTInt i;

    icetGetIntegerv(ICET_RANK, &rank);
    for (i = 0; i < size; i++) {
        if (processes[i] == rank) {
            found_myself = ICET_TRUE;
            break;
        }
    }

    if (!found_myself) {
        icetRaiseError("Local process not part of data replication group.",
                       ICET_INVALID_VALUE);
        return;
    }

    icetStateSetIntegerv(ICET_DATA_REPLICATION_GROUP_SIZE, 1, &size);
    icetStateSetIntegerv(ICET_DATA_REPLICATION_GROUP, size, processes);
}
Beispiel #23
0
static void rtfi_handleDataFunc(void *inSparseImageBuffer, IceTInt src) {
    if (inSparseImageBuffer == NULL) {
      /* Superfluous call from send to self. */
        if (!rtfi_first) {
            icetRaiseError("Unexpected callback order"
                           " in icetRenderTransferFullImages.",
                           ICET_SANITY_CHECK_FAIL);
        }
    } else {
        IceTSparseImage inSparseImage
            = icetSparseImageUnpackageFromReceive(inSparseImageBuffer);
        if (rtfi_first) {
            icetDecompressImage(inSparseImage, rtfi_image);
        } else {
            IceTInt rank;
            const IceTInt *process_orders;
            icetGetIntegerv(ICET_RANK, &rank);
            process_orders = icetUnsafeStateGetInteger(ICET_PROCESS_ORDERS);
            icetCompressedComposite(rtfi_image, inSparseImage,
                                    process_orders[src] < process_orders[rank]);
        }
    }
    rtfi_first = ICET_FALSE;
}
Beispiel #24
0
static void update_tile_projections(void)
{
    IceTInt num_tiles;
    const IceTInt *viewports;
    IceTDouble *tile_projections;
    IceTInt tile_idx;

    if (  icetStateGetTime(ICET_TILE_VIEWPORTS)
        < icetStateGetTime(ICET_TILE_PROJECTIONS) ) {
        /* Projections already up to date. */
        return;
    }

    icetGetIntegerv(ICET_NUM_TILES, &num_tiles);
    tile_projections = icetStateAllocateDouble(ICET_TILE_PROJECTIONS,
                                               num_tiles*16);
    viewports = icetUnsafeStateGetInteger(ICET_TILE_VIEWPORTS);

    for (tile_idx = 0; tile_idx < num_tiles; tile_idx++) {
        icetGetViewportProject(viewports[tile_idx*4+0], viewports[tile_idx*4+1],
                               viewports[tile_idx*4+2], viewports[tile_idx*4+3],
                               tile_projections + 16*tile_idx);
    }
}
Beispiel #25
0
static int SimpleExampleRun()
{
    float angle;

  /* Normally, the first thing that you do is set up your communication and
   * then create at least one IceT context.  This has already been done in
   * the calling function (i.e. icetTests_mpi.c).  See the init_mpi in
   * test_mpi.h for an example.
   */

  /* If we had set up the communication layer ourselves, we could have
   * gotten these parameters directly from it.  Since we did not, this
   * provides an alternate way. */
    icetGetIntegerv(ICET_RANK, &rank);
    icetGetIntegerv(ICET_NUM_PROCESSES, &num_proc);

  /* We should be able to set any color we want, but we should do it BEFORE
   * icetGLDrawFrame() is called, not in the callback drawing function.
   * There may also be limitations on the background color when performing
   * color blending. */
    glClearColor(0.2f, 0.5f, 0.1f, 1.0f);

  /* Give IceT a function that will issue the OpenGL drawing commands. */
    icetGLDrawCallback(draw);

  /* Give IceT the bounds of the polygons that will be drawn.  Note that
   * we must take into account any transformation that happens within the
   * draw function (but IceT will take care of any transformation that
   * happens before icetGLDrawFrame). */
    icetBoundingBoxd(-0.5+rank, 0.5+rank, -0.5, 0.5, -0.5, 0.5);

  /* Set up the tiled display.  Normally, the display will be fixed for a
   * given installation, but since this is a demo, we give two specific
   * examples. */
    if (num_proc < 4) {
      /* Here is an example of a "1 tile" case.  This is functionally
       * identical to a traditional sort last algorithm. */
        icetResetTiles();
        icetAddTile(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0);
    } else {
      /* Here is an example of a 4x4 tile layout.  The tiles are displayed
       * with the following ranks:
       *
       *               +---+---+
       *               | 0 | 1 |
       *               +---+---+
       *               | 2 | 3 |
       *               +---+---+
       *
       * Each tile is simply defined by grabing a viewport in an infinite
       * global display screen.  The global viewport projection is
       * automatically set to the smallest region containing all tiles.
       *
       * This example also shows tiles abutted against each other.
       * Mullions and overlaps can be implemented by simply shifting tiles
       * on top of or away from each other.
       */
        icetResetTiles();
        icetAddTile(0, (IceTInt)SCREEN_HEIGHT, SCREEN_WIDTH, SCREEN_HEIGHT, 0);
        icetAddTile((IceTInt)SCREEN_WIDTH,
                    (IceTInt)SCREEN_HEIGHT,
                    SCREEN_WIDTH,
                    SCREEN_HEIGHT,
                    1);
        icetAddTile(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 2);
        icetAddTile((IceTInt)SCREEN_WIDTH, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 3);
    }

  /* Tell IceT what strategy to use.  The REDUCE strategy is an all-around
   * good performer. */
    icetStrategy(ICET_STRATEGY_REDUCE);

  /* Set up the projection matrix as you normally would. */
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(-0.75, 0.75, -0.75, 0.75, -0.75, 0.75);

  /* Other normal OpenGL setup. */
    glEnable(GL_DEPTH_TEST);
    glEnable(GL_LIGHTING);
    glEnable(GL_LIGHT0);
    if (rank%8 != 0) {
        GLfloat color[4];
        color[0] = (float)(rank%2);
        color[1] = (float)((rank/2)%2);
        color[2] = (float)((rank/4)%2);
        color[3] = 1.0f;
        glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, color);
    }

  /* Here is an example of an animation loop. */
    for (angle = 0; angle < 360; angle += 10) {
      /* We can set up a modelview matrix here and IceT will factor this
       * in determining the screen projection of the geometry.  Note that
       * there is further transformation in the draw function that IceT
       * cannot take into account.  That transformation is handled in the
       * application by deforming the bounds before giving them to
       * IceT. */
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
        glRotated(angle, 0.0, 1.0, 0.0);
        glScaled(1.0f/num_proc, 1.0, 1.0);
        glTranslated(-(num_proc-1)/2.0, 0.0, 0.0);

      /* Instead of calling draw() directly, call it indirectly through
       * icetDrawFrame().  IceT will automatically handle image
       * compositing. */
        icetGLDrawFrame();

      /* For obvious reasons, IceT should be run in double-buffered frame
       * mode.  After calling icetDrawFrame, the application should do a
       * synchronize (a barrier is often about as good as you can do) and
       * then a swap buffers. */
        swap_buffers();
    }

    return TEST_PASSED;
}
Beispiel #26
0
IceTImage icetDirectCompose(void)
{
    IceTImage image;
    IceTVoid *inSparseImageBuffer;
    IceTSparseImage outSparseImage;
    IceTSizeType sparseImageSize;
    const IceTInt *contrib_counts;
    const IceTInt *display_nodes;
    IceTInt max_width, max_height;
    IceTInt num_tiles;
    IceTInt num_contributors;
    IceTInt display_tile;
    IceTInt tile;
    IceTInt *tile_image_dest;
    icetRaiseDebug("In Direct Compose");

    icetGetIntegerv(ICET_TILE_MAX_WIDTH, &max_width);
    icetGetIntegerv(ICET_TILE_MAX_HEIGHT, &max_height);
    icetGetIntegerv(ICET_NUM_TILES, &num_tiles);

    sparseImageSize = icetSparseImageBufferSize(max_width, max_height);

    image               = icetGetStateBufferImage(DIRECT_IMAGE_BUFFER,
                                                  max_width, max_height);
    inSparseImageBuffer = icetGetStateBuffer(DIRECT_IN_SPARSE_IMAGE_BUFFER,
                                             sparseImageSize);
    outSparseImage      = icetGetStateBufferSparseImage(
                                                 DIRECT_OUT_SPARSE_IMAGE_BUFFER,
                                                 max_width, max_height);
    tile_image_dest     = icetGetStateBuffer(DIRECT_TILE_IMAGE_DEST_BUFFER,
                                             num_tiles*sizeof(IceTInt));

    icetGetIntegerv(ICET_TILE_DISPLAYED, &display_tile);
    if (display_tile >= 0) {
        contrib_counts = icetUnsafeStateGetInteger(ICET_TILE_CONTRIB_COUNTS);
        num_contributors = contrib_counts[display_tile];
    } else {
        num_contributors = 0;
    }

    display_nodes = icetUnsafeStateGetInteger(ICET_DISPLAY_NODES);
    for (tile = 0; tile < num_tiles; tile++) {
        tile_image_dest[tile] = display_nodes[tile];
    }

    icetRaiseDebug("Rendering and transferring images.");
    icetRenderTransferFullImages(image,
                                 inSparseImageBuffer,
                                 outSparseImage,
                                 tile_image_dest);

    if (display_tile >= 0) {
        if (num_contributors > 0) {
            icetImageCorrectBackground(image);
        } else {
            /* Must be displaying a blank tile. */
            const IceTInt *tile_viewports
                = icetUnsafeStateGetInteger(ICET_TILE_VIEWPORTS);
            const IceTInt *display_tile_viewport
                = tile_viewports + 4*display_tile;
            IceTInt display_tile_width = display_tile_viewport[2];
            IceTInt display_tile_height = display_tile_viewport[3];

            icetRaiseDebug("Returning blank tile.");
            icetImageSetDimensions(image,
                                   display_tile_width,
                                   display_tile_height);
            icetClearImageTrueBackground(image);
        }
    }

    return image;
}
static int BoundsBehindViewerRun()
{
    float mat[16];
    IceTImage image;

    IceTInt rank;
    icetGetIntegerv(ICET_RANK, &rank);

    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);

    icetGLDrawCallback(draw);
    icetStrategy(ICET_STRATEGY_REDUCE);

    icetBoundingBoxd(-1.0, 1.0, -1.0, 1.0, -0.0, 0.0);

    icetSetColorFormat(ICET_IMAGE_COLOR_RGBA_UBYTE);
    icetSetDepthFormat(ICET_IMAGE_DEPTH_FLOAT);

  /* We're just going to use one tile. */
    icetResetTiles();
    icetAddTile(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0);

  /* Set up the transformation such that the quad in draw should cover the
     entire screen, but part of it extends behind the viewpoint.  Furthermore, a
     naive division by w will show all points to the right of the screen (which,
     of course, is wrong). */
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    glTranslated(0.0, 0.0, -1.5);
    glRotated(10.0, 0.0, 1.0, 0.0);
    glScaled(10.0, 10.0, 10.0);

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glFrustum(-1.0, 1.0, -1.0, 1.0, 1.0, 2.0);

    printstat("Modelview matrix:\n");
    glGetFloatv(GL_MODELVIEW_MATRIX, mat);
    PrintMatrix(mat);
    printstat("Projection matrix:\n");
    glGetFloatv(GL_PROJECTION_MATRIX, mat);
    PrintMatrix(mat);

  /* Other normal OpenGL setup. */
    glEnable(GL_DEPTH_TEST);
    glDisable(GL_LIGHTING);
    glColor3d(1.0, 1.0, 1.0);

  /* All the processes have the same data.  Go ahead and tell IceT. */
    icetDataReplicationGroupColor(0);

    image = icetGLDrawFrame();

  /* Test the resulting image to make sure the polygon was drawn over it. */
    if (rank == 0) {
        IceTUInt *cb = icetImageGetColorui(image);
        if (cb[0] != 0xFFFFFFFF) {
            printstat("First pixel in color buffer wrong: 0x%x\n", cb[0]);
            return TEST_FAILED;
        }
    }

    return TEST_PASSED;
}
Beispiel #28
0
IceTImage icetDrawFrame(const IceTDouble *projection_matrix,
                        const IceTDouble *modelview_matrix,
                        const IceTFloat *background_color)
{
    IceTInt frame_count;
    IceTImage image;
    IceTDouble render_time;
    IceTDouble buf_read_time;
    IceTDouble compose_time;
    IceTDouble total_time;

    icetRaiseDebug("In icetDrawFrame");

    {
        IceTBoolean isDrawing;
        icetGetBooleanv(ICET_IS_DRAWING_FRAME, &isDrawing);
        if (isDrawing) {
            icetRaiseError("Recursive frame draw detected.",
                           ICET_INVALID_OPERATION);
            return icetImageNull();
        }
    }

    icetStateResetTiming();
    icetTimingDrawFrameBegin();

    icetStateSetDoublev(ICET_PROJECTION_MATRIX, 16, projection_matrix);
    icetStateSetDoublev(ICET_MODELVIEW_MATRIX, 16, modelview_matrix);

    drawUseBackgroundColor(background_color);

    icetGetIntegerv(ICET_FRAME_COUNT, &frame_count);
    frame_count++;
    icetStateSetIntegerv(ICET_FRAME_COUNT, 1, &frame_count);

    drawProjectBounds();

    {
        IceTEnum strategy;
        icetGetEnumv(ICET_STRATEGY, &strategy);

        /* drawCollectTileInformation does an allgather to get information
         * about the tiles in other processes.  These variables are
         * ICET_ALL_CONTAINED_TILES_MASKS, ICET_TILE_CONTRIB_COUNTS, and
         * ICET_TOTAL_IMAGE_COUNT.  However, the sequential strategy ignores
         * this information and just uses all processes for all tiles.  When
         * compositing a single tile, this is a fine strategy and we can save
         * a significant proportion of frame time by skipping this step. */
        if (strategy != ICET_STRATEGY_SEQUENTIAL) {
            drawCollectTileInformation();
        }
    }

    {
        IceTInt tile_displayed;
        icetGetIntegerv(ICET_TILE_DISPLAYED, &tile_displayed);

        if (tile_displayed >= 0) {
            const IceTInt *tile_viewports
                = icetUnsafeStateGetInteger(ICET_TILE_VIEWPORTS);
            IceTInt num_pixels = (  tile_viewports[4*tile_displayed+2]
                                  * tile_viewports[4*tile_displayed+3] );
            icetStateSetInteger(ICET_VALID_PIXELS_TILE, tile_displayed);
            icetStateSetInteger(ICET_VALID_PIXELS_OFFSET, 0);
            icetStateSetInteger(ICET_VALID_PIXELS_NUM, num_pixels);
        } else {
            icetStateSetInteger(ICET_VALID_PIXELS_TILE, -1);
            icetStateSetInteger(ICET_VALID_PIXELS_OFFSET, 0);
            icetStateSetInteger(ICET_VALID_PIXELS_NUM, 0);
        }
    }

    image = drawInvokeStrategy();

    /* Calculate times. */
    icetGetDoublev(ICET_RENDER_TIME, &render_time);
    icetGetDoublev(ICET_BUFFER_READ_TIME, &buf_read_time);

    icetTimingDrawFrameEnd();

    icetGetDoublev(ICET_TOTAL_DRAW_TIME, &total_time);

    compose_time = total_time - render_time - buf_read_time;
    icetStateSetDouble(ICET_COMPOSITE_TIME, compose_time);

    icetStateSetDouble(ICET_BUFFER_WRITE_TIME, 0.0);

    icetStateCheckMemory();

    return image;
}
Beispiel #29
0
static void drawProjectBounds(void)
{
    IceTInt num_bounding_verts;
    IceTInt *contained_list;
    IceTBoolean *contained_mask;
    IceTInt contained_viewport[4];
    IceTDouble znear, zfar;
    IceTInt num_tiles;
    IceTInt num_contained;

    icetGetIntegerv(ICET_NUM_BOUNDING_VERTS, &num_bounding_verts);
    icetGetIntegerv(ICET_NUM_TILES, &num_tiles);

    contained_list = icetGetStateBuffer(ICET_CONTAINED_LIST_BUF,
                                        sizeof(IceTInt) * num_tiles);
    contained_mask = icetGetStateBuffer(ICET_CONTAINED_MASK_BUF,
                                        sizeof(IceTBoolean)*num_tiles);

    if (num_bounding_verts < 1) {
        /* User never set bounding vertices.  Assume image covers all tiles. */
        IceTInt i;
        for (i = 0; i < num_tiles; i++) {
            contained_list[i] = i;
            contained_mask[i] = 1;
        }
        icetGetIntegerv(ICET_GLOBAL_VIEWPORT, contained_viewport);
        znear = -1.0;
        zfar = 1.0;
        num_contained = num_tiles;
    } else {
      /* Figure out how the geometry projects onto the display. */
        drawFindContainedViewport(contained_viewport, &znear, &zfar);

      /* Now use this information to figure out which tiles need to be
         drawn. */
        drawDetermineContainedTiles(contained_viewport,
                                    znear,
                                    zfar,
                                    contained_list,
                                    contained_mask,
                                    &num_contained);
    }

    icetRaiseDebug4("contained_viewport = %d %d %d %d",
                    (int)contained_viewport[0], (int)contained_viewport[1],
                    (int)contained_viewport[2], (int)contained_viewport[3]);

    drawAdjustContainedForDataReplication(contained_viewport,
                                          contained_list,
                                          contained_mask,
                                          &num_contained);

    icetRaiseDebug4("new contained_viewport = %d %d %d %d",
                    (int)contained_viewport[0], (int)contained_viewport[1],
                    (int)contained_viewport[2], (int)contained_viewport[3]);
    icetStateSetIntegerv(ICET_CONTAINED_VIEWPORT, 4, contained_viewport);
    icetStateSetDoublev(ICET_NEAR_DEPTH, 1, &znear);
    icetStateSetDoublev(ICET_FAR_DEPTH, 1, &zfar);
    icetStateSetInteger(ICET_NUM_CONTAINED_TILES, num_contained);
    icetStateSetIntegerv(ICET_CONTAINED_TILES_LIST, num_contained,
                         contained_list);
    icetStateSetBooleanv(ICET_CONTAINED_TILES_MASK, num_tiles, contained_mask);
}
Beispiel #30
0
static void drawAdjustContainedForDataReplication(IceTInt *contained_viewport,
                                                  IceTInt *contained_list,
                                                  IceTBoolean *contained_mask,
                                                  IceTInt *num_contained_p)
{
    IceTInt *data_replication_group;
    IceTInt data_replication_group_size;
    const IceTInt *display_nodes;
    IceTInt rank;
    IceTInt num_proc;

    icetGetIntegerv(ICET_RANK, &rank);
    icetGetIntegerv(ICET_NUM_PROCESSES, &num_proc);

    display_nodes = icetUnsafeStateGetInteger(ICET_DISPLAY_NODES);

    /* If we are doing data replication, reduced the amount of screen space
       we are responsible for. */
    icetGetIntegerv(ICET_DATA_REPLICATION_GROUP_SIZE,
                    &data_replication_group_size);
    if (data_replication_group_size > 1) {
        /* Need to copy data_replication_group to temporary buffer so that we
           can modify it based on the current view's projection. */
        data_replication_group = icetGetStateBuffer(ICET_DATA_REP_GROUP_BUF,
                                                    sizeof(IceTInt)*num_proc);
        icetGetIntegerv(ICET_DATA_REPLICATION_GROUP, data_replication_group);
        if (data_replication_group_size >= *num_contained_p) {
            /* We have at least as many processes in the group as tiles we
               are projecting to.  First check to see if anybody in the group
               is displaying one of the tiles. */
            int tile_rendering = -1;
            int num_rendering_tile = 0;
            int tile_allocation_num = -1;
            int tile_id;

            for (tile_id = 0; tile_id < *num_contained_p; tile_id++) {
                int tile = contained_list[tile_id];
                int group_display_rank
                    = icetFindRankInGroup(data_replication_group,
                                          data_replication_group_size,
                                          display_nodes[tile]);
                if (group_display_rank >= 0) {
                    if (data_replication_group[group_display_rank] == rank) {
                        /* I'm displaying this tile, let's render it. */
                        tile_rendering = tile;
                        num_rendering_tile = 1;
                        tile_allocation_num = 0;
                    }
                    /* Remove both the tile and display node to prevent
                       pairing either with something else. */
                    (*num_contained_p)--;
                    contained_list[tile_id] = contained_list[*num_contained_p];
                    data_replication_group_size--;
                    data_replication_group[group_display_rank] =
                        data_replication_group[data_replication_group_size];
                    /* And decrement the tile counter so that we actually
                       check the tile we just moved. */
                    tile_id--;
                    break;
                }
            }

            /* Assign the rest of the processes to tiles. */
            if (*num_contained_p > 0) {
                int proc_per_tile = 0;
                int group_id;
                for (tile_id = 0, group_id = 0;
                     group_id < data_replication_group_size;
                     group_id++, tile_id++) {
                    if (tile_id >= *num_contained_p) {
                        tile_id = 0;
                        proc_per_tile++;
                    }
                    if (data_replication_group[group_id] == rank) {
                      /* Assign this process to the tile. */
                        tile_rendering = contained_list[tile_id];
                        tile_allocation_num = proc_per_tile;
                        num_rendering_tile = proc_per_tile+1;
                    } else if (tile_rendering == contained_list[tile_id]) {
                      /* This process already assigned to tile.  Mark that
                         another process is also assigned to it. */
                        num_rendering_tile++;
                    }
                }
            }

            /* Record a new viewport covering only my portion of the tile. */
            if (tile_rendering >= 0) {
                const IceTInt *tile_viewports
                    = icetUnsafeStateGetInteger(ICET_TILE_VIEWPORTS);
                const IceTInt *tv = tile_viewports + 4*tile_rendering;
                int new_length = tv[2]/num_rendering_tile;
                *num_contained_p = 1;
                contained_list[0] = tile_rendering;
                contained_viewport[1] = tv[1];
                contained_viewport[3] = tv[3];
                contained_viewport[0] = tv[0] + tile_allocation_num*new_length;
                if (tile_allocation_num == num_rendering_tile-1) {
                    /* Make sure last piece does not drop pixels due to rounding
                       errors. */
                    contained_viewport[2]
                        = tv[2] - tile_allocation_num*new_length;
                } else {
                    contained_viewport[2] = new_length;
                }
            } else {
                *num_contained_p = 0;
                contained_viewport[0] = -10000;
                contained_viewport[1] = -10000;
                contained_viewport[2] = 0;
                contained_viewport[3] = 0;
            }

            /* Fix contained_mask. */
            {
                int num_tiles;
                icetGetIntegerv(ICET_NUM_TILES, &num_tiles);
                for (tile_id = 0; tile_id < num_tiles; tile_id++) {
                    contained_mask[tile_id]
                        = (IceTBoolean)(tile_id == tile_rendering);
                }
            }
        } else {
            /* More tiles than processes.  Split up the contained_viewport as
               best as possible. */
            int factor = 2;
            while (factor <= data_replication_group_size) {
                int split_axis = contained_viewport[2] < contained_viewport[3];
                int new_length;
                int group_rank;
                int group_piece;
                while (data_replication_group_size%factor != 0) factor++;
              /* Split the viewport along the axis factor times.  Also
                 split the group into factor pieces. */
                new_length = contained_viewport[2+split_axis]/factor;
                group_rank = icetFindMyRankInGroup(data_replication_group,
                                                   data_replication_group_size);
                data_replication_group_size /= factor;  /* New subgroup. */
                group_piece = group_rank/data_replication_group_size;
                data_replication_group
                    += group_piece*data_replication_group_size;
                if (group_piece == factor-1) {
                  /* Make sure last piece does not drop pixels due to
                     rounding errors. */
                    contained_viewport[2+split_axis] -= group_piece*new_length;
                } else {
                    contained_viewport[2+split_axis] = new_length;
                }
                contained_viewport[split_axis] += group_piece*new_length;
            }
            drawDetermineContainedTiles(contained_viewport,
                                        0.0,    /* Fake znear and zfar. */
                                        0.0,    /* Already checked in range. */
                                        contained_list,
                                        contained_mask,
                                        num_contained_p);
        }
    }
}