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