i830_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 "i830_reg.h" 36 37struct blendinfo { 38 Bool dst_alpha; 39 Bool src_alpha; 40 uint32_t src_blend; 41 uint32_t dst_blend; 42}; 43 44struct formatinfo { 45 int fmt; 46 uint32_t card_fmt; 47}; 48 49#define TB0C_LAST_STAGE (1 << 31) 50#define TB0C_RESULT_SCALE_1X (0 << 29) 51#define TB0C_RESULT_SCALE_2X (1 << 29) 52#define TB0C_RESULT_SCALE_4X (2 << 29) 53#define TB0C_OP_MODULE (3 << 25) 54#define TB0C_OUTPUT_WRITE_CURRENT (0 << 24) 55#define TB0C_OUTPUT_WRITE_ACCUM (1 << 24) 56#define TB0C_ARG3_REPLICATE_ALPHA (1<<23) 57#define TB0C_ARG3_INVERT (1<<22) 58#define TB0C_ARG3_SEL_XXX 59#define TB0C_ARG2_REPLICATE_ALPHA (1<<17) 60#define TB0C_ARG2_INVERT (1<<16) 61#define TB0C_ARG2_SEL_ONE (0 << 12) 62#define TB0C_ARG2_SEL_FACTOR (1 << 12) 63#define TB0C_ARG2_SEL_TEXEL0 (6 << 12) 64#define TB0C_ARG2_SEL_TEXEL1 (7 << 12) 65#define TB0C_ARG2_SEL_TEXEL2 (8 << 12) 66#define TB0C_ARG2_SEL_TEXEL3 (9 << 12) 67#define TB0C_ARG1_REPLICATE_ALPHA (1<<11) 68#define TB0C_ARG1_INVERT (1<<10) 69#define TB0C_ARG1_SEL_ONE (0 << 6) 70#define TB0C_ARG1_SEL_TEXEL0 (6 << 6) 71#define TB0C_ARG1_SEL_TEXEL1 (7 << 6) 72#define TB0C_ARG1_SEL_TEXEL2 (8 << 6) 73#define TB0C_ARG1_SEL_TEXEL3 (9 << 6) 74#define TB0C_ARG0_REPLICATE_ALPHA (1<<5) 75#define TB0C_ARG0_SEL_XXX 76 77#define TB0A_CTR_STAGE_ENABLE (1<<31) 78#define TB0A_RESULT_SCALE_1X (0 << 29) 79#define TB0A_RESULT_SCALE_2X (1 << 29) 80#define TB0A_RESULT_SCALE_4X (2 << 29) 81#define TB0A_OP_MODULE (3 << 25) 82#define TB0A_OUTPUT_WRITE_CURRENT (0<<24) 83#define TB0A_OUTPUT_WRITE_ACCUM (1<<24) 84#define TB0A_CTR_STAGE_SEL_BITS_XXX 85#define TB0A_ARG3_SEL_XXX 86#define TB0A_ARG3_INVERT (1<<17) 87#define TB0A_ARG2_INVERT (1<<16) 88#define TB0A_ARG2_SEL_ONE (0 << 12) 89#define TB0A_ARG2_SEL_TEXEL0 (6 << 12) 90#define TB0A_ARG2_SEL_TEXEL1 (7 << 12) 91#define TB0A_ARG2_SEL_TEXEL2 (8 << 12) 92#define TB0A_ARG2_SEL_TEXEL3 (9 << 12) 93#define TB0A_ARG1_INVERT (1<<10) 94#define TB0A_ARG1_SEL_ONE (0 << 6) 95#define TB0A_ARG1_SEL_TEXEL0 (6 << 6) 96#define TB0A_ARG1_SEL_TEXEL1 (7 << 6) 97#define TB0A_ARG1_SEL_TEXEL2 (8 << 6) 98#define TB0A_ARG1_SEL_TEXEL3 (9 << 6) 99 100static struct blendinfo i830_blend_op[] = { 101 /* Clear */ 102 {0, 0, BLENDFACTOR_ZERO, BLENDFACTOR_ZERO}, 103 /* Src */ 104 {0, 0, BLENDFACTOR_ONE, BLENDFACTOR_ZERO}, 105 /* Dst */ 106 {0, 0, BLENDFACTOR_ZERO, BLENDFACTOR_ONE}, 107 /* Over */ 108 {0, 1, BLENDFACTOR_ONE, BLENDFACTOR_INV_SRC_ALPHA}, 109 /* OverReverse */ 110 {1, 0, BLENDFACTOR_INV_DST_ALPHA, BLENDFACTOR_ONE}, 111 /* In */ 112 {1, 0, BLENDFACTOR_DST_ALPHA, BLENDFACTOR_ZERO}, 113 /* InReverse */ 114 {0, 1, BLENDFACTOR_ZERO, BLENDFACTOR_SRC_ALPHA}, 115 /* Out */ 116 {1, 0, BLENDFACTOR_INV_DST_ALPHA, BLENDFACTOR_ZERO}, 117 /* OutReverse */ 118 {0, 1, BLENDFACTOR_ZERO, BLENDFACTOR_INV_SRC_ALPHA}, 119 /* Atop */ 120 {1, 1, BLENDFACTOR_DST_ALPHA, BLENDFACTOR_INV_SRC_ALPHA}, 121 /* AtopReverse */ 122 {1, 1, BLENDFACTOR_INV_DST_ALPHA, BLENDFACTOR_SRC_ALPHA}, 123 /* Xor */ 124 {1, 1, BLENDFACTOR_INV_DST_ALPHA, BLENDFACTOR_INV_SRC_ALPHA}, 125 /* Add */ 126 {0, 0, BLENDFACTOR_ONE, BLENDFACTOR_ONE}, 127}; 128 129/* The x8* formats could use MT_32BIT_X* on 855+, but since we implement 130 * workarounds for 830/845 anyway, we just rely on those whether the hardware 131 * could handle it for us or not. 132 */ 133static struct formatinfo i830_tex_formats[] = { 134 {PICT_a8r8g8b8, MT_32BIT_ARGB8888 }, 135 {PICT_x8r8g8b8, MT_32BIT_ARGB8888 }, 136 {PICT_a8b8g8r8, MT_32BIT_ABGR8888 }, 137 {PICT_x8b8g8r8, MT_32BIT_ABGR8888 }, 138 {PICT_r5g6b5, MT_16BIT_RGB565 }, 139 {PICT_a1r5g5b5, MT_16BIT_ARGB1555 }, 140 {PICT_x1r5g5b5, MT_16BIT_ARGB1555 }, 141 {PICT_a8, MT_8BIT_A8 }, 142}; 143 144static Bool i830_get_dest_format(PicturePtr pDstPicture, uint32_t *dst_format) 145{ 146 switch (pDstPicture->format) { 147 case PICT_a8r8g8b8: 148 case PICT_x8r8g8b8: 149 *dst_format = COLR_BUF_ARGB8888; 150 break; 151 case PICT_r5g6b5: 152 *dst_format = COLR_BUF_RGB565; 153 break; 154 case PICT_a1r5g5b5: 155 case PICT_x1r5g5b5: 156 *dst_format = COLR_BUF_ARGB1555; 157 break; 158 case PICT_a8: 159 *dst_format = COLR_BUF_8BIT; 160 break; 161 case PICT_a4r4g4b4: 162 case PICT_x4r4g4b4: 163 *dst_format = COLR_BUF_ARGB4444; 164 break; 165 default: 166 { 167 ScrnInfoPtr pScrn; 168 169 pScrn = xf86Screens[pDstPicture->pDrawable->pScreen->myNum]; 170 I830FALLBACK("Unsupported dest format 0x%x\n", 171 (int)pDstPicture->format); 172 } 173 } 174 *dst_format |= DSTORG_HORT_BIAS (0x8) | DSTORG_VERT_BIAS (0x8); 175 return TRUE; 176} 177 178 179static Bool i830_get_blend_cntl(ScrnInfoPtr pScrn, int op, PicturePtr pMask, 180 uint32_t dst_format, uint32_t *blendctl) 181{ 182 uint32_t sblend, dblend; 183 184 sblend = i830_blend_op[op].src_blend; 185 dblend = i830_blend_op[op].dst_blend; 186 187 /* If there's no dst alpha channel, adjust the blend op so that we'll treat 188 * it as always 1. 189 */ 190 if (PICT_FORMAT_A(dst_format) == 0 && i830_blend_op[op].dst_alpha) { 191 if (sblend == BLENDFACTOR_DST_ALPHA) 192 sblend = BLENDFACTOR_ONE; 193 else if (sblend == BLENDFACTOR_INV_DST_ALPHA) 194 sblend = BLENDFACTOR_ZERO; 195 } 196 197 /* For blending purposes, COLR_BUF_8BIT values show up in the green 198 * channel. So we can't use the alpha channel. 199 */ 200 if (dst_format == PICT_a8 && ((sblend == BLENDFACTOR_DST_ALPHA || 201 sblend == BLENDFACTOR_INV_DST_ALPHA))) { 202 I830FALLBACK("Can't do dst alpha blending with PICT_a8 dest.\n"); 203 } 204 205 /* If the source alpha is being used, then we should only be in a case 206 * where the source blend factor is 0, and the source blend value is the 207 * mask channels multiplied by the source picture's alpha. 208 */ 209 if (pMask && pMask->componentAlpha && PICT_FORMAT_RGB(pMask->format) 210 && i830_blend_op[op].src_alpha) { 211 if (dblend == BLENDFACTOR_SRC_ALPHA) { 212 dblend = BLENDFACTOR_SRC_COLR; 213 } else if (dblend == BLENDFACTOR_INV_SRC_ALPHA) { 214 dblend = BLENDFACTOR_INV_SRC_COLR; 215 } 216 } 217 218 *blendctl = (sblend << S8_SRC_BLEND_FACTOR_SHIFT) | 219 (dblend << S8_DST_BLEND_FACTOR_SHIFT); 220 221 return TRUE; 222} 223 224static Bool i830_check_composite_texture(ScrnInfoPtr pScrn, PicturePtr pPict, int unit) 225{ 226 if (pPict->repeatType > RepeatReflect) 227 I830FALLBACK("Unsupported picture repeat %d\n", pPict->repeatType); 228 229 if (pPict->filter != PictFilterNearest && 230 pPict->filter != PictFilterBilinear) 231 { 232 I830FALLBACK("Unsupported filter 0x%x\n", pPict->filter); 233 } 234 235 if (pPict->pDrawable) 236 { 237 int w, h, i; 238 239 w = pPict->pDrawable->width; 240 h = pPict->pDrawable->height; 241 if ((w > 2048) || (h > 2048)) 242 I830FALLBACK("Picture w/h too large (%dx%d)\n", w, h); 243 244 for (i = 0; i < sizeof(i830_tex_formats) / sizeof(i830_tex_formats[0]); 245 i++) 246 { 247 if (i830_tex_formats[i].fmt == pPict->format) 248 break; 249 } 250 if (i == sizeof(i830_tex_formats) / sizeof(i830_tex_formats[0])) 251 I830FALLBACK("Unsupported picture format 0x%x\n", 252 (int)pPict->format); 253 } 254 255 return TRUE; 256} 257 258static uint32_t 259i8xx_get_card_format(PicturePtr pPict) 260{ 261 int i; 262 for (i = 0; i < sizeof(i830_tex_formats) / sizeof(i830_tex_formats[0]); 263 i++) 264 { 265 if (i830_tex_formats[i].fmt == pPict->format) 266 return i830_tex_formats[i].card_fmt; 267 } 268 FatalError("Unsupported format type %d\n", pPict->format); 269} 270 271static void 272i830_texture_setup(PicturePtr pPict, PixmapPtr pPix, int unit) 273{ 274 275 ScrnInfoPtr pScrn = xf86Screens[pPict->pDrawable->pScreen->myNum]; 276 I830Ptr pI830 = I830PTR(pScrn); 277 uint32_t format, pitch, filter; 278 uint32_t wrap_mode; 279 uint32_t texcoordtype; 280 281 pitch = intel_get_pixmap_pitch(pPix); 282 pI830->scale_units[unit][0] = pPix->drawable.width; 283 pI830->scale_units[unit][1] = pPix->drawable.height; 284 pI830->transform[unit] = pPict->transform; 285 286 if (i830_transform_is_affine(pI830->transform[unit])) 287 texcoordtype = TEXCOORDTYPE_CARTESIAN; 288 else 289 texcoordtype = TEXCOORDTYPE_HOMOGENEOUS; 290 291 format = i8xx_get_card_format(pPict); 292 293 switch (pPict->repeatType) { 294 case RepeatNone: 295 wrap_mode = TEXCOORDMODE_CLAMP_BORDER; 296 break; 297 case RepeatNormal: 298 wrap_mode = TEXCOORDMODE_WRAP; 299 break; 300 case RepeatPad: 301 wrap_mode = TEXCOORDMODE_CLAMP; 302 break; 303 case RepeatReflect: 304 wrap_mode = TEXCOORDMODE_MIRROR; 305 break; 306 default: 307 FatalError("Unknown repeat type %d\n", pPict->repeatType); 308 } 309 310 switch (pPict->filter) { 311 case PictFilterNearest: 312 filter = ((FILTER_NEAREST<<TM0S3_MAG_FILTER_SHIFT) | 313 (FILTER_NEAREST<<TM0S3_MIN_FILTER_SHIFT)); 314 break; 315 case PictFilterBilinear: 316 filter = ((FILTER_LINEAR<<TM0S3_MAG_FILTER_SHIFT) | 317 (FILTER_LINEAR<<TM0S3_MIN_FILTER_SHIFT)); 318 break; 319 default: 320 filter = 0; 321 FatalError("Bad filter 0x%x\n", pPict->filter); 322 } 323 filter |= (MIPFILTER_NONE << TM0S3_MIP_FILTER_SHIFT); 324 325 { 326 if (pPix->drawable.bitsPerPixel == 8) 327 format |= MAPSURF_8BIT; 328 else if (pPix->drawable.bitsPerPixel == 16) 329 format |= MAPSURF_16BIT; 330 else 331 format |= MAPSURF_32BIT; 332 333 BEGIN_BATCH(10); 334 OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_2 | LOAD_TEXTURE_MAP(unit) | 4); 335 OUT_RELOC_PIXMAP(pPix, I915_GEM_DOMAIN_SAMPLER, 0, TM0S0_USE_FENCE); 336 OUT_BATCH(((pPix->drawable.height - 1) << TM0S1_HEIGHT_SHIFT) | 337 ((pPix->drawable.width - 1) << TM0S1_WIDTH_SHIFT) | format); 338 OUT_BATCH((pitch/4 - 1) << TM0S2_PITCH_SHIFT | TM0S2_MAP_2D); 339 OUT_BATCH(filter); 340 OUT_BATCH(0); /* default color */ 341 OUT_BATCH(_3DSTATE_MAP_COORD_SET_CMD | TEXCOORD_SET(unit) | 342 ENABLE_TEXCOORD_PARAMS | TEXCOORDS_ARE_NORMAL | 343 texcoordtype | ENABLE_ADDR_V_CNTL | 344 TEXCOORD_ADDR_V_MODE(wrap_mode) | 345 ENABLE_ADDR_U_CNTL | TEXCOORD_ADDR_U_MODE(wrap_mode)); 346 /* map texel stream */ 347 OUT_BATCH(_3DSTATE_MAP_COORD_SETBIND_CMD); 348 if (unit == 0) 349 OUT_BATCH(TEXBIND_SET0(TEXCOORDSRC_VTXSET_0) | 350 TEXBIND_SET1(TEXCOORDSRC_KEEP) | 351 TEXBIND_SET2(TEXCOORDSRC_KEEP) | 352 TEXBIND_SET3(TEXCOORDSRC_KEEP)); 353 else 354 OUT_BATCH(TEXBIND_SET0(TEXCOORDSRC_VTXSET_0) | 355 TEXBIND_SET1(TEXCOORDSRC_VTXSET_1) | 356 TEXBIND_SET2(TEXCOORDSRC_KEEP) | 357 TEXBIND_SET3(TEXCOORDSRC_KEEP)); 358 OUT_BATCH(_3DSTATE_MAP_TEX_STREAM_CMD | (unit << 16) | 359 DISABLE_TEX_STREAM_BUMP | 360 ENABLE_TEX_STREAM_COORD_SET | 361 TEX_STREAM_COORD_SET(unit) | 362 ENABLE_TEX_STREAM_MAP_IDX | 363 TEX_STREAM_MAP_IDX(unit)); 364 ADVANCE_BATCH(); 365 } 366} 367 368Bool 369i830_check_composite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture, 370 PicturePtr pDstPicture) 371{ 372 ScrnInfoPtr pScrn = xf86Screens[pDstPicture->pDrawable->pScreen->myNum]; 373 uint32_t tmp1; 374 375 /* Check for unsupported compositing operations. */ 376 if (op >= sizeof(i830_blend_op) / sizeof(i830_blend_op[0])) 377 I830FALLBACK("Unsupported Composite op 0x%x\n", op); 378 379 if (pMaskPicture != NULL && pMaskPicture->componentAlpha && 380 PICT_FORMAT_RGB(pMaskPicture->format)) { 381 /* Check if it's component alpha that relies on a source alpha and on 382 * the source value. We can only get one of those into the single 383 * source value that we get to blend with. 384 */ 385 if (i830_blend_op[op].src_alpha && 386 (i830_blend_op[op].src_blend != BLENDFACTOR_ZERO)) 387 I830FALLBACK("Component alpha not supported with source " 388 "alpha and source value blending.\n"); 389 } 390 391 if (!i830_check_composite_texture(pScrn, pSrcPicture, 0)) 392 I830FALLBACK("Check Src picture texture\n"); 393 if (pMaskPicture != NULL && !i830_check_composite_texture(pScrn, pMaskPicture, 1)) 394 I830FALLBACK("Check Mask picture texture\n"); 395 396 if (!i830_get_dest_format(pDstPicture, &tmp1)) 397 I830FALLBACK("Get Color buffer format\n"); 398 399 return TRUE; 400} 401 402Bool 403i830_prepare_composite(int op, PicturePtr pSrcPicture, 404 PicturePtr pMaskPicture, PicturePtr pDstPicture, 405 PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst) 406{ 407 ScrnInfoPtr pScrn = xf86Screens[pDstPicture->pDrawable->pScreen->myNum]; 408 I830Ptr pI830 = I830PTR(pScrn); 409 410 pI830->render_src_picture = pSrcPicture; 411 pI830->render_src = pSrc; 412 pI830->render_mask_picture = pMaskPicture; 413 pI830->render_mask = pMask; 414 pI830->render_dst_picture = pDstPicture; 415 pI830->render_dst = pDst; 416 417 i830_exa_check_pitch_3d(pSrc); 418 if (pMask) 419 i830_exa_check_pitch_3d(pMask); 420 i830_exa_check_pitch_3d(pDst); 421 422 if (!i830_get_dest_format(pDstPicture, &pI830->render_dst_format)) 423 return FALSE; 424 425 pI830->dst_coord_adjust = 0; 426 pI830->src_coord_adjust = 0; 427 pI830->mask_coord_adjust = 0; 428 if (pSrcPicture->filter == PictFilterNearest) 429 pI830->src_coord_adjust = 0.375; 430 if (pMask != NULL) { 431 pI830->mask_coord_adjust = 0; 432 if (pMaskPicture->filter == PictFilterNearest) 433 pI830->mask_coord_adjust = 0.375; 434 } else { 435 pI830->transform[1] = NULL; 436 pI830->scale_units[1][0] = -1; 437 pI830->scale_units[1][1] = -1; 438 } 439 440 { 441 uint32_t cblend, ablend, blendctl; 442 443 /* If component alpha is active in the mask and the blend operation 444 * uses the source alpha, then we know we don't need the source 445 * value (otherwise we would have hit a fallback earlier), so we 446 * provide the source alpha (src.A * mask.X) as output color. 447 * Conversely, if CA is set and we don't need the source alpha, then 448 * we produce the source value (src.X * mask.X) and the source alpha 449 * is unused.. Otherwise, we provide the non-CA source value 450 * (src.X * mask.A). 451 * 452 * The PICT_FORMAT_RGB(pict) == 0 fixups are not needed on 855+'s a8 453 * pictures, but we need to implement it for 830/845 and there's no 454 * harm done in leaving it in. 455 */ 456 cblend = TB0C_LAST_STAGE | TB0C_RESULT_SCALE_1X | TB0C_OP_MODULE | 457 TB0C_OUTPUT_WRITE_CURRENT; 458 ablend = TB0A_RESULT_SCALE_1X | TB0A_OP_MODULE | 459 TB0A_OUTPUT_WRITE_CURRENT; 460 461 /* Get the source picture's channels into TBx_ARG1 */ 462 if ((pMaskPicture != NULL && 463 pMaskPicture->componentAlpha && 464 PICT_FORMAT_RGB(pMaskPicture->format) && 465 i830_blend_op[op].src_alpha) || pDstPicture->format == PICT_a8) 466 { 467 /* Producing source alpha value, so the first set of channels 468 * is src.A instead of src.X. We also do this if the destination 469 * is a8, in which case src.G is what's written, and the other 470 * channels are ignored. 471 */ 472 if (PICT_FORMAT_A(pSrcPicture->format) != 0) { 473 ablend |= TB0A_ARG1_SEL_TEXEL0; 474 cblend |= TB0C_ARG1_SEL_TEXEL0 | TB0C_ARG1_REPLICATE_ALPHA; 475 } else { 476 ablend |= TB0A_ARG1_SEL_ONE; 477 cblend |= TB0C_ARG1_SEL_ONE; 478 } 479 } else { 480 if (PICT_FORMAT_A(pSrcPicture->format) != 0) { 481 ablend |= TB0A_ARG1_SEL_TEXEL0; 482 } else { 483 ablend |= TB0A_ARG1_SEL_ONE; 484 } 485 if (PICT_FORMAT_RGB(pSrcPicture->format) != 0) 486 cblend |= TB0C_ARG1_SEL_TEXEL0; 487 else 488 cblend |= TB0C_ARG1_SEL_ONE | TB0C_ARG1_INVERT; /* 0.0 */ 489 } 490 491 if (pMask) { 492 if (pDstPicture->format != PICT_a8 && 493 (pMaskPicture->componentAlpha && 494 PICT_FORMAT_RGB(pMaskPicture->format))) 495 { 496 cblend |= TB0C_ARG2_SEL_TEXEL1; 497 } else { 498 if (PICT_FORMAT_A(pMaskPicture->format) != 0) 499 cblend |= TB0C_ARG2_SEL_TEXEL1 | 500 TB0C_ARG2_REPLICATE_ALPHA; 501 else 502 cblend |= TB0C_ARG2_SEL_ONE; 503 } 504 if (PICT_FORMAT_A(pMaskPicture->format) != 0) 505 ablend |= TB0A_ARG2_SEL_TEXEL1; 506 else 507 ablend |= TB0A_ARG2_SEL_ONE; 508 } else { 509 cblend |= TB0C_ARG2_SEL_ONE; 510 ablend |= TB0A_ARG2_SEL_ONE; 511 } 512 513 if (!i830_get_blend_cntl(pScrn, op, pMaskPicture, pDstPicture->format, 514 &blendctl)) { 515 return FALSE; 516 } 517 518 pI830->cblend = cblend; 519 pI830->ablend = ablend; 520 pI830->s8_blendctl = blendctl; 521 } 522 523 i830_debug_sync(pScrn); 524 525 pI830->needs_render_state_emit = TRUE; 526 527 return TRUE; 528} 529 530static void 531i830_emit_composite_state(ScrnInfoPtr pScrn) 532{ 533 I830Ptr pI830 = I830PTR(pScrn); 534 uint32_t vf2; 535 uint32_t texcoordfmt = 0; 536 537 pI830->needs_render_state_emit = FALSE; 538 539 IntelEmitInvarientState(pScrn); 540 pI830->last_3d = LAST_3D_RENDER; 541 542 BEGIN_BATCH(21); 543 544 OUT_BATCH(_3DSTATE_BUF_INFO_CMD); 545 OUT_BATCH(BUF_3D_ID_COLOR_BACK| BUF_3D_USE_FENCE | 546 BUF_3D_PITCH(intel_get_pixmap_pitch(pI830->render_dst))); 547 OUT_RELOC_PIXMAP(pI830->render_dst, 548 I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0); 549 550 OUT_BATCH(_3DSTATE_DST_BUF_VARS_CMD); 551 OUT_BATCH(pI830->render_dst_format); 552 553 OUT_BATCH(_3DSTATE_DRAW_RECT_CMD); 554 OUT_BATCH(0); 555 OUT_BATCH(0); /* ymin, xmin */ 556 OUT_BATCH(DRAW_YMAX(pI830->render_dst->drawable.height - 1) | 557 DRAW_XMAX(pI830->render_dst->drawable.width - 1)); 558 OUT_BATCH(0); /* yorig, xorig */ 559 560 OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | 561 I1_LOAD_S(2) | 562 I1_LOAD_S(3) | 563 I1_LOAD_S(8) | 564 2); 565 if (pI830->render_mask) 566 vf2 = 2 << 12; /* 2 texture coord sets */ 567 else 568 vf2 = 1 << 12; 569 OUT_BATCH(vf2); /* number of coordinate sets */ 570 OUT_BATCH(S3_CULLMODE_NONE | S3_VERTEXHAS_XY); 571 OUT_BATCH(S8_ENABLE_COLOR_BLEND | S8_BLENDFUNC_ADD | pI830->s8_blendctl | 572 S8_ENABLE_COLOR_BUFFER_WRITE); 573 574 OUT_BATCH(_3DSTATE_INDPT_ALPHA_BLEND_CMD | DISABLE_INDPT_ALPHA_BLEND); 575 576 OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_2 | 577 LOAD_TEXTURE_BLEND_STAGE(0)|1); 578 OUT_BATCH(pI830->cblend); 579 OUT_BATCH(pI830->ablend); 580 581 OUT_BATCH(_3DSTATE_ENABLES_1_CMD | DISABLE_LOGIC_OP | 582 DISABLE_STENCIL_TEST | DISABLE_DEPTH_BIAS | 583 DISABLE_SPEC_ADD | DISABLE_FOG | DISABLE_ALPHA_TEST | 584 ENABLE_COLOR_BLEND | DISABLE_DEPTH_TEST); 585 /* We have to explicitly say we don't want write disabled */ 586 OUT_BATCH(_3DSTATE_ENABLES_2_CMD | ENABLE_COLOR_MASK | 587 DISABLE_STENCIL_WRITE | ENABLE_TEX_CACHE | 588 DISABLE_DITHER | ENABLE_COLOR_WRITE | 589 DISABLE_DEPTH_WRITE); 590 591 if (i830_transform_is_affine(pI830->render_src_picture->transform)) 592 texcoordfmt |= (TEXCOORDFMT_2D << 0); 593 else 594 texcoordfmt |= (TEXCOORDFMT_3D << 0); 595 if (pI830->render_mask) { 596 if (i830_transform_is_affine(pI830->render_mask_picture->transform)) 597 texcoordfmt |= (TEXCOORDFMT_2D << 2); 598 else 599 texcoordfmt |= (TEXCOORDFMT_3D << 2); 600 } 601 OUT_BATCH(_3DSTATE_VERTEX_FORMAT_2_CMD | texcoordfmt); 602 603 ADVANCE_BATCH(); 604 605 i830_texture_setup(pI830->render_src_picture, pI830->render_src, 0); 606 if (pI830->render_mask) { 607 i830_texture_setup(pI830->render_mask_picture, 608 pI830->render_mask, 1); 609 } 610} 611 612/* Emit the vertices for a single composite rectangle. 613 * 614 * This function is no longer shared between i830 and i915 generation code. 615 */ 616static void 617i830_emit_composite_primitive(PixmapPtr pDst, 618 int srcX, int srcY, 619 int maskX, int maskY, 620 int dstX, int dstY, 621 int w, int h) 622{ 623 ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum]; 624 I830Ptr pI830 = I830PTR(pScrn); 625 Bool is_affine_src, is_affine_mask = TRUE; 626 int per_vertex, num_floats; 627 float src_x[3], src_y[3], src_w[3], mask_x[3], mask_y[3], mask_w[3]; 628 629 per_vertex = 2; /* dest x/y */ 630 631 { 632 float x = srcX + pI830->src_coord_adjust; 633 float y = srcY + pI830->src_coord_adjust; 634 635 is_affine_src = i830_transform_is_affine (pI830->transform[0]); 636 if (is_affine_src) { 637 if (!i830_get_transformed_coordinates(x, y, 638 pI830->transform[0], 639 &src_x[0], &src_y[0])) 640 return; 641 642 if (!i830_get_transformed_coordinates(x, y + h, 643 pI830->transform[0], 644 &src_x[1], &src_y[1])) 645 return; 646 647 if (!i830_get_transformed_coordinates(x + w, y + h, 648 pI830->transform[0], 649 &src_x[2], &src_y[2])) 650 return; 651 652 per_vertex += 2; /* src x/y */ 653 } else { 654 if (!i830_get_transformed_coordinates_3d(x, y, 655 pI830->transform[0], 656 &src_x[0], 657 &src_y[0], 658 &src_w[0])) 659 return; 660 661 if (!i830_get_transformed_coordinates_3d(x, y + h, 662 pI830->transform[0], 663 &src_x[1], 664 &src_y[1], 665 &src_w[1])) 666 return; 667 668 if (!i830_get_transformed_coordinates_3d(x + w, y + h, 669 pI830->transform[0], 670 &src_x[2], 671 &src_y[2], 672 &src_w[2])) 673 return; 674 675 per_vertex += 3; /* src x/y/w */ 676 } 677 } 678 679 if (pI830->render_mask) { 680 float x = maskX + pI830->mask_coord_adjust; 681 float y = maskY + pI830->mask_coord_adjust; 682 683 is_affine_mask = i830_transform_is_affine (pI830->transform[1]); 684 if (is_affine_mask) { 685 if (!i830_get_transformed_coordinates(x, y, 686 pI830->transform[1], 687 &mask_x[0], &mask_y[0])) 688 return; 689 690 if (!i830_get_transformed_coordinates(x, y + h, 691 pI830->transform[1], 692 &mask_x[1], &mask_y[1])) 693 return; 694 695 if (!i830_get_transformed_coordinates(x + w, y + h, 696 pI830->transform[1], 697 &mask_x[2], &mask_y[2])) 698 return; 699 700 per_vertex += 2; /* mask x/y */ 701 } else { 702 if (!i830_get_transformed_coordinates_3d(x, y, 703 pI830->transform[1], 704 &mask_x[0], 705 &mask_y[0], 706 &mask_w[0])) 707 return; 708 709 if (!i830_get_transformed_coordinates_3d(x, y + h, 710 pI830->transform[1], 711 &mask_x[1], 712 &mask_y[1], 713 &mask_w[1])) 714 return; 715 716 if (!i830_get_transformed_coordinates_3d(x + w, y + h, 717 pI830->transform[1], 718 &mask_x[2], 719 &mask_y[2], 720 &mask_w[2])) 721 return; 722 723 per_vertex += 3; /* mask x/y/w */ 724 } 725 } 726 727 num_floats = 3 * per_vertex; 728 729 BEGIN_BATCH(1 + num_floats); 730 731 OUT_BATCH(PRIM3D_INLINE | PRIM3D_RECTLIST | (num_floats-1)); 732 OUT_BATCH_F(pI830->dst_coord_adjust + dstX + w); 733 OUT_BATCH_F(pI830->dst_coord_adjust + dstY + h); 734 OUT_BATCH_F(src_x[2] / pI830->scale_units[0][0]); 735 OUT_BATCH_F(src_y[2] / pI830->scale_units[0][1]); 736 if (!is_affine_src) { 737 OUT_BATCH_F(src_w[2]); 738 } 739 if (pI830->render_mask) { 740 OUT_BATCH_F(mask_x[2] / pI830->scale_units[1][0]); 741 OUT_BATCH_F(mask_y[2] / pI830->scale_units[1][1]); 742 if (!is_affine_mask) { 743 OUT_BATCH_F(mask_w[2]); 744 } 745 } 746 747 OUT_BATCH_F(pI830->dst_coord_adjust + dstX); 748 OUT_BATCH_F(pI830->dst_coord_adjust + dstY + h); 749 OUT_BATCH_F(src_x[1] / pI830->scale_units[0][0]); 750 OUT_BATCH_F(src_y[1] / pI830->scale_units[0][1]); 751 if (!is_affine_src) { 752 OUT_BATCH_F(src_w[1]); 753 } 754 if (pI830->render_mask) { 755 OUT_BATCH_F(mask_x[1] / pI830->scale_units[1][0]); 756 OUT_BATCH_F(mask_y[1] / pI830->scale_units[1][1]); 757 if (!is_affine_mask) { 758 OUT_BATCH_F(mask_w[1]); 759 } 760 } 761 762 OUT_BATCH_F(pI830->dst_coord_adjust + dstX); 763 OUT_BATCH_F(pI830->dst_coord_adjust + dstY); 764 OUT_BATCH_F(src_x[0] / pI830->scale_units[0][0]); 765 OUT_BATCH_F(src_y[0] / pI830->scale_units[0][1]); 766 if (!is_affine_src) { 767 OUT_BATCH_F(src_w[0]); 768 } 769 if (pI830->render_mask) { 770 OUT_BATCH_F(mask_x[0] / pI830->scale_units[1][0]); 771 OUT_BATCH_F(mask_y[0] / pI830->scale_units[1][1]); 772 if (!is_affine_mask) { 773 OUT_BATCH_F(mask_w[0]); 774 } 775 } 776 777 ADVANCE_BATCH(); 778} 779 780 781/** 782 * Do a single rectangle composite operation. 783 */ 784void 785i830_composite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY, 786 int dstX, int dstY, int w, int h) 787{ 788 ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum]; 789 I830Ptr pI830 = I830PTR(pScrn); 790 791 intel_batch_start_atomic(pScrn, 792 58 + /* invarient */ 793 22 + /* setup */ 794 20 + /* 2 * setup_texture */ 795 1 + 30 /* verts */); 796 797 if (pI830->needs_render_state_emit) 798 i830_emit_composite_state(pScrn); 799 800 i830_emit_composite_primitive(pDst, srcX, srcY, maskX, maskY, dstX, dstY, 801 w, h); 802 803 intel_batch_end_atomic(pScrn); 804 805 i830_debug_sync(pScrn); 806} 807 808void 809i830_batch_flush_notify(ScrnInfoPtr scrn) 810{ 811 I830Ptr i830 = I830PTR(scrn); 812 813 i830->needs_render_state_emit = TRUE; 814} 815