示例#1
0
CoglClipStack *
_cogl_clip_stack_push_from_path (CoglClipStack *stack,
                                 CoglPath *path,
                                 CoglMatrixEntry *modelview_entry,
                                 CoglMatrixEntry *projection_entry,
                                 const float *viewport)
{
  float x_1, y_1, x_2, y_2;

  _cogl_path_get_bounds (path, &x_1, &y_1, &x_2, &y_2);

  /* If the path is a simple rectangle then we can divert to pushing a
     rectangle clip instead which usually won't involve the stencil
     buffer */
  if (_cogl_path_is_rectangle (path))
    return _cogl_clip_stack_push_rectangle (stack,
                                            x_1, y_1,
                                            x_2, y_2,
                                            modelview_entry,
                                            projection_entry,
                                            viewport);
  else
    {
      CoglClipStackPath *entry;
      CoglMatrix modelview;
      CoglMatrix projection;
      float transformed_corners[8];

      entry = _cogl_clip_stack_push_entry (stack,
                                           sizeof (CoglClipStackPath),
                                           COGL_CLIP_STACK_PATH);

      entry->path = cogl_path_copy (path);

      entry->matrix_entry = _cogl_matrix_entry_ref (modelview_entry);

      _cogl_matrix_entry_get (modelview_entry, &modelview);
      _cogl_matrix_entry_get (projection_entry, &projection);

      get_transformed_corners (x_1, y_1, x_2, y_2,
                               &modelview,
                               &projection,
                               viewport,
                               transformed_corners);
      _cogl_clip_stack_entry_set_bounds ((CoglClipStack *) entry,
                                         transformed_corners);

      return (CoglClipStack *) entry;
    }
}
示例#2
0
CoglClipStack *
_cogl_clip_stack_push_primitive (CoglClipStack *stack,
                                 CoglPrimitive *primitive,
                                 float bounds_x1,
                                 float bounds_y1,
                                 float bounds_x2,
                                 float bounds_y2,
                                 CoglMatrixEntry *modelview_entry,
                                 CoglMatrixEntry *projection_entry,
                                 const float *viewport)
{
  CoglClipStackPrimitive *entry;
  CoglMatrix modelview;
  CoglMatrix projection;
  float transformed_corners[8];

  entry = _cogl_clip_stack_push_entry (stack,
                                       sizeof (CoglClipStackPrimitive),
                                       COGL_CLIP_STACK_PRIMITIVE);

  entry->primitive = cogl_object_ref (primitive);

  entry->matrix_entry = cogl_matrix_entry_ref (modelview_entry);

  entry->bounds_x1 = bounds_x1;
  entry->bounds_y1 = bounds_y1;
  entry->bounds_x2 = bounds_x2;
  entry->bounds_y2 = bounds_y2;

  cogl_matrix_entry_get (modelview_entry, &modelview);
  cogl_matrix_entry_get (projection_entry, &projection);

  get_transformed_corners (bounds_x1, bounds_y1, bounds_x2, bounds_y2,
                           &modelview,
                           &projection,
                           viewport,
                           transformed_corners);

  /* NB: this is referring to the bounds in window coordinates as opposed
   * to the bounds above in primitive local coordinates. */
  _cogl_clip_stack_entry_set_bounds ((CoglClipStack *) entry,
                                     transformed_corners);

  return (CoglClipStack *) entry;
}
示例#3
0
CoglClipStack *
_cogl_clip_stack_push_window_rectangle (CoglClipStack *stack,
                                        int x_offset,
                                        int y_offset,
                                        int width,
                                        int height)
{
  CoglClipStack *entry;

  entry = _cogl_clip_stack_push_entry (stack,
                                       sizeof (CoglClipStackWindowRect),
                                       COGL_CLIP_STACK_WINDOW_RECT);

  entry->bounds_x0 = x_offset;
  entry->bounds_x1 = x_offset + width;
  entry->bounds_y0 = y_offset;
  entry->bounds_y1 = y_offset + height;

  return entry;
}
示例#4
0
CoglClipStack *
_cogl_clip_stack_push_rectangle (CoglClipStack *stack,
                                 float x_1,
                                 float y_1,
                                 float x_2,
                                 float y_2,
                                 CoglMatrixEntry *modelview_entry,
                                 CoglMatrixEntry *projection_entry,
                                 const float *viewport)
{
  CoglClipStackRect *entry;
  CoglMatrix modelview;
  CoglMatrix projection;
  CoglMatrix modelview_projection;

  /* Corners of the given rectangle in an clockwise order:
   *  (0, 1)     (2, 3)
   *
   *
   *
   *  (6, 7)     (4, 5)
   */
  float rect[] = {
    x_1, y_1,
    x_2, y_1,
    x_2, y_2,
    x_1, y_2
  };

  /* Make a new entry */
  entry = _cogl_clip_stack_push_entry (stack,
                                       sizeof (CoglClipStackRect),
                                       COGL_CLIP_STACK_RECT);

  entry->x0 = x_1;
  entry->y0 = y_1;
  entry->x1 = x_2;
  entry->y1 = y_2;

  entry->matrix_entry = cogl_matrix_entry_ref (modelview_entry);

  cogl_matrix_entry_get (modelview_entry, &modelview);
  cogl_matrix_entry_get (projection_entry, &projection);

  cogl_matrix_multiply (&modelview_projection,
                        &projection,
                        &modelview);

  /* Technically we could avoid the viewport transform at this point
   * if we want to make this a bit faster. */
  _cogl_transform_point (&modelview, &projection, viewport, &rect[0], &rect[1]);
  _cogl_transform_point (&modelview, &projection, viewport, &rect[2], &rect[3]);
  _cogl_transform_point (&modelview, &projection, viewport, &rect[4], &rect[5]);
  _cogl_transform_point (&modelview, &projection, viewport, &rect[6], &rect[7]);

  /* If the fully transformed rectangle isn't still axis aligned we
   * can't handle it using a scissor.
   *
   * We don't use an epsilon here since we only really aim to catch
   * simple cases where the transform doesn't leave the rectangle screen
   * aligned and don't mind some false positives.
   */
  if (rect[0] != rect[6] ||
      rect[1] != rect[3] ||
      rect[2] != rect[4] ||
      rect[7] != rect[5])
    {
      entry->can_be_scissor = FALSE;

      _cogl_clip_stack_entry_set_bounds ((CoglClipStack *) entry,
                                         rect);
    }
  else
    {
      CoglClipStack *base_entry = (CoglClipStack *) entry;
      x_1 = rect[0];
      y_1 = rect[1];
      x_2 = rect[4];
      y_2 = rect[5];

      /* Consider that the modelview matrix may flip the rectangle
       * along the x or y axis... */
#define SWAP(A,B) do { float tmp = B; B = A; A = tmp; } while (0)
      if (x_1 > x_2)
        SWAP (x_1, x_2);
      if (y_1 > y_2)
        SWAP (y_1, y_2);
#undef SWAP

      base_entry->bounds_x0 = COGL_UTIL_NEARBYINT (x_1);
      base_entry->bounds_y0 = COGL_UTIL_NEARBYINT (y_1);
      base_entry->bounds_x1 = COGL_UTIL_NEARBYINT (x_2);
      base_entry->bounds_y1 = COGL_UTIL_NEARBYINT (y_2);
      entry->can_be_scissor = TRUE;
    }

  return (CoglClipStack *) entry;
}