summaryrefslogtreecommitdiff
path: root/src/drmmode_display.c
diff options
context:
space:
mode:
authorMichel Dänzer <michel.daenzer@amd.com>2015-03-18 16:23:24 +0900
committerMichel Dänzer <michel@daenzer.net>2015-04-03 11:42:00 +0900
commitae92d1765fa370a8d94c2856ad6c45d273ec3c69 (patch)
tree1c602a906d80ac92620f4a2d48e1b4353d5a9d19 /src/drmmode_display.c
parenteea79472a84672ee4dc7adc4487cec6a4037048a (diff)
glamor: Add Option "ShadowPrimary" v2
When this option is enabled, most pixmaps (including the screen pixmap) are allocated in system RAM and mostly accessed by the CPU. Changed areas of the screen pixmap are copied to dedicated per-CRTC scanout pixmaps regularly, triggered by the vblank interrupt. v2: * Set region data pointer to NULL for keeping only the extents * Move pRegion and pBox local variable declarations closer to their uses in drmmode_set_mode_major()
Diffstat (limited to 'src/drmmode_display.c')
-rw-r--r--src/drmmode_display.c89
1 files changed, 87 insertions, 2 deletions
diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index d8d3ca36..1f228698 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -33,6 +33,7 @@
#include <sys/ioctl.h>
#include <time.h>
#include "cursorstr.h"
+#include "damagestr.h"
#include "micmap.h"
#include "xf86cmap.h"
#include "radeon.h"
@@ -489,6 +490,26 @@ drmmode_crtc_scanout_destroy(drmmode_ptr drmmode,
}
+void
+drmmode_scanout_free(ScrnInfoPtr scrn)
+{
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+ int c;
+
+ for (c = 0; c < xf86_config->num_crtc; c++) {
+ drmmode_crtc_private_ptr drmmode_crtc =
+ xf86_config->crtc[c]->driver_private;
+
+ drmmode_crtc_scanout_destroy(drmmode_crtc->drmmode,
+ &drmmode_crtc->scanout);
+
+ if (drmmode_crtc->scanout_damage) {
+ DamageDestroy(drmmode_crtc->scanout_damage);
+ drmmode_crtc->scanout_damage = NULL;
+ }
+ }
+}
+
static void *
drmmode_crtc_scanout_allocate(xf86CrtcPtr crtc,
struct drmmode_scanout *scanout,
@@ -510,6 +531,13 @@ drmmode_crtc_scanout_allocate(xf86CrtcPtr crtc,
return NULL;
}
+ if (scanout->bo) {
+ if (scanout->width == width && scanout->height == height)
+ return scanout->bo->ptr;
+
+ drmmode_crtc_scanout_destroy(drmmode, scanout);
+ }
+
rotate_pitch =
RADEON_ALIGN(width, drmmode_get_pitch_align(pScrn, drmmode->cpp, 0))
* drmmode->cpp;
@@ -531,6 +559,8 @@ drmmode_crtc_scanout_allocate(xf86CrtcPtr crtc,
if (ret)
ErrorF("failed to add scanout fb\n");
+ scanout->width = width;
+ scanout->height = height;
return scanout->bo->ptr;
}
@@ -543,6 +573,13 @@ drmmode_crtc_scanout_create(xf86CrtcPtr crtc, struct drmmode_scanout *scanout,
drmmode_ptr drmmode = drmmode_crtc->drmmode;
unsigned long rotate_pitch;
+ if (scanout->pixmap) {
+ if (scanout->width == width && scanout->height == height)
+ return scanout->pixmap;
+
+ drmmode_crtc_scanout_destroy(drmmode, scanout);
+ }
+
if (!data)
data = drmmode_crtc_scanout_allocate(crtc, scanout, width, height);
@@ -562,6 +599,14 @@ drmmode_crtc_scanout_create(xf86CrtcPtr crtc, struct drmmode_scanout *scanout,
return scanout->pixmap;
}
+static void
+radeon_screen_damage_report(DamagePtr damage, RegionPtr region, void *closure)
+{
+ /* Only keep track of the extents */
+ RegionUninit(&damage->damage);
+ damage->damage.data = NULL;
+}
+
static Bool
drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
Rotation rotation, int x, int y)
@@ -631,6 +676,8 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
}
if (mode) {
+ ScreenPtr pScreen = pScrn->pScreen;
+
for (i = 0; i < xf86_config->num_output; i++) {
xf86OutputPtr output = xf86_config->output[i];
drmmode_output_private_ptr drmmode_output;
@@ -656,11 +703,46 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
if (crtc->randr_crtc && crtc->randr_crtc->scanout_pixmap) {
x = drmmode_crtc->prime_pixmap_x;
y = 0;
+
+ drmmode_crtc_scanout_destroy(drmmode, &drmmode_crtc->scanout);
} else
#endif
if (drmmode_crtc->rotate.fb_id) {
fb_id = drmmode_crtc->rotate.fb_id;
x = y = 0;
+
+ drmmode_crtc_scanout_destroy(drmmode, &drmmode_crtc->scanout);
+ } else if (info->shadow_primary) {
+ drmmode_crtc_scanout_create(crtc,
+ &drmmode_crtc->scanout,
+ NULL, mode->HDisplay,
+ mode->VDisplay);
+
+ if (drmmode_crtc->scanout.pixmap) {
+ RegionPtr pRegion;
+ BoxPtr pBox;
+
+ if (!drmmode_crtc->scanout_damage) {
+ drmmode_crtc->scanout_damage =
+ DamageCreate(radeon_screen_damage_report,
+ NULL, DamageReportRawRegion,
+ TRUE, pScreen, NULL);
+ DamageRegister(&pScreen->GetScreenPixmap(pScreen)->drawable,
+ drmmode_crtc->scanout_damage);
+ }
+
+ pRegion = DamageRegion(drmmode_crtc->scanout_damage);
+ RegionUninit(pRegion);
+ pRegion->data = NULL;
+ pBox = RegionExtents(pRegion);
+ pBox->x1 = min(pBox->x1, x);
+ pBox->y1 = min(pBox->y1, y);
+ pBox->x2 = max(pBox->x2, x + mode->HDisplay);
+ pBox->y2 = max(pBox->y2, y + mode->VDisplay);
+
+ fb_id = drmmode_crtc->scanout.fb_id;
+ x = y = 0;
+ }
}
ret = drmModeSetCrtc(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
fb_id, x, y, output_ids, output_count, &kmode);
@@ -1689,7 +1771,7 @@ drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height)
if (front_bo)
radeon_bo_wait(front_bo);
- if (info->allowColorTiling) {
+ if (info->allowColorTiling && !info->shadow_primary) {
if (info->ChipFamily >= CHIP_FAMILY_R600) {
if (info->allowColorTiling2D) {
tiling_flags |= RADEON_TILING_MACRO;
@@ -1770,7 +1852,10 @@ drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height)
scrn->virtualY = height;
scrn->displayWidth = pitch / cpp;
- info->front_bo = radeon_bo_open(info->bufmgr, 0, screen_size, base_align, RADEON_GEM_DOMAIN_VRAM, 0);
+ info->front_bo = radeon_bo_open(info->bufmgr, 0, screen_size, base_align,
+ info->shadow_primary ?
+ RADEON_GEM_DOMAIN_GTT :
+ RADEON_GEM_DOMAIN_VRAM, 0);
if (!info->front_bo)
goto fail;