intel_uxa.c revision 03b705cf
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 3403b705cfSriastradh#include <xf86.h> 3503b705cfSriastradh#include <xf86drm.h> 3603b705cfSriastradh#include <xaarop.h> 3703b705cfSriastradh#include <string.h> 3803b705cfSriastradh#include <errno.h> 3903b705cfSriastradh#include <unistd.h> 4003b705cfSriastradh 4103b705cfSriastradh#include "intel.h" 4203b705cfSriastradh#include "intel_glamor.h" 4303b705cfSriastradh#include "uxa.h" 4403b705cfSriastradh 4503b705cfSriastradh#include "i830_reg.h" 4603b705cfSriastradh#include "i915_drm.h" 4703b705cfSriastradh#include "brw_defines.h" 4803b705cfSriastradh 4903b705cfSriastradhstatic const int I830CopyROP[16] = { 5003b705cfSriastradh ROP_0, /* GXclear */ 5103b705cfSriastradh ROP_DSa, /* GXand */ 5203b705cfSriastradh ROP_SDna, /* GXandReverse */ 5303b705cfSriastradh ROP_S, /* GXcopy */ 5403b705cfSriastradh ROP_DSna, /* GXandInverted */ 5503b705cfSriastradh ROP_D, /* GXnoop */ 5603b705cfSriastradh ROP_DSx, /* GXxor */ 5703b705cfSriastradh ROP_DSo, /* GXor */ 5803b705cfSriastradh ROP_DSon, /* GXnor */ 5903b705cfSriastradh ROP_DSxn, /* GXequiv */ 6003b705cfSriastradh ROP_Dn, /* GXinvert */ 6103b705cfSriastradh ROP_SDno, /* GXorReverse */ 6203b705cfSriastradh ROP_Sn, /* GXcopyInverted */ 6303b705cfSriastradh ROP_DSno, /* GXorInverted */ 6403b705cfSriastradh ROP_DSan, /* GXnand */ 6503b705cfSriastradh ROP_1 /* GXset */ 6603b705cfSriastradh}; 6703b705cfSriastradh 6803b705cfSriastradhstatic const int I830PatternROP[16] = { 6903b705cfSriastradh ROP_0, 7003b705cfSriastradh ROP_DPa, 7103b705cfSriastradh ROP_PDna, 7203b705cfSriastradh ROP_P, 7303b705cfSriastradh ROP_DPna, 7403b705cfSriastradh ROP_D, 7503b705cfSriastradh ROP_DPx, 7603b705cfSriastradh ROP_DPo, 7703b705cfSriastradh ROP_DPon, 7803b705cfSriastradh ROP_PDxn, 7903b705cfSriastradh ROP_Dn, 8003b705cfSriastradh ROP_PDno, 8103b705cfSriastradh ROP_Pn, 8203b705cfSriastradh ROP_DPno, 8303b705cfSriastradh ROP_DPan, 8403b705cfSriastradh ROP_1 8503b705cfSriastradh}; 8603b705cfSriastradh 8703b705cfSriastradh#if HAS_DEVPRIVATEKEYREC 8803b705cfSriastradhDevPrivateKeyRec uxa_pixmap_index; 8903b705cfSriastradh#else 9003b705cfSriastradhint uxa_pixmap_index; 9103b705cfSriastradh#endif 9203b705cfSriastradh 9303b705cfSriastradhstatic void 9403b705cfSriastradhgen6_context_switch(intel_screen_private *intel, 9503b705cfSriastradh int new_mode) 9603b705cfSriastradh{ 9703b705cfSriastradh intel_batch_submit(intel->scrn); 9803b705cfSriastradh} 9903b705cfSriastradh 10003b705cfSriastradhstatic void 10103b705cfSriastradhgen5_context_switch(intel_screen_private *intel, 10203b705cfSriastradh int new_mode) 10303b705cfSriastradh{ 10403b705cfSriastradh /* Ironlake has a limitation that a 3D or Media command can't 10503b705cfSriastradh * be the first command after a BLT, unless it's 10603b705cfSriastradh * non-pipelined. Instead of trying to track it and emit a 10703b705cfSriastradh * command at the right time, we just emit a dummy 10803b705cfSriastradh * non-pipelined 3D instruction after each blit. 10903b705cfSriastradh */ 11003b705cfSriastradh 11103b705cfSriastradh if (new_mode == I915_EXEC_BLT) { 11203b705cfSriastradh OUT_BATCH(MI_FLUSH | 11303b705cfSriastradh MI_STATE_INSTRUCTION_CACHE_FLUSH | 11403b705cfSriastradh MI_INHIBIT_RENDER_CACHE_FLUSH); 11503b705cfSriastradh } else { 11603b705cfSriastradh OUT_BATCH(CMD_POLY_STIPPLE_OFFSET << 16); 11703b705cfSriastradh OUT_BATCH(0); 11803b705cfSriastradh } 11903b705cfSriastradh} 12003b705cfSriastradh 12103b705cfSriastradhstatic void 12203b705cfSriastradhgen4_context_switch(intel_screen_private *intel, 12303b705cfSriastradh int new_mode) 12403b705cfSriastradh{ 12503b705cfSriastradh if (new_mode == I915_EXEC_BLT) { 12603b705cfSriastradh OUT_BATCH(MI_FLUSH | 12703b705cfSriastradh MI_STATE_INSTRUCTION_CACHE_FLUSH | 12803b705cfSriastradh MI_INHIBIT_RENDER_CACHE_FLUSH); 12903b705cfSriastradh } 13003b705cfSriastradh} 13103b705cfSriastradh 13203b705cfSriastradhBool 13303b705cfSriastradhintel_get_aperture_space(ScrnInfoPtr scrn, drm_intel_bo ** bo_table, 13403b705cfSriastradh int num_bos) 13503b705cfSriastradh{ 13603b705cfSriastradh intel_screen_private *intel = intel_get_screen_private(scrn); 13703b705cfSriastradh 13803b705cfSriastradh if (intel->batch_bo == NULL) { 13903b705cfSriastradh intel_debug_fallback(scrn, "VT inactive\n"); 14003b705cfSriastradh return FALSE; 14103b705cfSriastradh } 14203b705cfSriastradh 14303b705cfSriastradh bo_table[0] = intel->batch_bo; 14403b705cfSriastradh if (drm_intel_bufmgr_check_aperture_space(bo_table, num_bos) != 0) { 14503b705cfSriastradh intel_batch_submit(scrn); 14603b705cfSriastradh bo_table[0] = intel->batch_bo; 14703b705cfSriastradh if (drm_intel_bufmgr_check_aperture_space(bo_table, num_bos) != 14803b705cfSriastradh 0) { 14903b705cfSriastradh intel_debug_fallback(scrn, "Couldn't get aperture " 15003b705cfSriastradh "space for BOs\n"); 15103b705cfSriastradh return FALSE; 15203b705cfSriastradh } 15303b705cfSriastradh } 15403b705cfSriastradh return TRUE; 15503b705cfSriastradh} 15603b705cfSriastradh 15703b705cfSriastradhstatic unsigned int 15803b705cfSriastradhintel_uxa_pixmap_compute_size(PixmapPtr pixmap, 15903b705cfSriastradh int w, int h, 16003b705cfSriastradh uint32_t *tiling, 16103b705cfSriastradh int *stride, 16203b705cfSriastradh unsigned usage) 16303b705cfSriastradh{ 16403b705cfSriastradh ScrnInfoPtr scrn = xf86ScreenToScrn(pixmap->drawable.pScreen); 16503b705cfSriastradh intel_screen_private *intel = intel_get_screen_private(scrn); 16603b705cfSriastradh int pitch, size; 16703b705cfSriastradh 16803b705cfSriastradh if (*tiling != I915_TILING_NONE) { 16903b705cfSriastradh /* First check whether tiling is necessary. */ 17003b705cfSriastradh pitch = (w * pixmap->drawable.bitsPerPixel + 7) / 8; 17103b705cfSriastradh pitch = ALIGN(pitch, 64); 17203b705cfSriastradh size = pitch * ALIGN (h, 2); 17303b705cfSriastradh if (INTEL_INFO(intel)->gen < 040) { 17403b705cfSriastradh /* Gen 2/3 has a maximum stride for tiling of 17503b705cfSriastradh * 8192 bytes. 17603b705cfSriastradh */ 17703b705cfSriastradh if (pitch > KB(8)) 17803b705cfSriastradh *tiling = I915_TILING_NONE; 17903b705cfSriastradh 18003b705cfSriastradh /* Narrower than half a tile? */ 18103b705cfSriastradh if (pitch < 256) 18203b705cfSriastradh *tiling = I915_TILING_NONE; 18303b705cfSriastradh 18403b705cfSriastradh /* Older hardware requires fences to be pot size 18503b705cfSriastradh * aligned with a minimum of 1 MiB, so causes 18603b705cfSriastradh * massive overallocation for small textures. 18703b705cfSriastradh */ 18803b705cfSriastradh if (size < 1024*1024/2 && !intel->has_relaxed_fencing) 18903b705cfSriastradh *tiling = I915_TILING_NONE; 19003b705cfSriastradh } else if (!(usage & INTEL_CREATE_PIXMAP_DRI2) && size <= 4096) { 19103b705cfSriastradh /* Disable tiling beneath a page size, we will not see 19203b705cfSriastradh * any benefit from reducing TLB misses and instead 19303b705cfSriastradh * just incur extra cost when we require a fence. 19403b705cfSriastradh */ 19503b705cfSriastradh *tiling = I915_TILING_NONE; 19603b705cfSriastradh } 19703b705cfSriastradh } 19803b705cfSriastradh 19903b705cfSriastradh pitch = (w * pixmap->drawable.bitsPerPixel + 7) / 8; 20003b705cfSriastradh if (!(usage & INTEL_CREATE_PIXMAP_DRI2) && pitch <= 256) 20103b705cfSriastradh *tiling = I915_TILING_NONE; 20203b705cfSriastradh 20303b705cfSriastradh if (*tiling != I915_TILING_NONE) { 20403b705cfSriastradh int aligned_h, tile_height; 20503b705cfSriastradh 20603b705cfSriastradh if (IS_GEN2(intel)) 20703b705cfSriastradh tile_height = 16; 20803b705cfSriastradh else if (*tiling == I915_TILING_X) 20903b705cfSriastradh tile_height = 8; 21003b705cfSriastradh else 21103b705cfSriastradh tile_height = 32; 21203b705cfSriastradh aligned_h = ALIGN(h, 2*tile_height); 21303b705cfSriastradh 21403b705cfSriastradh *stride = intel_get_fence_pitch(intel, 21503b705cfSriastradh ALIGN(pitch, 512), 21603b705cfSriastradh *tiling); 21703b705cfSriastradh 21803b705cfSriastradh /* Round the object up to the size of the fence it will live in 21903b705cfSriastradh * if necessary. We could potentially make the kernel allocate 22003b705cfSriastradh * a larger aperture space and just bind the subset of pages in, 22103b705cfSriastradh * but this is easier and also keeps us out of trouble (as much) 22203b705cfSriastradh * with drm_intel_bufmgr_check_aperture(). 22303b705cfSriastradh */ 22403b705cfSriastradh size = intel_get_fence_size(intel, *stride * aligned_h); 22503b705cfSriastradh 22603b705cfSriastradh if (size > intel->max_tiling_size) 22703b705cfSriastradh *tiling = I915_TILING_NONE; 22803b705cfSriastradh } 22903b705cfSriastradh 23003b705cfSriastradh if (*tiling == I915_TILING_NONE) { 23103b705cfSriastradh /* We only require a 64 byte alignment for scanouts, but 23203b705cfSriastradh * a 256 byte alignment for sharing with PRIME. 23303b705cfSriastradh */ 23403b705cfSriastradh *stride = ALIGN(pitch, 256); 23503b705cfSriastradh /* Round the height up so that the GPU's access to a 2x2 aligned 23603b705cfSriastradh * subspan doesn't address an invalid page offset beyond the 23703b705cfSriastradh * end of the GTT. 23803b705cfSriastradh */ 23903b705cfSriastradh size = *stride * ALIGN(h, 2); 24003b705cfSriastradh } 24103b705cfSriastradh 24203b705cfSriastradh return size; 24303b705cfSriastradh} 24403b705cfSriastradh 24503b705cfSriastradhstatic Bool 24603b705cfSriastradhintel_uxa_check_solid(DrawablePtr drawable, int alu, Pixel planemask) 24703b705cfSriastradh{ 24803b705cfSriastradh ScrnInfoPtr scrn = xf86ScreenToScrn(drawable->pScreen); 24903b705cfSriastradh 25003b705cfSriastradh if (!UXA_PM_IS_SOLID(drawable, planemask)) { 25103b705cfSriastradh intel_debug_fallback(scrn, "planemask is not solid\n"); 25203b705cfSriastradh return FALSE; 25303b705cfSriastradh } 25403b705cfSriastradh 25503b705cfSriastradh switch (drawable->bitsPerPixel) { 25603b705cfSriastradh case 8: 25703b705cfSriastradh case 16: 25803b705cfSriastradh case 32: 25903b705cfSriastradh break; 26003b705cfSriastradh default: 26103b705cfSriastradh return FALSE; 26203b705cfSriastradh } 26303b705cfSriastradh 26403b705cfSriastradh return TRUE; 26503b705cfSriastradh} 26603b705cfSriastradh 26703b705cfSriastradh/** 26803b705cfSriastradh * Sets up hardware state for a series of solid fills. 26903b705cfSriastradh */ 27003b705cfSriastradhstatic Bool 27103b705cfSriastradhintel_uxa_prepare_solid(PixmapPtr pixmap, int alu, Pixel planemask, Pixel fg) 27203b705cfSriastradh{ 27303b705cfSriastradh ScrnInfoPtr scrn = xf86ScreenToScrn(pixmap->drawable.pScreen); 27403b705cfSriastradh intel_screen_private *intel = intel_get_screen_private(scrn); 27503b705cfSriastradh drm_intel_bo *bo_table[] = { 27603b705cfSriastradh NULL, /* batch_bo */ 27703b705cfSriastradh intel_get_pixmap_bo(pixmap), 27803b705cfSriastradh }; 27903b705cfSriastradh 28003b705cfSriastradh if (!intel_check_pitch_2d(pixmap)) 28103b705cfSriastradh return FALSE; 28203b705cfSriastradh 28303b705cfSriastradh if (!intel_get_aperture_space(scrn, bo_table, ARRAY_SIZE(bo_table))) 28403b705cfSriastradh return FALSE; 28503b705cfSriastradh 28603b705cfSriastradh intel->BR[13] = (I830PatternROP[alu] & 0xff) << 16; 28703b705cfSriastradh switch (pixmap->drawable.bitsPerPixel) { 28803b705cfSriastradh case 8: 28903b705cfSriastradh break; 29003b705cfSriastradh case 16: 29103b705cfSriastradh /* RGB565 */ 29203b705cfSriastradh intel->BR[13] |= (1 << 24); 29303b705cfSriastradh break; 29403b705cfSriastradh case 32: 29503b705cfSriastradh /* RGB8888 */ 29603b705cfSriastradh intel->BR[13] |= ((1 << 24) | (1 << 25)); 29703b705cfSriastradh break; 29803b705cfSriastradh } 29903b705cfSriastradh intel->BR[16] = fg; 30003b705cfSriastradh 30103b705cfSriastradh return TRUE; 30203b705cfSriastradh} 30303b705cfSriastradh 30403b705cfSriastradhstatic void intel_uxa_solid(PixmapPtr pixmap, int x1, int y1, int x2, int y2) 30503b705cfSriastradh{ 30603b705cfSriastradh ScrnInfoPtr scrn = xf86ScreenToScrn(pixmap->drawable.pScreen); 30703b705cfSriastradh intel_screen_private *intel = intel_get_screen_private(scrn); 30803b705cfSriastradh unsigned long pitch; 30903b705cfSriastradh uint32_t cmd; 31003b705cfSriastradh 31103b705cfSriastradh if (x1 < 0) 31203b705cfSriastradh x1 = 0; 31303b705cfSriastradh if (y1 < 0) 31403b705cfSriastradh y1 = 0; 31503b705cfSriastradh if (x2 > pixmap->drawable.width) 31603b705cfSriastradh x2 = pixmap->drawable.width; 31703b705cfSriastradh if (y2 > pixmap->drawable.height) 31803b705cfSriastradh y2 = pixmap->drawable.height; 31903b705cfSriastradh 32003b705cfSriastradh if (x2 <= x1 || y2 <= y1) 32103b705cfSriastradh return; 32203b705cfSriastradh 32303b705cfSriastradh pitch = intel_pixmap_pitch(pixmap); 32403b705cfSriastradh 32503b705cfSriastradh { 32603b705cfSriastradh BEGIN_BATCH_BLT(6); 32703b705cfSriastradh 32803b705cfSriastradh cmd = XY_COLOR_BLT_CMD; 32903b705cfSriastradh 33003b705cfSriastradh if (pixmap->drawable.bitsPerPixel == 32) 33103b705cfSriastradh cmd |= 33203b705cfSriastradh XY_COLOR_BLT_WRITE_ALPHA | XY_COLOR_BLT_WRITE_RGB; 33303b705cfSriastradh 33403b705cfSriastradh if (INTEL_INFO(intel)->gen >= 040 && intel_pixmap_tiled(pixmap)) { 33503b705cfSriastradh assert((pitch % 512) == 0); 33603b705cfSriastradh pitch >>= 2; 33703b705cfSriastradh cmd |= XY_COLOR_BLT_TILED; 33803b705cfSriastradh } 33903b705cfSriastradh 34003b705cfSriastradh OUT_BATCH(cmd); 34103b705cfSriastradh 34203b705cfSriastradh OUT_BATCH(intel->BR[13] | pitch); 34303b705cfSriastradh OUT_BATCH((y1 << 16) | (x1 & 0xffff)); 34403b705cfSriastradh OUT_BATCH((y2 << 16) | (x2 & 0xffff)); 34503b705cfSriastradh OUT_RELOC_PIXMAP_FENCED(pixmap, I915_GEM_DOMAIN_RENDER, 34603b705cfSriastradh I915_GEM_DOMAIN_RENDER, 0); 34703b705cfSriastradh OUT_BATCH(intel->BR[16]); 34803b705cfSriastradh ADVANCE_BATCH(); 34903b705cfSriastradh } 35003b705cfSriastradh} 35103b705cfSriastradh 35203b705cfSriastradh/** 35303b705cfSriastradh * TODO: 35403b705cfSriastradh * - support planemask using FULL_BLT_CMD? 35503b705cfSriastradh */ 35603b705cfSriastradhstatic Bool 35703b705cfSriastradhintel_uxa_check_copy(PixmapPtr source, PixmapPtr dest, 35803b705cfSriastradh int alu, Pixel planemask) 35903b705cfSriastradh{ 36003b705cfSriastradh ScrnInfoPtr scrn = xf86ScreenToScrn(dest->drawable.pScreen); 36103b705cfSriastradh 36203b705cfSriastradh if (!UXA_PM_IS_SOLID(&source->drawable, planemask)) { 36303b705cfSriastradh intel_debug_fallback(scrn, "planemask is not solid"); 36403b705cfSriastradh return FALSE; 36503b705cfSriastradh } 36603b705cfSriastradh 36703b705cfSriastradh if (source->drawable.bitsPerPixel != dest->drawable.bitsPerPixel) { 36803b705cfSriastradh intel_debug_fallback(scrn, "mixed bpp copies unsupported\n"); 36903b705cfSriastradh return FALSE; 37003b705cfSriastradh } 37103b705cfSriastradh switch (source->drawable.bitsPerPixel) { 37203b705cfSriastradh case 8: 37303b705cfSriastradh case 16: 37403b705cfSriastradh case 32: 37503b705cfSriastradh break; 37603b705cfSriastradh default: 37703b705cfSriastradh return FALSE; 37803b705cfSriastradh } 37903b705cfSriastradh 38003b705cfSriastradh if (!intel_check_pitch_2d(source)) 38103b705cfSriastradh return FALSE; 38203b705cfSriastradh if (!intel_check_pitch_2d(dest)) 38303b705cfSriastradh return FALSE; 38403b705cfSriastradh 38503b705cfSriastradh return TRUE; 38603b705cfSriastradh} 38703b705cfSriastradh 38803b705cfSriastradhstatic Bool 38903b705cfSriastradhintel_uxa_prepare_copy(PixmapPtr source, PixmapPtr dest, int xdir, 39003b705cfSriastradh int ydir, int alu, Pixel planemask) 39103b705cfSriastradh{ 39203b705cfSriastradh ScrnInfoPtr scrn = xf86ScreenToScrn(dest->drawable.pScreen); 39303b705cfSriastradh intel_screen_private *intel = intel_get_screen_private(scrn); 39403b705cfSriastradh drm_intel_bo *bo_table[] = { 39503b705cfSriastradh NULL, /* batch_bo */ 39603b705cfSriastradh intel_get_pixmap_bo(source), 39703b705cfSriastradh intel_get_pixmap_bo(dest), 39803b705cfSriastradh }; 39903b705cfSriastradh 40003b705cfSriastradh if (!intel_get_aperture_space(scrn, bo_table, ARRAY_SIZE(bo_table))) 40103b705cfSriastradh return FALSE; 40203b705cfSriastradh 40303b705cfSriastradh intel->render_source = source; 40403b705cfSriastradh 40503b705cfSriastradh intel->BR[13] = I830CopyROP[alu] << 16; 40603b705cfSriastradh switch (source->drawable.bitsPerPixel) { 40703b705cfSriastradh case 8: 40803b705cfSriastradh break; 40903b705cfSriastradh case 16: 41003b705cfSriastradh intel->BR[13] |= (1 << 24); 41103b705cfSriastradh break; 41203b705cfSriastradh case 32: 41303b705cfSriastradh intel->BR[13] |= ((1 << 25) | (1 << 24)); 41403b705cfSriastradh break; 41503b705cfSriastradh } 41603b705cfSriastradh 41703b705cfSriastradh return TRUE; 41803b705cfSriastradh} 41903b705cfSriastradh 42003b705cfSriastradhstatic void 42103b705cfSriastradhintel_uxa_copy(PixmapPtr dest, int src_x1, int src_y1, int dst_x1, 42203b705cfSriastradh int dst_y1, int w, int h) 42303b705cfSriastradh{ 42403b705cfSriastradh ScrnInfoPtr scrn = xf86ScreenToScrn(dest->drawable.pScreen); 42503b705cfSriastradh intel_screen_private *intel = intel_get_screen_private(scrn); 42603b705cfSriastradh uint32_t cmd; 42703b705cfSriastradh int dst_x2, dst_y2, src_x2, src_y2; 42803b705cfSriastradh unsigned int dst_pitch, src_pitch; 42903b705cfSriastradh 43003b705cfSriastradh dst_x2 = dst_x1 + w; 43103b705cfSriastradh dst_y2 = dst_y1 + h; 43203b705cfSriastradh 43303b705cfSriastradh /* XXX Fixup extents as a lamentable workaround for missing 43403b705cfSriastradh * source clipping in the upper layers. 43503b705cfSriastradh */ 43603b705cfSriastradh if (dst_x1 < 0) 43703b705cfSriastradh src_x1 -= dst_x1, dst_x1 = 0; 43803b705cfSriastradh if (dst_y1 < 0) 43903b705cfSriastradh src_y1 -= dst_y1, dst_y1 = 0; 44003b705cfSriastradh if (dst_x2 > dest->drawable.width) 44103b705cfSriastradh dst_x2 = dest->drawable.width; 44203b705cfSriastradh if (dst_y2 > dest->drawable.height) 44303b705cfSriastradh dst_y2 = dest->drawable.height; 44403b705cfSriastradh 44503b705cfSriastradh src_x2 = src_x1 + (dst_x2 - dst_x1); 44603b705cfSriastradh src_y2 = src_y1 + (dst_y2 - dst_y1); 44703b705cfSriastradh 44803b705cfSriastradh if (src_x1 < 0) 44903b705cfSriastradh dst_x1 -= src_x1, src_x1 = 0; 45003b705cfSriastradh if (src_y1 < 0) 45103b705cfSriastradh dst_y1 -= src_y1, src_y1 = 0; 45203b705cfSriastradh if (src_x2 > intel->render_source->drawable.width) 45303b705cfSriastradh dst_x2 -= src_x2 - intel->render_source->drawable.width; 45403b705cfSriastradh if (src_y2 > intel->render_source->drawable.height) 45503b705cfSriastradh dst_y2 -= src_y2 - intel->render_source->drawable.height; 45603b705cfSriastradh 45703b705cfSriastradh if (dst_x2 <= dst_x1 || dst_y2 <= dst_y1) 45803b705cfSriastradh return; 45903b705cfSriastradh 46003b705cfSriastradh dst_pitch = intel_pixmap_pitch(dest); 46103b705cfSriastradh src_pitch = intel_pixmap_pitch(intel->render_source); 46203b705cfSriastradh 46303b705cfSriastradh { 46403b705cfSriastradh BEGIN_BATCH_BLT(8); 46503b705cfSriastradh 46603b705cfSriastradh cmd = XY_SRC_COPY_BLT_CMD; 46703b705cfSriastradh 46803b705cfSriastradh if (dest->drawable.bitsPerPixel == 32) 46903b705cfSriastradh cmd |= 47003b705cfSriastradh XY_SRC_COPY_BLT_WRITE_ALPHA | 47103b705cfSriastradh XY_SRC_COPY_BLT_WRITE_RGB; 47203b705cfSriastradh 47303b705cfSriastradh if (INTEL_INFO(intel)->gen >= 040) { 47403b705cfSriastradh if (intel_pixmap_tiled(dest)) { 47503b705cfSriastradh assert((dst_pitch % 512) == 0); 47603b705cfSriastradh dst_pitch >>= 2; 47703b705cfSriastradh cmd |= XY_SRC_COPY_BLT_DST_TILED; 47803b705cfSriastradh } 47903b705cfSriastradh 48003b705cfSriastradh if (intel_pixmap_tiled(intel->render_source)) { 48103b705cfSriastradh assert((src_pitch % 512) == 0); 48203b705cfSriastradh src_pitch >>= 2; 48303b705cfSriastradh cmd |= XY_SRC_COPY_BLT_SRC_TILED; 48403b705cfSriastradh } 48503b705cfSriastradh } 48603b705cfSriastradh 48703b705cfSriastradh OUT_BATCH(cmd); 48803b705cfSriastradh 48903b705cfSriastradh OUT_BATCH(intel->BR[13] | dst_pitch); 49003b705cfSriastradh OUT_BATCH((dst_y1 << 16) | (dst_x1 & 0xffff)); 49103b705cfSriastradh OUT_BATCH((dst_y2 << 16) | (dst_x2 & 0xffff)); 49203b705cfSriastradh OUT_RELOC_PIXMAP_FENCED(dest, 49303b705cfSriastradh I915_GEM_DOMAIN_RENDER, 49403b705cfSriastradh I915_GEM_DOMAIN_RENDER, 49503b705cfSriastradh 0); 49603b705cfSriastradh OUT_BATCH((src_y1 << 16) | (src_x1 & 0xffff)); 49703b705cfSriastradh OUT_BATCH(src_pitch); 49803b705cfSriastradh OUT_RELOC_PIXMAP_FENCED(intel->render_source, 49903b705cfSriastradh I915_GEM_DOMAIN_RENDER, 0, 50003b705cfSriastradh 0); 50103b705cfSriastradh 50203b705cfSriastradh ADVANCE_BATCH(); 50303b705cfSriastradh } 50403b705cfSriastradh} 50503b705cfSriastradh 50603b705cfSriastradhstatic void intel_uxa_done(PixmapPtr pixmap) 50703b705cfSriastradh{ 50803b705cfSriastradh ScrnInfoPtr scrn = xf86ScreenToScrn(pixmap->drawable.pScreen); 50903b705cfSriastradh intel_screen_private *intel = intel_get_screen_private(scrn); 51003b705cfSriastradh 51103b705cfSriastradh if (IS_GEN6(intel) || IS_GEN7(intel)) { 51203b705cfSriastradh /* workaround a random BLT hang */ 51303b705cfSriastradh BEGIN_BATCH_BLT(3); 51403b705cfSriastradh OUT_BATCH(XY_SETUP_CLIP_BLT_CMD); 51503b705cfSriastradh OUT_BATCH(0); 51603b705cfSriastradh OUT_BATCH(0); 51703b705cfSriastradh ADVANCE_BATCH(); 51803b705cfSriastradh } 51903b705cfSriastradh 52003b705cfSriastradh intel_debug_flush(scrn); 52103b705cfSriastradh} 52203b705cfSriastradh 52303b705cfSriastradh/** 52403b705cfSriastradh * Do any cleanup from the Composite operation. 52503b705cfSriastradh * 52603b705cfSriastradh * This is shared between i830 through i965. 52703b705cfSriastradh */ 52803b705cfSriastradhstatic void i830_done_composite(PixmapPtr dest) 52903b705cfSriastradh{ 53003b705cfSriastradh ScrnInfoPtr scrn = xf86ScreenToScrn(dest->drawable.pScreen); 53103b705cfSriastradh intel_screen_private *intel = intel_get_screen_private(scrn); 53203b705cfSriastradh 53303b705cfSriastradh if (intel->vertex_flush) 53403b705cfSriastradh intel->vertex_flush(intel); 53503b705cfSriastradh 53603b705cfSriastradh intel_debug_flush(scrn); 53703b705cfSriastradh} 53803b705cfSriastradh 53903b705cfSriastradh#define xFixedToFloat(val) \ 54003b705cfSriastradh ((float)xFixedToInt(val) + ((float)xFixedFrac(val) / 65536.0)) 54103b705cfSriastradh 54203b705cfSriastradhstatic Bool 54303b705cfSriastradh_intel_transform_point(PictTransformPtr transform, 54403b705cfSriastradh float x, float y, float result[3]) 54503b705cfSriastradh{ 54603b705cfSriastradh int j; 54703b705cfSriastradh 54803b705cfSriastradh for (j = 0; j < 3; j++) { 54903b705cfSriastradh result[j] = (xFixedToFloat(transform->matrix[j][0]) * x + 55003b705cfSriastradh xFixedToFloat(transform->matrix[j][1]) * y + 55103b705cfSriastradh xFixedToFloat(transform->matrix[j][2])); 55203b705cfSriastradh } 55303b705cfSriastradh if (!result[2]) 55403b705cfSriastradh return FALSE; 55503b705cfSriastradh return TRUE; 55603b705cfSriastradh} 55703b705cfSriastradh 55803b705cfSriastradh/** 55903b705cfSriastradh * Returns the floating-point coordinates transformed by the given transform. 56003b705cfSriastradh * 56103b705cfSriastradh * transform may be null. 56203b705cfSriastradh */ 56303b705cfSriastradhBool 56403b705cfSriastradhintel_get_transformed_coordinates(int x, int y, PictTransformPtr transform, 56503b705cfSriastradh float *x_out, float *y_out) 56603b705cfSriastradh{ 56703b705cfSriastradh if (transform == NULL) { 56803b705cfSriastradh *x_out = x; 56903b705cfSriastradh *y_out = y; 57003b705cfSriastradh } else { 57103b705cfSriastradh float result[3]; 57203b705cfSriastradh 57303b705cfSriastradh if (!_intel_transform_point(transform, 57403b705cfSriastradh x, y, 57503b705cfSriastradh result)) 57603b705cfSriastradh return FALSE; 57703b705cfSriastradh *x_out = result[0] / result[2]; 57803b705cfSriastradh *y_out = result[1] / result[2]; 57903b705cfSriastradh } 58003b705cfSriastradh return TRUE; 58103b705cfSriastradh} 58203b705cfSriastradh 58303b705cfSriastradh/** 58403b705cfSriastradh * Returns the un-normalized floating-point coordinates transformed by the given transform. 58503b705cfSriastradh * 58603b705cfSriastradh * transform may be null. 58703b705cfSriastradh */ 58803b705cfSriastradhBool 58903b705cfSriastradhintel_get_transformed_coordinates_3d(int x, int y, PictTransformPtr transform, 59003b705cfSriastradh float *x_out, float *y_out, float *w_out) 59103b705cfSriastradh{ 59203b705cfSriastradh if (transform == NULL) { 59303b705cfSriastradh *x_out = x; 59403b705cfSriastradh *y_out = y; 59503b705cfSriastradh *w_out = 1; 59603b705cfSriastradh } else { 59703b705cfSriastradh float result[3]; 59803b705cfSriastradh 59903b705cfSriastradh if (!_intel_transform_point(transform, 60003b705cfSriastradh x, y, 60103b705cfSriastradh result)) 60203b705cfSriastradh return FALSE; 60303b705cfSriastradh *x_out = result[0]; 60403b705cfSriastradh *y_out = result[1]; 60503b705cfSriastradh *w_out = result[2]; 60603b705cfSriastradh } 60703b705cfSriastradh return TRUE; 60803b705cfSriastradh} 60903b705cfSriastradh 61003b705cfSriastradh/** 61103b705cfSriastradh * Returns whether the provided transform is affine. 61203b705cfSriastradh * 61303b705cfSriastradh * transform may be null. 61403b705cfSriastradh */ 61503b705cfSriastradhBool intel_transform_is_affine(PictTransformPtr t) 61603b705cfSriastradh{ 61703b705cfSriastradh if (t == NULL) 61803b705cfSriastradh return TRUE; 61903b705cfSriastradh return t->matrix[2][0] == 0 && t->matrix[2][1] == 0; 62003b705cfSriastradh} 62103b705cfSriastradh 62203b705cfSriastradhdri_bo *intel_get_pixmap_bo(PixmapPtr pixmap) 62303b705cfSriastradh{ 62403b705cfSriastradh struct intel_pixmap *intel; 62503b705cfSriastradh 62603b705cfSriastradh intel = intel_get_pixmap_private(pixmap); 62703b705cfSriastradh if (intel == NULL) 62803b705cfSriastradh return NULL; 62903b705cfSriastradh 63003b705cfSriastradh return intel->bo; 63103b705cfSriastradh} 63203b705cfSriastradh 63303b705cfSriastradhvoid intel_set_pixmap_bo(PixmapPtr pixmap, dri_bo * bo) 63403b705cfSriastradh{ 63503b705cfSriastradh struct intel_pixmap *priv; 63603b705cfSriastradh 63703b705cfSriastradh priv = intel_get_pixmap_private(pixmap); 63803b705cfSriastradh if (priv == NULL && bo == NULL) 63903b705cfSriastradh return; 64003b705cfSriastradh 64103b705cfSriastradh if (priv != NULL) { 64203b705cfSriastradh if (priv->bo == bo) 64303b705cfSriastradh return; 64403b705cfSriastradh 64503b705cfSriastradh dri_bo_unreference(priv->bo); 64603b705cfSriastradh list_del(&priv->batch); 64703b705cfSriastradh 64803b705cfSriastradh free(priv); 64903b705cfSriastradh priv = NULL; 65003b705cfSriastradh } 65103b705cfSriastradh 65203b705cfSriastradh if (bo != NULL) { 65303b705cfSriastradh uint32_t tiling; 65403b705cfSriastradh uint32_t swizzle_mode; 65503b705cfSriastradh int ret; 65603b705cfSriastradh 65703b705cfSriastradh priv = calloc(1, sizeof (struct intel_pixmap)); 65803b705cfSriastradh if (priv == NULL) 65903b705cfSriastradh goto BAIL; 66003b705cfSriastradh 66103b705cfSriastradh list_init(&priv->batch); 66203b705cfSriastradh 66303b705cfSriastradh dri_bo_reference(bo); 66403b705cfSriastradh priv->bo = bo; 66503b705cfSriastradh priv->stride = intel_pixmap_pitch(pixmap); 66603b705cfSriastradh 66703b705cfSriastradh ret = drm_intel_bo_get_tiling(bo, &tiling, &swizzle_mode); 66803b705cfSriastradh if (ret != 0) { 66903b705cfSriastradh FatalError("Couldn't get tiling on bo %p: %s\n", 67003b705cfSriastradh bo, strerror(-ret)); 67103b705cfSriastradh } 67203b705cfSriastradh 67303b705cfSriastradh priv->tiling = tiling; 67403b705cfSriastradh priv->busy = -1; 67503b705cfSriastradh priv->offscreen = 1; 67603b705cfSriastradh } 67703b705cfSriastradh 67803b705cfSriastradh BAIL: 67903b705cfSriastradh intel_set_pixmap_private(pixmap, priv); 68003b705cfSriastradh} 68103b705cfSriastradh 68203b705cfSriastradhstatic Bool intel_uxa_pixmap_is_offscreen(PixmapPtr pixmap) 68303b705cfSriastradh{ 68403b705cfSriastradh return intel_pixmap_is_offscreen(pixmap); 68503b705cfSriastradh} 68603b705cfSriastradh 68703b705cfSriastradhstatic Bool intel_uxa_prepare_access(PixmapPtr pixmap, uxa_access_t access) 68803b705cfSriastradh{ 68903b705cfSriastradh ScrnInfoPtr scrn = xf86ScreenToScrn(pixmap->drawable.pScreen); 69003b705cfSriastradh intel_screen_private *intel = intel_get_screen_private(scrn); 69103b705cfSriastradh struct intel_pixmap *priv = intel_get_pixmap_private(pixmap); 69203b705cfSriastradh dri_bo *bo = priv->bo; 69303b705cfSriastradh int ret; 69403b705cfSriastradh 69503b705cfSriastradh /* Transitioning to glamor acceleration, we need to flush all pending 69603b705cfSriastradh * usage by UXA. */ 69703b705cfSriastradh if (access == UXA_GLAMOR_ACCESS_RW || access == UXA_GLAMOR_ACCESS_RO) { 69803b705cfSriastradh if (!list_is_empty(&priv->batch)) 69903b705cfSriastradh intel_batch_submit(scrn); 70003b705cfSriastradh return TRUE; 70103b705cfSriastradh } 70203b705cfSriastradh 70303b705cfSriastradh /* When falling back to swrast, flush all pending operations */ 70403b705cfSriastradh intel_glamor_flush(intel); 70503b705cfSriastradh if (access == UXA_ACCESS_RW || priv->dirty) 70603b705cfSriastradh intel_batch_submit(scrn); 70703b705cfSriastradh 70803b705cfSriastradh assert(bo->size <= intel->max_gtt_map_size); 70903b705cfSriastradh ret = drm_intel_gem_bo_map_gtt(bo); 71003b705cfSriastradh if (ret) { 71103b705cfSriastradh xf86DrvMsg(scrn->scrnIndex, X_WARNING, 71203b705cfSriastradh "%s: bo map (use gtt? %d, access %d) failed: %s\n", 71303b705cfSriastradh __FUNCTION__, 71403b705cfSriastradh priv->tiling || bo->size <= intel->max_gtt_map_size, 71503b705cfSriastradh access, 71603b705cfSriastradh strerror(-ret)); 71703b705cfSriastradh return FALSE; 71803b705cfSriastradh } 71903b705cfSriastradh 72003b705cfSriastradh pixmap->devPrivate.ptr = bo->virtual; 72103b705cfSriastradh priv->busy = 0; 72203b705cfSriastradh 72303b705cfSriastradh return TRUE; 72403b705cfSriastradh} 72503b705cfSriastradh 72603b705cfSriastradhstatic void intel_uxa_finish_access(PixmapPtr pixmap, uxa_access_t access) 72703b705cfSriastradh{ 72803b705cfSriastradh struct intel_pixmap *priv; 72903b705cfSriastradh 73003b705cfSriastradh if (access == UXA_GLAMOR_ACCESS_RW || access == UXA_GLAMOR_ACCESS_RO) 73103b705cfSriastradh return; 73203b705cfSriastradh 73303b705cfSriastradh priv = intel_get_pixmap_private(pixmap); 73403b705cfSriastradh if (priv == NULL) 73503b705cfSriastradh return; 73603b705cfSriastradh 73703b705cfSriastradh drm_intel_gem_bo_unmap_gtt(priv->bo); 73803b705cfSriastradh pixmap->devPrivate.ptr = NULL; 73903b705cfSriastradh} 74003b705cfSriastradh 74103b705cfSriastradhstatic Bool intel_uxa_pixmap_put_image(PixmapPtr pixmap, 74203b705cfSriastradh char *src, int src_pitch, 74303b705cfSriastradh int x, int y, int w, int h) 74403b705cfSriastradh{ 74503b705cfSriastradh struct intel_pixmap *priv = intel_get_pixmap_private(pixmap); 74603b705cfSriastradh int stride = intel_pixmap_pitch(pixmap); 74703b705cfSriastradh int cpp = pixmap->drawable.bitsPerPixel/8; 74803b705cfSriastradh int ret = FALSE; 74903b705cfSriastradh 75003b705cfSriastradh if (priv == NULL || priv->bo == NULL) 75103b705cfSriastradh return FALSE; 75203b705cfSriastradh 75303b705cfSriastradh if (priv->tiling == I915_TILING_NONE && 75403b705cfSriastradh (h == 1 || (src_pitch == stride && w == pixmap->drawable.width))) { 75503b705cfSriastradh return drm_intel_bo_subdata(priv->bo, y*stride + x*cpp, stride*(h-1) + w*cpp, src) == 0; 75603b705cfSriastradh } else if (drm_intel_gem_bo_map_gtt(priv->bo) == 0) { 75703b705cfSriastradh char *dst = priv->bo->virtual; 75803b705cfSriastradh int row_length = w * cpp; 75903b705cfSriastradh int num_rows = h; 76003b705cfSriastradh if (row_length == src_pitch && src_pitch == stride) 76103b705cfSriastradh num_rows = 1, row_length *= h; 76203b705cfSriastradh dst += y * stride + x * cpp; 76303b705cfSriastradh do { 76403b705cfSriastradh memcpy (dst, src, row_length); 76503b705cfSriastradh src += src_pitch; 76603b705cfSriastradh dst += stride; 76703b705cfSriastradh } while (--num_rows); 76803b705cfSriastradh drm_intel_gem_bo_unmap_gtt(priv->bo); 76903b705cfSriastradh ret = TRUE; 77003b705cfSriastradh } 77103b705cfSriastradh 77203b705cfSriastradh return ret; 77303b705cfSriastradh} 77403b705cfSriastradh 77503b705cfSriastradhstatic Bool intel_uxa_put_image(PixmapPtr pixmap, 77603b705cfSriastradh int x, int y, 77703b705cfSriastradh int w, int h, 77803b705cfSriastradh char *src, int src_pitch) 77903b705cfSriastradh{ 78003b705cfSriastradh struct intel_pixmap *priv; 78103b705cfSriastradh 78203b705cfSriastradh priv = intel_get_pixmap_private(pixmap); 78303b705cfSriastradh if (!intel_pixmap_is_busy(priv)) { 78403b705cfSriastradh /* bo is not busy so can be replaced without a stall, upload in-place. */ 78503b705cfSriastradh return intel_uxa_pixmap_put_image(pixmap, src, src_pitch, x, y, w, h); 78603b705cfSriastradh } else { 78703b705cfSriastradh ScreenPtr screen = pixmap->drawable.pScreen; 78803b705cfSriastradh 78903b705cfSriastradh if (!priv->pinned && 79003b705cfSriastradh x == 0 && y == 0 && 79103b705cfSriastradh w == pixmap->drawable.width && 79203b705cfSriastradh h == pixmap->drawable.height) 79303b705cfSriastradh { 79403b705cfSriastradh intel_screen_private *intel = intel_get_screen_private(xf86ScreenToScrn(screen)); 79503b705cfSriastradh uint32_t tiling = priv->tiling; 79603b705cfSriastradh int size, stride; 79703b705cfSriastradh dri_bo *bo; 79803b705cfSriastradh 79903b705cfSriastradh /* Replace busy bo. */ 80003b705cfSriastradh size = intel_uxa_pixmap_compute_size (pixmap, w, h, 80103b705cfSriastradh &tiling, &stride, 0); 80203b705cfSriastradh if (size > intel->max_gtt_map_size) 80303b705cfSriastradh return FALSE; 80403b705cfSriastradh 80503b705cfSriastradh bo = drm_intel_bo_alloc(intel->bufmgr, "pixmap", size, 0); 80603b705cfSriastradh if (bo == NULL) 80703b705cfSriastradh return FALSE; 80803b705cfSriastradh 80903b705cfSriastradh if (tiling != I915_TILING_NONE) 81003b705cfSriastradh drm_intel_bo_set_tiling(bo, &tiling, stride); 81103b705cfSriastradh priv->stride = stride; 81203b705cfSriastradh priv->tiling = tiling; 81303b705cfSriastradh 81403b705cfSriastradh screen->ModifyPixmapHeader(pixmap, 81503b705cfSriastradh w, h, 81603b705cfSriastradh 0, 0, 81703b705cfSriastradh stride, NULL); 81803b705cfSriastradh intel_set_pixmap_bo(pixmap, bo); 81903b705cfSriastradh dri_bo_unreference(bo); 82003b705cfSriastradh 82103b705cfSriastradh return intel_uxa_pixmap_put_image(pixmap, src, src_pitch, 0, 0, w, h); 82203b705cfSriastradh } 82303b705cfSriastradh else 82403b705cfSriastradh { 82503b705cfSriastradh PixmapPtr scratch; 82603b705cfSriastradh Bool ret; 82703b705cfSriastradh 82803b705cfSriastradh /* Upload to a linear buffer and queue a blit. */ 82903b705cfSriastradh scratch = (*screen->CreatePixmap)(screen, w, h, 83003b705cfSriastradh pixmap->drawable.depth, 83103b705cfSriastradh UXA_CREATE_PIXMAP_FOR_MAP); 83203b705cfSriastradh if (!scratch) 83303b705cfSriastradh return FALSE; 83403b705cfSriastradh 83503b705cfSriastradh if (!intel_uxa_pixmap_is_offscreen(scratch)) { 83603b705cfSriastradh screen->DestroyPixmap(scratch); 83703b705cfSriastradh return FALSE; 83803b705cfSriastradh } 83903b705cfSriastradh 84003b705cfSriastradh ret = intel_uxa_pixmap_put_image(scratch, src, src_pitch, 0, 0, w, h); 84103b705cfSriastradh if (ret) { 84203b705cfSriastradh GCPtr gc = GetScratchGC(pixmap->drawable.depth, screen); 84303b705cfSriastradh if (gc) { 84403b705cfSriastradh ValidateGC(&pixmap->drawable, gc); 84503b705cfSriastradh 84603b705cfSriastradh (*gc->ops->CopyArea)(&scratch->drawable, 84703b705cfSriastradh &pixmap->drawable, 84803b705cfSriastradh gc, 0, 0, w, h, x, y); 84903b705cfSriastradh 85003b705cfSriastradh FreeScratchGC(gc); 85103b705cfSriastradh } else 85203b705cfSriastradh ret = FALSE; 85303b705cfSriastradh } 85403b705cfSriastradh 85503b705cfSriastradh (*screen->DestroyPixmap)(scratch); 85603b705cfSriastradh return ret; 85703b705cfSriastradh } 85803b705cfSriastradh } 85903b705cfSriastradh} 86003b705cfSriastradh 86103b705cfSriastradhstatic Bool intel_uxa_pixmap_get_image(PixmapPtr pixmap, 86203b705cfSriastradh int x, int y, int w, int h, 86303b705cfSriastradh char *dst, int dst_pitch) 86403b705cfSriastradh{ 86503b705cfSriastradh struct intel_pixmap *priv = intel_get_pixmap_private(pixmap); 86603b705cfSriastradh int stride = intel_pixmap_pitch(pixmap); 86703b705cfSriastradh int cpp = pixmap->drawable.bitsPerPixel/8; 86803b705cfSriastradh 86903b705cfSriastradh /* assert(priv->tiling == I915_TILING_NONE); */ 87003b705cfSriastradh if (h == 1 || (dst_pitch == stride && w == pixmap->drawable.width)) { 87103b705cfSriastradh return drm_intel_bo_get_subdata(priv->bo, y*stride + x*cpp, (h-1)*stride + w*cpp, dst) == 0; 87203b705cfSriastradh } else { 87303b705cfSriastradh char *src; 87403b705cfSriastradh 87503b705cfSriastradh if (drm_intel_gem_bo_map_gtt(priv->bo)) 87603b705cfSriastradh return FALSE; 87703b705cfSriastradh 87803b705cfSriastradh src = (char *) priv->bo->virtual + y * stride + x * cpp; 87903b705cfSriastradh w *= cpp; 88003b705cfSriastradh do { 88103b705cfSriastradh memcpy(dst, src, w); 88203b705cfSriastradh src += stride; 88303b705cfSriastradh dst += dst_pitch; 88403b705cfSriastradh } while (--h); 88503b705cfSriastradh 88603b705cfSriastradh drm_intel_gem_bo_unmap_gtt(priv->bo); 88703b705cfSriastradh 88803b705cfSriastradh return TRUE; 88903b705cfSriastradh } 89003b705cfSriastradh} 89103b705cfSriastradh 89203b705cfSriastradhstatic Bool intel_uxa_get_image(PixmapPtr pixmap, 89303b705cfSriastradh int x, int y, 89403b705cfSriastradh int w, int h, 89503b705cfSriastradh char *dst, int dst_pitch) 89603b705cfSriastradh{ 89703b705cfSriastradh struct intel_pixmap *priv; 89803b705cfSriastradh PixmapPtr scratch = NULL; 89903b705cfSriastradh Bool ret; 90003b705cfSriastradh 90103b705cfSriastradh /* The presumption is that we wish to keep the target hot, so 90203b705cfSriastradh * copy to a new bo and move that to the CPU in preference to 90303b705cfSriastradh * causing ping-pong of the original. 90403b705cfSriastradh * 90503b705cfSriastradh * Also the gpu is much faster at detiling. 90603b705cfSriastradh */ 90703b705cfSriastradh 90803b705cfSriastradh priv = intel_get_pixmap_private(pixmap); 90903b705cfSriastradh if (intel_pixmap_is_busy(priv) || priv->tiling != I915_TILING_NONE) { 91003b705cfSriastradh ScreenPtr screen = pixmap->drawable.pScreen; 91103b705cfSriastradh GCPtr gc; 91203b705cfSriastradh 91303b705cfSriastradh /* Copy to a linear buffer and pull. */ 91403b705cfSriastradh scratch = screen->CreatePixmap(screen, w, h, 91503b705cfSriastradh pixmap->drawable.depth, 91603b705cfSriastradh INTEL_CREATE_PIXMAP_TILING_NONE); 91703b705cfSriastradh if (!scratch) 91803b705cfSriastradh return FALSE; 91903b705cfSriastradh 92003b705cfSriastradh if (!intel_uxa_pixmap_is_offscreen(scratch)) { 92103b705cfSriastradh screen->DestroyPixmap(scratch); 92203b705cfSriastradh return FALSE; 92303b705cfSriastradh } 92403b705cfSriastradh 92503b705cfSriastradh gc = GetScratchGC(pixmap->drawable.depth, screen); 92603b705cfSriastradh if (!gc) { 92703b705cfSriastradh screen->DestroyPixmap(scratch); 92803b705cfSriastradh return FALSE; 92903b705cfSriastradh } 93003b705cfSriastradh 93103b705cfSriastradh ValidateGC(&pixmap->drawable, gc); 93203b705cfSriastradh 93303b705cfSriastradh gc->ops->CopyArea(&pixmap->drawable, 93403b705cfSriastradh &scratch->drawable, 93503b705cfSriastradh gc, x, y, w, h, 0, 0); 93603b705cfSriastradh 93703b705cfSriastradh FreeScratchGC(gc); 93803b705cfSriastradh 93903b705cfSriastradh intel_batch_submit(xf86ScreenToScrn(screen)); 94003b705cfSriastradh 94103b705cfSriastradh x = y = 0; 94203b705cfSriastradh pixmap = scratch; 94303b705cfSriastradh } 94403b705cfSriastradh 94503b705cfSriastradh ret = intel_uxa_pixmap_get_image(pixmap, x, y, w, h, dst, dst_pitch); 94603b705cfSriastradh 94703b705cfSriastradh if (scratch) 94803b705cfSriastradh scratch->drawable.pScreen->DestroyPixmap(scratch); 94903b705cfSriastradh 95003b705cfSriastradh return ret; 95103b705cfSriastradh} 95203b705cfSriastradh 95303b705cfSriastradhstatic CARD32 intel_cache_expire(OsTimerPtr timer, CARD32 now, pointer data) 95403b705cfSriastradh{ 95503b705cfSriastradh intel_screen_private *intel = data; 95603b705cfSriastradh 95703b705cfSriastradh /* We just want to create and destroy a bo as this causes libdrm 95803b705cfSriastradh * to reap its caches. However, since we can't remove that buffer 95903b705cfSriastradh * from the cache due to its own activity, we want to use something 96003b705cfSriastradh * that we know we will reuse later. The most frequently reused buffer 96103b705cfSriastradh * we have is the batchbuffer, and the best way to trigger its 96203b705cfSriastradh * reallocation is to submit a flush. 96303b705cfSriastradh */ 96403b705cfSriastradh intel_batch_emit_flush(intel->scrn); 96503b705cfSriastradh intel_batch_submit(intel->scrn); 96603b705cfSriastradh 96703b705cfSriastradh return 0; 96803b705cfSriastradh} 96903b705cfSriastradh 97003b705cfSriastradhstatic void intel_flush_rendering(intel_screen_private *intel) 97103b705cfSriastradh{ 97203b705cfSriastradh if (intel->needs_flush == 0) 97303b705cfSriastradh return; 97403b705cfSriastradh 97503b705cfSriastradh if (intel->has_kernel_flush) { 97603b705cfSriastradh intel_batch_submit(intel->scrn); 97703b705cfSriastradh drm_intel_bo_busy(intel->front_buffer); 97803b705cfSriastradh } else { 97903b705cfSriastradh intel_batch_emit_flush(intel->scrn); 98003b705cfSriastradh intel_batch_submit(intel->scrn); 98103b705cfSriastradh } 98203b705cfSriastradh 98303b705cfSriastradh intel->cache_expire = TimerSet(intel->cache_expire, 0, 3000, 98403b705cfSriastradh intel_cache_expire, intel); 98503b705cfSriastradh 98603b705cfSriastradh intel->needs_flush = 0; 98703b705cfSriastradh} 98803b705cfSriastradh 98903b705cfSriastradhstatic void intel_throttle(intel_screen_private *intel) 99003b705cfSriastradh{ 99103b705cfSriastradh drmCommandNone(intel->drmSubFD, DRM_I915_GEM_THROTTLE); 99203b705cfSriastradh} 99303b705cfSriastradh 99403b705cfSriastradhvoid intel_uxa_block_handler(intel_screen_private *intel) 99503b705cfSriastradh{ 99603b705cfSriastradh /* Emit a flush of the rendering cache, or on the 965 99703b705cfSriastradh * and beyond rendering results may not hit the 99803b705cfSriastradh * framebuffer until significantly later. 99903b705cfSriastradh */ 100003b705cfSriastradh intel_glamor_flush(intel); 100103b705cfSriastradh intel_flush_rendering(intel); 100203b705cfSriastradh intel_throttle(intel); 100303b705cfSriastradh} 100403b705cfSriastradh 100503b705cfSriastradhstatic PixmapPtr 100603b705cfSriastradhintel_uxa_create_pixmap(ScreenPtr screen, int w, int h, int depth, 100703b705cfSriastradh unsigned usage) 100803b705cfSriastradh{ 100903b705cfSriastradh ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 101003b705cfSriastradh intel_screen_private *intel = intel_get_screen_private(scrn); 101103b705cfSriastradh struct intel_pixmap *priv; 101203b705cfSriastradh PixmapPtr pixmap, new_pixmap = NULL; 101303b705cfSriastradh 101403b705cfSriastradh if (!(usage & INTEL_CREATE_PIXMAP_DRI2)) { 101503b705cfSriastradh pixmap = intel_glamor_create_pixmap(screen, w, h, depth, usage); 101603b705cfSriastradh if (pixmap) 101703b705cfSriastradh return pixmap; 101803b705cfSriastradh } 101903b705cfSriastradh 102003b705cfSriastradh if (w > 32767 || h > 32767) 102103b705cfSriastradh return NullPixmap; 102203b705cfSriastradh 102303b705cfSriastradh if (depth == 1 || intel->force_fallback) 102403b705cfSriastradh return fbCreatePixmap(screen, w, h, depth, usage); 102503b705cfSriastradh 102603b705cfSriastradh if (usage == CREATE_PIXMAP_USAGE_GLYPH_PICTURE && w <= 32 && h <= 32) 102703b705cfSriastradh return fbCreatePixmap(screen, w, h, depth, usage); 102803b705cfSriastradh 102903b705cfSriastradh pixmap = fbCreatePixmap(screen, 0, 0, depth, usage); 103003b705cfSriastradh if (pixmap == NullPixmap) 103103b705cfSriastradh return pixmap; 103203b705cfSriastradh 103303b705cfSriastradh if (w && h) { 103403b705cfSriastradh unsigned int size, tiling; 103503b705cfSriastradh int stride; 103603b705cfSriastradh 103703b705cfSriastradh /* Always attempt to tile, compute_size() will remove the 103803b705cfSriastradh * tiling for pixmaps that are either too large or too small 103903b705cfSriastradh * to be effectively tiled. 104003b705cfSriastradh */ 104103b705cfSriastradh tiling = I915_TILING_X; 104203b705cfSriastradh if (usage & INTEL_CREATE_PIXMAP_TILING_Y) 104303b705cfSriastradh tiling = I915_TILING_Y; 104403b705cfSriastradh if (usage == UXA_CREATE_PIXMAP_FOR_MAP || usage & INTEL_CREATE_PIXMAP_TILING_NONE) 104503b705cfSriastradh tiling = I915_TILING_NONE; 104603b705cfSriastradh 104703b705cfSriastradh#ifdef CREATE_PIXMAP_USAGE_SHARED 104803b705cfSriastradh if (usage == CREATE_PIXMAP_USAGE_SHARED) 104903b705cfSriastradh tiling = I915_TILING_NONE; 105003b705cfSriastradh#endif 105103b705cfSriastradh /* if tiling is off force to none */ 105203b705cfSriastradh if (!intel->tiling) 105303b705cfSriastradh tiling = I915_TILING_NONE; 105403b705cfSriastradh 105503b705cfSriastradh if (tiling != I915_TILING_NONE && !(usage & INTEL_CREATE_PIXMAP_DRI2)) { 105603b705cfSriastradh if (h <= 4) 105703b705cfSriastradh tiling = I915_TILING_NONE; 105803b705cfSriastradh if (h <= 16 && tiling == I915_TILING_Y) 105903b705cfSriastradh tiling = I915_TILING_X; 106003b705cfSriastradh } 106103b705cfSriastradh size = intel_uxa_pixmap_compute_size(pixmap, w, h, &tiling, &stride, usage); 106203b705cfSriastradh 106303b705cfSriastradh /* Fail very large allocations. Large BOs will tend to hit SW fallbacks 106403b705cfSriastradh * frequently, and also will tend to fail to successfully map when doing 106503b705cfSriastradh * SW fallbacks because we overcommit address space for BO access. 106603b705cfSriastradh */ 106703b705cfSriastradh if (size > intel->max_bo_size || stride >= KB(32)) 106803b705cfSriastradh goto fallback_pixmap; 106903b705cfSriastradh 107003b705cfSriastradh priv = calloc(1, sizeof (struct intel_pixmap)); 107103b705cfSriastradh if (priv == NULL) 107203b705cfSriastradh goto fallback_pixmap; 107303b705cfSriastradh 107403b705cfSriastradh if (usage == UXA_CREATE_PIXMAP_FOR_MAP) { 107503b705cfSriastradh priv->busy = 0; 107603b705cfSriastradh priv->bo = drm_intel_bo_alloc(intel->bufmgr, 107703b705cfSriastradh "pixmap", size, 0); 107803b705cfSriastradh } else { 107903b705cfSriastradh priv->busy = -1; 108003b705cfSriastradh priv->bo = drm_intel_bo_alloc_for_render(intel->bufmgr, 108103b705cfSriastradh "pixmap", 108203b705cfSriastradh size, 0); 108303b705cfSriastradh } 108403b705cfSriastradh if (!priv->bo) 108503b705cfSriastradh goto fallback_priv; 108603b705cfSriastradh 108703b705cfSriastradh if (tiling != I915_TILING_NONE) 108803b705cfSriastradh drm_intel_bo_set_tiling(priv->bo, &tiling, stride); 108903b705cfSriastradh priv->stride = stride; 109003b705cfSriastradh priv->tiling = tiling; 109103b705cfSriastradh priv->offscreen = 1; 109203b705cfSriastradh 109303b705cfSriastradh list_init(&priv->batch); 109403b705cfSriastradh intel_set_pixmap_private(pixmap, priv); 109503b705cfSriastradh 109603b705cfSriastradh screen->ModifyPixmapHeader(pixmap, w, h, 0, 0, stride, NULL); 109703b705cfSriastradh 109803b705cfSriastradh if (!intel_glamor_create_textured_pixmap(pixmap)) 109903b705cfSriastradh goto fallback_glamor; 110003b705cfSriastradh } 110103b705cfSriastradh 110203b705cfSriastradh return pixmap; 110303b705cfSriastradh 110403b705cfSriastradhfallback_glamor: 110503b705cfSriastradh if (usage & INTEL_CREATE_PIXMAP_DRI2) { 110603b705cfSriastradh /* XXX need further work to handle the DRI2 failure case. 110703b705cfSriastradh * Glamor don't know how to handle a BO only pixmap. Put 110803b705cfSriastradh * a warning indicator here. 110903b705cfSriastradh */ 111003b705cfSriastradh xf86DrvMsg(scrn->scrnIndex, X_WARNING, 111103b705cfSriastradh "Failed to create textured DRI2 pixmap."); 111203b705cfSriastradh return pixmap; 111303b705cfSriastradh } 111403b705cfSriastradh /* Create textured pixmap failed means glamor failed to 111503b705cfSriastradh * create a texture from current BO for some reasons. We turn 111603b705cfSriastradh * to create a new glamor pixmap and clean up current one. 111703b705cfSriastradh * One thing need to be noted, this new pixmap doesn't 111803b705cfSriastradh * has a priv and bo attached to it. It's glamor's responsbility 111903b705cfSriastradh * to take care of it. Glamor will mark this new pixmap as a 112003b705cfSriastradh * texture only pixmap and will never fallback to DDX layer 112103b705cfSriastradh * afterwards. 112203b705cfSriastradh */ 112303b705cfSriastradh new_pixmap = intel_glamor_create_pixmap(screen, w, h, 112403b705cfSriastradh depth, usage); 112503b705cfSriastradh dri_bo_unreference(priv->bo); 112603b705cfSriastradhfallback_priv: 112703b705cfSriastradh free(priv); 112803b705cfSriastradhfallback_pixmap: 112903b705cfSriastradh fbDestroyPixmap(pixmap); 113003b705cfSriastradh if (new_pixmap) 113103b705cfSriastradh return new_pixmap; 113203b705cfSriastradh else 113303b705cfSriastradh return fbCreatePixmap(screen, w, h, depth, usage); 113403b705cfSriastradh} 113503b705cfSriastradh 113603b705cfSriastradhstatic Bool intel_uxa_destroy_pixmap(PixmapPtr pixmap) 113703b705cfSriastradh{ 113803b705cfSriastradh if (pixmap->refcnt == 1) { 113903b705cfSriastradh intel_glamor_destroy_pixmap(pixmap); 114003b705cfSriastradh intel_set_pixmap_bo(pixmap, NULL); 114103b705cfSriastradh } 114203b705cfSriastradh fbDestroyPixmap(pixmap); 114303b705cfSriastradh return TRUE; 114403b705cfSriastradh} 114503b705cfSriastradh 114603b705cfSriastradhBool intel_uxa_create_screen_resources(ScreenPtr screen) 114703b705cfSriastradh{ 114803b705cfSriastradh ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 114903b705cfSriastradh PixmapPtr pixmap; 115003b705cfSriastradh intel_screen_private *intel = intel_get_screen_private(scrn); 115103b705cfSriastradh dri_bo *bo = intel->front_buffer; 115203b705cfSriastradh 115303b705cfSriastradh if (!uxa_resources_init(screen)) 115403b705cfSriastradh return FALSE; 115503b705cfSriastradh 115603b705cfSriastradh if (drm_intel_gem_bo_map_gtt(bo)) 115703b705cfSriastradh return FALSE; 115803b705cfSriastradh 115903b705cfSriastradh pixmap = screen->GetScreenPixmap(screen); 116003b705cfSriastradh intel_set_pixmap_bo(pixmap, bo); 116103b705cfSriastradh intel_get_pixmap_private(pixmap)->pinned |= PIN_SCANOUT; 116203b705cfSriastradh screen->ModifyPixmapHeader(pixmap, 116303b705cfSriastradh scrn->virtualX, 116403b705cfSriastradh scrn->virtualY, 116503b705cfSriastradh -1, -1, 116603b705cfSriastradh intel->front_pitch, 116703b705cfSriastradh NULL); 116803b705cfSriastradh scrn->displayWidth = intel->front_pitch / intel->cpp; 116903b705cfSriastradh 117003b705cfSriastradh if (!intel_glamor_create_screen_resources(screen)) 117103b705cfSriastradh return FALSE; 117203b705cfSriastradh 117303b705cfSriastradh return TRUE; 117403b705cfSriastradh} 117503b705cfSriastradh 117603b705cfSriastradh#ifdef CREATE_PIXMAP_USAGE_SHARED 117703b705cfSriastradhstatic Bool 117803b705cfSriastradhintel_uxa_share_pixmap_backing(PixmapPtr ppix, ScreenPtr slave, void **fd_handle) 117903b705cfSriastradh{ 118003b705cfSriastradh ScrnInfoPtr scrn = xf86ScreenToScrn(ppix->drawable.pScreen); 118103b705cfSriastradh intel_screen_private *intel = intel_get_screen_private(scrn); 118203b705cfSriastradh struct intel_pixmap *priv = intel_get_pixmap_private(ppix); 118303b705cfSriastradh unsigned int size, tiling, swizzle; 118403b705cfSriastradh dri_bo *bo = intel_get_pixmap_bo(ppix), *newbo; 118503b705cfSriastradh int stride; 118603b705cfSriastradh int handle; 118703b705cfSriastradh 118803b705cfSriastradh if (drm_intel_bo_references(intel->batch_bo, bo)) 118903b705cfSriastradh intel_batch_submit(intel->scrn); 119003b705cfSriastradh 119103b705cfSriastradh drm_intel_bo_get_tiling(bo, &tiling, &swizzle); 119203b705cfSriastradh 119303b705cfSriastradh if (tiling == I915_TILING_X) { 119403b705cfSriastradh if (priv->pinned & ~PIN_DRI) 119503b705cfSriastradh return FALSE; 119603b705cfSriastradh 119703b705cfSriastradh tiling = I915_TILING_NONE; 119803b705cfSriastradh 119903b705cfSriastradh size = intel_uxa_pixmap_compute_size(ppix, ppix->drawable.width, ppix->drawable.height, &tiling, &stride, INTEL_CREATE_PIXMAP_DRI2); 120003b705cfSriastradh 120103b705cfSriastradh newbo = drm_intel_bo_alloc_for_render(intel->bufmgr, 120203b705cfSriastradh "pixmap", 120303b705cfSriastradh size, 0); 120403b705cfSriastradh 120503b705cfSriastradh if (tiling != I915_TILING_NONE) 120603b705cfSriastradh drm_intel_bo_set_tiling(newbo, &tiling, stride); 120703b705cfSriastradh priv->stride = stride; 120803b705cfSriastradh priv->tiling = tiling; 120903b705cfSriastradh intel_set_pixmap_bo(ppix, newbo); 121003b705cfSriastradh 121103b705cfSriastradh ppix->drawable.pScreen->ModifyPixmapHeader(ppix, ppix->drawable.width, 121203b705cfSriastradh ppix->drawable.height, 0, 0, 121303b705cfSriastradh stride, NULL); 121403b705cfSriastradh bo = newbo; 121503b705cfSriastradh } 121603b705cfSriastradh drm_intel_bo_get_tiling(bo, &tiling, &swizzle); 121703b705cfSriastradh drm_intel_bo_gem_export_to_prime(bo, &handle); 121803b705cfSriastradh priv->pinned |= PIN_DRI; 121903b705cfSriastradh 122003b705cfSriastradh *fd_handle = (void *)(long)handle; 122103b705cfSriastradh return TRUE; 122203b705cfSriastradh} 122303b705cfSriastradh 122403b705cfSriastradhstatic Bool 122503b705cfSriastradhintel_uxa_set_shared_pixmap_backing(PixmapPtr ppix, void *fd_handle) 122603b705cfSriastradh{ 122703b705cfSriastradh ScrnInfoPtr scrn = xf86ScreenToScrn(ppix->drawable.pScreen); 122803b705cfSriastradh intel_screen_private *intel = intel_get_screen_private(scrn); 122903b705cfSriastradh dri_bo *bo; 123003b705cfSriastradh int ihandle = (int)(long)fd_handle; 123103b705cfSriastradh 123203b705cfSriastradh /* force untiled for now */ 123303b705cfSriastradh bo = drm_intel_bo_gem_create_from_prime(intel->bufmgr, ihandle, 0); 123403b705cfSriastradh if (!bo) 123503b705cfSriastradh return FALSE; 123603b705cfSriastradh 123703b705cfSriastradh intel_set_pixmap_bo(ppix, bo); 123803b705cfSriastradh close(ihandle); 123903b705cfSriastradh return TRUE; 124003b705cfSriastradh} 124103b705cfSriastradh#endif 124203b705cfSriastradh 124303b705cfSriastradhstatic void 124403b705cfSriastradhintel_limits_init(intel_screen_private *intel) 124503b705cfSriastradh{ 124603b705cfSriastradh /* Limits are described in the BLT engine chapter under Graphics Data Size 124703b705cfSriastradh * Limitations, and the descriptions of SURFACE_STATE, 3DSTATE_BUFFER_INFO, 124803b705cfSriastradh * 3DSTATE_DRAWING_RECTANGLE, 3DSTATE_MAP_INFO, and 3DSTATE_MAP_INFO. 124903b705cfSriastradh * 125003b705cfSriastradh * i845 through i965 limits 2D rendering to 65536 lines and pitch of 32768. 125103b705cfSriastradh * 125203b705cfSriastradh * i965 limits 3D surface to (2*element size)-aligned offset if un-tiled. 125303b705cfSriastradh * i965 limits 3D surface to 4kB-aligned offset if tiled. 125403b705cfSriastradh * i965 limits 3D surfaces to w,h of ?,8192. 125503b705cfSriastradh * i965 limits 3D surface to pitch of 1B - 128kB. 125603b705cfSriastradh * i965 limits 3D surface pitch alignment to 1 or 2 times the element size. 125703b705cfSriastradh * i965 limits 3D surface pitch alignment to 512B if tiled. 125803b705cfSriastradh * i965 limits 3D destination drawing rect to w,h of 8192,8192. 125903b705cfSriastradh * 126003b705cfSriastradh * i915 limits 3D textures to 4B-aligned offset if un-tiled. 126103b705cfSriastradh * i915 limits 3D textures to ~4kB-aligned offset if tiled. 126203b705cfSriastradh * i915 limits 3D textures to width,height of 2048,2048. 126303b705cfSriastradh * i915 limits 3D textures to pitch of 16B - 8kB, in dwords. 126403b705cfSriastradh * i915 limits 3D destination to ~4kB-aligned offset if tiled. 126503b705cfSriastradh * i915 limits 3D destination to pitch of 16B - 8kB, in dwords, if un-tiled. 126603b705cfSriastradh * i915 limits 3D destination to pitch 64B-aligned if used with depth. 126703b705cfSriastradh * i915 limits 3D destination to pitch of 512B - 8kB, in tiles, if tiled. 126803b705cfSriastradh * i915 limits 3D destination to POT aligned pitch if tiled. 126903b705cfSriastradh * i915 limits 3D destination drawing rect to w,h of 2048,2048. 127003b705cfSriastradh * 127103b705cfSriastradh * i845 limits 3D textures to 4B-aligned offset if un-tiled. 127203b705cfSriastradh * i845 limits 3D textures to ~4kB-aligned offset if tiled. 127303b705cfSriastradh * i845 limits 3D textures to width,height of 2048,2048. 127403b705cfSriastradh * i845 limits 3D textures to pitch of 4B - 8kB, in dwords. 127503b705cfSriastradh * i845 limits 3D destination to 4B-aligned offset if un-tiled. 127603b705cfSriastradh * i845 limits 3D destination to ~4kB-aligned offset if tiled. 127703b705cfSriastradh * i845 limits 3D destination to pitch of 8B - 8kB, in dwords. 127803b705cfSriastradh * i845 limits 3D destination drawing rect to w,h of 2048,2048. 127903b705cfSriastradh * 128003b705cfSriastradh * For the tiled issues, the only tiled buffer we draw to should be 128103b705cfSriastradh * the front, which will have an appropriate pitch/offset already set up, 128203b705cfSriastradh * so UXA doesn't need to worry. 128303b705cfSriastradh */ 128403b705cfSriastradh if (INTEL_INFO(intel)->gen >= 040) { 128503b705cfSriastradh intel->accel_pixmap_offset_alignment = 4 * 2; 128603b705cfSriastradh intel->accel_max_x = 8192; 128703b705cfSriastradh intel->accel_max_y = 8192; 128803b705cfSriastradh } else { 128903b705cfSriastradh intel->accel_pixmap_offset_alignment = 4; 129003b705cfSriastradh intel->accel_max_x = 2048; 129103b705cfSriastradh intel->accel_max_y = 2048; 129203b705cfSriastradh } 129303b705cfSriastradh} 129403b705cfSriastradh 129503b705cfSriastradhstatic Bool intel_option_accel_blt(intel_screen_private *intel) 129603b705cfSriastradh{ 129703b705cfSriastradh const char *s; 129803b705cfSriastradh 129903b705cfSriastradh s = xf86GetOptValString(intel->Options, OPTION_ACCEL_METHOD); 130003b705cfSriastradh if (s == NULL) 130103b705cfSriastradh return FALSE; 130203b705cfSriastradh 130303b705cfSriastradh return strcasecmp(s, "blt") == 0; 130403b705cfSriastradh} 130503b705cfSriastradh 130603b705cfSriastradhBool intel_uxa_init(ScreenPtr screen) 130703b705cfSriastradh{ 130803b705cfSriastradh ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 130903b705cfSriastradh intel_screen_private *intel = intel_get_screen_private(scrn); 131003b705cfSriastradh 131103b705cfSriastradh#if HAS_DIXREGISTERPRIVATEKEY 131203b705cfSriastradh if (!dixRegisterPrivateKey(&uxa_pixmap_index, PRIVATE_PIXMAP, 0)) 131303b705cfSriastradh#else 131403b705cfSriastradh if (!dixRequestPrivate(&uxa_pixmap_index, 0)) 131503b705cfSriastradh#endif 131603b705cfSriastradh return FALSE; 131703b705cfSriastradh 131803b705cfSriastradh intel_limits_init(intel); 131903b705cfSriastradh 132003b705cfSriastradh intel->uxa_driver = uxa_driver_alloc(); 132103b705cfSriastradh if (intel->uxa_driver == NULL) 132203b705cfSriastradh return FALSE; 132303b705cfSriastradh 132403b705cfSriastradh memset(intel->uxa_driver, 0, sizeof(*intel->uxa_driver)); 132503b705cfSriastradh 132603b705cfSriastradh intel->uxa_driver->uxa_major = 1; 132703b705cfSriastradh intel->uxa_driver->uxa_minor = 0; 132803b705cfSriastradh 132903b705cfSriastradh intel->prim_offset = 0; 133003b705cfSriastradh intel->vertex_count = 0; 133103b705cfSriastradh intel->vertex_offset = 0; 133203b705cfSriastradh intel->vertex_used = 0; 133303b705cfSriastradh intel->floats_per_vertex = 0; 133403b705cfSriastradh intel->last_floats_per_vertex = 0; 133503b705cfSriastradh intel->vertex_bo = NULL; 133603b705cfSriastradh intel->surface_used = 0; 133703b705cfSriastradh intel->surface_reloc = 0; 133803b705cfSriastradh 133903b705cfSriastradh /* Solid fill */ 134003b705cfSriastradh intel->uxa_driver->check_solid = intel_uxa_check_solid; 134103b705cfSriastradh intel->uxa_driver->prepare_solid = intel_uxa_prepare_solid; 134203b705cfSriastradh intel->uxa_driver->solid = intel_uxa_solid; 134303b705cfSriastradh intel->uxa_driver->done_solid = intel_uxa_done; 134403b705cfSriastradh 134503b705cfSriastradh /* Copy */ 134603b705cfSriastradh intel->uxa_driver->check_copy = intel_uxa_check_copy; 134703b705cfSriastradh intel->uxa_driver->prepare_copy = intel_uxa_prepare_copy; 134803b705cfSriastradh intel->uxa_driver->copy = intel_uxa_copy; 134903b705cfSriastradh intel->uxa_driver->done_copy = intel_uxa_done; 135003b705cfSriastradh 135103b705cfSriastradh /* Composite */ 135203b705cfSriastradh if (intel_option_accel_blt(intel)) { 135303b705cfSriastradh } else if (IS_GEN2(intel)) { 135403b705cfSriastradh intel->uxa_driver->check_composite = i830_check_composite; 135503b705cfSriastradh intel->uxa_driver->check_composite_target = i830_check_composite_target; 135603b705cfSriastradh intel->uxa_driver->check_composite_texture = i830_check_composite_texture; 135703b705cfSriastradh intel->uxa_driver->prepare_composite = i830_prepare_composite; 135803b705cfSriastradh intel->uxa_driver->composite = i830_composite; 135903b705cfSriastradh intel->uxa_driver->done_composite = i830_done_composite; 136003b705cfSriastradh 136103b705cfSriastradh intel->vertex_flush = i830_vertex_flush; 136203b705cfSriastradh intel->batch_commit_notify = i830_batch_commit_notify; 136303b705cfSriastradh } else if (IS_GEN3(intel)) { 136403b705cfSriastradh intel->uxa_driver->check_composite = i915_check_composite; 136503b705cfSriastradh intel->uxa_driver->check_composite_target = i915_check_composite_target; 136603b705cfSriastradh intel->uxa_driver->check_composite_texture = i915_check_composite_texture; 136703b705cfSriastradh intel->uxa_driver->prepare_composite = i915_prepare_composite; 136803b705cfSriastradh intel->uxa_driver->composite = i915_composite; 136903b705cfSriastradh intel->uxa_driver->done_composite = i830_done_composite; 137003b705cfSriastradh 137103b705cfSriastradh intel->vertex_flush = i915_vertex_flush; 137203b705cfSriastradh intel->batch_commit_notify = i915_batch_commit_notify; 137303b705cfSriastradh } else { 137403b705cfSriastradh intel->uxa_driver->check_composite = i965_check_composite; 137503b705cfSriastradh intel->uxa_driver->check_composite_texture = i965_check_composite_texture; 137603b705cfSriastradh intel->uxa_driver->prepare_composite = i965_prepare_composite; 137703b705cfSriastradh intel->uxa_driver->composite = i965_composite; 137803b705cfSriastradh intel->uxa_driver->done_composite = i830_done_composite; 137903b705cfSriastradh 138003b705cfSriastradh intel->vertex_flush = i965_vertex_flush; 138103b705cfSriastradh intel->batch_flush = i965_batch_flush; 138203b705cfSriastradh intel->batch_commit_notify = i965_batch_commit_notify; 138303b705cfSriastradh 138403b705cfSriastradh if (IS_GEN4(intel)) { 138503b705cfSriastradh intel->context_switch = gen4_context_switch; 138603b705cfSriastradh } else if (IS_GEN5(intel)) { 138703b705cfSriastradh intel->context_switch = gen5_context_switch; 138803b705cfSriastradh } else { 138903b705cfSriastradh intel->context_switch = gen6_context_switch; 139003b705cfSriastradh } 139103b705cfSriastradh } 139203b705cfSriastradh 139303b705cfSriastradh /* PutImage */ 139403b705cfSriastradh intel->uxa_driver->put_image = intel_uxa_put_image; 139503b705cfSriastradh intel->uxa_driver->get_image = intel_uxa_get_image; 139603b705cfSriastradh 139703b705cfSriastradh intel->uxa_driver->prepare_access = intel_uxa_prepare_access; 139803b705cfSriastradh intel->uxa_driver->finish_access = intel_uxa_finish_access; 139903b705cfSriastradh intel->uxa_driver->pixmap_is_offscreen = intel_uxa_pixmap_is_offscreen; 140003b705cfSriastradh 140103b705cfSriastradh screen->CreatePixmap = intel_uxa_create_pixmap; 140203b705cfSriastradh screen->DestroyPixmap = intel_uxa_destroy_pixmap; 140303b705cfSriastradh 140403b705cfSriastradh#ifdef CREATE_PIXMAP_USAGE_SHARED 140503b705cfSriastradh screen->SharePixmapBacking = intel_uxa_share_pixmap_backing; 140603b705cfSriastradh screen->SetSharedPixmapBacking = intel_uxa_set_shared_pixmap_backing; 140703b705cfSriastradh#endif 140803b705cfSriastradh 140903b705cfSriastradh if (!uxa_driver_init(screen, intel->uxa_driver)) { 141003b705cfSriastradh xf86DrvMsg(scrn->scrnIndex, X_ERROR, 141103b705cfSriastradh "UXA initialization failed\n"); 141203b705cfSriastradh free(intel->uxa_driver); 141303b705cfSriastradh return FALSE; 141403b705cfSriastradh } 141503b705cfSriastradh 141603b705cfSriastradh uxa_set_fallback_debug(screen, intel->fallback_debug); 141703b705cfSriastradh uxa_set_force_fallback(screen, intel->force_fallback); 141803b705cfSriastradh 141903b705cfSriastradh return TRUE; 142003b705cfSriastradh} 1421