"Initial commit to Gerrit"
[profile/ivi/cogl.git] / cogl / cogl-clip-stack.h
1 /*
2  * Cogl
3  *
4  * An object oriented GL/GLES Abstraction/Utility Layer
5  *
6  * Copyright (C) 2007,2008,2009,2010 Intel Corporation.
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library. If not, see <http://www.gnu.org/licenses/>.
20  *
21  *
22  */
23
24 #ifndef __COGL_CLIP_STACK_H
25 #define __COGL_CLIP_STACK_H
26
27 #include "cogl2-path.h"
28 #include "cogl-matrix.h"
29 #include "cogl-primitive.h"
30 #include "cogl-framebuffer.h"
31
32 /* The clip stack works like a GSList where only a pointer to the top
33    of the stack is stored. The empty clip stack is represented simply
34    by the NULL pointer. When an entry is added to or removed from the
35    stack the new top of the stack is returned. When an entry is pushed
36    a new clip stack entry is created which effectively takes ownership
37    of the reference on the old entry. Therefore unrefing the top entry
38    effectively loses ownership of all entries in the stack */
39
40 typedef struct _CoglClipStack CoglClipStack;
41 typedef struct _CoglClipStackRect CoglClipStackRect;
42 typedef struct _CoglClipStackWindowRect CoglClipStackWindowRect;
43 typedef struct _CoglClipStackPath CoglClipStackPath;
44 typedef struct _CoglClipStackPrimitive CoglClipStackPrimitive;
45
46 typedef enum
47   {
48     COGL_CLIP_STACK_RECT,
49     COGL_CLIP_STACK_WINDOW_RECT,
50     COGL_CLIP_STACK_PATH,
51     COGL_CLIP_STACK_PRIMITIVE
52   } CoglClipStackType;
53
54 /* A clip stack consists a list of entries. Each entry has a reference
55  * count and a link to its parent node. The child takes a reference on
56  * the parent and the CoglClipStack holds a reference to the top of
57  * the stack. There are no links back from the parent to the
58  * children. This allows stacks that have common ancestry to share the
59  * entries.
60  *
61  * For example, the following sequence of operations would generate
62  * the tree below:
63  *
64  * CoglClipStack *stack_a = NULL;
65  * stack_a = _cogl_clip_stack_push_rectangle (stack_a, ...);
66  * stack_a = _cogl_clip_stack_push_rectangle (stack_a, ...);
67  * stack_a = _cogl_clip_stack_push_from_path (stack_a, ...);
68  * CoglClipStack *stack_b = NULL;
69  * stack_b = cogl_clip_stack_push_window_rectangle (stack_b, ...);
70  *
71  *  stack_a
72  *         \ holds a ref to
73  *          +-----------+
74  *          | path node |
75  *          |ref count 1|
76  *          +-----------+
77  *                       \
78  *                        +-----------+  +-----------+
79  *       both tops hold   | rect node |  | rect node |
80  *       a ref to the     |ref count 2|--|ref count 1|
81  *       same rect node   +-----------+  +-----------+
82  *                       /
83  *          +-----------+
84  *          | win. rect |
85  *          |ref count 1|
86  *          +-----------+
87  *         / holds a ref to
88  *  stack_b
89  *
90  */
91
92 struct _CoglClipStack
93 {
94   CoglClipStackType  type;
95
96   /* This will be null if there is no parent. If it is not null then
97      this node must be holding a reference to the parent */
98   CoglClipStack     *parent;
99
100   /* All clip entries have a window-space bounding box which we can
101      use to calculate a scissor. The scissor limits the clip so that
102      we don't need to do a full stencil clear if the stencil buffer is
103      needed. This is stored in Cogl's coordinate space (ie, 0,0 is the
104      top left) */
105   int                     bounds_x0;
106   int                     bounds_y0;
107   int                     bounds_x1;
108   int                     bounds_y1;
109
110   unsigned int            ref_count;
111 };
112
113 struct _CoglClipStackRect
114 {
115   CoglClipStack     _parent_data;
116
117   /* The rectangle for this clip */
118   float                  x0;
119   float                  y0;
120   float                  x1;
121   float                  y1;
122
123   /* If this is true then the clip for this rectangle is entirely
124      described by the scissor bounds. This implies that the rectangle
125      is screen aligned and we don't need to use the stencil buffer to
126      set the clip. We keep the entry as a rect entry rather than a
127      window rect entry so that it will be easier to detect if the
128      modelview matrix is that same as when a rectangle is added to the
129      journal. In that case we can use the original clip coordinates
130      and modify the rectangle instead. */
131   gboolean               can_be_scissor;
132
133   /* The matrix that was current when the clip was set */
134   CoglMatrix             matrix;
135 };
136
137 struct _CoglClipStackWindowRect
138 {
139   CoglClipStack     _parent_data;
140
141   /* The window rect clip doesn't need any specific data because it
142      just adds to the scissor clip */
143 };
144
145 struct _CoglClipStackPath
146 {
147   CoglClipStack     _parent_data;
148
149   /* The matrix that was current when the clip was set */
150   CoglMatrix             matrix;
151
152   CoglPath              *path;
153 };
154
155 struct _CoglClipStackPrimitive
156 {
157   CoglClipStack _parent_data;
158
159   /* The matrix that was current when the clip was set */
160   CoglMatrix matrix;
161
162   CoglPrimitive *primitive;
163
164   float bounds_x1;
165   float bounds_y1;
166   float bounds_x2;
167   float bounds_y2;
168 };
169
170 CoglClipStack *
171 _cogl_clip_stack_push_window_rectangle (CoglClipStack *stack,
172                                         int x_offset,
173                                         int y_offset,
174                                         int width,
175                                         int height);
176
177 CoglClipStack *
178 _cogl_clip_stack_push_rectangle (CoglClipStack *stack,
179                                  float x_1,
180                                  float y_1,
181                                  float x_2,
182                                  float y_2,
183                                  const CoglMatrix *modelview_matrix);
184
185 CoglClipStack *
186 _cogl_clip_stack_push_from_path (CoglClipStack *stack,
187                                  CoglPath *path,
188                                  const CoglMatrix *modelview_matrix);
189
190 CoglClipStack *
191 _cogl_clip_stack_push_primitive (CoglClipStack *stack,
192                                  CoglPrimitive *primitive,
193                                  float bounds_x1,
194                                  float bounds_y1,
195                                  float bounds_x2,
196                                  float bounds_y2,
197                                  const CoglMatrix *modelview_matrix);
198
199 CoglClipStack *
200 _cogl_clip_stack_pop (CoglClipStack *stack);
201
202 void
203 _cogl_clip_stack_get_bounds (CoglClipStack *stack,
204                              int *scissor_x0,
205                              int *scissor_y0,
206                              int *scissor_x1,
207                              int *scissor_y1);
208
209 void
210 _cogl_clip_stack_flush (CoglClipStack *stack,
211                         CoglFramebuffer *framebuffer);
212
213 CoglClipStack *
214 _cogl_clip_stack_ref (CoglClipStack *stack);
215
216 void
217 _cogl_clip_stack_unref (CoglClipStack *stack);
218
219 #endif /* __COGL_CLIP_STACK_H */