sna.h revision 63ef14f0
1/**************************************************************************
2
3Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
4Copyright © 2002 David Dawes
5
6All Rights Reserved.
7
8Permission is hereby granted, free of charge, to any person obtaining a
9copy of this software and associated documentation files (the
10"Software"), to deal in the Software without restriction, including
11without limitation the rights to use, copy, modify, merge, publish,
12distribute, sub license, and/or sell copies of the Software, and to
13permit persons to whom the Software is furnished to do so, subject to
14the following conditions:
15
16The above copyright notice and this permission notice (including the
17next paragraph) shall be included in all copies or substantial portions
18of the Software.
19
20THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
23IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
24ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
25TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
26SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27
28**************************************************************************/
29
30/*
31 * Authors:
32 *   Keith Whitwell <keith@tungstengraphics.com>
33 *   David Dawes <dawes@xfree86.org>
34 *
35 */
36
37#ifndef _SNA_H_
38#define _SNA_H_
39
40#include <stdint.h>
41
42#include <xorg-server.h>
43#include <xf86str.h>
44
45#include <xf86Crtc.h>
46#if XF86_CRTC_VERSION >= 5
47#define HAS_PIXMAP_SHARING 1
48#endif
49
50#include <windowstr.h>
51#include <glyphstr.h>
52#include <picturestr.h>
53#include <gcstruct.h>
54#include <xvdix.h>
55
56#include <pciaccess.h>
57
58#include <xf86drmMode.h>
59
60#include "../compat-api.h"
61#include <drm.h>
62#include <i915_drm.h>
63
64#if HAVE_DRI2
65#include <dri2.h>
66#endif
67
68#if HAVE_DRI3
69#include <misync.h>
70#endif
71
72#if HAVE_UDEV
73#include <libudev.h>
74#endif
75
76#include <signal.h>
77#include <setjmp.h>
78
79#include "xassert.h"
80#include "compiler.h"
81#include "debug.h"
82
83#define DEBUG_NO_BLT 0
84
85#define DEBUG_FLUSH_BATCH 0
86
87#define TEST_ALL 0
88#define TEST_ACCEL (TEST_ALL || 0)
89#define TEST_BATCH (TEST_ALL || 0)
90#define TEST_BLT (TEST_ALL || 0)
91#define TEST_COMPOSITE (TEST_ALL || 0)
92#define TEST_DAMAGE (TEST_ALL || 0)
93#define TEST_GRADIENT (TEST_ALL || 0)
94#define TEST_GLYPHS (TEST_ALL || 0)
95#define TEST_IO (TEST_ALL || 0)
96#define TEST_KGEM (TEST_ALL || 0)
97#define TEST_RENDER (TEST_ALL || 0)
98
99#include "intel_driver.h"
100#include "intel_list.h"
101#include "kgem.h"
102#include "sna_damage.h"
103#include "sna_render.h"
104#include "fb/fb.h"
105
106struct sna_cursor;
107struct sna_crtc;
108
109struct sna_client {
110	struct list events;
111	int is_compositor; /* only 4 bits used */
112};
113
114extern DevPrivateKeyRec sna_client_key;
115
116pure static inline struct sna_client *sna_client(ClientPtr client)
117{
118	return __get_private(client, sna_client_key);
119}
120
121struct sna_cow {
122	struct kgem_bo *bo;
123	struct list list;
124	int refcnt;
125};
126
127struct sna_pixmap {
128	PixmapPtr pixmap;
129	struct kgem_bo *gpu_bo, *cpu_bo;
130	struct sna_damage *gpu_damage, *cpu_damage;
131	struct sna_cow *cow;
132	void *ptr;
133#define PTR(ptr) ((void*)((uintptr_t)(ptr) & ~1))
134
135	bool (*move_to_gpu)(struct sna *, struct sna_pixmap *, unsigned);
136	void *move_to_gpu_data;
137
138	struct list flush_list;
139	struct list cow_list;
140
141	uint32_t stride;
142	uint32_t clear_color;
143
144#define SOURCE_BIAS 4
145	uint8_t source_count;
146	uint8_t pinned :4;
147#define PIN_SCANOUT 0x1
148#define PIN_DRI2 0x2
149#define PIN_DRI3 0x4
150#define PIN_PRIME 0x8
151	uint8_t create :4;
152	uint8_t mapped :2;
153#define MAPPED_NONE 0
154#define MAPPED_GTT 1
155#define MAPPED_CPU 2
156	uint8_t flush :2;
157#define FLUSH_READ 1
158#define FLUSH_WRITE 2
159	uint8_t shm :1;
160	uint8_t clear :1;
161	uint8_t header :1;
162	uint8_t cpu :1;
163};
164
165#define IS_STATIC_PTR(ptr) ((uintptr_t)(ptr) & 1)
166#define MAKE_STATIC_PTR(ptr) ((void*)((uintptr_t)(ptr) | 1))
167
168struct sna_glyph {
169	PicturePtr atlas;
170	struct sna_coordinate coordinate;
171	uint16_t size, pos;
172	pixman_image_t *image;
173};
174
175static inline WindowPtr get_root_window(ScreenPtr screen)
176{
177#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,10,0,0,0)
178	return screen->root;
179#else
180	return WindowTable[screen->myNum];
181#endif
182}
183
184#if !NDEBUG
185static PixmapPtr check_pixmap(PixmapPtr pixmap)
186{
187	if (pixmap != NULL) {
188		assert(pixmap->refcnt >= 1);
189		assert(pixmap->devKind != 0xdeadbeef);
190	}
191	return pixmap;
192}
193#else
194#define check_pixmap(p) p
195#endif
196
197static inline PixmapPtr get_window_pixmap(WindowPtr window)
198{
199	assert(window);
200	assert(window->drawable.type != DRAWABLE_PIXMAP);
201	return check_pixmap(fbGetWindowPixmap(window));
202}
203
204static inline PixmapPtr get_drawable_pixmap(DrawablePtr drawable)
205{
206	assert(drawable);
207	if (drawable->type == DRAWABLE_PIXMAP)
208		return check_pixmap((PixmapPtr)drawable);
209	else
210		return get_window_pixmap((WindowPtr)drawable);
211}
212
213extern DevPrivateKeyRec sna_pixmap_key;
214
215pure static inline struct sna_pixmap *sna_pixmap(PixmapPtr pixmap)
216{
217	return ((void **)__get_private(pixmap, sna_pixmap_key))[1];
218}
219
220static inline struct sna_pixmap *sna_pixmap_from_drawable(DrawablePtr drawable)
221{
222	return sna_pixmap(get_drawable_pixmap(drawable));
223}
224
225struct sna_gc {
226	long changes;
227	long serial;
228
229	const GCFuncs *old_funcs;
230	void *priv;
231};
232
233static inline struct sna_gc *sna_gc(GCPtr gc)
234{
235	return (struct sna_gc *)__get_private(gc, sna_gc_key);
236}
237
238enum {
239	FLUSH_TIMER = 0,
240	THROTTLE_TIMER,
241	EXPIRE_TIMER,
242#if DEBUG_MEMORY
243	DEBUG_MEMORY_TIMER,
244#endif
245	NUM_TIMERS
246};
247
248struct sna {
249	struct kgem kgem;
250
251	ScrnInfoPtr scrn;
252	struct intel_device *dev;
253
254	unsigned flags;
255#define SNA_IS_SLAVED		0x1
256#define SNA_IS_HOSTED		0x2
257#define SNA_NO_WAIT		0x10
258#define SNA_NO_FLIP		0x20
259#define SNA_NO_VSYNC		0x40
260#define SNA_TRIPLE_BUFFER	0x80
261#define SNA_TEAR_FREE		0x100
262#define SNA_WANT_TEAR_FREE	0x200
263#define SNA_FORCE_SHADOW	0x400
264#define SNA_FLUSH_GTT		0x800
265#define SNA_PERFORMANCE		0x1000
266#define SNA_POWERSAVE		0x2000
267#define SNA_NO_DPMS		0x4000
268#define SNA_HAS_FLIP		0x10000
269#define SNA_HAS_ASYNC_FLIP	0x20000
270#define SNA_LINEAR_FB		0x40000
271#define SNA_REPROBE		0x80000000
272
273	unsigned cpu_features;
274#define MMX 0x1
275#define SSE 0x2
276#define SSE2 0x4
277#define SSE3 0x8
278#define SSSE3 0x10
279#define SSE4_1 0x20
280#define SSE4_2 0x40
281#define AVX 0x80
282#define AVX2 0x100
283
284	bool ignore_copy_area : 1;
285
286	unsigned watch_shm_flush;
287	unsigned watch_dri_flush;
288	unsigned damage_event;
289	bool needs_shm_flush;
290	bool needs_dri_flush;
291
292	struct timeval timer_tv;
293	uint32_t timer_expire[NUM_TIMERS];
294	uint16_t timer_active;
295
296	int vblank_interval;
297
298	struct list flush_pixmaps;
299	struct list active_pixmaps;
300
301	PixmapPtr front;
302	PixmapPtr freed_pixmap;
303
304	struct sna_mode {
305		DamagePtr shadow_damage;
306		struct kgem_bo *shadow;
307		unsigned front_active;
308		unsigned shadow_active;
309		unsigned rr_active;
310		unsigned flip_active;
311		unsigned hidden;
312		bool shadow_enabled;
313		bool dirty;
314
315		struct drm_event_vblank *shadow_events;
316		int shadow_nevent;
317		int shadow_size;
318
319		int max_crtc_width, max_crtc_height;
320		RegionRec shadow_region;
321		RegionRec shadow_cancel;
322		struct list shadow_crtc;
323		bool shadow_dirty;
324
325		unsigned num_real_crtc;
326		unsigned num_real_output;
327		unsigned num_real_encoder;
328		unsigned num_fake;
329		unsigned serial;
330
331		uint32_t *encoders;
332
333#if HAVE_UDEV
334		struct udev_monitor *backlight_monitor;
335		pointer backlight_handler;
336#endif
337
338		Bool (*rrGetInfo)(ScreenPtr, Rotation *);
339	} mode;
340
341	struct {
342		struct sna_cursor *cursors;
343		xf86CursorInfoPtr info;
344		CursorPtr ref;
345
346		unsigned serial;
347		uint32_t fg, bg;
348		int size;
349
350		bool disable;
351		bool active;
352		int last_x;
353		int last_y;
354
355		unsigned max_size;
356		bool use_gtt;
357
358		int num_stash;
359		struct sna_cursor *stash;
360		void *scratch;
361	} cursor;
362
363	struct sna_dri2 {
364		bool available : 1;
365		bool enable : 1;
366		bool open : 1;
367
368#if HAVE_DRI2
369		void *flip_pending;
370		unsigned client_count;
371#endif
372	} dri2;
373
374	struct sna_dri3 {
375		bool available :1;
376		bool override : 1;
377		bool enable : 1;
378		bool open :1;
379
380#if HAVE_DRI3
381		SyncScreenCreateFenceFunc create_fence;
382		struct list pixmaps;
383#endif
384	} dri3;
385
386	struct sna_present {
387		bool available;
388		bool open;
389#if HAVE_PRESENT
390		struct list vblank_queue;
391		uint64_t unflip;
392		void *freed_info;
393#endif
394	} present;
395
396	struct sna_xv {
397		XvAdaptorPtr adaptors;
398		int num_adaptors;
399	} xv;
400
401	EntityInfoPtr pEnt;
402	const struct intel_device_info *info;
403
404#if !HAVE_NOTIFY_FD
405	ScreenBlockHandlerProcPtr BlockHandler;
406	ScreenWakeupHandlerProcPtr WakeupHandler;
407#endif
408	CloseScreenProcPtr CloseScreen;
409
410	PicturePtr clear;
411	struct {
412		uint32_t fill_bo;
413		uint32_t fill_pixel;
414		uint32_t fill_alu;
415	} blt_state;
416	union {
417		unsigned gt;
418		struct gen2_render_state gen2;
419		struct gen3_render_state gen3;
420		struct gen4_render_state gen4;
421		struct gen5_render_state gen5;
422		struct gen6_render_state gen6;
423		struct gen7_render_state gen7;
424		struct gen8_render_state gen8;
425		struct gen9_render_state gen9;
426	} render_state;
427
428	/* Broken-out options. */
429	OptionInfoPtr Options;
430
431	/* Driver phase/state information */
432	bool suspended;
433
434#if HAVE_UDEV
435	struct udev_monitor *uevent_monitor;
436	pointer uevent_handler;
437#endif
438
439	struct {
440		int fd;
441		uint8_t offset;
442		uint8_t remain;
443		char event[256];
444	} acpi;
445
446	struct sna_render render;
447
448#if DEBUG_MEMORY
449	struct {
450		int pixmap_allocs;
451		int pixmap_cached;
452		int cpu_bo_allocs;
453		size_t shadow_pixels_bytes;
454		size_t cpu_bo_bytes;
455	} debug_memory;
456#endif
457};
458
459bool sna_mode_pre_init(ScrnInfoPtr scrn, struct sna *sna);
460bool sna_mode_fake_init(struct sna *sna, int num_fake);
461bool sna_mode_wants_tear_free(struct sna *sna);
462void sna_mode_adjust_frame(struct sna *sna, int x, int y);
463extern void sna_mode_discover(struct sna *sna, bool tell);
464extern void sna_mode_check(struct sna *sna);
465extern bool sna_mode_disable(struct sna *sna);
466extern void sna_mode_enable(struct sna *sna);
467extern void sna_mode_reset(struct sna *sna);
468extern int sna_mode_wakeup(struct sna *sna);
469extern void sna_mode_redisplay(struct sna *sna);
470extern void sna_shadow_set_crtc(struct sna *sna, xf86CrtcPtr crtc, struct kgem_bo *bo);
471extern void sna_shadow_steal_crtcs(struct sna *sna, struct list *list);
472extern void sna_shadow_unsteal_crtcs(struct sna *sna, struct list *list);
473extern void sna_shadow_unset_crtc(struct sna *sna, xf86CrtcPtr crtc);
474extern bool sna_pixmap_discard_shadow_damage(struct sna_pixmap *priv,
475					     const RegionRec *region);
476extern void sna_mode_set_primary(struct sna *sna);
477extern bool sna_mode_find_hotplug_connector(struct sna *sna, unsigned id);
478extern void sna_mode_close(struct sna *sna);
479extern void sna_mode_fini(struct sna *sna);
480
481extern void sna_crtc_config_notify(ScreenPtr screen);
482
483extern bool sna_cursors_init(ScreenPtr screen, struct sna *sna);
484
485extern CARD32 sna_mode_coldplug(OsTimerPtr timer, CARD32 now, void *data);
486#define COLDPLUG_DELAY_MS 2000
487
488typedef void (*sna_flip_handler_t)(struct drm_event_vblank *e,
489				   void *data);
490
491extern bool sna_needs_page_flip(struct sna *sna, struct kgem_bo *bo);
492extern int sna_page_flip(struct sna *sna,
493			 struct kgem_bo *bo,
494			 sna_flip_handler_t handler,
495			 void *data);
496
497pure static inline struct sna *
498to_sna(ScrnInfoPtr scrn)
499{
500	struct sna *sna = scrn->driverPrivate;
501	assert(sna->scrn == scrn);
502	return sna;
503}
504
505pure static inline struct sna *
506to_sna_from_screen(ScreenPtr screen)
507{
508	return to_sna(xf86ScreenToScrn(screen));
509}
510
511pure static inline ScreenPtr to_screen_from_sna(struct sna *sna)
512{
513	ScreenPtr screen = xf86ScrnToScreen(sna->scrn);
514	assert(!screen || sna == to_sna_from_screen(screen));
515	return screen;
516}
517
518pure static inline struct sna *
519to_sna_from_pixmap(PixmapPtr pixmap)
520{
521	return ((void **)__get_private(pixmap, sna_pixmap_key))[0];
522}
523
524pure static inline struct sna *
525to_sna_from_drawable(DrawablePtr drawable)
526{
527	return to_sna_from_screen(drawable->pScreen);
528}
529
530static inline struct sna *
531to_sna_from_kgem(struct kgem *kgem)
532{
533	return container_of(kgem, struct sna, kgem);
534}
535
536#ifndef ARRAY_SIZE
537#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
538#endif
539
540#ifndef ALIGN
541#define ALIGN(i,m)	(((i) + (m) - 1) & ~((m) - 1))
542#endif
543
544#ifndef MIN
545#define MIN(a,b)	((a) <= (b) ? (a) : (b))
546#endif
547
548#ifndef MAX
549#define MAX(a,b)	((a) >= (b) ? (a) : (b))
550#endif
551
552extern xf86CrtcPtr sna_covering_crtc(struct sna *sna,
553				     const BoxRec *box,
554				     xf86CrtcPtr desired);
555extern xf86CrtcPtr sna_primary_crtc(struct sna *sna);
556
557extern bool sna_wait_for_scanline(struct sna *sna, PixmapPtr pixmap,
558				  xf86CrtcPtr crtc, const BoxRec *clip);
559
560const struct ust_msc {
561	uint64_t msc;
562	int tv_sec;
563	int tv_usec;
564} *sna_crtc_last_swap(xf86CrtcPtr crtc);
565
566uint64_t sna_crtc_record_swap(xf86CrtcPtr crtc,
567			      int tv_sec, int tv_usec, unsigned seq);
568
569static inline uint64_t sna_crtc_record_vblank(xf86CrtcPtr crtc,
570					      const union drm_wait_vblank *vbl)
571{
572	return sna_crtc_record_swap(crtc,
573				    vbl->reply.tval_sec,
574				    vbl->reply.tval_usec,
575				    vbl->reply.sequence);
576}
577
578static inline uint64_t sna_crtc_record_event(xf86CrtcPtr crtc,
579					     struct drm_event_vblank *event)
580{
581	return sna_crtc_record_swap(crtc,
582				    event->tv_sec,
583				    event->tv_usec,
584				    event->sequence);
585}
586
587static inline uint64_t ust64(int tv_sec, int tv_usec)
588{
589	return (uint64_t)tv_sec * 1000000 + tv_usec;
590}
591
592static inline uint64_t swap_ust(const struct ust_msc *swap)
593{
594	return ust64(swap->tv_sec, swap->tv_usec);
595}
596
597#if HAVE_DRI2
598bool sna_dri2_open(struct sna *sna, ScreenPtr pScreen);
599void sna_dri2_page_flip_handler(struct sna *sna, struct drm_event_vblank *event);
600void sna_dri2_vblank_handler(struct drm_event_vblank *event);
601void sna_dri2_pixmap_update_bo(struct sna *sna, PixmapPtr pixmap, struct kgem_bo *bo);
602void sna_dri2_decouple_window(WindowPtr win);
603void sna_dri2_destroy_window(WindowPtr win);
604void sna_dri2_close(struct sna *sna, ScreenPtr pScreen);
605#else
606static inline bool sna_dri2_open(struct sna *sna, ScreenPtr pScreen) { return false; }
607static inline void sna_dri2_page_flip_handler(struct sna *sna, struct drm_event_vblank *event) { }
608static inline void sna_dri2_vblank_handler(struct drm_event_vblank *event) { }
609static inline void sna_dri2_pixmap_update_bo(struct sna *sna, PixmapPtr pixmap, struct kgem_bo *bo) { }
610static inline void sna_dri2_decouple_window(WindowPtr win) { }
611static inline void sna_dri2_destroy_window(WindowPtr win) { }
612static inline void sna_dri2_close(struct sna *sna, ScreenPtr pScreen) { }
613#endif
614
615#if HAVE_DRI3
616bool sna_dri3_open(struct sna *sna, ScreenPtr pScreen);
617void sna_dri3_close(struct sna *sna, ScreenPtr pScreen);
618#else
619static inline bool sna_dri3_open(struct sna *sna, ScreenPtr pScreen) { return false; }
620static inline void sna_dri3_close(struct sna *sna, ScreenPtr pScreen) { }
621#endif
622
623#if HAVE_PRESENT
624bool sna_present_open(struct sna *sna, ScreenPtr pScreen);
625void sna_present_update(struct sna *sna);
626void sna_present_close(struct sna *sna, ScreenPtr pScreen);
627void sna_present_vblank_handler(struct drm_event_vblank *event);
628void sna_present_cancel_flip(struct sna *sna);
629#else
630static inline bool sna_present_open(struct sna *sna, ScreenPtr pScreen) { return false; }
631static inline void sna_present_update(struct sna *sna) { }
632static inline void sna_present_close(struct sna *sna, ScreenPtr pScreen) { }
633static inline void sna_present_vblank_handler(struct drm_event_vblank *event) { }
634static inline void sna_present_cancel_flip(struct sna *sna) { }
635#endif
636
637extern unsigned sna_crtc_count_sprites(xf86CrtcPtr crtc);
638extern bool sna_crtc_set_sprite_rotation(xf86CrtcPtr crtc, unsigned idx, uint32_t rotation);
639extern void sna_crtc_set_sprite_colorspace(xf86CrtcPtr crtc, unsigned idx, int colorspace);
640extern uint32_t sna_crtc_to_sprite(xf86CrtcPtr crtc, unsigned idx);
641extern bool sna_crtc_is_transformed(xf86CrtcPtr crtc);
642bool sna_has_sprite_format(struct sna *sna, uint32_t format);
643
644#define CRTC_VBLANK 0x7
645#define CRTC_ON 0x80000000
646
647uint32_t sna_crtc_id(xf86CrtcPtr crtc);
648
649struct sna_crtc_public {
650	unsigned long flags;
651	struct list vblank_queue;
652};
653
654static inline unsigned long *sna_crtc_flags(xf86CrtcPtr crtc)
655{
656	struct sna_crtc_public *pub = crtc->driver_private;
657	assert(pub);
658	return &pub->flags;
659}
660
661static inline struct list *sna_crtc_vblank_queue(xf86CrtcPtr crtc)
662{
663	struct sna_crtc_public *pub = crtc->driver_private;
664	assert(pub);
665	return &pub->vblank_queue;
666}
667
668static inline unsigned sna_crtc_pipe(xf86CrtcPtr crtc)
669{
670	return *sna_crtc_flags(crtc) >> 8 & 0xff;
671}
672
673static inline bool sna_crtc_is_on(xf86CrtcPtr crtc)
674{
675	return *sna_crtc_flags(crtc) & CRTC_ON;
676}
677
678static inline void sna_crtc_set_vblank(xf86CrtcPtr crtc)
679{
680	DBG(("%s: current vblank count: %d\n", __FUNCTION__, *sna_crtc_flags(crtc) & CRTC_VBLANK));
681	assert((*sna_crtc_flags(crtc) & CRTC_VBLANK) < CRTC_VBLANK);
682	++*sna_crtc_flags(crtc);
683}
684
685static inline void sna_crtc_clear_vblank(xf86CrtcPtr crtc)
686{
687	DBG(("%s: current vblank count: %d\n", __FUNCTION__, *sna_crtc_flags(crtc) & CRTC_VBLANK));
688	assert(*sna_crtc_flags(crtc) & CRTC_VBLANK);
689	--*sna_crtc_flags(crtc);
690}
691
692static inline bool sna_crtc_has_vblank(xf86CrtcPtr crtc)
693{
694	return *sna_crtc_flags(crtc) & CRTC_VBLANK;
695}
696
697CARD32 sna_format_for_depth(int depth);
698CARD32 sna_render_format_for_depth(int depth);
699
700void sna_debug_flush(struct sna *sna);
701
702static inline bool
703get_window_deltas(PixmapPtr pixmap, int16_t *x, int16_t *y)
704{
705#ifdef COMPOSITE
706	*x = -pixmap->screen_x;
707	*y = -pixmap->screen_y;
708	return pixmap->screen_x | pixmap->screen_y;
709#else
710	*x = *y = 0;
711	return false;
712#endif
713}
714
715static inline bool
716get_drawable_deltas(DrawablePtr drawable, PixmapPtr pixmap, int16_t *x, int16_t *y)
717{
718#ifdef COMPOSITE
719	if (drawable->type == DRAWABLE_WINDOW)
720		return get_window_deltas(pixmap, x, y);
721#endif
722	*x = *y = 0;
723	return false;
724}
725
726static inline int
727get_drawable_dx(DrawablePtr drawable)
728{
729#ifdef COMPOSITE
730	if (drawable->type == DRAWABLE_WINDOW)
731		return -get_drawable_pixmap(drawable)->screen_x;
732#endif
733	return 0;
734}
735
736static inline int
737get_drawable_dy(DrawablePtr drawable)
738{
739#ifdef COMPOSITE
740	if (drawable->type == DRAWABLE_WINDOW)
741		return -get_drawable_pixmap(drawable)->screen_y;
742#endif
743	return 0;
744}
745
746struct sna_pixmap *sna_pixmap_attach_to_bo(PixmapPtr pixmap, struct kgem_bo *bo);
747static inline bool sna_pixmap_is_scanout(struct sna *sna, PixmapPtr pixmap)
748{
749	return (pixmap == sna->front &&
750		!sna->mode.shadow_active &&
751		(sna->flags & SNA_NO_WAIT) == 0);
752}
753
754static inline int sna_max_tile_copy_size(struct sna *sna, struct kgem_bo *src, struct kgem_bo *dst)
755{
756	int min_object;
757	int max_size;
758
759	max_size = sna->kgem.aperture_high * PAGE_SIZE;
760	max_size -= MAX(kgem_bo_size(src), kgem_bo_size(dst));
761	if (max_size <= 0) {
762		DBG(("%s: tiles cannot fit into aperture\n", __FUNCTION__));
763		return 0;
764	}
765
766	if (max_size > sna->kgem.max_copy_tile_size)
767		max_size = sna->kgem.max_copy_tile_size;
768
769	min_object = MIN(kgem_bo_size(src), kgem_bo_size(dst)) / 2;
770	if (max_size > min_object)
771		max_size = min_object;
772	if (max_size <= 4096)
773		max_size = 0;
774
775	DBG(("%s: using max tile size of %d\n", __FUNCTION__, max_size));
776	return max_size;
777}
778
779PixmapPtr sna_pixmap_create_upload(ScreenPtr screen,
780				   int width, int height, int depth,
781				   unsigned flags);
782PixmapPtr sna_pixmap_create_unattached(ScreenPtr screen,
783				       int width, int height, int depth);
784void sna_pixmap_destroy(PixmapPtr pixmap);
785
786#define assert_pixmap_map(pixmap, priv)  do { \
787	assert(priv->mapped != MAPPED_NONE || pixmap->devPrivate.ptr == PTR(priv->ptr)); \
788	assert(priv->mapped != MAPPED_CPU || pixmap->devPrivate.ptr == MAP(priv->gpu_bo->map__cpu)); \
789	assert(priv->mapped != MAPPED_GTT || pixmap->devPrivate.ptr == priv->gpu_bo->map__gtt || pixmap->devPrivate.ptr == priv->gpu_bo->map__wc); \
790} while (0)
791
792static inline void sna_pixmap_unmap(PixmapPtr pixmap, struct sna_pixmap *priv)
793{
794	if (priv->mapped == MAPPED_NONE) {
795		assert(pixmap->devPrivate.ptr == PTR(priv->ptr));
796		return;
797	}
798
799	DBG(("%s: pixmap=%ld dropping %s mapping\n",
800	     __FUNCTION__, pixmap->drawable.serialNumber,
801	     priv->mapped == MAPPED_CPU ? "cpu" : "gtt"));
802
803	assert_pixmap_map(pixmap, priv);
804
805	pixmap->devPrivate.ptr = PTR(priv->ptr);
806	pixmap->devKind = priv->stride;
807
808	priv->mapped = MAPPED_NONE;
809}
810
811bool
812sna_pixmap_undo_cow(struct sna *sna, struct sna_pixmap *priv, unsigned flags);
813
814#define MOVE_WRITE 0x1
815#define MOVE_READ 0x2
816#define MOVE_INPLACE_HINT 0x4
817#define MOVE_ASYNC_HINT 0x8
818#define MOVE_SOURCE_HINT 0x10
819#define MOVE_WHOLE_HINT 0x20
820#define __MOVE_FORCE 0x40
821#define __MOVE_DRI 0x80
822#define __MOVE_SCANOUT 0x100
823#define __MOVE_TILED 0x200
824#define __MOVE_PRIME 0x400
825
826struct sna_pixmap *
827sna_pixmap_move_area_to_gpu(PixmapPtr pixmap, const BoxRec *box, unsigned int flags);
828
829struct sna_pixmap *sna_pixmap_move_to_gpu(PixmapPtr pixmap, unsigned flags);
830static inline struct sna_pixmap *
831sna_pixmap_force_to_gpu(PixmapPtr pixmap, unsigned flags)
832{
833	/* Unlike move-to-gpu, we ignore wedged and always create the GPU bo */
834	DBG(("%s(pixmap=%ld, flags=%x)\n", __FUNCTION__, pixmap->drawable.serialNumber, flags));
835	return sna_pixmap_move_to_gpu(pixmap, flags | __MOVE_FORCE);
836}
837bool must_check _sna_pixmap_move_to_cpu(PixmapPtr pixmap, unsigned flags);
838static inline bool must_check sna_pixmap_move_to_cpu(PixmapPtr pixmap, unsigned flags)
839{
840	if (flags == MOVE_READ) {
841		struct sna_pixmap *priv = sna_pixmap(pixmap);
842		if (priv == NULL)
843			return true;
844	}
845
846	return _sna_pixmap_move_to_cpu(pixmap, flags);
847}
848bool must_check sna_drawable_move_region_to_cpu(DrawablePtr drawable,
849						RegionPtr region,
850						unsigned flags);
851
852bool must_check sna_drawable_move_to_cpu(DrawablePtr drawable, unsigned flags);
853
854static inline bool must_check
855sna_drawable_move_to_gpu(DrawablePtr drawable, unsigned flags)
856{
857	return sna_pixmap_move_to_gpu(get_drawable_pixmap(drawable), flags) != NULL;
858}
859
860void sna_add_flush_pixmap(struct sna *sna,
861			  struct sna_pixmap *priv,
862			  struct kgem_bo *bo);
863
864struct kgem_bo *sna_pixmap_change_tiling(PixmapPtr pixmap, uint32_t tiling);
865
866#define PREFER_GPU	0x1
867#define FORCE_GPU	0x2
868#define RENDER_GPU	0x4
869#define IGNORE_DAMAGE	0x8
870#define REPLACES	0x10
871struct kgem_bo *
872sna_drawable_use_bo(DrawablePtr drawable, unsigned flags, const BoxRec *box,
873		    struct sna_damage ***damage);
874
875inline static int16_t bound(int16_t a, uint16_t b)
876{
877	int v = (int)a + (int)b;
878	if (v > MAXSHORT)
879		return MAXSHORT;
880	return v;
881}
882
883inline static int16_t clamp(int16_t a, int16_t b)
884{
885	int v = (int)a + (int)b;
886	if (v > MAXSHORT)
887		return MAXSHORT;
888	if (v < MINSHORT)
889		return MINSHORT;
890	return v;
891}
892
893static inline bool box_empty(const BoxRec *box)
894{
895	return box->x2 <= box->x1 || box->y2 <= box->y1;
896}
897
898static inline bool
899box_covers_pixmap(PixmapPtr pixmap, const BoxRec *box)
900{
901	int w = box->x2 - box->x1;
902	int h = box->y2 - box->y1;
903	return pixmap->drawable.width <= w && pixmap->drawable.height <= h;
904}
905
906static inline bool
907box_inplace(PixmapPtr pixmap, const BoxRec *box)
908{
909	struct sna *sna = to_sna_from_pixmap(pixmap);
910	return ((int)(box->x2 - box->x1) * (int)(box->y2 - box->y1) * pixmap->drawable.bitsPerPixel >> 12) >= sna->kgem.half_cpu_cache_pages;
911}
912
913static inline bool
914whole_pixmap_inplace(PixmapPtr pixmap)
915{
916	struct sna *sna = to_sna_from_pixmap(pixmap);
917	return ((int)pixmap->drawable.width * (int)pixmap->drawable.height * pixmap->drawable.bitsPerPixel >> 12) >= sna->kgem.half_cpu_cache_pages;
918}
919
920static inline bool
921region_subsumes_drawable(RegionPtr region, DrawablePtr drawable)
922{
923	const BoxRec *extents;
924
925	if (region->data)
926		return false;
927
928	extents = RegionExtents(region);
929	return  extents->x1 <= 0 && extents->y1 <= 0 &&
930		extents->x2 >= drawable->width &&
931		extents->y2 >= drawable->height;
932}
933
934static inline bool
935region_subsumes_pixmap(const RegionRec *region, PixmapPtr pixmap)
936{
937	if (region->data)
938		return false;
939
940	return (region->extents.x2 - region->extents.x1 >= pixmap->drawable.width &&
941		region->extents.y2 - region->extents.y1 >= pixmap->drawable.height);
942}
943
944static inline bool
945region_subsumes_damage(const RegionRec *region, struct sna_damage *damage)
946{
947	const BoxRec *re, *de;
948
949	DBG(("%s?\n", __FUNCTION__));
950	assert(damage);
951
952	re = &region->extents;
953	de = &DAMAGE_PTR(damage)->extents;
954	DBG(("%s: region (%d, %d), (%d, %d), damage (%d, %d), (%d, %d)\n",
955	     __FUNCTION__,
956	     re->x1, re->y1, re->x2, re->y2,
957	     de->x1, de->y1, de->x2, de->y2));
958
959	if (re->x2 < de->x2 || re->x1 > de->x1 ||
960	    re->y2 < de->y2 || re->y1 > de->y1) {
961		DBG(("%s: not contained\n", __FUNCTION__));
962		return false;
963	}
964
965	if (region->data == NULL) {
966		DBG(("%s: singular region contains damage\n", __FUNCTION__));
967		return true;
968	}
969
970	return pixman_region_contains_rectangle((RegionPtr)region,
971						(BoxPtr)de) == PIXMAN_REGION_IN;
972}
973
974static inline bool
975sna_drawable_is_clear(DrawablePtr d)
976{
977	struct sna_pixmap *priv = sna_pixmap(get_drawable_pixmap(d));
978	return priv && priv->clear && priv->clear_color == 0;
979}
980
981static inline struct kgem_bo *__sna_pixmap_get_bo(PixmapPtr pixmap)
982{
983	return sna_pixmap(pixmap)->gpu_bo;
984}
985
986static inline struct kgem_bo *__sna_drawable_peek_bo(DrawablePtr d)
987{
988	struct sna_pixmap *priv = sna_pixmap(get_drawable_pixmap(d));
989	return priv ? priv->gpu_bo : NULL;
990}
991
992static inline struct kgem_bo *sna_pixmap_pin(PixmapPtr pixmap, unsigned flags)
993{
994	struct sna_pixmap *priv;
995
996	priv = sna_pixmap_force_to_gpu(pixmap, MOVE_READ);
997	if (!priv)
998		return NULL;
999
1000	priv->pinned |= flags;
1001	return priv->gpu_bo;
1002}
1003
1004
1005static inline bool
1006_sna_transform_point(const PictTransform *transform,
1007		     int64_t x, int64_t y, int64_t result[3])
1008{
1009	int j;
1010
1011	for (j = 0; j < 3; j++)
1012		result[j] = (transform->matrix[j][0] * x +
1013			     transform->matrix[j][1] * y +
1014			     transform->matrix[j][2]);
1015
1016	return result[2] != 0;
1017}
1018
1019static inline void
1020_sna_get_transformed_coordinates(int x, int y,
1021				 const PictTransform *transform,
1022				 float *x_out, float *y_out)
1023{
1024
1025	int64_t result[3];
1026
1027	_sna_transform_point(transform, x, y, result);
1028	*x_out = result[0] / (double)result[2];
1029	*y_out = result[1] / (double)result[2];
1030}
1031
1032static inline void
1033_sna_get_transformed_scaled(int x, int y,
1034			    const PictTransform *transform, const float *sf,
1035			    float *x_out, float *y_out)
1036{
1037	*x_out = sf[0] * (transform->matrix[0][0] * x +
1038			  transform->matrix[0][1] * y +
1039			  transform->matrix[0][2]);
1040
1041	*y_out = sf[1] * (transform->matrix[1][0] * x +
1042			  transform->matrix[1][1] * y +
1043			  transform->matrix[1][2]);
1044}
1045
1046void
1047sna_get_transformed_coordinates(int x, int y,
1048				const PictTransform *transform,
1049				float *x_out, float *y_out);
1050
1051void
1052sna_get_transformed_coordinates_3d(int x, int y,
1053				   const PictTransform *transform,
1054				   float *x_out, float *y_out, float *z_out);
1055
1056bool sna_transform_is_affine(const PictTransform *t);
1057bool sna_transform_is_translation(const PictTransform *t,
1058				  pixman_fixed_t *tx, pixman_fixed_t *ty);
1059bool sna_transform_is_integer_translation(const PictTransform *t,
1060					  int16_t *tx, int16_t *ty);
1061bool sna_transform_is_imprecise_integer_translation(const PictTransform *t,
1062					       int filter, bool precise,
1063					       int16_t *tx, int16_t *ty);
1064static inline bool
1065sna_affine_transform_is_rotation(const PictTransform *t)
1066{
1067	assert(sna_transform_is_affine(t));
1068	return t->matrix[0][1] | t->matrix[1][0];
1069}
1070
1071static inline bool
1072sna_transform_equal(const PictTransform *a, const PictTransform *b)
1073{
1074	if (a == b)
1075		return true;
1076
1077	if (a == NULL || b == NULL)
1078		return false;
1079
1080	return memcmp(a, b, sizeof(*a)) == 0;
1081}
1082
1083static inline bool
1084sna_picture_alphamap_equal(PicturePtr a, PicturePtr b)
1085{
1086	if (a->alphaMap != b->alphaMap)
1087		return false;
1088
1089	if (a->alphaMap)
1090		return false;
1091
1092	return (a->alphaOrigin.x == b->alphaOrigin.x &&
1093		a->alphaOrigin.y == b->alphaOrigin.y);
1094}
1095
1096static inline bool wedged(struct sna *sna)
1097{
1098	return unlikely(sna->kgem.wedged);
1099}
1100
1101static inline bool can_render(struct sna *sna)
1102{
1103	return likely(!sna->kgem.wedged && sna->render.prefer_gpu & PREFER_GPU_RENDER);
1104}
1105
1106static inline uint32_t pixmap_size(PixmapPtr pixmap)
1107{
1108	return (pixmap->drawable.height - 1) * pixmap->devKind +
1109		pixmap->drawable.width * pixmap->drawable.bitsPerPixel/8;
1110}
1111
1112bool sna_accel_init(ScreenPtr sreen, struct sna *sna);
1113void sna_accel_create(struct sna *sna);
1114void sna_accel_block(struct sna *sna, struct timeval **tv);
1115void sna_accel_flush(struct sna *sna);
1116void sna_accel_enter(struct sna *sna);
1117void sna_accel_leave(struct sna *sna);
1118void sna_accel_close(struct sna *sna);
1119void sna_accel_free(struct sna *sna);
1120
1121void sna_watch_flush(struct sna *sna, int enable);
1122void sna_copy_fbcon(struct sna *sna);
1123
1124bool sna_composite_create(struct sna *sna);
1125void sna_composite_close(struct sna *sna);
1126
1127void sna_composite(CARD8 op,
1128		   PicturePtr src,
1129		   PicturePtr mask,
1130		   PicturePtr dst,
1131		   INT16 src_x,  INT16 src_y,
1132		   INT16 mask_x, INT16 mask_y,
1133		   INT16 dst_x,  INT16 dst_y,
1134		   CARD16 width, CARD16 height);
1135void sna_composite_fb(CARD8 op,
1136		      PicturePtr src,
1137		      PicturePtr mask,
1138		      PicturePtr dst,
1139		      RegionPtr region,
1140		      INT16 src_x,  INT16 src_y,
1141		      INT16 mask_x, INT16 mask_y,
1142		      INT16 dst_x,  INT16 dst_y,
1143		      CARD16 width, CARD16 height);
1144void sna_composite_rectangles(CARD8		 op,
1145			      PicturePtr		 dst,
1146			      xRenderColor	*color,
1147			      int			 num_rects,
1148			      xRectangle		*rects);
1149void sna_composite_trapezoids(CARD8 op,
1150			      PicturePtr src,
1151			      PicturePtr dst,
1152			      PictFormatPtr maskFormat,
1153			      INT16 xSrc, INT16 ySrc,
1154			      int ntrap, xTrapezoid *traps);
1155void sna_add_traps(PicturePtr picture, INT16 x, INT16 y, int n, xTrap *t);
1156
1157void sna_composite_triangles(CARD8 op,
1158			     PicturePtr src,
1159			     PicturePtr dst,
1160			     PictFormatPtr maskFormat,
1161			     INT16 xSrc, INT16 ySrc,
1162			     int ntri, xTriangle *tri);
1163
1164void sna_composite_tristrip(CARD8 op,
1165			    PicturePtr src,
1166			    PicturePtr dst,
1167			    PictFormatPtr maskFormat,
1168			    INT16 xSrc, INT16 ySrc,
1169			    int npoints, xPointFixed *points);
1170
1171void sna_composite_trifan(CARD8 op,
1172			  PicturePtr src,
1173			  PicturePtr dst,
1174			  PictFormatPtr maskFormat,
1175			  INT16 xSrc, INT16 ySrc,
1176			  int npoints, xPointFixed *points);
1177
1178bool sna_gradients_create(struct sna *sna);
1179void sna_gradients_close(struct sna *sna);
1180
1181bool sna_glyphs_create(struct sna *sna);
1182void sna_glyphs(CARD8 op,
1183		PicturePtr src,
1184		PicturePtr dst,
1185		PictFormatPtr mask,
1186		INT16 xSrc, INT16 ySrc,
1187		int nlist,
1188		GlyphListPtr list,
1189		GlyphPtr *glyphs);
1190void sna_glyphs__shared(CARD8 op,
1191			PicturePtr src,
1192			PicturePtr dst,
1193			PictFormatPtr mask,
1194			INT16 src_x, INT16 src_y,
1195			int nlist, GlyphListPtr list, GlyphPtr *glyphs);
1196void sna_glyph_unrealize(ScreenPtr screen, GlyphPtr glyph);
1197void sna_glyphs_close(struct sna *sna);
1198
1199void sna_read_boxes(struct sna *sna, PixmapPtr dst, struct kgem_bo *src_bo,
1200		    const BoxRec *box, int n);
1201bool sna_write_boxes(struct sna *sna, PixmapPtr dst,
1202		     struct kgem_bo *dst_bo, int16_t dst_dx, int16_t dst_dy,
1203		     const void *src, int stride, int16_t src_dx, int16_t src_dy,
1204		     const BoxRec *box, int n);
1205bool sna_write_boxes__xor(struct sna *sna, PixmapPtr dst,
1206			  struct kgem_bo *dst_bo, int16_t dst_dx, int16_t dst_dy,
1207			  const void *src, int stride, int16_t src_dx, int16_t src_dy,
1208			  const BoxRec *box, int nbox,
1209			  uint32_t and, uint32_t or);
1210
1211bool sna_replace(struct sna *sna,
1212		 PixmapPtr pixmap,
1213		 const void *src, int stride);
1214bool sna_replace__xor(struct sna *sna,
1215		      PixmapPtr pixmap,
1216		      const void *src, int stride,
1217		      uint32_t and, uint32_t or);
1218
1219bool
1220sna_compute_composite_extents(BoxPtr extents,
1221			      PicturePtr src, PicturePtr mask, PicturePtr dst,
1222			      INT16 src_x,  INT16 src_y,
1223			      INT16 mask_x, INT16 mask_y,
1224			      INT16 dst_x,  INT16 dst_y,
1225			      CARD16 width, CARD16 height);
1226bool
1227sna_compute_composite_region(RegionPtr region,
1228			     PicturePtr src, PicturePtr mask, PicturePtr dst,
1229			     INT16 src_x,  INT16 src_y,
1230			     INT16 mask_x, INT16 mask_y,
1231			     INT16 dst_x,  INT16 dst_y,
1232			     CARD16 width, CARD16 height);
1233
1234void
1235memcpy_blt(const void *src, void *dst, int bpp,
1236	   int32_t src_stride, int32_t dst_stride,
1237	   int16_t src_x, int16_t src_y,
1238	   int16_t dst_x, int16_t dst_y,
1239	   uint16_t width, uint16_t height);
1240
1241void
1242affine_blt(const void *src, void *dst, int bpp,
1243	   int16_t src_x, int16_t src_y,
1244	   int16_t src_width, int16_t src_height,
1245	   int32_t src_stride,
1246	   int16_t dst_x, int16_t dst_y,
1247	   uint16_t dst_width, uint16_t dst_height,
1248	   int32_t dst_stride,
1249	   const struct pixman_f_transform *t);
1250
1251void
1252memmove_box(const void *src, void *dst,
1253	    int bpp, int32_t stride,
1254	    const BoxRec *box,
1255	    int dx, int dy);
1256
1257void
1258memcpy_xor(const void *src, void *dst, int bpp,
1259	   int32_t src_stride, int32_t dst_stride,
1260	   int16_t src_x, int16_t src_y,
1261	   int16_t dst_x, int16_t dst_y,
1262	   uint16_t width, uint16_t height,
1263	   uint32_t and, uint32_t or);
1264
1265#define SNA_CREATE_FB 0x10
1266#define SNA_CREATE_SCRATCH 0x11
1267
1268inline static bool is_power_of_two(unsigned x)
1269{
1270	return (x & (x-1)) == 0;
1271}
1272
1273inline static bool is_clipped(const RegionRec *r,
1274			      const DrawableRec *d)
1275{
1276	DBG(("%s: region[%d]x(%d, %d),(%d, %d) against drawable %dx%d\n",
1277	     __FUNCTION__,
1278	     region_num_rects(r),
1279	     r->extents.x1, r->extents.y1,
1280	     r->extents.x2, r->extents.y2,
1281	     d->width, d->height));
1282	return (r->data ||
1283		r->extents.x2 - r->extents.x1 != d->width ||
1284		r->extents.y2 - r->extents.y1 != d->height);
1285}
1286
1287inline static bool
1288box_intersect(BoxPtr a, const BoxRec *b)
1289{
1290	if (a->x1 < b->x1)
1291		a->x1 = b->x1;
1292	if (a->x2 > b->x2)
1293		a->x2 = b->x2;
1294	if (a->x1 >= a->x2)
1295		return false;
1296
1297	if (a->y1 < b->y1)
1298		a->y1 = b->y1;
1299	if (a->y2 > b->y2)
1300		a->y2 = b->y2;
1301	if (a->y1 >= a->y2)
1302		return false;
1303
1304	return true;
1305}
1306
1307const BoxRec *
1308__find_clip_box_for_y(const BoxRec *begin, const BoxRec *end, int16_t y);
1309inline static const BoxRec *
1310find_clip_box_for_y(const BoxRec *begin, const BoxRec *end, int16_t y)
1311{
1312	/* Special case for incremental trapezoid clipping */
1313	if (begin == end)
1314		return end;
1315
1316	/* Quick test if scanline is within range of clip boxes */
1317	if (begin->y2 > y) {
1318		assert(end == begin + 1 ||
1319		       __find_clip_box_for_y(begin, end, y) == begin);
1320		return begin;
1321	}
1322	if (y >= end[-1].y2) {
1323		assert(end == begin + 1 ||
1324		       __find_clip_box_for_y(begin, end, y) == end);
1325		return end;
1326	}
1327
1328	/* Otherwise bisect to find the first box crossing y */
1329	return __find_clip_box_for_y(begin, end, y);
1330}
1331
1332unsigned sna_cpu_detect(void);
1333char *sna_cpu_features_to_string(unsigned features, char *line);
1334
1335/* sna_acpi.c */
1336int sna_acpi_open(void);
1337void sna_acpi_init(struct sna *sna);
1338void _sna_acpi_wakeup(struct sna *sna);
1339static inline void sna_acpi_wakeup(struct sna *sna)
1340{
1341	_sna_acpi_wakeup(sna);
1342}
1343void sna_acpi_fini(struct sna *sna);
1344
1345void sna_threads_init(void);
1346int sna_use_threads (int width, int height, int threshold);
1347void sna_threads_run(int id, void (*func)(void *arg), void *arg);
1348void sna_threads_trap(int sig);
1349void sna_threads_wait(void);
1350void sna_threads_kill(void);
1351
1352void sna_image_composite(pixman_op_t        op,
1353			 pixman_image_t    *src,
1354			 pixman_image_t    *mask,
1355			 pixman_image_t    *dst,
1356			 int16_t            src_x,
1357			 int16_t            src_y,
1358			 int16_t            mask_x,
1359			 int16_t            mask_y,
1360			 int16_t            dst_x,
1361			 int16_t            dst_y,
1362			 uint16_t           width,
1363			 uint16_t           height);
1364
1365extern jmp_buf sigjmp[4];
1366extern volatile sig_atomic_t sigtrap;
1367
1368#define sigtrap_assert_inactive() assert(sigtrap == 0)
1369#define sigtrap_assert_active() assert(sigtrap > 0 && sigtrap <= ARRAY_SIZE(sigjmp))
1370#define sigtrap_get() sigsetjmp(sigjmp[sigtrap++], 1)
1371
1372static inline void sigtrap_put(void)
1373{
1374	sigtrap_assert_active();
1375	--sigtrap;
1376}
1377
1378#define RR_Rotate_All (RR_Rotate_0 | RR_Rotate_90 | RR_Rotate_180 | RR_Rotate_270)
1379#define RR_Reflect_All (RR_Reflect_X | RR_Reflect_Y)
1380
1381#ifndef HAVE_GETLINE
1382#include <stdio.h>
1383extern int getline(char **line, size_t *len, FILE *file);
1384#endif
1385
1386static inline void add_shm_flush(struct sna *sna, struct sna_pixmap *priv)
1387{
1388	if (!priv->shm)
1389		return;
1390
1391	DBG(("%s: marking handle=%d for SHM flush\n",
1392	     __FUNCTION__, priv->cpu_bo->handle));
1393
1394	assert(!priv->flush);
1395	sna_add_flush_pixmap(sna, priv, priv->cpu_bo);
1396	sna->needs_shm_flush = true;
1397}
1398
1399#endif /* _SNA_H */
1400