mirror of
https://github.com/X11Libre/xf86-video-amdgpu.git
synced 2026-03-24 01:24:31 +00:00
This is adjusting randr_crtc_covering_drawable to cover scenario fixed in 9151f3b1c2ebcc34e63195888ba696f2183ba5e2 Signed-off-by: Łukasz Spintzyk <lukasz.spintzyk@synaptics.com> Signed-off-by: Shashank Sharma <contactshashanksharma@gmail.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
297 lines
6.8 KiB
C
297 lines
6.8 KiB
C
|
|
#ifdef HAVE_CONFIG_H
|
|
#include "config.h"
|
|
#endif
|
|
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <stdio.h>
|
|
#include <math.h>
|
|
|
|
#include "amdgpu_drv.h"
|
|
#include "amdgpu_glamor.h"
|
|
#include "amdgpu_probe.h"
|
|
#include "amdgpu_video.h"
|
|
#include "amdgpu_pixmap.h"
|
|
|
|
#include "xf86.h"
|
|
#include "dixstruct.h"
|
|
|
|
/* DPMS */
|
|
#ifdef HAVE_XEXTPROTO_71
|
|
#include <X11/extensions/dpmsconst.h>
|
|
#else
|
|
#define DPMS_SERVER
|
|
#include <X11/extensions/dpms.h>
|
|
#endif
|
|
|
|
#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
|
|
|
|
static void amdgpu_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;
|
|
if (dest->x1 >= dest->x2) {
|
|
dest->x1 = dest->x2 = dest->y1 = dest->y2 = 0;
|
|
return;
|
|
}
|
|
|
|
dest->y1 = a->y1 > b->y1 ? a->y1 : b->y1;
|
|
dest->y2 = a->y2 < b->y2 ? a->y2 : b->y2;
|
|
if (dest->y1 >= dest->y2)
|
|
dest->x1 = dest->x2 = dest->y1 = dest->y2 = 0;
|
|
}
|
|
|
|
static void amdgpu_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 amdgpu_box_area(BoxPtr box)
|
|
{
|
|
return (int)(box->x2 - box->x1) * (int)(box->y2 - box->y1);
|
|
}
|
|
|
|
Bool
|
|
amdgpu_crtc_is_enabled(xf86CrtcPtr crtc)
|
|
{
|
|
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
|
|
|
|
return crtc->enabled && drmmode_crtc->dpms_mode == DPMSModeOn;
|
|
}
|
|
|
|
xf86CrtcPtr
|
|
amdgpu_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 && !xf86_crtc_on(crtc))
|
|
continue;
|
|
|
|
amdgpu_crtc_box(crtc, &crtc_box);
|
|
box_intersect(&cover_box, &crtc_box, &box);
|
|
coverage = 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;
|
|
}
|
|
|
|
static void amdgpu_crtc_box(RRCrtcPtr crtc, BoxPtr crtc_box)
|
|
{
|
|
if (crtc->mode) {
|
|
crtc_box->x1 = crtc->x;
|
|
crtc_box->y1 = crtc->y;
|
|
switch (crtc->rotation) {
|
|
case RR_Rotate_0:
|
|
case RR_Rotate_180:
|
|
default:
|
|
crtc_box->x2 = crtc->x + crtc->mode->mode.width;
|
|
crtc_box->y2 = crtc->y + crtc->mode->mode.height;
|
|
break;
|
|
case RR_Rotate_90:
|
|
case RR_Rotate_270:
|
|
crtc_box->x2 = crtc->x + crtc->mode->mode.height;
|
|
crtc_box->y2 = crtc->y + crtc->mode->mode.width;
|
|
break;
|
|
}
|
|
} else
|
|
crtc_box->x1 = crtc_box->x2 = crtc_box->y1 = crtc_box->y2 = 0;
|
|
}
|
|
|
|
static Bool amdgpu_crtc_on(RRCrtcPtr crtc, Bool crtc_is_xf86_hint)
|
|
{
|
|
if (!crtc) {
|
|
return FALSE;
|
|
}
|
|
if (crtc_is_xf86_hint && crtc->devPrivate) {
|
|
return amdgpu_crtc_is_enabled(crtc->devPrivate);
|
|
} else {
|
|
return !!crtc->mode;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Return the crtc covering 'box'. If two crtcs cover a portion of
|
|
* 'box', then prefer the crtc with greater coverage.
|
|
*/
|
|
static RRCrtcPtr
|
|
amdgpu_crtc_covering_box(ScreenPtr pScreen, BoxPtr box, Bool screen_is_xf86_hint)
|
|
{
|
|
rrScrPrivPtr pScrPriv;
|
|
RRCrtcPtr crtc, best_crtc, primary_crtc;
|
|
int coverage, best_coverage;
|
|
int c;
|
|
BoxRec crtc_box, cover_box;
|
|
RROutputPtr primary_output;
|
|
|
|
best_crtc = NULL;
|
|
best_coverage = 0;
|
|
primary_crtc = NULL;
|
|
primary_output = NULL;
|
|
|
|
if (!dixPrivateKeyRegistered(rrPrivKey))
|
|
return NULL;
|
|
|
|
pScrPriv = rrGetScrPriv(pScreen);
|
|
|
|
if (!pScrPriv)
|
|
return NULL;
|
|
|
|
primary_output = RRFirstOutput(pScreen);
|
|
if (primary_output && primary_output->crtc)
|
|
primary_crtc = primary_output->crtc->devPrivate;
|
|
|
|
for (c = 0; c < pScrPriv->numCrtcs; c++) {
|
|
crtc = pScrPriv->crtcs[c];
|
|
|
|
/* If the CRTC is off, treat it as not covering */
|
|
if (!amdgpu_crtc_on(crtc, screen_is_xf86_hint))
|
|
continue;
|
|
|
|
amdgpu_crtc_box(crtc, &crtc_box);
|
|
amdgpu_box_intersect(&cover_box, &crtc_box, box);
|
|
coverage = amdgpu_box_area(&cover_box);
|
|
if (coverage > best_coverage ||
|
|
(crtc == primary_crtc && coverage == best_coverage)) {
|
|
best_crtc = crtc;
|
|
best_coverage = coverage;
|
|
}
|
|
}
|
|
|
|
return best_crtc;
|
|
}
|
|
|
|
#if ABI_VIDEODRV_VERSION >= SET_ABI_VERSION(23, 0)
|
|
static RRCrtcPtr
|
|
amdgpu_crtc_covering_box_on_secondary(ScreenPtr pScreen, BoxPtr box)
|
|
{
|
|
if (!pScreen->isGPU) {
|
|
ScreenPtr secondary;
|
|
RRCrtcPtr crtc = NULL;
|
|
|
|
xorg_list_for_each_entry(secondary, &pScreen->secondary_list, secondary_head) {
|
|
if (!secondary->is_output_secondary)
|
|
continue;
|
|
|
|
crtc = amdgpu_crtc_covering_box(secondary, box, FALSE);
|
|
if (crtc)
|
|
return crtc;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
#endif
|
|
|
|
RRCrtcPtr
|
|
amdgpu_randr_crtc_covering_drawable(DrawablePtr pDraw)
|
|
{
|
|
ScreenPtr pScreen = pDraw->pScreen;
|
|
RRCrtcPtr crtc = NULL;
|
|
BoxRec box;
|
|
|
|
box.x1 = pDraw->x;
|
|
box.y1 = pDraw->y;
|
|
box.x2 = box.x1 + pDraw->width;
|
|
box.y2 = box.y1 + pDraw->height;
|
|
|
|
crtc = amdgpu_crtc_covering_box(pScreen, &box, TRUE);
|
|
#if ABI_VIDEODRV_VERSION >= SET_ABI_VERSION(23, 0)
|
|
if (!crtc) {
|
|
crtc = amdgpu_crtc_covering_box_on_secondary(pScreen, &box);
|
|
}
|
|
#endif
|
|
return crtc;
|
|
}
|
|
|
|
void AMDGPUInitVideo(ScreenPtr pScreen)
|
|
{
|
|
ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
|
|
AMDGPUInfoPtr info = AMDGPUPTR(pScrn);
|
|
XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL;
|
|
XF86VideoAdaptorPtr texturedAdaptor = NULL;
|
|
int num_adaptors;
|
|
|
|
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 = amdgpu_glamor_xv_init(pScreen, 16);
|
|
if (texturedAdaptor != NULL) {
|
|
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");
|
|
}
|
|
|
|
if (num_adaptors)
|
|
xf86XVScreenInit(pScreen, adaptors, num_adaptors);
|
|
|
|
if (newAdaptors)
|
|
free(newAdaptors);
|
|
|
|
}
|