First import
[xorg_rtime.git] / xorg-server-1.4 / hw / kdrive / ati / ati_video.c
blobca0ab464a847dfbcc8e6708e29f99a3d3d3f2331
1 /*
2 * Copyright © 2004 Keith Packard
3 * Copyright © 2005 Eric Anholt
5 * Permission to use, copy, modify, distribute, and sell this software and its
6 * documentation for any purpose is hereby granted without fee, provided that
7 * the above copyright notice appear in all copies and that both that
8 * copyright notice and this permission notice appear in supporting
9 * documentation, and that the name of Eric Anholt not be used in
10 * advertising or publicity pertaining to distribution of the software without
11 * specific, written prior permission. Eric Anholt makes no
12 * representations about the suitability of this software for any purpose. It
13 * is provided "as is" without express or implied warranty.
15 * ERIC ANHOLT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
17 * EVENT SHALL ERIC ANHOLT BE LIABLE FOR ANY SPECIAL, INDIRECT OR
18 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
19 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
20 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
21 * PERFORMANCE OF THIS SOFTWARE.
23 * Based on mach64video.c by Keith Packard.
26 #ifdef HAVE_CONFIG_H
27 #include <kdrive-config.h>
28 #endif
29 #include "ati.h"
30 #include "ati_dma.h"
31 #include "ati_draw.h"
32 #include "ati_reg.h"
33 #include "kaa.h"
35 #include <X11/extensions/Xv.h>
36 #include "fourcc.h"
38 #define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)
40 static Atom xvBrightness, xvSaturation;
42 extern CARD8 ATIBltRop[16];
44 #define IMAGE_MAX_WIDTH 2048
45 #define IMAGE_MAX_HEIGHT 2048
47 static void
48 ATIStopVideo(KdScreenInfo *screen, pointer data, Bool exit)
50 ScreenPtr pScreen = screen->pScreen;
51 ATIPortPrivPtr pPortPriv = (ATIPortPrivPtr)data;
53 REGION_EMPTY(screen->pScreen, &pPortPriv->clip);
55 if (pPortPriv->off_screen) {
56 KdOffscreenFree (pScreen, pPortPriv->off_screen);
57 pPortPriv->off_screen = 0;
61 static int
62 ATISetPortAttribute(KdScreenInfo *screen, Atom attribute, int value,
63 pointer data)
65 return BadMatch;
68 static int
69 ATIGetPortAttribute(KdScreenInfo *screen, Atom attribute, int *value,
70 pointer data)
72 return BadMatch;
75 static void
76 ATIQueryBestSize(KdScreenInfo *screen, Bool motion, short vid_w, short vid_h,
77 short drw_w, short drw_h, unsigned int *p_w, unsigned int *p_h,
78 pointer data)
80 *p_w = drw_w;
81 *p_h = drw_h;
84 /* ATIClipVideo -
86 Takes the dst box in standard X BoxRec form (top and left
87 edges inclusive, bottom and right exclusive). The new dst
88 box is returned. The source boundaries are given (x1, y1
89 inclusive, x2, y2 exclusive) and returned are the new source
90 boundaries in 16.16 fixed point.
93 static void
94 ATIClipVideo(BoxPtr dst, INT32 *x1, INT32 *x2, INT32 *y1, INT32 *y2,
95 BoxPtr extents, INT32 width, INT32 height)
97 INT32 vscale, hscale, delta;
98 int diff;
100 hscale = ((*x2 - *x1) << 16) / (dst->x2 - dst->x1);
101 vscale = ((*y2 - *y1) << 16) / (dst->y2 - dst->y1);
103 *x1 <<= 16; *x2 <<= 16;
104 *y1 <<= 16; *y2 <<= 16;
106 diff = extents->x1 - dst->x1;
107 if (diff > 0) {
108 dst->x1 = extents->x1;
109 *x1 += diff * hscale;
111 diff = dst->x2 - extents->x2;
112 if (diff > 0) {
113 dst->x2 = extents->x2;
114 *x2 -= diff * hscale;
116 diff = extents->y1 - dst->y1;
117 if (diff > 0) {
118 dst->y1 = extents->y1;
119 *y1 += diff * vscale;
121 diff = dst->y2 - extents->y2;
122 if (diff > 0) {
123 dst->y2 = extents->y2;
124 *y2 -= diff * vscale;
127 if (*x1 < 0) {
128 diff = (- *x1 + hscale - 1)/ hscale;
129 dst->x1 += diff;
130 *x1 += diff * hscale;
132 delta = *x2 - (width << 16);
133 if (delta > 0) {
134 diff = (delta + hscale - 1)/ hscale;
135 dst->x2 -= diff;
136 *x2 -= diff * hscale;
138 if (*y1 < 0) {
139 diff = (- *y1 + vscale - 1)/ vscale;
140 dst->y1 += diff;
141 *y1 += diff * vscale;
143 delta = *y2 - (height << 16);
144 if (delta > 0) {
145 diff = (delta + vscale - 1)/ vscale;
146 dst->y2 -= diff;
147 *y2 -= diff * vscale;
151 static void
152 R128DisplayVideo(KdScreenInfo *screen, ATIPortPrivPtr pPortPriv)
154 ScreenPtr pScreen = screen->pScreen;
155 KdScreenPriv(pScreen);
156 ATIScreenInfo(pScreenPriv);
157 CARD32 dstDatatype, srcDatatype;
158 CARD32 dst_offset, dst_pitch;
159 int dstxoff, dstyoff;
160 PixmapPtr pPixmap = pPortPriv->pPixmap;
161 int bpp = pPixmap->drawable.bitsPerPixel;
162 RING_LOCALS;
164 BoxPtr pBox = REGION_RECTS(&pPortPriv->clip);
165 int nBox = REGION_NUM_RECTS(&pPortPriv->clip);
167 if (pPortPriv->id == FOURCC_UYVY)
168 srcDatatype = R128_DATATYPE_YVYU_422;
169 else
170 srcDatatype = R128_DATATYPE_VYUY_422;
172 switch (bpp)
174 case 16:
175 if (pPixmap->drawable.depth == 15)
176 dstDatatype = R128_DATATYPE_ARGB1555;
177 else
178 dstDatatype = R128_DATATYPE_RGB565;
179 break;
180 case 32:
181 dstDatatype = R128_DATATYPE_ARGB8888;
182 break;
183 default:
184 return;
187 dst_offset = ((CARD8 *)pPixmap->devPrivate.ptr -
188 pScreenPriv->screen->memory_base);
189 dst_pitch = pPixmap->devKind;
190 #ifdef COMPOSITE
191 dstxoff = -pPixmap->screen_x + pPixmap->drawable.x;
192 dstyoff = -pPixmap->screen_y + pPixmap->drawable.y;
193 #else
194 dstxoff = 0;
195 dstyoff = 0;
196 #endif
198 BEGIN_DMA(18);
199 OUT_REG(ATI_REG_DST_PITCH_OFFSET,
200 ((dst_pitch / bpp) << 21) | (dst_offset >> 5));
201 OUT_REG(ATI_REG_DP_GUI_MASTER_CNTL,
202 ATI_GMC_DST_PITCH_OFFSET_CNTL |
203 ATI_GMC_BRUSH_NONE |
204 (dstDatatype << 8) |
205 ATI_GMC_SRC_DATATYPE_COLOR |
206 (ATIBltRop[GXcopy] << 16) |
207 R128_GMC_3D_FCN_EN |
208 ATI_GMC_CLR_CMP_CNTL_DIS |
209 R128_GMC_AUX_CLIP_DIS);
210 OUT_REG(ATI_REG_DP_CNTL,
211 ATI_DST_X_LEFT_TO_RIGHT | ATI_DST_Y_TOP_TO_BOTTOM );
212 OUT_REG(R128_REG_SCALE_3D_CNTL,
213 R128_SCALE_3D_SCALE |
214 R128_SBLEND_ONE |
215 R128_DBLEND_ZERO);
216 OUT_REG(R128_REG_TEX_CNTL_C, R128_TEX_CACHE_FLUSH);
217 OUT_REG(R128_REG_SCALE_3D_DATATYPE, srcDatatype);
219 OUT_RING(DMA_PACKET0(R128_REG_SCALE_PITCH, 5));
220 OUT_RING_REG(R128_REG_SCALE_PITCH, pPortPriv->src_pitch / 16);
221 OUT_RING_REG(R128_REG_SCALE_X_INC,
222 (pPortPriv->src_w << 16) / pPortPriv->dst_w);
223 OUT_RING_REG(R128_REG_SCALE_Y_INC,
224 (pPortPriv->src_h << 16) / pPortPriv->dst_h);
225 OUT_RING_REG(R128_REG_SCALE_HACC, 0x0);
226 OUT_RING_REG(R128_REG_SCALE_VACC, 0x0);
228 END_DMA();
230 while (nBox--) {
231 int srcX, srcY, dstX, dstY, srcw, srch, dstw, dsth;
233 dstX = pBox->x1 + dstxoff;
234 dstY = pBox->y1 + dstyoff;
235 dstw = pBox->x2 - pBox->x1;
236 dsth = pBox->y2 - pBox->y1;
237 srcX = (pBox->x1 - pPortPriv->dst_x1) *
238 pPortPriv->src_w / pPortPriv->dst_w;
239 srcY = (pBox->y1 - pPortPriv->dst_y1) *
240 pPortPriv->src_h / pPortPriv->dst_h;
241 srcw = pPortPriv->src_w - srcX;
242 srch = pPortPriv->src_h - srcY;
244 BEGIN_DMA(6);
245 OUT_RING(DMA_PACKET0(R128_REG_SCALE_SRC_HEIGHT_WIDTH, 2));
246 OUT_RING_REG(R128_REG_SCALE_SRC_HEIGHT_WIDTH,
247 (srch << 16) | srcw);
248 OUT_RING_REG(R128_REG_SCALE_OFFSET_0, pPortPriv->src_offset +
249 srcY * pPortPriv->src_pitch + srcX * 2);
251 OUT_RING(DMA_PACKET0(R128_REG_SCALE_DST_X_Y, 2));
252 OUT_RING_REG(R128_REG_SCALE_DST_X_Y, (dstX << 16) | dstY);
253 OUT_RING_REG(R128_REG_SCALE_DST_HEIGHT_WIDTH,
254 (dsth << 16) | dstw);
255 END_DMA();
256 pBox++;
258 #ifdef DAMAGEEXT
259 /* XXX: Shouldn't this be in kxv.c instead? */
260 DamageDamageRegion(pPortPriv->pDraw, &pPortPriv->clip);
261 #endif
262 kaaMarkSync(pScreen);
265 union intfloat {
266 float f;
267 CARD32 i;
270 struct blend_vertex {
271 union intfloat x, y;
272 union intfloat s0, t0;
275 #define VTX_DWORD_COUNT 4
277 #define VTX_OUT(vtx) \
278 do { \
279 OUT_RING(vtx.x.i); \
280 OUT_RING(vtx.y.i); \
281 OUT_RING(vtx.s0.i); \
282 OUT_RING(vtx.t0.i); \
283 } while (0)
285 static void
286 RadeonDisplayVideo(KdScreenInfo *screen, ATIPortPrivPtr pPortPriv)
288 ScreenPtr pScreen = screen->pScreen;
289 KdScreenPriv(pScreen);
290 ATICardInfo(pScreenPriv);
291 ATIScreenInfo(pScreenPriv);
292 struct blend_vertex vtx[4];
293 PixmapPtr pPixmap = pPortPriv->pPixmap;
294 CARD32 txformat;
295 CARD32 dst_offset, dst_pitch, dst_format;
296 int dstxoff, dstyoff, pixel_shift;
297 RING_LOCALS;
299 BoxPtr pBox = REGION_RECTS(&pPortPriv->clip);
300 int nBox = REGION_NUM_RECTS(&pPortPriv->clip);
302 switch (pPixmap->drawable.bitsPerPixel) {
303 case 16:
304 if (pPixmap->drawable.depth == 15)
305 dst_format = RADEON_COLOR_FORMAT_ARGB1555;
306 else
307 dst_format = RADEON_COLOR_FORMAT_RGB565;
308 pixel_shift = 1;
309 break;
310 case 32:
311 dst_format = RADEON_COLOR_FORMAT_ARGB8888;
312 pixel_shift = 2;
313 break;
314 default:
315 return;
318 dst_offset = ((CARD8 *)pPixmap->devPrivate.ptr -
319 pScreenPriv->screen->memory_base);
320 dst_pitch = pPixmap->devKind;
322 #ifdef COMPOSITE
323 dstxoff = -pPixmap->screen_x + pPixmap->drawable.x;
324 dstyoff = -pPixmap->screen_y + pPixmap->drawable.y;
325 #else
326 dstxoff = 0;
327 dstyoff = 0;
328 #endif
330 /* Same for R100/R200 */
331 if (pPortPriv->id == FOURCC_UYVY)
332 txformat = RADEON_TXFORMAT_YVYU422;
333 else
334 txformat = RADEON_TXFORMAT_VYUY422;
336 txformat |= RADEON_TXFORMAT_NON_POWER2;
338 RadeonSwitchTo3D(atis);
340 BEGIN_DMA(8);
342 OUT_RING(DMA_PACKET0(RADEON_REG_PP_CNTL, 3));
343 OUT_RING_REG(RADEON_REG_PP_CNTL,
344 RADEON_TEX_0_ENABLE | RADEON_TEX_BLEND_0_ENABLE);
345 OUT_RING_REG(RADEON_REG_RB3D_CNTL,
346 dst_format | RADEON_ALPHA_BLEND_ENABLE);
347 OUT_RING_REG(RADEON_REG_RB3D_COLOROFFSET, dst_offset);
349 OUT_REG(RADEON_REG_RB3D_COLORPITCH, dst_pitch >> pixel_shift);
351 OUT_REG(RADEON_REG_RB3D_BLENDCNTL,
352 RADEON_SBLEND_GL_ONE | RADEON_DBLEND_GL_ZERO);
354 END_DMA();
356 if (atic->is_r200) {
357 BEGIN_DMA(17);
359 OUT_REG(R200_REG_SE_VTX_FMT_0, R200_VTX_XY);
360 OUT_REG(R200_REG_SE_VTX_FMT_1,
361 (2 << R200_VTX_TEX0_COMP_CNT_SHIFT));
363 OUT_RING(DMA_PACKET0(R200_REG_PP_TXFILTER_0, 5));
364 OUT_RING_REG(R200_REG_PP_TXFILTER_0,
365 R200_MAG_FILTER_LINEAR |
366 R200_MIN_FILTER_LINEAR |
367 R200_YUV_TO_RGB);
368 OUT_RING_REG(R200_REG_PP_TXFORMAT_0, txformat);
369 OUT_RING_REG(R200_REG_PP_TXFORMAT_X_0, 0);
370 OUT_RING_REG(R200_REG_PP_TXSIZE_0,
371 (pPixmap->drawable.width - 1) |
372 ((pPixmap->drawable.height - 1) << RADEON_TEX_VSIZE_SHIFT));
373 OUT_RING_REG(R200_REG_PP_TXPITCH_0, pPortPriv->src_pitch - 32);
375 OUT_REG(R200_PP_TXOFFSET_0, pPortPriv->src_offset);
377 OUT_RING(DMA_PACKET0(R200_REG_PP_TXCBLEND_0, 4));
378 OUT_RING_REG(R200_REG_PP_TXCBLEND_0,
379 R200_TXC_ARG_A_ZERO |
380 R200_TXC_ARG_B_ZERO |
381 R200_TXC_ARG_C_R0_COLOR |
382 R200_TXC_OP_MADD);
383 OUT_RING_REG(R200_REG_PP_TXCBLEND2_0,
384 R200_TXC_CLAMP_0_1 | R200_TXC_OUTPUT_REG_R0);
385 OUT_RING_REG(R200_REG_PP_TXABLEND_0,
386 R200_TXA_ARG_A_ZERO |
387 R200_TXA_ARG_B_ZERO |
388 R200_TXA_ARG_C_R0_ALPHA |
389 R200_TXA_OP_MADD);
390 OUT_RING_REG(R200_REG_PP_TXABLEND2_0,
391 R200_TXA_CLAMP_0_1 | R200_TXA_OUTPUT_REG_R0);
393 END_DMA();
394 } else {
395 // BEGIN_DMA(11);
396 BEGIN_DMA(9);
398 OUT_RING(DMA_PACKET0(RADEON_REG_PP_TXFILTER_0, 5));
399 OUT_RING_REG(RADEON_REG_PP_TXFILTER_0, RADEON_MAG_FILTER_LINEAR |
400 RADEON_MIN_FILTER_LINEAR |
401 RADEON_YUV_TO_RGB);
402 OUT_RING_REG(RADEON_REG_PP_TXFORMAT_0, txformat);
403 OUT_RING_REG(RADEON_REG_PP_TXOFFSET_0, pPortPriv->src_offset);
404 OUT_RING_REG(RADEON_REG_PP_TXCBLEND_0,
405 RADEON_COLOR_ARG_A_ZERO |
406 RADEON_COLOR_ARG_B_ZERO |
407 RADEON_COLOR_ARG_C_T0_COLOR |
408 RADEON_BLEND_CTL_ADD |
409 RADEON_CLAMP_TX);
410 OUT_RING_REG(RADEON_REG_PP_TXABLEND_0,
411 RADEON_ALPHA_ARG_A_ZERO |
412 RADEON_ALPHA_ARG_B_ZERO |
413 RADEON_ALPHA_ARG_C_T0_ALPHA |
414 RADEON_BLEND_CTL_ADD |
415 RADEON_CLAMP_TX);
417 OUT_RING(DMA_PACKET0(RADEON_REG_PP_TEX_SIZE_0, 2));
418 OUT_RING_REG(RADEON_REG_PP_TEX_SIZE_0,
419 (pPixmap->drawable.width - 1) |
420 ((pPixmap->drawable.height - 1) << RADEON_TEX_VSIZE_SHIFT));
421 OUT_RING_REG(RADEON_REG_PP_TEX_PITCH_0,
422 pPortPriv->src_pitch - 32);
424 // OUT_RING_REG(ATI_REG_WAIT_UNTIL, ATI_WAIT_CRTC_VLINE);
426 END_DMA();
429 while (nBox--) {
430 float srcX, srcY, dstX, dstY, srcw, srch, dstw, dsth;
432 dstX = pBox->x1 + dstxoff;
433 dstY = pBox->y1 + dstyoff;
434 dstw = pBox->x2 - pBox->x1;
435 dsth = pBox->y2 - pBox->y1;
436 srcX = (pBox->x1 - pPortPriv->dst_x1) *
437 pPortPriv->src_w / pPortPriv->dst_w;
438 srcY = (pBox->y1 - pPortPriv->dst_y1) *
439 pPortPriv->src_h / pPortPriv->dst_h;
440 srcw = pPortPriv->src_w * (dstw / pPortPriv->dst_w);
441 srch = pPortPriv->src_h * (dsth / pPortPriv->dst_h);
444 * rectangle:
446 * +---------2
447 * | |
448 * | |
449 * 0---------1
452 vtx[0].x.f = dstX;
453 vtx[0].y.f = dstY + dsth;
454 vtx[0].s0.f = srcX;
455 vtx[0].t0.f = srcY + srch;
457 vtx[1].x.f = dstX + dstw;
458 vtx[1].y.f = dstY + dsth;
459 vtx[1].s0.f = srcX + srcw;
460 vtx[1].t0.f = srcY + srch;
462 vtx[2].x.f = dstX + dstw;
463 vtx[2].y.f = dstY;
464 vtx[2].s0.f = srcX + srcw;
465 vtx[2].t0.f = srcY;
467 if (atic->is_r100) {
468 BEGIN_DMA(3 * VTX_DWORD_COUNT + 3);
469 OUT_RING(DMA_PACKET3(RADEON_CP_PACKET3_3D_DRAW_IMMD,
470 3 * VTX_DWORD_COUNT + 2));
471 OUT_RING(RADEON_CP_VC_FRMT_XY |
472 RADEON_CP_VC_FRMT_ST0);
473 OUT_RING(RADEON_CP_VC_CNTL_PRIM_TYPE_RECT_LIST |
474 RADEON_CP_VC_CNTL_PRIM_WALK_RING |
475 RADEON_CP_VC_CNTL_MAOS_ENABLE |
476 RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE |
477 (3 << RADEON_CP_VC_CNTL_NUM_SHIFT));
478 } else {
479 BEGIN_DMA(3 * VTX_DWORD_COUNT + 2);
480 OUT_RING(DMA_PACKET3(R200_CP_PACKET3_3D_DRAW_IMMD_2,
481 3 * VTX_DWORD_COUNT + 1));
482 OUT_RING(RADEON_CP_VC_CNTL_PRIM_TYPE_RECT_LIST |
483 RADEON_CP_VC_CNTL_PRIM_WALK_RING |
484 (3 << RADEON_CP_VC_CNTL_NUM_SHIFT));
487 VTX_OUT(vtx[0]);
488 VTX_OUT(vtx[1]);
489 VTX_OUT(vtx[2]);
490 END_DMA();
492 pBox++;
494 #ifdef DAMAGEEXT
495 /* XXX: Shouldn't this be in kxv.c instead? */
496 DamageDamageRegion(pPortPriv->pDraw, &pPortPriv->clip);
497 #endif
498 kaaMarkSync(pScreen);
501 static void
502 ATIVideoSave(ScreenPtr pScreen, KdOffscreenArea *area)
504 KdScreenPriv(pScreen);
505 ATIScreenInfo(pScreenPriv);
506 ATIPortPrivPtr pPortPriv = atis->pAdaptor->pPortPrivates[0].ptr;
508 if (pPortPriv->off_screen == area)
509 pPortPriv->off_screen = 0;
512 static int
513 ATIPutImage(KdScreenInfo *screen, DrawablePtr pDraw,
514 short src_x, short src_y,
515 short drw_x, short drw_y,
516 short src_w, short src_h,
517 short drw_w, short drw_h,
518 int id,
519 unsigned char *buf,
520 short width,
521 short height,
522 Bool sync,
523 RegionPtr clipBoxes,
524 pointer data)
526 ScreenPtr pScreen = screen->pScreen;
527 KdScreenPriv(pScreen);
528 ATICardInfo(pScreenPriv);
529 ATIScreenInfo(pScreenPriv);
530 ATIPortPrivPtr pPortPriv = (ATIPortPrivPtr)data;
531 char *mmio = atic->reg_base;
532 INT32 x1, x2, y1, y2;
533 int randr = RR_Rotate_0 /* XXX */;
534 int srcPitch, srcPitch2, dstPitch;
535 int top, left, npixels, nlines, size;
536 BoxRec dstBox;
537 int dst_width = width, dst_height = height;
538 int rot_x1, rot_y1, rot_x2, rot_y2;
539 int dst_x1, dst_y1, dst_x2, dst_y2;
540 int rot_src_w, rot_src_h, rot_drw_w, rot_drw_h;
542 /* Clip */
543 x1 = src_x;
544 x2 = src_x + src_w;
545 y1 = src_y;
546 y2 = src_y + src_h;
548 dstBox.x1 = drw_x;
549 dstBox.x2 = drw_x + drw_w;
550 dstBox.y1 = drw_y;
551 dstBox.y2 = drw_y + drw_h;
553 ATIClipVideo(&dstBox, &x1, &x2, &y1, &y2,
554 REGION_EXTENTS(pScreen, clipBoxes), width, height);
556 src_w = (x2 - x1) >> 16;
557 src_h = (y2 - y1) >> 16;
558 drw_w = dstBox.x2 - dstBox.x1;
559 drw_h = dstBox.y2 - dstBox.y1;
561 if ((x1 >= x2) || (y1 >= y2))
562 return Success;
564 if (mmio == NULL)
565 return BadAlloc;
567 if (randr & (RR_Rotate_0|RR_Rotate_180)) {
568 dst_width = width;
569 dst_height = height;
570 rot_src_w = src_w;
571 rot_src_h = src_h;
572 rot_drw_w = drw_w;
573 rot_drw_h = drw_h;
574 } else {
575 dst_width = height;
576 dst_height = width;
577 rot_src_w = src_h;
578 rot_src_h = src_w;
579 rot_drw_w = drw_h;
580 rot_drw_h = drw_w;
583 switch (randr & RR_Rotate_All) {
584 case RR_Rotate_0:
585 default:
586 dst_x1 = dstBox.x1;
587 dst_y1 = dstBox.y1;
588 dst_x2 = dstBox.x2;
589 dst_y2 = dstBox.y2;
590 rot_x1 = x1;
591 rot_y1 = y1;
592 rot_x2 = x2;
593 rot_y2 = y2;
594 break;
595 case RR_Rotate_90:
596 dst_x1 = dstBox.y1;
597 dst_y1 = screen->height - dstBox.x2;
598 dst_x2 = dstBox.y2;
599 dst_y2 = screen->height - dstBox.x1;
600 rot_x1 = y1;
601 rot_y1 = (src_w << 16) - x2;
602 rot_x2 = y2;
603 rot_y2 = (src_w << 16) - x1;
604 break;
605 case RR_Rotate_180:
606 dst_x1 = screen->width - dstBox.x2;
607 dst_y1 = screen->height - dstBox.y2;
608 dst_x2 = screen->width - dstBox.x1;
609 dst_y2 = screen->height - dstBox.y1;
610 rot_x1 = (src_w << 16) - x2;
611 rot_y1 = (src_h << 16) - y2;
612 rot_x2 = (src_w << 16) - x1;
613 rot_y2 = (src_h << 16) - y1;
614 break;
615 case RR_Rotate_270:
616 dst_x1 = screen->width - dstBox.y2;
617 dst_y1 = dstBox.x1;
618 dst_x2 = screen->width - dstBox.y1;
619 dst_y2 = dstBox.x2;
620 rot_x1 = (src_h << 16) - y2;
621 rot_y1 = x1;
622 rot_x2 = (src_h << 16) - y1;
623 rot_y2 = x2;
624 break;
627 switch(id) {
628 case FOURCC_YV12:
629 case FOURCC_I420:
630 dstPitch = ((dst_width << 1) + 15) & ~15;
631 srcPitch = (width + 3) & ~3;
632 srcPitch2 = ((width >> 1) + 3) & ~3;
633 size = dstPitch * dst_height;
634 break;
635 case FOURCC_UYVY:
636 case FOURCC_YUY2:
637 default:
638 dstPitch = ((dst_width << 1) + 15) & ~15;
639 srcPitch = (width << 1);
640 srcPitch2 = 0;
641 size = dstPitch * dst_height;
642 break;
645 if (pPortPriv->off_screen != NULL && size != pPortPriv->size) {
646 KdOffscreenFree(screen->pScreen, pPortPriv->off_screen);
647 pPortPriv->off_screen = 0;
650 if (pPortPriv->off_screen == NULL) {
651 pPortPriv->off_screen = KdOffscreenAlloc(screen->pScreen,
652 size * 2, 64, TRUE, ATIVideoSave, pPortPriv);
653 if (pPortPriv->off_screen == NULL)
654 return BadAlloc;
658 if (pDraw->type == DRAWABLE_WINDOW)
659 pPortPriv->pPixmap =
660 (*pScreen->GetWindowPixmap)((WindowPtr)pDraw);
661 else
662 pPortPriv->pPixmap = (PixmapPtr)pDraw;
664 /* Migrate the pixmap to offscreen if necessary. */
665 if (!kaaPixmapIsOffscreen(pPortPriv->pPixmap))
666 kaaMoveInPixmap(pPortPriv->pPixmap);
668 if (!kaaPixmapIsOffscreen(pPortPriv->pPixmap)) {
669 return BadAlloc;
672 pPortPriv->src_offset = pPortPriv->off_screen->offset;
673 pPortPriv->src_addr = (CARD8 *)(pScreenPriv->screen->memory_base +
674 pPortPriv->src_offset);
675 pPortPriv->src_pitch = dstPitch;
676 pPortPriv->size = size;
677 pPortPriv->pDraw = pDraw;
679 /* copy data */
680 top = rot_y1 >> 16;
681 left = (rot_x1 >> 16) & ~1;
682 npixels = ((((rot_x2 + 0xffff) >> 16) + 1) & ~1) - left;
684 /* Since we're probably overwriting the area that might still be used
685 * for the last PutImage request, wait for idle.
687 ATIWaitIdle(atis);
689 switch(id) {
690 case FOURCC_YV12:
691 case FOURCC_I420:
692 top &= ~1;
693 nlines = ((((rot_y2 + 0xffff) >> 16) + 1) & ~1) - top;
694 KdXVCopyPlanarData(screen, buf, pPortPriv->src_addr, randr,
695 srcPitch, srcPitch2, dstPitch, rot_src_w, rot_src_h,
696 height, top, left, nlines, npixels, id);
697 break;
698 case FOURCC_UYVY:
699 case FOURCC_YUY2:
700 default:
701 nlines = ((rot_y2 + 0xffff) >> 16) - top;
702 KdXVCopyPackedData(screen, buf, pPortPriv->src_addr, randr,
703 srcPitch, dstPitch, rot_src_w, rot_src_h, top, left,
704 nlines, npixels);
705 break;
708 /* update cliplist */
709 if (!REGION_EQUAL(screen->pScreen, &pPortPriv->clip, clipBoxes)) {
710 REGION_COPY(screen->pScreen, &pPortPriv->clip, clipBoxes);
713 pPortPriv->id = id;
714 pPortPriv->src_x1 = rot_x1;
715 pPortPriv->src_y1 = rot_y1;
716 pPortPriv->src_x2 = rot_x2;
717 pPortPriv->src_y2 = rot_y2;
718 pPortPriv->src_w = rot_src_w;
719 pPortPriv->src_h = rot_src_h;
720 pPortPriv->dst_x1 = dst_x1;
721 pPortPriv->dst_y1 = dst_y1;
722 pPortPriv->dst_x2 = dst_x2;
723 pPortPriv->dst_y2 = dst_y2;
724 pPortPriv->dst_w = rot_drw_w;
725 pPortPriv->dst_h = rot_drw_h;
727 if (atic->is_radeon)
728 RadeonDisplayVideo(screen, pPortPriv);
729 else
730 R128DisplayVideo(screen, pPortPriv);
732 return Success;
735 static int
736 ATIReputImage(KdScreenInfo *screen, DrawablePtr pDraw, short drw_x, short drw_y,
737 RegionPtr clipBoxes, pointer data)
739 ScreenPtr pScreen = screen->pScreen;
740 KdScreenPriv(pScreen);
741 ATICardInfo(pScreenPriv);
742 ATIPortPrivPtr pPortPriv = (ATIPortPrivPtr)data;
743 BoxPtr pOldExtents = REGION_EXTENTS(screen->pScreen, &pPortPriv->clip);
744 BoxPtr pNewExtents = REGION_EXTENTS(screen->pScreen, clipBoxes);
746 if (pOldExtents->x1 != pNewExtents->x1 ||
747 pOldExtents->x2 != pNewExtents->x2 ||
748 pOldExtents->y1 != pNewExtents->y1 ||
749 pOldExtents->y2 != pNewExtents->y2)
750 return BadMatch;
752 if (pDraw->type == DRAWABLE_WINDOW)
753 pPortPriv->pPixmap =
754 (*pScreen->GetWindowPixmap)((WindowPtr)pDraw);
755 else
756 pPortPriv->pPixmap = (PixmapPtr)pDraw;
758 if (!kaaPixmapIsOffscreen(pPortPriv->pPixmap))
759 kaaMoveInPixmap(pPortPriv->pPixmap);
761 if (!kaaPixmapIsOffscreen(pPortPriv->pPixmap)) {
762 ErrorF("err\n");
763 return BadAlloc;
767 /* update cliplist */
768 if (!REGION_EQUAL(screen->pScreen, &pPortPriv->clip, clipBoxes))
769 REGION_COPY(screen->pScreen, &pPortPriv->clip, clipBoxes);
771 /* XXX: What do the drw_x and drw_y here mean for us? */
773 if (atic->is_radeon)
774 RadeonDisplayVideo(screen, pPortPriv);
775 else
776 R128DisplayVideo(screen, pPortPriv);
778 return Success;
781 static int
782 ATIQueryImageAttributes(KdScreenInfo *screen, int id, unsigned short *w,
783 unsigned short *h, int *pitches, int *offsets)
785 int size, tmp;
787 if (*w > IMAGE_MAX_WIDTH)
788 *w = IMAGE_MAX_WIDTH;
789 if (*h > IMAGE_MAX_HEIGHT)
790 *h = IMAGE_MAX_HEIGHT;
792 *w = (*w + 1) & ~1;
793 if (offsets)
794 offsets[0] = 0;
796 switch (id)
798 case FOURCC_YV12:
799 case FOURCC_I420:
800 *h = (*h + 1) & ~1;
801 size = (*w + 3) & ~3;
802 if (pitches)
803 pitches[0] = size;
804 size *= *h;
805 if (offsets)
806 offsets[1] = size;
807 tmp = ((*w >> 1) + 3) & ~3;
808 if (pitches)
809 pitches[1] = pitches[2] = tmp;
810 tmp *= (*h >> 1);
811 size += tmp;
812 if (offsets)
813 offsets[2] = size;
814 size += tmp;
815 break;
816 case FOURCC_UYVY:
817 case FOURCC_YUY2:
818 default:
819 size = *w << 1;
820 if (pitches)
821 pitches[0] = size;
822 size *= *h;
823 break;
826 return size;
830 /* client libraries expect an encoding */
831 static KdVideoEncodingRec DummyEncoding[1] =
835 "XV_IMAGE",
836 IMAGE_MAX_WIDTH, IMAGE_MAX_HEIGHT,
837 {1, 1}
841 #define NUM_FORMATS 3
843 static KdVideoFormatRec Formats[NUM_FORMATS] =
845 {15, TrueColor}, {16, TrueColor}, {24, TrueColor}
848 #define NUM_ATTRIBUTES 0
850 static KdAttributeRec Attributes[NUM_ATTRIBUTES] =
854 #define NUM_IMAGES 4
856 static KdImageRec Images[NUM_IMAGES] =
858 XVIMAGE_YUY2,
859 XVIMAGE_YV12,
860 XVIMAGE_I420,
861 XVIMAGE_UYVY
864 static KdVideoAdaptorPtr
865 ATISetupImageVideo(ScreenPtr pScreen)
867 KdScreenPriv(pScreen);
868 ATIScreenInfo(pScreenPriv);
869 KdVideoAdaptorPtr adapt;
870 ATIPortPrivPtr pPortPriv;
871 int i;
873 atis->num_texture_ports = 16;
875 adapt = xcalloc(1, sizeof(KdVideoAdaptorRec) + atis->num_texture_ports *
876 (sizeof(ATIPortPrivRec) + sizeof(DevUnion)));
877 if (adapt == NULL)
878 return NULL;
880 adapt->type = XvWindowMask | XvInputMask | XvImageMask;
881 adapt->flags = VIDEO_CLIP_TO_VIEWPORT;
882 adapt->name = "ATI Texture Video";
883 adapt->nEncodings = 1;
884 adapt->pEncodings = DummyEncoding;
885 adapt->nFormats = NUM_FORMATS;
886 adapt->pFormats = Formats;
887 adapt->nPorts = atis->num_texture_ports;
888 adapt->pPortPrivates = (DevUnion*)(&adapt[1]);
890 pPortPriv =
891 (ATIPortPrivPtr)(&adapt->pPortPrivates[atis->num_texture_ports]);
893 for (i = 0; i < atis->num_texture_ports; i++)
894 adapt->pPortPrivates[i].ptr = &pPortPriv[i];
896 adapt->nAttributes = NUM_ATTRIBUTES;
897 adapt->pAttributes = Attributes;
898 adapt->pImages = Images;
899 adapt->nImages = NUM_IMAGES;
900 adapt->PutVideo = NULL;
901 adapt->PutStill = NULL;
902 adapt->GetVideo = NULL;
903 adapt->GetStill = NULL;
904 adapt->StopVideo = ATIStopVideo;
905 adapt->SetPortAttribute = ATISetPortAttribute;
906 adapt->GetPortAttribute = ATIGetPortAttribute;
907 adapt->QueryBestSize = ATIQueryBestSize;
908 adapt->PutImage = ATIPutImage;
909 adapt->ReputImage = ATIReputImage;
910 adapt->QueryImageAttributes = ATIQueryImageAttributes;
912 /* gotta uninit this someplace */
913 REGION_INIT(pScreen, &pPortPriv->clip, NullBox, 0);
915 atis->pAdaptor = adapt;
917 xvBrightness = MAKE_ATOM("XV_BRIGHTNESS");
918 xvSaturation = MAKE_ATOM("XV_SATURATION");
920 return adapt;
923 Bool ATIInitVideo(ScreenPtr pScreen)
925 KdScreenPriv(pScreen);
926 ATIScreenInfo(pScreenPriv);
927 ATICardInfo(pScreenPriv);
928 KdScreenInfo *screen = pScreenPriv->screen;
929 KdVideoAdaptorPtr *adaptors, *newAdaptors = NULL;
930 KdVideoAdaptorPtr newAdaptor = NULL;
931 int num_adaptors;
933 atis->pAdaptor = NULL;
935 if (atic->reg_base == NULL)
936 return FALSE;
937 if (atic->is_r300)
938 return FALSE;
940 num_adaptors = KdXVListGenericAdaptors(screen, &adaptors);
942 newAdaptor = ATISetupImageVideo(pScreen);
944 if (newAdaptor) {
945 if (!num_adaptors) {
946 num_adaptors = 1;
947 adaptors = &newAdaptor;
948 } else {
949 newAdaptors = xalloc((num_adaptors + 1) *
950 sizeof(KdVideoAdaptorPtr *));
951 if (newAdaptors) {
952 memcpy(newAdaptors, adaptors, num_adaptors *
953 sizeof(KdVideoAdaptorPtr));
954 newAdaptors[num_adaptors] = newAdaptor;
955 adaptors = newAdaptors;
956 num_adaptors++;
961 if (num_adaptors)
962 KdXVScreenInit(pScreen, adaptors, num_adaptors);
964 if (newAdaptors)
965 xfree(newAdaptors);
967 return TRUE;
970 void
971 ATIFiniVideo(ScreenPtr pScreen)
973 KdScreenPriv(pScreen);
974 ATIScreenInfo(pScreenPriv);
975 KdVideoAdaptorPtr adapt = atis->pAdaptor;
976 ATIPortPrivPtr pPortPriv;
977 int i;
979 if (!adapt)
980 return;
982 for (i = 0; i < atis->num_texture_ports; i++) {
983 pPortPriv = (ATIPortPrivPtr)(&adapt->pPortPrivates[i].ptr);
984 REGION_UNINIT(pScreen, &pPortPriv->clip);
986 xfree(adapt);
987 atis->pAdaptor = NULL;