272 lines
6.8 KiB
C
272 lines
6.8 KiB
C
#include "config.h"
|
|
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <stdio.h>
|
|
#include <math.h>
|
|
|
|
#include "radeon.h"
|
|
#include "radeon_glamor.h"
|
|
#include "radeon_reg.h"
|
|
#include "radeon_probe.h"
|
|
#include "radeon_video.h"
|
|
|
|
#include "xf86.h"
|
|
#include "dixstruct.h"
|
|
|
|
/* DPMS */
|
|
#include <X11/extensions/dpmsconst.h>
|
|
|
|
#include <X11/extensions/Xv.h>
|
|
#include "fourcc.h"
|
|
|
|
#define OFF_DELAY 250 /* milliseconds */
|
|
#define FREE_DELAY 15000
|
|
|
|
#define OFF_TIMER 0x01
|
|
#define FREE_TIMER 0x02
|
|
#define CLIENT_VIDEO_ON 0x04
|
|
|
|
#define GET_PORT_PRIVATE(pScrn) \
|
|
(RADEONPortPrivPtr)((RADEONPTR(pScrn))->adaptor->pPortPrivates[0].ptr)
|
|
|
|
static void
|
|
radeon_box_intersect(BoxPtr dest, BoxPtr a, BoxPtr b)
|
|
{
|
|
dest->x1 = a->x1 > b->x1 ? a->x1 : b->x1;
|
|
dest->x2 = a->x2 < b->x2 ? a->x2 : b->x2;
|
|
dest->y1 = a->y1 > b->y1 ? a->y1 : b->y1;
|
|
dest->y2 = a->y2 < b->y2 ? a->y2 : b->y2;
|
|
|
|
if (dest->x1 >= dest->x2 || dest->y1 >= dest->y2)
|
|
dest->x1 = dest->x2 = dest->y1 = dest->y2 = 0;
|
|
}
|
|
|
|
static void
|
|
radeon_crtc_box(xf86CrtcPtr crtc, BoxPtr crtc_box)
|
|
{
|
|
if (crtc->enabled) {
|
|
crtc_box->x1 = crtc->x;
|
|
crtc_box->x2 = crtc->x + xf86ModeWidth(&crtc->mode, crtc->rotation);
|
|
crtc_box->y1 = crtc->y;
|
|
crtc_box->y2 = crtc->y + xf86ModeHeight(&crtc->mode, crtc->rotation);
|
|
} else
|
|
crtc_box->x1 = crtc_box->x2 = crtc_box->y1 = crtc_box->y2 = 0;
|
|
}
|
|
|
|
static int
|
|
radeon_box_area(BoxPtr box)
|
|
{
|
|
return (int) (box->x2 - box->x1) * (int) (box->y2 - box->y1);
|
|
}
|
|
|
|
Bool radeon_crtc_is_enabled(xf86CrtcPtr crtc)
|
|
{
|
|
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
|
|
return drmmode_crtc->dpms_mode == DPMSModeOn;
|
|
}
|
|
|
|
xf86CrtcPtr
|
|
radeon_pick_best_crtc(ScrnInfoPtr pScrn, Bool consider_disabled,
|
|
int x1, int x2, int y1, int y2)
|
|
{
|
|
xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
|
|
int coverage, best_coverage, c, cd;
|
|
BoxRec box, crtc_box, cover_box;
|
|
RROutputPtr primary_output = NULL;
|
|
xf86CrtcPtr best_crtc = NULL, primary_crtc = NULL;
|
|
|
|
if (!pScrn->vtSema)
|
|
return NULL;
|
|
|
|
box.x1 = x1;
|
|
box.x2 = x2;
|
|
box.y1 = y1;
|
|
box.y2 = y2;
|
|
best_coverage = 0;
|
|
|
|
/* Prefer the CRTC of the primary output */
|
|
if (dixPrivateKeyRegistered(rrPrivKey))
|
|
{
|
|
primary_output = RRFirstOutput(pScrn->pScreen);
|
|
}
|
|
if (primary_output && primary_output->crtc)
|
|
primary_crtc = primary_output->crtc->devPrivate;
|
|
|
|
/* first consider only enabled CRTCs
|
|
* then on second pass consider disabled ones
|
|
*/
|
|
for (cd = 0; cd < (consider_disabled ? 2 : 1); cd++) {
|
|
for (c = 0; c < xf86_config->num_crtc; c++) {
|
|
xf86CrtcPtr crtc = xf86_config->crtc[c];
|
|
|
|
if (!cd && !radeon_crtc_is_enabled(crtc))
|
|
continue;
|
|
|
|
radeon_crtc_box(crtc, &crtc_box);
|
|
radeon_box_intersect(&cover_box, &crtc_box, &box);
|
|
coverage = radeon_box_area(&cover_box);
|
|
if (coverage > best_coverage ||
|
|
(coverage == best_coverage &&
|
|
crtc == primary_crtc)) {
|
|
best_crtc = crtc;
|
|
best_coverage = coverage;
|
|
}
|
|
}
|
|
if (best_crtc)
|
|
break;
|
|
}
|
|
|
|
return best_crtc;
|
|
}
|
|
|
|
|
|
void RADEONInitVideo(ScreenPtr pScreen)
|
|
{
|
|
ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
|
|
RADEONInfoPtr info = RADEONPTR(pScrn);
|
|
RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn);
|
|
XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL;
|
|
XF86VideoAdaptorPtr texturedAdaptor = NULL;
|
|
int num_adaptors;
|
|
|
|
/* no overlay or 3D on RN50 */
|
|
if (info->ChipFamily == CHIP_FAMILY_RV100 && !pRADEONEnt->HasCRTC2)
|
|
return;
|
|
|
|
num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors);
|
|
newAdaptors = malloc((num_adaptors + 2) * sizeof(*newAdaptors));
|
|
if (!newAdaptors)
|
|
return;
|
|
|
|
memcpy(newAdaptors, adaptors, num_adaptors * sizeof(XF86VideoAdaptorPtr));
|
|
adaptors = newAdaptors;
|
|
|
|
if (info->use_glamor) {
|
|
texturedAdaptor = radeon_glamor_xv_init(pScreen, 16);
|
|
if (texturedAdaptor) {
|
|
adaptors[num_adaptors++] = texturedAdaptor;
|
|
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Set up textured video (glamor)\n");
|
|
} else
|
|
xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to set up textured video (glamor)\n");
|
|
} else if ((info->ChipFamily < CHIP_FAMILY_RS400)
|
|
|| (info->directRenderingEnabled)
|
|
) {
|
|
texturedAdaptor = RADEONSetupImageTexturedVideo(pScreen);
|
|
if (texturedAdaptor) {
|
|
adaptors[num_adaptors++] = texturedAdaptor;
|
|
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Set up textured video\n");
|
|
} else
|
|
xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to set up textured video\n");
|
|
} else
|
|
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Textured video requires CP on R5xx/R6xx/R7xx/IGP\n");
|
|
|
|
if(num_adaptors)
|
|
xf86XVScreenInit(pScreen, adaptors, num_adaptors);
|
|
|
|
if(texturedAdaptor) {
|
|
XF86MCAdaptorPtr xvmcAdaptor = RADEONCreateAdaptorXvMC(pScreen, (char *)texturedAdaptor->name);
|
|
if(xvmcAdaptor) {
|
|
if(!xf86XvMCScreenInit(pScreen, 1, &xvmcAdaptor))
|
|
xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "[XvMC] Failed to initialize extension.\n");
|
|
else
|
|
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[XvMC] Extension initialized.\n");
|
|
}
|
|
}
|
|
|
|
if(newAdaptors)
|
|
free(newAdaptors);
|
|
|
|
}
|
|
|
|
void
|
|
RADEONCopyData(
|
|
ScrnInfoPtr pScrn,
|
|
unsigned char *src,
|
|
unsigned char *dst,
|
|
unsigned int srcPitch,
|
|
unsigned int dstPitch,
|
|
unsigned int h,
|
|
unsigned int w,
|
|
unsigned int bpp
|
|
){
|
|
/* Get the byte-swapping right for big endian systems */
|
|
if ( bpp == 2 ) {
|
|
w *= 2;
|
|
bpp = 1;
|
|
}
|
|
|
|
{
|
|
int swap = RADEON_HOST_DATA_SWAP_NONE;
|
|
|
|
#if X_BYTE_ORDER == X_BIG_ENDIAN
|
|
switch(bpp) {
|
|
case 2:
|
|
swap = RADEON_HOST_DATA_SWAP_16BIT;
|
|
break;
|
|
case 4:
|
|
swap = RADEON_HOST_DATA_SWAP_32BIT;
|
|
break;
|
|
}
|
|
#endif
|
|
|
|
w *= bpp;
|
|
|
|
if (dstPitch == w && dstPitch == srcPitch)
|
|
RADEONCopySwap(dst, src, h * dstPitch, swap);
|
|
else {
|
|
while (h--) {
|
|
RADEONCopySwap(dst, src, w, swap);
|
|
src += srcPitch;
|
|
dst += dstPitch;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void
|
|
RADEONCopyMungedData(
|
|
ScrnInfoPtr pScrn,
|
|
unsigned char *src1,
|
|
unsigned char *src2,
|
|
unsigned char *src3,
|
|
unsigned char *dst1,
|
|
unsigned int srcPitch,
|
|
unsigned int srcPitch2,
|
|
unsigned int dstPitch,
|
|
unsigned int h,
|
|
unsigned int w
|
|
){
|
|
uint32_t *dst;
|
|
uint8_t *s1, *s2, *s3;
|
|
int i, j;
|
|
|
|
w /= 2;
|
|
|
|
for( j = 0; j < h; j++ ) {
|
|
dst = (void*)dst1;
|
|
s1 = src1; s2 = src2; s3 = src3;
|
|
i = w;
|
|
while( i > 4 ) {
|
|
dst[0] = cpu_to_le32(s1[0] | (s1[1] << 16) | (s3[0] << 8) | (s2[0] << 24));
|
|
dst[1] = cpu_to_le32(s1[2] | (s1[3] << 16) | (s3[1] << 8) | (s2[1] << 24));
|
|
dst[2] = cpu_to_le32(s1[4] | (s1[5] << 16) | (s3[2] << 8) | (s2[2] << 24));
|
|
dst[3] = cpu_to_le32(s1[6] | (s1[7] << 16) | (s3[3] << 8) | (s2[3] << 24));
|
|
dst += 4; s2 += 4; s3 += 4; s1 += 8;
|
|
i -= 4;
|
|
}
|
|
while( i-- ) {
|
|
dst[0] = cpu_to_le32(s1[0] | (s1[1] << 16) | (s3[0] << 8) | (s2[0] << 24));
|
|
dst++; s2++; s3++;
|
|
s1 += 2;
|
|
}
|
|
|
|
dst1 += dstPitch;
|
|
src1 += srcPitch;
|
|
if( j & 1 ) {
|
|
src2 += srcPitch2;
|
|
src3 += srcPitch2;
|
|
}
|
|
}
|
|
}
|