intel_uxa.c revision fe8aea9e
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" 4313496ba1Ssnj#include "intel_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 13313496ba1Ssnjintel_uxa_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) { 13913496ba1Ssnj intel_uxa_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) { 14913496ba1Ssnj intel_uxa_debug_fallback(scrn, "Couldn't get aperture " 15003b705cfSriastradh "space for BOs\n"); 15103b705cfSriastradh return FALSE; 15203b705cfSriastradh } 15303b705cfSriastradh } 15403b705cfSriastradh return TRUE; 15503b705cfSriastradh} 15603b705cfSriastradh 15703b705cfSriastradhstatic Bool 15803b705cfSriastradhintel_uxa_check_solid(DrawablePtr drawable, int alu, Pixel planemask) 15903b705cfSriastradh{ 16003b705cfSriastradh ScrnInfoPtr scrn = xf86ScreenToScrn(drawable->pScreen); 16103b705cfSriastradh 16203b705cfSriastradh if (!UXA_PM_IS_SOLID(drawable, planemask)) { 16313496ba1Ssnj intel_uxa_debug_fallback(scrn, "planemask is not solid\n"); 16403b705cfSriastradh return FALSE; 16503b705cfSriastradh } 16603b705cfSriastradh 16703b705cfSriastradh switch (drawable->bitsPerPixel) { 16803b705cfSriastradh case 8: 16903b705cfSriastradh case 16: 17003b705cfSriastradh case 32: 17103b705cfSriastradh break; 17203b705cfSriastradh default: 17303b705cfSriastradh return FALSE; 17403b705cfSriastradh } 17503b705cfSriastradh 17603b705cfSriastradh return TRUE; 17703b705cfSriastradh} 17803b705cfSriastradh 179fe8aea9eSmrgstatic Bool 180fe8aea9eSmrgintel_uxa_check_bo_tiling(intel_screen_private *intel, 181fe8aea9eSmrg PixmapPtr pixmap, 182fe8aea9eSmrg unsigned *tiling_out) 183fe8aea9eSmrg{ 184fe8aea9eSmrg struct intel_uxa_pixmap *priv; 185fe8aea9eSmrg 186fe8aea9eSmrg priv = intel_uxa_get_pixmap_private(pixmap); 187fe8aea9eSmrg if (!priv) 188fe8aea9eSmrg return FALSE; 189fe8aea9eSmrg 190fe8aea9eSmrg if (priv->tiling == I915_TILING_Y && INTEL_INFO(intel)->gen < 060) 191fe8aea9eSmrg return FALSE; 192fe8aea9eSmrg 193fe8aea9eSmrg *tiling_out = priv->tiling; 194fe8aea9eSmrg return TRUE; 195fe8aea9eSmrg} 196fe8aea9eSmrg 19703b705cfSriastradh/** 19803b705cfSriastradh * Sets up hardware state for a series of solid fills. 19903b705cfSriastradh */ 20003b705cfSriastradhstatic Bool 20103b705cfSriastradhintel_uxa_prepare_solid(PixmapPtr pixmap, int alu, Pixel planemask, Pixel fg) 20203b705cfSriastradh{ 20303b705cfSriastradh ScrnInfoPtr scrn = xf86ScreenToScrn(pixmap->drawable.pScreen); 20403b705cfSriastradh intel_screen_private *intel = intel_get_screen_private(scrn); 20503b705cfSriastradh drm_intel_bo *bo_table[] = { 20603b705cfSriastradh NULL, /* batch_bo */ 20713496ba1Ssnj intel_uxa_get_pixmap_bo(pixmap), 20803b705cfSriastradh }; 20903b705cfSriastradh 210fe8aea9eSmrg if (!intel_uxa_check_bo_tiling(intel, pixmap, &intel->BR_tiling[0])) 211fe8aea9eSmrg return FALSE; 212fe8aea9eSmrg 21313496ba1Ssnj if (!intel_uxa_check_pitch_2d(pixmap)) 21403b705cfSriastradh return FALSE; 21503b705cfSriastradh 21613496ba1Ssnj if (!intel_uxa_get_aperture_space(scrn, bo_table, ARRAY_SIZE(bo_table))) 21703b705cfSriastradh return FALSE; 21803b705cfSriastradh 21903b705cfSriastradh intel->BR[13] = (I830PatternROP[alu] & 0xff) << 16; 22003b705cfSriastradh switch (pixmap->drawable.bitsPerPixel) { 22103b705cfSriastradh case 8: 22203b705cfSriastradh break; 22303b705cfSriastradh case 16: 22403b705cfSriastradh /* RGB565 */ 22503b705cfSriastradh intel->BR[13] |= (1 << 24); 22603b705cfSriastradh break; 22703b705cfSriastradh case 32: 22803b705cfSriastradh /* RGB8888 */ 22903b705cfSriastradh intel->BR[13] |= ((1 << 24) | (1 << 25)); 23003b705cfSriastradh break; 23103b705cfSriastradh } 23203b705cfSriastradh intel->BR[16] = fg; 23303b705cfSriastradh 23403b705cfSriastradh return TRUE; 23503b705cfSriastradh} 23603b705cfSriastradh 23703b705cfSriastradhstatic void intel_uxa_solid(PixmapPtr pixmap, int x1, int y1, int x2, int y2) 23803b705cfSriastradh{ 23903b705cfSriastradh ScrnInfoPtr scrn = xf86ScreenToScrn(pixmap->drawable.pScreen); 24003b705cfSriastradh intel_screen_private *intel = intel_get_screen_private(scrn); 24103b705cfSriastradh unsigned long pitch; 24203b705cfSriastradh uint32_t cmd; 24303b705cfSriastradh 24403b705cfSriastradh if (x1 < 0) 24503b705cfSriastradh x1 = 0; 24603b705cfSriastradh if (y1 < 0) 24703b705cfSriastradh y1 = 0; 24803b705cfSriastradh if (x2 > pixmap->drawable.width) 24903b705cfSriastradh x2 = pixmap->drawable.width; 25003b705cfSriastradh if (y2 > pixmap->drawable.height) 25103b705cfSriastradh y2 = pixmap->drawable.height; 25203b705cfSriastradh 25303b705cfSriastradh if (x2 <= x1 || y2 <= y1) 25403b705cfSriastradh return; 25503b705cfSriastradh 25603b705cfSriastradh pitch = intel_pixmap_pitch(pixmap); 25703b705cfSriastradh 25803b705cfSriastradh { 25942542f5fSchristos int len = INTEL_INFO(intel)->gen >= 0100 ? 7 : 6; 260fe8aea9eSmrg BEGIN_BATCH_BLT_TILED(len); 26103b705cfSriastradh 26242542f5fSchristos cmd = XY_COLOR_BLT_CMD | (len - 2); 26303b705cfSriastradh 26403b705cfSriastradh if (pixmap->drawable.bitsPerPixel == 32) 26503b705cfSriastradh cmd |= 26603b705cfSriastradh XY_COLOR_BLT_WRITE_ALPHA | XY_COLOR_BLT_WRITE_RGB; 26703b705cfSriastradh 26813496ba1Ssnj if (INTEL_INFO(intel)->gen >= 040 && intel_uxa_pixmap_tiled(pixmap)) { 26903b705cfSriastradh assert((pitch % 512) == 0); 27003b705cfSriastradh pitch >>= 2; 27103b705cfSriastradh cmd |= XY_COLOR_BLT_TILED; 27203b705cfSriastradh } 27303b705cfSriastradh 27403b705cfSriastradh OUT_BATCH(cmd); 27503b705cfSriastradh 27603b705cfSriastradh OUT_BATCH(intel->BR[13] | pitch); 27703b705cfSriastradh OUT_BATCH((y1 << 16) | (x1 & 0xffff)); 27803b705cfSriastradh OUT_BATCH((y2 << 16) | (x2 & 0xffff)); 27903b705cfSriastradh OUT_RELOC_PIXMAP_FENCED(pixmap, I915_GEM_DOMAIN_RENDER, 28003b705cfSriastradh I915_GEM_DOMAIN_RENDER, 0); 28103b705cfSriastradh OUT_BATCH(intel->BR[16]); 28203b705cfSriastradh ADVANCE_BATCH(); 28303b705cfSriastradh } 28403b705cfSriastradh} 28503b705cfSriastradh 28603b705cfSriastradh/** 28703b705cfSriastradh * TODO: 28803b705cfSriastradh * - support planemask using FULL_BLT_CMD? 28903b705cfSriastradh */ 29003b705cfSriastradhstatic Bool 29103b705cfSriastradhintel_uxa_check_copy(PixmapPtr source, PixmapPtr dest, 29203b705cfSriastradh int alu, Pixel planemask) 29303b705cfSriastradh{ 29403b705cfSriastradh ScrnInfoPtr scrn = xf86ScreenToScrn(dest->drawable.pScreen); 29503b705cfSriastradh 29603b705cfSriastradh if (!UXA_PM_IS_SOLID(&source->drawable, planemask)) { 29713496ba1Ssnj intel_uxa_debug_fallback(scrn, "planemask is not solid"); 29803b705cfSriastradh return FALSE; 29903b705cfSriastradh } 30003b705cfSriastradh 30103b705cfSriastradh if (source->drawable.bitsPerPixel != dest->drawable.bitsPerPixel) { 30213496ba1Ssnj intel_uxa_debug_fallback(scrn, "mixed bpp copies unsupported\n"); 30303b705cfSriastradh return FALSE; 30403b705cfSriastradh } 30503b705cfSriastradh switch (source->drawable.bitsPerPixel) { 30603b705cfSriastradh case 8: 30703b705cfSriastradh case 16: 30803b705cfSriastradh case 32: 30903b705cfSriastradh break; 31003b705cfSriastradh default: 31103b705cfSriastradh return FALSE; 31203b705cfSriastradh } 31303b705cfSriastradh 31413496ba1Ssnj if (!intel_uxa_check_pitch_2d(source)) 31503b705cfSriastradh return FALSE; 31613496ba1Ssnj if (!intel_uxa_check_pitch_2d(dest)) 31703b705cfSriastradh return FALSE; 31803b705cfSriastradh 31903b705cfSriastradh return TRUE; 32003b705cfSriastradh} 32103b705cfSriastradh 32203b705cfSriastradhstatic Bool 32303b705cfSriastradhintel_uxa_prepare_copy(PixmapPtr source, PixmapPtr dest, int xdir, 32403b705cfSriastradh int ydir, int alu, Pixel planemask) 32503b705cfSriastradh{ 32603b705cfSriastradh ScrnInfoPtr scrn = xf86ScreenToScrn(dest->drawable.pScreen); 32703b705cfSriastradh intel_screen_private *intel = intel_get_screen_private(scrn); 32803b705cfSriastradh drm_intel_bo *bo_table[] = { 32903b705cfSriastradh NULL, /* batch_bo */ 33013496ba1Ssnj intel_uxa_get_pixmap_bo(source), 33113496ba1Ssnj intel_uxa_get_pixmap_bo(dest), 33203b705cfSriastradh }; 33303b705cfSriastradh 334fe8aea9eSmrg if (!intel_uxa_check_bo_tiling(intel, dest, &intel->BR_tiling[0]) || 335fe8aea9eSmrg !intel_uxa_check_bo_tiling(intel, source, &intel->BR_tiling[1])) 336fe8aea9eSmrg return FALSE; 337fe8aea9eSmrg 33813496ba1Ssnj if (!intel_uxa_get_aperture_space(scrn, bo_table, ARRAY_SIZE(bo_table))) 33903b705cfSriastradh return FALSE; 34003b705cfSriastradh 34103b705cfSriastradh intel->render_source = source; 34203b705cfSriastradh 34303b705cfSriastradh intel->BR[13] = I830CopyROP[alu] << 16; 34403b705cfSriastradh switch (source->drawable.bitsPerPixel) { 34503b705cfSriastradh case 8: 34603b705cfSriastradh break; 34703b705cfSriastradh case 16: 34803b705cfSriastradh intel->BR[13] |= (1 << 24); 34903b705cfSriastradh break; 35003b705cfSriastradh case 32: 35103b705cfSriastradh intel->BR[13] |= ((1 << 25) | (1 << 24)); 35203b705cfSriastradh break; 35303b705cfSriastradh } 35403b705cfSriastradh 35503b705cfSriastradh return TRUE; 35603b705cfSriastradh} 35703b705cfSriastradh 35803b705cfSriastradhstatic void 35903b705cfSriastradhintel_uxa_copy(PixmapPtr dest, int src_x1, int src_y1, int dst_x1, 36003b705cfSriastradh int dst_y1, int w, int h) 36103b705cfSriastradh{ 36203b705cfSriastradh ScrnInfoPtr scrn = xf86ScreenToScrn(dest->drawable.pScreen); 36303b705cfSriastradh intel_screen_private *intel = intel_get_screen_private(scrn); 36403b705cfSriastradh uint32_t cmd; 36503b705cfSriastradh int dst_x2, dst_y2, src_x2, src_y2; 36603b705cfSriastradh unsigned int dst_pitch, src_pitch; 36703b705cfSriastradh 36803b705cfSriastradh dst_x2 = dst_x1 + w; 36903b705cfSriastradh dst_y2 = dst_y1 + h; 37003b705cfSriastradh 37103b705cfSriastradh /* XXX Fixup extents as a lamentable workaround for missing 37203b705cfSriastradh * source clipping in the upper layers. 37303b705cfSriastradh */ 37403b705cfSriastradh if (dst_x1 < 0) 37503b705cfSriastradh src_x1 -= dst_x1, dst_x1 = 0; 37603b705cfSriastradh if (dst_y1 < 0) 37703b705cfSriastradh src_y1 -= dst_y1, dst_y1 = 0; 37803b705cfSriastradh if (dst_x2 > dest->drawable.width) 37903b705cfSriastradh dst_x2 = dest->drawable.width; 38003b705cfSriastradh if (dst_y2 > dest->drawable.height) 38103b705cfSriastradh dst_y2 = dest->drawable.height; 38203b705cfSriastradh 38303b705cfSriastradh src_x2 = src_x1 + (dst_x2 - dst_x1); 38403b705cfSriastradh src_y2 = src_y1 + (dst_y2 - dst_y1); 38503b705cfSriastradh 38603b705cfSriastradh if (src_x1 < 0) 38703b705cfSriastradh dst_x1 -= src_x1, src_x1 = 0; 38803b705cfSriastradh if (src_y1 < 0) 38903b705cfSriastradh dst_y1 -= src_y1, src_y1 = 0; 39003b705cfSriastradh if (src_x2 > intel->render_source->drawable.width) 39103b705cfSriastradh dst_x2 -= src_x2 - intel->render_source->drawable.width; 39203b705cfSriastradh if (src_y2 > intel->render_source->drawable.height) 39303b705cfSriastradh dst_y2 -= src_y2 - intel->render_source->drawable.height; 39403b705cfSriastradh 39503b705cfSriastradh if (dst_x2 <= dst_x1 || dst_y2 <= dst_y1) 39603b705cfSriastradh return; 39703b705cfSriastradh 39803b705cfSriastradh dst_pitch = intel_pixmap_pitch(dest); 39903b705cfSriastradh src_pitch = intel_pixmap_pitch(intel->render_source); 40003b705cfSriastradh 40103b705cfSriastradh { 40242542f5fSchristos int len = INTEL_INFO(intel)->gen >= 0100 ? 10 : 8; 403fe8aea9eSmrg BEGIN_BATCH_BLT_TILED(len); 40403b705cfSriastradh 40542542f5fSchristos cmd = XY_SRC_COPY_BLT_CMD | (len - 2); 40603b705cfSriastradh 40703b705cfSriastradh if (dest->drawable.bitsPerPixel == 32) 40803b705cfSriastradh cmd |= 40903b705cfSriastradh XY_SRC_COPY_BLT_WRITE_ALPHA | 41003b705cfSriastradh XY_SRC_COPY_BLT_WRITE_RGB; 41103b705cfSriastradh 41203b705cfSriastradh if (INTEL_INFO(intel)->gen >= 040) { 41313496ba1Ssnj if (intel_uxa_pixmap_tiled(dest)) { 41403b705cfSriastradh assert((dst_pitch % 512) == 0); 41503b705cfSriastradh dst_pitch >>= 2; 41603b705cfSriastradh cmd |= XY_SRC_COPY_BLT_DST_TILED; 41703b705cfSriastradh } 41803b705cfSriastradh 41913496ba1Ssnj if (intel_uxa_pixmap_tiled(intel->render_source)) { 42003b705cfSriastradh assert((src_pitch % 512) == 0); 42103b705cfSriastradh src_pitch >>= 2; 42203b705cfSriastradh cmd |= XY_SRC_COPY_BLT_SRC_TILED; 42303b705cfSriastradh } 42403b705cfSriastradh } 42503b705cfSriastradh 42603b705cfSriastradh OUT_BATCH(cmd); 42703b705cfSriastradh 42803b705cfSriastradh OUT_BATCH(intel->BR[13] | dst_pitch); 42903b705cfSriastradh OUT_BATCH((dst_y1 << 16) | (dst_x1 & 0xffff)); 43003b705cfSriastradh OUT_BATCH((dst_y2 << 16) | (dst_x2 & 0xffff)); 43103b705cfSriastradh OUT_RELOC_PIXMAP_FENCED(dest, 43203b705cfSriastradh I915_GEM_DOMAIN_RENDER, 43303b705cfSriastradh I915_GEM_DOMAIN_RENDER, 43403b705cfSriastradh 0); 43503b705cfSriastradh OUT_BATCH((src_y1 << 16) | (src_x1 & 0xffff)); 43603b705cfSriastradh OUT_BATCH(src_pitch); 43703b705cfSriastradh OUT_RELOC_PIXMAP_FENCED(intel->render_source, 43803b705cfSriastradh I915_GEM_DOMAIN_RENDER, 0, 43903b705cfSriastradh 0); 44003b705cfSriastradh 44103b705cfSriastradh ADVANCE_BATCH(); 44203b705cfSriastradh } 44303b705cfSriastradh} 44403b705cfSriastradh 44503b705cfSriastradhstatic void intel_uxa_done(PixmapPtr pixmap) 44603b705cfSriastradh{ 44703b705cfSriastradh ScrnInfoPtr scrn = xf86ScreenToScrn(pixmap->drawable.pScreen); 44803b705cfSriastradh intel_screen_private *intel = intel_get_screen_private(scrn); 44903b705cfSriastradh 45042542f5fSchristos if (INTEL_INFO(intel)->gen >= 060) { 45103b705cfSriastradh /* workaround a random BLT hang */ 45203b705cfSriastradh BEGIN_BATCH_BLT(3); 45342542f5fSchristos OUT_BATCH(XY_SETUP_CLIP_BLT_CMD | (3 - 2)); 45403b705cfSriastradh OUT_BATCH(0); 45503b705cfSriastradh OUT_BATCH(0); 45603b705cfSriastradh ADVANCE_BATCH(); 45703b705cfSriastradh } 45803b705cfSriastradh 45913496ba1Ssnj intel_uxa_debug_flush(scrn); 46003b705cfSriastradh} 46103b705cfSriastradh 46203b705cfSriastradh/** 46303b705cfSriastradh * Do any cleanup from the Composite operation. 46403b705cfSriastradh * 46503b705cfSriastradh * This is shared between i830 through i965. 46603b705cfSriastradh */ 46703b705cfSriastradhstatic void i830_done_composite(PixmapPtr dest) 46803b705cfSriastradh{ 46903b705cfSriastradh ScrnInfoPtr scrn = xf86ScreenToScrn(dest->drawable.pScreen); 47003b705cfSriastradh intel_screen_private *intel = intel_get_screen_private(scrn); 47103b705cfSriastradh 47203b705cfSriastradh if (intel->vertex_flush) 47303b705cfSriastradh intel->vertex_flush(intel); 47403b705cfSriastradh 47513496ba1Ssnj intel_uxa_debug_flush(scrn); 47603b705cfSriastradh} 47703b705cfSriastradh 47803b705cfSriastradh#define xFixedToFloat(val) \ 47903b705cfSriastradh ((float)xFixedToInt(val) + ((float)xFixedFrac(val) / 65536.0)) 48003b705cfSriastradh 48103b705cfSriastradhstatic Bool 48203b705cfSriastradh_intel_transform_point(PictTransformPtr transform, 48303b705cfSriastradh float x, float y, float result[3]) 48403b705cfSriastradh{ 48503b705cfSriastradh int j; 48603b705cfSriastradh 48703b705cfSriastradh for (j = 0; j < 3; j++) { 48803b705cfSriastradh result[j] = (xFixedToFloat(transform->matrix[j][0]) * x + 48903b705cfSriastradh xFixedToFloat(transform->matrix[j][1]) * y + 49003b705cfSriastradh xFixedToFloat(transform->matrix[j][2])); 49103b705cfSriastradh } 49203b705cfSriastradh if (!result[2]) 49303b705cfSriastradh return FALSE; 49403b705cfSriastradh return TRUE; 49503b705cfSriastradh} 49603b705cfSriastradh 49703b705cfSriastradh/** 49803b705cfSriastradh * Returns the floating-point coordinates transformed by the given transform. 49903b705cfSriastradh * 50003b705cfSriastradh * transform may be null. 50103b705cfSriastradh */ 50203b705cfSriastradhBool 50313496ba1Ssnjintel_uxa_get_transformed_coordinates(int x, int y, PictTransformPtr transform, 50403b705cfSriastradh float *x_out, float *y_out) 50503b705cfSriastradh{ 50603b705cfSriastradh if (transform == NULL) { 50703b705cfSriastradh *x_out = x; 50803b705cfSriastradh *y_out = y; 50903b705cfSriastradh } else { 51003b705cfSriastradh float result[3]; 51103b705cfSriastradh 51203b705cfSriastradh if (!_intel_transform_point(transform, 51303b705cfSriastradh x, y, 51403b705cfSriastradh result)) 51503b705cfSriastradh return FALSE; 51603b705cfSriastradh *x_out = result[0] / result[2]; 51703b705cfSriastradh *y_out = result[1] / result[2]; 51803b705cfSriastradh } 51903b705cfSriastradh return TRUE; 52003b705cfSriastradh} 52103b705cfSriastradh 52203b705cfSriastradh/** 52303b705cfSriastradh * Returns the un-normalized floating-point coordinates transformed by the given transform. 52403b705cfSriastradh * 52503b705cfSriastradh * transform may be null. 52603b705cfSriastradh */ 52703b705cfSriastradhBool 52813496ba1Ssnjintel_uxa_get_transformed_coordinates_3d(int x, int y, PictTransformPtr transform, 52903b705cfSriastradh float *x_out, float *y_out, float *w_out) 53003b705cfSriastradh{ 53103b705cfSriastradh if (transform == NULL) { 53203b705cfSriastradh *x_out = x; 53303b705cfSriastradh *y_out = y; 53403b705cfSriastradh *w_out = 1; 53503b705cfSriastradh } else { 53603b705cfSriastradh float result[3]; 53703b705cfSriastradh 53803b705cfSriastradh if (!_intel_transform_point(transform, 53903b705cfSriastradh x, y, 54003b705cfSriastradh result)) 54103b705cfSriastradh return FALSE; 54203b705cfSriastradh *x_out = result[0]; 54303b705cfSriastradh *y_out = result[1]; 54403b705cfSriastradh *w_out = result[2]; 54503b705cfSriastradh } 54603b705cfSriastradh return TRUE; 54703b705cfSriastradh} 54803b705cfSriastradh 54903b705cfSriastradh/** 55003b705cfSriastradh * Returns whether the provided transform is affine. 55103b705cfSriastradh * 55203b705cfSriastradh * transform may be null. 55303b705cfSriastradh */ 55413496ba1SsnjBool intel_uxa_transform_is_affine(PictTransformPtr t) 55503b705cfSriastradh{ 55603b705cfSriastradh if (t == NULL) 55703b705cfSriastradh return TRUE; 55803b705cfSriastradh return t->matrix[2][0] == 0 && t->matrix[2][1] == 0; 55903b705cfSriastradh} 56003b705cfSriastradh 56113496ba1Ssnjdri_bo *intel_uxa_get_pixmap_bo(PixmapPtr pixmap) 56203b705cfSriastradh{ 56313496ba1Ssnj struct intel_uxa_pixmap *intel; 56403b705cfSriastradh 56513496ba1Ssnj intel = intel_uxa_get_pixmap_private(pixmap); 56603b705cfSriastradh if (intel == NULL) 56703b705cfSriastradh return NULL; 56803b705cfSriastradh 56903b705cfSriastradh return intel->bo; 57003b705cfSriastradh} 57103b705cfSriastradh 57242542f5fSchristosstatic unsigned intel_get_tile_width(intel_screen_private *intel, int tiling, int pitch) 57342542f5fSchristos{ 57442542f5fSchristos unsigned long tile_width; 57542542f5fSchristos 57642542f5fSchristos if (tiling == I915_TILING_NONE) 57742542f5fSchristos return 4; 57842542f5fSchristos 57942542f5fSchristos tile_width = (tiling == I915_TILING_Y) ? 128 : 512; 58042542f5fSchristos if (INTEL_INFO(intel)->gen >= 040) 58142542f5fSchristos return tile_width; 58242542f5fSchristos 58342542f5fSchristos while (tile_width < pitch) 58442542f5fSchristos tile_width <<= 1; 58542542f5fSchristos 58642542f5fSchristos return tile_width; 58742542f5fSchristos} 58842542f5fSchristos 58913496ba1Ssnjvoid intel_uxa_set_pixmap_bo(PixmapPtr pixmap, dri_bo * bo) 59003b705cfSriastradh{ 59142542f5fSchristos ScrnInfoPtr scrn = xf86ScreenToScrn(pixmap->drawable.pScreen); 59242542f5fSchristos intel_screen_private *intel = intel_get_screen_private(scrn); 59313496ba1Ssnj struct intel_uxa_pixmap *priv; 59403b705cfSriastradh 59513496ba1Ssnj priv = intel_uxa_get_pixmap_private(pixmap); 59603b705cfSriastradh if (priv == NULL && bo == NULL) 59742542f5fSchristos return; 59803b705cfSriastradh 59903b705cfSriastradh if (priv != NULL) { 60003b705cfSriastradh if (priv->bo == bo) 60103b705cfSriastradh return; 60203b705cfSriastradh 60342542f5fSchristosfree_priv: 60403b705cfSriastradh dri_bo_unreference(priv->bo); 60503b705cfSriastradh list_del(&priv->batch); 60603b705cfSriastradh 60703b705cfSriastradh free(priv); 60803b705cfSriastradh priv = NULL; 60903b705cfSriastradh } 61003b705cfSriastradh 61103b705cfSriastradh if (bo != NULL) { 61242542f5fSchristos uint32_t tiling, swizzle_mode; 61342542f5fSchristos unsigned tile_width; 61442542f5fSchristos int size, stride; 61503b705cfSriastradh 61613496ba1Ssnj priv = calloc(1, sizeof (struct intel_uxa_pixmap)); 61703b705cfSriastradh if (priv == NULL) 61803b705cfSriastradh goto BAIL; 61903b705cfSriastradh 62003b705cfSriastradh list_init(&priv->batch); 62103b705cfSriastradh 62203b705cfSriastradh dri_bo_reference(bo); 62303b705cfSriastradh priv->bo = bo; 62403b705cfSriastradh 62542542f5fSchristos if (drm_intel_bo_get_tiling(bo, &tiling, &swizzle_mode)) { 62642542f5fSchristos bo = NULL; 62742542f5fSchristos goto free_priv; 62803b705cfSriastradh } 62903b705cfSriastradh 63003b705cfSriastradh priv->tiling = tiling; 63103b705cfSriastradh priv->busy = -1; 63203b705cfSriastradh priv->offscreen = 1; 63342542f5fSchristos 63442542f5fSchristos stride = (pixmap->drawable.width * pixmap->drawable.bitsPerPixel + 7) / 8; 63542542f5fSchristos tile_width = intel_get_tile_width(intel, tiling, stride); 63642542f5fSchristos stride = ALIGN(stride, tile_width); 63742542f5fSchristos 63813496ba1Ssnj if (intel_pixmap_pitch(pixmap) < stride || 63913496ba1Ssnj intel_pixmap_pitch(pixmap) & (tile_width - 1) || 64013496ba1Ssnj intel_pixmap_pitch(pixmap) >= KB(32)) { 64142542f5fSchristos xf86DrvMsg(scrn->scrnIndex, X_ERROR, 64242542f5fSchristos "%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", 64313496ba1Ssnj __FUNCTION__, intel_pixmap_pitch(pixmap), stride, KB(32), tile_width); 64442542f5fSchristos bo = NULL; 64542542f5fSchristos goto free_priv; 64642542f5fSchristos } 64742542f5fSchristos 64842542f5fSchristos if (tiling != I915_TILING_NONE) { 64942542f5fSchristos int height; 65042542f5fSchristos 65142542f5fSchristos if (IS_GEN2(intel)) 65242542f5fSchristos height = 16; 65342542f5fSchristos else if (tiling == I915_TILING_X) 65442542f5fSchristos height = 8; 65542542f5fSchristos else 65642542f5fSchristos height = 32; 65742542f5fSchristos 65813496ba1Ssnj height = ALIGN(pixmap->drawable.height, height); 65913496ba1Ssnj size = intel_get_fence_size(intel, intel_pixmap_pitch(pixmap) * height); 66042542f5fSchristos } else 66113496ba1Ssnj size = intel_pixmap_pitch(pixmap) * pixmap->drawable.height; 66242542f5fSchristos 66342542f5fSchristos if (bo->size < size || bo->size > intel->max_bo_size) { 66442542f5fSchristos xf86DrvMsg(scrn->scrnIndex, X_ERROR, 66542542f5fSchristos "%s: size of buffer object does not match constraints: size=%ld, must be greater than %d, but less than %d\n", 66642542f5fSchristos __FUNCTION__, (long)bo->size, size, intel->max_bo_size); 66742542f5fSchristos bo = NULL; 66842542f5fSchristos goto free_priv; 66942542f5fSchristos } 67003b705cfSriastradh } 67103b705cfSriastradh 67203b705cfSriastradh BAIL: 67313496ba1Ssnj intel_uxa_set_pixmap_private(pixmap, priv); 67403b705cfSriastradh} 67503b705cfSriastradh 67603b705cfSriastradhstatic Bool intel_uxa_prepare_access(PixmapPtr pixmap, uxa_access_t access) 67703b705cfSriastradh{ 67803b705cfSriastradh ScrnInfoPtr scrn = xf86ScreenToScrn(pixmap->drawable.pScreen); 67903b705cfSriastradh intel_screen_private *intel = intel_get_screen_private(scrn); 68013496ba1Ssnj struct intel_uxa_pixmap *priv = intel_uxa_get_pixmap_private(pixmap); 68103b705cfSriastradh dri_bo *bo = priv->bo; 68203b705cfSriastradh int ret; 68303b705cfSriastradh 68403b705cfSriastradh /* When falling back to swrast, flush all pending operations */ 68503b705cfSriastradh if (access == UXA_ACCESS_RW || priv->dirty) 68603b705cfSriastradh intel_batch_submit(scrn); 68703b705cfSriastradh 68803b705cfSriastradh assert(bo->size <= intel->max_gtt_map_size); 68903b705cfSriastradh ret = drm_intel_gem_bo_map_gtt(bo); 69003b705cfSriastradh if (ret) { 69103b705cfSriastradh xf86DrvMsg(scrn->scrnIndex, X_WARNING, 69203b705cfSriastradh "%s: bo map (use gtt? %d, access %d) failed: %s\n", 69303b705cfSriastradh __FUNCTION__, 69403b705cfSriastradh priv->tiling || bo->size <= intel->max_gtt_map_size, 69503b705cfSriastradh access, 69603b705cfSriastradh strerror(-ret)); 69703b705cfSriastradh return FALSE; 69803b705cfSriastradh } 69903b705cfSriastradh 70003b705cfSriastradh pixmap->devPrivate.ptr = bo->virtual; 70103b705cfSriastradh priv->busy = 0; 70203b705cfSriastradh 70303b705cfSriastradh return TRUE; 70403b705cfSriastradh} 70503b705cfSriastradh 70603b705cfSriastradhstatic void intel_uxa_finish_access(PixmapPtr pixmap, uxa_access_t access) 70703b705cfSriastradh{ 70813496ba1Ssnj struct intel_uxa_pixmap *priv; 70903b705cfSriastradh 71013496ba1Ssnj priv = intel_uxa_get_pixmap_private(pixmap); 71103b705cfSriastradh if (priv == NULL) 71203b705cfSriastradh return; 71303b705cfSriastradh 71403b705cfSriastradh drm_intel_gem_bo_unmap_gtt(priv->bo); 71503b705cfSriastradh pixmap->devPrivate.ptr = NULL; 71603b705cfSriastradh} 71703b705cfSriastradh 71803b705cfSriastradhstatic Bool intel_uxa_pixmap_put_image(PixmapPtr pixmap, 71903b705cfSriastradh char *src, int src_pitch, 72003b705cfSriastradh int x, int y, int w, int h) 72103b705cfSriastradh{ 72213496ba1Ssnj struct intel_uxa_pixmap *priv = intel_uxa_get_pixmap_private(pixmap); 72303b705cfSriastradh int stride = intel_pixmap_pitch(pixmap); 72403b705cfSriastradh int cpp = pixmap->drawable.bitsPerPixel/8; 72503b705cfSriastradh int ret = FALSE; 72603b705cfSriastradh 72703b705cfSriastradh if (priv == NULL || priv->bo == NULL) 72803b705cfSriastradh return FALSE; 72903b705cfSriastradh 73003b705cfSriastradh if (priv->tiling == I915_TILING_NONE && 73103b705cfSriastradh (h == 1 || (src_pitch == stride && w == pixmap->drawable.width))) { 73203b705cfSriastradh return drm_intel_bo_subdata(priv->bo, y*stride + x*cpp, stride*(h-1) + w*cpp, src) == 0; 73303b705cfSriastradh } else if (drm_intel_gem_bo_map_gtt(priv->bo) == 0) { 73403b705cfSriastradh char *dst = priv->bo->virtual; 73503b705cfSriastradh int row_length = w * cpp; 73603b705cfSriastradh int num_rows = h; 73703b705cfSriastradh if (row_length == src_pitch && src_pitch == stride) 73803b705cfSriastradh num_rows = 1, row_length *= h; 73903b705cfSriastradh dst += y * stride + x * cpp; 74003b705cfSriastradh do { 74103b705cfSriastradh memcpy (dst, src, row_length); 74203b705cfSriastradh src += src_pitch; 74303b705cfSriastradh dst += stride; 74403b705cfSriastradh } while (--num_rows); 74503b705cfSriastradh drm_intel_gem_bo_unmap_gtt(priv->bo); 74603b705cfSriastradh ret = TRUE; 74703b705cfSriastradh } 74803b705cfSriastradh 74903b705cfSriastradh return ret; 75003b705cfSriastradh} 75103b705cfSriastradh 75203b705cfSriastradhstatic Bool intel_uxa_put_image(PixmapPtr pixmap, 75303b705cfSriastradh int x, int y, 75403b705cfSriastradh int w, int h, 75503b705cfSriastradh char *src, int src_pitch) 75603b705cfSriastradh{ 75713496ba1Ssnj struct intel_uxa_pixmap *priv; 75803b705cfSriastradh 75913496ba1Ssnj priv = intel_uxa_get_pixmap_private(pixmap); 76013496ba1Ssnj if (!intel_uxa_pixmap_is_busy(priv)) { 76103b705cfSriastradh /* bo is not busy so can be replaced without a stall, upload in-place. */ 76203b705cfSriastradh return intel_uxa_pixmap_put_image(pixmap, src, src_pitch, x, y, w, h); 76303b705cfSriastradh } else { 76403b705cfSriastradh ScreenPtr screen = pixmap->drawable.pScreen; 76503b705cfSriastradh 76603b705cfSriastradh if (!priv->pinned && 76703b705cfSriastradh x == 0 && y == 0 && 76803b705cfSriastradh w == pixmap->drawable.width && 76903b705cfSriastradh h == pixmap->drawable.height) 77003b705cfSriastradh { 77103b705cfSriastradh intel_screen_private *intel = intel_get_screen_private(xf86ScreenToScrn(screen)); 77203b705cfSriastradh uint32_t tiling = priv->tiling; 77303b705cfSriastradh int size, stride; 77403b705cfSriastradh dri_bo *bo; 77503b705cfSriastradh 77603b705cfSriastradh /* Replace busy bo. */ 77713496ba1Ssnj size = intel_compute_size(intel, 77813496ba1Ssnj w, h, 77913496ba1Ssnj pixmap->drawable.bitsPerPixel, pixmap->usage_hint, 78013496ba1Ssnj &tiling, &stride); 78103b705cfSriastradh if (size > intel->max_gtt_map_size) 78203b705cfSriastradh return FALSE; 78303b705cfSriastradh 78403b705cfSriastradh bo = drm_intel_bo_alloc(intel->bufmgr, "pixmap", size, 0); 78503b705cfSriastradh if (bo == NULL) 78603b705cfSriastradh return FALSE; 78703b705cfSriastradh 78803b705cfSriastradh if (tiling != I915_TILING_NONE) 78903b705cfSriastradh drm_intel_bo_set_tiling(bo, &tiling, stride); 79003b705cfSriastradh priv->tiling = tiling; 79103b705cfSriastradh 79203b705cfSriastradh screen->ModifyPixmapHeader(pixmap, 79303b705cfSriastradh w, h, 79403b705cfSriastradh 0, 0, 79503b705cfSriastradh stride, NULL); 79613496ba1Ssnj intel_uxa_set_pixmap_bo(pixmap, bo); 79703b705cfSriastradh dri_bo_unreference(bo); 79803b705cfSriastradh 79903b705cfSriastradh return intel_uxa_pixmap_put_image(pixmap, src, src_pitch, 0, 0, w, h); 80003b705cfSriastradh } 80103b705cfSriastradh else 80203b705cfSriastradh { 80303b705cfSriastradh PixmapPtr scratch; 80403b705cfSriastradh Bool ret; 80503b705cfSriastradh 80603b705cfSriastradh /* Upload to a linear buffer and queue a blit. */ 80703b705cfSriastradh scratch = (*screen->CreatePixmap)(screen, w, h, 80803b705cfSriastradh pixmap->drawable.depth, 80903b705cfSriastradh UXA_CREATE_PIXMAP_FOR_MAP); 81003b705cfSriastradh if (!scratch) 81103b705cfSriastradh return FALSE; 81203b705cfSriastradh 81303b705cfSriastradh if (!intel_uxa_pixmap_is_offscreen(scratch)) { 81403b705cfSriastradh screen->DestroyPixmap(scratch); 81503b705cfSriastradh return FALSE; 81603b705cfSriastradh } 81703b705cfSriastradh 81803b705cfSriastradh ret = intel_uxa_pixmap_put_image(scratch, src, src_pitch, 0, 0, w, h); 81903b705cfSriastradh if (ret) { 82003b705cfSriastradh GCPtr gc = GetScratchGC(pixmap->drawable.depth, screen); 82103b705cfSriastradh if (gc) { 82203b705cfSriastradh ValidateGC(&pixmap->drawable, gc); 82303b705cfSriastradh 82403b705cfSriastradh (*gc->ops->CopyArea)(&scratch->drawable, 82503b705cfSriastradh &pixmap->drawable, 82603b705cfSriastradh gc, 0, 0, w, h, x, y); 82703b705cfSriastradh 82803b705cfSriastradh FreeScratchGC(gc); 82903b705cfSriastradh } else 83003b705cfSriastradh ret = FALSE; 83103b705cfSriastradh } 83203b705cfSriastradh 83303b705cfSriastradh (*screen->DestroyPixmap)(scratch); 83403b705cfSriastradh return ret; 83503b705cfSriastradh } 83603b705cfSriastradh } 83703b705cfSriastradh} 83803b705cfSriastradh 83903b705cfSriastradhstatic Bool intel_uxa_pixmap_get_image(PixmapPtr pixmap, 84003b705cfSriastradh int x, int y, int w, int h, 84103b705cfSriastradh char *dst, int dst_pitch) 84203b705cfSriastradh{ 84313496ba1Ssnj struct intel_uxa_pixmap *priv = intel_uxa_get_pixmap_private(pixmap); 84403b705cfSriastradh int stride = intel_pixmap_pitch(pixmap); 84503b705cfSriastradh int cpp = pixmap->drawable.bitsPerPixel/8; 84603b705cfSriastradh 84703b705cfSriastradh /* assert(priv->tiling == I915_TILING_NONE); */ 84803b705cfSriastradh if (h == 1 || (dst_pitch == stride && w == pixmap->drawable.width)) { 84903b705cfSriastradh return drm_intel_bo_get_subdata(priv->bo, y*stride + x*cpp, (h-1)*stride + w*cpp, dst) == 0; 85003b705cfSriastradh } else { 85103b705cfSriastradh char *src; 85203b705cfSriastradh 85303b705cfSriastradh if (drm_intel_gem_bo_map_gtt(priv->bo)) 85403b705cfSriastradh return FALSE; 85503b705cfSriastradh 85603b705cfSriastradh src = (char *) priv->bo->virtual + y * stride + x * cpp; 85703b705cfSriastradh w *= cpp; 85803b705cfSriastradh do { 85903b705cfSriastradh memcpy(dst, src, w); 86003b705cfSriastradh src += stride; 86103b705cfSriastradh dst += dst_pitch; 86203b705cfSriastradh } while (--h); 86303b705cfSriastradh 86403b705cfSriastradh drm_intel_gem_bo_unmap_gtt(priv->bo); 86503b705cfSriastradh 86603b705cfSriastradh return TRUE; 86703b705cfSriastradh } 86803b705cfSriastradh} 86903b705cfSriastradh 87003b705cfSriastradhstatic Bool intel_uxa_get_image(PixmapPtr pixmap, 87103b705cfSriastradh int x, int y, 87203b705cfSriastradh int w, int h, 87303b705cfSriastradh char *dst, int dst_pitch) 87403b705cfSriastradh{ 87513496ba1Ssnj struct intel_uxa_pixmap *priv; 87603b705cfSriastradh PixmapPtr scratch = NULL; 87703b705cfSriastradh Bool ret; 87803b705cfSriastradh 87903b705cfSriastradh /* The presumption is that we wish to keep the target hot, so 88003b705cfSriastradh * copy to a new bo and move that to the CPU in preference to 88103b705cfSriastradh * causing ping-pong of the original. 88203b705cfSriastradh * 88303b705cfSriastradh * Also the gpu is much faster at detiling. 88403b705cfSriastradh */ 88503b705cfSriastradh 88613496ba1Ssnj priv = intel_uxa_get_pixmap_private(pixmap); 88713496ba1Ssnj if (intel_uxa_pixmap_is_busy(priv) || priv->tiling != I915_TILING_NONE) { 88803b705cfSriastradh ScreenPtr screen = pixmap->drawable.pScreen; 88903b705cfSriastradh GCPtr gc; 89003b705cfSriastradh 89103b705cfSriastradh /* Copy to a linear buffer and pull. */ 89203b705cfSriastradh scratch = screen->CreatePixmap(screen, w, h, 89303b705cfSriastradh pixmap->drawable.depth, 89403b705cfSriastradh INTEL_CREATE_PIXMAP_TILING_NONE); 89503b705cfSriastradh if (!scratch) 89603b705cfSriastradh return FALSE; 89703b705cfSriastradh 89803b705cfSriastradh if (!intel_uxa_pixmap_is_offscreen(scratch)) { 89903b705cfSriastradh screen->DestroyPixmap(scratch); 90003b705cfSriastradh return FALSE; 90103b705cfSriastradh } 90203b705cfSriastradh 90303b705cfSriastradh gc = GetScratchGC(pixmap->drawable.depth, screen); 90403b705cfSriastradh if (!gc) { 90503b705cfSriastradh screen->DestroyPixmap(scratch); 90603b705cfSriastradh return FALSE; 90703b705cfSriastradh } 90803b705cfSriastradh 90903b705cfSriastradh ValidateGC(&pixmap->drawable, gc); 91003b705cfSriastradh 91103b705cfSriastradh gc->ops->CopyArea(&pixmap->drawable, 91203b705cfSriastradh &scratch->drawable, 91303b705cfSriastradh gc, x, y, w, h, 0, 0); 91403b705cfSriastradh 91503b705cfSriastradh FreeScratchGC(gc); 91603b705cfSriastradh 91703b705cfSriastradh intel_batch_submit(xf86ScreenToScrn(screen)); 91803b705cfSriastradh 91903b705cfSriastradh x = y = 0; 92003b705cfSriastradh pixmap = scratch; 92103b705cfSriastradh } 92203b705cfSriastradh 92303b705cfSriastradh ret = intel_uxa_pixmap_get_image(pixmap, x, y, w, h, dst, dst_pitch); 92403b705cfSriastradh 92503b705cfSriastradh if (scratch) 92603b705cfSriastradh scratch->drawable.pScreen->DestroyPixmap(scratch); 92703b705cfSriastradh 92803b705cfSriastradh return ret; 92903b705cfSriastradh} 93003b705cfSriastradh 93103b705cfSriastradhstatic CARD32 intel_cache_expire(OsTimerPtr timer, CARD32 now, pointer data) 93203b705cfSriastradh{ 93303b705cfSriastradh intel_screen_private *intel = data; 93403b705cfSriastradh 93503b705cfSriastradh /* We just want to create and destroy a bo as this causes libdrm 93603b705cfSriastradh * to reap its caches. However, since we can't remove that buffer 93703b705cfSriastradh * from the cache due to its own activity, we want to use something 93803b705cfSriastradh * that we know we will reuse later. The most frequently reused buffer 93903b705cfSriastradh * we have is the batchbuffer, and the best way to trigger its 94003b705cfSriastradh * reallocation is to submit a flush. 94103b705cfSriastradh */ 94203b705cfSriastradh intel_batch_emit_flush(intel->scrn); 94303b705cfSriastradh intel_batch_submit(intel->scrn); 94403b705cfSriastradh 94503b705cfSriastradh return 0; 94603b705cfSriastradh} 94703b705cfSriastradh 94803b705cfSriastradhstatic void intel_flush_rendering(intel_screen_private *intel) 94903b705cfSriastradh{ 95003b705cfSriastradh if (intel->needs_flush == 0) 95103b705cfSriastradh return; 95203b705cfSriastradh 95303b705cfSriastradh if (intel->has_kernel_flush) { 95403b705cfSriastradh intel_batch_submit(intel->scrn); 95503b705cfSriastradh drm_intel_bo_busy(intel->front_buffer); 95603b705cfSriastradh } else { 95703b705cfSriastradh intel_batch_emit_flush(intel->scrn); 95803b705cfSriastradh intel_batch_submit(intel->scrn); 95903b705cfSriastradh } 96003b705cfSriastradh 96103b705cfSriastradh intel->cache_expire = TimerSet(intel->cache_expire, 0, 3000, 96203b705cfSriastradh intel_cache_expire, intel); 96303b705cfSriastradh 96403b705cfSriastradh intel->needs_flush = 0; 96503b705cfSriastradh} 96603b705cfSriastradh 96703b705cfSriastradhstatic void intel_throttle(intel_screen_private *intel) 96803b705cfSriastradh{ 96903b705cfSriastradh drmCommandNone(intel->drmSubFD, DRM_I915_GEM_THROTTLE); 97003b705cfSriastradh} 97103b705cfSriastradh 97203b705cfSriastradhvoid intel_uxa_block_handler(intel_screen_private *intel) 97303b705cfSriastradh{ 97403b705cfSriastradh /* Emit a flush of the rendering cache, or on the 965 97503b705cfSriastradh * and beyond rendering results may not hit the 97603b705cfSriastradh * framebuffer until significantly later. 97703b705cfSriastradh */ 97803b705cfSriastradh intel_flush_rendering(intel); 97903b705cfSriastradh intel_throttle(intel); 98003b705cfSriastradh} 98103b705cfSriastradh 98203b705cfSriastradhstatic PixmapPtr 98303b705cfSriastradhintel_uxa_create_pixmap(ScreenPtr screen, int w, int h, int depth, 98403b705cfSriastradh unsigned usage) 98503b705cfSriastradh{ 98603b705cfSriastradh ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 98703b705cfSriastradh intel_screen_private *intel = intel_get_screen_private(scrn); 98813496ba1Ssnj struct intel_uxa_pixmap *priv; 98903b705cfSriastradh PixmapPtr pixmap, new_pixmap = NULL; 99003b705cfSriastradh 99103b705cfSriastradh if (w > 32767 || h > 32767) 99203b705cfSriastradh return NullPixmap; 99303b705cfSriastradh 99403b705cfSriastradh if (depth == 1 || intel->force_fallback) 99503b705cfSriastradh return fbCreatePixmap(screen, w, h, depth, usage); 99603b705cfSriastradh 99703b705cfSriastradh if (usage == CREATE_PIXMAP_USAGE_GLYPH_PICTURE && w <= 32 && h <= 32) 99803b705cfSriastradh return fbCreatePixmap(screen, w, h, depth, usage); 99903b705cfSriastradh 100003b705cfSriastradh pixmap = fbCreatePixmap(screen, 0, 0, depth, usage); 100103b705cfSriastradh if (pixmap == NullPixmap) 100203b705cfSriastradh return pixmap; 100303b705cfSriastradh 100403b705cfSriastradh if (w && h) { 100503b705cfSriastradh unsigned int size, tiling; 100603b705cfSriastradh int stride; 100703b705cfSriastradh 100803b705cfSriastradh /* Always attempt to tile, compute_size() will remove the 100903b705cfSriastradh * tiling for pixmaps that are either too large or too small 101003b705cfSriastradh * to be effectively tiled. 101103b705cfSriastradh */ 101203b705cfSriastradh tiling = I915_TILING_X; 101303b705cfSriastradh if (usage & INTEL_CREATE_PIXMAP_TILING_Y) 101403b705cfSriastradh tiling = I915_TILING_Y; 101503b705cfSriastradh if (usage == UXA_CREATE_PIXMAP_FOR_MAP || usage & INTEL_CREATE_PIXMAP_TILING_NONE) 101603b705cfSriastradh tiling = I915_TILING_NONE; 101703b705cfSriastradh 101803b705cfSriastradh#ifdef CREATE_PIXMAP_USAGE_SHARED 101903b705cfSriastradh if (usage == CREATE_PIXMAP_USAGE_SHARED) 102003b705cfSriastradh tiling = I915_TILING_NONE; 102103b705cfSriastradh#endif 102203b705cfSriastradh /* if tiling is off force to none */ 102303b705cfSriastradh if (!intel->tiling) 102403b705cfSriastradh tiling = I915_TILING_NONE; 102503b705cfSriastradh 102603b705cfSriastradh if (tiling != I915_TILING_NONE && !(usage & INTEL_CREATE_PIXMAP_DRI2)) { 102703b705cfSriastradh if (h <= 4) 102803b705cfSriastradh tiling = I915_TILING_NONE; 102903b705cfSriastradh if (h <= 16 && tiling == I915_TILING_Y) 103003b705cfSriastradh tiling = I915_TILING_X; 103103b705cfSriastradh } 103213496ba1Ssnj size = intel_compute_size(intel, 103313496ba1Ssnj w, h, pixmap->drawable.bitsPerPixel, usage, 103413496ba1Ssnj &tiling, &stride); 103503b705cfSriastradh 103603b705cfSriastradh /* Fail very large allocations. Large BOs will tend to hit SW fallbacks 103703b705cfSriastradh * frequently, and also will tend to fail to successfully map when doing 103803b705cfSriastradh * SW fallbacks because we overcommit address space for BO access. 103903b705cfSriastradh */ 104003b705cfSriastradh if (size > intel->max_bo_size || stride >= KB(32)) 104103b705cfSriastradh goto fallback_pixmap; 104203b705cfSriastradh 104313496ba1Ssnj priv = calloc(1, sizeof (struct intel_uxa_pixmap)); 104403b705cfSriastradh if (priv == NULL) 104503b705cfSriastradh goto fallback_pixmap; 104603b705cfSriastradh 104703b705cfSriastradh if (usage == UXA_CREATE_PIXMAP_FOR_MAP) { 104803b705cfSriastradh priv->busy = 0; 104903b705cfSriastradh priv->bo = drm_intel_bo_alloc(intel->bufmgr, 105003b705cfSriastradh "pixmap", size, 0); 105103b705cfSriastradh } else { 105203b705cfSriastradh priv->busy = -1; 105303b705cfSriastradh priv->bo = drm_intel_bo_alloc_for_render(intel->bufmgr, 105403b705cfSriastradh "pixmap", 105503b705cfSriastradh size, 0); 105603b705cfSriastradh } 105703b705cfSriastradh if (!priv->bo) 105803b705cfSriastradh goto fallback_priv; 105903b705cfSriastradh 106003b705cfSriastradh if (tiling != I915_TILING_NONE) 106103b705cfSriastradh drm_intel_bo_set_tiling(priv->bo, &tiling, stride); 106203b705cfSriastradh priv->tiling = tiling; 106303b705cfSriastradh priv->offscreen = 1; 106403b705cfSriastradh 106503b705cfSriastradh list_init(&priv->batch); 106613496ba1Ssnj intel_uxa_set_pixmap_private(pixmap, priv); 106703b705cfSriastradh 106803b705cfSriastradh screen->ModifyPixmapHeader(pixmap, w, h, 0, 0, stride, NULL); 106903b705cfSriastradh } 107003b705cfSriastradh 107103b705cfSriastradh return pixmap; 107203b705cfSriastradh 107303b705cfSriastradhfallback_priv: 107403b705cfSriastradh free(priv); 107503b705cfSriastradhfallback_pixmap: 107603b705cfSriastradh fbDestroyPixmap(pixmap); 107703b705cfSriastradh if (new_pixmap) 107803b705cfSriastradh return new_pixmap; 107903b705cfSriastradh else 108003b705cfSriastradh return fbCreatePixmap(screen, w, h, depth, usage); 108103b705cfSriastradh} 108203b705cfSriastradh 108303b705cfSriastradhstatic Bool intel_uxa_destroy_pixmap(PixmapPtr pixmap) 108403b705cfSriastradh{ 108513496ba1Ssnj if (pixmap->refcnt == 1) 108613496ba1Ssnj intel_uxa_set_pixmap_bo(pixmap, NULL); 108703b705cfSriastradh fbDestroyPixmap(pixmap); 108803b705cfSriastradh return TRUE; 108903b705cfSriastradh} 109003b705cfSriastradh 109103b705cfSriastradhBool intel_uxa_create_screen_resources(ScreenPtr screen) 109203b705cfSriastradh{ 109303b705cfSriastradh ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 109403b705cfSriastradh PixmapPtr pixmap; 109503b705cfSriastradh intel_screen_private *intel = intel_get_screen_private(scrn); 1096fe8aea9eSmrg dri_bo *bo = intel->front_buffer, *old_bo; 109742542f5fSchristos int old_width, old_height, old_pitch; 109803b705cfSriastradh 109903b705cfSriastradh if (!uxa_resources_init(screen)) 110003b705cfSriastradh return FALSE; 110103b705cfSriastradh 110203b705cfSriastradh if (drm_intel_gem_bo_map_gtt(bo)) 110303b705cfSriastradh return FALSE; 110403b705cfSriastradh 110503b705cfSriastradh pixmap = screen->GetScreenPixmap(screen); 110642542f5fSchristos old_width = pixmap->drawable.width; 110742542f5fSchristos old_height = pixmap->drawable.height; 110842542f5fSchristos old_pitch = pixmap->devKind; 1109fe8aea9eSmrg old_bo = intel_uxa_get_pixmap_bo(pixmap); 111042542f5fSchristos 111142542f5fSchristos if (!screen->ModifyPixmapHeader(pixmap, 111242542f5fSchristos scrn->virtualX, 111342542f5fSchristos scrn->virtualY, 111442542f5fSchristos -1, -1, 111542542f5fSchristos intel->front_pitch, 111642542f5fSchristos NULL)) 111742542f5fSchristos return FALSE; 111842542f5fSchristos 111913496ba1Ssnj intel_uxa_set_pixmap_bo(pixmap, bo); 112013496ba1Ssnj if (intel_uxa_get_pixmap_private(pixmap) == NULL) 112142542f5fSchristos goto err; 112203b705cfSriastradh 112313496ba1Ssnj intel_uxa_get_pixmap_private(pixmap)->pinned |= PIN_SCANOUT; 112442542f5fSchristos scrn->displayWidth = intel->front_pitch / intel->cpp; 112503b705cfSriastradh 112603b705cfSriastradh return TRUE; 112742542f5fSchristos 112842542f5fSchristoserr: 112942542f5fSchristos screen->ModifyPixmapHeader(pixmap, 113042542f5fSchristos old_width, old_height, -1, -1, old_pitch, NULL); 1131fe8aea9eSmrg if (old_bo) 1132fe8aea9eSmrg intel_uxa_set_pixmap_bo(pixmap, old_bo); 1133fe8aea9eSmrg 113442542f5fSchristos return FALSE; 113503b705cfSriastradh} 113603b705cfSriastradh 113703b705cfSriastradh#ifdef CREATE_PIXMAP_USAGE_SHARED 113803b705cfSriastradhstatic Bool 113903b705cfSriastradhintel_uxa_share_pixmap_backing(PixmapPtr ppix, ScreenPtr slave, void **fd_handle) 114003b705cfSriastradh{ 114103b705cfSriastradh ScrnInfoPtr scrn = xf86ScreenToScrn(ppix->drawable.pScreen); 114203b705cfSriastradh intel_screen_private *intel = intel_get_screen_private(scrn); 114313496ba1Ssnj struct intel_uxa_pixmap *priv = intel_uxa_get_pixmap_private(ppix); 114403b705cfSriastradh unsigned int size, tiling, swizzle; 114513496ba1Ssnj dri_bo *bo = intel_uxa_get_pixmap_bo(ppix), *newbo; 114603b705cfSriastradh int stride; 114703b705cfSriastradh int handle; 114803b705cfSriastradh 114903b705cfSriastradh if (drm_intel_bo_references(intel->batch_bo, bo)) 115003b705cfSriastradh intel_batch_submit(intel->scrn); 115103b705cfSriastradh 115203b705cfSriastradh drm_intel_bo_get_tiling(bo, &tiling, &swizzle); 115303b705cfSriastradh 115403b705cfSriastradh if (tiling == I915_TILING_X) { 115542542f5fSchristos if (priv->pinned) 115603b705cfSriastradh return FALSE; 115703b705cfSriastradh 115803b705cfSriastradh tiling = I915_TILING_NONE; 115903b705cfSriastradh 116013496ba1Ssnj size = intel_compute_size(intel, 116113496ba1Ssnj ppix->drawable.width, ppix->drawable.height, 116213496ba1Ssnj ppix->drawable.bitsPerPixel, INTEL_CREATE_PIXMAP_DRI2, 116313496ba1Ssnj &tiling, &stride); 116403b705cfSriastradh 116503b705cfSriastradh newbo = drm_intel_bo_alloc_for_render(intel->bufmgr, 116603b705cfSriastradh "pixmap", 116703b705cfSriastradh size, 0); 116803b705cfSriastradh 116903b705cfSriastradh if (tiling != I915_TILING_NONE) 117003b705cfSriastradh drm_intel_bo_set_tiling(newbo, &tiling, stride); 117103b705cfSriastradh priv->tiling = tiling; 117213496ba1Ssnj intel_uxa_set_pixmap_bo(ppix, newbo); 117303b705cfSriastradh 117403b705cfSriastradh ppix->drawable.pScreen->ModifyPixmapHeader(ppix, ppix->drawable.width, 117503b705cfSriastradh ppix->drawable.height, 0, 0, 117603b705cfSriastradh stride, NULL); 117703b705cfSriastradh bo = newbo; 117803b705cfSriastradh } 117903b705cfSriastradh drm_intel_bo_get_tiling(bo, &tiling, &swizzle); 118003b705cfSriastradh drm_intel_bo_gem_export_to_prime(bo, &handle); 118142542f5fSchristos priv->pinned |= PIN_PRIME; 118203b705cfSriastradh 118303b705cfSriastradh *fd_handle = (void *)(long)handle; 118403b705cfSriastradh return TRUE; 118503b705cfSriastradh} 118603b705cfSriastradh 118703b705cfSriastradhstatic Bool 118803b705cfSriastradhintel_uxa_set_shared_pixmap_backing(PixmapPtr ppix, void *fd_handle) 118903b705cfSriastradh{ 119003b705cfSriastradh ScrnInfoPtr scrn = xf86ScreenToScrn(ppix->drawable.pScreen); 119103b705cfSriastradh intel_screen_private *intel = intel_get_screen_private(scrn); 119203b705cfSriastradh dri_bo *bo; 119303b705cfSriastradh int ihandle = (int)(long)fd_handle; 119403b705cfSriastradh 119503b705cfSriastradh /* force untiled for now */ 119603b705cfSriastradh bo = drm_intel_bo_gem_create_from_prime(intel->bufmgr, ihandle, 0); 119703b705cfSriastradh if (!bo) 119803b705cfSriastradh return FALSE; 119903b705cfSriastradh 120013496ba1Ssnj intel_uxa_set_pixmap_bo(ppix, bo); 120103b705cfSriastradh close(ihandle); 120203b705cfSriastradh return TRUE; 120303b705cfSriastradh} 120403b705cfSriastradh#endif 120503b705cfSriastradh 120603b705cfSriastradhstatic void 120703b705cfSriastradhintel_limits_init(intel_screen_private *intel) 120803b705cfSriastradh{ 120903b705cfSriastradh /* Limits are described in the BLT engine chapter under Graphics Data Size 121003b705cfSriastradh * Limitations, and the descriptions of SURFACE_STATE, 3DSTATE_BUFFER_INFO, 121103b705cfSriastradh * 3DSTATE_DRAWING_RECTANGLE, 3DSTATE_MAP_INFO, and 3DSTATE_MAP_INFO. 121203b705cfSriastradh * 121303b705cfSriastradh * i845 through i965 limits 2D rendering to 65536 lines and pitch of 32768. 121403b705cfSriastradh * 121503b705cfSriastradh * i965 limits 3D surface to (2*element size)-aligned offset if un-tiled. 121603b705cfSriastradh * i965 limits 3D surface to 4kB-aligned offset if tiled. 121703b705cfSriastradh * i965 limits 3D surfaces to w,h of ?,8192. 121803b705cfSriastradh * i965 limits 3D surface to pitch of 1B - 128kB. 121903b705cfSriastradh * i965 limits 3D surface pitch alignment to 1 or 2 times the element size. 122003b705cfSriastradh * i965 limits 3D surface pitch alignment to 512B if tiled. 122103b705cfSriastradh * i965 limits 3D destination drawing rect to w,h of 8192,8192. 122203b705cfSriastradh * 122303b705cfSriastradh * i915 limits 3D textures to 4B-aligned offset if un-tiled. 122403b705cfSriastradh * i915 limits 3D textures to ~4kB-aligned offset if tiled. 122503b705cfSriastradh * i915 limits 3D textures to width,height of 2048,2048. 122603b705cfSriastradh * i915 limits 3D textures to pitch of 16B - 8kB, in dwords. 122703b705cfSriastradh * i915 limits 3D destination to ~4kB-aligned offset if tiled. 122803b705cfSriastradh * i915 limits 3D destination to pitch of 16B - 8kB, in dwords, if un-tiled. 122903b705cfSriastradh * i915 limits 3D destination to pitch 64B-aligned if used with depth. 123003b705cfSriastradh * i915 limits 3D destination to pitch of 512B - 8kB, in tiles, if tiled. 123103b705cfSriastradh * i915 limits 3D destination to POT aligned pitch if tiled. 123203b705cfSriastradh * i915 limits 3D destination drawing rect to w,h of 2048,2048. 123303b705cfSriastradh * 123403b705cfSriastradh * i845 limits 3D textures to 4B-aligned offset if un-tiled. 123503b705cfSriastradh * i845 limits 3D textures to ~4kB-aligned offset if tiled. 123603b705cfSriastradh * i845 limits 3D textures to width,height of 2048,2048. 123703b705cfSriastradh * i845 limits 3D textures to pitch of 4B - 8kB, in dwords. 123803b705cfSriastradh * i845 limits 3D destination to 4B-aligned offset if un-tiled. 123903b705cfSriastradh * i845 limits 3D destination to ~4kB-aligned offset if tiled. 124003b705cfSriastradh * i845 limits 3D destination to pitch of 8B - 8kB, in dwords. 124103b705cfSriastradh * i845 limits 3D destination drawing rect to w,h of 2048,2048. 124203b705cfSriastradh * 124303b705cfSriastradh * For the tiled issues, the only tiled buffer we draw to should be 124403b705cfSriastradh * the front, which will have an appropriate pitch/offset already set up, 124503b705cfSriastradh * so UXA doesn't need to worry. 124603b705cfSriastradh */ 124703b705cfSriastradh if (INTEL_INFO(intel)->gen >= 040) { 124803b705cfSriastradh intel->accel_pixmap_offset_alignment = 4 * 2; 124903b705cfSriastradh intel->accel_max_x = 8192; 125003b705cfSriastradh intel->accel_max_y = 8192; 125103b705cfSriastradh } else { 125203b705cfSriastradh intel->accel_pixmap_offset_alignment = 4; 125303b705cfSriastradh intel->accel_max_x = 2048; 125403b705cfSriastradh intel->accel_max_y = 2048; 125503b705cfSriastradh } 125603b705cfSriastradh} 125703b705cfSriastradh 125842542f5fSchristosstatic Bool intel_option_accel_none(intel_screen_private *intel) 125942542f5fSchristos{ 126042542f5fSchristos const char *s; 126142542f5fSchristos 126242542f5fSchristos s = xf86GetOptValString(intel->Options, OPTION_ACCEL_METHOD); 126342542f5fSchristos if (s == NULL) 126442542f5fSchristos return IS_DEFAULT_ACCEL_METHOD(NOACCEL); 126542542f5fSchristos 126642542f5fSchristos return strcasecmp(s, "none") == 0; 126742542f5fSchristos} 126842542f5fSchristos 126903b705cfSriastradhstatic Bool intel_option_accel_blt(intel_screen_private *intel) 127003b705cfSriastradh{ 127103b705cfSriastradh const char *s; 127203b705cfSriastradh 127303b705cfSriastradh s = xf86GetOptValString(intel->Options, OPTION_ACCEL_METHOD); 127403b705cfSriastradh if (s == NULL) 127503b705cfSriastradh return FALSE; 127603b705cfSriastradh 127703b705cfSriastradh return strcasecmp(s, "blt") == 0; 127803b705cfSriastradh} 127903b705cfSriastradh 128013496ba1Ssnj/** 128113496ba1Ssnj * Intialiazes the hardware for the 3D pipeline use in the 2D driver. 128213496ba1Ssnj * 128313496ba1Ssnj * Some state caching is performed to avoid redundant state emits. This 128413496ba1Ssnj * function is also responsible for marking the state as clobbered for DRI 128513496ba1Ssnj * clients. 128613496ba1Ssnj */ 128713496ba1Ssnjvoid IntelEmitInvarientState(ScrnInfoPtr scrn) 128813496ba1Ssnj{ 128913496ba1Ssnj intel_screen_private *intel = intel_get_screen_private(scrn); 129013496ba1Ssnj 129113496ba1Ssnj /* If we've emitted our state since the last clobber by another client, 129213496ba1Ssnj * skip it. 129313496ba1Ssnj */ 129413496ba1Ssnj if (intel->last_3d != LAST_3D_OTHER) 129513496ba1Ssnj return; 129613496ba1Ssnj 129713496ba1Ssnj if (IS_GEN2(intel)) 129813496ba1Ssnj I830EmitInvarientState(scrn); 129913496ba1Ssnj else if IS_GEN3(intel) 130013496ba1Ssnj I915EmitInvarientState(scrn); 130113496ba1Ssnj} 130213496ba1Ssnj 130303b705cfSriastradhBool intel_uxa_init(ScreenPtr screen) 130403b705cfSriastradh{ 130503b705cfSriastradh ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 130603b705cfSriastradh intel_screen_private *intel = intel_get_screen_private(scrn); 130703b705cfSriastradh 130813496ba1Ssnj intel_batch_init(scrn); 130913496ba1Ssnj 131013496ba1Ssnj if (INTEL_INFO(intel)->gen >= 040 && INTEL_INFO(intel)->gen < 0100) 131113496ba1Ssnj gen4_render_state_init(scrn); 131213496ba1Ssnj 131303b705cfSriastradh#if HAS_DIXREGISTERPRIVATEKEY 131403b705cfSriastradh if (!dixRegisterPrivateKey(&uxa_pixmap_index, PRIVATE_PIXMAP, 0)) 131503b705cfSriastradh#else 131603b705cfSriastradh if (!dixRequestPrivate(&uxa_pixmap_index, 0)) 131703b705cfSriastradh#endif 131803b705cfSriastradh return FALSE; 131903b705cfSriastradh 132003b705cfSriastradh intel_limits_init(intel); 132103b705cfSriastradh 132203b705cfSriastradh intel->uxa_driver = uxa_driver_alloc(); 132303b705cfSriastradh if (intel->uxa_driver == NULL) 132403b705cfSriastradh return FALSE; 132503b705cfSriastradh 132603b705cfSriastradh memset(intel->uxa_driver, 0, sizeof(*intel->uxa_driver)); 132703b705cfSriastradh 132803b705cfSriastradh intel->uxa_driver->uxa_major = 1; 132903b705cfSriastradh intel->uxa_driver->uxa_minor = 0; 133003b705cfSriastradh 133103b705cfSriastradh intel->prim_offset = 0; 133203b705cfSriastradh intel->vertex_count = 0; 133303b705cfSriastradh intel->vertex_offset = 0; 133403b705cfSriastradh intel->vertex_used = 0; 133503b705cfSriastradh intel->floats_per_vertex = 0; 133603b705cfSriastradh intel->last_floats_per_vertex = 0; 133703b705cfSriastradh intel->vertex_bo = NULL; 133803b705cfSriastradh intel->surface_used = 0; 133903b705cfSriastradh intel->surface_reloc = 0; 134003b705cfSriastradh 134103b705cfSriastradh /* Solid fill */ 134203b705cfSriastradh intel->uxa_driver->check_solid = intel_uxa_check_solid; 134303b705cfSriastradh intel->uxa_driver->prepare_solid = intel_uxa_prepare_solid; 134403b705cfSriastradh intel->uxa_driver->solid = intel_uxa_solid; 134503b705cfSriastradh intel->uxa_driver->done_solid = intel_uxa_done; 134603b705cfSriastradh 134703b705cfSriastradh /* Copy */ 134803b705cfSriastradh intel->uxa_driver->check_copy = intel_uxa_check_copy; 134903b705cfSriastradh intel->uxa_driver->prepare_copy = intel_uxa_prepare_copy; 135003b705cfSriastradh intel->uxa_driver->copy = intel_uxa_copy; 135103b705cfSriastradh intel->uxa_driver->done_copy = intel_uxa_done; 135203b705cfSriastradh 135303b705cfSriastradh /* Composite */ 135403b705cfSriastradh if (intel_option_accel_blt(intel)) { 135542542f5fSchristos } else if (INTEL_INFO(intel)->gen < 030) { 135603b705cfSriastradh intel->uxa_driver->check_composite = i830_check_composite; 135703b705cfSriastradh intel->uxa_driver->check_composite_target = i830_check_composite_target; 135803b705cfSriastradh intel->uxa_driver->check_composite_texture = i830_check_composite_texture; 135903b705cfSriastradh intel->uxa_driver->prepare_composite = i830_prepare_composite; 136003b705cfSriastradh intel->uxa_driver->composite = i830_composite; 136103b705cfSriastradh intel->uxa_driver->done_composite = i830_done_composite; 136203b705cfSriastradh 136303b705cfSriastradh intel->vertex_flush = i830_vertex_flush; 136403b705cfSriastradh intel->batch_commit_notify = i830_batch_commit_notify; 136542542f5fSchristos } else if (INTEL_INFO(intel)->gen < 040) { 136603b705cfSriastradh intel->uxa_driver->check_composite = i915_check_composite; 136703b705cfSriastradh intel->uxa_driver->check_composite_target = i915_check_composite_target; 136803b705cfSriastradh intel->uxa_driver->check_composite_texture = i915_check_composite_texture; 136903b705cfSriastradh intel->uxa_driver->prepare_composite = i915_prepare_composite; 137003b705cfSriastradh intel->uxa_driver->composite = i915_composite; 137103b705cfSriastradh intel->uxa_driver->done_composite = i830_done_composite; 137203b705cfSriastradh 137303b705cfSriastradh intel->vertex_flush = i915_vertex_flush; 137403b705cfSriastradh intel->batch_commit_notify = i915_batch_commit_notify; 137542542f5fSchristos } else if (INTEL_INFO(intel)->gen < 0100) { 137603b705cfSriastradh intel->uxa_driver->check_composite = i965_check_composite; 137703b705cfSriastradh intel->uxa_driver->check_composite_texture = i965_check_composite_texture; 137803b705cfSriastradh intel->uxa_driver->prepare_composite = i965_prepare_composite; 137903b705cfSriastradh intel->uxa_driver->composite = i965_composite; 138003b705cfSriastradh intel->uxa_driver->done_composite = i830_done_composite; 138103b705cfSriastradh 138203b705cfSriastradh intel->vertex_flush = i965_vertex_flush; 138303b705cfSriastradh intel->batch_flush = i965_batch_flush; 138403b705cfSriastradh intel->batch_commit_notify = i965_batch_commit_notify; 138503b705cfSriastradh 138642542f5fSchristos if (INTEL_INFO(intel)->gen < 050) { 138703b705cfSriastradh intel->context_switch = gen4_context_switch; 138842542f5fSchristos } else if (INTEL_INFO(intel)->gen < 060) { 138903b705cfSriastradh intel->context_switch = gen5_context_switch; 139003b705cfSriastradh } else { 139103b705cfSriastradh intel->context_switch = gen6_context_switch; 139203b705cfSriastradh } 139303b705cfSriastradh } 139403b705cfSriastradh 139503b705cfSriastradh /* PutImage */ 139603b705cfSriastradh intel->uxa_driver->put_image = intel_uxa_put_image; 139703b705cfSriastradh intel->uxa_driver->get_image = intel_uxa_get_image; 139803b705cfSriastradh 139903b705cfSriastradh intel->uxa_driver->prepare_access = intel_uxa_prepare_access; 140003b705cfSriastradh intel->uxa_driver->finish_access = intel_uxa_finish_access; 140103b705cfSriastradh intel->uxa_driver->pixmap_is_offscreen = intel_uxa_pixmap_is_offscreen; 140203b705cfSriastradh 140303b705cfSriastradh screen->CreatePixmap = intel_uxa_create_pixmap; 140403b705cfSriastradh screen->DestroyPixmap = intel_uxa_destroy_pixmap; 140503b705cfSriastradh 140603b705cfSriastradh#ifdef CREATE_PIXMAP_USAGE_SHARED 140703b705cfSriastradh screen->SharePixmapBacking = intel_uxa_share_pixmap_backing; 140803b705cfSriastradh screen->SetSharedPixmapBacking = intel_uxa_set_shared_pixmap_backing; 140903b705cfSriastradh#endif 141003b705cfSriastradh 141103b705cfSriastradh if (!uxa_driver_init(screen, intel->uxa_driver)) { 141203b705cfSriastradh xf86DrvMsg(scrn->scrnIndex, X_ERROR, 141303b705cfSriastradh "UXA initialization failed\n"); 141403b705cfSriastradh free(intel->uxa_driver); 141503b705cfSriastradh return FALSE; 141603b705cfSriastradh } 141703b705cfSriastradh 141842542f5fSchristos if (intel_option_accel_none(intel)) 141942542f5fSchristos intel->force_fallback = 1; 142042542f5fSchristos 142103b705cfSriastradh uxa_set_fallback_debug(screen, intel->fallback_debug); 142203b705cfSriastradh uxa_set_force_fallback(screen, intel->force_fallback); 142303b705cfSriastradh 142442542f5fSchristos intel->flush_rendering = intel_flush_rendering; 142503b705cfSriastradh return TRUE; 142603b705cfSriastradh} 1427