Commit fca6300e authored by Dongwon Kim's avatar Dongwon Kim Committed by Vivek Kasireddy
Browse files

modesetting: Add support for headless display



In some Virtualization environments, a CRTC may not be available but a
graphics device may still be present (/dev/dri/card0). In such
situations, the modesetting DDX should still load Glamor (and DRI) and
work in a "Headless" fashion.

Present's screen flip mode will handle the vblanks (and flips) in these
situations.
Signed-off-by: Vivek Kasireddy's avatarVivek Kasireddy <vivek.kasireddy@intel.com>
Signed-off-by: default avatarDongwon Kim <dongwon.kim@intel.com>
parent aac28e16
Pipeline #185824 passed with stages
in 6 minutes and 19 seconds
......@@ -50,6 +50,7 @@ modesetting_drv_la_SOURCES = \
driver.h \
drmmode_display.c \
drmmode_display.h \
headless_display.c \
dumb_bo.c \
dumb_bo.h \
present.c \
......
......@@ -131,6 +131,7 @@ static const OptionInfoRec Options[] = {
{OPTION_ZAPHOD_HEADS, "ZaphodHeads", OPTV_STRING, {0}, FALSE},
{OPTION_DOUBLE_SHADOW, "DoubleShadow", OPTV_BOOLEAN, {0}, FALSE},
{OPTION_ATOMIC, "Atomic", OPTV_BOOLEAN, {0}, FALSE},
{OPTION_HEADLESS, "Headless", OPTV_BOOLEAN, {0}, FALSE},
{-1, NULL, OPTV_NONE, {0}, FALSE}
};
......@@ -232,15 +233,17 @@ static int
check_outputs(int fd, int *count)
{
drmModeResPtr res = drmModeGetResources(fd);
int ret;
int ret = FALSE;
if (!res)
return FALSE;
goto no_res;
if (count)
*count = res->count_connectors;
ret = res->count_connectors > 0;
drmModeFreeResources(res);
no_res:
#if defined(GLAMOR_HAS_GBM_LINEAR)
if (ret == FALSE) {
uint64_t value = 0;
......@@ -249,7 +252,6 @@ check_outputs(int fd, int *count)
ret = TRUE;
}
#endif
drmModeFreeResources(res);
return ret;
}
......
......@@ -52,6 +52,7 @@ typedef enum {
OPTION_ZAPHOD_HEADS,
OPTION_DOUBLE_SHADOW,
OPTION_ATOMIC,
OPTION_HEADLESS,
} modesettingOpts;
typedef struct
......@@ -121,6 +122,7 @@ typedef struct _modesettingRec {
Bool tried_queue_sequence;
Bool kms_has_modifiers;
Bool headless;
/* shadow API */
struct {
......
......@@ -89,8 +89,12 @@ Bool
drmmode_is_format_supported(ScrnInfoPtr scrn, uint32_t format, uint64_t modifier)
{
xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
modesettingPtr ms = modesettingPTR(scrn);
int c, i, j;
if (ms->headless)
return TRUE;
/* BO are imported as opaque surface, so let's pretend there is no alpha */
format = get_opaque_format(format);
......@@ -145,6 +149,9 @@ get_modifiers_set(ScrnInfoPtr scrn, uint32_t format, uint64_t **modifiers,
int c, i, j, k, count_modifiers = 0;
uint64_t *tmp, *ret = NULL;
if (ms->headless)
return 0;
/* BOs are imported as opaque surfaces, so pretend the same thing here */
format = get_opaque_format(format);
......@@ -3397,12 +3404,30 @@ Bool
drmmode_pre_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int cpp)
{
modesettingEntPtr ms_ent = ms_ent_priv(pScrn);
modesettingPtr ms = modesettingPTR(pScrn);
int i;
int ret;
uint64_t value = 0;
unsigned int crtcs_needed = 0;
drmModeResPtr mode_res;
int crtcshift;
Bool headless;
if (xf86GetOptValBool(ms->drmmode.Options, OPTION_HEADLESS, &headless))
ms->headless = headless;
drmmode->scrn = pScrn;
drmmode->cpp = cpp;
mode_res = drmModeGetResources(drmmode->fd);
if (!mode_res && ms->headless) {
if (!headless_output_init(pScrn))
return FALSE;
if (!headless_crtc_init(pScrn))
return FALSE;
goto out;
}
/* check for dumb capability */
ret = drmGetCap(drmmode->fd, DRM_CAP_DUMB_BUFFER, &value);
......@@ -3413,13 +3438,6 @@ drmmode_pre_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int cpp)
}
xf86CrtcConfigInit(pScrn, &drmmode_xf86crtc_config_funcs);
drmmode->scrn = pScrn;
drmmode->cpp = cpp;
mode_res = drmModeGetResources(drmmode->fd);
if (!mode_res)
return FALSE;
crtcshift = ffs(ms_ent->assigned_crtcs ^ 0xffffffff) - 1;
for (i = 0; i < mode_res->count_connectors; i++)
crtcs_needed += drmmode_output_init(pScrn, drmmode, mode_res, i, FALSE,
......@@ -3445,6 +3463,8 @@ drmmode_pre_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int cpp)
drmmode_clones_init(pScrn, drmmode, mode_res);
drmModeFreeResources(mode_res);
out:
xf86ProviderSetup(pScrn, NULL, "modesetting");
xf86InitialConfiguration(pScrn, TRUE);
......@@ -3488,8 +3508,12 @@ Bool
drmmode_set_desired_modes(ScrnInfoPtr pScrn, drmmode_ptr drmmode, Bool set_hw)
{
xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
modesettingPtr ms = modesettingPTR(pScrn);
int c;
if (ms->headless)
return TRUE;
for (c = 0; c < config->num_crtc; c++) {
xf86CrtcPtr crtc = config->crtc[c];
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
......@@ -3558,6 +3582,7 @@ drmmode_load_palette(ScrnInfoPtr pScrn, int numColors,
int *indices, LOCO * colors, VisualPtr pVisual)
{
xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
modesettingPtr ms = modesettingPTR(pScrn);
uint16_t lut_r[256], lut_g[256], lut_b[256];
int index, j, i;
int c;
......@@ -3566,11 +3591,13 @@ drmmode_load_palette(ScrnInfoPtr pScrn, int numColors,
xf86CrtcPtr crtc = xf86_config->crtc[c];
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
for (i = 0; i < 256; i++) {
lut_r[i] = drmmode_crtc->lut_r[i] << 6;
lut_g[i] = drmmode_crtc->lut_g[i] << 6;
lut_b[i] = drmmode_crtc->lut_b[i] << 6;
}
if (!ms->headless) {
for (i = 0; i < 256; i++) {
lut_r[i] = drmmode_crtc->lut_r[i] << 6;
lut_g[i] = drmmode_crtc->lut_g[i] << 6;
lut_b[i] = drmmode_crtc->lut_b[i] << 6;
}
}
switch (pScrn->depth) {
case 15:
......@@ -3849,8 +3876,10 @@ drmmode_create_initial_bos(ScrnInfoPtr pScrn, drmmode_ptr drmmode)
xf86CrtcPtr crtc = xf86_config->crtc[i];
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
drmmode_crtc->cursor_bo =
dumb_bo_create(drmmode->fd, width, height, bpp);
if (!ms->headless) {
drmmode_crtc->cursor_bo =
dumb_bo_create(drmmode->fd, width, height, bpp);
}
}
return TRUE;
}
......@@ -3880,8 +3909,12 @@ Bool
drmmode_map_cursor_bos(ScrnInfoPtr pScrn, drmmode_ptr drmmode)
{
xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
modesettingPtr ms = modesettingPTR(pScrn);
int i, ret;
if (ms->headless)
return TRUE;
for (i = 0; i < xf86_config->num_crtc; i++) {
xf86CrtcPtr crtc = xf86_config->crtc[i];
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
......@@ -3897,6 +3930,7 @@ void
drmmode_free_bos(ScrnInfoPtr pScrn, drmmode_ptr drmmode)
{
xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
modesettingPtr ms = modesettingPTR(pScrn);
int i;
if (drmmode->fb_id) {
......@@ -3910,7 +3944,8 @@ drmmode_free_bos(ScrnInfoPtr pScrn, drmmode_ptr drmmode)
xf86CrtcPtr crtc = xf86_config->crtc[i];
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
dumb_bo_destroy(drmmode->fd, drmmode_crtc->cursor_bo);
if (!ms->headless)
dumb_bo_destroy(drmmode->fd, drmmode_crtc->cursor_bo);
}
}
......
......@@ -294,4 +294,7 @@ int drmmode_crtc_flip(xf86CrtcPtr crtc, uint32_t fb_id, uint32_t flags, void *da
void drmmode_set_dpms(ScrnInfoPtr scrn, int PowerManagementMode, int flags);
Bool headless_output_init(ScrnInfoPtr pScrn);
Bool headless_crtc_init(ScrnInfoPtr pScrn);
#endif
/*
* Copyright © 2020 Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
#ifdef HAVE_DIX_CONFIG_H
#include "dix-config.h"
#endif
#include "driver.h"
static void
headless_crtc_dpms(xf86CrtcPtr crtc, int mode)
{
}
static Bool
headless_crtc_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
Rotation rotation, int x, int y)
{
return TRUE;
}
static void
headless_crtc_destroy(xf86CrtcPtr crtc)
{
}
static const xf86CrtcFuncsRec headless_crtc_funcs = {
.dpms = headless_crtc_dpms,
.set_mode_major = headless_crtc_set_mode_major,
.destroy = headless_crtc_destroy,
};
static void
headless_output_create_resources(xf86OutputPtr output)
{
}
static Bool
headless_output_set_property(xf86OutputPtr output, Atom property,
RRPropertyValuePtr value)
{
return TRUE;
}
static Bool
headless_output_get_property(xf86OutputPtr output, Atom property)
{
return TRUE;
}
static void
headless_output_dpms(xf86OutputPtr output, int mode)
{
}
static xf86OutputStatus
headless_output_detect(xf86OutputPtr output)
{
return XF86OutputStatusConnected;
}
static Bool
headless_output_mode_valid(xf86OutputPtr output, DisplayModePtr pModes)
{
return MODE_OK;
}
static DisplayModePtr
headless_output_get_modes(xf86OutputPtr output)
{
return NULL;
}
static void
headless_output_destroy(xf86OutputPtr output)
{
}
static const xf86OutputFuncsRec headless_output_funcs = {
.dpms = headless_output_dpms,
.create_resources = headless_output_create_resources,
.set_property = headless_output_set_property,
.get_property = headless_output_get_property,
.detect = headless_output_detect,
.mode_valid = headless_output_mode_valid,
.get_modes = headless_output_get_modes,
.destroy = headless_output_destroy
};
static Bool
headless_xf86crtc_resize(ScrnInfoPtr scrn, int width, int height)
{
return TRUE;
}
static const xf86CrtcConfigFuncsRec headless_xf86crtc_config_funcs = {
.resize = headless_xf86crtc_resize,
};
Bool
headless_output_init(ScrnInfoPtr pScrn)
{
xf86OutputPtr output;
char name[32];
xf86CrtcConfigInit(pScrn, &headless_xf86crtc_config_funcs);
snprintf(name, 32, "%s", "HEADLESS");
output = xf86OutputCreate(pScrn, &headless_output_funcs, name);
if (!output)
return FALSE;
output->mm_width = 0;
output->mm_height = 0;
output->subpixel_order = SubPixelNone;
output->interlaceAllowed = FALSE;
output->doubleScanAllowed = FALSE;
output->status = XF86OutputStatusConnected;
output->possible_crtcs = 0xFF;
output->possible_clones = 0;
return TRUE;
}
Bool
headless_crtc_init(ScrnInfoPtr pScrn)
{
xf86CrtcPtr crtc;
xf86CrtcSetSizeRange(pScrn, 320, 200, 7680, 4320);
crtc = xf86CrtcCreate(pScrn, &headless_crtc_funcs);
if (!crtc)
return FALSE;
return TRUE;
}
......@@ -2,6 +2,7 @@ modesetting_srcs = [
'dri2.c',
'driver.c',
'drmmode_display.c',
'headless_display.c',
'dumb_bo.c',
'pageflip.c',
'present.c',
......
......@@ -428,5 +428,8 @@ ms_present_screen_init(ScreenPtr screen)
if (ret == 0 && value == 1)
ms_present_screen_info.capabilities |= PresentCapabilityAsync;
return present_screen_init(screen, &ms_present_screen_info);
if (!ms->headless)
return present_screen_init(screen, &ms_present_screen_info);
else
return present_screen_init(screen, NULL);
}
......@@ -107,8 +107,14 @@ static int ms_box_area(BoxPtr box)
Bool
ms_crtc_on(xf86CrtcPtr crtc)
{
ScreenPtr screen = crtc->randr_crtc->pScreen;
ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
modesettingPtr ms = modesettingPTR(scrn);
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
if (ms->headless)
return TRUE;
return crtc->enabled && drmmode_crtc->dpms_mode == DPMSModeOn;
}
......@@ -470,6 +476,9 @@ ms_get_crtc_ust_msc(xf86CrtcPtr crtc, CARD64 *ust, CARD64 *msc)
modesettingPtr ms = modesettingPTR(scrn);
uint64_t kernel_msc;
if (ms->headless)
return Success;
if (!ms_get_kernel_ust_msc(crtc, &kernel_msc, ust))
return BadMatch;
*msc = ms_kernel_msc_to_crtc_msc(crtc, kernel_msc, ms->has_queue_sequence);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment