1428d7b3dSmrg/**************************************************************************
2428d7b3dSmrg
3428d7b3dSmrgCopyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
4428d7b3dSmrgCopyright © 2002 David Dawes
5428d7b3dSmrg
6428d7b3dSmrgAll Rights Reserved.
7428d7b3dSmrg
8428d7b3dSmrgPermission is hereby granted, free of charge, to any person obtaining a
9428d7b3dSmrgcopy of this software and associated documentation files (the
10428d7b3dSmrg"Software"), to deal in the Software without restriction, including
11428d7b3dSmrgwithout limitation the rights to use, copy, modify, merge, publish,
12428d7b3dSmrgdistribute, sub license, and/or sell copies of the Software, and to
13428d7b3dSmrgpermit persons to whom the Software is furnished to do so, subject to
14428d7b3dSmrgthe following conditions:
15428d7b3dSmrg
16428d7b3dSmrgThe above copyright notice and this permission notice (including the
17428d7b3dSmrgnext paragraph) shall be included in all copies or substantial portions
18428d7b3dSmrgof the Software.
19428d7b3dSmrg
20428d7b3dSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21428d7b3dSmrgOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22428d7b3dSmrgMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
23428d7b3dSmrgIN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
24428d7b3dSmrgANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
25428d7b3dSmrgTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
26428d7b3dSmrgSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27428d7b3dSmrg
28428d7b3dSmrg**************************************************************************/
29428d7b3dSmrg
30428d7b3dSmrg/*
31428d7b3dSmrg * Authors:
32428d7b3dSmrg *   Keith Whitwell <keith@tungstengraphics.com>
33428d7b3dSmrg *   David Dawes <dawes@xfree86.org>
34428d7b3dSmrg *
35428d7b3dSmrg */
36428d7b3dSmrg
37428d7b3dSmrg#ifndef _SNA_H_
38428d7b3dSmrg#define _SNA_H_
39428d7b3dSmrg
40428d7b3dSmrg#include <stdint.h>
41428d7b3dSmrg
42428d7b3dSmrg#include <xorg-server.h>
43428d7b3dSmrg#include <xf86str.h>
44428d7b3dSmrg
45428d7b3dSmrg#include <xf86Crtc.h>
46428d7b3dSmrg#if XF86_CRTC_VERSION >= 5
47428d7b3dSmrg#define HAS_PIXMAP_SHARING 1
48428d7b3dSmrg#endif
49428d7b3dSmrg
50428d7b3dSmrg#include <windowstr.h>
51428d7b3dSmrg#include <glyphstr.h>
52428d7b3dSmrg#include <picturestr.h>
53428d7b3dSmrg#include <gcstruct.h>
54428d7b3dSmrg#include <xvdix.h>
55428d7b3dSmrg
56428d7b3dSmrg#include <pciaccess.h>
57428d7b3dSmrg
58428d7b3dSmrg#include <xf86drmMode.h>
59428d7b3dSmrg
60428d7b3dSmrg#include "../compat-api.h"
61428d7b3dSmrg#include <drm.h>
62428d7b3dSmrg#include <i915_drm.h>
63428d7b3dSmrg
64428d7b3dSmrg#if HAVE_DRI2
65428d7b3dSmrg#include <dri2.h>
66428d7b3dSmrg#endif
67428d7b3dSmrg
68428d7b3dSmrg#if HAVE_DRI3
69428d7b3dSmrg#include <misync.h>
70428d7b3dSmrg#endif
71428d7b3dSmrg
72428d7b3dSmrg#if HAVE_UDEV
73428d7b3dSmrg#include <libudev.h>
74428d7b3dSmrg#endif
75428d7b3dSmrg
76428d7b3dSmrg#include <signal.h>
77428d7b3dSmrg#include <setjmp.h>
78428d7b3dSmrg
79428d7b3dSmrg#include "xassert.h"
80428d7b3dSmrg#include "compiler.h"
81428d7b3dSmrg#include "debug.h"
82428d7b3dSmrg
83428d7b3dSmrg#define DEBUG_NO_BLT 0
84428d7b3dSmrg
85428d7b3dSmrg#define DEBUG_FLUSH_BATCH 0
86428d7b3dSmrg
87428d7b3dSmrg#define TEST_ALL 0
88428d7b3dSmrg#define TEST_ACCEL (TEST_ALL || 0)
89428d7b3dSmrg#define TEST_BATCH (TEST_ALL || 0)
90428d7b3dSmrg#define TEST_BLT (TEST_ALL || 0)
91428d7b3dSmrg#define TEST_COMPOSITE (TEST_ALL || 0)
92428d7b3dSmrg#define TEST_DAMAGE (TEST_ALL || 0)
93428d7b3dSmrg#define TEST_GRADIENT (TEST_ALL || 0)
94428d7b3dSmrg#define TEST_GLYPHS (TEST_ALL || 0)
95428d7b3dSmrg#define TEST_IO (TEST_ALL || 0)
96428d7b3dSmrg#define TEST_KGEM (TEST_ALL || 0)
97428d7b3dSmrg#define TEST_RENDER (TEST_ALL || 0)
98428d7b3dSmrg
99428d7b3dSmrg#include "intel_driver.h"
100428d7b3dSmrg#include "intel_list.h"
101428d7b3dSmrg#include "kgem.h"
102428d7b3dSmrg#include "sna_damage.h"
103428d7b3dSmrg#include "sna_render.h"
104428d7b3dSmrg#include "fb/fb.h"
105428d7b3dSmrg
106428d7b3dSmrgstruct sna_cursor;
107428d7b3dSmrgstruct sna_crtc;
108428d7b3dSmrg
109428d7b3dSmrgstruct sna_client {
110428d7b3dSmrg	struct list events;
111428d7b3dSmrg	int is_compositor; /* only 4 bits used */
112428d7b3dSmrg};
113428d7b3dSmrg
114428d7b3dSmrgextern DevPrivateKeyRec sna_client_key;
115428d7b3dSmrg
116428d7b3dSmrgpure static inline struct sna_client *sna_client(ClientPtr client)
117428d7b3dSmrg{
118428d7b3dSmrg	return __get_private(client, sna_client_key);
119428d7b3dSmrg}
120428d7b3dSmrg
121428d7b3dSmrgstruct sna_cow {
122428d7b3dSmrg	struct kgem_bo *bo;
123428d7b3dSmrg	struct list list;
124428d7b3dSmrg	int refcnt;
125428d7b3dSmrg};
126428d7b3dSmrg
127428d7b3dSmrgstruct sna_pixmap {
128428d7b3dSmrg	PixmapPtr pixmap;
129428d7b3dSmrg	struct kgem_bo *gpu_bo, *cpu_bo;
130428d7b3dSmrg	struct sna_damage *gpu_damage, *cpu_damage;
131428d7b3dSmrg	struct sna_cow *cow;
132428d7b3dSmrg	void *ptr;
133428d7b3dSmrg#define PTR(ptr) ((void*)((uintptr_t)(ptr) & ~1))
134428d7b3dSmrg
135428d7b3dSmrg	bool (*move_to_gpu)(struct sna *, struct sna_pixmap *, unsigned);
136428d7b3dSmrg	void *move_to_gpu_data;
137428d7b3dSmrg
138428d7b3dSmrg	struct list flush_list;
139428d7b3dSmrg	struct list cow_list;
140428d7b3dSmrg
141428d7b3dSmrg	uint32_t stride;
142428d7b3dSmrg	uint32_t clear_color;
143428d7b3dSmrg
144428d7b3dSmrg#define SOURCE_BIAS 4
145428d7b3dSmrg	uint8_t source_count;
146428d7b3dSmrg	uint8_t pinned :4;
147428d7b3dSmrg#define PIN_SCANOUT 0x1
148428d7b3dSmrg#define PIN_DRI2 0x2
149428d7b3dSmrg#define PIN_DRI3 0x4
150428d7b3dSmrg#define PIN_PRIME 0x8
151428d7b3dSmrg	uint8_t create :4;
152428d7b3dSmrg	uint8_t mapped :2;
153428d7b3dSmrg#define MAPPED_NONE 0
154428d7b3dSmrg#define MAPPED_GTT 1
155428d7b3dSmrg#define MAPPED_CPU 2
156428d7b3dSmrg	uint8_t flush :2;
157428d7b3dSmrg	uint8_t shm :1;
158428d7b3dSmrg	uint8_t clear :1;
159428d7b3dSmrg	uint8_t header :1;
160428d7b3dSmrg	uint8_t cpu :1;
161428d7b3dSmrg};
162428d7b3dSmrg
163428d7b3dSmrg#define IS_STATIC_PTR(ptr) ((uintptr_t)(ptr) & 1)
164428d7b3dSmrg#define MAKE_STATIC_PTR(ptr) ((void*)((uintptr_t)(ptr) | 1))
165428d7b3dSmrg
166428d7b3dSmrgstruct sna_glyph {
167428d7b3dSmrg	PicturePtr atlas;
168428d7b3dSmrg	struct sna_coordinate coordinate;
169428d7b3dSmrg	uint16_t size, pos;
170428d7b3dSmrg	pixman_image_t *image;
171428d7b3dSmrg};
172428d7b3dSmrg
173428d7b3dSmrgstatic inline WindowPtr get_root_window(ScreenPtr screen)
174428d7b3dSmrg{
175428d7b3dSmrg#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,10,0,0,0)
176428d7b3dSmrg	return screen->root;
177428d7b3dSmrg#else
178428d7b3dSmrg	return WindowTable[screen->myNum];
179428d7b3dSmrg#endif
180428d7b3dSmrg}
181428d7b3dSmrg
182428d7b3dSmrgstatic inline PixmapPtr get_window_pixmap(WindowPtr window)
183428d7b3dSmrg{
184428d7b3dSmrg	assert(window);
185428d7b3dSmrg	assert(window->drawable.type != DRAWABLE_PIXMAP);
186428d7b3dSmrg	return fbGetWindowPixmap(window);
187428d7b3dSmrg}
188428d7b3dSmrg
189428d7b3dSmrgstatic inline PixmapPtr get_drawable_pixmap(DrawablePtr drawable)
190428d7b3dSmrg{
191428d7b3dSmrg	assert(drawable);
192428d7b3dSmrg	if (drawable->type == DRAWABLE_PIXMAP)
193428d7b3dSmrg		return (PixmapPtr)drawable;
194428d7b3dSmrg	else
195428d7b3dSmrg		return get_window_pixmap((WindowPtr)drawable);
196428d7b3dSmrg}
197428d7b3dSmrg
198428d7b3dSmrgextern DevPrivateKeyRec sna_pixmap_key;
199428d7b3dSmrg
200428d7b3dSmrgpure static inline struct sna_pixmap *sna_pixmap(PixmapPtr pixmap)
201428d7b3dSmrg{
202428d7b3dSmrg	return ((void **)__get_private(pixmap, sna_pixmap_key))[1];
203428d7b3dSmrg}
204428d7b3dSmrg
205428d7b3dSmrgstatic inline struct sna_pixmap *sna_pixmap_from_drawable(DrawablePtr drawable)
206428d7b3dSmrg{
207428d7b3dSmrg	return sna_pixmap(get_drawable_pixmap(drawable));
208428d7b3dSmrg}
209428d7b3dSmrg
210428d7b3dSmrgstruct sna_gc {
211428d7b3dSmrg	long changes;
212428d7b3dSmrg	long serial;
213428d7b3dSmrg
214428d7b3dSmrg	const GCFuncs *old_funcs;
215428d7b3dSmrg	void *priv;
216428d7b3dSmrg};
217428d7b3dSmrg
218428d7b3dSmrgstatic inline struct sna_gc *sna_gc(GCPtr gc)
219428d7b3dSmrg{
220428d7b3dSmrg	return (struct sna_gc *)__get_private(gc, sna_gc_key);
221428d7b3dSmrg}
222428d7b3dSmrg
223428d7b3dSmrgenum {
224428d7b3dSmrg	FLUSH_TIMER = 0,
225428d7b3dSmrg	THROTTLE_TIMER,
226428d7b3dSmrg	EXPIRE_TIMER,
227428d7b3dSmrg#if DEBUG_MEMORY
228428d7b3dSmrg	DEBUG_MEMORY_TIMER,
229428d7b3dSmrg#endif
230428d7b3dSmrg	NUM_TIMERS
231428d7b3dSmrg};
232428d7b3dSmrg
233428d7b3dSmrgstruct sna {
234428d7b3dSmrg	struct kgem kgem;
235428d7b3dSmrg
236428d7b3dSmrg	ScrnInfoPtr scrn;
237428d7b3dSmrg	struct intel_device *dev;
238428d7b3dSmrg
239428d7b3dSmrg	unsigned flags;
240428d7b3dSmrg#define SNA_IS_SLAVED		0x1
241428d7b3dSmrg#define SNA_IS_HOSTED		0x2
242428d7b3dSmrg#define SNA_NO_WAIT		0x10
243428d7b3dSmrg#define SNA_NO_FLIP		0x20
244428d7b3dSmrg#define SNA_NO_VSYNC		0x40
245428d7b3dSmrg#define SNA_TRIPLE_BUFFER	0x80
246428d7b3dSmrg#define SNA_TEAR_FREE		0x100
247428d7b3dSmrg#define SNA_FORCE_SHADOW	0x200
248428d7b3dSmrg#define SNA_FLUSH_GTT		0x400
249428d7b3dSmrg#define SNA_PERFORMANCE		0x1000
250428d7b3dSmrg#define SNA_POWERSAVE		0x2000
251428d7b3dSmrg#define SNA_REMOVE_OUTPUTS	0x4000
252428d7b3dSmrg#define SNA_HAS_FLIP		0x10000
253428d7b3dSmrg#define SNA_HAS_ASYNC_FLIP	0x20000
254428d7b3dSmrg#define SNA_LINEAR_FB		0x40000
255428d7b3dSmrg#define SNA_REPROBE		0x80000000
256428d7b3dSmrg
257428d7b3dSmrg	unsigned cpu_features;
258428d7b3dSmrg#define MMX 0x1
259428d7b3dSmrg#define SSE 0x2
260428d7b3dSmrg#define SSE2 0x4
261428d7b3dSmrg#define SSE3 0x8
262428d7b3dSmrg#define SSSE3 0x10
263428d7b3dSmrg#define SSE4_1 0x20
264428d7b3dSmrg#define SSE4_2 0x40
265428d7b3dSmrg#define AVX 0x80
266428d7b3dSmrg#define AVX2 0x100
267428d7b3dSmrg
268428d7b3dSmrg	unsigned watch_flush;
269428d7b3dSmrg
270428d7b3dSmrg	struct timeval timer_tv;
271428d7b3dSmrg	uint32_t timer_expire[NUM_TIMERS];
272428d7b3dSmrg	uint16_t timer_active;
273428d7b3dSmrg
274428d7b3dSmrg	int vblank_interval;
275428d7b3dSmrg
276428d7b3dSmrg	struct list flush_pixmaps;
277428d7b3dSmrg	struct list active_pixmaps;
278428d7b3dSmrg
279428d7b3dSmrg	PixmapPtr front;
280428d7b3dSmrg	PixmapPtr freed_pixmap;
281428d7b3dSmrg
282428d7b3dSmrg	struct sna_mode {
283428d7b3dSmrg		DamagePtr shadow_damage;
284428d7b3dSmrg		struct kgem_bo *shadow;
285428d7b3dSmrg		unsigned front_active;
286428d7b3dSmrg		unsigned shadow_active;
287428d7b3dSmrg		unsigned flip_active;
288428d7b3dSmrg		bool dirty;
289428d7b3dSmrg
290428d7b3dSmrg		int max_crtc_width, max_crtc_height;
291428d7b3dSmrg		RegionRec shadow_region;
292428d7b3dSmrg		RegionRec shadow_cancel;
293428d7b3dSmrg		struct list shadow_crtc;
294428d7b3dSmrg		bool shadow_dirty;
295428d7b3dSmrg
296428d7b3dSmrg		unsigned num_real_crtc;
297428d7b3dSmrg		unsigned num_real_output;
298428d7b3dSmrg		unsigned num_real_encoder;
299428d7b3dSmrg		unsigned num_fake;
300428d7b3dSmrg		unsigned serial;
301428d7b3dSmrg
302428d7b3dSmrg		uint32_t *encoders;
303428d7b3dSmrg
304428d7b3dSmrg#if HAVE_UDEV
305428d7b3dSmrg		struct udev_monitor *backlight_monitor;
306428d7b3dSmrg		pointer backlight_handler;
307428d7b3dSmrg#endif
308428d7b3dSmrg
309428d7b3dSmrg		Bool (*rrGetInfo)(ScreenPtr, Rotation *);
310428d7b3dSmrg	} mode;
311428d7b3dSmrg
312428d7b3dSmrg	struct {
313428d7b3dSmrg		struct sna_cursor *cursors;
314428d7b3dSmrg		xf86CursorInfoPtr info;
315428d7b3dSmrg		CursorPtr ref;
316428d7b3dSmrg
317428d7b3dSmrg		unsigned serial;
318428d7b3dSmrg		uint32_t fg, bg;
319428d7b3dSmrg		int size;
320428d7b3dSmrg
321428d7b3dSmrg		int active;
322428d7b3dSmrg		int last_x;
323428d7b3dSmrg		int last_y;
324428d7b3dSmrg
325428d7b3dSmrg		unsigned max_size;
326428d7b3dSmrg		bool use_gtt;
327428d7b3dSmrg
328428d7b3dSmrg		int num_stash;
329428d7b3dSmrg		struct sna_cursor *stash;
330428d7b3dSmrg		void *scratch;
331428d7b3dSmrg	} cursor;
332428d7b3dSmrg
333428d7b3dSmrg	struct sna_dri2 {
334428d7b3dSmrg		bool available;
335428d7b3dSmrg		bool open;
336428d7b3dSmrg
337428d7b3dSmrg#if HAVE_DRI2
338428d7b3dSmrg		void *flip_pending;
339428d7b3dSmrg		unsigned client_count;
340428d7b3dSmrg#endif
341428d7b3dSmrg	} dri2;
342428d7b3dSmrg
343428d7b3dSmrg	struct sna_dri3 {
344428d7b3dSmrg		bool available;
345428d7b3dSmrg		bool open;
346428d7b3dSmrg#if HAVE_DRI3
347428d7b3dSmrg		SyncScreenCreateFenceFunc create_fence;
348428d7b3dSmrg		struct list pixmaps;
349428d7b3dSmrg#endif
350428d7b3dSmrg	} dri3;
351428d7b3dSmrg
352428d7b3dSmrg	struct sna_present {
353428d7b3dSmrg		bool available;
354428d7b3dSmrg		bool open;
355428d7b3dSmrg#if HAVE_PRESENT
356428d7b3dSmrg#endif
357428d7b3dSmrg	} present;
358428d7b3dSmrg
359428d7b3dSmrg	struct sna_xv {
360428d7b3dSmrg		XvAdaptorPtr adaptors;
361428d7b3dSmrg		int num_adaptors;
362428d7b3dSmrg	} xv;
363428d7b3dSmrg
364428d7b3dSmrg	EntityInfoPtr pEnt;
365428d7b3dSmrg	const struct intel_device_info *info;
366428d7b3dSmrg
367428d7b3dSmrg	ScreenBlockHandlerProcPtr BlockHandler;
368428d7b3dSmrg	ScreenWakeupHandlerProcPtr WakeupHandler;
369428d7b3dSmrg	CloseScreenProcPtr CloseScreen;
370428d7b3dSmrg
371428d7b3dSmrg	PicturePtr clear;
372428d7b3dSmrg	struct {
373428d7b3dSmrg		uint32_t fill_bo;
374428d7b3dSmrg		uint32_t fill_pixel;
375428d7b3dSmrg		uint32_t fill_alu;
376428d7b3dSmrg	} blt_state;
377428d7b3dSmrg	union {
378428d7b3dSmrg		unsigned gt;
379428d7b3dSmrg		struct gen2_render_state gen2;
380428d7b3dSmrg		struct gen3_render_state gen3;
381428d7b3dSmrg		struct gen4_render_state gen4;
382428d7b3dSmrg		struct gen5_render_state gen5;
383428d7b3dSmrg		struct gen6_render_state gen6;
384428d7b3dSmrg		struct gen7_render_state gen7;
385428d7b3dSmrg		struct gen8_render_state gen8;
386428d7b3dSmrg	} render_state;
387428d7b3dSmrg
388428d7b3dSmrg	/* Broken-out options. */
389428d7b3dSmrg	OptionInfoPtr Options;
390428d7b3dSmrg
391428d7b3dSmrg	/* Driver phase/state information */
392428d7b3dSmrg	bool suspended;
393428d7b3dSmrg
394428d7b3dSmrg#if HAVE_UDEV
395428d7b3dSmrg	struct udev_monitor *uevent_monitor;
396428d7b3dSmrg	pointer uevent_handler;
397428d7b3dSmrg#endif
398428d7b3dSmrg
399428d7b3dSmrg	struct {
400428d7b3dSmrg		int fd;
401428d7b3dSmrg		uint8_t offset;
402428d7b3dSmrg		uint8_t remain;
403428d7b3dSmrg		char event[256];
404428d7b3dSmrg	} acpi;
405428d7b3dSmrg
406428d7b3dSmrg	struct sna_render render;
407428d7b3dSmrg
408428d7b3dSmrg#if DEBUG_MEMORY
409428d7b3dSmrg	struct {
410428d7b3dSmrg		int pixmap_allocs;
411428d7b3dSmrg		int pixmap_cached;
412428d7b3dSmrg		int cpu_bo_allocs;
413428d7b3dSmrg		size_t shadow_pixels_bytes;
414428d7b3dSmrg		size_t cpu_bo_bytes;
415428d7b3dSmrg	} debug_memory;
416428d7b3dSmrg#endif
417428d7b3dSmrg};
418428d7b3dSmrg
419428d7b3dSmrgbool sna_mode_pre_init(ScrnInfoPtr scrn, struct sna *sna);
420428d7b3dSmrgbool sna_mode_fake_init(struct sna *sna, int num_fake);
421428d7b3dSmrgbool sna_mode_wants_tear_free(struct sna *sna);
422428d7b3dSmrgvoid sna_mode_adjust_frame(struct sna *sna, int x, int y);
423428d7b3dSmrgextern void sna_mode_discover(struct sna *sna);
424428d7b3dSmrgextern void sna_mode_check(struct sna *sna);
425428d7b3dSmrgextern bool sna_mode_disable(struct sna *sna);
426428d7b3dSmrgextern void sna_mode_enable(struct sna *sna);
427428d7b3dSmrgextern void sna_mode_reset(struct sna *sna);
428428d7b3dSmrgextern int sna_mode_wakeup(struct sna *sna);
429428d7b3dSmrgextern void sna_mode_redisplay(struct sna *sna);
430428d7b3dSmrgextern void sna_shadow_set_crtc(struct sna *sna, xf86CrtcPtr crtc, struct kgem_bo *bo);
431428d7b3dSmrgextern void sna_shadow_steal_crtcs(struct sna *sna, struct list *list);
432428d7b3dSmrgextern void sna_shadow_unsteal_crtcs(struct sna *sna, struct list *list);
433428d7b3dSmrgextern void sna_shadow_unset_crtc(struct sna *sna, xf86CrtcPtr crtc);
434428d7b3dSmrgextern bool sna_pixmap_discard_shadow_damage(struct sna_pixmap *priv,
435428d7b3dSmrg					     const RegionRec *region);
436428d7b3dSmrgextern void sna_mode_set_primary(struct sna *sna);
437428d7b3dSmrgextern void sna_mode_close(struct sna *sna);
438428d7b3dSmrgextern void sna_mode_fini(struct sna *sna);
439428d7b3dSmrg
440428d7b3dSmrgextern void sna_crtc_config_notify(ScreenPtr screen);
441428d7b3dSmrg
442428d7b3dSmrgextern bool sna_cursors_init(ScreenPtr screen, struct sna *sna);
443428d7b3dSmrg
444428d7b3dSmrgtypedef void (*sna_flip_handler_t)(struct drm_event_vblank *e,
445428d7b3dSmrg				   void *data);
446428d7b3dSmrg
447428d7b3dSmrgextern int sna_page_flip(struct sna *sna,
448428d7b3dSmrg			 struct kgem_bo *bo,
449428d7b3dSmrg			 sna_flip_handler_t handler,
450428d7b3dSmrg			 void *data);
451428d7b3dSmrg
452428d7b3dSmrgpure static inline struct sna *
453428d7b3dSmrgto_sna(ScrnInfoPtr scrn)
454428d7b3dSmrg{
455428d7b3dSmrg	return (struct sna *)(scrn->driverPrivate);
456428d7b3dSmrg}
457428d7b3dSmrg
458428d7b3dSmrgpure static inline struct sna *
459428d7b3dSmrgto_sna_from_screen(ScreenPtr screen)
460428d7b3dSmrg{
461428d7b3dSmrg	return to_sna(xf86ScreenToScrn(screen));
462428d7b3dSmrg}
463428d7b3dSmrg
464428d7b3dSmrgpure static inline struct sna *
465428d7b3dSmrgto_sna_from_pixmap(PixmapPtr pixmap)
466428d7b3dSmrg{
467428d7b3dSmrg	return ((void **)__get_private(pixmap, sna_pixmap_key))[0];
468428d7b3dSmrg}
469428d7b3dSmrg
470428d7b3dSmrgpure static inline struct sna *
471428d7b3dSmrgto_sna_from_drawable(DrawablePtr drawable)
472428d7b3dSmrg{
473428d7b3dSmrg	return to_sna_from_screen(drawable->pScreen);
474428d7b3dSmrg}
475428d7b3dSmrg
476428d7b3dSmrgstatic inline struct sna *
477428d7b3dSmrgto_sna_from_kgem(struct kgem *kgem)
478428d7b3dSmrg{
479428d7b3dSmrg	return container_of(kgem, struct sna, kgem);
480428d7b3dSmrg}
481428d7b3dSmrg
482428d7b3dSmrg#ifndef ARRAY_SIZE
483428d7b3dSmrg#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
484428d7b3dSmrg#endif
485428d7b3dSmrg
486428d7b3dSmrg#ifndef ALIGN
487428d7b3dSmrg#define ALIGN(i,m)	(((i) + (m) - 1) & ~((m) - 1))
488428d7b3dSmrg#endif
489428d7b3dSmrg
490428d7b3dSmrg#ifndef MIN
491428d7b3dSmrg#define MIN(a,b)	((a) <= (b) ? (a) : (b))
492428d7b3dSmrg#endif
493428d7b3dSmrg
494428d7b3dSmrg#ifndef MAX
495428d7b3dSmrg#define MAX(a,b)	((a) >= (b) ? (a) : (b))
496428d7b3dSmrg#endif
497428d7b3dSmrg
498428d7b3dSmrgextern xf86CrtcPtr sna_covering_crtc(struct sna *sna,
499428d7b3dSmrg				     const BoxRec *box,
500428d7b3dSmrg				     xf86CrtcPtr desired);
501428d7b3dSmrg
502428d7b3dSmrgextern bool sna_wait_for_scanline(struct sna *sna, PixmapPtr pixmap,
503428d7b3dSmrg				  xf86CrtcPtr crtc, const BoxRec *clip);
504428d7b3dSmrg
505428d7b3dSmrgxf86CrtcPtr sna_mode_first_crtc(struct sna *sna);
506428d7b3dSmrg
507428d7b3dSmrgconst struct ust_msc {
508428d7b3dSmrg	uint64_t msc;
509428d7b3dSmrg	int tv_sec;
510428d7b3dSmrg	int tv_usec;
511428d7b3dSmrg} *sna_crtc_last_swap(xf86CrtcPtr crtc);
512428d7b3dSmrg
513428d7b3dSmrguint64_t sna_crtc_record_swap(xf86CrtcPtr crtc,
514428d7b3dSmrg			      int tv_sec, int tv_usec, unsigned seq);
515428d7b3dSmrg
516428d7b3dSmrgstatic inline uint64_t sna_crtc_record_vblank(xf86CrtcPtr crtc,
517428d7b3dSmrg					      const union drm_wait_vblank *vbl)
518428d7b3dSmrg{
519428d7b3dSmrg	return sna_crtc_record_swap(crtc,
520428d7b3dSmrg				    vbl->reply.tval_sec,
521428d7b3dSmrg				    vbl->reply.tval_usec,
522428d7b3dSmrg				    vbl->reply.sequence);
523428d7b3dSmrg}
524428d7b3dSmrg
525428d7b3dSmrgstatic inline uint64_t sna_crtc_record_event(xf86CrtcPtr crtc,
526428d7b3dSmrg					     struct drm_event_vblank *event)
527428d7b3dSmrg{
528428d7b3dSmrg	return sna_crtc_record_swap(crtc,
529428d7b3dSmrg				    event->tv_sec,
530428d7b3dSmrg				    event->tv_usec,
531428d7b3dSmrg				    event->sequence);
532428d7b3dSmrg}
533428d7b3dSmrg
534428d7b3dSmrgstatic inline uint64_t ust64(int tv_sec, int tv_usec)
535428d7b3dSmrg{
536428d7b3dSmrg	return (uint64_t)tv_sec * 1000000 + tv_usec;
537428d7b3dSmrg}
538428d7b3dSmrg
539428d7b3dSmrg#if HAVE_DRI2
540428d7b3dSmrgbool sna_dri2_open(struct sna *sna, ScreenPtr pScreen);
541428d7b3dSmrgvoid sna_dri2_page_flip_handler(struct sna *sna, struct drm_event_vblank *event);
542428d7b3dSmrgvoid sna_dri2_vblank_handler(struct drm_event_vblank *event);
543428d7b3dSmrgvoid sna_dri2_pixmap_update_bo(struct sna *sna, PixmapPtr pixmap, struct kgem_bo *bo);
544428d7b3dSmrgvoid sna_dri2_decouple_window(WindowPtr win);
545428d7b3dSmrgvoid sna_dri2_destroy_window(WindowPtr win);
546428d7b3dSmrgvoid sna_dri2_close(struct sna *sna, ScreenPtr pScreen);
547428d7b3dSmrg#else
548428d7b3dSmrgstatic inline bool sna_dri2_open(struct sna *sna, ScreenPtr pScreen) { return false; }
549428d7b3dSmrgstatic inline void sna_dri2_page_flip_handler(struct sna *sna, struct drm_event_vblank *event) { }
550428d7b3dSmrgstatic inline void sna_dri2_vblank_handler(struct drm_event_vblank *event) { }
551428d7b3dSmrgstatic inline void sna_dri2_pixmap_update_bo(struct sna *sna, PixmapPtr pixmap, struct kgem_bo *bo) { }
552428d7b3dSmrgstatic inline void sna_dri2_decouple_window(WindowPtr win) { }
553428d7b3dSmrgstatic inline void sna_dri2_destroy_window(WindowPtr win) { }
554428d7b3dSmrgstatic inline void sna_dri2_close(struct sna *sna, ScreenPtr pScreen) { }
555428d7b3dSmrg#endif
556428d7b3dSmrg
557428d7b3dSmrg#if HAVE_DRI3
558428d7b3dSmrgbool sna_dri3_open(struct sna *sna, ScreenPtr pScreen);
559428d7b3dSmrgvoid sna_dri3_close(struct sna *sna, ScreenPtr pScreen);
560428d7b3dSmrg#else
561428d7b3dSmrgstatic inline bool sna_dri3_open(struct sna *sna, ScreenPtr pScreen) { return false; }
562428d7b3dSmrgstatic inline void sna_dri3_close(struct sna *sna, ScreenPtr pScreen) { }
563428d7b3dSmrg#endif
564428d7b3dSmrg
565428d7b3dSmrg#if HAVE_PRESENT
566428d7b3dSmrgbool sna_present_open(struct sna *sna, ScreenPtr pScreen);
567428d7b3dSmrgvoid sna_present_update(struct sna *sna);
568428d7b3dSmrgvoid sna_present_close(struct sna *sna, ScreenPtr pScreen);
569428d7b3dSmrgvoid sna_present_vblank_handler(struct drm_event_vblank *event);
570428d7b3dSmrg#else
571428d7b3dSmrgstatic inline bool sna_present_open(struct sna *sna, ScreenPtr pScreen) { return false; }
572428d7b3dSmrgstatic inline void sna_present_update(struct sna *sna) { }
573428d7b3dSmrgstatic inline void sna_present_close(struct sna *sna, ScreenPtr pScreen) { }
574428d7b3dSmrgstatic inline void sna_present_vblank_handler(struct drm_event_vblank *event) { }
575428d7b3dSmrg#endif
576428d7b3dSmrg
577428d7b3dSmrgextern bool sna_crtc_set_sprite_rotation(xf86CrtcPtr crtc, uint32_t rotation);
578428d7b3dSmrgextern int sna_crtc_to_pipe(xf86CrtcPtr crtc);
579428d7b3dSmrgextern uint32_t sna_crtc_to_sprite(xf86CrtcPtr crtc);
580428d7b3dSmrgextern uint32_t sna_crtc_id(xf86CrtcPtr crtc);
581428d7b3dSmrgextern bool sna_crtc_is_on(xf86CrtcPtr crtc);
582428d7b3dSmrgextern bool sna_crtc_is_transformed(xf86CrtcPtr crtc);
583428d7b3dSmrg
584428d7b3dSmrgCARD32 sna_format_for_depth(int depth);
585428d7b3dSmrgCARD32 sna_render_format_for_depth(int depth);
586428d7b3dSmrg
587428d7b3dSmrgvoid sna_debug_flush(struct sna *sna);
588428d7b3dSmrg
589428d7b3dSmrgstatic inline bool
590428d7b3dSmrgget_window_deltas(PixmapPtr pixmap, int16_t *x, int16_t *y)
591428d7b3dSmrg{
592428d7b3dSmrg#ifdef COMPOSITE
593428d7b3dSmrg	*x = -pixmap->screen_x;
594428d7b3dSmrg	*y = -pixmap->screen_y;
595428d7b3dSmrg	return pixmap->screen_x | pixmap->screen_y;
596428d7b3dSmrg#else
597428d7b3dSmrg	*x = *y = 0;
598428d7b3dSmrg	return false;
599428d7b3dSmrg#endif
600428d7b3dSmrg}
601428d7b3dSmrg
602428d7b3dSmrgstatic inline bool
603428d7b3dSmrgget_drawable_deltas(DrawablePtr drawable, PixmapPtr pixmap, int16_t *x, int16_t *y)
604428d7b3dSmrg{
605428d7b3dSmrg#ifdef COMPOSITE
606428d7b3dSmrg	if (drawable->type == DRAWABLE_WINDOW)
607428d7b3dSmrg		return get_window_deltas(pixmap, x, y);
608428d7b3dSmrg#endif
609428d7b3dSmrg	*x = *y = 0;
610428d7b3dSmrg	return false;
611428d7b3dSmrg}
612428d7b3dSmrg
613428d7b3dSmrgstatic inline int
614428d7b3dSmrgget_drawable_dx(DrawablePtr drawable)
615428d7b3dSmrg{
616428d7b3dSmrg#ifdef COMPOSITE
617428d7b3dSmrg	if (drawable->type == DRAWABLE_WINDOW)
618428d7b3dSmrg		return -get_drawable_pixmap(drawable)->screen_x;
619428d7b3dSmrg#endif
620428d7b3dSmrg	return 0;
621428d7b3dSmrg}
622428d7b3dSmrg
623428d7b3dSmrgstatic inline int
624428d7b3dSmrgget_drawable_dy(DrawablePtr drawable)
625428d7b3dSmrg{
626428d7b3dSmrg#ifdef COMPOSITE
627428d7b3dSmrg	if (drawable->type == DRAWABLE_WINDOW)
628428d7b3dSmrg		return -get_drawable_pixmap(drawable)->screen_y;
629428d7b3dSmrg#endif
630428d7b3dSmrg	return 0;
631428d7b3dSmrg}
632428d7b3dSmrg
633428d7b3dSmrgstruct sna_pixmap *sna_pixmap_attach_to_bo(PixmapPtr pixmap, struct kgem_bo *bo);
634428d7b3dSmrgstatic inline bool sna_pixmap_is_scanout(struct sna *sna, PixmapPtr pixmap)
635428d7b3dSmrg{
636428d7b3dSmrg	return (pixmap == sna->front &&
637428d7b3dSmrg		!sna->mode.shadow_active &&
638428d7b3dSmrg		(sna->flags & SNA_NO_WAIT) == 0);
639428d7b3dSmrg}
640428d7b3dSmrg
641428d7b3dSmrgstatic inline int sna_max_tile_copy_size(struct sna *sna, struct kgem_bo *src, struct kgem_bo *dst)
642428d7b3dSmrg{
643428d7b3dSmrg	int min_object;
644428d7b3dSmrg	int max_size;
645428d7b3dSmrg
646428d7b3dSmrg	max_size = sna->kgem.aperture_high * PAGE_SIZE;
647428d7b3dSmrg	max_size -= MAX(kgem_bo_size(src), kgem_bo_size(dst));
648428d7b3dSmrg	if (max_size <= 0) {
649428d7b3dSmrg		DBG(("%s: tiles cannot fit into aperture\n", __FUNCTION__));
650428d7b3dSmrg		return 0;
651428d7b3dSmrg	}
652428d7b3dSmrg
653428d7b3dSmrg	if (max_size > sna->kgem.max_copy_tile_size)
654428d7b3dSmrg		max_size = sna->kgem.max_copy_tile_size;
655428d7b3dSmrg
656428d7b3dSmrg	min_object = MIN(kgem_bo_size(src), kgem_bo_size(dst)) / 2;
657428d7b3dSmrg	if (max_size > min_object)
658428d7b3dSmrg		max_size = min_object;
659428d7b3dSmrg	if (max_size <= 4096)
660428d7b3dSmrg		max_size = 0;
661428d7b3dSmrg
662428d7b3dSmrg	DBG(("%s: using max tile size of %d\n", __FUNCTION__, max_size));
663428d7b3dSmrg	return max_size;
664428d7b3dSmrg}
665428d7b3dSmrg
666428d7b3dSmrgPixmapPtr sna_pixmap_create_upload(ScreenPtr screen,
667428d7b3dSmrg				   int width, int height, int depth,
668428d7b3dSmrg				   unsigned flags);
669428d7b3dSmrgPixmapPtr sna_pixmap_create_unattached(ScreenPtr screen,
670428d7b3dSmrg				       int width, int height, int depth);
671428d7b3dSmrgvoid sna_pixmap_destroy(PixmapPtr pixmap);
672428d7b3dSmrg
673428d7b3dSmrg#define assert_pixmap_map(pixmap, priv)  do { \
674428d7b3dSmrg	assert(priv->mapped != MAPPED_NONE || pixmap->devPrivate.ptr == PTR(priv->ptr)); \
675428d7b3dSmrg	assert(priv->mapped != MAPPED_CPU || pixmap->devPrivate.ptr == MAP(priv->gpu_bo->map__cpu)); \
676428d7b3dSmrg	assert(priv->mapped != MAPPED_GTT || pixmap->devPrivate.ptr == priv->gpu_bo->map__gtt || pixmap->devPrivate.ptr == priv->gpu_bo->map__wc); \
677428d7b3dSmrg} while (0)
678428d7b3dSmrg
679428d7b3dSmrgstatic inline void sna_pixmap_unmap(PixmapPtr pixmap, struct sna_pixmap *priv)
680428d7b3dSmrg{
681428d7b3dSmrg	if (priv->mapped == MAPPED_NONE) {
682428d7b3dSmrg		assert(pixmap->devPrivate.ptr == PTR(priv->ptr));
683428d7b3dSmrg		return;
684428d7b3dSmrg	}
685428d7b3dSmrg
686428d7b3dSmrg	DBG(("%s: pixmap=%ld dropping %s mapping\n",
687428d7b3dSmrg	     __FUNCTION__, pixmap->drawable.serialNumber,
688428d7b3dSmrg	     priv->mapped == MAPPED_CPU ? "cpu" : "gtt"));
689428d7b3dSmrg
690428d7b3dSmrg	assert_pixmap_map(pixmap, priv);
691428d7b3dSmrg
692428d7b3dSmrg	pixmap->devPrivate.ptr = PTR(priv->ptr);
693428d7b3dSmrg	pixmap->devKind = priv->stride;
694428d7b3dSmrg
695428d7b3dSmrg	priv->mapped = MAPPED_NONE;
696428d7b3dSmrg}
697428d7b3dSmrg
698428d7b3dSmrgbool
699428d7b3dSmrgsna_pixmap_undo_cow(struct sna *sna, struct sna_pixmap *priv, unsigned flags);
700428d7b3dSmrg
701428d7b3dSmrg#define MOVE_WRITE 0x1
702428d7b3dSmrg#define MOVE_READ 0x2
703428d7b3dSmrg#define MOVE_INPLACE_HINT 0x4
704428d7b3dSmrg#define MOVE_ASYNC_HINT 0x8
705428d7b3dSmrg#define MOVE_SOURCE_HINT 0x10
706428d7b3dSmrg#define MOVE_WHOLE_HINT 0x20
707428d7b3dSmrg#define __MOVE_FORCE 0x40
708428d7b3dSmrg#define __MOVE_DRI 0x80
709428d7b3dSmrg#define __MOVE_SCANOUT 0x100
710428d7b3dSmrg#define __MOVE_TILED 0x200
711428d7b3dSmrg#define __MOVE_PRIME 0x400
712428d7b3dSmrg
713428d7b3dSmrgstruct sna_pixmap *
714428d7b3dSmrgsna_pixmap_move_area_to_gpu(PixmapPtr pixmap, const BoxRec *box, unsigned int flags);
715428d7b3dSmrg
716428d7b3dSmrgstruct sna_pixmap *sna_pixmap_move_to_gpu(PixmapPtr pixmap, unsigned flags);
717428d7b3dSmrgstatic inline struct sna_pixmap *
718428d7b3dSmrgsna_pixmap_force_to_gpu(PixmapPtr pixmap, unsigned flags)
719428d7b3dSmrg{
720428d7b3dSmrg	/* Unlike move-to-gpu, we ignore wedged and always create the GPU bo */
721428d7b3dSmrg	DBG(("%s(pixmap=%ld, flags=%x)\n", __FUNCTION__, pixmap->drawable.serialNumber, flags));
722428d7b3dSmrg	return sna_pixmap_move_to_gpu(pixmap, flags | __MOVE_FORCE);
723428d7b3dSmrg}
724428d7b3dSmrgbool must_check _sna_pixmap_move_to_cpu(PixmapPtr pixmap, unsigned flags);
725428d7b3dSmrgstatic inline bool must_check sna_pixmap_move_to_cpu(PixmapPtr pixmap, unsigned flags)
726428d7b3dSmrg{
727428d7b3dSmrg	if (flags == MOVE_READ) {
728428d7b3dSmrg		struct sna_pixmap *priv = sna_pixmap(pixmap);
729428d7b3dSmrg		if (priv == NULL)
730428d7b3dSmrg			return true;
731428d7b3dSmrg	}
732428d7b3dSmrg
733428d7b3dSmrg	return _sna_pixmap_move_to_cpu(pixmap, flags);
734428d7b3dSmrg}
735428d7b3dSmrgbool must_check sna_drawable_move_region_to_cpu(DrawablePtr drawable,
736428d7b3dSmrg						RegionPtr region,
737428d7b3dSmrg						unsigned flags);
738428d7b3dSmrg
739428d7b3dSmrgbool must_check sna_drawable_move_to_cpu(DrawablePtr drawable, unsigned flags);
740428d7b3dSmrg
741428d7b3dSmrgstatic inline bool must_check
742428d7b3dSmrgsna_drawable_move_to_gpu(DrawablePtr drawable, unsigned flags)
743428d7b3dSmrg{
744428d7b3dSmrg	return sna_pixmap_move_to_gpu(get_drawable_pixmap(drawable), flags) != NULL;
745428d7b3dSmrg}
746428d7b3dSmrg
747428d7b3dSmrgvoid sna_add_flush_pixmap(struct sna *sna,
748428d7b3dSmrg			  struct sna_pixmap *priv,
749428d7b3dSmrg			  struct kgem_bo *bo);
750428d7b3dSmrg
751428d7b3dSmrgstruct kgem_bo *sna_pixmap_change_tiling(PixmapPtr pixmap, uint32_t tiling);
752428d7b3dSmrg
753428d7b3dSmrg#define PREFER_GPU	0x1
754428d7b3dSmrg#define FORCE_GPU	0x2
755428d7b3dSmrg#define RENDER_GPU	0x4
756428d7b3dSmrg#define IGNORE_DAMAGE	0x8
757428d7b3dSmrg#define REPLACES	0x10
758428d7b3dSmrgstruct kgem_bo *
759428d7b3dSmrgsna_drawable_use_bo(DrawablePtr drawable, unsigned flags, const BoxRec *box,
760428d7b3dSmrg		    struct sna_damage ***damage);
761428d7b3dSmrg
762428d7b3dSmrginline static int16_t bound(int16_t a, uint16_t b)
763428d7b3dSmrg{
764428d7b3dSmrg	int v = (int)a + (int)b;
765428d7b3dSmrg	if (v > MAXSHORT)
766428d7b3dSmrg		return MAXSHORT;
767428d7b3dSmrg	return v;
768428d7b3dSmrg}
769428d7b3dSmrg
770428d7b3dSmrginline static int16_t clamp(int16_t a, int16_t b)
771428d7b3dSmrg{
772428d7b3dSmrg	int v = (int)a + (int)b;
773428d7b3dSmrg	if (v > MAXSHORT)
774428d7b3dSmrg		return MAXSHORT;
775428d7b3dSmrg	if (v < MINSHORT)
776428d7b3dSmrg		return MINSHORT;
777428d7b3dSmrg	return v;
778428d7b3dSmrg}
779428d7b3dSmrg
780428d7b3dSmrgstatic inline bool box_empty(const BoxRec *box)
781428d7b3dSmrg{
782428d7b3dSmrg	return box->x2 <= box->x1 || box->y2 <= box->y1;
783428d7b3dSmrg}
784428d7b3dSmrg
785428d7b3dSmrgstatic inline bool
786428d7b3dSmrgbox_covers_pixmap(PixmapPtr pixmap, const BoxRec *box)
787428d7b3dSmrg{
788428d7b3dSmrg	int w = box->x2 - box->x1;
789428d7b3dSmrg	int h = box->y2 - box->y1;
790428d7b3dSmrg	return pixmap->drawable.width <= w && pixmap->drawable.height <= h;
791428d7b3dSmrg}
792428d7b3dSmrg
793428d7b3dSmrgstatic inline bool
794428d7b3dSmrgbox_inplace(PixmapPtr pixmap, const BoxRec *box)
795428d7b3dSmrg{
796428d7b3dSmrg	struct sna *sna = to_sna_from_pixmap(pixmap);
797428d7b3dSmrg	return ((int)(box->x2 - box->x1) * (int)(box->y2 - box->y1) * pixmap->drawable.bitsPerPixel >> 12) >= sna->kgem.half_cpu_cache_pages;
798428d7b3dSmrg}
799428d7b3dSmrg
800428d7b3dSmrgstatic inline bool
801428d7b3dSmrgwhole_pixmap_inplace(PixmapPtr pixmap)
802428d7b3dSmrg{
803428d7b3dSmrg	struct sna *sna = to_sna_from_pixmap(pixmap);
804428d7b3dSmrg	return ((int)pixmap->drawable.width * (int)pixmap->drawable.height * pixmap->drawable.bitsPerPixel >> 12) >= sna->kgem.half_cpu_cache_pages;
805428d7b3dSmrg}
806428d7b3dSmrg
807428d7b3dSmrgstatic inline bool
808428d7b3dSmrgregion_subsumes_drawable(RegionPtr region, DrawablePtr drawable)
809428d7b3dSmrg{
810428d7b3dSmrg	const BoxRec *extents;
811428d7b3dSmrg
812428d7b3dSmrg	if (region->data)
813428d7b3dSmrg		return false;
814428d7b3dSmrg
815428d7b3dSmrg	extents = RegionExtents(region);
816428d7b3dSmrg	return  extents->x1 <= 0 && extents->y1 <= 0 &&
817428d7b3dSmrg		extents->x2 >= drawable->width &&
818428d7b3dSmrg		extents->y2 >= drawable->height;
819428d7b3dSmrg}
820428d7b3dSmrg
821428d7b3dSmrgstatic inline bool
822428d7b3dSmrgregion_subsumes_pixmap(const RegionRec *region, PixmapPtr pixmap)
823428d7b3dSmrg{
824428d7b3dSmrg	if (region->data)
825428d7b3dSmrg		return false;
826428d7b3dSmrg
827428d7b3dSmrg	return (region->extents.x2 - region->extents.x1 >= pixmap->drawable.width &&
828428d7b3dSmrg		region->extents.y2 - region->extents.y1 >= pixmap->drawable.height);
829428d7b3dSmrg}
830428d7b3dSmrg
831428d7b3dSmrgstatic inline bool
832428d7b3dSmrgregion_subsumes_damage(const RegionRec *region, struct sna_damage *damage)
833428d7b3dSmrg{
834428d7b3dSmrg	const BoxRec *re, *de;
835428d7b3dSmrg
836428d7b3dSmrg	DBG(("%s?\n", __FUNCTION__));
837428d7b3dSmrg	assert(damage);
838428d7b3dSmrg
839428d7b3dSmrg	re = &region->extents;
840428d7b3dSmrg	de = &DAMAGE_PTR(damage)->extents;
841428d7b3dSmrg	DBG(("%s: region (%d, %d), (%d, %d), damage (%d, %d), (%d, %d)\n",
842428d7b3dSmrg	     __FUNCTION__,
843428d7b3dSmrg	     re->x1, re->y1, re->x2, re->y2,
844428d7b3dSmrg	     de->x1, de->y1, de->x2, de->y2));
845428d7b3dSmrg
846428d7b3dSmrg	if (re->x2 < de->x2 || re->x1 > de->x1 ||
847428d7b3dSmrg	    re->y2 < de->y2 || re->y1 > de->y1) {
848428d7b3dSmrg		DBG(("%s: not contained\n", __FUNCTION__));
849428d7b3dSmrg		return false;
850428d7b3dSmrg	}
851428d7b3dSmrg
852428d7b3dSmrg	if (region->data == NULL) {
853428d7b3dSmrg		DBG(("%s: singular region contains damage\n", __FUNCTION__));
854428d7b3dSmrg		return true;
855428d7b3dSmrg	}
856428d7b3dSmrg
857428d7b3dSmrg	return pixman_region_contains_rectangle((RegionPtr)region,
858428d7b3dSmrg						(BoxPtr)de) == PIXMAN_REGION_IN;
859428d7b3dSmrg}
860428d7b3dSmrg
861428d7b3dSmrgstatic inline bool
862428d7b3dSmrgsna_drawable_is_clear(DrawablePtr d)
863428d7b3dSmrg{
864428d7b3dSmrg	struct sna_pixmap *priv = sna_pixmap(get_drawable_pixmap(d));
865428d7b3dSmrg	return priv && priv->clear && priv->clear_color == 0;
866428d7b3dSmrg}
867428d7b3dSmrg
868428d7b3dSmrgstatic inline struct kgem_bo *__sna_pixmap_get_bo(PixmapPtr pixmap)
869428d7b3dSmrg{
870428d7b3dSmrg	return sna_pixmap(pixmap)->gpu_bo;
871428d7b3dSmrg}
872428d7b3dSmrg
873428d7b3dSmrgstatic inline struct kgem_bo *__sna_drawable_peek_bo(DrawablePtr d)
874428d7b3dSmrg{
875428d7b3dSmrg	struct sna_pixmap *priv = sna_pixmap(get_drawable_pixmap(d));
876428d7b3dSmrg	return priv ? priv->gpu_bo : NULL;
877428d7b3dSmrg}
878428d7b3dSmrg
879428d7b3dSmrgstatic inline struct kgem_bo *sna_pixmap_pin(PixmapPtr pixmap, unsigned flags)
880428d7b3dSmrg{
881428d7b3dSmrg	struct sna_pixmap *priv;
882428d7b3dSmrg
883428d7b3dSmrg	priv = sna_pixmap_force_to_gpu(pixmap, MOVE_READ);
884428d7b3dSmrg	if (!priv)
885428d7b3dSmrg		return NULL;
886428d7b3dSmrg
887428d7b3dSmrg	priv->pinned |= flags;
888428d7b3dSmrg	return priv->gpu_bo;
889428d7b3dSmrg}
890428d7b3dSmrg
891428d7b3dSmrg
892428d7b3dSmrgstatic inline bool
893428d7b3dSmrg_sna_transform_point(const PictTransform *transform,
894428d7b3dSmrg		     int64_t x, int64_t y, int64_t result[3])
895428d7b3dSmrg{
896428d7b3dSmrg	int j;
897428d7b3dSmrg
898428d7b3dSmrg	for (j = 0; j < 3; j++)
899428d7b3dSmrg		result[j] = (transform->matrix[j][0] * x +
900428d7b3dSmrg			     transform->matrix[j][1] * y +
901428d7b3dSmrg			     transform->matrix[j][2]);
902428d7b3dSmrg
903428d7b3dSmrg	return result[2] != 0;
904428d7b3dSmrg}
905428d7b3dSmrg
906428d7b3dSmrgstatic inline void
907428d7b3dSmrg_sna_get_transformed_coordinates(int x, int y,
908428d7b3dSmrg				 const PictTransform *transform,
909428d7b3dSmrg				 float *x_out, float *y_out)
910428d7b3dSmrg{
911428d7b3dSmrg
912428d7b3dSmrg	int64_t result[3];
913428d7b3dSmrg
914428d7b3dSmrg	_sna_transform_point(transform, x, y, result);
915428d7b3dSmrg	*x_out = result[0] / (double)result[2];
916428d7b3dSmrg	*y_out = result[1] / (double)result[2];
917428d7b3dSmrg}
918428d7b3dSmrg
919428d7b3dSmrgstatic inline void
920428d7b3dSmrg_sna_get_transformed_scaled(int x, int y,
921428d7b3dSmrg			    const PictTransform *transform, const float *sf,
922428d7b3dSmrg			    float *x_out, float *y_out)
923428d7b3dSmrg{
924428d7b3dSmrg	*x_out = sf[0] * (transform->matrix[0][0] * x +
925428d7b3dSmrg			  transform->matrix[0][1] * y +
926428d7b3dSmrg			  transform->matrix[0][2]);
927428d7b3dSmrg
928428d7b3dSmrg	*y_out = sf[1] * (transform->matrix[1][0] * x +
929428d7b3dSmrg			  transform->matrix[1][1] * y +
930428d7b3dSmrg			  transform->matrix[1][2]);
931428d7b3dSmrg}
932428d7b3dSmrg
933428d7b3dSmrgvoid
934428d7b3dSmrgsna_get_transformed_coordinates(int x, int y,
935428d7b3dSmrg				const PictTransform *transform,
936428d7b3dSmrg				float *x_out, float *y_out);
937428d7b3dSmrg
938428d7b3dSmrgvoid
939428d7b3dSmrgsna_get_transformed_coordinates_3d(int x, int y,
940428d7b3dSmrg				   const PictTransform *transform,
941428d7b3dSmrg				   float *x_out, float *y_out, float *z_out);
942428d7b3dSmrg
943428d7b3dSmrgbool sna_transform_is_affine(const PictTransform *t);
944428d7b3dSmrgbool sna_transform_is_translation(const PictTransform *t,
945428d7b3dSmrg				  pixman_fixed_t *tx, pixman_fixed_t *ty);
946428d7b3dSmrgbool sna_transform_is_integer_translation(const PictTransform *t,
947428d7b3dSmrg					  int16_t *tx, int16_t *ty);
948428d7b3dSmrgbool sna_transform_is_imprecise_integer_translation(const PictTransform *t,
949428d7b3dSmrg					       int filter, bool precise,
950428d7b3dSmrg					       int16_t *tx, int16_t *ty);
951428d7b3dSmrgstatic inline bool
952428d7b3dSmrgsna_affine_transform_is_rotation(const PictTransform *t)
953428d7b3dSmrg{
954428d7b3dSmrg	assert(sna_transform_is_affine(t));
955428d7b3dSmrg	return t->matrix[0][1] | t->matrix[1][0];
956428d7b3dSmrg}
957428d7b3dSmrg
958428d7b3dSmrgstatic inline bool
959428d7b3dSmrgsna_transform_equal(const PictTransform *a, const PictTransform *b)
960428d7b3dSmrg{
961428d7b3dSmrg	if (a == b)
962428d7b3dSmrg		return true;
963428d7b3dSmrg
964428d7b3dSmrg	if (a == NULL || b == NULL)
965428d7b3dSmrg		return false;
966428d7b3dSmrg
967428d7b3dSmrg	return memcmp(a, b, sizeof(*a)) == 0;
968428d7b3dSmrg}
969428d7b3dSmrg
970428d7b3dSmrgstatic inline bool
971428d7b3dSmrgsna_picture_alphamap_equal(PicturePtr a, PicturePtr b)
972428d7b3dSmrg{
973428d7b3dSmrg	if (a->alphaMap != b->alphaMap)
974428d7b3dSmrg		return false;
975428d7b3dSmrg
976428d7b3dSmrg	if (a->alphaMap)
977428d7b3dSmrg		return false;
978428d7b3dSmrg
979428d7b3dSmrg	return (a->alphaOrigin.x == b->alphaOrigin.x &&
980428d7b3dSmrg		a->alphaOrigin.y == b->alphaOrigin.y);
981428d7b3dSmrg}
982428d7b3dSmrg
983428d7b3dSmrgstatic inline bool wedged(struct sna *sna)
984428d7b3dSmrg{
985428d7b3dSmrg	return unlikely(sna->kgem.wedged);
986428d7b3dSmrg}
987428d7b3dSmrg
988428d7b3dSmrgstatic inline bool can_render(struct sna *sna)
989428d7b3dSmrg{
990428d7b3dSmrg	return likely(!sna->kgem.wedged && sna->render.prefer_gpu & PREFER_GPU_RENDER);
991428d7b3dSmrg}
992428d7b3dSmrg
993428d7b3dSmrgstatic inline uint32_t pixmap_size(PixmapPtr pixmap)
994428d7b3dSmrg{
995428d7b3dSmrg	return (pixmap->drawable.height - 1) * pixmap->devKind +
996428d7b3dSmrg		pixmap->drawable.width * pixmap->drawable.bitsPerPixel/8;
997428d7b3dSmrg}
998428d7b3dSmrg
999428d7b3dSmrgbool sna_accel_init(ScreenPtr sreen, struct sna *sna);
1000428d7b3dSmrgvoid sna_accel_create(struct sna *sna);
1001428d7b3dSmrg#if ABI_VIDEODRV_VERSION < SET_ABI_VERSION(23, 0)
1002428d7b3dSmrgvoid sna_accel_block_handler(struct sna *sna, struct timeval **tv);
1003428d7b3dSmrg#else
1004428d7b3dSmrgvoid sna_accel_block_handler(struct sna *sna, int *tv_msec);
1005428d7b3dSmrg#endif
1006428d7b3dSmrgvoid sna_accel_wakeup_handler(struct sna *sna);
1007428d7b3dSmrgvoid sna_accel_watch_flush(struct sna *sna, int enable);
1008428d7b3dSmrgvoid sna_accel_flush(struct sna *sna);
1009428d7b3dSmrgvoid sna_accel_enter(struct sna *sna);
1010428d7b3dSmrgvoid sna_accel_leave(struct sna *sna);
1011428d7b3dSmrgvoid sna_accel_close(struct sna *sna);
1012428d7b3dSmrgvoid sna_accel_free(struct sna *sna);
1013428d7b3dSmrg
1014428d7b3dSmrgvoid sna_copy_fbcon(struct sna *sna);
1015428d7b3dSmrg
1016428d7b3dSmrgbool sna_composite_create(struct sna *sna);
1017428d7b3dSmrgvoid sna_composite_close(struct sna *sna);
1018428d7b3dSmrg
1019428d7b3dSmrgvoid sna_composite(CARD8 op,
1020428d7b3dSmrg		   PicturePtr src,
1021428d7b3dSmrg		   PicturePtr mask,
1022428d7b3dSmrg		   PicturePtr dst,
1023428d7b3dSmrg		   INT16 src_x,  INT16 src_y,
1024428d7b3dSmrg		   INT16 mask_x, INT16 mask_y,
1025428d7b3dSmrg		   INT16 dst_x,  INT16 dst_y,
1026428d7b3dSmrg		   CARD16 width, CARD16 height);
1027428d7b3dSmrgvoid sna_composite_fb(CARD8 op,
1028428d7b3dSmrg		      PicturePtr src,
1029428d7b3dSmrg		      PicturePtr mask,
1030428d7b3dSmrg		      PicturePtr dst,
1031428d7b3dSmrg		      RegionPtr region,
1032428d7b3dSmrg		      INT16 src_x,  INT16 src_y,
1033428d7b3dSmrg		      INT16 mask_x, INT16 mask_y,
1034428d7b3dSmrg		      INT16 dst_x,  INT16 dst_y,
1035428d7b3dSmrg		      CARD16 width, CARD16 height);
1036428d7b3dSmrgvoid sna_composite_rectangles(CARD8		 op,
1037428d7b3dSmrg			      PicturePtr		 dst,
1038428d7b3dSmrg			      xRenderColor	*color,
1039428d7b3dSmrg			      int			 num_rects,
1040428d7b3dSmrg			      xRectangle		*rects);
1041428d7b3dSmrgvoid sna_composite_trapezoids(CARD8 op,
1042428d7b3dSmrg			      PicturePtr src,
1043428d7b3dSmrg			      PicturePtr dst,
1044428d7b3dSmrg			      PictFormatPtr maskFormat,
1045428d7b3dSmrg			      INT16 xSrc, INT16 ySrc,
1046428d7b3dSmrg			      int ntrap, xTrapezoid *traps);
1047428d7b3dSmrgvoid sna_add_traps(PicturePtr picture, INT16 x, INT16 y, int n, xTrap *t);
1048428d7b3dSmrg
1049428d7b3dSmrgvoid sna_composite_triangles(CARD8 op,
1050428d7b3dSmrg			     PicturePtr src,
1051428d7b3dSmrg			     PicturePtr dst,
1052428d7b3dSmrg			     PictFormatPtr maskFormat,
1053428d7b3dSmrg			     INT16 xSrc, INT16 ySrc,
1054428d7b3dSmrg			     int ntri, xTriangle *tri);
1055428d7b3dSmrg
1056428d7b3dSmrgvoid sna_composite_tristrip(CARD8 op,
1057428d7b3dSmrg			    PicturePtr src,
1058428d7b3dSmrg			    PicturePtr dst,
1059428d7b3dSmrg			    PictFormatPtr maskFormat,
1060428d7b3dSmrg			    INT16 xSrc, INT16 ySrc,
1061428d7b3dSmrg			    int npoints, xPointFixed *points);
1062428d7b3dSmrg
1063428d7b3dSmrgvoid sna_composite_trifan(CARD8 op,
1064428d7b3dSmrg			  PicturePtr src,
1065428d7b3dSmrg			  PicturePtr dst,
1066428d7b3dSmrg			  PictFormatPtr maskFormat,
1067428d7b3dSmrg			  INT16 xSrc, INT16 ySrc,
1068428d7b3dSmrg			  int npoints, xPointFixed *points);
1069428d7b3dSmrg
1070428d7b3dSmrgbool sna_gradients_create(struct sna *sna);
1071428d7b3dSmrgvoid sna_gradients_close(struct sna *sna);
1072428d7b3dSmrg
1073428d7b3dSmrgbool sna_glyphs_create(struct sna *sna);
1074428d7b3dSmrgvoid sna_glyphs(CARD8 op,
1075428d7b3dSmrg		PicturePtr src,
1076428d7b3dSmrg		PicturePtr dst,
1077428d7b3dSmrg		PictFormatPtr mask,
1078428d7b3dSmrg		INT16 xSrc, INT16 ySrc,
1079428d7b3dSmrg		int nlist,
1080428d7b3dSmrg		GlyphListPtr list,
1081428d7b3dSmrg		GlyphPtr *glyphs);
1082428d7b3dSmrgvoid sna_glyphs__shared(CARD8 op,
1083428d7b3dSmrg			PicturePtr src,
1084428d7b3dSmrg			PicturePtr dst,
1085428d7b3dSmrg			PictFormatPtr mask,
1086428d7b3dSmrg			INT16 src_x, INT16 src_y,
1087428d7b3dSmrg			int nlist, GlyphListPtr list, GlyphPtr *glyphs);
1088428d7b3dSmrgvoid sna_glyph_unrealize(ScreenPtr screen, GlyphPtr glyph);
1089428d7b3dSmrgvoid sna_glyphs_close(struct sna *sna);
1090428d7b3dSmrg
1091428d7b3dSmrgvoid sna_read_boxes(struct sna *sna, PixmapPtr dst, struct kgem_bo *src_bo,
1092428d7b3dSmrg		    const BoxRec *box, int n);
1093428d7b3dSmrgbool sna_write_boxes(struct sna *sna, PixmapPtr dst,
1094428d7b3dSmrg		     struct kgem_bo *dst_bo, int16_t dst_dx, int16_t dst_dy,
1095428d7b3dSmrg		     const void *src, int stride, int16_t src_dx, int16_t src_dy,
1096428d7b3dSmrg		     const BoxRec *box, int n);
1097428d7b3dSmrgbool sna_write_boxes__xor(struct sna *sna, PixmapPtr dst,
1098428d7b3dSmrg			  struct kgem_bo *dst_bo, int16_t dst_dx, int16_t dst_dy,
1099428d7b3dSmrg			  const void *src, int stride, int16_t src_dx, int16_t src_dy,
1100428d7b3dSmrg			  const BoxRec *box, int nbox,
1101428d7b3dSmrg			  uint32_t and, uint32_t or);
1102428d7b3dSmrg
1103428d7b3dSmrgbool sna_replace(struct sna *sna,
1104428d7b3dSmrg		 PixmapPtr pixmap,
1105428d7b3dSmrg		 const void *src, int stride);
1106428d7b3dSmrgbool sna_replace__xor(struct sna *sna,
1107428d7b3dSmrg		      PixmapPtr pixmap,
1108428d7b3dSmrg		      const void *src, int stride,
1109428d7b3dSmrg		      uint32_t and, uint32_t or);
1110428d7b3dSmrg
1111428d7b3dSmrgbool
1112428d7b3dSmrgsna_compute_composite_extents(BoxPtr extents,
1113428d7b3dSmrg			      PicturePtr src, PicturePtr mask, PicturePtr dst,
1114428d7b3dSmrg			      INT16 src_x,  INT16 src_y,
1115428d7b3dSmrg			      INT16 mask_x, INT16 mask_y,
1116428d7b3dSmrg			      INT16 dst_x,  INT16 dst_y,
1117428d7b3dSmrg			      CARD16 width, CARD16 height);
1118428d7b3dSmrgbool
1119428d7b3dSmrgsna_compute_composite_region(RegionPtr region,
1120428d7b3dSmrg			     PicturePtr src, PicturePtr mask, PicturePtr dst,
1121428d7b3dSmrg			     INT16 src_x,  INT16 src_y,
1122428d7b3dSmrg			     INT16 mask_x, INT16 mask_y,
1123428d7b3dSmrg			     INT16 dst_x,  INT16 dst_y,
1124428d7b3dSmrg			     CARD16 width, CARD16 height);
1125428d7b3dSmrg
1126428d7b3dSmrgvoid
1127428d7b3dSmrgmemcpy_blt(const void *src, void *dst, int bpp,
1128428d7b3dSmrg	   int32_t src_stride, int32_t dst_stride,
1129428d7b3dSmrg	   int16_t src_x, int16_t src_y,
1130428d7b3dSmrg	   int16_t dst_x, int16_t dst_y,
1131428d7b3dSmrg	   uint16_t width, uint16_t height);
1132428d7b3dSmrg
1133428d7b3dSmrgvoid
1134428d7b3dSmrgmemmove_box(const void *src, void *dst,
1135428d7b3dSmrg	    int bpp, int32_t stride,
1136428d7b3dSmrg	    const BoxRec *box,
1137428d7b3dSmrg	    int dx, int dy);
1138428d7b3dSmrg
1139428d7b3dSmrgvoid
1140428d7b3dSmrgmemcpy_xor(const void *src, void *dst, int bpp,
1141428d7b3dSmrg	   int32_t src_stride, int32_t dst_stride,
1142428d7b3dSmrg	   int16_t src_x, int16_t src_y,
1143428d7b3dSmrg	   int16_t dst_x, int16_t dst_y,
1144428d7b3dSmrg	   uint16_t width, uint16_t height,
1145428d7b3dSmrg	   uint32_t and, uint32_t or);
1146428d7b3dSmrg
1147428d7b3dSmrg#define SNA_CREATE_FB 0x10
1148428d7b3dSmrg#define SNA_CREATE_SCRATCH 0x11
1149428d7b3dSmrg
1150428d7b3dSmrginline static bool is_power_of_two(unsigned x)
1151428d7b3dSmrg{
1152428d7b3dSmrg	return (x & (x-1)) == 0;
1153428d7b3dSmrg}
1154428d7b3dSmrg
1155428d7b3dSmrginline static bool is_clipped(const RegionRec *r,
1156428d7b3dSmrg			      const DrawableRec *d)
1157428d7b3dSmrg{
1158428d7b3dSmrg	DBG(("%s: region[%d]x(%d, %d),(%d, %d) against drawable %dx%d\n",
1159428d7b3dSmrg	     __FUNCTION__,
1160428d7b3dSmrg	     region_num_rects(r),
1161428d7b3dSmrg	     r->extents.x1, r->extents.y1,
1162428d7b3dSmrg	     r->extents.x2, r->extents.y2,
1163428d7b3dSmrg	     d->width, d->height));
1164428d7b3dSmrg	return (r->data ||
1165428d7b3dSmrg		r->extents.x2 - r->extents.x1 != d->width ||
1166428d7b3dSmrg		r->extents.y2 - r->extents.y1 != d->height);
1167428d7b3dSmrg}
1168428d7b3dSmrg
1169428d7b3dSmrginline static bool
1170428d7b3dSmrgbox_intersect(BoxPtr a, const BoxRec *b)
1171428d7b3dSmrg{
1172428d7b3dSmrg	if (a->x1 < b->x1)
1173428d7b3dSmrg		a->x1 = b->x1;
1174428d7b3dSmrg	if (a->x2 > b->x2)
1175428d7b3dSmrg		a->x2 = b->x2;
1176428d7b3dSmrg	if (a->x1 >= a->x2)
1177428d7b3dSmrg		return false;
1178428d7b3dSmrg
1179428d7b3dSmrg	if (a->y1 < b->y1)
1180428d7b3dSmrg		a->y1 = b->y1;
1181428d7b3dSmrg	if (a->y2 > b->y2)
1182428d7b3dSmrg		a->y2 = b->y2;
1183428d7b3dSmrg	if (a->y1 >= a->y2)
1184428d7b3dSmrg		return false;
1185428d7b3dSmrg
1186428d7b3dSmrg	return true;
1187428d7b3dSmrg}
1188428d7b3dSmrg
1189428d7b3dSmrgunsigned sna_cpu_detect(void);
1190428d7b3dSmrgchar *sna_cpu_features_to_string(unsigned features, char *line);
1191428d7b3dSmrg
1192428d7b3dSmrg/* sna_acpi.c */
1193428d7b3dSmrgint sna_acpi_open(void);
1194428d7b3dSmrgvoid sna_acpi_init(struct sna *sna);
1195428d7b3dSmrgvoid _sna_acpi_wakeup(struct sna *sna);
1196428d7b3dSmrgstatic inline void sna_acpi_wakeup(struct sna *sna)
1197428d7b3dSmrg{
1198428d7b3dSmrg	_sna_acpi_wakeup(sna);
1199428d7b3dSmrg}
1200428d7b3dSmrgvoid sna_acpi_fini(struct sna *sna);
1201428d7b3dSmrg
1202428d7b3dSmrgvoid sna_threads_init(void);
1203428d7b3dSmrgint sna_use_threads (int width, int height, int threshold);
1204428d7b3dSmrgvoid sna_threads_run(int id, void (*func)(void *arg), void *arg);
1205428d7b3dSmrgvoid sna_threads_trap(int sig);
1206428d7b3dSmrgvoid sna_threads_wait(void);
1207428d7b3dSmrgvoid sna_threads_kill(void);
1208428d7b3dSmrg
1209428d7b3dSmrgvoid sna_image_composite(pixman_op_t        op,
1210428d7b3dSmrg			 pixman_image_t    *src,
1211428d7b3dSmrg			 pixman_image_t    *mask,
1212428d7b3dSmrg			 pixman_image_t    *dst,
1213428d7b3dSmrg			 int16_t            src_x,
1214428d7b3dSmrg			 int16_t            src_y,
1215428d7b3dSmrg			 int16_t            mask_x,
1216428d7b3dSmrg			 int16_t            mask_y,
1217428d7b3dSmrg			 int16_t            dst_x,
1218428d7b3dSmrg			 int16_t            dst_y,
1219428d7b3dSmrg			 uint16_t           width,
1220428d7b3dSmrg			 uint16_t           height);
1221428d7b3dSmrg
1222428d7b3dSmrgextern jmp_buf sigjmp[4];
1223428d7b3dSmrgextern volatile sig_atomic_t sigtrap;
1224428d7b3dSmrg
1225428d7b3dSmrg#define sigtrap_assert_inactive() assert(sigtrap == 0)
1226428d7b3dSmrg#define sigtrap_assert_active() assert(sigtrap > 0 && sigtrap <= ARRAY_SIZE(sigjmp))
1227428d7b3dSmrg#define sigtrap_get() sigsetjmp(sigjmp[sigtrap++], 1)
1228428d7b3dSmrg
1229428d7b3dSmrgstatic inline void sigtrap_put(void)
1230428d7b3dSmrg{
1231428d7b3dSmrg	sigtrap_assert_active();
1232428d7b3dSmrg	--sigtrap;
1233428d7b3dSmrg}
1234428d7b3dSmrg
1235428d7b3dSmrg#define RR_Rotate_All (RR_Rotate_0 | RR_Rotate_90 | RR_Rotate_180 | RR_Rotate_270)
1236428d7b3dSmrg#define RR_Reflect_All (RR_Reflect_X | RR_Reflect_Y)
1237428d7b3dSmrg
1238428d7b3dSmrg#ifndef HAVE_GETLINE
1239428d7b3dSmrg#include <stdio.h>
1240428d7b3dSmrgextern int getline(char **line, size_t *len, FILE *file);
1241428d7b3dSmrg#endif
1242428d7b3dSmrg
1243428d7b3dSmrg#endif /* _SNA_H */
1244