intel_uxa.c revision 13496ba1
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 17903b705cfSriastradh/** 18003b705cfSriastradh * Sets up hardware state for a series of solid fills. 18103b705cfSriastradh */ 18203b705cfSriastradhstatic Bool 18303b705cfSriastradhintel_uxa_prepare_solid(PixmapPtr pixmap, int alu, Pixel planemask, Pixel fg) 18403b705cfSriastradh{ 18503b705cfSriastradh ScrnInfoPtr scrn = xf86ScreenToScrn(pixmap->drawable.pScreen); 18603b705cfSriastradh intel_screen_private *intel = intel_get_screen_private(scrn); 18703b705cfSriastradh drm_intel_bo *bo_table[] = { 18803b705cfSriastradh NULL, /* batch_bo */ 18913496ba1Ssnj intel_uxa_get_pixmap_bo(pixmap), 19003b705cfSriastradh }; 19103b705cfSriastradh 19213496ba1Ssnj if (!intel_uxa_check_pitch_2d(pixmap)) 19303b705cfSriastradh return FALSE; 19403b705cfSriastradh 19513496ba1Ssnj if (!intel_uxa_get_aperture_space(scrn, bo_table, ARRAY_SIZE(bo_table))) 19603b705cfSriastradh return FALSE; 19703b705cfSriastradh 19803b705cfSriastradh intel->BR[13] = (I830PatternROP[alu] & 0xff) << 16; 19903b705cfSriastradh switch (pixmap->drawable.bitsPerPixel) { 20003b705cfSriastradh case 8: 20103b705cfSriastradh break; 20203b705cfSriastradh case 16: 20303b705cfSriastradh /* RGB565 */ 20403b705cfSriastradh intel->BR[13] |= (1 << 24); 20503b705cfSriastradh break; 20603b705cfSriastradh case 32: 20703b705cfSriastradh /* RGB8888 */ 20803b705cfSriastradh intel->BR[13] |= ((1 << 24) | (1 << 25)); 20903b705cfSriastradh break; 21003b705cfSriastradh } 21103b705cfSriastradh intel->BR[16] = fg; 21203b705cfSriastradh 21303b705cfSriastradh return TRUE; 21403b705cfSriastradh} 21503b705cfSriastradh 21603b705cfSriastradhstatic void intel_uxa_solid(PixmapPtr pixmap, int x1, int y1, int x2, int y2) 21703b705cfSriastradh{ 21803b705cfSriastradh ScrnInfoPtr scrn = xf86ScreenToScrn(pixmap->drawable.pScreen); 21903b705cfSriastradh intel_screen_private *intel = intel_get_screen_private(scrn); 22003b705cfSriastradh unsigned long pitch; 22103b705cfSriastradh uint32_t cmd; 22203b705cfSriastradh 22303b705cfSriastradh if (x1 < 0) 22403b705cfSriastradh x1 = 0; 22503b705cfSriastradh if (y1 < 0) 22603b705cfSriastradh y1 = 0; 22703b705cfSriastradh if (x2 > pixmap->drawable.width) 22803b705cfSriastradh x2 = pixmap->drawable.width; 22903b705cfSriastradh if (y2 > pixmap->drawable.height) 23003b705cfSriastradh y2 = pixmap->drawable.height; 23103b705cfSriastradh 23203b705cfSriastradh if (x2 <= x1 || y2 <= y1) 23303b705cfSriastradh return; 23403b705cfSriastradh 23503b705cfSriastradh pitch = intel_pixmap_pitch(pixmap); 23603b705cfSriastradh 23703b705cfSriastradh { 23842542f5fSchristos int len = INTEL_INFO(intel)->gen >= 0100 ? 7 : 6; 23942542f5fSchristos BEGIN_BATCH_BLT(len); 24003b705cfSriastradh 24142542f5fSchristos cmd = XY_COLOR_BLT_CMD | (len - 2); 24203b705cfSriastradh 24303b705cfSriastradh if (pixmap->drawable.bitsPerPixel == 32) 24403b705cfSriastradh cmd |= 24503b705cfSriastradh XY_COLOR_BLT_WRITE_ALPHA | XY_COLOR_BLT_WRITE_RGB; 24603b705cfSriastradh 24713496ba1Ssnj if (INTEL_INFO(intel)->gen >= 040 && intel_uxa_pixmap_tiled(pixmap)) { 24803b705cfSriastradh assert((pitch % 512) == 0); 24903b705cfSriastradh pitch >>= 2; 25003b705cfSriastradh cmd |= XY_COLOR_BLT_TILED; 25103b705cfSriastradh } 25203b705cfSriastradh 25303b705cfSriastradh OUT_BATCH(cmd); 25403b705cfSriastradh 25503b705cfSriastradh OUT_BATCH(intel->BR[13] | pitch); 25603b705cfSriastradh OUT_BATCH((y1 << 16) | (x1 & 0xffff)); 25703b705cfSriastradh OUT_BATCH((y2 << 16) | (x2 & 0xffff)); 25803b705cfSriastradh OUT_RELOC_PIXMAP_FENCED(pixmap, I915_GEM_DOMAIN_RENDER, 25903b705cfSriastradh I915_GEM_DOMAIN_RENDER, 0); 26003b705cfSriastradh OUT_BATCH(intel->BR[16]); 26103b705cfSriastradh ADVANCE_BATCH(); 26203b705cfSriastradh } 26303b705cfSriastradh} 26403b705cfSriastradh 26503b705cfSriastradh/** 26603b705cfSriastradh * TODO: 26703b705cfSriastradh * - support planemask using FULL_BLT_CMD? 26803b705cfSriastradh */ 26903b705cfSriastradhstatic Bool 27003b705cfSriastradhintel_uxa_check_copy(PixmapPtr source, PixmapPtr dest, 27103b705cfSriastradh int alu, Pixel planemask) 27203b705cfSriastradh{ 27303b705cfSriastradh ScrnInfoPtr scrn = xf86ScreenToScrn(dest->drawable.pScreen); 27403b705cfSriastradh 27503b705cfSriastradh if (!UXA_PM_IS_SOLID(&source->drawable, planemask)) { 27613496ba1Ssnj intel_uxa_debug_fallback(scrn, "planemask is not solid"); 27703b705cfSriastradh return FALSE; 27803b705cfSriastradh } 27903b705cfSriastradh 28003b705cfSriastradh if (source->drawable.bitsPerPixel != dest->drawable.bitsPerPixel) { 28113496ba1Ssnj intel_uxa_debug_fallback(scrn, "mixed bpp copies unsupported\n"); 28203b705cfSriastradh return FALSE; 28303b705cfSriastradh } 28403b705cfSriastradh switch (source->drawable.bitsPerPixel) { 28503b705cfSriastradh case 8: 28603b705cfSriastradh case 16: 28703b705cfSriastradh case 32: 28803b705cfSriastradh break; 28903b705cfSriastradh default: 29003b705cfSriastradh return FALSE; 29103b705cfSriastradh } 29203b705cfSriastradh 29313496ba1Ssnj if (!intel_uxa_check_pitch_2d(source)) 29403b705cfSriastradh return FALSE; 29513496ba1Ssnj if (!intel_uxa_check_pitch_2d(dest)) 29603b705cfSriastradh return FALSE; 29703b705cfSriastradh 29803b705cfSriastradh return TRUE; 29903b705cfSriastradh} 30003b705cfSriastradh 30103b705cfSriastradhstatic Bool 30203b705cfSriastradhintel_uxa_prepare_copy(PixmapPtr source, PixmapPtr dest, int xdir, 30303b705cfSriastradh int ydir, int alu, Pixel planemask) 30403b705cfSriastradh{ 30503b705cfSriastradh ScrnInfoPtr scrn = xf86ScreenToScrn(dest->drawable.pScreen); 30603b705cfSriastradh intel_screen_private *intel = intel_get_screen_private(scrn); 30703b705cfSriastradh drm_intel_bo *bo_table[] = { 30803b705cfSriastradh NULL, /* batch_bo */ 30913496ba1Ssnj intel_uxa_get_pixmap_bo(source), 31013496ba1Ssnj intel_uxa_get_pixmap_bo(dest), 31103b705cfSriastradh }; 31203b705cfSriastradh 31313496ba1Ssnj if (!intel_uxa_get_aperture_space(scrn, bo_table, ARRAY_SIZE(bo_table))) 31403b705cfSriastradh return FALSE; 31503b705cfSriastradh 31603b705cfSriastradh intel->render_source = source; 31703b705cfSriastradh 31803b705cfSriastradh intel->BR[13] = I830CopyROP[alu] << 16; 31903b705cfSriastradh switch (source->drawable.bitsPerPixel) { 32003b705cfSriastradh case 8: 32103b705cfSriastradh break; 32203b705cfSriastradh case 16: 32303b705cfSriastradh intel->BR[13] |= (1 << 24); 32403b705cfSriastradh break; 32503b705cfSriastradh case 32: 32603b705cfSriastradh intel->BR[13] |= ((1 << 25) | (1 << 24)); 32703b705cfSriastradh break; 32803b705cfSriastradh } 32903b705cfSriastradh 33003b705cfSriastradh return TRUE; 33103b705cfSriastradh} 33203b705cfSriastradh 33303b705cfSriastradhstatic void 33403b705cfSriastradhintel_uxa_copy(PixmapPtr dest, int src_x1, int src_y1, int dst_x1, 33503b705cfSriastradh int dst_y1, int w, int h) 33603b705cfSriastradh{ 33703b705cfSriastradh ScrnInfoPtr scrn = xf86ScreenToScrn(dest->drawable.pScreen); 33803b705cfSriastradh intel_screen_private *intel = intel_get_screen_private(scrn); 33903b705cfSriastradh uint32_t cmd; 34003b705cfSriastradh int dst_x2, dst_y2, src_x2, src_y2; 34103b705cfSriastradh unsigned int dst_pitch, src_pitch; 34203b705cfSriastradh 34303b705cfSriastradh dst_x2 = dst_x1 + w; 34403b705cfSriastradh dst_y2 = dst_y1 + h; 34503b705cfSriastradh 34603b705cfSriastradh /* XXX Fixup extents as a lamentable workaround for missing 34703b705cfSriastradh * source clipping in the upper layers. 34803b705cfSriastradh */ 34903b705cfSriastradh if (dst_x1 < 0) 35003b705cfSriastradh src_x1 -= dst_x1, dst_x1 = 0; 35103b705cfSriastradh if (dst_y1 < 0) 35203b705cfSriastradh src_y1 -= dst_y1, dst_y1 = 0; 35303b705cfSriastradh if (dst_x2 > dest->drawable.width) 35403b705cfSriastradh dst_x2 = dest->drawable.width; 35503b705cfSriastradh if (dst_y2 > dest->drawable.height) 35603b705cfSriastradh dst_y2 = dest->drawable.height; 35703b705cfSriastradh 35803b705cfSriastradh src_x2 = src_x1 + (dst_x2 - dst_x1); 35903b705cfSriastradh src_y2 = src_y1 + (dst_y2 - dst_y1); 36003b705cfSriastradh 36103b705cfSriastradh if (src_x1 < 0) 36203b705cfSriastradh dst_x1 -= src_x1, src_x1 = 0; 36303b705cfSriastradh if (src_y1 < 0) 36403b705cfSriastradh dst_y1 -= src_y1, src_y1 = 0; 36503b705cfSriastradh if (src_x2 > intel->render_source->drawable.width) 36603b705cfSriastradh dst_x2 -= src_x2 - intel->render_source->drawable.width; 36703b705cfSriastradh if (src_y2 > intel->render_source->drawable.height) 36803b705cfSriastradh dst_y2 -= src_y2 - intel->render_source->drawable.height; 36903b705cfSriastradh 37003b705cfSriastradh if (dst_x2 <= dst_x1 || dst_y2 <= dst_y1) 37103b705cfSriastradh return; 37203b705cfSriastradh 37303b705cfSriastradh dst_pitch = intel_pixmap_pitch(dest); 37403b705cfSriastradh src_pitch = intel_pixmap_pitch(intel->render_source); 37503b705cfSriastradh 37603b705cfSriastradh { 37742542f5fSchristos int len = INTEL_INFO(intel)->gen >= 0100 ? 10 : 8; 37842542f5fSchristos BEGIN_BATCH_BLT(len); 37903b705cfSriastradh 38042542f5fSchristos cmd = XY_SRC_COPY_BLT_CMD | (len - 2); 38103b705cfSriastradh 38203b705cfSriastradh if (dest->drawable.bitsPerPixel == 32) 38303b705cfSriastradh cmd |= 38403b705cfSriastradh XY_SRC_COPY_BLT_WRITE_ALPHA | 38503b705cfSriastradh XY_SRC_COPY_BLT_WRITE_RGB; 38603b705cfSriastradh 38703b705cfSriastradh if (INTEL_INFO(intel)->gen >= 040) { 38813496ba1Ssnj if (intel_uxa_pixmap_tiled(dest)) { 38903b705cfSriastradh assert((dst_pitch % 512) == 0); 39003b705cfSriastradh dst_pitch >>= 2; 39103b705cfSriastradh cmd |= XY_SRC_COPY_BLT_DST_TILED; 39203b705cfSriastradh } 39303b705cfSriastradh 39413496ba1Ssnj if (intel_uxa_pixmap_tiled(intel->render_source)) { 39503b705cfSriastradh assert((src_pitch % 512) == 0); 39603b705cfSriastradh src_pitch >>= 2; 39703b705cfSriastradh cmd |= XY_SRC_COPY_BLT_SRC_TILED; 39803b705cfSriastradh } 39903b705cfSriastradh } 40003b705cfSriastradh 40103b705cfSriastradh OUT_BATCH(cmd); 40203b705cfSriastradh 40303b705cfSriastradh OUT_BATCH(intel->BR[13] | dst_pitch); 40403b705cfSriastradh OUT_BATCH((dst_y1 << 16) | (dst_x1 & 0xffff)); 40503b705cfSriastradh OUT_BATCH((dst_y2 << 16) | (dst_x2 & 0xffff)); 40603b705cfSriastradh OUT_RELOC_PIXMAP_FENCED(dest, 40703b705cfSriastradh I915_GEM_DOMAIN_RENDER, 40803b705cfSriastradh I915_GEM_DOMAIN_RENDER, 40903b705cfSriastradh 0); 41003b705cfSriastradh OUT_BATCH((src_y1 << 16) | (src_x1 & 0xffff)); 41103b705cfSriastradh OUT_BATCH(src_pitch); 41203b705cfSriastradh OUT_RELOC_PIXMAP_FENCED(intel->render_source, 41303b705cfSriastradh I915_GEM_DOMAIN_RENDER, 0, 41403b705cfSriastradh 0); 41503b705cfSriastradh 41603b705cfSriastradh ADVANCE_BATCH(); 41703b705cfSriastradh } 41803b705cfSriastradh} 41903b705cfSriastradh 42003b705cfSriastradhstatic void intel_uxa_done(PixmapPtr pixmap) 42103b705cfSriastradh{ 42203b705cfSriastradh ScrnInfoPtr scrn = xf86ScreenToScrn(pixmap->drawable.pScreen); 42303b705cfSriastradh intel_screen_private *intel = intel_get_screen_private(scrn); 42403b705cfSriastradh 42542542f5fSchristos if (INTEL_INFO(intel)->gen >= 060) { 42603b705cfSriastradh /* workaround a random BLT hang */ 42703b705cfSriastradh BEGIN_BATCH_BLT(3); 42842542f5fSchristos OUT_BATCH(XY_SETUP_CLIP_BLT_CMD | (3 - 2)); 42903b705cfSriastradh OUT_BATCH(0); 43003b705cfSriastradh OUT_BATCH(0); 43103b705cfSriastradh ADVANCE_BATCH(); 43203b705cfSriastradh } 43303b705cfSriastradh 43413496ba1Ssnj intel_uxa_debug_flush(scrn); 43503b705cfSriastradh} 43603b705cfSriastradh 43703b705cfSriastradh/** 43803b705cfSriastradh * Do any cleanup from the Composite operation. 43903b705cfSriastradh * 44003b705cfSriastradh * This is shared between i830 through i965. 44103b705cfSriastradh */ 44203b705cfSriastradhstatic void i830_done_composite(PixmapPtr dest) 44303b705cfSriastradh{ 44403b705cfSriastradh ScrnInfoPtr scrn = xf86ScreenToScrn(dest->drawable.pScreen); 44503b705cfSriastradh intel_screen_private *intel = intel_get_screen_private(scrn); 44603b705cfSriastradh 44703b705cfSriastradh if (intel->vertex_flush) 44803b705cfSriastradh intel->vertex_flush(intel); 44903b705cfSriastradh 45013496ba1Ssnj intel_uxa_debug_flush(scrn); 45103b705cfSriastradh} 45203b705cfSriastradh 45303b705cfSriastradh#define xFixedToFloat(val) \ 45403b705cfSriastradh ((float)xFixedToInt(val) + ((float)xFixedFrac(val) / 65536.0)) 45503b705cfSriastradh 45603b705cfSriastradhstatic Bool 45703b705cfSriastradh_intel_transform_point(PictTransformPtr transform, 45803b705cfSriastradh float x, float y, float result[3]) 45903b705cfSriastradh{ 46003b705cfSriastradh int j; 46103b705cfSriastradh 46203b705cfSriastradh for (j = 0; j < 3; j++) { 46303b705cfSriastradh result[j] = (xFixedToFloat(transform->matrix[j][0]) * x + 46403b705cfSriastradh xFixedToFloat(transform->matrix[j][1]) * y + 46503b705cfSriastradh xFixedToFloat(transform->matrix[j][2])); 46603b705cfSriastradh } 46703b705cfSriastradh if (!result[2]) 46803b705cfSriastradh return FALSE; 46903b705cfSriastradh return TRUE; 47003b705cfSriastradh} 47103b705cfSriastradh 47203b705cfSriastradh/** 47303b705cfSriastradh * Returns the floating-point coordinates transformed by the given transform. 47403b705cfSriastradh * 47503b705cfSriastradh * transform may be null. 47603b705cfSriastradh */ 47703b705cfSriastradhBool 47813496ba1Ssnjintel_uxa_get_transformed_coordinates(int x, int y, PictTransformPtr transform, 47903b705cfSriastradh float *x_out, float *y_out) 48003b705cfSriastradh{ 48103b705cfSriastradh if (transform == NULL) { 48203b705cfSriastradh *x_out = x; 48303b705cfSriastradh *y_out = y; 48403b705cfSriastradh } else { 48503b705cfSriastradh float result[3]; 48603b705cfSriastradh 48703b705cfSriastradh if (!_intel_transform_point(transform, 48803b705cfSriastradh x, y, 48903b705cfSriastradh result)) 49003b705cfSriastradh return FALSE; 49103b705cfSriastradh *x_out = result[0] / result[2]; 49203b705cfSriastradh *y_out = result[1] / result[2]; 49303b705cfSriastradh } 49403b705cfSriastradh return TRUE; 49503b705cfSriastradh} 49603b705cfSriastradh 49703b705cfSriastradh/** 49803b705cfSriastradh * Returns the un-normalized floating-point coordinates transformed by the given transform. 49903b705cfSriastradh * 50003b705cfSriastradh * transform may be null. 50103b705cfSriastradh */ 50203b705cfSriastradhBool 50313496ba1Ssnjintel_uxa_get_transformed_coordinates_3d(int x, int y, PictTransformPtr transform, 50403b705cfSriastradh float *x_out, float *y_out, float *w_out) 50503b705cfSriastradh{ 50603b705cfSriastradh if (transform == NULL) { 50703b705cfSriastradh *x_out = x; 50803b705cfSriastradh *y_out = y; 50903b705cfSriastradh *w_out = 1; 51003b705cfSriastradh } else { 51103b705cfSriastradh float result[3]; 51203b705cfSriastradh 51303b705cfSriastradh if (!_intel_transform_point(transform, 51403b705cfSriastradh x, y, 51503b705cfSriastradh result)) 51603b705cfSriastradh return FALSE; 51703b705cfSriastradh *x_out = result[0]; 51803b705cfSriastradh *y_out = result[1]; 51903b705cfSriastradh *w_out = result[2]; 52003b705cfSriastradh } 52103b705cfSriastradh return TRUE; 52203b705cfSriastradh} 52303b705cfSriastradh 52403b705cfSriastradh/** 52503b705cfSriastradh * Returns whether the provided transform is affine. 52603b705cfSriastradh * 52703b705cfSriastradh * transform may be null. 52803b705cfSriastradh */ 52913496ba1SsnjBool intel_uxa_transform_is_affine(PictTransformPtr t) 53003b705cfSriastradh{ 53103b705cfSriastradh if (t == NULL) 53203b705cfSriastradh return TRUE; 53303b705cfSriastradh return t->matrix[2][0] == 0 && t->matrix[2][1] == 0; 53403b705cfSriastradh} 53503b705cfSriastradh 53613496ba1Ssnjdri_bo *intel_uxa_get_pixmap_bo(PixmapPtr pixmap) 53703b705cfSriastradh{ 53813496ba1Ssnj struct intel_uxa_pixmap *intel; 53903b705cfSriastradh 54013496ba1Ssnj intel = intel_uxa_get_pixmap_private(pixmap); 54103b705cfSriastradh if (intel == NULL) 54203b705cfSriastradh return NULL; 54303b705cfSriastradh 54403b705cfSriastradh return intel->bo; 54503b705cfSriastradh} 54603b705cfSriastradh 54742542f5fSchristosstatic unsigned intel_get_tile_width(intel_screen_private *intel, int tiling, int pitch) 54842542f5fSchristos{ 54942542f5fSchristos unsigned long tile_width; 55042542f5fSchristos 55142542f5fSchristos if (tiling == I915_TILING_NONE) 55242542f5fSchristos return 4; 55342542f5fSchristos 55442542f5fSchristos tile_width = (tiling == I915_TILING_Y) ? 128 : 512; 55542542f5fSchristos if (INTEL_INFO(intel)->gen >= 040) 55642542f5fSchristos return tile_width; 55742542f5fSchristos 55842542f5fSchristos while (tile_width < pitch) 55942542f5fSchristos tile_width <<= 1; 56042542f5fSchristos 56142542f5fSchristos return tile_width; 56242542f5fSchristos} 56342542f5fSchristos 56413496ba1Ssnjvoid intel_uxa_set_pixmap_bo(PixmapPtr pixmap, dri_bo * bo) 56503b705cfSriastradh{ 56642542f5fSchristos ScrnInfoPtr scrn = xf86ScreenToScrn(pixmap->drawable.pScreen); 56742542f5fSchristos intel_screen_private *intel = intel_get_screen_private(scrn); 56813496ba1Ssnj struct intel_uxa_pixmap *priv; 56903b705cfSriastradh 57013496ba1Ssnj priv = intel_uxa_get_pixmap_private(pixmap); 57103b705cfSriastradh if (priv == NULL && bo == NULL) 57242542f5fSchristos return; 57303b705cfSriastradh 57403b705cfSriastradh if (priv != NULL) { 57503b705cfSriastradh if (priv->bo == bo) 57603b705cfSriastradh return; 57703b705cfSriastradh 57842542f5fSchristosfree_priv: 57903b705cfSriastradh dri_bo_unreference(priv->bo); 58003b705cfSriastradh list_del(&priv->batch); 58103b705cfSriastradh 58203b705cfSriastradh free(priv); 58303b705cfSriastradh priv = NULL; 58403b705cfSriastradh } 58503b705cfSriastradh 58603b705cfSriastradh if (bo != NULL) { 58742542f5fSchristos uint32_t tiling, swizzle_mode; 58842542f5fSchristos unsigned tile_width; 58942542f5fSchristos int size, stride; 59003b705cfSriastradh 59113496ba1Ssnj priv = calloc(1, sizeof (struct intel_uxa_pixmap)); 59203b705cfSriastradh if (priv == NULL) 59303b705cfSriastradh goto BAIL; 59403b705cfSriastradh 59503b705cfSriastradh list_init(&priv->batch); 59603b705cfSriastradh 59703b705cfSriastradh dri_bo_reference(bo); 59803b705cfSriastradh priv->bo = bo; 59903b705cfSriastradh 60042542f5fSchristos if (drm_intel_bo_get_tiling(bo, &tiling, &swizzle_mode)) { 60142542f5fSchristos bo = NULL; 60242542f5fSchristos goto free_priv; 60303b705cfSriastradh } 60403b705cfSriastradh 60503b705cfSriastradh priv->tiling = tiling; 60603b705cfSriastradh priv->busy = -1; 60703b705cfSriastradh priv->offscreen = 1; 60842542f5fSchristos 60942542f5fSchristos stride = (pixmap->drawable.width * pixmap->drawable.bitsPerPixel + 7) / 8; 61042542f5fSchristos tile_width = intel_get_tile_width(intel, tiling, stride); 61142542f5fSchristos stride = ALIGN(stride, tile_width); 61242542f5fSchristos 61313496ba1Ssnj if (intel_pixmap_pitch(pixmap) < stride || 61413496ba1Ssnj intel_pixmap_pitch(pixmap) & (tile_width - 1) || 61513496ba1Ssnj intel_pixmap_pitch(pixmap) >= KB(32)) { 61642542f5fSchristos xf86DrvMsg(scrn->scrnIndex, X_ERROR, 61742542f5fSchristos "%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", 61813496ba1Ssnj __FUNCTION__, intel_pixmap_pitch(pixmap), stride, KB(32), tile_width); 61942542f5fSchristos bo = NULL; 62042542f5fSchristos goto free_priv; 62142542f5fSchristos } 62242542f5fSchristos 62342542f5fSchristos if (tiling != I915_TILING_NONE) { 62442542f5fSchristos int height; 62542542f5fSchristos 62642542f5fSchristos if (IS_GEN2(intel)) 62742542f5fSchristos height = 16; 62842542f5fSchristos else if (tiling == I915_TILING_X) 62942542f5fSchristos height = 8; 63042542f5fSchristos else 63142542f5fSchristos height = 32; 63242542f5fSchristos 63313496ba1Ssnj height = ALIGN(pixmap->drawable.height, height); 63413496ba1Ssnj size = intel_get_fence_size(intel, intel_pixmap_pitch(pixmap) * height); 63542542f5fSchristos } else 63613496ba1Ssnj size = intel_pixmap_pitch(pixmap) * pixmap->drawable.height; 63742542f5fSchristos 63842542f5fSchristos if (bo->size < size || bo->size > intel->max_bo_size) { 63942542f5fSchristos xf86DrvMsg(scrn->scrnIndex, X_ERROR, 64042542f5fSchristos "%s: size of buffer object does not match constraints: size=%ld, must be greater than %d, but less than %d\n", 64142542f5fSchristos __FUNCTION__, (long)bo->size, size, intel->max_bo_size); 64242542f5fSchristos bo = NULL; 64342542f5fSchristos goto free_priv; 64442542f5fSchristos } 64503b705cfSriastradh } 64603b705cfSriastradh 64703b705cfSriastradh BAIL: 64813496ba1Ssnj intel_uxa_set_pixmap_private(pixmap, priv); 64903b705cfSriastradh} 65003b705cfSriastradh 65103b705cfSriastradhstatic Bool intel_uxa_prepare_access(PixmapPtr pixmap, uxa_access_t access) 65203b705cfSriastradh{ 65303b705cfSriastradh ScrnInfoPtr scrn = xf86ScreenToScrn(pixmap->drawable.pScreen); 65403b705cfSriastradh intel_screen_private *intel = intel_get_screen_private(scrn); 65513496ba1Ssnj struct intel_uxa_pixmap *priv = intel_uxa_get_pixmap_private(pixmap); 65603b705cfSriastradh dri_bo *bo = priv->bo; 65703b705cfSriastradh int ret; 65803b705cfSriastradh 65903b705cfSriastradh /* When falling back to swrast, flush all pending operations */ 66003b705cfSriastradh if (access == UXA_ACCESS_RW || priv->dirty) 66103b705cfSriastradh intel_batch_submit(scrn); 66203b705cfSriastradh 66303b705cfSriastradh assert(bo->size <= intel->max_gtt_map_size); 66403b705cfSriastradh ret = drm_intel_gem_bo_map_gtt(bo); 66503b705cfSriastradh if (ret) { 66603b705cfSriastradh xf86DrvMsg(scrn->scrnIndex, X_WARNING, 66703b705cfSriastradh "%s: bo map (use gtt? %d, access %d) failed: %s\n", 66803b705cfSriastradh __FUNCTION__, 66903b705cfSriastradh priv->tiling || bo->size <= intel->max_gtt_map_size, 67003b705cfSriastradh access, 67103b705cfSriastradh strerror(-ret)); 67203b705cfSriastradh return FALSE; 67303b705cfSriastradh } 67403b705cfSriastradh 67503b705cfSriastradh pixmap->devPrivate.ptr = bo->virtual; 67603b705cfSriastradh priv->busy = 0; 67703b705cfSriastradh 67803b705cfSriastradh return TRUE; 67903b705cfSriastradh} 68003b705cfSriastradh 68103b705cfSriastradhstatic void intel_uxa_finish_access(PixmapPtr pixmap, uxa_access_t access) 68203b705cfSriastradh{ 68313496ba1Ssnj struct intel_uxa_pixmap *priv; 68403b705cfSriastradh 68513496ba1Ssnj priv = intel_uxa_get_pixmap_private(pixmap); 68603b705cfSriastradh if (priv == NULL) 68703b705cfSriastradh return; 68803b705cfSriastradh 68903b705cfSriastradh drm_intel_gem_bo_unmap_gtt(priv->bo); 69003b705cfSriastradh pixmap->devPrivate.ptr = NULL; 69103b705cfSriastradh} 69203b705cfSriastradh 69303b705cfSriastradhstatic Bool intel_uxa_pixmap_put_image(PixmapPtr pixmap, 69403b705cfSriastradh char *src, int src_pitch, 69503b705cfSriastradh int x, int y, int w, int h) 69603b705cfSriastradh{ 69713496ba1Ssnj struct intel_uxa_pixmap *priv = intel_uxa_get_pixmap_private(pixmap); 69803b705cfSriastradh int stride = intel_pixmap_pitch(pixmap); 69903b705cfSriastradh int cpp = pixmap->drawable.bitsPerPixel/8; 70003b705cfSriastradh int ret = FALSE; 70103b705cfSriastradh 70203b705cfSriastradh if (priv == NULL || priv->bo == NULL) 70303b705cfSriastradh return FALSE; 70403b705cfSriastradh 70503b705cfSriastradh if (priv->tiling == I915_TILING_NONE && 70603b705cfSriastradh (h == 1 || (src_pitch == stride && w == pixmap->drawable.width))) { 70703b705cfSriastradh return drm_intel_bo_subdata(priv->bo, y*stride + x*cpp, stride*(h-1) + w*cpp, src) == 0; 70803b705cfSriastradh } else if (drm_intel_gem_bo_map_gtt(priv->bo) == 0) { 70903b705cfSriastradh char *dst = priv->bo->virtual; 71003b705cfSriastradh int row_length = w * cpp; 71103b705cfSriastradh int num_rows = h; 71203b705cfSriastradh if (row_length == src_pitch && src_pitch == stride) 71303b705cfSriastradh num_rows = 1, row_length *= h; 71403b705cfSriastradh dst += y * stride + x * cpp; 71503b705cfSriastradh do { 71603b705cfSriastradh memcpy (dst, src, row_length); 71703b705cfSriastradh src += src_pitch; 71803b705cfSriastradh dst += stride; 71903b705cfSriastradh } while (--num_rows); 72003b705cfSriastradh drm_intel_gem_bo_unmap_gtt(priv->bo); 72103b705cfSriastradh ret = TRUE; 72203b705cfSriastradh } 72303b705cfSriastradh 72403b705cfSriastradh return ret; 72503b705cfSriastradh} 72603b705cfSriastradh 72703b705cfSriastradhstatic Bool intel_uxa_put_image(PixmapPtr pixmap, 72803b705cfSriastradh int x, int y, 72903b705cfSriastradh int w, int h, 73003b705cfSriastradh char *src, int src_pitch) 73103b705cfSriastradh{ 73213496ba1Ssnj struct intel_uxa_pixmap *priv; 73303b705cfSriastradh 73413496ba1Ssnj priv = intel_uxa_get_pixmap_private(pixmap); 73513496ba1Ssnj if (!intel_uxa_pixmap_is_busy(priv)) { 73603b705cfSriastradh /* bo is not busy so can be replaced without a stall, upload in-place. */ 73703b705cfSriastradh return intel_uxa_pixmap_put_image(pixmap, src, src_pitch, x, y, w, h); 73803b705cfSriastradh } else { 73903b705cfSriastradh ScreenPtr screen = pixmap->drawable.pScreen; 74003b705cfSriastradh 74103b705cfSriastradh if (!priv->pinned && 74203b705cfSriastradh x == 0 && y == 0 && 74303b705cfSriastradh w == pixmap->drawable.width && 74403b705cfSriastradh h == pixmap->drawable.height) 74503b705cfSriastradh { 74603b705cfSriastradh intel_screen_private *intel = intel_get_screen_private(xf86ScreenToScrn(screen)); 74703b705cfSriastradh uint32_t tiling = priv->tiling; 74803b705cfSriastradh int size, stride; 74903b705cfSriastradh dri_bo *bo; 75003b705cfSriastradh 75103b705cfSriastradh /* Replace busy bo. */ 75213496ba1Ssnj size = intel_compute_size(intel, 75313496ba1Ssnj w, h, 75413496ba1Ssnj pixmap->drawable.bitsPerPixel, pixmap->usage_hint, 75513496ba1Ssnj &tiling, &stride); 75603b705cfSriastradh if (size > intel->max_gtt_map_size) 75703b705cfSriastradh return FALSE; 75803b705cfSriastradh 75903b705cfSriastradh bo = drm_intel_bo_alloc(intel->bufmgr, "pixmap", size, 0); 76003b705cfSriastradh if (bo == NULL) 76103b705cfSriastradh return FALSE; 76203b705cfSriastradh 76303b705cfSriastradh if (tiling != I915_TILING_NONE) 76403b705cfSriastradh drm_intel_bo_set_tiling(bo, &tiling, stride); 76503b705cfSriastradh priv->tiling = tiling; 76603b705cfSriastradh 76703b705cfSriastradh screen->ModifyPixmapHeader(pixmap, 76803b705cfSriastradh w, h, 76903b705cfSriastradh 0, 0, 77003b705cfSriastradh stride, NULL); 77113496ba1Ssnj intel_uxa_set_pixmap_bo(pixmap, bo); 77203b705cfSriastradh dri_bo_unreference(bo); 77303b705cfSriastradh 77403b705cfSriastradh return intel_uxa_pixmap_put_image(pixmap, src, src_pitch, 0, 0, w, h); 77503b705cfSriastradh } 77603b705cfSriastradh else 77703b705cfSriastradh { 77803b705cfSriastradh PixmapPtr scratch; 77903b705cfSriastradh Bool ret; 78003b705cfSriastradh 78103b705cfSriastradh /* Upload to a linear buffer and queue a blit. */ 78203b705cfSriastradh scratch = (*screen->CreatePixmap)(screen, w, h, 78303b705cfSriastradh pixmap->drawable.depth, 78403b705cfSriastradh UXA_CREATE_PIXMAP_FOR_MAP); 78503b705cfSriastradh if (!scratch) 78603b705cfSriastradh return FALSE; 78703b705cfSriastradh 78803b705cfSriastradh if (!intel_uxa_pixmap_is_offscreen(scratch)) { 78903b705cfSriastradh screen->DestroyPixmap(scratch); 79003b705cfSriastradh return FALSE; 79103b705cfSriastradh } 79203b705cfSriastradh 79303b705cfSriastradh ret = intel_uxa_pixmap_put_image(scratch, src, src_pitch, 0, 0, w, h); 79403b705cfSriastradh if (ret) { 79503b705cfSriastradh GCPtr gc = GetScratchGC(pixmap->drawable.depth, screen); 79603b705cfSriastradh if (gc) { 79703b705cfSriastradh ValidateGC(&pixmap->drawable, gc); 79803b705cfSriastradh 79903b705cfSriastradh (*gc->ops->CopyArea)(&scratch->drawable, 80003b705cfSriastradh &pixmap->drawable, 80103b705cfSriastradh gc, 0, 0, w, h, x, y); 80203b705cfSriastradh 80303b705cfSriastradh FreeScratchGC(gc); 80403b705cfSriastradh } else 80503b705cfSriastradh ret = FALSE; 80603b705cfSriastradh } 80703b705cfSriastradh 80803b705cfSriastradh (*screen->DestroyPixmap)(scratch); 80903b705cfSriastradh return ret; 81003b705cfSriastradh } 81103b705cfSriastradh } 81203b705cfSriastradh} 81303b705cfSriastradh 81403b705cfSriastradhstatic Bool intel_uxa_pixmap_get_image(PixmapPtr pixmap, 81503b705cfSriastradh int x, int y, int w, int h, 81603b705cfSriastradh char *dst, int dst_pitch) 81703b705cfSriastradh{ 81813496ba1Ssnj struct intel_uxa_pixmap *priv = intel_uxa_get_pixmap_private(pixmap); 81903b705cfSriastradh int stride = intel_pixmap_pitch(pixmap); 82003b705cfSriastradh int cpp = pixmap->drawable.bitsPerPixel/8; 82103b705cfSriastradh 82203b705cfSriastradh /* assert(priv->tiling == I915_TILING_NONE); */ 82303b705cfSriastradh if (h == 1 || (dst_pitch == stride && w == pixmap->drawable.width)) { 82403b705cfSriastradh return drm_intel_bo_get_subdata(priv->bo, y*stride + x*cpp, (h-1)*stride + w*cpp, dst) == 0; 82503b705cfSriastradh } else { 82603b705cfSriastradh char *src; 82703b705cfSriastradh 82803b705cfSriastradh if (drm_intel_gem_bo_map_gtt(priv->bo)) 82903b705cfSriastradh return FALSE; 83003b705cfSriastradh 83103b705cfSriastradh src = (char *) priv->bo->virtual + y * stride + x * cpp; 83203b705cfSriastradh w *= cpp; 83303b705cfSriastradh do { 83403b705cfSriastradh memcpy(dst, src, w); 83503b705cfSriastradh src += stride; 83603b705cfSriastradh dst += dst_pitch; 83703b705cfSriastradh } while (--h); 83803b705cfSriastradh 83903b705cfSriastradh drm_intel_gem_bo_unmap_gtt(priv->bo); 84003b705cfSriastradh 84103b705cfSriastradh return TRUE; 84203b705cfSriastradh } 84303b705cfSriastradh} 84403b705cfSriastradh 84503b705cfSriastradhstatic Bool intel_uxa_get_image(PixmapPtr pixmap, 84603b705cfSriastradh int x, int y, 84703b705cfSriastradh int w, int h, 84803b705cfSriastradh char *dst, int dst_pitch) 84903b705cfSriastradh{ 85013496ba1Ssnj struct intel_uxa_pixmap *priv; 85103b705cfSriastradh PixmapPtr scratch = NULL; 85203b705cfSriastradh Bool ret; 85303b705cfSriastradh 85403b705cfSriastradh /* The presumption is that we wish to keep the target hot, so 85503b705cfSriastradh * copy to a new bo and move that to the CPU in preference to 85603b705cfSriastradh * causing ping-pong of the original. 85703b705cfSriastradh * 85803b705cfSriastradh * Also the gpu is much faster at detiling. 85903b705cfSriastradh */ 86003b705cfSriastradh 86113496ba1Ssnj priv = intel_uxa_get_pixmap_private(pixmap); 86213496ba1Ssnj if (intel_uxa_pixmap_is_busy(priv) || priv->tiling != I915_TILING_NONE) { 86303b705cfSriastradh ScreenPtr screen = pixmap->drawable.pScreen; 86403b705cfSriastradh GCPtr gc; 86503b705cfSriastradh 86603b705cfSriastradh /* Copy to a linear buffer and pull. */ 86703b705cfSriastradh scratch = screen->CreatePixmap(screen, w, h, 86803b705cfSriastradh pixmap->drawable.depth, 86903b705cfSriastradh INTEL_CREATE_PIXMAP_TILING_NONE); 87003b705cfSriastradh if (!scratch) 87103b705cfSriastradh return FALSE; 87203b705cfSriastradh 87303b705cfSriastradh if (!intel_uxa_pixmap_is_offscreen(scratch)) { 87403b705cfSriastradh screen->DestroyPixmap(scratch); 87503b705cfSriastradh return FALSE; 87603b705cfSriastradh } 87703b705cfSriastradh 87803b705cfSriastradh gc = GetScratchGC(pixmap->drawable.depth, screen); 87903b705cfSriastradh if (!gc) { 88003b705cfSriastradh screen->DestroyPixmap(scratch); 88103b705cfSriastradh return FALSE; 88203b705cfSriastradh } 88303b705cfSriastradh 88403b705cfSriastradh ValidateGC(&pixmap->drawable, gc); 88503b705cfSriastradh 88603b705cfSriastradh gc->ops->CopyArea(&pixmap->drawable, 88703b705cfSriastradh &scratch->drawable, 88803b705cfSriastradh gc, x, y, w, h, 0, 0); 88903b705cfSriastradh 89003b705cfSriastradh FreeScratchGC(gc); 89103b705cfSriastradh 89203b705cfSriastradh intel_batch_submit(xf86ScreenToScrn(screen)); 89303b705cfSriastradh 89403b705cfSriastradh x = y = 0; 89503b705cfSriastradh pixmap = scratch; 89603b705cfSriastradh } 89703b705cfSriastradh 89803b705cfSriastradh ret = intel_uxa_pixmap_get_image(pixmap, x, y, w, h, dst, dst_pitch); 89903b705cfSriastradh 90003b705cfSriastradh if (scratch) 90103b705cfSriastradh scratch->drawable.pScreen->DestroyPixmap(scratch); 90203b705cfSriastradh 90303b705cfSriastradh return ret; 90403b705cfSriastradh} 90503b705cfSriastradh 90603b705cfSriastradhstatic CARD32 intel_cache_expire(OsTimerPtr timer, CARD32 now, pointer data) 90703b705cfSriastradh{ 90803b705cfSriastradh intel_screen_private *intel = data; 90903b705cfSriastradh 91003b705cfSriastradh /* We just want to create and destroy a bo as this causes libdrm 91103b705cfSriastradh * to reap its caches. However, since we can't remove that buffer 91203b705cfSriastradh * from the cache due to its own activity, we want to use something 91303b705cfSriastradh * that we know we will reuse later. The most frequently reused buffer 91403b705cfSriastradh * we have is the batchbuffer, and the best way to trigger its 91503b705cfSriastradh * reallocation is to submit a flush. 91603b705cfSriastradh */ 91703b705cfSriastradh intel_batch_emit_flush(intel->scrn); 91803b705cfSriastradh intel_batch_submit(intel->scrn); 91903b705cfSriastradh 92003b705cfSriastradh return 0; 92103b705cfSriastradh} 92203b705cfSriastradh 92303b705cfSriastradhstatic void intel_flush_rendering(intel_screen_private *intel) 92403b705cfSriastradh{ 92503b705cfSriastradh if (intel->needs_flush == 0) 92603b705cfSriastradh return; 92703b705cfSriastradh 92803b705cfSriastradh if (intel->has_kernel_flush) { 92903b705cfSriastradh intel_batch_submit(intel->scrn); 93003b705cfSriastradh drm_intel_bo_busy(intel->front_buffer); 93103b705cfSriastradh } else { 93203b705cfSriastradh intel_batch_emit_flush(intel->scrn); 93303b705cfSriastradh intel_batch_submit(intel->scrn); 93403b705cfSriastradh } 93503b705cfSriastradh 93603b705cfSriastradh intel->cache_expire = TimerSet(intel->cache_expire, 0, 3000, 93703b705cfSriastradh intel_cache_expire, intel); 93803b705cfSriastradh 93903b705cfSriastradh intel->needs_flush = 0; 94003b705cfSriastradh} 94103b705cfSriastradh 94203b705cfSriastradhstatic void intel_throttle(intel_screen_private *intel) 94303b705cfSriastradh{ 94403b705cfSriastradh drmCommandNone(intel->drmSubFD, DRM_I915_GEM_THROTTLE); 94503b705cfSriastradh} 94603b705cfSriastradh 94703b705cfSriastradhvoid intel_uxa_block_handler(intel_screen_private *intel) 94803b705cfSriastradh{ 94903b705cfSriastradh /* Emit a flush of the rendering cache, or on the 965 95003b705cfSriastradh * and beyond rendering results may not hit the 95103b705cfSriastradh * framebuffer until significantly later. 95203b705cfSriastradh */ 95303b705cfSriastradh intel_flush_rendering(intel); 95403b705cfSriastradh intel_throttle(intel); 95503b705cfSriastradh} 95603b705cfSriastradh 95703b705cfSriastradhstatic PixmapPtr 95803b705cfSriastradhintel_uxa_create_pixmap(ScreenPtr screen, int w, int h, int depth, 95903b705cfSriastradh unsigned usage) 96003b705cfSriastradh{ 96103b705cfSriastradh ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 96203b705cfSriastradh intel_screen_private *intel = intel_get_screen_private(scrn); 96313496ba1Ssnj struct intel_uxa_pixmap *priv; 96403b705cfSriastradh PixmapPtr pixmap, new_pixmap = NULL; 96503b705cfSriastradh 96603b705cfSriastradh if (w > 32767 || h > 32767) 96703b705cfSriastradh return NullPixmap; 96803b705cfSriastradh 96903b705cfSriastradh if (depth == 1 || intel->force_fallback) 97003b705cfSriastradh return fbCreatePixmap(screen, w, h, depth, usage); 97103b705cfSriastradh 97203b705cfSriastradh if (usage == CREATE_PIXMAP_USAGE_GLYPH_PICTURE && w <= 32 && h <= 32) 97303b705cfSriastradh return fbCreatePixmap(screen, w, h, depth, usage); 97403b705cfSriastradh 97503b705cfSriastradh pixmap = fbCreatePixmap(screen, 0, 0, depth, usage); 97603b705cfSriastradh if (pixmap == NullPixmap) 97703b705cfSriastradh return pixmap; 97803b705cfSriastradh 97903b705cfSriastradh if (w && h) { 98003b705cfSriastradh unsigned int size, tiling; 98103b705cfSriastradh int stride; 98203b705cfSriastradh 98303b705cfSriastradh /* Always attempt to tile, compute_size() will remove the 98403b705cfSriastradh * tiling for pixmaps that are either too large or too small 98503b705cfSriastradh * to be effectively tiled. 98603b705cfSriastradh */ 98703b705cfSriastradh tiling = I915_TILING_X; 98803b705cfSriastradh if (usage & INTEL_CREATE_PIXMAP_TILING_Y) 98903b705cfSriastradh tiling = I915_TILING_Y; 99003b705cfSriastradh if (usage == UXA_CREATE_PIXMAP_FOR_MAP || usage & INTEL_CREATE_PIXMAP_TILING_NONE) 99103b705cfSriastradh tiling = I915_TILING_NONE; 99203b705cfSriastradh 99303b705cfSriastradh#ifdef CREATE_PIXMAP_USAGE_SHARED 99403b705cfSriastradh if (usage == CREATE_PIXMAP_USAGE_SHARED) 99503b705cfSriastradh tiling = I915_TILING_NONE; 99603b705cfSriastradh#endif 99703b705cfSriastradh /* if tiling is off force to none */ 99803b705cfSriastradh if (!intel->tiling) 99903b705cfSriastradh tiling = I915_TILING_NONE; 100003b705cfSriastradh 100103b705cfSriastradh if (tiling != I915_TILING_NONE && !(usage & INTEL_CREATE_PIXMAP_DRI2)) { 100203b705cfSriastradh if (h <= 4) 100303b705cfSriastradh tiling = I915_TILING_NONE; 100403b705cfSriastradh if (h <= 16 && tiling == I915_TILING_Y) 100503b705cfSriastradh tiling = I915_TILING_X; 100603b705cfSriastradh } 100713496ba1Ssnj size = intel_compute_size(intel, 100813496ba1Ssnj w, h, pixmap->drawable.bitsPerPixel, usage, 100913496ba1Ssnj &tiling, &stride); 101003b705cfSriastradh 101103b705cfSriastradh /* Fail very large allocations. Large BOs will tend to hit SW fallbacks 101203b705cfSriastradh * frequently, and also will tend to fail to successfully map when doing 101303b705cfSriastradh * SW fallbacks because we overcommit address space for BO access. 101403b705cfSriastradh */ 101503b705cfSriastradh if (size > intel->max_bo_size || stride >= KB(32)) 101603b705cfSriastradh goto fallback_pixmap; 101703b705cfSriastradh 101813496ba1Ssnj priv = calloc(1, sizeof (struct intel_uxa_pixmap)); 101903b705cfSriastradh if (priv == NULL) 102003b705cfSriastradh goto fallback_pixmap; 102103b705cfSriastradh 102203b705cfSriastradh if (usage == UXA_CREATE_PIXMAP_FOR_MAP) { 102303b705cfSriastradh priv->busy = 0; 102403b705cfSriastradh priv->bo = drm_intel_bo_alloc(intel->bufmgr, 102503b705cfSriastradh "pixmap", size, 0); 102603b705cfSriastradh } else { 102703b705cfSriastradh priv->busy = -1; 102803b705cfSriastradh priv->bo = drm_intel_bo_alloc_for_render(intel->bufmgr, 102903b705cfSriastradh "pixmap", 103003b705cfSriastradh size, 0); 103103b705cfSriastradh } 103203b705cfSriastradh if (!priv->bo) 103303b705cfSriastradh goto fallback_priv; 103403b705cfSriastradh 103503b705cfSriastradh if (tiling != I915_TILING_NONE) 103603b705cfSriastradh drm_intel_bo_set_tiling(priv->bo, &tiling, stride); 103703b705cfSriastradh priv->tiling = tiling; 103803b705cfSriastradh priv->offscreen = 1; 103903b705cfSriastradh 104003b705cfSriastradh list_init(&priv->batch); 104113496ba1Ssnj intel_uxa_set_pixmap_private(pixmap, priv); 104203b705cfSriastradh 104303b705cfSriastradh screen->ModifyPixmapHeader(pixmap, w, h, 0, 0, stride, NULL); 104403b705cfSriastradh } 104503b705cfSriastradh 104603b705cfSriastradh return pixmap; 104703b705cfSriastradh 104803b705cfSriastradhfallback_priv: 104903b705cfSriastradh free(priv); 105003b705cfSriastradhfallback_pixmap: 105103b705cfSriastradh fbDestroyPixmap(pixmap); 105203b705cfSriastradh if (new_pixmap) 105303b705cfSriastradh return new_pixmap; 105403b705cfSriastradh else 105503b705cfSriastradh return fbCreatePixmap(screen, w, h, depth, usage); 105603b705cfSriastradh} 105703b705cfSriastradh 105803b705cfSriastradhstatic Bool intel_uxa_destroy_pixmap(PixmapPtr pixmap) 105903b705cfSriastradh{ 106013496ba1Ssnj if (pixmap->refcnt == 1) 106113496ba1Ssnj intel_uxa_set_pixmap_bo(pixmap, NULL); 106203b705cfSriastradh fbDestroyPixmap(pixmap); 106303b705cfSriastradh return TRUE; 106403b705cfSriastradh} 106503b705cfSriastradh 106603b705cfSriastradhBool intel_uxa_create_screen_resources(ScreenPtr screen) 106703b705cfSriastradh{ 106803b705cfSriastradh ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 106903b705cfSriastradh PixmapPtr pixmap; 107003b705cfSriastradh intel_screen_private *intel = intel_get_screen_private(scrn); 107103b705cfSriastradh dri_bo *bo = intel->front_buffer; 107242542f5fSchristos int old_width, old_height, old_pitch; 107303b705cfSriastradh 107403b705cfSriastradh if (!uxa_resources_init(screen)) 107503b705cfSriastradh return FALSE; 107603b705cfSriastradh 107703b705cfSriastradh if (drm_intel_gem_bo_map_gtt(bo)) 107803b705cfSriastradh return FALSE; 107903b705cfSriastradh 108003b705cfSriastradh pixmap = screen->GetScreenPixmap(screen); 108142542f5fSchristos old_width = pixmap->drawable.width; 108242542f5fSchristos old_height = pixmap->drawable.height; 108342542f5fSchristos old_pitch = pixmap->devKind; 108442542f5fSchristos 108542542f5fSchristos if (!screen->ModifyPixmapHeader(pixmap, 108642542f5fSchristos scrn->virtualX, 108742542f5fSchristos scrn->virtualY, 108842542f5fSchristos -1, -1, 108942542f5fSchristos intel->front_pitch, 109042542f5fSchristos NULL)) 109142542f5fSchristos return FALSE; 109242542f5fSchristos 109313496ba1Ssnj intel_uxa_set_pixmap_bo(pixmap, bo); 109413496ba1Ssnj if (intel_uxa_get_pixmap_private(pixmap) == NULL) 109542542f5fSchristos goto err; 109603b705cfSriastradh 109713496ba1Ssnj intel_uxa_get_pixmap_private(pixmap)->pinned |= PIN_SCANOUT; 109842542f5fSchristos scrn->displayWidth = intel->front_pitch / intel->cpp; 109903b705cfSriastradh 110003b705cfSriastradh return TRUE; 110142542f5fSchristos 110242542f5fSchristoserr: 110342542f5fSchristos screen->ModifyPixmapHeader(pixmap, 110442542f5fSchristos old_width, old_height, -1, -1, old_pitch, NULL); 110542542f5fSchristos return FALSE; 110603b705cfSriastradh} 110703b705cfSriastradh 110803b705cfSriastradh#ifdef CREATE_PIXMAP_USAGE_SHARED 110903b705cfSriastradhstatic Bool 111003b705cfSriastradhintel_uxa_share_pixmap_backing(PixmapPtr ppix, ScreenPtr slave, void **fd_handle) 111103b705cfSriastradh{ 111203b705cfSriastradh ScrnInfoPtr scrn = xf86ScreenToScrn(ppix->drawable.pScreen); 111303b705cfSriastradh intel_screen_private *intel = intel_get_screen_private(scrn); 111413496ba1Ssnj struct intel_uxa_pixmap *priv = intel_uxa_get_pixmap_private(ppix); 111503b705cfSriastradh unsigned int size, tiling, swizzle; 111613496ba1Ssnj dri_bo *bo = intel_uxa_get_pixmap_bo(ppix), *newbo; 111703b705cfSriastradh int stride; 111803b705cfSriastradh int handle; 111903b705cfSriastradh 112003b705cfSriastradh if (drm_intel_bo_references(intel->batch_bo, bo)) 112103b705cfSriastradh intel_batch_submit(intel->scrn); 112203b705cfSriastradh 112303b705cfSriastradh drm_intel_bo_get_tiling(bo, &tiling, &swizzle); 112403b705cfSriastradh 112503b705cfSriastradh if (tiling == I915_TILING_X) { 112642542f5fSchristos if (priv->pinned) 112703b705cfSriastradh return FALSE; 112803b705cfSriastradh 112903b705cfSriastradh tiling = I915_TILING_NONE; 113003b705cfSriastradh 113113496ba1Ssnj size = intel_compute_size(intel, 113213496ba1Ssnj ppix->drawable.width, ppix->drawable.height, 113313496ba1Ssnj ppix->drawable.bitsPerPixel, INTEL_CREATE_PIXMAP_DRI2, 113413496ba1Ssnj &tiling, &stride); 113503b705cfSriastradh 113603b705cfSriastradh newbo = drm_intel_bo_alloc_for_render(intel->bufmgr, 113703b705cfSriastradh "pixmap", 113803b705cfSriastradh size, 0); 113903b705cfSriastradh 114003b705cfSriastradh if (tiling != I915_TILING_NONE) 114103b705cfSriastradh drm_intel_bo_set_tiling(newbo, &tiling, stride); 114203b705cfSriastradh priv->tiling = tiling; 114313496ba1Ssnj intel_uxa_set_pixmap_bo(ppix, newbo); 114403b705cfSriastradh 114503b705cfSriastradh ppix->drawable.pScreen->ModifyPixmapHeader(ppix, ppix->drawable.width, 114603b705cfSriastradh ppix->drawable.height, 0, 0, 114703b705cfSriastradh stride, NULL); 114803b705cfSriastradh bo = newbo; 114903b705cfSriastradh } 115003b705cfSriastradh drm_intel_bo_get_tiling(bo, &tiling, &swizzle); 115103b705cfSriastradh drm_intel_bo_gem_export_to_prime(bo, &handle); 115242542f5fSchristos priv->pinned |= PIN_PRIME; 115303b705cfSriastradh 115403b705cfSriastradh *fd_handle = (void *)(long)handle; 115503b705cfSriastradh return TRUE; 115603b705cfSriastradh} 115703b705cfSriastradh 115803b705cfSriastradhstatic Bool 115903b705cfSriastradhintel_uxa_set_shared_pixmap_backing(PixmapPtr ppix, void *fd_handle) 116003b705cfSriastradh{ 116103b705cfSriastradh ScrnInfoPtr scrn = xf86ScreenToScrn(ppix->drawable.pScreen); 116203b705cfSriastradh intel_screen_private *intel = intel_get_screen_private(scrn); 116303b705cfSriastradh dri_bo *bo; 116403b705cfSriastradh int ihandle = (int)(long)fd_handle; 116503b705cfSriastradh 116603b705cfSriastradh /* force untiled for now */ 116703b705cfSriastradh bo = drm_intel_bo_gem_create_from_prime(intel->bufmgr, ihandle, 0); 116803b705cfSriastradh if (!bo) 116903b705cfSriastradh return FALSE; 117003b705cfSriastradh 117113496ba1Ssnj intel_uxa_set_pixmap_bo(ppix, bo); 117203b705cfSriastradh close(ihandle); 117303b705cfSriastradh return TRUE; 117403b705cfSriastradh} 117503b705cfSriastradh#endif 117603b705cfSriastradh 117703b705cfSriastradhstatic void 117803b705cfSriastradhintel_limits_init(intel_screen_private *intel) 117903b705cfSriastradh{ 118003b705cfSriastradh /* Limits are described in the BLT engine chapter under Graphics Data Size 118103b705cfSriastradh * Limitations, and the descriptions of SURFACE_STATE, 3DSTATE_BUFFER_INFO, 118203b705cfSriastradh * 3DSTATE_DRAWING_RECTANGLE, 3DSTATE_MAP_INFO, and 3DSTATE_MAP_INFO. 118303b705cfSriastradh * 118403b705cfSriastradh * i845 through i965 limits 2D rendering to 65536 lines and pitch of 32768. 118503b705cfSriastradh * 118603b705cfSriastradh * i965 limits 3D surface to (2*element size)-aligned offset if un-tiled. 118703b705cfSriastradh * i965 limits 3D surface to 4kB-aligned offset if tiled. 118803b705cfSriastradh * i965 limits 3D surfaces to w,h of ?,8192. 118903b705cfSriastradh * i965 limits 3D surface to pitch of 1B - 128kB. 119003b705cfSriastradh * i965 limits 3D surface pitch alignment to 1 or 2 times the element size. 119103b705cfSriastradh * i965 limits 3D surface pitch alignment to 512B if tiled. 119203b705cfSriastradh * i965 limits 3D destination drawing rect to w,h of 8192,8192. 119303b705cfSriastradh * 119403b705cfSriastradh * i915 limits 3D textures to 4B-aligned offset if un-tiled. 119503b705cfSriastradh * i915 limits 3D textures to ~4kB-aligned offset if tiled. 119603b705cfSriastradh * i915 limits 3D textures to width,height of 2048,2048. 119703b705cfSriastradh * i915 limits 3D textures to pitch of 16B - 8kB, in dwords. 119803b705cfSriastradh * i915 limits 3D destination to ~4kB-aligned offset if tiled. 119903b705cfSriastradh * i915 limits 3D destination to pitch of 16B - 8kB, in dwords, if un-tiled. 120003b705cfSriastradh * i915 limits 3D destination to pitch 64B-aligned if used with depth. 120103b705cfSriastradh * i915 limits 3D destination to pitch of 512B - 8kB, in tiles, if tiled. 120203b705cfSriastradh * i915 limits 3D destination to POT aligned pitch if tiled. 120303b705cfSriastradh * i915 limits 3D destination drawing rect to w,h of 2048,2048. 120403b705cfSriastradh * 120503b705cfSriastradh * i845 limits 3D textures to 4B-aligned offset if un-tiled. 120603b705cfSriastradh * i845 limits 3D textures to ~4kB-aligned offset if tiled. 120703b705cfSriastradh * i845 limits 3D textures to width,height of 2048,2048. 120803b705cfSriastradh * i845 limits 3D textures to pitch of 4B - 8kB, in dwords. 120903b705cfSriastradh * i845 limits 3D destination to 4B-aligned offset if un-tiled. 121003b705cfSriastradh * i845 limits 3D destination to ~4kB-aligned offset if tiled. 121103b705cfSriastradh * i845 limits 3D destination to pitch of 8B - 8kB, in dwords. 121203b705cfSriastradh * i845 limits 3D destination drawing rect to w,h of 2048,2048. 121303b705cfSriastradh * 121403b705cfSriastradh * For the tiled issues, the only tiled buffer we draw to should be 121503b705cfSriastradh * the front, which will have an appropriate pitch/offset already set up, 121603b705cfSriastradh * so UXA doesn't need to worry. 121703b705cfSriastradh */ 121803b705cfSriastradh if (INTEL_INFO(intel)->gen >= 040) { 121903b705cfSriastradh intel->accel_pixmap_offset_alignment = 4 * 2; 122003b705cfSriastradh intel->accel_max_x = 8192; 122103b705cfSriastradh intel->accel_max_y = 8192; 122203b705cfSriastradh } else { 122303b705cfSriastradh intel->accel_pixmap_offset_alignment = 4; 122403b705cfSriastradh intel->accel_max_x = 2048; 122503b705cfSriastradh intel->accel_max_y = 2048; 122603b705cfSriastradh } 122703b705cfSriastradh} 122803b705cfSriastradh 122942542f5fSchristosstatic Bool intel_option_accel_none(intel_screen_private *intel) 123042542f5fSchristos{ 123142542f5fSchristos const char *s; 123242542f5fSchristos 123342542f5fSchristos s = xf86GetOptValString(intel->Options, OPTION_ACCEL_METHOD); 123442542f5fSchristos if (s == NULL) 123542542f5fSchristos return IS_DEFAULT_ACCEL_METHOD(NOACCEL); 123642542f5fSchristos 123742542f5fSchristos return strcasecmp(s, "none") == 0; 123842542f5fSchristos} 123942542f5fSchristos 124003b705cfSriastradhstatic Bool intel_option_accel_blt(intel_screen_private *intel) 124103b705cfSriastradh{ 124203b705cfSriastradh const char *s; 124303b705cfSriastradh 124403b705cfSriastradh s = xf86GetOptValString(intel->Options, OPTION_ACCEL_METHOD); 124503b705cfSriastradh if (s == NULL) 124603b705cfSriastradh return FALSE; 124703b705cfSriastradh 124803b705cfSriastradh return strcasecmp(s, "blt") == 0; 124903b705cfSriastradh} 125003b705cfSriastradh 125113496ba1Ssnj/** 125213496ba1Ssnj * Intialiazes the hardware for the 3D pipeline use in the 2D driver. 125313496ba1Ssnj * 125413496ba1Ssnj * Some state caching is performed to avoid redundant state emits. This 125513496ba1Ssnj * function is also responsible for marking the state as clobbered for DRI 125613496ba1Ssnj * clients. 125713496ba1Ssnj */ 125813496ba1Ssnjvoid IntelEmitInvarientState(ScrnInfoPtr scrn) 125913496ba1Ssnj{ 126013496ba1Ssnj intel_screen_private *intel = intel_get_screen_private(scrn); 126113496ba1Ssnj 126213496ba1Ssnj /* If we've emitted our state since the last clobber by another client, 126313496ba1Ssnj * skip it. 126413496ba1Ssnj */ 126513496ba1Ssnj if (intel->last_3d != LAST_3D_OTHER) 126613496ba1Ssnj return; 126713496ba1Ssnj 126813496ba1Ssnj if (IS_GEN2(intel)) 126913496ba1Ssnj I830EmitInvarientState(scrn); 127013496ba1Ssnj else if IS_GEN3(intel) 127113496ba1Ssnj I915EmitInvarientState(scrn); 127213496ba1Ssnj} 127313496ba1Ssnj 127403b705cfSriastradhBool intel_uxa_init(ScreenPtr screen) 127503b705cfSriastradh{ 127603b705cfSriastradh ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 127703b705cfSriastradh intel_screen_private *intel = intel_get_screen_private(scrn); 127803b705cfSriastradh 127913496ba1Ssnj intel_batch_init(scrn); 128013496ba1Ssnj 128113496ba1Ssnj if (INTEL_INFO(intel)->gen >= 040 && INTEL_INFO(intel)->gen < 0100) 128213496ba1Ssnj gen4_render_state_init(scrn); 128313496ba1Ssnj 128403b705cfSriastradh#if HAS_DIXREGISTERPRIVATEKEY 128503b705cfSriastradh if (!dixRegisterPrivateKey(&uxa_pixmap_index, PRIVATE_PIXMAP, 0)) 128603b705cfSriastradh#else 128703b705cfSriastradh if (!dixRequestPrivate(&uxa_pixmap_index, 0)) 128803b705cfSriastradh#endif 128903b705cfSriastradh return FALSE; 129003b705cfSriastradh 129103b705cfSriastradh intel_limits_init(intel); 129203b705cfSriastradh 129303b705cfSriastradh intel->uxa_driver = uxa_driver_alloc(); 129403b705cfSriastradh if (intel->uxa_driver == NULL) 129503b705cfSriastradh return FALSE; 129603b705cfSriastradh 129703b705cfSriastradh memset(intel->uxa_driver, 0, sizeof(*intel->uxa_driver)); 129803b705cfSriastradh 129903b705cfSriastradh intel->uxa_driver->uxa_major = 1; 130003b705cfSriastradh intel->uxa_driver->uxa_minor = 0; 130103b705cfSriastradh 130203b705cfSriastradh intel->prim_offset = 0; 130303b705cfSriastradh intel->vertex_count = 0; 130403b705cfSriastradh intel->vertex_offset = 0; 130503b705cfSriastradh intel->vertex_used = 0; 130603b705cfSriastradh intel->floats_per_vertex = 0; 130703b705cfSriastradh intel->last_floats_per_vertex = 0; 130803b705cfSriastradh intel->vertex_bo = NULL; 130903b705cfSriastradh intel->surface_used = 0; 131003b705cfSriastradh intel->surface_reloc = 0; 131103b705cfSriastradh 131203b705cfSriastradh /* Solid fill */ 131303b705cfSriastradh intel->uxa_driver->check_solid = intel_uxa_check_solid; 131403b705cfSriastradh intel->uxa_driver->prepare_solid = intel_uxa_prepare_solid; 131503b705cfSriastradh intel->uxa_driver->solid = intel_uxa_solid; 131603b705cfSriastradh intel->uxa_driver->done_solid = intel_uxa_done; 131703b705cfSriastradh 131803b705cfSriastradh /* Copy */ 131903b705cfSriastradh intel->uxa_driver->check_copy = intel_uxa_check_copy; 132003b705cfSriastradh intel->uxa_driver->prepare_copy = intel_uxa_prepare_copy; 132103b705cfSriastradh intel->uxa_driver->copy = intel_uxa_copy; 132203b705cfSriastradh intel->uxa_driver->done_copy = intel_uxa_done; 132303b705cfSriastradh 132403b705cfSriastradh /* Composite */ 132503b705cfSriastradh if (intel_option_accel_blt(intel)) { 132642542f5fSchristos } else if (INTEL_INFO(intel)->gen < 030) { 132703b705cfSriastradh intel->uxa_driver->check_composite = i830_check_composite; 132803b705cfSriastradh intel->uxa_driver->check_composite_target = i830_check_composite_target; 132903b705cfSriastradh intel->uxa_driver->check_composite_texture = i830_check_composite_texture; 133003b705cfSriastradh intel->uxa_driver->prepare_composite = i830_prepare_composite; 133103b705cfSriastradh intel->uxa_driver->composite = i830_composite; 133203b705cfSriastradh intel->uxa_driver->done_composite = i830_done_composite; 133303b705cfSriastradh 133403b705cfSriastradh intel->vertex_flush = i830_vertex_flush; 133503b705cfSriastradh intel->batch_commit_notify = i830_batch_commit_notify; 133642542f5fSchristos } else if (INTEL_INFO(intel)->gen < 040) { 133703b705cfSriastradh intel->uxa_driver->check_composite = i915_check_composite; 133803b705cfSriastradh intel->uxa_driver->check_composite_target = i915_check_composite_target; 133903b705cfSriastradh intel->uxa_driver->check_composite_texture = i915_check_composite_texture; 134003b705cfSriastradh intel->uxa_driver->prepare_composite = i915_prepare_composite; 134103b705cfSriastradh intel->uxa_driver->composite = i915_composite; 134203b705cfSriastradh intel->uxa_driver->done_composite = i830_done_composite; 134303b705cfSriastradh 134403b705cfSriastradh intel->vertex_flush = i915_vertex_flush; 134503b705cfSriastradh intel->batch_commit_notify = i915_batch_commit_notify; 134642542f5fSchristos } else if (INTEL_INFO(intel)->gen < 0100) { 134703b705cfSriastradh intel->uxa_driver->check_composite = i965_check_composite; 134803b705cfSriastradh intel->uxa_driver->check_composite_texture = i965_check_composite_texture; 134903b705cfSriastradh intel->uxa_driver->prepare_composite = i965_prepare_composite; 135003b705cfSriastradh intel->uxa_driver->composite = i965_composite; 135103b705cfSriastradh intel->uxa_driver->done_composite = i830_done_composite; 135203b705cfSriastradh 135303b705cfSriastradh intel->vertex_flush = i965_vertex_flush; 135403b705cfSriastradh intel->batch_flush = i965_batch_flush; 135503b705cfSriastradh intel->batch_commit_notify = i965_batch_commit_notify; 135603b705cfSriastradh 135742542f5fSchristos if (INTEL_INFO(intel)->gen < 050) { 135803b705cfSriastradh intel->context_switch = gen4_context_switch; 135942542f5fSchristos } else if (INTEL_INFO(intel)->gen < 060) { 136003b705cfSriastradh intel->context_switch = gen5_context_switch; 136103b705cfSriastradh } else { 136203b705cfSriastradh intel->context_switch = gen6_context_switch; 136303b705cfSriastradh } 136403b705cfSriastradh } 136503b705cfSriastradh 136603b705cfSriastradh /* PutImage */ 136703b705cfSriastradh intel->uxa_driver->put_image = intel_uxa_put_image; 136803b705cfSriastradh intel->uxa_driver->get_image = intel_uxa_get_image; 136903b705cfSriastradh 137003b705cfSriastradh intel->uxa_driver->prepare_access = intel_uxa_prepare_access; 137103b705cfSriastradh intel->uxa_driver->finish_access = intel_uxa_finish_access; 137203b705cfSriastradh intel->uxa_driver->pixmap_is_offscreen = intel_uxa_pixmap_is_offscreen; 137303b705cfSriastradh 137403b705cfSriastradh screen->CreatePixmap = intel_uxa_create_pixmap; 137503b705cfSriastradh screen->DestroyPixmap = intel_uxa_destroy_pixmap; 137603b705cfSriastradh 137703b705cfSriastradh#ifdef CREATE_PIXMAP_USAGE_SHARED 137803b705cfSriastradh screen->SharePixmapBacking = intel_uxa_share_pixmap_backing; 137903b705cfSriastradh screen->SetSharedPixmapBacking = intel_uxa_set_shared_pixmap_backing; 138003b705cfSriastradh#endif 138103b705cfSriastradh 138203b705cfSriastradh if (!uxa_driver_init(screen, intel->uxa_driver)) { 138303b705cfSriastradh xf86DrvMsg(scrn->scrnIndex, X_ERROR, 138403b705cfSriastradh "UXA initialization failed\n"); 138503b705cfSriastradh free(intel->uxa_driver); 138603b705cfSriastradh return FALSE; 138703b705cfSriastradh } 138803b705cfSriastradh 138942542f5fSchristos if (intel_option_accel_none(intel)) 139042542f5fSchristos intel->force_fallback = 1; 139142542f5fSchristos 139203b705cfSriastradh uxa_set_fallback_debug(screen, intel->fallback_debug); 139303b705cfSriastradh uxa_set_force_fallback(screen, intel->force_fallback); 139403b705cfSriastradh 139542542f5fSchristos intel->flush_rendering = intel_flush_rendering; 139603b705cfSriastradh return TRUE; 139703b705cfSriastradh} 1398