intel_uxa.c revision 42542f5f
103b705cfSriastradh/************************************************************************** 203b705cfSriastradh 303b705cfSriastradhCopyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. 403b705cfSriastradhAll Rights Reserved. 503b705cfSriastradhCopyright (c) 2005 Jesse Barnes <jbarnes@virtuousgeek.org> 603b705cfSriastradh Based on code from i830_xaa.c. 703b705cfSriastradh 803b705cfSriastradhPermission is hereby granted, free of charge, to any person obtaining a 903b705cfSriastradhcopy of this software and associated documentation files (the 1003b705cfSriastradh"Software"), to deal in the Software without restriction, including 1103b705cfSriastradhwithout limitation the rights to use, copy, modify, merge, publish, 1203b705cfSriastradhdistribute, sub license, and/or sell copies of the Software, and to 1303b705cfSriastradhpermit persons to whom the Software is furnished to do so, subject to 1403b705cfSriastradhthe following conditions: 1503b705cfSriastradh 1603b705cfSriastradhThe above copyright notice and this permission notice (including the 1703b705cfSriastradhnext paragraph) shall be included in all copies or substantial portions 1803b705cfSriastradhof the Software. 1903b705cfSriastradh 2003b705cfSriastradhTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 2103b705cfSriastradhOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 2203b705cfSriastradhMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 2303b705cfSriastradhIN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR 2403b705cfSriastradhANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 2503b705cfSriastradhTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 2603b705cfSriastradhSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 2703b705cfSriastradh 2803b705cfSriastradh**************************************************************************/ 2903b705cfSriastradh 3003b705cfSriastradh#ifdef HAVE_CONFIG_H 3103b705cfSriastradh#include "config.h" 3203b705cfSriastradh#endif 3303b705cfSriastradh 3442542f5fSchristos#include "xorg-server.h" 3503b705cfSriastradh#include <xf86.h> 3603b705cfSriastradh#include <xf86drm.h> 3703b705cfSriastradh#include <xaarop.h> 3803b705cfSriastradh#include <string.h> 3903b705cfSriastradh#include <errno.h> 4003b705cfSriastradh#include <unistd.h> 4103b705cfSriastradh 4203b705cfSriastradh#include "intel.h" 4303b705cfSriastradh#include "intel_glamor.h" 4403b705cfSriastradh#include "uxa.h" 4503b705cfSriastradh 4603b705cfSriastradh#include "i830_reg.h" 4703b705cfSriastradh#include "i915_drm.h" 4803b705cfSriastradh#include "brw_defines.h" 4903b705cfSriastradh 5003b705cfSriastradhstatic const int I830CopyROP[16] = { 5103b705cfSriastradh ROP_0, /* GXclear */ 5203b705cfSriastradh ROP_DSa, /* GXand */ 5303b705cfSriastradh ROP_SDna, /* GXandReverse */ 5403b705cfSriastradh ROP_S, /* GXcopy */ 5503b705cfSriastradh ROP_DSna, /* GXandInverted */ 5603b705cfSriastradh ROP_D, /* GXnoop */ 5703b705cfSriastradh ROP_DSx, /* GXxor */ 5803b705cfSriastradh ROP_DSo, /* GXor */ 5903b705cfSriastradh ROP_DSon, /* GXnor */ 6003b705cfSriastradh ROP_DSxn, /* GXequiv */ 6103b705cfSriastradh ROP_Dn, /* GXinvert */ 6203b705cfSriastradh ROP_SDno, /* GXorReverse */ 6303b705cfSriastradh ROP_Sn, /* GXcopyInverted */ 6403b705cfSriastradh ROP_DSno, /* GXorInverted */ 6503b705cfSriastradh ROP_DSan, /* GXnand */ 6603b705cfSriastradh ROP_1 /* GXset */ 6703b705cfSriastradh}; 6803b705cfSriastradh 6903b705cfSriastradhstatic const int I830PatternROP[16] = { 7003b705cfSriastradh ROP_0, 7103b705cfSriastradh ROP_DPa, 7203b705cfSriastradh ROP_PDna, 7303b705cfSriastradh ROP_P, 7403b705cfSriastradh ROP_DPna, 7503b705cfSriastradh ROP_D, 7603b705cfSriastradh ROP_DPx, 7703b705cfSriastradh ROP_DPo, 7803b705cfSriastradh ROP_DPon, 7903b705cfSriastradh ROP_PDxn, 8003b705cfSriastradh ROP_Dn, 8103b705cfSriastradh ROP_PDno, 8203b705cfSriastradh ROP_Pn, 8303b705cfSriastradh ROP_DPno, 8403b705cfSriastradh ROP_DPan, 8503b705cfSriastradh ROP_1 8603b705cfSriastradh}; 8703b705cfSriastradh 8803b705cfSriastradh#if HAS_DEVPRIVATEKEYREC 8903b705cfSriastradhDevPrivateKeyRec uxa_pixmap_index; 9003b705cfSriastradh#else 9103b705cfSriastradhint uxa_pixmap_index; 9203b705cfSriastradh#endif 9303b705cfSriastradh 9403b705cfSriastradhstatic void 9503b705cfSriastradhgen6_context_switch(intel_screen_private *intel, 9603b705cfSriastradh int new_mode) 9703b705cfSriastradh{ 9803b705cfSriastradh intel_batch_submit(intel->scrn); 9903b705cfSriastradh} 10003b705cfSriastradh 10103b705cfSriastradhstatic void 10203b705cfSriastradhgen5_context_switch(intel_screen_private *intel, 10303b705cfSriastradh int new_mode) 10403b705cfSriastradh{ 10503b705cfSriastradh /* Ironlake has a limitation that a 3D or Media command can't 10603b705cfSriastradh * be the first command after a BLT, unless it's 10703b705cfSriastradh * non-pipelined. Instead of trying to track it and emit a 10803b705cfSriastradh * command at the right time, we just emit a dummy 10903b705cfSriastradh * non-pipelined 3D instruction after each blit. 11003b705cfSriastradh */ 11103b705cfSriastradh 11203b705cfSriastradh if (new_mode == I915_EXEC_BLT) { 11303b705cfSriastradh OUT_BATCH(MI_FLUSH | 11403b705cfSriastradh MI_STATE_INSTRUCTION_CACHE_FLUSH | 11503b705cfSriastradh MI_INHIBIT_RENDER_CACHE_FLUSH); 11603b705cfSriastradh } else { 11703b705cfSriastradh OUT_BATCH(CMD_POLY_STIPPLE_OFFSET << 16); 11803b705cfSriastradh OUT_BATCH(0); 11903b705cfSriastradh } 12003b705cfSriastradh} 12103b705cfSriastradh 12203b705cfSriastradhstatic void 12303b705cfSriastradhgen4_context_switch(intel_screen_private *intel, 12403b705cfSriastradh int new_mode) 12503b705cfSriastradh{ 12603b705cfSriastradh if (new_mode == I915_EXEC_BLT) { 12703b705cfSriastradh OUT_BATCH(MI_FLUSH | 12803b705cfSriastradh MI_STATE_INSTRUCTION_CACHE_FLUSH | 12903b705cfSriastradh MI_INHIBIT_RENDER_CACHE_FLUSH); 13003b705cfSriastradh } 13103b705cfSriastradh} 13203b705cfSriastradh 13303b705cfSriastradhBool 13403b705cfSriastradhintel_get_aperture_space(ScrnInfoPtr scrn, drm_intel_bo ** bo_table, 13503b705cfSriastradh int num_bos) 13603b705cfSriastradh{ 13703b705cfSriastradh intel_screen_private *intel = intel_get_screen_private(scrn); 13803b705cfSriastradh 13903b705cfSriastradh if (intel->batch_bo == NULL) { 14003b705cfSriastradh intel_debug_fallback(scrn, "VT inactive\n"); 14103b705cfSriastradh return FALSE; 14203b705cfSriastradh } 14303b705cfSriastradh 14403b705cfSriastradh bo_table[0] = intel->batch_bo; 14503b705cfSriastradh if (drm_intel_bufmgr_check_aperture_space(bo_table, num_bos) != 0) { 14603b705cfSriastradh intel_batch_submit(scrn); 14703b705cfSriastradh bo_table[0] = intel->batch_bo; 14803b705cfSriastradh if (drm_intel_bufmgr_check_aperture_space(bo_table, num_bos) != 14903b705cfSriastradh 0) { 15003b705cfSriastradh intel_debug_fallback(scrn, "Couldn't get aperture " 15103b705cfSriastradh "space for BOs\n"); 15203b705cfSriastradh return FALSE; 15303b705cfSriastradh } 15403b705cfSriastradh } 15503b705cfSriastradh return TRUE; 15603b705cfSriastradh} 15703b705cfSriastradh 15803b705cfSriastradhstatic unsigned int 15942542f5fSchristosintel_uxa_compute_size(struct intel_screen_private *intel, 16042542f5fSchristos int w, int h, int bpp, unsigned usage, 16142542f5fSchristos uint32_t *tiling, int *stride) 16203b705cfSriastradh{ 16303b705cfSriastradh int pitch, size; 16403b705cfSriastradh 16503b705cfSriastradh if (*tiling != I915_TILING_NONE) { 16603b705cfSriastradh /* First check whether tiling is necessary. */ 16742542f5fSchristos pitch = (w * bpp + 7) / 8; 16803b705cfSriastradh pitch = ALIGN(pitch, 64); 16903b705cfSriastradh size = pitch * ALIGN (h, 2); 17003b705cfSriastradh if (INTEL_INFO(intel)->gen < 040) { 17103b705cfSriastradh /* Gen 2/3 has a maximum stride for tiling of 17203b705cfSriastradh * 8192 bytes. 17303b705cfSriastradh */ 17403b705cfSriastradh if (pitch > KB(8)) 17503b705cfSriastradh *tiling = I915_TILING_NONE; 17603b705cfSriastradh 17703b705cfSriastradh /* Narrower than half a tile? */ 17803b705cfSriastradh if (pitch < 256) 17903b705cfSriastradh *tiling = I915_TILING_NONE; 18003b705cfSriastradh 18103b705cfSriastradh /* Older hardware requires fences to be pot size 18203b705cfSriastradh * aligned with a minimum of 1 MiB, so causes 18303b705cfSriastradh * massive overallocation for small textures. 18403b705cfSriastradh */ 18503b705cfSriastradh if (size < 1024*1024/2 && !intel->has_relaxed_fencing) 18603b705cfSriastradh *tiling = I915_TILING_NONE; 18703b705cfSriastradh } else if (!(usage & INTEL_CREATE_PIXMAP_DRI2) && size <= 4096) { 18803b705cfSriastradh /* Disable tiling beneath a page size, we will not see 18903b705cfSriastradh * any benefit from reducing TLB misses and instead 19003b705cfSriastradh * just incur extra cost when we require a fence. 19103b705cfSriastradh */ 19203b705cfSriastradh *tiling = I915_TILING_NONE; 19303b705cfSriastradh } 19403b705cfSriastradh } 19503b705cfSriastradh 19642542f5fSchristos pitch = (w * bpp + 7) / 8; 19703b705cfSriastradh if (!(usage & INTEL_CREATE_PIXMAP_DRI2) && pitch <= 256) 19803b705cfSriastradh *tiling = I915_TILING_NONE; 19903b705cfSriastradh 20003b705cfSriastradh if (*tiling != I915_TILING_NONE) { 20103b705cfSriastradh int aligned_h, tile_height; 20203b705cfSriastradh 20303b705cfSriastradh if (IS_GEN2(intel)) 20403b705cfSriastradh tile_height = 16; 20503b705cfSriastradh else if (*tiling == I915_TILING_X) 20603b705cfSriastradh tile_height = 8; 20703b705cfSriastradh else 20803b705cfSriastradh tile_height = 32; 20903b705cfSriastradh aligned_h = ALIGN(h, 2*tile_height); 21003b705cfSriastradh 21103b705cfSriastradh *stride = intel_get_fence_pitch(intel, 21203b705cfSriastradh ALIGN(pitch, 512), 21303b705cfSriastradh *tiling); 21403b705cfSriastradh 21503b705cfSriastradh /* Round the object up to the size of the fence it will live in 21603b705cfSriastradh * if necessary. We could potentially make the kernel allocate 21703b705cfSriastradh * a larger aperture space and just bind the subset of pages in, 21803b705cfSriastradh * but this is easier and also keeps us out of trouble (as much) 21903b705cfSriastradh * with drm_intel_bufmgr_check_aperture(). 22003b705cfSriastradh */ 22103b705cfSriastradh size = intel_get_fence_size(intel, *stride * aligned_h); 22203b705cfSriastradh 22303b705cfSriastradh if (size > intel->max_tiling_size) 22403b705cfSriastradh *tiling = I915_TILING_NONE; 22503b705cfSriastradh } 22603b705cfSriastradh 22703b705cfSriastradh if (*tiling == I915_TILING_NONE) { 22803b705cfSriastradh /* We only require a 64 byte alignment for scanouts, but 22903b705cfSriastradh * a 256 byte alignment for sharing with PRIME. 23003b705cfSriastradh */ 23103b705cfSriastradh *stride = ALIGN(pitch, 256); 23203b705cfSriastradh /* Round the height up so that the GPU's access to a 2x2 aligned 23303b705cfSriastradh * subspan doesn't address an invalid page offset beyond the 23403b705cfSriastradh * end of the GTT. 23503b705cfSriastradh */ 23603b705cfSriastradh size = *stride * ALIGN(h, 2); 23703b705cfSriastradh } 23803b705cfSriastradh 23903b705cfSriastradh return size; 24003b705cfSriastradh} 24103b705cfSriastradh 24242542f5fSchristosdrm_intel_bo *intel_allocate_framebuffer(ScrnInfoPtr scrn, 24342542f5fSchristos int width, int height, int cpp, 24442542f5fSchristos int *out_stride, 24542542f5fSchristos uint32_t *out_tiling) 24642542f5fSchristos{ 24742542f5fSchristos intel_screen_private *intel = intel_get_screen_private(scrn); 24842542f5fSchristos uint32_t tiling; 24942542f5fSchristos int stride, size; 25042542f5fSchristos drm_intel_bo *bo; 25142542f5fSchristos 25242542f5fSchristos if (intel->tiling & INTEL_TILING_FB) 25342542f5fSchristos tiling = I915_TILING_X; 25442542f5fSchristos else 25542542f5fSchristos tiling = I915_TILING_NONE; 25642542f5fSchristos 25742542f5fSchristosretry: 25842542f5fSchristos size = intel_uxa_compute_size(intel, 25942542f5fSchristos width, height, 26042542f5fSchristos intel->cpp*8, 0, 26142542f5fSchristos &tiling, &stride); 26242542f5fSchristos if (!intel_check_display_stride(scrn, stride, tiling)) { 26342542f5fSchristos if (tiling != I915_TILING_NONE) { 26442542f5fSchristos tiling = I915_TILING_NONE; 26542542f5fSchristos goto retry; 26642542f5fSchristos } 26742542f5fSchristos 26842542f5fSchristos xf86DrvMsg(scrn->scrnIndex, X_ERROR, 26942542f5fSchristos "Front buffer stride %d kB " 27042542f5fSchristos "exceeds display limit\n", stride / 1024); 27142542f5fSchristos return NULL; 27242542f5fSchristos } 27342542f5fSchristos 27442542f5fSchristos bo = drm_intel_bo_alloc(intel->bufmgr, "front buffer", size, 0); 27542542f5fSchristos if (bo == NULL) 27642542f5fSchristos return FALSE; 27742542f5fSchristos 27842542f5fSchristos if (tiling != I915_TILING_NONE) 27942542f5fSchristos drm_intel_bo_set_tiling(bo, &tiling, stride); 28042542f5fSchristos 28142542f5fSchristos xf86DrvMsg(scrn->scrnIndex, X_INFO, 28242542f5fSchristos "Allocated new frame buffer %dx%d stride %d, %s\n", 28342542f5fSchristos width, height, stride, 28442542f5fSchristos tiling == I915_TILING_NONE ? "untiled" : "tiled"); 28542542f5fSchristos 28642542f5fSchristos drm_intel_bo_disable_reuse(bo); 28742542f5fSchristos 28842542f5fSchristos intel_set_gem_max_sizes(scrn); 28942542f5fSchristos *out_stride = stride; 29042542f5fSchristos *out_tiling = tiling; 29142542f5fSchristos return bo; 29242542f5fSchristos} 29342542f5fSchristos 29403b705cfSriastradhstatic Bool 29503b705cfSriastradhintel_uxa_check_solid(DrawablePtr drawable, int alu, Pixel planemask) 29603b705cfSriastradh{ 29703b705cfSriastradh ScrnInfoPtr scrn = xf86ScreenToScrn(drawable->pScreen); 29803b705cfSriastradh 29903b705cfSriastradh if (!UXA_PM_IS_SOLID(drawable, planemask)) { 30003b705cfSriastradh intel_debug_fallback(scrn, "planemask is not solid\n"); 30103b705cfSriastradh return FALSE; 30203b705cfSriastradh } 30303b705cfSriastradh 30403b705cfSriastradh switch (drawable->bitsPerPixel) { 30503b705cfSriastradh case 8: 30603b705cfSriastradh case 16: 30703b705cfSriastradh case 32: 30803b705cfSriastradh break; 30903b705cfSriastradh default: 31003b705cfSriastradh return FALSE; 31103b705cfSriastradh } 31203b705cfSriastradh 31303b705cfSriastradh return TRUE; 31403b705cfSriastradh} 31503b705cfSriastradh 31603b705cfSriastradh/** 31703b705cfSriastradh * Sets up hardware state for a series of solid fills. 31803b705cfSriastradh */ 31903b705cfSriastradhstatic Bool 32003b705cfSriastradhintel_uxa_prepare_solid(PixmapPtr pixmap, int alu, Pixel planemask, Pixel fg) 32103b705cfSriastradh{ 32203b705cfSriastradh ScrnInfoPtr scrn = xf86ScreenToScrn(pixmap->drawable.pScreen); 32303b705cfSriastradh intel_screen_private *intel = intel_get_screen_private(scrn); 32403b705cfSriastradh drm_intel_bo *bo_table[] = { 32503b705cfSriastradh NULL, /* batch_bo */ 32603b705cfSriastradh intel_get_pixmap_bo(pixmap), 32703b705cfSriastradh }; 32803b705cfSriastradh 32903b705cfSriastradh if (!intel_check_pitch_2d(pixmap)) 33003b705cfSriastradh return FALSE; 33103b705cfSriastradh 33203b705cfSriastradh if (!intel_get_aperture_space(scrn, bo_table, ARRAY_SIZE(bo_table))) 33303b705cfSriastradh return FALSE; 33403b705cfSriastradh 33503b705cfSriastradh intel->BR[13] = (I830PatternROP[alu] & 0xff) << 16; 33603b705cfSriastradh switch (pixmap->drawable.bitsPerPixel) { 33703b705cfSriastradh case 8: 33803b705cfSriastradh break; 33903b705cfSriastradh case 16: 34003b705cfSriastradh /* RGB565 */ 34103b705cfSriastradh intel->BR[13] |= (1 << 24); 34203b705cfSriastradh break; 34303b705cfSriastradh case 32: 34403b705cfSriastradh /* RGB8888 */ 34503b705cfSriastradh intel->BR[13] |= ((1 << 24) | (1 << 25)); 34603b705cfSriastradh break; 34703b705cfSriastradh } 34803b705cfSriastradh intel->BR[16] = fg; 34903b705cfSriastradh 35003b705cfSriastradh return TRUE; 35103b705cfSriastradh} 35203b705cfSriastradh 35303b705cfSriastradhstatic void intel_uxa_solid(PixmapPtr pixmap, int x1, int y1, int x2, int y2) 35403b705cfSriastradh{ 35503b705cfSriastradh ScrnInfoPtr scrn = xf86ScreenToScrn(pixmap->drawable.pScreen); 35603b705cfSriastradh intel_screen_private *intel = intel_get_screen_private(scrn); 35703b705cfSriastradh unsigned long pitch; 35803b705cfSriastradh uint32_t cmd; 35903b705cfSriastradh 36003b705cfSriastradh if (x1 < 0) 36103b705cfSriastradh x1 = 0; 36203b705cfSriastradh if (y1 < 0) 36303b705cfSriastradh y1 = 0; 36403b705cfSriastradh if (x2 > pixmap->drawable.width) 36503b705cfSriastradh x2 = pixmap->drawable.width; 36603b705cfSriastradh if (y2 > pixmap->drawable.height) 36703b705cfSriastradh y2 = pixmap->drawable.height; 36803b705cfSriastradh 36903b705cfSriastradh if (x2 <= x1 || y2 <= y1) 37003b705cfSriastradh return; 37103b705cfSriastradh 37203b705cfSriastradh pitch = intel_pixmap_pitch(pixmap); 37303b705cfSriastradh 37403b705cfSriastradh { 37542542f5fSchristos int len = INTEL_INFO(intel)->gen >= 0100 ? 7 : 6; 37642542f5fSchristos BEGIN_BATCH_BLT(len); 37703b705cfSriastradh 37842542f5fSchristos cmd = XY_COLOR_BLT_CMD | (len - 2); 37903b705cfSriastradh 38003b705cfSriastradh if (pixmap->drawable.bitsPerPixel == 32) 38103b705cfSriastradh cmd |= 38203b705cfSriastradh XY_COLOR_BLT_WRITE_ALPHA | XY_COLOR_BLT_WRITE_RGB; 38303b705cfSriastradh 38403b705cfSriastradh if (INTEL_INFO(intel)->gen >= 040 && intel_pixmap_tiled(pixmap)) { 38503b705cfSriastradh assert((pitch % 512) == 0); 38603b705cfSriastradh pitch >>= 2; 38703b705cfSriastradh cmd |= XY_COLOR_BLT_TILED; 38803b705cfSriastradh } 38903b705cfSriastradh 39003b705cfSriastradh OUT_BATCH(cmd); 39103b705cfSriastradh 39203b705cfSriastradh OUT_BATCH(intel->BR[13] | pitch); 39303b705cfSriastradh OUT_BATCH((y1 << 16) | (x1 & 0xffff)); 39403b705cfSriastradh OUT_BATCH((y2 << 16) | (x2 & 0xffff)); 39503b705cfSriastradh OUT_RELOC_PIXMAP_FENCED(pixmap, I915_GEM_DOMAIN_RENDER, 39603b705cfSriastradh I915_GEM_DOMAIN_RENDER, 0); 39703b705cfSriastradh OUT_BATCH(intel->BR[16]); 39803b705cfSriastradh ADVANCE_BATCH(); 39903b705cfSriastradh } 40003b705cfSriastradh} 40103b705cfSriastradh 40203b705cfSriastradh/** 40303b705cfSriastradh * TODO: 40403b705cfSriastradh * - support planemask using FULL_BLT_CMD? 40503b705cfSriastradh */ 40603b705cfSriastradhstatic Bool 40703b705cfSriastradhintel_uxa_check_copy(PixmapPtr source, PixmapPtr dest, 40803b705cfSriastradh int alu, Pixel planemask) 40903b705cfSriastradh{ 41003b705cfSriastradh ScrnInfoPtr scrn = xf86ScreenToScrn(dest->drawable.pScreen); 41103b705cfSriastradh 41203b705cfSriastradh if (!UXA_PM_IS_SOLID(&source->drawable, planemask)) { 41303b705cfSriastradh intel_debug_fallback(scrn, "planemask is not solid"); 41403b705cfSriastradh return FALSE; 41503b705cfSriastradh } 41603b705cfSriastradh 41703b705cfSriastradh if (source->drawable.bitsPerPixel != dest->drawable.bitsPerPixel) { 41803b705cfSriastradh intel_debug_fallback(scrn, "mixed bpp copies unsupported\n"); 41903b705cfSriastradh return FALSE; 42003b705cfSriastradh } 42103b705cfSriastradh switch (source->drawable.bitsPerPixel) { 42203b705cfSriastradh case 8: 42303b705cfSriastradh case 16: 42403b705cfSriastradh case 32: 42503b705cfSriastradh break; 42603b705cfSriastradh default: 42703b705cfSriastradh return FALSE; 42803b705cfSriastradh } 42903b705cfSriastradh 43003b705cfSriastradh if (!intel_check_pitch_2d(source)) 43103b705cfSriastradh return FALSE; 43203b705cfSriastradh if (!intel_check_pitch_2d(dest)) 43303b705cfSriastradh return FALSE; 43403b705cfSriastradh 43503b705cfSriastradh return TRUE; 43603b705cfSriastradh} 43703b705cfSriastradh 43803b705cfSriastradhstatic Bool 43903b705cfSriastradhintel_uxa_prepare_copy(PixmapPtr source, PixmapPtr dest, int xdir, 44003b705cfSriastradh int ydir, int alu, Pixel planemask) 44103b705cfSriastradh{ 44203b705cfSriastradh ScrnInfoPtr scrn = xf86ScreenToScrn(dest->drawable.pScreen); 44303b705cfSriastradh intel_screen_private *intel = intel_get_screen_private(scrn); 44403b705cfSriastradh drm_intel_bo *bo_table[] = { 44503b705cfSriastradh NULL, /* batch_bo */ 44603b705cfSriastradh intel_get_pixmap_bo(source), 44703b705cfSriastradh intel_get_pixmap_bo(dest), 44803b705cfSriastradh }; 44903b705cfSriastradh 45003b705cfSriastradh if (!intel_get_aperture_space(scrn, bo_table, ARRAY_SIZE(bo_table))) 45103b705cfSriastradh return FALSE; 45203b705cfSriastradh 45303b705cfSriastradh intel->render_source = source; 45403b705cfSriastradh 45503b705cfSriastradh intel->BR[13] = I830CopyROP[alu] << 16; 45603b705cfSriastradh switch (source->drawable.bitsPerPixel) { 45703b705cfSriastradh case 8: 45803b705cfSriastradh break; 45903b705cfSriastradh case 16: 46003b705cfSriastradh intel->BR[13] |= (1 << 24); 46103b705cfSriastradh break; 46203b705cfSriastradh case 32: 46303b705cfSriastradh intel->BR[13] |= ((1 << 25) | (1 << 24)); 46403b705cfSriastradh break; 46503b705cfSriastradh } 46603b705cfSriastradh 46703b705cfSriastradh return TRUE; 46803b705cfSriastradh} 46903b705cfSriastradh 47003b705cfSriastradhstatic void 47103b705cfSriastradhintel_uxa_copy(PixmapPtr dest, int src_x1, int src_y1, int dst_x1, 47203b705cfSriastradh int dst_y1, int w, int h) 47303b705cfSriastradh{ 47403b705cfSriastradh ScrnInfoPtr scrn = xf86ScreenToScrn(dest->drawable.pScreen); 47503b705cfSriastradh intel_screen_private *intel = intel_get_screen_private(scrn); 47603b705cfSriastradh uint32_t cmd; 47703b705cfSriastradh int dst_x2, dst_y2, src_x2, src_y2; 47803b705cfSriastradh unsigned int dst_pitch, src_pitch; 47903b705cfSriastradh 48003b705cfSriastradh dst_x2 = dst_x1 + w; 48103b705cfSriastradh dst_y2 = dst_y1 + h; 48203b705cfSriastradh 48303b705cfSriastradh /* XXX Fixup extents as a lamentable workaround for missing 48403b705cfSriastradh * source clipping in the upper layers. 48503b705cfSriastradh */ 48603b705cfSriastradh if (dst_x1 < 0) 48703b705cfSriastradh src_x1 -= dst_x1, dst_x1 = 0; 48803b705cfSriastradh if (dst_y1 < 0) 48903b705cfSriastradh src_y1 -= dst_y1, dst_y1 = 0; 49003b705cfSriastradh if (dst_x2 > dest->drawable.width) 49103b705cfSriastradh dst_x2 = dest->drawable.width; 49203b705cfSriastradh if (dst_y2 > dest->drawable.height) 49303b705cfSriastradh dst_y2 = dest->drawable.height; 49403b705cfSriastradh 49503b705cfSriastradh src_x2 = src_x1 + (dst_x2 - dst_x1); 49603b705cfSriastradh src_y2 = src_y1 + (dst_y2 - dst_y1); 49703b705cfSriastradh 49803b705cfSriastradh if (src_x1 < 0) 49903b705cfSriastradh dst_x1 -= src_x1, src_x1 = 0; 50003b705cfSriastradh if (src_y1 < 0) 50103b705cfSriastradh dst_y1 -= src_y1, src_y1 = 0; 50203b705cfSriastradh if (src_x2 > intel->render_source->drawable.width) 50303b705cfSriastradh dst_x2 -= src_x2 - intel->render_source->drawable.width; 50403b705cfSriastradh if (src_y2 > intel->render_source->drawable.height) 50503b705cfSriastradh dst_y2 -= src_y2 - intel->render_source->drawable.height; 50603b705cfSriastradh 50703b705cfSriastradh if (dst_x2 <= dst_x1 || dst_y2 <= dst_y1) 50803b705cfSriastradh return; 50903b705cfSriastradh 51003b705cfSriastradh dst_pitch = intel_pixmap_pitch(dest); 51103b705cfSriastradh src_pitch = intel_pixmap_pitch(intel->render_source); 51203b705cfSriastradh 51303b705cfSriastradh { 51442542f5fSchristos int len = INTEL_INFO(intel)->gen >= 0100 ? 10 : 8; 51542542f5fSchristos BEGIN_BATCH_BLT(len); 51603b705cfSriastradh 51742542f5fSchristos cmd = XY_SRC_COPY_BLT_CMD | (len - 2); 51803b705cfSriastradh 51903b705cfSriastradh if (dest->drawable.bitsPerPixel == 32) 52003b705cfSriastradh cmd |= 52103b705cfSriastradh XY_SRC_COPY_BLT_WRITE_ALPHA | 52203b705cfSriastradh XY_SRC_COPY_BLT_WRITE_RGB; 52303b705cfSriastradh 52403b705cfSriastradh if (INTEL_INFO(intel)->gen >= 040) { 52503b705cfSriastradh if (intel_pixmap_tiled(dest)) { 52603b705cfSriastradh assert((dst_pitch % 512) == 0); 52703b705cfSriastradh dst_pitch >>= 2; 52803b705cfSriastradh cmd |= XY_SRC_COPY_BLT_DST_TILED; 52903b705cfSriastradh } 53003b705cfSriastradh 53103b705cfSriastradh if (intel_pixmap_tiled(intel->render_source)) { 53203b705cfSriastradh assert((src_pitch % 512) == 0); 53303b705cfSriastradh src_pitch >>= 2; 53403b705cfSriastradh cmd |= XY_SRC_COPY_BLT_SRC_TILED; 53503b705cfSriastradh } 53603b705cfSriastradh } 53703b705cfSriastradh 53803b705cfSriastradh OUT_BATCH(cmd); 53903b705cfSriastradh 54003b705cfSriastradh OUT_BATCH(intel->BR[13] | dst_pitch); 54103b705cfSriastradh OUT_BATCH((dst_y1 << 16) | (dst_x1 & 0xffff)); 54203b705cfSriastradh OUT_BATCH((dst_y2 << 16) | (dst_x2 & 0xffff)); 54303b705cfSriastradh OUT_RELOC_PIXMAP_FENCED(dest, 54403b705cfSriastradh I915_GEM_DOMAIN_RENDER, 54503b705cfSriastradh I915_GEM_DOMAIN_RENDER, 54603b705cfSriastradh 0); 54703b705cfSriastradh OUT_BATCH((src_y1 << 16) | (src_x1 & 0xffff)); 54803b705cfSriastradh OUT_BATCH(src_pitch); 54903b705cfSriastradh OUT_RELOC_PIXMAP_FENCED(intel->render_source, 55003b705cfSriastradh I915_GEM_DOMAIN_RENDER, 0, 55103b705cfSriastradh 0); 55203b705cfSriastradh 55303b705cfSriastradh ADVANCE_BATCH(); 55403b705cfSriastradh } 55503b705cfSriastradh} 55603b705cfSriastradh 55703b705cfSriastradhstatic void intel_uxa_done(PixmapPtr pixmap) 55803b705cfSriastradh{ 55903b705cfSriastradh ScrnInfoPtr scrn = xf86ScreenToScrn(pixmap->drawable.pScreen); 56003b705cfSriastradh intel_screen_private *intel = intel_get_screen_private(scrn); 56103b705cfSriastradh 56242542f5fSchristos if (INTEL_INFO(intel)->gen >= 060) { 56303b705cfSriastradh /* workaround a random BLT hang */ 56403b705cfSriastradh BEGIN_BATCH_BLT(3); 56542542f5fSchristos OUT_BATCH(XY_SETUP_CLIP_BLT_CMD | (3 - 2)); 56603b705cfSriastradh OUT_BATCH(0); 56703b705cfSriastradh OUT_BATCH(0); 56803b705cfSriastradh ADVANCE_BATCH(); 56903b705cfSriastradh } 57003b705cfSriastradh 57103b705cfSriastradh intel_debug_flush(scrn); 57203b705cfSriastradh} 57303b705cfSriastradh 57403b705cfSriastradh/** 57503b705cfSriastradh * Do any cleanup from the Composite operation. 57603b705cfSriastradh * 57703b705cfSriastradh * This is shared between i830 through i965. 57803b705cfSriastradh */ 57903b705cfSriastradhstatic void i830_done_composite(PixmapPtr dest) 58003b705cfSriastradh{ 58103b705cfSriastradh ScrnInfoPtr scrn = xf86ScreenToScrn(dest->drawable.pScreen); 58203b705cfSriastradh intel_screen_private *intel = intel_get_screen_private(scrn); 58303b705cfSriastradh 58403b705cfSriastradh if (intel->vertex_flush) 58503b705cfSriastradh intel->vertex_flush(intel); 58603b705cfSriastradh 58703b705cfSriastradh intel_debug_flush(scrn); 58803b705cfSriastradh} 58903b705cfSriastradh 59003b705cfSriastradh#define xFixedToFloat(val) \ 59103b705cfSriastradh ((float)xFixedToInt(val) + ((float)xFixedFrac(val) / 65536.0)) 59203b705cfSriastradh 59303b705cfSriastradhstatic Bool 59403b705cfSriastradh_intel_transform_point(PictTransformPtr transform, 59503b705cfSriastradh float x, float y, float result[3]) 59603b705cfSriastradh{ 59703b705cfSriastradh int j; 59803b705cfSriastradh 59903b705cfSriastradh for (j = 0; j < 3; j++) { 60003b705cfSriastradh result[j] = (xFixedToFloat(transform->matrix[j][0]) * x + 60103b705cfSriastradh xFixedToFloat(transform->matrix[j][1]) * y + 60203b705cfSriastradh xFixedToFloat(transform->matrix[j][2])); 60303b705cfSriastradh } 60403b705cfSriastradh if (!result[2]) 60503b705cfSriastradh return FALSE; 60603b705cfSriastradh return TRUE; 60703b705cfSriastradh} 60803b705cfSriastradh 60903b705cfSriastradh/** 61003b705cfSriastradh * Returns the floating-point coordinates transformed by the given transform. 61103b705cfSriastradh * 61203b705cfSriastradh * transform may be null. 61303b705cfSriastradh */ 61403b705cfSriastradhBool 61503b705cfSriastradhintel_get_transformed_coordinates(int x, int y, PictTransformPtr transform, 61603b705cfSriastradh float *x_out, float *y_out) 61703b705cfSriastradh{ 61803b705cfSriastradh if (transform == NULL) { 61903b705cfSriastradh *x_out = x; 62003b705cfSriastradh *y_out = y; 62103b705cfSriastradh } else { 62203b705cfSriastradh float result[3]; 62303b705cfSriastradh 62403b705cfSriastradh if (!_intel_transform_point(transform, 62503b705cfSriastradh x, y, 62603b705cfSriastradh result)) 62703b705cfSriastradh return FALSE; 62803b705cfSriastradh *x_out = result[0] / result[2]; 62903b705cfSriastradh *y_out = result[1] / result[2]; 63003b705cfSriastradh } 63103b705cfSriastradh return TRUE; 63203b705cfSriastradh} 63303b705cfSriastradh 63403b705cfSriastradh/** 63503b705cfSriastradh * Returns the un-normalized floating-point coordinates transformed by the given transform. 63603b705cfSriastradh * 63703b705cfSriastradh * transform may be null. 63803b705cfSriastradh */ 63903b705cfSriastradhBool 64003b705cfSriastradhintel_get_transformed_coordinates_3d(int x, int y, PictTransformPtr transform, 64103b705cfSriastradh float *x_out, float *y_out, float *w_out) 64203b705cfSriastradh{ 64303b705cfSriastradh if (transform == NULL) { 64403b705cfSriastradh *x_out = x; 64503b705cfSriastradh *y_out = y; 64603b705cfSriastradh *w_out = 1; 64703b705cfSriastradh } else { 64803b705cfSriastradh float result[3]; 64903b705cfSriastradh 65003b705cfSriastradh if (!_intel_transform_point(transform, 65103b705cfSriastradh x, y, 65203b705cfSriastradh result)) 65303b705cfSriastradh return FALSE; 65403b705cfSriastradh *x_out = result[0]; 65503b705cfSriastradh *y_out = result[1]; 65603b705cfSriastradh *w_out = result[2]; 65703b705cfSriastradh } 65803b705cfSriastradh return TRUE; 65903b705cfSriastradh} 66003b705cfSriastradh 66103b705cfSriastradh/** 66203b705cfSriastradh * Returns whether the provided transform is affine. 66303b705cfSriastradh * 66403b705cfSriastradh * transform may be null. 66503b705cfSriastradh */ 66603b705cfSriastradhBool intel_transform_is_affine(PictTransformPtr t) 66703b705cfSriastradh{ 66803b705cfSriastradh if (t == NULL) 66903b705cfSriastradh return TRUE; 67003b705cfSriastradh return t->matrix[2][0] == 0 && t->matrix[2][1] == 0; 67103b705cfSriastradh} 67203b705cfSriastradh 67303b705cfSriastradhdri_bo *intel_get_pixmap_bo(PixmapPtr pixmap) 67403b705cfSriastradh{ 67503b705cfSriastradh struct intel_pixmap *intel; 67603b705cfSriastradh 67703b705cfSriastradh intel = intel_get_pixmap_private(pixmap); 67803b705cfSriastradh if (intel == NULL) 67903b705cfSriastradh return NULL; 68003b705cfSriastradh 68103b705cfSriastradh return intel->bo; 68203b705cfSriastradh} 68303b705cfSriastradh 68442542f5fSchristosstatic unsigned intel_get_tile_width(intel_screen_private *intel, int tiling, int pitch) 68542542f5fSchristos{ 68642542f5fSchristos unsigned long tile_width; 68742542f5fSchristos 68842542f5fSchristos if (tiling == I915_TILING_NONE) 68942542f5fSchristos return 4; 69042542f5fSchristos 69142542f5fSchristos tile_width = (tiling == I915_TILING_Y) ? 128 : 512; 69242542f5fSchristos if (INTEL_INFO(intel)->gen >= 040) 69342542f5fSchristos return tile_width; 69442542f5fSchristos 69542542f5fSchristos while (tile_width < pitch) 69642542f5fSchristos tile_width <<= 1; 69742542f5fSchristos 69842542f5fSchristos return tile_width; 69942542f5fSchristos} 70042542f5fSchristos 70103b705cfSriastradhvoid intel_set_pixmap_bo(PixmapPtr pixmap, dri_bo * bo) 70203b705cfSriastradh{ 70342542f5fSchristos ScrnInfoPtr scrn = xf86ScreenToScrn(pixmap->drawable.pScreen); 70442542f5fSchristos intel_screen_private *intel = intel_get_screen_private(scrn); 70503b705cfSriastradh struct intel_pixmap *priv; 70603b705cfSriastradh 70703b705cfSriastradh priv = intel_get_pixmap_private(pixmap); 70803b705cfSriastradh if (priv == NULL && bo == NULL) 70942542f5fSchristos return; 71003b705cfSriastradh 71103b705cfSriastradh if (priv != NULL) { 71203b705cfSriastradh if (priv->bo == bo) 71303b705cfSriastradh return; 71403b705cfSriastradh 71542542f5fSchristosfree_priv: 71603b705cfSriastradh dri_bo_unreference(priv->bo); 71703b705cfSriastradh list_del(&priv->batch); 71803b705cfSriastradh 71903b705cfSriastradh free(priv); 72003b705cfSriastradh priv = NULL; 72103b705cfSriastradh } 72203b705cfSriastradh 72303b705cfSriastradh if (bo != NULL) { 72442542f5fSchristos uint32_t tiling, swizzle_mode; 72542542f5fSchristos unsigned tile_width; 72642542f5fSchristos int size, stride; 72703b705cfSriastradh 72803b705cfSriastradh priv = calloc(1, sizeof (struct intel_pixmap)); 72903b705cfSriastradh if (priv == NULL) 73003b705cfSriastradh goto BAIL; 73103b705cfSriastradh 73203b705cfSriastradh list_init(&priv->batch); 73303b705cfSriastradh 73403b705cfSriastradh dri_bo_reference(bo); 73503b705cfSriastradh priv->bo = bo; 73603b705cfSriastradh priv->stride = intel_pixmap_pitch(pixmap); 73703b705cfSriastradh 73842542f5fSchristos if (drm_intel_bo_get_tiling(bo, &tiling, &swizzle_mode)) { 73942542f5fSchristos bo = NULL; 74042542f5fSchristos goto free_priv; 74103b705cfSriastradh } 74203b705cfSriastradh 74303b705cfSriastradh priv->tiling = tiling; 74403b705cfSriastradh priv->busy = -1; 74503b705cfSriastradh priv->offscreen = 1; 74642542f5fSchristos 74742542f5fSchristos stride = (pixmap->drawable.width * pixmap->drawable.bitsPerPixel + 7) / 8; 74842542f5fSchristos tile_width = intel_get_tile_width(intel, tiling, stride); 74942542f5fSchristos stride = ALIGN(stride, tile_width); 75042542f5fSchristos 75142542f5fSchristos if (priv->stride < stride || 75242542f5fSchristos priv->stride & (tile_width - 1) || 75342542f5fSchristos priv->stride >= KB(32)) { 75442542f5fSchristos xf86DrvMsg(scrn->scrnIndex, X_ERROR, 75542542f5fSchristos "%s: stride on buffer object does not match constraints: stride=%d, must be greater than %d, but less than %d, and have alignment at least %d\n", 75642542f5fSchristos __FUNCTION__, priv->stride, stride, KB(32), tile_width); 75742542f5fSchristos bo = NULL; 75842542f5fSchristos goto free_priv; 75942542f5fSchristos } 76042542f5fSchristos 76142542f5fSchristos if (tiling != I915_TILING_NONE) { 76242542f5fSchristos int height; 76342542f5fSchristos 76442542f5fSchristos if (IS_GEN2(intel)) 76542542f5fSchristos height = 16; 76642542f5fSchristos else if (tiling == I915_TILING_X) 76742542f5fSchristos height = 8; 76842542f5fSchristos else 76942542f5fSchristos height = 32; 77042542f5fSchristos 77142542f5fSchristos height = ALIGN(pixmap->drawable.height, 2*height); 77242542f5fSchristos size = intel_get_fence_size(intel, priv->stride * height); 77342542f5fSchristos } else 77442542f5fSchristos size = priv->stride * pixmap->drawable.height; 77542542f5fSchristos 77642542f5fSchristos if (bo->size < size || bo->size > intel->max_bo_size) { 77742542f5fSchristos xf86DrvMsg(scrn->scrnIndex, X_ERROR, 77842542f5fSchristos "%s: size of buffer object does not match constraints: size=%ld, must be greater than %d, but less than %d\n", 77942542f5fSchristos __FUNCTION__, (long)bo->size, size, intel->max_bo_size); 78042542f5fSchristos bo = NULL; 78142542f5fSchristos goto free_priv; 78242542f5fSchristos } 78303b705cfSriastradh } 78403b705cfSriastradh 78503b705cfSriastradh BAIL: 78603b705cfSriastradh intel_set_pixmap_private(pixmap, priv); 78703b705cfSriastradh} 78803b705cfSriastradh 78903b705cfSriastradhstatic Bool intel_uxa_pixmap_is_offscreen(PixmapPtr pixmap) 79003b705cfSriastradh{ 79103b705cfSriastradh return intel_pixmap_is_offscreen(pixmap); 79203b705cfSriastradh} 79303b705cfSriastradh 79403b705cfSriastradhstatic Bool intel_uxa_prepare_access(PixmapPtr pixmap, uxa_access_t access) 79503b705cfSriastradh{ 79603b705cfSriastradh ScrnInfoPtr scrn = xf86ScreenToScrn(pixmap->drawable.pScreen); 79703b705cfSriastradh intel_screen_private *intel = intel_get_screen_private(scrn); 79803b705cfSriastradh struct intel_pixmap *priv = intel_get_pixmap_private(pixmap); 79903b705cfSriastradh dri_bo *bo = priv->bo; 80003b705cfSriastradh int ret; 80103b705cfSriastradh 80203b705cfSriastradh /* Transitioning to glamor acceleration, we need to flush all pending 80303b705cfSriastradh * usage by UXA. */ 80403b705cfSriastradh if (access == UXA_GLAMOR_ACCESS_RW || access == UXA_GLAMOR_ACCESS_RO) { 80503b705cfSriastradh if (!list_is_empty(&priv->batch)) 80603b705cfSriastradh intel_batch_submit(scrn); 80703b705cfSriastradh return TRUE; 80803b705cfSriastradh } 80903b705cfSriastradh 81003b705cfSriastradh /* When falling back to swrast, flush all pending operations */ 81103b705cfSriastradh intel_glamor_flush(intel); 81203b705cfSriastradh if (access == UXA_ACCESS_RW || priv->dirty) 81303b705cfSriastradh intel_batch_submit(scrn); 81403b705cfSriastradh 81503b705cfSriastradh assert(bo->size <= intel->max_gtt_map_size); 81603b705cfSriastradh ret = drm_intel_gem_bo_map_gtt(bo); 81703b705cfSriastradh if (ret) { 81803b705cfSriastradh xf86DrvMsg(scrn->scrnIndex, X_WARNING, 81903b705cfSriastradh "%s: bo map (use gtt? %d, access %d) failed: %s\n", 82003b705cfSriastradh __FUNCTION__, 82103b705cfSriastradh priv->tiling || bo->size <= intel->max_gtt_map_size, 82203b705cfSriastradh access, 82303b705cfSriastradh strerror(-ret)); 82403b705cfSriastradh return FALSE; 82503b705cfSriastradh } 82603b705cfSriastradh 82703b705cfSriastradh pixmap->devPrivate.ptr = bo->virtual; 82803b705cfSriastradh priv->busy = 0; 82903b705cfSriastradh 83003b705cfSriastradh return TRUE; 83103b705cfSriastradh} 83203b705cfSriastradh 83303b705cfSriastradhstatic void intel_uxa_finish_access(PixmapPtr pixmap, uxa_access_t access) 83403b705cfSriastradh{ 83503b705cfSriastradh struct intel_pixmap *priv; 83603b705cfSriastradh 83703b705cfSriastradh if (access == UXA_GLAMOR_ACCESS_RW || access == UXA_GLAMOR_ACCESS_RO) 83803b705cfSriastradh return; 83903b705cfSriastradh 84003b705cfSriastradh priv = intel_get_pixmap_private(pixmap); 84103b705cfSriastradh if (priv == NULL) 84203b705cfSriastradh return; 84303b705cfSriastradh 84403b705cfSriastradh drm_intel_gem_bo_unmap_gtt(priv->bo); 84503b705cfSriastradh pixmap->devPrivate.ptr = NULL; 84603b705cfSriastradh} 84703b705cfSriastradh 84803b705cfSriastradhstatic Bool intel_uxa_pixmap_put_image(PixmapPtr pixmap, 84903b705cfSriastradh char *src, int src_pitch, 85003b705cfSriastradh int x, int y, int w, int h) 85103b705cfSriastradh{ 85203b705cfSriastradh struct intel_pixmap *priv = intel_get_pixmap_private(pixmap); 85303b705cfSriastradh int stride = intel_pixmap_pitch(pixmap); 85403b705cfSriastradh int cpp = pixmap->drawable.bitsPerPixel/8; 85503b705cfSriastradh int ret = FALSE; 85603b705cfSriastradh 85703b705cfSriastradh if (priv == NULL || priv->bo == NULL) 85803b705cfSriastradh return FALSE; 85903b705cfSriastradh 86003b705cfSriastradh if (priv->tiling == I915_TILING_NONE && 86103b705cfSriastradh (h == 1 || (src_pitch == stride && w == pixmap->drawable.width))) { 86203b705cfSriastradh return drm_intel_bo_subdata(priv->bo, y*stride + x*cpp, stride*(h-1) + w*cpp, src) == 0; 86303b705cfSriastradh } else if (drm_intel_gem_bo_map_gtt(priv->bo) == 0) { 86403b705cfSriastradh char *dst = priv->bo->virtual; 86503b705cfSriastradh int row_length = w * cpp; 86603b705cfSriastradh int num_rows = h; 86703b705cfSriastradh if (row_length == src_pitch && src_pitch == stride) 86803b705cfSriastradh num_rows = 1, row_length *= h; 86903b705cfSriastradh dst += y * stride + x * cpp; 87003b705cfSriastradh do { 87103b705cfSriastradh memcpy (dst, src, row_length); 87203b705cfSriastradh src += src_pitch; 87303b705cfSriastradh dst += stride; 87403b705cfSriastradh } while (--num_rows); 87503b705cfSriastradh drm_intel_gem_bo_unmap_gtt(priv->bo); 87603b705cfSriastradh ret = TRUE; 87703b705cfSriastradh } 87803b705cfSriastradh 87903b705cfSriastradh return ret; 88003b705cfSriastradh} 88103b705cfSriastradh 88203b705cfSriastradhstatic Bool intel_uxa_put_image(PixmapPtr pixmap, 88303b705cfSriastradh int x, int y, 88403b705cfSriastradh int w, int h, 88503b705cfSriastradh char *src, int src_pitch) 88603b705cfSriastradh{ 88703b705cfSriastradh struct intel_pixmap *priv; 88803b705cfSriastradh 88903b705cfSriastradh priv = intel_get_pixmap_private(pixmap); 89003b705cfSriastradh if (!intel_pixmap_is_busy(priv)) { 89103b705cfSriastradh /* bo is not busy so can be replaced without a stall, upload in-place. */ 89203b705cfSriastradh return intel_uxa_pixmap_put_image(pixmap, src, src_pitch, x, y, w, h); 89303b705cfSriastradh } else { 89403b705cfSriastradh ScreenPtr screen = pixmap->drawable.pScreen; 89503b705cfSriastradh 89603b705cfSriastradh if (!priv->pinned && 89703b705cfSriastradh x == 0 && y == 0 && 89803b705cfSriastradh w == pixmap->drawable.width && 89903b705cfSriastradh h == pixmap->drawable.height) 90003b705cfSriastradh { 90103b705cfSriastradh intel_screen_private *intel = intel_get_screen_private(xf86ScreenToScrn(screen)); 90203b705cfSriastradh uint32_t tiling = priv->tiling; 90303b705cfSriastradh int size, stride; 90403b705cfSriastradh dri_bo *bo; 90503b705cfSriastradh 90603b705cfSriastradh /* Replace busy bo. */ 90742542f5fSchristos size = intel_uxa_compute_size(intel, 90842542f5fSchristos w, h, 90942542f5fSchristos pixmap->drawable.bitsPerPixel, pixmap->usage_hint, 91042542f5fSchristos &tiling, &stride); 91103b705cfSriastradh if (size > intel->max_gtt_map_size) 91203b705cfSriastradh return FALSE; 91303b705cfSriastradh 91403b705cfSriastradh bo = drm_intel_bo_alloc(intel->bufmgr, "pixmap", size, 0); 91503b705cfSriastradh if (bo == NULL) 91603b705cfSriastradh return FALSE; 91703b705cfSriastradh 91803b705cfSriastradh if (tiling != I915_TILING_NONE) 91903b705cfSriastradh drm_intel_bo_set_tiling(bo, &tiling, stride); 92003b705cfSriastradh priv->stride = stride; 92103b705cfSriastradh priv->tiling = tiling; 92203b705cfSriastradh 92303b705cfSriastradh screen->ModifyPixmapHeader(pixmap, 92403b705cfSriastradh w, h, 92503b705cfSriastradh 0, 0, 92603b705cfSriastradh stride, NULL); 92703b705cfSriastradh intel_set_pixmap_bo(pixmap, bo); 92803b705cfSriastradh dri_bo_unreference(bo); 92903b705cfSriastradh 93003b705cfSriastradh return intel_uxa_pixmap_put_image(pixmap, src, src_pitch, 0, 0, w, h); 93103b705cfSriastradh } 93203b705cfSriastradh else 93303b705cfSriastradh { 93403b705cfSriastradh PixmapPtr scratch; 93503b705cfSriastradh Bool ret; 93603b705cfSriastradh 93703b705cfSriastradh /* Upload to a linear buffer and queue a blit. */ 93803b705cfSriastradh scratch = (*screen->CreatePixmap)(screen, w, h, 93903b705cfSriastradh pixmap->drawable.depth, 94003b705cfSriastradh UXA_CREATE_PIXMAP_FOR_MAP); 94103b705cfSriastradh if (!scratch) 94203b705cfSriastradh return FALSE; 94303b705cfSriastradh 94403b705cfSriastradh if (!intel_uxa_pixmap_is_offscreen(scratch)) { 94503b705cfSriastradh screen->DestroyPixmap(scratch); 94603b705cfSriastradh return FALSE; 94703b705cfSriastradh } 94803b705cfSriastradh 94903b705cfSriastradh ret = intel_uxa_pixmap_put_image(scratch, src, src_pitch, 0, 0, w, h); 95003b705cfSriastradh if (ret) { 95103b705cfSriastradh GCPtr gc = GetScratchGC(pixmap->drawable.depth, screen); 95203b705cfSriastradh if (gc) { 95303b705cfSriastradh ValidateGC(&pixmap->drawable, gc); 95403b705cfSriastradh 95503b705cfSriastradh (*gc->ops->CopyArea)(&scratch->drawable, 95603b705cfSriastradh &pixmap->drawable, 95703b705cfSriastradh gc, 0, 0, w, h, x, y); 95803b705cfSriastradh 95903b705cfSriastradh FreeScratchGC(gc); 96003b705cfSriastradh } else 96103b705cfSriastradh ret = FALSE; 96203b705cfSriastradh } 96303b705cfSriastradh 96403b705cfSriastradh (*screen->DestroyPixmap)(scratch); 96503b705cfSriastradh return ret; 96603b705cfSriastradh } 96703b705cfSriastradh } 96803b705cfSriastradh} 96903b705cfSriastradh 97003b705cfSriastradhstatic Bool intel_uxa_pixmap_get_image(PixmapPtr pixmap, 97103b705cfSriastradh int x, int y, int w, int h, 97203b705cfSriastradh char *dst, int dst_pitch) 97303b705cfSriastradh{ 97403b705cfSriastradh struct intel_pixmap *priv = intel_get_pixmap_private(pixmap); 97503b705cfSriastradh int stride = intel_pixmap_pitch(pixmap); 97603b705cfSriastradh int cpp = pixmap->drawable.bitsPerPixel/8; 97703b705cfSriastradh 97803b705cfSriastradh /* assert(priv->tiling == I915_TILING_NONE); */ 97903b705cfSriastradh if (h == 1 || (dst_pitch == stride && w == pixmap->drawable.width)) { 98003b705cfSriastradh return drm_intel_bo_get_subdata(priv->bo, y*stride + x*cpp, (h-1)*stride + w*cpp, dst) == 0; 98103b705cfSriastradh } else { 98203b705cfSriastradh char *src; 98303b705cfSriastradh 98403b705cfSriastradh if (drm_intel_gem_bo_map_gtt(priv->bo)) 98503b705cfSriastradh return FALSE; 98603b705cfSriastradh 98703b705cfSriastradh src = (char *) priv->bo->virtual + y * stride + x * cpp; 98803b705cfSriastradh w *= cpp; 98903b705cfSriastradh do { 99003b705cfSriastradh memcpy(dst, src, w); 99103b705cfSriastradh src += stride; 99203b705cfSriastradh dst += dst_pitch; 99303b705cfSriastradh } while (--h); 99403b705cfSriastradh 99503b705cfSriastradh drm_intel_gem_bo_unmap_gtt(priv->bo); 99603b705cfSriastradh 99703b705cfSriastradh return TRUE; 99803b705cfSriastradh } 99903b705cfSriastradh} 100003b705cfSriastradh 100103b705cfSriastradhstatic Bool intel_uxa_get_image(PixmapPtr pixmap, 100203b705cfSriastradh int x, int y, 100303b705cfSriastradh int w, int h, 100403b705cfSriastradh char *dst, int dst_pitch) 100503b705cfSriastradh{ 100603b705cfSriastradh struct intel_pixmap *priv; 100703b705cfSriastradh PixmapPtr scratch = NULL; 100803b705cfSriastradh Bool ret; 100903b705cfSriastradh 101003b705cfSriastradh /* The presumption is that we wish to keep the target hot, so 101103b705cfSriastradh * copy to a new bo and move that to the CPU in preference to 101203b705cfSriastradh * causing ping-pong of the original. 101303b705cfSriastradh * 101403b705cfSriastradh * Also the gpu is much faster at detiling. 101503b705cfSriastradh */ 101603b705cfSriastradh 101703b705cfSriastradh priv = intel_get_pixmap_private(pixmap); 101803b705cfSriastradh if (intel_pixmap_is_busy(priv) || priv->tiling != I915_TILING_NONE) { 101903b705cfSriastradh ScreenPtr screen = pixmap->drawable.pScreen; 102003b705cfSriastradh GCPtr gc; 102103b705cfSriastradh 102203b705cfSriastradh /* Copy to a linear buffer and pull. */ 102303b705cfSriastradh scratch = screen->CreatePixmap(screen, w, h, 102403b705cfSriastradh pixmap->drawable.depth, 102503b705cfSriastradh INTEL_CREATE_PIXMAP_TILING_NONE); 102603b705cfSriastradh if (!scratch) 102703b705cfSriastradh return FALSE; 102803b705cfSriastradh 102903b705cfSriastradh if (!intel_uxa_pixmap_is_offscreen(scratch)) { 103003b705cfSriastradh screen->DestroyPixmap(scratch); 103103b705cfSriastradh return FALSE; 103203b705cfSriastradh } 103303b705cfSriastradh 103403b705cfSriastradh gc = GetScratchGC(pixmap->drawable.depth, screen); 103503b705cfSriastradh if (!gc) { 103603b705cfSriastradh screen->DestroyPixmap(scratch); 103703b705cfSriastradh return FALSE; 103803b705cfSriastradh } 103903b705cfSriastradh 104003b705cfSriastradh ValidateGC(&pixmap->drawable, gc); 104103b705cfSriastradh 104203b705cfSriastradh gc->ops->CopyArea(&pixmap->drawable, 104303b705cfSriastradh &scratch->drawable, 104403b705cfSriastradh gc, x, y, w, h, 0, 0); 104503b705cfSriastradh 104603b705cfSriastradh FreeScratchGC(gc); 104703b705cfSriastradh 104803b705cfSriastradh intel_batch_submit(xf86ScreenToScrn(screen)); 104903b705cfSriastradh 105003b705cfSriastradh x = y = 0; 105103b705cfSriastradh pixmap = scratch; 105203b705cfSriastradh } 105303b705cfSriastradh 105403b705cfSriastradh ret = intel_uxa_pixmap_get_image(pixmap, x, y, w, h, dst, dst_pitch); 105503b705cfSriastradh 105603b705cfSriastradh if (scratch) 105703b705cfSriastradh scratch->drawable.pScreen->DestroyPixmap(scratch); 105803b705cfSriastradh 105903b705cfSriastradh return ret; 106003b705cfSriastradh} 106103b705cfSriastradh 106203b705cfSriastradhstatic CARD32 intel_cache_expire(OsTimerPtr timer, CARD32 now, pointer data) 106303b705cfSriastradh{ 106403b705cfSriastradh intel_screen_private *intel = data; 106503b705cfSriastradh 106603b705cfSriastradh /* We just want to create and destroy a bo as this causes libdrm 106703b705cfSriastradh * to reap its caches. However, since we can't remove that buffer 106803b705cfSriastradh * from the cache due to its own activity, we want to use something 106903b705cfSriastradh * that we know we will reuse later. The most frequently reused buffer 107003b705cfSriastradh * we have is the batchbuffer, and the best way to trigger its 107103b705cfSriastradh * reallocation is to submit a flush. 107203b705cfSriastradh */ 107303b705cfSriastradh intel_batch_emit_flush(intel->scrn); 107403b705cfSriastradh intel_batch_submit(intel->scrn); 107503b705cfSriastradh 107603b705cfSriastradh return 0; 107703b705cfSriastradh} 107803b705cfSriastradh 107903b705cfSriastradhstatic void intel_flush_rendering(intel_screen_private *intel) 108003b705cfSriastradh{ 108103b705cfSriastradh if (intel->needs_flush == 0) 108203b705cfSriastradh return; 108303b705cfSriastradh 108403b705cfSriastradh if (intel->has_kernel_flush) { 108503b705cfSriastradh intel_batch_submit(intel->scrn); 108603b705cfSriastradh drm_intel_bo_busy(intel->front_buffer); 108703b705cfSriastradh } else { 108803b705cfSriastradh intel_batch_emit_flush(intel->scrn); 108903b705cfSriastradh intel_batch_submit(intel->scrn); 109003b705cfSriastradh } 109103b705cfSriastradh 109203b705cfSriastradh intel->cache_expire = TimerSet(intel->cache_expire, 0, 3000, 109303b705cfSriastradh intel_cache_expire, intel); 109403b705cfSriastradh 109503b705cfSriastradh intel->needs_flush = 0; 109603b705cfSriastradh} 109703b705cfSriastradh 109803b705cfSriastradhstatic void intel_throttle(intel_screen_private *intel) 109903b705cfSriastradh{ 110003b705cfSriastradh drmCommandNone(intel->drmSubFD, DRM_I915_GEM_THROTTLE); 110103b705cfSriastradh} 110203b705cfSriastradh 110303b705cfSriastradhvoid intel_uxa_block_handler(intel_screen_private *intel) 110403b705cfSriastradh{ 110503b705cfSriastradh /* Emit a flush of the rendering cache, or on the 965 110603b705cfSriastradh * and beyond rendering results may not hit the 110703b705cfSriastradh * framebuffer until significantly later. 110803b705cfSriastradh */ 110903b705cfSriastradh intel_glamor_flush(intel); 111003b705cfSriastradh intel_flush_rendering(intel); 111103b705cfSriastradh intel_throttle(intel); 111203b705cfSriastradh} 111303b705cfSriastradh 111403b705cfSriastradhstatic PixmapPtr 111503b705cfSriastradhintel_uxa_create_pixmap(ScreenPtr screen, int w, int h, int depth, 111603b705cfSriastradh unsigned usage) 111703b705cfSriastradh{ 111803b705cfSriastradh ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 111903b705cfSriastradh intel_screen_private *intel = intel_get_screen_private(scrn); 112003b705cfSriastradh struct intel_pixmap *priv; 112103b705cfSriastradh PixmapPtr pixmap, new_pixmap = NULL; 112203b705cfSriastradh 112303b705cfSriastradh if (!(usage & INTEL_CREATE_PIXMAP_DRI2)) { 112403b705cfSriastradh pixmap = intel_glamor_create_pixmap(screen, w, h, depth, usage); 112503b705cfSriastradh if (pixmap) 112603b705cfSriastradh return pixmap; 112703b705cfSriastradh } 112803b705cfSriastradh 112903b705cfSriastradh if (w > 32767 || h > 32767) 113003b705cfSriastradh return NullPixmap; 113103b705cfSriastradh 113203b705cfSriastradh if (depth == 1 || intel->force_fallback) 113303b705cfSriastradh return fbCreatePixmap(screen, w, h, depth, usage); 113403b705cfSriastradh 113503b705cfSriastradh if (usage == CREATE_PIXMAP_USAGE_GLYPH_PICTURE && w <= 32 && h <= 32) 113603b705cfSriastradh return fbCreatePixmap(screen, w, h, depth, usage); 113703b705cfSriastradh 113803b705cfSriastradh pixmap = fbCreatePixmap(screen, 0, 0, depth, usage); 113903b705cfSriastradh if (pixmap == NullPixmap) 114003b705cfSriastradh return pixmap; 114103b705cfSriastradh 114203b705cfSriastradh if (w && h) { 114303b705cfSriastradh unsigned int size, tiling; 114403b705cfSriastradh int stride; 114503b705cfSriastradh 114603b705cfSriastradh /* Always attempt to tile, compute_size() will remove the 114703b705cfSriastradh * tiling for pixmaps that are either too large or too small 114803b705cfSriastradh * to be effectively tiled. 114903b705cfSriastradh */ 115003b705cfSriastradh tiling = I915_TILING_X; 115103b705cfSriastradh if (usage & INTEL_CREATE_PIXMAP_TILING_Y) 115203b705cfSriastradh tiling = I915_TILING_Y; 115303b705cfSriastradh if (usage == UXA_CREATE_PIXMAP_FOR_MAP || usage & INTEL_CREATE_PIXMAP_TILING_NONE) 115403b705cfSriastradh tiling = I915_TILING_NONE; 115503b705cfSriastradh 115603b705cfSriastradh#ifdef CREATE_PIXMAP_USAGE_SHARED 115703b705cfSriastradh if (usage == CREATE_PIXMAP_USAGE_SHARED) 115803b705cfSriastradh tiling = I915_TILING_NONE; 115903b705cfSriastradh#endif 116003b705cfSriastradh /* if tiling is off force to none */ 116103b705cfSriastradh if (!intel->tiling) 116203b705cfSriastradh tiling = I915_TILING_NONE; 116303b705cfSriastradh 116403b705cfSriastradh if (tiling != I915_TILING_NONE && !(usage & INTEL_CREATE_PIXMAP_DRI2)) { 116503b705cfSriastradh if (h <= 4) 116603b705cfSriastradh tiling = I915_TILING_NONE; 116703b705cfSriastradh if (h <= 16 && tiling == I915_TILING_Y) 116803b705cfSriastradh tiling = I915_TILING_X; 116903b705cfSriastradh } 117042542f5fSchristos size = intel_uxa_compute_size(intel, 117142542f5fSchristos w, h, pixmap->drawable.bitsPerPixel, usage, 117242542f5fSchristos &tiling, &stride); 117303b705cfSriastradh 117403b705cfSriastradh /* Fail very large allocations. Large BOs will tend to hit SW fallbacks 117503b705cfSriastradh * frequently, and also will tend to fail to successfully map when doing 117603b705cfSriastradh * SW fallbacks because we overcommit address space for BO access. 117703b705cfSriastradh */ 117803b705cfSriastradh if (size > intel->max_bo_size || stride >= KB(32)) 117903b705cfSriastradh goto fallback_pixmap; 118003b705cfSriastradh 118103b705cfSriastradh priv = calloc(1, sizeof (struct intel_pixmap)); 118203b705cfSriastradh if (priv == NULL) 118303b705cfSriastradh goto fallback_pixmap; 118403b705cfSriastradh 118503b705cfSriastradh if (usage == UXA_CREATE_PIXMAP_FOR_MAP) { 118603b705cfSriastradh priv->busy = 0; 118703b705cfSriastradh priv->bo = drm_intel_bo_alloc(intel->bufmgr, 118803b705cfSriastradh "pixmap", size, 0); 118903b705cfSriastradh } else { 119003b705cfSriastradh priv->busy = -1; 119103b705cfSriastradh priv->bo = drm_intel_bo_alloc_for_render(intel->bufmgr, 119203b705cfSriastradh "pixmap", 119303b705cfSriastradh size, 0); 119403b705cfSriastradh } 119503b705cfSriastradh if (!priv->bo) 119603b705cfSriastradh goto fallback_priv; 119703b705cfSriastradh 119803b705cfSriastradh if (tiling != I915_TILING_NONE) 119903b705cfSriastradh drm_intel_bo_set_tiling(priv->bo, &tiling, stride); 120003b705cfSriastradh priv->stride = stride; 120103b705cfSriastradh priv->tiling = tiling; 120203b705cfSriastradh priv->offscreen = 1; 120303b705cfSriastradh 120403b705cfSriastradh list_init(&priv->batch); 120503b705cfSriastradh intel_set_pixmap_private(pixmap, priv); 120603b705cfSriastradh 120703b705cfSriastradh screen->ModifyPixmapHeader(pixmap, w, h, 0, 0, stride, NULL); 120803b705cfSriastradh 120903b705cfSriastradh if (!intel_glamor_create_textured_pixmap(pixmap)) 121003b705cfSriastradh goto fallback_glamor; 121103b705cfSriastradh } 121203b705cfSriastradh 121303b705cfSriastradh return pixmap; 121403b705cfSriastradh 121503b705cfSriastradhfallback_glamor: 121603b705cfSriastradh if (usage & INTEL_CREATE_PIXMAP_DRI2) { 121703b705cfSriastradh /* XXX need further work to handle the DRI2 failure case. 121803b705cfSriastradh * Glamor don't know how to handle a BO only pixmap. Put 121903b705cfSriastradh * a warning indicator here. 122003b705cfSriastradh */ 122103b705cfSriastradh xf86DrvMsg(scrn->scrnIndex, X_WARNING, 122203b705cfSriastradh "Failed to create textured DRI2 pixmap."); 122303b705cfSriastradh return pixmap; 122403b705cfSriastradh } 122503b705cfSriastradh /* Create textured pixmap failed means glamor failed to 122603b705cfSriastradh * create a texture from current BO for some reasons. We turn 122703b705cfSriastradh * to create a new glamor pixmap and clean up current one. 122803b705cfSriastradh * One thing need to be noted, this new pixmap doesn't 122903b705cfSriastradh * has a priv and bo attached to it. It's glamor's responsbility 123003b705cfSriastradh * to take care of it. Glamor will mark this new pixmap as a 123103b705cfSriastradh * texture only pixmap and will never fallback to DDX layer 123203b705cfSriastradh * afterwards. 123303b705cfSriastradh */ 123403b705cfSriastradh new_pixmap = intel_glamor_create_pixmap(screen, w, h, 123503b705cfSriastradh depth, usage); 123603b705cfSriastradh dri_bo_unreference(priv->bo); 123703b705cfSriastradhfallback_priv: 123803b705cfSriastradh free(priv); 123903b705cfSriastradhfallback_pixmap: 124003b705cfSriastradh fbDestroyPixmap(pixmap); 124103b705cfSriastradh if (new_pixmap) 124203b705cfSriastradh return new_pixmap; 124303b705cfSriastradh else 124403b705cfSriastradh return fbCreatePixmap(screen, w, h, depth, usage); 124503b705cfSriastradh} 124603b705cfSriastradh 124703b705cfSriastradhstatic Bool intel_uxa_destroy_pixmap(PixmapPtr pixmap) 124803b705cfSriastradh{ 124903b705cfSriastradh if (pixmap->refcnt == 1) { 125003b705cfSriastradh intel_glamor_destroy_pixmap(pixmap); 125103b705cfSriastradh intel_set_pixmap_bo(pixmap, NULL); 125203b705cfSriastradh } 125303b705cfSriastradh fbDestroyPixmap(pixmap); 125403b705cfSriastradh return TRUE; 125503b705cfSriastradh} 125603b705cfSriastradh 125703b705cfSriastradhBool intel_uxa_create_screen_resources(ScreenPtr screen) 125803b705cfSriastradh{ 125903b705cfSriastradh ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 126003b705cfSriastradh PixmapPtr pixmap; 126103b705cfSriastradh intel_screen_private *intel = intel_get_screen_private(scrn); 126203b705cfSriastradh dri_bo *bo = intel->front_buffer; 126342542f5fSchristos int old_width, old_height, old_pitch; 126403b705cfSriastradh 126503b705cfSriastradh if (!uxa_resources_init(screen)) 126603b705cfSriastradh return FALSE; 126703b705cfSriastradh 126803b705cfSriastradh if (drm_intel_gem_bo_map_gtt(bo)) 126903b705cfSriastradh return FALSE; 127003b705cfSriastradh 127103b705cfSriastradh pixmap = screen->GetScreenPixmap(screen); 127242542f5fSchristos old_width = pixmap->drawable.width; 127342542f5fSchristos old_height = pixmap->drawable.height; 127442542f5fSchristos old_pitch = pixmap->devKind; 127542542f5fSchristos 127642542f5fSchristos if (!screen->ModifyPixmapHeader(pixmap, 127742542f5fSchristos scrn->virtualX, 127842542f5fSchristos scrn->virtualY, 127942542f5fSchristos -1, -1, 128042542f5fSchristos intel->front_pitch, 128142542f5fSchristos NULL)) 128242542f5fSchristos return FALSE; 128342542f5fSchristos 128403b705cfSriastradh intel_set_pixmap_bo(pixmap, bo); 128542542f5fSchristos if (intel_get_pixmap_private(pixmap) == NULL) 128642542f5fSchristos goto err; 128703b705cfSriastradh 128803b705cfSriastradh if (!intel_glamor_create_screen_resources(screen)) 128942542f5fSchristos goto err; 129042542f5fSchristos 129142542f5fSchristos intel_get_pixmap_private(pixmap)->pinned |= PIN_SCANOUT; 129242542f5fSchristos scrn->displayWidth = intel->front_pitch / intel->cpp; 129303b705cfSriastradh 129403b705cfSriastradh return TRUE; 129542542f5fSchristos 129642542f5fSchristoserr: 129742542f5fSchristos screen->ModifyPixmapHeader(pixmap, 129842542f5fSchristos old_width, old_height, -1, -1, old_pitch, NULL); 129942542f5fSchristos return FALSE; 130003b705cfSriastradh} 130103b705cfSriastradh 130203b705cfSriastradh#ifdef CREATE_PIXMAP_USAGE_SHARED 130303b705cfSriastradhstatic Bool 130403b705cfSriastradhintel_uxa_share_pixmap_backing(PixmapPtr ppix, ScreenPtr slave, void **fd_handle) 130503b705cfSriastradh{ 130603b705cfSriastradh ScrnInfoPtr scrn = xf86ScreenToScrn(ppix->drawable.pScreen); 130703b705cfSriastradh intel_screen_private *intel = intel_get_screen_private(scrn); 130803b705cfSriastradh struct intel_pixmap *priv = intel_get_pixmap_private(ppix); 130903b705cfSriastradh unsigned int size, tiling, swizzle; 131003b705cfSriastradh dri_bo *bo = intel_get_pixmap_bo(ppix), *newbo; 131103b705cfSriastradh int stride; 131203b705cfSriastradh int handle; 131303b705cfSriastradh 131403b705cfSriastradh if (drm_intel_bo_references(intel->batch_bo, bo)) 131503b705cfSriastradh intel_batch_submit(intel->scrn); 131603b705cfSriastradh 131703b705cfSriastradh drm_intel_bo_get_tiling(bo, &tiling, &swizzle); 131803b705cfSriastradh 131903b705cfSriastradh if (tiling == I915_TILING_X) { 132042542f5fSchristos if (priv->pinned) 132103b705cfSriastradh return FALSE; 132203b705cfSriastradh 132303b705cfSriastradh tiling = I915_TILING_NONE; 132403b705cfSriastradh 132542542f5fSchristos size = intel_uxa_compute_size(intel, 132642542f5fSchristos ppix->drawable.width, ppix->drawable.height, 132742542f5fSchristos ppix->drawable.bitsPerPixel, INTEL_CREATE_PIXMAP_DRI2, 132842542f5fSchristos &tiling, &stride); 132903b705cfSriastradh 133003b705cfSriastradh newbo = drm_intel_bo_alloc_for_render(intel->bufmgr, 133103b705cfSriastradh "pixmap", 133203b705cfSriastradh size, 0); 133303b705cfSriastradh 133403b705cfSriastradh if (tiling != I915_TILING_NONE) 133503b705cfSriastradh drm_intel_bo_set_tiling(newbo, &tiling, stride); 133603b705cfSriastradh priv->stride = stride; 133703b705cfSriastradh priv->tiling = tiling; 133803b705cfSriastradh intel_set_pixmap_bo(ppix, newbo); 133903b705cfSriastradh 134003b705cfSriastradh ppix->drawable.pScreen->ModifyPixmapHeader(ppix, ppix->drawable.width, 134103b705cfSriastradh ppix->drawable.height, 0, 0, 134203b705cfSriastradh stride, NULL); 134303b705cfSriastradh bo = newbo; 134403b705cfSriastradh } 134503b705cfSriastradh drm_intel_bo_get_tiling(bo, &tiling, &swizzle); 134603b705cfSriastradh drm_intel_bo_gem_export_to_prime(bo, &handle); 134742542f5fSchristos priv->pinned |= PIN_PRIME; 134803b705cfSriastradh 134903b705cfSriastradh *fd_handle = (void *)(long)handle; 135003b705cfSriastradh return TRUE; 135103b705cfSriastradh} 135203b705cfSriastradh 135303b705cfSriastradhstatic Bool 135403b705cfSriastradhintel_uxa_set_shared_pixmap_backing(PixmapPtr ppix, void *fd_handle) 135503b705cfSriastradh{ 135603b705cfSriastradh ScrnInfoPtr scrn = xf86ScreenToScrn(ppix->drawable.pScreen); 135703b705cfSriastradh intel_screen_private *intel = intel_get_screen_private(scrn); 135803b705cfSriastradh dri_bo *bo; 135903b705cfSriastradh int ihandle = (int)(long)fd_handle; 136003b705cfSriastradh 136103b705cfSriastradh /* force untiled for now */ 136203b705cfSriastradh bo = drm_intel_bo_gem_create_from_prime(intel->bufmgr, ihandle, 0); 136303b705cfSriastradh if (!bo) 136403b705cfSriastradh return FALSE; 136503b705cfSriastradh 136603b705cfSriastradh intel_set_pixmap_bo(ppix, bo); 136703b705cfSriastradh close(ihandle); 136803b705cfSriastradh return TRUE; 136903b705cfSriastradh} 137003b705cfSriastradh#endif 137103b705cfSriastradh 137203b705cfSriastradhstatic void 137303b705cfSriastradhintel_limits_init(intel_screen_private *intel) 137403b705cfSriastradh{ 137503b705cfSriastradh /* Limits are described in the BLT engine chapter under Graphics Data Size 137603b705cfSriastradh * Limitations, and the descriptions of SURFACE_STATE, 3DSTATE_BUFFER_INFO, 137703b705cfSriastradh * 3DSTATE_DRAWING_RECTANGLE, 3DSTATE_MAP_INFO, and 3DSTATE_MAP_INFO. 137803b705cfSriastradh * 137903b705cfSriastradh * i845 through i965 limits 2D rendering to 65536 lines and pitch of 32768. 138003b705cfSriastradh * 138103b705cfSriastradh * i965 limits 3D surface to (2*element size)-aligned offset if un-tiled. 138203b705cfSriastradh * i965 limits 3D surface to 4kB-aligned offset if tiled. 138303b705cfSriastradh * i965 limits 3D surfaces to w,h of ?,8192. 138403b705cfSriastradh * i965 limits 3D surface to pitch of 1B - 128kB. 138503b705cfSriastradh * i965 limits 3D surface pitch alignment to 1 or 2 times the element size. 138603b705cfSriastradh * i965 limits 3D surface pitch alignment to 512B if tiled. 138703b705cfSriastradh * i965 limits 3D destination drawing rect to w,h of 8192,8192. 138803b705cfSriastradh * 138903b705cfSriastradh * i915 limits 3D textures to 4B-aligned offset if un-tiled. 139003b705cfSriastradh * i915 limits 3D textures to ~4kB-aligned offset if tiled. 139103b705cfSriastradh * i915 limits 3D textures to width,height of 2048,2048. 139203b705cfSriastradh * i915 limits 3D textures to pitch of 16B - 8kB, in dwords. 139303b705cfSriastradh * i915 limits 3D destination to ~4kB-aligned offset if tiled. 139403b705cfSriastradh * i915 limits 3D destination to pitch of 16B - 8kB, in dwords, if un-tiled. 139503b705cfSriastradh * i915 limits 3D destination to pitch 64B-aligned if used with depth. 139603b705cfSriastradh * i915 limits 3D destination to pitch of 512B - 8kB, in tiles, if tiled. 139703b705cfSriastradh * i915 limits 3D destination to POT aligned pitch if tiled. 139803b705cfSriastradh * i915 limits 3D destination drawing rect to w,h of 2048,2048. 139903b705cfSriastradh * 140003b705cfSriastradh * i845 limits 3D textures to 4B-aligned offset if un-tiled. 140103b705cfSriastradh * i845 limits 3D textures to ~4kB-aligned offset if tiled. 140203b705cfSriastradh * i845 limits 3D textures to width,height of 2048,2048. 140303b705cfSriastradh * i845 limits 3D textures to pitch of 4B - 8kB, in dwords. 140403b705cfSriastradh * i845 limits 3D destination to 4B-aligned offset if un-tiled. 140503b705cfSriastradh * i845 limits 3D destination to ~4kB-aligned offset if tiled. 140603b705cfSriastradh * i845 limits 3D destination to pitch of 8B - 8kB, in dwords. 140703b705cfSriastradh * i845 limits 3D destination drawing rect to w,h of 2048,2048. 140803b705cfSriastradh * 140903b705cfSriastradh * For the tiled issues, the only tiled buffer we draw to should be 141003b705cfSriastradh * the front, which will have an appropriate pitch/offset already set up, 141103b705cfSriastradh * so UXA doesn't need to worry. 141203b705cfSriastradh */ 141303b705cfSriastradh if (INTEL_INFO(intel)->gen >= 040) { 141403b705cfSriastradh intel->accel_pixmap_offset_alignment = 4 * 2; 141503b705cfSriastradh intel->accel_max_x = 8192; 141603b705cfSriastradh intel->accel_max_y = 8192; 141703b705cfSriastradh } else { 141803b705cfSriastradh intel->accel_pixmap_offset_alignment = 4; 141903b705cfSriastradh intel->accel_max_x = 2048; 142003b705cfSriastradh intel->accel_max_y = 2048; 142103b705cfSriastradh } 142203b705cfSriastradh} 142303b705cfSriastradh 142442542f5fSchristosstatic Bool intel_option_accel_none(intel_screen_private *intel) 142542542f5fSchristos{ 142642542f5fSchristos const char *s; 142742542f5fSchristos 142842542f5fSchristos s = xf86GetOptValString(intel->Options, OPTION_ACCEL_METHOD); 142942542f5fSchristos if (s == NULL) 143042542f5fSchristos return IS_DEFAULT_ACCEL_METHOD(NOACCEL); 143142542f5fSchristos 143242542f5fSchristos return strcasecmp(s, "none") == 0; 143342542f5fSchristos} 143442542f5fSchristos 143503b705cfSriastradhstatic Bool intel_option_accel_blt(intel_screen_private *intel) 143603b705cfSriastradh{ 143703b705cfSriastradh const char *s; 143803b705cfSriastradh 143903b705cfSriastradh s = xf86GetOptValString(intel->Options, OPTION_ACCEL_METHOD); 144003b705cfSriastradh if (s == NULL) 144103b705cfSriastradh return FALSE; 144203b705cfSriastradh 144303b705cfSriastradh return strcasecmp(s, "blt") == 0; 144403b705cfSriastradh} 144503b705cfSriastradh 144603b705cfSriastradhBool intel_uxa_init(ScreenPtr screen) 144703b705cfSriastradh{ 144803b705cfSriastradh ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 144903b705cfSriastradh intel_screen_private *intel = intel_get_screen_private(scrn); 145003b705cfSriastradh 145103b705cfSriastradh#if HAS_DIXREGISTERPRIVATEKEY 145203b705cfSriastradh if (!dixRegisterPrivateKey(&uxa_pixmap_index, PRIVATE_PIXMAP, 0)) 145303b705cfSriastradh#else 145403b705cfSriastradh if (!dixRequestPrivate(&uxa_pixmap_index, 0)) 145503b705cfSriastradh#endif 145603b705cfSriastradh return FALSE; 145703b705cfSriastradh 145803b705cfSriastradh intel_limits_init(intel); 145903b705cfSriastradh 146003b705cfSriastradh intel->uxa_driver = uxa_driver_alloc(); 146103b705cfSriastradh if (intel->uxa_driver == NULL) 146203b705cfSriastradh return FALSE; 146303b705cfSriastradh 146403b705cfSriastradh memset(intel->uxa_driver, 0, sizeof(*intel->uxa_driver)); 146503b705cfSriastradh 146603b705cfSriastradh intel->uxa_driver->uxa_major = 1; 146703b705cfSriastradh intel->uxa_driver->uxa_minor = 0; 146803b705cfSriastradh 146903b705cfSriastradh intel->prim_offset = 0; 147003b705cfSriastradh intel->vertex_count = 0; 147103b705cfSriastradh intel->vertex_offset = 0; 147203b705cfSriastradh intel->vertex_used = 0; 147303b705cfSriastradh intel->floats_per_vertex = 0; 147403b705cfSriastradh intel->last_floats_per_vertex = 0; 147503b705cfSriastradh intel->vertex_bo = NULL; 147603b705cfSriastradh intel->surface_used = 0; 147703b705cfSriastradh intel->surface_reloc = 0; 147803b705cfSriastradh 147903b705cfSriastradh /* Solid fill */ 148003b705cfSriastradh intel->uxa_driver->check_solid = intel_uxa_check_solid; 148103b705cfSriastradh intel->uxa_driver->prepare_solid = intel_uxa_prepare_solid; 148203b705cfSriastradh intel->uxa_driver->solid = intel_uxa_solid; 148303b705cfSriastradh intel->uxa_driver->done_solid = intel_uxa_done; 148403b705cfSriastradh 148503b705cfSriastradh /* Copy */ 148603b705cfSriastradh intel->uxa_driver->check_copy = intel_uxa_check_copy; 148703b705cfSriastradh intel->uxa_driver->prepare_copy = intel_uxa_prepare_copy; 148803b705cfSriastradh intel->uxa_driver->copy = intel_uxa_copy; 148903b705cfSriastradh intel->uxa_driver->done_copy = intel_uxa_done; 149003b705cfSriastradh 149103b705cfSriastradh /* Composite */ 149203b705cfSriastradh if (intel_option_accel_blt(intel)) { 149342542f5fSchristos } else if (INTEL_INFO(intel)->gen < 030) { 149403b705cfSriastradh intel->uxa_driver->check_composite = i830_check_composite; 149503b705cfSriastradh intel->uxa_driver->check_composite_target = i830_check_composite_target; 149603b705cfSriastradh intel->uxa_driver->check_composite_texture = i830_check_composite_texture; 149703b705cfSriastradh intel->uxa_driver->prepare_composite = i830_prepare_composite; 149803b705cfSriastradh intel->uxa_driver->composite = i830_composite; 149903b705cfSriastradh intel->uxa_driver->done_composite = i830_done_composite; 150003b705cfSriastradh 150103b705cfSriastradh intel->vertex_flush = i830_vertex_flush; 150203b705cfSriastradh intel->batch_commit_notify = i830_batch_commit_notify; 150342542f5fSchristos } else if (INTEL_INFO(intel)->gen < 040) { 150403b705cfSriastradh intel->uxa_driver->check_composite = i915_check_composite; 150503b705cfSriastradh intel->uxa_driver->check_composite_target = i915_check_composite_target; 150603b705cfSriastradh intel->uxa_driver->check_composite_texture = i915_check_composite_texture; 150703b705cfSriastradh intel->uxa_driver->prepare_composite = i915_prepare_composite; 150803b705cfSriastradh intel->uxa_driver->composite = i915_composite; 150903b705cfSriastradh intel->uxa_driver->done_composite = i830_done_composite; 151003b705cfSriastradh 151103b705cfSriastradh intel->vertex_flush = i915_vertex_flush; 151203b705cfSriastradh intel->batch_commit_notify = i915_batch_commit_notify; 151342542f5fSchristos } else if (INTEL_INFO(intel)->gen < 0100) { 151403b705cfSriastradh intel->uxa_driver->check_composite = i965_check_composite; 151503b705cfSriastradh intel->uxa_driver->check_composite_texture = i965_check_composite_texture; 151603b705cfSriastradh intel->uxa_driver->prepare_composite = i965_prepare_composite; 151703b705cfSriastradh intel->uxa_driver->composite = i965_composite; 151803b705cfSriastradh intel->uxa_driver->done_composite = i830_done_composite; 151903b705cfSriastradh 152003b705cfSriastradh intel->vertex_flush = i965_vertex_flush; 152103b705cfSriastradh intel->batch_flush = i965_batch_flush; 152203b705cfSriastradh intel->batch_commit_notify = i965_batch_commit_notify; 152303b705cfSriastradh 152442542f5fSchristos if (INTEL_INFO(intel)->gen < 050) { 152503b705cfSriastradh intel->context_switch = gen4_context_switch; 152642542f5fSchristos } else if (INTEL_INFO(intel)->gen < 060) { 152703b705cfSriastradh intel->context_switch = gen5_context_switch; 152803b705cfSriastradh } else { 152903b705cfSriastradh intel->context_switch = gen6_context_switch; 153003b705cfSriastradh } 153103b705cfSriastradh } 153203b705cfSriastradh 153303b705cfSriastradh /* PutImage */ 153403b705cfSriastradh intel->uxa_driver->put_image = intel_uxa_put_image; 153503b705cfSriastradh intel->uxa_driver->get_image = intel_uxa_get_image; 153603b705cfSriastradh 153703b705cfSriastradh intel->uxa_driver->prepare_access = intel_uxa_prepare_access; 153803b705cfSriastradh intel->uxa_driver->finish_access = intel_uxa_finish_access; 153903b705cfSriastradh intel->uxa_driver->pixmap_is_offscreen = intel_uxa_pixmap_is_offscreen; 154003b705cfSriastradh 154103b705cfSriastradh screen->CreatePixmap = intel_uxa_create_pixmap; 154203b705cfSriastradh screen->DestroyPixmap = intel_uxa_destroy_pixmap; 154303b705cfSriastradh 154403b705cfSriastradh#ifdef CREATE_PIXMAP_USAGE_SHARED 154503b705cfSriastradh screen->SharePixmapBacking = intel_uxa_share_pixmap_backing; 154603b705cfSriastradh screen->SetSharedPixmapBacking = intel_uxa_set_shared_pixmap_backing; 154703b705cfSriastradh#endif 154803b705cfSriastradh 154903b705cfSriastradh if (!uxa_driver_init(screen, intel->uxa_driver)) { 155003b705cfSriastradh xf86DrvMsg(scrn->scrnIndex, X_ERROR, 155103b705cfSriastradh "UXA initialization failed\n"); 155203b705cfSriastradh free(intel->uxa_driver); 155303b705cfSriastradh return FALSE; 155403b705cfSriastradh } 155503b705cfSriastradh 155642542f5fSchristos if (intel_option_accel_none(intel)) 155742542f5fSchristos intel->force_fallback = 1; 155842542f5fSchristos 155903b705cfSriastradh uxa_set_fallback_debug(screen, intel->fallback_debug); 156003b705cfSriastradh uxa_set_force_fallback(screen, intel->force_fallback); 156103b705cfSriastradh 156242542f5fSchristos intel->flush_rendering = intel_flush_rendering; 156303b705cfSriastradh return TRUE; 156403b705cfSriastradh} 1565