xf86-video-ati/src/radeon_video.c
Enrico Weigelt, metux IT consult 03c42577c9 replace obsolete "pointer" typedef by plain void*
Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>
2026-01-05 17:45:08 +01:00

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;
}
}
}