752 lines
19 KiB
C
752 lines
19 KiB
C
/*
|
|
* 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>
|
|
*
|
|
*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include "config.h"
|
|
#endif
|
|
|
|
#include "xorgVersion.h"
|
|
|
|
#ifdef XF86DRM_MODE
|
|
#include "i830.h"
|
|
#include "intel_bufmgr.h"
|
|
#include "xf86drmMode.h"
|
|
|
|
typedef struct {
|
|
int fd;
|
|
uint32_t fb_id;
|
|
drmModeResPtr mode_res;
|
|
int cpp;
|
|
} drmmode_rec, *drmmode_ptr;
|
|
|
|
typedef struct {
|
|
drmmode_ptr drmmode;
|
|
drmModeCrtcPtr mode_crtc;
|
|
dri_bo *cursor;
|
|
dri_bo *rotate_bo;
|
|
uint32_t rotate_fb_id;
|
|
} drmmode_crtc_private_rec, *drmmode_crtc_private_ptr;
|
|
|
|
typedef struct {
|
|
drmmode_ptr drmmode;
|
|
int output_id;
|
|
drmModeConnectorPtr mode_output;
|
|
drmModeEncoderPtr mode_encoder;
|
|
drmModePropertyBlobPtr edid_blob;
|
|
} drmmode_output_private_rec, *drmmode_output_private_ptr;
|
|
|
|
static void
|
|
drmmode_ConvertFromKMode(ScrnInfoPtr scrn,
|
|
drmModeModeInfoPtr kmode,
|
|
DisplayModePtr mode)
|
|
{
|
|
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);
|
|
}
|
|
|
|
static void
|
|
drmmode_ConvertToKMode(ScrnInfoPtr scrn,
|
|
drmModeModeInfoPtr kmode,
|
|
DisplayModePtr mode)
|
|
{
|
|
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;
|
|
|
|
}
|
|
|
|
static void
|
|
drmmode_crtc_dpms(xf86CrtcPtr drmmode_crtc, int mode)
|
|
{
|
|
|
|
}
|
|
|
|
static Bool
|
|
drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
|
|
Rotation rotation, int x, int y)
|
|
{
|
|
ScrnInfoPtr pScrn = crtc->scrn;
|
|
I830Ptr pI830 = I830PTR(pScrn);
|
|
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;
|
|
int ret = TRUE;
|
|
int i;
|
|
int fb_id;
|
|
drmModeModeInfo kmode;
|
|
unsigned int pitch = pScrn->displayWidth * pI830->cpp;
|
|
|
|
if (drmmode->fb_id == 0) {
|
|
ret = drmModeAddFB(drmmode->fd,
|
|
pScrn->virtualX, pScrn->virtualY,
|
|
pScrn->depth, pScrn->bitsPerPixel,
|
|
pitch, pI830->front_buffer->bo->handle,
|
|
&drmmode->fb_id);
|
|
if (ret < 0) {
|
|
ErrorF("failed to add fb\n");
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
saved_mode = crtc->mode;
|
|
saved_x = crtc->x;
|
|
saved_y = crtc->y;
|
|
saved_rotation = crtc->rotation;
|
|
|
|
crtc->mode = *mode;
|
|
crtc->x = x;
|
|
crtc->y = y;
|
|
crtc->rotation = rotation;
|
|
#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,5,99,0,0)
|
|
crtc->transformPresent = FALSE;
|
|
#endif
|
|
|
|
output_ids = xcalloc(sizeof(uint32_t), xf86_config->num_output);
|
|
if (!output_ids) {
|
|
ret = FALSE;
|
|
goto done;
|
|
}
|
|
|
|
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++;
|
|
}
|
|
|
|
#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1,5,99,0,0)
|
|
if (!xf86CrtcRotate(crtc, mode, rotation))
|
|
goto done;
|
|
#else
|
|
if (!xf86CrtcRotate(crtc))
|
|
goto done;
|
|
#endif
|
|
|
|
drmmode_ConvertToKMode(crtc->scrn, &kmode, mode);
|
|
|
|
|
|
fb_id = drmmode->fb_id;
|
|
if (drmmode_crtc->rotate_fb_id)
|
|
fb_id = drmmode_crtc->rotate_fb_id;
|
|
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;
|
|
|
|
done:
|
|
if (!ret) {
|
|
crtc->x = saved_x;
|
|
crtc->y = saved_y;
|
|
crtc->rotation = saved_rotation;
|
|
crtc->mode = saved_mode;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
static void
|
|
drmmode_set_cursor_colors (xf86CrtcPtr crtc, int bg, int fg)
|
|
{
|
|
|
|
}
|
|
|
|
static void
|
|
drmmode_set_cursor_position (xf86CrtcPtr crtc, int x, int y)
|
|
{
|
|
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
|
|
drmmode_ptr drmmode = drmmode_crtc->drmmode;
|
|
|
|
drmModeMoveCursor(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, x, y);
|
|
}
|
|
|
|
static void
|
|
drmmode_load_cursor_argb (xf86CrtcPtr crtc, CARD32 *image)
|
|
{
|
|
ScrnInfoPtr pScrn = crtc->scrn;
|
|
I830Ptr pI830 = I830PTR(pScrn);
|
|
int ret;
|
|
|
|
/* cursor should be mapped already */
|
|
ret = dri_bo_subdata(pI830->cursor_mem->bo, 0, 64*64*4, image);
|
|
if (ret)
|
|
xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR,
|
|
"failed to set cursor: %s", strerror(-ret));
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
static void
|
|
drmmode_hide_cursor (xf86CrtcPtr crtc)
|
|
{
|
|
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
|
|
drmmode_ptr drmmode = drmmode_crtc->drmmode;
|
|
|
|
drmModeSetCursor(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
|
|
0, 64, 64);
|
|
}
|
|
|
|
static void
|
|
drmmode_show_cursor (xf86CrtcPtr crtc)
|
|
{
|
|
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
|
|
drmmode_ptr drmmode = drmmode_crtc->drmmode;
|
|
ScrnInfoPtr pScrn = crtc->scrn;
|
|
I830Ptr pI830 = I830PTR(pScrn);
|
|
|
|
drmModeSetCursor(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
|
|
pI830->cursor_mem->bo->handle, 64, 64);
|
|
}
|
|
|
|
static void *
|
|
drmmode_crtc_shadow_allocate(xf86CrtcPtr crtc, int width, int height)
|
|
{
|
|
ScrnInfoPtr pScrn = crtc->scrn;
|
|
I830Ptr pI830 = I830PTR(pScrn);
|
|
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
|
|
drmmode_ptr drmmode = drmmode_crtc->drmmode;
|
|
int size, ret;
|
|
unsigned long rotate_pitch;
|
|
|
|
width = i830_pad_drawable_width(width, drmmode->cpp);
|
|
rotate_pitch = width * drmmode->cpp;
|
|
size = rotate_pitch * height;
|
|
|
|
drmmode_crtc->rotate_bo =
|
|
drm_intel_bo_alloc(pI830->bufmgr, "rotate", size, 4096);
|
|
|
|
if (!drmmode_crtc->rotate_bo) {
|
|
xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR,
|
|
"Couldn't allocate shadow memory for rotated CRTC\n");
|
|
return NULL;
|
|
}
|
|
|
|
drm_intel_gem_bo_map_gtt(drmmode_crtc->rotate_bo);
|
|
|
|
ret = drmModeAddFB(drmmode->fd, width, height, crtc->scrn->depth,
|
|
crtc->scrn->bitsPerPixel, rotate_pitch,
|
|
drmmode_crtc->rotate_bo->handle,
|
|
&drmmode_crtc->rotate_fb_id);
|
|
if (ret) {
|
|
ErrorF("failed to add rotate fb\n");
|
|
drm_intel_bo_unreference(drmmode_crtc->rotate_bo);
|
|
return NULL;
|
|
}
|
|
|
|
return drmmode_crtc->rotate_bo->virtual;
|
|
}
|
|
|
|
static PixmapPtr
|
|
drmmode_crtc_shadow_create(xf86CrtcPtr crtc, void *data, int width, int height)
|
|
{
|
|
ScrnInfoPtr pScrn = crtc->scrn;
|
|
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
|
|
drmmode_ptr drmmode = drmmode_crtc->drmmode;
|
|
unsigned long rotate_pitch;
|
|
PixmapPtr rotate_pixmap;
|
|
|
|
if (!data)
|
|
data = drmmode_crtc_shadow_allocate (crtc, width, height);
|
|
|
|
rotate_pitch =
|
|
i830_pad_drawable_width(width, drmmode->cpp) * drmmode->cpp;
|
|
rotate_pixmap = GetScratchPixmapHeader(pScrn->pScreen,
|
|
width, height,
|
|
pScrn->depth,
|
|
pScrn->bitsPerPixel,
|
|
rotate_pitch,
|
|
data);
|
|
|
|
if (rotate_pixmap == NULL) {
|
|
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
|
|
"Couldn't allocate shadow pixmap for rotated CRTC\n");
|
|
}
|
|
|
|
if (drmmode_crtc->rotate_bo)
|
|
i830_set_pixmap_bo(rotate_pixmap, drmmode_crtc->rotate_bo);
|
|
|
|
return rotate_pixmap;
|
|
}
|
|
|
|
static void
|
|
drmmode_crtc_shadow_destroy(xf86CrtcPtr crtc, PixmapPtr rotate_pixmap, void *data)
|
|
{
|
|
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
|
|
drmmode_ptr drmmode = drmmode_crtc->drmmode;
|
|
|
|
if (rotate_pixmap)
|
|
FreeScratchPixmapHeader(rotate_pixmap);
|
|
|
|
|
|
if (data) {
|
|
/* Be sure to sync acceleration before the memory gets
|
|
* unbound. */
|
|
drmModeRmFB(drmmode->fd, drmmode_crtc->rotate_fb_id);
|
|
drmmode_crtc->rotate_fb_id = 0;
|
|
drm_intel_bo_unmap(drmmode_crtc->rotate_bo);
|
|
dri_bo_unreference(drmmode_crtc->rotate_bo);
|
|
drmmode_crtc->rotate_bo = NULL;
|
|
}
|
|
}
|
|
|
|
static void
|
|
drmmode_crtc_gamma_set(xf86CrtcPtr crtc,
|
|
CARD16 *red, CARD16 *green, CARD16 *blue, int size)
|
|
{
|
|
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
|
|
drmmode_ptr drmmode = drmmode_crtc->drmmode;
|
|
|
|
drmModeCrtcSetGamma(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
|
|
size, red, green, blue);
|
|
}
|
|
|
|
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,
|
|
.shadow_create = drmmode_crtc_shadow_create,
|
|
.shadow_allocate = drmmode_crtc_shadow_allocate,
|
|
.shadow_destroy = drmmode_crtc_shadow_destroy,
|
|
.gamma_set = drmmode_crtc_gamma_set,
|
|
.destroy = NULL, /* XXX */
|
|
};
|
|
|
|
|
|
static void
|
|
drmmode_crtc_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int num)
|
|
{
|
|
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;
|
|
crtc->driver_private = drmmode_crtc;
|
|
|
|
return;
|
|
}
|
|
|
|
static xf86OutputStatus
|
|
drmmode_output_detect(xf86OutputPtr output)
|
|
{
|
|
/* 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);
|
|
|
|
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;
|
|
}
|
|
|
|
static Bool
|
|
drmmode_output_mode_valid(xf86OutputPtr output, DisplayModePtr pModes)
|
|
{
|
|
return MODE_OK;
|
|
}
|
|
|
|
static DisplayModePtr
|
|
drmmode_output_get_modes(xf86OutputPtr output)
|
|
{
|
|
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;
|
|
|
|
/* 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))
|
|
continue;
|
|
|
|
if (!strcmp(props->name, "EDID") &&
|
|
drmmode_output->edid_blob == NULL) {
|
|
drmModeFreePropertyBlob(drmmode_output->edid_blob);
|
|
drmmode_output->edid_blob =
|
|
drmModeGetPropertyBlob(drmmode->fd,
|
|
koutput->prop_values[i]);
|
|
}
|
|
drmModeFreeProperty(props);
|
|
}
|
|
|
|
if (drmmode_output->edid_blob)
|
|
xf86OutputSetEDID(output,
|
|
xf86InterpretEDID(output->scrn->scrnIndex,
|
|
drmmode_output->edid_blob->data));
|
|
else
|
|
xf86OutputSetEDID(output,
|
|
xf86InterpretEDID(output->scrn->scrnIndex,
|
|
NULL));
|
|
|
|
/* 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 Modes;
|
|
}
|
|
|
|
static void
|
|
drmmode_output_destroy(xf86OutputPtr output)
|
|
{
|
|
drmmode_output_private_ptr drmmode_output = output->driver_private;
|
|
|
|
if (drmmode_output->edid_blob)
|
|
drmModeFreePropertyBlob(drmmode_output->edid_blob);
|
|
drmModeFreeConnector(drmmode_output->mode_output);
|
|
xfree(drmmode_output);
|
|
output->driver_private = NULL;
|
|
}
|
|
|
|
static void
|
|
drmmode_output_dpms(xf86OutputPtr output, int mode)
|
|
{
|
|
return;
|
|
}
|
|
|
|
static const xf86OutputFuncsRec drmmode_output_funcs = {
|
|
.dpms = drmmode_output_dpms,
|
|
#if 0
|
|
|
|
.save = drmmode_crt_save,
|
|
.restore = drmmode_crt_restore,
|
|
.mode_fixup = drmmode_crt_mode_fixup,
|
|
.prepare = drmmode_output_prepare,
|
|
.mode_set = drmmode_crt_mode_set,
|
|
.commit = drmmode_output_commit,
|
|
#endif
|
|
.detect = drmmode_output_detect,
|
|
.mode_valid = drmmode_output_mode_valid,
|
|
|
|
.get_modes = drmmode_output_get_modes,
|
|
.destroy = drmmode_output_destroy
|
|
};
|
|
|
|
static int subpixel_conv_table[7] = { 0, SubPixelUnknown,
|
|
SubPixelHorizontalRGB,
|
|
SubPixelHorizontalBGR,
|
|
SubPixelVerticalRGB,
|
|
SubPixelVerticalBGR,
|
|
SubPixelNone };
|
|
|
|
const char *output_names[] = { "None",
|
|
"VGA",
|
|
"DVI",
|
|
"DVI",
|
|
"DVI",
|
|
"Composite",
|
|
"TV",
|
|
"LVDS",
|
|
"CTV",
|
|
"DIN",
|
|
"DP",
|
|
"HDMI",
|
|
"HDMI",
|
|
};
|
|
|
|
|
|
static void
|
|
drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int num)
|
|
{
|
|
xf86OutputPtr output;
|
|
drmModeConnectorPtr koutput;
|
|
drmModeEncoderPtr kencoder;
|
|
drmmode_output_private_ptr drmmode_output;
|
|
char name[32];
|
|
|
|
koutput = drmModeGetConnector(drmmode->fd,
|
|
drmmode->mode_res->connectors[num]);
|
|
if (!koutput)
|
|
return;
|
|
|
|
kencoder = drmModeGetEncoder(drmmode->fd, koutput->encoders[0]);
|
|
if (!kencoder) {
|
|
drmModeFreeConnector(koutput);
|
|
return;
|
|
}
|
|
|
|
snprintf(name, 32, "%s%d", output_names[koutput->connector_type],
|
|
koutput->connector_type_id);
|
|
|
|
output = xf86OutputCreate (pScrn, &drmmode_output_funcs, name);
|
|
if (!output) {
|
|
drmModeFreeEncoder(kencoder);
|
|
drmModeFreeConnector(koutput);
|
|
return;
|
|
}
|
|
|
|
drmmode_output = xcalloc(sizeof(drmmode_output_private_rec), 1);
|
|
if (!drmmode_output) {
|
|
xf86OutputDestroy(output);
|
|
drmModeFreeConnector(koutput);
|
|
drmModeFreeEncoder(kencoder);
|
|
return;
|
|
}
|
|
|
|
drmmode_output->output_id = drmmode->mode_res->connectors[num];
|
|
drmmode_output->mode_output = koutput;
|
|
drmmode_output->mode_encoder = kencoder;
|
|
drmmode_output->drmmode = drmmode;
|
|
output->mm_width = koutput->mmWidth;
|
|
output->mm_height = koutput->mmHeight;
|
|
|
|
output->subpixel_order = subpixel_conv_table[koutput->subpixel];
|
|
output->driver_private = drmmode_output;
|
|
|
|
output->possible_crtcs = kencoder->possible_crtcs;
|
|
output->possible_clones = kencoder->possible_clones;
|
|
return;
|
|
}
|
|
|
|
static Bool
|
|
drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height)
|
|
{
|
|
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;
|
|
I830Ptr pI830 = I830PTR(scrn);
|
|
i830_memory *old_front = NULL;
|
|
BoxRec mem_box;
|
|
Bool tiled, ret;
|
|
ScreenPtr screen = screenInfo.screens[scrn->scrnIndex];
|
|
uint32_t old_fb_id;
|
|
int i, pitch, old_width, old_height, old_pitch;
|
|
|
|
if (scrn->virtualX == width && scrn->virtualY == height)
|
|
return TRUE;
|
|
|
|
if (!pI830->can_resize)
|
|
return FALSE;
|
|
|
|
pitch = i830_pad_drawable_width(width, pI830->cpp);
|
|
tiled = i830_tiled_width(pI830, &pitch, pI830->cpp);
|
|
xf86DrvMsg(scrn->scrnIndex, X_INFO,
|
|
"Allocate new frame buffer %dx%d stride %d\n",
|
|
width, height, pitch);
|
|
|
|
old_width = scrn->virtualX;
|
|
old_height = scrn->virtualY;
|
|
old_pitch = scrn->displayWidth;
|
|
old_fb_id = drmmode->fb_id;
|
|
old_front = pI830->front_buffer;
|
|
|
|
scrn->virtualX = width;
|
|
scrn->virtualY = height;
|
|
scrn->displayWidth = pitch;
|
|
pI830->front_buffer =
|
|
i830_allocate_framebuffer(scrn, pI830, &mem_box, FALSE);
|
|
if (!pI830->front_buffer)
|
|
goto fail;
|
|
|
|
ret = drmModeAddFB(drmmode->fd, width, height, scrn->depth,
|
|
scrn->bitsPerPixel, pitch * pI830->cpp,
|
|
pI830->front_buffer->bo->handle,
|
|
&drmmode->fb_id);
|
|
if (ret)
|
|
goto fail;
|
|
|
|
i830_set_pixmap_bo(screen->GetScreenPixmap(screen), pI830->front_buffer->bo);
|
|
scrn->fbOffset = pI830->front_buffer->offset;
|
|
|
|
screen->ModifyPixmapHeader(screen->GetScreenPixmap(screen),
|
|
width, height, -1, -1, pitch * pI830->cpp, NULL);
|
|
xf86DrvMsg(scrn->scrnIndex, X_INFO, "New front buffer at 0x%lx\n",
|
|
pI830->front_buffer->offset);
|
|
|
|
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);
|
|
if (old_front)
|
|
i830_free_memory(scrn, old_front);
|
|
|
|
return TRUE;
|
|
|
|
fail:
|
|
if (pI830->front_buffer)
|
|
i830_free_memory(scrn, pI830->front_buffer);
|
|
pI830->front_buffer = old_front;
|
|
scrn->virtualX = old_width;
|
|
scrn->virtualY = old_height;
|
|
scrn->displayWidth = old_pitch;
|
|
drmmode->fb_id = old_fb_id;
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static const xf86CrtcConfigFuncsRec drmmode_xf86crtc_config_funcs = {
|
|
drmmode_xf86crtc_resize
|
|
};
|
|
|
|
Bool drmmode_pre_init(ScrnInfoPtr pScrn, int fd, int cpp)
|
|
{
|
|
I830Ptr pI830 = I830PTR(pScrn);
|
|
xf86CrtcConfigPtr xf86_config;
|
|
drmmode_ptr drmmode;
|
|
int i;
|
|
|
|
drmmode = xnfalloc(sizeof *drmmode);
|
|
drmmode->fd = fd;
|
|
drmmode->fb_id = 0;
|
|
|
|
xf86CrtcConfigInit(pScrn, &drmmode_xf86crtc_config_funcs);
|
|
xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
|
|
|
|
drmmode->cpp = cpp;
|
|
drmmode->mode_res = drmModeGetResources(drmmode->fd);
|
|
if (!drmmode->mode_res)
|
|
return FALSE;
|
|
|
|
xf86CrtcSetSizeRange(pScrn, 320, 200, drmmode->mode_res->max_width,
|
|
drmmode->mode_res->max_height);
|
|
for (i = 0; i < drmmode->mode_res->count_crtcs; i++)
|
|
drmmode_crtc_init(pScrn, drmmode, i);
|
|
|
|
for (i = 0; i < drmmode->mode_res->count_connectors; i++)
|
|
drmmode_output_init(pScrn, drmmode, i);
|
|
|
|
xf86InitialConfiguration(pScrn, pI830->can_resize);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
Bool drmmode_is_rotate_pixmap(ScrnInfoPtr pScrn, pointer pPixData, dri_bo **bo)
|
|
{
|
|
return FALSE;
|
|
|
|
#if 0
|
|
xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR (pScrn);
|
|
int i;
|
|
|
|
for (i = 0; i < config->num_crtc; i++) {
|
|
xf86CrtcPtr crtc = config->crtc[i];
|
|
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
|
|
|
|
if (!drmmode_crtc->rotate_bo)
|
|
continue;
|
|
|
|
if (drmmode_crtc->rotate_bo->virtual == pPixData) {
|
|
*bo = drmmode_crtc->rotate_bo;
|
|
return TRUE;
|
|
}
|
|
}
|
|
return FALSE;
|
|
#endif
|
|
}
|
|
|
|
#endif
|