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