xserver-multidpi/hw/kdrive/src/kdrive.c
Adam Jackson d8ec33fe05 glx: Use vnd layer for dispatch (v4)
The big change here is MakeCurrent and context tag tracking. We now
delegate context tags entirely to the vnd layer, and simply store a
pointer to the context state as the tag data. If a context is deleted
while it's current, we allocate a fake ID for the context and move the
context state there, so the tag data still points to a real context. As
a result we can stop trying so hard to detach the client from contexts
at disconnect time and just let resource destruction handle it.

Since vnd handles all the MakeCurrent protocol now, our request handlers
for it can just be return BadImplementation. We also remove a bunch of
LEGAL_NEW_RESOURCE, because now by the time we're called vnd has already
allocated its tracking resource on that XID.

v2: Update to match v2 of the vnd import, and remove more redundant work
like request length checks.

v3: Add/remove the XID map from the vendor private thunk, not the
backend. (Kyle Brenneman)

v4: Fix deletion of ghost contexts (Kyle Brenneman)

Signed-off-by: Adam Jackson <ajax@redhat.com>
2018-02-14 17:04:44 -05:00

1022 lines
27 KiB
C

/*
* Copyright © 1999 Keith Packard
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation, and that the name of Keith Packard not be used in
* advertising or publicity pertaining to distribution of the software without
* specific, written prior permission. Keith Packard makes no
* representations about the suitability of this software for any purpose. It
* is provided "as is" without express or implied warranty.
*
* KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
* EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif
#include "kdrive.h"
#include <mivalidate.h>
#include <dixstruct.h>
#include "privates.h"
#ifdef RANDR
#include <randrstr.h>
#endif
#include "glx_extinit.h"
#ifdef XV
#include "kxv.h"
#endif
#ifdef DPMSExtension
#include "dpmsproc.h"
#endif
#ifdef HAVE_EXECINFO_H
#include <execinfo.h>
#endif
#if defined(CONFIG_UDEV) || defined(CONFIG_HAL)
#include <hotplug.h>
#endif
/* This stub can be safely removed once we can
* split input and GPU parts in hotplug.h et al. */
#include <systemd-logind.h>
typedef struct _kdDepths {
CARD8 depth;
CARD8 bpp;
} KdDepths;
KdDepths kdDepths[] = {
{1, 1},
{4, 4},
{8, 8},
{15, 16},
{16, 16},
{24, 32},
{32, 32}
};
#define KD_DEFAULT_BUTTONS 5
DevPrivateKeyRec kdScreenPrivateKeyRec;
static unsigned long kdGeneration;
Bool kdEmulateMiddleButton;
Bool kdRawPointerCoordinates;
Bool kdDisableZaphod;
static Bool kdEnabled;
static int kdSubpixelOrder;
static char *kdSwitchCmd;
static DDXPointRec kdOrigin;
Bool kdHasPointer = FALSE;
Bool kdHasKbd = FALSE;
const char *kdGlobalXkbRules = NULL;
const char *kdGlobalXkbModel = NULL;
const char *kdGlobalXkbLayout = NULL;
const char *kdGlobalXkbVariant = NULL;
const char *kdGlobalXkbOptions = NULL;
void
KdDisableScreen(ScreenPtr pScreen)
{
KdScreenPriv(pScreen);
if (!pScreenPriv->enabled)
return;
if (!pScreenPriv->closed)
SetRootClip(pScreen, ROOT_CLIP_NONE);
KdDisableColormap(pScreen);
if (!pScreenPriv->screen->dumb && pScreenPriv->card->cfuncs->disableAccel)
(*pScreenPriv->card->cfuncs->disableAccel) (pScreen);
pScreenPriv->enabled = FALSE;
}
static void
KdDoSwitchCmd(const char *reason)
{
if (kdSwitchCmd) {
char *command;
int ret;
if (asprintf(&command, "%s %s", kdSwitchCmd, reason) == -1)
return;
/* Ignore the return value from system; I'm not sure
* there's anything more useful to be done when
* it fails
*/
ret = system(command);
(void) ret;
free(command);
}
}
static void
KdSuspend(void)
{
KdCardInfo *card;
KdScreenInfo *screen;
if (kdEnabled) {
for (card = kdCardInfo; card; card = card->next) {
for (screen = card->screenList; screen; screen = screen->next)
if (screen->mynum == card->selected && screen->pScreen)
KdDisableScreen(screen->pScreen);
}
KdDisableInput();
KdDoSwitchCmd("suspend");
}
}
static void
KdDisableScreens(void)
{
KdSuspend();
kdEnabled = FALSE;
}
Bool
KdEnableScreen(ScreenPtr pScreen)
{
KdScreenPriv(pScreen);
if (pScreenPriv->enabled)
return TRUE;
pScreenPriv->enabled = TRUE;
pScreenPriv->dpmsState = KD_DPMS_NORMAL;
pScreenPriv->card->selected = pScreenPriv->screen->mynum;
if (!pScreenPriv->screen->dumb && pScreenPriv->card->cfuncs->enableAccel)
(*pScreenPriv->card->cfuncs->enableAccel) (pScreen);
KdEnableColormap(pScreen);
SetRootClip(pScreen, ROOT_CLIP_FULL);
return TRUE;
}
void
AbortDDX(enum ExitCode error)
{
KdDisableScreens();
}
void
ddxGiveUp(enum ExitCode error)
{
AbortDDX(error);
}
static Bool kdDumbDriver;
static Bool kdSoftCursor;
const char *
KdParseFindNext(const char *cur, const char *delim, char *save, char *last)
{
while (*cur && !strchr(delim, *cur)) {
*save++ = *cur++;
}
*save = 0;
*last = *cur;
if (*cur)
cur++;
return cur;
}
Rotation
KdAddRotation(Rotation a, Rotation b)
{
Rotation rotate = (a & RR_Rotate_All) * (b & RR_Rotate_All);
Rotation reflect = (a & RR_Reflect_All) ^ (b & RR_Reflect_All);
if (rotate > RR_Rotate_270)
rotate /= (RR_Rotate_270 * RR_Rotate_90);
return reflect | rotate;
}
Rotation
KdSubRotation(Rotation a, Rotation b)
{
Rotation rotate = (a & RR_Rotate_All) * 16 / (b & RR_Rotate_All);
Rotation reflect = (a & RR_Reflect_All) ^ (b & RR_Reflect_All);
if (rotate > RR_Rotate_270)
rotate /= (RR_Rotate_270 * RR_Rotate_90);
return reflect | rotate;
}
void
KdParseScreen(KdScreenInfo * screen, const char *arg)
{
char delim;
char save[1024];
int i;
int pixels, mm;
screen->dumb = kdDumbDriver;
screen->softCursor = kdSoftCursor;
screen->origin = kdOrigin;
screen->randr = RR_Rotate_0;
screen->x = 0;
screen->y = 0;
screen->width = 0;
screen->height = 0;
screen->width_mm = 0;
screen->height_mm = 0;
screen->subpixel_order = kdSubpixelOrder;
screen->rate = 0;
screen->fb.depth = 0;
if (!arg)
return;
if (strlen(arg) >= sizeof(save))
return;
for (i = 0; i < 2; i++) {
arg = KdParseFindNext(arg, "x/+@XY", save, &delim);
if (!save[0])
return;
pixels = atoi(save);
mm = 0;
if (delim == '/') {
arg = KdParseFindNext(arg, "x+@XY", save, &delim);
if (!save[0])
return;
mm = atoi(save);
}
if (i == 0) {
screen->width = pixels;
screen->width_mm = mm;
}
else {
screen->height = pixels;
screen->height_mm = mm;
}
if (delim != 'x' && delim != '+' && delim != '@' &&
delim != 'X' && delim != 'Y' &&
(delim != '\0' || i == 0))
return;
}
kdOrigin.x += screen->width;
kdOrigin.y = 0;
kdDumbDriver = FALSE;
kdSoftCursor = FALSE;
kdSubpixelOrder = SubPixelUnknown;
if (delim == '+') {
arg = KdParseFindNext(arg, "+@xXY", save, &delim);
if (save[0])
screen->x = atoi(save);
}
if (delim == '+') {
arg = KdParseFindNext(arg, "@xXY", save, &delim);
if (save[0])
screen->y = atoi(save);
}
if (delim == '@') {
arg = KdParseFindNext(arg, "xXY", save, &delim);
if (save[0]) {
int rotate = atoi(save);
if (rotate < 45)
screen->randr = RR_Rotate_0;
else if (rotate < 135)
screen->randr = RR_Rotate_90;
else if (rotate < 225)
screen->randr = RR_Rotate_180;
else if (rotate < 315)
screen->randr = RR_Rotate_270;
else
screen->randr = RR_Rotate_0;
}
}
if (delim == 'X') {
arg = KdParseFindNext(arg, "xY", save, &delim);
screen->randr |= RR_Reflect_X;
}
if (delim == 'Y') {
arg = KdParseFindNext(arg, "xY", save, &delim);
screen->randr |= RR_Reflect_Y;
}
arg = KdParseFindNext(arg, "x/,", save, &delim);
if (save[0]) {
screen->fb.depth = atoi(save);
if (delim == '/') {
arg = KdParseFindNext(arg, "x,", save, &delim);
if (save[0])
screen->fb.bitsPerPixel = atoi(save);
}
else
screen->fb.bitsPerPixel = 0;
}
if (delim == 'x') {
arg = KdParseFindNext(arg, "x", save, &delim);
if (save[0])
screen->rate = atoi(save);
}
}
static void
KdParseRgba(char *rgba)
{
if (!strcmp(rgba, "rgb"))
kdSubpixelOrder = SubPixelHorizontalRGB;
else if (!strcmp(rgba, "bgr"))
kdSubpixelOrder = SubPixelHorizontalBGR;
else if (!strcmp(rgba, "vrgb"))
kdSubpixelOrder = SubPixelVerticalRGB;
else if (!strcmp(rgba, "vbgr"))
kdSubpixelOrder = SubPixelVerticalBGR;
else if (!strcmp(rgba, "none"))
kdSubpixelOrder = SubPixelNone;
else
kdSubpixelOrder = SubPixelUnknown;
}
void
KdUseMsg(void)
{
ErrorF("\nTinyX Device Dependent Usage:\n");
ErrorF
("-screen WIDTH[/WIDTHMM]xHEIGHT[/HEIGHTMM][+[-]XOFFSET][+[-]YOFFSET][@ROTATION][X][Y][xDEPTH/BPP[xFREQ]] Specify screen characteristics\n");
ErrorF
("-rgba rgb/bgr/vrgb/vbgr/none Specify subpixel ordering for LCD panels\n");
ErrorF
("-mouse driver [,n,,options] Specify the pointer driver and its options (n is the number of buttons)\n");
ErrorF
("-keybd driver [,,options] Specify the keyboard driver and its options\n");
ErrorF("-xkb-rules Set default XkbRules value (can be overriden by -keybd options)\n");
ErrorF("-xkb-model Set default XkbModel value (can be overriden by -keybd options)\n");
ErrorF("-xkb-layout Set default XkbLayout value (can be overriden by -keybd options)\n");
ErrorF("-xkb-variant Set default XkbVariant value (can be overriden by -keybd options)\n");
ErrorF("-xkb-options Set default XkbOptions value (can be overriden by -keybd options)\n");
ErrorF("-zaphod Disable cursor screen switching\n");
ErrorF("-2button Emulate 3 button mouse\n");
ErrorF("-3button Disable 3 button mouse emulation\n");
ErrorF
("-rawcoord Don't transform pointer coordinates on rotation\n");
ErrorF("-dumb Disable hardware acceleration\n");
ErrorF("-softCursor Force software cursor\n");
ErrorF("-videoTest Start the server, pause momentarily and exit\n");
ErrorF
("-origin X,Y Locates the next screen in the the virtual screen (Xinerama)\n");
ErrorF("-switchCmd Command to execute on vt switch\n");
ErrorF
("vtxx Use virtual terminal xx instead of the next available\n");
}
int
KdProcessArgument(int argc, char **argv, int i)
{
KdCardInfo *card;
KdScreenInfo *screen;
if (!strcmp(argv[i], "-screen")) {
if ((i + 1) < argc) {
card = KdCardInfoLast();
if (!card) {
InitCard(0);
card = KdCardInfoLast();
}
if (card) {
screen = KdScreenInfoAdd(card);
KdParseScreen(screen, argv[i + 1]);
}
else
ErrorF("No matching card found!\n");
}
else
UseMsg();
return 2;
}
if (!strcmp(argv[i], "-zaphod")) {
kdDisableZaphod = TRUE;
return 1;
}
if (!strcmp(argv[i], "-3button")) {
kdEmulateMiddleButton = FALSE;
return 1;
}
if (!strcmp(argv[i], "-2button")) {
kdEmulateMiddleButton = TRUE;
return 1;
}
if (!strcmp(argv[i], "-rawcoord")) {
kdRawPointerCoordinates = 1;
return 1;
}
if (!strcmp(argv[i], "-dumb")) {
kdDumbDriver = TRUE;
return 1;
}
if (!strcmp(argv[i], "-softCursor")) {
kdSoftCursor = TRUE;
return 1;
}
if (!strcmp(argv[i], "-origin")) {
if ((i + 1) < argc) {
char *x = argv[i + 1];
char *y = strchr(x, ',');
if (x)
kdOrigin.x = atoi(x);
else
kdOrigin.x = 0;
if (y)
kdOrigin.y = atoi(y + 1);
else
kdOrigin.y = 0;
}
else
UseMsg();
return 2;
}
if (!strcmp(argv[i], "-rgba")) {
if ((i + 1) < argc)
KdParseRgba(argv[i + 1]);
else
UseMsg();
return 2;
}
if (!strcmp(argv[i], "-switchCmd")) {
if ((i + 1) < argc)
kdSwitchCmd = argv[i + 1];
else
UseMsg();
return 2;
}
if (!strcmp(argv[i], "-xkb-rules")) {
if (i + 1 >= argc) {
UseMsg();
FatalError("Missing argument for option -xkb-rules.\n");
}
kdGlobalXkbRules = argv[i + 1];
return 2;
}
if (!strcmp(argv[i], "-xkb-model")) {
if (i + 1 >= argc) {
UseMsg();
FatalError("Missing argument for option -xkb-model.\n");
}
kdGlobalXkbModel = argv[i + 1];
return 2;
}
if (!strcmp(argv[i], "-xkb-layout")) {
if (i + 1 >= argc) {
UseMsg();
FatalError("Missing argument for option -xkb-layout.\n");
}
kdGlobalXkbLayout = argv[i + 1];
return 2;
}
if (!strcmp(argv[i], "-xkb-variant")) {
if (i + 1 >= argc) {
UseMsg();
FatalError("Missing argument for option -xkb-variant.\n");
}
kdGlobalXkbVariant = argv[i + 1];
return 2;
}
if (!strcmp(argv[i], "-xkb-options")) {
if (i + 1 >= argc) {
UseMsg();
FatalError("Missing argument for option -xkb-options.\n");
}
kdGlobalXkbOptions = argv[i + 1];
return 2;
}
if (!strcmp(argv[i], "-mouse") || !strcmp(argv[i], "-pointer")) {
if (i + 1 >= argc)
UseMsg();
KdAddConfigPointer(argv[i + 1]);
kdHasPointer = TRUE;
return 2;
}
if (!strcmp(argv[i], "-keybd")) {
if (i + 1 >= argc)
UseMsg();
KdAddConfigKeyboard(argv[i + 1]);
kdHasKbd = TRUE;
return 2;
}
return 0;
}
static Bool
KdAllocatePrivates(ScreenPtr pScreen)
{
KdPrivScreenPtr pScreenPriv;
if (kdGeneration != serverGeneration)
kdGeneration = serverGeneration;
if (!dixRegisterPrivateKey(&kdScreenPrivateKeyRec, PRIVATE_SCREEN, 0))
return FALSE;
pScreenPriv = calloc(1, sizeof(*pScreenPriv));
if (!pScreenPriv)
return FALSE;
KdSetScreenPriv(pScreen, pScreenPriv);
return TRUE;
}
static Bool
KdCreateScreenResources(ScreenPtr pScreen)
{
KdScreenPriv(pScreen);
KdCardInfo *card = pScreenPriv->card;
Bool ret;
pScreen->CreateScreenResources = pScreenPriv->CreateScreenResources;
if (pScreen->CreateScreenResources)
ret = (*pScreen->CreateScreenResources) (pScreen);
else
ret = -1;
pScreenPriv->CreateScreenResources = pScreen->CreateScreenResources;
pScreen->CreateScreenResources = KdCreateScreenResources;
if (ret && card->cfuncs->createRes)
ret = (*card->cfuncs->createRes) (pScreen);
return ret;
}
static Bool
KdCloseScreen(ScreenPtr pScreen)
{
KdScreenPriv(pScreen);
KdScreenInfo *screen = pScreenPriv->screen;
KdCardInfo *card = pScreenPriv->card;
Bool ret;
if (card->cfuncs->closeScreen)
(*card->cfuncs->closeScreen)(pScreen);
pScreenPriv->closed = TRUE;
pScreen->CloseScreen = pScreenPriv->CloseScreen;
if (pScreen->CloseScreen)
ret = (*pScreen->CloseScreen) (pScreen);
else
ret = TRUE;
if (screen->mynum == card->selected)
KdDisableScreen(pScreen);
if (!pScreenPriv->screen->dumb && card->cfuncs->finiAccel)
(*card->cfuncs->finiAccel) (pScreen);
if (card->cfuncs->scrfini)
(*card->cfuncs->scrfini) (screen);
/*
* Clean up card when last screen is closed, DIX closes them in
* reverse order, thus we check for when the first in the list is closed
*/
if (screen == card->screenList) {
if (card->cfuncs->cardfini)
(*card->cfuncs->cardfini) (card);
/*
* Clean up OS when last card is closed
*/
if (card == kdCardInfo) {
kdEnabled = FALSE;
}
}
pScreenPriv->screen->pScreen = 0;
free((void *) pScreenPriv);
return ret;
}
static Bool
KdSaveScreen(ScreenPtr pScreen, int on)
{
return FALSE;
}
static Bool
KdCreateWindow(WindowPtr pWin)
{
#ifndef PHOENIX
if (!pWin->parent) {
KdScreenPriv(pWin->drawable.pScreen);
if (!pScreenPriv->enabled) {
RegionEmpty(&pWin->borderClip);
RegionBreak(&pWin->clipList);
}
}
#endif
return fbCreateWindow(pWin);
}
void
KdSetSubpixelOrder(ScreenPtr pScreen, Rotation randr)
{
KdScreenPriv(pScreen);
KdScreenInfo *screen = pScreenPriv->screen;
int subpixel_order = screen->subpixel_order;
Rotation subpixel_dir;
int i;
static struct {
int subpixel_order;
Rotation direction;
} orders[] = {
{SubPixelHorizontalRGB, RR_Rotate_0},
{SubPixelHorizontalBGR, RR_Rotate_180},
{SubPixelVerticalRGB, RR_Rotate_270},
{SubPixelVerticalBGR, RR_Rotate_90},
};
static struct {
int bit;
int normal;
int reflect;
} reflects[] = {
{RR_Reflect_X, SubPixelHorizontalRGB, SubPixelHorizontalBGR},
{RR_Reflect_X, SubPixelHorizontalBGR, SubPixelHorizontalRGB},
{RR_Reflect_Y, SubPixelVerticalRGB, SubPixelVerticalBGR},
{RR_Reflect_Y, SubPixelVerticalRGB, SubPixelVerticalRGB},
};
/* map subpixel to direction */
for (i = 0; i < 4; i++)
if (orders[i].subpixel_order == subpixel_order)
break;
if (i < 4) {
subpixel_dir =
KdAddRotation(randr & RR_Rotate_All, orders[i].direction);
/* map back to subpixel order */
for (i = 0; i < 4; i++)
if (orders[i].direction & subpixel_dir) {
subpixel_order = orders[i].subpixel_order;
break;
}
/* reflect */
for (i = 0; i < 4; i++)
if ((randr & reflects[i].bit) &&
reflects[i].normal == subpixel_order) {
subpixel_order = reflects[i].reflect;
break;
}
}
PictureSetSubpixelOrder(pScreen, subpixel_order);
}
/* Pass through AddScreen, which doesn't take any closure */
static KdScreenInfo *kdCurrentScreen;
static Bool
KdScreenInit(ScreenPtr pScreen, int argc, char **argv)
{
KdScreenInfo *screen = kdCurrentScreen;
KdCardInfo *card = screen->card;
KdPrivScreenPtr pScreenPriv;
/*
* note that screen->fb is set up for the nominal orientation
* of the screen; that means if randr is rotated, the values
* there should reflect a rotated frame buffer (or shadow).
*/
Bool rotated = (screen->randr & (RR_Rotate_90 | RR_Rotate_270)) != 0;
int width, height, *width_mmp, *height_mmp;
KdAllocatePrivates(pScreen);
pScreenPriv = KdGetScreenPriv(pScreen);
if (!rotated) {
width = screen->width;
height = screen->height;
width_mmp = &screen->width_mm;
height_mmp = &screen->height_mm;
}
else {
width = screen->height;
height = screen->width;
width_mmp = &screen->height_mm;
height_mmp = &screen->width_mm;
}
screen->pScreen = pScreen;
pScreenPriv->screen = screen;
pScreenPriv->card = card;
pScreenPriv->bytesPerPixel = screen->fb.bitsPerPixel >> 3;
pScreenPriv->dpmsState = KD_DPMS_NORMAL;
pScreen->x = screen->origin.x;
pScreen->y = screen->origin.y;
if (!monitorResolution)
monitorResolution = 75;
/*
* This is done in this order so that backing store wraps
* our GC functions; fbFinishScreenInit initializes MI
* backing store
*/
if (!fbSetupScreen(pScreen,
screen->fb.frameBuffer,
width, height,
monitorResolution, monitorResolution,
screen->fb.pixelStride, screen->fb.bitsPerPixel)) {
return FALSE;
}
/*
* Set colormap functions
*/
pScreen->InstallColormap = KdInstallColormap;
pScreen->UninstallColormap = KdUninstallColormap;
pScreen->ListInstalledColormaps = KdListInstalledColormaps;
pScreen->StoreColors = KdStoreColors;
pScreen->SaveScreen = KdSaveScreen;
pScreen->CreateWindow = KdCreateWindow;
if (!fbFinishScreenInit(pScreen,
screen->fb.frameBuffer,
width, height,
monitorResolution, monitorResolution,
screen->fb.pixelStride, screen->fb.bitsPerPixel)) {
return FALSE;
}
/*
* Fix screen sizes; for some reason mi takes dpi instead of mm.
* Rounding errors are annoying
*/
if (*width_mmp)
pScreen->mmWidth = *width_mmp;
else
*width_mmp = pScreen->mmWidth;
if (*height_mmp)
pScreen->mmHeight = *height_mmp;
else
*height_mmp = pScreen->mmHeight;
/*
* Plug in our own block/wakeup handlers.
* miScreenInit installs NoopDDA in both places
*/
pScreen->BlockHandler = KdBlockHandler;
pScreen->WakeupHandler = KdWakeupHandler;
if (!fbPictureInit(pScreen, 0, 0))
return FALSE;
if (card->cfuncs->initScreen)
if (!(*card->cfuncs->initScreen) (pScreen))
return FALSE;
if (!screen->dumb && card->cfuncs->initAccel)
if (!(*card->cfuncs->initAccel) (pScreen))
screen->dumb = TRUE;
if (card->cfuncs->finishInitScreen)
if (!(*card->cfuncs->finishInitScreen) (pScreen))
return FALSE;
/*
* Wrap CloseScreen, the order now is:
* KdCloseScreen
* fbCloseScreen
*/
pScreenPriv->CloseScreen = pScreen->CloseScreen;
pScreen->CloseScreen = KdCloseScreen;
pScreenPriv->CreateScreenResources = pScreen->CreateScreenResources;
pScreen->CreateScreenResources = KdCreateScreenResources;
if (screen->softCursor ||
!card->cfuncs->initCursor || !(*card->cfuncs->initCursor) (pScreen)) {
/* Use MI for cursor display and event queueing. */
screen->softCursor = TRUE;
miDCInitialize(pScreen, &kdPointerScreenFuncs);
}
if (!fbCreateDefColormap(pScreen)) {
return FALSE;
}
KdSetSubpixelOrder(pScreen, screen->randr);
/*
* Enable the hardware
*/
kdEnabled = TRUE;
if (screen->mynum == card->selected) {
pScreenPriv->enabled = TRUE;
KdEnableColormap(pScreen);
if (!screen->dumb && card->cfuncs->enableAccel)
(*card->cfuncs->enableAccel) (pScreen);
}
return TRUE;
}
static void
KdInitScreen(ScreenInfo * pScreenInfo,
KdScreenInfo * screen, int argc, char **argv)
{
KdCardInfo *card = screen->card;
if (!(*card->cfuncs->scrinit) (screen))
FatalError("Screen initialization failed!\n");
if (!card->cfuncs->initAccel)
screen->dumb = TRUE;
if (!card->cfuncs->initCursor)
screen->softCursor = TRUE;
}
static Bool
KdSetPixmapFormats(ScreenInfo * pScreenInfo)
{
CARD8 depthToBpp[33]; /* depth -> bpp map */
KdCardInfo *card;
KdScreenInfo *screen;
int i;
int bpp;
PixmapFormatRec *format;
for (i = 1; i <= 32; i++)
depthToBpp[i] = 0;
/*
* Generate mappings between bitsPerPixel and depth,
* also ensure that all screens comply with protocol
* restrictions on equivalent formats for the same
* depth on different screens
*/
for (card = kdCardInfo; card; card = card->next) {
for (screen = card->screenList; screen; screen = screen->next) {
bpp = screen->fb.bitsPerPixel;
if (bpp == 24)
bpp = 32;
if (!depthToBpp[screen->fb.depth])
depthToBpp[screen->fb.depth] = bpp;
else if (depthToBpp[screen->fb.depth] != bpp)
return FALSE;
}
}
/*
* Fill in additional formats
*/
for (i = 0; i < ARRAY_SIZE(kdDepths); i++)
if (!depthToBpp[kdDepths[i].depth])
depthToBpp[kdDepths[i].depth] = kdDepths[i].bpp;
pScreenInfo->imageByteOrder = IMAGE_BYTE_ORDER;
pScreenInfo->bitmapScanlineUnit = BITMAP_SCANLINE_UNIT;
pScreenInfo->bitmapScanlinePad = BITMAP_SCANLINE_PAD;
pScreenInfo->bitmapBitOrder = BITMAP_BIT_ORDER;
pScreenInfo->numPixmapFormats = 0;
for (i = 1; i <= 32; i++) {
if (depthToBpp[i]) {
format = &pScreenInfo->formats[pScreenInfo->numPixmapFormats++];
format->depth = i;
format->bitsPerPixel = depthToBpp[i];
format->scanlinePad = BITMAP_SCANLINE_PAD;
}
}
return TRUE;
}
static void
KdAddScreen(ScreenInfo * pScreenInfo,
KdScreenInfo * screen, int argc, char **argv)
{
int i;
/*
* Fill in fb visual type masks for this screen
*/
for (i = 0; i < pScreenInfo->numPixmapFormats; i++) {
unsigned long visuals;
Pixel rm, gm, bm;
visuals = 0;
rm = gm = bm = 0;
if (pScreenInfo->formats[i].depth == screen->fb.depth) {
visuals = screen->fb.visuals;
rm = screen->fb.redMask;
gm = screen->fb.greenMask;
bm = screen->fb.blueMask;
}
fbSetVisualTypesAndMasks(pScreenInfo->formats[i].depth,
visuals, 8, rm, gm, bm);
}
kdCurrentScreen = screen;
AddScreen(KdScreenInit, argc, argv);
}
void
KdInitOutput(ScreenInfo * pScreenInfo, int argc, char **argv)
{
KdCardInfo *card;
KdScreenInfo *screen;
if (!kdCardInfo) {
InitCard(0);
if (!(card = KdCardInfoLast()))
FatalError("No matching cards found!\n");
screen = KdScreenInfoAdd(card);
KdParseScreen(screen, 0);
}
/*
* Initialize all of the screens for all of the cards
*/
for (card = kdCardInfo; card; card = card->next) {
int ret = 1;
if (card->cfuncs->cardinit)
ret = (*card->cfuncs->cardinit) (card);
if (ret) {
for (screen = card->screenList; screen; screen = screen->next)
KdInitScreen(pScreenInfo, screen, argc, argv);
}
}
/*
* Merge the various pixmap formats together, this can fail
* when two screens share depth but not bitsPerPixel
*/
if (!KdSetPixmapFormats(pScreenInfo))
return;
/*
* Add all of the screens
*/
for (card = kdCardInfo; card; card = card->next)
for (screen = card->screenList; screen; screen = screen->next)
KdAddScreen(pScreenInfo, screen, argc, argv);
xorgGlxCreateVendor();
#if defined(CONFIG_UDEV) || defined(CONFIG_HAL)
if (SeatId) /* Enable input hot-plugging */
config_pre_init();
#endif
}
void
OsVendorFatalError(const char *f, va_list args)
{
}
/* These stubs can be safely removed once we can
* split input and GPU parts in hotplug.h et al. */
#ifdef CONFIG_UDEV_KMS
void
NewGPUDeviceRequest(struct OdevAttributes *attribs)
{
}
void
DeleteGPUDeviceRequest(struct OdevAttributes *attribs)
{
}
#endif
struct xf86_platform_device *
xf86_find_platform_device_by_devnum(int major, int minor)
{
return NULL;
}
#ifdef SYSTEMD_LOGIND
void
systemd_logind_vtenter(void)
{
}
void
systemd_logind_release_fd(int major, int minor, int fd)
{
close(fd);
}
#endif