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