i915_render.c revision fa225cbc
1/* 2 * Copyright © 2006 Intel Corporation 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice (including the next 12 * paragraph) shall be included in all copies or substantial portions of the 13 * Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 * SOFTWARE. 22 * 23 * Authors: 24 * Wang Zhenyu <zhenyu.z.wang@intel.com> 25 * Eric Anholt <eric@anholt.net> 26 * 27 */ 28 29#ifdef HAVE_CONFIG_H 30#include "config.h" 31#endif 32 33#include "xf86.h" 34#include "i830.h" 35#include "i915_reg.h" 36#include "i915_3d.h" 37 38struct formatinfo { 39 int fmt; 40 uint32_t card_fmt; 41}; 42 43struct blendinfo { 44 Bool dst_alpha; 45 Bool src_alpha; 46 uint32_t src_blend; 47 uint32_t dst_blend; 48}; 49 50static struct blendinfo i915_blend_op[] = { 51 /* Clear */ 52 {0, 0, BLENDFACT_ZERO, BLENDFACT_ZERO}, 53 /* Src */ 54 {0, 0, BLENDFACT_ONE, BLENDFACT_ZERO}, 55 /* Dst */ 56 {0, 0, BLENDFACT_ZERO, BLENDFACT_ONE}, 57 /* Over */ 58 {0, 1, BLENDFACT_ONE, BLENDFACT_INV_SRC_ALPHA}, 59 /* OverReverse */ 60 {1, 0, BLENDFACT_INV_DST_ALPHA, BLENDFACT_ONE}, 61 /* In */ 62 {1, 0, BLENDFACT_DST_ALPHA, BLENDFACT_ZERO}, 63 /* InReverse */ 64 {0, 1, BLENDFACT_ZERO, BLENDFACT_SRC_ALPHA}, 65 /* Out */ 66 {1, 0, BLENDFACT_INV_DST_ALPHA, BLENDFACT_ZERO}, 67 /* OutReverse */ 68 {0, 1, BLENDFACT_ZERO, BLENDFACT_INV_SRC_ALPHA}, 69 /* Atop */ 70 {1, 1, BLENDFACT_DST_ALPHA, BLENDFACT_INV_SRC_ALPHA}, 71 /* AtopReverse */ 72 {1, 1, BLENDFACT_INV_DST_ALPHA, BLENDFACT_SRC_ALPHA}, 73 /* Xor */ 74 {1, 1, BLENDFACT_INV_DST_ALPHA, BLENDFACT_INV_SRC_ALPHA}, 75 /* Add */ 76 {0, 0, BLENDFACT_ONE, BLENDFACT_ONE}, 77}; 78 79static struct formatinfo i915_tex_formats[] = { 80 {PICT_a8r8g8b8, MAPSURF_32BIT | MT_32BIT_ARGB8888 }, 81 {PICT_x8r8g8b8, MAPSURF_32BIT | MT_32BIT_XRGB8888 }, 82 {PICT_a8b8g8r8, MAPSURF_32BIT | MT_32BIT_ABGR8888 }, 83 {PICT_x8b8g8r8, MAPSURF_32BIT | MT_32BIT_XBGR8888 }, 84 {PICT_r5g6b5, MAPSURF_16BIT | MT_16BIT_RGB565 }, 85 {PICT_a1r5g5b5, MAPSURF_16BIT | MT_16BIT_ARGB1555 }, 86 {PICT_x1r5g5b5, MAPSURF_16BIT | MT_16BIT_ARGB1555 }, 87 {PICT_a4r4g4b4, MAPSURF_16BIT | MT_16BIT_ARGB4444 }, 88 {PICT_x4r4g4b4, MAPSURF_16BIT | MT_16BIT_ARGB4444 }, 89 {PICT_a8, MAPSURF_8BIT | MT_8BIT_A8 }, 90}; 91 92static uint32_t i915_get_blend_cntl(int op, PicturePtr pMask, 93 uint32_t dst_format) 94{ 95 uint32_t sblend, dblend; 96 97 sblend = i915_blend_op[op].src_blend; 98 dblend = i915_blend_op[op].dst_blend; 99 100 /* If there's no dst alpha channel, adjust the blend op so that we'll treat 101 * it as always 1. 102 */ 103 if (PICT_FORMAT_A(dst_format) == 0 && i915_blend_op[op].dst_alpha) { 104 if (sblend == BLENDFACT_DST_ALPHA) 105 sblend = BLENDFACT_ONE; 106 else if (sblend == BLENDFACT_INV_DST_ALPHA) 107 sblend = BLENDFACT_ZERO; 108 } 109 110 /* i915 engine reads 8bit color buffer into green channel in cases 111 like color buffer blending .etc, and also writes back green channel. 112 So with dst_alpha blend we should use color factor. See spec on 113 "8-bit rendering" */ 114 if ((dst_format == PICT_a8) && i915_blend_op[op].dst_alpha) { 115 if (sblend == BLENDFACT_DST_ALPHA) 116 sblend = BLENDFACT_DST_COLR; 117 else if (sblend == BLENDFACT_INV_DST_ALPHA) 118 sblend = BLENDFACT_INV_DST_COLR; 119 } 120 121 /* If the source alpha is being used, then we should only be in a case 122 * where the source blend factor is 0, and the source blend value is the 123 * mask channels multiplied by the source picture's alpha. 124 */ 125 if (pMask && pMask->componentAlpha && PICT_FORMAT_RGB(pMask->format) && 126 i915_blend_op[op].src_alpha) 127 { 128 if (dblend == BLENDFACT_SRC_ALPHA) { 129 dblend = BLENDFACT_SRC_COLR; 130 } else if (dblend == BLENDFACT_INV_SRC_ALPHA) { 131 dblend = BLENDFACT_INV_SRC_COLR; 132 } 133 } 134 135 return (sblend << S6_CBUF_SRC_BLEND_FACT_SHIFT) | 136 (dblend << S6_CBUF_DST_BLEND_FACT_SHIFT); 137} 138 139static Bool i915_get_dest_format(PicturePtr pDstPicture, uint32_t *dst_format) 140{ 141 switch (pDstPicture->format) { 142 case PICT_a8r8g8b8: 143 case PICT_x8r8g8b8: 144 *dst_format = COLR_BUF_ARGB8888; 145 break; 146 case PICT_r5g6b5: 147 *dst_format = COLR_BUF_RGB565; 148 break; 149 case PICT_a1r5g5b5: 150 case PICT_x1r5g5b5: 151 *dst_format = COLR_BUF_ARGB1555; 152 break; 153 case PICT_a8: 154 *dst_format = COLR_BUF_8BIT; 155 break; 156 case PICT_a4r4g4b4: 157 case PICT_x4r4g4b4: 158 *dst_format = COLR_BUF_ARGB4444; 159 break; 160 default: 161 { 162 ScrnInfoPtr pScrn; 163 164 pScrn = xf86Screens[pDstPicture->pDrawable->pScreen->myNum]; 165 I830FALLBACK("Unsupported dest format 0x%x\n", 166 (int)pDstPicture->format); 167 } 168 } 169 return TRUE; 170} 171 172static Bool i915_check_composite_texture(ScrnInfoPtr pScrn, PicturePtr pPict, int unit) 173{ 174 if (pPict->repeatType > RepeatReflect) 175 I830FALLBACK("Unsupported picture repeat %d\n", pPict->repeatType); 176 177 if (pPict->filter != PictFilterNearest && 178 pPict->filter != PictFilterBilinear) 179 I830FALLBACK("Unsupported filter 0x%x\n", pPict->filter); 180 181 if (pPict->pDrawable) 182 { 183 int w, h, i; 184 185 w = pPict->pDrawable->width; 186 h = pPict->pDrawable->height; 187 if ((w > 2048) || (h > 2048)) 188 I830FALLBACK("Picture w/h too large (%dx%d)\n", w, h); 189 190 for (i = 0; i < sizeof(i915_tex_formats) / sizeof(i915_tex_formats[0]); 191 i++) 192 { 193 if (i915_tex_formats[i].fmt == pPict->format) 194 break; 195 } 196 if (i == sizeof(i915_tex_formats) / sizeof(i915_tex_formats[0])) 197 I830FALLBACK("Unsupported picture format 0x%x\n", 198 (int)pPict->format); 199 } 200 201 return TRUE; 202} 203 204Bool 205i915_check_composite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture, 206 PicturePtr pDstPicture) 207{ 208 ScrnInfoPtr pScrn = xf86Screens[pDstPicture->pDrawable->pScreen->myNum]; 209 uint32_t tmp1; 210 211 /* Check for unsupported compositing operations. */ 212 if (op >= sizeof(i915_blend_op) / sizeof(i915_blend_op[0])) 213 I830FALLBACK("Unsupported Composite op 0x%x\n", op); 214 if (pMaskPicture != NULL && pMaskPicture->componentAlpha && 215 PICT_FORMAT_RGB(pMaskPicture->format)) 216 { 217 /* Check if it's component alpha that relies on a source alpha and on 218 * the source value. We can only get one of those into the single 219 * source value that we get to blend with. 220 */ 221 if (i915_blend_op[op].src_alpha && 222 (i915_blend_op[op].src_blend != BLENDFACT_ZERO)) 223 I830FALLBACK("Component alpha not supported with source " 224 "alpha and source value blending.\n"); 225 } 226 227 if (!i915_check_composite_texture(pScrn, pSrcPicture, 0)) 228 I830FALLBACK("Check Src picture texture\n"); 229 if (pMaskPicture != NULL && !i915_check_composite_texture(pScrn, pMaskPicture, 1)) 230 I830FALLBACK("Check Mask picture texture\n"); 231 232 if (!i915_get_dest_format(pDstPicture, &tmp1)) 233 I830FALLBACK("Get Color buffer format\n"); 234 235 return TRUE; 236} 237 238static Bool 239i915_texture_setup(PicturePtr pPict, PixmapPtr pPix, int unit) 240{ 241 ScrnInfoPtr pScrn = xf86Screens[pPict->pDrawable->pScreen->myNum]; 242 I830Ptr pI830 = I830PTR(pScrn); 243 uint32_t format, pitch, filter; 244 int w, h, i; 245 uint32_t wrap_mode; 246 247 pitch = intel_get_pixmap_pitch(pPix); 248 w = pPict->pDrawable->width; 249 h = pPict->pDrawable->height; 250 pI830->scale_units[unit][0] = pPix->drawable.width; 251 pI830->scale_units[unit][1] = pPix->drawable.height; 252 253 for (i = 0; i < sizeof(i915_tex_formats) / sizeof(i915_tex_formats[0]); 254 i++) 255 { 256 if (i915_tex_formats[i].fmt == pPict->format) 257 break; 258 } 259 if (i == sizeof(i915_tex_formats)/ sizeof(i915_tex_formats[0])) 260 I830FALLBACK("unknown texture format\n"); 261 format = i915_tex_formats[i].card_fmt; 262 263 switch (pPict->repeatType) { 264 case RepeatNone: 265 wrap_mode = TEXCOORDMODE_CLAMP_BORDER; 266 break; 267 case RepeatNormal: 268 wrap_mode = TEXCOORDMODE_WRAP; 269 break; 270 case RepeatPad: 271 wrap_mode = TEXCOORDMODE_CLAMP_EDGE; 272 break; 273 case RepeatReflect: 274 wrap_mode = TEXCOORDMODE_MIRROR; 275 break; 276 default: 277 FatalError("Unknown repeat type %d\n", pPict->repeatType); 278 } 279 280 switch (pPict->filter) { 281 case PictFilterNearest: 282 filter = (FILTER_NEAREST << SS2_MAG_FILTER_SHIFT) | 283 (FILTER_NEAREST << SS2_MIN_FILTER_SHIFT); 284 break; 285 case PictFilterBilinear: 286 filter = (FILTER_LINEAR << SS2_MAG_FILTER_SHIFT) | 287 (FILTER_LINEAR << SS2_MIN_FILTER_SHIFT); 288 break; 289 default: 290 filter = 0; 291 I830FALLBACK("Bad filter 0x%x\n", pPict->filter); 292 } 293 294 pI830->mapstate[unit * 3 + 0] = 0; /* offset filled in at emit time */ 295 pI830->mapstate[unit * 3 + 1] = format | 296 MS3_USE_FENCE_REGS | 297 ((pPix->drawable.height - 1) << MS3_HEIGHT_SHIFT) | 298 ((pPix->drawable.width - 1) << MS3_WIDTH_SHIFT); 299 pI830->mapstate[unit * 3 + 2] = ((pitch / 4) - 1) << MS4_PITCH_SHIFT; 300 301 pI830->samplerstate[unit * 3 + 0] = (MIPFILTER_NONE << 302 SS2_MIP_FILTER_SHIFT); 303 pI830->samplerstate[unit * 3 + 0] |= filter; 304 pI830->samplerstate[unit * 3 + 1] = SS3_NORMALIZED_COORDS; 305 pI830->samplerstate[unit * 3 + 1] |= wrap_mode << SS3_TCX_ADDR_MODE_SHIFT; 306 pI830->samplerstate[unit * 3 + 1] |= wrap_mode << SS3_TCY_ADDR_MODE_SHIFT; 307 pI830->samplerstate[unit * 3 + 1] |= unit << SS3_TEXTUREMAP_INDEX_SHIFT; 308 pI830->samplerstate[unit * 3 + 2] = 0x00000000; /* border color */ 309 310 pI830->transform[unit] = pPict->transform; 311 312 return TRUE; 313} 314 315Bool 316i915_prepare_composite(int op, PicturePtr pSrcPicture, 317 PicturePtr pMaskPicture, PicturePtr pDstPicture, 318 PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst) 319{ 320 ScrnInfoPtr pScrn = xf86Screens[pSrcPicture->pDrawable->pScreen->myNum]; 321 I830Ptr pI830 = I830PTR(pScrn); 322 drm_intel_bo *bo_table[] = { 323 NULL, /* batch_bo */ 324 i830_get_pixmap_bo(pSrc), 325 pMask ? i830_get_pixmap_bo(pMask) : NULL, 326 i830_get_pixmap_bo(pDst), 327 }; 328 329 pI830->render_src_picture = pSrcPicture; 330 pI830->render_src = pSrc; 331 pI830->render_mask_picture = pMaskPicture; 332 pI830->render_mask = pMask; 333 pI830->render_dst_picture = pDstPicture; 334 pI830->render_dst = pDst; 335 336 i830_exa_check_pitch_3d(pSrc); 337 if (pMask) 338 i830_exa_check_pitch_3d(pMask); 339 i830_exa_check_pitch_3d(pDst); 340 341 if (!i915_get_dest_format(pDstPicture, 342 &pI830->i915_render_state.dst_format)) 343 return FALSE; 344 345 if (!i830_get_aperture_space(pScrn, bo_table, ARRAY_SIZE(bo_table))) 346 return FALSE; 347 348 if (!i915_texture_setup(pSrcPicture, pSrc, 0)) 349 I830FALLBACK("fail to setup src texture\n"); 350 351 pI830->dst_coord_adjust = 0; 352 pI830->src_coord_adjust = 0; 353 pI830->mask_coord_adjust = 0; 354 if (pSrcPicture->filter == PictFilterNearest) 355 pI830->dst_coord_adjust = -0.125; 356 if (pMask != NULL) { 357 if (!i915_texture_setup(pMaskPicture, pMask, 1)) 358 I830FALLBACK("fail to setup mask texture\n"); 359 360 if (pMaskPicture->filter == PictFilterNearest) 361 pI830->dst_coord_adjust = -0.125; 362 } else { 363 pI830->transform[1] = NULL; 364 pI830->scale_units[1][0] = -1; 365 pI830->scale_units[1][1] = -1; 366 } 367 368 pI830->i915_render_state.op = op; 369 pI830->i915_render_state.needs_emit = TRUE; 370 371 return TRUE; 372} 373 374static void 375i915_emit_composite_setup(ScrnInfoPtr pScrn) 376{ 377 I830Ptr pI830 = I830PTR(pScrn); 378 int op = pI830->i915_render_state.op; 379 PicturePtr pSrcPicture = pI830->render_src_picture; 380 PicturePtr pMaskPicture = pI830->render_mask_picture; 381 PicturePtr pDstPicture = pI830->render_dst_picture; 382 PixmapPtr pSrc = pI830->render_src; 383 PixmapPtr pMask = pI830->render_mask; 384 PixmapPtr pDst = pI830->render_dst; 385 uint32_t dst_format = pI830->i915_render_state.dst_format, dst_pitch; 386 uint32_t blendctl; 387 int out_reg = FS_OC; 388 FS_LOCALS(20); 389 Bool is_affine_src, is_affine_mask; 390 391 pI830->i915_render_state.needs_emit = FALSE; 392 393 IntelEmitInvarientState(pScrn); 394 pI830->last_3d = LAST_3D_RENDER; 395 396 dst_pitch = intel_get_pixmap_pitch(pDst); 397 398 is_affine_src = i830_transform_is_affine (pI830->transform[0]); 399 is_affine_mask = i830_transform_is_affine (pI830->transform[1]); 400 401 if (pMask == NULL) { 402 BEGIN_BATCH(10); 403 OUT_BATCH(_3DSTATE_MAP_STATE | 3); 404 OUT_BATCH(0x00000001); /* map 0 */ 405 OUT_RELOC_PIXMAP(pSrc, I915_GEM_DOMAIN_SAMPLER, 0, 0); 406 OUT_BATCH(pI830->mapstate[1]); 407 OUT_BATCH(pI830->mapstate[2]); 408 409 OUT_BATCH(_3DSTATE_SAMPLER_STATE | 3); 410 OUT_BATCH(0x00000001); /* sampler 0 */ 411 OUT_BATCH(pI830->samplerstate[0]); 412 OUT_BATCH(pI830->samplerstate[1]); 413 OUT_BATCH(pI830->samplerstate[2]); 414 ADVANCE_BATCH(); 415 } else { 416 BEGIN_BATCH(16); 417 OUT_BATCH(_3DSTATE_MAP_STATE | 6); 418 OUT_BATCH(0x00000003); /* map 0,1 */ 419 OUT_RELOC_PIXMAP(pSrc, I915_GEM_DOMAIN_SAMPLER, 0, 0); 420 OUT_BATCH(pI830->mapstate[1]); 421 OUT_BATCH(pI830->mapstate[2]); 422 OUT_RELOC_PIXMAP(pMask, I915_GEM_DOMAIN_SAMPLER, 0, 0); 423 OUT_BATCH(pI830->mapstate[4]); 424 OUT_BATCH(pI830->mapstate[5]); 425 426 OUT_BATCH(_3DSTATE_SAMPLER_STATE | 6); 427 OUT_BATCH(0x00000003); /* sampler 0,1 */ 428 OUT_BATCH(pI830->samplerstate[0]); 429 OUT_BATCH(pI830->samplerstate[1]); 430 OUT_BATCH(pI830->samplerstate[2]); 431 OUT_BATCH(pI830->samplerstate[3]); 432 OUT_BATCH(pI830->samplerstate[4]); 433 OUT_BATCH(pI830->samplerstate[5]); 434 ADVANCE_BATCH(); 435 } 436 { 437 uint32_t ss2; 438 439 BEGIN_BATCH(16); 440 OUT_BATCH(_3DSTATE_BUF_INFO_CMD); 441 OUT_BATCH(BUF_3D_ID_COLOR_BACK| BUF_3D_USE_FENCE| 442 BUF_3D_PITCH(dst_pitch)); 443 OUT_RELOC_PIXMAP(pDst, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0); 444 445 OUT_BATCH(_3DSTATE_DST_BUF_VARS_CMD); 446 OUT_BATCH(dst_format); 447 448 OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(2) | 449 I1_LOAD_S(4) | I1_LOAD_S(5) | I1_LOAD_S(6) | 3); 450 ss2 = S2_TEXCOORD_FMT(0, is_affine_src ? TEXCOORDFMT_2D : TEXCOORDFMT_4D); 451 if (pMask) 452 ss2 |= S2_TEXCOORD_FMT(1, is_affine_mask ? TEXCOORDFMT_2D : TEXCOORDFMT_4D); 453 else 454 ss2 |= S2_TEXCOORD_FMT(1, TEXCOORDFMT_NOT_PRESENT); 455 ss2 |= S2_TEXCOORD_FMT(2, TEXCOORDFMT_NOT_PRESENT); 456 ss2 |= S2_TEXCOORD_FMT(3, TEXCOORDFMT_NOT_PRESENT); 457 ss2 |= S2_TEXCOORD_FMT(4, TEXCOORDFMT_NOT_PRESENT); 458 ss2 |= S2_TEXCOORD_FMT(5, TEXCOORDFMT_NOT_PRESENT); 459 ss2 |= S2_TEXCOORD_FMT(6, TEXCOORDFMT_NOT_PRESENT); 460 ss2 |= S2_TEXCOORD_FMT(7, TEXCOORDFMT_NOT_PRESENT); 461 OUT_BATCH(ss2); 462 OUT_BATCH((1 << S4_POINT_WIDTH_SHIFT) | S4_LINE_WIDTH_ONE | 463 S4_CULLMODE_NONE| S4_VFMT_XY); 464 blendctl = i915_get_blend_cntl(op, pMaskPicture, pDstPicture->format); 465 OUT_BATCH(0x00000000); /* Disable stencil buffer */ 466 OUT_BATCH(S6_CBUF_BLEND_ENABLE | S6_COLOR_WRITE_ENABLE | 467 (BLENDFUNC_ADD << S6_CBUF_BLEND_FUNC_SHIFT) | blendctl); 468 469 /* draw rect is unconditional */ 470 OUT_BATCH(_3DSTATE_DRAW_RECT_CMD); 471 OUT_BATCH(0x00000000); 472 OUT_BATCH(0x00000000); /* ymin, xmin*/ 473 OUT_BATCH(DRAW_YMAX(pDst->drawable.height - 1) | 474 DRAW_XMAX(pDst->drawable.width - 1)); 475 OUT_BATCH(0x00000000); /* yorig, xorig (relate to color buffer?)*/ 476 OUT_BATCH(MI_NOOP); 477 ADVANCE_BATCH(); 478 } 479 480 if (dst_format == COLR_BUF_8BIT) 481 out_reg = FS_U0; 482 483 FS_BEGIN(); 484 485 /* Declare the registers necessary for our program. I don't think the 486 * S then T ordering is necessary. 487 */ 488 i915_fs_dcl(FS_S0); 489 if (pMask) 490 i915_fs_dcl(FS_S1); 491 i915_fs_dcl(FS_T0); 492 if (pMask) 493 i915_fs_dcl(FS_T1); 494 495 /* Load the pSrcPicture texel */ 496 if (is_affine_src) { 497 i915_fs_texld(FS_R0, FS_S0, FS_T0); 498 } else { 499 i915_fs_texldp(FS_R0, FS_S0, FS_T0); 500 } 501 502 /* If the texture lacks an alpha channel, force the alpha to 1. */ 503 if (PICT_FORMAT_A(pSrcPicture->format) == 0) 504 i915_fs_mov_masked(FS_R0, MASK_W, i915_fs_operand_one()); 505 506 if (!pMask) { 507 /* No mask, so move to output color */ 508 i915_fs_mov(out_reg, i915_fs_operand_reg(FS_R0)); 509 } else { 510 /* Load the pMaskPicture texel */ 511 if (is_affine_mask) { 512 i915_fs_texld(FS_R1, FS_S1, FS_T1); 513 } else { 514 i915_fs_texldp(FS_R1, FS_S1, FS_T1); 515 } 516 /* If the texture lacks an alpha channel, force the alpha to 1. */ 517 if (PICT_FORMAT_A(pMaskPicture->format) == 0) 518 i915_fs_mov_masked(FS_R1, MASK_W, i915_fs_operand_one()); 519 520 /* If component alpha is active in the mask and the blend operation 521 * uses the source alpha, then we know we don't need the source 522 * value (otherwise we would have hit a fallback earlier), so we 523 * provide the source alpha (src.A * mask.X) as output color. 524 * Conversely, if CA is set and we don't need the source alpha, then 525 * we produce the source value (src.X * mask.X) and the source alpha 526 * is unused.. Otherwise, we provide the non-CA source value 527 * (src.X * mask.A). 528 */ 529 if (pMaskPicture->componentAlpha && 530 PICT_FORMAT_RGB(pMaskPicture->format)) 531 { 532 if (i915_blend_op[op].src_alpha) { 533 i915_fs_mul(out_reg, i915_fs_operand(FS_R0, W, W, W, W), 534 i915_fs_operand_reg(FS_R1)); 535 } else { 536 i915_fs_mul(out_reg, i915_fs_operand_reg(FS_R0), 537 i915_fs_operand_reg(FS_R1)); 538 } 539 } else { 540 i915_fs_mul(out_reg, i915_fs_operand_reg(FS_R0), 541 i915_fs_operand(FS_R1, W, W, W, W)); 542 } 543 } 544 if (dst_format == COLR_BUF_8BIT) 545 i915_fs_mov(FS_OC, i915_fs_operand(out_reg, W, W, W, W)); 546 547 FS_END(); 548} 549 550 551 552/* Emit the vertices for a single composite rectangle. 553 * 554 * This function is no longer shared between i830 and i915 generation code. 555 */ 556static void 557i915_emit_composite_primitive(PixmapPtr pDst, 558 int srcX, int srcY, 559 int maskX, int maskY, 560 int dstX, int dstY, 561 int w, int h) 562{ 563 ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum]; 564 I830Ptr pI830 = I830PTR(pScrn); 565 Bool is_affine_src, is_affine_mask = TRUE; 566 int per_vertex, num_floats; 567 float src_x[3], src_y[3], src_w[3], mask_x[3], mask_y[3], mask_w[3]; 568 569 per_vertex = 2; /* dest x/y */ 570 571 { 572 float x = srcX + pI830->src_coord_adjust; 573 float y = srcY + pI830->src_coord_adjust; 574 575 is_affine_src = i830_transform_is_affine (pI830->transform[0]); 576 if (is_affine_src) { 577 if (!i830_get_transformed_coordinates(x, y, 578 pI830->transform[0], 579 &src_x[0], &src_y[0])) 580 return; 581 582 if (!i830_get_transformed_coordinates(x, y + h, 583 pI830->transform[0], 584 &src_x[1], &src_y[1])) 585 return; 586 587 if (!i830_get_transformed_coordinates(x + w, y + h, 588 pI830->transform[0], 589 &src_x[2], &src_y[2])) 590 return; 591 592 per_vertex += 2; /* src x/y */ 593 } else { 594 if (!i830_get_transformed_coordinates_3d(x, y, 595 pI830->transform[0], 596 &src_x[0], 597 &src_y[0], 598 &src_w[0])) 599 return; 600 601 if (!i830_get_transformed_coordinates_3d(x, y + h, 602 pI830->transform[0], 603 &src_x[1], 604 &src_y[1], 605 &src_w[1])) 606 return; 607 608 if (!i830_get_transformed_coordinates_3d(x + w, y + h, 609 pI830->transform[0], 610 &src_x[2], 611 &src_y[2], 612 &src_w[2])) 613 return; 614 615 per_vertex += 4; /* src x/y/z/w */ 616 } 617 } 618 619 if (pI830->render_mask) { 620 float x = maskX + pI830->mask_coord_adjust; 621 float y = maskY + pI830->mask_coord_adjust; 622 623 is_affine_mask = i830_transform_is_affine (pI830->transform[1]); 624 if (is_affine_mask) { 625 if (!i830_get_transformed_coordinates(x, y, 626 pI830->transform[1], 627 &mask_x[0], &mask_y[0])) 628 return; 629 630 if (!i830_get_transformed_coordinates(x, y + h, 631 pI830->transform[1], 632 &mask_x[1], &mask_y[1])) 633 return; 634 635 if (!i830_get_transformed_coordinates(x + w, y + h, 636 pI830->transform[1], 637 &mask_x[2], &mask_y[2])) 638 return; 639 640 per_vertex += 2; /* mask x/y */ 641 } else { 642 if (!i830_get_transformed_coordinates_3d(x, y, 643 pI830->transform[1], 644 &mask_x[0], 645 &mask_y[0], 646 &mask_w[0])) 647 return; 648 649 if (!i830_get_transformed_coordinates_3d(x, y + h, 650 pI830->transform[1], 651 &mask_x[1], 652 &mask_y[1], 653 &mask_w[1])) 654 return; 655 656 if (!i830_get_transformed_coordinates_3d(x + w, y + h, 657 pI830->transform[1], 658 &mask_x[2], 659 &mask_y[2], 660 &mask_w[2])) 661 return; 662 663 per_vertex += 4; /* mask x/y/z/w */ 664 } 665 } 666 667 num_floats = 3 * per_vertex; 668 669 BEGIN_BATCH(1 + num_floats); 670 671 OUT_BATCH(PRIM3D_INLINE | PRIM3D_RECTLIST | (num_floats-1)); 672 OUT_BATCH_F(pI830->dst_coord_adjust + dstX + w); 673 OUT_BATCH_F(pI830->dst_coord_adjust + dstY + h); 674 OUT_BATCH_F(src_x[2] / pI830->scale_units[0][0]); 675 OUT_BATCH_F(src_y[2] / pI830->scale_units[0][1]); 676 if (!is_affine_src) { 677 OUT_BATCH_F(0.0); 678 OUT_BATCH_F(src_w[2]); 679 } 680 if (pI830->render_mask) { 681 OUT_BATCH_F(mask_x[2] / pI830->scale_units[1][0]); 682 OUT_BATCH_F(mask_y[2] / pI830->scale_units[1][1]); 683 if (!is_affine_mask) { 684 OUT_BATCH_F(0.0); 685 OUT_BATCH_F(mask_w[2]); 686 } 687 } 688 689 OUT_BATCH_F(pI830->dst_coord_adjust + dstX); 690 OUT_BATCH_F(pI830->dst_coord_adjust + dstY + h); 691 OUT_BATCH_F(src_x[1] / pI830->scale_units[0][0]); 692 OUT_BATCH_F(src_y[1] / pI830->scale_units[0][1]); 693 if (!is_affine_src) { 694 OUT_BATCH_F(0.0); 695 OUT_BATCH_F(src_w[1]); 696 } 697 if (pI830->render_mask) { 698 OUT_BATCH_F(mask_x[1] / pI830->scale_units[1][0]); 699 OUT_BATCH_F(mask_y[1] / pI830->scale_units[1][1]); 700 if (!is_affine_mask) { 701 OUT_BATCH_F(0.0); 702 OUT_BATCH_F(mask_w[1]); 703 } 704 } 705 706 OUT_BATCH_F(pI830->dst_coord_adjust + dstX); 707 OUT_BATCH_F(pI830->dst_coord_adjust + dstY); 708 OUT_BATCH_F(src_x[0] / pI830->scale_units[0][0]); 709 OUT_BATCH_F(src_y[0] / pI830->scale_units[0][1]); 710 if (!is_affine_src) { 711 OUT_BATCH_F(0.0); 712 OUT_BATCH_F(src_w[0]); 713 } 714 if (pI830->render_mask) { 715 OUT_BATCH_F(mask_x[0] / pI830->scale_units[1][0]); 716 OUT_BATCH_F(mask_y[0] / pI830->scale_units[1][1]); 717 if (!is_affine_mask) { 718 OUT_BATCH_F(0.0); 719 OUT_BATCH_F(mask_w[0]); 720 } 721 } 722 723 ADVANCE_BATCH(); 724} 725 726void 727i915_composite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY, 728 int dstX, int dstY, int w, int h) 729{ 730 ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum]; 731 I830Ptr pI830 = I830PTR(pScrn); 732 733 intel_batch_start_atomic(pScrn, 150); 734 735 if (pI830->i915_render_state.needs_emit) 736 i915_emit_composite_setup(pScrn); 737 738 i915_emit_composite_primitive(pDst, srcX, srcY, maskX, maskY, dstX, dstY, 739 w, h); 740 741 intel_batch_end_atomic(pScrn); 742} 743 744void 745i915_batch_flush_notify(ScrnInfoPtr pScrn) 746{ 747 I830Ptr pI830 = I830PTR(pScrn); 748 749 pI830->i915_render_state.needs_emit = TRUE; 750} 751