mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-02-15 21:50:28 +01:00
egl: EGL->DRI adaptor/driver
Allows regular DRI drivers to work with libEGL.
This commit is contained in:
parent
ab102d5a9f
commit
8dafe470fc
2 changed files with 900 additions and 0 deletions
67
src/egl/drivers/xdri/Makefile
Normal file
67
src/egl/drivers/xdri/Makefile
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
# src/egl/drivers/xdri/Makefile
|
||||
|
||||
# Build XEGL DRI driver loader library: egl_xdri.so
|
||||
|
||||
|
||||
TOP = ../../../..
|
||||
include $(TOP)/configs/current
|
||||
|
||||
|
||||
DRIVER_NAME = egl_xdri.so
|
||||
|
||||
|
||||
INCLUDE_DIRS = \
|
||||
-I. \
|
||||
-I/usr/include \
|
||||
-I/usr/include/drm \
|
||||
-I$(TOP)/include \
|
||||
-I$(TOP)/include/GL/internal \
|
||||
-I$(TOP)/src/mesa/glapi \
|
||||
-I$(TOP)/src/mesa/drivers/dri/common \
|
||||
-I$(TOP)/src/egl/main \
|
||||
-I$(TOP)/src/glx/x11
|
||||
|
||||
SOURCES = egl_xdri.c
|
||||
|
||||
OBJECTS = $(SOURCES:.c=.o)
|
||||
|
||||
DRM_LIB = `pkg-config --libs libdrm`
|
||||
|
||||
|
||||
.c.o:
|
||||
$(CC) -c $(INCLUDE_DIRS) $(CFLAGS) $< -o $@
|
||||
|
||||
|
||||
.PHONY: library
|
||||
|
||||
|
||||
default: depend library Makefile
|
||||
|
||||
|
||||
library: $(TOP)/$(LIB_DIR)/$(DRIVER_NAME)
|
||||
|
||||
|
||||
# Make the egl_xdri.so library
|
||||
$(TOP)/$(LIB_DIR)/$(DRIVER_NAME): $(OBJECTS)
|
||||
$(TOP)/bin/mklib -o $(DRIVER_NAME) \
|
||||
-noprefix \
|
||||
-major 1 -minor 0 \
|
||||
-install $(TOP)/$(LIB_DIR) \
|
||||
-ldl $(OBJECTS) $(DRM_LIB)
|
||||
|
||||
|
||||
clean:
|
||||
rm -f *.o
|
||||
rm -f *.so
|
||||
rm -f depend depend.bak
|
||||
|
||||
|
||||
depend: $(SOURCES) $(HEADERS)
|
||||
@ echo "running $(MKDEP)"
|
||||
@ rm -f depend
|
||||
@ touch depend
|
||||
$(MKDEP) $(MKDEP_OPTIONS) $(DEFINES) $(INCLUDE_DIRS) \
|
||||
$(SOURCES) $(HEADERS) >/dev/null 2>/dev/null
|
||||
|
||||
include depend
|
||||
# DO NOT DELETE
|
||||
833
src/egl/drivers/xdri/egl_xdri.c
Normal file
833
src/egl/drivers/xdri/egl_xdri.c
Normal file
|
|
@ -0,0 +1,833 @@
|
|||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* 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, sub license, 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 NON-INFRINGEMENT.
|
||||
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS 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.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
|
||||
/**
|
||||
* Code to interface a DRI driver to libEGL.
|
||||
* Note that unlike previous DRI/EGL interfaces, this one is meant to
|
||||
* be used _with_ X. Applications will use eglCreateWindowSurface()
|
||||
* to render into X-created windows.
|
||||
*
|
||||
* This is an EGL driver that, in turn, loads a regular DRI driver.
|
||||
* There are some dependencies on code in libGL, but those coudl be
|
||||
* removed with some effort.
|
||||
*
|
||||
* Authors: Brian Paul
|
||||
*/
|
||||
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include "dlfcn.h"
|
||||
#include <X11/Xlib.h>
|
||||
#include <GL/gl.h>
|
||||
#include "xf86dri.h"
|
||||
#include "glxclient.h"
|
||||
#include "dri_util.h"
|
||||
#include "drm_sarea.h"
|
||||
|
||||
#define _EGL_PLATFORM_X
|
||||
|
||||
#include "eglconfig.h"
|
||||
#include "eglcontext.h"
|
||||
#include "egldisplay.h"
|
||||
#include "egldriver.h"
|
||||
#include "eglglobals.h"
|
||||
#include "eglhash.h"
|
||||
#include "egllog.h"
|
||||
#include "eglsurface.h"
|
||||
|
||||
|
||||
|
||||
#define CALLOC_STRUCT(T) (struct T *) calloc(1, sizeof(struct T))
|
||||
|
||||
|
||||
/** subclass of _EGLDriver */
|
||||
struct xdri_egl_driver
|
||||
{
|
||||
_EGLDriver Base; /**< base class */
|
||||
|
||||
const char *dri_driver_name; /**< name of DRI driver to load */
|
||||
void *dri_driver_handle; /**< returned by dlopen(dri_driver_name) */
|
||||
|
||||
int chipset;
|
||||
int minor;
|
||||
int drmFD;
|
||||
|
||||
__DRIscreen driScreen;
|
||||
__DRIframebuffer framebuffer;
|
||||
drm_handle_t hSAREA;
|
||||
drmAddress pSAREA;
|
||||
char *busID;
|
||||
drm_magic_t magic;
|
||||
};
|
||||
|
||||
|
||||
/** subclass of _EGLContext */
|
||||
struct xdri_egl_context
|
||||
{
|
||||
_EGLContext Base; /**< base class */
|
||||
|
||||
__DRIcontext driContext;
|
||||
};
|
||||
|
||||
|
||||
/** subclass of _EGLSurface */
|
||||
struct xdri_egl_surface
|
||||
{
|
||||
_EGLSurface Base; /**< base class */
|
||||
|
||||
__DRIid driDrawable; /**< DRI surface */
|
||||
drm_drawable_t hDrawable;
|
||||
};
|
||||
|
||||
|
||||
/** subclass of _EGLConfig */
|
||||
struct xdri_egl_config
|
||||
{
|
||||
_EGLConfig Base; /**< base class */
|
||||
|
||||
const __GLcontextModes *mode; /**< corresponding GLX mode */
|
||||
};
|
||||
|
||||
|
||||
/** cast wrapper */
|
||||
static struct xdri_egl_driver *
|
||||
xdri_egl_driver(_EGLDriver *drv)
|
||||
{
|
||||
return (struct xdri_egl_driver *) drv;
|
||||
}
|
||||
|
||||
|
||||
/** Map EGLSurface handle to xdri_egl_surface object */
|
||||
static struct xdri_egl_surface *
|
||||
lookup_surface(EGLSurface surf)
|
||||
{
|
||||
_EGLSurface *surface = _eglLookupSurface(surf);
|
||||
return (struct xdri_egl_surface *) surface;
|
||||
}
|
||||
|
||||
|
||||
/** Map EGLContext handle to xdri_egl_context object */
|
||||
static struct xdri_egl_context *
|
||||
lookup_context(EGLContext c)
|
||||
{
|
||||
_EGLContext *context = _eglLookupContext(c);
|
||||
return (struct xdri_egl_context *) context;
|
||||
}
|
||||
|
||||
|
||||
/** Map EGLConfig handle to xdri_egl_config object */
|
||||
static struct xdri_egl_config *
|
||||
lookup_config(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config)
|
||||
{
|
||||
_EGLConfig *conf = _eglLookupConfig(drv, dpy, config);
|
||||
return (struct xdri_egl_config *) conf;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Produce a set of EGL configs.
|
||||
* Note that we get the list of GLcontextModes from the GLX library.
|
||||
* This dependency on GLX lib will be removed someday.
|
||||
*/
|
||||
static void
|
||||
create_configs(_EGLDisplay *disp)
|
||||
{
|
||||
const __GLcontextModes *m;
|
||||
__GLXdisplayPrivate *priv = __glXInitialize(disp->Xdpy);
|
||||
__GLXscreenConfigs *scrn = priv->screenConfigs;
|
||||
int id = 1;
|
||||
|
||||
for (m = scrn->configs; m; m = m->next) {
|
||||
/* EGL requires double-buffered configs */
|
||||
if (m->doubleBufferMode) {
|
||||
struct xdri_egl_config *config = CALLOC_STRUCT(xdri_egl_config);
|
||||
|
||||
_eglInitConfig(&config->Base, id++);
|
||||
|
||||
SET_CONFIG_ATTRIB(&config->Base, EGL_BUFFER_SIZE, m->rgbBits);
|
||||
SET_CONFIG_ATTRIB(&config->Base, EGL_RED_SIZE, m->redBits);
|
||||
SET_CONFIG_ATTRIB(&config->Base, EGL_GREEN_SIZE, m->greenBits);
|
||||
SET_CONFIG_ATTRIB(&config->Base, EGL_BLUE_SIZE, m->blueBits);
|
||||
SET_CONFIG_ATTRIB(&config->Base, EGL_ALPHA_SIZE, m->alphaBits);
|
||||
SET_CONFIG_ATTRIB(&config->Base, EGL_DEPTH_SIZE, m->depthBits);
|
||||
SET_CONFIG_ATTRIB(&config->Base, EGL_STENCIL_SIZE, m->stencilBits);
|
||||
SET_CONFIG_ATTRIB(&config->Base, EGL_NATIVE_VISUAL_ID, m->visualID);
|
||||
SET_CONFIG_ATTRIB(&config->Base, EGL_NATIVE_VISUAL_TYPE, m->visualType);
|
||||
/* XXX possibly other things to init... */
|
||||
|
||||
/* Ptr from EGL config to GLcontextMode. Used in CreateContext(). */
|
||||
config->mode = m;
|
||||
|
||||
_eglAddConfig(disp, &config->Base);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called via __DRIinterfaceMethods object
|
||||
*/
|
||||
static __DRIfuncPtr
|
||||
dri_get_proc_address(const char * proc_name)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
dri_context_modes_destroy(__GLcontextModes *modes)
|
||||
{
|
||||
_eglLog(_EGL_DEBUG, "%s", __FUNCTION__);
|
||||
|
||||
while (modes) {
|
||||
__GLcontextModes * const next = modes->next;
|
||||
free(modes);
|
||||
modes = next;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a linked list of 'count' GLcontextModes.
|
||||
* These are used during the client/server visual negotiation phase,
|
||||
* then discarded.
|
||||
*/
|
||||
static __GLcontextModes *
|
||||
dri_context_modes_create(unsigned count, size_t minimum_size)
|
||||
{
|
||||
/* This code copied from libGLX, and modified */
|
||||
const size_t size = (minimum_size > sizeof(__GLcontextModes))
|
||||
? minimum_size : sizeof(__GLcontextModes);
|
||||
__GLcontextModes * head = NULL;
|
||||
__GLcontextModes ** next;
|
||||
unsigned i;
|
||||
|
||||
next = & head;
|
||||
for (i = 0 ; i < count ; i++) {
|
||||
*next = (__GLcontextModes *) calloc(1, size);
|
||||
if (*next == NULL) {
|
||||
dri_context_modes_destroy(head);
|
||||
head = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
(*next)->doubleBufferMode = 1;
|
||||
(*next)->visualID = GLX_DONT_CARE;
|
||||
(*next)->visualType = GLX_DONT_CARE;
|
||||
(*next)->visualRating = GLX_NONE;
|
||||
(*next)->transparentPixel = GLX_NONE;
|
||||
(*next)->transparentRed = GLX_DONT_CARE;
|
||||
(*next)->transparentGreen = GLX_DONT_CARE;
|
||||
(*next)->transparentBlue = GLX_DONT_CARE;
|
||||
(*next)->transparentAlpha = GLX_DONT_CARE;
|
||||
(*next)->transparentIndex = GLX_DONT_CARE;
|
||||
(*next)->xRenderable = GLX_DONT_CARE;
|
||||
(*next)->fbconfigID = GLX_DONT_CARE;
|
||||
(*next)->swapMethod = GLX_SWAP_UNDEFINED_OML;
|
||||
(*next)->bindToTextureRgb = GLX_DONT_CARE;
|
||||
(*next)->bindToTextureRgba = GLX_DONT_CARE;
|
||||
(*next)->bindToMipmapTexture = GLX_DONT_CARE;
|
||||
(*next)->bindToTextureTargets = 0;
|
||||
(*next)->yInverted = GLX_DONT_CARE;
|
||||
|
||||
next = & ((*next)->next);
|
||||
}
|
||||
|
||||
return head;
|
||||
}
|
||||
|
||||
|
||||
static __DRIscreen *
|
||||
dri_find_dri_screen(__DRInativeDisplay *ndpy, int scrn)
|
||||
{
|
||||
/* unused? */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static GLboolean
|
||||
dri_window_exists(__DRInativeDisplay *dpy, __DRIid draw)
|
||||
{
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
static GLboolean
|
||||
dri_create_context(__DRInativeDisplay *dpy, int screenNum, int configID,
|
||||
void * contextID, drm_context_t * hw_context)
|
||||
{
|
||||
assert(configID >= 0);
|
||||
return XF86DRICreateContextWithConfig(dpy, screenNum,
|
||||
configID, contextID, hw_context);
|
||||
}
|
||||
|
||||
|
||||
static GLboolean
|
||||
dri_destroy_context(__DRInativeDisplay * ndpy, int screen, __DRIid context)
|
||||
{
|
||||
return XF86DRIDestroyContext(ndpy, screen, context);
|
||||
}
|
||||
|
||||
|
||||
static GLboolean
|
||||
dri_create_drawable(__DRInativeDisplay * ndpy, int screen,
|
||||
__DRIid drawable, drm_drawable_t * hHWDrawable)
|
||||
{
|
||||
_eglLog(_EGL_DEBUG, "XDRI: %s", __FUNCTION__);
|
||||
|
||||
/* Create DRI drawable for given window ID (drawable) */
|
||||
if (!XF86DRICreateDrawable(ndpy, screen, drawable, hHWDrawable))
|
||||
return EGL_FALSE;
|
||||
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
static GLboolean
|
||||
dri_destroy_drawable(__DRInativeDisplay * ndpy, int screen, __DRIid drawable)
|
||||
{
|
||||
_eglLog(_EGL_DEBUG, "XDRI: %s", __FUNCTION__);
|
||||
return XF86DRIDestroyDrawable(ndpy, screen, drawable);
|
||||
}
|
||||
|
||||
|
||||
static GLboolean
|
||||
dri_get_drawable_info(__DRInativeDisplay *dpy, int scrn,
|
||||
__DRIid draw, unsigned int * index, unsigned int * stamp,
|
||||
int * x, int * y, int * width, int * height,
|
||||
int * numClipRects, drm_clip_rect_t ** pClipRects,
|
||||
int * backX, int * backY,
|
||||
int * numBackClipRects,
|
||||
drm_clip_rect_t ** pBackClipRects)
|
||||
{
|
||||
_eglLog(_EGL_DEBUG, "XDRI: %s", __FUNCTION__);
|
||||
|
||||
if (!XF86DRIGetDrawableInfo(dpy, scrn, draw, index, stamp,
|
||||
x, y, width, height,
|
||||
numClipRects, pClipRects,
|
||||
backX, backY,
|
||||
numBackClipRects, pBackClipRects)) {
|
||||
return EGL_FALSE;
|
||||
}
|
||||
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Table of functions exported by the loader to the driver.
|
||||
*/
|
||||
static const __DRIinterfaceMethods interface_methods = {
|
||||
dri_get_proc_address,
|
||||
|
||||
dri_context_modes_create,
|
||||
dri_context_modes_destroy,
|
||||
|
||||
dri_find_dri_screen,
|
||||
dri_window_exists,
|
||||
|
||||
dri_create_context,
|
||||
dri_destroy_context,
|
||||
|
||||
dri_create_drawable,
|
||||
dri_destroy_drawable,
|
||||
dri_get_drawable_info,
|
||||
|
||||
NULL,/*__eglGetUST,*/
|
||||
NULL,/*__eglGetMSCRate,*/
|
||||
};
|
||||
|
||||
|
||||
|
||||
static EGLBoolean
|
||||
init_drm(struct xdri_egl_driver *xdri_drv, _EGLDisplay *disp)
|
||||
{
|
||||
static const char createNewScreenName[] = "__driCreateNewScreen_20050727";
|
||||
PFNCREATENEWSCREENFUNC createNewScreen;
|
||||
int api_ver = 0;/*__glXGetInternalVersion();*/
|
||||
__DRIversion ddx_version;
|
||||
__DRIversion dri_version;
|
||||
__DRIversion drm_version;
|
||||
drmVersionPtr version;
|
||||
drm_handle_t hFB;
|
||||
int newlyopened;
|
||||
int status;
|
||||
__GLcontextModes *modes;
|
||||
int scrn = DefaultScreen(disp->Xdpy);
|
||||
|
||||
createNewScreen = (PFNCREATENEWSCREENFUNC)
|
||||
dlsym(xdri_drv->dri_driver_handle, createNewScreenName);
|
||||
if (!createNewScreen) {
|
||||
_eglLog(_EGL_WARNING, "XDRI: Couldn't find %s function in the driver.",
|
||||
createNewScreenName);
|
||||
return EGL_FALSE;
|
||||
}
|
||||
else {
|
||||
_eglLog(_EGL_DEBUG, "XDRI: Found %s", createNewScreenName);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the DRI X extension version.
|
||||
*/
|
||||
dri_version.major = 4;
|
||||
dri_version.minor = 0;
|
||||
dri_version.patch = 0;
|
||||
|
||||
|
||||
if (!XF86DRIOpenConnection(disp->Xdpy, scrn,
|
||||
&xdri_drv->hSAREA, &xdri_drv->busID)) {
|
||||
_eglLog(_EGL_WARNING, "XF86DRIOpenConnection failed");
|
||||
}
|
||||
|
||||
xdri_drv->drmFD = drmOpenOnce(NULL, xdri_drv->busID, &newlyopened);
|
||||
if (xdri_drv->drmFD < 0) {
|
||||
perror("drmOpenOnce failed: ");
|
||||
return EGL_FALSE;
|
||||
}
|
||||
else {
|
||||
_eglLog(_EGL_DEBUG, "XDRI: drmOpenOnce returned %d", xdri_drv->drmFD);
|
||||
}
|
||||
|
||||
|
||||
if (drmGetMagic(xdri_drv->drmFD, &xdri_drv->magic)) {
|
||||
perror("drmGetMagic failed: ");
|
||||
return EGL_FALSE;
|
||||
}
|
||||
|
||||
version = drmGetVersion(xdri_drv->drmFD);
|
||||
if (version) {
|
||||
drm_version.major = version->version_major;
|
||||
drm_version.minor = version->version_minor;
|
||||
drm_version.patch = version->version_patchlevel;
|
||||
drmFreeVersion(version);
|
||||
_eglLog(_EGL_DEBUG, "XDRI: Got DRM version %d.%d.%d",
|
||||
drm_version.major,
|
||||
drm_version.minor,
|
||||
drm_version.patch);
|
||||
}
|
||||
else {
|
||||
drm_version.major = -1;
|
||||
drm_version.minor = -1;
|
||||
drm_version.patch = -1;
|
||||
_eglLog(_EGL_WARNING, "XDRI: drmGetVersion() failed");
|
||||
return EGL_FALSE;
|
||||
}
|
||||
|
||||
/* Authenticate w/ server.
|
||||
*/
|
||||
if (!XF86DRIAuthConnection(disp->Xdpy, scrn, xdri_drv->magic)) {
|
||||
_eglLog(_EGL_WARNING, "XDRI: XF86DRIAuthConnection() failed");
|
||||
return EGL_FALSE;
|
||||
}
|
||||
else {
|
||||
_eglLog(_EGL_DEBUG, "XDRI: XF86DRIAuthConnection() success");
|
||||
}
|
||||
|
||||
/* Get ddx version.
|
||||
*/
|
||||
{
|
||||
char *driverName;
|
||||
|
||||
/*
|
||||
* Get device name (like "tdfx") and the ddx version
|
||||
* numbers. We'll check the version in each DRI driver's
|
||||
* "createNewScreen" function.
|
||||
*/
|
||||
if (!XF86DRIGetClientDriverName(disp->Xdpy, scrn,
|
||||
&ddx_version.major,
|
||||
&ddx_version.minor,
|
||||
&ddx_version.patch,
|
||||
&driverName)) {
|
||||
_eglLog(_EGL_WARNING, "XDRI: XF86DRIGetClientDriverName failed");
|
||||
return EGL_FALSE;
|
||||
}
|
||||
else {
|
||||
_eglLog(_EGL_DEBUG, "XDRI: XF86DRIGetClientDriverName returned %s", driverName);
|
||||
}
|
||||
}
|
||||
|
||||
/* Get framebuffer info.
|
||||
*/
|
||||
{
|
||||
int junk;
|
||||
if (!XF86DRIGetDeviceInfo(disp->Xdpy, scrn,
|
||||
&hFB,
|
||||
&junk,
|
||||
&xdri_drv->framebuffer.size,
|
||||
&xdri_drv->framebuffer.stride,
|
||||
&xdri_drv->framebuffer.dev_priv_size,
|
||||
&xdri_drv->framebuffer.dev_priv)) {
|
||||
_eglLog(_EGL_WARNING, "XDRI: XF86DRIGetDeviceInfo() failed");
|
||||
return EGL_FALSE;
|
||||
}
|
||||
else {
|
||||
_eglLog(_EGL_DEBUG, "XDRI: XF86DRIGetDeviceInfo() success");
|
||||
}
|
||||
xdri_drv->framebuffer.width = DisplayWidth(disp->Xdpy, scrn);
|
||||
xdri_drv->framebuffer.height = DisplayHeight(disp->Xdpy, scrn);
|
||||
}
|
||||
|
||||
/* Map the framebuffer region. (this may not be needed)
|
||||
*/
|
||||
status = drmMap(xdri_drv->drmFD, hFB, xdri_drv->framebuffer.size,
|
||||
(drmAddressPtr) &xdri_drv->framebuffer.base);
|
||||
if (status != 0) {
|
||||
_eglLog(_EGL_WARNING, "XDRI: drmMap(framebuffer) failed");
|
||||
return EGL_FALSE;
|
||||
}
|
||||
else {
|
||||
_eglLog(_EGL_DEBUG, "XDRI: drmMap(framebuffer) success");
|
||||
}
|
||||
|
||||
/* Map the SAREA region.
|
||||
*/
|
||||
status = drmMap(xdri_drv->drmFD, xdri_drv->hSAREA, SAREA_MAX, &xdri_drv->pSAREA);
|
||||
if (status != 0) {
|
||||
_eglLog(_EGL_WARNING, "XDRI: drmMap(sarea) failed");
|
||||
return EGL_FALSE;
|
||||
}
|
||||
else {
|
||||
_eglLog(_EGL_DEBUG, "XDRI: drmMap(sarea) success");
|
||||
}
|
||||
|
||||
/* Create the DRI screen.
|
||||
*/
|
||||
xdri_drv->driScreen.private = createNewScreen(disp->Xdpy,
|
||||
scrn, /* screen number */
|
||||
&xdri_drv->driScreen,
|
||||
NULL, /* visuals */
|
||||
&ddx_version,
|
||||
&dri_version,
|
||||
&drm_version,
|
||||
&xdri_drv->framebuffer,
|
||||
xdri_drv->pSAREA,
|
||||
xdri_drv->drmFD,
|
||||
api_ver,
|
||||
&interface_methods,
|
||||
&modes);
|
||||
if (!xdri_drv->driScreen.private) {
|
||||
_eglLog(_EGL_WARNING, "XDRI: create new screen failed");
|
||||
return EGL_FALSE;
|
||||
}
|
||||
else {
|
||||
_eglLog(_EGL_DEBUG, "XDRI: create new screen success");
|
||||
}
|
||||
|
||||
create_configs(disp);
|
||||
|
||||
/* print modes / debug */
|
||||
if (0) {
|
||||
__GLcontextModes *m;
|
||||
|
||||
for (m = modes; m; m = m->next) {
|
||||
_eglLog(_EGL_DEBUG,
|
||||
"mode ID 0x%x rgba %d %d %d %d z %d s %d db %d\n", m->visualID,
|
||||
m->redBits, m->greenBits, m->blueBits, m->alphaBits,
|
||||
m->depthBits, m->stencilBits, m->doubleBufferMode);
|
||||
}
|
||||
}
|
||||
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
static EGLBoolean
|
||||
load_dri_driver(struct xdri_egl_driver *xdri_drv)
|
||||
{
|
||||
char filename[100];
|
||||
int flags = RTLD_NOW;
|
||||
|
||||
snprintf(filename, sizeof(filename), "%s.so", xdri_drv->dri_driver_name);
|
||||
_eglLog(_EGL_DEBUG, "XDRI: dlopen(%s)", filename);
|
||||
|
||||
xdri_drv->dri_driver_handle = dlopen(filename, flags);
|
||||
if (!xdri_drv->dri_driver_handle) {
|
||||
_eglLog(_EGL_WARNING, "XDRI Could not open %s (%s)",
|
||||
filename, dlerror());
|
||||
|
||||
return EGL_FALSE;
|
||||
}
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called via eglInitialize(), xdri_drv->API.Initialize().
|
||||
*/
|
||||
static EGLBoolean
|
||||
xdri_eglInitialize(_EGLDriver *drv, EGLDisplay dpy,
|
||||
EGLint *minor, EGLint *major)
|
||||
{
|
||||
struct xdri_egl_driver *xdri_drv = xdri_egl_driver(drv);
|
||||
_EGLDisplay *disp = _eglLookupDisplay(dpy);
|
||||
static char name[100];
|
||||
|
||||
_eglLog(_EGL_DEBUG, "XDRI: eglInitialize");
|
||||
|
||||
if (!disp->Xdpy) {
|
||||
disp->Xdpy = XOpenDisplay(NULL);
|
||||
if (!disp->Xdpy) {
|
||||
_eglLog(_EGL_WARNING, "XDRI: XOpenDisplay failed");
|
||||
return EGL_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* choose the DRI driver to load */
|
||||
xdri_drv->dri_driver_name = _eglChooseDRMDriver(0);
|
||||
if (!load_dri_driver(xdri_drv))
|
||||
return EGL_FALSE;
|
||||
|
||||
if (!init_drm(xdri_drv, disp))
|
||||
return EGL_FALSE;
|
||||
|
||||
xdri_drv->Base.Initialized = EGL_TRUE;
|
||||
|
||||
snprintf(name, sizeof(name), "X/DRI:%s", xdri_drv->dri_driver_name);
|
||||
xdri_drv->Base.Name = name;
|
||||
|
||||
/* we're supporting EGL 1.4 */
|
||||
*minor = 1;
|
||||
*major = 4;
|
||||
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called via eglTerminate(), drv->API.Terminate().
|
||||
*/
|
||||
static EGLBoolean
|
||||
xdri_eglTerminate(_EGLDriver *drv, EGLDisplay dpy)
|
||||
{
|
||||
struct xdri_egl_driver *xdri_drv = xdri_egl_driver(drv);
|
||||
|
||||
_eglLog(_EGL_DEBUG, "XDRI: eglTerminate");
|
||||
|
||||
_eglLog(_EGL_DEBUG, "XDRI: Closing %s", xdri_drv->dri_driver_name);
|
||||
dlclose(xdri_drv->dri_driver_handle);
|
||||
xdri_drv->dri_driver_handle = NULL;
|
||||
|
||||
free((void*) xdri_drv->dri_driver_name);
|
||||
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called via eglCreateContext(), drv->API.CreateContext().
|
||||
*/
|
||||
static EGLContext
|
||||
xdri_eglCreateContext(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config,
|
||||
EGLContext share_list, const EGLint *attrib_list)
|
||||
{
|
||||
struct xdri_egl_driver *xdri_drv = xdri_egl_driver(drv);
|
||||
_EGLDisplay *disp = _eglLookupDisplay(dpy);
|
||||
struct xdri_egl_config *xdri_config = lookup_config(drv, dpy, config);
|
||||
void *shared = NULL;
|
||||
int renderType = GLX_RGBA_BIT;
|
||||
|
||||
struct xdri_egl_context *xdri_ctx = CALLOC_STRUCT(xdri_egl_context);
|
||||
if (!xdri_ctx)
|
||||
return EGL_NO_CONTEXT;
|
||||
|
||||
if (!_eglInitContext(drv, dpy, &xdri_ctx->Base, config, attrib_list)) {
|
||||
free(xdri_ctx);
|
||||
return EGL_NO_CONTEXT;
|
||||
}
|
||||
|
||||
assert(xdri_config);
|
||||
|
||||
xdri_ctx->driContext.private =
|
||||
xdri_drv->driScreen.createNewContext(disp->Xdpy,
|
||||
xdri_config->mode, renderType,
|
||||
shared, &xdri_ctx->driContext);
|
||||
if (!xdri_ctx->driContext.private) {
|
||||
free(xdri_ctx);
|
||||
return EGL_NO_CONTEXT;
|
||||
}
|
||||
|
||||
xdri_ctx->driContext.mode = xdri_config->mode;
|
||||
|
||||
return _eglGetContextHandle(&xdri_ctx->Base);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called via eglMakeCurrent(), drv->API.MakeCurrent().
|
||||
*/
|
||||
static EGLBoolean
|
||||
xdri_eglMakeCurrent(_EGLDriver *drv, EGLDisplay dpy, EGLSurface d,
|
||||
EGLSurface r, EGLContext context)
|
||||
{
|
||||
_EGLDisplay *disp = _eglLookupDisplay(dpy);
|
||||
struct xdri_egl_context *xdri_ctx = lookup_context(context);
|
||||
struct xdri_egl_surface *xdri_draw = lookup_surface(d);
|
||||
struct xdri_egl_surface *xdri_read = lookup_surface(r);
|
||||
__DRIid draw = xdri_draw->driDrawable;
|
||||
__DRIid read = xdri_read->driDrawable;
|
||||
int scrn = DefaultScreen(disp->Xdpy);
|
||||
|
||||
if (!_eglMakeCurrent(drv, dpy, d, r, context))
|
||||
return EGL_FALSE;
|
||||
|
||||
|
||||
if (!xdri_ctx->driContext.bindContext(disp->Xdpy, scrn, draw, read,
|
||||
&xdri_ctx->driContext)) {
|
||||
return EGL_FALSE;
|
||||
}
|
||||
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called via eglCreateWindowSurface(), drv->API.CreateWindowSurface().
|
||||
*/
|
||||
static EGLSurface
|
||||
xdri_eglCreateWindowSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config,
|
||||
NativeWindowType window, const EGLint *attrib_list)
|
||||
{
|
||||
_EGLDisplay *disp = _eglLookupDisplay(dpy);
|
||||
struct xdri_egl_surface *xdri_surf;
|
||||
int scrn = DefaultScreen(disp->Xdpy);
|
||||
|
||||
xdri_surf = CALLOC_STRUCT(xdri_egl_surface);
|
||||
if (!xdri_surf)
|
||||
return EGL_NO_SURFACE;
|
||||
|
||||
if (!_eglInitSurface(drv, dpy, &xdri_surf->Base, EGL_WINDOW_BIT,
|
||||
config, attrib_list)) {
|
||||
free(xdri_surf);
|
||||
return EGL_FALSE;
|
||||
}
|
||||
|
||||
if (!XF86DRICreateDrawable(disp->Xdpy, scrn, window, &xdri_surf->hDrawable)) {
|
||||
free(xdri_surf);
|
||||
return EGL_FALSE;
|
||||
}
|
||||
|
||||
xdri_surf->driDrawable = window;
|
||||
|
||||
_eglSaveSurface(&xdri_surf->Base);
|
||||
|
||||
_eglLog(_EGL_DEBUG,
|
||||
"XDRI: CreateWindowSurface win 0x%x handle %d hDrawable %d",
|
||||
(int) window, _eglGetSurfaceHandle(&xdri_surf->Base),
|
||||
(int) xdri_surf->hDrawable);
|
||||
|
||||
return _eglGetSurfaceHandle(&xdri_surf->Base);
|
||||
}
|
||||
|
||||
|
||||
static EGLBoolean
|
||||
xdri_eglDestroySurface(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface)
|
||||
{
|
||||
struct xdri_egl_surface *xdri_surf = lookup_surface(surface);
|
||||
if (xdri_surf) {
|
||||
_eglHashRemove(_eglGlobal.Surfaces, (EGLuint) surface);
|
||||
if (xdri_surf->Base.IsBound) {
|
||||
xdri_surf->Base.DeletePending = EGL_TRUE;
|
||||
}
|
||||
else {
|
||||
/*
|
||||
st_unreference_framebuffer(&surf->Framebuffer);
|
||||
*/
|
||||
free(xdri_surf);
|
||||
}
|
||||
return EGL_TRUE;
|
||||
}
|
||||
else {
|
||||
_eglError(EGL_BAD_SURFACE, "eglDestroySurface");
|
||||
return EGL_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static EGLBoolean
|
||||
xdri_eglSwapBuffers(_EGLDriver *drv, EGLDisplay dpy, EGLSurface draw)
|
||||
{
|
||||
_EGLDisplay *disp = _eglLookupDisplay(dpy);
|
||||
|
||||
_eglLog(_EGL_DEBUG, "XDRI: EGL SwapBuffers");
|
||||
|
||||
/* error checking step: */
|
||||
if (!_eglSwapBuffers(drv, dpy, draw))
|
||||
return EGL_FALSE;
|
||||
|
||||
{
|
||||
struct xdri_egl_surface *xdri_surf = lookup_surface(draw);
|
||||
__GLXdisplayPrivate *priv = __glXInitialize(disp->Xdpy);
|
||||
__GLXscreenConfigs *scrn = priv->screenConfigs;
|
||||
__DRIscreen *psc = &scrn->driScreen;
|
||||
__DRIdrawable * const pdraw = psc->getDrawable(disp->Xdpy,
|
||||
xdri_surf->driDrawable,
|
||||
psc->private);
|
||||
|
||||
if (pdraw)
|
||||
pdraw->swapBuffers(disp->Xdpy, pdraw->private);
|
||||
else
|
||||
_eglLog(_EGL_WARNING, "pdraw is null in SwapBuffers");
|
||||
}
|
||||
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This is the main entrypoint into the driver, called by libEGL.
|
||||
* Create a new _EGLDriver object and init its dispatch table.
|
||||
*/
|
||||
_EGLDriver *
|
||||
_eglMain(_EGLDisplay *disp, const char *args)
|
||||
{
|
||||
struct xdri_egl_driver *xdri_drv = CALLOC_STRUCT(xdri_egl_driver);
|
||||
if (!xdri_drv)
|
||||
return NULL;
|
||||
|
||||
_eglInitDriverFallbacks(&xdri_drv->Base);
|
||||
xdri_drv->Base.API.Initialize = xdri_eglInitialize;
|
||||
xdri_drv->Base.API.Terminate = xdri_eglTerminate;
|
||||
|
||||
xdri_drv->Base.API.CreateContext = xdri_eglCreateContext;
|
||||
xdri_drv->Base.API.MakeCurrent = xdri_eglMakeCurrent;
|
||||
xdri_drv->Base.API.CreateWindowSurface = xdri_eglCreateWindowSurface;
|
||||
xdri_drv->Base.API.DestroySurface = xdri_eglDestroySurface;
|
||||
xdri_drv->Base.API.SwapBuffers = xdri_eglSwapBuffers;
|
||||
|
||||
xdri_drv->Base.ClientAPIsMask = EGL_OPENGL_BIT /*| EGL_OPENGL_ES_BIT*/;
|
||||
xdri_drv->Base.Name = "X/DRI";
|
||||
|
||||
_eglLog(_EGL_DEBUG, "XDRI: main(%s)", args);
|
||||
|
||||
return &xdri_drv->Base;
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue