540 lines
14 KiB
C
540 lines
14 KiB
C
/*
|
|
* Copyright © 2010 Intel Corporation.
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person
|
|
* obtaining a copy of this software and associated documentation
|
|
* files (the "Software"), to deal in the Software without
|
|
* restriction, including without limitation the rights to use, copy,
|
|
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
|
* of the Software, and to permit persons to whom the Software is
|
|
* furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice (including
|
|
* the next paragraph) shall be included in all copies or substantial
|
|
* portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
|
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
|
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
* DEALINGS IN THE SOFTWARE.
|
|
*
|
|
* Authors:
|
|
* Kristian Høgsberg <krh@bitplanet.net>
|
|
*
|
|
*/
|
|
|
|
#ifdef HAVE_DIX_CONFIG_H
|
|
#include <dix-config.h>
|
|
#endif
|
|
#include <unistd.h>
|
|
#include <fcntl.h>
|
|
#include <errno.h>
|
|
#include <xf86drm.h>
|
|
|
|
#define GL_GLEXT_PROTOTYPES
|
|
#define EGL_EGLEXT_PROTOTYPES
|
|
#define EGL_DISPLAY_NO_X_MESA
|
|
#include <GL/gl.h>
|
|
#include <EGL/egl.h>
|
|
#include <EGL/eglext.h>
|
|
|
|
#include "../../../mi/micmap.h"
|
|
#include <xf86Crtc.h>
|
|
#include <xf86.h>
|
|
#define GC XORG_GC
|
|
#include <glamor.h>
|
|
#undef GC
|
|
|
|
#include "glamor_ddx.h"
|
|
|
|
#define GLAMOR_VERSION_MAJOR 0
|
|
#define GLAMOR_VERSION_MINOR 1
|
|
#define GLAMOR_VERSION_PATCH 0
|
|
|
|
static const char glamor_name[] = "glamor";
|
|
|
|
static void
|
|
glamor_identify(int flags)
|
|
{
|
|
xf86Msg(X_INFO, "%s: OpenGL accelerated X.org driver\n", glamor_name);
|
|
}
|
|
|
|
struct glamor_screen_private {
|
|
EGLDisplay display;
|
|
EGLContext context;
|
|
EGLImageKHR root;
|
|
EGLint major, minor;
|
|
|
|
CreateScreenResourcesProcPtr CreateScreenResources;
|
|
CloseScreenProcPtr CloseScreen;
|
|
int fd;
|
|
int cpp;
|
|
};
|
|
|
|
static inline struct glamor_screen_private *
|
|
glamor_get_screen_private(ScrnInfoPtr scrn)
|
|
{
|
|
return (struct glamor_screen_private *) (scrn->driverPrivate);
|
|
}
|
|
|
|
Bool
|
|
glamor_resize(ScrnInfoPtr scrn, int width, int height)
|
|
{
|
|
struct glamor_screen_private *glamor = glamor_get_screen_private(scrn);
|
|
ScreenPtr screen = screenInfo.screens[scrn->scrnIndex];
|
|
EGLImageKHR image;
|
|
GLuint texture;
|
|
EGLint attribs[] = {
|
|
EGL_WIDTH, 0,
|
|
EGL_HEIGHT, 0,
|
|
EGL_DRM_BUFFER_FORMAT_MESA, EGL_DRM_BUFFER_FORMAT_ARGB32_MESA,
|
|
EGL_DRM_BUFFER_USE_MESA, EGL_DRM_BUFFER_USE_SHARE_MESA |
|
|
EGL_DRM_BUFFER_USE_SCANOUT_MESA,
|
|
EGL_NONE
|
|
};
|
|
|
|
if (glamor->root != EGL_NO_IMAGE_KHR &&
|
|
scrn->virtualX == width && scrn->virtualY == height)
|
|
return TRUE;
|
|
|
|
attribs[1] = width;
|
|
attribs[3] = height;
|
|
image = eglCreateDRMImageMESA(glamor->display, attribs);
|
|
if (image == EGL_NO_IMAGE_KHR)
|
|
return FALSE;
|
|
|
|
glGenTextures(1, &texture);
|
|
glBindTexture(GL_TEXTURE_2D, texture);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
|
glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image);
|
|
|
|
glamor_set_pixmap_texture(screen->GetScreenPixmap(screen),
|
|
width, height, texture);
|
|
glamor->root = image;
|
|
scrn->virtualX = width;
|
|
scrn->virtualY = height;
|
|
return TRUE;
|
|
}
|
|
|
|
void
|
|
glamor_frontbuffer_handle(ScrnInfoPtr scrn, uint32_t *handle, uint32_t *pitch)
|
|
{
|
|
struct glamor_screen_private *glamor = glamor_get_screen_private(scrn);
|
|
EGLint name;
|
|
eglExportDRMImageMESA (glamor->display, glamor->root, &name, (EGLint*) handle, (EGLint*) pitch);
|
|
}
|
|
|
|
EGLImageKHR glamor_create_cursor_argb(ScrnInfoPtr scrn, int width, int height)
|
|
{
|
|
struct glamor_screen_private *glamor = glamor_get_screen_private(scrn);
|
|
EGLint attribs[] = {
|
|
EGL_WIDTH, 0,
|
|
EGL_HEIGHT, 0,
|
|
EGL_DRM_BUFFER_FORMAT_MESA, EGL_DRM_BUFFER_FORMAT_ARGB32_MESA,
|
|
EGL_DRM_BUFFER_USE_MESA, EGL_DRM_BUFFER_USE_SHARE_MESA |
|
|
EGL_DRM_BUFFER_USE_SCANOUT_MESA | EGL_DRM_BUFFER_USE_CURSOR_MESA,
|
|
EGL_NONE
|
|
};
|
|
|
|
attribs[1] = width;
|
|
attribs[3] = height;
|
|
return eglCreateDRMImageMESA(glamor->display, attribs);
|
|
}
|
|
|
|
void
|
|
glamor_cursor_handle(ScrnInfoPtr scrn, EGLImageKHR cursor, uint32_t *handle, uint32_t *pitch)
|
|
{
|
|
struct glamor_screen_private *glamor = glamor_get_screen_private(scrn);
|
|
EGLint name;
|
|
eglExportDRMImageMESA (glamor->display, cursor, &name, (EGLint*) handle, (EGLint*) pitch);
|
|
ErrorF("cursor stride: %d\n", *pitch);
|
|
}
|
|
|
|
char * dri_device_name = "/dev/dri/card0";
|
|
static Bool
|
|
glamor_pre_init(ScrnInfoPtr scrn, int flags)
|
|
{
|
|
struct glamor_screen_private *glamor;
|
|
rgb defaultWeight = { 0, 0, 0 };
|
|
|
|
glamor = xnfcalloc(sizeof *glamor, 1);
|
|
|
|
scrn->driverPrivate = glamor;
|
|
glamor->fd = open(dri_device_name, O_RDWR);
|
|
if (glamor->fd == -1 ) {
|
|
ErrorF("Failed to open %s: %s\n", dri_device_name, strerror(errno));
|
|
goto fail;
|
|
}
|
|
|
|
glamor->cpp = 4;
|
|
|
|
scrn->monitor = scrn->confScreen->monitor;
|
|
scrn->progClock = TRUE;
|
|
scrn->rgbBits = 8;
|
|
|
|
if (!xf86SetDepthBpp(scrn, 0, 0, 0, Support32bppFb))
|
|
goto fail;
|
|
|
|
xf86PrintDepthBpp(scrn);
|
|
|
|
if (!xf86SetWeight(scrn, defaultWeight, defaultWeight))
|
|
goto fail;
|
|
if (!xf86SetDefaultVisual(scrn, -1))
|
|
goto fail;
|
|
|
|
glamor->cpp = scrn->bitsPerPixel / 8;
|
|
|
|
if (drmmode_pre_init(scrn, glamor->fd, glamor->cpp) == FALSE) {
|
|
xf86DrvMsg(scrn->scrnIndex, X_ERROR,
|
|
"Kernel modesetting setup failed\n");
|
|
goto fail;
|
|
}
|
|
|
|
scrn->currentMode = scrn->modes;
|
|
xf86SetDpi(scrn, 0, 0);
|
|
|
|
/* Load the required sub modules */
|
|
if (!xf86LoadSubModule(scrn, "fb"))
|
|
goto fail;
|
|
|
|
return TRUE;
|
|
|
|
fail:
|
|
scrn->driverPrivate = NULL;
|
|
free(glamor);
|
|
return FALSE;
|
|
}
|
|
|
|
static void
|
|
glamor_adjust_frame(int scrnIndex, int x, int y, int flags)
|
|
{
|
|
}
|
|
|
|
static Bool
|
|
glamor_enter_vt(int scrnIndex, int flags)
|
|
{
|
|
ScrnInfoPtr scrn = xf86Screens[scrnIndex];
|
|
struct glamor_screen_private *glamor = glamor_get_screen_private(scrn);
|
|
|
|
if (drmSetMaster(glamor->fd)) {
|
|
xf86DrvMsg(scrn->scrnIndex, X_WARNING,
|
|
"drmSetMaster failed: %s\n", strerror(errno));
|
|
return FALSE;
|
|
}
|
|
#if 0
|
|
if (!xf86SetDesiredModes(scrn))
|
|
return FALSE;
|
|
#endif
|
|
return TRUE;
|
|
}
|
|
|
|
static void
|
|
glamor_leave_vt(int scrnIndex, int flags)
|
|
{
|
|
ScrnInfoPtr scrn = xf86Screens[scrnIndex];
|
|
struct glamor_screen_private *glamor = glamor_get_screen_private(scrn);
|
|
|
|
drmDropMaster(glamor->fd);
|
|
}
|
|
|
|
static Bool
|
|
glamor_create_screen_resources(ScreenPtr screen)
|
|
{
|
|
ScrnInfoPtr scrn = xf86Screens[screen->myNum];
|
|
struct glamor_screen_private *glamor = glamor_get_screen_private(scrn);
|
|
|
|
screen->CreateScreenResources = glamor->CreateScreenResources;
|
|
if (!(*screen->CreateScreenResources) (screen))
|
|
return FALSE;
|
|
|
|
|
|
if (!xf86SetDesiredModes(scrn))
|
|
return FALSE;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static Bool
|
|
glamor_close_screen(int scrnIndex, ScreenPtr screen)
|
|
{
|
|
ScrnInfoPtr scrn = xf86Screens[scrnIndex];
|
|
struct glamor_screen_private *glamor = glamor_get_screen_private(scrn);
|
|
|
|
if (scrn->vtSema == TRUE)
|
|
glamor_leave_vt(scrnIndex, 0);
|
|
|
|
glamor_fini(screen);
|
|
|
|
eglMakeCurrent(glamor->display,
|
|
EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
|
eglTerminate(glamor->display);
|
|
|
|
drmmode_closefb(scrn);
|
|
|
|
screen->CloseScreen = glamor->CloseScreen;
|
|
(*screen->CloseScreen) (scrnIndex, screen);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static Bool
|
|
glamor_screen_init(int scrnIndex, ScreenPtr screen, int argc, char **argv)
|
|
{
|
|
ScrnInfoPtr scrn = xf86Screens[screen->myNum];
|
|
struct glamor_screen_private *glamor = glamor_get_screen_private(scrn);
|
|
const char *version;
|
|
VisualPtr visual;
|
|
|
|
glamor->display = eglGetDRMDisplayMESA(glamor->fd);
|
|
eglBindAPI(EGL_OPENGL_API);
|
|
LogMessageVerb(X_INFO, 0, "%s glCreateProgramObjectARB=%p", __FUNCTION__, *(&glCreateProgramObjectARB));
|
|
if (!eglInitialize(glamor->display, &glamor->major, &glamor->minor)) {
|
|
xf86DrvMsg(scrn->scrnIndex, X_ERROR,
|
|
"eglInitialize() failed\n");
|
|
return FALSE;
|
|
}
|
|
|
|
version = eglQueryString(glamor->display, EGL_VERSION);
|
|
xf86Msg(X_INFO, "%s: EGL version %s:", glamor_name, version);
|
|
|
|
glamor->context = eglCreateContext(glamor->display,
|
|
NULL, EGL_NO_CONTEXT, NULL);
|
|
if (glamor->context == EGL_NO_CONTEXT) {
|
|
xf86DrvMsg(scrn->scrnIndex, X_ERROR,
|
|
"Failed to create EGL context\n");
|
|
return FALSE;
|
|
}
|
|
|
|
if (!eglMakeCurrent(glamor->display,
|
|
EGL_NO_SURFACE, EGL_NO_SURFACE, glamor->context)) {
|
|
xf86DrvMsg(scrn->scrnIndex, X_ERROR,
|
|
"Failed to make EGL context current\n");
|
|
return FALSE;
|
|
}
|
|
|
|
miClearVisualTypes();
|
|
if (!miSetVisualTypes(scrn->depth,
|
|
miGetDefaultVisualMask(scrn->depth),
|
|
scrn->rgbBits, scrn->defaultVisual))
|
|
return FALSE;
|
|
if (!miSetPixmapDepths())
|
|
return FALSE;
|
|
|
|
if (!fbScreenInit(screen, NULL,
|
|
scrn->virtualX, scrn->virtualY,
|
|
scrn->xDpi, scrn->yDpi,
|
|
1, scrn->bitsPerPixel))
|
|
return FALSE;
|
|
|
|
if (scrn->bitsPerPixel > 8) {
|
|
/* Fixup RGB ordering */
|
|
visual = screen->visuals + screen->numVisuals;
|
|
while(--visual >= screen->visuals) {
|
|
if ((visual->class | DynamicClass) == DirectColor) {
|
|
visual->offsetRed = scrn->offset.red;
|
|
visual->offsetGreen = scrn->offset.green;
|
|
visual->offsetBlue = scrn->offset.blue;
|
|
visual->redMask = scrn->mask.red;
|
|
visual->blueMask = scrn->mask.blue;
|
|
}
|
|
}
|
|
}
|
|
|
|
fbPictureInit(screen, NULL, 0);
|
|
xf86SetBlackWhitePixels(screen);
|
|
|
|
if (!glamor_init(screen, GLAMOR_INVERTED_Y_AXIS)) {
|
|
xf86DrvMsg(scrn->scrnIndex, X_ERROR,
|
|
"Failed to initialize glamor\n");
|
|
return FALSE;
|
|
}
|
|
|
|
miInitializeBackingStore(screen);
|
|
xf86SetBackingStore(screen);
|
|
xf86SetSilkenMouse(screen);
|
|
miDCInitialize(screen, xf86GetPointerScreenFuncs());
|
|
|
|
xf86DrvMsg(scrn->scrnIndex, X_INFO, "Initializing HW Cursor\n");
|
|
|
|
if (!xf86_cursors_init(screen, 64, 64,
|
|
(HARDWARE_CURSOR_TRUECOLOR_AT_8BPP |
|
|
HARDWARE_CURSOR_BIT_ORDER_MSBFIRST |
|
|
HARDWARE_CURSOR_INVERT_MASK |
|
|
HARDWARE_CURSOR_SWAP_SOURCE_AND_MASK |
|
|
HARDWARE_CURSOR_AND_SOURCE_WITH_MASK |
|
|
HARDWARE_CURSOR_SOURCE_MASK_NOT_INTERLEAVED |
|
|
HARDWARE_CURSOR_UPDATE_UNHIDDEN |
|
|
HARDWARE_CURSOR_ARGB))) {
|
|
xf86DrvMsg(scrn->scrnIndex, X_ERROR,
|
|
"Hardware cursor initialization failed\n");
|
|
}
|
|
|
|
/* Must force it before EnterVT, so we are in control of VT and
|
|
* later memory should be bound when allocating, e.g rotate_mem */
|
|
scrn->vtSema = TRUE;
|
|
|
|
if (!glamor_enter_vt(scrnIndex, 0))
|
|
return FALSE;
|
|
|
|
screen->SaveScreen = xf86SaveScreen;
|
|
glamor->CreateScreenResources = screen->CreateScreenResources;
|
|
screen->CreateScreenResources = glamor_create_screen_resources;
|
|
glamor->CloseScreen = screen->CloseScreen;
|
|
screen->CloseScreen = glamor_close_screen;
|
|
|
|
/* Fixme should we init crtc screen here? */
|
|
if (!xf86CrtcScreenInit(screen))
|
|
return FALSE;
|
|
if (!miCreateDefColormap(screen))
|
|
return FALSE;
|
|
/* Fixme should we add handle colormap here? */
|
|
|
|
xf86DPMSInit(screen, xf86DPMSSet, 0);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static void
|
|
glamor_free_screen(int scrnIndex, int flags)
|
|
{
|
|
ScrnInfoPtr scrn = xf86Screens[scrnIndex];
|
|
struct glamor_screen_private *glamor = glamor_get_screen_private(scrn);
|
|
if (glamor != NULL)
|
|
{
|
|
close(glamor->fd);
|
|
free(glamor);
|
|
scrn->driverPrivate = NULL;
|
|
}
|
|
}
|
|
|
|
static ModeStatus
|
|
glamor_valid_mode(int scrnIndex, DisplayModePtr mode, Bool verbose, int flags)
|
|
{
|
|
if (mode->Flags & V_INTERLACE) {
|
|
if (verbose) {
|
|
xf86DrvMsg(scrnIndex, X_PROBED,
|
|
"Removing interlaced mode \"%s\"\n",
|
|
mode->name);
|
|
}
|
|
return MODE_BAD;
|
|
}
|
|
return MODE_OK;
|
|
}
|
|
|
|
static Bool
|
|
glamor_probe(struct _DriverRec *drv, int flags)
|
|
{
|
|
ScrnInfoPtr scrn = NULL;
|
|
GDevPtr *sections;
|
|
int entity, n;
|
|
|
|
n = xf86MatchDevice(glamor_name, §ions);
|
|
if (n <= 0)
|
|
return FALSE;
|
|
|
|
entity = xf86ClaimFbSlot(drv, 0, sections[0], TRUE);
|
|
|
|
scrn = xf86ConfigFbEntity(scrn, 0, entity, NULL, NULL, NULL, NULL);
|
|
if (scrn == NULL) {
|
|
xf86Msg(X_ERROR, "Failed to add fb entity\n");
|
|
return FALSE;
|
|
}
|
|
|
|
scrn->driverVersion = 1;
|
|
scrn->driverName = (char *) glamor_name;
|
|
scrn->name = (char *) glamor_name;
|
|
scrn->Probe = NULL;
|
|
|
|
scrn->PreInit = glamor_pre_init;
|
|
scrn->ScreenInit = glamor_screen_init;
|
|
scrn->AdjustFrame = glamor_adjust_frame;
|
|
scrn->EnterVT = glamor_enter_vt;
|
|
scrn->LeaveVT = glamor_leave_vt;
|
|
scrn->FreeScreen = glamor_free_screen;
|
|
scrn->ValidMode = glamor_valid_mode;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static const OptionInfoRec *
|
|
glamor_available_options(int chipid, int busid)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
static Bool
|
|
glamor_driver_func(ScrnInfoPtr pScrn, xorgDriverFuncOp op, pointer ptr)
|
|
{
|
|
xorgHWFlags *flag;
|
|
|
|
switch (op) {
|
|
case GET_REQUIRED_HW_INTERFACES:
|
|
flag = (CARD32*)ptr;
|
|
(*flag) = 0;
|
|
return TRUE;
|
|
default:
|
|
/* Unknown or deprecated function */
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
_X_EXPORT DriverRec glamor = {
|
|
1,
|
|
"glamor",
|
|
glamor_identify,
|
|
glamor_probe,
|
|
glamor_available_options,
|
|
NULL,
|
|
0,
|
|
glamor_driver_func,
|
|
};
|
|
|
|
static pointer
|
|
glamor_setup(pointer module, pointer opts, int *errmaj, int *errmin)
|
|
{
|
|
static Bool setupDone = 0;
|
|
|
|
/* This module should be loaded only once, but check to be sure.
|
|
*/
|
|
if (!setupDone) {
|
|
setupDone = 1;
|
|
xf86AddDriver(&glamor, module, HaveDriverFuncs);
|
|
|
|
/*
|
|
* The return value must be non-NULL on success even though there
|
|
* is no TearDownProc.
|
|
*/
|
|
return (pointer) 1;
|
|
} else {
|
|
if (errmaj)
|
|
*errmaj = LDR_ONCEONLY;
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
static XF86ModuleVersionInfo glamor_version_info = {
|
|
glamor_name,
|
|
MODULEVENDORSTRING,
|
|
MODINFOSTRING1,
|
|
MODINFOSTRING2,
|
|
XORG_VERSION_CURRENT,
|
|
GLAMOR_VERSION_MAJOR,
|
|
GLAMOR_VERSION_MINOR,
|
|
GLAMOR_VERSION_PATCH,
|
|
ABI_CLASS_VIDEODRV,
|
|
ABI_VIDEODRV_VERSION,
|
|
MOD_CLASS_VIDEODRV,
|
|
{0, 0, 0, 0}
|
|
};
|
|
|
|
_X_EXPORT XF86ModuleData glamorModuleData = {
|
|
&glamor_version_info,
|
|
glamor_setup,
|
|
NULL
|
|
};
|