1428d7b3dSmrg/* 2428d7b3dSmrg * Copyright © 2006 Intel Corporation 3428d7b3dSmrg * 4428d7b3dSmrg * Permission is hereby granted, free of charge, to any person obtaining a 5428d7b3dSmrg * copy of this software and associated documentation files (the "Software"), 6428d7b3dSmrg * to deal in the Software without restriction, including without limitation 7428d7b3dSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8428d7b3dSmrg * and/or sell copies of the Software, and to permit persons to whom the 9428d7b3dSmrg * Software is furnished to do so, subject to the following conditions: 10428d7b3dSmrg * 11428d7b3dSmrg * The above copyright notice and this permission notice (including the next 12428d7b3dSmrg * paragraph) shall be included in all copies or substantial portions of the 13428d7b3dSmrg * Software. 14428d7b3dSmrg * 15428d7b3dSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16428d7b3dSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17428d7b3dSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18428d7b3dSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19428d7b3dSmrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20428d7b3dSmrg * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21428d7b3dSmrg * SOFTWARE. 22428d7b3dSmrg * 23428d7b3dSmrg * Authors: 24428d7b3dSmrg * Wang Zhenyu <zhenyu.z.wang@intel.com> 25428d7b3dSmrg * Eric Anholt <eric@anholt.net> 26428d7b3dSmrg * 27428d7b3dSmrg */ 28428d7b3dSmrg 29428d7b3dSmrg#ifdef HAVE_CONFIG_H 30428d7b3dSmrg#include "config.h" 31428d7b3dSmrg#endif 32428d7b3dSmrg 33428d7b3dSmrg#include "xorg-server.h" 34428d7b3dSmrg#include "xf86.h" 35428d7b3dSmrg#include "intel.h" 36428d7b3dSmrg#include "intel_uxa.h" 37428d7b3dSmrg#include "i830_reg.h" 38428d7b3dSmrg 39428d7b3dSmrgstruct blendinfo { 40428d7b3dSmrg Bool dst_alpha; 41428d7b3dSmrg Bool src_alpha; 42428d7b3dSmrg uint32_t src_blend; 43428d7b3dSmrg uint32_t dst_blend; 44428d7b3dSmrg}; 45428d7b3dSmrg 46428d7b3dSmrgstruct formatinfo { 47428d7b3dSmrg int fmt; 48428d7b3dSmrg uint32_t card_fmt; 49428d7b3dSmrg}; 50428d7b3dSmrg 51428d7b3dSmrg#define TB0C_LAST_STAGE (1 << 31) 52428d7b3dSmrg#define TB0C_RESULT_SCALE_1X (0 << 29) 53428d7b3dSmrg#define TB0C_RESULT_SCALE_2X (1 << 29) 54428d7b3dSmrg#define TB0C_RESULT_SCALE_4X (2 << 29) 55428d7b3dSmrg#define TB0C_OP_MODULE (3 << 25) 56428d7b3dSmrg#define TB0C_OUTPUT_WRITE_CURRENT (0 << 24) 57428d7b3dSmrg#define TB0C_OUTPUT_WRITE_ACCUM (1 << 24) 58428d7b3dSmrg#define TB0C_ARG3_REPLICATE_ALPHA (1<<23) 59428d7b3dSmrg#define TB0C_ARG3_INVERT (1<<22) 60428d7b3dSmrg#define TB0C_ARG3_SEL_XXX 61428d7b3dSmrg#define TB0C_ARG2_REPLICATE_ALPHA (1<<17) 62428d7b3dSmrg#define TB0C_ARG2_INVERT (1<<16) 63428d7b3dSmrg#define TB0C_ARG2_SEL_ONE (0 << 12) 64428d7b3dSmrg#define TB0C_ARG2_SEL_FACTOR (1 << 12) 65428d7b3dSmrg#define TB0C_ARG2_SEL_TEXEL0 (6 << 12) 66428d7b3dSmrg#define TB0C_ARG2_SEL_TEXEL1 (7 << 12) 67428d7b3dSmrg#define TB0C_ARG2_SEL_TEXEL2 (8 << 12) 68428d7b3dSmrg#define TB0C_ARG2_SEL_TEXEL3 (9 << 12) 69428d7b3dSmrg#define TB0C_ARG1_REPLICATE_ALPHA (1<<11) 70428d7b3dSmrg#define TB0C_ARG1_INVERT (1<<10) 71428d7b3dSmrg#define TB0C_ARG1_SEL_ONE (0 << 6) 72428d7b3dSmrg#define TB0C_ARG1_SEL_TEXEL0 (6 << 6) 73428d7b3dSmrg#define TB0C_ARG1_SEL_TEXEL1 (7 << 6) 74428d7b3dSmrg#define TB0C_ARG1_SEL_TEXEL2 (8 << 6) 75428d7b3dSmrg#define TB0C_ARG1_SEL_TEXEL3 (9 << 6) 76428d7b3dSmrg#define TB0C_ARG0_REPLICATE_ALPHA (1<<5) 77428d7b3dSmrg#define TB0C_ARG0_SEL_XXX 78428d7b3dSmrg 79428d7b3dSmrg#define TB0A_CTR_STAGE_ENABLE (1<<31) 80428d7b3dSmrg#define TB0A_RESULT_SCALE_1X (0 << 29) 81428d7b3dSmrg#define TB0A_RESULT_SCALE_2X (1 << 29) 82428d7b3dSmrg#define TB0A_RESULT_SCALE_4X (2 << 29) 83428d7b3dSmrg#define TB0A_OP_MODULE (3 << 25) 84428d7b3dSmrg#define TB0A_OUTPUT_WRITE_CURRENT (0<<24) 85428d7b3dSmrg#define TB0A_OUTPUT_WRITE_ACCUM (1<<24) 86428d7b3dSmrg#define TB0A_CTR_STAGE_SEL_BITS_XXX 87428d7b3dSmrg#define TB0A_ARG3_SEL_XXX 88428d7b3dSmrg#define TB0A_ARG3_INVERT (1<<17) 89428d7b3dSmrg#define TB0A_ARG2_INVERT (1<<16) 90428d7b3dSmrg#define TB0A_ARG2_SEL_ONE (0 << 12) 91428d7b3dSmrg#define TB0A_ARG2_SEL_TEXEL0 (6 << 12) 92428d7b3dSmrg#define TB0A_ARG2_SEL_TEXEL1 (7 << 12) 93428d7b3dSmrg#define TB0A_ARG2_SEL_TEXEL2 (8 << 12) 94428d7b3dSmrg#define TB0A_ARG2_SEL_TEXEL3 (9 << 12) 95428d7b3dSmrg#define TB0A_ARG1_INVERT (1<<10) 96428d7b3dSmrg#define TB0A_ARG1_SEL_ONE (0 << 6) 97428d7b3dSmrg#define TB0A_ARG1_SEL_TEXEL0 (6 << 6) 98428d7b3dSmrg#define TB0A_ARG1_SEL_TEXEL1 (7 << 6) 99428d7b3dSmrg#define TB0A_ARG1_SEL_TEXEL2 (8 << 6) 100428d7b3dSmrg#define TB0A_ARG1_SEL_TEXEL3 (9 << 6) 101428d7b3dSmrg 102428d7b3dSmrgstatic struct blendinfo i830_blend_op[] = { 103428d7b3dSmrg /* Clear */ 104428d7b3dSmrg {0, 0, BLENDFACTOR_ZERO, BLENDFACTOR_ZERO}, 105428d7b3dSmrg /* Src */ 106428d7b3dSmrg {0, 0, BLENDFACTOR_ONE, BLENDFACTOR_ZERO}, 107428d7b3dSmrg /* Dst */ 108428d7b3dSmrg {0, 0, BLENDFACTOR_ZERO, BLENDFACTOR_ONE}, 109428d7b3dSmrg /* Over */ 110428d7b3dSmrg {0, 1, BLENDFACTOR_ONE, BLENDFACTOR_INV_SRC_ALPHA}, 111428d7b3dSmrg /* OverReverse */ 112428d7b3dSmrg {1, 0, BLENDFACTOR_INV_DST_ALPHA, BLENDFACTOR_ONE}, 113428d7b3dSmrg /* In */ 114428d7b3dSmrg {1, 0, BLENDFACTOR_DST_ALPHA, BLENDFACTOR_ZERO}, 115428d7b3dSmrg /* InReverse */ 116428d7b3dSmrg {0, 1, BLENDFACTOR_ZERO, BLENDFACTOR_SRC_ALPHA}, 117428d7b3dSmrg /* Out */ 118428d7b3dSmrg {1, 0, BLENDFACTOR_INV_DST_ALPHA, BLENDFACTOR_ZERO}, 119428d7b3dSmrg /* OutReverse */ 120428d7b3dSmrg {0, 1, BLENDFACTOR_ZERO, BLENDFACTOR_INV_SRC_ALPHA}, 121428d7b3dSmrg /* Atop */ 122428d7b3dSmrg {1, 1, BLENDFACTOR_DST_ALPHA, BLENDFACTOR_INV_SRC_ALPHA}, 123428d7b3dSmrg /* AtopReverse */ 124428d7b3dSmrg {1, 1, BLENDFACTOR_INV_DST_ALPHA, BLENDFACTOR_SRC_ALPHA}, 125428d7b3dSmrg /* Xor */ 126428d7b3dSmrg {1, 1, BLENDFACTOR_INV_DST_ALPHA, BLENDFACTOR_INV_SRC_ALPHA}, 127428d7b3dSmrg /* Add */ 128428d7b3dSmrg {0, 0, BLENDFACTOR_ONE, BLENDFACTOR_ONE}, 129428d7b3dSmrg}; 130428d7b3dSmrg 131428d7b3dSmrgstatic struct formatinfo i830_tex_formats[] = { 132428d7b3dSmrg {PICT_a8, MAPSURF_8BIT | MT_8BIT_A8}, 133428d7b3dSmrg {PICT_a8r8g8b8, MAPSURF_32BIT | MT_32BIT_ARGB8888}, 134428d7b3dSmrg {PICT_a8b8g8r8, MAPSURF_32BIT | MT_32BIT_ABGR8888}, 135428d7b3dSmrg {PICT_r5g6b5, MAPSURF_16BIT | MT_16BIT_RGB565}, 136428d7b3dSmrg {PICT_a1r5g5b5, MAPSURF_16BIT | MT_16BIT_ARGB1555}, 137428d7b3dSmrg {PICT_a4r4g4b4, MAPSURF_16BIT | MT_16BIT_ARGB4444}, 138428d7b3dSmrg}; 139428d7b3dSmrg 140428d7b3dSmrgstatic struct formatinfo i855_tex_formats[] = { 141428d7b3dSmrg {PICT_x8r8g8b8, MAPSURF_32BIT | MT_32BIT_XRGB8888}, 142428d7b3dSmrg {PICT_x8b8g8r8, MAPSURF_32BIT | MT_32BIT_XBGR8888}, 143428d7b3dSmrg}; 144428d7b3dSmrg 145428d7b3dSmrgstatic Bool i830_get_dest_format(PicturePtr dest_picture, uint32_t * dst_format) 146428d7b3dSmrg{ 147428d7b3dSmrg ScrnInfoPtr scrn; 148428d7b3dSmrg 149428d7b3dSmrg switch (dest_picture->format) { 150428d7b3dSmrg case PICT_a8r8g8b8: 151428d7b3dSmrg case PICT_x8r8g8b8: 152428d7b3dSmrg *dst_format = COLR_BUF_ARGB8888; 153428d7b3dSmrg break; 154428d7b3dSmrg case PICT_r5g6b5: 155428d7b3dSmrg *dst_format = COLR_BUF_RGB565; 156428d7b3dSmrg break; 157428d7b3dSmrg case PICT_a1r5g5b5: 158428d7b3dSmrg case PICT_x1r5g5b5: 159428d7b3dSmrg *dst_format = COLR_BUF_ARGB1555; 160428d7b3dSmrg break; 161428d7b3dSmrg case PICT_a8: 162428d7b3dSmrg *dst_format = COLR_BUF_8BIT; 163428d7b3dSmrg break; 164428d7b3dSmrg case PICT_a4r4g4b4: 165428d7b3dSmrg case PICT_x4r4g4b4: 166428d7b3dSmrg *dst_format = COLR_BUF_ARGB4444; 167428d7b3dSmrg break; 168428d7b3dSmrg default: 169428d7b3dSmrg scrn = xf86ScreenToScrn(dest_picture->pDrawable->pScreen); 170428d7b3dSmrg intel_uxa_debug_fallback(scrn, "Unsupported dest format 0x%x\n", 171428d7b3dSmrg (int)dest_picture->format); 172428d7b3dSmrg return FALSE; 173428d7b3dSmrg } 174428d7b3dSmrg *dst_format |= DSTORG_HORT_BIAS(0x8) | DSTORG_VERT_BIAS(0x8); 175428d7b3dSmrg return TRUE; 176428d7b3dSmrg} 177428d7b3dSmrg 178428d7b3dSmrgstatic Bool i830_get_blend_cntl(ScrnInfoPtr scrn, int op, PicturePtr mask, 179428d7b3dSmrg uint32_t dst_format, uint32_t * blendctl) 180428d7b3dSmrg{ 181428d7b3dSmrg uint32_t sblend, dblend; 182428d7b3dSmrg 183428d7b3dSmrg sblend = i830_blend_op[op].src_blend; 184428d7b3dSmrg dblend = i830_blend_op[op].dst_blend; 185428d7b3dSmrg 186428d7b3dSmrg /* If there's no dst alpha channel, adjust the blend op so that we'll treat 187428d7b3dSmrg * it as always 1. 188428d7b3dSmrg */ 189428d7b3dSmrg if (PICT_FORMAT_A(dst_format) == 0 && i830_blend_op[op].dst_alpha) { 190428d7b3dSmrg if (sblend == BLENDFACTOR_DST_ALPHA) 191428d7b3dSmrg sblend = BLENDFACTOR_ONE; 192428d7b3dSmrg else if (sblend == BLENDFACTOR_INV_DST_ALPHA) 193428d7b3dSmrg sblend = BLENDFACTOR_ZERO; 194428d7b3dSmrg } 195428d7b3dSmrg 196428d7b3dSmrg /* For blending purposes, COLR_BUF_8BIT values show up in the green 197428d7b3dSmrg * channel. So we can't use the alpha channel. 198428d7b3dSmrg */ 199428d7b3dSmrg if (dst_format == PICT_a8 && ((sblend == BLENDFACTOR_DST_ALPHA || 200428d7b3dSmrg sblend == BLENDFACTOR_INV_DST_ALPHA))) { 201428d7b3dSmrg intel_uxa_debug_fallback(scrn, "Can't do dst alpha blending with " 202428d7b3dSmrg "PICT_a8 dest.\n"); 203428d7b3dSmrg return FALSE; 204428d7b3dSmrg } 205428d7b3dSmrg 206428d7b3dSmrg /* If the source alpha is being used, then we should only be in a case 207428d7b3dSmrg * where the source blend factor is 0, and the source blend value is the 208428d7b3dSmrg * mask channels multiplied by the source picture's alpha. 209428d7b3dSmrg */ 210428d7b3dSmrg if (mask && mask->componentAlpha && PICT_FORMAT_RGB(mask->format) 211428d7b3dSmrg && i830_blend_op[op].src_alpha) { 212428d7b3dSmrg if (dblend == BLENDFACTOR_SRC_ALPHA) { 213428d7b3dSmrg dblend = BLENDFACTOR_SRC_COLR; 214428d7b3dSmrg } else if (dblend == BLENDFACTOR_INV_SRC_ALPHA) { 215428d7b3dSmrg dblend = BLENDFACTOR_INV_SRC_COLR; 216428d7b3dSmrg } 217428d7b3dSmrg } 218428d7b3dSmrg 219428d7b3dSmrg *blendctl = (sblend << S8_SRC_BLEND_FACTOR_SHIFT) | 220428d7b3dSmrg (dblend << S8_DST_BLEND_FACTOR_SHIFT); 221428d7b3dSmrg 222428d7b3dSmrg return TRUE; 223428d7b3dSmrg} 224428d7b3dSmrg 225428d7b3dSmrgstatic uint32_t i8xx_get_card_format(intel_screen_private *intel, 226428d7b3dSmrg PicturePtr picture) 227428d7b3dSmrg{ 228428d7b3dSmrg int i; 229428d7b3dSmrg 230428d7b3dSmrg for (i = 0; i < sizeof(i830_tex_formats) / sizeof(i830_tex_formats[0]); 231428d7b3dSmrg i++) { 232428d7b3dSmrg if (i830_tex_formats[i].fmt == picture->format) 233428d7b3dSmrg return i830_tex_formats[i].card_fmt; 234428d7b3dSmrg } 235428d7b3dSmrg 236428d7b3dSmrg if (!(IS_I830(intel) || IS_845G(intel))) { 237428d7b3dSmrg for (i = 0; i < sizeof(i855_tex_formats) / sizeof(i855_tex_formats[0]); 238428d7b3dSmrg i++) { 239428d7b3dSmrg if (i855_tex_formats[i].fmt == picture->format) 240428d7b3dSmrg return i855_tex_formats[i].card_fmt; 241428d7b3dSmrg } 242428d7b3dSmrg } 243428d7b3dSmrg 244428d7b3dSmrg return 0; 245428d7b3dSmrg} 246428d7b3dSmrg 247428d7b3dSmrgstatic void i830_texture_setup(PicturePtr picture, PixmapPtr pixmap, int unit) 248428d7b3dSmrg{ 249428d7b3dSmrg 250428d7b3dSmrg ScrnInfoPtr scrn = xf86ScreenToScrn(picture->pDrawable->pScreen); 251428d7b3dSmrg intel_screen_private *intel = intel_get_screen_private(scrn); 252428d7b3dSmrg uint32_t format, tiling_bits, pitch, filter; 253428d7b3dSmrg uint32_t wrap_mode; 254428d7b3dSmrg uint32_t texcoordtype; 255428d7b3dSmrg 256428d7b3dSmrg pitch = intel_pixmap_pitch(pixmap); 257428d7b3dSmrg intel->scale_units[unit][0] = pixmap->drawable.width; 258428d7b3dSmrg intel->scale_units[unit][1] = pixmap->drawable.height; 259428d7b3dSmrg intel->transform[unit] = picture->transform; 260428d7b3dSmrg 261428d7b3dSmrg if (intel_uxa_transform_is_affine(intel->transform[unit])) 262428d7b3dSmrg texcoordtype = TEXCOORDTYPE_CARTESIAN; 263428d7b3dSmrg else 264428d7b3dSmrg texcoordtype = TEXCOORDTYPE_HOMOGENEOUS; 265428d7b3dSmrg 266428d7b3dSmrg switch (picture->repeatType) { 267428d7b3dSmrg case RepeatNone: 268428d7b3dSmrg wrap_mode = TEXCOORDMODE_CLAMP_BORDER; 269428d7b3dSmrg break; 270428d7b3dSmrg case RepeatNormal: 271428d7b3dSmrg wrap_mode = TEXCOORDMODE_WRAP; 272428d7b3dSmrg break; 273428d7b3dSmrg case RepeatPad: 274428d7b3dSmrg wrap_mode = TEXCOORDMODE_CLAMP; 275428d7b3dSmrg break; 276428d7b3dSmrg case RepeatReflect: 277428d7b3dSmrg wrap_mode = TEXCOORDMODE_MIRROR; 278428d7b3dSmrg break; 279428d7b3dSmrg default: 280428d7b3dSmrg FatalError("Unknown repeat type %d\n", picture->repeatType); 281428d7b3dSmrg } 282428d7b3dSmrg 283428d7b3dSmrg switch (picture->filter) { 284428d7b3dSmrg case PictFilterNearest: 285428d7b3dSmrg filter = ((FILTER_NEAREST << TM0S3_MAG_FILTER_SHIFT) | 286428d7b3dSmrg (FILTER_NEAREST << TM0S3_MIN_FILTER_SHIFT)); 287428d7b3dSmrg break; 288428d7b3dSmrg case PictFilterBilinear: 289428d7b3dSmrg filter = ((FILTER_LINEAR << TM0S3_MAG_FILTER_SHIFT) | 290428d7b3dSmrg (FILTER_LINEAR << TM0S3_MIN_FILTER_SHIFT)); 291428d7b3dSmrg break; 292428d7b3dSmrg default: 293428d7b3dSmrg FatalError("Bad filter 0x%x\n", picture->filter); 294428d7b3dSmrg } 295428d7b3dSmrg filter |= (MIPFILTER_NONE << TM0S3_MIP_FILTER_SHIFT); 296428d7b3dSmrg 297428d7b3dSmrg if (intel_uxa_pixmap_tiled(pixmap)) { 298428d7b3dSmrg tiling_bits = TM0S1_TILED_SURFACE; 299428d7b3dSmrg if (intel_uxa_get_pixmap_private(pixmap)->tiling 300428d7b3dSmrg == I915_TILING_Y) 301428d7b3dSmrg tiling_bits |= TM0S1_TILE_WALK; 302428d7b3dSmrg } else 303428d7b3dSmrg tiling_bits = 0; 304428d7b3dSmrg 305428d7b3dSmrg format = i8xx_get_card_format(intel, picture); 306428d7b3dSmrg 307428d7b3dSmrg assert(intel->in_batch_atomic); 308428d7b3dSmrg 309428d7b3dSmrg OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_2 | 310428d7b3dSmrg LOAD_TEXTURE_MAP(unit) | 4); 311428d7b3dSmrg OUT_RELOC_PIXMAP(pixmap, I915_GEM_DOMAIN_SAMPLER, 0, 0); 312428d7b3dSmrg OUT_BATCH(((pixmap->drawable.height - 313428d7b3dSmrg 1) << TM0S1_HEIGHT_SHIFT) | ((pixmap->drawable.width - 314428d7b3dSmrg 1) << 315428d7b3dSmrg TM0S1_WIDTH_SHIFT) | 316428d7b3dSmrg format | tiling_bits); 317428d7b3dSmrg OUT_BATCH((pitch / 4 - 1) << TM0S2_PITCH_SHIFT | TM0S2_MAP_2D); 318428d7b3dSmrg OUT_BATCH(filter); 319428d7b3dSmrg OUT_BATCH(0); /* default color */ 320428d7b3dSmrg OUT_BATCH(_3DSTATE_MAP_COORD_SET_CMD | TEXCOORD_SET(unit) | 321428d7b3dSmrg ENABLE_TEXCOORD_PARAMS | TEXCOORDS_ARE_NORMAL | 322428d7b3dSmrg texcoordtype | ENABLE_ADDR_V_CNTL | 323428d7b3dSmrg TEXCOORD_ADDR_V_MODE(wrap_mode) | 324428d7b3dSmrg ENABLE_ADDR_U_CNTL | TEXCOORD_ADDR_U_MODE(wrap_mode)); 325428d7b3dSmrg /* map texel stream */ 326428d7b3dSmrg OUT_BATCH(_3DSTATE_MAP_COORD_SETBIND_CMD); 327428d7b3dSmrg if (unit == 0) 328428d7b3dSmrg OUT_BATCH(TEXBIND_SET0(TEXCOORDSRC_VTXSET_0) | 329428d7b3dSmrg TEXBIND_SET1(TEXCOORDSRC_KEEP) | 330428d7b3dSmrg TEXBIND_SET2(TEXCOORDSRC_KEEP) | 331428d7b3dSmrg TEXBIND_SET3(TEXCOORDSRC_KEEP)); 332428d7b3dSmrg else 333428d7b3dSmrg OUT_BATCH(TEXBIND_SET0(TEXCOORDSRC_VTXSET_0) | 334428d7b3dSmrg TEXBIND_SET1(TEXCOORDSRC_VTXSET_1) | 335428d7b3dSmrg TEXBIND_SET2(TEXCOORDSRC_KEEP) | 336428d7b3dSmrg TEXBIND_SET3(TEXCOORDSRC_KEEP)); 337428d7b3dSmrg OUT_BATCH(_3DSTATE_MAP_TEX_STREAM_CMD | (unit << 16) | 338428d7b3dSmrg DISABLE_TEX_STREAM_BUMP | 339428d7b3dSmrg ENABLE_TEX_STREAM_COORD_SET | 340428d7b3dSmrg TEX_STREAM_COORD_SET(unit) | 341428d7b3dSmrg ENABLE_TEX_STREAM_MAP_IDX | TEX_STREAM_MAP_IDX(unit)); 342428d7b3dSmrg} 343428d7b3dSmrg 344428d7b3dSmrgBool 345428d7b3dSmrgi830_check_composite(int op, 346428d7b3dSmrg PicturePtr source_picture, 347428d7b3dSmrg PicturePtr mask_picture, 348428d7b3dSmrg PicturePtr dest_picture, 349428d7b3dSmrg int width, int height) 350428d7b3dSmrg{ 351428d7b3dSmrg ScrnInfoPtr scrn = xf86ScreenToScrn(dest_picture->pDrawable->pScreen); 352428d7b3dSmrg uint32_t tmp1; 353428d7b3dSmrg 354428d7b3dSmrg /* Check for unsupported compositing operations. */ 355428d7b3dSmrg if (op >= sizeof(i830_blend_op) / sizeof(i830_blend_op[0])) { 356428d7b3dSmrg intel_uxa_debug_fallback(scrn, "Unsupported Composite op 0x%x\n", 357428d7b3dSmrg op); 358428d7b3dSmrg return FALSE; 359428d7b3dSmrg } 360428d7b3dSmrg 361428d7b3dSmrg if (mask_picture != NULL && mask_picture->componentAlpha && 362428d7b3dSmrg PICT_FORMAT_RGB(mask_picture->format)) { 363428d7b3dSmrg /* Check if it's component alpha that relies on a source alpha and on 364428d7b3dSmrg * the source value. We can only get one of those into the single 365428d7b3dSmrg * source value that we get to blend with. 366428d7b3dSmrg */ 367428d7b3dSmrg if (i830_blend_op[op].src_alpha && 368428d7b3dSmrg (i830_blend_op[op].src_blend != BLENDFACTOR_ZERO)) { 369428d7b3dSmrg intel_uxa_debug_fallback(scrn, "Component alpha not " 370428d7b3dSmrg "supported with source alpha and " 371428d7b3dSmrg "source value blending.\n"); 372428d7b3dSmrg return FALSE; 373428d7b3dSmrg } 374428d7b3dSmrg } 375428d7b3dSmrg 376428d7b3dSmrg if (!i830_get_dest_format(dest_picture, &tmp1)) { 377428d7b3dSmrg intel_uxa_debug_fallback(scrn, "Get Color buffer format\n"); 378428d7b3dSmrg return FALSE; 379428d7b3dSmrg } 380428d7b3dSmrg 381428d7b3dSmrg if (width > 2048 || height > 2048) { 382428d7b3dSmrg intel_uxa_debug_fallback(scrn, "Operation is too large (%d, %d)\n", width, height); 383428d7b3dSmrg return FALSE; 384428d7b3dSmrg } 385428d7b3dSmrg 386428d7b3dSmrg return TRUE; 387428d7b3dSmrg} 388428d7b3dSmrg 389428d7b3dSmrgBool 390428d7b3dSmrgi830_check_composite_target(PixmapPtr pixmap) 391428d7b3dSmrg{ 392428d7b3dSmrg if (pixmap->drawable.width > 2048 || pixmap->drawable.height > 2048) 393428d7b3dSmrg return FALSE; 394428d7b3dSmrg 395428d7b3dSmrg if(!intel_uxa_check_pitch_3d(pixmap)) 396428d7b3dSmrg return FALSE; 397428d7b3dSmrg 398428d7b3dSmrg return TRUE; 399428d7b3dSmrg} 400428d7b3dSmrg 401428d7b3dSmrgBool 402428d7b3dSmrgi830_check_composite_texture(ScreenPtr screen, PicturePtr picture) 403428d7b3dSmrg{ 404428d7b3dSmrg ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 405428d7b3dSmrg intel_screen_private *intel = intel_get_screen_private(scrn); 406428d7b3dSmrg 407428d7b3dSmrg if (picture->repeatType > RepeatReflect) { 408428d7b3dSmrg intel_uxa_debug_fallback(scrn, "Unsupported picture repeat %d\n", 409428d7b3dSmrg picture->repeatType); 410428d7b3dSmrg return FALSE; 411428d7b3dSmrg } 412428d7b3dSmrg 413428d7b3dSmrg if (picture->filter != PictFilterNearest && 414428d7b3dSmrg picture->filter != PictFilterBilinear) { 415428d7b3dSmrg intel_uxa_debug_fallback(scrn, "Unsupported filter 0x%x\n", 416428d7b3dSmrg picture->filter); 417428d7b3dSmrg return FALSE; 418428d7b3dSmrg } 419428d7b3dSmrg 420428d7b3dSmrg if (picture->pDrawable) { 421428d7b3dSmrg int w, h; 422428d7b3dSmrg 423428d7b3dSmrg w = picture->pDrawable->width; 424428d7b3dSmrg h = picture->pDrawable->height; 425428d7b3dSmrg if ((w > 2048) || (h > 2048)) { 426428d7b3dSmrg intel_uxa_debug_fallback(scrn, 427428d7b3dSmrg "Picture w/h too large (%dx%d)\n", 428428d7b3dSmrg w, h); 429428d7b3dSmrg return FALSE; 430428d7b3dSmrg } 431428d7b3dSmrg 432428d7b3dSmrg /* XXX we can use the xrgb32 types if there the picture covers the clip */ 433428d7b3dSmrg if (!i8xx_get_card_format(intel, picture)) { 434428d7b3dSmrg intel_uxa_debug_fallback(scrn, "Unsupported picture format " 435428d7b3dSmrg "0x%x\n", 436428d7b3dSmrg (int)picture->format); 437428d7b3dSmrg return FALSE; 438428d7b3dSmrg } 439428d7b3dSmrg 440428d7b3dSmrg return TRUE; 441428d7b3dSmrg } 442428d7b3dSmrg 443428d7b3dSmrg return FALSE; 444428d7b3dSmrg} 445428d7b3dSmrg 446428d7b3dSmrgBool 447428d7b3dSmrgi830_prepare_composite(int op, PicturePtr source_picture, 448428d7b3dSmrg PicturePtr mask_picture, PicturePtr dest_picture, 449428d7b3dSmrg PixmapPtr source, PixmapPtr mask, PixmapPtr dest) 450428d7b3dSmrg{ 451428d7b3dSmrg ScrnInfoPtr scrn = xf86ScreenToScrn(dest_picture->pDrawable->pScreen); 452428d7b3dSmrg intel_screen_private *intel = intel_get_screen_private(scrn); 453428d7b3dSmrg drm_intel_bo *bo_table[] = { 454428d7b3dSmrg NULL, /* batch_bo */ 455428d7b3dSmrg intel_uxa_get_pixmap_bo(source), 456428d7b3dSmrg mask ? intel_uxa_get_pixmap_bo(mask) : NULL, 457428d7b3dSmrg intel_uxa_get_pixmap_bo(dest), 458428d7b3dSmrg }; 459428d7b3dSmrg 460428d7b3dSmrg intel->render_source_picture = source_picture; 461428d7b3dSmrg intel->render_source = source; 462428d7b3dSmrg intel->render_mask_picture = mask_picture; 463428d7b3dSmrg intel->render_mask = mask; 464428d7b3dSmrg intel->render_dest_picture = dest_picture; 465428d7b3dSmrg intel->render_dest = dest; 466428d7b3dSmrg 467428d7b3dSmrg if (!intel_uxa_check_pitch_3d(source)) 468428d7b3dSmrg return FALSE; 469428d7b3dSmrg if (mask) { 470428d7b3dSmrg if (mask_picture->componentAlpha && 471428d7b3dSmrg PICT_FORMAT_RGB(mask_picture->format)) { 472428d7b3dSmrg /* Check if it's component alpha that relies on a source alpha and on 473428d7b3dSmrg * the source value. We can only get one of those into the single 474428d7b3dSmrg * source value that we get to blend with. 475428d7b3dSmrg */ 476428d7b3dSmrg if (i830_blend_op[op].src_alpha && 477428d7b3dSmrg (i830_blend_op[op].src_blend != BLENDFACTOR_ZERO)) { 478428d7b3dSmrg intel_uxa_debug_fallback(scrn, "Component alpha not " 479428d7b3dSmrg "supported with source alpha and " 480428d7b3dSmrg "source value blending.\n"); 481428d7b3dSmrg return FALSE; 482428d7b3dSmrg } 483428d7b3dSmrg } 484428d7b3dSmrg if (!intel_uxa_check_pitch_3d(mask)) 485428d7b3dSmrg return FALSE; 486428d7b3dSmrg } 487428d7b3dSmrg if (!intel_uxa_check_pitch_3d(dest)) 488428d7b3dSmrg return FALSE; 489428d7b3dSmrg 490428d7b3dSmrg if (!i830_get_dest_format(dest_picture, &intel->render_dest_format)) 491428d7b3dSmrg return FALSE; 492428d7b3dSmrg 493428d7b3dSmrg if (!intel_uxa_get_aperture_space(scrn, bo_table, ARRAY_SIZE(bo_table))) 494428d7b3dSmrg return FALSE; 495428d7b3dSmrg 496428d7b3dSmrg if (mask) { 497428d7b3dSmrg intel->transform[1] = NULL; 498428d7b3dSmrg intel->scale_units[1][0] = -1; 499428d7b3dSmrg intel->scale_units[1][1] = -1; 500428d7b3dSmrg } 501428d7b3dSmrg 502428d7b3dSmrg { 503428d7b3dSmrg uint32_t cblend, ablend, blendctl; 504428d7b3dSmrg 505428d7b3dSmrg /* If component alpha is active in the mask and the blend operation 506428d7b3dSmrg * uses the source alpha, then we know we don't need the source 507428d7b3dSmrg * value (otherwise we would have hit a fallback earlier), so we 508428d7b3dSmrg * provide the source alpha (src.A * mask.X) as output color. 509428d7b3dSmrg * Conversely, if CA is set and we don't need the source alpha, then 510428d7b3dSmrg * we produce the source value (src.X * mask.X) and the source alpha 511428d7b3dSmrg * is unused.. Otherwise, we provide the non-CA source value 512428d7b3dSmrg * (src.X * mask.A). 513428d7b3dSmrg * 514428d7b3dSmrg * The PICT_FORMAT_RGB(pict) == 0 fixups are not needed on 855+'s a8 515428d7b3dSmrg * pictures, but we need to implement it for 830/845 and there's no 516428d7b3dSmrg * harm done in leaving it in. 517428d7b3dSmrg */ 518428d7b3dSmrg cblend = 519428d7b3dSmrg TB0C_LAST_STAGE | TB0C_RESULT_SCALE_1X | TB0C_OP_MODULE | 520428d7b3dSmrg TB0C_OUTPUT_WRITE_CURRENT; 521428d7b3dSmrg ablend = 522428d7b3dSmrg TB0A_RESULT_SCALE_1X | TB0A_OP_MODULE | 523428d7b3dSmrg TB0A_OUTPUT_WRITE_CURRENT; 524428d7b3dSmrg 525428d7b3dSmrg /* Get the source picture's channels into TBx_ARG1 */ 526428d7b3dSmrg if ((mask_picture != NULL && 527428d7b3dSmrg mask_picture->componentAlpha && 528428d7b3dSmrg PICT_FORMAT_RGB(mask_picture->format) && 529428d7b3dSmrg i830_blend_op[op].src_alpha) 530428d7b3dSmrg || dest_picture->format == PICT_a8) { 531428d7b3dSmrg /* Producing source alpha value, so the first set of channels 532428d7b3dSmrg * is src.A instead of src.X. We also do this if the destination 533428d7b3dSmrg * is a8, in which case src.G is what's written, and the other 534428d7b3dSmrg * channels are ignored. 535428d7b3dSmrg */ 536428d7b3dSmrg ablend |= TB0A_ARG1_SEL_TEXEL0; 537428d7b3dSmrg cblend |= TB0C_ARG1_SEL_TEXEL0 | TB0C_ARG1_REPLICATE_ALPHA; 538428d7b3dSmrg } else { 539428d7b3dSmrg if (PICT_FORMAT_RGB(source_picture->format) != 0) 540428d7b3dSmrg cblend |= TB0C_ARG1_SEL_TEXEL0; 541428d7b3dSmrg else 542428d7b3dSmrg cblend |= TB0C_ARG1_SEL_ONE | TB0C_ARG1_INVERT; /* 0.0 */ 543428d7b3dSmrg ablend |= TB0A_ARG1_SEL_TEXEL0; 544428d7b3dSmrg } 545428d7b3dSmrg 546428d7b3dSmrg if (mask) { 547428d7b3dSmrg cblend |= TB0C_ARG2_SEL_TEXEL1; 548428d7b3dSmrg if (dest_picture->format == PICT_a8 || 549428d7b3dSmrg ! mask_picture->componentAlpha || 550428d7b3dSmrg ! PICT_FORMAT_RGB(mask_picture->format)) 551428d7b3dSmrg cblend |= TB0C_ARG2_REPLICATE_ALPHA; 552428d7b3dSmrg ablend |= TB0A_ARG2_SEL_TEXEL1; 553428d7b3dSmrg } else { 554428d7b3dSmrg cblend |= TB0C_ARG2_SEL_ONE; 555428d7b3dSmrg ablend |= TB0A_ARG2_SEL_ONE; 556428d7b3dSmrg } 557428d7b3dSmrg 558428d7b3dSmrg if (!i830_get_blend_cntl 559428d7b3dSmrg (scrn, op, mask_picture, dest_picture->format, &blendctl)) { 560428d7b3dSmrg return FALSE; 561428d7b3dSmrg } 562428d7b3dSmrg 563428d7b3dSmrg intel->cblend = cblend; 564428d7b3dSmrg intel->ablend = ablend; 565428d7b3dSmrg intel->s8_blendctl = blendctl; 566428d7b3dSmrg } 567428d7b3dSmrg 568428d7b3dSmrg if (intel_uxa_pixmap_is_dirty(source) || intel_uxa_pixmap_is_dirty(mask)) 569428d7b3dSmrg intel_batch_emit_flush(scrn); 570428d7b3dSmrg 571428d7b3dSmrg intel->needs_render_state_emit = TRUE; 572428d7b3dSmrg 573428d7b3dSmrg return TRUE; 574428d7b3dSmrg} 575428d7b3dSmrg 576428d7b3dSmrgstatic void i830_emit_composite_state(ScrnInfoPtr scrn) 577428d7b3dSmrg{ 578428d7b3dSmrg intel_screen_private *intel = intel_get_screen_private(scrn); 579428d7b3dSmrg uint32_t vf2, tiling_bits; 580428d7b3dSmrg uint32_t texcoordfmt = 0; 581428d7b3dSmrg 582428d7b3dSmrg intel->needs_render_state_emit = FALSE; 583428d7b3dSmrg 584428d7b3dSmrg IntelEmitInvarientState(scrn); 585428d7b3dSmrg intel->last_3d = LAST_3D_RENDER; 586428d7b3dSmrg 587428d7b3dSmrg assert(intel->in_batch_atomic); 588428d7b3dSmrg 589428d7b3dSmrg if (intel_uxa_pixmap_tiled(intel->render_dest)) { 590428d7b3dSmrg tiling_bits = BUF_3D_TILED_SURFACE; 591428d7b3dSmrg if (intel_uxa_get_pixmap_private(intel->render_dest)->tiling 592428d7b3dSmrg == I915_TILING_Y) 593428d7b3dSmrg tiling_bits |= BUF_3D_TILE_WALK_Y; 594428d7b3dSmrg } else 595428d7b3dSmrg tiling_bits = 0; 596428d7b3dSmrg 597428d7b3dSmrg OUT_BATCH(_3DSTATE_BUF_INFO_CMD); 598428d7b3dSmrg OUT_BATCH(BUF_3D_ID_COLOR_BACK | tiling_bits | 599428d7b3dSmrg BUF_3D_PITCH(intel_pixmap_pitch(intel->render_dest))); 600428d7b3dSmrg OUT_RELOC_PIXMAP(intel->render_dest, 601428d7b3dSmrg I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0); 602428d7b3dSmrg 603428d7b3dSmrg OUT_BATCH(_3DSTATE_DST_BUF_VARS_CMD); 604428d7b3dSmrg OUT_BATCH(intel->render_dest_format); 605428d7b3dSmrg 606428d7b3dSmrg OUT_BATCH(_3DSTATE_DRAW_RECT_CMD); 607428d7b3dSmrg OUT_BATCH(0); 608428d7b3dSmrg OUT_BATCH(0); /* ymin, xmin */ 609428d7b3dSmrg OUT_BATCH(DRAW_YMAX(intel->render_dest->drawable.height - 1) | 610428d7b3dSmrg DRAW_XMAX(intel->render_dest->drawable.width - 1)); 611428d7b3dSmrg OUT_BATCH(0); /* yorig, xorig */ 612428d7b3dSmrg 613428d7b3dSmrg OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | 614428d7b3dSmrg I1_LOAD_S(2) | I1_LOAD_S(3) | I1_LOAD_S(8) | 2); 615428d7b3dSmrg if (intel->render_mask) 616428d7b3dSmrg vf2 = 2 << 12; /* 2 texture coord sets */ 617428d7b3dSmrg else 618428d7b3dSmrg vf2 = 1 << 12; 619428d7b3dSmrg OUT_BATCH(vf2); /* number of coordinate sets */ 620428d7b3dSmrg OUT_BATCH(S3_CULLMODE_NONE | S3_VERTEXHAS_XY); 621428d7b3dSmrg OUT_BATCH(S8_ENABLE_COLOR_BLEND | S8_BLENDFUNC_ADD | intel-> 622428d7b3dSmrg s8_blendctl | S8_ENABLE_COLOR_BUFFER_WRITE); 623428d7b3dSmrg 624428d7b3dSmrg OUT_BATCH(_3DSTATE_INDPT_ALPHA_BLEND_CMD | DISABLE_INDPT_ALPHA_BLEND); 625428d7b3dSmrg 626428d7b3dSmrg OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_2 | 627428d7b3dSmrg LOAD_TEXTURE_BLEND_STAGE(0) | 1); 628428d7b3dSmrg OUT_BATCH(intel->cblend); 629428d7b3dSmrg OUT_BATCH(intel->ablend); 630428d7b3dSmrg 631428d7b3dSmrg OUT_BATCH(_3DSTATE_ENABLES_1_CMD | DISABLE_LOGIC_OP | 632428d7b3dSmrg DISABLE_STENCIL_TEST | DISABLE_DEPTH_BIAS | 633428d7b3dSmrg DISABLE_SPEC_ADD | DISABLE_FOG | DISABLE_ALPHA_TEST | 634428d7b3dSmrg ENABLE_COLOR_BLEND | DISABLE_DEPTH_TEST); 635428d7b3dSmrg /* We have to explicitly say we don't want write disabled */ 636428d7b3dSmrg OUT_BATCH(_3DSTATE_ENABLES_2_CMD | ENABLE_COLOR_MASK | 637428d7b3dSmrg DISABLE_STENCIL_WRITE | ENABLE_TEX_CACHE | 638428d7b3dSmrg DISABLE_DITHER | ENABLE_COLOR_WRITE | DISABLE_DEPTH_WRITE); 639428d7b3dSmrg 640428d7b3dSmrg if (intel_uxa_transform_is_affine(intel->render_source_picture->transform)) 641428d7b3dSmrg texcoordfmt |= (TEXCOORDFMT_2D << 0); 642428d7b3dSmrg else 643428d7b3dSmrg texcoordfmt |= (TEXCOORDFMT_3D << 0); 644428d7b3dSmrg if (intel->render_mask) { 645428d7b3dSmrg if (intel_uxa_transform_is_affine 646428d7b3dSmrg (intel->render_mask_picture->transform)) 647428d7b3dSmrg texcoordfmt |= (TEXCOORDFMT_2D << 2); 648428d7b3dSmrg else 649428d7b3dSmrg texcoordfmt |= (TEXCOORDFMT_3D << 2); 650428d7b3dSmrg } 651428d7b3dSmrg OUT_BATCH(_3DSTATE_VERTEX_FORMAT_2_CMD | texcoordfmt); 652428d7b3dSmrg 653428d7b3dSmrg i830_texture_setup(intel->render_source_picture, intel->render_source, 0); 654428d7b3dSmrg if (intel->render_mask) { 655428d7b3dSmrg i830_texture_setup(intel->render_mask_picture, 656428d7b3dSmrg intel->render_mask, 1); 657428d7b3dSmrg } 658428d7b3dSmrg} 659428d7b3dSmrg 660428d7b3dSmrg/* Emit the vertices for a single composite rectangle. 661428d7b3dSmrg * 662428d7b3dSmrg * This function is no longer shared between i830 and i915 generation code. 663428d7b3dSmrg */ 664428d7b3dSmrgstatic void 665428d7b3dSmrgi830_emit_composite_primitive(PixmapPtr dest, 666428d7b3dSmrg int srcX, int srcY, 667428d7b3dSmrg int maskX, int maskY, 668428d7b3dSmrg int dstX, int dstY, int w, int h) 669428d7b3dSmrg{ 670428d7b3dSmrg ScrnInfoPtr scrn = xf86ScreenToScrn(dest->drawable.pScreen); 671428d7b3dSmrg intel_screen_private *intel = intel_get_screen_private(scrn); 672428d7b3dSmrg Bool is_affine_src, is_affine_mask = TRUE; 673428d7b3dSmrg int per_vertex; 674428d7b3dSmrg float src_x[3], src_y[3], src_w[3], mask_x[3], mask_y[3], mask_w[3]; 675428d7b3dSmrg 676428d7b3dSmrg per_vertex = 2; /* dest x/y */ 677428d7b3dSmrg 678428d7b3dSmrg { 679428d7b3dSmrg float x = srcX, y = srcY; 680428d7b3dSmrg 681428d7b3dSmrg is_affine_src = intel_uxa_transform_is_affine(intel->transform[0]); 682428d7b3dSmrg if (is_affine_src) { 683428d7b3dSmrg if (!intel_uxa_get_transformed_coordinates(x, y, 684428d7b3dSmrg intel-> 685428d7b3dSmrg transform[0], 686428d7b3dSmrg &src_x[0], 687428d7b3dSmrg &src_y[0])) 688428d7b3dSmrg return; 689428d7b3dSmrg 690428d7b3dSmrg if (!intel_uxa_get_transformed_coordinates(x, y + h, 691428d7b3dSmrg intel-> 692428d7b3dSmrg transform[0], 693428d7b3dSmrg &src_x[1], 694428d7b3dSmrg &src_y[1])) 695428d7b3dSmrg return; 696428d7b3dSmrg 697428d7b3dSmrg if (!intel_uxa_get_transformed_coordinates(x + w, y + h, 698428d7b3dSmrg intel-> 699428d7b3dSmrg transform[0], 700428d7b3dSmrg &src_x[2], 701428d7b3dSmrg &src_y[2])) 702428d7b3dSmrg return; 703428d7b3dSmrg 704428d7b3dSmrg per_vertex += 2; /* src x/y */ 705428d7b3dSmrg } else { 706428d7b3dSmrg if (!intel_uxa_get_transformed_coordinates_3d(x, y, 707428d7b3dSmrg intel-> 708428d7b3dSmrg transform[0], 709428d7b3dSmrg &src_x[0], 710428d7b3dSmrg &src_y[0], 711428d7b3dSmrg &src_w[0])) 712428d7b3dSmrg return; 713428d7b3dSmrg 714428d7b3dSmrg if (!intel_uxa_get_transformed_coordinates_3d(x, y + h, 715428d7b3dSmrg intel-> 716428d7b3dSmrg transform[0], 717428d7b3dSmrg &src_x[1], 718428d7b3dSmrg &src_y[1], 719428d7b3dSmrg &src_w[1])) 720428d7b3dSmrg return; 721428d7b3dSmrg 722428d7b3dSmrg if (!intel_uxa_get_transformed_coordinates_3d(x + w, y + h, 723428d7b3dSmrg intel-> 724428d7b3dSmrg transform[0], 725428d7b3dSmrg &src_x[2], 726428d7b3dSmrg &src_y[2], 727428d7b3dSmrg &src_w[2])) 728428d7b3dSmrg return; 729428d7b3dSmrg 730428d7b3dSmrg per_vertex += 3; /* src x/y/w */ 731428d7b3dSmrg } 732428d7b3dSmrg } 733428d7b3dSmrg 734428d7b3dSmrg if (intel->render_mask) { 735428d7b3dSmrg float x = maskX, y = maskY; 736428d7b3dSmrg 737428d7b3dSmrg is_affine_mask = intel_uxa_transform_is_affine(intel->transform[1]); 738428d7b3dSmrg if (is_affine_mask) { 739428d7b3dSmrg if (!intel_uxa_get_transformed_coordinates(x, y, 740428d7b3dSmrg intel-> 741428d7b3dSmrg transform[1], 742428d7b3dSmrg &mask_x[0], 743428d7b3dSmrg &mask_y[0])) 744428d7b3dSmrg return; 745428d7b3dSmrg 746428d7b3dSmrg if (!intel_uxa_get_transformed_coordinates(x, y + h, 747428d7b3dSmrg intel-> 748428d7b3dSmrg transform[1], 749428d7b3dSmrg &mask_x[1], 750428d7b3dSmrg &mask_y[1])) 751428d7b3dSmrg return; 752428d7b3dSmrg 753428d7b3dSmrg if (!intel_uxa_get_transformed_coordinates(x + w, y + h, 754428d7b3dSmrg intel-> 755428d7b3dSmrg transform[1], 756428d7b3dSmrg &mask_x[2], 757428d7b3dSmrg &mask_y[2])) 758428d7b3dSmrg return; 759428d7b3dSmrg 760428d7b3dSmrg per_vertex += 2; /* mask x/y */ 761428d7b3dSmrg } else { 762428d7b3dSmrg if (!intel_uxa_get_transformed_coordinates_3d(x, y, 763428d7b3dSmrg intel-> 764428d7b3dSmrg transform[1], 765428d7b3dSmrg &mask_x[0], 766428d7b3dSmrg &mask_y[0], 767428d7b3dSmrg &mask_w[0])) 768428d7b3dSmrg return; 769428d7b3dSmrg 770428d7b3dSmrg if (!intel_uxa_get_transformed_coordinates_3d(x, y + h, 771428d7b3dSmrg intel-> 772428d7b3dSmrg transform[1], 773428d7b3dSmrg &mask_x[1], 774428d7b3dSmrg &mask_y[1], 775428d7b3dSmrg &mask_w[1])) 776428d7b3dSmrg return; 777428d7b3dSmrg 778428d7b3dSmrg if (!intel_uxa_get_transformed_coordinates_3d(x + w, y + h, 779428d7b3dSmrg intel-> 780428d7b3dSmrg transform[1], 781428d7b3dSmrg &mask_x[2], 782428d7b3dSmrg &mask_y[2], 783428d7b3dSmrg &mask_w[2])) 784428d7b3dSmrg return; 785428d7b3dSmrg 786428d7b3dSmrg per_vertex += 3; /* mask x/y/w */ 787428d7b3dSmrg } 788428d7b3dSmrg } 789428d7b3dSmrg 790428d7b3dSmrg if (intel->vertex_count == 0) { 791428d7b3dSmrg intel->vertex_index = intel->batch_used; 792428d7b3dSmrg OUT_BATCH(PRIM3D_INLINE | PRIM3D_RECTLIST); 793428d7b3dSmrg } 794428d7b3dSmrg OUT_BATCH_F(dstX + w); 795428d7b3dSmrg OUT_BATCH_F(dstY + h); 796428d7b3dSmrg OUT_BATCH_F(src_x[2] / intel->scale_units[0][0]); 797428d7b3dSmrg OUT_BATCH_F(src_y[2] / intel->scale_units[0][1]); 798428d7b3dSmrg if (!is_affine_src) { 799428d7b3dSmrg OUT_BATCH_F(src_w[2]); 800428d7b3dSmrg } 801428d7b3dSmrg if (intel->render_mask) { 802428d7b3dSmrg OUT_BATCH_F(mask_x[2] / intel->scale_units[1][0]); 803428d7b3dSmrg OUT_BATCH_F(mask_y[2] / intel->scale_units[1][1]); 804428d7b3dSmrg if (!is_affine_mask) { 805428d7b3dSmrg OUT_BATCH_F(mask_w[2]); 806428d7b3dSmrg } 807428d7b3dSmrg } 808428d7b3dSmrg 809428d7b3dSmrg OUT_BATCH_F(dstX); 810428d7b3dSmrg OUT_BATCH_F(dstY + h); 811428d7b3dSmrg OUT_BATCH_F(src_x[1] / intel->scale_units[0][0]); 812428d7b3dSmrg OUT_BATCH_F(src_y[1] / intel->scale_units[0][1]); 813428d7b3dSmrg if (!is_affine_src) { 814428d7b3dSmrg OUT_BATCH_F(src_w[1]); 815428d7b3dSmrg } 816428d7b3dSmrg if (intel->render_mask) { 817428d7b3dSmrg OUT_BATCH_F(mask_x[1] / intel->scale_units[1][0]); 818428d7b3dSmrg OUT_BATCH_F(mask_y[1] / intel->scale_units[1][1]); 819428d7b3dSmrg if (!is_affine_mask) { 820428d7b3dSmrg OUT_BATCH_F(mask_w[1]); 821428d7b3dSmrg } 822428d7b3dSmrg } 823428d7b3dSmrg 824428d7b3dSmrg OUT_BATCH_F(dstX); 825428d7b3dSmrg OUT_BATCH_F(dstY); 826428d7b3dSmrg OUT_BATCH_F(src_x[0] / intel->scale_units[0][0]); 827428d7b3dSmrg OUT_BATCH_F(src_y[0] / intel->scale_units[0][1]); 828428d7b3dSmrg if (!is_affine_src) { 829428d7b3dSmrg OUT_BATCH_F(src_w[0]); 830428d7b3dSmrg } 831428d7b3dSmrg if (intel->render_mask) { 832428d7b3dSmrg OUT_BATCH_F(mask_x[0] / intel->scale_units[1][0]); 833428d7b3dSmrg OUT_BATCH_F(mask_y[0] / intel->scale_units[1][1]); 834428d7b3dSmrg if (!is_affine_mask) { 835428d7b3dSmrg OUT_BATCH_F(mask_w[0]); 836428d7b3dSmrg } 837428d7b3dSmrg } 838428d7b3dSmrg 839428d7b3dSmrg intel->vertex_count += 3 * per_vertex; 840428d7b3dSmrg 841428d7b3dSmrg} 842428d7b3dSmrg 843428d7b3dSmrgvoid i830_vertex_flush(intel_screen_private *intel) 844428d7b3dSmrg{ 845428d7b3dSmrg if (intel->vertex_count) { 846428d7b3dSmrg intel->batch_ptr[intel->vertex_index] |= intel->vertex_count - 1; 847428d7b3dSmrg intel->vertex_count = 0; 848428d7b3dSmrg } 849428d7b3dSmrg} 850428d7b3dSmrg 851428d7b3dSmrg/** 852428d7b3dSmrg * Do a single rectangle composite operation. 853428d7b3dSmrg */ 854428d7b3dSmrgvoid 855428d7b3dSmrgi830_composite(PixmapPtr dest, int srcX, int srcY, int maskX, int maskY, 856428d7b3dSmrg int dstX, int dstY, int w, int h) 857428d7b3dSmrg{ 858428d7b3dSmrg ScrnInfoPtr scrn = xf86ScreenToScrn(dest->drawable.pScreen); 859428d7b3dSmrg intel_screen_private *intel = intel_get_screen_private(scrn); 860428d7b3dSmrg 861428d7b3dSmrg intel_batch_start_atomic(scrn, 58 + /* invarient */ 862428d7b3dSmrg 22 + /* setup */ 863428d7b3dSmrg 20 + /* 2 * setup_texture */ 864428d7b3dSmrg 1 + 30 /* verts */ ); 865428d7b3dSmrg 866428d7b3dSmrg if (intel->needs_render_state_emit) 867428d7b3dSmrg i830_emit_composite_state(scrn); 868428d7b3dSmrg 869428d7b3dSmrg i830_emit_composite_primitive(dest, srcX, srcY, maskX, maskY, dstX, 870428d7b3dSmrg dstY, w, h); 871428d7b3dSmrg 872428d7b3dSmrg intel_batch_end_atomic(scrn); 873428d7b3dSmrg} 874428d7b3dSmrg 875428d7b3dSmrgvoid i830_batch_commit_notify(intel_screen_private *intel) 876428d7b3dSmrg{ 877428d7b3dSmrg intel->needs_render_state_emit = TRUE; 878428d7b3dSmrg} 879