sna.h revision 63ef14f0
103b705cfSriastradh/**************************************************************************
203b705cfSriastradh
303b705cfSriastradhCopyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
403b705cfSriastradhCopyright © 2002 David Dawes
503b705cfSriastradh
603b705cfSriastradhAll Rights Reserved.
703b705cfSriastradh
803b705cfSriastradhPermission is hereby granted, free of charge, to any person obtaining a
903b705cfSriastradhcopy of this software and associated documentation files (the
1003b705cfSriastradh"Software"), to deal in the Software without restriction, including
1103b705cfSriastradhwithout limitation the rights to use, copy, modify, merge, publish,
1203b705cfSriastradhdistribute, sub license, and/or sell copies of the Software, and to
1303b705cfSriastradhpermit persons to whom the Software is furnished to do so, subject to
1403b705cfSriastradhthe following conditions:
1503b705cfSriastradh
1603b705cfSriastradhThe above copyright notice and this permission notice (including the
1703b705cfSriastradhnext paragraph) shall be included in all copies or substantial portions
1803b705cfSriastradhof the Software.
1903b705cfSriastradh
2003b705cfSriastradhTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
2103b705cfSriastradhOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
2203b705cfSriastradhMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
2303b705cfSriastradhIN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
2403b705cfSriastradhANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
2503b705cfSriastradhTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
2603b705cfSriastradhSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2703b705cfSriastradh
2803b705cfSriastradh**************************************************************************/
2903b705cfSriastradh
3003b705cfSriastradh/*
3103b705cfSriastradh * Authors:
3203b705cfSriastradh *   Keith Whitwell <keith@tungstengraphics.com>
3303b705cfSriastradh *   David Dawes <dawes@xfree86.org>
3403b705cfSriastradh *
3503b705cfSriastradh */
3603b705cfSriastradh
3703b705cfSriastradh#ifndef _SNA_H_
3803b705cfSriastradh#define _SNA_H_
3903b705cfSriastradh
4003b705cfSriastradh#include <stdint.h>
4103b705cfSriastradh
4203b705cfSriastradh#include <xorg-server.h>
4342542f5fSchristos#include <xf86str.h>
4403b705cfSriastradh
4503b705cfSriastradh#include <xf86Crtc.h>
4603b705cfSriastradh#if XF86_CRTC_VERSION >= 5
4703b705cfSriastradh#define HAS_PIXMAP_SHARING 1
4803b705cfSriastradh#endif
4903b705cfSriastradh
5003b705cfSriastradh#include <windowstr.h>
5103b705cfSriastradh#include <glyphstr.h>
5203b705cfSriastradh#include <picturestr.h>
5303b705cfSriastradh#include <gcstruct.h>
5403b705cfSriastradh#include <xvdix.h>
5503b705cfSriastradh
5603b705cfSriastradh#include <pciaccess.h>
5703b705cfSriastradh
5803b705cfSriastradh#include <xf86drmMode.h>
5903b705cfSriastradh
6003b705cfSriastradh#include "../compat-api.h"
6103b705cfSriastradh#include <drm.h>
6203b705cfSriastradh#include <i915_drm.h>
6303b705cfSriastradh
6442542f5fSchristos#if HAVE_DRI2
6503b705cfSriastradh#include <dri2.h>
6603b705cfSriastradh#endif
6703b705cfSriastradh
6842542f5fSchristos#if HAVE_DRI3
6942542f5fSchristos#include <misync.h>
7042542f5fSchristos#endif
7142542f5fSchristos
7203b705cfSriastradh#if HAVE_UDEV
7303b705cfSriastradh#include <libudev.h>
7403b705cfSriastradh#endif
7503b705cfSriastradh
7642542f5fSchristos#include <signal.h>
7742542f5fSchristos#include <setjmp.h>
7842542f5fSchristos
7913496ba1Ssnj#include "xassert.h"
8042542f5fSchristos#include "compiler.h"
8113496ba1Ssnj#include "debug.h"
8203b705cfSriastradh
8303b705cfSriastradh#define DEBUG_NO_BLT 0
8403b705cfSriastradh
8503b705cfSriastradh#define DEBUG_FLUSH_BATCH 0
8603b705cfSriastradh
8703b705cfSriastradh#define TEST_ALL 0
8803b705cfSriastradh#define TEST_ACCEL (TEST_ALL || 0)
8903b705cfSriastradh#define TEST_BATCH (TEST_ALL || 0)
9003b705cfSriastradh#define TEST_BLT (TEST_ALL || 0)
9103b705cfSriastradh#define TEST_COMPOSITE (TEST_ALL || 0)
9203b705cfSriastradh#define TEST_DAMAGE (TEST_ALL || 0)
9303b705cfSriastradh#define TEST_GRADIENT (TEST_ALL || 0)
9403b705cfSriastradh#define TEST_GLYPHS (TEST_ALL || 0)
9503b705cfSriastradh#define TEST_IO (TEST_ALL || 0)
9603b705cfSriastradh#define TEST_KGEM (TEST_ALL || 0)
9703b705cfSriastradh#define TEST_RENDER (TEST_ALL || 0)
9803b705cfSriastradh
9903b705cfSriastradh#include "intel_driver.h"
10003b705cfSriastradh#include "intel_list.h"
10103b705cfSriastradh#include "kgem.h"
10203b705cfSriastradh#include "sna_damage.h"
10303b705cfSriastradh#include "sna_render.h"
10403b705cfSriastradh#include "fb/fb.h"
10503b705cfSriastradh
10642542f5fSchristosstruct sna_cursor;
10742542f5fSchristosstruct sna_crtc;
10803b705cfSriastradh
10903b705cfSriastradhstruct sna_client {
11042542f5fSchristos	struct list events;
11103b705cfSriastradh	int is_compositor; /* only 4 bits used */
11203b705cfSriastradh};
11303b705cfSriastradh
11403b705cfSriastradhextern DevPrivateKeyRec sna_client_key;
11503b705cfSriastradh
11603b705cfSriastradhpure static inline struct sna_client *sna_client(ClientPtr client)
11703b705cfSriastradh{
11803b705cfSriastradh	return __get_private(client, sna_client_key);
11903b705cfSriastradh}
12003b705cfSriastradh
12103b705cfSriastradhstruct sna_cow {
12203b705cfSriastradh	struct kgem_bo *bo;
12303b705cfSriastradh	struct list list;
12403b705cfSriastradh	int refcnt;
12503b705cfSriastradh};
12603b705cfSriastradh
12703b705cfSriastradhstruct sna_pixmap {
12803b705cfSriastradh	PixmapPtr pixmap;
12903b705cfSriastradh	struct kgem_bo *gpu_bo, *cpu_bo;
13003b705cfSriastradh	struct sna_damage *gpu_damage, *cpu_damage;
13103b705cfSriastradh	struct sna_cow *cow;
13203b705cfSriastradh	void *ptr;
13303b705cfSriastradh#define PTR(ptr) ((void*)((uintptr_t)(ptr) & ~1))
13403b705cfSriastradh
13542542f5fSchristos	bool (*move_to_gpu)(struct sna *, struct sna_pixmap *, unsigned);
13642542f5fSchristos	void *move_to_gpu_data;
13742542f5fSchristos
13803b705cfSriastradh	struct list flush_list;
13903b705cfSriastradh	struct list cow_list;
14003b705cfSriastradh
14103b705cfSriastradh	uint32_t stride;
14203b705cfSriastradh	uint32_t clear_color;
14303b705cfSriastradh
14403b705cfSriastradh#define SOURCE_BIAS 4
14542542f5fSchristos	uint8_t source_count;
14642542f5fSchristos	uint8_t pinned :4;
14703b705cfSriastradh#define PIN_SCANOUT 0x1
14842542f5fSchristos#define PIN_DRI2 0x2
14942542f5fSchristos#define PIN_DRI3 0x4
15042542f5fSchristos#define PIN_PRIME 0x8
15103b705cfSriastradh	uint8_t create :4;
15242542f5fSchristos	uint8_t mapped :2;
15342542f5fSchristos#define MAPPED_NONE 0
15442542f5fSchristos#define MAPPED_GTT 1
15542542f5fSchristos#define MAPPED_CPU 2
15642542f5fSchristos	uint8_t flush :2;
15763ef14f0Smrg#define FLUSH_READ 1
15863ef14f0Smrg#define FLUSH_WRITE 2
15903b705cfSriastradh	uint8_t shm :1;
16003b705cfSriastradh	uint8_t clear :1;
16103b705cfSriastradh	uint8_t header :1;
16203b705cfSriastradh	uint8_t cpu :1;
16303b705cfSriastradh};
16403b705cfSriastradh
16542542f5fSchristos#define IS_STATIC_PTR(ptr) ((uintptr_t)(ptr) & 1)
16642542f5fSchristos#define MAKE_STATIC_PTR(ptr) ((void*)((uintptr_t)(ptr) | 1))
16742542f5fSchristos
16803b705cfSriastradhstruct sna_glyph {
16903b705cfSriastradh	PicturePtr atlas;
17003b705cfSriastradh	struct sna_coordinate coordinate;
17103b705cfSriastradh	uint16_t size, pos;
17203b705cfSriastradh	pixman_image_t *image;
17303b705cfSriastradh};
17403b705cfSriastradh
17503b705cfSriastradhstatic inline WindowPtr get_root_window(ScreenPtr screen)
17603b705cfSriastradh{
17703b705cfSriastradh#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,10,0,0,0)
17803b705cfSriastradh	return screen->root;
17903b705cfSriastradh#else
18003b705cfSriastradh	return WindowTable[screen->myNum];
18103b705cfSriastradh#endif
18203b705cfSriastradh}
18303b705cfSriastradh
18463ef14f0Smrg#if !NDEBUG
18563ef14f0Smrgstatic PixmapPtr check_pixmap(PixmapPtr pixmap)
18663ef14f0Smrg{
18763ef14f0Smrg	if (pixmap != NULL) {
18863ef14f0Smrg		assert(pixmap->refcnt >= 1);
18963ef14f0Smrg		assert(pixmap->devKind != 0xdeadbeef);
19063ef14f0Smrg	}
19163ef14f0Smrg	return pixmap;
19263ef14f0Smrg}
19363ef14f0Smrg#else
19463ef14f0Smrg#define check_pixmap(p) p
19563ef14f0Smrg#endif
19663ef14f0Smrg
19703b705cfSriastradhstatic inline PixmapPtr get_window_pixmap(WindowPtr window)
19803b705cfSriastradh{
19942542f5fSchristos	assert(window);
20042542f5fSchristos	assert(window->drawable.type != DRAWABLE_PIXMAP);
20163ef14f0Smrg	return check_pixmap(fbGetWindowPixmap(window));
20203b705cfSriastradh}
20303b705cfSriastradh
20403b705cfSriastradhstatic inline PixmapPtr get_drawable_pixmap(DrawablePtr drawable)
20503b705cfSriastradh{
20642542f5fSchristos	assert(drawable);
20703b705cfSriastradh	if (drawable->type == DRAWABLE_PIXMAP)
20863ef14f0Smrg		return check_pixmap((PixmapPtr)drawable);
20903b705cfSriastradh	else
21003b705cfSriastradh		return get_window_pixmap((WindowPtr)drawable);
21103b705cfSriastradh}
21203b705cfSriastradh
21303b705cfSriastradhextern DevPrivateKeyRec sna_pixmap_key;
21403b705cfSriastradh
21503b705cfSriastradhpure static inline struct sna_pixmap *sna_pixmap(PixmapPtr pixmap)
21603b705cfSriastradh{
21703b705cfSriastradh	return ((void **)__get_private(pixmap, sna_pixmap_key))[1];
21803b705cfSriastradh}
21903b705cfSriastradh
22003b705cfSriastradhstatic inline struct sna_pixmap *sna_pixmap_from_drawable(DrawablePtr drawable)
22103b705cfSriastradh{
22203b705cfSriastradh	return sna_pixmap(get_drawable_pixmap(drawable));
22303b705cfSriastradh}
22403b705cfSriastradh
22503b705cfSriastradhstruct sna_gc {
22603b705cfSriastradh	long changes;
22703b705cfSriastradh	long serial;
22803b705cfSriastradh
22942542f5fSchristos	const GCFuncs *old_funcs;
23003b705cfSriastradh	void *priv;
23103b705cfSriastradh};
23203b705cfSriastradh
23303b705cfSriastradhstatic inline struct sna_gc *sna_gc(GCPtr gc)
23403b705cfSriastradh{
23503b705cfSriastradh	return (struct sna_gc *)__get_private(gc, sna_gc_key);
23603b705cfSriastradh}
23703b705cfSriastradh
23803b705cfSriastradhenum {
23903b705cfSriastradh	FLUSH_TIMER = 0,
24003b705cfSriastradh	THROTTLE_TIMER,
24103b705cfSriastradh	EXPIRE_TIMER,
24203b705cfSriastradh#if DEBUG_MEMORY
24303b705cfSriastradh	DEBUG_MEMORY_TIMER,
24403b705cfSriastradh#endif
24503b705cfSriastradh	NUM_TIMERS
24603b705cfSriastradh};
24703b705cfSriastradh
24803b705cfSriastradhstruct sna {
24903b705cfSriastradh	struct kgem kgem;
25003b705cfSriastradh
25103b705cfSriastradh	ScrnInfoPtr scrn;
25213496ba1Ssnj	struct intel_device *dev;
25303b705cfSriastradh
25403b705cfSriastradh	unsigned flags;
25542542f5fSchristos#define SNA_IS_SLAVED		0x1
25642542f5fSchristos#define SNA_IS_HOSTED		0x2
25742542f5fSchristos#define SNA_NO_WAIT		0x10
25842542f5fSchristos#define SNA_NO_FLIP		0x20
25942542f5fSchristos#define SNA_NO_VSYNC		0x40
26042542f5fSchristos#define SNA_TRIPLE_BUFFER	0x80
26142542f5fSchristos#define SNA_TEAR_FREE		0x100
26263ef14f0Smrg#define SNA_WANT_TEAR_FREE	0x200
26363ef14f0Smrg#define SNA_FORCE_SHADOW	0x400
26463ef14f0Smrg#define SNA_FLUSH_GTT		0x800
26542542f5fSchristos#define SNA_PERFORMANCE		0x1000
26642542f5fSchristos#define SNA_POWERSAVE		0x2000
26763ef14f0Smrg#define SNA_NO_DPMS		0x4000
26842542f5fSchristos#define SNA_HAS_FLIP		0x10000
26942542f5fSchristos#define SNA_HAS_ASYNC_FLIP	0x20000
27042542f5fSchristos#define SNA_LINEAR_FB		0x40000
27103b705cfSriastradh#define SNA_REPROBE		0x80000000
27203b705cfSriastradh
27303b705cfSriastradh	unsigned cpu_features;
27403b705cfSriastradh#define MMX 0x1
27503b705cfSriastradh#define SSE 0x2
27603b705cfSriastradh#define SSE2 0x4
27703b705cfSriastradh#define SSE3 0x8
27803b705cfSriastradh#define SSSE3 0x10
27903b705cfSriastradh#define SSE4_1 0x20
28003b705cfSriastradh#define SSE4_2 0x40
28103b705cfSriastradh#define AVX 0x80
28203b705cfSriastradh#define AVX2 0x100
28303b705cfSriastradh
28463ef14f0Smrg	bool ignore_copy_area : 1;
28563ef14f0Smrg
28663ef14f0Smrg	unsigned watch_shm_flush;
28763ef14f0Smrg	unsigned watch_dri_flush;
28863ef14f0Smrg	unsigned damage_event;
28963ef14f0Smrg	bool needs_shm_flush;
29063ef14f0Smrg	bool needs_dri_flush;
29103b705cfSriastradh
29203b705cfSriastradh	struct timeval timer_tv;
29303b705cfSriastradh	uint32_t timer_expire[NUM_TIMERS];
29403b705cfSriastradh	uint16_t timer_active;
29503b705cfSriastradh
29603b705cfSriastradh	int vblank_interval;
29703b705cfSriastradh
29803b705cfSriastradh	struct list flush_pixmaps;
29903b705cfSriastradh	struct list active_pixmaps;
30003b705cfSriastradh
30103b705cfSriastradh	PixmapPtr front;
30203b705cfSriastradh	PixmapPtr freed_pixmap;
30303b705cfSriastradh
30403b705cfSriastradh	struct sna_mode {
30503b705cfSriastradh		DamagePtr shadow_damage;
30603b705cfSriastradh		struct kgem_bo *shadow;
30742542f5fSchristos		unsigned front_active;
30842542f5fSchristos		unsigned shadow_active;
30963ef14f0Smrg		unsigned rr_active;
31042542f5fSchristos		unsigned flip_active;
31163ef14f0Smrg		unsigned hidden;
31263ef14f0Smrg		bool shadow_enabled;
31342542f5fSchristos		bool dirty;
31442542f5fSchristos
31563ef14f0Smrg		struct drm_event_vblank *shadow_events;
31663ef14f0Smrg		int shadow_nevent;
31763ef14f0Smrg		int shadow_size;
31863ef14f0Smrg
31942542f5fSchristos		int max_crtc_width, max_crtc_height;
32042542f5fSchristos		RegionRec shadow_region;
32142542f5fSchristos		RegionRec shadow_cancel;
32242542f5fSchristos		struct list shadow_crtc;
32342542f5fSchristos		bool shadow_dirty;
32442542f5fSchristos
32542542f5fSchristos		unsigned num_real_crtc;
32642542f5fSchristos		unsigned num_real_output;
32742542f5fSchristos		unsigned num_real_encoder;
32842542f5fSchristos		unsigned num_fake;
32942542f5fSchristos		unsigned serial;
33042542f5fSchristos
33142542f5fSchristos		uint32_t *encoders;
33242542f5fSchristos
33342542f5fSchristos#if HAVE_UDEV
33442542f5fSchristos		struct udev_monitor *backlight_monitor;
33542542f5fSchristos		pointer backlight_handler;
33642542f5fSchristos#endif
33713496ba1Ssnj
33813496ba1Ssnj		Bool (*rrGetInfo)(ScreenPtr, Rotation *);
33903b705cfSriastradh	} mode;
34003b705cfSriastradh
34142542f5fSchristos	struct {
34242542f5fSchristos		struct sna_cursor *cursors;
34342542f5fSchristos		xf86CursorInfoPtr info;
34442542f5fSchristos		CursorPtr ref;
34542542f5fSchristos
34642542f5fSchristos		unsigned serial;
34742542f5fSchristos		uint32_t fg, bg;
34842542f5fSchristos		int size;
34942542f5fSchristos
35063ef14f0Smrg		bool disable;
35163ef14f0Smrg		bool active;
35242542f5fSchristos		int last_x;
35342542f5fSchristos		int last_y;
35442542f5fSchristos
35542542f5fSchristos		unsigned max_size;
35642542f5fSchristos		bool use_gtt;
35742542f5fSchristos
35842542f5fSchristos		int num_stash;
35942542f5fSchristos		struct sna_cursor *stash;
36042542f5fSchristos		void *scratch;
36142542f5fSchristos	} cursor;
36242542f5fSchristos
36342542f5fSchristos	struct sna_dri2 {
36463ef14f0Smrg		bool available : 1;
36563ef14f0Smrg		bool enable : 1;
36663ef14f0Smrg		bool open : 1;
36742542f5fSchristos
36842542f5fSchristos#if HAVE_DRI2
36903b705cfSriastradh		void *flip_pending;
37042542f5fSchristos		unsigned client_count;
37142542f5fSchristos#endif
37242542f5fSchristos	} dri2;
37342542f5fSchristos
37442542f5fSchristos	struct sna_dri3 {
37563ef14f0Smrg		bool available :1;
37663ef14f0Smrg		bool override : 1;
37763ef14f0Smrg		bool enable : 1;
37863ef14f0Smrg		bool open :1;
37963ef14f0Smrg
38042542f5fSchristos#if HAVE_DRI3
38142542f5fSchristos		SyncScreenCreateFenceFunc create_fence;
38242542f5fSchristos		struct list pixmaps;
38342542f5fSchristos#endif
38442542f5fSchristos	} dri3;
38542542f5fSchristos
38642542f5fSchristos	struct sna_present {
38742542f5fSchristos		bool available;
38842542f5fSchristos		bool open;
38942542f5fSchristos#if HAVE_PRESENT
39063ef14f0Smrg		struct list vblank_queue;
39163ef14f0Smrg		uint64_t unflip;
39263ef14f0Smrg		void *freed_info;
39342542f5fSchristos#endif
39442542f5fSchristos	} present;
39503b705cfSriastradh
39603b705cfSriastradh	struct sna_xv {
39703b705cfSriastradh		XvAdaptorPtr adaptors;
39803b705cfSriastradh		int num_adaptors;
39903b705cfSriastradh	} xv;
40003b705cfSriastradh
40103b705cfSriastradh	EntityInfoPtr pEnt;
40203b705cfSriastradh	const struct intel_device_info *info;
40303b705cfSriastradh
40463ef14f0Smrg#if !HAVE_NOTIFY_FD
40503b705cfSriastradh	ScreenBlockHandlerProcPtr BlockHandler;
40603b705cfSriastradh	ScreenWakeupHandlerProcPtr WakeupHandler;
40763ef14f0Smrg#endif
40803b705cfSriastradh	CloseScreenProcPtr CloseScreen;
40903b705cfSriastradh
41003b705cfSriastradh	PicturePtr clear;
41103b705cfSriastradh	struct {
41203b705cfSriastradh		uint32_t fill_bo;
41303b705cfSriastradh		uint32_t fill_pixel;
41403b705cfSriastradh		uint32_t fill_alu;
41503b705cfSriastradh	} blt_state;
41603b705cfSriastradh	union {
41742542f5fSchristos		unsigned gt;
41803b705cfSriastradh		struct gen2_render_state gen2;
41903b705cfSriastradh		struct gen3_render_state gen3;
42003b705cfSriastradh		struct gen4_render_state gen4;
42103b705cfSriastradh		struct gen5_render_state gen5;
42203b705cfSriastradh		struct gen6_render_state gen6;
42303b705cfSriastradh		struct gen7_render_state gen7;
42442542f5fSchristos		struct gen8_render_state gen8;
42563ef14f0Smrg		struct gen9_render_state gen9;
42603b705cfSriastradh	} render_state;
42703b705cfSriastradh
42803b705cfSriastradh	/* Broken-out options. */
42903b705cfSriastradh	OptionInfoPtr Options;
43003b705cfSriastradh
43103b705cfSriastradh	/* Driver phase/state information */
43203b705cfSriastradh	bool suspended;
43303b705cfSriastradh
43403b705cfSriastradh#if HAVE_UDEV
43503b705cfSriastradh	struct udev_monitor *uevent_monitor;
43642542f5fSchristos	pointer uevent_handler;
43703b705cfSriastradh#endif
43803b705cfSriastradh
43942542f5fSchristos	struct {
44042542f5fSchristos		int fd;
44142542f5fSchristos		uint8_t offset;
44242542f5fSchristos		uint8_t remain;
44342542f5fSchristos		char event[256];
44442542f5fSchristos	} acpi;
44542542f5fSchristos
44603b705cfSriastradh	struct sna_render render;
44703b705cfSriastradh
44803b705cfSriastradh#if DEBUG_MEMORY
44903b705cfSriastradh	struct {
45003b705cfSriastradh		int pixmap_allocs;
45142542f5fSchristos		int pixmap_cached;
45203b705cfSriastradh		int cpu_bo_allocs;
45303b705cfSriastradh		size_t shadow_pixels_bytes;
45403b705cfSriastradh		size_t cpu_bo_bytes;
45503b705cfSriastradh	} debug_memory;
45603b705cfSriastradh#endif
45703b705cfSriastradh};
45803b705cfSriastradh
45903b705cfSriastradhbool sna_mode_pre_init(ScrnInfoPtr scrn, struct sna *sna);
46042542f5fSchristosbool sna_mode_fake_init(struct sna *sna, int num_fake);
46142542f5fSchristosbool sna_mode_wants_tear_free(struct sna *sna);
46203b705cfSriastradhvoid sna_mode_adjust_frame(struct sna *sna, int x, int y);
46363ef14f0Smrgextern void sna_mode_discover(struct sna *sna, bool tell);
46442542f5fSchristosextern void sna_mode_check(struct sna *sna);
46513496ba1Ssnjextern bool sna_mode_disable(struct sna *sna);
46613496ba1Ssnjextern void sna_mode_enable(struct sna *sna);
46742542f5fSchristosextern void sna_mode_reset(struct sna *sna);
46813496ba1Ssnjextern int sna_mode_wakeup(struct sna *sna);
46903b705cfSriastradhextern void sna_mode_redisplay(struct sna *sna);
47042542f5fSchristosextern void sna_shadow_set_crtc(struct sna *sna, xf86CrtcPtr crtc, struct kgem_bo *bo);
47113496ba1Ssnjextern void sna_shadow_steal_crtcs(struct sna *sna, struct list *list);
47213496ba1Ssnjextern void sna_shadow_unsteal_crtcs(struct sna *sna, struct list *list);
47342542f5fSchristosextern void sna_shadow_unset_crtc(struct sna *sna, xf86CrtcPtr crtc);
47442542f5fSchristosextern bool sna_pixmap_discard_shadow_damage(struct sna_pixmap *priv,
47542542f5fSchristos					     const RegionRec *region);
47642542f5fSchristosextern void sna_mode_set_primary(struct sna *sna);
47763ef14f0Smrgextern bool sna_mode_find_hotplug_connector(struct sna *sna, unsigned id);
47803b705cfSriastradhextern void sna_mode_close(struct sna *sna);
47903b705cfSriastradhextern void sna_mode_fini(struct sna *sna);
48003b705cfSriastradh
48142542f5fSchristosextern void sna_crtc_config_notify(ScreenPtr screen);
48242542f5fSchristos
48342542f5fSchristosextern bool sna_cursors_init(ScreenPtr screen, struct sna *sna);
48442542f5fSchristos
48563ef14f0Smrgextern CARD32 sna_mode_coldplug(OsTimerPtr timer, CARD32 now, void *data);
48663ef14f0Smrg#define COLDPLUG_DELAY_MS 2000
48763ef14f0Smrg
48813496ba1Ssnjtypedef void (*sna_flip_handler_t)(struct drm_event_vblank *e,
48942542f5fSchristos				   void *data);
49042542f5fSchristos
49163ef14f0Smrgextern bool sna_needs_page_flip(struct sna *sna, struct kgem_bo *bo);
49203b705cfSriastradhextern int sna_page_flip(struct sna *sna,
49303b705cfSriastradh			 struct kgem_bo *bo,
49442542f5fSchristos			 sna_flip_handler_t handler,
49542542f5fSchristos			 void *data);
49603b705cfSriastradh
49703b705cfSriastradhpure static inline struct sna *
49803b705cfSriastradhto_sna(ScrnInfoPtr scrn)
49903b705cfSriastradh{
50063ef14f0Smrg	struct sna *sna = scrn->driverPrivate;
50163ef14f0Smrg	assert(sna->scrn == scrn);
50263ef14f0Smrg	return sna;
50303b705cfSriastradh}
50403b705cfSriastradh
50503b705cfSriastradhpure static inline struct sna *
50603b705cfSriastradhto_sna_from_screen(ScreenPtr screen)
50703b705cfSriastradh{
50803b705cfSriastradh	return to_sna(xf86ScreenToScrn(screen));
50903b705cfSriastradh}
51003b705cfSriastradh
51163ef14f0Smrgpure static inline ScreenPtr to_screen_from_sna(struct sna *sna)
51263ef14f0Smrg{
51363ef14f0Smrg	ScreenPtr screen = xf86ScrnToScreen(sna->scrn);
51463ef14f0Smrg	assert(!screen || sna == to_sna_from_screen(screen));
51563ef14f0Smrg	return screen;
51663ef14f0Smrg}
51763ef14f0Smrg
51803b705cfSriastradhpure static inline struct sna *
51903b705cfSriastradhto_sna_from_pixmap(PixmapPtr pixmap)
52003b705cfSriastradh{
52103b705cfSriastradh	return ((void **)__get_private(pixmap, sna_pixmap_key))[0];
52203b705cfSriastradh}
52303b705cfSriastradh
52403b705cfSriastradhpure static inline struct sna *
52503b705cfSriastradhto_sna_from_drawable(DrawablePtr drawable)
52603b705cfSriastradh{
52703b705cfSriastradh	return to_sna_from_screen(drawable->pScreen);
52803b705cfSriastradh}
52903b705cfSriastradh
53003b705cfSriastradhstatic inline struct sna *
53103b705cfSriastradhto_sna_from_kgem(struct kgem *kgem)
53203b705cfSriastradh{
53303b705cfSriastradh	return container_of(kgem, struct sna, kgem);
53403b705cfSriastradh}
53503b705cfSriastradh
53603b705cfSriastradh#ifndef ARRAY_SIZE
53703b705cfSriastradh#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
53803b705cfSriastradh#endif
53903b705cfSriastradh
54003b705cfSriastradh#ifndef ALIGN
54103b705cfSriastradh#define ALIGN(i,m)	(((i) + (m) - 1) & ~((m) - 1))
54203b705cfSriastradh#endif
54303b705cfSriastradh
54403b705cfSriastradh#ifndef MIN
54503b705cfSriastradh#define MIN(a,b)	((a) <= (b) ? (a) : (b))
54603b705cfSriastradh#endif
54703b705cfSriastradh
54803b705cfSriastradh#ifndef MAX
54903b705cfSriastradh#define MAX(a,b)	((a) >= (b) ? (a) : (b))
55003b705cfSriastradh#endif
55103b705cfSriastradh
55242542f5fSchristosextern xf86CrtcPtr sna_covering_crtc(struct sna *sna,
55303b705cfSriastradh				     const BoxRec *box,
55403b705cfSriastradh				     xf86CrtcPtr desired);
55563ef14f0Smrgextern xf86CrtcPtr sna_primary_crtc(struct sna *sna);
55603b705cfSriastradh
55703b705cfSriastradhextern bool sna_wait_for_scanline(struct sna *sna, PixmapPtr pixmap,
55803b705cfSriastradh				  xf86CrtcPtr crtc, const BoxRec *clip);
55903b705cfSriastradh
56042542f5fSchristosconst struct ust_msc {
56142542f5fSchristos	uint64_t msc;
56242542f5fSchristos	int tv_sec;
56342542f5fSchristos	int tv_usec;
56442542f5fSchristos} *sna_crtc_last_swap(xf86CrtcPtr crtc);
56542542f5fSchristos
56642542f5fSchristosuint64_t sna_crtc_record_swap(xf86CrtcPtr crtc,
56742542f5fSchristos			      int tv_sec, int tv_usec, unsigned seq);
56842542f5fSchristos
56942542f5fSchristosstatic inline uint64_t sna_crtc_record_vblank(xf86CrtcPtr crtc,
57042542f5fSchristos					      const union drm_wait_vblank *vbl)
57142542f5fSchristos{
57242542f5fSchristos	return sna_crtc_record_swap(crtc,
57342542f5fSchristos				    vbl->reply.tval_sec,
57442542f5fSchristos				    vbl->reply.tval_usec,
57542542f5fSchristos				    vbl->reply.sequence);
57642542f5fSchristos}
57742542f5fSchristos
57842542f5fSchristosstatic inline uint64_t sna_crtc_record_event(xf86CrtcPtr crtc,
57942542f5fSchristos					     struct drm_event_vblank *event)
58042542f5fSchristos{
58142542f5fSchristos	return sna_crtc_record_swap(crtc,
58242542f5fSchristos				    event->tv_sec,
58342542f5fSchristos				    event->tv_usec,
58442542f5fSchristos				    event->sequence);
58542542f5fSchristos}
58642542f5fSchristos
58742542f5fSchristosstatic inline uint64_t ust64(int tv_sec, int tv_usec)
58842542f5fSchristos{
58942542f5fSchristos	return (uint64_t)tv_sec * 1000000 + tv_usec;
59042542f5fSchristos}
59142542f5fSchristos
59263ef14f0Smrgstatic inline uint64_t swap_ust(const struct ust_msc *swap)
59363ef14f0Smrg{
59463ef14f0Smrg	return ust64(swap->tv_sec, swap->tv_usec);
59563ef14f0Smrg}
59663ef14f0Smrg
59742542f5fSchristos#if HAVE_DRI2
59842542f5fSchristosbool sna_dri2_open(struct sna *sna, ScreenPtr pScreen);
59942542f5fSchristosvoid sna_dri2_page_flip_handler(struct sna *sna, struct drm_event_vblank *event);
60013496ba1Ssnjvoid sna_dri2_vblank_handler(struct drm_event_vblank *event);
60142542f5fSchristosvoid sna_dri2_pixmap_update_bo(struct sna *sna, PixmapPtr pixmap, struct kgem_bo *bo);
60213496ba1Ssnjvoid sna_dri2_decouple_window(WindowPtr win);
60342542f5fSchristosvoid sna_dri2_destroy_window(WindowPtr win);
60442542f5fSchristosvoid sna_dri2_close(struct sna *sna, ScreenPtr pScreen);
60542542f5fSchristos#else
60642542f5fSchristosstatic inline bool sna_dri2_open(struct sna *sna, ScreenPtr pScreen) { return false; }
60742542f5fSchristosstatic inline void sna_dri2_page_flip_handler(struct sna *sna, struct drm_event_vblank *event) { }
60813496ba1Ssnjstatic inline void sna_dri2_vblank_handler(struct drm_event_vblank *event) { }
60942542f5fSchristosstatic inline void sna_dri2_pixmap_update_bo(struct sna *sna, PixmapPtr pixmap, struct kgem_bo *bo) { }
61013496ba1Ssnjstatic inline void sna_dri2_decouple_window(WindowPtr win) { }
61142542f5fSchristosstatic inline void sna_dri2_destroy_window(WindowPtr win) { }
61242542f5fSchristosstatic inline void sna_dri2_close(struct sna *sna, ScreenPtr pScreen) { }
61342542f5fSchristos#endif
61442542f5fSchristos
61542542f5fSchristos#if HAVE_DRI3
61642542f5fSchristosbool sna_dri3_open(struct sna *sna, ScreenPtr pScreen);
61742542f5fSchristosvoid sna_dri3_close(struct sna *sna, ScreenPtr pScreen);
61842542f5fSchristos#else
61942542f5fSchristosstatic inline bool sna_dri3_open(struct sna *sna, ScreenPtr pScreen) { return false; }
62042542f5fSchristosstatic inline void sna_dri3_close(struct sna *sna, ScreenPtr pScreen) { }
62142542f5fSchristos#endif
62242542f5fSchristos
62342542f5fSchristos#if HAVE_PRESENT
62442542f5fSchristosbool sna_present_open(struct sna *sna, ScreenPtr pScreen);
62542542f5fSchristosvoid sna_present_update(struct sna *sna);
62642542f5fSchristosvoid sna_present_close(struct sna *sna, ScreenPtr pScreen);
62713496ba1Ssnjvoid sna_present_vblank_handler(struct drm_event_vblank *event);
62863ef14f0Smrgvoid sna_present_cancel_flip(struct sna *sna);
62903b705cfSriastradh#else
63042542f5fSchristosstatic inline bool sna_present_open(struct sna *sna, ScreenPtr pScreen) { return false; }
63142542f5fSchristosstatic inline void sna_present_update(struct sna *sna) { }
63242542f5fSchristosstatic inline void sna_present_close(struct sna *sna, ScreenPtr pScreen) { }
63313496ba1Ssnjstatic inline void sna_present_vblank_handler(struct drm_event_vblank *event) { }
63463ef14f0Smrgstatic inline void sna_present_cancel_flip(struct sna *sna) { }
63503b705cfSriastradh#endif
63603b705cfSriastradh
63763ef14f0Smrgextern unsigned sna_crtc_count_sprites(xf86CrtcPtr crtc);
63863ef14f0Smrgextern bool sna_crtc_set_sprite_rotation(xf86CrtcPtr crtc, unsigned idx, uint32_t rotation);
63963ef14f0Smrgextern void sna_crtc_set_sprite_colorspace(xf86CrtcPtr crtc, unsigned idx, int colorspace);
64063ef14f0Smrgextern uint32_t sna_crtc_to_sprite(xf86CrtcPtr crtc, unsigned idx);
64142542f5fSchristosextern bool sna_crtc_is_transformed(xf86CrtcPtr crtc);
64263ef14f0Smrgbool sna_has_sprite_format(struct sna *sna, uint32_t format);
64363ef14f0Smrg
64463ef14f0Smrg#define CRTC_VBLANK 0x7
64563ef14f0Smrg#define CRTC_ON 0x80000000
64663ef14f0Smrg
64763ef14f0Smrguint32_t sna_crtc_id(xf86CrtcPtr crtc);
64863ef14f0Smrg
64963ef14f0Smrgstruct sna_crtc_public {
65063ef14f0Smrg	unsigned long flags;
65163ef14f0Smrg	struct list vblank_queue;
65263ef14f0Smrg};
65363ef14f0Smrg
65463ef14f0Smrgstatic inline unsigned long *sna_crtc_flags(xf86CrtcPtr crtc)
65563ef14f0Smrg{
65663ef14f0Smrg	struct sna_crtc_public *pub = crtc->driver_private;
65763ef14f0Smrg	assert(pub);
65863ef14f0Smrg	return &pub->flags;
65963ef14f0Smrg}
66063ef14f0Smrg
66163ef14f0Smrgstatic inline struct list *sna_crtc_vblank_queue(xf86CrtcPtr crtc)
66263ef14f0Smrg{
66363ef14f0Smrg	struct sna_crtc_public *pub = crtc->driver_private;
66463ef14f0Smrg	assert(pub);
66563ef14f0Smrg	return &pub->vblank_queue;
66663ef14f0Smrg}
66763ef14f0Smrg
66863ef14f0Smrgstatic inline unsigned sna_crtc_pipe(xf86CrtcPtr crtc)
66963ef14f0Smrg{
67063ef14f0Smrg	return *sna_crtc_flags(crtc) >> 8 & 0xff;
67163ef14f0Smrg}
67263ef14f0Smrg
67363ef14f0Smrgstatic inline bool sna_crtc_is_on(xf86CrtcPtr crtc)
67463ef14f0Smrg{
67563ef14f0Smrg	return *sna_crtc_flags(crtc) & CRTC_ON;
67663ef14f0Smrg}
67763ef14f0Smrg
67863ef14f0Smrgstatic inline void sna_crtc_set_vblank(xf86CrtcPtr crtc)
67963ef14f0Smrg{
68063ef14f0Smrg	DBG(("%s: current vblank count: %d\n", __FUNCTION__, *sna_crtc_flags(crtc) & CRTC_VBLANK));
68163ef14f0Smrg	assert((*sna_crtc_flags(crtc) & CRTC_VBLANK) < CRTC_VBLANK);
68263ef14f0Smrg	++*sna_crtc_flags(crtc);
68363ef14f0Smrg}
68463ef14f0Smrg
68563ef14f0Smrgstatic inline void sna_crtc_clear_vblank(xf86CrtcPtr crtc)
68663ef14f0Smrg{
68763ef14f0Smrg	DBG(("%s: current vblank count: %d\n", __FUNCTION__, *sna_crtc_flags(crtc) & CRTC_VBLANK));
68863ef14f0Smrg	assert(*sna_crtc_flags(crtc) & CRTC_VBLANK);
68963ef14f0Smrg	--*sna_crtc_flags(crtc);
69063ef14f0Smrg}
69163ef14f0Smrg
69263ef14f0Smrgstatic inline bool sna_crtc_has_vblank(xf86CrtcPtr crtc)
69363ef14f0Smrg{
69463ef14f0Smrg	return *sna_crtc_flags(crtc) & CRTC_VBLANK;
69563ef14f0Smrg}
69603b705cfSriastradh
69703b705cfSriastradhCARD32 sna_format_for_depth(int depth);
69803b705cfSriastradhCARD32 sna_render_format_for_depth(int depth);
69903b705cfSriastradh
70003b705cfSriastradhvoid sna_debug_flush(struct sna *sna);
70103b705cfSriastradh
70242542f5fSchristosstatic inline bool
70342542f5fSchristosget_window_deltas(PixmapPtr pixmap, int16_t *x, int16_t *y)
70442542f5fSchristos{
70542542f5fSchristos#ifdef COMPOSITE
70642542f5fSchristos	*x = -pixmap->screen_x;
70742542f5fSchristos	*y = -pixmap->screen_y;
70842542f5fSchristos	return pixmap->screen_x | pixmap->screen_y;
70942542f5fSchristos#else
71042542f5fSchristos	*x = *y = 0;
71142542f5fSchristos	return false;
71242542f5fSchristos#endif
71342542f5fSchristos}
71442542f5fSchristos
71503b705cfSriastradhstatic inline bool
71603b705cfSriastradhget_drawable_deltas(DrawablePtr drawable, PixmapPtr pixmap, int16_t *x, int16_t *y)
71703b705cfSriastradh{
71803b705cfSriastradh#ifdef COMPOSITE
71942542f5fSchristos	if (drawable->type == DRAWABLE_WINDOW)
72042542f5fSchristos		return get_window_deltas(pixmap, x, y);
72103b705cfSriastradh#endif
72203b705cfSriastradh	*x = *y = 0;
72303b705cfSriastradh	return false;
72403b705cfSriastradh}
72503b705cfSriastradh
72603b705cfSriastradhstatic inline int
72703b705cfSriastradhget_drawable_dx(DrawablePtr drawable)
72803b705cfSriastradh{
72903b705cfSriastradh#ifdef COMPOSITE
73003b705cfSriastradh	if (drawable->type == DRAWABLE_WINDOW)
73103b705cfSriastradh		return -get_drawable_pixmap(drawable)->screen_x;
73203b705cfSriastradh#endif
73303b705cfSriastradh	return 0;
73403b705cfSriastradh}
73503b705cfSriastradh
73603b705cfSriastradhstatic inline int
73703b705cfSriastradhget_drawable_dy(DrawablePtr drawable)
73803b705cfSriastradh{
73903b705cfSriastradh#ifdef COMPOSITE
74003b705cfSriastradh	if (drawable->type == DRAWABLE_WINDOW)
74103b705cfSriastradh		return -get_drawable_pixmap(drawable)->screen_y;
74203b705cfSriastradh#endif
74303b705cfSriastradh	return 0;
74403b705cfSriastradh}
74503b705cfSriastradh
74642542f5fSchristosstruct sna_pixmap *sna_pixmap_attach_to_bo(PixmapPtr pixmap, struct kgem_bo *bo);
74703b705cfSriastradhstatic inline bool sna_pixmap_is_scanout(struct sna *sna, PixmapPtr pixmap)
74803b705cfSriastradh{
74903b705cfSriastradh	return (pixmap == sna->front &&
75003b705cfSriastradh		!sna->mode.shadow_active &&
75103b705cfSriastradh		(sna->flags & SNA_NO_WAIT) == 0);
75203b705cfSriastradh}
75303b705cfSriastradh
75442542f5fSchristosstatic inline int sna_max_tile_copy_size(struct sna *sna, struct kgem_bo *src, struct kgem_bo *dst)
75542542f5fSchristos{
75642542f5fSchristos	int min_object;
75742542f5fSchristos	int max_size;
75842542f5fSchristos
75942542f5fSchristos	max_size = sna->kgem.aperture_high * PAGE_SIZE;
76042542f5fSchristos	max_size -= MAX(kgem_bo_size(src), kgem_bo_size(dst));
76142542f5fSchristos	if (max_size <= 0) {
76242542f5fSchristos		DBG(("%s: tiles cannot fit into aperture\n", __FUNCTION__));
76342542f5fSchristos		return 0;
76442542f5fSchristos	}
76542542f5fSchristos
76642542f5fSchristos	if (max_size > sna->kgem.max_copy_tile_size)
76742542f5fSchristos		max_size = sna->kgem.max_copy_tile_size;
76842542f5fSchristos
76942542f5fSchristos	min_object = MIN(kgem_bo_size(src), kgem_bo_size(dst)) / 2;
77042542f5fSchristos	if (max_size > min_object)
77142542f5fSchristos		max_size = min_object;
77242542f5fSchristos	if (max_size <= 4096)
77342542f5fSchristos		max_size = 0;
77442542f5fSchristos
77542542f5fSchristos	DBG(("%s: using max tile size of %d\n", __FUNCTION__, max_size));
77642542f5fSchristos	return max_size;
77742542f5fSchristos}
77842542f5fSchristos
77903b705cfSriastradhPixmapPtr sna_pixmap_create_upload(ScreenPtr screen,
78003b705cfSriastradh				   int width, int height, int depth,
78103b705cfSriastradh				   unsigned flags);
78203b705cfSriastradhPixmapPtr sna_pixmap_create_unattached(ScreenPtr screen,
78303b705cfSriastradh				       int width, int height, int depth);
78403b705cfSriastradhvoid sna_pixmap_destroy(PixmapPtr pixmap);
78503b705cfSriastradh
78642542f5fSchristos#define assert_pixmap_map(pixmap, priv)  do { \
78742542f5fSchristos	assert(priv->mapped != MAPPED_NONE || pixmap->devPrivate.ptr == PTR(priv->ptr)); \
78813496ba1Ssnj	assert(priv->mapped != MAPPED_CPU || pixmap->devPrivate.ptr == MAP(priv->gpu_bo->map__cpu)); \
78913496ba1Ssnj	assert(priv->mapped != MAPPED_GTT || pixmap->devPrivate.ptr == priv->gpu_bo->map__gtt || pixmap->devPrivate.ptr == priv->gpu_bo->map__wc); \
79042542f5fSchristos} while (0)
79142542f5fSchristos
79242542f5fSchristosstatic inline void sna_pixmap_unmap(PixmapPtr pixmap, struct sna_pixmap *priv)
79342542f5fSchristos{
79442542f5fSchristos	if (priv->mapped == MAPPED_NONE) {
79542542f5fSchristos		assert(pixmap->devPrivate.ptr == PTR(priv->ptr));
79642542f5fSchristos		return;
79742542f5fSchristos	}
79842542f5fSchristos
79942542f5fSchristos	DBG(("%s: pixmap=%ld dropping %s mapping\n",
80042542f5fSchristos	     __FUNCTION__, pixmap->drawable.serialNumber,
80142542f5fSchristos	     priv->mapped == MAPPED_CPU ? "cpu" : "gtt"));
80242542f5fSchristos
80342542f5fSchristos	assert_pixmap_map(pixmap, priv);
80442542f5fSchristos
80542542f5fSchristos	pixmap->devPrivate.ptr = PTR(priv->ptr);
80642542f5fSchristos	pixmap->devKind = priv->stride;
80742542f5fSchristos
80842542f5fSchristos	priv->mapped = MAPPED_NONE;
80942542f5fSchristos}
81042542f5fSchristos
81103b705cfSriastradhbool
81203b705cfSriastradhsna_pixmap_undo_cow(struct sna *sna, struct sna_pixmap *priv, unsigned flags);
81303b705cfSriastradh
81403b705cfSriastradh#define MOVE_WRITE 0x1
81503b705cfSriastradh#define MOVE_READ 0x2
81603b705cfSriastradh#define MOVE_INPLACE_HINT 0x4
81703b705cfSriastradh#define MOVE_ASYNC_HINT 0x8
81803b705cfSriastradh#define MOVE_SOURCE_HINT 0x10
81903b705cfSriastradh#define MOVE_WHOLE_HINT 0x20
82003b705cfSriastradh#define __MOVE_FORCE 0x40
82103b705cfSriastradh#define __MOVE_DRI 0x80
82242542f5fSchristos#define __MOVE_SCANOUT 0x100
82342542f5fSchristos#define __MOVE_TILED 0x200
82413496ba1Ssnj#define __MOVE_PRIME 0x400
82503b705cfSriastradh
82642542f5fSchristosstruct sna_pixmap *
82703b705cfSriastradhsna_pixmap_move_area_to_gpu(PixmapPtr pixmap, const BoxRec *box, unsigned int flags);
82803b705cfSriastradh
82903b705cfSriastradhstruct sna_pixmap *sna_pixmap_move_to_gpu(PixmapPtr pixmap, unsigned flags);
83003b705cfSriastradhstatic inline struct sna_pixmap *
83103b705cfSriastradhsna_pixmap_force_to_gpu(PixmapPtr pixmap, unsigned flags)
83203b705cfSriastradh{
83303b705cfSriastradh	/* Unlike move-to-gpu, we ignore wedged and always create the GPU bo */
83442542f5fSchristos	DBG(("%s(pixmap=%ld, flags=%x)\n", __FUNCTION__, pixmap->drawable.serialNumber, flags));
83503b705cfSriastradh	return sna_pixmap_move_to_gpu(pixmap, flags | __MOVE_FORCE);
83603b705cfSriastradh}
83703b705cfSriastradhbool must_check _sna_pixmap_move_to_cpu(PixmapPtr pixmap, unsigned flags);
83803b705cfSriastradhstatic inline bool must_check sna_pixmap_move_to_cpu(PixmapPtr pixmap, unsigned flags)
83903b705cfSriastradh{
84003b705cfSriastradh	if (flags == MOVE_READ) {
84103b705cfSriastradh		struct sna_pixmap *priv = sna_pixmap(pixmap);
84203b705cfSriastradh		if (priv == NULL)
84303b705cfSriastradh			return true;
84403b705cfSriastradh	}
84503b705cfSriastradh
84603b705cfSriastradh	return _sna_pixmap_move_to_cpu(pixmap, flags);
84703b705cfSriastradh}
84803b705cfSriastradhbool must_check sna_drawable_move_region_to_cpu(DrawablePtr drawable,
84903b705cfSriastradh						RegionPtr region,
85003b705cfSriastradh						unsigned flags);
85103b705cfSriastradh
85203b705cfSriastradhbool must_check sna_drawable_move_to_cpu(DrawablePtr drawable, unsigned flags);
85303b705cfSriastradh
85403b705cfSriastradhstatic inline bool must_check
85503b705cfSriastradhsna_drawable_move_to_gpu(DrawablePtr drawable, unsigned flags)
85603b705cfSriastradh{
85703b705cfSriastradh	return sna_pixmap_move_to_gpu(get_drawable_pixmap(drawable), flags) != NULL;
85803b705cfSriastradh}
85903b705cfSriastradh
86003b705cfSriastradhvoid sna_add_flush_pixmap(struct sna *sna,
86103b705cfSriastradh			  struct sna_pixmap *priv,
86203b705cfSriastradh			  struct kgem_bo *bo);
86303b705cfSriastradh
86403b705cfSriastradhstruct kgem_bo *sna_pixmap_change_tiling(PixmapPtr pixmap, uint32_t tiling);
86503b705cfSriastradh
86603b705cfSriastradh#define PREFER_GPU	0x1
86703b705cfSriastradh#define FORCE_GPU	0x2
86803b705cfSriastradh#define RENDER_GPU	0x4
86942542f5fSchristos#define IGNORE_DAMAGE	0x8
87003b705cfSriastradh#define REPLACES	0x10
87103b705cfSriastradhstruct kgem_bo *
87203b705cfSriastradhsna_drawable_use_bo(DrawablePtr drawable, unsigned flags, const BoxRec *box,
87303b705cfSriastradh		    struct sna_damage ***damage);
87403b705cfSriastradh
87503b705cfSriastradhinline static int16_t bound(int16_t a, uint16_t b)
87603b705cfSriastradh{
87703b705cfSriastradh	int v = (int)a + (int)b;
87803b705cfSriastradh	if (v > MAXSHORT)
87903b705cfSriastradh		return MAXSHORT;
88003b705cfSriastradh	return v;
88103b705cfSriastradh}
88203b705cfSriastradh
88303b705cfSriastradhinline static int16_t clamp(int16_t a, int16_t b)
88403b705cfSriastradh{
88503b705cfSriastradh	int v = (int)a + (int)b;
88603b705cfSriastradh	if (v > MAXSHORT)
88703b705cfSriastradh		return MAXSHORT;
88803b705cfSriastradh	if (v < MINSHORT)
88903b705cfSriastradh		return MINSHORT;
89003b705cfSriastradh	return v;
89103b705cfSriastradh}
89203b705cfSriastradh
89303b705cfSriastradhstatic inline bool box_empty(const BoxRec *box)
89403b705cfSriastradh{
89503b705cfSriastradh	return box->x2 <= box->x1 || box->y2 <= box->y1;
89603b705cfSriastradh}
89703b705cfSriastradh
89842542f5fSchristosstatic inline bool
89942542f5fSchristosbox_covers_pixmap(PixmapPtr pixmap, const BoxRec *box)
90042542f5fSchristos{
90142542f5fSchristos	int w = box->x2 - box->x1;
90242542f5fSchristos	int h = box->y2 - box->y1;
90342542f5fSchristos	return pixmap->drawable.width <= w && pixmap->drawable.height <= h;
90442542f5fSchristos}
90542542f5fSchristos
90603b705cfSriastradhstatic inline bool
90703b705cfSriastradhbox_inplace(PixmapPtr pixmap, const BoxRec *box)
90803b705cfSriastradh{
90903b705cfSriastradh	struct sna *sna = to_sna_from_pixmap(pixmap);
91003b705cfSriastradh	return ((int)(box->x2 - box->x1) * (int)(box->y2 - box->y1) * pixmap->drawable.bitsPerPixel >> 12) >= sna->kgem.half_cpu_cache_pages;
91103b705cfSriastradh}
91203b705cfSriastradh
91342542f5fSchristosstatic inline bool
91442542f5fSchristoswhole_pixmap_inplace(PixmapPtr pixmap)
91542542f5fSchristos{
91642542f5fSchristos	struct sna *sna = to_sna_from_pixmap(pixmap);
91742542f5fSchristos	return ((int)pixmap->drawable.width * (int)pixmap->drawable.height * pixmap->drawable.bitsPerPixel >> 12) >= sna->kgem.half_cpu_cache_pages;
91842542f5fSchristos}
91942542f5fSchristos
92003b705cfSriastradhstatic inline bool
92103b705cfSriastradhregion_subsumes_drawable(RegionPtr region, DrawablePtr drawable)
92203b705cfSriastradh{
92303b705cfSriastradh	const BoxRec *extents;
92403b705cfSriastradh
92503b705cfSriastradh	if (region->data)
92603b705cfSriastradh		return false;
92703b705cfSriastradh
92803b705cfSriastradh	extents = RegionExtents(region);
92903b705cfSriastradh	return  extents->x1 <= 0 && extents->y1 <= 0 &&
93003b705cfSriastradh		extents->x2 >= drawable->width &&
93103b705cfSriastradh		extents->y2 >= drawable->height;
93203b705cfSriastradh}
93303b705cfSriastradh
93442542f5fSchristosstatic inline bool
93542542f5fSchristosregion_subsumes_pixmap(const RegionRec *region, PixmapPtr pixmap)
93642542f5fSchristos{
93742542f5fSchristos	if (region->data)
93842542f5fSchristos		return false;
93942542f5fSchristos
94042542f5fSchristos	return (region->extents.x2 - region->extents.x1 >= pixmap->drawable.width &&
94142542f5fSchristos		region->extents.y2 - region->extents.y1 >= pixmap->drawable.height);
94242542f5fSchristos}
94342542f5fSchristos
94403b705cfSriastradhstatic inline bool
94503b705cfSriastradhregion_subsumes_damage(const RegionRec *region, struct sna_damage *damage)
94603b705cfSriastradh{
94703b705cfSriastradh	const BoxRec *re, *de;
94803b705cfSriastradh
94903b705cfSriastradh	DBG(("%s?\n", __FUNCTION__));
95003b705cfSriastradh	assert(damage);
95103b705cfSriastradh
95203b705cfSriastradh	re = &region->extents;
95303b705cfSriastradh	de = &DAMAGE_PTR(damage)->extents;
95403b705cfSriastradh	DBG(("%s: region (%d, %d), (%d, %d), damage (%d, %d), (%d, %d)\n",
95503b705cfSriastradh	     __FUNCTION__,
95603b705cfSriastradh	     re->x1, re->y1, re->x2, re->y2,
95703b705cfSriastradh	     de->x1, de->y1, de->x2, de->y2));
95803b705cfSriastradh
95903b705cfSriastradh	if (re->x2 < de->x2 || re->x1 > de->x1 ||
96003b705cfSriastradh	    re->y2 < de->y2 || re->y1 > de->y1) {
96103b705cfSriastradh		DBG(("%s: not contained\n", __FUNCTION__));
96203b705cfSriastradh		return false;
96303b705cfSriastradh	}
96403b705cfSriastradh
96503b705cfSriastradh	if (region->data == NULL) {
96603b705cfSriastradh		DBG(("%s: singular region contains damage\n", __FUNCTION__));
96703b705cfSriastradh		return true;
96803b705cfSriastradh	}
96903b705cfSriastradh
97003b705cfSriastradh	return pixman_region_contains_rectangle((RegionPtr)region,
97103b705cfSriastradh						(BoxPtr)de) == PIXMAN_REGION_IN;
97203b705cfSriastradh}
97303b705cfSriastradh
97403b705cfSriastradhstatic inline bool
97503b705cfSriastradhsna_drawable_is_clear(DrawablePtr d)
97603b705cfSriastradh{
97703b705cfSriastradh	struct sna_pixmap *priv = sna_pixmap(get_drawable_pixmap(d));
97803b705cfSriastradh	return priv && priv->clear && priv->clear_color == 0;
97903b705cfSriastradh}
98003b705cfSriastradh
98103b705cfSriastradhstatic inline struct kgem_bo *__sna_pixmap_get_bo(PixmapPtr pixmap)
98203b705cfSriastradh{
98303b705cfSriastradh	return sna_pixmap(pixmap)->gpu_bo;
98403b705cfSriastradh}
98503b705cfSriastradh
98603b705cfSriastradhstatic inline struct kgem_bo *__sna_drawable_peek_bo(DrawablePtr d)
98703b705cfSriastradh{
98842542f5fSchristos	struct sna_pixmap *priv = sna_pixmap(get_drawable_pixmap(d));
98942542f5fSchristos	return priv ? priv->gpu_bo : NULL;
99003b705cfSriastradh}
99103b705cfSriastradh
99203b705cfSriastradhstatic inline struct kgem_bo *sna_pixmap_pin(PixmapPtr pixmap, unsigned flags)
99303b705cfSriastradh{
99403b705cfSriastradh	struct sna_pixmap *priv;
99503b705cfSriastradh
99642542f5fSchristos	priv = sna_pixmap_force_to_gpu(pixmap, MOVE_READ);
99703b705cfSriastradh	if (!priv)
99803b705cfSriastradh		return NULL;
99903b705cfSriastradh
100003b705cfSriastradh	priv->pinned |= flags;
100103b705cfSriastradh	return priv->gpu_bo;
100203b705cfSriastradh}
100303b705cfSriastradh
100403b705cfSriastradh
100503b705cfSriastradhstatic inline bool
100603b705cfSriastradh_sna_transform_point(const PictTransform *transform,
100703b705cfSriastradh		     int64_t x, int64_t y, int64_t result[3])
100803b705cfSriastradh{
100903b705cfSriastradh	int j;
101003b705cfSriastradh
101103b705cfSriastradh	for (j = 0; j < 3; j++)
101203b705cfSriastradh		result[j] = (transform->matrix[j][0] * x +
101303b705cfSriastradh			     transform->matrix[j][1] * y +
101403b705cfSriastradh			     transform->matrix[j][2]);
101503b705cfSriastradh
101603b705cfSriastradh	return result[2] != 0;
101703b705cfSriastradh}
101803b705cfSriastradh
101903b705cfSriastradhstatic inline void
102003b705cfSriastradh_sna_get_transformed_coordinates(int x, int y,
102103b705cfSriastradh				 const PictTransform *transform,
102203b705cfSriastradh				 float *x_out, float *y_out)
102303b705cfSriastradh{
102403b705cfSriastradh
102503b705cfSriastradh	int64_t result[3];
102603b705cfSriastradh
102703b705cfSriastradh	_sna_transform_point(transform, x, y, result);
102803b705cfSriastradh	*x_out = result[0] / (double)result[2];
102903b705cfSriastradh	*y_out = result[1] / (double)result[2];
103003b705cfSriastradh}
103103b705cfSriastradh
103203b705cfSriastradhstatic inline void
103303b705cfSriastradh_sna_get_transformed_scaled(int x, int y,
103403b705cfSriastradh			    const PictTransform *transform, const float *sf,
103503b705cfSriastradh			    float *x_out, float *y_out)
103603b705cfSriastradh{
103703b705cfSriastradh	*x_out = sf[0] * (transform->matrix[0][0] * x +
103803b705cfSriastradh			  transform->matrix[0][1] * y +
103903b705cfSriastradh			  transform->matrix[0][2]);
104003b705cfSriastradh
104103b705cfSriastradh	*y_out = sf[1] * (transform->matrix[1][0] * x +
104203b705cfSriastradh			  transform->matrix[1][1] * y +
104303b705cfSriastradh			  transform->matrix[1][2]);
104403b705cfSriastradh}
104503b705cfSriastradh
104603b705cfSriastradhvoid
104703b705cfSriastradhsna_get_transformed_coordinates(int x, int y,
104803b705cfSriastradh				const PictTransform *transform,
104903b705cfSriastradh				float *x_out, float *y_out);
105003b705cfSriastradh
105103b705cfSriastradhvoid
105203b705cfSriastradhsna_get_transformed_coordinates_3d(int x, int y,
105303b705cfSriastradh				   const PictTransform *transform,
105403b705cfSriastradh				   float *x_out, float *y_out, float *z_out);
105503b705cfSriastradh
105603b705cfSriastradhbool sna_transform_is_affine(const PictTransform *t);
105703b705cfSriastradhbool sna_transform_is_translation(const PictTransform *t,
105803b705cfSriastradh				  pixman_fixed_t *tx, pixman_fixed_t *ty);
105942542f5fSchristosbool sna_transform_is_integer_translation(const PictTransform *t,
106042542f5fSchristos					  int16_t *tx, int16_t *ty);
106142542f5fSchristosbool sna_transform_is_imprecise_integer_translation(const PictTransform *t,
106242542f5fSchristos					       int filter, bool precise,
106342542f5fSchristos					       int16_t *tx, int16_t *ty);
106403b705cfSriastradhstatic inline bool
106503b705cfSriastradhsna_affine_transform_is_rotation(const PictTransform *t)
106603b705cfSriastradh{
106703b705cfSriastradh	assert(sna_transform_is_affine(t));
106803b705cfSriastradh	return t->matrix[0][1] | t->matrix[1][0];
106903b705cfSriastradh}
107003b705cfSriastradh
107103b705cfSriastradhstatic inline bool
107203b705cfSriastradhsna_transform_equal(const PictTransform *a, const PictTransform *b)
107303b705cfSriastradh{
107403b705cfSriastradh	if (a == b)
107503b705cfSriastradh		return true;
107603b705cfSriastradh
107703b705cfSriastradh	if (a == NULL || b == NULL)
107803b705cfSriastradh		return false;
107903b705cfSriastradh
108003b705cfSriastradh	return memcmp(a, b, sizeof(*a)) == 0;
108103b705cfSriastradh}
108203b705cfSriastradh
108303b705cfSriastradhstatic inline bool
108403b705cfSriastradhsna_picture_alphamap_equal(PicturePtr a, PicturePtr b)
108503b705cfSriastradh{
108603b705cfSriastradh	if (a->alphaMap != b->alphaMap)
108703b705cfSriastradh		return false;
108803b705cfSriastradh
108903b705cfSriastradh	if (a->alphaMap)
109003b705cfSriastradh		return false;
109103b705cfSriastradh
109203b705cfSriastradh	return (a->alphaOrigin.x == b->alphaOrigin.x &&
109303b705cfSriastradh		a->alphaOrigin.y == b->alphaOrigin.y);
109403b705cfSriastradh}
109503b705cfSriastradh
109603b705cfSriastradhstatic inline bool wedged(struct sna *sna)
109703b705cfSriastradh{
109803b705cfSriastradh	return unlikely(sna->kgem.wedged);
109903b705cfSriastradh}
110003b705cfSriastradh
110103b705cfSriastradhstatic inline bool can_render(struct sna *sna)
110203b705cfSriastradh{
110303b705cfSriastradh	return likely(!sna->kgem.wedged && sna->render.prefer_gpu & PREFER_GPU_RENDER);
110403b705cfSriastradh}
110503b705cfSriastradh
110603b705cfSriastradhstatic inline uint32_t pixmap_size(PixmapPtr pixmap)
110703b705cfSriastradh{
110803b705cfSriastradh	return (pixmap->drawable.height - 1) * pixmap->devKind +
110903b705cfSriastradh		pixmap->drawable.width * pixmap->drawable.bitsPerPixel/8;
111003b705cfSriastradh}
111103b705cfSriastradh
111203b705cfSriastradhbool sna_accel_init(ScreenPtr sreen, struct sna *sna);
111303b705cfSriastradhvoid sna_accel_create(struct sna *sna);
111463ef14f0Smrgvoid sna_accel_block(struct sna *sna, struct timeval **tv);
111542542f5fSchristosvoid sna_accel_flush(struct sna *sna);
111642542f5fSchristosvoid sna_accel_enter(struct sna *sna);
111742542f5fSchristosvoid sna_accel_leave(struct sna *sna);
111803b705cfSriastradhvoid sna_accel_close(struct sna *sna);
111903b705cfSriastradhvoid sna_accel_free(struct sna *sna);
112003b705cfSriastradh
112163ef14f0Smrgvoid sna_watch_flush(struct sna *sna, int enable);
112203b705cfSriastradhvoid sna_copy_fbcon(struct sna *sna);
112303b705cfSriastradh
112403b705cfSriastradhbool sna_composite_create(struct sna *sna);
112503b705cfSriastradhvoid sna_composite_close(struct sna *sna);
112603b705cfSriastradh
112703b705cfSriastradhvoid sna_composite(CARD8 op,
112803b705cfSriastradh		   PicturePtr src,
112903b705cfSriastradh		   PicturePtr mask,
113003b705cfSriastradh		   PicturePtr dst,
113103b705cfSriastradh		   INT16 src_x,  INT16 src_y,
113203b705cfSriastradh		   INT16 mask_x, INT16 mask_y,
113303b705cfSriastradh		   INT16 dst_x,  INT16 dst_y,
113403b705cfSriastradh		   CARD16 width, CARD16 height);
113503b705cfSriastradhvoid sna_composite_fb(CARD8 op,
113603b705cfSriastradh		      PicturePtr src,
113703b705cfSriastradh		      PicturePtr mask,
113803b705cfSriastradh		      PicturePtr dst,
113903b705cfSriastradh		      RegionPtr region,
114003b705cfSriastradh		      INT16 src_x,  INT16 src_y,
114103b705cfSriastradh		      INT16 mask_x, INT16 mask_y,
114203b705cfSriastradh		      INT16 dst_x,  INT16 dst_y,
114303b705cfSriastradh		      CARD16 width, CARD16 height);
114403b705cfSriastradhvoid sna_composite_rectangles(CARD8		 op,
114503b705cfSriastradh			      PicturePtr		 dst,
114603b705cfSriastradh			      xRenderColor	*color,
114703b705cfSriastradh			      int			 num_rects,
114803b705cfSriastradh			      xRectangle		*rects);
114903b705cfSriastradhvoid sna_composite_trapezoids(CARD8 op,
115003b705cfSriastradh			      PicturePtr src,
115103b705cfSriastradh			      PicturePtr dst,
115203b705cfSriastradh			      PictFormatPtr maskFormat,
115303b705cfSriastradh			      INT16 xSrc, INT16 ySrc,
115403b705cfSriastradh			      int ntrap, xTrapezoid *traps);
115503b705cfSriastradhvoid sna_add_traps(PicturePtr picture, INT16 x, INT16 y, int n, xTrap *t);
115603b705cfSriastradh
115703b705cfSriastradhvoid sna_composite_triangles(CARD8 op,
115803b705cfSriastradh			     PicturePtr src,
115903b705cfSriastradh			     PicturePtr dst,
116003b705cfSriastradh			     PictFormatPtr maskFormat,
116103b705cfSriastradh			     INT16 xSrc, INT16 ySrc,
116203b705cfSriastradh			     int ntri, xTriangle *tri);
116303b705cfSriastradh
116403b705cfSriastradhvoid sna_composite_tristrip(CARD8 op,
116503b705cfSriastradh			    PicturePtr src,
116603b705cfSriastradh			    PicturePtr dst,
116703b705cfSriastradh			    PictFormatPtr maskFormat,
116803b705cfSriastradh			    INT16 xSrc, INT16 ySrc,
116903b705cfSriastradh			    int npoints, xPointFixed *points);
117003b705cfSriastradh
117103b705cfSriastradhvoid sna_composite_trifan(CARD8 op,
117203b705cfSriastradh			  PicturePtr src,
117303b705cfSriastradh			  PicturePtr dst,
117403b705cfSriastradh			  PictFormatPtr maskFormat,
117503b705cfSriastradh			  INT16 xSrc, INT16 ySrc,
117603b705cfSriastradh			  int npoints, xPointFixed *points);
117703b705cfSriastradh
117803b705cfSriastradhbool sna_gradients_create(struct sna *sna);
117903b705cfSriastradhvoid sna_gradients_close(struct sna *sna);
118003b705cfSriastradh
118103b705cfSriastradhbool sna_glyphs_create(struct sna *sna);
118203b705cfSriastradhvoid sna_glyphs(CARD8 op,
118303b705cfSriastradh		PicturePtr src,
118403b705cfSriastradh		PicturePtr dst,
118503b705cfSriastradh		PictFormatPtr mask,
118603b705cfSriastradh		INT16 xSrc, INT16 ySrc,
118703b705cfSriastradh		int nlist,
118803b705cfSriastradh		GlyphListPtr list,
118903b705cfSriastradh		GlyphPtr *glyphs);
119003b705cfSriastradhvoid sna_glyphs__shared(CARD8 op,
119103b705cfSriastradh			PicturePtr src,
119203b705cfSriastradh			PicturePtr dst,
119303b705cfSriastradh			PictFormatPtr mask,
119403b705cfSriastradh			INT16 src_x, INT16 src_y,
119503b705cfSriastradh			int nlist, GlyphListPtr list, GlyphPtr *glyphs);
119603b705cfSriastradhvoid sna_glyph_unrealize(ScreenPtr screen, GlyphPtr glyph);
119703b705cfSriastradhvoid sna_glyphs_close(struct sna *sna);
119803b705cfSriastradh
119903b705cfSriastradhvoid sna_read_boxes(struct sna *sna, PixmapPtr dst, struct kgem_bo *src_bo,
120003b705cfSriastradh		    const BoxRec *box, int n);
120103b705cfSriastradhbool sna_write_boxes(struct sna *sna, PixmapPtr dst,
120203b705cfSriastradh		     struct kgem_bo *dst_bo, int16_t dst_dx, int16_t dst_dy,
120303b705cfSriastradh		     const void *src, int stride, int16_t src_dx, int16_t src_dy,
120403b705cfSriastradh		     const BoxRec *box, int n);
120542542f5fSchristosbool sna_write_boxes__xor(struct sna *sna, PixmapPtr dst,
120603b705cfSriastradh			  struct kgem_bo *dst_bo, int16_t dst_dx, int16_t dst_dy,
120703b705cfSriastradh			  const void *src, int stride, int16_t src_dx, int16_t src_dy,
120803b705cfSriastradh			  const BoxRec *box, int nbox,
120903b705cfSriastradh			  uint32_t and, uint32_t or);
121003b705cfSriastradh
121103b705cfSriastradhbool sna_replace(struct sna *sna,
121203b705cfSriastradh		 PixmapPtr pixmap,
121303b705cfSriastradh		 const void *src, int stride);
121442542f5fSchristosbool sna_replace__xor(struct sna *sna,
121542542f5fSchristos		      PixmapPtr pixmap,
121642542f5fSchristos		      const void *src, int stride,
121742542f5fSchristos		      uint32_t and, uint32_t or);
121803b705cfSriastradh
121903b705cfSriastradhbool
122003b705cfSriastradhsna_compute_composite_extents(BoxPtr extents,
122103b705cfSriastradh			      PicturePtr src, PicturePtr mask, PicturePtr dst,
122203b705cfSriastradh			      INT16 src_x,  INT16 src_y,
122303b705cfSriastradh			      INT16 mask_x, INT16 mask_y,
122403b705cfSriastradh			      INT16 dst_x,  INT16 dst_y,
122503b705cfSriastradh			      CARD16 width, CARD16 height);
122603b705cfSriastradhbool
122703b705cfSriastradhsna_compute_composite_region(RegionPtr region,
122803b705cfSriastradh			     PicturePtr src, PicturePtr mask, PicturePtr dst,
122903b705cfSriastradh			     INT16 src_x,  INT16 src_y,
123003b705cfSriastradh			     INT16 mask_x, INT16 mask_y,
123103b705cfSriastradh			     INT16 dst_x,  INT16 dst_y,
123203b705cfSriastradh			     CARD16 width, CARD16 height);
123303b705cfSriastradh
123403b705cfSriastradhvoid
123503b705cfSriastradhmemcpy_blt(const void *src, void *dst, int bpp,
123603b705cfSriastradh	   int32_t src_stride, int32_t dst_stride,
123703b705cfSriastradh	   int16_t src_x, int16_t src_y,
123803b705cfSriastradh	   int16_t dst_x, int16_t dst_y,
123903b705cfSriastradh	   uint16_t width, uint16_t height);
124003b705cfSriastradh
124163ef14f0Smrgvoid
124263ef14f0Smrgaffine_blt(const void *src, void *dst, int bpp,
124363ef14f0Smrg	   int16_t src_x, int16_t src_y,
124463ef14f0Smrg	   int16_t src_width, int16_t src_height,
124563ef14f0Smrg	   int32_t src_stride,
124663ef14f0Smrg	   int16_t dst_x, int16_t dst_y,
124763ef14f0Smrg	   uint16_t dst_width, uint16_t dst_height,
124863ef14f0Smrg	   int32_t dst_stride,
124963ef14f0Smrg	   const struct pixman_f_transform *t);
125063ef14f0Smrg
125103b705cfSriastradhvoid
125203b705cfSriastradhmemmove_box(const void *src, void *dst,
125303b705cfSriastradh	    int bpp, int32_t stride,
125403b705cfSriastradh	    const BoxRec *box,
125503b705cfSriastradh	    int dx, int dy);
125603b705cfSriastradh
125703b705cfSriastradhvoid
125803b705cfSriastradhmemcpy_xor(const void *src, void *dst, int bpp,
125903b705cfSriastradh	   int32_t src_stride, int32_t dst_stride,
126003b705cfSriastradh	   int16_t src_x, int16_t src_y,
126103b705cfSriastradh	   int16_t dst_x, int16_t dst_y,
126203b705cfSriastradh	   uint16_t width, uint16_t height,
126303b705cfSriastradh	   uint32_t and, uint32_t or);
126403b705cfSriastradh
126503b705cfSriastradh#define SNA_CREATE_FB 0x10
126603b705cfSriastradh#define SNA_CREATE_SCRATCH 0x11
126703b705cfSriastradh
126803b705cfSriastradhinline static bool is_power_of_two(unsigned x)
126903b705cfSriastradh{
127003b705cfSriastradh	return (x & (x-1)) == 0;
127103b705cfSriastradh}
127203b705cfSriastradh
127303b705cfSriastradhinline static bool is_clipped(const RegionRec *r,
127403b705cfSriastradh			      const DrawableRec *d)
127503b705cfSriastradh{
127642542f5fSchristos	DBG(("%s: region[%d]x(%d, %d),(%d, %d) against drawable %dx%d\n",
127742542f5fSchristos	     __FUNCTION__,
127842542f5fSchristos	     region_num_rects(r),
127942542f5fSchristos	     r->extents.x1, r->extents.y1,
128042542f5fSchristos	     r->extents.x2, r->extents.y2,
128142542f5fSchristos	     d->width, d->height));
128203b705cfSriastradh	return (r->data ||
128303b705cfSriastradh		r->extents.x2 - r->extents.x1 != d->width ||
128403b705cfSriastradh		r->extents.y2 - r->extents.y1 != d->height);
128503b705cfSriastradh}
128603b705cfSriastradh
128703b705cfSriastradhinline static bool
128803b705cfSriastradhbox_intersect(BoxPtr a, const BoxRec *b)
128903b705cfSriastradh{
129003b705cfSriastradh	if (a->x1 < b->x1)
129103b705cfSriastradh		a->x1 = b->x1;
129203b705cfSriastradh	if (a->x2 > b->x2)
129303b705cfSriastradh		a->x2 = b->x2;
129403b705cfSriastradh	if (a->x1 >= a->x2)
129503b705cfSriastradh		return false;
129603b705cfSriastradh
129703b705cfSriastradh	if (a->y1 < b->y1)
129803b705cfSriastradh		a->y1 = b->y1;
129903b705cfSriastradh	if (a->y2 > b->y2)
130003b705cfSriastradh		a->y2 = b->y2;
130103b705cfSriastradh	if (a->y1 >= a->y2)
130203b705cfSriastradh		return false;
130303b705cfSriastradh
130403b705cfSriastradh	return true;
130503b705cfSriastradh}
130603b705cfSriastradh
130763ef14f0Smrgconst BoxRec *
130863ef14f0Smrg__find_clip_box_for_y(const BoxRec *begin, const BoxRec *end, int16_t y);
130963ef14f0Smrginline static const BoxRec *
131063ef14f0Smrgfind_clip_box_for_y(const BoxRec *begin, const BoxRec *end, int16_t y)
131163ef14f0Smrg{
131263ef14f0Smrg	/* Special case for incremental trapezoid clipping */
131363ef14f0Smrg	if (begin == end)
131463ef14f0Smrg		return end;
131563ef14f0Smrg
131663ef14f0Smrg	/* Quick test if scanline is within range of clip boxes */
131763ef14f0Smrg	if (begin->y2 > y) {
131863ef14f0Smrg		assert(end == begin + 1 ||
131963ef14f0Smrg		       __find_clip_box_for_y(begin, end, y) == begin);
132063ef14f0Smrg		return begin;
132163ef14f0Smrg	}
132263ef14f0Smrg	if (y >= end[-1].y2) {
132363ef14f0Smrg		assert(end == begin + 1 ||
132463ef14f0Smrg		       __find_clip_box_for_y(begin, end, y) == end);
132563ef14f0Smrg		return end;
132663ef14f0Smrg	}
132763ef14f0Smrg
132863ef14f0Smrg	/* Otherwise bisect to find the first box crossing y */
132963ef14f0Smrg	return __find_clip_box_for_y(begin, end, y);
133063ef14f0Smrg}
133163ef14f0Smrg
133203b705cfSriastradhunsigned sna_cpu_detect(void);
133303b705cfSriastradhchar *sna_cpu_features_to_string(unsigned features, char *line);
133403b705cfSriastradh
133542542f5fSchristos/* sna_acpi.c */
133642542f5fSchristosint sna_acpi_open(void);
133742542f5fSchristosvoid sna_acpi_init(struct sna *sna);
133842542f5fSchristosvoid _sna_acpi_wakeup(struct sna *sna);
1339fe196524Smrgstatic inline void sna_acpi_wakeup(struct sna *sna)
134042542f5fSchristos{
1341fe196524Smrg	_sna_acpi_wakeup(sna);
134242542f5fSchristos}
134342542f5fSchristosvoid sna_acpi_fini(struct sna *sna);
134442542f5fSchristos
134503b705cfSriastradhvoid sna_threads_init(void);
134603b705cfSriastradhint sna_use_threads (int width, int height, int threshold);
134742542f5fSchristosvoid sna_threads_run(int id, void (*func)(void *arg), void *arg);
134842542f5fSchristosvoid sna_threads_trap(int sig);
134903b705cfSriastradhvoid sna_threads_wait(void);
135042542f5fSchristosvoid sna_threads_kill(void);
135103b705cfSriastradh
135203b705cfSriastradhvoid sna_image_composite(pixman_op_t        op,
135303b705cfSriastradh			 pixman_image_t    *src,
135403b705cfSriastradh			 pixman_image_t    *mask,
135503b705cfSriastradh			 pixman_image_t    *dst,
135603b705cfSriastradh			 int16_t            src_x,
135703b705cfSriastradh			 int16_t            src_y,
135803b705cfSriastradh			 int16_t            mask_x,
135903b705cfSriastradh			 int16_t            mask_y,
136003b705cfSriastradh			 int16_t            dst_x,
136103b705cfSriastradh			 int16_t            dst_y,
136203b705cfSriastradh			 uint16_t           width,
136303b705cfSriastradh			 uint16_t           height);
136403b705cfSriastradh
136542542f5fSchristosextern jmp_buf sigjmp[4];
136642542f5fSchristosextern volatile sig_atomic_t sigtrap;
136742542f5fSchristos
136842542f5fSchristos#define sigtrap_assert_inactive() assert(sigtrap == 0)
136942542f5fSchristos#define sigtrap_assert_active() assert(sigtrap > 0 && sigtrap <= ARRAY_SIZE(sigjmp))
137042542f5fSchristos#define sigtrap_get() sigsetjmp(sigjmp[sigtrap++], 1)
137142542f5fSchristos
137242542f5fSchristosstatic inline void sigtrap_put(void)
137342542f5fSchristos{
137442542f5fSchristos	sigtrap_assert_active();
137542542f5fSchristos	--sigtrap;
137642542f5fSchristos}
137742542f5fSchristos
137842542f5fSchristos#define RR_Rotate_All (RR_Rotate_0 | RR_Rotate_90 | RR_Rotate_180 | RR_Rotate_270)
137942542f5fSchristos#define RR_Reflect_All (RR_Reflect_X | RR_Reflect_Y)
138042542f5fSchristos
138142542f5fSchristos#ifndef HAVE_GETLINE
138242542f5fSchristos#include <stdio.h>
138342542f5fSchristosextern int getline(char **line, size_t *len, FILE *file);
138442542f5fSchristos#endif
138542542f5fSchristos
138663ef14f0Smrgstatic inline void add_shm_flush(struct sna *sna, struct sna_pixmap *priv)
138763ef14f0Smrg{
138863ef14f0Smrg	if (!priv->shm)
138963ef14f0Smrg		return;
139063ef14f0Smrg
139163ef14f0Smrg	DBG(("%s: marking handle=%d for SHM flush\n",
139263ef14f0Smrg	     __FUNCTION__, priv->cpu_bo->handle));
139363ef14f0Smrg
139463ef14f0Smrg	assert(!priv->flush);
139563ef14f0Smrg	sna_add_flush_pixmap(sna, priv, priv->cpu_bo);
139663ef14f0Smrg	sna->needs_shm_flush = true;
139763ef14f0Smrg}
139863ef14f0Smrg
139903b705cfSriastradh#endif /* _SNA_H */
1400