2011-09-29 12:49:26 +02:00
|
|
|
/*
|
|
|
|
* Copyright © 2007 Red Hat, Inc.
|
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*
|
|
|
|
* Authors:
|
|
|
|
* Dave Airlie <airlied@redhat.com>
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2014-08-26 20:06:23 +02:00
|
|
|
#ifdef HAVE_DIX_CONFIG_H
|
|
|
|
#include "dix-config.h"
|
2011-09-29 12:49:26 +02:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <errno.h>
|
|
|
|
#include <sys/ioctl.h>
|
|
|
|
#include <sys/mman.h>
|
2012-07-25 07:38:34 +02:00
|
|
|
#include <unistd.h>
|
2014-12-09 20:17:30 +01:00
|
|
|
#include "dumb_bo.h"
|
2011-09-29 12:49:26 +02:00
|
|
|
#include "xf86str.h"
|
|
|
|
#include "X11/Xatom.h"
|
|
|
|
#include "micmap.h"
|
|
|
|
#include "xf86cmap.h"
|
|
|
|
#include "xf86DDC.h"
|
|
|
|
|
|
|
|
#include <xf86drm.h>
|
|
|
|
#include "xf86Crtc.h"
|
|
|
|
#include "drmmode_display.h"
|
|
|
|
|
2014-01-20 02:06:42 +01:00
|
|
|
#include <cursorstr.h>
|
|
|
|
|
2011-09-29 12:49:26 +02:00
|
|
|
#include <X11/extensions/dpmsconst.h>
|
|
|
|
|
2014-02-12 19:06:51 +01:00
|
|
|
#include "driver.h"
|
|
|
|
|
2014-11-28 11:20:48 +01:00
|
|
|
#ifdef GLAMOR
|
|
|
|
#define GLAMOR_FOR_XORG 1
|
|
|
|
#include "glamor.h"
|
2014-12-09 21:43:57 +01:00
|
|
|
#ifdef GLAMOR_HAS_GBM
|
|
|
|
#include <gbm.h>
|
|
|
|
#endif
|
2014-11-28 11:20:48 +01:00
|
|
|
#endif
|
|
|
|
|
2014-12-10 00:20:44 +01:00
|
|
|
static int
|
|
|
|
drmmode_bo_destroy(drmmode_ptr drmmode, drmmode_bo *bo)
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
|
2014-12-09 21:43:57 +01:00
|
|
|
#ifdef GLAMOR_HAS_GBM
|
|
|
|
if (bo->gbm) {
|
|
|
|
gbm_bo_destroy(bo->gbm);
|
|
|
|
bo->gbm = NULL;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2014-12-10 00:20:44 +01:00
|
|
|
if (bo->dumb) {
|
|
|
|
ret = dumb_bo_destroy(drmmode->fd, bo->dumb);
|
|
|
|
if (ret == 0)
|
|
|
|
bo->dumb = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static uint32_t
|
|
|
|
drmmode_bo_get_pitch(drmmode_bo *bo)
|
|
|
|
{
|
2014-12-09 21:43:57 +01:00
|
|
|
#ifdef GLAMOR_HAS_GBM
|
|
|
|
if (bo->gbm)
|
|
|
|
return gbm_bo_get_stride(bo->gbm);
|
|
|
|
#endif
|
|
|
|
|
2014-12-10 00:20:44 +01:00
|
|
|
return bo->dumb->pitch;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t
|
|
|
|
drmmode_bo_get_handle(drmmode_bo *bo)
|
|
|
|
{
|
2014-12-09 21:43:57 +01:00
|
|
|
#ifdef GLAMOR_HAS_GBM
|
|
|
|
if (bo->gbm)
|
|
|
|
return gbm_bo_get_handle(bo->gbm).u32;
|
|
|
|
#endif
|
|
|
|
|
2014-12-10 00:20:44 +01:00
|
|
|
return bo->dumb->handle;
|
|
|
|
}
|
|
|
|
|
|
|
|
static Bool
|
|
|
|
drmmode_create_bo(drmmode_ptr drmmode, drmmode_bo *bo,
|
|
|
|
unsigned width, unsigned height, unsigned bpp)
|
|
|
|
{
|
2014-12-09 21:43:57 +01:00
|
|
|
#ifdef GLAMOR_HAS_GBM
|
|
|
|
if (drmmode->glamor) {
|
|
|
|
bo->gbm = gbm_bo_create(drmmode->gbm, width, height,
|
|
|
|
GBM_FORMAT_ARGB8888,
|
|
|
|
GBM_BO_USE_RENDERING | GBM_BO_USE_SCANOUT);
|
|
|
|
return bo->gbm != NULL;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2014-12-10 00:20:44 +01:00
|
|
|
bo->dumb = dumb_bo_create(drmmode->fd, width, height, bpp);
|
|
|
|
return bo->dumb != NULL;
|
|
|
|
}
|
|
|
|
|
2014-10-08 09:39:15 +02:00
|
|
|
Bool
|
|
|
|
drmmode_SetSlaveBO(PixmapPtr ppix,
|
|
|
|
drmmode_ptr drmmode, int fd_handle, int pitch, int size)
|
2012-07-19 06:12:59 +02:00
|
|
|
{
|
2014-10-08 09:39:15 +02:00
|
|
|
msPixmapPrivPtr ppriv = msGetPixmapPriv(drmmode, ppix);
|
2012-07-19 06:12:59 +02:00
|
|
|
|
2014-10-08 09:39:15 +02:00
|
|
|
ppriv->backing_bo =
|
2013-12-30 09:25:37 +01:00
|
|
|
dumb_get_bo_from_fd(drmmode->fd, fd_handle, pitch, size);
|
2014-10-08 09:39:15 +02:00
|
|
|
if (!ppriv->backing_bo)
|
|
|
|
return FALSE;
|
2012-07-19 06:12:59 +02:00
|
|
|
|
2014-10-08 09:39:15 +02:00
|
|
|
close(fd_handle);
|
|
|
|
return TRUE;
|
2012-07-19 06:12:59 +02:00
|
|
|
}
|
|
|
|
|
2011-09-29 12:49:26 +02:00
|
|
|
static void
|
2014-10-08 09:39:15 +02:00
|
|
|
drmmode_ConvertFromKMode(ScrnInfoPtr scrn,
|
|
|
|
drmModeModeInfo * kmode, DisplayModePtr mode)
|
2011-09-29 12:49:26 +02:00
|
|
|
{
|
2014-10-08 09:39:15 +02:00
|
|
|
memset(mode, 0, sizeof(DisplayModeRec));
|
|
|
|
mode->status = MODE_OK;
|
|
|
|
|
|
|
|
mode->Clock = kmode->clock;
|
|
|
|
|
|
|
|
mode->HDisplay = kmode->hdisplay;
|
|
|
|
mode->HSyncStart = kmode->hsync_start;
|
|
|
|
mode->HSyncEnd = kmode->hsync_end;
|
|
|
|
mode->HTotal = kmode->htotal;
|
|
|
|
mode->HSkew = kmode->hskew;
|
|
|
|
|
|
|
|
mode->VDisplay = kmode->vdisplay;
|
|
|
|
mode->VSyncStart = kmode->vsync_start;
|
|
|
|
mode->VSyncEnd = kmode->vsync_end;
|
|
|
|
mode->VTotal = kmode->vtotal;
|
|
|
|
mode->VScan = kmode->vscan;
|
|
|
|
|
|
|
|
mode->Flags = kmode->flags; //& FLAG_BITS;
|
|
|
|
mode->name = strdup(kmode->name);
|
|
|
|
|
|
|
|
if (kmode->type & DRM_MODE_TYPE_DRIVER)
|
|
|
|
mode->type = M_T_DRIVER;
|
|
|
|
if (kmode->type & DRM_MODE_TYPE_PREFERRED)
|
|
|
|
mode->type |= M_T_PREFERRED;
|
|
|
|
xf86SetModeCrtc(mode, scrn->adjustFlags);
|
2011-09-29 12:49:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2014-10-08 09:39:15 +02:00
|
|
|
drmmode_ConvertToKMode(ScrnInfoPtr scrn,
|
|
|
|
drmModeModeInfo * kmode, DisplayModePtr mode)
|
2011-09-29 12:49:26 +02:00
|
|
|
{
|
2014-10-08 09:39:15 +02:00
|
|
|
memset(kmode, 0, sizeof(*kmode));
|
|
|
|
|
|
|
|
kmode->clock = mode->Clock;
|
|
|
|
kmode->hdisplay = mode->HDisplay;
|
|
|
|
kmode->hsync_start = mode->HSyncStart;
|
|
|
|
kmode->hsync_end = mode->HSyncEnd;
|
|
|
|
kmode->htotal = mode->HTotal;
|
|
|
|
kmode->hskew = mode->HSkew;
|
|
|
|
|
|
|
|
kmode->vdisplay = mode->VDisplay;
|
|
|
|
kmode->vsync_start = mode->VSyncStart;
|
|
|
|
kmode->vsync_end = mode->VSyncEnd;
|
|
|
|
kmode->vtotal = mode->VTotal;
|
|
|
|
kmode->vscan = mode->VScan;
|
|
|
|
|
|
|
|
kmode->flags = mode->Flags; //& FLAG_BITS;
|
|
|
|
if (mode->name)
|
|
|
|
strncpy(kmode->name, mode->name, DRM_DISPLAY_MODE_LEN);
|
|
|
|
kmode->name[DRM_DISPLAY_MODE_LEN - 1] = 0;
|
2011-09-29 12:49:26 +02:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
drmmode_crtc_dpms(xf86CrtcPtr crtc, int mode)
|
|
|
|
{
|
|
|
|
#if 0
|
2014-10-08 09:39:15 +02:00
|
|
|
xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
|
|
|
|
|
|
|
|
// drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
|
|
|
|
// drmmode_ptr drmmode = drmmode_crtc->drmmode;
|
|
|
|
|
|
|
|
/* bonghits in the randr 1.2 - uses dpms to disable crtc - bad buzz */
|
|
|
|
if (mode == DPMSModeOff) {
|
|
|
|
// drmModeSetCrtc(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
|
|
|
|
// 0, 0, 0, NULL, 0, NULL);
|
|
|
|
}
|
2011-09-29 12:49:26 +02:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
static PixmapPtr
|
2014-10-08 09:39:15 +02:00
|
|
|
create_pixmap_for_fbcon(drmmode_ptr drmmode, ScrnInfoPtr pScrn, int crtc_id)
|
2011-09-29 12:49:26 +02:00
|
|
|
{
|
2014-10-08 09:39:15 +02:00
|
|
|
xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
|
|
|
|
drmmode_crtc_private_ptr drmmode_crtc;
|
|
|
|
ScreenPtr pScreen = pScrn->pScreen;
|
|
|
|
PixmapPtr pixmap;
|
|
|
|
struct radeon_bo *bo;
|
|
|
|
drmModeFBPtr fbcon;
|
|
|
|
struct drm_gem_flink flink;
|
|
|
|
|
|
|
|
drmmode_crtc = xf86_config->crtc[crtc_id]->driver_private;
|
|
|
|
|
|
|
|
fbcon = drmModeGetFB(drmmode->fd, drmmode_crtc->mode_crtc->buffer_id);
|
|
|
|
if (fbcon == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
flink.handle = fbcon->handle;
|
|
|
|
if (ioctl(drmmode->fd, DRM_IOCTL_GEM_FLINK, &flink) < 0) {
|
|
|
|
xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Couldn't flink fbcon handle\n");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
bo = radeon_bo_open(drmmode->bufmgr, flink.name, 0, 0, 0, 0);
|
|
|
|
if (bo == NULL) {
|
|
|
|
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
|
|
|
|
"Couldn't allocate bo for fbcon handle\n");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
pixmap = drmmode_create_bo_pixmap(pScreen, fbcon->width, fbcon->height,
|
|
|
|
fbcon->depth, fbcon->bpp,
|
|
|
|
fbcon->pitch, bo);
|
|
|
|
if (!pixmap)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
radeon_bo_unref(bo);
|
|
|
|
drmModeFreeFB(fbcon);
|
|
|
|
return pixmap;
|
2011-09-29 12:49:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
static Bool
|
|
|
|
drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
|
2014-10-08 09:39:15 +02:00
|
|
|
Rotation rotation, int x, int y)
|
2011-09-29 12:49:26 +02:00
|
|
|
{
|
2014-10-08 09:39:15 +02:00
|
|
|
ScrnInfoPtr pScrn = crtc->scrn;
|
|
|
|
xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
|
|
|
|
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
|
|
|
|
drmmode_ptr drmmode = drmmode_crtc->drmmode;
|
|
|
|
int saved_x, saved_y;
|
|
|
|
Rotation saved_rotation;
|
|
|
|
DisplayModeRec saved_mode;
|
|
|
|
uint32_t *output_ids;
|
|
|
|
int output_count = 0;
|
|
|
|
Bool ret = TRUE;
|
|
|
|
int i;
|
|
|
|
uint32_t fb_id;
|
|
|
|
drmModeModeInfo kmode;
|
|
|
|
int height;
|
|
|
|
|
|
|
|
height = pScrn->virtualY;
|
|
|
|
|
|
|
|
if (drmmode->fb_id == 0) {
|
|
|
|
ret = drmModeAddFB(drmmode->fd,
|
|
|
|
pScrn->virtualX, height,
|
|
|
|
pScrn->depth, pScrn->bitsPerPixel,
|
2014-12-10 00:20:44 +01:00
|
|
|
drmmode_bo_get_pitch(&drmmode->front_bo),
|
|
|
|
drmmode_bo_get_handle(&drmmode->front_bo),
|
|
|
|
&drmmode->fb_id);
|
2014-10-08 09:39:15 +02:00
|
|
|
if (ret < 0) {
|
|
|
|
ErrorF("failed to add fb %d\n", ret);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
saved_mode = crtc->mode;
|
|
|
|
saved_x = crtc->x;
|
|
|
|
saved_y = crtc->y;
|
|
|
|
saved_rotation = crtc->rotation;
|
|
|
|
|
|
|
|
if (mode) {
|
|
|
|
crtc->mode = *mode;
|
|
|
|
crtc->x = x;
|
|
|
|
crtc->y = y;
|
|
|
|
crtc->rotation = rotation;
|
|
|
|
crtc->transformPresent = FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
output_ids = calloc(sizeof(uint32_t), xf86_config->num_output);
|
|
|
|
if (!output_ids) {
|
|
|
|
ret = FALSE;
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mode) {
|
|
|
|
for (i = 0; i < xf86_config->num_output; i++) {
|
|
|
|
xf86OutputPtr output = xf86_config->output[i];
|
|
|
|
drmmode_output_private_ptr drmmode_output;
|
|
|
|
|
|
|
|
if (output->crtc != crtc)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
drmmode_output = output->driver_private;
|
|
|
|
output_ids[output_count] =
|
|
|
|
drmmode_output->mode_output->connector_id;
|
|
|
|
output_count++;
|
2011-09-29 12:49:26 +02:00
|
|
|
}
|
|
|
|
|
2014-10-08 09:39:15 +02:00
|
|
|
if (!xf86CrtcRotate(crtc)) {
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
crtc->funcs->gamma_set(crtc, crtc->gamma_red, crtc->gamma_green,
|
|
|
|
crtc->gamma_blue, crtc->gamma_size);
|
|
|
|
|
|
|
|
drmmode_ConvertToKMode(crtc->scrn, &kmode, mode);
|
|
|
|
|
|
|
|
fb_id = drmmode->fb_id;
|
|
|
|
if (crtc->randr_crtc->scanout_pixmap) {
|
|
|
|
msPixmapPrivPtr ppriv =
|
|
|
|
msGetPixmapPriv(drmmode, crtc->randr_crtc->scanout_pixmap);
|
|
|
|
fb_id = ppriv->fb_id;
|
|
|
|
x = y = 0;
|
|
|
|
}
|
|
|
|
else if (drmmode_crtc->rotate_fb_id) {
|
|
|
|
fb_id = drmmode_crtc->rotate_fb_id;
|
|
|
|
x = y = 0;
|
|
|
|
}
|
|
|
|
ret = drmModeSetCrtc(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
|
|
|
|
fb_id, x, y, output_ids, output_count, &kmode);
|
|
|
|
if (ret)
|
|
|
|
xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR,
|
|
|
|
"failed to set mode: %s", strerror(-ret));
|
|
|
|
else
|
|
|
|
ret = TRUE;
|
|
|
|
|
|
|
|
if (crtc->scrn->pScreen)
|
|
|
|
xf86CrtcSetScreenSubpixelOrder(crtc->scrn->pScreen);
|
|
|
|
/* go through all the outputs and force DPMS them back on? */
|
|
|
|
for (i = 0; i < xf86_config->num_output; i++) {
|
|
|
|
xf86OutputPtr output = xf86_config->output[i];
|
|
|
|
|
|
|
|
if (output->crtc != crtc)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
output->funcs->dpms(output, DPMSModeOn);
|
|
|
|
}
|
|
|
|
}
|
2011-09-29 12:49:26 +02:00
|
|
|
|
|
|
|
#if 0
|
2014-10-08 09:39:15 +02:00
|
|
|
if (pScrn->pScreen &&
|
|
|
|
!xf86ReturnOptValBool(info->Options, OPTION_SW_CURSOR, FALSE))
|
|
|
|
xf86_reload_cursors(pScrn->pScreen);
|
2011-09-29 12:49:26 +02:00
|
|
|
#endif
|
2014-10-08 09:39:15 +02:00
|
|
|
done:
|
|
|
|
if (!ret) {
|
|
|
|
crtc->x = saved_x;
|
|
|
|
crtc->y = saved_y;
|
|
|
|
crtc->rotation = saved_rotation;
|
|
|
|
crtc->mode = saved_mode;
|
|
|
|
}
|
2011-09-29 12:49:26 +02:00
|
|
|
#if defined(XF86_CRTC_VERSION) && XF86_CRTC_VERSION >= 3
|
2014-10-08 09:39:15 +02:00
|
|
|
else
|
|
|
|
crtc->active = TRUE;
|
2011-09-29 12:49:26 +02:00
|
|
|
#endif
|
|
|
|
|
2014-10-08 09:39:15 +02:00
|
|
|
return ret;
|
2011-09-29 12:49:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2014-10-08 09:39:15 +02:00
|
|
|
drmmode_set_cursor_colors(xf86CrtcPtr crtc, int bg, int fg)
|
2011-09-29 12:49:26 +02:00
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2014-10-08 09:39:15 +02:00
|
|
|
drmmode_set_cursor_position(xf86CrtcPtr crtc, int x, int y)
|
2011-09-29 12:49:26 +02:00
|
|
|
{
|
2014-10-08 09:39:15 +02:00
|
|
|
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
|
|
|
|
drmmode_ptr drmmode = drmmode_crtc->drmmode;
|
2011-09-29 12:49:26 +02:00
|
|
|
|
2014-10-08 09:39:15 +02:00
|
|
|
drmModeMoveCursor(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, x, y);
|
2011-09-29 12:49:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2014-12-17 08:14:34 +01:00
|
|
|
drmmode_set_cursor(xf86CrtcPtr crtc)
|
2011-09-29 12:49:26 +02:00
|
|
|
{
|
2014-10-08 09:39:15 +02:00
|
|
|
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
|
2014-12-17 08:14:34 +01:00
|
|
|
drmmode_ptr drmmode = drmmode_crtc->drmmode;
|
2014-10-08 09:39:15 +02:00
|
|
|
uint32_t handle = drmmode_crtc->cursor_bo->handle;
|
2014-12-17 08:14:34 +01:00
|
|
|
modesettingPtr ms = modesettingPTR(crtc->scrn);
|
|
|
|
static Bool use_set_cursor2 = TRUE;
|
2014-10-08 09:39:15 +02:00
|
|
|
int ret;
|
|
|
|
|
2014-12-17 08:14:34 +01:00
|
|
|
if (use_set_cursor2) {
|
|
|
|
xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
|
|
|
|
CursorPtr cursor = xf86_config->cursor;
|
2014-10-08 09:39:15 +02:00
|
|
|
|
2014-12-17 08:14:34 +01:00
|
|
|
ret =
|
|
|
|
drmModeSetCursor2(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
|
|
|
|
handle, ms->cursor_width, ms->cursor_height,
|
|
|
|
cursor->bits->xhot, cursor->bits->yhot);
|
|
|
|
if (ret == -EINVAL)
|
|
|
|
use_set_cursor2 = FALSE;
|
|
|
|
else
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = drmModeSetCursor(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, handle,
|
|
|
|
ms->cursor_width, ms->cursor_height);
|
2014-10-08 09:39:15 +02:00
|
|
|
|
|
|
|
if (ret) {
|
|
|
|
xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
|
|
|
|
xf86CursorInfoPtr cursor_info = xf86_config->cursor_info;
|
|
|
|
|
|
|
|
cursor_info->MaxWidth = cursor_info->MaxHeight = 0;
|
|
|
|
drmmode_crtc->drmmode->sw_cursor = TRUE;
|
|
|
|
/* fallback to swcursor */
|
|
|
|
}
|
2011-09-29 12:49:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2014-12-17 08:14:34 +01:00
|
|
|
drmmode_load_cursor_argb(xf86CrtcPtr crtc, CARD32 *image)
|
2011-09-29 12:49:26 +02:00
|
|
|
{
|
2014-10-08 09:39:15 +02:00
|
|
|
modesettingPtr ms = modesettingPTR(crtc->scrn);
|
|
|
|
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
|
2014-12-17 08:14:34 +01:00
|
|
|
int i;
|
|
|
|
uint32_t *ptr;
|
2011-09-29 12:49:26 +02:00
|
|
|
|
2014-12-17 08:14:34 +01:00
|
|
|
/* cursor should be mapped already */
|
|
|
|
ptr = (uint32_t *) (drmmode_crtc->cursor_bo->ptr);
|
|
|
|
|
|
|
|
for (i = 0; i < ms->cursor_width * ms->cursor_height; i++)
|
|
|
|
ptr[i] = image[i]; // cpu_to_le32(image[i]);
|
2011-09-29 12:49:26 +02:00
|
|
|
|
2014-12-17 08:14:34 +01:00
|
|
|
if (drmmode_crtc->cursor_up)
|
|
|
|
drmmode_set_cursor(crtc);
|
2011-09-29 12:49:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2014-12-17 08:14:34 +01:00
|
|
|
drmmode_hide_cursor(xf86CrtcPtr crtc)
|
2011-09-29 12:49:26 +02:00
|
|
|
{
|
2014-10-08 09:39:15 +02:00
|
|
|
modesettingPtr ms = modesettingPTR(crtc->scrn);
|
|
|
|
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
|
|
|
|
drmmode_ptr drmmode = drmmode_crtc->drmmode;
|
|
|
|
|
2014-12-17 08:14:34 +01:00
|
|
|
drmmode_crtc->cursor_up = FALSE;
|
|
|
|
drmModeSetCursor(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, 0,
|
2014-10-08 09:39:15 +02:00
|
|
|
ms->cursor_width, ms->cursor_height);
|
2011-09-29 12:49:26 +02:00
|
|
|
}
|
|
|
|
|
2014-12-17 08:14:34 +01:00
|
|
|
static void
|
|
|
|
drmmode_show_cursor(xf86CrtcPtr crtc)
|
|
|
|
{
|
|
|
|
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
|
|
|
|
drmmode_crtc->cursor_up = TRUE;
|
|
|
|
drmmode_set_cursor(crtc);
|
|
|
|
}
|
|
|
|
|
2011-09-29 12:49:26 +02:00
|
|
|
static void
|
2014-10-08 09:39:15 +02:00
|
|
|
drmmode_crtc_gamma_set(xf86CrtcPtr crtc, uint16_t * red, uint16_t * green,
|
|
|
|
uint16_t * blue, int size)
|
2011-09-29 12:49:26 +02:00
|
|
|
{
|
2014-10-08 09:39:15 +02:00
|
|
|
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
|
|
|
|
drmmode_ptr drmmode = drmmode_crtc->drmmode;
|
2011-09-29 12:49:26 +02:00
|
|
|
|
2014-10-08 09:39:15 +02:00
|
|
|
drmModeCrtcSetGamma(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
|
|
|
|
size, red, green, blue);
|
2011-09-29 12:49:26 +02:00
|
|
|
}
|
|
|
|
|
2012-07-19 06:12:59 +02:00
|
|
|
static Bool
|
|
|
|
drmmode_set_scanout_pixmap(xf86CrtcPtr crtc, PixmapPtr ppix)
|
|
|
|
{
|
2014-10-08 09:39:15 +02:00
|
|
|
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
|
|
|
|
drmmode_ptr drmmode = drmmode_crtc->drmmode;
|
|
|
|
msPixmapPrivPtr ppriv;
|
|
|
|
void *ptr;
|
|
|
|
|
|
|
|
if (!ppix) {
|
|
|
|
if (crtc->randr_crtc->scanout_pixmap) {
|
|
|
|
ppriv = msGetPixmapPriv(drmmode, crtc->randr_crtc->scanout_pixmap);
|
|
|
|
drmModeRmFB(drmmode->fd, ppriv->fb_id);
|
|
|
|
}
|
|
|
|
if (drmmode_crtc->slave_damage) {
|
|
|
|
DamageUnregister(drmmode_crtc->slave_damage);
|
|
|
|
drmmode_crtc->slave_damage = NULL;
|
|
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
ppriv = msGetPixmapPriv(drmmode, ppix);
|
|
|
|
if (!drmmode_crtc->slave_damage) {
|
|
|
|
drmmode_crtc->slave_damage = DamageCreate(NULL, NULL,
|
|
|
|
DamageReportNone,
|
|
|
|
TRUE,
|
|
|
|
crtc->randr_crtc->pScreen,
|
|
|
|
NULL);
|
|
|
|
}
|
|
|
|
ptr = drmmode_map_slave_bo(drmmode, ppriv);
|
|
|
|
ppix->devPrivate.ptr = ptr;
|
|
|
|
DamageRegister(&ppix->drawable, drmmode_crtc->slave_damage);
|
|
|
|
|
|
|
|
if (ppriv->fb_id == 0) {
|
|
|
|
drmModeAddFB(drmmode->fd, ppix->drawable.width,
|
|
|
|
ppix->drawable.height,
|
|
|
|
ppix->drawable.depth,
|
|
|
|
ppix->drawable.bitsPerPixel,
|
|
|
|
ppix->devKind, ppriv->backing_bo->handle, &ppriv->fb_id);
|
|
|
|
}
|
|
|
|
return TRUE;
|
2012-07-19 06:12:59 +02:00
|
|
|
}
|
|
|
|
|
2014-10-08 09:39:15 +02:00
|
|
|
static void *
|
|
|
|
drmmode_shadow_allocate(xf86CrtcPtr crtc, int width, int height)
|
2013-02-07 03:24:20 +01:00
|
|
|
{
|
2014-10-08 09:39:15 +02:00
|
|
|
return NULL;
|
2013-02-07 03:24:20 +01:00
|
|
|
}
|
|
|
|
|
2014-10-08 09:39:15 +02:00
|
|
|
static PixmapPtr
|
|
|
|
drmmode_shadow_create(xf86CrtcPtr crtc, void *data, int width, int height)
|
2013-02-07 03:24:20 +01:00
|
|
|
{
|
2014-10-08 09:39:15 +02:00
|
|
|
return NULL;
|
2013-02-07 03:24:20 +01:00
|
|
|
}
|
|
|
|
|
2011-09-29 12:49:26 +02:00
|
|
|
static const xf86CrtcFuncsRec drmmode_crtc_funcs = {
|
|
|
|
.dpms = drmmode_crtc_dpms,
|
|
|
|
.set_mode_major = drmmode_set_mode_major,
|
|
|
|
.set_cursor_colors = drmmode_set_cursor_colors,
|
|
|
|
.set_cursor_position = drmmode_set_cursor_position,
|
|
|
|
.show_cursor = drmmode_show_cursor,
|
|
|
|
.hide_cursor = drmmode_hide_cursor,
|
|
|
|
.load_cursor_argb = drmmode_load_cursor_argb,
|
|
|
|
|
|
|
|
.gamma_set = drmmode_crtc_gamma_set,
|
2014-10-08 09:39:15 +02:00
|
|
|
.destroy = NULL, /* XXX */
|
2012-07-19 06:12:59 +02:00
|
|
|
.set_scanout_pixmap = drmmode_set_scanout_pixmap,
|
2013-02-07 03:24:20 +01:00
|
|
|
.shadow_allocate = drmmode_shadow_allocate,
|
|
|
|
.shadow_create = drmmode_shadow_create,
|
2011-09-29 12:49:26 +02:00
|
|
|
};
|
|
|
|
|
modesetting: Add support for DRI2 with glamor.
This is derived from the intel driver DRI2 code, with swapchain and
pageflipping dropped, functions renamed, and vblank event management
shared code moved to a vblank.c for reuse by Present.
This allows AIGLX to load, which means that you get appropriate
visuals exposed in GL, along with many extensions under
direct-rendering that require presence in GLX (which aren't supported
in glxdriswrast.c).
v2: Drop unused header includes in pageflip.c, wrap in #ifdef GLAMOR.
Drop triple-buffering, which was totally broken in practice (I'll
try to fix this later). Fix up some style nits. Document the
general flow of pageflipping and why, rename the DRI2 frame event
type enums to reflect what they're for, and handle them in a
single switch statement so you can understand the state machine
more easily.
v3: Drop pageflipping entirely -- it's unstable on my Intel laptop
(not that the normal 2D driver is stable with pageflipping for
me), and I won't get it fixed before the merge window. It now
passes all of the OML_sync_control tests from Jamey and Theo
(except for occasional warns in timing -fullscreen -divisor 2).
v4: Fix doxygen at the top of vblank.c
Signed-off-by: Eric Anholt <eric@anholt.net>
Reviewed-by: Adam Jackson <ajax@redhat.com>
2013-12-31 02:23:38 +01:00
|
|
|
static uint32_t
|
|
|
|
drmmode_crtc_vblank_pipe(int crtc_id)
|
|
|
|
{
|
|
|
|
if (crtc_id > 1)
|
|
|
|
return crtc_id << DRM_VBLANK_HIGH_CRTC_SHIFT;
|
|
|
|
else if (crtc_id > 0)
|
|
|
|
return DRM_VBLANK_SECONDARY;
|
|
|
|
else
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2011-09-29 12:49:26 +02:00
|
|
|
static void
|
|
|
|
drmmode_crtc_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int num)
|
|
|
|
{
|
2014-10-08 09:39:15 +02:00
|
|
|
xf86CrtcPtr crtc;
|
|
|
|
drmmode_crtc_private_ptr drmmode_crtc;
|
|
|
|
|
|
|
|
crtc = xf86CrtcCreate(pScrn, &drmmode_crtc_funcs);
|
|
|
|
if (crtc == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
drmmode_crtc = xnfcalloc(sizeof(drmmode_crtc_private_rec), 1);
|
|
|
|
drmmode_crtc->mode_crtc =
|
|
|
|
drmModeGetCrtc(drmmode->fd, drmmode->mode_res->crtcs[num]);
|
|
|
|
drmmode_crtc->drmmode = drmmode;
|
modesetting: Add support for DRI2 with glamor.
This is derived from the intel driver DRI2 code, with swapchain and
pageflipping dropped, functions renamed, and vblank event management
shared code moved to a vblank.c for reuse by Present.
This allows AIGLX to load, which means that you get appropriate
visuals exposed in GL, along with many extensions under
direct-rendering that require presence in GLX (which aren't supported
in glxdriswrast.c).
v2: Drop unused header includes in pageflip.c, wrap in #ifdef GLAMOR.
Drop triple-buffering, which was totally broken in practice (I'll
try to fix this later). Fix up some style nits. Document the
general flow of pageflipping and why, rename the DRI2 frame event
type enums to reflect what they're for, and handle them in a
single switch statement so you can understand the state machine
more easily.
v3: Drop pageflipping entirely -- it's unstable on my Intel laptop
(not that the normal 2D driver is stable with pageflipping for
me), and I won't get it fixed before the merge window. It now
passes all of the OML_sync_control tests from Jamey and Theo
(except for occasional warns in timing -fullscreen -divisor 2).
v4: Fix doxygen at the top of vblank.c
Signed-off-by: Eric Anholt <eric@anholt.net>
Reviewed-by: Adam Jackson <ajax@redhat.com>
2013-12-31 02:23:38 +01:00
|
|
|
drmmode_crtc->vblank_pipe = drmmode_crtc_vblank_pipe(num);
|
2014-10-08 09:39:15 +02:00
|
|
|
crtc->driver_private = drmmode_crtc;
|
2011-09-29 12:49:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static xf86OutputStatus
|
|
|
|
drmmode_output_detect(xf86OutputPtr output)
|
|
|
|
{
|
2014-10-08 09:39:15 +02:00
|
|
|
/* go to the hw and retrieve a new output struct */
|
|
|
|
drmmode_output_private_ptr drmmode_output = output->driver_private;
|
|
|
|
drmmode_ptr drmmode = drmmode_output->drmmode;
|
|
|
|
xf86OutputStatus status;
|
|
|
|
|
|
|
|
drmModeFreeConnector(drmmode_output->mode_output);
|
|
|
|
|
|
|
|
drmmode_output->mode_output =
|
|
|
|
drmModeGetConnector(drmmode->fd, drmmode_output->output_id);
|
|
|
|
if (!drmmode_output->mode_output)
|
|
|
|
return XF86OutputStatusDisconnected;
|
|
|
|
|
|
|
|
switch (drmmode_output->mode_output->connection) {
|
|
|
|
case DRM_MODE_CONNECTED:
|
|
|
|
status = XF86OutputStatusConnected;
|
|
|
|
break;
|
|
|
|
case DRM_MODE_DISCONNECTED:
|
|
|
|
status = XF86OutputStatusDisconnected;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
case DRM_MODE_UNKNOWNCONNECTION:
|
|
|
|
status = XF86OutputStatusUnknown;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return status;
|
2011-09-29 12:49:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static Bool
|
|
|
|
drmmode_output_mode_valid(xf86OutputPtr output, DisplayModePtr pModes)
|
|
|
|
{
|
2014-10-08 09:39:15 +02:00
|
|
|
return MODE_OK;
|
2011-09-29 12:49:26 +02:00
|
|
|
}
|
|
|
|
|
2012-12-03 14:25:19 +01:00
|
|
|
static Bool
|
|
|
|
has_panel_fitter(xf86OutputPtr output)
|
|
|
|
{
|
2014-10-08 09:39:15 +02:00
|
|
|
drmmode_output_private_ptr drmmode_output = output->driver_private;
|
|
|
|
drmModeConnectorPtr koutput = drmmode_output->mode_output;
|
|
|
|
drmmode_ptr drmmode = drmmode_output->drmmode;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
/* Presume that if the output supports scaling, then we have a
|
|
|
|
* panel fitter capable of adjust any mode to suit.
|
|
|
|
*/
|
|
|
|
for (i = 0; i < koutput->count_props; i++) {
|
|
|
|
drmModePropertyPtr props;
|
|
|
|
Bool found = FALSE;
|
|
|
|
|
|
|
|
props = drmModeGetProperty(drmmode->fd, koutput->props[i]);
|
|
|
|
if (props) {
|
|
|
|
found = strcmp(props->name, "scaling mode") == 0;
|
|
|
|
drmModeFreeProperty(props);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (found)
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return FALSE;
|
2012-12-03 14:25:19 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static DisplayModePtr
|
2014-10-08 09:39:15 +02:00
|
|
|
drmmode_output_add_gtf_modes(xf86OutputPtr output, DisplayModePtr Modes)
|
2012-12-03 14:25:19 +01:00
|
|
|
{
|
2014-10-08 09:39:15 +02:00
|
|
|
xf86MonPtr mon = output->MonInfo;
|
|
|
|
DisplayModePtr i, m, preferred = NULL;
|
|
|
|
int max_x = 0, max_y = 0;
|
|
|
|
float max_vrefresh = 0.0;
|
|
|
|
|
|
|
|
if (mon && GTF_SUPPORTED(mon->features.msc))
|
|
|
|
return Modes;
|
|
|
|
|
|
|
|
if (!has_panel_fitter(output))
|
|
|
|
return Modes;
|
|
|
|
|
|
|
|
for (m = Modes; m; m = m->next) {
|
|
|
|
if (m->type & M_T_PREFERRED)
|
|
|
|
preferred = m;
|
|
|
|
max_x = max(max_x, m->HDisplay);
|
|
|
|
max_y = max(max_y, m->VDisplay);
|
|
|
|
max_vrefresh = max(max_vrefresh, xf86ModeVRefresh(m));
|
|
|
|
}
|
|
|
|
|
|
|
|
max_vrefresh = max(max_vrefresh, 60.0);
|
|
|
|
max_vrefresh *= (1 + SYNC_TOLERANCE);
|
|
|
|
|
|
|
|
m = xf86GetDefaultModes();
|
|
|
|
xf86ValidateModesSize(output->scrn, m, max_x, max_y, 0);
|
|
|
|
|
|
|
|
for (i = m; i; i = i->next) {
|
|
|
|
if (xf86ModeVRefresh(i) > max_vrefresh)
|
|
|
|
i->status = MODE_VSYNC;
|
|
|
|
if (preferred &&
|
|
|
|
i->HDisplay >= preferred->HDisplay &&
|
|
|
|
i->VDisplay >= preferred->VDisplay &&
|
|
|
|
xf86ModeVRefresh(i) >= xf86ModeVRefresh(preferred))
|
|
|
|
i->status = MODE_VSYNC;
|
|
|
|
}
|
|
|
|
|
|
|
|
xf86PruneInvalidModes(output->scrn, &m, FALSE);
|
|
|
|
|
|
|
|
return xf86ModesAdd(Modes, m);
|
2012-12-03 14:25:19 +01:00
|
|
|
}
|
|
|
|
|
2011-09-29 12:49:26 +02:00
|
|
|
static DisplayModePtr
|
|
|
|
drmmode_output_get_modes(xf86OutputPtr output)
|
|
|
|
{
|
2014-10-08 09:39:15 +02:00
|
|
|
drmmode_output_private_ptr drmmode_output = output->driver_private;
|
|
|
|
drmModeConnectorPtr koutput = drmmode_output->mode_output;
|
|
|
|
drmmode_ptr drmmode = drmmode_output->drmmode;
|
|
|
|
int i;
|
|
|
|
DisplayModePtr Modes = NULL, Mode;
|
|
|
|
drmModePropertyPtr props;
|
|
|
|
xf86MonPtr mon = NULL;
|
|
|
|
|
|
|
|
if (!koutput)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
/* look for an EDID property */
|
|
|
|
for (i = 0; i < koutput->count_props; i++) {
|
|
|
|
props = drmModeGetProperty(drmmode->fd, koutput->props[i]);
|
|
|
|
if (props && (props->flags & DRM_MODE_PROP_BLOB)) {
|
|
|
|
if (!strcmp(props->name, "EDID")) {
|
|
|
|
if (drmmode_output->edid_blob)
|
|
|
|
drmModeFreePropertyBlob(drmmode_output->edid_blob);
|
|
|
|
drmmode_output->edid_blob =
|
|
|
|
drmModeGetPropertyBlob(drmmode->fd,
|
|
|
|
koutput->prop_values[i]);
|
|
|
|
}
|
|
|
|
drmModeFreeProperty(props);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (drmmode_output->edid_blob) {
|
|
|
|
mon = xf86InterpretEDID(output->scrn->scrnIndex,
|
|
|
|
drmmode_output->edid_blob->data);
|
|
|
|
if (mon && drmmode_output->edid_blob->length > 128)
|
|
|
|
mon->flags |= MONITOR_EDID_COMPLETE_RAWDATA;
|
|
|
|
}
|
|
|
|
xf86OutputSetEDID(output, mon);
|
|
|
|
|
|
|
|
/* modes should already be available */
|
|
|
|
for (i = 0; i < koutput->count_modes; i++) {
|
|
|
|
Mode = xnfalloc(sizeof(DisplayModeRec));
|
|
|
|
|
|
|
|
drmmode_ConvertFromKMode(output->scrn, &koutput->modes[i], Mode);
|
|
|
|
Modes = xf86ModesAdd(Modes, Mode);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return drmmode_output_add_gtf_modes(output, Modes);
|
2011-09-29 12:49:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
drmmode_output_destroy(xf86OutputPtr output)
|
|
|
|
{
|
2014-10-08 09:39:15 +02:00
|
|
|
drmmode_output_private_ptr drmmode_output = output->driver_private;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (drmmode_output->edid_blob)
|
|
|
|
drmModeFreePropertyBlob(drmmode_output->edid_blob);
|
|
|
|
for (i = 0; i < drmmode_output->num_props; i++) {
|
|
|
|
drmModeFreeProperty(drmmode_output->props[i].mode_prop);
|
|
|
|
free(drmmode_output->props[i].atoms);
|
|
|
|
}
|
|
|
|
free(drmmode_output->props);
|
|
|
|
for (i = 0; i < drmmode_output->mode_output->count_encoders; i++) {
|
|
|
|
drmModeFreeEncoder(drmmode_output->mode_encoders[i]);
|
|
|
|
}
|
|
|
|
free(drmmode_output->mode_encoders);
|
|
|
|
drmModeFreeConnector(drmmode_output->mode_output);
|
|
|
|
free(drmmode_output);
|
|
|
|
output->driver_private = NULL;
|
2011-09-29 12:49:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
drmmode_output_dpms(xf86OutputPtr output, int mode)
|
|
|
|
{
|
2014-10-08 09:39:15 +02:00
|
|
|
drmmode_output_private_ptr drmmode_output = output->driver_private;
|
|
|
|
drmModeConnectorPtr koutput = drmmode_output->mode_output;
|
|
|
|
drmmode_ptr drmmode = drmmode_output->drmmode;
|
2011-09-29 12:49:26 +02:00
|
|
|
|
2014-10-08 09:39:15 +02:00
|
|
|
if (!koutput)
|
|
|
|
return;
|
2013-01-09 03:48:30 +01:00
|
|
|
|
2014-10-08 09:39:15 +02:00
|
|
|
drmModeConnectorSetProperty(drmmode->fd, koutput->connector_id,
|
|
|
|
drmmode_output->dpms_enum_id, mode);
|
|
|
|
return;
|
2011-09-29 12:49:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static Bool
|
|
|
|
drmmode_property_ignore(drmModePropertyPtr prop)
|
|
|
|
{
|
|
|
|
if (!prop)
|
2014-10-08 09:39:15 +02:00
|
|
|
return TRUE;
|
2011-09-29 12:49:26 +02:00
|
|
|
/* ignore blob prop */
|
|
|
|
if (prop->flags & DRM_MODE_PROP_BLOB)
|
2014-10-08 09:39:15 +02:00
|
|
|
return TRUE;
|
2011-09-29 12:49:26 +02:00
|
|
|
/* ignore standard property */
|
2014-10-08 09:39:15 +02:00
|
|
|
if (!strcmp(prop->name, "EDID") || !strcmp(prop->name, "DPMS"))
|
|
|
|
return TRUE;
|
2011-09-29 12:49:26 +02:00
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
drmmode_output_create_resources(xf86OutputPtr output)
|
|
|
|
{
|
|
|
|
drmmode_output_private_ptr drmmode_output = output->driver_private;
|
|
|
|
drmModeConnectorPtr mode_output = drmmode_output->mode_output;
|
|
|
|
drmmode_ptr drmmode = drmmode_output->drmmode;
|
|
|
|
drmModePropertyPtr drmmode_prop;
|
|
|
|
int i, j, err;
|
|
|
|
|
2014-10-08 09:39:15 +02:00
|
|
|
drmmode_output->props =
|
|
|
|
calloc(mode_output->count_props, sizeof(drmmode_prop_rec));
|
2011-09-29 12:49:26 +02:00
|
|
|
if (!drmmode_output->props)
|
2014-10-08 09:39:15 +02:00
|
|
|
return;
|
|
|
|
|
2011-09-29 12:49:26 +02:00
|
|
|
drmmode_output->num_props = 0;
|
|
|
|
for (i = 0, j = 0; i < mode_output->count_props; i++) {
|
2014-10-08 09:39:15 +02:00
|
|
|
drmmode_prop = drmModeGetProperty(drmmode->fd, mode_output->props[i]);
|
|
|
|
if (drmmode_property_ignore(drmmode_prop)) {
|
|
|
|
drmModeFreeProperty(drmmode_prop);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
drmmode_output->props[j].mode_prop = drmmode_prop;
|
|
|
|
drmmode_output->props[j].value = mode_output->prop_values[i];
|
|
|
|
drmmode_output->num_props++;
|
|
|
|
j++;
|
2011-09-29 12:49:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < drmmode_output->num_props; i++) {
|
2014-10-08 09:39:15 +02:00
|
|
|
drmmode_prop_ptr p = &drmmode_output->props[i];
|
|
|
|
|
|
|
|
drmmode_prop = p->mode_prop;
|
|
|
|
|
|
|
|
if (drmmode_prop->flags & DRM_MODE_PROP_RANGE) {
|
|
|
|
INT32 prop_range[2];
|
|
|
|
INT32 value = p->value;
|
|
|
|
|
|
|
|
p->num_atoms = 1;
|
|
|
|
p->atoms = calloc(p->num_atoms, sizeof(Atom));
|
|
|
|
if (!p->atoms)
|
|
|
|
continue;
|
|
|
|
p->atoms[0] =
|
|
|
|
MakeAtom(drmmode_prop->name, strlen(drmmode_prop->name), TRUE);
|
|
|
|
prop_range[0] = drmmode_prop->values[0];
|
|
|
|
prop_range[1] = drmmode_prop->values[1];
|
|
|
|
err = RRConfigureOutputProperty(output->randr_output, p->atoms[0],
|
|
|
|
FALSE, TRUE,
|
|
|
|
drmmode_prop->
|
|
|
|
flags & DRM_MODE_PROP_IMMUTABLE ?
|
|
|
|
TRUE : FALSE, 2, prop_range);
|
|
|
|
if (err != 0) {
|
|
|
|
xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
|
|
|
|
"RRConfigureOutputProperty error, %d\n", err);
|
|
|
|
}
|
|
|
|
err = RRChangeOutputProperty(output->randr_output, p->atoms[0],
|
|
|
|
XA_INTEGER, 32, PropModeReplace, 1,
|
|
|
|
&value, FALSE, TRUE);
|
|
|
|
if (err != 0) {
|
|
|
|
xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
|
|
|
|
"RRChangeOutputProperty error, %d\n", err);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (drmmode_prop->flags & DRM_MODE_PROP_ENUM) {
|
|
|
|
p->num_atoms = drmmode_prop->count_enums + 1;
|
|
|
|
p->atoms = calloc(p->num_atoms, sizeof(Atom));
|
|
|
|
if (!p->atoms)
|
|
|
|
continue;
|
|
|
|
p->atoms[0] =
|
|
|
|
MakeAtom(drmmode_prop->name, strlen(drmmode_prop->name), TRUE);
|
|
|
|
for (j = 1; j <= drmmode_prop->count_enums; j++) {
|
|
|
|
struct drm_mode_property_enum *e = &drmmode_prop->enums[j - 1];
|
|
|
|
|
|
|
|
p->atoms[j] = MakeAtom(e->name, strlen(e->name), TRUE);
|
|
|
|
}
|
|
|
|
err = RRConfigureOutputProperty(output->randr_output, p->atoms[0],
|
|
|
|
FALSE, FALSE,
|
|
|
|
drmmode_prop->
|
|
|
|
flags & DRM_MODE_PROP_IMMUTABLE ?
|
|
|
|
TRUE : FALSE, p->num_atoms - 1,
|
|
|
|
(INT32 *) &p->atoms[1]);
|
|
|
|
if (err != 0) {
|
|
|
|
xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
|
|
|
|
"RRConfigureOutputProperty error, %d\n", err);
|
|
|
|
}
|
|
|
|
for (j = 0; j < drmmode_prop->count_enums; j++)
|
|
|
|
if (drmmode_prop->enums[j].value == p->value)
|
|
|
|
break;
|
|
|
|
/* there's always a matching value */
|
|
|
|
err = RRChangeOutputProperty(output->randr_output, p->atoms[0],
|
|
|
|
XA_ATOM, 32, PropModeReplace, 1,
|
|
|
|
&p->atoms[j + 1], FALSE, TRUE);
|
|
|
|
if (err != 0) {
|
|
|
|
xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
|
|
|
|
"RRChangeOutputProperty error, %d\n", err);
|
|
|
|
}
|
|
|
|
}
|
2011-09-29 12:49:26 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static Bool
|
|
|
|
drmmode_output_set_property(xf86OutputPtr output, Atom property,
|
2014-10-08 09:39:15 +02:00
|
|
|
RRPropertyValuePtr value)
|
2011-09-29 12:49:26 +02:00
|
|
|
{
|
|
|
|
drmmode_output_private_ptr drmmode_output = output->driver_private;
|
|
|
|
drmmode_ptr drmmode = drmmode_output->drmmode;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < drmmode_output->num_props; i++) {
|
2014-10-08 09:39:15 +02:00
|
|
|
drmmode_prop_ptr p = &drmmode_output->props[i];
|
|
|
|
|
|
|
|
if (p->atoms[0] != property)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (p->mode_prop->flags & DRM_MODE_PROP_RANGE) {
|
|
|
|
uint32_t val;
|
|
|
|
|
|
|
|
if (value->type != XA_INTEGER || value->format != 32 ||
|
|
|
|
value->size != 1)
|
|
|
|
return FALSE;
|
|
|
|
val = *(uint32_t *) value->data;
|
|
|
|
|
|
|
|
drmModeConnectorSetProperty(drmmode->fd, drmmode_output->output_id,
|
|
|
|
p->mode_prop->prop_id, (uint64_t) val);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
else if (p->mode_prop->flags & DRM_MODE_PROP_ENUM) {
|
|
|
|
Atom atom;
|
|
|
|
const char *name;
|
|
|
|
int j;
|
|
|
|
|
|
|
|
if (value->type != XA_ATOM || value->format != 32 ||
|
|
|
|
value->size != 1)
|
|
|
|
return FALSE;
|
|
|
|
memcpy(&atom, value->data, 4);
|
|
|
|
name = NameForAtom(atom);
|
|
|
|
|
|
|
|
/* search for matching name string, then set its value down */
|
|
|
|
for (j = 0; j < p->mode_prop->count_enums; j++) {
|
|
|
|
if (!strcmp(p->mode_prop->enums[j].name, name)) {
|
|
|
|
drmModeConnectorSetProperty(drmmode->fd,
|
|
|
|
drmmode_output->output_id,
|
|
|
|
p->mode_prop->prop_id,
|
|
|
|
p->mode_prop->enums[j].value);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2011-09-29 12:49:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static Bool
|
|
|
|
drmmode_output_get_property(xf86OutputPtr output, Atom property)
|
|
|
|
{
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const xf86OutputFuncsRec drmmode_output_funcs = {
|
|
|
|
.dpms = drmmode_output_dpms,
|
|
|
|
.create_resources = drmmode_output_create_resources,
|
|
|
|
.set_property = drmmode_output_set_property,
|
|
|
|
.get_property = drmmode_output_get_property,
|
|
|
|
.detect = drmmode_output_detect,
|
|
|
|
.mode_valid = drmmode_output_mode_valid,
|
|
|
|
|
|
|
|
.get_modes = drmmode_output_get_modes,
|
|
|
|
.destroy = drmmode_output_destroy
|
|
|
|
};
|
|
|
|
|
2014-10-08 09:41:13 +02:00
|
|
|
static int subpixel_conv_table[7] = {
|
|
|
|
0,
|
|
|
|
SubPixelUnknown,
|
2014-10-08 09:39:15 +02:00
|
|
|
SubPixelHorizontalRGB,
|
|
|
|
SubPixelHorizontalBGR,
|
|
|
|
SubPixelVerticalRGB,
|
|
|
|
SubPixelVerticalBGR,
|
|
|
|
SubPixelNone
|
|
|
|
};
|
|
|
|
|
2014-10-08 09:41:13 +02:00
|
|
|
static const char *const output_names[] = {
|
|
|
|
"None",
|
2014-10-08 09:39:15 +02:00
|
|
|
"VGA",
|
|
|
|
"DVI",
|
|
|
|
"DVI",
|
|
|
|
"DVI",
|
|
|
|
"Composite",
|
|
|
|
"S-video",
|
|
|
|
"LVDS",
|
|
|
|
"CTV",
|
|
|
|
"DIN",
|
|
|
|
"DisplayPort",
|
|
|
|
"HDMI",
|
|
|
|
"HDMI",
|
|
|
|
"TV",
|
|
|
|
"eDP",
|
|
|
|
"Virtual",
|
|
|
|
"DSI",
|
2011-09-29 12:49:26 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
static void
|
2014-11-28 11:20:50 +01:00
|
|
|
drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int num)
|
2011-09-29 12:49:26 +02:00
|
|
|
{
|
2014-10-08 09:39:15 +02:00
|
|
|
xf86OutputPtr output;
|
|
|
|
drmModeConnectorPtr koutput;
|
|
|
|
drmModeEncoderPtr *kencoders = NULL;
|
|
|
|
drmmode_output_private_ptr drmmode_output;
|
|
|
|
drmModePropertyPtr props;
|
|
|
|
char name[32];
|
|
|
|
int i;
|
|
|
|
|
|
|
|
koutput =
|
|
|
|
drmModeGetConnector(drmmode->fd, drmmode->mode_res->connectors[num]);
|
|
|
|
if (!koutput)
|
|
|
|
return;
|
|
|
|
|
|
|
|
kencoders = calloc(sizeof(drmModeEncoderPtr), koutput->count_encoders);
|
|
|
|
if (!kencoders) {
|
|
|
|
goto out_free_encoders;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < koutput->count_encoders; i++) {
|
|
|
|
kencoders[i] = drmModeGetEncoder(drmmode->fd, koutput->encoders[i]);
|
|
|
|
if (!kencoders[i]) {
|
|
|
|
goto out_free_encoders;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* need to do smart conversion here for compat with non-kms ATI driver */
|
|
|
|
if (koutput->connector_type >= MS_ARRAY_SIZE(output_names))
|
|
|
|
snprintf(name, 32, "Unknown-%d", koutput->connector_type_id - 1);
|
|
|
|
else if (pScrn->is_gpu)
|
|
|
|
snprintf(name, 32, "%s-%d-%d", output_names[koutput->connector_type],
|
|
|
|
pScrn->scrnIndex - GPU_SCREEN_OFFSET + 1,
|
|
|
|
koutput->connector_type_id - 1);
|
|
|
|
else
|
|
|
|
snprintf(name, 32, "%s-%d", output_names[koutput->connector_type],
|
|
|
|
koutput->connector_type_id - 1);
|
|
|
|
|
|
|
|
output = xf86OutputCreate(pScrn, &drmmode_output_funcs, name);
|
|
|
|
if (!output) {
|
|
|
|
goto out_free_encoders;
|
|
|
|
}
|
|
|
|
|
|
|
|
drmmode_output = calloc(sizeof(drmmode_output_private_rec), 1);
|
|
|
|
if (!drmmode_output) {
|
|
|
|
xf86OutputDestroy(output);
|
|
|
|
goto out_free_encoders;
|
|
|
|
}
|
|
|
|
|
|
|
|
drmmode_output->output_id = drmmode->mode_res->connectors[num];
|
|
|
|
drmmode_output->mode_output = koutput;
|
|
|
|
drmmode_output->mode_encoders = kencoders;
|
|
|
|
drmmode_output->drmmode = drmmode;
|
|
|
|
output->mm_width = koutput->mmWidth;
|
|
|
|
output->mm_height = koutput->mmHeight;
|
|
|
|
|
|
|
|
output->subpixel_order = subpixel_conv_table[koutput->subpixel];
|
|
|
|
output->interlaceAllowed = TRUE;
|
|
|
|
output->doubleScanAllowed = TRUE;
|
|
|
|
output->driver_private = drmmode_output;
|
|
|
|
|
|
|
|
output->possible_crtcs = 0x7f;
|
|
|
|
for (i = 0; i < koutput->count_encoders; i++) {
|
|
|
|
output->possible_crtcs &= kencoders[i]->possible_crtcs;
|
|
|
|
}
|
|
|
|
/* work out the possible clones later */
|
|
|
|
output->possible_clones = 0;
|
|
|
|
|
|
|
|
for (i = 0; i < koutput->count_props; i++) {
|
|
|
|
props = drmModeGetProperty(drmmode->fd, koutput->props[i]);
|
|
|
|
if (props && (props->flags & DRM_MODE_PROP_ENUM)) {
|
|
|
|
if (!strcmp(props->name, "DPMS")) {
|
|
|
|
drmmode_output->dpms_enum_id = koutput->props[i];
|
|
|
|
drmModeFreeProperty(props);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
drmModeFreeProperty(props);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
|
|
|
out_free_encoders:
|
|
|
|
if (kencoders) {
|
|
|
|
for (i = 0; i < koutput->count_encoders; i++)
|
|
|
|
drmModeFreeEncoder(kencoders[i]);
|
|
|
|
free(kencoders);
|
|
|
|
}
|
|
|
|
drmModeFreeConnector(koutput);
|
|
|
|
|
2011-09-29 12:49:26 +02:00
|
|
|
}
|
|
|
|
|
2014-10-08 09:39:15 +02:00
|
|
|
static uint32_t
|
|
|
|
find_clones(ScrnInfoPtr scrn, xf86OutputPtr output)
|
2011-09-29 12:49:26 +02:00
|
|
|
{
|
2014-10-08 09:39:15 +02:00
|
|
|
drmmode_output_private_ptr drmmode_output =
|
|
|
|
output->driver_private, clone_drmout;
|
|
|
|
int i;
|
|
|
|
xf86OutputPtr clone_output;
|
|
|
|
xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
|
|
|
|
int index_mask = 0;
|
|
|
|
|
|
|
|
if (drmmode_output->enc_clone_mask == 0)
|
|
|
|
return index_mask;
|
|
|
|
|
|
|
|
for (i = 0; i < xf86_config->num_output; i++) {
|
|
|
|
clone_output = xf86_config->output[i];
|
|
|
|
clone_drmout = clone_output->driver_private;
|
|
|
|
if (output == clone_output)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (clone_drmout->enc_mask == 0)
|
|
|
|
continue;
|
|
|
|
if (drmmode_output->enc_clone_mask == clone_drmout->enc_mask)
|
|
|
|
index_mask |= (1 << i);
|
|
|
|
}
|
|
|
|
return index_mask;
|
2011-09-29 12:49:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
drmmode_clones_init(ScrnInfoPtr scrn, drmmode_ptr drmmode)
|
|
|
|
{
|
2014-10-08 09:39:15 +02:00
|
|
|
int i, j;
|
|
|
|
xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
|
|
|
|
|
|
|
|
for (i = 0; i < xf86_config->num_output; i++) {
|
|
|
|
xf86OutputPtr output = xf86_config->output[i];
|
|
|
|
drmmode_output_private_ptr drmmode_output;
|
|
|
|
|
|
|
|
drmmode_output = output->driver_private;
|
|
|
|
drmmode_output->enc_clone_mask = 0xff;
|
|
|
|
/* and all the possible encoder clones for this output together */
|
|
|
|
for (j = 0; j < drmmode_output->mode_output->count_encoders; j++) {
|
|
|
|
int k;
|
|
|
|
|
|
|
|
for (k = 0; k < drmmode->mode_res->count_encoders; k++) {
|
|
|
|
if (drmmode->mode_res->encoders[k] ==
|
|
|
|
drmmode_output->mode_encoders[j]->encoder_id)
|
|
|
|
drmmode_output->enc_mask |= (1 << k);
|
|
|
|
}
|
|
|
|
|
|
|
|
drmmode_output->enc_clone_mask &=
|
|
|
|
drmmode_output->mode_encoders[j]->possible_clones;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < xf86_config->num_output; i++) {
|
|
|
|
xf86OutputPtr output = xf86_config->output[i];
|
|
|
|
|
|
|
|
output->possible_clones = find_clones(scrn, output);
|
|
|
|
}
|
2011-09-29 12:49:26 +02:00
|
|
|
}
|
|
|
|
|
2014-12-10 00:18:39 +01:00
|
|
|
Bool
|
|
|
|
drmmode_glamor_handle_new_screen_pixmap(drmmode_ptr drmmode)
|
|
|
|
{
|
|
|
|
#ifdef GLAMOR
|
|
|
|
ScrnInfoPtr scrn = drmmode->scrn;
|
|
|
|
ScreenPtr screen = xf86ScrnToScreen(drmmode->scrn);
|
2014-12-09 21:43:57 +01:00
|
|
|
PixmapPtr screen_pixmap;
|
|
|
|
void *gbm_bo;
|
2014-12-10 00:18:39 +01:00
|
|
|
|
|
|
|
if (!drmmode->glamor)
|
|
|
|
return TRUE;
|
|
|
|
|
2014-12-09 21:43:57 +01:00
|
|
|
#ifdef GLAMOR_HAS_GBM
|
|
|
|
gbm_bo = drmmode->front_bo.gbm;
|
|
|
|
screen_pixmap = screen->GetScreenPixmap(screen);
|
|
|
|
|
|
|
|
if (!glamor_egl_create_textured_pixmap_from_gbm_bo(screen_pixmap, gbm_bo)) {
|
|
|
|
xf86DrvMsg(scrn->scrnIndex, X_ERROR, "Failed");
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
glamor_set_screen_pixmap(screen_pixmap, NULL);
|
|
|
|
#else
|
2014-12-10 00:18:39 +01:00
|
|
|
if (!glamor_egl_create_textured_screen(screen,
|
2014-12-10 00:20:44 +01:00
|
|
|
drmmode_bo_get_handle(&drmmode->front_bo),
|
2014-12-10 00:18:39 +01:00
|
|
|
scrn->displayWidth *
|
|
|
|
scrn->bitsPerPixel / 8)) {
|
|
|
|
xf86DrvMsg(scrn->scrnIndex, X_ERROR,
|
|
|
|
"glamor_egl_create_textured_screen() failed\n");
|
|
|
|
return FALSE;
|
|
|
|
}
|
2014-12-09 21:43:57 +01:00
|
|
|
#endif
|
2014-12-10 00:18:39 +01:00
|
|
|
#endif
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2011-09-29 12:49:26 +02:00
|
|
|
static Bool
|
2014-10-08 09:39:15 +02:00
|
|
|
drmmode_xf86crtc_resize(ScrnInfoPtr scrn, int width, int height)
|
2011-09-29 12:49:26 +02:00
|
|
|
{
|
2014-10-08 09:39:15 +02:00
|
|
|
xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
|
|
|
|
|
|
|
|
drmmode_crtc_private_ptr
|
|
|
|
drmmode_crtc = xf86_config->crtc[0]->driver_private;
|
|
|
|
drmmode_ptr drmmode = drmmode_crtc->drmmode;
|
2014-12-10 00:20:44 +01:00
|
|
|
drmmode_bo old_front;
|
2014-10-08 09:39:15 +02:00
|
|
|
Bool ret;
|
|
|
|
ScreenPtr screen = xf86ScrnToScreen(scrn);
|
|
|
|
uint32_t old_fb_id;
|
|
|
|
int i, pitch, old_width, old_height, old_pitch;
|
|
|
|
int cpp = (scrn->bitsPerPixel + 7) / 8;
|
|
|
|
PixmapPtr ppix = screen->GetScreenPixmap(screen);
|
2014-12-09 21:43:57 +01:00
|
|
|
void *new_pixels = NULL;
|
2014-10-08 09:39:15 +02:00
|
|
|
|
|
|
|
if (scrn->virtualX == width && scrn->virtualY == height)
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
xf86DrvMsg(scrn->scrnIndex, X_INFO,
|
|
|
|
"Allocate new frame buffer %dx%d stride\n", width, height);
|
|
|
|
|
modesetting: Add support for DRI2 with glamor.
This is derived from the intel driver DRI2 code, with swapchain and
pageflipping dropped, functions renamed, and vblank event management
shared code moved to a vblank.c for reuse by Present.
This allows AIGLX to load, which means that you get appropriate
visuals exposed in GL, along with many extensions under
direct-rendering that require presence in GLX (which aren't supported
in glxdriswrast.c).
v2: Drop unused header includes in pageflip.c, wrap in #ifdef GLAMOR.
Drop triple-buffering, which was totally broken in practice (I'll
try to fix this later). Fix up some style nits. Document the
general flow of pageflipping and why, rename the DRI2 frame event
type enums to reflect what they're for, and handle them in a
single switch statement so you can understand the state machine
more easily.
v3: Drop pageflipping entirely -- it's unstable on my Intel laptop
(not that the normal 2D driver is stable with pageflipping for
me), and I won't get it fixed before the merge window. It now
passes all of the OML_sync_control tests from Jamey and Theo
(except for occasional warns in timing -fullscreen -divisor 2).
v4: Fix doxygen at the top of vblank.c
Signed-off-by: Eric Anholt <eric@anholt.net>
Reviewed-by: Adam Jackson <ajax@redhat.com>
2013-12-31 02:23:38 +01:00
|
|
|
if (drmmode->triple_buffer_pixmap) {
|
|
|
|
screen->DestroyPixmap(drmmode->triple_buffer_pixmap);
|
|
|
|
drmmode->triple_buffer_pixmap = NULL;
|
|
|
|
}
|
|
|
|
|
2014-10-08 09:39:15 +02:00
|
|
|
old_width = scrn->virtualX;
|
|
|
|
old_height = scrn->virtualY;
|
2014-12-10 00:20:44 +01:00
|
|
|
old_pitch = drmmode_bo_get_pitch(&drmmode->front_bo);
|
2014-10-08 09:39:15 +02:00
|
|
|
old_fb_id = drmmode->fb_id;
|
|
|
|
old_front = drmmode->front_bo;
|
|
|
|
|
2014-12-10 00:20:44 +01:00
|
|
|
if (!drmmode_create_bo(drmmode, &drmmode->front_bo,
|
|
|
|
width, height, scrn->bitsPerPixel))
|
2014-10-08 09:39:15 +02:00
|
|
|
goto fail;
|
|
|
|
|
2014-12-10 00:20:44 +01:00
|
|
|
pitch = drmmode_bo_get_pitch(&drmmode->front_bo);
|
2014-10-08 09:39:15 +02:00
|
|
|
|
|
|
|
scrn->virtualX = width;
|
|
|
|
scrn->virtualY = height;
|
|
|
|
scrn->displayWidth = pitch / cpp;
|
|
|
|
|
|
|
|
ret = drmModeAddFB(drmmode->fd, width, height, scrn->depth,
|
|
|
|
scrn->bitsPerPixel, pitch,
|
2014-12-10 00:20:44 +01:00
|
|
|
drmmode_bo_get_handle(&drmmode->front_bo),
|
|
|
|
&drmmode->fb_id);
|
2014-10-08 09:39:15 +02:00
|
|
|
if (ret)
|
|
|
|
goto fail;
|
|
|
|
|
2014-12-09 21:43:57 +01:00
|
|
|
if (!drmmode->gbm) {
|
|
|
|
new_pixels = drmmode_map_front_bo(drmmode);
|
|
|
|
if (!new_pixels)
|
|
|
|
goto fail;
|
|
|
|
}
|
2014-10-08 09:39:15 +02:00
|
|
|
|
2014-12-09 23:38:39 +01:00
|
|
|
if (drmmode->shadow_enable) {
|
2014-10-08 09:39:15 +02:00
|
|
|
uint32_t size = scrn->displayWidth * scrn->virtualY *
|
|
|
|
((scrn->bitsPerPixel + 7) >> 3);
|
2014-12-09 23:38:39 +01:00
|
|
|
new_pixels = calloc(1, size);
|
|
|
|
if (new_pixels == NULL)
|
2014-10-08 09:39:15 +02:00
|
|
|
goto fail;
|
|
|
|
free(drmmode->shadow_fb);
|
2014-12-09 23:38:39 +01:00
|
|
|
drmmode->shadow_fb = new_pixels;
|
2014-10-08 09:39:15 +02:00
|
|
|
}
|
|
|
|
|
2014-12-09 23:38:39 +01:00
|
|
|
screen->ModifyPixmapHeader(ppix, width, height, -1, -1, pitch, new_pixels);
|
|
|
|
|
2014-12-10 00:18:39 +01:00
|
|
|
if (!drmmode_glamor_handle_new_screen_pixmap(drmmode))
|
|
|
|
goto fail;
|
2014-11-28 11:20:48 +01:00
|
|
|
|
2014-10-08 09:39:15 +02:00
|
|
|
for (i = 0; i < xf86_config->num_crtc; i++) {
|
|
|
|
xf86CrtcPtr crtc = xf86_config->crtc[i];
|
|
|
|
|
|
|
|
if (!crtc->enabled)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
drmmode_set_mode_major(crtc, &crtc->mode,
|
|
|
|
crtc->rotation, crtc->x, crtc->y);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (old_fb_id) {
|
|
|
|
drmModeRmFB(drmmode->fd, old_fb_id);
|
2014-12-10 00:20:44 +01:00
|
|
|
drmmode_bo_destroy(drmmode, &old_front);
|
2014-10-08 09:39:15 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
2011-09-29 12:49:26 +02:00
|
|
|
|
|
|
|
fail:
|
2014-12-10 00:20:44 +01:00
|
|
|
drmmode_bo_destroy(drmmode, &drmmode->front_bo);
|
2014-10-08 09:39:15 +02:00
|
|
|
drmmode->front_bo = old_front;
|
|
|
|
scrn->virtualX = old_width;
|
|
|
|
scrn->virtualY = old_height;
|
|
|
|
scrn->displayWidth = old_pitch / cpp;
|
|
|
|
drmmode->fb_id = old_fb_id;
|
|
|
|
|
|
|
|
return FALSE;
|
2011-09-29 12:49:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static const xf86CrtcConfigFuncsRec drmmode_xf86crtc_config_funcs = {
|
2014-10-08 09:39:15 +02:00
|
|
|
drmmode_xf86crtc_resize
|
2011-09-29 12:49:26 +02:00
|
|
|
};
|
|
|
|
|
2014-10-08 09:39:15 +02:00
|
|
|
Bool
|
|
|
|
drmmode_pre_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int cpp)
|
2011-09-29 12:49:26 +02:00
|
|
|
{
|
2014-11-28 11:20:50 +01:00
|
|
|
int i;
|
2014-10-08 09:39:15 +02:00
|
|
|
int ret;
|
|
|
|
uint64_t value = 0;
|
|
|
|
|
|
|
|
/* check for dumb capability */
|
|
|
|
ret = drmGetCap(drmmode->fd, DRM_CAP_DUMB_BUFFER, &value);
|
|
|
|
if (ret > 0 || value != 1) {
|
|
|
|
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
|
|
|
|
"KMS doesn't support dumb interface\n");
|
|
|
|
return FALSE;
|
|
|
|
}
|
2011-09-29 12:49:26 +02:00
|
|
|
|
2014-10-08 09:39:15 +02:00
|
|
|
xf86CrtcConfigInit(pScrn, &drmmode_xf86crtc_config_funcs);
|
2011-09-29 12:49:26 +02:00
|
|
|
|
2014-10-08 09:39:15 +02:00
|
|
|
drmmode->scrn = pScrn;
|
|
|
|
drmmode->cpp = cpp;
|
|
|
|
drmmode->mode_res = drmModeGetResources(drmmode->fd);
|
|
|
|
if (!drmmode->mode_res)
|
|
|
|
return FALSE;
|
2011-09-29 12:49:26 +02:00
|
|
|
|
2014-10-08 09:39:15 +02:00
|
|
|
xf86CrtcSetSizeRange(pScrn, 320, 200, drmmode->mode_res->max_width,
|
|
|
|
drmmode->mode_res->max_height);
|
|
|
|
for (i = 0; i < drmmode->mode_res->count_crtcs; i++)
|
|
|
|
if (!xf86IsEntityShared(pScrn->entityList[0]) ||
|
|
|
|
pScrn->confScreen->device->screen == i)
|
|
|
|
drmmode_crtc_init(pScrn, drmmode, i);
|
2011-09-29 12:49:26 +02:00
|
|
|
|
2014-10-08 09:39:15 +02:00
|
|
|
for (i = 0; i < drmmode->mode_res->count_connectors; i++)
|
2014-11-28 11:20:50 +01:00
|
|
|
drmmode_output_init(pScrn, drmmode, i);
|
2011-09-29 12:49:26 +02:00
|
|
|
|
2014-10-08 09:39:15 +02:00
|
|
|
/* workout clones */
|
|
|
|
drmmode_clones_init(pScrn, drmmode);
|
2011-09-29 12:49:26 +02:00
|
|
|
|
2012-07-19 06:12:59 +02:00
|
|
|
#if XF86_CRTC_VERSION >= 5
|
2014-10-08 09:39:15 +02:00
|
|
|
xf86ProviderSetup(pScrn, NULL, "modesetting");
|
2012-07-19 06:12:59 +02:00
|
|
|
#endif
|
|
|
|
|
2014-10-08 09:39:15 +02:00
|
|
|
xf86InitialConfiguration(pScrn, TRUE);
|
2011-09-29 12:49:26 +02:00
|
|
|
|
2014-10-08 09:39:15 +02:00
|
|
|
return TRUE;
|
2011-09-29 12:49:26 +02:00
|
|
|
}
|
|
|
|
|
2014-10-08 09:39:15 +02:00
|
|
|
void
|
|
|
|
drmmode_adjust_frame(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int x, int y)
|
2011-09-29 12:49:26 +02:00
|
|
|
{
|
2014-10-08 09:39:15 +02:00
|
|
|
xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
|
|
|
|
xf86OutputPtr output = config->output[config->compat_output];
|
|
|
|
xf86CrtcPtr crtc = output->crtc;
|
|
|
|
|
|
|
|
if (crtc && crtc->enabled) {
|
|
|
|
drmmode_set_mode_major(crtc, &crtc->mode, crtc->rotation, x, y);
|
|
|
|
}
|
2011-09-29 12:49:26 +02:00
|
|
|
}
|
|
|
|
|
2014-10-08 09:39:15 +02:00
|
|
|
Bool
|
|
|
|
drmmode_set_desired_modes(ScrnInfoPtr pScrn, drmmode_ptr drmmode)
|
2011-09-29 12:49:26 +02:00
|
|
|
{
|
2014-10-08 09:39:15 +02:00
|
|
|
xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
|
|
|
|
int c;
|
|
|
|
|
|
|
|
for (c = 0; c < config->num_crtc; c++) {
|
|
|
|
xf86CrtcPtr crtc = config->crtc[c];
|
|
|
|
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
|
|
|
|
xf86OutputPtr output = NULL;
|
|
|
|
int o;
|
|
|
|
|
|
|
|
/* Skip disabled CRTCs */
|
|
|
|
if (!crtc->enabled) {
|
|
|
|
drmModeSetCrtc(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
|
|
|
|
0, 0, 0, NULL, 0, NULL);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (config->output[config->compat_output]->crtc == crtc)
|
|
|
|
output = config->output[config->compat_output];
|
|
|
|
else {
|
|
|
|
for (o = 0; o < config->num_output; o++)
|
|
|
|
if (config->output[o]->crtc == crtc) {
|
|
|
|
output = config->output[o];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* paranoia */
|
|
|
|
if (!output)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
/* Mark that we'll need to re-set the mode for sure */
|
|
|
|
memset(&crtc->mode, 0, sizeof(crtc->mode));
|
|
|
|
if (!crtc->desiredMode.CrtcHDisplay) {
|
|
|
|
DisplayModePtr mode =
|
|
|
|
xf86OutputFindClosestMode(output, pScrn->currentMode);
|
|
|
|
|
|
|
|
if (!mode)
|
|
|
|
return FALSE;
|
|
|
|
crtc->desiredMode = *mode;
|
|
|
|
crtc->desiredRotation = RR_Rotate_0;
|
|
|
|
crtc->desiredX = 0;
|
|
|
|
crtc->desiredY = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!crtc->funcs->
|
|
|
|
set_mode_major(crtc, &crtc->desiredMode, crtc->desiredRotation,
|
|
|
|
crtc->desiredX, crtc->desiredY))
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
return TRUE;
|
2011-09-29 12:49:26 +02:00
|
|
|
}
|
|
|
|
|
2014-10-08 09:39:15 +02:00
|
|
|
static void
|
|
|
|
drmmode_load_palette(ScrnInfoPtr pScrn, int numColors,
|
|
|
|
int *indices, LOCO * colors, VisualPtr pVisual)
|
2011-09-29 12:49:26 +02:00
|
|
|
{
|
2014-10-08 09:39:15 +02:00
|
|
|
xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
|
|
|
|
uint16_t lut_r[256], lut_g[256], lut_b[256];
|
2011-09-29 12:49:26 +02:00
|
|
|
int index, j, i;
|
|
|
|
int c;
|
|
|
|
|
|
|
|
for (c = 0; c < xf86_config->num_crtc; c++) {
|
|
|
|
xf86CrtcPtr crtc = xf86_config->crtc[c];
|
2014-10-08 09:39:15 +02:00
|
|
|
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
|
2011-09-29 12:49:26 +02:00
|
|
|
|
2014-10-08 09:39:15 +02:00
|
|
|
for (i = 0; i < 256; i++) {
|
2011-09-29 12:49:26 +02:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2014-10-08 09:39:15 +02:00
|
|
|
switch (pScrn->depth) {
|
2011-09-29 12:49:26 +02:00
|
|
|
case 15:
|
|
|
|
for (i = 0; i < numColors; i++) {
|
|
|
|
index = indices[i];
|
|
|
|
for (j = 0; j < 8; j++) {
|
|
|
|
lut_r[index * 8 + j] = colors[index].red << 6;
|
|
|
|
lut_g[index * 8 + j] = colors[index].green << 6;
|
|
|
|
lut_b[index * 8 + j] = colors[index].blue << 6;
|
|
|
|
}
|
|
|
|
}
|
2014-10-08 09:39:15 +02:00
|
|
|
break;
|
|
|
|
case 16:
|
|
|
|
for (i = 0; i < numColors; i++) {
|
|
|
|
index = indices[i];
|
|
|
|
|
|
|
|
if (i <= 31) {
|
|
|
|
for (j = 0; j < 8; j++) {
|
|
|
|
lut_r[index * 8 + j] = colors[index].red << 6;
|
|
|
|
lut_b[index * 8 + j] = colors[index].blue << 6;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (j = 0; j < 4; j++) {
|
|
|
|
lut_g[index * 4 + j] = colors[index].green << 6;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
for (i = 0; i < numColors; i++) {
|
|
|
|
index = indices[i];
|
|
|
|
lut_r[index] = colors[index].red << 6;
|
|
|
|
lut_g[index] = colors[index].green << 6;
|
|
|
|
lut_b[index] = colors[index].blue << 6;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Make the change through RandR */
|
2011-09-29 12:49:26 +02:00
|
|
|
if (crtc->randr_crtc)
|
|
|
|
RRCrtcGammaSet(crtc->randr_crtc, lut_r, lut_g, lut_b);
|
|
|
|
else
|
|
|
|
crtc->funcs->gamma_set(crtc, lut_r, lut_g, lut_b, 256);
|
2014-10-08 09:39:15 +02:00
|
|
|
}
|
2011-09-29 12:49:26 +02:00
|
|
|
}
|
|
|
|
|
2014-10-08 09:39:15 +02:00
|
|
|
Bool
|
|
|
|
drmmode_setup_colormap(ScreenPtr pScreen, ScrnInfoPtr pScrn)
|
2011-09-29 12:49:26 +02:00
|
|
|
{
|
2014-10-08 09:39:15 +02:00
|
|
|
xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 0, "Initializing kms color map\n");
|
2011-09-29 12:49:26 +02:00
|
|
|
if (!miCreateDefColormap(pScreen))
|
|
|
|
return FALSE;
|
|
|
|
/* all radeons support 10 bit CLUTs */
|
|
|
|
if (!xf86HandleColormaps(pScreen, 256, 10,
|
2014-10-08 09:39:15 +02:00
|
|
|
drmmode_load_palette, NULL, CMAP_PALETTED_TRUECOLOR
|
|
|
|
#if 0 /* This option messes up text mode! (eich@suse.de) */
|
2011-09-29 12:49:26 +02:00
|
|
|
| CMAP_LOAD_EVEN_IF_OFFSCREEN
|
|
|
|
#endif
|
|
|
|
| CMAP_RELOAD_ON_MODE_SWITCH))
|
2014-10-08 09:39:15 +02:00
|
|
|
return FALSE;
|
2011-09-29 12:49:26 +02:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2014-11-28 11:20:49 +01:00
|
|
|
#ifdef CONFIG_UDEV_KMS
|
2011-09-29 12:49:26 +02:00
|
|
|
static void
|
|
|
|
drmmode_handle_uevents(int fd, void *closure)
|
|
|
|
{
|
2014-10-08 09:39:15 +02:00
|
|
|
drmmode_ptr drmmode = closure;
|
|
|
|
ScrnInfoPtr scrn = drmmode->scrn;
|
|
|
|
struct udev_device *dev;
|
|
|
|
|
|
|
|
dev = udev_monitor_receive_device(drmmode->uevent_monitor);
|
|
|
|
if (!dev)
|
|
|
|
return;
|
|
|
|
|
|
|
|
RRGetInfo(xf86ScrnToScreen(scrn), TRUE);
|
|
|
|
udev_device_unref(dev);
|
2011-09-29 12:49:26 +02:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2014-10-08 09:39:15 +02:00
|
|
|
void
|
|
|
|
drmmode_uevent_init(ScrnInfoPtr scrn, drmmode_ptr drmmode)
|
2011-09-29 12:49:26 +02:00
|
|
|
{
|
2014-11-28 11:20:49 +01:00
|
|
|
#ifdef CONFIG_UDEV_KMS
|
2014-10-08 09:39:15 +02:00
|
|
|
struct udev *u;
|
|
|
|
struct udev_monitor *mon;
|
|
|
|
|
|
|
|
u = udev_new();
|
|
|
|
if (!u)
|
|
|
|
return;
|
|
|
|
mon = udev_monitor_new_from_netlink(u, "udev");
|
|
|
|
if (!mon) {
|
|
|
|
udev_unref(u);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (udev_monitor_filter_add_match_subsystem_devtype(mon,
|
|
|
|
"drm",
|
|
|
|
"drm_minor") < 0 ||
|
|
|
|
udev_monitor_enable_receiving(mon) < 0) {
|
|
|
|
udev_monitor_unref(mon);
|
|
|
|
udev_unref(u);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
drmmode->uevent_handler =
|
|
|
|
xf86AddGeneralHandler(udev_monitor_get_fd(mon),
|
|
|
|
drmmode_handle_uevents, drmmode);
|
|
|
|
|
|
|
|
drmmode->uevent_monitor = mon;
|
2011-09-29 12:49:26 +02:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2014-10-08 09:39:15 +02:00
|
|
|
void
|
|
|
|
drmmode_uevent_fini(ScrnInfoPtr scrn, drmmode_ptr drmmode)
|
2011-09-29 12:49:26 +02:00
|
|
|
{
|
2014-11-28 11:20:49 +01:00
|
|
|
#ifdef CONFIG_UDEV_KMS
|
2014-10-08 09:39:15 +02:00
|
|
|
if (drmmode->uevent_handler) {
|
|
|
|
struct udev *u = udev_monitor_get_udev(drmmode->uevent_monitor);
|
|
|
|
|
|
|
|
xf86RemoveGeneralHandler(drmmode->uevent_handler);
|
2011-09-29 12:49:26 +02:00
|
|
|
|
2014-10-08 09:39:15 +02:00
|
|
|
udev_monitor_unref(drmmode->uevent_monitor);
|
|
|
|
udev_unref(u);
|
|
|
|
}
|
2011-09-29 12:49:26 +02:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
/* create front and cursor BOs */
|
2014-10-08 09:39:15 +02:00
|
|
|
Bool
|
|
|
|
drmmode_create_initial_bos(ScrnInfoPtr pScrn, drmmode_ptr drmmode)
|
2011-09-29 12:49:26 +02:00
|
|
|
{
|
2014-10-08 09:39:15 +02:00
|
|
|
modesettingPtr ms = modesettingPTR(pScrn);
|
|
|
|
xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
|
|
|
|
int width;
|
|
|
|
int height;
|
|
|
|
int bpp = pScrn->bitsPerPixel;
|
|
|
|
int i;
|
|
|
|
int cpp = (bpp + 7) / 8;
|
|
|
|
|
|
|
|
width = pScrn->virtualX;
|
|
|
|
height = pScrn->virtualY;
|
|
|
|
|
2014-12-10 00:20:44 +01:00
|
|
|
if (!drmmode_create_bo(drmmode, &drmmode->front_bo, width, height, bpp))
|
2014-10-08 09:39:15 +02:00
|
|
|
return FALSE;
|
2014-12-10 00:20:44 +01:00
|
|
|
pScrn->displayWidth = drmmode_bo_get_pitch(&drmmode->front_bo) / cpp;
|
2014-10-08 09:39:15 +02:00
|
|
|
|
|
|
|
width = ms->cursor_width;
|
|
|
|
height = ms->cursor_height;
|
|
|
|
bpp = 32;
|
|
|
|
for (i = 0; i < xf86_config->num_crtc; i++) {
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
return TRUE;
|
2011-09-29 12:49:26 +02:00
|
|
|
}
|
|
|
|
|
2014-10-08 09:39:15 +02:00
|
|
|
void *
|
|
|
|
drmmode_map_front_bo(drmmode_ptr drmmode)
|
2011-09-29 12:49:26 +02:00
|
|
|
{
|
2014-10-08 09:39:15 +02:00
|
|
|
int ret;
|
2011-09-29 12:49:26 +02:00
|
|
|
|
2014-12-10 00:20:44 +01:00
|
|
|
if (drmmode->front_bo.dumb->ptr)
|
|
|
|
return drmmode->front_bo.dumb->ptr;
|
2011-09-29 12:49:26 +02:00
|
|
|
|
2014-12-10 00:20:44 +01:00
|
|
|
ret = dumb_bo_map(drmmode->fd, drmmode->front_bo.dumb);
|
2014-10-08 09:39:15 +02:00
|
|
|
if (ret)
|
|
|
|
return NULL;
|
|
|
|
|
2014-12-10 00:20:44 +01:00
|
|
|
return drmmode->front_bo.dumb->ptr;
|
2011-09-29 12:49:26 +02:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2014-10-08 09:39:15 +02:00
|
|
|
void *
|
|
|
|
drmmode_map_slave_bo(drmmode_ptr drmmode, msPixmapPrivPtr ppriv)
|
2012-07-19 06:12:59 +02:00
|
|
|
{
|
2014-10-08 09:39:15 +02:00
|
|
|
int ret;
|
2012-07-19 06:12:59 +02:00
|
|
|
|
2014-10-08 09:39:15 +02:00
|
|
|
if (ppriv->backing_bo->ptr)
|
|
|
|
return ppriv->backing_bo->ptr;
|
2012-07-19 06:12:59 +02:00
|
|
|
|
2014-10-08 09:39:15 +02:00
|
|
|
ret = dumb_bo_map(drmmode->fd, ppriv->backing_bo);
|
|
|
|
if (ret)
|
|
|
|
return NULL;
|
2012-07-19 06:12:59 +02:00
|
|
|
|
2014-10-08 09:39:15 +02:00
|
|
|
return ppriv->backing_bo->ptr;
|
2012-07-19 06:12:59 +02:00
|
|
|
}
|
|
|
|
|
2014-10-08 09:39:15 +02:00
|
|
|
Bool
|
|
|
|
drmmode_map_cursor_bos(ScrnInfoPtr pScrn, drmmode_ptr drmmode)
|
2011-09-29 12:49:26 +02:00
|
|
|
{
|
2014-10-08 09:39:15 +02:00
|
|
|
xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
|
|
|
|
int i, ret;
|
|
|
|
|
|
|
|
for (i = 0; i < xf86_config->num_crtc; i++) {
|
|
|
|
xf86CrtcPtr crtc = xf86_config->crtc[i];
|
|
|
|
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
|
|
|
|
|
|
|
|
ret = dumb_bo_map(drmmode->fd, drmmode_crtc->cursor_bo);
|
|
|
|
if (ret)
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
return TRUE;
|
2011-09-29 12:49:26 +02:00
|
|
|
}
|
|
|
|
|
2014-10-08 09:39:15 +02:00
|
|
|
void
|
|
|
|
drmmode_free_bos(ScrnInfoPtr pScrn, drmmode_ptr drmmode)
|
2011-09-29 12:49:26 +02:00
|
|
|
{
|
2014-10-08 09:39:15 +02:00
|
|
|
xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (drmmode->fb_id) {
|
|
|
|
drmModeRmFB(drmmode->fd, drmmode->fb_id);
|
|
|
|
drmmode->fb_id = 0;
|
|
|
|
}
|
|
|
|
|
2014-12-10 00:20:44 +01:00
|
|
|
drmmode_bo_destroy(drmmode, &drmmode->front_bo);
|
2014-10-08 09:39:15 +02:00
|
|
|
|
|
|
|
for (i = 0; i < xf86_config->num_crtc; i++) {
|
|
|
|
xf86CrtcPtr crtc = xf86_config->crtc[i];
|
|
|
|
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
|
|
|
|
|
|
|
|
dumb_bo_destroy(drmmode->fd, drmmode_crtc->cursor_bo);
|
|
|
|
}
|
2011-09-29 12:49:26 +02:00
|
|
|
}
|
2012-05-01 18:12:29 +02:00
|
|
|
|
|
|
|
/* ugly workaround to see if we can create 32bpp */
|
2014-10-08 09:39:15 +02:00
|
|
|
void
|
|
|
|
drmmode_get_default_bpp(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int *depth,
|
|
|
|
int *bpp)
|
2012-05-01 18:12:29 +02:00
|
|
|
{
|
2014-10-08 09:39:15 +02:00
|
|
|
drmModeResPtr mode_res;
|
|
|
|
uint64_t value;
|
|
|
|
struct dumb_bo *bo;
|
|
|
|
uint32_t fb_id;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
/* 16 is fine */
|
|
|
|
ret = drmGetCap(drmmode->fd, DRM_CAP_DUMB_PREFERRED_DEPTH, &value);
|
|
|
|
if (!ret && (value == 16 || value == 8)) {
|
|
|
|
*depth = value;
|
|
|
|
*bpp = value;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
*depth = 24;
|
|
|
|
mode_res = drmModeGetResources(drmmode->fd);
|
|
|
|
if (!mode_res)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (mode_res->min_width == 0)
|
|
|
|
mode_res->min_width = 1;
|
|
|
|
if (mode_res->min_height == 0)
|
|
|
|
mode_res->min_height = 1;
|
|
|
|
/*create a bo */
|
|
|
|
bo = dumb_bo_create(drmmode->fd, mode_res->min_width, mode_res->min_height,
|
|
|
|
32);
|
|
|
|
if (!bo) {
|
|
|
|
*bpp = 24;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = drmModeAddFB(drmmode->fd, mode_res->min_width, mode_res->min_height,
|
|
|
|
24, 32, bo->pitch, bo->handle, &fb_id);
|
|
|
|
|
|
|
|
if (ret) {
|
|
|
|
*bpp = 24;
|
|
|
|
dumb_bo_destroy(drmmode->fd, bo);
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
drmModeRmFB(drmmode->fd, fb_id);
|
|
|
|
*bpp = 32;
|
|
|
|
|
|
|
|
dumb_bo_destroy(drmmode->fd, bo);
|
|
|
|
out:
|
|
|
|
drmModeFreeResources(mode_res);
|
|
|
|
return;
|
2012-05-01 18:12:29 +02:00
|
|
|
}
|