Changes.
[cairo/gpu.git] / src / gpu / cairo-gpu-impl-base.h
bloba9542664358ed84e16cf688654c1ba48e1a02109
1 #define CHAN_C 1
3 // means that A is not "uniform"
4 #define CHAN_A 2
6 #define CHAN_KA 4
8 typedef struct
10 cairo_pattern_t *src;
11 int chan;
12 int src_x;
13 int src_y;
14 cairo_gpu_surface_t *surface;
15 cairo_gpu_texture_t* texture;
16 unsigned char owns_texture;
17 unsigned char owns_surface;
18 unsigned char unpremultiplied : 1;
19 unsigned char gradient_discontinuous : 1;
20 unsigned char has_coords : 1;
21 cairo_surface_attributes_t attributes;
22 unsigned gradient_denominator;
23 unsigned gradient_width;
24 } cairo_gpu_composite_operand_t;
26 #define BLEND_COLOR_C_DIV_A 1
27 #define BLEND_COLOR_A 2
28 #define BLEND_COLOR_1_MINUS_A 3
30 typedef struct
32 unsigned frag;
33 unsigned vert;
34 cairo_gpu_blend_t blend;
35 unsigned char blend_color;
36 unsigned char chan;
37 unsigned char component;
38 unsigned char unpremultiplied : 1;
39 unsigned char unpremultiplied_one_alpha : 1;
40 unsigned char draw_geometry : 1;
41 char operands[MAX_OPERANDS];
42 } cairo_gpu_composite_pass_t;
44 #define BLEND_ALPHA 2
46 typedef struct
48 cairo_gpu_surface_t *dst;
49 int obj_x;
50 int obj_y;
52 int dst_x;
53 int dst_y;
54 int width;
55 int height;
57 cairo_gpu_color_t c;
58 cairo_gpu_color_t a;
59 float ka;
61 unsigned char blend_dst;
62 unsigned char blend_src;
63 unsigned char smooth;
64 unsigned char saturate : 1;
65 unsigned char dst_alpha_mask : 1;
66 unsigned char unpremultiplied : 1;
68 int primary_chan;
69 int constant_chan;
70 int zero_chan;
71 int operands_chan;
72 cairo_gpu_composite_operand_t operands[MAX_OPERANDS];
73 char cur_operands[MAX_OPERANDS];
75 int npasses;
76 cairo_gpu_composite_pass_t passes[4];
77 } cairo_gpu_composite_setup_t;
79 #if 0
80 #if CAIRO_NO_MUTEX
81 #define CURRENT_THREAD() ((void*)1)
82 #elif HAVE_PTHREAD_H
83 #define CURRENT_THREAD() ((void*)pthread_self())
84 #elif defined(HAVE_WINDOWS_H) || defined(_MSC_VER)
85 #define CURRENT_THREAD() ((void*)GetCurrentThreadId())
86 #elif defined __OS2__
87 #error Implement CURRENT_THREAD for OS/2
88 #elif CAIRO_HAS_BEOS_SURFACE
89 #define CURRENT_THREAD() ((void*)find_thread(0))
90 #else
91 #error Implement CURRENT_THREAD for your platform
92 #endif
94 static inline void
95 _cairo_gpu_context__lock(cairo_gpu_context_t* ctx)
97 if(ctx->owner_thread != CURRENT_THREAD())
99 CAIRO_MUTEX_LOCK(ctx->mutex);
100 ctx->owner_thread = CURRENT_THREAD();
102 ++ctx->lock_depth;
105 static inline void
106 _cairo_gpu_context__unlock(cairo_gpu_context_t* ctx)
108 if(!--ctx->lock_depth)
110 ctx->owner_thread = 0;
111 CAIRO_MUTEX_UNLOCK(ctx->mutex);
114 #endif
116 #define ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0]))
118 static inline float
119 int_as_float(uint32_t val)
121 union fi
123 float f;
124 uint32_t u;
125 } fi;
127 fi.u = val;
128 return fi.f;
131 /* Some loss of precision possible */
132 static inline float
133 _cairo_fixed_to_float(cairo_fixed_t f)
135 return ((float)f) * (1.0f / (float)(1 << CAIRO_FIXED_FRAC_BITS));
138 #ifdef _XLIB_H_
139 static int
140 parse_boolean (const char *v)
142 char c0, c1;
144 c0 = *v;
145 if (c0 == 't' || c0 == 'T' || c0 == 'y' || c0 == 'Y' || c0 == '1')
146 return 1;
147 if (c0 == 'f' || c0 == 'F' || c0 == 'n' || c0 == 'N' || c0 == '0')
148 return 0;
149 if (c0 == 'o')
151 c1 = v[1];
152 if (c1 == 'n' || c1 == 'N')
153 return 1;
154 if (c1 == 'f' || c1 == 'F')
155 return 0;
158 return -1;
161 static cairo_bool_t
162 get_boolean_default (Display *dpy,
163 const char *option,
164 cairo_bool_t *value)
166 char *v;
167 int i;
169 v = XGetDefault (dpy, "Xft", option);
170 if (v) {
171 i = parse_boolean (v);
172 if (i >= 0) {
173 *value = i;
174 return TRUE;
178 return FALSE;
181 #if CAIRO_HAS_FT_FONT
182 int __attribute__((weak)) FcNameConstant (unsigned char* string, int *result);
183 #endif
185 static cairo_bool_t
186 get_integer_default (Display *dpy,
187 const char *option,
188 int *value)
190 char *v, *e;
192 v = XGetDefault (dpy, "Xft", option);
193 if (v) {
194 #if CAIRO_HAS_FT_FONT
195 if (FcNameConstant ((unsigned char*) v, value))
196 return TRUE;
197 #endif
199 *value = strtol (v, &e, 0);
200 if (e != v)
201 return TRUE;
204 return FALSE;
207 #ifndef FC_RGBA_UNKNOWN
208 #define FC_RGBA_UNKNOWN 0
209 #define FC_RGBA_RGB 1
210 #define FC_RGBA_BGR 2
211 #define FC_RGBA_VRGB 3
212 #define FC_RGBA_VBGR 4
213 #define FC_RGBA_NONE 5
214 #endif
216 /* Old versions of fontconfig didn't have these options */
217 #ifndef FC_HINT_NONE
218 #define FC_HINT_NONE 0
219 #define FC_HINT_SLIGHT 1
220 #define FC_HINT_MEDIUM 2
221 #define FC_HINT_FULL 3
222 #endif
224 /* Fontconfig version older than 2.6 didn't have these options */
225 #ifndef FC_LCD_FILTER
226 #define FC_LCD_FILTER "lcdfilter"
227 #endif
228 /* Some Ubuntu versions defined FC_LCD_FILTER without defining the following */
229 #ifndef FC_LCD_NONE
230 #define FC_LCD_NONE 0
231 #define FC_LCD_DEFAULT 1
232 #define FC_LCD_LIGHT 2
233 #define FC_LCD_LEGACY 3
234 #endif
236 static void
237 _cairo_gpu_init_font_options_for_display (cairo_font_options_t * font_options, Display* dpy)
239 cairo_bool_t xft_hinting;
240 cairo_bool_t xft_antialias;
241 int xft_hintstyle;
242 int xft_rgba;
243 cairo_antialias_t antialias;
244 cairo_subpixel_order_t subpixel_order;
245 cairo_hint_style_t hint_style;
247 if (!get_boolean_default (dpy, "antialias", &xft_antialias))
248 xft_antialias = TRUE;
250 if (!get_boolean_default (dpy, "hinting", &xft_hinting))
251 xft_hinting = TRUE;
253 if (!get_integer_default (dpy, "hintstyle", &xft_hintstyle))
254 xft_hintstyle = FC_HINT_FULL;
256 if (!get_integer_default (dpy, "rgba", &xft_rgba))
258 int event_base, error_base, has_render;
259 xft_rgba = FC_RGBA_UNKNOWN;
263 has_render = (XRenderQueryExtension (dpy, &event_base, &error_base) &&
264 (XRenderFindVisualFormat (dpy, DefaultVisual (dpy, DefaultScreen (dpy))) != 0));
266 #if RENDER_MAJOR > 0 || RENDER_MINOR >= 6
267 if (has_render)
269 int render_order = XRenderQuerySubpixelOrder (dpy, DefaultScreen(dpy));
271 switch (render_order)
273 default:
274 case SubPixelUnknown:
275 xft_rgba = FC_RGBA_UNKNOWN;
276 break;
277 case SubPixelHorizontalRGB:
278 xft_rgba = FC_RGBA_RGB;
279 break;
280 case SubPixelHorizontalBGR:
281 xft_rgba = FC_RGBA_BGR;
282 break;
283 case SubPixelVerticalRGB:
284 xft_rgba = FC_RGBA_VRGB;
285 break;
286 case SubPixelVerticalBGR:
287 xft_rgba = FC_RGBA_VBGR;
288 break;
289 case SubPixelNone:
290 xft_rgba = FC_RGBA_NONE;
291 break;
294 #endif
297 if (xft_hinting) {
298 switch (xft_hintstyle) {
299 case FC_HINT_NONE:
300 hint_style = CAIRO_HINT_STYLE_NONE;
301 break;
302 case FC_HINT_SLIGHT:
303 hint_style = CAIRO_HINT_STYLE_SLIGHT;
304 break;
305 case FC_HINT_MEDIUM:
306 hint_style = CAIRO_HINT_STYLE_MEDIUM;
307 break;
308 case FC_HINT_FULL:
309 hint_style = CAIRO_HINT_STYLE_FULL;
310 break;
311 default:
312 hint_style = CAIRO_HINT_STYLE_DEFAULT;
314 } else {
315 hint_style = CAIRO_HINT_STYLE_NONE;
318 switch (xft_rgba) {
319 case FC_RGBA_RGB:
320 subpixel_order = CAIRO_SUBPIXEL_ORDER_RGB;
321 break;
322 case FC_RGBA_BGR:
323 subpixel_order = CAIRO_SUBPIXEL_ORDER_BGR;
324 break;
325 case FC_RGBA_VRGB:
326 subpixel_order = CAIRO_SUBPIXEL_ORDER_VRGB;
327 break;
328 case FC_RGBA_VBGR:
329 subpixel_order = CAIRO_SUBPIXEL_ORDER_VBGR;
330 break;
331 case FC_RGBA_UNKNOWN:
332 case FC_RGBA_NONE:
333 default:
334 subpixel_order = CAIRO_SUBPIXEL_ORDER_DEFAULT;
337 if (xft_antialias) {
338 if (subpixel_order == CAIRO_SUBPIXEL_ORDER_DEFAULT)
339 antialias = CAIRO_ANTIALIAS_GRAY;
340 else
341 antialias = CAIRO_ANTIALIAS_SUBPIXEL;
342 } else {
343 antialias = CAIRO_ANTIALIAS_NONE;
346 cairo_font_options_set_hint_style (font_options, hint_style);
347 cairo_font_options_set_antialias (font_options, antialias);
348 cairo_font_options_set_subpixel_order (font_options, subpixel_order);
349 cairo_font_options_set_hint_metrics (font_options, CAIRO_HINT_METRICS_ON);
351 #endif
353 static inline cairo_gpu_space_tls_t*
354 _cairo_gpu_space_alloc_tls(cairo_gpu_space_t* space);
356 static cairo_gpu_space_tls_t*
357 _cairo_gpu_space_create_tls(cairo_gpu_space_t* space)
359 cairo_gpu_space_tls_t* tls = _cairo_gpu_space_alloc_tls(space);
360 tls->space = space;
362 CAIRO_MUTEX_LOCK(space->mutex);
363 insert_after(&space->tls_list, &tls->node);
364 CAIRO_MUTEX_UNLOCK(space->mutex);
366 pthread_setspecific(space->tls, tls);
367 return tls;
370 static cairo_gpu_space_tls_t*
371 _cairo_gpu_space_get_tls(cairo_gpu_space_t* space)
373 cairo_gpu_space_tls_t* tls = pthread_getspecific(space->tls);
374 if(tls)
375 return tls;
377 return _cairo_gpu_space_create_tls(space);
380 static inline cairo_gpu_context_t *
381 _cairo_gpu_space_tls_lookup_context(cairo_gpu_space_tls_t* gpu_tls);
383 static inline void
384 _cairo_gpu_context_bind(cairo_gpu_context_t* ctx);
386 static inline cairo_gpu_context_t *
387 _cairo_gpu_space_bind(cairo_gpu_space_t* space)
389 cairo_gpu_context_t* ctx = _cairo_gpu_space_tls_lookup_context(_cairo_gpu_space_get_tls(space));
390 _cairo_gpu_context_bind(ctx);
391 return ctx;
394 static inline void
395 _cairo_gpu_space_tls_destroy_contexts(cairo_gpu_space_tls_t* gpu_tls);
397 static void
398 _cairo_gpu_space_tls_destroy(cairo_gpu_space_tls_t* tls)
400 int i;
401 cairo_gpu_context_t* ctx = _cairo_gpu_space_tls_lookup_context(tls);
402 _cairo_gpu_context_bind(ctx);
404 for(i = 0; i < MAX_OPERANDS; ++i)
406 int j;
407 for(j = 0; j < MAX_SMALL_WIDTH; ++j)
409 if(tls->small_texture_pools[i].texture[j])
411 _cairo_gpu_texture_fini(ctx, tls->small_texture_pools[i].texture[j]);
412 free(tls->small_texture_pools[i].texture[j]);
413 tls->small_texture_pools[i].texture[j] = 0;
418 _cairo_gpu_space_tls_destroy_contexts(tls);
420 free(tls);
423 static void
424 _cairo_gpu_space_tls_dtor(void* abstract)
426 cairo_gpu_space_tls_t* tls = abstract;
428 if(tls)
430 CAIRO_MUTEX_LOCK(tls->space->mutex);
431 unlink_node(&tls->node);
432 CAIRO_MUTEX_UNLOCK(tls->space->mutex);
434 _cairo_gpu_space_tls_destroy(tls);
438 #define _cairo_gpu_context_geometry(ctx, unused) _cairo_gpu_geometry_init((cairo_gpu_geometry_t*)alloca(sizeof(cairo_gpu_geometry_t)))
439 #define _cairo_gpu_geometry_put(ctx, geometry) _cairo_gpu_geometry_fini(ctx, geometry)
441 #define _cairo_gpu_context_geometry_long(ctx, unused) _cairo_gpu_geometry_init((cairo_gpu_geometry_t*)malloc(sizeof(cairo_gpu_geometry_t)))
442 #define _cairo_gpu_geometry_put_long(ctx, geometry) free(_cairo_gpu_geometry_fini(ctx, geometry))