w32tex
About: TeX Live provides a comprehensive TeX system including all the major TeX-related programs, macro packages, and fonts that are free software. Windows sources.
  Fossies Dox: w32tex-src.tar.xz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

cairo-cogl-surface.c
Go to the documentation of this file.
1 /* cairo - a vector graphics library with display and print output
2  *
3  * Copyright © 2011 Intel Corporation.
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it either under the terms of the GNU Lesser General Public
7  * License version 2.1 as published by the Free Software Foundation
8  * (the "LGPL") or, at your option, under the terms of the Mozilla
9  * Public License Version 1.1 (the "MPL"). If you do not alter this
10  * notice, a recipient may use your version of this file under either
11  * the MPL or the LGPL.
12  *
13  * You should have received a copy of the LGPL along with this library
14  * in the file COPYING-LGPL-2.1; if not, write to the Free Software
15  * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
16  * You should have received a copy of the MPL along with this library
17  * in the file COPYING-MPL-1.1
18  *
19  * The contents of this file are subject to the Mozilla Public License
20  * Version 1.1 (the "License"); you may not use this file except in
21  * compliance with the License. You may obtain a copy of the License at
22  * http://www.mozilla.og/MPL/
23  *
24  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
25  * OF ANY KIND, either express or implied. See the LGPL or the MPL for
26  * the specific language governing rights and limitations.
27  *
28  * Contributor(s):
29  * Robert Bragg <robert@linux.intel.com>
30  */
31 #include "cairoint.h"
32 
33 #include "cairo-cache-private.h"
34 #include "cairo-error-private.h"
38 #include "cairo-fixed-private.h"
39 #include "cairo-device-private.h"
42 #include "cairo-cogl-private.h"
44 #include "cairo-arc-private.h"
45 #include "cairo-traps-private.h"
48 #include "cairo-box-inline.h"
52 
53 #include "cairo-cogl.h"
54 
55 #include <cogl/cogl2-experimental.h>
56 #include <glib.h>
57 
58 #define CAIRO_COGL_DEBUG 0
59 //#define FILL_WITH_COGL_PATH
60 //#define USE_CAIRO_PATH_FLATTENER
61 #define ENABLE_PATH_CACHE
62 //#define DISABLE_BATCHING
63 #define USE_COGL_RECTANGLE_API
64 #define ENABLE_RECTANGLES_FASTPATH
65 
66 #if defined (USE_COGL_RECTANGLE_API) || defined (ENABLE_PATH_CACHE)
67 #define NEED_COGL_CONTEXT
68 #endif
69 
70 #if CAIRO_COGL_DEBUG && __GNUC__
71 #define UNSUPPORTED(reason) ({ \
72  g_warning ("cairo-cogl: hit unsupported operation: %s", reason); \
73  CAIRO_INT_STATUS_UNSUPPORTED; \
74 })
75 #else
76 #define UNSUPPORTED(reason) CAIRO_INT_STATUS_UNSUPPORTED
77 #endif
78 
79 #define CAIRO_COGL_PATH_META_CACHE_SIZE (1024 * 1024)
80 
81 typedef struct _cairo_cogl_texture_attributes {
82  /* nabbed from cairo_surface_attributes_t... */
87 
88  CoglPipelineWrapMode s_wrap;
89  CoglPipelineWrapMode t_wrap;
91 
98 
99 typedef struct _cairo_cogl_journal_entry {
102 
103 typedef struct _cairo_cogl_journal_clip_entry {
107 
108 typedef struct _cairo_cogl_journal_rect_entry {
110  CoglPipeline *pipeline;
111  float x;
112  float y;
113  float width;
114  float height;
115  int n_layers;
118 
119 typedef struct _cairo_cogl_journal_prim_entry {
121  CoglPipeline *pipeline;
122  CoglPrimitive *primitive;
123  gboolean has_transform;
126 
127 typedef struct _cairo_cogl_journal_path_entry {
129  CoglPipeline *pipeline;
130  CoglPath *path;
132 
133 typedef struct _cairo_cogl_path_fill_meta {
136  int counter;
139 
140  /* TODO */
141 #if 0
142  /* A cached path tessellation should be re-usable with different rotations
143  * and translations but not for different scales.
144  *
145  * one idea is to track the diagonal lenghts of a unit rectangle
146  * transformed through the original ctm use to tessellate the geometry
147  * so we can check what the lengths are for any new ctm to know if
148  * this geometry is compatible.
149  */
150 #endif
151 
152  CoglPrimitive *prim;
154 
155 typedef struct _cairo_cogl_path_stroke_meta {
158  int counter;
162  double tolerance;
163 
164  /* TODO */
165 #if 0
166  /* A cached path tessellation should be re-usable with different rotations
167  * and translations but not for different scales.
168  *
169  * one idea is to track the diagonal lenghts of a unit rectangle
170  * transformed through the original ctm use to tessellate the geometry
171  * so we can check what the lengths are for any new ctm to know if
172  * this geometry is compatible.
173  */
174 #endif
175 
176  CoglPrimitive *prim;
178 
179 static cairo_surface_t *
181  cairo_bool_t ignore_alpha,
182  CoglFramebuffer *framebuffer,
183  CoglTexture *texture);
184 
185 static cairo_int_status_t
186 _cairo_cogl_surface_fill (void *abstract_surface,
188  const cairo_pattern_t *source,
189  const cairo_path_fixed_t *path,
190  cairo_fill_rule_t fill_rule,
191  double tolerance,
193  const cairo_clip_t *clip);
194 
195 static void
197 
199 
205 
206 static cairo_cogl_device_t *
208 {
209  return (cairo_cogl_device_t *)device;
210 }
211 
212 /* moves trap points such that they become the actual corners of the trapezoid */
213 static void
215 {
216  cairo_trapezoid_t s = *t;
217 
218 #define FIX(lr, tb, p) \
219  if (t->lr.p.y != t->tb) { \
220  t->lr.p.x = s.lr.p2.x + _cairo_fixed_mul_div_floor (s.lr.p1.x - s.lr.p2.x, s.tb - s.lr.p2.y, s.lr.p1.y - s.lr.p2.y); \
221  t->lr.p.y = s.tb; \
222  }
223  FIX (left, top, p1);
224  FIX (left, bottom, p2);
225  FIX (right, top, p1);
226  FIX (right, bottom, p2);
227 }
228 
229 static cairo_status_t
231 {
232  GError *error = NULL;
233 
234  if (surface->framebuffer)
235  return CAIRO_STATUS_SUCCESS;
236 
237  surface->framebuffer = COGL_FRAMEBUFFER (cogl_offscreen_new_to_texture (surface->texture));
238  if (!cogl_framebuffer_allocate (surface->framebuffer, &error)) {
239  g_error_free (error);
240  cogl_object_unref (surface->framebuffer);
241  surface->framebuffer = NULL;
242  return CAIRO_STATUS_NO_MEMORY;
243  }
244 
245  cogl_push_framebuffer (surface->framebuffer);
246  cogl_ortho (0, surface->width,
247  surface->height, 0,
248  -1, 100);
249  cogl_pop_framebuffer ();
250 
251  return CAIRO_STATUS_SUCCESS;
252 }
253 
254 static cairo_surface_t *
255 _cairo_cogl_surface_create_similar (void *abstract_surface,
257  int width,
258  int height)
259 {
260  cairo_cogl_surface_t *reference_surface = abstract_surface;
262  CoglTexture *texture;
264 
265  texture = cogl_texture_new_with_size (width, height,
266  COGL_TEXTURE_NO_SLICING,
268  COGL_PIXEL_FORMAT_BGRA_8888_PRE :
269  COGL_PIXEL_FORMAT_A_8);
270  if (!texture)
272 
275  (content & CAIRO_CONTENT_ALPHA) == 0,
276  NULL,
277  texture);
278  if (unlikely (surface->base.status))
279  return &surface->base;
280 
282  if (unlikely (status)) {
285  }
286 
287  return &surface->base;
288 }
289 
290 static cairo_bool_t
291 _cairo_cogl_surface_get_extents (void *abstract_surface,
293 {
294  cairo_cogl_surface_t *surface = abstract_surface;
295 
296  extents->x = 0;
297  extents->y = 0;
298  extents->width = surface->width;
299  extents->height = surface->height;
300 
301  return TRUE;
302 }
303 
304 static void
306 {
307  GList *l;
308 
309  for (l = surface->journal->head; l; l = l->next) {
311 
313  cairo_cogl_journal_prim_entry_t *prim_entry =
315  cogl_object_unref (prim_entry->primitive);
317  cairo_cogl_journal_path_entry_t *path_entry =
319  cogl_object_unref (path_entry->path);
320  }
321  }
322 
323  g_queue_free (surface->journal);
324  surface->journal = NULL;
325 }
326 
327 #ifdef FILL_WITH_COGL_PATH
328 static void
329 _cairo_cogl_journal_log_path (cairo_cogl_surface_t *surface,
330  CoglPipeline *pipeline,
331  CoglPath *path)
332 {
334 
335  if (unlikely (surface->journal == NULL))
336  surface->journal = g_queue_new ();
337 
338  /* FIXME: Instead of a GList here we should stack allocate the journal
339  * entries so it would be cheaper to allocate and they can all be freed in
340  * one go after flushing! */
341  entry = g_slice_new (cairo_cogl_journal_path_entry_t);
343 
344  entry->pipeline = cogl_object_ref (pipeline);
345  entry->path = cogl_object_ref (path);
346 
347  g_queue_push_tail (surface->journal, entry);
348 
349 #ifdef DISABLE_BATCHING
351 #endif
352 }
353 #endif /* FILL_WITH_COGL_PATH */
354 
355 static void
357  CoglPipeline *pipeline,
358  CoglPrimitive *primitive,
360 {
362 
363  if (unlikely (surface->journal == NULL))
364  surface->journal = g_queue_new ();
365 
366  /* FIXME: Instead of a GList here we should stack allocate the journal
367  * entries so it would be cheaper to allocate and they can all be freed in
368  * one go after flushing! */
369  entry = g_slice_new (cairo_cogl_journal_prim_entry_t);
371 
372  entry->pipeline = cogl_object_ref (pipeline);
373 
374  if (transform) {
375  entry->transform = *transform;
376  entry->has_transform = TRUE;
377  } else
378  entry->has_transform = FALSE;
379 
380  entry->primitive = cogl_object_ref (primitive);
381 
382  g_queue_push_tail (surface->journal, entry);
383 
384 #ifdef DISABLE_BATCHING
386 #endif
387 }
388 
389 static void
391  CoglPipeline *pipeline,
392  float x,
393  float y,
394  float width,
395  float height,
396  int n_layers,
397  cairo_matrix_t *ctm)
398 {
400 
401  if (unlikely (surface->journal == NULL))
402  surface->journal = g_queue_new ();
403 
404  /* FIXME: Instead of a GList here we should stack allocate the journal
405  * entries so it would be cheaper to allocate and they can all be freed in
406  * one go after flushing! */
407  entry = g_slice_new (cairo_cogl_journal_rect_entry_t);
409 
410  entry->pipeline = cogl_object_ref (pipeline);
411 
412  entry->x = x;
413  entry->y = y;
414  entry->width = width;
415  entry->height = height;
416  entry->ctm = *ctm;
417 
418  entry->n_layers = n_layers;
419 
420  g_queue_push_tail (surface->journal, entry);
421 
422 #ifdef DISABLE_BATCHING
424 #endif
425 }
426 
427 static void
429  const cairo_clip_t *clip)
430 {
432 
433  if (unlikely (surface->journal == NULL))
434  surface->journal = g_queue_new ();
435 
436  /* FIXME: Instead of a GList here we should stack allocate the journal
437  * entries so it would be cheaper to allocate and they can all be freed in
438  * one go after flushing! */
439  entry = g_slice_new (cairo_cogl_journal_clip_entry_t);
441  entry->clip = _cairo_clip_copy (clip);
442 
443  g_queue_push_tail (surface->journal, entry);
444 }
445 
446 static void
448 {
449  GList *l;
450 
451  if (!surface->journal) {
452  assert (surface->last_clip == NULL);
453  return;
454  }
455 
456  if (surface->buffer_stack && surface->buffer_stack_offset) {
457  cogl_buffer_unmap (COGL_BUFFER (surface->buffer_stack));
458  cogl_object_unref (surface->buffer_stack);
459  surface->buffer_stack = NULL;
460  }
461 
462  for (l = surface->journal->head; l; l = l->next) {
464  gsize entry_size;
465 
466  switch (entry->type)
467  {
469  cairo_cogl_journal_clip_entry_t *clip_entry =
471  _cairo_clip_destroy (clip_entry->clip);
472  entry_size = sizeof (cairo_cogl_journal_clip_entry_t);
473  break;
474  }
476  cairo_cogl_journal_rect_entry_t *rect_entry =
478  cogl_object_unref (rect_entry->pipeline);
479  entry_size = sizeof (cairo_cogl_journal_rect_entry_t);
480  break;
481  }
483  cairo_cogl_journal_prim_entry_t *prim_entry =
485  cogl_object_unref (prim_entry->pipeline);
486  cogl_object_unref (prim_entry->primitive);
487  entry_size = sizeof (cairo_cogl_journal_prim_entry_t);
488  break;
489  }
491  cairo_cogl_journal_path_entry_t *path_entry =
493  cogl_object_unref (path_entry->pipeline);
494  cogl_object_unref (path_entry->path);
495  entry_size = sizeof (cairo_cogl_journal_path_entry_t);
496  break;
497  }
498  default:
499  assert (0); /* not reached! */
500  entry_size = 0; /* avoid compiler warning */
501  }
502  g_slice_free1 (entry_size, entry);
503  }
504 
505  g_queue_clear (surface->journal);
506 
507  if (surface->last_clip) {
508  _cairo_clip_destroy (surface->last_clip);
509  surface->last_clip = NULL;
510  }
511 }
512 
513 static CoglAttributeBuffer *
515  size_t size,
516  size_t *offset,
517  void **pointer)
518 {
519  /* XXX: In the Cogl journal we found it more efficient to have a pool of
520  * buffers that we re-cycle but for now we simply throw away our stack
521  * buffer each time we flush. */
522  if (unlikely (surface->buffer_stack &&
523  (surface->buffer_stack_size - surface->buffer_stack_offset) < size)) {
524  cogl_buffer_unmap (COGL_BUFFER (surface->buffer_stack));
525  cogl_object_unref (surface->buffer_stack);
526  surface->buffer_stack = NULL;
527  surface->buffer_stack_size *= 2;
528  }
529 
530  if (unlikely (surface->buffer_stack_size < size))
531  surface->buffer_stack_size = size * 2;
532 
533  if (unlikely (surface->buffer_stack == NULL)) {
534  surface->buffer_stack = cogl_attribute_buffer_new (surface->buffer_stack_size, NULL);
535  surface->buffer_stack_pointer =
536  cogl_buffer_map (COGL_BUFFER (surface->buffer_stack),
537  COGL_BUFFER_ACCESS_WRITE,
538  COGL_BUFFER_MAP_HINT_DISCARD);
539  surface->buffer_stack_offset = 0;
540  }
541 
542  *pointer = surface->buffer_stack_pointer + surface->buffer_stack_offset;
543  *offset = surface->buffer_stack_offset;
544 
545  surface->buffer_stack_offset += size;
546  return cogl_object_ref (surface->buffer_stack);
547 }
548 
549 
550 static CoglAttributeBuffer *
552  cairo_traps_t *traps,
553  size_t *offset,
554  gboolean one_shot)
555 {
556  CoglAttributeBuffer *buffer;
557  int n_traps = traps->num_traps;
558  int i;
559  CoglVertexP2 *triangles;
560 
561  if (one_shot) {
563  n_traps * sizeof (CoglVertexP2) * 6,
564  offset,
565  (void **)&triangles);
566  if (!buffer)
567  return NULL;
568  } else {
569  buffer = cogl_attribute_buffer_new (n_traps * sizeof (CoglVertexP2) * 6, NULL);
570  if (!buffer)
571  return NULL;
572  triangles = cogl_buffer_map (COGL_BUFFER (buffer),
573  COGL_BUFFER_ACCESS_WRITE,
574  COGL_BUFFER_MAP_HINT_DISCARD);
575  if (!triangles)
576  return NULL;
577  *offset = 0;
578  }
579 
580  /* XXX: This is can be very expensive. I'm not sure a.t.m if it's
581  * predominantly the bandwidth required or the cost of the fixed_to_float
582  * conversions but either way we should try using an index buffer to
583  * reduce the amount we upload by 1/3 (offset by allocating and uploading
584  * indices though) sadly though my experience with the intel mesa drivers
585  * is that slow paths can easily be hit when starting to use indices.
586  */
587  for (i = 0; i < n_traps; i++)
588  {
589  CoglVertexP2 *p = &triangles[i * 6];
590  cairo_trapezoid_t *trap = &traps->traps[i];
591 
592  p[0].x = _cairo_cogl_util_fixed_to_float (trap->left.p1.x);
593  p[0].y = _cairo_cogl_util_fixed_to_float (trap->left.p1.y);
594 
595  p[1].x = _cairo_cogl_util_fixed_to_float (trap->left.p2.x);
596  p[1].y = _cairo_cogl_util_fixed_to_float (trap->left.p2.y);
597 
598  p[2].x = _cairo_cogl_util_fixed_to_float (trap->right.p2.x);
599  p[2].y = _cairo_cogl_util_fixed_to_float (trap->right.p2.y);
600 
601  p[3].x = _cairo_cogl_util_fixed_to_float (trap->left.p1.x);
602  p[3].y = _cairo_cogl_util_fixed_to_float (trap->left.p1.y);
603 
604  p[4].x = _cairo_cogl_util_fixed_to_float (trap->right.p2.x);
605  p[4].y = _cairo_cogl_util_fixed_to_float (trap->right.p2.y);
606 
607  p[5].x = _cairo_cogl_util_fixed_to_float (trap->right.p1.x);
608  p[5].y = _cairo_cogl_util_fixed_to_float (trap->right.p1.y);
609  }
610 
611  if (!one_shot)
612  cogl_buffer_unmap (COGL_BUFFER (buffer));
613 
614  return buffer;
615 }
616 
617 /* Used for solid fills, in this case we just need a mesh made of
618  * a single (2-component) position attribute. */
619 static CoglPrimitive *
621  cairo_traps_t *traps,
622  gboolean one_shot)
623 {
624  size_t offset;
625  CoglAttributeBuffer *buffer = _cairo_cogl_traps_to_triangles_buffer (surface, traps, &offset, one_shot);
626  CoglAttribute *pos = cogl_attribute_new (buffer,
627  "cogl_position_in",
628  sizeof (CoglVertexP2),
629  offset,
630  2,
631  COGL_ATTRIBUTE_TYPE_FLOAT);
632  CoglPrimitive *prim;
633 
634  /* The attribute will have taken a reference on the buffer */
635  cogl_object_unref (buffer);
636 
637  prim = cogl_primitive_new (COGL_VERTICES_MODE_TRIANGLES,
638  traps->num_traps * 6, pos, NULL);
639 
640  /* The primitive will now keep the attribute alive... */
641  cogl_object_unref (pos);
642 
643  return prim;
644 }
645 
646 /* Used for surface fills, in this case we need a mesh made of a single
647  * (2-component) position attribute + we also alias the same attribute as
648  * (2-component) texture coordinates */
649 static CoglPrimitive *
651  cairo_traps_t *traps,
652  gboolean one_shot)
653 {
654  size_t offset;
655  CoglAttributeBuffer *buffer = _cairo_cogl_traps_to_triangles_buffer (surface, traps, &offset, one_shot);
656  CoglAttribute *pos = cogl_attribute_new (buffer,
657  "cogl_position_in",
658  sizeof (CoglVertexP2),
659  offset,
660  2,
661  COGL_ATTRIBUTE_TYPE_FLOAT);
662  CoglAttribute *tex_coords = cogl_attribute_new (buffer,
663  "cogl_tex_coord0_in",
664  sizeof (CoglVertexP2),
665  0,
666  2,
667  COGL_ATTRIBUTE_TYPE_FLOAT);
668  CoglPrimitive *prim;
669 
670  /* The attributes will have taken references on the buffer */
671  cogl_object_unref (buffer);
672 
673  prim = cogl_primitive_new (COGL_VERTICES_MODE_TRIANGLES,
674  traps->num_traps * 6, pos, tex_coords, NULL);
675 
676  /* The primitive will now keep the attributes alive... */
677  cogl_object_unref (pos);
678  cogl_object_unref (tex_coords);
679 
680  return prim;
681 }
682 
683 static CoglPrimitive *
685  cairo_traps_t *traps,
686  int n_layers,
687  gboolean one_shot)
688 {
689  int n_traps = traps->num_traps;
690  int i;
691 
692  /* XXX: Ideally we would skip tessellating to traps entirely since
693  * given their representation, conversion to triangles is quite expensive.
694  *
695  * This simplifies the conversion to triangles by making the end points of
696  * the two side lines actually just correspond to the corners of the
697  * traps.
698  */
699  for (i = 0; i < n_traps; i++)
700  _sanitize_trap (&traps->traps[i]);
701 
702  if (n_layers == 0)
703  return _cairo_cogl_traps_to_composite_prim_p2 (surface, traps, one_shot);
704  else {
705  assert (n_layers == 1);
706  return _cairo_cogl_traps_to_composite_prim_p2t2 (surface, traps, one_shot);
707  }
708 }
709 
710 static cairo_int_status_t
712  const cairo_path_fixed_t *path,
713  cairo_fill_rule_t fill_rule,
714  double tolerance,
715  int n_layers,
716  cairo_bool_t one_shot,
717  CoglPrimitive **primitive,
718  size_t *size)
719 {
720  cairo_traps_t traps;
722 
723  _cairo_traps_init (&traps);
724  status = _cairo_path_fixed_fill_to_traps (path, fill_rule, tolerance, &traps);
725  if (unlikely (status))
726  goto BAIL;
727 
728  if (traps.num_traps == 0) {
730  goto BAIL;
731  }
732 
733  *size = traps.num_traps * sizeof (CoglVertexP2) * 6;
734 
735  *primitive = _cairo_cogl_traps_to_composite_prim (surface, &traps, n_layers, one_shot);
736  if (!*primitive) {
738  goto BAIL;
739  }
740 
741 BAIL:
742  _cairo_traps_fini (&traps);
743  return status;
744 }
745 
746 static void
748 {
752  cogl_clip_push_window_rectangle (rect.x, rect.y,
753  rect.width, rect.height);
754  } else {
755  double x1, y1, x2, y2;
756  _cairo_box_to_doubles (box, &x1, &y1, &x2, &y2);
757  cogl_clip_push_rectangle (x1, y1, x2, y2);
758  }
759 }
760 
761 static void
763 {
764  GList *l;
765  int clip_stack_depth = 0;
766  int i;
767 
768  if (!surface->journal)
769  return;
770 
771  if (surface->buffer_stack && surface->buffer_stack_offset) {
772  cogl_buffer_unmap (COGL_BUFFER (surface->buffer_stack));
773  cogl_object_unref (surface->buffer_stack);
774  surface->buffer_stack = NULL;
775  }
776 
777  cogl_set_framebuffer (surface->framebuffer);
778 
779  cogl_push_matrix ();
780 
781  for (l = surface->journal->head; l; l = l->next) {
783 
784  switch (entry->type)
785  {
787  cairo_cogl_journal_clip_entry_t *clip_entry =
790 #if 0
791  cairo_bool_t checked_for_primitives = FALSE;
792  cairo_cogl_clip_primitives_t *clip_primitives;
793 #endif
794 
795  for (i = 0; i < clip_stack_depth; i++)
796  cogl_clip_pop ();
797  clip_stack_depth = 0;
798 
799  for (path = clip_entry->clip->path, i = 0; path; path = path->prev, i++) {
802  CoglPrimitive *prim;
803  size_t prim_size;
804 
806 
807  /* TODO - maintain a fifo of the last 10 used clips with cached
808  * primitives to see if we can avoid tessellating the path and
809  * uploading the vertices...
810  */
811 #if 0
812  if (!checked_for_primitives) {
813  clip_primitives = find_clip_primitives (clip);
814  checked_for_primitives = TRUE;
815  }
816  if (clip_primitives)
817  prim = clip_primitives->primitives[i];
818 #endif
820  &path->path,
821  path->fill_rule,
822  path->tolerance,
823  0,
824  TRUE,
825  &prim,
826  &prim_size);
827  if (unlikely (status)) {
828  g_warning ("Failed to get primitive for clip path while flushing journal");
829  continue;
830  }
831  clip_stack_depth++;
832  cogl_clip_push_primitive (prim,
833  extents.x, extents.y,
834  extents.x + extents.width,
835  extents.y + extents.height);
836  cogl_object_unref (prim);
837  }
838 
839  for (i = 0; i < clip_entry->clip->num_boxes; i++) {
840  clip_stack_depth++;
841  _cairo_cogl_clip_push_box (&clip_entry->clip->boxes[i]);
842  }
843 
844  surface->n_clip_updates_per_frame++;
845  break;
846  }
848  cairo_cogl_journal_rect_entry_t *rect_entry =
850  float tex_coords[8];
851  float x1 = rect_entry->x;
852  float y1 = rect_entry->y;
853  float x2 = rect_entry->x + rect_entry->width;
854  float y2 = rect_entry->y + rect_entry->height;
855  cairo_matrix_t *ctm = &rect_entry->ctm;
856  float ctmfv[16] = {
857  ctm->xx, ctm->yx, 0, 0,
858  ctm->xy, ctm->yy, 0, 0,
859  0, 0, 1, 0,
860  ctm->x0, ctm->y0, 0, 1
861  };
862  CoglMatrix transform;
863 
864  cogl_matrix_init_from_array (&transform, ctmfv);
865 
866  if (rect_entry->n_layers) {
867  g_assert (rect_entry->n_layers <= 2);
868  tex_coords[0] = x1;
869  tex_coords[1] = y1;
870  tex_coords[2] = x2;
871  tex_coords[3] = y2;
872  if (rect_entry->n_layers > 1)
873  memcpy (&tex_coords[4], tex_coords, sizeof (float) * 4);
874  }
875 
876  cogl_set_source (rect_entry->pipeline);
877  cogl_push_matrix ();
878  cogl_transform (&transform);
879  cogl_rectangle_with_multitexture_coords (x1, y1, x2, y2,
880  tex_coords, 4 * rect_entry->n_layers);
881  cogl_pop_matrix ();
882  break;
883  }
885  cairo_cogl_journal_prim_entry_t *prim_entry =
887  CoglMatrix transform;
888 
889  cogl_push_matrix ();
890  if (prim_entry->has_transform) {
891  cairo_matrix_t *ctm = &prim_entry->transform;
892  float ctmfv[16] = {
893  ctm->xx, ctm->yx, 0, 0,
894  ctm->xy, ctm->yy, 0, 0,
895  0, 0, 1, 0,
896  ctm->x0, ctm->y0, 0, 1
897  };
898  cogl_matrix_init_from_array (&transform, ctmfv);
899  cogl_transform (&transform);
900  } else {
901  cogl_matrix_init_identity (&transform);
902  cogl_set_modelview_matrix (&transform);
903  }
904 
905  cogl_set_source (prim_entry->pipeline);
906  cogl_primitive_draw (prim_entry->primitive);
907  cogl_pop_matrix ();
908  break;
909  }
911  cairo_cogl_journal_path_entry_t *path_entry =
913 
914  cogl_set_source (path_entry->pipeline);
915  cogl_path_fill (path_entry->path);
916  break;
917  }
918  default:
919  assert (0); /* not reached! */
920  }
921  }
922 
923  cogl_pop_matrix ();
924 
925  for (i = 0; i < clip_stack_depth; i++)
926  cogl_clip_pop ();
927 
929 }
930 
931 static cairo_status_t
932 _cairo_cogl_surface_flush (void *abstract_surface,
933  unsigned flags)
934 {
935  cairo_cogl_surface_t *surface = (cairo_cogl_surface_t *)abstract_surface;
936 
937  if (flags)
938  return CAIRO_STATUS_SUCCESS;
939 
941 
942  return CAIRO_STATUS_SUCCESS;
943 }
944 
945 static cairo_status_t
946 _cairo_cogl_surface_finish (void *abstract_surface)
947 {
948  cairo_cogl_surface_t *surface = abstract_surface;
949 
950  if (surface->texture)
951  cogl_object_unref (surface->texture);
952 
953  if (surface->framebuffer)
954  cogl_object_unref (surface->framebuffer);
955 
956  if (surface->journal)
958 
959  /*XXX wtf */
961 
962  return CAIRO_STATUS_SUCCESS;
963 }
964 
965 static CoglPixelFormat
967 
968 /* XXX: We often use RGBA format for onscreen framebuffers so make sure
969  * to handle CAIRO_FORMAT_INVALID sensibly */
970 static cairo_format_t
972 {
973  switch ((int)format)
974  {
975  case COGL_PIXEL_FORMAT_A_8:
976  return CAIRO_FORMAT_A8;
977  case COGL_PIXEL_FORMAT_RGB_565:
978  return CAIRO_FORMAT_RGB16_565;
979 
980  case COGL_PIXEL_FORMAT_BGRA_8888_PRE:
981  case COGL_PIXEL_FORMAT_ARGB_8888_PRE:
982  case COGL_PIXEL_FORMAT_RGBA_8888_PRE:
983  /* Note: this is ambiguous since CAIRO_FORMAT_RGB24
984  * would also map to the same CoglPixelFormat */
985  return CAIRO_FORMAT_ARGB32;
986 
987  default:
988  g_warning("bad format: %x a? %d, bgr? %d, pre %d, format: %d\n",
989  format,
990  format & COGL_A_BIT,
991  format & COGL_BGR_BIT,
992  format & COGL_PREMULT_BIT,
993  format & ~(COGL_A_BIT | COGL_BGR_BIT | COGL_PREMULT_BIT));
994  return CAIRO_FORMAT_INVALID;
995  }
996 }
997 
998 static CoglPixelFormat
1000 {
1001  switch (cairo_format)
1002  {
1003  case CAIRO_FORMAT_ARGB32:
1004  case CAIRO_FORMAT_RGB24:
1005 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1006  return COGL_PIXEL_FORMAT_BGRA_8888_PRE;
1007 #else
1008  return COGL_PIXEL_FORMAT_ARGB_8888_PRE;
1009 #endif
1010  case CAIRO_FORMAT_A8:
1011  return COGL_PIXEL_FORMAT_A_8;
1013  return COGL_PIXEL_FORMAT_RGB_565;
1014  case CAIRO_FORMAT_INVALID:
1015  case CAIRO_FORMAT_A1:
1016  case CAIRO_FORMAT_RGB30:
1017  return 0;
1018  }
1019 
1020  g_warn_if_reached ();
1021  return 0;
1022 }
1023 
1024 static cairo_status_t
1027  cairo_image_surface_t **image_out)
1028 {
1031  cairo_format_t cairo_format;
1032  CoglPixelFormat cogl_format;
1033 
1034  /* TODO: Add cogl_texture_get_region() API so we don't have to ensure the
1035  * surface is bound to an fbo to read back pixels */
1037  if (unlikely (status))
1038  return status;
1039 
1040  cairo_format = get_cairo_format_from_cogl_format (surface->cogl_format);
1041  if (cairo_format == CAIRO_FORMAT_INVALID) {
1042  cairo_format = CAIRO_FORMAT_ARGB32;
1043  cogl_format = get_cogl_format_from_cairo_format (cairo_format);
1044  } else {
1045  cogl_format = cogl_framebuffer_get_color_format (surface->framebuffer);
1046  }
1047 
1049  cairo_image_surface_create (cairo_format, surface->width, surface->height);
1050  if (image->base.status)
1051  return image->base.status;
1052 
1053  /* TODO: Add cogl_framebuffer_read_pixels() API */
1054  cogl_push_framebuffer (surface->framebuffer);
1055  cogl_read_pixels (0, 0, surface->width, surface->height,
1056  COGL_READ_PIXELS_COLOR_BUFFER,
1057  cogl_format,
1058  image->data);
1059  cogl_pop_framebuffer ();
1060 
1061  *image_out = image;
1062 
1063  return CAIRO_STATUS_SUCCESS;
1064 }
1065 
1066 static cairo_status_t
1068  cairo_image_surface_t **image_out,
1069  void **image_extra)
1070 {
1071  cairo_cogl_surface_t *surface = abstract_surface;
1073 
1074  if (surface->texture) {
1077  cairo_image_surface_create (format, surface->width, surface->height);
1078  if (image->base.status)
1079  return image->base.status;
1080 
1081  cogl_texture_get_data (surface->texture,
1082  cogl_texture_get_format (surface->texture),
1083  0,
1084  image->data);
1085 
1086  image->base.is_clear = FALSE;
1087  *image_out = image;
1088  } else {
1090  0, 0, surface->width, surface->height
1091  };
1093  image_out);
1094  if (unlikely (status))
1095  return status;
1096  }
1097 
1098  *image_extra = NULL;
1099 
1100  return CAIRO_STATUS_SUCCESS;
1101 }
1102 
1103 static void
1106  void *image_extra)
1107 {
1108  cairo_surface_destroy (&image->base);
1109 }
1110 
1111 static cairo_status_t
1113  const cairo_color_t *color)
1114 {
1115  /* Anything batched in the journal up until now is redundant... */
1117 
1118  /* XXX: we currently implicitly clear the depth and stencil buffer here
1119  * but since we use the framebuffer_discard extension when available I
1120  * suppose this doesn't matter too much.
1121  *
1122  * The main concern is that we want to avoid re-loading an external z
1123  * buffer at the start of each frame, but also many gpu architectures have
1124  * optimizations for how they handle the depth/stencil buffers and can get
1125  * upset if they aren't cleared together at the start of the frame.
1126  *
1127  * FIXME: we need a way to assert that the clip stack currently isn't
1128  * using the stencil buffer before clearing it here!
1129  */
1130  cogl_framebuffer_clear4f (surface->framebuffer,
1131  COGL_BUFFER_BIT_COLOR |
1132  COGL_BUFFER_BIT_DEPTH |
1133  COGL_BUFFER_BIT_STENCIL,
1134  color->red * color->alpha,
1135  color->green * color->alpha,
1136  color->blue * color->alpha,
1137  color->alpha);
1138  return CAIRO_STATUS_SUCCESS;
1139 }
1140 
1143  cairo_fixed_t x,
1144  cairo_fixed_t y,
1147 {
1149 
1151  if (unlikely (status))
1152  return status;
1153 
1155  if (unlikely (status))
1156  return status;
1157 
1159  if (unlikely (status))
1160  return status;
1161 
1163  if (unlikely (status))
1164  return status;
1165 
1167  if (unlikely (status))
1168  return status;
1169 
1170  return CAIRO_STATUS_SUCCESS;
1171 }
1172 
1173 static cairo_int_status_t
1174 _cairo_cogl_surface_paint (void *abstract_surface,
1176  const cairo_pattern_t *source,
1177  const cairo_clip_t *clip)
1178 {
1183 
1184  if (clip == NULL) {
1185  if (op == CAIRO_OPERATOR_CLEAR)
1186  return _cairo_cogl_surface_clear (abstract_surface, CAIRO_COLOR_TRANSPARENT);
1187  else if (source->type == CAIRO_PATTERN_TYPE_SOLID &&
1188  (op == CAIRO_OPERATOR_SOURCE ||
1189  (op == CAIRO_OPERATOR_OVER && (((cairo_surface_t *)abstract_surface)->is_clear || _cairo_pattern_is_opaque_solid (source))))) {
1190  return _cairo_cogl_surface_clear (abstract_surface,
1192  }
1193  }
1194 
1195  /* fallback to handling the paint in terms of a fill... */
1196 
1197  surface = abstract_surface;
1198 
1200 
1201  status = _cairo_cogl_path_fixed_rectangle (&path, 0, 0, surface->width, surface->height);
1202  if (unlikely (status))
1203  goto BAIL;
1204 
1205 #ifdef NEED_COGL_CONTEXT
1206  /* XXX: in cairo-cogl-context.c we set some sideband data on the
1207  * surface before issuing a fill so we need to do that here too... */
1208  surface->user_path = &path;
1210  surface->ctm = &identity;
1211  surface->ctm_inverse = &identity;
1212  surface->path_is_rectangle = TRUE;
1213  surface->path_rectangle_x = 0;
1214  surface->path_rectangle_y = 0;
1215  surface->path_rectangle_width = surface->width;
1216  surface->path_rectangle_height = surface->height;
1217 #endif
1218 
1219  status = _cairo_cogl_surface_fill (abstract_surface,
1220  op,
1221  source,
1222  &path,
1224  1,
1226  clip);
1227 BAIL:
1229  return status;
1230 }
1231 
1232 static CoglPipelineWrapMode
1234 {
1235  switch (extend_mode)
1236  {
1237  case CAIRO_EXTEND_NONE:
1238  return COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE;
1239  case CAIRO_EXTEND_PAD:
1240  return COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE;
1241  case CAIRO_EXTEND_REPEAT:
1242  return COGL_PIPELINE_WRAP_MODE_REPEAT;
1243  case CAIRO_EXTEND_REFLECT:
1244  /* TODO: return COGL_PIPELINE_WRAP_MODE_MIRROR; */
1245  return CAIRO_EXTEND_REPEAT;
1246  }
1247  assert (0); /* not reached */
1248  return COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE;
1249 }
1250 
1251 #if 0
1252 /* Given an arbitrary texture, check if it's already a pot texture and simply
1253  * return it back if so. If not create a new pot texture, scale the old to
1254  * fill it, unref the old and return a pointer to the new pot texture. */
1255 static cairo_int_status_t
1256 _cairo_cogl_get_pot_texture (CoglContext *context,
1257  CoglTexture *texture,
1258  CoglTexture **pot_texture)
1259 {
1260  int width = cogl_texture_get_width (texture);
1261  int height = cogl_texture_get_height (texture);
1262  int pot_width;
1263  int pot_height;
1264  CoglHandle offscreen = NULL;
1265  CoglTexture2D *pot = NULL;
1266  GError *error;
1267 
1268  pot_width = _cairo_cogl_util_next_p2 (width);
1269  pot_height = _cairo_cogl_util_next_p2 (height);
1270 
1271  if (pot_width == width && pot_height == height)
1272  return CAIRO_INT_STATUS_SUCCESS;
1273 
1274  for (;;) {
1275  error = NULL;
1276  pot = cogl_texture_2d_new_with_size (context,
1277  pot_width,
1278  pot_height,
1279  cogl_texture_get_format (texture),
1280  &error);
1281  if (pot)
1282  break;
1283  else
1284  g_error_free (error);
1285 
1286  if (pot_width > pot_height)
1287  pot_width >>= 1;
1288  else
1289  pot_height >>= 1;
1290 
1291  if (!pot_width || !pot_height)
1292  break;
1293  }
1294 
1295  *pot_texture = COGL_TEXTURE (pot);
1296 
1297  if (!pot)
1299 
1300  /* Use the GPU to do a bilinear filtered scale from npot to pot... */
1301  offscreen = cogl_offscreen_new_to_texture (COGL_TEXTURE (pot));
1302  error = NULL;
1303  if (!cogl_framebuffer_allocate (COGL_FRAMEBUFFER (offscreen), &error)) {
1304  /* NB: if we don't pass an error then Cogl is allowed to simply abort
1305  * automatically. */
1306  g_error_free (error);
1307  cogl_object_unref (pot);
1308  *pot_texture = NULL;
1310  }
1311 
1312  cogl_push_framebuffer (COGL_FRAMEBUFFER (offscreen));
1313  cogl_set_source_texture (texture);
1314  cogl_rectangle (-1, 1, 1, -1);
1315  cogl_pop_framebuffer ();
1316 
1317  cogl_object_unref (offscreen);
1318 }
1319 #endif
1320 
1321 /* NB: a reference for the texture is transferred to the caller which should
1322  * be unrefed */
1323 static CoglTexture *
1325  cairo_surface_t *abstract_surface)
1326 {
1328  cairo_image_surface_t *acquired_image = NULL;
1329  void *image_extra;
1330  CoglPixelFormat format;
1331  cairo_image_surface_t *image_clone = NULL;
1332  CoglTexture2D *texture;
1333  GError *error = NULL;
1334  cairo_surface_t *clone;
1335 
1336  if (abstract_surface->device == reference_surface->base.device) {
1337  cairo_cogl_surface_t *surface = (cairo_cogl_surface_t *)abstract_surface;
1339  return surface->texture ? cogl_object_ref (surface->texture) : NULL;
1340  }
1341 
1342  if (abstract_surface->type == CAIRO_SURFACE_TYPE_COGL) {
1343  if (_cairo_surface_is_subsurface (abstract_surface)) {
1345 
1347  _cairo_surface_subsurface_get_target (abstract_surface);
1348  if (surface->base.device == reference_surface->base.device)
1349  return surface->texture ? cogl_object_ref (surface->texture) : NULL;
1350  }
1351  }
1352 
1353  clone = _cairo_surface_has_snapshot (abstract_surface, &_cairo_cogl_surface_backend);
1354  if (clone) {
1356  return surface->texture ? cogl_object_ref (surface->texture) : NULL;
1357  }
1358 
1359  g_warning ("Uploading image surface to texture");
1360 
1361  if (_cairo_surface_is_image (abstract_surface)) {
1362  image = (cairo_image_surface_t *)abstract_surface;
1363  } else {
1365  &acquired_image, &image_extra);
1366  if (unlikely (status)) {
1367  g_warning ("acquire_source_image failed: %s [%d]\n",
1369  return NULL;
1370  }
1371  image = acquired_image;
1372  }
1373 
1375  if (!format)
1376  {
1377  image_clone = _cairo_image_surface_coerce (image);
1378  if (unlikely (image_clone->base.status)) {
1379  g_warning ("image_surface_coerce failed");
1380  texture = NULL;
1381  goto BAIL;
1382  }
1383 
1385  assert (format);
1386  }
1387 
1388  texture = cogl_texture_2d_new_from_data (to_device(reference_surface->base.device)->cogl_context,
1389  image->width,
1390  image->height,
1391  format, /* incoming */
1392  format, /* desired */
1393  image->stride,
1394  image->data,
1395  &error);
1396  if (!texture) {
1397  g_warning ("Failed to allocate texture: %s", error->message);
1398  g_error_free (error);
1399  goto BAIL;
1400  }
1401 
1402  clone = _cairo_cogl_surface_create_full (to_device(reference_surface->base.device),
1403  reference_surface->ignore_alpha,
1404  NULL, COGL_TEXTURE (texture));
1405 
1406  _cairo_surface_attach_snapshot (abstract_surface, clone, NULL);
1407 
1408  /* Attaching the snapshot will take a reference on the clone surface... */
1409  cairo_surface_destroy (clone);
1410 
1411 BAIL:
1412  if (image_clone)
1413  cairo_surface_destroy (&image_clone->base);
1414  if (acquired_image)
1415  _cairo_surface_release_source_image (abstract_surface, acquired_image, image_extra);
1416 
1417  return COGL_TEXTURE (texture);
1418 }
1419 
1420 /* NB: a reference for the texture is transferred to the caller which should
1421  * be unrefed */
1422 static CoglTexture *
1424  cairo_cogl_surface_t *destination,
1426  const cairo_rectangle_int_t *sample,
1427  cairo_cogl_texture_attributes_t *attributes)
1428 {
1429  CoglTexture *texture = NULL;
1430 
1431  switch ((int)pattern->type)
1432  {
1435  texture = _cairo_cogl_acquire_surface_texture (destination, surface);
1436  if (!texture)
1437  return NULL;
1438 
1439  /* XXX: determine if it would have no effect to change the
1440  * extend mode to EXTEND_PAD instead since we can simply map
1441  * EXTEND_PAD to CLAMP_TO_EDGE without needing fragment shader
1442  * tricks or extra border texels. */
1443 #if 0
1444  /* TODO: We still need to consider HW such as SGX which doesn't have
1445  * full support for NPOT textures. */
1446  if (pattern->extend == CAIRO_EXTEND_REPEAT || pattern->extend == CAIRO_EXTEND_REFLECT) {
1447  _cairo_cogl_get_pot_texture ();
1448  }
1449 #endif
1450 
1451  cairo_matrix_init_identity (&attributes->matrix);
1452 
1453  /* Convert from un-normalized source coordinates in backend
1454  * coordinates to normalized texture coordinates */
1455  cairo_matrix_scale (&attributes->matrix,
1456  1.0f / cogl_texture_get_width (texture),
1457  1.0f / cogl_texture_get_height (texture));
1458 
1459  /* XXX: need to multiply in the pattern->matrix */
1460 
1461  attributes->extend = pattern->extend;
1462  attributes->filter = CAIRO_FILTER_BILINEAR;
1463  attributes->has_component_alpha = pattern->has_component_alpha;
1464 
1465  attributes->s_wrap = get_cogl_wrap_mode_for_extend (pattern->extend);
1466  attributes->t_wrap = attributes->s_wrap;
1467 
1468  return texture;
1469  }
1471  case CAIRO_PATTERN_TYPE_MESH: {
1473  cairo_matrix_t texture_matrix;
1474 
1476  extents->width, extents->height);
1478  extents->x, extents->y,
1480  pattern, NULL)) {
1482  return NULL;
1483  }
1484 
1485  texture = _cairo_cogl_acquire_surface_texture (destination, surface);
1486  if (!texture)
1487  goto BAIL;
1488 
1489  cairo_matrix_init_identity (&texture_matrix);
1490 
1491  /* Convert from un-normalized source coordinates in backend
1492  * coordinates to normalized texture coordinates */
1493  cairo_matrix_scale (&texture_matrix,
1494  1.0f / cogl_texture_get_width (texture),
1495  1.0f / cogl_texture_get_height (texture));
1496 
1497  cairo_matrix_translate (&texture_matrix, -extents->x, -extents->y);
1498 
1499  attributes->matrix = texture_matrix;
1500  attributes->extend = pattern->extend;
1501  attributes->filter = CAIRO_FILTER_NEAREST;
1502  attributes->has_component_alpha = pattern->has_component_alpha;
1503 
1504  /* any pattern extend modes have already been dealt with... */
1505  attributes->s_wrap = COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE;
1506  attributes->t_wrap = attributes->s_wrap;
1507 
1508 BAIL:
1510 
1511  return texture;
1512  }
1516  cairo_cogl_linear_texture_entry_t *linear_texture;
1518  float a, b;
1519  float dist;
1520  float scale;
1521  float angle;
1522 
1524  pattern->extend,
1525  linear_pattern->base.n_stops,
1526  linear_pattern->base.stops,
1527  &gradient);
1528  if (unlikely (status))
1529  return NULL;
1530 
1532 
1533  attributes->extend = pattern->extend;
1534  attributes->filter = CAIRO_FILTER_BILINEAR;
1535  attributes->has_component_alpha = pattern->has_component_alpha;
1536  attributes->s_wrap = get_cogl_wrap_mode_for_extend (pattern->extend);
1537  attributes->t_wrap = COGL_PIPELINE_WRAP_MODE_REPEAT;
1538 
1539  cairo_matrix_init_identity (&attributes->matrix);
1540 
1541  a = linear_pattern->pd2.x - linear_pattern->pd1.x;
1542  b = linear_pattern->pd2.y - linear_pattern->pd1.y;
1543  dist = sqrtf (a*a + b*b);
1544  scale = 1.0f / dist;
1545  angle = - atan2f (b, a);
1546 
1547  cairo_matrix_rotate (&attributes->matrix, angle);
1548  cairo_matrix_scale (&attributes->matrix, scale, scale);
1549 
1550  cairo_matrix_translate (&attributes->matrix,
1551  -linear_pattern->pd1.x,
1552  -linear_pattern->pd1.y);
1553 
1554  /* XXX: this caught me out: cairo doesn't follow the standard
1555  * maths convention for multiplying two matrices A x B - cairo
1556  * does B x A so the final matrix is as if A's transforms were
1557  * applied first.
1558  */
1559  cairo_matrix_multiply (&attributes->matrix,
1560  &pattern->matrix,
1561  &attributes->matrix);
1562 
1563  return cogl_object_ref (linear_texture->texture);
1564  }
1565  default:
1566  g_warning ("Un-supported source type");
1567  return NULL;
1568  }
1569 }
1570 
1571 static void
1572 set_layer_texture_with_attributes (CoglPipeline *pipeline,
1573  int layer_index,
1574  CoglTexture *texture,
1575  cairo_cogl_texture_attributes_t *attributes)
1576 {
1577  cogl_pipeline_set_layer_texture (pipeline, layer_index, texture);
1578 
1579  if (!_cairo_matrix_is_identity (&attributes->matrix)) {
1580  cairo_matrix_t *m = &attributes->matrix;
1581  float texture_matrixfv[16] = {
1582  m->xx, m->yx, 0, 0,
1583  m->xy, m->yy, 0, 0,
1584  0, 0, 1, 0,
1585  m->x0, m->y0, 0, 1
1586  };
1587  CoglMatrix texture_matrix;
1588  cogl_matrix_init_from_array (&texture_matrix, texture_matrixfv);
1589  cogl_pipeline_set_layer_matrix (pipeline, layer_index, &texture_matrix);
1590  }
1591 
1592  if (attributes->s_wrap != attributes->t_wrap) {
1593  cogl_pipeline_set_layer_wrap_mode_s (pipeline, layer_index, attributes->s_wrap);
1594  cogl_pipeline_set_layer_wrap_mode_t (pipeline, layer_index, attributes->t_wrap);
1595  } else
1596  cogl_pipeline_set_layer_wrap_mode (pipeline, layer_index, attributes->s_wrap);
1597 }
1598 
1599 static CoglPipeline *
1601  const cairo_pattern_t *source,
1603  cairo_cogl_surface_t *destination,
1605 {
1606  cairo_cogl_template_type template_type;
1607  CoglPipeline *pipeline;
1608 
1609  switch ((int)source->type)
1610  {
1612  template_type = mask ?
1614  break;
1619  template_type = mask ?
1621  break;
1622  default:
1623  g_warning ("Un-supported source type");
1624  return NULL;
1625  }
1626 
1627  pipeline = cogl_pipeline_copy (to_device(destination->base.device)->template_pipelines[op][template_type]);
1628 
1631  cogl_pipeline_set_color4f (pipeline,
1632  solid_pattern->color.red * solid_pattern->color.alpha,
1633  solid_pattern->color.green * solid_pattern->color.alpha,
1634  solid_pattern->color.blue * solid_pattern->color.alpha,
1635  solid_pattern->color.alpha);
1636  } else {
1638  CoglTexture *texture =
1640  &extents->bounded,
1641  &extents->source_sample_area,
1642  &attributes);
1643  if (!texture)
1644  goto BAIL;
1645  set_layer_texture_with_attributes (pipeline, 0, texture, &attributes);
1646  cogl_object_unref (texture);
1647  }
1648 
1649  if (mask) {
1650  if (mask->type == CAIRO_PATTERN_TYPE_SOLID) {
1651  cairo_solid_pattern_t *solid_pattern = (cairo_solid_pattern_t *)mask;
1652  CoglColor color;
1653  cogl_color_init_from_4f (&color,
1654  solid_pattern->color.red * solid_pattern->color.alpha,
1655  solid_pattern->color.green * solid_pattern->color.alpha,
1656  solid_pattern->color.blue * solid_pattern->color.alpha,
1657  solid_pattern->color.alpha);
1658  cogl_pipeline_set_layer_combine_constant (pipeline, 1, &color);
1659  } else {
1661  CoglTexture *texture =
1663  &extents->bounded,
1664  &extents->mask_sample_area,
1665  &attributes);
1666  if (!texture)
1667  goto BAIL;
1668  set_layer_texture_with_attributes (pipeline, 1, texture, &attributes);
1669  cogl_object_unref (texture);
1670  }
1671  }
1672 
1673  return pipeline;
1674 
1675 BAIL:
1676  cogl_object_unref (pipeline);
1677  return NULL;
1678 }
1679 
1680 #if 0
1681 CoglPrimitive *
1682 _cairo_cogl_rectangle_new_p2t2t2 (float x,
1683  float y,
1684  float width,
1685  float height)
1686 {
1687  CoglVertexP2 vertices[] = {
1688  {x, y}, {x, y + height}, {x + width, y + height},
1689  {x, y}, {x + width, y + height}, {x + width, y}
1690  };
1691  CoglAttributeBuffer *buffer = cogl_attribute_buffer_new (sizeof (vertices));
1692  CoglAttribute *pos = cogl_attribute_new (buffer,
1693  "cogl_position_in",
1694  sizeof (CoglVertexP2),
1695  0,
1696  2,
1697  COGL_ATTRIBUTE_TYPE_FLOAT);
1698  CoglAttribute *tex_coords0 = cogl_attribute_new (buffer,
1699  "cogl_tex_coord0_in",
1700  sizeof (CoglVertexP2),
1701  0,
1702  2,
1703  COGL_ATTRIBUTE_TYPE_FLOAT);
1704  CoglAttribute *tex_coords0 = cogl_attribute_new (buffer,
1705  "cogl_tex_coord0_in",
1706  sizeof (CoglVertexP2),
1707  0,
1708  2,
1709  COGL_ATTRIBUTE_TYPE_FLOAT);
1710  CoglPrimitive *prim;
1711 
1712  cogl_buffer_set_data (COGL_BUFFER (buffer), 0, vertices, sizeof (vertices));
1713 
1714  /* The attributes will now keep the buffer alive... */
1715  cogl_object_unref (buffer);
1716 
1717  prim = cogl_primitive_new (COGL_VERTICES_MODE_TRIANGLES,
1718  6, pos, tex_coords, NULL);
1719 
1720  /* The primitive will now keep the attribute alive... */
1721  cogl_object_unref (pos);
1722 
1723  return prim;
1724 }
1725 #endif
1726 
1727 static void
1729  const cairo_clip_t *clip)
1730 {
1731  if (!_cairo_clip_equal (clip, surface->last_clip)) {
1733  _cairo_clip_destroy (surface->last_clip);
1734  surface->last_clip = _cairo_clip_copy (clip);
1735  }
1736 }
1737 
1738 static void
1741 {
1742  cairo_clip_t *clip = composite->clip;
1743 
1745  clip = NULL;
1746 
1747  if (clip == NULL) {
1749  surface->last_clip))
1750  return;
1751  }
1752 
1754 }
1755 
1756 static cairo_bool_t
1758 {
1759  switch ((int)op) {
1760  case CAIRO_OPERATOR_SOURCE:
1761  case CAIRO_OPERATOR_OVER:
1762  case CAIRO_OPERATOR_IN:
1765  case CAIRO_OPERATOR_ADD:
1766  return TRUE;
1767 
1768  default:
1769  return FALSE;
1770  }
1771 }
1772 
1773 static cairo_int_status_t
1774 _cairo_cogl_surface_mask (void *abstract_surface,
1776  const cairo_pattern_t *source,
1777  const cairo_pattern_t *mask,
1778  const cairo_clip_t *clip)
1779 {
1780  cairo_cogl_surface_t *surface = abstract_surface;
1783  CoglPipeline *pipeline;
1785 
1786  /* XXX: Use this to smoke test the acquire_source/dest_image fallback
1787  * paths... */
1788  //return CAIRO_INT_STATUS_UNSUPPORTED;
1789 
1790  if (!is_operator_supported (op))
1792 
1794  &surface->base,
1795  op, source, mask, clip);
1796  if (unlikely (status))
1797  return status;
1798 
1800  op, surface, &extents);
1801  if (!pipeline){
1803  goto BAIL;
1804  }
1805 
1807 
1810  extents.bounded.x,
1811  extents.bounded.y,
1812  extents.bounded.width,
1813  extents.bounded.height,
1814  2,
1815  &identity);
1816 
1817  /* The journal will take a reference on the pipeline and clip_path... */
1818  cogl_object_unref (pipeline);
1819 
1820 BAIL:
1821  return status;
1822 }
1823 
1824 static int
1826 {
1827  switch ((int)source->type)
1828  {
1830  return 0;
1835  return 1;
1836  default:
1837  g_warning ("Unsupported source type");
1838  return 0;
1839  }
1840 }
1841 
1842 static cairo_bool_t
1843 _cairo_cogl_path_fill_meta_equal (const void *key_a, const void *key_b)
1844 {
1845  const cairo_cogl_path_fill_meta_t *meta0 = key_a;
1846  const cairo_cogl_path_fill_meta_t *meta1 = key_b;
1847 
1848  return _cairo_path_fixed_equal (meta0->user_path, meta1->user_path);
1849 }
1850 
1851 static cairo_bool_t
1853  const cairo_stroke_style_t *b)
1854 {
1855  if (a->line_width == b->line_width &&
1856  a->line_cap == b->line_cap &&
1857  a->line_join == b->line_join &&
1858  a->miter_limit == b->miter_limit &&
1859  a->num_dashes == b->num_dashes &&
1860  a->dash_offset == b->dash_offset)
1861  {
1862  unsigned int i;
1863  for (i = 0; i < a->num_dashes; i++) {
1864  if (a->dash[i] != b->dash[i])
1865  return FALSE;
1866  }
1867  }
1868  return TRUE;
1869 }
1870 
1871 static cairo_bool_t
1872 _cairo_cogl_path_stroke_meta_equal (const void *key_a, const void *key_b)
1873 {
1874  const cairo_cogl_path_stroke_meta_t *meta0 = key_a;
1875  const cairo_cogl_path_stroke_meta_t *meta1 = key_b;
1876 
1877  return _cairo_cogl_stroke_style_equal (&meta0->style, &meta1->style) &&
1878  _cairo_path_fixed_equal (meta0->user_path, meta1->user_path);
1879 }
1880 
1883 {
1885 
1887 
1888  return meta;
1889 }
1890 
1891 static void
1893 {
1895 
1897  return;
1898 
1900  free (meta->user_path);
1901 
1903 
1904  if (meta->prim)
1905  cogl_object_unref (meta->prim);
1906 
1907  free (meta);
1908 }
1909 
1912  unsigned long hash,
1914  const cairo_stroke_style_t *style,
1915  double tolerance)
1916 {
1919 
1920  lookup.cache_entry.hash = hash;
1921  lookup.user_path = user_path;
1922  lookup.style = *style;
1923  lookup.tolerance = tolerance;
1924 
1925  ret = _cairo_cache_lookup (&ctx->path_stroke_staging_cache, &lookup.cache_entry);
1926  if (!ret)
1927  ret = _cairo_cache_lookup (&ctx->path_stroke_prim_cache, &lookup.cache_entry);
1928  return ret;
1929 }
1930 
1931 static void
1934  size_t size)
1935 {
1936  /* now that we know the meta structure is associated with a primitive
1937  * we promote it from the staging cache into the primitive cache.
1938  */
1939 
1940  /* XXX: _cairo_cache borks if you try and remove an entry that's already
1941  * been evicted so we explicitly look it up first... */
1945  }
1946 
1947  meta->cache_entry.size = size;
1951 }
1952 
1953 static unsigned int
1955  const cairo_stroke_style_t *style)
1956 {
1957  unsigned int i;
1958  hash = _cairo_hash_bytes (hash, &style->line_width, sizeof (style->line_width));
1959  hash = _cairo_hash_bytes (hash, &style->line_cap, sizeof (style->line_cap));
1960  hash = _cairo_hash_bytes (hash, &style->line_join, sizeof (style->line_join));
1961  hash = _cairo_hash_bytes (hash, &style->miter_limit, sizeof (style->miter_limit));
1962  hash = _cairo_hash_bytes (hash, &style->num_dashes, sizeof (style->num_dashes));
1963  hash = _cairo_hash_bytes (hash, &style->dash_offset, sizeof (style->dash_offset));
1964  for (i = 0; i < style->num_dashes; i++)
1965  hash = _cairo_hash_bytes (hash, &style->dash[i], sizeof (double));
1966  return hash;
1967 }
1968 
1971  const cairo_stroke_style_t *style,
1972  double tolerance)
1973 {
1974  unsigned long hash;
1976  cairo_path_fixed_t *meta_path = NULL;
1978 
1979  if (!surface->user_path)
1980  return NULL;
1981 
1982  hash = _cairo_path_fixed_hash (surface->user_path);
1984  hash = _cairo_hash_bytes (hash, &tolerance, sizeof (tolerance));
1985 
1987  surface->user_path, style, tolerance);
1988  if (meta)
1989  return meta;
1990 
1991  meta = calloc (1, sizeof (cairo_cogl_path_stroke_meta_t));
1992  if (!meta)
1993  goto BAIL;
1995  meta->cache_entry.hash = hash;
1996  meta->counter = 0;
1997  meta_path = _cairo_malloc (sizeof (cairo_path_fixed_t));
1998  if (!meta_path)
1999  goto BAIL;
2000  /* FIXME: we should add a ref-counted wrapper for our user_paths
2001  * so we don't have to keep copying them here! */
2002  status = _cairo_path_fixed_init_copy (meta_path, surface->user_path);
2003  if (unlikely (status))
2004  goto BAIL;
2005  meta->user_path = meta_path;
2006  meta->ctm_inverse = *surface->ctm_inverse;
2007 
2009  if (unlikely (status)) {
2010  _cairo_path_fixed_fini (meta_path);
2011  goto BAIL;
2012  }
2013  meta->tolerance = tolerance;
2014 
2015  return meta;
2016 
2017 BAIL:
2018  free (meta_path);
2019  free (meta);
2020  return NULL;
2021 }
2022 
2023 static cairo_int_status_t
2025  const cairo_path_fixed_t *path,
2026  const cairo_stroke_style_t *style,
2027  const cairo_matrix_t *ctm,
2028  const cairo_matrix_t *ctm_inverse,
2029  double tolerance,
2030  int n_layers,
2031  cairo_bool_t one_shot,
2032  CoglPrimitive **primitive,
2033  size_t *size)
2034 {
2035  cairo_traps_t traps;
2037 
2038  _cairo_traps_init (&traps);
2039 
2041  ctm, ctm_inverse,
2042  tolerance,
2043  &traps);
2044  if (unlikely (status))
2045  goto BAIL;
2046 
2047  if (traps.num_traps == 0) {
2049  goto BAIL;
2050  }
2051 
2052  *size = traps.num_traps * sizeof (CoglVertexP2) * 6;
2053 
2054  //g_print ("new stroke prim\n");
2055  *primitive = _cairo_cogl_traps_to_composite_prim (surface, &traps, n_layers, one_shot);
2056  if (!*primitive) {
2058  goto BAIL;
2059  }
2060 
2061 BAIL:
2062  _cairo_traps_fini (&traps);
2063  return status;
2064 }
2065 
2066 static cairo_int_status_t
2067 _cairo_cogl_surface_stroke (void *abstract_surface,
2069  const cairo_pattern_t *source,
2070  const cairo_path_fixed_t *path,
2071  const cairo_stroke_style_t *style,
2072  const cairo_matrix_t *ctm,
2073  const cairo_matrix_t *ctm_inverse,
2074  double tolerance,
2076  const cairo_clip_t *clip)
2077 {
2078  cairo_cogl_surface_t *surface = (cairo_cogl_surface_t *)abstract_surface;
2080  CoglPipeline *pipeline;
2082 #ifdef ENABLE_PATH_CACHE
2084  cairo_matrix_t transform_matrix;
2085 #endif
2087  gboolean one_shot = TRUE;
2088  CoglPrimitive *prim = NULL;
2089  cairo_bool_t new_prim = FALSE;
2090 
2091  if (! is_operator_supported (op))
2093 
2094  /* FIXME - support unbounded operators */
2096  /* Currently IN this is the only unbounded operator we aim to support
2097  * in cairo-cogl. */
2099  g_warning ("FIXME: handle stroking with unbounded operators!");
2101  }
2102 
2104  &surface->base,
2105  op, source, path,
2106  style,
2107  ctm,
2108  clip);
2109  if (unlikely (status))
2110  return status;
2111 
2112 #ifdef ENABLE_PATH_CACHE
2113  /* FIXME: we are currently leaking the meta state if we don't reach
2114  * the cache_insert at the end. */
2116  if (meta) {
2117  prim = meta->prim;
2118  if (prim) {
2119  cairo_matrix_multiply (&transform_matrix, &meta->ctm_inverse, surface->ctm);
2120  transform = &transform_matrix;
2121  } else if (meta->counter++ > 10)
2122  one_shot = FALSE;
2123  }
2124 #endif
2125 
2126  if (!prim) {
2127  int n_layers = _cairo_cogl_source_n_layers (source);
2128  size_t prim_size = 0;
2130  ctm, ctm_inverse, tolerance,
2131  n_layers, one_shot,
2132  &prim, &prim_size);
2133  if (unlikely (status))
2134  return status;
2135  new_prim = TRUE;
2136 #if defined (ENABLE_PATH_CACHE)
2137  if (meta) {
2138  meta->prim = cogl_object_ref (prim);
2140  }
2141 #endif
2142  }
2143 
2145  op, surface, &extents);
2146  if (!pipeline)
2148 
2150 
2152 
2153  /* The journal will take a reference on the pipeline and primitive... */
2154  cogl_object_unref (pipeline);
2155  if (new_prim)
2156  cogl_object_unref (prim);
2157 
2158  return CAIRO_INT_STATUS_SUCCESS;
2159 }
2160 
2163 {
2165 
2167 
2168  return meta;
2169 }
2170 
2171 static void
2173 {
2175 
2177  return;
2178 
2180  free (meta->user_path);
2181 
2182  if (meta->prim)
2183  cogl_object_unref (meta->prim);
2184 
2185  free (meta);
2186 }
2187 
2190  unsigned long hash,
2192 {
2195 
2196  lookup.cache_entry.hash = hash;
2197  lookup.user_path = user_path;
2198 
2199  ret = _cairo_cache_lookup (&ctx->path_fill_staging_cache, &lookup.cache_entry);
2200  if (!ret)
2201  ret = _cairo_cache_lookup (&ctx->path_fill_prim_cache, &lookup.cache_entry);
2202  return ret;
2203 }
2204 
2205 static void
2208  size_t size)
2209 {
2210  /* now that we know the meta structure is associated with a primitive
2211  * we promote it from the staging cache into the primitive cache.
2212  */
2213 
2214  /* XXX: _cairo_cache borks if you try and remove an entry that's already
2215  * been evicted so we explicitly look it up first... */
2219  }
2220 
2221  meta->cache_entry.size = size;
2225 }
2226 
2229 {
2230  unsigned long hash;
2232  cairo_path_fixed_t *meta_path = NULL;
2234 
2235  if (!surface->user_path)
2236  return NULL;
2237 
2238  hash = _cairo_path_fixed_hash (surface->user_path);
2239 
2241  hash, surface->user_path);
2242  if (meta)
2243  return meta;
2244 
2245  meta = calloc (1, sizeof (cairo_cogl_path_fill_meta_t));
2246  if (!meta)
2247  goto BAIL;
2248  meta->cache_entry.hash = hash;
2249  meta->counter = 0;
2251  meta_path = _cairo_malloc (sizeof (cairo_path_fixed_t));
2252  if (!meta_path)
2253  goto BAIL;
2254  /* FIXME: we should add a ref-counted wrapper for our user_paths
2255  * so we don't have to keep copying them here! */
2256  status = _cairo_path_fixed_init_copy (meta_path, surface->user_path);
2257  if (unlikely (status))
2258  goto BAIL;
2259  meta->user_path = meta_path;
2260  meta->ctm_inverse = *surface->ctm_inverse;
2261 
2262  /* To start with - until we associate a CoglPrimitive with the meta
2263  * structure - we keep the meta in a staging structure until we
2264  * see whether it actually gets re-used. */
2265  meta->cache_entry.size = 1;
2269 
2270  return meta;
2271 
2272 BAIL:
2273  free (meta_path);
2274  free (meta);
2275  return NULL;
2276 }
2277 
2278 static cairo_int_status_t
2279 _cairo_cogl_surface_fill (void *abstract_surface,
2281  const cairo_pattern_t *source,
2282  const cairo_path_fixed_t *path,
2283  cairo_fill_rule_t fill_rule,
2284  double tolerance,
2286  const cairo_clip_t *clip)
2287 {
2288  cairo_cogl_surface_t *surface = abstract_surface;
2291 #ifdef ENABLE_PATH_CACHE
2293  cairo_matrix_t transform_matrix;
2294 #endif
2296  cairo_bool_t one_shot = TRUE;
2297  CoglPrimitive *prim = NULL;
2298  cairo_bool_t new_prim = FALSE;
2299  CoglPipeline *pipeline;
2300 
2301  if (! is_operator_supported (op))
2303 
2304  /* FIXME - support unbounded operators */
2306  /* Currently IN this is the only unbounded operator we aim to support
2307  * in cairo-cogl. */
2309  g_warning ("FIXME: handle filling with unbounded operators!");
2311  }
2312 
2314  &surface->base,
2315  op, source, path,
2316  clip);
2317  if (unlikely (status))
2318  return status;
2319 
2320 #ifndef FILL_WITH_COGL_PATH
2321 #ifdef ENABLE_PATH_CACHE
2323  if (meta) {
2324  prim = meta->prim;
2325  if (prim) {
2326  cairo_matrix_multiply (&transform_matrix, &meta->ctm_inverse, surface->ctm);
2327  transform = &transform_matrix;
2328  } else if (meta->counter++ > 10)
2329  one_shot = FALSE;
2330  }
2331 #endif /* ENABLE_PATH_CACHE */
2332 
2333  if (!prim) {
2334  int n_layers = _cairo_cogl_source_n_layers (source);
2335  size_t prim_size;
2337  one_shot, n_layers, &prim, &prim_size);
2338  if (unlikely (status))
2339  return status;
2340  new_prim = TRUE;
2341 #ifdef ENABLE_PATH_CACHE
2342  if (meta) {
2343  meta->prim = cogl_object_ref (prim);
2345  }
2346 #endif /* ENABLE_PATH_CACHE */
2347  }
2348 
2349 #endif /* !FILL_WITH_COGL_PATH */
2350 
2352  op, surface, &extents);
2353  if (!pipeline)
2355 
2357 
2358 #ifndef FILL_WITH_COGL_PATH
2360  /* The journal will take a reference on the prim */
2361  if (new_prim)
2362  cogl_object_unref (prim);
2363 #else
2364  CoglPath * cogl_path = _cairo_cogl_util_path_from_cairo (path, fill_rule, tolerance);
2365  _cairo_cogl_journal_log_path (surface, pipeline, cogl_path);
2366  cogl_object_unref (cogl_path);
2367 #endif
2368 
2369  /* The journal will take a reference on the pipeline... */
2370  cogl_object_unref (pipeline);
2371 
2372  return CAIRO_INT_STATUS_SUCCESS;
2373 }
2374 
2376 _cairo_cogl_surface_fill_rectangle (void *abstract_surface,
2378  const cairo_pattern_t *source,
2379  double x,
2380  double y,
2381  double width,
2382  double height,
2383  cairo_matrix_t *ctm,
2384  const cairo_clip_t *clip)
2385 {
2386  cairo_cogl_surface_t *surface = abstract_surface;
2387  CoglPipeline *pipeline;
2388 
2389  if (! is_operator_supported (op))
2391 
2392  /* FIXME - support unbounded operators */
2394  /* Currently IN this is the only unbounded operator we aim to support
2395  * in cairo-cogl. */
2397  g_warning ("FIXME: handle filling with unbounded operators!");
2399  }
2400 
2401  /* FIXME */
2402 #if 0
2403  status = _cairo_composite_rectangles_init_for_fill_rectangle (&extents,
2404  &surface->base,
2405  op, source, path,
2406  clip);
2407  if (unlikely (status))
2408  return status;
2409 #endif
2410 
2412  double x1 = x;
2413  double y1 = y;
2414  double x2 = x1 + width;
2415  double y2 = y1 + height;
2416 
2418  op, surface, NULL);
2419  if (!pipeline)
2421 
2423 
2425  pipeline,
2426  x1, y1, x2, y2,
2427  0,
2428  ctm);
2429  return CAIRO_INT_STATUS_SUCCESS;
2430  } else
2432 
2433  /* TODO:
2434  * We need to acquire the textures here, look at the corresponding
2435  * attributes and see if this can be trivially handled by logging
2436  * a textured rectangle only needing simple scaling or translation
2437  * of texture coordinates.
2438  *
2439  * At this point we should also aim to remap the default
2440  * EXTEND_NONE mode to EXTEND_PAD which is more efficient if we
2441  * know it makes no difference either way since we can map that to
2442  * CLAMP_TO_EDGE.
2443  */
2444 }
2445 
2446 static cairo_int_status_t
2449  const cairo_pattern_t *source,
2451  int num_glyphs,
2452  cairo_scaled_font_t *scaled_font,
2453  const cairo_clip_t *clip)
2454 {
2456 }
2457 
2461 #ifdef NEED_COGL_CONTEXT
2463 #else
2465 #endif
2466 
2468  NULL, /* create similar image */
2469  NULL, /* map to image */
2470  NULL, /* unmap image */
2471 
2475  NULL, /* snapshot */
2476 
2477  NULL, /* copy_page */
2478  NULL, /* show_page */
2479 
2481  NULL, /* get_font_options */
2482 
2483  _cairo_cogl_surface_flush, /* flush */
2484  NULL, /* mark_dirty_rectangle */
2485 
2490  NULL, /* fill_stroke*/
2492 };
2493 
2494 static cairo_surface_t *
2496  cairo_bool_t ignore_alpha,
2497  CoglFramebuffer *framebuffer,
2498  CoglTexture *texture)
2499 {
2502 
2503  status = cairo_device_acquire (&dev->base);
2504  if (unlikely (status))
2506 
2508  if (unlikely (surface == NULL))
2510 
2511  surface->ignore_alpha = ignore_alpha;
2512 
2513  surface->framebuffer = framebuffer;
2514  if (framebuffer) {
2515  surface->width = cogl_framebuffer_get_width (framebuffer);
2516  surface->height = cogl_framebuffer_get_height (framebuffer);
2517  surface->cogl_format = cogl_framebuffer_get_color_format (framebuffer);
2518  cogl_object_ref (framebuffer);
2519  }
2520 
2521  /* FIXME: If texture == NULL and we are given an offscreen framebuffer
2522  * then we want a way to poke inside the framebuffer to get a texture */
2523  surface->texture = texture;
2524  if (texture) {
2525  if (!framebuffer) {
2526  surface->width = cogl_texture_get_width (texture);
2527  surface->height = cogl_texture_get_height (texture);
2528  surface->cogl_format = cogl_texture_get_format (texture);
2529  }
2530  cogl_object_ref (texture);
2531  }
2532 
2533  assert(surface->width && surface->height);
2534 
2535  surface->journal = NULL;
2536 
2537  surface->buffer_stack = NULL;
2538  surface->buffer_stack_size = 4096;
2539 
2540  surface->last_clip = NULL;
2541 
2542  surface->n_clip_updates_per_frame = 0;
2543 
2544  _cairo_surface_init (&surface->base,
2546  &dev->base,
2548  FALSE); /* is_vector */
2549 
2550  return &surface->base;
2551 }
2552 
2555  CoglFramebuffer *framebuffer)
2556 {
2557  cairo_cogl_device_t *dev = (cairo_cogl_device_t *)abstract_device;
2558 
2559  if (abstract_device == NULL)
2561 
2562  if (abstract_device->status)
2563  return _cairo_surface_create_in_error (abstract_device->status);
2564 
2565  if (abstract_device->backend->type != CAIRO_DEVICE_TYPE_COGL)
2567 
2568  return _cairo_cogl_surface_create_full (dev, FALSE, framebuffer, NULL);
2569 }
2571 
2572 CoglFramebuffer *
2574 {
2576 
2577  if (abstract_surface->backend != &_cairo_cogl_surface_backend) {
2579  return NULL;
2580  }
2581 
2582  surface = (cairo_cogl_surface_t *) abstract_surface;
2583 
2584  return surface->framebuffer;
2585 }
2587 
2588 CoglTexture *
2590 {
2592 
2593  if (abstract_surface->backend != &_cairo_cogl_surface_backend) {
2595  return NULL;
2596  }
2597 
2598  surface = (cairo_cogl_surface_t *) abstract_surface;
2599 
2600  return surface->texture;
2601 }
2603 
2604 static cairo_status_t
2606 {
2608 
2609  status = cairo_device_acquire (device);
2610  if (unlikely (status))
2611  return status;
2612 
2613  /* XXX: we don't need to flush Cogl here, we just need to flush
2614  * any batching we do of compositing primitives. */
2615 
2616  cairo_device_release (device);
2617 
2618  return CAIRO_STATUS_SUCCESS;
2619 }
2620 
2621 static void
2623 {
2625 
2626  status = cairo_device_acquire (device);
2627  if (unlikely (status))
2628  return;
2629 
2630  /* XXX: Drop references to external resources */
2631 
2632  cairo_device_release (device);
2633 }
2634 
2635 static void
2637 {
2638  cairo_cogl_device_t *dev = device;
2639 
2640  /* FIXME: Free stuff! */
2641 
2642  g_free (dev);
2643 }
2644 
2647 
2648  NULL, /* lock */
2649  NULL, /* unlock */
2650 
2654 };
2655 
2656 static cairo_bool_t
2657 set_blend (CoglPipeline *pipeline, const char *blend_string)
2658 {
2659  GError *error = NULL;
2660  if (!cogl_pipeline_set_blend (pipeline, blend_string, &error)) {
2661  g_warning ("Unsupported blend string with current gpu/driver: %s", blend_string);
2662  g_error_free (error);
2663  return FALSE;
2664  }
2665  return TRUE;
2666 }
2667 
2668 static cairo_bool_t
2670 {
2672 
2673  switch ((int)op)
2674  {
2675  case CAIRO_OPERATOR_SOURCE:
2676  status = set_blend (pipeline, "RGBA = ADD (SRC_COLOR, 0)");
2677  break;
2678  case CAIRO_OPERATOR_OVER:
2679  status = set_blend (pipeline, "RGBA = ADD (SRC_COLOR, DST_COLOR * (1 - SRC_COLOR[A]))");
2680  break;
2681  case CAIRO_OPERATOR_IN:
2682  status = set_blend (pipeline, "RGBA = ADD (SRC_COLOR * DST_COLOR[A], 0)");
2683  break;
2685  status = set_blend (pipeline, "RGBA = ADD (SRC_COLOR * (1 - DST_COLOR[A]), DST_COLOR)");
2686  break;
2688  status = set_blend (pipeline, "RGBA = ADD (0, DST_COLOR * SRC_COLOR[A])");
2689  break;
2690  case CAIRO_OPERATOR_ADD:
2691  status = set_blend (pipeline, "RGBA = ADD (SRC_COLOR, DST_COLOR)");
2692  break;
2693  }
2694 
2695  return status;
2696 }
2697 
2698 static void
2700 {
2701  CoglPipeline *base = cogl_pipeline_new ();
2702  CoglPipeline *pipeline;
2703  CoglColor color;
2704 
2706  cogl_object_unref (base);
2707  return;
2708  }
2709 
2711 
2712  pipeline = cogl_pipeline_copy (base);
2713  cogl_pipeline_set_layer_texture (pipeline, 0, dev->dummy_texture);
2715 
2716  pipeline = cogl_pipeline_copy (base);
2717  cogl_pipeline_set_layer_combine (pipeline, 1,
2718  "RGBA = MODULATE (PREVIOUS, CONSTANT[A])",
2719  NULL);
2720  cogl_pipeline_set_layer_combine_constant (pipeline, 1, &color);
2721  cogl_pipeline_set_layer_texture (pipeline, 1, dev->dummy_texture);
2723 
2724  pipeline = cogl_pipeline_copy (base);
2725  cogl_pipeline_set_layer_combine (pipeline, 1,
2726  "RGBA = MODULATE (PREVIOUS, TEXTURE[A])",
2727  NULL);
2728  cogl_pipeline_set_layer_texture (pipeline, 1, dev->dummy_texture);
2730 }
2731 
2733 cairo_cogl_device_create (CoglContext *cogl_context)
2734 {
2735  cairo_cogl_device_t *dev = g_new0 (cairo_cogl_device_t, 1);
2737 
2739 
2740  dev->cogl_context = cogl_context;
2741 
2742  dev->dummy_texture = cogl_texture_new_with_size (1, 1,
2743  COGL_TEXTURE_NO_SLICING,
2744  COGL_PIXEL_FORMAT_ANY);
2745  if (!dev->dummy_texture)
2746  goto ERROR;
2747 
2755 
2758  NULL,
2761  if (unlikely (status))
2763 
2766  NULL,
2768  1000);
2769 
2772  NULL,
2774  1000);
2775 
2778  NULL,
2781 
2784  NULL,
2787 
2789  return &dev->base;
2790 
2791 ERROR:
2792  g_free (dev);
2794 }
2796 
2797 void
2799 {
2800  cairo_cogl_surface_t *surface = (cairo_cogl_surface_t *)abstract_surface;
2801  cairo_surface_flush (abstract_surface);
2802 
2803  //g_print ("n_clip_update_per_frame = %d\n", surface->n_clip_updates_per_frame);
2804  surface->n_clip_updates_per_frame = 0;
2805 }
__inline float __cdecl atan2f(float _Y, float _X)
Definition: CPAL.d:18913
__inline float __cdecl sqrtf(float _X)
Definition: CPAL.d:19039
static int interest(char *s)
Definition: afm2pl.c:553
int lookup(const char *)
#define primitive(s, c, o)
#define width(a)
Definition: aptex-macros.h:198
#define tolerance
Definition: aptex-macros.h:786
#define prim_size
Definition: aptex-macros.h:558
#define height(a)
Definition: aptex-macros.h:200
static char * dist
Definition: aptex-src.c:59
static two_halves prim[2100+1]
Definition: aptex.h:393
#define hash
Definition: aptex.h:388
char * p2
Definition: bmpfont.h:62
char * p1
Definition: bmpfont.h:62
#define CAIRO_INT_STATUS_SUCCESS
static cairo_bool_t _cairo_box_is_pixel_aligned(const cairo_box_t *box)
cairo_status_t _cairo_cache_insert(cairo_cache_t *cache, cairo_cache_entry_t *entry)
Definition: cairo-cache.c:261
void * _cairo_cache_lookup(cairo_cache_t *cache, cairo_cache_entry_t *key)
Definition: cairo-cache.c:197
cairo_status_t _cairo_cache_init(cairo_cache_t *cache, cairo_cache_keys_equal_func_t keys_equal, cairo_cache_predicate_func_t predicate, cairo_destroy_func_t entry_destroy, unsigned long max_size)
Definition: cairo-cache.c:89
void _cairo_cache_remove(cairo_cache_t *cache, cairo_cache_entry_t *entry)
Definition: cairo-cache.c:287
unsigned long _cairo_hash_bytes(unsigned long hash, const void *ptr, unsigned int length)
Definition: cairo-cache.c:329
static int pot(int v)
void _cairo_clip_destroy(cairo_clip_t *clip)
Definition: cairo-clip.c:128
cairo_clip_t * _cairo_clip_copy(const cairo_clip_t *clip)
Definition: cairo-clip.c:144
cairo_bool_t _cairo_clip_equal(const cairo_clip_t *clip_a, const cairo_clip_t *clip_b)
Definition: cairo-clip.c:352
cairo_t * _cairo_cogl_context_create(void *target)
cairo_int_status_t _cairo_cogl_get_linear_gradient(cairo_cogl_device_t *context, cairo_extend_t extend_mode, int n_stops, const cairo_gradient_stop_t *stops, cairo_cogl_linear_gradient_t **gradient_out)
#define CAIRO_COGL_LINEAR_GRADIENT_CACHE_SIZE
void _cairo_cogl_linear_gradient_destroy(cairo_cogl_linear_gradient_t *gradient)
cairo_bool_t _cairo_cogl_linear_gradient_equal(const void *key_a, const void *key_b)
cairo_cogl_linear_texture_entry_t * _cairo_cogl_linear_gradient_texture_for_extend(cairo_cogl_linear_gradient_t *gradient, cairo_extend_t extend_mode)
static int _cairo_cogl_util_next_p2(int a)
@ CAIRO_COGL_TEMPLATE_TYPE_SOLID
@ CAIRO_COGL_TEMPLATE_TYPE_MASK_TEXTURE
@ CAIRO_COGL_TEMPLATE_TYPE_TEXTURE
@ CAIRO_COGL_TEMPLATE_TYPE_MASK_SOLID
enum _cairo_cogl_template_type cairo_cogl_template_type
cairo_status_t _cairo_cogl_path_fixed_rectangle(cairo_path_fixed_t *path, cairo_fixed_t x, cairo_fixed_t y, cairo_fixed_t width, cairo_fixed_t height)
struct _cairo_cogl_texture_attributes cairo_cogl_texture_attributes_t
cairo_device_t * cairo_cogl_device_create(CoglContext *cogl_context)
struct _cairo_cogl_journal_rect_entry cairo_cogl_journal_rect_entry_t
struct _cairo_cogl_path_stroke_meta cairo_cogl_path_stroke_meta_t
cairo_surface_t * cairo_cogl_surface_create(cairo_device_t *abstract_device, CoglFramebuffer *framebuffer)
cairo_int_status_t _cairo_cogl_surface_fill_rectangle(void *abstract_surface, cairo_operator_t op, const cairo_pattern_t *source, double x, double y, double width, double height, cairo_matrix_t *ctm, const cairo_clip_t *clip)
enum _cairo_cogl_journal_entry_type cairo_cogl_journal_entry_type_t
void cairo_cogl_surface_end_frame(cairo_surface_t *abstract_surface)
struct _cairo_cogl_path_fill_meta cairo_cogl_path_fill_meta_t
struct _cairo_cogl_journal_prim_entry cairo_cogl_journal_prim_entry_t
struct _cairo_cogl_journal_clip_entry cairo_cogl_journal_clip_entry_t
CoglFramebuffer * cairo_cogl_surface_get_framebuffer(cairo_surface_t *abstract_surface)
_cairo_cogl_journal_entry_type
@ CAIRO_COGL_JOURNAL_ENTRY_TYPE_PRIMITIVE
@ CAIRO_COGL_JOURNAL_ENTRY_TYPE_RECTANGLE
@ CAIRO_COGL_JOURNAL_ENTRY_TYPE_PATH
@ CAIRO_COGL_JOURNAL_ENTRY_TYPE_CLIP
struct _cairo_cogl_journal_path_entry cairo_cogl_journal_path_entry_t
const cairo_surface_backend_t _cairo_cogl_surface_backend
CoglTexture * cairo_cogl_surface_get_texture(cairo_surface_t *abstract_surface)
struct _cairo_cogl_journal_entry cairo_cogl_journal_entry_t
static float _cairo_cogl_util_fixed_to_float(cairo_fixed_t f)
CoglPath * _cairo_cogl_util_path_from_cairo(const cairo_path_fixed_t *path, cairo_fill_rule_t fill_rule, float tolerance)
#define cairo_private
#define slim_hidden_def(name)
#define slim_hidden_proto(name)
cairo_int_status_t _cairo_composite_rectangles_init_for_fill(cairo_composite_rectangles_t *extents, cairo_surface_t *surface, cairo_operator_t op, const cairo_pattern_t *source, const cairo_path_fixed_t *path, const cairo_clip_t *clip)
cairo_int_status_t _cairo_composite_rectangles_init_for_mask(cairo_composite_rectangles_t *extents, cairo_surface_t *surface, cairo_operator_t op, const cairo_pattern_t *source, const cairo_pattern_t *mask, const cairo_clip_t *clip)
cairo_bool_t _cairo_composite_rectangles_can_reduce_clip(cairo_composite_rectangles_t *composite, cairo_clip_t *clip)
cairo_int_status_t _cairo_composite_rectangles_init_for_stroke(cairo_composite_rectangles_t *extents, cairo_surface_t *surface, cairo_operator_t op, const cairo_pattern_t *source, const cairo_path_fixed_t *path, const cairo_stroke_style_t *style, const cairo_matrix_t *ctm, const cairo_clip_t *clip)
cairo_t * _cairo_default_context_create(void *target)
void _cairo_device_init(cairo_device_t *device, const cairo_device_backend_t *backend)
Definition: cairo-device.c:173
cairo_device_t * _cairo_device_create_in_error(cairo_status_t status)
Definition: cairo-device.c:113
void cairo_device_release(cairo_device_t *device)
Definition: cairo-device.c:445
cairo_status_t cairo_device_acquire(cairo_device_t *device)
Definition: cairo-device.c:414
cairo_status_t _cairo_error(cairo_status_t status)
Definition: cairo-error.c:65
enum _cairo_int_status cairo_int_status_t
#define _cairo_error_throw(status)
@ CAIRO_INT_STATUS_NOTHING_TO_DO
@ CAIRO_INT_STATUS_UNSUPPORTED
@ CAIRO_INT_STATUS_NO_MEMORY
int32_t cairo_fixed_t
static cairo_bool_t _cairo_surface_is_image(const cairo_surface_t *surface)
cairo_image_surface_t * _cairo_image_surface_coerce(cairo_image_surface_t *surface)
cairo_surface_t * cairo_image_surface_create(cairo_format_t format, int width, int height)
#define _cairo_malloc(size)
void cairo_matrix_init_identity(cairo_matrix_t *matrix)
Definition: cairo-matrix.c:81
void cairo_matrix_translate(cairo_matrix_t *matrix, double tx, double ty)
Definition: cairo-matrix.c:197
void cairo_matrix_scale(cairo_matrix_t *matrix, double sx, double sy)
Definition: cairo-matrix.c:242
void cairo_matrix_rotate(cairo_matrix_t *matrix, double radians)
Definition: cairo-matrix.c:299
void cairo_matrix_multiply(cairo_matrix_t *result, const cairo_matrix_t *a, const cairo_matrix_t *b)
Definition: cairo-matrix.c:331
cairo_bool_t _cairo_operator_bounded_by_mask(cairo_operator_t op)
Definition: cairo-misc.c:370
const char * cairo_status_to_string(cairo_status_t status)
Definition: cairo-misc.c:87
void _cairo_path_fixed_approximate_clip_extents(const cairo_path_fixed_t *path, cairo_rectangle_int_t *extents)
cairo_status_t _cairo_path_fixed_fill_to_traps(const cairo_path_fixed_t *path, cairo_fill_rule_t fill_rule, double tolerance, cairo_traps_t *traps)
cairo_bool_t _cairo_path_fixed_equal(const cairo_path_fixed_t *a, const cairo_path_fixed_t *b)
unsigned long _cairo_path_fixed_hash(const cairo_path_fixed_t *path)
void _cairo_path_fixed_fini(cairo_path_fixed_t *path)
cairo_status_t _cairo_path_fixed_move_to(cairo_path_fixed_t *path, cairo_fixed_t x, cairo_fixed_t y)
cairo_status_t _cairo_path_fixed_rel_line_to(cairo_path_fixed_t *path, cairo_fixed_t dx, cairo_fixed_t dy)
void _cairo_path_fixed_init(cairo_path_fixed_t *path)
cairo_status_t _cairo_path_fixed_init_copy(cairo_path_fixed_t *path, const cairo_path_fixed_t *other)
cairo_status_t _cairo_path_fixed_close_path(cairo_path_fixed_t *path)
cairo_int_status_t _cairo_path_fixed_stroke_polygon_to_traps(const cairo_path_fixed_t *path, const cairo_stroke_style_t *stroke_style, const cairo_matrix_t *ctm, const cairo_matrix_t *ctm_inverse, double tolerance, cairo_traps_t *traps)
cairo_bool_t _cairo_pattern_is_opaque_solid(const cairo_pattern_t *pattern)
void _cairo_box_round_to_rectangle(const cairo_box_t *box, cairo_rectangle_int_t *rectangle)
void _cairo_box_to_doubles(const cairo_box_t *box, double *x1, double *y1, double *x2, double *y2)
#define CAIRO_REFERENCE_COUNT_HAS_REFERENCE(RC)
#define _cairo_reference_count_inc(RC)
#define _cairo_reference_count_dec_and_test(RC)
#define CAIRO_REFERENCE_COUNT_INIT(RC, VALUE)
cairo_status_t _cairo_stroke_style_init_copy(cairo_stroke_style_t *style, const cairo_stroke_style_t *other)
void _cairo_stroke_style_fini(cairo_stroke_style_t *style)
cairo_surface_t * _cairo_surface_default_source(void *surface, cairo_rectangle_int_t *extents)
cairo_int_status_t _cairo_surface_fallback_glyphs(void *abstract_surface, cairo_operator_t op, const cairo_pattern_t *source, cairo_glyph_t *glyphs, int num_glyphs, cairo_scaled_font_t *scaled_font, const cairo_clip_t *clip)
cairo_status_t _cairo_surface_offset_paint(cairo_surface_t *target, int x, int y, cairo_operator_t op, const cairo_pattern_t *source, const cairo_clip_t *clip)
cairo_surface_t * _cairo_surface_create_in_error(cairo_status_t status)
static cairo_bool_t _cairo_surface_is_subsurface(cairo_surface_t *surface)
static cairo_surface_t * _cairo_surface_subsurface_get_target(cairo_surface_t *surface)
void _cairo_surface_release_source_image(cairo_surface_t *surface, cairo_image_surface_t *image, void *image_extra)
void _cairo_surface_init(cairo_surface_t *surface, const cairo_surface_backend_t *backend, cairo_device_t *device, cairo_content_t content, cairo_bool_t is_vector)
void cairo_surface_destroy(cairo_surface_t *surface)
cairo_surface_t * _cairo_surface_has_snapshot(cairo_surface_t *surface, const cairo_surface_backend_t *backend)
cairo_status_t _cairo_surface_acquire_source_image(cairo_surface_t *surface, cairo_image_surface_t **image_out, void **image_extra)
void cairo_surface_flush(cairo_surface_t *surface)
void _cairo_surface_attach_snapshot(cairo_surface_t *surface, cairo_surface_t *snapshot, cairo_surface_func_t detach_func)
void _cairo_traps_init(cairo_traps_t *traps)
Definition: cairo-traps.c:54
void _cairo_traps_fini(cairo_traps_t *traps)
Definition: cairo-traps.c:111
enum _cairo_operator cairo_operator_t
@ CAIRO_SURFACE_TYPE_COGL
Definition: cairo.h:2422
enum _cairo_filter cairo_filter_t
@ CAIRO_FILTER_BILINEAR
Definition: cairo.h:2954
@ CAIRO_FILTER_NEAREST
Definition: cairo.h:2953
enum _cairo_fill_rule cairo_fill_rule_t
enum _cairo_antialias cairo_antialias_t
int cairo_bool_t
Definition: cairo.h:107
@ CAIRO_EXTEND_REFLECT
Definition: cairo.h:2919
@ CAIRO_EXTEND_PAD
Definition: cairo.h:2920
@ CAIRO_EXTEND_NONE
Definition: cairo.h:2917
@ CAIRO_EXTEND_REPEAT
Definition: cairo.h:2918
@ CAIRO_STATUS_SUCCESS
Definition: cairo.h:315
@ CAIRO_STATUS_SURFACE_TYPE_MISMATCH
Definition: cairo.h:329
@ CAIRO_STATUS_DEVICE_ERROR
Definition: cairo.h:351
@ CAIRO_STATUS_NO_MEMORY
Definition: cairo.h:317
@ CAIRO_CONTENT_ALPHA
Definition: cairo.h:381
@ CAIRO_CONTENT_COLOR_ALPHA
Definition: cairo.h:382
@ CAIRO_CONTENT_COLOR
Definition: cairo.h:380
enum _cairo_content cairo_content_t
@ CAIRO_ANTIALIAS_DEFAULT
Definition: cairo.h:710
@ CAIRO_OPERATOR_IN
Definition: cairo.h:618
@ CAIRO_OPERATOR_DEST_OVER
Definition: cairo.h:623
@ CAIRO_OPERATOR_DEST_IN
Definition: cairo.h:624
@ CAIRO_OPERATOR_CLEAR
Definition: cairo.h:614
@ CAIRO_OPERATOR_ADD
Definition: cairo.h:629
@ CAIRO_OPERATOR_SOURCE
Definition: cairo.h:616
@ CAIRO_OPERATOR_OVER
Definition: cairo.h:617
enum _cairo_status cairo_status_t
void(* cairo_destroy_func_t)(void *data)
Definition: cairo.h:232
enum _cairo_extend cairo_extend_t
enum _cairo_format cairo_format_t
@ CAIRO_FORMAT_RGB30
Definition: cairo.h:423
@ CAIRO_FORMAT_A8
Definition: cairo.h:420
@ CAIRO_FORMAT_RGB24
Definition: cairo.h:419
@ CAIRO_FORMAT_INVALID
Definition: cairo.h:417
@ CAIRO_FORMAT_ARGB32
Definition: cairo.h:418
@ CAIRO_FORMAT_RGB16_565
Definition: cairo.h:422
@ CAIRO_FORMAT_A1
Definition: cairo.h:421
@ CAIRO_DEVICE_TYPE_COGL
Definition: cairo.h:2170
@ CAIRO_FILL_RULE_WINDING
Definition: cairo.h:754
@ CAIRO_PATTERN_TYPE_LINEAR
Definition: cairo.h:2827
@ CAIRO_PATTERN_TYPE_SURFACE
Definition: cairo.h:2826
@ CAIRO_PATTERN_TYPE_SOLID
Definition: cairo.h:2825
@ CAIRO_PATTERN_TYPE_RADIAL
Definition: cairo.h:2828
@ CAIRO_PATTERN_TYPE_MESH
Definition: cairo.h:2829
#define CAIRO_COLOR_TRANSPARENT
Definition: cairoint.h:795
static cairo_bool_t _cairo_matrix_is_identity(const cairo_matrix_t *matrix)
Definition: cairoint.h:1786
static void _cairo_cogl_maybe_log_clip(cairo_cogl_surface_t *surface, cairo_composite_rectangles_t *composite)
static void _cairo_cogl_path_fill_meta_destroy(cairo_cogl_path_fill_meta_t *meta)
static cairo_bool_t _cairo_cogl_path_fill_meta_equal(const void *key_a, const void *key_b)
static CoglPipelineWrapMode get_cogl_wrap_mode_for_extend(cairo_extend_t extend_mode)
static CoglPrimitive * _cairo_cogl_traps_to_composite_prim_p2t2(cairo_cogl_surface_t *surface, cairo_traps_t *traps, gboolean one_shot)
static cairo_bool_t set_blend(CoglPipeline *pipeline, const char *blend_string)
static cairo_status_t _cairo_cogl_surface_read_rect_to_image_surface(cairo_cogl_surface_t *surface, cairo_rectangle_int_t *interest, cairo_image_surface_t **image_out)
static CoglTexture * _cairo_cogl_acquire_surface_texture(cairo_cogl_surface_t *reference_surface, cairo_surface_t *abstract_surface)
static cairo_format_t get_cairo_format_from_cogl_format(CoglPixelFormat format)
static void _cairo_cogl_journal_log_rectangle(cairo_cogl_surface_t *surface, CoglPipeline *pipeline, float x, float y, float width, float height, int n_layers, cairo_matrix_t *ctm)
static cairo_cogl_path_fill_meta_t * _cairo_cogl_path_fill_meta_reference(cairo_cogl_path_fill_meta_t *meta)
static CoglPipeline * get_source_mask_operator_destination_pipeline(const cairo_pattern_t *mask, const cairo_pattern_t *source, cairo_operator_t op, cairo_cogl_surface_t *destination, cairo_composite_rectangles_t *extents)
static cairo_surface_t * _cairo_cogl_surface_create_full(cairo_cogl_device_t *dev, cairo_bool_t ignore_alpha, CoglFramebuffer *framebuffer, CoglTexture *texture)
static void _cairo_cogl_journal_log_clip(cairo_cogl_surface_t *surface, const cairo_clip_t *clip)
static CoglTexture * _cairo_cogl_acquire_pattern_texture(const cairo_pattern_t *pattern, cairo_cogl_surface_t *destination, const cairo_rectangle_int_t *extents, const cairo_rectangle_int_t *sample, cairo_cogl_texture_attributes_t *attributes)
static cairo_surface_t * _cairo_cogl_surface_create_similar(void *abstract_surface, cairo_content_t content, int width, int height)
static cairo_status_t _cairo_cogl_surface_clear(cairo_cogl_surface_t *surface, const cairo_color_t *color)
static cairo_cogl_path_fill_meta_t * _cairo_cogl_get_path_fill_meta(cairo_cogl_surface_t *surface)
static cairo_status_t _cairo_cogl_surface_flush(void *abstract_surface, unsigned flags)
static cairo_bool_t _cairo_cogl_stroke_style_equal(const cairo_stroke_style_t *a, const cairo_stroke_style_t *b)
static void create_templates_for_op(cairo_cogl_device_t *dev, cairo_operator_t op)
static void set_layer_texture_with_attributes(CoglPipeline *pipeline, int layer_index, CoglTexture *texture, cairo_cogl_texture_attributes_t *attributes)
static cairo_int_status_t _cairo_cogl_surface_mask(void *abstract_surface, cairo_operator_t op, const cairo_pattern_t *source, const cairo_pattern_t *mask, const cairo_clip_t *clip)
static void _cairo_cogl_path_stroke_meta_destroy(cairo_cogl_path_stroke_meta_t *meta)
#define CAIRO_COGL_PATH_META_CACHE_SIZE
static void _cairo_cogl_path_stroke_meta_set_prim_size(cairo_cogl_surface_t *surface, cairo_cogl_path_stroke_meta_t *meta, size_t size)
static const cairo_device_backend_t _cairo_cogl_device_backend
static void _cairo_cogl_surface_release_source_image(void *abstract_surface, cairo_image_surface_t *image, void *image_extra)
#define FIX(lr, tb, p)
static cairo_int_status_t _cairo_cogl_surface_paint(void *abstract_surface, cairo_operator_t op, const cairo_pattern_t *source, const cairo_clip_t *clip)
static cairo_cogl_device_t * to_device(cairo_device_t *device)
static CoglAttributeBuffer * _cairo_cogl_surface_allocate_buffer_space(cairo_cogl_surface_t *surface, size_t size, size_t *offset, void **pointer)
static cairo_status_t _cairo_cogl_device_flush(void *device)
static void _cairo_cogl_clip_push_box(const cairo_box_t *box)
static void _cairo_cogl_device_destroy(void *device)
static void _cairo_cogl_log_clip(cairo_cogl_surface_t *surface, const cairo_clip_t *clip)
static cairo_bool_t _cairo_cogl_path_stroke_meta_equal(const void *key_a, const void *key_b)
static void _cairo_cogl_journal_flush(cairo_cogl_surface_t *surface)
static CoglPrimitive * _cairo_cogl_traps_to_composite_prim_p2(cairo_cogl_surface_t *surface, cairo_traps_t *traps, gboolean one_shot)
static cairo_int_status_t _cairo_cogl_fill_to_primitive(cairo_cogl_surface_t *surface, const cairo_path_fixed_t *path, cairo_fill_rule_t fill_rule, double tolerance, int n_layers, cairo_bool_t one_shot, CoglPrimitive **primitive, size_t *size)
static CoglPrimitive * _cairo_cogl_traps_to_composite_prim(cairo_cogl_surface_t *surface, cairo_traps_t *traps, int n_layers, gboolean one_shot)
static cairo_int_status_t _cairo_cogl_surface_stroke(void *abstract_surface, cairo_operator_t op, const cairo_pattern_t *source, const cairo_path_fixed_t *path, const cairo_stroke_style_t *style, const cairo_matrix_t *ctm, const cairo_matrix_t *ctm_inverse, double tolerance, cairo_antialias_t antialias, const cairo_clip_t *clip)
static cairo_cogl_path_stroke_meta_t * _cairo_cogl_get_path_stroke_meta(cairo_cogl_surface_t *surface, const cairo_stroke_style_t *style, double tolerance)
static cairo_bool_t _cairo_cogl_setup_op_state(CoglPipeline *pipeline, cairo_operator_t op)
static cairo_cogl_path_stroke_meta_t * _cairo_cogl_path_stroke_meta_reference(cairo_cogl_path_stroke_meta_t *meta)
static unsigned int _cairo_cogl_stroke_style_hash(unsigned int hash, const cairo_stroke_style_t *style)
static void _sanitize_trap(cairo_trapezoid_t *t)
static cairo_status_t _cairo_cogl_surface_finish(void *abstract_surface)
static cairo_cogl_path_stroke_meta_t * _cairo_cogl_path_stroke_meta_lookup(cairo_cogl_device_t *ctx, unsigned long hash, cairo_path_fixed_t *user_path, const cairo_stroke_style_t *style, double tolerance)
static cairo_int_status_t _cairo_cogl_surface_fill(void *abstract_surface, cairo_operator_t op, const cairo_pattern_t *source, const cairo_path_fixed_t *path, cairo_fill_rule_t fill_rule, double tolerance, cairo_antialias_t antialias, const cairo_clip_t *clip)
static void _cairo_cogl_journal_free(cairo_cogl_surface_t *surface)
static cairo_status_t _cairo_cogl_surface_ensure_framebuffer(cairo_cogl_surface_t *surface)
static cairo_bool_t is_operator_supported(cairo_operator_t op)
static cairo_int_status_t _cairo_cogl_stroke_to_primitive(cairo_cogl_surface_t *surface, const cairo_path_fixed_t *path, const cairo_stroke_style_t *style, const cairo_matrix_t *ctm, const cairo_matrix_t *ctm_inverse, double tolerance, int n_layers, cairo_bool_t one_shot, CoglPrimitive **primitive, size_t *size)
static void _cairo_cogl_path_fill_meta_set_prim_size(cairo_cogl_surface_t *surface, cairo_cogl_path_fill_meta_t *meta, size_t size)
static cairo_cogl_path_fill_meta_t * _cairo_cogl_path_fill_meta_lookup(cairo_cogl_device_t *ctx, unsigned long hash, cairo_path_fixed_t *user_path)
static void _cairo_cogl_journal_log_primitive(cairo_cogl_surface_t *surface, CoglPipeline *pipeline, CoglPrimitive *primitive, cairo_matrix_t *transform)
static int _cairo_cogl_source_n_layers(const cairo_pattern_t *source)
static cairo_status_t _cairo_cogl_surface_acquire_source_image(void *abstract_surface, cairo_image_surface_t **image_out, void **image_extra)
static cairo_int_status_t _cairo_cogl_surface_show_glyphs(void *surface, cairo_operator_t op, const cairo_pattern_t *source, cairo_glyph_t *glyphs, int num_glyphs, cairo_scaled_font_t *scaled_font, const cairo_clip_t *clip)
static cairo_bool_t _cairo_cogl_surface_get_extents(void *abstract_surface, cairo_rectangle_int_t *extents)
static CoglPixelFormat get_cogl_format_from_cairo_format(cairo_format_t cairo_format)
static CoglAttributeBuffer * _cairo_cogl_traps_to_triangles_buffer(cairo_cogl_surface_t *surface, cairo_traps_t *traps, size_t *offset, gboolean one_shot)
static void _cairo_cogl_journal_discard(cairo_cogl_surface_t *surface)
static void _cairo_cogl_device_finish(void *device)
Definition: GList.h:24
#define b
Definition: jpegint.h:372
@ FALSE
Definition: dd.h:101
@ TRUE
Definition: dd.h:102
#define free(a)
Definition: decNumber.cpp:310
void glyphs(int opcode)
Definition: disdvi.c:775
#define error(a)
Definition: dviinfo.c:48
struct rect rect
Definition: dvipdfm.c:59
unsigned char * pointer
Definition: fontmisc.h:33
#define s
Definition: afcover.h:80
#define t
Definition: afcover.h:96
#define a(n)
Definition: gpos-common.c:148
int base
Definition: gsftopk.c:1502
#define memcpy(d, s, n)
Definition: gsftopk.c:64
assert(pcxLoadImage24((char *)((void *) 0), fp, pinfo, hdr))
unsigned char * image
Definition: in_pcx.cpp:323
#define unlikely(x)
Definition: jbig2arith.cc:116
#define NULL
Definition: ftobjs.h:61
small capitals from c petite p
Definition: afcover.h:72
small capitals from c petite p scientific i
Definition: afcover.h:80
sizeof(AF_ModuleRec)
Arabic default style
Definition: afstyles.h:94
kerning y
Definition: ttdriver.c:212
@ right
Definition: annotate.c:15
int int double double double char double char * top
Definition: gdfx.h:19
int int double double double char double char char * bottom
Definition: gdfx.h:20
voidp calloc()
#define ERROR(string)
Definition: error.h:36
pdf_obj * entry
Definition: pdfdoc.c:64
string user_path
Definition: kpsewhich.c:78
static int ret
Definition: convert.c:72
#define transform(xusr, yusr, xdev, ydev)
Definition: type1.c:1420
const int * pos
Definition: combiners.h:905
void g_free(void *p)
Definition: miniglib.c:52
angle
Definition: cordic.py:17
float x
Definition: cordic.py:15
static int format
Definition: pbmclean.c:15
static cairo_surface_t * surface
Definition: pdftocairo.cc:234
static GooString antialias
Definition: pdftocairo.cc:119
void composite()
double scale
Definition: pnmhistmap.c:38
static int size
Definition: ppmlabel.c:24
static int offset
Definition: ppmtogif.c:642
bstring c int memset(void *s, int c, int length)
#define x1
#define y1
#define y2
#define x2
#define status
#define flags
#define mask(n)
Definition: lbitlib.c:93
static void(* trap)(void)
Definition: memory.c:38
static struct XYspace identity
Definition: spaces.c:163
size_t size
size_t hash
cairo_box_t * boxes
cairo_clip_path_t * path
CoglPipeline * template_pipelines[CAIRO_OPERATOR_ADD+1][CAIRO_COGL_TEMPLATE_TYPE_COUNT]
cairo_cache_t path_stroke_staging_cache
CoglTexture * dummy_texture
cairo_cache_t path_stroke_prim_cache
CoglContext * cogl_context
cairo_cache_t linear_cache
cairo_cache_t path_fill_prim_cache
cairo_cache_t path_fill_staging_cache
cairo_bool_t backend_vtable_initialized
cairo_cogl_journal_entry_t base
cairo_clip_t * clip
cairo_cogl_journal_entry_type_t type
cairo_cogl_journal_entry_t base
CoglPath * path
CoglPipeline * pipeline
cairo_matrix_t transform
gboolean has_transform
cairo_cogl_journal_entry_t base
CoglPrimitive * primitive
CoglPipeline * pipeline
float height
cairo_cogl_journal_entry_t base
float width
float x
cairo_matrix_t ctm
CoglPipeline * pipeline
float y
int n_layers
CoglTexture * texture
cairo_cache_entry_t cache_entry
cairo_path_fixed_t * user_path
cairo_reference_count_t ref_count
cairo_reference_count_t ref_count
cairo_path_fixed_t * user_path
cairo_surface_t base
cairo_device_type_t type
cairo_status_t status
const cairo_device_backend_t * backend
cairo_gradient_stop_t * stops
cairo_gradient_pattern_t base
cairo_point_double_t pd2
cairo_point_double_t pd1
double x0
Definition: cairo.h:195
double xy
Definition: cairo.h:194
double yx
Definition: cairo.h:193
double yy
Definition: cairo.h:194
double xx
Definition: cairo.h:193
double y0
Definition: cairo.h:195
cairo_status_t status
cairo_surface_type_t type
const cairo_surface_backend_t * backend
cairo_device_t * device
cairo_trapezoid_t * traps
Definition: jquant2.c:258
Definition: utils.c:300
Definition: pdfdev.c:706
Definition: sd.h:76
Definition: zic.c:306
Definition: sh.h:1226
Definition: tpic.c:45
unsigned int type[8]
int type
Definition: pdfobj.c:64
Definition: dvipdfm.c:55
double height
Definition: dvipdfm.c:57
double width
Definition: dvipdfm.c:56
Definition: sh.h:1345
int type
Definition: sh.h:1347
Definition: dvips.h:235
pointer path
Definition: t1imager.h:36
m
Definition: tex4ht.c:3990
op
Definition: tex4ht.c:3129
#define buffer
Definition: xmlparse.c:611