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; } }
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; }
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; }
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; }