#ifdef HAVE_CONFIG_H
#include <kdrive-config.h>
#endif
#include "ati.h"
#include "ati_dma.h"
#include "ati_draw.h"
#include "ati_reg.h"
#include "kaa.h"
#include <X11/extensions/Xv.h>
#include "fourcc.h"
#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)
static Atom xvBrightness, xvSaturation;
extern CARD8 ATIBltRop[16];
#define IMAGE_MAX_WIDTH 2048
#define IMAGE_MAX_HEIGHT 2048
static void
ATIStopVideo(KdScreenInfo *screen, pointer data, Bool exit)
{
ScreenPtr pScreen = screen->pScreen;
ATIPortPrivPtr pPortPriv = (ATIPortPrivPtr)data;
REGION_EMPTY(screen->pScreen, &pPortPriv->clip);
if (pPortPriv->off_screen) {
KdOffscreenFree (pScreen, pPortPriv->off_screen);
pPortPriv->off_screen = 0;
}
}
static int
ATISetPortAttribute(KdScreenInfo *screen, Atom attribute, int value,
pointer data)
{
return BadMatch;
}
static int
ATIGetPortAttribute(KdScreenInfo *screen, Atom attribute, int *value,
pointer data)
{
return BadMatch;
}
static void
ATIQueryBestSize(KdScreenInfo *screen, Bool motion, short vid_w, short vid_h,
short drw_w, short drw_h, unsigned int *p_w, unsigned int *p_h,
pointer data)
{
*p_w = drw_w;
*p_h = drw_h;
}
static void
ATIClipVideo(BoxPtr dst, INT32 *x1, INT32 *x2, INT32 *y1, INT32 *y2,
BoxPtr extents, INT32 width, INT32 height)
{
INT32 vscale, hscale, delta;
int diff;
hscale = ((*x2 - *x1) << 16) / (dst->x2 - dst->x1);
vscale = ((*y2 - *y1) << 16) / (dst->y2 - dst->y1);
*x1 <<= 16; *x2 <<= 16;
*y1 <<= 16; *y2 <<= 16;
diff = extents->x1 - dst->x1;
if (diff > 0) {
dst->x1 = extents->x1;
*x1 += diff * hscale;
}
diff = dst->x2 - extents->x2;
if (diff > 0) {
dst->x2 = extents->x2;
*x2 -= diff * hscale;
}
diff = extents->y1 - dst->y1;
if (diff > 0) {
dst->y1 = extents->y1;
*y1 += diff * vscale;
}
diff = dst->y2 - extents->y2;
if (diff > 0) {
dst->y2 = extents->y2;
*y2 -= diff * vscale;
}
if (*x1 < 0) {
diff = (- *x1 + hscale - 1)/ hscale;
dst->x1 += diff;
*x1 += diff * hscale;
}
delta = *x2 - (width << 16);
if (delta > 0) {
diff = (delta + hscale - 1)/ hscale;
dst->x2 -= diff;
*x2 -= diff * hscale;
}
if (*y1 < 0) {
diff = (- *y1 + vscale - 1)/ vscale;
dst->y1 += diff;
*y1 += diff * vscale;
}
delta = *y2 - (height << 16);
if (delta > 0) {
diff = (delta + vscale - 1)/ vscale;
dst->y2 -= diff;
*y2 -= diff * vscale;
}
}
static void
R128DisplayVideo(KdScreenInfo *screen, ATIPortPrivPtr pPortPriv)
{
ScreenPtr pScreen = screen->pScreen;
KdScreenPriv(pScreen);
ATIScreenInfo(pScreenPriv);
CARD32 dstDatatype, srcDatatype;
CARD32 dst_offset, dst_pitch;
int dstxoff, dstyoff;
PixmapPtr pPixmap = pPortPriv->pPixmap;
int bpp = pPixmap->drawable.bitsPerPixel;
RING_LOCALS;
BoxPtr pBox = REGION_RECTS(&pPortPriv->clip);
int nBox = REGION_NUM_RECTS(&pPortPriv->clip);
if (pPortPriv->id == FOURCC_UYVY)
srcDatatype = R128_DATATYPE_YVYU_422;
else
srcDatatype = R128_DATATYPE_VYUY_422;
switch (bpp)
{
case 16:
if (pPixmap->drawable.depth == 15)
dstDatatype = R128_DATATYPE_ARGB1555;
else
dstDatatype = R128_DATATYPE_RGB565;
break;
case 32:
dstDatatype = R128_DATATYPE_ARGB8888;
break;
default:
return;
}
dst_offset = ((CARD8 *)pPixmap->devPrivate.ptr -
pScreenPriv->screen->memory_base);
dst_pitch = pPixmap->devKind;
#ifdef COMPOSITE
dstxoff = -pPixmap->screen_x + pPixmap->drawable.x;
dstyoff = -pPixmap->screen_y + pPixmap->drawable.y;
#else
dstxoff = 0;
dstyoff = 0;
#endif
BEGIN_DMA(18);
OUT_REG(ATI_REG_DST_PITCH_OFFSET,
((dst_pitch / bpp) << 21) | (dst_offset >> 5));
OUT_REG(ATI_REG_DP_GUI_MASTER_CNTL,
ATI_GMC_DST_PITCH_OFFSET_CNTL |
ATI_GMC_BRUSH_NONE |
(dstDatatype << 8) |
ATI_GMC_SRC_DATATYPE_COLOR |
(ATIBltRop[GXcopy] << 16) |
R128_GMC_3D_FCN_EN |
ATI_GMC_CLR_CMP_CNTL_DIS |
R128_GMC_AUX_CLIP_DIS);
OUT_REG(ATI_REG_DP_CNTL,
ATI_DST_X_LEFT_TO_RIGHT | ATI_DST_Y_TOP_TO_BOTTOM );
OUT_REG(R128_REG_SCALE_3D_CNTL,
R128_SCALE_3D_SCALE |
R128_SBLEND_ONE |
R128_DBLEND_ZERO);
OUT_REG(R128_REG_TEX_CNTL_C, R128_TEX_CACHE_FLUSH);
OUT_REG(R128_REG_SCALE_3D_DATATYPE, srcDatatype);
OUT_RING(DMA_PACKET0(R128_REG_SCALE_PITCH, 5));
OUT_RING_REG(R128_REG_SCALE_PITCH, pPortPriv->src_pitch / 16);
OUT_RING_REG(R128_REG_SCALE_X_INC,
(pPortPriv->src_w << 16) / pPortPriv->dst_w);
OUT_RING_REG(R128_REG_SCALE_Y_INC,
(pPortPriv->src_h << 16) / pPortPriv->dst_h);
OUT_RING_REG(R128_REG_SCALE_HACC, 0x0);
OUT_RING_REG(R128_REG_SCALE_VACC, 0x0);
END_DMA();
while (nBox--) {
int srcX, srcY, dstX, dstY, srcw, srch, dstw, dsth;
dstX = pBox->x1 + dstxoff;
dstY = pBox->y1 + dstyoff;
dstw = pBox->x2 - pBox->x1;
dsth = pBox->y2 - pBox->y1;
srcX = (pBox->x1 - pPortPriv->dst_x1) *
pPortPriv->src_w / pPortPriv->dst_w;
srcY = (pBox->y1 - pPortPriv->dst_y1) *
pPortPriv->src_h / pPortPriv->dst_h;
srcw = pPortPriv->src_w - srcX;
srch = pPortPriv->src_h - srcY;
BEGIN_DMA(6);
OUT_RING(DMA_PACKET0(R128_REG_SCALE_SRC_HEIGHT_WIDTH, 2));
OUT_RING_REG(R128_REG_SCALE_SRC_HEIGHT_WIDTH,
(srch << 16) | srcw);
OUT_RING_REG(R128_REG_SCALE_OFFSET_0, pPortPriv->src_offset +
srcY * pPortPriv->src_pitch + srcX * 2);
OUT_RING(DMA_PACKET0(R128_REG_SCALE_DST_X_Y, 2));
OUT_RING_REG(R128_REG_SCALE_DST_X_Y, (dstX << 16) | dstY);
OUT_RING_REG(R128_REG_SCALE_DST_HEIGHT_WIDTH,
(dsth << 16) | dstw);
END_DMA();
pBox++;
}
#ifdef DAMAGEEXT
DamageDamageRegion(pPortPriv->pDraw, &pPortPriv->clip);
#endif
kaaMarkSync(pScreen);
}
union intfloat {
float f;
CARD32 i;
};
struct blend_vertex {
union intfloat x, y;
union intfloat s0, t0;
};
#define VTX_DWORD_COUNT 4
#define VTX_OUT(vtx) \
do { \
OUT_RING(vtx.x.i); \
OUT_RING(vtx.y.i); \
OUT_RING(vtx.s0.i); \
OUT_RING(vtx.t0.i); \
} while (0)
static void
RadeonDisplayVideo(KdScreenInfo *screen, ATIPortPrivPtr pPortPriv)
{
ScreenPtr pScreen = screen->pScreen;
KdScreenPriv(pScreen);
ATICardInfo(pScreenPriv);
ATIScreenInfo(pScreenPriv);
struct blend_vertex vtx[4];
PixmapPtr pPixmap = pPortPriv->pPixmap;
CARD32 txformat;
CARD32 dst_offset, dst_pitch, dst_format;
int dstxoff, dstyoff, pixel_shift;
RING_LOCALS;
BoxPtr pBox = REGION_RECTS(&pPortPriv->clip);
int nBox = REGION_NUM_RECTS(&pPortPriv->clip);
switch (pPixmap->drawable.bitsPerPixel) {
case 16:
if (pPixmap->drawable.depth == 15)
dst_format = RADEON_COLOR_FORMAT_ARGB1555;
else
dst_format = RADEON_COLOR_FORMAT_RGB565;
pixel_shift = 1;
break;
case 32:
dst_format = RADEON_COLOR_FORMAT_ARGB8888;
pixel_shift = 2;
break;
default:
return;
}
dst_offset = ((CARD8 *)pPixmap->devPrivate.ptr -
pScreenPriv->screen->memory_base);
dst_pitch = pPixmap->devKind;
#ifdef COMPOSITE
dstxoff = -pPixmap->screen_x + pPixmap->drawable.x;
dstyoff = -pPixmap->screen_y + pPixmap->drawable.y;
#else
dstxoff = 0;
dstyoff = 0;
#endif
if (pPortPriv->id == FOURCC_UYVY)
txformat = RADEON_TXFORMAT_YVYU422;
else
txformat = RADEON_TXFORMAT_VYUY422;
txformat |= RADEON_TXFORMAT_NON_POWER2;
RadeonSwitchTo3D(atis);
BEGIN_DMA(8);
OUT_RING(DMA_PACKET0(RADEON_REG_PP_CNTL, 3));
OUT_RING_REG(RADEON_REG_PP_CNTL,
RADEON_TEX_0_ENABLE | RADEON_TEX_BLEND_0_ENABLE);
OUT_RING_REG(RADEON_REG_RB3D_CNTL,
dst_format | RADEON_ALPHA_BLEND_ENABLE);
OUT_RING_REG(RADEON_REG_RB3D_COLOROFFSET, dst_offset);
OUT_REG(RADEON_REG_RB3D_COLORPITCH, dst_pitch >> pixel_shift);
OUT_REG(RADEON_REG_RB3D_BLENDCNTL,
RADEON_SBLEND_GL_ONE | RADEON_DBLEND_GL_ZERO);
END_DMA();
if (atic->is_r200) {
BEGIN_DMA(17);
OUT_REG(R200_REG_SE_VTX_FMT_0, R200_VTX_XY);
OUT_REG(R200_REG_SE_VTX_FMT_1,
(2 << R200_VTX_TEX0_COMP_CNT_SHIFT));
OUT_RING(DMA_PACKET0(R200_REG_PP_TXFILTER_0, 5));
OUT_RING_REG(R200_REG_PP_TXFILTER_0,
R200_MAG_FILTER_LINEAR |
R200_MIN_FILTER_LINEAR |
R200_YUV_TO_RGB);
OUT_RING_REG(R200_REG_PP_TXFORMAT_0, txformat);
OUT_RING_REG(R200_REG_PP_TXFORMAT_X_0, 0);
OUT_RING_REG(R200_REG_PP_TXSIZE_0,
(pPixmap->drawable.width - 1) |
((pPixmap->drawable.height - 1) << RADEON_TEX_VSIZE_SHIFT));
OUT_RING_REG(R200_REG_PP_TXPITCH_0, pPortPriv->src_pitch - 32);
OUT_REG(R200_PP_TXOFFSET_0, pPortPriv->src_offset);
OUT_RING(DMA_PACKET0(R200_REG_PP_TXCBLEND_0, 4));
OUT_RING_REG(R200_REG_PP_TXCBLEND_0,
R200_TXC_ARG_A_ZERO |
R200_TXC_ARG_B_ZERO |
R200_TXC_ARG_C_R0_COLOR |
R200_TXC_OP_MADD);
OUT_RING_REG(R200_REG_PP_TXCBLEND2_0,
R200_TXC_CLAMP_0_1 | R200_TXC_OUTPUT_REG_R0);
OUT_RING_REG(R200_REG_PP_TXABLEND_0,
R200_TXA_ARG_A_ZERO |
R200_TXA_ARG_B_ZERO |
R200_TXA_ARG_C_R0_ALPHA |
R200_TXA_OP_MADD);
OUT_RING_REG(R200_REG_PP_TXABLEND2_0,
R200_TXA_CLAMP_0_1 | R200_TXA_OUTPUT_REG_R0);
END_DMA();
} else {
BEGIN_DMA(9);
OUT_RING(DMA_PACKET0(RADEON_REG_PP_TXFILTER_0, 5));
OUT_RING_REG(RADEON_REG_PP_TXFILTER_0, RADEON_MAG_FILTER_LINEAR |
RADEON_MIN_FILTER_LINEAR |
RADEON_YUV_TO_RGB);
OUT_RING_REG(RADEON_REG_PP_TXFORMAT_0, txformat);
OUT_RING_REG(RADEON_REG_PP_TXOFFSET_0, pPortPriv->src_offset);
OUT_RING_REG(RADEON_REG_PP_TXCBLEND_0,
RADEON_COLOR_ARG_A_ZERO |
RADEON_COLOR_ARG_B_ZERO |
RADEON_COLOR_ARG_C_T0_COLOR |
RADEON_BLEND_CTL_ADD |
RADEON_CLAMP_TX);
OUT_RING_REG(RADEON_REG_PP_TXABLEND_0,
RADEON_ALPHA_ARG_A_ZERO |
RADEON_ALPHA_ARG_B_ZERO |
RADEON_ALPHA_ARG_C_T0_ALPHA |
RADEON_BLEND_CTL_ADD |
RADEON_CLAMP_TX);
OUT_RING(DMA_PACKET0(RADEON_REG_PP_TEX_SIZE_0, 2));
OUT_RING_REG(RADEON_REG_PP_TEX_SIZE_0,
(pPixmap->drawable.width - 1) |
((pPixmap->drawable.height - 1) << RADEON_TEX_VSIZE_SHIFT));
OUT_RING_REG(RADEON_REG_PP_TEX_PITCH_0,
pPortPriv->src_pitch - 32);
END_DMA();
}
while (nBox--) {
float srcX, srcY, dstX, dstY, srcw, srch, dstw, dsth;
dstX = pBox->x1 + dstxoff;
dstY = pBox->y1 + dstyoff;
dstw = pBox->x2 - pBox->x1;
dsth = pBox->y2 - pBox->y1;
srcX = (pBox->x1 - pPortPriv->dst_x1) *
pPortPriv->src_w / pPortPriv->dst_w;
srcY = (pBox->y1 - pPortPriv->dst_y1) *
pPortPriv->src_h / pPortPriv->dst_h;
srcw = pPortPriv->src_w * (dstw / pPortPriv->dst_w);
srch = pPortPriv->src_h * (dsth / pPortPriv->dst_h);
vtx[0].x.f = dstX;
vtx[0].y.f = dstY + dsth;
vtx[0].s0.f = srcX;
vtx[0].t0.f = srcY + srch;
vtx[1].x.f = dstX + dstw;
vtx[1].y.f = dstY + dsth;
vtx[1].s0.f = srcX + srcw;
vtx[1].t0.f = srcY + srch;
vtx[2].x.f = dstX + dstw;
vtx[2].y.f = dstY;
vtx[2].s0.f = srcX + srcw;
vtx[2].t0.f = srcY;
if (atic->is_r100) {
BEGIN_DMA(3 * VTX_DWORD_COUNT + 3);
OUT_RING(DMA_PACKET3(RADEON_CP_PACKET3_3D_DRAW_IMMD,
3 * VTX_DWORD_COUNT + 2));
OUT_RING(RADEON_CP_VC_FRMT_XY |
RADEON_CP_VC_FRMT_ST0);
OUT_RING(RADEON_CP_VC_CNTL_PRIM_TYPE_RECT_LIST |
RADEON_CP_VC_CNTL_PRIM_WALK_RING |
RADEON_CP_VC_CNTL_MAOS_ENABLE |
RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE |
(3 << RADEON_CP_VC_CNTL_NUM_SHIFT));
} else {
BEGIN_DMA(3 * VTX_DWORD_COUNT + 2);
OUT_RING(DMA_PACKET3(R200_CP_PACKET3_3D_DRAW_IMMD_2,
3 * VTX_DWORD_COUNT + 1));
OUT_RING(RADEON_CP_VC_CNTL_PRIM_TYPE_RECT_LIST |
RADEON_CP_VC_CNTL_PRIM_WALK_RING |
(3 << RADEON_CP_VC_CNTL_NUM_SHIFT));
}
VTX_OUT(vtx[0]);
VTX_OUT(vtx[1]);
VTX_OUT(vtx[2]);
END_DMA();
pBox++;
}
#ifdef DAMAGEEXT
DamageDamageRegion(pPortPriv->pDraw, &pPortPriv->clip);
#endif
kaaMarkSync(pScreen);
}
static void
ATIVideoSave(ScreenPtr pScreen, KdOffscreenArea *area)
{
KdScreenPriv(pScreen);
ATIScreenInfo(pScreenPriv);
ATIPortPrivPtr pPortPriv = atis->pAdaptor->pPortPrivates[0].ptr;
if (pPortPriv->off_screen == area)
pPortPriv->off_screen = 0;
}
static int
ATIPutImage(KdScreenInfo *screen, DrawablePtr pDraw,
short src_x, short src_y,
short drw_x, short drw_y,
short src_w, short src_h,
short drw_w, short drw_h,
int id,
unsigned char *buf,
short width,
short height,
Bool sync,
RegionPtr clipBoxes,
pointer data)
{
ScreenPtr pScreen = screen->pScreen;
KdScreenPriv(pScreen);
ATICardInfo(pScreenPriv);
ATIScreenInfo(pScreenPriv);
ATIPortPrivPtr pPortPriv = (ATIPortPrivPtr)data;
char *mmio = atic->reg_base;
INT32 x1, x2, y1, y2;
int randr = RR_Rotate_0 ;
int srcPitch, srcPitch2, dstPitch;
int top, left, npixels, nlines, size;
BoxRec dstBox;
int dst_width = width, dst_height = height;
int rot_x1, rot_y1, rot_x2, rot_y2;
int dst_x1, dst_y1, dst_x2, dst_y2;
int rot_src_w, rot_src_h, rot_drw_w, rot_drw_h;
x1 = src_x;
x2 = src_x + src_w;
y1 = src_y;
y2 = src_y + src_h;
dstBox.x1 = drw_x;
dstBox.x2 = drw_x + drw_w;
dstBox.y1 = drw_y;
dstBox.y2 = drw_y + drw_h;
ATIClipVideo(&dstBox, &x1, &x2, &y1, &y2,
REGION_EXTENTS(pScreen, clipBoxes), width, height);
src_w = (x2 - x1) >> 16;
src_h = (y2 - y1) >> 16;
drw_w = dstBox.x2 - dstBox.x1;
drw_h = dstBox.y2 - dstBox.y1;
if ((x1 >= x2) || (y1 >= y2))
return Success;
if (mmio == NULL)
return BadAlloc;
if (randr & (RR_Rotate_0|RR_Rotate_180)) {
dst_width = width;
dst_height = height;
rot_src_w = src_w;
rot_src_h = src_h;
rot_drw_w = drw_w;
rot_drw_h = drw_h;
} else {
dst_width = height;
dst_height = width;
rot_src_w = src_h;
rot_src_h = src_w;
rot_drw_w = drw_h;
rot_drw_h = drw_w;
}
switch (randr & RR_Rotate_All) {
case RR_Rotate_0:
default:
dst_x1 = dstBox.x1;
dst_y1 = dstBox.y1;
dst_x2 = dstBox.x2;
dst_y2 = dstBox.y2;
rot_x1 = x1;
rot_y1 = y1;
rot_x2 = x2;
rot_y2 = y2;
break;
case RR_Rotate_90:
dst_x1 = dstBox.y1;
dst_y1 = screen->height - dstBox.x2;
dst_x2 = dstBox.y2;
dst_y2 = screen->height - dstBox.x1;
rot_x1 = y1;
rot_y1 = (src_w << 16) - x2;
rot_x2 = y2;
rot_y2 = (src_w << 16) - x1;
break;
case RR_Rotate_180:
dst_x1 = screen->width - dstBox.x2;
dst_y1 = screen->height - dstBox.y2;
dst_x2 = screen->width - dstBox.x1;
dst_y2 = screen->height - dstBox.y1;
rot_x1 = (src_w << 16) - x2;
rot_y1 = (src_h << 16) - y2;
rot_x2 = (src_w << 16) - x1;
rot_y2 = (src_h << 16) - y1;
break;
case RR_Rotate_270:
dst_x1 = screen->width - dstBox.y2;
dst_y1 = dstBox.x1;
dst_x2 = screen->width - dstBox.y1;
dst_y2 = dstBox.x2;
rot_x1 = (src_h << 16) - y2;
rot_y1 = x1;
rot_x2 = (src_h << 16) - y1;
rot_y2 = x2;
break;
}
switch(id) {
case FOURCC_YV12:
case FOURCC_I420:
dstPitch = ((dst_width << 1) + 15) & ~15;
srcPitch = (width + 3) & ~3;
srcPitch2 = ((width >> 1) + 3) & ~3;
size = dstPitch * dst_height;
break;
case FOURCC_UYVY:
case FOURCC_YUY2:
default:
dstPitch = ((dst_width << 1) + 15) & ~15;
srcPitch = (width << 1);
srcPitch2 = 0;
size = dstPitch * dst_height;
break;
}
if (pPortPriv->off_screen != NULL && size != pPortPriv->size) {
KdOffscreenFree(screen->pScreen, pPortPriv->off_screen);
pPortPriv->off_screen = 0;
}
if (pPortPriv->off_screen == NULL) {
pPortPriv->off_screen = KdOffscreenAlloc(screen->pScreen,
size * 2, 64, TRUE, ATIVideoSave, pPortPriv);
if (pPortPriv->off_screen == NULL)
return BadAlloc;
}
if (pDraw->type == DRAWABLE_WINDOW)
pPortPriv->pPixmap =
(*pScreen->GetWindowPixmap)((WindowPtr)pDraw);
else
pPortPriv->pPixmap = (PixmapPtr)pDraw;
if (!kaaPixmapIsOffscreen(pPortPriv->pPixmap))
kaaMoveInPixmap(pPortPriv->pPixmap);
if (!kaaPixmapIsOffscreen(pPortPriv->pPixmap)) {
return BadAlloc;
}
pPortPriv->src_offset = pPortPriv->off_screen->offset;
pPortPriv->src_addr = (CARD8 *)(pScreenPriv->screen->memory_base +
pPortPriv->src_offset);
pPortPriv->src_pitch = dstPitch;
pPortPriv->size = size;
pPortPriv->pDraw = pDraw;
top = rot_y1 >> 16;
left = (rot_x1 >> 16) & ~1;
npixels = ((((rot_x2 + 0xffff) >> 16) + 1) & ~1) - left;
ATIWaitIdle(atis);
switch(id) {
case FOURCC_YV12:
case FOURCC_I420:
top &= ~1;
nlines = ((((rot_y2 + 0xffff) >> 16) + 1) & ~1) - top;
KdXVCopyPlanarData(screen, buf, pPortPriv->src_addr, randr,
srcPitch, srcPitch2, dstPitch, rot_src_w, rot_src_h,
height, top, left, nlines, npixels, id);
break;
case FOURCC_UYVY:
case FOURCC_YUY2:
default:
nlines = ((rot_y2 + 0xffff) >> 16) - top;
KdXVCopyPackedData(screen, buf, pPortPriv->src_addr, randr,
srcPitch, dstPitch, rot_src_w, rot_src_h, top, left,
nlines, npixels);
break;
}
if (!REGION_EQUAL(screen->pScreen, &pPortPriv->clip, clipBoxes)) {
REGION_COPY(screen->pScreen, &pPortPriv->clip, clipBoxes);
}
pPortPriv->id = id;
pPortPriv->src_x1 = rot_x1;
pPortPriv->src_y1 = rot_y1;
pPortPriv->src_x2 = rot_x2;
pPortPriv->src_y2 = rot_y2;
pPortPriv->src_w = rot_src_w;
pPortPriv->src_h = rot_src_h;
pPortPriv->dst_x1 = dst_x1;
pPortPriv->dst_y1 = dst_y1;
pPortPriv->dst_x2 = dst_x2;
pPortPriv->dst_y2 = dst_y2;
pPortPriv->dst_w = rot_drw_w;
pPortPriv->dst_h = rot_drw_h;
if (atic->is_radeon)
RadeonDisplayVideo(screen, pPortPriv);
else
R128DisplayVideo(screen, pPortPriv);
return Success;
}
static int
ATIReputImage(KdScreenInfo *screen, DrawablePtr pDraw, short drw_x, short drw_y,
RegionPtr clipBoxes, pointer data)
{
ScreenPtr pScreen = screen->pScreen;
KdScreenPriv(pScreen);
ATICardInfo(pScreenPriv);
ATIPortPrivPtr pPortPriv = (ATIPortPrivPtr)data;
BoxPtr pOldExtents = REGION_EXTENTS(screen->pScreen, &pPortPriv->clip);
BoxPtr pNewExtents = REGION_EXTENTS(screen->pScreen, clipBoxes);
if (pOldExtents->x1 != pNewExtents->x1 ||
pOldExtents->x2 != pNewExtents->x2 ||
pOldExtents->y1 != pNewExtents->y1 ||
pOldExtents->y2 != pNewExtents->y2)
return BadMatch;
if (pDraw->type == DRAWABLE_WINDOW)
pPortPriv->pPixmap =
(*pScreen->GetWindowPixmap)((WindowPtr)pDraw);
else
pPortPriv->pPixmap = (PixmapPtr)pDraw;
if (!kaaPixmapIsOffscreen(pPortPriv->pPixmap))
kaaMoveInPixmap(pPortPriv->pPixmap);
if (!kaaPixmapIsOffscreen(pPortPriv->pPixmap)) {
ErrorF("err\n");
return BadAlloc;
}
if (!REGION_EQUAL(screen->pScreen, &pPortPriv->clip, clipBoxes))
REGION_COPY(screen->pScreen, &pPortPriv->clip, clipBoxes);
if (atic->is_radeon)
RadeonDisplayVideo(screen, pPortPriv);
else
R128DisplayVideo(screen, pPortPriv);
return Success;
}
static int
ATIQueryImageAttributes(KdScreenInfo *screen, int id, unsigned short *w,
unsigned short *h, int *pitches, int *offsets)
{
int size, tmp;
if (*w > IMAGE_MAX_WIDTH)
*w = IMAGE_MAX_WIDTH;
if (*h > IMAGE_MAX_HEIGHT)
*h = IMAGE_MAX_HEIGHT;
*w = (*w + 1) & ~1;
if (offsets)
offsets[0] = 0;
switch (id)
{
case FOURCC_YV12:
case FOURCC_I420:
*h = (*h + 1) & ~1;
size = (*w + 3) & ~3;
if (pitches)
pitches[0] = size;
size *= *h;
if (offsets)
offsets[1] = size;
tmp = ((*w >> 1) + 3) & ~3;
if (pitches)
pitches[1] = pitches[2] = tmp;
tmp *= (*h >> 1);
size += tmp;
if (offsets)
offsets[2] = size;
size += tmp;
break;
case FOURCC_UYVY:
case FOURCC_YUY2:
default:
size = *w << 1;
if (pitches)
pitches[0] = size;
size *= *h;
break;
}
return size;
}
static KdVideoEncodingRec DummyEncoding[1] =
{
{
0,
"XV_IMAGE",
IMAGE_MAX_WIDTH, IMAGE_MAX_HEIGHT,
{1, 1}
}
};
#define NUM_FORMATS 3
static KdVideoFormatRec Formats[NUM_FORMATS] =
{
{15, TrueColor}, {16, TrueColor}, {24, TrueColor}
};
#define NUM_ATTRIBUTES 0
static KdAttributeRec Attributes[NUM_ATTRIBUTES] =
{
};
#define NUM_IMAGES 4
static KdImageRec Images[NUM_IMAGES] =
{
XVIMAGE_YUY2,
XVIMAGE_YV12,
XVIMAGE_I420,
XVIMAGE_UYVY
};
static KdVideoAdaptorPtr
ATISetupImageVideo(ScreenPtr pScreen)
{
KdScreenPriv(pScreen);
ATIScreenInfo(pScreenPriv);
KdVideoAdaptorPtr adapt;
ATIPortPrivPtr pPortPriv;
int i;
atis->num_texture_ports = 16;
adapt = xcalloc(1, sizeof(KdVideoAdaptorRec) + atis->num_texture_ports *
(sizeof(ATIPortPrivRec) + sizeof(DevUnion)));
if (adapt == NULL)
return NULL;
adapt->type = XvWindowMask | XvInputMask | XvImageMask;
adapt->flags = VIDEO_CLIP_TO_VIEWPORT;
adapt->name = "ATI Texture Video";
adapt->nEncodings = 1;
adapt->pEncodings = DummyEncoding;
adapt->nFormats = NUM_FORMATS;
adapt->pFormats = Formats;
adapt->nPorts = atis->num_texture_ports;
adapt->pPortPrivates = (DevUnion*)(&adapt[1]);
pPortPriv =
(ATIPortPrivPtr)(&adapt->pPortPrivates[atis->num_texture_ports]);
for (i = 0; i < atis->num_texture_ports; i++)
adapt->pPortPrivates[i].ptr = &pPortPriv[i];
adapt->nAttributes = NUM_ATTRIBUTES;
adapt->pAttributes = Attributes;
adapt->pImages = Images;
adapt->nImages = NUM_IMAGES;
adapt->PutVideo = NULL;
adapt->PutStill = NULL;
adapt->GetVideo = NULL;
adapt->GetStill = NULL;
adapt->StopVideo = ATIStopVideo;
adapt->SetPortAttribute = ATISetPortAttribute;
adapt->GetPortAttribute = ATIGetPortAttribute;
adapt->QueryBestSize = ATIQueryBestSize;
adapt->PutImage = ATIPutImage;
adapt->ReputImage = ATIReputImage;
adapt->QueryImageAttributes = ATIQueryImageAttributes;
REGION_INIT(pScreen, &pPortPriv->clip, NullBox, 0);
atis->pAdaptor = adapt;
xvBrightness = MAKE_ATOM("XV_BRIGHTNESS");
xvSaturation = MAKE_ATOM("XV_SATURATION");
return adapt;
}
Bool ATIInitVideo(ScreenPtr pScreen)
{
KdScreenPriv(pScreen);
ATIScreenInfo(pScreenPriv);
ATICardInfo(pScreenPriv);
KdScreenInfo *screen = pScreenPriv->screen;
KdVideoAdaptorPtr *adaptors, *newAdaptors = NULL;
KdVideoAdaptorPtr newAdaptor = NULL;
int num_adaptors;
atis->pAdaptor = NULL;
if (atic->reg_base == NULL)
return FALSE;
if (atic->is_r300)
return FALSE;
num_adaptors = KdXVListGenericAdaptors(screen, &adaptors);
newAdaptor = ATISetupImageVideo(pScreen);
if (newAdaptor) {
if (!num_adaptors) {
num_adaptors = 1;
adaptors = &newAdaptor;
} else {
newAdaptors = xalloc((num_adaptors + 1) *
sizeof(KdVideoAdaptorPtr *));
if (newAdaptors) {
memcpy(newAdaptors, adaptors, num_adaptors *
sizeof(KdVideoAdaptorPtr));
newAdaptors[num_adaptors] = newAdaptor;
adaptors = newAdaptors;
num_adaptors++;
}
}
}
if (num_adaptors)
KdXVScreenInit(pScreen, adaptors, num_adaptors);
if (newAdaptors)
xfree(newAdaptors);
return TRUE;
}
void
ATIFiniVideo(ScreenPtr pScreen)
{
KdScreenPriv(pScreen);
ATIScreenInfo(pScreenPriv);
KdVideoAdaptorPtr adapt = atis->pAdaptor;
ATIPortPrivPtr pPortPriv;
int i;
if (!adapt)
return;
for (i = 0; i < atis->num_texture_ports; i++) {
pPortPriv = (ATIPortPrivPtr)(&adapt->pPortPrivates[i].ptr);
REGION_UNINIT(pScreen, &pPortPriv->clip);
}
xfree(adapt);
atis->pAdaptor = NULL;
}