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