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