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	uint8_t shm :1;
158	uint8_t clear :1;
159	uint8_t header :1;
160	uint8_t cpu :1;
161};
162
163#define IS_STATIC_PTR(ptr) ((uintptr_t)(ptr) & 1)
164#define MAKE_STATIC_PTR(ptr) ((void*)((uintptr_t)(ptr) | 1))
165
166struct sna_glyph {
167	PicturePtr atlas;
168	struct sna_coordinate coordinate;
169	uint16_t size, pos;
170	pixman_image_t *image;
171};
172
173static inline WindowPtr get_root_window(ScreenPtr screen)
174{
175#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,10,0,0,0)
176	return screen->root;
177#else
178	return WindowTable[screen->myNum];
179#endif
180}
181
182static inline PixmapPtr get_window_pixmap(WindowPtr window)
183{
184	assert(window);
185	assert(window->drawable.type != DRAWABLE_PIXMAP);
186	return fbGetWindowPixmap(window);
187}
188
189static inline PixmapPtr get_drawable_pixmap(DrawablePtr drawable)
190{
191	assert(drawable);
192	if (drawable->type == DRAWABLE_PIXMAP)
193		return (PixmapPtr)drawable;
194	else
195		return get_window_pixmap((WindowPtr)drawable);
196}
197
198extern DevPrivateKeyRec sna_pixmap_key;
199
200pure static inline struct sna_pixmap *sna_pixmap(PixmapPtr pixmap)
201{
202	return ((void **)__get_private(pixmap, sna_pixmap_key))[1];
203}
204
205static inline struct sna_pixmap *sna_pixmap_from_drawable(DrawablePtr drawable)
206{
207	return sna_pixmap(get_drawable_pixmap(drawable));
208}
209
210struct sna_gc {
211	long changes;
212	long serial;
213
214	const GCFuncs *old_funcs;
215	void *priv;
216};
217
218static inline struct sna_gc *sna_gc(GCPtr gc)
219{
220	return (struct sna_gc *)__get_private(gc, sna_gc_key);
221}
222
223enum {
224	FLUSH_TIMER = 0,
225	THROTTLE_TIMER,
226	EXPIRE_TIMER,
227#if DEBUG_MEMORY
228	DEBUG_MEMORY_TIMER,
229#endif
230	NUM_TIMERS
231};
232
233struct sna {
234	struct kgem kgem;
235
236	ScrnInfoPtr scrn;
237	struct intel_device *dev;
238
239	unsigned flags;
240#define SNA_IS_SLAVED		0x1
241#define SNA_IS_HOSTED		0x2
242#define SNA_NO_WAIT		0x10
243#define SNA_NO_FLIP		0x20
244#define SNA_NO_VSYNC		0x40
245#define SNA_TRIPLE_BUFFER	0x80
246#define SNA_TEAR_FREE		0x100
247#define SNA_FORCE_SHADOW	0x200
248#define SNA_FLUSH_GTT		0x400
249#define SNA_PERFORMANCE		0x1000
250#define SNA_POWERSAVE		0x2000
251#define SNA_REMOVE_OUTPUTS	0x4000
252#define SNA_HAS_FLIP		0x10000
253#define SNA_HAS_ASYNC_FLIP	0x20000
254#define SNA_LINEAR_FB		0x40000
255#define SNA_REPROBE		0x80000000
256
257	unsigned cpu_features;
258#define MMX 0x1
259#define SSE 0x2
260#define SSE2 0x4
261#define SSE3 0x8
262#define SSSE3 0x10
263#define SSE4_1 0x20
264#define SSE4_2 0x40
265#define AVX 0x80
266#define AVX2 0x100
267
268	unsigned watch_flush;
269
270	struct timeval timer_tv;
271	uint32_t timer_expire[NUM_TIMERS];
272	uint16_t timer_active;
273
274	int vblank_interval;
275
276	struct list flush_pixmaps;
277	struct list active_pixmaps;
278
279	PixmapPtr front;
280	PixmapPtr freed_pixmap;
281
282	struct sna_mode {
283		DamagePtr shadow_damage;
284		struct kgem_bo *shadow;
285		unsigned front_active;
286		unsigned shadow_active;
287		unsigned flip_active;
288		bool dirty;
289
290		int max_crtc_width, max_crtc_height;
291		RegionRec shadow_region;
292		RegionRec shadow_cancel;
293		struct list shadow_crtc;
294		bool shadow_dirty;
295
296		unsigned num_real_crtc;
297		unsigned num_real_output;
298		unsigned num_real_encoder;
299		unsigned num_fake;
300		unsigned serial;
301
302		uint32_t *encoders;
303
304#if HAVE_UDEV
305		struct udev_monitor *backlight_monitor;
306		pointer backlight_handler;
307#endif
308
309		Bool (*rrGetInfo)(ScreenPtr, Rotation *);
310	} mode;
311
312	struct {
313		struct sna_cursor *cursors;
314		xf86CursorInfoPtr info;
315		CursorPtr ref;
316
317		unsigned serial;
318		uint32_t fg, bg;
319		int size;
320
321		int active;
322		int last_x;
323		int last_y;
324
325		unsigned max_size;
326		bool use_gtt;
327
328		int num_stash;
329		struct sna_cursor *stash;
330		void *scratch;
331	} cursor;
332
333	struct sna_dri2 {
334		bool available;
335		bool open;
336
337#if HAVE_DRI2
338		void *flip_pending;
339		unsigned client_count;
340#endif
341	} dri2;
342
343	struct sna_dri3 {
344		bool available;
345		bool open;
346#if HAVE_DRI3
347		SyncScreenCreateFenceFunc create_fence;
348		struct list pixmaps;
349#endif
350	} dri3;
351
352	struct sna_present {
353		bool available;
354		bool open;
355#if HAVE_PRESENT
356#endif
357	} present;
358
359	struct sna_xv {
360		XvAdaptorPtr adaptors;
361		int num_adaptors;
362	} xv;
363
364	EntityInfoPtr pEnt;
365	const struct intel_device_info *info;
366
367	ScreenBlockHandlerProcPtr BlockHandler;
368	ScreenWakeupHandlerProcPtr WakeupHandler;
369	CloseScreenProcPtr CloseScreen;
370
371	PicturePtr clear;
372	struct {
373		uint32_t fill_bo;
374		uint32_t fill_pixel;
375		uint32_t fill_alu;
376	} blt_state;
377	union {
378		unsigned gt;
379		struct gen2_render_state gen2;
380		struct gen3_render_state gen3;
381		struct gen4_render_state gen4;
382		struct gen5_render_state gen5;
383		struct gen6_render_state gen6;
384		struct gen7_render_state gen7;
385		struct gen8_render_state gen8;
386	} render_state;
387
388	/* Broken-out options. */
389	OptionInfoPtr Options;
390
391	/* Driver phase/state information */
392	bool suspended;
393
394#if HAVE_UDEV
395	struct udev_monitor *uevent_monitor;
396	pointer uevent_handler;
397#endif
398
399	struct {
400		int fd;
401		uint8_t offset;
402		uint8_t remain;
403		char event[256];
404	} acpi;
405
406	struct sna_render render;
407
408#if DEBUG_MEMORY
409	struct {
410		int pixmap_allocs;
411		int pixmap_cached;
412		int cpu_bo_allocs;
413		size_t shadow_pixels_bytes;
414		size_t cpu_bo_bytes;
415	} debug_memory;
416#endif
417};
418
419bool sna_mode_pre_init(ScrnInfoPtr scrn, struct sna *sna);
420bool sna_mode_fake_init(struct sna *sna, int num_fake);
421bool sna_mode_wants_tear_free(struct sna *sna);
422void sna_mode_adjust_frame(struct sna *sna, int x, int y);
423extern void sna_mode_discover(struct sna *sna);
424extern void sna_mode_check(struct sna *sna);
425extern bool sna_mode_disable(struct sna *sna);
426extern void sna_mode_enable(struct sna *sna);
427extern void sna_mode_reset(struct sna *sna);
428extern int sna_mode_wakeup(struct sna *sna);
429extern void sna_mode_redisplay(struct sna *sna);
430extern void sna_shadow_set_crtc(struct sna *sna, xf86CrtcPtr crtc, struct kgem_bo *bo);
431extern void sna_shadow_steal_crtcs(struct sna *sna, struct list *list);
432extern void sna_shadow_unsteal_crtcs(struct sna *sna, struct list *list);
433extern void sna_shadow_unset_crtc(struct sna *sna, xf86CrtcPtr crtc);
434extern bool sna_pixmap_discard_shadow_damage(struct sna_pixmap *priv,
435					     const RegionRec *region);
436extern void sna_mode_set_primary(struct sna *sna);
437extern void sna_mode_close(struct sna *sna);
438extern void sna_mode_fini(struct sna *sna);
439
440extern void sna_crtc_config_notify(ScreenPtr screen);
441
442extern bool sna_cursors_init(ScreenPtr screen, struct sna *sna);
443
444typedef void (*sna_flip_handler_t)(struct drm_event_vblank *e,
445				   void *data);
446
447extern int sna_page_flip(struct sna *sna,
448			 struct kgem_bo *bo,
449			 sna_flip_handler_t handler,
450			 void *data);
451
452pure static inline struct sna *
453to_sna(ScrnInfoPtr scrn)
454{
455	return (struct sna *)(scrn->driverPrivate);
456}
457
458pure static inline struct sna *
459to_sna_from_screen(ScreenPtr screen)
460{
461	return to_sna(xf86ScreenToScrn(screen));
462}
463
464pure static inline struct sna *
465to_sna_from_pixmap(PixmapPtr pixmap)
466{
467	return ((void **)__get_private(pixmap, sna_pixmap_key))[0];
468}
469
470pure static inline struct sna *
471to_sna_from_drawable(DrawablePtr drawable)
472{
473	return to_sna_from_screen(drawable->pScreen);
474}
475
476static inline struct sna *
477to_sna_from_kgem(struct kgem *kgem)
478{
479	return container_of(kgem, struct sna, kgem);
480}
481
482#ifndef ARRAY_SIZE
483#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
484#endif
485
486#ifndef ALIGN
487#define ALIGN(i,m)	(((i) + (m) - 1) & ~((m) - 1))
488#endif
489
490#ifndef MIN
491#define MIN(a,b)	((a) <= (b) ? (a) : (b))
492#endif
493
494#ifndef MAX
495#define MAX(a,b)	((a) >= (b) ? (a) : (b))
496#endif
497
498extern xf86CrtcPtr sna_covering_crtc(struct sna *sna,
499				     const BoxRec *box,
500				     xf86CrtcPtr desired);
501
502extern bool sna_wait_for_scanline(struct sna *sna, PixmapPtr pixmap,
503				  xf86CrtcPtr crtc, const BoxRec *clip);
504
505xf86CrtcPtr sna_mode_first_crtc(struct sna *sna);
506
507const struct ust_msc {
508	uint64_t msc;
509	int tv_sec;
510	int tv_usec;
511} *sna_crtc_last_swap(xf86CrtcPtr crtc);
512
513uint64_t sna_crtc_record_swap(xf86CrtcPtr crtc,
514			      int tv_sec, int tv_usec, unsigned seq);
515
516static inline uint64_t sna_crtc_record_vblank(xf86CrtcPtr crtc,
517					      const union drm_wait_vblank *vbl)
518{
519	return sna_crtc_record_swap(crtc,
520				    vbl->reply.tval_sec,
521				    vbl->reply.tval_usec,
522				    vbl->reply.sequence);
523}
524
525static inline uint64_t sna_crtc_record_event(xf86CrtcPtr crtc,
526					     struct drm_event_vblank *event)
527{
528	return sna_crtc_record_swap(crtc,
529				    event->tv_sec,
530				    event->tv_usec,
531				    event->sequence);
532}
533
534static inline uint64_t ust64(int tv_sec, int tv_usec)
535{
536	return (uint64_t)tv_sec * 1000000 + tv_usec;
537}
538
539#if HAVE_DRI2
540bool sna_dri2_open(struct sna *sna, ScreenPtr pScreen);
541void sna_dri2_page_flip_handler(struct sna *sna, struct drm_event_vblank *event);
542void sna_dri2_vblank_handler(struct drm_event_vblank *event);
543void sna_dri2_pixmap_update_bo(struct sna *sna, PixmapPtr pixmap, struct kgem_bo *bo);
544void sna_dri2_decouple_window(WindowPtr win);
545void sna_dri2_destroy_window(WindowPtr win);
546void sna_dri2_close(struct sna *sna, ScreenPtr pScreen);
547#else
548static inline bool sna_dri2_open(struct sna *sna, ScreenPtr pScreen) { return false; }
549static inline void sna_dri2_page_flip_handler(struct sna *sna, struct drm_event_vblank *event) { }
550static inline void sna_dri2_vblank_handler(struct drm_event_vblank *event) { }
551static inline void sna_dri2_pixmap_update_bo(struct sna *sna, PixmapPtr pixmap, struct kgem_bo *bo) { }
552static inline void sna_dri2_decouple_window(WindowPtr win) { }
553static inline void sna_dri2_destroy_window(WindowPtr win) { }
554static inline void sna_dri2_close(struct sna *sna, ScreenPtr pScreen) { }
555#endif
556
557#if HAVE_DRI3
558bool sna_dri3_open(struct sna *sna, ScreenPtr pScreen);
559void sna_dri3_close(struct sna *sna, ScreenPtr pScreen);
560#else
561static inline bool sna_dri3_open(struct sna *sna, ScreenPtr pScreen) { return false; }
562static inline void sna_dri3_close(struct sna *sna, ScreenPtr pScreen) { }
563#endif
564
565#if HAVE_PRESENT
566bool sna_present_open(struct sna *sna, ScreenPtr pScreen);
567void sna_present_update(struct sna *sna);
568void sna_present_close(struct sna *sna, ScreenPtr pScreen);
569void sna_present_vblank_handler(struct drm_event_vblank *event);
570#else
571static inline bool sna_present_open(struct sna *sna, ScreenPtr pScreen) { return false; }
572static inline void sna_present_update(struct sna *sna) { }
573static inline void sna_present_close(struct sna *sna, ScreenPtr pScreen) { }
574static inline void sna_present_vblank_handler(struct drm_event_vblank *event) { }
575#endif
576
577extern bool sna_crtc_set_sprite_rotation(xf86CrtcPtr crtc, uint32_t rotation);
578extern int sna_crtc_to_pipe(xf86CrtcPtr crtc);
579extern uint32_t sna_crtc_to_sprite(xf86CrtcPtr crtc);
580extern uint32_t sna_crtc_id(xf86CrtcPtr crtc);
581extern bool sna_crtc_is_on(xf86CrtcPtr crtc);
582extern bool sna_crtc_is_transformed(xf86CrtcPtr crtc);
583
584CARD32 sna_format_for_depth(int depth);
585CARD32 sna_render_format_for_depth(int depth);
586
587void sna_debug_flush(struct sna *sna);
588
589static inline bool
590get_window_deltas(PixmapPtr pixmap, int16_t *x, int16_t *y)
591{
592#ifdef COMPOSITE
593	*x = -pixmap->screen_x;
594	*y = -pixmap->screen_y;
595	return pixmap->screen_x | pixmap->screen_y;
596#else
597	*x = *y = 0;
598	return false;
599#endif
600}
601
602static inline bool
603get_drawable_deltas(DrawablePtr drawable, PixmapPtr pixmap, int16_t *x, int16_t *y)
604{
605#ifdef COMPOSITE
606	if (drawable->type == DRAWABLE_WINDOW)
607		return get_window_deltas(pixmap, x, y);
608#endif
609	*x = *y = 0;
610	return false;
611}
612
613static inline int
614get_drawable_dx(DrawablePtr drawable)
615{
616#ifdef COMPOSITE
617	if (drawable->type == DRAWABLE_WINDOW)
618		return -get_drawable_pixmap(drawable)->screen_x;
619#endif
620	return 0;
621}
622
623static inline int
624get_drawable_dy(DrawablePtr drawable)
625{
626#ifdef COMPOSITE
627	if (drawable->type == DRAWABLE_WINDOW)
628		return -get_drawable_pixmap(drawable)->screen_y;
629#endif
630	return 0;
631}
632
633struct sna_pixmap *sna_pixmap_attach_to_bo(PixmapPtr pixmap, struct kgem_bo *bo);
634static inline bool sna_pixmap_is_scanout(struct sna *sna, PixmapPtr pixmap)
635{
636	return (pixmap == sna->front &&
637		!sna->mode.shadow_active &&
638		(sna->flags & SNA_NO_WAIT) == 0);
639}
640
641static inline int sna_max_tile_copy_size(struct sna *sna, struct kgem_bo *src, struct kgem_bo *dst)
642{
643	int min_object;
644	int max_size;
645
646	max_size = sna->kgem.aperture_high * PAGE_SIZE;
647	max_size -= MAX(kgem_bo_size(src), kgem_bo_size(dst));
648	if (max_size <= 0) {
649		DBG(("%s: tiles cannot fit into aperture\n", __FUNCTION__));
650		return 0;
651	}
652
653	if (max_size > sna->kgem.max_copy_tile_size)
654		max_size = sna->kgem.max_copy_tile_size;
655
656	min_object = MIN(kgem_bo_size(src), kgem_bo_size(dst)) / 2;
657	if (max_size > min_object)
658		max_size = min_object;
659	if (max_size <= 4096)
660		max_size = 0;
661
662	DBG(("%s: using max tile size of %d\n", __FUNCTION__, max_size));
663	return max_size;
664}
665
666PixmapPtr sna_pixmap_create_upload(ScreenPtr screen,
667				   int width, int height, int depth,
668				   unsigned flags);
669PixmapPtr sna_pixmap_create_unattached(ScreenPtr screen,
670				       int width, int height, int depth);
671void sna_pixmap_destroy(PixmapPtr pixmap);
672
673#define assert_pixmap_map(pixmap, priv)  do { \
674	assert(priv->mapped != MAPPED_NONE || pixmap->devPrivate.ptr == PTR(priv->ptr)); \
675	assert(priv->mapped != MAPPED_CPU || pixmap->devPrivate.ptr == MAP(priv->gpu_bo->map__cpu)); \
676	assert(priv->mapped != MAPPED_GTT || pixmap->devPrivate.ptr == priv->gpu_bo->map__gtt || pixmap->devPrivate.ptr == priv->gpu_bo->map__wc); \
677} while (0)
678
679static inline void sna_pixmap_unmap(PixmapPtr pixmap, struct sna_pixmap *priv)
680{
681	if (priv->mapped == MAPPED_NONE) {
682		assert(pixmap->devPrivate.ptr == PTR(priv->ptr));
683		return;
684	}
685
686	DBG(("%s: pixmap=%ld dropping %s mapping\n",
687	     __FUNCTION__, pixmap->drawable.serialNumber,
688	     priv->mapped == MAPPED_CPU ? "cpu" : "gtt"));
689
690	assert_pixmap_map(pixmap, priv);
691
692	pixmap->devPrivate.ptr = PTR(priv->ptr);
693	pixmap->devKind = priv->stride;
694
695	priv->mapped = MAPPED_NONE;
696}
697
698bool
699sna_pixmap_undo_cow(struct sna *sna, struct sna_pixmap *priv, unsigned flags);
700
701#define MOVE_WRITE 0x1
702#define MOVE_READ 0x2
703#define MOVE_INPLACE_HINT 0x4
704#define MOVE_ASYNC_HINT 0x8
705#define MOVE_SOURCE_HINT 0x10
706#define MOVE_WHOLE_HINT 0x20
707#define __MOVE_FORCE 0x40
708#define __MOVE_DRI 0x80
709#define __MOVE_SCANOUT 0x100
710#define __MOVE_TILED 0x200
711#define __MOVE_PRIME 0x400
712
713struct sna_pixmap *
714sna_pixmap_move_area_to_gpu(PixmapPtr pixmap, const BoxRec *box, unsigned int flags);
715
716struct sna_pixmap *sna_pixmap_move_to_gpu(PixmapPtr pixmap, unsigned flags);
717static inline struct sna_pixmap *
718sna_pixmap_force_to_gpu(PixmapPtr pixmap, unsigned flags)
719{
720	/* Unlike move-to-gpu, we ignore wedged and always create the GPU bo */
721	DBG(("%s(pixmap=%ld, flags=%x)\n", __FUNCTION__, pixmap->drawable.serialNumber, flags));
722	return sna_pixmap_move_to_gpu(pixmap, flags | __MOVE_FORCE);
723}
724bool must_check _sna_pixmap_move_to_cpu(PixmapPtr pixmap, unsigned flags);
725static inline bool must_check sna_pixmap_move_to_cpu(PixmapPtr pixmap, unsigned flags)
726{
727	if (flags == MOVE_READ) {
728		struct sna_pixmap *priv = sna_pixmap(pixmap);
729		if (priv == NULL)
730			return true;
731	}
732
733	return _sna_pixmap_move_to_cpu(pixmap, flags);
734}
735bool must_check sna_drawable_move_region_to_cpu(DrawablePtr drawable,
736						RegionPtr region,
737						unsigned flags);
738
739bool must_check sna_drawable_move_to_cpu(DrawablePtr drawable, unsigned flags);
740
741static inline bool must_check
742sna_drawable_move_to_gpu(DrawablePtr drawable, unsigned flags)
743{
744	return sna_pixmap_move_to_gpu(get_drawable_pixmap(drawable), flags) != NULL;
745}
746
747void sna_add_flush_pixmap(struct sna *sna,
748			  struct sna_pixmap *priv,
749			  struct kgem_bo *bo);
750
751struct kgem_bo *sna_pixmap_change_tiling(PixmapPtr pixmap, uint32_t tiling);
752
753#define PREFER_GPU	0x1
754#define FORCE_GPU	0x2
755#define RENDER_GPU	0x4
756#define IGNORE_DAMAGE	0x8
757#define REPLACES	0x10
758struct kgem_bo *
759sna_drawable_use_bo(DrawablePtr drawable, unsigned flags, const BoxRec *box,
760		    struct sna_damage ***damage);
761
762inline static int16_t bound(int16_t a, uint16_t b)
763{
764	int v = (int)a + (int)b;
765	if (v > MAXSHORT)
766		return MAXSHORT;
767	return v;
768}
769
770inline static int16_t clamp(int16_t a, int16_t b)
771{
772	int v = (int)a + (int)b;
773	if (v > MAXSHORT)
774		return MAXSHORT;
775	if (v < MINSHORT)
776		return MINSHORT;
777	return v;
778}
779
780static inline bool box_empty(const BoxRec *box)
781{
782	return box->x2 <= box->x1 || box->y2 <= box->y1;
783}
784
785static inline bool
786box_covers_pixmap(PixmapPtr pixmap, const BoxRec *box)
787{
788	int w = box->x2 - box->x1;
789	int h = box->y2 - box->y1;
790	return pixmap->drawable.width <= w && pixmap->drawable.height <= h;
791}
792
793static inline bool
794box_inplace(PixmapPtr pixmap, const BoxRec *box)
795{
796	struct sna *sna = to_sna_from_pixmap(pixmap);
797	return ((int)(box->x2 - box->x1) * (int)(box->y2 - box->y1) * pixmap->drawable.bitsPerPixel >> 12) >= sna->kgem.half_cpu_cache_pages;
798}
799
800static inline bool
801whole_pixmap_inplace(PixmapPtr pixmap)
802{
803	struct sna *sna = to_sna_from_pixmap(pixmap);
804	return ((int)pixmap->drawable.width * (int)pixmap->drawable.height * pixmap->drawable.bitsPerPixel >> 12) >= sna->kgem.half_cpu_cache_pages;
805}
806
807static inline bool
808region_subsumes_drawable(RegionPtr region, DrawablePtr drawable)
809{
810	const BoxRec *extents;
811
812	if (region->data)
813		return false;
814
815	extents = RegionExtents(region);
816	return  extents->x1 <= 0 && extents->y1 <= 0 &&
817		extents->x2 >= drawable->width &&
818		extents->y2 >= drawable->height;
819}
820
821static inline bool
822region_subsumes_pixmap(const RegionRec *region, PixmapPtr pixmap)
823{
824	if (region->data)
825		return false;
826
827	return (region->extents.x2 - region->extents.x1 >= pixmap->drawable.width &&
828		region->extents.y2 - region->extents.y1 >= pixmap->drawable.height);
829}
830
831static inline bool
832region_subsumes_damage(const RegionRec *region, struct sna_damage *damage)
833{
834	const BoxRec *re, *de;
835
836	DBG(("%s?\n", __FUNCTION__));
837	assert(damage);
838
839	re = &region->extents;
840	de = &DAMAGE_PTR(damage)->extents;
841	DBG(("%s: region (%d, %d), (%d, %d), damage (%d, %d), (%d, %d)\n",
842	     __FUNCTION__,
843	     re->x1, re->y1, re->x2, re->y2,
844	     de->x1, de->y1, de->x2, de->y2));
845
846	if (re->x2 < de->x2 || re->x1 > de->x1 ||
847	    re->y2 < de->y2 || re->y1 > de->y1) {
848		DBG(("%s: not contained\n", __FUNCTION__));
849		return false;
850	}
851
852	if (region->data == NULL) {
853		DBG(("%s: singular region contains damage\n", __FUNCTION__));
854		return true;
855	}
856
857	return pixman_region_contains_rectangle((RegionPtr)region,
858						(BoxPtr)de) == PIXMAN_REGION_IN;
859}
860
861static inline bool
862sna_drawable_is_clear(DrawablePtr d)
863{
864	struct sna_pixmap *priv = sna_pixmap(get_drawable_pixmap(d));
865	return priv && priv->clear && priv->clear_color == 0;
866}
867
868static inline struct kgem_bo *__sna_pixmap_get_bo(PixmapPtr pixmap)
869{
870	return sna_pixmap(pixmap)->gpu_bo;
871}
872
873static inline struct kgem_bo *__sna_drawable_peek_bo(DrawablePtr d)
874{
875	struct sna_pixmap *priv = sna_pixmap(get_drawable_pixmap(d));
876	return priv ? priv->gpu_bo : NULL;
877}
878
879static inline struct kgem_bo *sna_pixmap_pin(PixmapPtr pixmap, unsigned flags)
880{
881	struct sna_pixmap *priv;
882
883	priv = sna_pixmap_force_to_gpu(pixmap, MOVE_READ);
884	if (!priv)
885		return NULL;
886
887	priv->pinned |= flags;
888	return priv->gpu_bo;
889}
890
891
892static inline bool
893_sna_transform_point(const PictTransform *transform,
894		     int64_t x, int64_t y, int64_t result[3])
895{
896	int j;
897
898	for (j = 0; j < 3; j++)
899		result[j] = (transform->matrix[j][0] * x +
900			     transform->matrix[j][1] * y +
901			     transform->matrix[j][2]);
902
903	return result[2] != 0;
904}
905
906static inline void
907_sna_get_transformed_coordinates(int x, int y,
908				 const PictTransform *transform,
909				 float *x_out, float *y_out)
910{
911
912	int64_t result[3];
913
914	_sna_transform_point(transform, x, y, result);
915	*x_out = result[0] / (double)result[2];
916	*y_out = result[1] / (double)result[2];
917}
918
919static inline void
920_sna_get_transformed_scaled(int x, int y,
921			    const PictTransform *transform, const float *sf,
922			    float *x_out, float *y_out)
923{
924	*x_out = sf[0] * (transform->matrix[0][0] * x +
925			  transform->matrix[0][1] * y +
926			  transform->matrix[0][2]);
927
928	*y_out = sf[1] * (transform->matrix[1][0] * x +
929			  transform->matrix[1][1] * y +
930			  transform->matrix[1][2]);
931}
932
933void
934sna_get_transformed_coordinates(int x, int y,
935				const PictTransform *transform,
936				float *x_out, float *y_out);
937
938void
939sna_get_transformed_coordinates_3d(int x, int y,
940				   const PictTransform *transform,
941				   float *x_out, float *y_out, float *z_out);
942
943bool sna_transform_is_affine(const PictTransform *t);
944bool sna_transform_is_translation(const PictTransform *t,
945				  pixman_fixed_t *tx, pixman_fixed_t *ty);
946bool sna_transform_is_integer_translation(const PictTransform *t,
947					  int16_t *tx, int16_t *ty);
948bool sna_transform_is_imprecise_integer_translation(const PictTransform *t,
949					       int filter, bool precise,
950					       int16_t *tx, int16_t *ty);
951static inline bool
952sna_affine_transform_is_rotation(const PictTransform *t)
953{
954	assert(sna_transform_is_affine(t));
955	return t->matrix[0][1] | t->matrix[1][0];
956}
957
958static inline bool
959sna_transform_equal(const PictTransform *a, const PictTransform *b)
960{
961	if (a == b)
962		return true;
963
964	if (a == NULL || b == NULL)
965		return false;
966
967	return memcmp(a, b, sizeof(*a)) == 0;
968}
969
970static inline bool
971sna_picture_alphamap_equal(PicturePtr a, PicturePtr b)
972{
973	if (a->alphaMap != b->alphaMap)
974		return false;
975
976	if (a->alphaMap)
977		return false;
978
979	return (a->alphaOrigin.x == b->alphaOrigin.x &&
980		a->alphaOrigin.y == b->alphaOrigin.y);
981}
982
983static inline bool wedged(struct sna *sna)
984{
985	return unlikely(sna->kgem.wedged);
986}
987
988static inline bool can_render(struct sna *sna)
989{
990	return likely(!sna->kgem.wedged && sna->render.prefer_gpu & PREFER_GPU_RENDER);
991}
992
993static inline uint32_t pixmap_size(PixmapPtr pixmap)
994{
995	return (pixmap->drawable.height - 1) * pixmap->devKind +
996		pixmap->drawable.width * pixmap->drawable.bitsPerPixel/8;
997}
998
999bool sna_accel_init(ScreenPtr sreen, struct sna *sna);
1000void sna_accel_create(struct sna *sna);
1001#if ABI_VIDEODRV_VERSION < SET_ABI_VERSION(23, 0)
1002void sna_accel_block_handler(struct sna *sna, struct timeval **tv);
1003#else
1004void sna_accel_block_handler(struct sna *sna, int *tv_msec);
1005#endif
1006void sna_accel_wakeup_handler(struct sna *sna);
1007void sna_accel_watch_flush(struct sna *sna, int enable);
1008void sna_accel_flush(struct sna *sna);
1009void sna_accel_enter(struct sna *sna);
1010void sna_accel_leave(struct sna *sna);
1011void sna_accel_close(struct sna *sna);
1012void sna_accel_free(struct sna *sna);
1013
1014void sna_copy_fbcon(struct sna *sna);
1015
1016bool sna_composite_create(struct sna *sna);
1017void sna_composite_close(struct sna *sna);
1018
1019void sna_composite(CARD8 op,
1020		   PicturePtr src,
1021		   PicturePtr mask,
1022		   PicturePtr dst,
1023		   INT16 src_x,  INT16 src_y,
1024		   INT16 mask_x, INT16 mask_y,
1025		   INT16 dst_x,  INT16 dst_y,
1026		   CARD16 width, CARD16 height);
1027void sna_composite_fb(CARD8 op,
1028		      PicturePtr src,
1029		      PicturePtr mask,
1030		      PicturePtr dst,
1031		      RegionPtr region,
1032		      INT16 src_x,  INT16 src_y,
1033		      INT16 mask_x, INT16 mask_y,
1034		      INT16 dst_x,  INT16 dst_y,
1035		      CARD16 width, CARD16 height);
1036void sna_composite_rectangles(CARD8		 op,
1037			      PicturePtr		 dst,
1038			      xRenderColor	*color,
1039			      int			 num_rects,
1040			      xRectangle		*rects);
1041void sna_composite_trapezoids(CARD8 op,
1042			      PicturePtr src,
1043			      PicturePtr dst,
1044			      PictFormatPtr maskFormat,
1045			      INT16 xSrc, INT16 ySrc,
1046			      int ntrap, xTrapezoid *traps);
1047void sna_add_traps(PicturePtr picture, INT16 x, INT16 y, int n, xTrap *t);
1048
1049void sna_composite_triangles(CARD8 op,
1050			     PicturePtr src,
1051			     PicturePtr dst,
1052			     PictFormatPtr maskFormat,
1053			     INT16 xSrc, INT16 ySrc,
1054			     int ntri, xTriangle *tri);
1055
1056void sna_composite_tristrip(CARD8 op,
1057			    PicturePtr src,
1058			    PicturePtr dst,
1059			    PictFormatPtr maskFormat,
1060			    INT16 xSrc, INT16 ySrc,
1061			    int npoints, xPointFixed *points);
1062
1063void sna_composite_trifan(CARD8 op,
1064			  PicturePtr src,
1065			  PicturePtr dst,
1066			  PictFormatPtr maskFormat,
1067			  INT16 xSrc, INT16 ySrc,
1068			  int npoints, xPointFixed *points);
1069
1070bool sna_gradients_create(struct sna *sna);
1071void sna_gradients_close(struct sna *sna);
1072
1073bool sna_glyphs_create(struct sna *sna);
1074void sna_glyphs(CARD8 op,
1075		PicturePtr src,
1076		PicturePtr dst,
1077		PictFormatPtr mask,
1078		INT16 xSrc, INT16 ySrc,
1079		int nlist,
1080		GlyphListPtr list,
1081		GlyphPtr *glyphs);
1082void sna_glyphs__shared(CARD8 op,
1083			PicturePtr src,
1084			PicturePtr dst,
1085			PictFormatPtr mask,
1086			INT16 src_x, INT16 src_y,
1087			int nlist, GlyphListPtr list, GlyphPtr *glyphs);
1088void sna_glyph_unrealize(ScreenPtr screen, GlyphPtr glyph);
1089void sna_glyphs_close(struct sna *sna);
1090
1091void sna_read_boxes(struct sna *sna, PixmapPtr dst, struct kgem_bo *src_bo,
1092		    const BoxRec *box, int n);
1093bool sna_write_boxes(struct sna *sna, PixmapPtr dst,
1094		     struct kgem_bo *dst_bo, int16_t dst_dx, int16_t dst_dy,
1095		     const void *src, int stride, int16_t src_dx, int16_t src_dy,
1096		     const BoxRec *box, int n);
1097bool sna_write_boxes__xor(struct sna *sna, PixmapPtr dst,
1098			  struct kgem_bo *dst_bo, int16_t dst_dx, int16_t dst_dy,
1099			  const void *src, int stride, int16_t src_dx, int16_t src_dy,
1100			  const BoxRec *box, int nbox,
1101			  uint32_t and, uint32_t or);
1102
1103bool sna_replace(struct sna *sna,
1104		 PixmapPtr pixmap,
1105		 const void *src, int stride);
1106bool sna_replace__xor(struct sna *sna,
1107		      PixmapPtr pixmap,
1108		      const void *src, int stride,
1109		      uint32_t and, uint32_t or);
1110
1111bool
1112sna_compute_composite_extents(BoxPtr extents,
1113			      PicturePtr src, PicturePtr mask, PicturePtr dst,
1114			      INT16 src_x,  INT16 src_y,
1115			      INT16 mask_x, INT16 mask_y,
1116			      INT16 dst_x,  INT16 dst_y,
1117			      CARD16 width, CARD16 height);
1118bool
1119sna_compute_composite_region(RegionPtr region,
1120			     PicturePtr src, PicturePtr mask, PicturePtr dst,
1121			     INT16 src_x,  INT16 src_y,
1122			     INT16 mask_x, INT16 mask_y,
1123			     INT16 dst_x,  INT16 dst_y,
1124			     CARD16 width, CARD16 height);
1125
1126void
1127memcpy_blt(const void *src, void *dst, int bpp,
1128	   int32_t src_stride, int32_t dst_stride,
1129	   int16_t src_x, int16_t src_y,
1130	   int16_t dst_x, int16_t dst_y,
1131	   uint16_t width, uint16_t height);
1132
1133void
1134memmove_box(const void *src, void *dst,
1135	    int bpp, int32_t stride,
1136	    const BoxRec *box,
1137	    int dx, int dy);
1138
1139void
1140memcpy_xor(const void *src, void *dst, int bpp,
1141	   int32_t src_stride, int32_t dst_stride,
1142	   int16_t src_x, int16_t src_y,
1143	   int16_t dst_x, int16_t dst_y,
1144	   uint16_t width, uint16_t height,
1145	   uint32_t and, uint32_t or);
1146
1147#define SNA_CREATE_FB 0x10
1148#define SNA_CREATE_SCRATCH 0x11
1149
1150inline static bool is_power_of_two(unsigned x)
1151{
1152	return (x & (x-1)) == 0;
1153}
1154
1155inline static bool is_clipped(const RegionRec *r,
1156			      const DrawableRec *d)
1157{
1158	DBG(("%s: region[%d]x(%d, %d),(%d, %d) against drawable %dx%d\n",
1159	     __FUNCTION__,
1160	     region_num_rects(r),
1161	     r->extents.x1, r->extents.y1,
1162	     r->extents.x2, r->extents.y2,
1163	     d->width, d->height));
1164	return (r->data ||
1165		r->extents.x2 - r->extents.x1 != d->width ||
1166		r->extents.y2 - r->extents.y1 != d->height);
1167}
1168
1169inline static bool
1170box_intersect(BoxPtr a, const BoxRec *b)
1171{
1172	if (a->x1 < b->x1)
1173		a->x1 = b->x1;
1174	if (a->x2 > b->x2)
1175		a->x2 = b->x2;
1176	if (a->x1 >= a->x2)
1177		return false;
1178
1179	if (a->y1 < b->y1)
1180		a->y1 = b->y1;
1181	if (a->y2 > b->y2)
1182		a->y2 = b->y2;
1183	if (a->y1 >= a->y2)
1184		return false;
1185
1186	return true;
1187}
1188
1189unsigned sna_cpu_detect(void);
1190char *sna_cpu_features_to_string(unsigned features, char *line);
1191
1192/* sna_acpi.c */
1193int sna_acpi_open(void);
1194void sna_acpi_init(struct sna *sna);
1195void _sna_acpi_wakeup(struct sna *sna);
1196static inline void sna_acpi_wakeup(struct sna *sna)
1197{
1198	_sna_acpi_wakeup(sna);
1199}
1200void sna_acpi_fini(struct sna *sna);
1201
1202void sna_threads_init(void);
1203int sna_use_threads (int width, int height, int threshold);
1204void sna_threads_run(int id, void (*func)(void *arg), void *arg);
1205void sna_threads_trap(int sig);
1206void sna_threads_wait(void);
1207void sna_threads_kill(void);
1208
1209void sna_image_composite(pixman_op_t        op,
1210			 pixman_image_t    *src,
1211			 pixman_image_t    *mask,
1212			 pixman_image_t    *dst,
1213			 int16_t            src_x,
1214			 int16_t            src_y,
1215			 int16_t            mask_x,
1216			 int16_t            mask_y,
1217			 int16_t            dst_x,
1218			 int16_t            dst_y,
1219			 uint16_t           width,
1220			 uint16_t           height);
1221
1222extern jmp_buf sigjmp[4];
1223extern volatile sig_atomic_t sigtrap;
1224
1225#define sigtrap_assert_inactive() assert(sigtrap == 0)
1226#define sigtrap_assert_active() assert(sigtrap > 0 && sigtrap <= ARRAY_SIZE(sigjmp))
1227#define sigtrap_get() sigsetjmp(sigjmp[sigtrap++], 1)
1228
1229static inline void sigtrap_put(void)
1230{
1231	sigtrap_assert_active();
1232	--sigtrap;
1233}
1234
1235#define RR_Rotate_All (RR_Rotate_0 | RR_Rotate_90 | RR_Rotate_180 | RR_Rotate_270)
1236#define RR_Reflect_All (RR_Reflect_X | RR_Reflect_Y)
1237
1238#ifndef HAVE_GETLINE
1239#include <stdio.h>
1240extern int getline(char **line, size_t *len, FILE *file);
1241#endif
1242
1243#endif /* _SNA_H */
1244