/* * Copyright 2000 ATI Technologies Inc., Markham, Ontario, and * VA Linux Systems Inc., Fremont, California. * * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation on the rights to use, copy, modify, merge, * publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * * The above copyright notice and this permission notice (including the * next paragraph) shall be included in all copies or substantial * portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NON-INFRINGEMENT. IN NO EVENT SHALL ATI, VA LINUX SYSTEMS AND/OR * THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ /* * Authors: * Kevin E. Martin * Rickard E. Faith * Alan Hourihane * */ #ifndef _RADEON_H_ #define _RADEON_H_ #include /* For abs() */ #include /* For usleep() */ #include /* For gettimeofday() */ #include "config.h" #include "xf86str.h" #include "compiler.h" /* PCI support */ #include "xf86Pci.h" #include "exa.h" /* Exa and Cursor Support */ #include "xf86Cursor.h" /* DDC support */ #include "xf86DDC.h" /* Xv support */ #include "xf86xv.h" #include "radeon_probe.h" /* DRI support */ #include "xf86drm.h" #include "radeon_drm.h" #ifndef RADEON_GEM_NO_CPU_ACCESS #define RADEON_GEM_NO_CPU_ACCESS (1 << 4) #endif #ifdef DAMAGE #include "damage.h" #include "globals.h" #endif #include "xf86Crtc.h" #include "X11/Xatom.h" #include "radeon_bo.h" #include "radeon_cs.h" #include "radeon_dri2.h" #include "drmmode_display.h" #include "radeon_surface.h" #include "radeon_bo_helper.h" /* Render support */ #ifdef RENDER #include "picturestr.h" #endif #include "compat-api.h" #include "simple_list.h" #include "atipcirename.h" struct _SyncFence; #ifndef HAVE_REGIONDUPLICATE static inline RegionPtr RegionDuplicate(RegionPtr pOld) { RegionPtr pNew; pNew = RegionCreate(&pOld->extents, 0); if (!pNew) return NULL; if (!RegionCopy(pNew, pOld)) { RegionDestroy(pNew); return NULL; } return pNew; } #endif #ifndef MAX #define MAX(a,b) ((a)>(b)?(a):(b)) #endif #ifndef MIN #define MIN(a,b) ((a)>(b)?(b):(a)) #endif #if HAVE_BYTESWAP_H #include #define radeon_bswap_16 bswap_16 #define radeon_bswap_32 bswap_32 #define radeon_bswap_64 bswap_64 #elif defined(USE_SYS_ENDIAN_H) #include #else #define radeon_bswap_16(value) \ ((((value) & 0xff) << 8) | ((value) >> 8)) #define radeon_bswap_32(value) \ (((uint32_t)radeon_bswap_16((uint16_t)((value) & 0xffff)) << 16) | \ (uint32_t)radeon_bswap_16((uint16_t)((value) >> 16))) #define radeon_bswap_64(value) \ (((uint64_t)radeon_bswap_32((uint32_t)((value) & 0xffffffff)) \ << 32) | \ (uint64_t)radeon_bswap_32((uint32_t)((value) >> 32))) #endif #if X_BYTE_ORDER == X_BIG_ENDIAN #define le32_to_cpu(x) radeon_bswap_32(x) #define le16_to_cpu(x) radeon_bswap_16(x) #define cpu_to_le32(x) radeon_bswap_32(x) #define cpu_to_le16(x) radeon_bswap_16(x) #else #define le32_to_cpu(x) (x) #define le16_to_cpu(x) (x) #define cpu_to_le32(x) (x) #define cpu_to_le16(x) (x) #endif /* Provide substitutes for gcc's __FUNCTION__ on other compilers */ #if !defined(__GNUC__) && !defined(__FUNCTION__) # define __FUNCTION__ __func__ /* C99 */ #endif typedef enum { OPTION_ACCEL, OPTION_SW_CURSOR, OPTION_PAGE_FLIP, OPTION_EXA_PIXMAPS, OPTION_COLOR_TILING, OPTION_COLOR_TILING_2D, #ifdef RENDER OPTION_RENDER_ACCEL, OPTION_SUBPIXEL_ORDER, #endif OPTION_ACCELMETHOD, OPTION_EXA_VSYNC, OPTION_ZAPHOD_HEADS, OPTION_SWAPBUFFERS_WAIT, OPTION_DELETE_DP12, OPTION_DRI3, OPTION_DRI, OPTION_SHADOW_PRIMARY, OPTION_TEAR_FREE, } RADEONOpts; static inline ScreenPtr radeon_primary_screen(ScreenPtr screen) { if (screen->current_primary) return screen->current_primary; return screen; } static inline ScreenPtr radeon_dirty_primary(PixmapDirtyUpdatePtr dirty) { return radeon_primary_screen(dirty->secondary_dst->drawable.pScreen); } static inline DrawablePtr radeon_dirty_src_drawable(PixmapDirtyUpdatePtr dirty) { #ifdef HAS_DIRTYTRACKING_DRAWABLE_SRC return dirty->src; #else return &dirty->src->drawable; #endif } static inline Bool radeon_dirty_src_equals(PixmapDirtyUpdatePtr dirty, PixmapPtr pixmap) { return radeon_dirty_src_drawable(dirty) == &pixmap->drawable; } #define RADEON_VSYNC_TIMEOUT 20000 /* Maximum wait for VSYNC (in usecs) */ /* Buffer are aligned on 4096 byte boundaries */ #define RADEON_GPU_PAGE_SIZE 4096 #define RADEON_BUFFER_ALIGN (RADEON_GPU_PAGE_SIZE - 1) #define xFixedToFloat(f) (((float) (f)) / 65536) #define RADEON_LOGLEVEL_DEBUG 4 /* for Xv, outputs */ #define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE) /* Other macros */ #define RADEON_ALIGN(x,bytes) (((x) + ((bytes) - 1)) & ~((bytes) - 1)) #define RADEONPTR(pScrn) ((RADEONInfoPtr)(pScrn)->driverPrivate) #define IS_RV100_VARIANT ((info->ChipFamily == CHIP_FAMILY_RV100) || \ (info->ChipFamily == CHIP_FAMILY_RV200) || \ (info->ChipFamily == CHIP_FAMILY_RS100) || \ (info->ChipFamily == CHIP_FAMILY_RS200) || \ (info->ChipFamily == CHIP_FAMILY_RV250) || \ (info->ChipFamily == CHIP_FAMILY_RV280) || \ (info->ChipFamily == CHIP_FAMILY_RS300)) #define IS_R300_VARIANT ((info->ChipFamily == CHIP_FAMILY_R300) || \ (info->ChipFamily == CHIP_FAMILY_RV350) || \ (info->ChipFamily == CHIP_FAMILY_R350) || \ (info->ChipFamily == CHIP_FAMILY_RV380) || \ (info->ChipFamily == CHIP_FAMILY_R420) || \ (info->ChipFamily == CHIP_FAMILY_RV410) || \ (info->ChipFamily == CHIP_FAMILY_RS400) || \ (info->ChipFamily == CHIP_FAMILY_RS480)) #define IS_AVIVO_VARIANT ((info->ChipFamily >= CHIP_FAMILY_RV515)) #define IS_DCE3_VARIANT ((info->ChipFamily >= CHIP_FAMILY_RV620)) #define IS_DCE32_VARIANT ((info->ChipFamily >= CHIP_FAMILY_RV730)) #define IS_DCE4_VARIANT ((info->ChipFamily >= CHIP_FAMILY_CEDAR)) #define IS_DCE41_VARIANT ((info->ChipFamily >= CHIP_FAMILY_PALM)) #define IS_DCE5_VARIANT ((info->ChipFamily >= CHIP_FAMILY_BARTS)) #define IS_EVERGREEN_3D (info->ChipFamily >= CHIP_FAMILY_CEDAR) #define IS_R600_3D (info->ChipFamily >= CHIP_FAMILY_R600) #define IS_R500_3D ((info->ChipFamily == CHIP_FAMILY_RV515) || \ (info->ChipFamily == CHIP_FAMILY_R520) || \ (info->ChipFamily == CHIP_FAMILY_RV530) || \ (info->ChipFamily == CHIP_FAMILY_R580) || \ (info->ChipFamily == CHIP_FAMILY_RV560) || \ (info->ChipFamily == CHIP_FAMILY_RV570)) /* RS6xx, RS740 are technically R4xx as well, but the * clipping hardware seems to follow the r3xx restrictions */ #define IS_R400_3D ((info->ChipFamily == CHIP_FAMILY_R420) || \ (info->ChipFamily == CHIP_FAMILY_RV410)) #define IS_R300_3D ((info->ChipFamily == CHIP_FAMILY_R300) || \ (info->ChipFamily == CHIP_FAMILY_RV350) || \ (info->ChipFamily == CHIP_FAMILY_R350) || \ (info->ChipFamily == CHIP_FAMILY_RV380) || \ (info->ChipFamily == CHIP_FAMILY_R420) || \ (info->ChipFamily == CHIP_FAMILY_RV410) || \ (info->ChipFamily == CHIP_FAMILY_RS690) || \ (info->ChipFamily == CHIP_FAMILY_RS600) || \ (info->ChipFamily == CHIP_FAMILY_RS740) || \ (info->ChipFamily == CHIP_FAMILY_RS400) || \ (info->ChipFamily == CHIP_FAMILY_RS480)) #define IS_R200_3D ((info->ChipFamily == CHIP_FAMILY_RV250) || \ (info->ChipFamily == CHIP_FAMILY_RV280) || \ (info->ChipFamily == CHIP_FAMILY_RS300) || \ (info->ChipFamily == CHIP_FAMILY_R200)) #define CURSOR_WIDTH 64 #define CURSOR_HEIGHT 64 #define CURSOR_WIDTH_CIK 128 #define CURSOR_HEIGHT_CIK 128 #ifdef USE_GLAMOR struct radeon_pixmap { uint_fast32_t gpu_read; uint_fast32_t gpu_write; struct radeon_buffer *bo; struct drmmode_fb *fb; Bool fb_failed; uint32_t tiling_flags; /* GEM handle for glamor-only pixmaps shared via DRI3 */ Bool handle_valid; uint32_t handle; }; extern DevPrivateKeyRec glamor_pixmap_index; static inline struct radeon_pixmap *radeon_get_pixmap_private(PixmapPtr pixmap) { return dixGetPrivate(&pixmap->devPrivates, &glamor_pixmap_index); } static inline void radeon_set_pixmap_private(PixmapPtr pixmap, struct radeon_pixmap *priv) { dixSetPrivate(&pixmap->devPrivates, &glamor_pixmap_index, priv); } #endif /* USE_GLAMOR */ struct radeon_exa_pixmap_priv { struct radeon_buffer *bo; struct drmmode_fb *fb; uint32_t tiling_flags; struct radeon_surface surface; Bool bo_mapped; Bool shared; }; #define RADEON_2D_EXA_COPY 1 #define RADEON_2D_EXA_SOLID 2 struct radeon_2d_state { int op; // uint32_t dst_pitch_offset; uint32_t src_pitch_offset; uint32_t dp_gui_master_cntl; uint32_t dp_cntl; uint32_t dp_write_mask; uint32_t dp_brush_frgd_clr; uint32_t dp_brush_bkgd_clr; uint32_t dp_src_frgd_clr; uint32_t dp_src_bkgd_clr; uint32_t default_sc_bottom_right; uint32_t dst_domain; struct radeon_bo *dst_bo; struct radeon_bo *src_bo; }; #define DMA_BO_FREE_TIME 1000 struct radeon_dma_bo { struct radeon_dma_bo *next, *prev; struct radeon_bo *bo; int expire_counter; }; struct r600_accel_object { uint32_t pitch; uint32_t width; uint32_t height; int bpp; uint32_t domain; struct radeon_bo *bo; uint32_t tiling_flags; struct radeon_surface *surface; }; struct radeon_vbo_object { int vb_offset; int vb_total; uint32_t vb_size; uint32_t vb_op_vert_size; int32_t vb_start_op; struct radeon_bo *vb_bo; unsigned verts_per_op; }; struct radeon_accel_state { /* Saved values for ScreenToScreenCopy */ int xdir; int ydir; /* render accel */ unsigned short texW[2]; unsigned short texH[2]; Bool XInited3D; /* X itself has the 3D context */ int num_gb_pipes; Bool has_tcl; Bool allowHWDFS; /* EXA */ ExaDriverPtr exa; int exaSyncMarker; int exaMarkerSynced; int engineMode; #define EXA_ENGINEMODE_UNKNOWN 0 #define EXA_ENGINEMODE_2D 1 #define EXA_ENGINEMODE_3D 2 int composite_op; PicturePtr dst_pic; PicturePtr msk_pic; PicturePtr src_pic; PixmapPtr dst_pix; PixmapPtr msk_pix; PixmapPtr src_pix; Bool is_transform[2]; PictTransform *transform[2]; /* Whether we are tiling horizontally and vertically */ Bool need_src_tile_x; Bool need_src_tile_y; /* Size of tiles ... set to 65536x65536 if not tiling in that direction */ Bool src_tile_width; Bool src_tile_height; uint32_t *draw_header; unsigned vtx_count; unsigned num_vtx; Bool vsync; struct radeon_vbo_object vbo; struct radeon_vbo_object cbuf; /* where to discard IB from if we cancel operation */ uint32_t ib_reset_op; struct radeon_dma_bo bo_free; struct radeon_dma_bo bo_wait; struct radeon_dma_bo bo_reserved; Bool use_vbos; void (*finish_op)(ScrnInfoPtr, int); // shader storage struct radeon_bo *shaders_bo; uint32_t solid_vs_offset; uint32_t solid_ps_offset; uint32_t copy_vs_offset; uint32_t copy_ps_offset; uint32_t comp_vs_offset; uint32_t comp_ps_offset; uint32_t xv_vs_offset; uint32_t xv_ps_offset; // shader consts uint32_t solid_vs_const_offset; uint32_t solid_ps_const_offset; uint32_t copy_vs_const_offset; uint32_t copy_ps_const_offset; uint32_t comp_vs_const_offset; uint32_t comp_ps_const_offset; uint32_t comp_mask_ps_const_offset; uint32_t xv_vs_const_offset; uint32_t xv_ps_const_offset; //size/addr stuff struct r600_accel_object src_obj[2]; struct r600_accel_object dst_obj; uint32_t src_size[2]; uint32_t dst_size; uint32_t vs_size; uint64_t vs_mc_addr; uint32_t ps_size; uint64_t ps_mc_addr; // solid/copy void *copy_area; struct radeon_bo *copy_area_bo; Bool same_surface; int rop; uint32_t planemask; uint32_t fg; // composite Bool component_alpha; Bool src_alpha; // vline xf86CrtcPtr vline_crtc; int vline_y1; int vline_y2; Bool force; }; struct radeon_client_priv { uint_fast32_t needs_flush; }; struct radeon_device_priv { CursorPtr cursor; Bool sprite_visible; }; extern DevScreenPrivateKeyRec radeon_device_private_key; typedef struct { EntityInfoPtr pEnt; pciVideoPtr PciInfo; int Chipset; RADEONChipFamily ChipFamily; Bool (*CloseScreen)(ScreenPtr pScreen); void (*BlockHandler)(BLOCKHANDLER_ARGS_DECL); void (*CreateFence) (ScreenPtr pScreen, struct _SyncFence *pFence, Bool initially_triggered); int pix24bpp; /* Depth of pixmap for 24bpp fb */ Bool dac6bits; /* Use 6 bit DAC? */ int pixel_bytes; Bool directRenderingEnabled; struct radeon_dri2 dri2; /* accel */ Bool RenderAccel; /* Render */ Bool allowColorTiling; Bool allowColorTiling2D; int callback_event_type; uint_fast32_t gpu_flushed; uint_fast32_t gpu_synced; struct radeon_accel_state *accel_state; PixmapPtr fbcon_pixmap; Bool accelOn; Bool use_glamor; Bool shadow_primary; int tear_free; Bool exa_pixmaps; Bool exa_force_create; XF86ModReqInfo exaReq; Bool is_fast_fb; /* use direct mapping for fast fb access */ unsigned int xv_max_width; unsigned int xv_max_height; /* general */ OptionInfoPtr Options; DisplayModePtr currentMode; CreateScreenResourcesProcPtr CreateScreenResources; CreateWindowProcPtr CreateWindow; WindowExposuresProcPtr WindowExposures; miPointerSpriteFuncPtr SpriteFuncs; /* Number of SW cursors currently visible on this screen */ int sprites_visible; int instance_id; Bool r600_shadow_fb; void *fb_shadow; void (*reemit_current2d)(ScrnInfoPtr pScrn, int op); // emit the current 2D state into the IB struct radeon_2d_state state_2d; struct radeon_buffer *front_buffer; struct radeon_bo_manager *bufmgr; struct radeon_cs_manager *csm; struct radeon_cs *cs; uint64_t vram_size; uint64_t gart_size; drmmode_rec drmmode; Bool drmmode_inited; /* r6xx+ tile config */ Bool have_tiling_info; uint32_t tile_config; int group_bytes; int num_channels; int num_banks; int r7xx_bank_op; struct radeon_surface_manager *surf_man; struct radeon_surface front_surface; /* Xv bicubic filtering */ struct radeon_bo *bicubic_bo; /* kms pageflipping */ Bool allowPageFlip; /* Perform vsync'ed SwapBuffers? */ Bool swapBuffersWait; /* cursor size */ int cursor_w; int cursor_h; /* If bit n of this field is set, xf86_config->crtc[n] currently can't * use the HW cursor */ unsigned hwcursor_disabled; #ifdef USE_GLAMOR struct gbm_device *gbm; struct { CreateGCProcPtr SavedCreateGC; RegionPtr (*SavedCopyArea)(DrawablePtr, DrawablePtr, GCPtr, int, int, int, int, int, int); void (*SavedPolyFillRect)(DrawablePtr, GCPtr, int, xRectangle*); CloseScreenProcPtr SavedCloseScreen; GetImageProcPtr SavedGetImage; GetSpansProcPtr SavedGetSpans; CreatePixmapProcPtr SavedCreatePixmap; DestroyPixmapProcPtr SavedDestroyPixmap; CopyWindowProcPtr SavedCopyWindow; ChangeWindowAttributesProcPtr SavedChangeWindowAttributes; BitmapToRegionProcPtr SavedBitmapToRegion; #ifdef RENDER CompositeProcPtr SavedComposite; TrianglesProcPtr SavedTriangles; GlyphsProcPtr SavedGlyphs; TrapezoidsProcPtr SavedTrapezoids; AddTrapsProcPtr SavedAddTraps; UnrealizeGlyphProcPtr SavedUnrealizeGlyph; #endif SharePixmapBackingProcPtr SavedSharePixmapBacking; SetSharedPixmapBackingProcPtr SavedSetSharedPixmapBacking; } glamor; #endif /* USE_GLAMOR */ xf86CrtcFuncsRec drmmode_crtc_funcs; } RADEONInfoRec, *RADEONInfoPtr; /* radeon_accel.c */ extern Bool RADEONAccelInit(ScreenPtr pScreen); extern void RADEONEngineInit(ScrnInfoPtr pScrn); extern void RADEONCopySwap(uint8_t *dst, uint8_t *src, unsigned int size, int swap); extern void RADEONInit3DEngine(ScrnInfoPtr pScrn); extern int radeon_cs_space_remaining(ScrnInfoPtr pScrn); /* radeon_bo_helper.c */ extern Bool radeon_surface_initialize(RADEONInfoPtr info, struct radeon_surface *surface, int width, int height, int cpp, uint32_t tiling_flags, int usage_hint); extern Bool radeon_get_pixmap_handle(PixmapPtr pixmap, uint32_t *handle); /* radeon_commonfuncs.c */ extern void RADEONWaitForVLine(ScrnInfoPtr pScrn, PixmapPtr pPix, xf86CrtcPtr crtc, int start, int stop); /* radeon_exa.c */ extern unsigned eg_tile_split(unsigned tile_split); extern Bool radeon_transform_is_affine_or_scaled(PictTransformPtr t); /* radeon_exa_funcs.c */ extern Bool RADEONDrawInit(ScreenPtr pScreen); extern Bool R600DrawInit(ScreenPtr pScreen); extern Bool R600LoadShaders(ScrnInfoPtr pScrn); extern Bool EVERGREENDrawInit(ScreenPtr pScreen); /* radeon_exa.c */ extern Bool RADEONGetDatatypeBpp(int bpp, uint32_t *type); extern Bool RADEONGetPixmapOffsetPitch(PixmapPtr pPix, uint32_t *pitch_offset); /* radeon_dri3.c */ Bool radeon_dri3_screen_init(ScreenPtr screen); /* radeon_kms.c */ Bool radeon_scanout_do_update(xf86CrtcPtr xf86_crtc, int scanout_id, PixmapPtr src_pix, BoxRec extents); void RADEONWindowExposures_oneshot(WindowPtr pWin, RegionPtr pRegion #if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1,16,99,901,0) , RegionPtr pBSRegion #endif ); /* radeon_present.c */ Bool radeon_present_screen_init(ScreenPtr screen); /* radeon_sync.c */ extern Bool radeon_sync_init(ScreenPtr screen); extern void radeon_sync_close(ScreenPtr screen); /* radeon_video.c */ extern void RADEONInitVideo(ScreenPtr pScreen); extern void RADEONResetVideo(ScrnInfoPtr pScrn); extern Bool radeon_load_bicubic_texture(ScrnInfoPtr pScrn); extern xf86CrtcPtr radeon_pick_best_crtc(ScrnInfoPtr pScrn, Bool consider_disabled, int x1, int x2, int y1, int y2); extern void radeon_cs_flush_indirect(ScrnInfoPtr pScrn); extern void radeon_ddx_cs_start(ScrnInfoPtr pScrn, int num, const char *file, const char *func, int line); void radeon_kms_update_vram_limit(ScrnInfoPtr pScrn, uint32_t new_fb_size); extern RADEONEntPtr RADEONEntPriv(ScrnInfoPtr pScrn); static inline struct radeon_surface *radeon_get_pixmap_surface(PixmapPtr pPix) { struct radeon_exa_pixmap_priv *driver_priv = exaGetPixmapDriverPrivate(pPix); return &driver_priv->surface; } uint32_t radeon_get_pixmap_tiling(PixmapPtr pPix); static inline Bool radeon_set_pixmap_bo(PixmapPtr pPix, struct radeon_buffer *bo) { ScrnInfoPtr scrn = xf86ScreenToScrn(pPix->drawable.pScreen); RADEONEntPtr pRADEONEnt = RADEONEntPriv(scrn); #ifdef USE_GLAMOR RADEONInfoPtr info = RADEONPTR(scrn); if (info->use_glamor) { struct radeon_pixmap *priv; priv = radeon_get_pixmap_private(pPix); if (!priv && !bo) return TRUE; if (priv) { if (priv->bo) { if (priv->bo == bo) return TRUE; radeon_buffer_unref(&priv->bo); priv->handle_valid = FALSE; } drmmode_fb_reference(pRADEONEnt->fd, &priv->fb, NULL); if (!bo) { free(priv); priv = NULL; } } if (bo) { if (!priv) { priv = calloc(1, sizeof (struct radeon_pixmap)); if (!priv) return FALSE; } radeon_buffer_ref(bo); priv->bo = bo; } radeon_set_pixmap_private(pPix, priv); radeon_get_pixmap_tiling_flags(pPix); return TRUE; } else #endif /* USE_GLAMOR */ { struct radeon_exa_pixmap_priv *driver_priv; driver_priv = exaGetPixmapDriverPrivate(pPix); if (driver_priv) { uint32_t pitch; radeon_buffer_unref(&driver_priv->bo); drmmode_fb_reference(pRADEONEnt->fd, &driver_priv->fb, NULL); driver_priv->bo = bo; if (bo) { radeon_buffer_ref(bo); radeon_bo_get_tiling(bo->bo.radeon, &driver_priv->tiling_flags, &pitch); } else driver_priv->tiling_flags = 0; return TRUE; } return FALSE; } } static inline struct radeon_buffer *radeon_get_pixmap_bo(PixmapPtr pPix) { RADEONInfoPtr info = RADEONPTR(xf86ScreenToScrn(pPix->drawable.pScreen)); #ifdef USE_GLAMOR if (info->use_glamor) { struct radeon_pixmap *priv; priv = radeon_get_pixmap_private(pPix); return priv ? priv->bo : NULL; } else #endif if (info->accelOn) { struct radeon_exa_pixmap_priv *driver_priv; driver_priv = exaGetPixmapDriverPrivate(pPix); return driver_priv ? driver_priv->bo : NULL; } return NULL; } static inline Bool radeon_get_pixmap_shared(PixmapPtr pPix) { #ifdef USE_GLAMOR RADEONInfoPtr info = RADEONPTR(xf86ScreenToScrn(pPix->drawable.pScreen)); if (info->use_glamor) { ErrorF("glamor sharing todo\n"); return FALSE; } else #endif { struct radeon_exa_pixmap_priv *driver_priv; driver_priv = exaGetPixmapDriverPrivate(pPix); return driver_priv->shared; } return FALSE; } static inline struct drmmode_fb* radeon_fb_create(ScrnInfoPtr scrn, int drm_fd, uint32_t width, uint32_t height, uint32_t pitch, uint32_t handle) { struct drmmode_fb *fb = malloc(sizeof(*fb)); if (!fb) return NULL; fb->refcnt = 1; if (drmModeAddFB(drm_fd, width, height, scrn->depth, scrn->bitsPerPixel, pitch, handle, &fb->handle) == 0) return fb; free(fb); return NULL; } static inline struct drmmode_fb** radeon_pixmap_get_fb_ptr(PixmapPtr pix) { ScrnInfoPtr scrn = xf86ScreenToScrn(pix->drawable.pScreen); RADEONInfoPtr info = RADEONPTR(scrn); #ifdef USE_GLAMOR if (info->use_glamor) { struct radeon_pixmap *priv = radeon_get_pixmap_private(pix); if (!priv) return NULL; return &priv->fb; } else #endif if (info->accelOn) { struct radeon_exa_pixmap_priv *driver_priv = exaGetPixmapDriverPrivate(pix); if (!driver_priv) return NULL; return &driver_priv->fb; } return NULL; } static inline struct drmmode_fb* radeon_pixmap_get_fb(PixmapPtr pix) { struct drmmode_fb **fb_ptr = radeon_pixmap_get_fb_ptr(pix); uint32_t handle; if (fb_ptr && *fb_ptr) return *fb_ptr; if (radeon_get_pixmap_handle(pix, &handle)) { ScrnInfoPtr scrn = xf86ScreenToScrn(pix->drawable.pScreen); RADEONEntPtr pRADEONEnt = RADEONEntPriv(scrn); if (!fb_ptr) fb_ptr = radeon_pixmap_get_fb_ptr(pix); *fb_ptr = radeon_fb_create(scrn, pRADEONEnt->fd, pix->drawable.width, pix->drawable.height, pix->devKind, handle); } return fb_ptr ? *fb_ptr : NULL; } #define CP_PACKET0(reg, n) \ (RADEON_CP_PACKET0 | ((n) << 16) | ((reg) >> 2)) #define CP_PACKET1(reg0, reg1) \ (RADEON_CP_PACKET1 | (((reg1) >> 2) << 11) | ((reg0) >> 2)) #define CP_PACKET2() \ (RADEON_CP_PACKET2) #define CP_PACKET3(pkt, n) \ (RADEON_CP_PACKET3 | (pkt) | ((n) << 16)) #define RADEON_VERBOSE 0 #define BEGIN_RING(n) do { \ if (RADEON_VERBOSE) { \ xf86DrvMsg(pScrn->scrnIndex, X_INFO, \ "BEGIN_RING(%d) in %s\n", (unsigned int)n, __FUNCTION__);\ } \ radeon_ddx_cs_start(pScrn, n, __FILE__, __func__, __LINE__); \ } while (0) #define ADVANCE_RING() do { \ radeon_cs_end(info->cs, __FILE__, __func__, __LINE__); \ } while (0) #define OUT_RING(x) do { \ if (RADEON_VERBOSE) { \ xf86DrvMsg(pScrn->scrnIndex, X_INFO, \ " OUT_RING(0x%08x)\n", (unsigned int)(x)); \ } \ radeon_cs_write_dword(info->cs, (x)); \ } while (0) #define OUT_RING_REG(reg, val) \ do { \ OUT_RING(CP_PACKET0(reg, 0)); \ OUT_RING(val); \ } while (0) #define OUT_RING_RELOC(x, read_domains, write_domain) \ do { \ int _ret; \ _ret = radeon_cs_write_reloc(info->cs, x, read_domains, write_domain, 0); \ if (_ret) ErrorF("reloc emit failure %d\n", _ret); \ } while(0) #define FLUSH_RING() \ do { \ if (RADEON_VERBOSE) \ xf86DrvMsg(pScrn->scrnIndex, X_INFO, \ "FLUSH_RING in %s\n", __FUNCTION__); \ radeon_cs_flush_indirect(pScrn); \ } while (0) #define CS_FULL(cs) ((cs)->cdw > 15 * 1024) #define RADEON_SWITCH_TO_2D() \ do { \ uint32_t flush = 0; \ switch (info->accel_state->engineMode) { \ case EXA_ENGINEMODE_UNKNOWN: \ flush = 1; \ break; \ case EXA_ENGINEMODE_3D: \ flush = CS_FULL(info->cs); \ break; \ case EXA_ENGINEMODE_2D: \ flush = CS_FULL(info->cs); \ break; \ } \ if (flush) { \ radeon_cs_flush_indirect(pScrn); \ } \ info->accel_state->engineMode = EXA_ENGINEMODE_2D; \ } while (0); #define RADEON_SWITCH_TO_3D() \ do { \ uint32_t flush = 0; \ switch (info->accel_state->engineMode) { \ case EXA_ENGINEMODE_UNKNOWN: \ flush = 1; \ break; \ case EXA_ENGINEMODE_2D: \ flush = CS_FULL(info->cs); \ break; \ case EXA_ENGINEMODE_3D: \ flush = CS_FULL(info->cs); \ break; \ } \ if (flush) { \ radeon_cs_flush_indirect(pScrn); \ } \ if (!info->accel_state->XInited3D) \ RADEONInit3DEngine(pScrn); \ info->accel_state->engineMode = EXA_ENGINEMODE_3D; \ } while (0); /* Memory mapped register access macros */ #define BEGIN_ACCEL_RELOC(n, r) do { \ int _nqw = (n) + (r); \ BEGIN_RING(2*_nqw); \ } while (0) #define EMIT_OFFSET(reg, value, pPix, rd, wd) do { \ driver_priv = exaGetPixmapDriverPrivate(pPix); \ OUT_RING_REG((reg), (value)); \ OUT_RING_RELOC(driver_priv->bo->bo.radeon, (rd), (wd)); \ } while(0) #define EMIT_READ_OFFSET(reg, value, pPix) EMIT_OFFSET(reg, value, pPix, (RADEON_GEM_DOMAIN_VRAM | RADEON_GEM_DOMAIN_GTT), 0) #define EMIT_WRITE_OFFSET(reg, value, pPix) EMIT_OFFSET(reg, value, pPix, 0, RADEON_GEM_DOMAIN_VRAM) #define OUT_TEXTURE_REG(reg, offset, bo) do { \ OUT_RING_REG((reg), (offset)); \ OUT_RING_RELOC((bo), RADEON_GEM_DOMAIN_VRAM | RADEON_GEM_DOMAIN_GTT, 0); \ } while(0) #define EMIT_COLORPITCH(reg, value, pPix) do { \ driver_priv = exaGetPixmapDriverPrivate(pPix); \ OUT_RING_REG((reg), value); \ OUT_RING_RELOC(driver_priv->bo->bo.radeon, 0, RADEON_GEM_DOMAIN_VRAM); \ } while(0) static __inline__ void RADEON_SYNC(RADEONInfoPtr info, ScrnInfoPtr pScrn) { if (pScrn->pScreen) exaWaitSync(pScrn->pScreen); } enum { RADEON_CREATE_PIXMAP_SCANOUT = 0x02000000, RADEON_CREATE_PIXMAP_DRI2 = 0x04000000, RADEON_CREATE_PIXMAP_TILING_MICRO_SQUARE = 0x08000000, RADEON_CREATE_PIXMAP_TILING_MACRO = 0x10000000, RADEON_CREATE_PIXMAP_TILING_MICRO = 0x20000000, RADEON_CREATE_PIXMAP_DEPTH = 0x40000000, /* for r200 */ RADEON_CREATE_PIXMAP_SZBUFFER = 0x80000000, /* for eg */ }; #define RADEON_CREATE_PIXMAP_TILING_FLAGS \ (RADEON_CREATE_PIXMAP_TILING_MICRO_SQUARE | \ RADEON_CREATE_PIXMAP_TILING_MACRO | \ RADEON_CREATE_PIXMAP_TILING_MICRO | \ RADEON_CREATE_PIXMAP_DEPTH | \ RADEON_CREATE_PIXMAP_SZBUFFER) /* Compute log base 2 of val. */ static __inline__ int RADEONLog2(int val) { return 31 - __builtin_clz(val); } #define RADEON_TILING_MASK 0xff #define RADEON_TILING_LINEAR 0x0 #endif /* _RADEON_H_ */