Home | History | Annotate | Line # | Download | only in src
      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 (at) intel.com>
     25  *    Eric Anholt <eric (at) 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 
     38 struct formatinfo {
     39     int fmt;
     40     uint32_t card_fmt;
     41 };
     42 
     43 struct blendinfo {
     44     Bool dst_alpha;
     45     Bool src_alpha;
     46     uint32_t src_blend;
     47     uint32_t dst_blend;
     48 };
     49 
     50 static 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 
     79 static 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 
     92 static 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 
    139 static 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 
    172 static 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 
    204 Bool
    205 i915_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 
    238 static Bool
    239 i915_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 
    315 Bool
    316 i915_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 
    374 static void
    375 i915_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  */
    556 static void
    557 i915_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 
    726 void
    727 i915_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 
    744 void
    745 i915_batch_flush_notify(ScrnInfoPtr pScrn)
    746 {
    747     I830Ptr pI830 = I830PTR(pScrn);
    748 
    749     pI830->i915_render_state.needs_emit = TRUE;
    750 }
    751