1428d7b3dSmrg/************************************************************************** 2428d7b3dSmrg 3428d7b3dSmrgCopyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. 4428d7b3dSmrgAll Rights Reserved. 5428d7b3dSmrgCopyright (c) 2005 Jesse Barnes <jbarnes@virtuousgeek.org> 6428d7b3dSmrg Based on code from i830_xaa.c. 7428d7b3dSmrg 8428d7b3dSmrgPermission is hereby granted, free of charge, to any person obtaining a 9428d7b3dSmrgcopy of this software and associated documentation files (the 10428d7b3dSmrg"Software"), to deal in the Software without restriction, including 11428d7b3dSmrgwithout limitation the rights to use, copy, modify, merge, publish, 12428d7b3dSmrgdistribute, sub license, and/or sell copies of the Software, and to 13428d7b3dSmrgpermit persons to whom the Software is furnished to do so, subject to 14428d7b3dSmrgthe following conditions: 15428d7b3dSmrg 16428d7b3dSmrgThe above copyright notice and this permission notice (including the 17428d7b3dSmrgnext paragraph) shall be included in all copies or substantial portions 18428d7b3dSmrgof the Software. 19428d7b3dSmrg 20428d7b3dSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 21428d7b3dSmrgOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 22428d7b3dSmrgMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 23428d7b3dSmrgIN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR 24428d7b3dSmrgANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 25428d7b3dSmrgTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 26428d7b3dSmrgSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 27428d7b3dSmrg 28428d7b3dSmrg**************************************************************************/ 29428d7b3dSmrg 30428d7b3dSmrg#ifdef HAVE_CONFIG_H 31428d7b3dSmrg#include "config.h" 32428d7b3dSmrg#endif 33428d7b3dSmrg 34428d7b3dSmrg#include "xorg-server.h" 35428d7b3dSmrg#include <xf86.h> 36428d7b3dSmrg#include <xf86drm.h> 37428d7b3dSmrg#include <xaarop.h> 38428d7b3dSmrg#include <string.h> 39428d7b3dSmrg#include <errno.h> 40428d7b3dSmrg#include <unistd.h> 41428d7b3dSmrg 42428d7b3dSmrg#include "intel.h" 43428d7b3dSmrg#include "intel_uxa.h" 44428d7b3dSmrg 45428d7b3dSmrg#include "i830_reg.h" 46428d7b3dSmrg#include "i915_drm.h" 47428d7b3dSmrg#include "brw_defines.h" 48428d7b3dSmrg 49428d7b3dSmrgstatic const int I830CopyROP[16] = { 50428d7b3dSmrg ROP_0, /* GXclear */ 51428d7b3dSmrg ROP_DSa, /* GXand */ 52428d7b3dSmrg ROP_SDna, /* GXandReverse */ 53428d7b3dSmrg ROP_S, /* GXcopy */ 54428d7b3dSmrg ROP_DSna, /* GXandInverted */ 55428d7b3dSmrg ROP_D, /* GXnoop */ 56428d7b3dSmrg ROP_DSx, /* GXxor */ 57428d7b3dSmrg ROP_DSo, /* GXor */ 58428d7b3dSmrg ROP_DSon, /* GXnor */ 59428d7b3dSmrg ROP_DSxn, /* GXequiv */ 60428d7b3dSmrg ROP_Dn, /* GXinvert */ 61428d7b3dSmrg ROP_SDno, /* GXorReverse */ 62428d7b3dSmrg ROP_Sn, /* GXcopyInverted */ 63428d7b3dSmrg ROP_DSno, /* GXorInverted */ 64428d7b3dSmrg ROP_DSan, /* GXnand */ 65428d7b3dSmrg ROP_1 /* GXset */ 66428d7b3dSmrg}; 67428d7b3dSmrg 68428d7b3dSmrgstatic const int I830PatternROP[16] = { 69428d7b3dSmrg ROP_0, 70428d7b3dSmrg ROP_DPa, 71428d7b3dSmrg ROP_PDna, 72428d7b3dSmrg ROP_P, 73428d7b3dSmrg ROP_DPna, 74428d7b3dSmrg ROP_D, 75428d7b3dSmrg ROP_DPx, 76428d7b3dSmrg ROP_DPo, 77428d7b3dSmrg ROP_DPon, 78428d7b3dSmrg ROP_PDxn, 79428d7b3dSmrg ROP_Dn, 80428d7b3dSmrg ROP_PDno, 81428d7b3dSmrg ROP_Pn, 82428d7b3dSmrg ROP_DPno, 83428d7b3dSmrg ROP_DPan, 84428d7b3dSmrg ROP_1 85428d7b3dSmrg}; 86428d7b3dSmrg 87428d7b3dSmrg#if HAS_DEVPRIVATEKEYREC 88428d7b3dSmrgDevPrivateKeyRec uxa_pixmap_index; 89428d7b3dSmrg#else 90428d7b3dSmrgint uxa_pixmap_index; 91428d7b3dSmrg#endif 92428d7b3dSmrg 93428d7b3dSmrgstatic void 94428d7b3dSmrggen6_context_switch(intel_screen_private *intel, 95428d7b3dSmrg int new_mode) 96428d7b3dSmrg{ 97428d7b3dSmrg intel_batch_submit(intel->scrn); 98428d7b3dSmrg} 99428d7b3dSmrg 100428d7b3dSmrgstatic void 101428d7b3dSmrggen5_context_switch(intel_screen_private *intel, 102428d7b3dSmrg int new_mode) 103428d7b3dSmrg{ 104428d7b3dSmrg /* Ironlake has a limitation that a 3D or Media command can't 105428d7b3dSmrg * be the first command after a BLT, unless it's 106428d7b3dSmrg * non-pipelined. Instead of trying to track it and emit a 107428d7b3dSmrg * command at the right time, we just emit a dummy 108428d7b3dSmrg * non-pipelined 3D instruction after each blit. 109428d7b3dSmrg */ 110428d7b3dSmrg 111428d7b3dSmrg if (new_mode == I915_EXEC_BLT) { 112428d7b3dSmrg OUT_BATCH(MI_FLUSH | 113428d7b3dSmrg MI_STATE_INSTRUCTION_CACHE_FLUSH | 114428d7b3dSmrg MI_INHIBIT_RENDER_CACHE_FLUSH); 115428d7b3dSmrg } else { 116428d7b3dSmrg OUT_BATCH(CMD_POLY_STIPPLE_OFFSET << 16); 117428d7b3dSmrg OUT_BATCH(0); 118428d7b3dSmrg } 119428d7b3dSmrg} 120428d7b3dSmrg 121428d7b3dSmrgstatic void 122428d7b3dSmrggen4_context_switch(intel_screen_private *intel, 123428d7b3dSmrg int new_mode) 124428d7b3dSmrg{ 125428d7b3dSmrg if (new_mode == I915_EXEC_BLT) { 126428d7b3dSmrg OUT_BATCH(MI_FLUSH | 127428d7b3dSmrg MI_STATE_INSTRUCTION_CACHE_FLUSH | 128428d7b3dSmrg MI_INHIBIT_RENDER_CACHE_FLUSH); 129428d7b3dSmrg } 130428d7b3dSmrg} 131428d7b3dSmrg 132428d7b3dSmrgBool 133428d7b3dSmrgintel_uxa_get_aperture_space(ScrnInfoPtr scrn, drm_intel_bo ** bo_table, 134428d7b3dSmrg int num_bos) 135428d7b3dSmrg{ 136428d7b3dSmrg intel_screen_private *intel = intel_get_screen_private(scrn); 137428d7b3dSmrg 138428d7b3dSmrg if (intel->batch_bo == NULL) { 139428d7b3dSmrg intel_uxa_debug_fallback(scrn, "VT inactive\n"); 140428d7b3dSmrg return FALSE; 141428d7b3dSmrg } 142428d7b3dSmrg 143428d7b3dSmrg bo_table[0] = intel->batch_bo; 144428d7b3dSmrg if (drm_intel_bufmgr_check_aperture_space(bo_table, num_bos) != 0) { 145428d7b3dSmrg intel_batch_submit(scrn); 146428d7b3dSmrg bo_table[0] = intel->batch_bo; 147428d7b3dSmrg if (drm_intel_bufmgr_check_aperture_space(bo_table, num_bos) != 148428d7b3dSmrg 0) { 149428d7b3dSmrg intel_uxa_debug_fallback(scrn, "Couldn't get aperture " 150428d7b3dSmrg "space for BOs\n"); 151428d7b3dSmrg return FALSE; 152428d7b3dSmrg } 153428d7b3dSmrg } 154428d7b3dSmrg return TRUE; 155428d7b3dSmrg} 156428d7b3dSmrg 157428d7b3dSmrgstatic Bool 158428d7b3dSmrgintel_uxa_check_solid(DrawablePtr drawable, int alu, Pixel planemask) 159428d7b3dSmrg{ 160428d7b3dSmrg ScrnInfoPtr scrn = xf86ScreenToScrn(drawable->pScreen); 161428d7b3dSmrg 162428d7b3dSmrg if (!UXA_PM_IS_SOLID(drawable, planemask)) { 163428d7b3dSmrg intel_uxa_debug_fallback(scrn, "planemask is not solid\n"); 164428d7b3dSmrg return FALSE; 165428d7b3dSmrg } 166428d7b3dSmrg 167428d7b3dSmrg switch (drawable->bitsPerPixel) { 168428d7b3dSmrg case 8: 169428d7b3dSmrg case 16: 170428d7b3dSmrg case 32: 171428d7b3dSmrg break; 172428d7b3dSmrg default: 173428d7b3dSmrg return FALSE; 174428d7b3dSmrg } 175428d7b3dSmrg 176428d7b3dSmrg return TRUE; 177428d7b3dSmrg} 178428d7b3dSmrg 179428d7b3dSmrg/** 180428d7b3dSmrg * Sets up hardware state for a series of solid fills. 181428d7b3dSmrg */ 182428d7b3dSmrgstatic Bool 183428d7b3dSmrgintel_uxa_prepare_solid(PixmapPtr pixmap, int alu, Pixel planemask, Pixel fg) 184428d7b3dSmrg{ 185428d7b3dSmrg ScrnInfoPtr scrn = xf86ScreenToScrn(pixmap->drawable.pScreen); 186428d7b3dSmrg intel_screen_private *intel = intel_get_screen_private(scrn); 187428d7b3dSmrg drm_intel_bo *bo_table[] = { 188428d7b3dSmrg NULL, /* batch_bo */ 189428d7b3dSmrg intel_uxa_get_pixmap_bo(pixmap), 190428d7b3dSmrg }; 191428d7b3dSmrg 192428d7b3dSmrg if (!intel_uxa_check_pitch_2d(pixmap)) 193428d7b3dSmrg return FALSE; 194428d7b3dSmrg 195428d7b3dSmrg if (!intel_uxa_get_aperture_space(scrn, bo_table, ARRAY_SIZE(bo_table))) 196428d7b3dSmrg return FALSE; 197428d7b3dSmrg 198428d7b3dSmrg intel->BR[13] = (I830PatternROP[alu] & 0xff) << 16; 199428d7b3dSmrg switch (pixmap->drawable.bitsPerPixel) { 200428d7b3dSmrg case 8: 201428d7b3dSmrg break; 202428d7b3dSmrg case 16: 203428d7b3dSmrg /* RGB565 */ 204428d7b3dSmrg intel->BR[13] |= (1 << 24); 205428d7b3dSmrg break; 206428d7b3dSmrg case 32: 207428d7b3dSmrg /* RGB8888 */ 208428d7b3dSmrg intel->BR[13] |= ((1 << 24) | (1 << 25)); 209428d7b3dSmrg break; 210428d7b3dSmrg } 211428d7b3dSmrg intel->BR[16] = fg; 212428d7b3dSmrg 213428d7b3dSmrg return TRUE; 214428d7b3dSmrg} 215428d7b3dSmrg 216428d7b3dSmrgstatic void intel_uxa_solid(PixmapPtr pixmap, int x1, int y1, int x2, int y2) 217428d7b3dSmrg{ 218428d7b3dSmrg ScrnInfoPtr scrn = xf86ScreenToScrn(pixmap->drawable.pScreen); 219428d7b3dSmrg intel_screen_private *intel = intel_get_screen_private(scrn); 220428d7b3dSmrg unsigned long pitch; 221428d7b3dSmrg uint32_t cmd; 222428d7b3dSmrg 223428d7b3dSmrg if (x1 < 0) 224428d7b3dSmrg x1 = 0; 225428d7b3dSmrg if (y1 < 0) 226428d7b3dSmrg y1 = 0; 227428d7b3dSmrg if (x2 > pixmap->drawable.width) 228428d7b3dSmrg x2 = pixmap->drawable.width; 229428d7b3dSmrg if (y2 > pixmap->drawable.height) 230428d7b3dSmrg y2 = pixmap->drawable.height; 231428d7b3dSmrg 232428d7b3dSmrg if (x2 <= x1 || y2 <= y1) 233428d7b3dSmrg return; 234428d7b3dSmrg 235428d7b3dSmrg pitch = intel_pixmap_pitch(pixmap); 236428d7b3dSmrg 237428d7b3dSmrg { 238428d7b3dSmrg int len = INTEL_INFO(intel)->gen >= 0100 ? 7 : 6; 239428d7b3dSmrg BEGIN_BATCH_BLT(len); 240428d7b3dSmrg 241428d7b3dSmrg cmd = XY_COLOR_BLT_CMD | (len - 2); 242428d7b3dSmrg 243428d7b3dSmrg if (pixmap->drawable.bitsPerPixel == 32) 244428d7b3dSmrg cmd |= 245428d7b3dSmrg XY_COLOR_BLT_WRITE_ALPHA | XY_COLOR_BLT_WRITE_RGB; 246428d7b3dSmrg 247428d7b3dSmrg if (INTEL_INFO(intel)->gen >= 040 && intel_uxa_pixmap_tiled(pixmap)) { 248428d7b3dSmrg assert((pitch % 512) == 0); 249428d7b3dSmrg pitch >>= 2; 250428d7b3dSmrg cmd |= XY_COLOR_BLT_TILED; 251428d7b3dSmrg } 252428d7b3dSmrg 253428d7b3dSmrg OUT_BATCH(cmd); 254428d7b3dSmrg 255428d7b3dSmrg OUT_BATCH(intel->BR[13] | pitch); 256428d7b3dSmrg OUT_BATCH((y1 << 16) | (x1 & 0xffff)); 257428d7b3dSmrg OUT_BATCH((y2 << 16) | (x2 & 0xffff)); 258428d7b3dSmrg OUT_RELOC_PIXMAP_FENCED(pixmap, I915_GEM_DOMAIN_RENDER, 259428d7b3dSmrg I915_GEM_DOMAIN_RENDER, 0); 260428d7b3dSmrg OUT_BATCH(intel->BR[16]); 261428d7b3dSmrg ADVANCE_BATCH(); 262428d7b3dSmrg } 263428d7b3dSmrg} 264428d7b3dSmrg 265428d7b3dSmrg/** 266428d7b3dSmrg * TODO: 267428d7b3dSmrg * - support planemask using FULL_BLT_CMD? 268428d7b3dSmrg */ 269428d7b3dSmrgstatic Bool 270428d7b3dSmrgintel_uxa_check_copy(PixmapPtr source, PixmapPtr dest, 271428d7b3dSmrg int alu, Pixel planemask) 272428d7b3dSmrg{ 273428d7b3dSmrg ScrnInfoPtr scrn = xf86ScreenToScrn(dest->drawable.pScreen); 274428d7b3dSmrg 275428d7b3dSmrg if (!UXA_PM_IS_SOLID(&source->drawable, planemask)) { 276428d7b3dSmrg intel_uxa_debug_fallback(scrn, "planemask is not solid"); 277428d7b3dSmrg return FALSE; 278428d7b3dSmrg } 279428d7b3dSmrg 280428d7b3dSmrg if (source->drawable.bitsPerPixel != dest->drawable.bitsPerPixel) { 281428d7b3dSmrg intel_uxa_debug_fallback(scrn, "mixed bpp copies unsupported\n"); 282428d7b3dSmrg return FALSE; 283428d7b3dSmrg } 284428d7b3dSmrg switch (source->drawable.bitsPerPixel) { 285428d7b3dSmrg case 8: 286428d7b3dSmrg case 16: 287428d7b3dSmrg case 32: 288428d7b3dSmrg break; 289428d7b3dSmrg default: 290428d7b3dSmrg return FALSE; 291428d7b3dSmrg } 292428d7b3dSmrg 293428d7b3dSmrg if (!intel_uxa_check_pitch_2d(source)) 294428d7b3dSmrg return FALSE; 295428d7b3dSmrg if (!intel_uxa_check_pitch_2d(dest)) 296428d7b3dSmrg return FALSE; 297428d7b3dSmrg 298428d7b3dSmrg return TRUE; 299428d7b3dSmrg} 300428d7b3dSmrg 301428d7b3dSmrgstatic Bool 302428d7b3dSmrgintel_uxa_prepare_copy(PixmapPtr source, PixmapPtr dest, int xdir, 303428d7b3dSmrg int ydir, int alu, Pixel planemask) 304428d7b3dSmrg{ 305428d7b3dSmrg ScrnInfoPtr scrn = xf86ScreenToScrn(dest->drawable.pScreen); 306428d7b3dSmrg intel_screen_private *intel = intel_get_screen_private(scrn); 307428d7b3dSmrg drm_intel_bo *bo_table[] = { 308428d7b3dSmrg NULL, /* batch_bo */ 309428d7b3dSmrg intel_uxa_get_pixmap_bo(source), 310428d7b3dSmrg intel_uxa_get_pixmap_bo(dest), 311428d7b3dSmrg }; 312428d7b3dSmrg 313428d7b3dSmrg if (!intel_uxa_get_aperture_space(scrn, bo_table, ARRAY_SIZE(bo_table))) 314428d7b3dSmrg return FALSE; 315428d7b3dSmrg 316428d7b3dSmrg intel->render_source = source; 317428d7b3dSmrg 318428d7b3dSmrg intel->BR[13] = I830CopyROP[alu] << 16; 319428d7b3dSmrg switch (source->drawable.bitsPerPixel) { 320428d7b3dSmrg case 8: 321428d7b3dSmrg break; 322428d7b3dSmrg case 16: 323428d7b3dSmrg intel->BR[13] |= (1 << 24); 324428d7b3dSmrg break; 325428d7b3dSmrg case 32: 326428d7b3dSmrg intel->BR[13] |= ((1 << 25) | (1 << 24)); 327428d7b3dSmrg break; 328428d7b3dSmrg } 329428d7b3dSmrg 330428d7b3dSmrg return TRUE; 331428d7b3dSmrg} 332428d7b3dSmrg 333428d7b3dSmrgstatic void 334428d7b3dSmrgintel_uxa_copy(PixmapPtr dest, int src_x1, int src_y1, int dst_x1, 335428d7b3dSmrg int dst_y1, int w, int h) 336428d7b3dSmrg{ 337428d7b3dSmrg ScrnInfoPtr scrn = xf86ScreenToScrn(dest->drawable.pScreen); 338428d7b3dSmrg intel_screen_private *intel = intel_get_screen_private(scrn); 339428d7b3dSmrg uint32_t cmd; 340428d7b3dSmrg int dst_x2, dst_y2, src_x2, src_y2; 341428d7b3dSmrg unsigned int dst_pitch, src_pitch; 342428d7b3dSmrg 343428d7b3dSmrg dst_x2 = dst_x1 + w; 344428d7b3dSmrg dst_y2 = dst_y1 + h; 345428d7b3dSmrg 346428d7b3dSmrg /* XXX Fixup extents as a lamentable workaround for missing 347428d7b3dSmrg * source clipping in the upper layers. 348428d7b3dSmrg */ 349428d7b3dSmrg if (dst_x1 < 0) 350428d7b3dSmrg src_x1 -= dst_x1, dst_x1 = 0; 351428d7b3dSmrg if (dst_y1 < 0) 352428d7b3dSmrg src_y1 -= dst_y1, dst_y1 = 0; 353428d7b3dSmrg if (dst_x2 > dest->drawable.width) 354428d7b3dSmrg dst_x2 = dest->drawable.width; 355428d7b3dSmrg if (dst_y2 > dest->drawable.height) 356428d7b3dSmrg dst_y2 = dest->drawable.height; 357428d7b3dSmrg 358428d7b3dSmrg src_x2 = src_x1 + (dst_x2 - dst_x1); 359428d7b3dSmrg src_y2 = src_y1 + (dst_y2 - dst_y1); 360428d7b3dSmrg 361428d7b3dSmrg if (src_x1 < 0) 362428d7b3dSmrg dst_x1 -= src_x1, src_x1 = 0; 363428d7b3dSmrg if (src_y1 < 0) 364428d7b3dSmrg dst_y1 -= src_y1, src_y1 = 0; 365428d7b3dSmrg if (src_x2 > intel->render_source->drawable.width) 366428d7b3dSmrg dst_x2 -= src_x2 - intel->render_source->drawable.width; 367428d7b3dSmrg if (src_y2 > intel->render_source->drawable.height) 368428d7b3dSmrg dst_y2 -= src_y2 - intel->render_source->drawable.height; 369428d7b3dSmrg 370428d7b3dSmrg if (dst_x2 <= dst_x1 || dst_y2 <= dst_y1) 371428d7b3dSmrg return; 372428d7b3dSmrg 373428d7b3dSmrg dst_pitch = intel_pixmap_pitch(dest); 374428d7b3dSmrg src_pitch = intel_pixmap_pitch(intel->render_source); 375428d7b3dSmrg 376428d7b3dSmrg { 377428d7b3dSmrg int len = INTEL_INFO(intel)->gen >= 0100 ? 10 : 8; 378428d7b3dSmrg BEGIN_BATCH_BLT(len); 379428d7b3dSmrg 380428d7b3dSmrg cmd = XY_SRC_COPY_BLT_CMD | (len - 2); 381428d7b3dSmrg 382428d7b3dSmrg if (dest->drawable.bitsPerPixel == 32) 383428d7b3dSmrg cmd |= 384428d7b3dSmrg XY_SRC_COPY_BLT_WRITE_ALPHA | 385428d7b3dSmrg XY_SRC_COPY_BLT_WRITE_RGB; 386428d7b3dSmrg 387428d7b3dSmrg if (INTEL_INFO(intel)->gen >= 040) { 388428d7b3dSmrg if (intel_uxa_pixmap_tiled(dest)) { 389428d7b3dSmrg assert((dst_pitch % 512) == 0); 390428d7b3dSmrg dst_pitch >>= 2; 391428d7b3dSmrg cmd |= XY_SRC_COPY_BLT_DST_TILED; 392428d7b3dSmrg } 393428d7b3dSmrg 394428d7b3dSmrg if (intel_uxa_pixmap_tiled(intel->render_source)) { 395428d7b3dSmrg assert((src_pitch % 512) == 0); 396428d7b3dSmrg src_pitch >>= 2; 397428d7b3dSmrg cmd |= XY_SRC_COPY_BLT_SRC_TILED; 398428d7b3dSmrg } 399428d7b3dSmrg } 400428d7b3dSmrg 401428d7b3dSmrg OUT_BATCH(cmd); 402428d7b3dSmrg 403428d7b3dSmrg OUT_BATCH(intel->BR[13] | dst_pitch); 404428d7b3dSmrg OUT_BATCH((dst_y1 << 16) | (dst_x1 & 0xffff)); 405428d7b3dSmrg OUT_BATCH((dst_y2 << 16) | (dst_x2 & 0xffff)); 406428d7b3dSmrg OUT_RELOC_PIXMAP_FENCED(dest, 407428d7b3dSmrg I915_GEM_DOMAIN_RENDER, 408428d7b3dSmrg I915_GEM_DOMAIN_RENDER, 409428d7b3dSmrg 0); 410428d7b3dSmrg OUT_BATCH((src_y1 << 16) | (src_x1 & 0xffff)); 411428d7b3dSmrg OUT_BATCH(src_pitch); 412428d7b3dSmrg OUT_RELOC_PIXMAP_FENCED(intel->render_source, 413428d7b3dSmrg I915_GEM_DOMAIN_RENDER, 0, 414428d7b3dSmrg 0); 415428d7b3dSmrg 416428d7b3dSmrg ADVANCE_BATCH(); 417428d7b3dSmrg } 418428d7b3dSmrg} 419428d7b3dSmrg 420428d7b3dSmrgstatic void intel_uxa_done(PixmapPtr pixmap) 421428d7b3dSmrg{ 422428d7b3dSmrg ScrnInfoPtr scrn = xf86ScreenToScrn(pixmap->drawable.pScreen); 423428d7b3dSmrg intel_screen_private *intel = intel_get_screen_private(scrn); 424428d7b3dSmrg 425428d7b3dSmrg if (INTEL_INFO(intel)->gen >= 060) { 426428d7b3dSmrg /* workaround a random BLT hang */ 427428d7b3dSmrg BEGIN_BATCH_BLT(3); 428428d7b3dSmrg OUT_BATCH(XY_SETUP_CLIP_BLT_CMD | (3 - 2)); 429428d7b3dSmrg OUT_BATCH(0); 430428d7b3dSmrg OUT_BATCH(0); 431428d7b3dSmrg ADVANCE_BATCH(); 432428d7b3dSmrg } 433428d7b3dSmrg 434428d7b3dSmrg intel_uxa_debug_flush(scrn); 435428d7b3dSmrg} 436428d7b3dSmrg 437428d7b3dSmrg/** 438428d7b3dSmrg * Do any cleanup from the Composite operation. 439428d7b3dSmrg * 440428d7b3dSmrg * This is shared between i830 through i965. 441428d7b3dSmrg */ 442428d7b3dSmrgstatic void i830_done_composite(PixmapPtr dest) 443428d7b3dSmrg{ 444428d7b3dSmrg ScrnInfoPtr scrn = xf86ScreenToScrn(dest->drawable.pScreen); 445428d7b3dSmrg intel_screen_private *intel = intel_get_screen_private(scrn); 446428d7b3dSmrg 447428d7b3dSmrg if (intel->vertex_flush) 448428d7b3dSmrg intel->vertex_flush(intel); 449428d7b3dSmrg 450428d7b3dSmrg intel_uxa_debug_flush(scrn); 451428d7b3dSmrg} 452428d7b3dSmrg 453428d7b3dSmrg#define xFixedToFloat(val) \ 454428d7b3dSmrg ((float)xFixedToInt(val) + ((float)xFixedFrac(val) / 65536.0)) 455428d7b3dSmrg 456428d7b3dSmrgstatic Bool 457428d7b3dSmrg_intel_transform_point(PictTransformPtr transform, 458428d7b3dSmrg float x, float y, float result[3]) 459428d7b3dSmrg{ 460428d7b3dSmrg int j; 461428d7b3dSmrg 462428d7b3dSmrg for (j = 0; j < 3; j++) { 463428d7b3dSmrg result[j] = (xFixedToFloat(transform->matrix[j][0]) * x + 464428d7b3dSmrg xFixedToFloat(transform->matrix[j][1]) * y + 465428d7b3dSmrg xFixedToFloat(transform->matrix[j][2])); 466428d7b3dSmrg } 467428d7b3dSmrg if (!result[2]) 468428d7b3dSmrg return FALSE; 469428d7b3dSmrg return TRUE; 470428d7b3dSmrg} 471428d7b3dSmrg 472428d7b3dSmrg/** 473428d7b3dSmrg * Returns the floating-point coordinates transformed by the given transform. 474428d7b3dSmrg * 475428d7b3dSmrg * transform may be null. 476428d7b3dSmrg */ 477428d7b3dSmrgBool 478428d7b3dSmrgintel_uxa_get_transformed_coordinates(int x, int y, PictTransformPtr transform, 479428d7b3dSmrg float *x_out, float *y_out) 480428d7b3dSmrg{ 481428d7b3dSmrg if (transform == NULL) { 482428d7b3dSmrg *x_out = x; 483428d7b3dSmrg *y_out = y; 484428d7b3dSmrg } else { 485428d7b3dSmrg float result[3]; 486428d7b3dSmrg 487428d7b3dSmrg if (!_intel_transform_point(transform, 488428d7b3dSmrg x, y, 489428d7b3dSmrg result)) 490428d7b3dSmrg return FALSE; 491428d7b3dSmrg *x_out = result[0] / result[2]; 492428d7b3dSmrg *y_out = result[1] / result[2]; 493428d7b3dSmrg } 494428d7b3dSmrg return TRUE; 495428d7b3dSmrg} 496428d7b3dSmrg 497428d7b3dSmrg/** 498428d7b3dSmrg * Returns the un-normalized floating-point coordinates transformed by the given transform. 499428d7b3dSmrg * 500428d7b3dSmrg * transform may be null. 501428d7b3dSmrg */ 502428d7b3dSmrgBool 503428d7b3dSmrgintel_uxa_get_transformed_coordinates_3d(int x, int y, PictTransformPtr transform, 504428d7b3dSmrg float *x_out, float *y_out, float *w_out) 505428d7b3dSmrg{ 506428d7b3dSmrg if (transform == NULL) { 507428d7b3dSmrg *x_out = x; 508428d7b3dSmrg *y_out = y; 509428d7b3dSmrg *w_out = 1; 510428d7b3dSmrg } else { 511428d7b3dSmrg float result[3]; 512428d7b3dSmrg 513428d7b3dSmrg if (!_intel_transform_point(transform, 514428d7b3dSmrg x, y, 515428d7b3dSmrg result)) 516428d7b3dSmrg return FALSE; 517428d7b3dSmrg *x_out = result[0]; 518428d7b3dSmrg *y_out = result[1]; 519428d7b3dSmrg *w_out = result[2]; 520428d7b3dSmrg } 521428d7b3dSmrg return TRUE; 522428d7b3dSmrg} 523428d7b3dSmrg 524428d7b3dSmrg/** 525428d7b3dSmrg * Returns whether the provided transform is affine. 526428d7b3dSmrg * 527428d7b3dSmrg * transform may be null. 528428d7b3dSmrg */ 529428d7b3dSmrgBool intel_uxa_transform_is_affine(PictTransformPtr t) 530428d7b3dSmrg{ 531428d7b3dSmrg if (t == NULL) 532428d7b3dSmrg return TRUE; 533428d7b3dSmrg return t->matrix[2][0] == 0 && t->matrix[2][1] == 0; 534428d7b3dSmrg} 535428d7b3dSmrg 536428d7b3dSmrgdri_bo *intel_uxa_get_pixmap_bo(PixmapPtr pixmap) 537428d7b3dSmrg{ 538428d7b3dSmrg struct intel_uxa_pixmap *intel; 539428d7b3dSmrg 540428d7b3dSmrg intel = intel_uxa_get_pixmap_private(pixmap); 541428d7b3dSmrg if (intel == NULL) 542428d7b3dSmrg return NULL; 543428d7b3dSmrg 544428d7b3dSmrg return intel->bo; 545428d7b3dSmrg} 546428d7b3dSmrg 547428d7b3dSmrgstatic unsigned intel_get_tile_width(intel_screen_private *intel, int tiling, int pitch) 548428d7b3dSmrg{ 549428d7b3dSmrg unsigned long tile_width; 550428d7b3dSmrg 551428d7b3dSmrg if (tiling == I915_TILING_NONE) 552428d7b3dSmrg return 4; 553428d7b3dSmrg 554428d7b3dSmrg tile_width = (tiling == I915_TILING_Y) ? 128 : 512; 555428d7b3dSmrg if (INTEL_INFO(intel)->gen >= 040) 556428d7b3dSmrg return tile_width; 557428d7b3dSmrg 558428d7b3dSmrg while (tile_width < pitch) 559428d7b3dSmrg tile_width <<= 1; 560428d7b3dSmrg 561428d7b3dSmrg return tile_width; 562428d7b3dSmrg} 563428d7b3dSmrg 564428d7b3dSmrgvoid intel_uxa_set_pixmap_bo(PixmapPtr pixmap, dri_bo * bo) 565428d7b3dSmrg{ 566428d7b3dSmrg ScrnInfoPtr scrn = xf86ScreenToScrn(pixmap->drawable.pScreen); 567428d7b3dSmrg intel_screen_private *intel = intel_get_screen_private(scrn); 568428d7b3dSmrg struct intel_uxa_pixmap *priv; 569428d7b3dSmrg 570428d7b3dSmrg priv = intel_uxa_get_pixmap_private(pixmap); 571428d7b3dSmrg if (priv == NULL && bo == NULL) 572428d7b3dSmrg return; 573428d7b3dSmrg 574428d7b3dSmrg if (priv != NULL) { 575428d7b3dSmrg if (priv->bo == bo) 576428d7b3dSmrg return; 577428d7b3dSmrg 578428d7b3dSmrgfree_priv: 579428d7b3dSmrg dri_bo_unreference(priv->bo); 580428d7b3dSmrg list_del(&priv->batch); 581428d7b3dSmrg 582428d7b3dSmrg free(priv); 583428d7b3dSmrg priv = NULL; 584428d7b3dSmrg } 585428d7b3dSmrg 586428d7b3dSmrg if (bo != NULL) { 587428d7b3dSmrg uint32_t tiling, swizzle_mode; 588428d7b3dSmrg unsigned tile_width; 589428d7b3dSmrg int size, stride; 590428d7b3dSmrg 591428d7b3dSmrg priv = calloc(1, sizeof (struct intel_uxa_pixmap)); 592428d7b3dSmrg if (priv == NULL) 593428d7b3dSmrg goto BAIL; 594428d7b3dSmrg 595428d7b3dSmrg list_init(&priv->batch); 596428d7b3dSmrg 597428d7b3dSmrg dri_bo_reference(bo); 598428d7b3dSmrg priv->bo = bo; 599428d7b3dSmrg 600428d7b3dSmrg if (drm_intel_bo_get_tiling(bo, &tiling, &swizzle_mode)) { 601428d7b3dSmrg bo = NULL; 602428d7b3dSmrg goto free_priv; 603428d7b3dSmrg } 604428d7b3dSmrg 605428d7b3dSmrg priv->tiling = tiling; 606428d7b3dSmrg priv->busy = -1; 607428d7b3dSmrg priv->offscreen = 1; 608428d7b3dSmrg 609428d7b3dSmrg stride = (pixmap->drawable.width * pixmap->drawable.bitsPerPixel + 7) / 8; 610428d7b3dSmrg tile_width = intel_get_tile_width(intel, tiling, stride); 611428d7b3dSmrg stride = ALIGN(stride, tile_width); 612428d7b3dSmrg 613428d7b3dSmrg if (intel_pixmap_pitch(pixmap) < stride || 614428d7b3dSmrg intel_pixmap_pitch(pixmap) & (tile_width - 1) || 615428d7b3dSmrg intel_pixmap_pitch(pixmap) >= KB(32)) { 616428d7b3dSmrg xf86DrvMsg(scrn->scrnIndex, X_ERROR, 617428d7b3dSmrg "%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", 618428d7b3dSmrg __FUNCTION__, intel_pixmap_pitch(pixmap), stride, KB(32), tile_width); 619428d7b3dSmrg bo = NULL; 620428d7b3dSmrg goto free_priv; 621428d7b3dSmrg } 622428d7b3dSmrg 623428d7b3dSmrg if (tiling != I915_TILING_NONE) { 624428d7b3dSmrg int height; 625428d7b3dSmrg 626428d7b3dSmrg if (IS_GEN2(intel)) 627428d7b3dSmrg height = 16; 628428d7b3dSmrg else if (tiling == I915_TILING_X) 629428d7b3dSmrg height = 8; 630428d7b3dSmrg else 631428d7b3dSmrg height = 32; 632428d7b3dSmrg 633428d7b3dSmrg height = ALIGN(pixmap->drawable.height, height); 634428d7b3dSmrg size = intel_get_fence_size(intel, intel_pixmap_pitch(pixmap) * height); 635428d7b3dSmrg } else 636428d7b3dSmrg size = intel_pixmap_pitch(pixmap) * pixmap->drawable.height; 637428d7b3dSmrg 638428d7b3dSmrg if (bo->size < size || bo->size > intel->max_bo_size) { 639428d7b3dSmrg xf86DrvMsg(scrn->scrnIndex, X_ERROR, 640428d7b3dSmrg "%s: size of buffer object does not match constraints: size=%ld, must be greater than %d, but less than %d\n", 641428d7b3dSmrg __FUNCTION__, (long)bo->size, size, intel->max_bo_size); 642428d7b3dSmrg bo = NULL; 643428d7b3dSmrg goto free_priv; 644428d7b3dSmrg } 645428d7b3dSmrg } 646428d7b3dSmrg 647428d7b3dSmrg BAIL: 648428d7b3dSmrg intel_uxa_set_pixmap_private(pixmap, priv); 649428d7b3dSmrg} 650428d7b3dSmrg 651428d7b3dSmrgstatic Bool intel_uxa_prepare_access(PixmapPtr pixmap, uxa_access_t access) 652428d7b3dSmrg{ 653428d7b3dSmrg ScrnInfoPtr scrn = xf86ScreenToScrn(pixmap->drawable.pScreen); 654428d7b3dSmrg intel_screen_private *intel = intel_get_screen_private(scrn); 655428d7b3dSmrg struct intel_uxa_pixmap *priv = intel_uxa_get_pixmap_private(pixmap); 656428d7b3dSmrg dri_bo *bo = priv->bo; 657428d7b3dSmrg int ret; 658428d7b3dSmrg 659428d7b3dSmrg /* When falling back to swrast, flush all pending operations */ 660428d7b3dSmrg if (access == UXA_ACCESS_RW || priv->dirty) 661428d7b3dSmrg intel_batch_submit(scrn); 662428d7b3dSmrg 663428d7b3dSmrg assert(bo->size <= intel->max_gtt_map_size); 664428d7b3dSmrg ret = drm_intel_gem_bo_map_gtt(bo); 665428d7b3dSmrg if (ret) { 666428d7b3dSmrg xf86DrvMsg(scrn->scrnIndex, X_WARNING, 667428d7b3dSmrg "%s: bo map (use gtt? %d, access %d) failed: %s\n", 668428d7b3dSmrg __FUNCTION__, 669428d7b3dSmrg priv->tiling || bo->size <= intel->max_gtt_map_size, 670428d7b3dSmrg access, 671428d7b3dSmrg strerror(-ret)); 672428d7b3dSmrg return FALSE; 673428d7b3dSmrg } 674428d7b3dSmrg 675428d7b3dSmrg pixmap->devPrivate.ptr = bo->virtual; 676428d7b3dSmrg priv->busy = 0; 677428d7b3dSmrg 678428d7b3dSmrg return TRUE; 679428d7b3dSmrg} 680428d7b3dSmrg 681428d7b3dSmrgstatic void intel_uxa_finish_access(PixmapPtr pixmap, uxa_access_t access) 682428d7b3dSmrg{ 683428d7b3dSmrg struct intel_uxa_pixmap *priv; 684428d7b3dSmrg 685428d7b3dSmrg priv = intel_uxa_get_pixmap_private(pixmap); 686428d7b3dSmrg if (priv == NULL) 687428d7b3dSmrg return; 688428d7b3dSmrg 689428d7b3dSmrg drm_intel_gem_bo_unmap_gtt(priv->bo); 690428d7b3dSmrg pixmap->devPrivate.ptr = NULL; 691428d7b3dSmrg} 692428d7b3dSmrg 693428d7b3dSmrgstatic Bool intel_uxa_pixmap_put_image(PixmapPtr pixmap, 694428d7b3dSmrg char *src, int src_pitch, 695428d7b3dSmrg int x, int y, int w, int h) 696428d7b3dSmrg{ 697428d7b3dSmrg struct intel_uxa_pixmap *priv = intel_uxa_get_pixmap_private(pixmap); 698428d7b3dSmrg int stride = intel_pixmap_pitch(pixmap); 699428d7b3dSmrg int cpp = pixmap->drawable.bitsPerPixel/8; 700428d7b3dSmrg int ret = FALSE; 701428d7b3dSmrg 702428d7b3dSmrg if (priv == NULL || priv->bo == NULL) 703428d7b3dSmrg return FALSE; 704428d7b3dSmrg 705428d7b3dSmrg if (priv->tiling == I915_TILING_NONE && 706428d7b3dSmrg (h == 1 || (src_pitch == stride && w == pixmap->drawable.width))) { 707428d7b3dSmrg return drm_intel_bo_subdata(priv->bo, y*stride + x*cpp, stride*(h-1) + w*cpp, src) == 0; 708428d7b3dSmrg } else if (drm_intel_gem_bo_map_gtt(priv->bo) == 0) { 709428d7b3dSmrg char *dst = priv->bo->virtual; 710428d7b3dSmrg int row_length = w * cpp; 711428d7b3dSmrg int num_rows = h; 712428d7b3dSmrg if (row_length == src_pitch && src_pitch == stride) 713428d7b3dSmrg num_rows = 1, row_length *= h; 714428d7b3dSmrg dst += y * stride + x * cpp; 715428d7b3dSmrg do { 716428d7b3dSmrg memcpy (dst, src, row_length); 717428d7b3dSmrg src += src_pitch; 718428d7b3dSmrg dst += stride; 719428d7b3dSmrg } while (--num_rows); 720428d7b3dSmrg drm_intel_gem_bo_unmap_gtt(priv->bo); 721428d7b3dSmrg ret = TRUE; 722428d7b3dSmrg } 723428d7b3dSmrg 724428d7b3dSmrg return ret; 725428d7b3dSmrg} 726428d7b3dSmrg 727428d7b3dSmrgstatic Bool intel_uxa_put_image(PixmapPtr pixmap, 728428d7b3dSmrg int x, int y, 729428d7b3dSmrg int w, int h, 730428d7b3dSmrg char *src, int src_pitch) 731428d7b3dSmrg{ 732428d7b3dSmrg struct intel_uxa_pixmap *priv; 733428d7b3dSmrg 734428d7b3dSmrg priv = intel_uxa_get_pixmap_private(pixmap); 735428d7b3dSmrg if (!intel_uxa_pixmap_is_busy(priv)) { 736428d7b3dSmrg /* bo is not busy so can be replaced without a stall, upload in-place. */ 737428d7b3dSmrg return intel_uxa_pixmap_put_image(pixmap, src, src_pitch, x, y, w, h); 738428d7b3dSmrg } else { 739428d7b3dSmrg ScreenPtr screen = pixmap->drawable.pScreen; 740428d7b3dSmrg 741428d7b3dSmrg if (!priv->pinned && 742428d7b3dSmrg x == 0 && y == 0 && 743428d7b3dSmrg w == pixmap->drawable.width && 744428d7b3dSmrg h == pixmap->drawable.height) 745428d7b3dSmrg { 746428d7b3dSmrg intel_screen_private *intel = intel_get_screen_private(xf86ScreenToScrn(screen)); 747428d7b3dSmrg uint32_t tiling = priv->tiling; 748428d7b3dSmrg int size, stride; 749428d7b3dSmrg dri_bo *bo; 750428d7b3dSmrg 751428d7b3dSmrg /* Replace busy bo. */ 752428d7b3dSmrg size = intel_compute_size(intel, 753428d7b3dSmrg w, h, 754428d7b3dSmrg pixmap->drawable.bitsPerPixel, pixmap->usage_hint, 755428d7b3dSmrg &tiling, &stride); 756428d7b3dSmrg if (size > intel->max_gtt_map_size) 757428d7b3dSmrg return FALSE; 758428d7b3dSmrg 759428d7b3dSmrg bo = drm_intel_bo_alloc(intel->bufmgr, "pixmap", size, 0); 760428d7b3dSmrg if (bo == NULL) 761428d7b3dSmrg return FALSE; 762428d7b3dSmrg 763428d7b3dSmrg if (tiling != I915_TILING_NONE) 764428d7b3dSmrg drm_intel_bo_set_tiling(bo, &tiling, stride); 765428d7b3dSmrg priv->tiling = tiling; 766428d7b3dSmrg 767428d7b3dSmrg screen->ModifyPixmapHeader(pixmap, 768428d7b3dSmrg w, h, 769428d7b3dSmrg 0, 0, 770428d7b3dSmrg stride, NULL); 771428d7b3dSmrg intel_uxa_set_pixmap_bo(pixmap, bo); 772428d7b3dSmrg dri_bo_unreference(bo); 773428d7b3dSmrg 774428d7b3dSmrg return intel_uxa_pixmap_put_image(pixmap, src, src_pitch, 0, 0, w, h); 775428d7b3dSmrg } 776428d7b3dSmrg else 777428d7b3dSmrg { 778428d7b3dSmrg PixmapPtr scratch; 779428d7b3dSmrg Bool ret; 780428d7b3dSmrg 781428d7b3dSmrg /* Upload to a linear buffer and queue a blit. */ 782428d7b3dSmrg scratch = (*screen->CreatePixmap)(screen, w, h, 783428d7b3dSmrg pixmap->drawable.depth, 784428d7b3dSmrg UXA_CREATE_PIXMAP_FOR_MAP); 785428d7b3dSmrg if (!scratch) 786428d7b3dSmrg return FALSE; 787428d7b3dSmrg 788428d7b3dSmrg if (!intel_uxa_pixmap_is_offscreen(scratch)) { 789428d7b3dSmrg screen->DestroyPixmap(scratch); 790428d7b3dSmrg return FALSE; 791428d7b3dSmrg } 792428d7b3dSmrg 793428d7b3dSmrg ret = intel_uxa_pixmap_put_image(scratch, src, src_pitch, 0, 0, w, h); 794428d7b3dSmrg if (ret) { 795428d7b3dSmrg GCPtr gc = GetScratchGC(pixmap->drawable.depth, screen); 796428d7b3dSmrg if (gc) { 797428d7b3dSmrg ValidateGC(&pixmap->drawable, gc); 798428d7b3dSmrg 799428d7b3dSmrg (*gc->ops->CopyArea)(&scratch->drawable, 800428d7b3dSmrg &pixmap->drawable, 801428d7b3dSmrg gc, 0, 0, w, h, x, y); 802428d7b3dSmrg 803428d7b3dSmrg FreeScratchGC(gc); 804428d7b3dSmrg } else 805428d7b3dSmrg ret = FALSE; 806428d7b3dSmrg } 807428d7b3dSmrg 808428d7b3dSmrg (*screen->DestroyPixmap)(scratch); 809428d7b3dSmrg return ret; 810428d7b3dSmrg } 811428d7b3dSmrg } 812428d7b3dSmrg} 813428d7b3dSmrg 814428d7b3dSmrgstatic Bool intel_uxa_pixmap_get_image(PixmapPtr pixmap, 815428d7b3dSmrg int x, int y, int w, int h, 816428d7b3dSmrg char *dst, int dst_pitch) 817428d7b3dSmrg{ 818428d7b3dSmrg struct intel_uxa_pixmap *priv = intel_uxa_get_pixmap_private(pixmap); 819428d7b3dSmrg int stride = intel_pixmap_pitch(pixmap); 820428d7b3dSmrg int cpp = pixmap->drawable.bitsPerPixel/8; 821428d7b3dSmrg 822428d7b3dSmrg /* assert(priv->tiling == I915_TILING_NONE); */ 823428d7b3dSmrg if (h == 1 || (dst_pitch == stride && w == pixmap->drawable.width)) { 824428d7b3dSmrg return drm_intel_bo_get_subdata(priv->bo, y*stride + x*cpp, (h-1)*stride + w*cpp, dst) == 0; 825428d7b3dSmrg } else { 826428d7b3dSmrg char *src; 827428d7b3dSmrg 828428d7b3dSmrg if (drm_intel_gem_bo_map_gtt(priv->bo)) 829428d7b3dSmrg return FALSE; 830428d7b3dSmrg 831428d7b3dSmrg src = (char *) priv->bo->virtual + y * stride + x * cpp; 832428d7b3dSmrg w *= cpp; 833428d7b3dSmrg do { 834428d7b3dSmrg memcpy(dst, src, w); 835428d7b3dSmrg src += stride; 836428d7b3dSmrg dst += dst_pitch; 837428d7b3dSmrg } while (--h); 838428d7b3dSmrg 839428d7b3dSmrg drm_intel_gem_bo_unmap_gtt(priv->bo); 840428d7b3dSmrg 841428d7b3dSmrg return TRUE; 842428d7b3dSmrg } 843428d7b3dSmrg} 844428d7b3dSmrg 845428d7b3dSmrgstatic Bool intel_uxa_get_image(PixmapPtr pixmap, 846428d7b3dSmrg int x, int y, 847428d7b3dSmrg int w, int h, 848428d7b3dSmrg char *dst, int dst_pitch) 849428d7b3dSmrg{ 850428d7b3dSmrg struct intel_uxa_pixmap *priv; 851428d7b3dSmrg PixmapPtr scratch = NULL; 852428d7b3dSmrg Bool ret; 853428d7b3dSmrg 854428d7b3dSmrg /* The presumption is that we wish to keep the target hot, so 855428d7b3dSmrg * copy to a new bo and move that to the CPU in preference to 856428d7b3dSmrg * causing ping-pong of the original. 857428d7b3dSmrg * 858428d7b3dSmrg * Also the gpu is much faster at detiling. 859428d7b3dSmrg */ 860428d7b3dSmrg 861428d7b3dSmrg priv = intel_uxa_get_pixmap_private(pixmap); 862428d7b3dSmrg if (intel_uxa_pixmap_is_busy(priv) || priv->tiling != I915_TILING_NONE) { 863428d7b3dSmrg ScreenPtr screen = pixmap->drawable.pScreen; 864428d7b3dSmrg GCPtr gc; 865428d7b3dSmrg 866428d7b3dSmrg /* Copy to a linear buffer and pull. */ 867428d7b3dSmrg scratch = screen->CreatePixmap(screen, w, h, 868428d7b3dSmrg pixmap->drawable.depth, 869428d7b3dSmrg INTEL_CREATE_PIXMAP_TILING_NONE); 870428d7b3dSmrg if (!scratch) 871428d7b3dSmrg return FALSE; 872428d7b3dSmrg 873428d7b3dSmrg if (!intel_uxa_pixmap_is_offscreen(scratch)) { 874428d7b3dSmrg screen->DestroyPixmap(scratch); 875428d7b3dSmrg return FALSE; 876428d7b3dSmrg } 877428d7b3dSmrg 878428d7b3dSmrg gc = GetScratchGC(pixmap->drawable.depth, screen); 879428d7b3dSmrg if (!gc) { 880428d7b3dSmrg screen->DestroyPixmap(scratch); 881428d7b3dSmrg return FALSE; 882428d7b3dSmrg } 883428d7b3dSmrg 884428d7b3dSmrg ValidateGC(&pixmap->drawable, gc); 885428d7b3dSmrg 886428d7b3dSmrg gc->ops->CopyArea(&pixmap->drawable, 887428d7b3dSmrg &scratch->drawable, 888428d7b3dSmrg gc, x, y, w, h, 0, 0); 889428d7b3dSmrg 890428d7b3dSmrg FreeScratchGC(gc); 891428d7b3dSmrg 892428d7b3dSmrg intel_batch_submit(xf86ScreenToScrn(screen)); 893428d7b3dSmrg 894428d7b3dSmrg x = y = 0; 895428d7b3dSmrg pixmap = scratch; 896428d7b3dSmrg } 897428d7b3dSmrg 898428d7b3dSmrg ret = intel_uxa_pixmap_get_image(pixmap, x, y, w, h, dst, dst_pitch); 899428d7b3dSmrg 900428d7b3dSmrg if (scratch) 901428d7b3dSmrg scratch->drawable.pScreen->DestroyPixmap(scratch); 902428d7b3dSmrg 903428d7b3dSmrg return ret; 904428d7b3dSmrg} 905428d7b3dSmrg 906428d7b3dSmrgstatic CARD32 intel_cache_expire(OsTimerPtr timer, CARD32 now, pointer data) 907428d7b3dSmrg{ 908428d7b3dSmrg intel_screen_private *intel = data; 909428d7b3dSmrg 910428d7b3dSmrg /* We just want to create and destroy a bo as this causes libdrm 911428d7b3dSmrg * to reap its caches. However, since we can't remove that buffer 912428d7b3dSmrg * from the cache due to its own activity, we want to use something 913428d7b3dSmrg * that we know we will reuse later. The most frequently reused buffer 914428d7b3dSmrg * we have is the batchbuffer, and the best way to trigger its 915428d7b3dSmrg * reallocation is to submit a flush. 916428d7b3dSmrg */ 917428d7b3dSmrg intel_batch_emit_flush(intel->scrn); 918428d7b3dSmrg intel_batch_submit(intel->scrn); 919428d7b3dSmrg 920428d7b3dSmrg return 0; 921428d7b3dSmrg} 922428d7b3dSmrg 923428d7b3dSmrgstatic void intel_flush_rendering(intel_screen_private *intel) 924428d7b3dSmrg{ 925428d7b3dSmrg if (intel->needs_flush == 0) 926428d7b3dSmrg return; 927428d7b3dSmrg 928428d7b3dSmrg if (intel->has_kernel_flush) { 929428d7b3dSmrg intel_batch_submit(intel->scrn); 930428d7b3dSmrg drm_intel_bo_busy(intel->front_buffer); 931428d7b3dSmrg } else { 932428d7b3dSmrg intel_batch_emit_flush(intel->scrn); 933428d7b3dSmrg intel_batch_submit(intel->scrn); 934428d7b3dSmrg } 935428d7b3dSmrg 936428d7b3dSmrg intel->cache_expire = TimerSet(intel->cache_expire, 0, 3000, 937428d7b3dSmrg intel_cache_expire, intel); 938428d7b3dSmrg 939428d7b3dSmrg intel->needs_flush = 0; 940428d7b3dSmrg} 941428d7b3dSmrg 942428d7b3dSmrgstatic void intel_throttle(intel_screen_private *intel) 943428d7b3dSmrg{ 944428d7b3dSmrg drmCommandNone(intel->drmSubFD, DRM_I915_GEM_THROTTLE); 945428d7b3dSmrg} 946428d7b3dSmrg 947428d7b3dSmrgvoid intel_uxa_block_handler(intel_screen_private *intel) 948428d7b3dSmrg{ 949428d7b3dSmrg /* Emit a flush of the rendering cache, or on the 965 950428d7b3dSmrg * and beyond rendering results may not hit the 951428d7b3dSmrg * framebuffer until significantly later. 952428d7b3dSmrg */ 953428d7b3dSmrg intel_flush_rendering(intel); 954428d7b3dSmrg intel_throttle(intel); 955428d7b3dSmrg} 956428d7b3dSmrg 957428d7b3dSmrgstatic PixmapPtr 958428d7b3dSmrgintel_uxa_create_pixmap(ScreenPtr screen, int w, int h, int depth, 959428d7b3dSmrg unsigned usage) 960428d7b3dSmrg{ 961428d7b3dSmrg ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 962428d7b3dSmrg intel_screen_private *intel = intel_get_screen_private(scrn); 963428d7b3dSmrg struct intel_uxa_pixmap *priv; 964428d7b3dSmrg PixmapPtr pixmap, new_pixmap = NULL; 965428d7b3dSmrg 966428d7b3dSmrg if (w > 32767 || h > 32767) 967428d7b3dSmrg return NullPixmap; 968428d7b3dSmrg 969428d7b3dSmrg if (depth == 1 || intel->force_fallback) 970428d7b3dSmrg return fbCreatePixmap(screen, w, h, depth, usage); 971428d7b3dSmrg 972428d7b3dSmrg if (usage == CREATE_PIXMAP_USAGE_GLYPH_PICTURE && w <= 32 && h <= 32) 973428d7b3dSmrg return fbCreatePixmap(screen, w, h, depth, usage); 974428d7b3dSmrg 975428d7b3dSmrg pixmap = fbCreatePixmap(screen, 0, 0, depth, usage); 976428d7b3dSmrg if (pixmap == NullPixmap) 977428d7b3dSmrg return pixmap; 978428d7b3dSmrg 979428d7b3dSmrg if (w && h) { 980428d7b3dSmrg unsigned int size, tiling; 981428d7b3dSmrg int stride; 982428d7b3dSmrg 983428d7b3dSmrg /* Always attempt to tile, compute_size() will remove the 984428d7b3dSmrg * tiling for pixmaps that are either too large or too small 985428d7b3dSmrg * to be effectively tiled. 986428d7b3dSmrg */ 987428d7b3dSmrg tiling = I915_TILING_X; 988428d7b3dSmrg if (usage & INTEL_CREATE_PIXMAP_TILING_Y) 989428d7b3dSmrg tiling = I915_TILING_Y; 990428d7b3dSmrg if (usage == UXA_CREATE_PIXMAP_FOR_MAP || usage & INTEL_CREATE_PIXMAP_TILING_NONE) 991428d7b3dSmrg tiling = I915_TILING_NONE; 992428d7b3dSmrg 993428d7b3dSmrg#ifdef CREATE_PIXMAP_USAGE_SHARED 994428d7b3dSmrg if (usage == CREATE_PIXMAP_USAGE_SHARED) 995428d7b3dSmrg tiling = I915_TILING_NONE; 996428d7b3dSmrg#endif 997428d7b3dSmrg /* if tiling is off force to none */ 998428d7b3dSmrg if (!intel->tiling) 999428d7b3dSmrg tiling = I915_TILING_NONE; 1000428d7b3dSmrg 1001428d7b3dSmrg if (tiling != I915_TILING_NONE && !(usage & INTEL_CREATE_PIXMAP_DRI2)) { 1002428d7b3dSmrg if (h <= 4) 1003428d7b3dSmrg tiling = I915_TILING_NONE; 1004428d7b3dSmrg if (h <= 16 && tiling == I915_TILING_Y) 1005428d7b3dSmrg tiling = I915_TILING_X; 1006428d7b3dSmrg } 1007428d7b3dSmrg size = intel_compute_size(intel, 1008428d7b3dSmrg w, h, pixmap->drawable.bitsPerPixel, usage, 1009428d7b3dSmrg &tiling, &stride); 1010428d7b3dSmrg 1011428d7b3dSmrg /* Fail very large allocations. Large BOs will tend to hit SW fallbacks 1012428d7b3dSmrg * frequently, and also will tend to fail to successfully map when doing 1013428d7b3dSmrg * SW fallbacks because we overcommit address space for BO access. 1014428d7b3dSmrg */ 1015428d7b3dSmrg if (size > intel->max_bo_size || stride >= KB(32)) 1016428d7b3dSmrg goto fallback_pixmap; 1017428d7b3dSmrg 1018428d7b3dSmrg priv = calloc(1, sizeof (struct intel_uxa_pixmap)); 1019428d7b3dSmrg if (priv == NULL) 1020428d7b3dSmrg goto fallback_pixmap; 1021428d7b3dSmrg 1022428d7b3dSmrg if (usage == UXA_CREATE_PIXMAP_FOR_MAP) { 1023428d7b3dSmrg priv->busy = 0; 1024428d7b3dSmrg priv->bo = drm_intel_bo_alloc(intel->bufmgr, 1025428d7b3dSmrg "pixmap", size, 0); 1026428d7b3dSmrg } else { 1027428d7b3dSmrg priv->busy = -1; 1028428d7b3dSmrg priv->bo = drm_intel_bo_alloc_for_render(intel->bufmgr, 1029428d7b3dSmrg "pixmap", 1030428d7b3dSmrg size, 0); 1031428d7b3dSmrg } 1032428d7b3dSmrg if (!priv->bo) 1033428d7b3dSmrg goto fallback_priv; 1034428d7b3dSmrg 1035428d7b3dSmrg if (tiling != I915_TILING_NONE) 1036428d7b3dSmrg drm_intel_bo_set_tiling(priv->bo, &tiling, stride); 1037428d7b3dSmrg priv->tiling = tiling; 1038428d7b3dSmrg priv->offscreen = 1; 1039428d7b3dSmrg 1040428d7b3dSmrg list_init(&priv->batch); 1041428d7b3dSmrg intel_uxa_set_pixmap_private(pixmap, priv); 1042428d7b3dSmrg 1043428d7b3dSmrg screen->ModifyPixmapHeader(pixmap, w, h, 0, 0, stride, NULL); 1044428d7b3dSmrg } 1045428d7b3dSmrg 1046428d7b3dSmrg return pixmap; 1047428d7b3dSmrg 1048428d7b3dSmrgfallback_priv: 1049428d7b3dSmrg free(priv); 1050428d7b3dSmrgfallback_pixmap: 1051428d7b3dSmrg fbDestroyPixmap(pixmap); 1052428d7b3dSmrg if (new_pixmap) 1053428d7b3dSmrg return new_pixmap; 1054428d7b3dSmrg else 1055428d7b3dSmrg return fbCreatePixmap(screen, w, h, depth, usage); 1056428d7b3dSmrg} 1057428d7b3dSmrg 1058428d7b3dSmrgstatic Bool intel_uxa_destroy_pixmap(PixmapPtr pixmap) 1059428d7b3dSmrg{ 1060428d7b3dSmrg if (pixmap->refcnt == 1) 1061428d7b3dSmrg intel_uxa_set_pixmap_bo(pixmap, NULL); 1062428d7b3dSmrg fbDestroyPixmap(pixmap); 1063428d7b3dSmrg return TRUE; 1064428d7b3dSmrg} 1065428d7b3dSmrg 1066428d7b3dSmrgBool intel_uxa_create_screen_resources(ScreenPtr screen) 1067428d7b3dSmrg{ 1068428d7b3dSmrg ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 1069428d7b3dSmrg PixmapPtr pixmap; 1070428d7b3dSmrg intel_screen_private *intel = intel_get_screen_private(scrn); 1071428d7b3dSmrg dri_bo *bo = intel->front_buffer; 1072428d7b3dSmrg int old_width, old_height, old_pitch; 1073428d7b3dSmrg 1074428d7b3dSmrg if (!uxa_resources_init(screen)) 1075428d7b3dSmrg return FALSE; 1076428d7b3dSmrg 1077428d7b3dSmrg if (drm_intel_gem_bo_map_gtt(bo)) 1078428d7b3dSmrg return FALSE; 1079428d7b3dSmrg 1080428d7b3dSmrg pixmap = screen->GetScreenPixmap(screen); 1081428d7b3dSmrg old_width = pixmap->drawable.width; 1082428d7b3dSmrg old_height = pixmap->drawable.height; 1083428d7b3dSmrg old_pitch = pixmap->devKind; 1084428d7b3dSmrg 1085428d7b3dSmrg if (!screen->ModifyPixmapHeader(pixmap, 1086428d7b3dSmrg scrn->virtualX, 1087428d7b3dSmrg scrn->virtualY, 1088428d7b3dSmrg -1, -1, 1089428d7b3dSmrg intel->front_pitch, 1090428d7b3dSmrg NULL)) 1091428d7b3dSmrg return FALSE; 1092428d7b3dSmrg 1093428d7b3dSmrg intel_uxa_set_pixmap_bo(pixmap, bo); 1094428d7b3dSmrg if (intel_uxa_get_pixmap_private(pixmap) == NULL) 1095428d7b3dSmrg goto err; 1096428d7b3dSmrg 1097428d7b3dSmrg intel_uxa_get_pixmap_private(pixmap)->pinned |= PIN_SCANOUT; 1098428d7b3dSmrg scrn->displayWidth = intel->front_pitch / intel->cpp; 1099428d7b3dSmrg 1100428d7b3dSmrg return TRUE; 1101428d7b3dSmrg 1102428d7b3dSmrgerr: 1103428d7b3dSmrg screen->ModifyPixmapHeader(pixmap, 1104428d7b3dSmrg old_width, old_height, -1, -1, old_pitch, NULL); 1105428d7b3dSmrg return FALSE; 1106428d7b3dSmrg} 1107428d7b3dSmrg 1108428d7b3dSmrg#ifdef CREATE_PIXMAP_USAGE_SHARED 1109428d7b3dSmrgstatic Bool 1110428d7b3dSmrgintel_uxa_share_pixmap_backing(PixmapPtr ppix, ScreenPtr slave, void **fd_handle) 1111428d7b3dSmrg{ 1112428d7b3dSmrg ScrnInfoPtr scrn = xf86ScreenToScrn(ppix->drawable.pScreen); 1113428d7b3dSmrg intel_screen_private *intel = intel_get_screen_private(scrn); 1114428d7b3dSmrg struct intel_uxa_pixmap *priv = intel_uxa_get_pixmap_private(ppix); 1115428d7b3dSmrg unsigned int size, tiling, swizzle; 1116428d7b3dSmrg dri_bo *bo = intel_uxa_get_pixmap_bo(ppix), *newbo; 1117428d7b3dSmrg int stride; 1118428d7b3dSmrg int handle; 1119428d7b3dSmrg 1120428d7b3dSmrg if (drm_intel_bo_references(intel->batch_bo, bo)) 1121428d7b3dSmrg intel_batch_submit(intel->scrn); 1122428d7b3dSmrg 1123428d7b3dSmrg drm_intel_bo_get_tiling(bo, &tiling, &swizzle); 1124428d7b3dSmrg 1125428d7b3dSmrg if (tiling == I915_TILING_X) { 1126428d7b3dSmrg if (priv->pinned) 1127428d7b3dSmrg return FALSE; 1128428d7b3dSmrg 1129428d7b3dSmrg tiling = I915_TILING_NONE; 1130428d7b3dSmrg 1131428d7b3dSmrg size = intel_compute_size(intel, 1132428d7b3dSmrg ppix->drawable.width, ppix->drawable.height, 1133428d7b3dSmrg ppix->drawable.bitsPerPixel, INTEL_CREATE_PIXMAP_DRI2, 1134428d7b3dSmrg &tiling, &stride); 1135428d7b3dSmrg 1136428d7b3dSmrg newbo = drm_intel_bo_alloc_for_render(intel->bufmgr, 1137428d7b3dSmrg "pixmap", 1138428d7b3dSmrg size, 0); 1139428d7b3dSmrg 1140428d7b3dSmrg if (tiling != I915_TILING_NONE) 1141428d7b3dSmrg drm_intel_bo_set_tiling(newbo, &tiling, stride); 1142428d7b3dSmrg priv->tiling = tiling; 1143428d7b3dSmrg intel_uxa_set_pixmap_bo(ppix, newbo); 1144428d7b3dSmrg 1145428d7b3dSmrg ppix->drawable.pScreen->ModifyPixmapHeader(ppix, ppix->drawable.width, 1146428d7b3dSmrg ppix->drawable.height, 0, 0, 1147428d7b3dSmrg stride, NULL); 1148428d7b3dSmrg bo = newbo; 1149428d7b3dSmrg } 1150428d7b3dSmrg drm_intel_bo_get_tiling(bo, &tiling, &swizzle); 1151428d7b3dSmrg drm_intel_bo_gem_export_to_prime(bo, &handle); 1152428d7b3dSmrg priv->pinned |= PIN_PRIME; 1153428d7b3dSmrg 1154428d7b3dSmrg *fd_handle = (void *)(long)handle; 1155428d7b3dSmrg return TRUE; 1156428d7b3dSmrg} 1157428d7b3dSmrg 1158428d7b3dSmrgstatic Bool 1159428d7b3dSmrgintel_uxa_set_shared_pixmap_backing(PixmapPtr ppix, void *fd_handle) 1160428d7b3dSmrg{ 1161428d7b3dSmrg ScrnInfoPtr scrn = xf86ScreenToScrn(ppix->drawable.pScreen); 1162428d7b3dSmrg intel_screen_private *intel = intel_get_screen_private(scrn); 1163428d7b3dSmrg dri_bo *bo; 1164428d7b3dSmrg int ihandle = (int)(long)fd_handle; 1165428d7b3dSmrg 1166428d7b3dSmrg /* force untiled for now */ 1167428d7b3dSmrg bo = drm_intel_bo_gem_create_from_prime(intel->bufmgr, ihandle, 0); 1168428d7b3dSmrg if (!bo) 1169428d7b3dSmrg return FALSE; 1170428d7b3dSmrg 1171428d7b3dSmrg intel_uxa_set_pixmap_bo(ppix, bo); 1172428d7b3dSmrg close(ihandle); 1173428d7b3dSmrg return TRUE; 1174428d7b3dSmrg} 1175428d7b3dSmrg#endif 1176428d7b3dSmrg 1177428d7b3dSmrgstatic void 1178428d7b3dSmrgintel_limits_init(intel_screen_private *intel) 1179428d7b3dSmrg{ 1180428d7b3dSmrg /* Limits are described in the BLT engine chapter under Graphics Data Size 1181428d7b3dSmrg * Limitations, and the descriptions of SURFACE_STATE, 3DSTATE_BUFFER_INFO, 1182428d7b3dSmrg * 3DSTATE_DRAWING_RECTANGLE, 3DSTATE_MAP_INFO, and 3DSTATE_MAP_INFO. 1183428d7b3dSmrg * 1184428d7b3dSmrg * i845 through i965 limits 2D rendering to 65536 lines and pitch of 32768. 1185428d7b3dSmrg * 1186428d7b3dSmrg * i965 limits 3D surface to (2*element size)-aligned offset if un-tiled. 1187428d7b3dSmrg * i965 limits 3D surface to 4kB-aligned offset if tiled. 1188428d7b3dSmrg * i965 limits 3D surfaces to w,h of ?,8192. 1189428d7b3dSmrg * i965 limits 3D surface to pitch of 1B - 128kB. 1190428d7b3dSmrg * i965 limits 3D surface pitch alignment to 1 or 2 times the element size. 1191428d7b3dSmrg * i965 limits 3D surface pitch alignment to 512B if tiled. 1192428d7b3dSmrg * i965 limits 3D destination drawing rect to w,h of 8192,8192. 1193428d7b3dSmrg * 1194428d7b3dSmrg * i915 limits 3D textures to 4B-aligned offset if un-tiled. 1195428d7b3dSmrg * i915 limits 3D textures to ~4kB-aligned offset if tiled. 1196428d7b3dSmrg * i915 limits 3D textures to width,height of 2048,2048. 1197428d7b3dSmrg * i915 limits 3D textures to pitch of 16B - 8kB, in dwords. 1198428d7b3dSmrg * i915 limits 3D destination to ~4kB-aligned offset if tiled. 1199428d7b3dSmrg * i915 limits 3D destination to pitch of 16B - 8kB, in dwords, if un-tiled. 1200428d7b3dSmrg * i915 limits 3D destination to pitch 64B-aligned if used with depth. 1201428d7b3dSmrg * i915 limits 3D destination to pitch of 512B - 8kB, in tiles, if tiled. 1202428d7b3dSmrg * i915 limits 3D destination to POT aligned pitch if tiled. 1203428d7b3dSmrg * i915 limits 3D destination drawing rect to w,h of 2048,2048. 1204428d7b3dSmrg * 1205428d7b3dSmrg * i845 limits 3D textures to 4B-aligned offset if un-tiled. 1206428d7b3dSmrg * i845 limits 3D textures to ~4kB-aligned offset if tiled. 1207428d7b3dSmrg * i845 limits 3D textures to width,height of 2048,2048. 1208428d7b3dSmrg * i845 limits 3D textures to pitch of 4B - 8kB, in dwords. 1209428d7b3dSmrg * i845 limits 3D destination to 4B-aligned offset if un-tiled. 1210428d7b3dSmrg * i845 limits 3D destination to ~4kB-aligned offset if tiled. 1211428d7b3dSmrg * i845 limits 3D destination to pitch of 8B - 8kB, in dwords. 1212428d7b3dSmrg * i845 limits 3D destination drawing rect to w,h of 2048,2048. 1213428d7b3dSmrg * 1214428d7b3dSmrg * For the tiled issues, the only tiled buffer we draw to should be 1215428d7b3dSmrg * the front, which will have an appropriate pitch/offset already set up, 1216428d7b3dSmrg * so UXA doesn't need to worry. 1217428d7b3dSmrg */ 1218428d7b3dSmrg if (INTEL_INFO(intel)->gen >= 040) { 1219428d7b3dSmrg intel->accel_pixmap_offset_alignment = 4 * 2; 1220428d7b3dSmrg intel->accel_max_x = 8192; 1221428d7b3dSmrg intel->accel_max_y = 8192; 1222428d7b3dSmrg } else { 1223428d7b3dSmrg intel->accel_pixmap_offset_alignment = 4; 1224428d7b3dSmrg intel->accel_max_x = 2048; 1225428d7b3dSmrg intel->accel_max_y = 2048; 1226428d7b3dSmrg } 1227428d7b3dSmrg} 1228428d7b3dSmrg 1229428d7b3dSmrgstatic Bool intel_option_accel_none(intel_screen_private *intel) 1230428d7b3dSmrg{ 1231428d7b3dSmrg const char *s; 1232428d7b3dSmrg 1233428d7b3dSmrg s = xf86GetOptValString(intel->Options, OPTION_ACCEL_METHOD); 1234428d7b3dSmrg if (s == NULL) 1235428d7b3dSmrg return IS_DEFAULT_ACCEL_METHOD(NOACCEL); 1236428d7b3dSmrg 1237428d7b3dSmrg return strcasecmp(s, "none") == 0; 1238428d7b3dSmrg} 1239428d7b3dSmrg 1240428d7b3dSmrgstatic Bool intel_option_accel_blt(intel_screen_private *intel) 1241428d7b3dSmrg{ 1242428d7b3dSmrg const char *s; 1243428d7b3dSmrg 1244428d7b3dSmrg s = xf86GetOptValString(intel->Options, OPTION_ACCEL_METHOD); 1245428d7b3dSmrg if (s == NULL) 1246428d7b3dSmrg return FALSE; 1247428d7b3dSmrg 1248428d7b3dSmrg return strcasecmp(s, "blt") == 0; 1249428d7b3dSmrg} 1250428d7b3dSmrg 1251428d7b3dSmrg/** 1252428d7b3dSmrg * Intialiazes the hardware for the 3D pipeline use in the 2D driver. 1253428d7b3dSmrg * 1254428d7b3dSmrg * Some state caching is performed to avoid redundant state emits. This 1255428d7b3dSmrg * function is also responsible for marking the state as clobbered for DRI 1256428d7b3dSmrg * clients. 1257428d7b3dSmrg */ 1258428d7b3dSmrgvoid IntelEmitInvarientState(ScrnInfoPtr scrn) 1259428d7b3dSmrg{ 1260428d7b3dSmrg intel_screen_private *intel = intel_get_screen_private(scrn); 1261428d7b3dSmrg 1262428d7b3dSmrg /* If we've emitted our state since the last clobber by another client, 1263428d7b3dSmrg * skip it. 1264428d7b3dSmrg */ 1265428d7b3dSmrg if (intel->last_3d != LAST_3D_OTHER) 1266428d7b3dSmrg return; 1267428d7b3dSmrg 1268428d7b3dSmrg if (IS_GEN2(intel)) 1269428d7b3dSmrg I830EmitInvarientState(scrn); 1270428d7b3dSmrg else if IS_GEN3(intel) 1271428d7b3dSmrg I915EmitInvarientState(scrn); 1272428d7b3dSmrg} 1273428d7b3dSmrg 1274428d7b3dSmrgBool intel_uxa_init(ScreenPtr screen) 1275428d7b3dSmrg{ 1276428d7b3dSmrg ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 1277428d7b3dSmrg intel_screen_private *intel = intel_get_screen_private(scrn); 1278428d7b3dSmrg 1279428d7b3dSmrg intel_batch_init(scrn); 1280428d7b3dSmrg 1281428d7b3dSmrg if (INTEL_INFO(intel)->gen >= 040 && INTEL_INFO(intel)->gen < 0100) 1282428d7b3dSmrg gen4_render_state_init(scrn); 1283428d7b3dSmrg 1284428d7b3dSmrg#if HAS_DIXREGISTERPRIVATEKEY 1285428d7b3dSmrg if (!dixRegisterPrivateKey(&uxa_pixmap_index, PRIVATE_PIXMAP, 0)) 1286428d7b3dSmrg#else 1287428d7b3dSmrg if (!dixRequestPrivate(&uxa_pixmap_index, 0)) 1288428d7b3dSmrg#endif 1289428d7b3dSmrg return FALSE; 1290428d7b3dSmrg 1291428d7b3dSmrg intel_limits_init(intel); 1292428d7b3dSmrg 1293428d7b3dSmrg intel->uxa_driver = uxa_driver_alloc(); 1294428d7b3dSmrg if (intel->uxa_driver == NULL) 1295428d7b3dSmrg return FALSE; 1296428d7b3dSmrg 1297428d7b3dSmrg memset(intel->uxa_driver, 0, sizeof(*intel->uxa_driver)); 1298428d7b3dSmrg 1299428d7b3dSmrg intel->uxa_driver->uxa_major = 1; 1300428d7b3dSmrg intel->uxa_driver->uxa_minor = 0; 1301428d7b3dSmrg 1302428d7b3dSmrg intel->prim_offset = 0; 1303428d7b3dSmrg intel->vertex_count = 0; 1304428d7b3dSmrg intel->vertex_offset = 0; 1305428d7b3dSmrg intel->vertex_used = 0; 1306428d7b3dSmrg intel->floats_per_vertex = 0; 1307428d7b3dSmrg intel->last_floats_per_vertex = 0; 1308428d7b3dSmrg intel->vertex_bo = NULL; 1309428d7b3dSmrg intel->surface_used = 0; 1310428d7b3dSmrg intel->surface_reloc = 0; 1311428d7b3dSmrg 1312428d7b3dSmrg /* Solid fill */ 1313428d7b3dSmrg intel->uxa_driver->check_solid = intel_uxa_check_solid; 1314428d7b3dSmrg intel->uxa_driver->prepare_solid = intel_uxa_prepare_solid; 1315428d7b3dSmrg intel->uxa_driver->solid = intel_uxa_solid; 1316428d7b3dSmrg intel->uxa_driver->done_solid = intel_uxa_done; 1317428d7b3dSmrg 1318428d7b3dSmrg /* Copy */ 1319428d7b3dSmrg intel->uxa_driver->check_copy = intel_uxa_check_copy; 1320428d7b3dSmrg intel->uxa_driver->prepare_copy = intel_uxa_prepare_copy; 1321428d7b3dSmrg intel->uxa_driver->copy = intel_uxa_copy; 1322428d7b3dSmrg intel->uxa_driver->done_copy = intel_uxa_done; 1323428d7b3dSmrg 1324428d7b3dSmrg /* Composite */ 1325428d7b3dSmrg if (intel_option_accel_blt(intel)) { 1326428d7b3dSmrg } else if (INTEL_INFO(intel)->gen < 030) { 1327428d7b3dSmrg intel->uxa_driver->check_composite = i830_check_composite; 1328428d7b3dSmrg intel->uxa_driver->check_composite_target = i830_check_composite_target; 1329428d7b3dSmrg intel->uxa_driver->check_composite_texture = i830_check_composite_texture; 1330428d7b3dSmrg intel->uxa_driver->prepare_composite = i830_prepare_composite; 1331428d7b3dSmrg intel->uxa_driver->composite = i830_composite; 1332428d7b3dSmrg intel->uxa_driver->done_composite = i830_done_composite; 1333428d7b3dSmrg 1334428d7b3dSmrg intel->vertex_flush = i830_vertex_flush; 1335428d7b3dSmrg intel->batch_commit_notify = i830_batch_commit_notify; 1336428d7b3dSmrg } else if (INTEL_INFO(intel)->gen < 040) { 1337428d7b3dSmrg intel->uxa_driver->check_composite = i915_check_composite; 1338428d7b3dSmrg intel->uxa_driver->check_composite_target = i915_check_composite_target; 1339428d7b3dSmrg intel->uxa_driver->check_composite_texture = i915_check_composite_texture; 1340428d7b3dSmrg intel->uxa_driver->prepare_composite = i915_prepare_composite; 1341428d7b3dSmrg intel->uxa_driver->composite = i915_composite; 1342428d7b3dSmrg intel->uxa_driver->done_composite = i830_done_composite; 1343428d7b3dSmrg 1344428d7b3dSmrg intel->vertex_flush = i915_vertex_flush; 1345428d7b3dSmrg intel->batch_commit_notify = i915_batch_commit_notify; 1346428d7b3dSmrg } else if (INTEL_INFO(intel)->gen < 0100) { 1347428d7b3dSmrg intel->uxa_driver->check_composite = i965_check_composite; 1348428d7b3dSmrg intel->uxa_driver->check_composite_texture = i965_check_composite_texture; 1349428d7b3dSmrg intel->uxa_driver->prepare_composite = i965_prepare_composite; 1350428d7b3dSmrg intel->uxa_driver->composite = i965_composite; 1351428d7b3dSmrg intel->uxa_driver->done_composite = i830_done_composite; 1352428d7b3dSmrg 1353428d7b3dSmrg intel->vertex_flush = i965_vertex_flush; 1354428d7b3dSmrg intel->batch_flush = i965_batch_flush; 1355428d7b3dSmrg intel->batch_commit_notify = i965_batch_commit_notify; 1356428d7b3dSmrg 1357428d7b3dSmrg if (INTEL_INFO(intel)->gen < 050) { 1358428d7b3dSmrg intel->context_switch = gen4_context_switch; 1359428d7b3dSmrg } else if (INTEL_INFO(intel)->gen < 060) { 1360428d7b3dSmrg intel->context_switch = gen5_context_switch; 1361428d7b3dSmrg } else { 1362428d7b3dSmrg intel->context_switch = gen6_context_switch; 1363428d7b3dSmrg } 1364428d7b3dSmrg } 1365428d7b3dSmrg 1366428d7b3dSmrg /* PutImage */ 1367428d7b3dSmrg intel->uxa_driver->put_image = intel_uxa_put_image; 1368428d7b3dSmrg intel->uxa_driver->get_image = intel_uxa_get_image; 1369428d7b3dSmrg 1370428d7b3dSmrg intel->uxa_driver->prepare_access = intel_uxa_prepare_access; 1371428d7b3dSmrg intel->uxa_driver->finish_access = intel_uxa_finish_access; 1372428d7b3dSmrg intel->uxa_driver->pixmap_is_offscreen = intel_uxa_pixmap_is_offscreen; 1373428d7b3dSmrg 1374428d7b3dSmrg screen->CreatePixmap = intel_uxa_create_pixmap; 1375428d7b3dSmrg screen->DestroyPixmap = intel_uxa_destroy_pixmap; 1376428d7b3dSmrg 1377428d7b3dSmrg#ifdef CREATE_PIXMAP_USAGE_SHARED 1378428d7b3dSmrg screen->SharePixmapBacking = intel_uxa_share_pixmap_backing; 1379428d7b3dSmrg screen->SetSharedPixmapBacking = intel_uxa_set_shared_pixmap_backing; 1380428d7b3dSmrg#endif 1381428d7b3dSmrg 1382428d7b3dSmrg if (!uxa_driver_init(screen, intel->uxa_driver)) { 1383428d7b3dSmrg xf86DrvMsg(scrn->scrnIndex, X_ERROR, 1384428d7b3dSmrg "UXA initialization failed\n"); 1385428d7b3dSmrg free(intel->uxa_driver); 1386428d7b3dSmrg return FALSE; 1387428d7b3dSmrg } 1388428d7b3dSmrg 1389428d7b3dSmrg if (intel_option_accel_none(intel)) 1390428d7b3dSmrg intel->force_fallback = 1; 1391428d7b3dSmrg 1392428d7b3dSmrg uxa_set_fallback_debug(screen, intel->fallback_debug); 1393428d7b3dSmrg uxa_set_force_fallback(screen, intel->force_fallback); 1394428d7b3dSmrg 1395428d7b3dSmrg intel->flush_rendering = intel_flush_rendering; 1396428d7b3dSmrg return TRUE; 1397428d7b3dSmrg} 1398