Пример #1
0
void icetProjectTile(GLint tile)
{
    GLint *viewports;
    GLint physical_viewport[4];
    GLint tile_width, tile_height;
    GLint renderable_width, renderable_height;

  /* Update tile projections. */
    if (viewport_time != icetStateGetTime(ICET_TILE_VIEWPORTS)) {
        update_tile_projections();
        viewport_time = icetStateGetTime(ICET_TILE_VIEWPORTS);
    }

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

    viewports = icetUnsafeStateGet(ICET_TILE_VIEWPORTS);
    tile_width = viewports[tile*4+2];
    tile_height = viewports[tile*4+3];
    glGetIntegerv(GL_VIEWPORT, physical_viewport);
    renderable_width = physical_viewport[2];
    renderable_height = physical_viewport[3];

    if ((renderable_width != tile_width) || (renderable_height != tile_height)){
      /* Compensate for fact that tile is smaller than actual window. */
        glOrtho(-1.0, 2.0*renderable_width/tile_width - 1.0,
                -1.0, 2.0*renderable_height/tile_height - 1.0,
                1.0, -1.0);
    }

    glMultMatrixd(tile_projections + 16*tile);

    if (projection_time != icetStateGetTime(ICET_PROJECTION_MATRIX)) {
        icetGetDoublev(ICET_PROJECTION_MATRIX, global_projection);
        projection_time = icetStateGetTime(ICET_PROJECTION_MATRIX);
    }

    glMultMatrixd(global_projection);
}
Пример #2
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;
}
Пример #3
0
static void drawFindContainedViewport(IceTInt contained_viewport[4],
                                      IceTDouble *znear, IceTDouble *zfar)
{
    IceTDouble total_transform[16];
    IceTDouble left, right, bottom, top;
    IceTDouble *transformed_verts;
    IceTInt global_viewport[4];
    IceTInt num_bounding_verts;
    int i;

    icetGetIntegerv(ICET_GLOBAL_VIEWPORT, global_viewport);

    {
        IceTDouble projection_matrix[16];
        IceTDouble modelview_matrix[16];
        IceTDouble viewport_matrix[16];
        IceTDouble tmp_matrix[16];

        icetGetDoublev(ICET_PROJECTION_MATRIX, projection_matrix);
        icetGetDoublev(ICET_MODELVIEW_MATRIX, modelview_matrix);

        /* Strange projection matrix that transforms the x and y of normalized
           screen coordinates into viewport coordinates that may be cast to
           integers. */
        viewport_matrix[ 0] = global_viewport[2];
        viewport_matrix[ 1] = 0.0;
        viewport_matrix[ 2] = 0.0;
        viewport_matrix[ 3] = 0.0;

        viewport_matrix[ 4] = 0.0;
        viewport_matrix[ 5] = global_viewport[3];
        viewport_matrix[ 6] = 0.0;
        viewport_matrix[ 7] = 0.0;

        viewport_matrix[ 8] = 0.0;
        viewport_matrix[ 9] = 0.0;
        viewport_matrix[10] = 2.0;
        viewport_matrix[11] = 0.0;

        viewport_matrix[12] = global_viewport[2] + global_viewport[0]*2.0;
        viewport_matrix[13] = global_viewport[3] + global_viewport[1]*2.0;
        viewport_matrix[14] = 0.0;
        viewport_matrix[15] = 2.0;

        icetMatrixMultiply(tmp_matrix,
                           (const IceTDouble *)projection_matrix,
                           (const IceTDouble *)modelview_matrix);
        icetMatrixMultiply(total_transform,
                           (const IceTDouble *)viewport_matrix,
                           (const IceTDouble *)tmp_matrix);
    }

    icetGetIntegerv(ICET_NUM_BOUNDING_VERTS, &num_bounding_verts);
    transformed_verts = icetGetStateBuffer(
                                       ICET_TRANSFORMED_BOUNDS,
                                       sizeof(IceTDouble)*num_bounding_verts*4);

    /* Transform each vertex to find where it lies in the global viewport and
       normalized z.  Leave the results in homogeneous coordinates for now. */
    {
        const IceTDouble *bound_vert
            = icetUnsafeStateGetDouble(ICET_GEOMETRY_BOUNDS);
        for (i = 0; i < num_bounding_verts; i++) {
            IceTDouble bound_vert_4vec[4];
            bound_vert_4vec[0] = bound_vert[3*i+0];
            bound_vert_4vec[1] = bound_vert[3*i+1];
            bound_vert_4vec[2] = bound_vert[3*i+2];
            bound_vert_4vec[3] = 1.0;
            icetMatrixVectorMultiply(transformed_verts + 4*i,
                                     (const IceTDouble *)total_transform,
                                     (const IceTDouble *)bound_vert_4vec);
        }
    }

    /* Set absolute mins and maxes. */
    left   = global_viewport[0] + global_viewport[2];
    right  = global_viewport[0];
    bottom = global_viewport[1] + global_viewport[3];
    top    = global_viewport[1];
    *znear = 1.0;
    *zfar  = -1.0;

    /* Now iterate over all the transformed verts and adjust the absolute mins
       and maxs to include them all. */
    for (i = 0; i < num_bounding_verts; i++)
    {
        IceTDouble *vert = transformed_verts + 4*i;

        /* Check to see if the vertex is in front of the near cut plane.  This
           is true when z/w >= -1 or z + w >= 0.  The second form is better just
           in case w is 0. */
        if (vert[2] + vert[3] >= 0.0) {
          /* Normalize homogeneous coordinates. */
            IceTDouble invw = 1.0/vert[3];
            IceTDouble x = vert[0]*invw;
            IceTDouble y = vert[1]*invw;
            IceTDouble z = vert[2]*invw;

          /* Update contained region. */
            if (left   > x) left   = x;
            if (right  < x) right  = x;
            if (bottom > y) bottom = y;
            if (top    < y) top    = y;
            if (*znear > z) *znear = z;
            if (*zfar  < z) *zfar  = z;
        } else {
          /* The vertex is being clipped by the near plane.  In perspective
             mode, vertices behind the near clipping plane can sometimes give
             misleading projections.  Instead, find all the other vertices on
             the other side of the near plane, compute the intersection of the
             segment between the two points and the near plane (in homogeneous
             coordinates) and use that as the projection. */
            int j;
            for (j = 0; j < num_bounding_verts; j++) {
                IceTDouble *vert2 = transformed_verts + 4*j;
                double t;
                IceTDouble x, y, invw;
                if (vert2[2] + vert2[3] < 0.0) {
                  /* Ignore other points behind near plane. */
                    continue;
                }
              /* Let the two points in question be v_i and v_j.  Define the
                 segment between them with the parametric equation
                 p(t) = (vert - vert2)t + vert2.  First, find t where the z and
                 w coordinates of p(t) sum to zero. */
                t = (vert2[2]+vert2[3])/(vert2[2]-vert[2] + vert2[3]-vert[3]);
              /* Use t to find the intersection point.  While we are at it,
                 normalize the resulting coordinates.  We don't need z because
                 we know it is going to be -1. */
                invw = 1.0/((vert[3] - vert2[3])*t + vert2[3] );
                x = ((vert[0] - vert2[0])*t + vert2[0] ) * invw;
                y = ((vert[1] - vert2[1])*t + vert2[1] ) * invw;

              /* Update contained region. */
                if (left   > x) left   = x;
                if (right  < x) right  = x;
                if (bottom > y) bottom = y;
                if (top    < y) top    = y;
                *znear = -1.0;
            }
        }
    }

    left = floor(left);
    right = ceil(right);
    bottom = floor(bottom);
    top = ceil(top);

  /* Clip bounds to global viewport. */
    if (left   < global_viewport[0]) left = global_viewport[0];
    if (right  > global_viewport[0] + global_viewport[2])
        right  = global_viewport[0] + global_viewport[2];
    if (bottom < global_viewport[1]) bottom = global_viewport[1];
    if (top    > global_viewport[1] + global_viewport[3])
        top    = global_viewport[1] + global_viewport[3];
    if (*znear < -1.0) *znear = -1.0;
    if (*zfar  >  1.0) *zfar = 1.0;

  /* Use this information to build a containing viewport. */
    contained_viewport[0] = (IceTInt)left;
    contained_viewport[1] = (IceTInt)bottom;
    contained_viewport[2] = (IceTInt)(right - left);
    contained_viewport[3] = (IceTInt)(top - bottom);
}