First import
[xorg_rtime.git] / xorg-server-1.4 / hw / kdrive / ati / radeon_composite.c
blobddad343e3596e0c4e241ba53b11ef4cf1818f7b6
1 /*
2 * Copyright © 2003 Eric Anholt
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation, and that the name of Eric Anholt not be used in
9 * advertising or publicity pertaining to distribution of the software without
10 * specific, written prior permission. Eric Anholt makes no
11 * representations about the suitability of this software for any purpose. It
12 * is provided "as is" without express or implied warranty.
14 * ERIC ANHOLT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL ERIC ANHOLT BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20 * PERFORMANCE OF THIS SOFTWARE.
23 #ifdef HAVE_CONFIG_H
24 #include <kdrive-config.h>
25 #endif
26 #include "ati.h"
27 #include "ati_reg.h"
28 #include "ati_dma.h"
29 #include "ati_draw.h"
31 extern ATIScreenInfo *accel_atis;
32 extern int sample_count;
33 extern float sample_offsets_x[255];
34 extern float sample_offsets_y[255];
35 static Bool is_transform[2];
36 static PictTransform *transform[2];
38 struct blendinfo {
39 Bool dst_alpha;
40 Bool src_alpha;
41 CARD32 blend_cntl;
44 static struct blendinfo RadeonBlendOp[] = {
45 /* Clear */
46 {0, 0, RADEON_SBLEND_GL_ZERO | RADEON_DBLEND_GL_ZERO},
47 /* Src */
48 {0, 0, RADEON_SBLEND_GL_ONE | RADEON_DBLEND_GL_ZERO},
49 /* Dst */
50 {0, 0, RADEON_SBLEND_GL_ZERO | RADEON_DBLEND_GL_ONE},
51 /* Over */
52 {0, 1, RADEON_SBLEND_GL_ONE | RADEON_DBLEND_GL_INV_SRC_ALPHA},
53 /* OverReverse */
54 {1, 0, RADEON_SBLEND_GL_INV_DST_ALPHA | RADEON_DBLEND_GL_ONE},
55 /* In */
56 {1, 0, RADEON_SBLEND_GL_DST_ALPHA | RADEON_DBLEND_GL_ZERO},
57 /* InReverse */
58 {0, 1, RADEON_SBLEND_GL_ZERO | RADEON_DBLEND_GL_SRC_ALPHA},
59 /* Out */
60 {1, 0, RADEON_SBLEND_GL_INV_DST_ALPHA | RADEON_DBLEND_GL_ZERO},
61 /* OutReverse */
62 {0, 1, RADEON_SBLEND_GL_ZERO | RADEON_DBLEND_GL_INV_SRC_ALPHA},
63 /* Atop */
64 {1, 1, RADEON_SBLEND_GL_DST_ALPHA | RADEON_DBLEND_GL_INV_SRC_ALPHA},
65 /* AtopReverse */
66 {1, 1, RADEON_SBLEND_GL_INV_DST_ALPHA | RADEON_DBLEND_GL_SRC_ALPHA},
67 /* Xor */
68 {1, 1, RADEON_SBLEND_GL_INV_DST_ALPHA | RADEON_DBLEND_GL_INV_SRC_ALPHA},
69 /* Add */
70 {0, 0, RADEON_SBLEND_GL_ONE | RADEON_DBLEND_GL_ONE},
73 struct formatinfo {
74 int fmt;
75 Bool byte_swap;
76 CARD32 card_fmt;
79 /* Note on texture formats:
80 * TXFORMAT_Y8 expands to (Y,Y,Y,1). TXFORMAT_I8 expands to (I,I,I,I)
82 static struct formatinfo R100TexFormats[] = {
83 {PICT_a8r8g8b8, 0, RADEON_TXFORMAT_ARGB8888 | RADEON_TXFORMAT_ALPHA_IN_MAP},
84 {PICT_x8r8g8b8, 0, RADEON_TXFORMAT_ARGB8888},
85 {PICT_a8b8g8r8, 1, RADEON_TXFORMAT_RGBA8888 | RADEON_TXFORMAT_ALPHA_IN_MAP},
86 {PICT_x8b8g8r8, 1, RADEON_TXFORMAT_RGBA8888},
87 {PICT_r5g6b5, 0, RADEON_TXFORMAT_RGB565},
88 {PICT_a1r5g5b5, 0, RADEON_TXFORMAT_ARGB1555 | RADEON_TXFORMAT_ALPHA_IN_MAP},
89 {PICT_x1r5g5b5, 0, RADEON_TXFORMAT_ARGB1555},
90 {PICT_a8, 0, RADEON_TXFORMAT_I8 | RADEON_TXFORMAT_ALPHA_IN_MAP},
93 static struct formatinfo R200TexFormats[] = {
94 {PICT_a8r8g8b8, 0, R200_TXFORMAT_ARGB8888 | R200_TXFORMAT_ALPHA_IN_MAP},
95 {PICT_x8r8g8b8, 0, R200_TXFORMAT_ARGB8888},
96 {PICT_a8r8g8b8, 1, R200_TXFORMAT_RGBA8888 | R200_TXFORMAT_ALPHA_IN_MAP},
97 {PICT_x8r8g8b8, 1, R200_TXFORMAT_RGBA8888},
98 {PICT_r5g6b5, 0, R200_TXFORMAT_RGB565},
99 {PICT_a1r5g5b5, 0, R200_TXFORMAT_ARGB1555 | R200_TXFORMAT_ALPHA_IN_MAP},
100 {PICT_x1r5g5b5, 0, R200_TXFORMAT_ARGB1555},
101 {PICT_a8, 0, R200_TXFORMAT_I8 | R200_TXFORMAT_ALPHA_IN_MAP},
104 /* Common Radeon setup code */
106 static Bool
107 RadeonGetDestFormat(PicturePtr pDstPicture, CARD32 *dst_format)
109 switch (pDstPicture->format) {
110 case PICT_a8r8g8b8:
111 case PICT_x8r8g8b8:
112 *dst_format = RADEON_COLOR_FORMAT_ARGB8888;
113 break;
114 case PICT_r5g6b5:
115 *dst_format = RADEON_COLOR_FORMAT_RGB565;
116 break;
117 case PICT_a1r5g5b5:
118 case PICT_x1r5g5b5:
119 *dst_format = RADEON_COLOR_FORMAT_ARGB1555;
120 break;
121 case PICT_a8:
122 *dst_format = RADEON_COLOR_FORMAT_RGB8;
123 break;
124 default:
125 ATI_FALLBACK(("Unsupported dest format 0x%x\n",
126 pDstPicture->format));
129 return TRUE;
132 /* R100-specific code */
134 static Bool
135 R100CheckCompositeTexture(PicturePtr pPict, int unit)
137 int w = pPict->pDrawable->width;
138 int h = pPict->pDrawable->height;
139 int i;
141 if ((w > 0x7ff) || (h > 0x7ff))
142 ATI_FALLBACK(("Picture w/h too large (%dx%d)\n", w, h));
144 for (i = 0; i < sizeof(R100TexFormats) / sizeof(R100TexFormats[0]); i++)
146 if (R100TexFormats[i].fmt == pPict->format)
147 break;
149 if (i == sizeof(R100TexFormats) / sizeof(R100TexFormats[0]))
150 ATI_FALLBACK(("Unsupported picture format 0x%x\n",
151 pPict->format));
153 if (pPict->repeat && ((w & (w - 1)) != 0 || (h & (h - 1)) != 0))
154 ATI_FALLBACK(("NPOT repeat unsupported (%dx%d)\n", w, h));
156 if (pPict->filter != PictFilterNearest &&
157 pPict->filter != PictFilterBilinear)
158 ATI_FALLBACK(("Unsupported filter 0x%x\n", pPict->filter));
160 return TRUE;
163 static Bool
164 R100TextureSetup(PicturePtr pPict, PixmapPtr pPix, int unit)
166 ATIScreenInfo *atis = accel_atis;
167 KdScreenPriv(pPix->drawable.pScreen);
168 CARD32 txfilter, txformat, txoffset, txpitch;
169 int w = pPict->pDrawable->width;
170 int h = pPict->pDrawable->height;
171 int i;
172 RING_LOCALS;
174 txpitch = pPix->devKind;
175 txoffset = ((CARD8 *)pPix->devPrivate.ptr -
176 pScreenPriv->screen->memory_base);
178 for (i = 0; i < sizeof(R100TexFormats) / sizeof(R100TexFormats[0]); i++)
180 if (R100TexFormats[i].fmt == pPict->format)
181 break;
183 txformat = R100TexFormats[i].card_fmt;
184 if (R100TexFormats[i].byte_swap)
185 txoffset |= RADEON_TXO_ENDIAN_BYTE_SWAP;
187 if (pPict->repeat) {
188 txformat |= ATILog2(w) << RADEON_TXFORMAT_WIDTH_SHIFT;
189 txformat |= ATILog2(h) << RADEON_TXFORMAT_HEIGHT_SHIFT;
190 } else
191 txformat |= RADEON_TXFORMAT_NON_POWER2;
192 txformat |= unit << 24; /* RADEON_TXFORMAT_ST_ROUTE_STQX */
195 if ((txoffset & 0x1f) != 0)
196 ATI_FALLBACK(("Bad texture offset 0x%x\n", txoffset));
197 if ((txpitch & 0x1f) != 0)
198 ATI_FALLBACK(("Bad texture pitch 0x%x\n", txpitch));
200 switch (pPict->filter) {
201 case PictFilterNearest:
202 txfilter = (RADEON_MAG_FILTER_NEAREST |
203 RADEON_MIN_FILTER_NEAREST);
204 break;
205 case PictFilterBilinear:
206 txfilter = (RADEON_MAG_FILTER_LINEAR |
207 RADEON_MIN_FILTER_LINEAR);
208 break;
209 default:
210 ATI_FALLBACK(("Bad filter 0x%x\n", pPict->filter));
213 BEGIN_DMA(7);
214 if (unit == 0) {
215 OUT_RING(DMA_PACKET0(RADEON_REG_PP_TXFILTER_0, 3));
216 OUT_RING_REG(RADEON_REG_PP_TXFILTER_0, txfilter);
217 OUT_RING_REG(RADEON_REG_PP_TXFORMAT_0, txformat);
218 OUT_RING_REG(RADEON_REG_PP_TXOFFSET_0, txoffset);
219 OUT_RING(DMA_PACKET0(RADEON_REG_PP_TEX_SIZE_0, 2));
220 OUT_RING_REG(RADEON_REG_PP_TEX_SIZE_0,
221 (pPix->drawable.width - 1) |
222 ((pPix->drawable.height - 1) << RADEON_TEX_VSIZE_SHIFT));
223 OUT_RING_REG(RADEON_REG_PP_TEX_PITCH_0, txpitch - 32);
224 } else {
225 OUT_RING(DMA_PACKET0(RADEON_REG_PP_TXFILTER_1, 3));
226 OUT_RING_REG(RADEON_REG_PP_TXFILTER_1, txfilter);
227 OUT_RING_REG(RADEON_REG_PP_TXFORMAT_1, txformat);
228 OUT_RING_REG(RADEON_REG_PP_TXOFFSET_1, txoffset);
229 OUT_RING(DMA_PACKET0(RADEON_REG_PP_TEX_SIZE_1, 2));
230 OUT_RING_REG(RADEON_REG_PP_TEX_SIZE_1,
231 (pPix->drawable.width - 1) |
232 ((pPix->drawable.height - 1) << RADEON_TEX_VSIZE_SHIFT));
233 OUT_RING_REG(RADEON_REG_PP_TEX_PITCH_1, txpitch - 32);
235 END_DMA();
237 if (pPict->transform != 0) {
238 is_transform[unit] = TRUE;
239 transform[unit] = pPict->transform;
240 } else {
241 is_transform[unit] = FALSE;
244 return TRUE;
247 Bool
248 R100CheckComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture,
249 PicturePtr pDstPicture)
251 CARD32 tmp1;
253 /* Check for unsupported compositing operations. */
254 if (op >= sizeof(RadeonBlendOp) / sizeof(RadeonBlendOp[0]))
255 ATI_FALLBACK(("Unsupported Composite op 0x%x\n", op));
256 if (pMaskPicture != NULL && pMaskPicture->componentAlpha &&
257 RadeonBlendOp[op].src_alpha)
258 ATI_FALLBACK(("Component alpha not supported with source "
259 "alpha blending.\n"));
260 if (pDstPicture->pDrawable->width >= (1 << 11) ||
261 pDstPicture->pDrawable->height >= (1 << 11))
262 ATI_FALLBACK(("Dest w/h too large (%d,%d).\n",
263 pDstPicture->pDrawable->width,
264 pDstPicture->pDrawable->height));
266 if (!R100CheckCompositeTexture(pSrcPicture, 0))
267 return FALSE;
268 if (pMaskPicture != NULL && !R100CheckCompositeTexture(pMaskPicture, 1))
269 return FALSE;
271 if (pDstPicture->componentAlpha)
272 return FALSE;
274 if (!RadeonGetDestFormat(pDstPicture, &tmp1))
275 return FALSE;
277 return TRUE;
280 Bool
281 R100PrepareComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture,
282 PicturePtr pDstPicture, PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst)
284 KdScreenPriv(pDst->drawable.pScreen);
285 ATIScreenInfo(pScreenPriv);
286 CARD32 dst_format, dst_offset, dst_pitch;
287 CARD32 pp_cntl, blendcntl, cblend, ablend;
288 int pixel_shift;
289 RING_LOCALS;
291 accel_atis = atis;
293 RadeonGetDestFormat(pDstPicture, &dst_format);
294 pixel_shift = pDst->drawable.bitsPerPixel >> 4;
296 dst_offset = ((CARD8 *)pDst->devPrivate.ptr -
297 pScreenPriv->screen->memory_base);
298 dst_pitch = pDst->devKind;
299 if ((dst_offset & 0x0f) != 0)
300 ATI_FALLBACK(("Bad destination offset 0x%x\n", dst_offset));
301 if (((dst_pitch >> pixel_shift) & 0x7) != 0)
302 ATI_FALLBACK(("Bad destination pitch 0x%x\n", dst_pitch));
304 if (!R100TextureSetup(pSrcPicture, pSrc, 0))
305 return FALSE;
306 pp_cntl = RADEON_TEX_0_ENABLE | RADEON_TEX_BLEND_0_ENABLE;
308 if (pMask != NULL) {
309 if (!R100TextureSetup(pMaskPicture, pMask, 1))
310 return FALSE;
311 pp_cntl |= RADEON_TEX_1_ENABLE;
312 } else {
313 is_transform[1] = FALSE;
316 ENTER_DRAW(pDst);
318 RadeonSwitchTo3D(atis);
320 BEGIN_DMA(12);
322 OUT_RING(DMA_PACKET0(RADEON_REG_PP_CNTL, 3));
323 OUT_RING_REG(RADEON_REG_PP_CNTL, pp_cntl);
324 OUT_RING_REG(RADEON_REG_RB3D_CNTL,
325 dst_format | RADEON_ALPHA_BLEND_ENABLE);
326 OUT_RING_REG(RADEON_REG_RB3D_COLOROFFSET, dst_offset);
328 OUT_REG(RADEON_REG_RB3D_COLORPITCH, dst_pitch >> pixel_shift);
330 /* IN operator: Multiply src by mask components or mask alpha.
331 * BLEND_CTL_ADD is A * B + C.
332 * If a picture is a8, we have to explicitly zero its color values.
333 * If the destination is a8, we have to route the alpha to red, I think.
335 cblend = RADEON_BLEND_CTL_ADD | RADEON_CLAMP_TX |
336 RADEON_COLOR_ARG_C_ZERO;
337 ablend = RADEON_BLEND_CTL_ADD | RADEON_CLAMP_TX |
338 RADEON_ALPHA_ARG_C_ZERO;
340 if (pDstPicture->format == PICT_a8)
341 cblend |= RADEON_COLOR_ARG_A_T0_ALPHA;
342 else if (pSrcPicture->format == PICT_a8)
343 cblend |= RADEON_COLOR_ARG_A_ZERO;
344 else
345 cblend |= RADEON_COLOR_ARG_A_T0_COLOR;
346 ablend |= RADEON_ALPHA_ARG_A_T0_ALPHA;
348 if (pMask) {
349 if (pMaskPicture->componentAlpha &&
350 pDstPicture->format != PICT_a8)
351 cblend |= RADEON_COLOR_ARG_B_T1_COLOR;
352 else
353 cblend |= RADEON_COLOR_ARG_B_T1_ALPHA;
354 ablend |= RADEON_ALPHA_ARG_B_T1_ALPHA;
355 } else {
356 cblend |= RADEON_COLOR_ARG_B_ZERO | RADEON_COMP_ARG_B;
357 ablend |= RADEON_ALPHA_ARG_B_ZERO | RADEON_COMP_ARG_B;
360 OUT_REG(RADEON_REG_PP_TXCBLEND_0, cblend);
361 OUT_REG(RADEON_REG_PP_TXABLEND_0, ablend);
363 /* Op operator. */
364 blendcntl = RadeonBlendOp[op].blend_cntl;
365 if (PICT_FORMAT_A(pDstPicture->format) == 0 &&
366 RadeonBlendOp[op].dst_alpha) {
367 if ((blendcntl & RADEON_SBLEND_MASK) ==
368 RADEON_SBLEND_GL_DST_ALPHA)
369 blendcntl = (blendcntl & ~RADEON_SBLEND_MASK) |
370 RADEON_SBLEND_GL_ONE;
371 else if ((blendcntl & RADEON_SBLEND_MASK) ==
372 RADEON_SBLEND_GL_INV_DST_ALPHA)
373 blendcntl = (blendcntl & ~RADEON_SBLEND_MASK) |
374 RADEON_SBLEND_GL_ZERO;
376 OUT_REG(RADEON_REG_RB3D_BLENDCNTL, blendcntl);
377 END_DMA();
379 LEAVE_DRAW(pDst);
381 return TRUE;
384 static Bool
385 R200CheckCompositeTexture(PicturePtr pPict, int unit)
387 int w = pPict->pDrawable->width;
388 int h = pPict->pDrawable->height;
389 int i;
391 if ((w > 0x7ff) || (h > 0x7ff))
392 ATI_FALLBACK(("Picture w/h too large (%dx%d)\n", w, h));
394 for (i = 0; i < sizeof(R200TexFormats) / sizeof(R200TexFormats[0]); i++)
396 if (R200TexFormats[i].fmt == pPict->format)
397 break;
399 if (i == sizeof(R200TexFormats) / sizeof(R200TexFormats[0]))
400 ATI_FALLBACK(("Unsupported picture format 0x%x\n",
401 pPict->format));
403 if (pPict->repeat && ((w & (w - 1)) != 0 || (h & (h - 1)) != 0))
404 ATI_FALLBACK(("NPOT repeat unsupported (%dx%d)\n", w, h));
406 if (pPict->filter != PictFilterNearest &&
407 pPict->filter != PictFilterBilinear)
408 ATI_FALLBACK(("Unsupported filter 0x%x\n", pPict->filter));
410 return TRUE;
413 static Bool
414 R200TextureSetup(PicturePtr pPict, PixmapPtr pPix, int unit)
416 ATIScreenInfo *atis = accel_atis;
417 KdScreenPriv(pPix->drawable.pScreen);
418 CARD32 txfilter, txformat, txoffset, txpitch;
419 int w = pPict->pDrawable->width;
420 int h = pPict->pDrawable->height;
421 int i;
422 RING_LOCALS;
424 txpitch = pPix->devKind;
425 txoffset = ((CARD8 *)pPix->devPrivate.ptr -
426 pScreenPriv->screen->memory_base);
428 for (i = 0; i < sizeof(R200TexFormats) / sizeof(R200TexFormats[0]); i++)
430 if (R200TexFormats[i].fmt == pPict->format)
431 break;
433 txformat = R200TexFormats[i].card_fmt;
434 if (R200TexFormats[i].byte_swap)
435 txoffset |= R200_TXO_ENDIAN_BYTE_SWAP;
437 if (pPict->repeat) {
438 txformat |= ATILog2(w) << R200_TXFORMAT_WIDTH_SHIFT;
439 txformat |= ATILog2(h) << R200_TXFORMAT_HEIGHT_SHIFT;
440 } else
441 txformat |= R200_TXFORMAT_NON_POWER2;
442 txformat |= unit << R200_TXFORMAT_ST_ROUTE_SHIFT;
444 if ((txoffset & 0x1f) != 0)
445 ATI_FALLBACK(("Bad texture offset 0x%x\n", txoffset));
446 if ((txpitch & 0x1f) != 0)
447 ATI_FALLBACK(("Bad texture pitch 0x%x\n", txpitch));
449 switch (pPict->filter) {
450 case PictFilterNearest:
451 txfilter = (R200_MAG_FILTER_NEAREST |
452 R200_MIN_FILTER_NEAREST);
453 break;
454 case PictFilterBilinear:
455 txfilter = (R200_MAG_FILTER_LINEAR |
456 R200_MIN_FILTER_LINEAR);
457 break;
458 default:
459 ATI_FALLBACK(("Bad filter 0x%x\n", pPict->filter));
462 if (unit == 0) {
463 BEGIN_DMA(6);
464 OUT_RING(DMA_PACKET0(R200_REG_PP_TXFILTER_0 + 0x20 * unit, 5));
465 OUT_RING_REG(R200_REG_PP_TXFILTER_0, txfilter);
466 OUT_RING_REG(R200_REG_PP_TXFORMAT_0, txformat);
467 OUT_RING_REG(R200_REG_PP_TXFORMAT_X_0, 0);
468 OUT_RING_REG(R200_REG_PP_TXSIZE_0,
469 (pPix->drawable.width - 1) |
470 ((pPix->drawable.height - 1) << RADEON_TEX_VSIZE_SHIFT));
471 OUT_RING_REG(R200_REG_PP_TXPITCH_0, txpitch - 32);
472 END_DMA();
473 } else {
474 BEGIN_DMA(6);
475 OUT_RING(DMA_PACKET0(R200_REG_PP_TXFILTER_1, 5));
476 OUT_RING_REG(R200_REG_PP_TXFILTER_1, txfilter);
477 OUT_RING_REG(R200_REG_PP_TXFORMAT_1, txformat);
478 OUT_RING_REG(R200_REG_PP_TXFORMAT_X_1, 0);
479 OUT_RING_REG(R200_REG_PP_TXSIZE_1,
480 (pPix->drawable.width - 1) |
481 ((pPix->drawable.height - 1) << RADEON_TEX_VSIZE_SHIFT));
482 OUT_RING_REG(R200_REG_PP_TXPITCH_1, txpitch - 32);
483 END_DMA();
486 BEGIN_DMA(2);
487 OUT_REG(R200_PP_TXOFFSET_0 + 0x18 * unit, txoffset);
488 END_DMA();
490 if (pPict->transform != 0) {
491 is_transform[unit] = TRUE;
492 transform[unit] = pPict->transform;
493 } else {
494 is_transform[unit] = FALSE;
497 return TRUE;
500 Bool
501 R200CheckComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture,
502 PicturePtr pDstPicture)
504 CARD32 tmp1;
506 /* Check for unsupported compositing operations. */
507 if (op >= sizeof(RadeonBlendOp) / sizeof(RadeonBlendOp[0]))
508 ATI_FALLBACK(("Unsupported Composite op 0x%x\n", op));
509 if (pMaskPicture != NULL && pMaskPicture->componentAlpha &&
510 RadeonBlendOp[op].src_alpha)
511 ATI_FALLBACK(("Component alpha not supported with source "
512 "alpha blending.\n"));
514 if (!R200CheckCompositeTexture(pSrcPicture, 0))
515 return FALSE;
516 if (pMaskPicture != NULL && !R200CheckCompositeTexture(pMaskPicture, 1))
517 return FALSE;
519 if (!RadeonGetDestFormat(pDstPicture, &tmp1))
520 return FALSE;
522 return TRUE;
525 Bool
526 R200PrepareComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture,
527 PicturePtr pDstPicture, PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst)
529 KdScreenPriv(pDst->drawable.pScreen);
530 ATIScreenInfo(pScreenPriv);
531 CARD32 dst_format, dst_offset, dst_pitch;
532 CARD32 pp_cntl, blendcntl, cblend, ablend;
533 int pixel_shift;
534 RING_LOCALS;
536 RadeonGetDestFormat(pDstPicture, &dst_format);
537 pixel_shift = pDst->drawable.bitsPerPixel >> 4;
539 accel_atis = atis;
541 dst_offset = ((CARD8 *)pDst->devPrivate.ptr -
542 pScreenPriv->screen->memory_base);
543 dst_pitch = pDst->devKind;
544 if ((dst_offset & 0x0f) != 0)
545 ATI_FALLBACK(("Bad destination offset 0x%x\n", dst_offset));
546 if (((dst_pitch >> pixel_shift) & 0x7) != 0)
547 ATI_FALLBACK(("Bad destination pitch 0x%x\n", dst_pitch));
549 if (!R200TextureSetup(pSrcPicture, pSrc, 0))
550 return FALSE;
551 pp_cntl = RADEON_TEX_0_ENABLE | RADEON_TEX_BLEND_0_ENABLE;
553 if (pMask != NULL) {
554 if (!R200TextureSetup(pMaskPicture, pMask, 1))
555 return FALSE;
556 pp_cntl |= RADEON_TEX_1_ENABLE;
557 } else {
558 is_transform[1] = FALSE;
561 RadeonSwitchTo3D(atis);
563 BEGIN_DMA(17);
565 OUT_RING(DMA_PACKET0(RADEON_REG_PP_CNTL, 3));
566 OUT_RING_REG(RADEON_REG_PP_CNTL, pp_cntl);
567 OUT_RING_REG(RADEON_REG_RB3D_CNTL, dst_format | RADEON_ALPHA_BLEND_ENABLE);
568 OUT_RING_REG(RADEON_REG_RB3D_COLOROFFSET, dst_offset);
570 OUT_REG(R200_REG_SE_VTX_FMT_0, R200_VTX_XY);
571 OUT_REG(R200_REG_SE_VTX_FMT_1,
572 (2 << R200_VTX_TEX0_COMP_CNT_SHIFT) |
573 (2 << R200_VTX_TEX1_COMP_CNT_SHIFT));
575 OUT_REG(RADEON_REG_RB3D_COLORPITCH, dst_pitch >> pixel_shift);
577 /* IN operator: Multiply src by mask components or mask alpha.
578 * BLEND_CTL_ADD is A * B + C.
579 * If a picture is a8, we have to explicitly zero its color values.
580 * If the destination is a8, we have to route the alpha to red, I think.
582 cblend = R200_TXC_OP_MADD | R200_TXC_ARG_C_ZERO;
583 ablend = R200_TXA_OP_MADD | R200_TXA_ARG_C_ZERO;
585 if (pDstPicture->format == PICT_a8)
586 cblend |= R200_TXC_ARG_A_R0_ALPHA;
587 else if (pSrcPicture->format == PICT_a8)
588 cblend |= R200_TXC_ARG_A_ZERO;
589 else
590 cblend |= R200_TXC_ARG_A_R0_COLOR;
591 ablend |= R200_TXA_ARG_A_R0_ALPHA;
593 if (pMask) {
594 if (pMaskPicture->componentAlpha &&
595 pDstPicture->format != PICT_a8)
596 cblend |= R200_TXC_ARG_B_R1_COLOR;
597 else
598 cblend |= R200_TXC_ARG_B_R1_ALPHA;
599 ablend |= R200_TXA_ARG_B_R1_ALPHA;
600 } else {
601 cblend |= R200_TXC_ARG_B_ZERO | R200_TXC_COMP_ARG_B;
602 ablend |= R200_TXA_ARG_B_ZERO | R200_TXA_COMP_ARG_B;
605 OUT_RING(DMA_PACKET0(R200_REG_PP_TXCBLEND_0, 4));
606 OUT_RING_REG(R200_REG_PP_TXCBLEND_0, cblend);
607 OUT_RING_REG(R200_REG_PP_TXCBLEND2_0,
608 R200_TXC_CLAMP_0_1 | R200_TXC_OUTPUT_REG_R0);
609 OUT_RING_REG(R200_REG_PP_TXABLEND_0, ablend);
610 OUT_RING_REG(R200_REG_PP_TXABLEND2_0,
611 R200_TXA_CLAMP_0_1 | R200_TXA_OUTPUT_REG_R0);
613 /* Op operator. */
614 blendcntl = RadeonBlendOp[op].blend_cntl;
615 if (PICT_FORMAT_A(pDstPicture->format) == 0 &&
616 RadeonBlendOp[op].dst_alpha) {
617 if ((blendcntl & RADEON_SBLEND_MASK) ==
618 RADEON_SBLEND_GL_DST_ALPHA)
619 blendcntl = (blendcntl & ~RADEON_SBLEND_MASK) |
620 RADEON_SBLEND_GL_ONE;
621 else if ((blendcntl & RADEON_SBLEND_MASK) ==
622 RADEON_SBLEND_GL_INV_DST_ALPHA)
623 blendcntl = (blendcntl & ~RADEON_SBLEND_MASK) |
624 RADEON_SBLEND_GL_ZERO;
626 OUT_REG(RADEON_REG_RB3D_BLENDCNTL, blendcntl);
627 END_DMA();
629 return TRUE;
632 union intfloat {
633 float f;
634 CARD32 i;
637 struct blend_vertex {
638 union intfloat x, y;
639 union intfloat s0, t0;
640 union intfloat s1, t1;
643 #define VTX_DWORD_COUNT 6
645 #define VTX_OUT(_dstX, _dstY, _srcX, _srcY, _maskX, _maskY) \
646 do { \
647 OUT_RING_F(_dstX); \
648 OUT_RING_F(_dstY); \
649 OUT_RING_F(_srcX); \
650 OUT_RING_F(_srcY); \
651 OUT_RING_F(_maskX); \
652 OUT_RING_F(_maskY); \
653 } while (0)
655 void
656 RadeonComposite(int srcX, int srcY, int maskX, int maskY, int dstX, int dstY,
657 int w, int h)
659 ATIScreenInfo *atis = accel_atis;
660 ATICardInfo *atic = atis->atic;
661 int srcXend, srcYend, maskXend, maskYend;
662 RING_LOCALS;
663 PictVector v;
665 ENTER_DRAW(0);
667 /*ErrorF("RadeonComposite (%d,%d) (%d,%d) (%d,%d) (%d,%d)\n",
668 srcX, srcY, maskX, maskY,dstX, dstY, w, h);*/
670 srcXend = srcX + w;
671 srcYend = srcY + h;
672 maskXend = maskX + w;
673 maskYend = maskY + h;
674 if (is_transform[0]) {
675 v.vector[0] = IntToxFixed(srcX);
676 v.vector[1] = IntToxFixed(srcY);
677 v.vector[2] = xFixed1;
678 PictureTransformPoint(transform[0], &v);
679 srcX = xFixedToInt(v.vector[0]);
680 srcY = xFixedToInt(v.vector[1]);
681 v.vector[0] = IntToxFixed(srcXend);
682 v.vector[1] = IntToxFixed(srcYend);
683 v.vector[2] = xFixed1;
684 PictureTransformPoint(transform[0], &v);
685 srcXend = xFixedToInt(v.vector[0]);
686 srcYend = xFixedToInt(v.vector[1]);
688 if (is_transform[1]) {
689 v.vector[0] = IntToxFixed(maskX);
690 v.vector[1] = IntToxFixed(maskY);
691 v.vector[2] = xFixed1;
692 PictureTransformPoint(transform[1], &v);
693 maskX = xFixedToInt(v.vector[0]);
694 maskY = xFixedToInt(v.vector[1]);
695 v.vector[0] = IntToxFixed(maskXend);
696 v.vector[1] = IntToxFixed(maskYend);
697 v.vector[2] = xFixed1;
698 PictureTransformPoint(transform[1], &v);
699 maskXend = xFixedToInt(v.vector[0]);
700 maskYend = xFixedToInt(v.vector[1]);
703 if (atic->is_r100) {
704 BEGIN_DMA(4 * VTX_DWORD_COUNT + 3);
705 OUT_RING(DMA_PACKET3(RADEON_CP_PACKET3_3D_DRAW_IMMD,
706 4 * VTX_DWORD_COUNT + 2));
707 OUT_RING(RADEON_CP_VC_FRMT_XY |
708 RADEON_CP_VC_FRMT_ST0 |
709 RADEON_CP_VC_FRMT_ST1);
710 OUT_RING(RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_FAN |
711 RADEON_CP_VC_CNTL_PRIM_WALK_RING |
712 RADEON_CP_VC_CNTL_MAOS_ENABLE |
713 RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE |
714 (4 << RADEON_CP_VC_CNTL_NUM_SHIFT));
715 } else {
716 BEGIN_DMA(4 * VTX_DWORD_COUNT + 2);
717 OUT_RING(DMA_PACKET3(R200_CP_PACKET3_3D_DRAW_IMMD_2,
718 4 * VTX_DWORD_COUNT + 1));
719 OUT_RING(RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_FAN |
720 RADEON_CP_VC_CNTL_PRIM_WALK_RING |
721 (4 << RADEON_CP_VC_CNTL_NUM_SHIFT));
724 VTX_OUT(dstX, dstY, srcX, srcY, maskX, maskY);
725 VTX_OUT(dstX, dstY + h, srcX, srcYend, maskX, maskYend);
726 VTX_OUT(dstX + w, dstY + h, srcXend, srcYend, maskXend, maskYend);
727 VTX_OUT(dstX + w, dstY, srcXend, srcY, maskXend, maskY);
729 LEAVE_DRAW(0);
731 END_DMA();
734 void
735 RadeonDoneComposite(void)
737 ENTER_DRAW(0);
738 LEAVE_DRAW(0);
741 Bool
742 RadeonPrepareTrapezoids(PicturePtr pDstPicture, PixmapPtr pDst)
744 KdScreenPriv(pDst->drawable.pScreen);
745 ATIScreenInfo(pScreenPriv);
746 ATICardInfo(pScreenPriv);
747 CARD32 dst_offset, dst_pitch;
748 int pixel_shift;
749 RING_LOCALS;
751 pixel_shift = pDst->drawable.bitsPerPixel >> 4;
753 accel_atis = atis;
755 dst_offset = ((CARD8 *)pDst->devPrivate.ptr -
756 pScreenPriv->screen->memory_base);
757 dst_pitch = pDst->devKind;
758 if ((dst_offset & 0x0f) != 0)
759 ATI_FALLBACK(("Bad destination offset 0x%x\n", dst_offset));
760 if (((dst_pitch >> pixel_shift) & 0x7) != 0)
761 ATI_FALLBACK(("Bad destination pitch 0x%x\n", dst_pitch));
763 RadeonSwitchTo3D(atis);
765 BEGIN_DMA(8);
767 OUT_RING(DMA_PACKET0(RADEON_REG_PP_CNTL, 5));
768 OUT_RING_REG(RADEON_REG_PP_CNTL, RADEON_TEX_BLEND_0_ENABLE);
769 OUT_RING_REG(RADEON_REG_RB3D_CNTL,
770 RADEON_COLOR_FORMAT_RGB8 | RADEON_ALPHA_BLEND_ENABLE);
771 OUT_RING_REG(RADEON_REG_RB3D_COLOROFFSET, dst_offset);
772 OUT_RING_REG(RADEON_REG_RE_WIDTH_HEIGHT,
773 ((pDst->drawable.height - 1) << 16) |
774 (pDst->drawable.width - 1));
775 OUT_RING_REG(RADEON_REG_RB3D_COLORPITCH, dst_pitch >> pixel_shift);
776 OUT_REG(RADEON_REG_RB3D_BLENDCNTL, RadeonBlendOp[PictOpAdd].blend_cntl);
777 END_DMA();
779 if (atic->is_r100) {
780 BEGIN_DMA(4);
781 OUT_RING(DMA_PACKET0(RADEON_REG_PP_TXCBLEND_0, 3));
782 OUT_RING_REG(RADEON_REG_PP_TXCBLEND_0,
783 RADEON_BLEND_CTL_ADD | RADEON_CLAMP_TX |
784 RADEON_COLOR_ARG_C_TFACTOR_ALPHA);
785 OUT_RING_REG(RADEON_REG_PP_TXABLEND_0,
786 RADEON_BLEND_CTL_ADD | RADEON_CLAMP_TX |
787 RADEON_ALPHA_ARG_C_TFACTOR_ALPHA);
788 OUT_RING_REG(RADEON_REG_PP_TFACTOR_0, 0x01000000);
789 END_DMA();
790 } else if (atic->is_r200) {
791 BEGIN_DMA(14);
792 OUT_REG(R200_REG_SE_VTX_FMT_0, R200_VTX_XY);
793 OUT_REG(R200_REG_SE_VTX_FMT_1, 0);
794 OUT_REG(R200_REG_PP_TXCBLEND_0,
795 R200_TXC_ARG_C_TFACTOR_COLOR);
796 OUT_REG(R200_REG_PP_TXABLEND_0,
797 R200_TXA_ARG_C_TFACTOR_ALPHA);
798 OUT_REG(R200_REG_PP_TXCBLEND2_0, R200_TXC_OUTPUT_REG_R0);
799 OUT_REG(R200_REG_PP_TXABLEND2_0, R200_TXA_OUTPUT_REG_R0);
800 OUT_REG(RADEON_REG_PP_TFACTOR_0, 0x01000000);
801 END_DMA();
804 return TRUE;
807 #define TRAP_VERT_RING_COUNT 2
809 #define TRAP_VERT(_x, _y) \
810 do { \
811 OUT_RING_F((_x) + sample_x); \
812 OUT_RING_F((_y) + sample_y); \
813 } while (0)
815 void
816 RadeonTrapezoids(KaaTrapezoid *traps, int ntraps)
818 ATIScreenInfo *atis = accel_atis;
819 ATICardInfo *atic = atis->atic;
820 RING_LOCALS;
822 while (ntraps > 0) {
823 int i, sample, count, vertcount;
825 count = 0xffff / 4 / sample_count;
826 if (count > ntraps)
827 count = ntraps;
828 vertcount = count * sample_count * 4;
830 if (atic->is_r100) {
831 BEGIN_DMA(3 + vertcount * TRAP_VERT_RING_COUNT);
832 OUT_RING(DMA_PACKET3(RADEON_CP_PACKET3_3D_DRAW_IMMD,
833 2 + vertcount * TRAP_VERT_RING_COUNT));
834 OUT_RING(RADEON_CP_VC_FRMT_XY);
835 OUT_RING(RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_FAN |
836 RADEON_CP_VC_CNTL_PRIM_WALK_RING |
837 RADEON_CP_VC_CNTL_MAOS_ENABLE |
838 RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE |
839 (vertcount << RADEON_CP_VC_CNTL_NUM_SHIFT));
840 } else {
841 BEGIN_DMA(2 + vertcount * TRAP_VERT_RING_COUNT);
842 OUT_RING(DMA_PACKET3(R200_CP_PACKET3_3D_DRAW_IMMD_2,
843 1 + vertcount * TRAP_VERT_RING_COUNT));
844 OUT_RING(RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_FAN |
845 RADEON_CP_VC_CNTL_PRIM_WALK_RING |
846 (vertcount << RADEON_CP_VC_CNTL_NUM_SHIFT));
849 for (i = 0; i < count; i++) {
850 for (sample = 0; sample < sample_count; sample++) {
851 float sample_x = sample_offsets_x[sample];
852 float sample_y = sample_offsets_y[sample];
853 TRAP_VERT(traps[i].tl, traps[i].ty);
854 TRAP_VERT(traps[i].bl, traps[i].by);
855 TRAP_VERT(traps[i].br, traps[i].by);
856 TRAP_VERT(traps[i].tr, traps[i].ty);
859 END_DMA();
861 ntraps -= count;
862 traps += count;
866 void
867 RadeonDoneTrapezoids(void)
869 ATIScreenInfo *atis = accel_atis;
870 RING_LOCALS;
872 BEGIN_DMA(2);
873 OUT_REG(RADEON_REG_RE_WIDTH_HEIGHT, 0xffffffff);
874 END_DMA();