~noskcaj/ubuntu/trusty/cogl/1.16.2

« back to all changes in this revision

Viewing changes to cogl/cogl-clip-stack.c

  • Committer: Package Import Robot
  • Author(s): Jeremy Bicha, Jeremy Bicha, Rico Tzschichholz
  • Date: 2013-02-26 16:43:25 UTC
  • mfrom: (1.1.10)
  • Revision ID: package-import@ubuntu.com-20130226164325-t4z9rylpa20v0p6q
Tags: 1.13.4-0ubuntu1
[ Jeremy Bicha ]
* New upstream release
  - soname bump
* debian/control.in:
  - Bump minimum glib to 2.32
  - Drop obsolete breaks/replaces
  - Bump libclutter-1.0-dev breaks for soname transition
* debian/libcogl-dev.install:
  - Add some missing files

[ Rico Tzschichholz ]
* debian/control.in:
  - Build-depend on libxrandr-dev

Show diffs side-by-side

added added

removed removed

Lines of Context:
16
16
 * Lesser General Public License for more details.
17
17
 *
18
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/>.
 
19
 * License along with this library. If not, see
 
20
 * <http://www.gnu.org/licenses/>.
20
21
 *
21
22
 *
22
23
 */
33
34
#include "cogl-clip-stack.h"
34
35
#include "cogl-primitives.h"
35
36
#include "cogl-context-private.h"
36
 
#include "cogl-internal.h"
37
37
#include "cogl-framebuffer-private.h"
38
38
#include "cogl-journal-private.h"
39
39
#include "cogl-util.h"
48
48
#include "cogl-offscreen.h"
49
49
#include "cogl-matrix-stack.h"
50
50
 
51
 
#ifndef GL_CLIP_PLANE0
52
 
#define GL_CLIP_PLANE0 0x3000
53
 
#define GL_CLIP_PLANE1 0x3001
54
 
#define GL_CLIP_PLANE2 0x3002
55
 
#define GL_CLIP_PLANE3 0x3003
56
 
#define GL_CLIP_PLANE4 0x3004
57
 
#define GL_CLIP_PLANE5 0x3005
58
 
#endif
59
 
 
60
 
static void
61
 
project_vertex (const CoglMatrix *modelview_projection,
62
 
                float *vertex)
63
 
{
64
 
  int i;
65
 
 
66
 
  cogl_matrix_transform_point (modelview_projection,
67
 
                               &vertex[0], &vertex[1],
68
 
                               &vertex[2], &vertex[3]);
69
 
 
70
 
  /* Convert from homogenized coordinates */
71
 
  for (i = 0; i < 4; i++)
72
 
    vertex[i] /= vertex[3];
73
 
}
74
 
 
75
 
static void
76
 
set_clip_plane (CoglFramebuffer *framebuffer,
77
 
                GLint plane_num,
78
 
                const float *vertex_a,
79
 
                const float *vertex_b)
80
 
{
81
 
  GLfloat planef[4];
82
 
  double planed[4];
83
 
  GLfloat angle;
84
 
  CoglMatrixStack *modelview_stack =
85
 
    _cogl_framebuffer_get_modelview_stack (framebuffer);
86
 
  CoglMatrixStack *projection_stack =
87
 
    _cogl_framebuffer_get_projection_stack (framebuffer);
88
 
  CoglMatrix inverse_projection;
89
 
 
90
 
  _COGL_GET_CONTEXT (ctx, NO_RETVAL);
91
 
 
92
 
  _cogl_matrix_stack_get_inverse (projection_stack, &inverse_projection);
93
 
 
94
 
  /* Calculate the angle between the axes and the line crossing the
95
 
     two points */
96
 
  angle = atan2f (vertex_b[1] - vertex_a[1],
97
 
                  vertex_b[0] - vertex_a[0]) * (180.0/G_PI);
98
 
 
99
 
  _cogl_matrix_stack_push (modelview_stack);
100
 
 
101
 
  /* Load the inverse of the projection matrix so we can specify the plane
102
 
   * in screen coordinates */
103
 
  _cogl_matrix_stack_set (modelview_stack, &inverse_projection);
104
 
 
105
 
  /* Rotate about point a */
106
 
  _cogl_matrix_stack_translate (modelview_stack,
107
 
                                vertex_a[0], vertex_a[1], vertex_a[2]);
108
 
  /* Rotate the plane by the calculated angle so that it will connect
109
 
     the two points */
110
 
  _cogl_matrix_stack_rotate (modelview_stack, angle, 0.0f, 0.0f, 1.0f);
111
 
  _cogl_matrix_stack_translate (modelview_stack,
112
 
                                -vertex_a[0], -vertex_a[1], -vertex_a[2]);
113
 
 
114
 
  /* Clip planes can only be used when a fixed function backend is in
115
 
     use so we know we can directly push this matrix to the builtin
116
 
     state */
117
 
  _cogl_matrix_entry_flush_to_gl_builtins (ctx,
118
 
                                           modelview_stack->last_entry,
119
 
                                           COGL_MATRIX_MODELVIEW,
120
 
                                           framebuffer,
121
 
                                           FALSE /* don't disable flip */);
122
 
 
123
 
  planef[0] = 0;
124
 
  planef[1] = -1.0;
125
 
  planef[2] = 0;
126
 
  planef[3] = vertex_a[1];
127
 
 
128
 
  switch (ctx->driver)
129
 
    {
130
 
    default:
131
 
      g_assert_not_reached ();
132
 
      break;
133
 
 
134
 
    case COGL_DRIVER_GLES1:
135
 
      GE( ctx, glClipPlanef (plane_num, planef) );
136
 
      break;
137
 
 
138
 
    case COGL_DRIVER_GL:
139
 
      planed[0] = planef[0];
140
 
      planed[1] = planef[1];
141
 
      planed[2] = planef[2];
142
 
      planed[3] = planef[3];
143
 
      GE( ctx, glClipPlane (plane_num, planed) );
144
 
      break;
145
 
    }
146
 
 
147
 
  _cogl_matrix_stack_pop (modelview_stack);
148
 
}
149
 
 
150
 
static void
151
 
set_clip_planes (CoglFramebuffer *framebuffer,
152
 
                 CoglMatrixEntry *modelview_entry,
153
 
                 float x_1,
154
 
                 float y_1,
155
 
                 float x_2,
156
 
                 float y_2)
157
 
{
158
 
  CoglMatrix modelview_matrix;
159
 
  CoglMatrixStack *projection_stack =
160
 
    _cogl_framebuffer_get_projection_stack (framebuffer);
161
 
  CoglMatrix projection_matrix;
162
 
  CoglMatrix modelview_projection;
163
 
  float signed_area;
164
 
 
165
 
  float vertex_tl[4] = { x_1, y_1, 0, 1.0 };
166
 
  float vertex_tr[4] = { x_2, y_1, 0, 1.0 };
167
 
  float vertex_bl[4] = { x_1, y_2, 0, 1.0 };
168
 
  float vertex_br[4] = { x_2, y_2, 0, 1.0 };
169
 
 
170
 
  _cogl_matrix_stack_get (projection_stack, &projection_matrix);
171
 
  _cogl_matrix_entry_get (modelview_entry, &modelview_matrix);
172
 
 
173
 
  cogl_matrix_multiply (&modelview_projection,
174
 
                        &projection_matrix,
175
 
                        &modelview_matrix);
176
 
 
177
 
  project_vertex (&modelview_projection, vertex_tl);
178
 
  project_vertex (&modelview_projection, vertex_tr);
179
 
  project_vertex (&modelview_projection, vertex_bl);
180
 
  project_vertex (&modelview_projection, vertex_br);
181
 
 
182
 
  /* Calculate the signed area of the polygon formed by the four
183
 
     vertices so that we can know its orientation */
184
 
  signed_area = (vertex_tl[0] * (vertex_tr[1] - vertex_bl[1])
185
 
                 + vertex_tr[0] * (vertex_br[1] - vertex_tl[1])
186
 
                 + vertex_br[0] * (vertex_bl[1] - vertex_tr[1])
187
 
                 + vertex_bl[0] * (vertex_tl[1] - vertex_br[1]));
188
 
 
189
 
  /* Set the clip planes to form lines between all of the vertices
190
 
     using the same orientation as we calculated */
191
 
  if (signed_area > 0.0f)
192
 
    {
193
 
      /* counter-clockwise */
194
 
      set_clip_plane (framebuffer, GL_CLIP_PLANE0, vertex_tl, vertex_bl);
195
 
      set_clip_plane (framebuffer, GL_CLIP_PLANE1, vertex_bl, vertex_br);
196
 
      set_clip_plane (framebuffer, GL_CLIP_PLANE2, vertex_br, vertex_tr);
197
 
      set_clip_plane (framebuffer, GL_CLIP_PLANE3, vertex_tr, vertex_tl);
198
 
    }
199
 
  else
200
 
    {
201
 
      /* clockwise */
202
 
      set_clip_plane (framebuffer, GL_CLIP_PLANE0, vertex_tl, vertex_tr);
203
 
      set_clip_plane (framebuffer, GL_CLIP_PLANE1, vertex_tr, vertex_br);
204
 
      set_clip_plane (framebuffer, GL_CLIP_PLANE2, vertex_br, vertex_bl);
205
 
      set_clip_plane (framebuffer, GL_CLIP_PLANE3, vertex_bl, vertex_tl);
206
 
    }
207
 
}
208
 
 
209
 
static void
210
 
add_stencil_clip_rectangle (CoglFramebuffer *framebuffer,
211
 
                            CoglMatrixEntry *modelview_entry,
212
 
                            float x_1,
213
 
                            float y_1,
214
 
                            float x_2,
215
 
                            float y_2,
216
 
                            CoglBool first)
217
 
{
218
 
  CoglMatrixStack *projection_stack =
219
 
    _cogl_framebuffer_get_projection_stack (framebuffer);
220
 
  CoglContext *ctx = cogl_framebuffer_get_context (framebuffer);
221
 
 
222
 
  /* NB: This can be called while flushing the journal so we need
223
 
   * to be very conservative with what state we change.
224
 
   */
225
 
 
226
 
  _cogl_context_set_current_projection_entry (ctx,
227
 
                                              projection_stack->last_entry);
228
 
  _cogl_context_set_current_modelview_entry (ctx, modelview_entry);
229
 
 
230
 
  if (first)
231
 
    {
232
 
      GE( ctx, glEnable (GL_STENCIL_TEST) );
233
 
 
234
 
      /* Initially disallow everything */
235
 
      GE( ctx, glClearStencil (0) );
236
 
      GE( ctx, glClear (GL_STENCIL_BUFFER_BIT) );
237
 
 
238
 
      /* Punch out a hole to allow the rectangle */
239
 
      GE( ctx, glStencilFunc (GL_NEVER, 0x1, 0x1) );
240
 
      GE( ctx, glStencilOp (GL_REPLACE, GL_REPLACE, GL_REPLACE) );
241
 
 
242
 
      _cogl_rectangle_immediate (framebuffer,
243
 
                                 ctx->stencil_pipeline,
244
 
                                 x_1, y_1, x_2, y_2);
245
 
    }
246
 
  else
247
 
    {
248
 
      /* Add one to every pixel of the stencil buffer in the
249
 
         rectangle */
250
 
      GE( ctx, glStencilFunc (GL_NEVER, 0x1, 0x3) );
251
 
      GE( ctx, glStencilOp (GL_INCR, GL_INCR, GL_INCR) );
252
 
      _cogl_rectangle_immediate (framebuffer,
253
 
                                 ctx->stencil_pipeline,
254
 
                                 x_1, y_1, x_2, y_2);
255
 
 
256
 
      /* Subtract one from all pixels in the stencil buffer so that
257
 
         only pixels where both the original stencil buffer and the
258
 
         rectangle are set will be valid */
259
 
      GE( ctx, glStencilOp (GL_DECR, GL_DECR, GL_DECR) );
260
 
 
261
 
      _cogl_context_set_current_projection_entry (ctx, &ctx->identity_entry);
262
 
      _cogl_context_set_current_modelview_entry (ctx, &ctx->identity_entry);
263
 
 
264
 
      _cogl_rectangle_immediate (framebuffer,
265
 
                                 ctx->stencil_pipeline,
266
 
                                 -1.0, -1.0, 1.0, 1.0);
267
 
    }
268
 
 
269
 
  /* Restore the stencil mode */
270
 
  GE( ctx, glStencilFunc (GL_EQUAL, 0x1, 0x1) );
271
 
  GE( ctx, glStencilOp (GL_KEEP, GL_KEEP, GL_KEEP) );
272
 
}
273
 
 
274
 
typedef void (*SilhouettePaintCallback) (CoglFramebuffer *framebuffer,
275
 
                                         CoglPipeline *pipeline,
276
 
                                         void *user_data);
277
 
 
278
 
static void
279
 
add_stencil_clip_silhouette (CoglFramebuffer *framebuffer,
280
 
                             SilhouettePaintCallback silhouette_callback,
281
 
                             CoglMatrixEntry *modelview_entry,
282
 
                             float bounds_x1,
283
 
                             float bounds_y1,
284
 
                             float bounds_x2,
285
 
                             float bounds_y2,
286
 
                             CoglBool merge,
287
 
                             CoglBool need_clear,
288
 
                             void *user_data)
289
 
{
290
 
  CoglMatrixStack *projection_stack =
291
 
    _cogl_framebuffer_get_projection_stack (framebuffer);
292
 
  CoglContext *ctx = cogl_framebuffer_get_context (framebuffer);
293
 
 
294
 
  /* NB: This can be called while flushing the journal so we need
295
 
   * to be very conservative with what state we change.
296
 
   */
297
 
 
298
 
  _cogl_context_set_current_projection_entry (ctx,
299
 
                                              projection_stack->last_entry);
300
 
  _cogl_context_set_current_modelview_entry (ctx, modelview_entry);
301
 
 
302
 
  _cogl_pipeline_flush_gl_state (ctx->stencil_pipeline, framebuffer, FALSE, 0);
303
 
 
304
 
  GE( ctx, glEnable (GL_STENCIL_TEST) );
305
 
 
306
 
  GE( ctx, glColorMask (FALSE, FALSE, FALSE, FALSE) );
307
 
  GE( ctx, glDepthMask (FALSE) );
308
 
 
309
 
  if (merge)
310
 
    {
311
 
      GE (ctx, glStencilMask (2));
312
 
      GE (ctx, glStencilFunc (GL_LEQUAL, 0x2, 0x6));
313
 
    }
314
 
  else
315
 
    {
316
 
      /* If we're not using the stencil buffer for clipping then we
317
 
         don't need to clear the whole stencil buffer, just the area
318
 
         that will be drawn */
319
 
      if (need_clear)
320
 
        /* If this is being called from the clip stack code then it
321
 
           will have set up a scissor for the minimum bounding box of
322
 
           all of the clips. That box will likely mean that this
323
 
           _cogl_clear won't need to clear the entire
324
 
           buffer. _cogl_framebuffer_clear_without_flush4f is used instead
325
 
           of cogl_clear because it won't try to flush the journal */
326
 
        _cogl_framebuffer_clear_without_flush4f (framebuffer,
327
 
                                                 COGL_BUFFER_BIT_STENCIL,
328
 
                                                 0, 0, 0, 0);
329
 
      else
330
 
        {
331
 
          /* Just clear the bounding box */
332
 
          GE( ctx, glStencilMask (~(GLuint) 0) );
333
 
          GE( ctx, glStencilOp (GL_ZERO, GL_ZERO, GL_ZERO) );
334
 
          _cogl_rectangle_immediate (framebuffer,
335
 
                                     ctx->stencil_pipeline,
336
 
                                     bounds_x1, bounds_y1,
337
 
                                     bounds_x2, bounds_y2);
338
 
        }
339
 
      GE (ctx, glStencilMask (1));
340
 
      GE (ctx, glStencilFunc (GL_LEQUAL, 0x1, 0x3));
341
 
    }
342
 
 
343
 
  GE (ctx, glStencilOp (GL_INVERT, GL_INVERT, GL_INVERT));
344
 
 
345
 
  silhouette_callback (framebuffer, ctx->stencil_pipeline, user_data);
346
 
 
347
 
  if (merge)
348
 
    {
349
 
      /* Now we have the new stencil buffer in bit 1 and the old
350
 
         stencil buffer in bit 0 so we need to intersect them */
351
 
      GE (ctx, glStencilMask (3));
352
 
      GE (ctx, glStencilFunc (GL_NEVER, 0x2, 0x3));
353
 
      GE (ctx, glStencilOp (GL_DECR, GL_DECR, GL_DECR));
354
 
      /* Decrement all of the bits twice so that only pixels where the
355
 
         value is 3 will remain */
356
 
 
357
 
      _cogl_context_set_current_projection_entry (ctx, &ctx->identity_entry);
358
 
      _cogl_context_set_current_modelview_entry (ctx, &ctx->identity_entry);
359
 
 
360
 
      _cogl_rectangle_immediate (framebuffer, ctx->stencil_pipeline,
361
 
                                 -1.0, -1.0, 1.0, 1.0);
362
 
      _cogl_rectangle_immediate (framebuffer, ctx->stencil_pipeline,
363
 
                                 -1.0, -1.0, 1.0, 1.0);
364
 
    }
365
 
 
366
 
  GE (ctx, glStencilMask (~(GLuint) 0));
367
 
  GE (ctx, glDepthMask (TRUE));
368
 
  GE (ctx, glColorMask (TRUE, TRUE, TRUE, TRUE));
369
 
 
370
 
  GE (ctx, glStencilFunc (GL_EQUAL, 0x1, 0x1));
371
 
  GE (ctx, glStencilOp (GL_KEEP, GL_KEEP, GL_KEEP));
372
 
}
373
 
 
374
 
static void
375
 
paint_path_silhouette (CoglFramebuffer *framebuffer,
376
 
                       CoglPipeline *pipeline,
377
 
                       void *user_data)
378
 
{
379
 
  CoglPath *path = user_data;
380
 
  if (path->data->path_nodes->len >= 3)
381
 
    _cogl_path_fill_nodes (path,
382
 
                           framebuffer,
383
 
                           pipeline,
384
 
                           COGL_DRAW_SKIP_JOURNAL_FLUSH |
385
 
                           COGL_DRAW_SKIP_PIPELINE_VALIDATION |
386
 
                           COGL_DRAW_SKIP_FRAMEBUFFER_FLUSH);
387
 
}
388
 
 
389
 
static void
390
 
add_stencil_clip_path (CoglFramebuffer *framebuffer,
391
 
                       CoglMatrixEntry *modelview_entry,
392
 
                       CoglPath *path,
393
 
                       CoglBool merge,
394
 
                       CoglBool need_clear)
395
 
{
396
 
  CoglPathData *data = path->data;
397
 
  add_stencil_clip_silhouette (framebuffer,
398
 
                               paint_path_silhouette,
399
 
                               modelview_entry,
400
 
                               data->path_nodes_min.x,
401
 
                               data->path_nodes_min.y,
402
 
                               data->path_nodes_max.x,
403
 
                               data->path_nodes_max.y,
404
 
                               merge,
405
 
                               need_clear,
406
 
                               path);
407
 
}
408
 
 
409
 
static void
410
 
paint_primitive_silhouette (CoglFramebuffer *framebuffer,
411
 
                            CoglPipeline *pipeline,
412
 
                            void *user_data)
413
 
{
414
 
  _cogl_framebuffer_draw_primitive (framebuffer,
415
 
                                    pipeline,
416
 
                                    user_data,
417
 
                                    COGL_DRAW_SKIP_JOURNAL_FLUSH |
418
 
                                    COGL_DRAW_SKIP_PIPELINE_VALIDATION |
419
 
                                    COGL_DRAW_SKIP_FRAMEBUFFER_FLUSH |
420
 
                                    COGL_DRAW_SKIP_LEGACY_STATE);
421
 
}
422
 
 
423
 
static void
424
 
add_stencil_clip_primitive (CoglFramebuffer *framebuffer,
425
 
                            CoglMatrixEntry *modelview_entry,
426
 
                            CoglPrimitive *primitive,
427
 
                            float bounds_x1,
428
 
                            float bounds_y1,
429
 
                            float bounds_x2,
430
 
                            float bounds_y2,
431
 
                            CoglBool merge,
432
 
                            CoglBool need_clear)
433
 
{
434
 
  add_stencil_clip_silhouette (framebuffer,
435
 
                               paint_primitive_silhouette,
436
 
                               modelview_entry,
437
 
                               bounds_x1,
438
 
                               bounds_y1,
439
 
                               bounds_x2,
440
 
                               bounds_y2,
441
 
                               merge,
442
 
                               need_clear,
443
 
                               primitive);
444
 
}
445
 
 
446
 
static void
447
 
disable_stencil_buffer (void)
448
 
{
449
 
  _COGL_GET_CONTEXT (ctx, NO_RETVAL);
450
 
 
451
 
  GE( ctx, glDisable (GL_STENCIL_TEST) );
452
 
}
453
 
 
454
 
static void
455
 
enable_clip_planes (void)
456
 
{
457
 
  _COGL_GET_CONTEXT (ctx, NO_RETVAL);
458
 
 
459
 
  GE( ctx, glEnable (GL_CLIP_PLANE0) );
460
 
  GE( ctx, glEnable (GL_CLIP_PLANE1) );
461
 
  GE( ctx, glEnable (GL_CLIP_PLANE2) );
462
 
  GE( ctx, glEnable (GL_CLIP_PLANE3) );
463
 
}
464
 
 
465
 
static void
466
 
disable_clip_planes (void)
467
 
{
468
 
  _COGL_GET_CONTEXT (ctx, NO_RETVAL);
469
 
 
470
 
  GE( ctx, glDisable (GL_CLIP_PLANE3) );
471
 
  GE( ctx, glDisable (GL_CLIP_PLANE2) );
472
 
  GE( ctx, glDisable (GL_CLIP_PLANE1) );
473
 
  GE( ctx, glDisable (GL_CLIP_PLANE0) );
474
 
}
 
51
 
475
52
 
476
53
static void *
477
54
_cogl_clip_stack_push_entry (CoglClipStack *clip_stack,
612
189
  entry->x1 = x_2;
613
190
  entry->y1 = y_2;
614
191
 
615
 
  entry->matrix_entry = _cogl_matrix_entry_ref (modelview_entry);
 
192
  entry->matrix_entry = cogl_matrix_entry_ref (modelview_entry);
616
193
 
617
 
  _cogl_matrix_entry_get (modelview_entry, &modelview);
618
 
  _cogl_matrix_entry_get (projection_entry, &projection);
 
194
  cogl_matrix_entry_get (modelview_entry, &modelview);
 
195
  cogl_matrix_entry_get (projection_entry, &projection);
619
196
 
620
197
  cogl_matrix_multiply (&modelview_projection,
621
198
                        &projection,
706
283
 
707
284
      entry->path = cogl_path_copy (path);
708
285
 
709
 
      entry->matrix_entry = _cogl_matrix_entry_ref (modelview_entry);
 
286
      entry->matrix_entry = cogl_matrix_entry_ref (modelview_entry);
710
287
 
711
 
      _cogl_matrix_entry_get (modelview_entry, &modelview);
712
 
      _cogl_matrix_entry_get (projection_entry, &projection);
 
288
      cogl_matrix_entry_get (modelview_entry, &modelview);
 
289
      cogl_matrix_entry_get (projection_entry, &projection);
713
290
 
714
291
      get_transformed_corners (x_1, y_1, x_2, y_2,
715
292
                               &modelview,
745
322
 
746
323
  entry->primitive = cogl_object_ref (primitive);
747
324
 
748
 
  entry->matrix_entry = _cogl_matrix_entry_ref (modelview_entry);
 
325
  entry->matrix_entry = cogl_matrix_entry_ref (modelview_entry);
749
326
 
750
327
  entry->bounds_x1 = bounds_x1;
751
328
  entry->bounds_y1 = bounds_y1;
752
329
  entry->bounds_x2 = bounds_x2;
753
330
  entry->bounds_y2 = bounds_y2;
754
331
 
755
 
  _cogl_matrix_entry_get (modelview_entry, &modelview);
756
 
  _cogl_matrix_entry_get (modelview_entry, &projection);
 
332
  cogl_matrix_entry_get (modelview_entry, &modelview);
 
333
  cogl_matrix_entry_get (modelview_entry, &projection);
757
334
 
758
335
  get_transformed_corners (bounds_x1, bounds_y1, bounds_x2, bounds_y2,
759
336
                           &modelview,
794
371
        case COGL_CLIP_STACK_RECT:
795
372
          {
796
373
            CoglClipStackRect *rect = (CoglClipStackRect *) entry;
797
 
            _cogl_matrix_entry_unref (rect->matrix_entry);
 
374
            cogl_matrix_entry_unref (rect->matrix_entry);
798
375
            g_slice_free1 (sizeof (CoglClipStackRect), entry);
799
376
            break;
800
377
          }
805
382
        case COGL_CLIP_STACK_PATH:
806
383
          {
807
384
            CoglClipStackPath *path_entry = (CoglClipStackPath *) entry;
808
 
            _cogl_matrix_entry_unref (path_entry->matrix_entry);
 
385
            cogl_matrix_entry_unref (path_entry->matrix_entry);
809
386
            cogl_object_unref (path_entry->path);
810
387
            g_slice_free1 (sizeof (CoglClipStackPath), entry);
811
388
            break;
814
391
          {
815
392
            CoglClipStackPrimitive *primitive_entry =
816
393
              (CoglClipStackPrimitive *) entry;
817
 
            _cogl_matrix_entry_unref (primitive_entry->matrix_entry);
 
394
            cogl_matrix_entry_unref (primitive_entry->matrix_entry);
818
395
            cogl_object_unref (primitive_entry->primitive);
819
396
            g_slice_free1 (sizeof (CoglClipStackPrimitive), entry);
820
397
            break;
869
446
    {
870
447
      /* Get the intersection of the current scissor and the bounding
871
448
         box of this clip */
872
 
      *scissor_x0 = MAX (*scissor_x0, entry->bounds_x0);
873
 
      *scissor_y0 = MAX (*scissor_y0, entry->bounds_y0);
874
 
      *scissor_x1 = MIN (*scissor_x1, entry->bounds_x1);
875
 
      *scissor_y1 = MIN (*scissor_y1, entry->bounds_y1);
 
449
      _cogl_util_scissor_intersect (entry->bounds_x0,
 
450
                                    entry->bounds_y0,
 
451
                                    entry->bounds_x1,
 
452
                                    entry->bounds_y1,
 
453
                                    scissor_x0,
 
454
                                    scissor_y0,
 
455
                                    scissor_x1,
 
456
                                    scissor_y1);
876
457
    }
877
458
}
878
459
 
881
462
                        CoglFramebuffer *framebuffer)
882
463
{
883
464
  CoglContext *ctx = framebuffer->context;
884
 
  int has_clip_planes;
885
 
  CoglBool using_clip_planes = FALSE;
886
 
  CoglBool using_stencil_buffer = FALSE;
887
 
  int scissor_x0;
888
 
  int scissor_y0;
889
 
  int scissor_x1;
890
 
  int scissor_y1;
891
 
  CoglClipStack *entry;
892
 
  int scissor_y_start;
893
 
 
894
 
  /* If we have already flushed this state then we don't need to do
895
 
     anything */
896
 
  if (ctx->current_clip_stack_valid)
897
 
    {
898
 
      if (ctx->current_clip_stack == stack)
899
 
        return;
900
 
 
901
 
      _cogl_clip_stack_unref (ctx->current_clip_stack);
902
 
    }
903
 
 
904
 
  ctx->current_clip_stack_valid = TRUE;
905
 
  ctx->current_clip_stack = _cogl_clip_stack_ref (stack);
906
 
 
907
 
  has_clip_planes =
908
 
    ctx->private_feature_flags & COGL_PRIVATE_FEATURE_FOUR_CLIP_PLANES;
909
 
 
910
 
  if (has_clip_planes)
911
 
    disable_clip_planes ();
912
 
  disable_stencil_buffer ();
913
 
 
914
 
  /* If the stack is empty then there's nothing else to do */
915
 
  if (stack == NULL)
916
 
    {
917
 
      COGL_NOTE (CLIPPING, "Flushed empty clip stack");
918
 
 
919
 
      ctx->current_clip_stack_uses_stencil = FALSE;
920
 
      GE (ctx, glDisable (GL_SCISSOR_TEST));
921
 
      return;
922
 
    }
923
 
 
924
 
  /* Calculate the scissor rect first so that if we eventually have to
925
 
     clear the stencil buffer then the clear will be clipped to the
926
 
     intersection of all of the bounding boxes. This saves having to
927
 
     clear the whole stencil buffer */
928
 
  _cogl_clip_stack_get_bounds (stack,
929
 
                               &scissor_x0, &scissor_y0,
930
 
                               &scissor_x1, &scissor_y1);
931
 
 
932
 
  /* Enable scissoring as soon as possible */
933
 
  if (scissor_x0 >= scissor_x1 || scissor_y0 >= scissor_y1)
934
 
    scissor_x0 = scissor_y0 = scissor_x1 = scissor_y1 = scissor_y_start = 0;
935
 
  else
936
 
    {
937
 
      /* We store the entry coordinates in Cogl coordinate space
938
 
       * but OpenGL requires the window origin to be the bottom
939
 
       * left so we may need to convert the incoming coordinates.
940
 
       *
941
 
       * NB: Cogl forces all offscreen rendering to be done upside
942
 
       * down so in this case no conversion is needed.
943
 
       */
944
 
 
945
 
      if (cogl_is_offscreen (framebuffer))
946
 
        scissor_y_start = scissor_y0;
947
 
      else
948
 
        {
949
 
          int framebuffer_height =
950
 
            cogl_framebuffer_get_height (framebuffer);
951
 
 
952
 
          scissor_y_start = framebuffer_height - scissor_y1;
953
 
        }
954
 
    }
955
 
 
956
 
  COGL_NOTE (CLIPPING, "Flushing scissor to (%i, %i, %i, %i)",
957
 
             scissor_x0, scissor_y0,
958
 
             scissor_x1, scissor_y1);
959
 
 
960
 
  GE (ctx, glEnable (GL_SCISSOR_TEST));
961
 
  GE (ctx, glScissor (scissor_x0, scissor_y_start,
962
 
                      scissor_x1 - scissor_x0,
963
 
                      scissor_y1 - scissor_y0));
964
 
 
965
 
  /* Add all of the entries. This will end up adding them in the
966
 
     reverse order that they were specified but as all of the clips
967
 
     are intersecting it should work out the same regardless of the
968
 
     order */
969
 
  for (entry = stack; entry; entry = entry->parent)
970
 
    {
971
 
      switch (entry->type)
972
 
        {
973
 
        case COGL_CLIP_STACK_PATH:
974
 
            {
975
 
              CoglClipStackPath *path_entry = (CoglClipStackPath *) entry;
976
 
 
977
 
              COGL_NOTE (CLIPPING, "Adding stencil clip for path");
978
 
 
979
 
              add_stencil_clip_path (framebuffer,
980
 
                                     path_entry->matrix_entry,
981
 
                                     path_entry->path,
982
 
                                     using_stencil_buffer,
983
 
                                     TRUE);
984
 
 
985
 
              using_stencil_buffer = TRUE;
986
 
              break;
987
 
            }
988
 
        case COGL_CLIP_STACK_PRIMITIVE:
989
 
            {
990
 
              CoglClipStackPrimitive *primitive_entry =
991
 
                (CoglClipStackPrimitive *) entry;
992
 
 
993
 
              COGL_NOTE (CLIPPING, "Adding stencil clip for primitive");
994
 
 
995
 
              add_stencil_clip_primitive (framebuffer,
996
 
                                          primitive_entry->matrix_entry,
997
 
                                          primitive_entry->primitive,
998
 
                                          primitive_entry->bounds_x1,
999
 
                                          primitive_entry->bounds_y1,
1000
 
                                          primitive_entry->bounds_x2,
1001
 
                                          primitive_entry->bounds_y2,
1002
 
                                          using_stencil_buffer,
1003
 
                                          TRUE);
1004
 
 
1005
 
              using_stencil_buffer = TRUE;
1006
 
              break;
1007
 
            }
1008
 
        case COGL_CLIP_STACK_RECT:
1009
 
            {
1010
 
              CoglClipStackRect *rect = (CoglClipStackRect *) entry;
1011
 
 
1012
 
              /* We don't need to do anything extra if the clip for this
1013
 
                 rectangle was entirely described by its scissor bounds */
1014
 
              if (!rect->can_be_scissor)
1015
 
                {
1016
 
                  /* If we support clip planes and we haven't already used
1017
 
                     them then use that instead */
1018
 
                  if (has_clip_planes)
1019
 
                    {
1020
 
                      COGL_NOTE (CLIPPING,
1021
 
                                 "Adding clip planes clip for rectangle");
1022
 
 
1023
 
                      set_clip_planes (framebuffer,
1024
 
                                       rect->matrix_entry,
1025
 
                                       rect->x0,
1026
 
                                       rect->y0,
1027
 
                                       rect->x1,
1028
 
                                       rect->y1);
1029
 
                      using_clip_planes = TRUE;
1030
 
                      /* We can't use clip planes a second time */
1031
 
                      has_clip_planes = FALSE;
1032
 
                    }
1033
 
                  else
1034
 
                    {
1035
 
                      COGL_NOTE (CLIPPING, "Adding stencil clip for rectangle");
1036
 
 
1037
 
                      add_stencil_clip_rectangle (framebuffer,
1038
 
                                                  rect->matrix_entry,
1039
 
                                                  rect->x0,
1040
 
                                                  rect->y0,
1041
 
                                                  rect->x1,
1042
 
                                                  rect->y1,
1043
 
                                                  !using_stencil_buffer);
1044
 
                      using_stencil_buffer = TRUE;
1045
 
                    }
1046
 
                }
1047
 
              break;
1048
 
            }
1049
 
        case COGL_CLIP_STACK_WINDOW_RECT:
1050
 
          break;
1051
 
          /* We don't need to do anything for window space rectangles because
1052
 
           * their functionality is entirely implemented by the entry bounding
1053
 
           * box */
1054
 
        }
1055
 
    }
1056
 
 
1057
 
  /* Enabling clip planes is delayed to now so that they won't affect
1058
 
     setting up the stencil buffer */
1059
 
  if (using_clip_planes)
1060
 
    enable_clip_planes ();
1061
 
 
1062
 
  ctx->current_clip_stack_uses_stencil = using_stencil_buffer;
 
465
 
 
466
  ctx->driver_vtable->clip_stack_flush (stack, framebuffer);
1063
467
}