Add EXA winsys for gallium pipe driver interface.

Plug in the EXA framework into the pipe driver
for surface_copy & surface_fill.

Back pixmaps with drmBO's including the front buffer.
This commit is contained in:
Alan Hourihane 2008-06-26 22:27:44 +01:00
parent 0e1aa03708
commit ccd0c76472
3 changed files with 596 additions and 346 deletions

View File

@ -40,7 +40,6 @@
#include "xf86Resources.h"
#include "mipointer.h"
#include "micmap.h"
#include "shadowfb.h"
#include <X11/extensions/randr.h>
#include "fb.h"
#include "edid.h"
@ -50,7 +49,6 @@
#include "dixstruct.h"
#include "xf86xv.h"
#include <X11/extensions/Xv.h>
#include "shadow.h"
#include <xorg-server.h>
#if XSERVER_LIBPCIACCESS
#include <pciaccess.h>
@ -120,15 +118,11 @@ static PciChipsets PciDevices[] = {
typedef enum
{
OPTION_NOACCEL,
OPTION_SW_CURSOR,
OPTION_SHADOWFB,
} modesettingOpts;
static const OptionInfoRec Options[] = {
{OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN, {0}, FALSE},
{OPTION_SW_CURSOR, "SWcursor", OPTV_BOOLEAN, {0}, FALSE},
{OPTION_SHADOWFB, "ShadowFB", OPTV_BOOLEAN, {0}, FALSE},
{-1, NULL, OPTV_NONE, {0}, FALSE}
};
@ -154,12 +148,6 @@ static const char *ddcSymbols[] = {
NULL
};
static const char *shadowSymbols[] = {
"shadowInit",
"shadowUpdatePackedWeak",
NULL
};
static const char *i2cSymbols[] = {
"xf86CreateI2CBusRec",
"xf86I2CBusInit",
@ -200,7 +188,7 @@ Setup(pointer module, pointer opts, int *errmaj, int *errmin)
* Tell the loader about symbols from other modules that this module
* might refer to.
*/
LoaderRefSymLists(exaSymbols, fbSymbols, shadowSymbols, ddcSymbols, NULL);
LoaderRefSymLists(exaSymbols, fbSymbols, ddcSymbols, NULL);
/*
* The return value must be non-NULL on success even though there
@ -323,7 +311,6 @@ Probe(DriverPtr drv, int flags)
if (numUsed > 0)
foundScreen = TRUE;
} else {
ErrorF("NUMUSED %d\n", numUsed);
for (i = 0; i < numUsed; i++) {
ScrnInfoPtr pScrn = NULL;
@ -419,36 +406,6 @@ ProbeDDC(ScrnInfoPtr pScrn, int index)
ConfiguredMonitor = NULL;
}
static Bool
MapMem(ScrnInfoPtr pScrn)
{
modesettingPtr ms = modesettingPTR(pScrn);
drmBOMap(ms->fd,
&ms->bo, DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE, 0, &ms->virtual);
ms->virtual = ms->bo.virtual;
return TRUE;
}
static Bool
UnmapMem(ScrnInfoPtr pScrn)
{
modesettingPtr ms = modesettingPTR(pScrn);
drmBOUnmap(ms->fd, &ms->bo);
return TRUE;
}
static void
LoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices,
LOCO * colors, VisualPtr pVisual)
{
xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
}
static Bool
CreateFrontBuffer(ScrnInfoPtr pScrn)
{
@ -456,18 +413,15 @@ CreateFrontBuffer(ScrnInfoPtr pScrn)
ScreenPtr pScreen = pScrn->pScreen;
PixmapPtr rootPixmap = pScreen->GetScreenPixmap(pScreen);
Bool fbAccessDisabled;
CARD8 *fbstart;
int flags;
drmBOCreate(ms->fd,
pScrn->virtualY * pScrn->displayWidth *
pScrn->bitsPerPixel / 8, 0, NULL,
DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE | DRM_BO_FLAG_SHAREABLE
| DRM_BO_FLAG_CACHED_MAPPED
| DRM_BO_FLAG_NO_EVICT | DRM_BO_FLAG_MAPPABLE |
/*DRM_BO_FLAG_MEM_VRAM |*/ DRM_BO_FLAG_MEM_TT,
0, &ms->bo);
MapMem(pScrn);
ms->noEvict = TRUE;
pScreen->ModifyPixmapHeader(rootPixmap,
pScrn->virtualX, pScrn->virtualY,
pScrn->depth, pScrn->bitsPerPixel,
pScrn->displayWidth * pScrn->bitsPerPixel / 8,
NULL);
ms->noEvict = FALSE;
drmModeAddFB(ms->fd,
pScrn->virtualX,
@ -475,50 +429,12 @@ CreateFrontBuffer(ScrnInfoPtr pScrn)
pScrn->depth,
pScrn->bitsPerPixel,
pScrn->displayWidth * pScrn->bitsPerPixel / 8,
ms->bo.handle, &ms->fb_id);
if (ms->shadowFB) {
if ((ms->shadowMem =
shadowAlloc(pScrn->displayWidth, pScrn->virtualY,
pScrn->bitsPerPixel)) == NULL) {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"Allocation of shadow memory failed\n");
return FALSE;
}
fbstart = ms->shadowMem;
} else {
fbstart = ms->bo.virtual;
}
/*
* If we are in a fb disabled state, the virtual address of the root
* pixmap should always be NULL, and it will be overwritten later
* if we try to set it to something.
*
* Therefore, set it to NULL, and modify the backup copy instead.
*/
fbAccessDisabled = (rootPixmap->devPrivate.ptr == NULL);
pScreen->ModifyPixmapHeader(rootPixmap,
pScrn->virtualX, pScrn->virtualY,
pScrn->depth, pScrn->bitsPerPixel,
pScrn->displayWidth * pScrn->bitsPerPixel / 8,
fbstart);
if (fbAccessDisabled) {
pScrn->pixmapPrivate.ptr = fbstart;
rootPixmap->devPrivate.ptr = NULL;
}
driGetPixmapHandle(rootPixmap, &flags), &ms->fb_id);
pScrn->frameX0 = 0;
pScrn->frameY0 = 0;
AdjustFrame(pScrn->scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
UnmapMem(pScrn);
ms->front = TRUE;
return TRUE;
}
@ -538,22 +454,12 @@ crtc_resize(ScrnInfoPtr pScrn, int width, int height)
pScrn->virtualX = width;
pScrn->virtualY = height;
pScrn->displayWidth = (pScrn->virtualX + 63) & ~63;
if (ms->shadowMem) {
xfree(ms->shadowMem);
ms->shadowMem = NULL;
}
/* HW dependent - FIXME */
pScrn->displayWidth = pScrn->virtualX;
drmModeRmFB(ms->fd, ms->fb_id);
/* move old buffer out of the way */
drmBOSetStatus(ms->fd, &ms->bo, 0, 0, 0, 0, 0);
/* unreference it */
drmBOUnreference(ms->fd, &ms->bo);
ms->front = FALSE;
/* now create new frontbuffer */
return CreateFrontBuffer(pScrn);
}
@ -571,7 +477,6 @@ PreInit(ScrnInfoPtr pScrn, int flags)
rgb defaultWeight = { 0, 0, 0 };
EntityInfoPtr pEnt;
EntPtr msEnt = NULL;
int flags24;
char *BusID;
int i;
char *s;
@ -645,13 +550,12 @@ PreInit(ScrnInfoPtr pScrn, int flags)
pScrn->progClock = TRUE;
pScrn->rgbBits = 8;
flags24 = Support32bppFb | PreferConvert24to32 | SupportConvert24to32;
if (!xf86SetDepthBpp(pScrn, 0, 0, 0, flags24))
if (!xf86SetDepthBpp
(pScrn, 0, 0, 0,
PreferConvert24to32 | SupportConvert24to32 | Support32bppFb))
return FALSE;
switch (pScrn->depth) {
case 8:
case 15:
case 16:
case 24:
@ -684,23 +588,10 @@ PreInit(ScrnInfoPtr pScrn, int flags)
max_height = 8192;
xf86CrtcSetSizeRange(pScrn, 320, 200, max_width, max_height);
if (xf86ReturnOptValBool(ms->Options, OPTION_NOACCEL, FALSE)) {
ms->noAccel = TRUE;
}
if (xf86ReturnOptValBool(ms->Options, OPTION_SW_CURSOR, FALSE)) {
ms->SWCursor = TRUE;
}
if (xf86ReturnOptValBool(ms->Options, OPTION_SHADOWFB, FALSE)) {
if (!xf86LoadSubModule(pScrn, "shadow"))
return FALSE;
xf86LoaderReqSymLists(shadowSymbols, NULL);
ms->shadowFB = TRUE;
}
SaveHWState(pScrn);
crtc_init(pScrn);
@ -767,42 +658,37 @@ RestoreHWState(ScrnInfoPtr pScrn)
return TRUE;
}
static void *
WindowLinear(ScreenPtr pScreen, CARD32 row, CARD32 offset, int mode,
CARD32 * size, void *closure)
{
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
modesettingPtr ms = modesettingPTR(pScrn);
if (!pScrn->vtSema)
return NULL;
*size = pScrn->displayWidth * pScrn->bitsPerPixel / 8;
return ((CARD8 *) ms->bo.virtual + row * (*size) + offset);
}
static Bool
CreateScreenResources(ScreenPtr pScreen)
{
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
modesettingPtr ms = modesettingPTR(pScrn);
PixmapPtr rootPixmap = pScreen->GetScreenPixmap(pScreen);
PixmapPtr rootPixmap;
Bool ret;
int flags;
ms->noEvict = TRUE;
pScreen->CreateScreenResources = ms->createScreenResources;
ret = pScreen->CreateScreenResources(pScreen);
pScreen->CreateScreenResources = CreateScreenResources;
if (ms->shadowFB)
shadowAdd(pScreen, rootPixmap,
ms->update, WindowLinear, 0, 0);
rootPixmap = pScreen->GetScreenPixmap(pScreen);
if (!pScreen->ModifyPixmapHeader(pScreen->GetScreenPixmap(pScreen),
-1, -1, -1, -1, -1,
ms->shadowFB ? (pointer)ms->shadowMem : (pointer)ms->bo.virtual))
if (!pScreen->ModifyPixmapHeader(rootPixmap, -1, -1, -1, -1, -1, NULL))
FatalError("Couldn't adjust screen pixmap\n");
ms->noEvict = FALSE;
drmModeAddFB(ms->fd,
pScrn->virtualX,
pScrn->virtualY,
pScrn->depth,
pScrn->bitsPerPixel,
pScrn->displayWidth * pScrn->bitsPerPixel / 8,
driGetPixmapHandle(rootPixmap, &flags), &ms->fb_id);
AdjustFrame(pScrn->scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
return ret;
}
@ -816,33 +702,33 @@ ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
unsigned long sys_mem;
int c;
MessageType from;
CARD8 *fbstart;
/* deal with server regeneration */
if (ms->fd < 0) {
char *BusID;
char *BusID;
BusID = xalloc(64);
sprintf(BusID, "PCI:%d:%d:%d",
BusID = xalloc(64);
sprintf(BusID, "PCI:%d:%d:%d",
#if XSERVER_LIBPCIACCESS
((ms->PciInfo->domain << 8) | ms->PciInfo->bus),
ms->PciInfo->dev, ms->PciInfo->func
((ms->PciInfo->domain << 8) | ms->PciInfo->bus),
ms->PciInfo->dev, ms->PciInfo->func
#else
((pciConfigPtr) ms->PciInfo->thisCard)->busnum,
((pciConfigPtr) ms->PciInfo->thisCard)->devnum,
((pciConfigPtr) ms->PciInfo->thisCard)->funcnum
((pciConfigPtr) ms->PciInfo->thisCard)->busnum,
((pciConfigPtr) ms->PciInfo->thisCard)->devnum,
((pciConfigPtr) ms->PciInfo->thisCard)->funcnum
#endif
);
);
ms->fd = drmOpen(NULL, BusID);
ms->fd = drmOpen(NULL, BusID);
if (ms->fd < 0)
if (ms->fd < 0)
return FALSE;
}
pScrn->pScreen = pScreen;
pScrn->displayWidth = (pScrn->virtualX + 63) & ~63;
/* HW dependent - FIXME */
pScrn->displayWidth = pScrn->virtualX;
miClearVisualTypes();
@ -857,39 +743,7 @@ ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
pScrn->memPhysBase = 0;
pScrn->fbOffset = 0;
drmBOCreate(ms->fd,
pScrn->virtualY * pScrn->displayWidth *
pScrn->bitsPerPixel / 8, 0, NULL,
DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE | DRM_BO_FLAG_SHAREABLE
| DRM_BO_FLAG_CACHED_MAPPED
| DRM_BO_FLAG_NO_EVICT | DRM_BO_FLAG_MAPPABLE |
/*DRM_BO_FLAG_MEM_VRAM |*/ DRM_BO_FLAG_MEM_TT,
0, &ms->bo);
MapMem(pScrn);
drmModeAddFB(ms->fd,
pScrn->virtualX,
pScrn->virtualY,
pScrn->depth,
pScrn->bitsPerPixel,
pScrn->displayWidth * pScrn->bitsPerPixel / 8,
ms->bo.handle, &ms->fb_id);
if (ms->shadowFB) {
if ((ms->shadowMem =
shadowAlloc(pScrn->displayWidth, pScrn->virtualY,
pScrn->bitsPerPixel)) == NULL) {
xf86DrvMsg(scrnIndex, X_ERROR,
"Allocation of shadow memory failed\n");
return FALSE;
}
fbstart = ms->shadowMem;
} else {
fbstart = ms->bo.virtual;
}
if (!fbScreenInit(pScreen, fbstart,
if (!fbScreenInit(pScreen, NULL,
pScrn->virtualX, pScrn->virtualY,
pScrn->xDpi, pScrn->yDpi,
pScrn->displayWidth, pScrn->bitsPerPixel))
@ -911,26 +765,13 @@ ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
}
fbPictureInit(pScreen, NULL, 0);
if (ms->shadowFB) {
ms->update = shadowUpdatePackedWeak();
if (!shadowSetup(pScreen)) {
xf86DrvMsg(scrnIndex, X_ERROR,
"Shadow framebuffer initialization failed.\n");
return FALSE;
}
}
ms->createScreenResources = pScreen->CreateScreenResources;
pScreen->CreateScreenResources = CreateScreenResources;
xf86SetBlackWhitePixels(pScreen);
#if 0
glucoseScreenInit(pScreen, 0);
#endif
#if 1
ms->pExa = ExaInit(pScrn);
#endif
ms->exa = ExaInit(pScrn);
miInitializeBackingStore(pScreen);
xf86SetBackingStore(pScreen);
@ -939,9 +780,9 @@ ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
/* Need to extend HWcursor support to handle mask interleave */
if (!ms->SWCursor)
xf86_cursors_init (pScreen, 64, 64,
HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_64 |
HARDWARE_CURSOR_ARGB);
xf86_cursors_init(pScreen, 64, 64,
HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_64 |
HARDWARE_CURSOR_ARGB);
/* Must force it before EnterVT, so we are in control of VT and
* later memory should be bound when allocating, e.g rotate_mem */
@ -957,20 +798,8 @@ ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
if (!miCreateDefColormap(pScreen))
return FALSE;
#if 0
if (!xf86HandleColormaps(pScreen, 256, 8, LoadPalette, NULL,
CMAP_RELOAD_ON_MODE_SWITCH |
CMAP_PALETTED_TRUECOLOR)) {
return FALSE;
}
#endif
xf86DPMSInit(pScreen, xf86DPMSSet, 0);
#if 0
glucoseInitVideo(pScreen);
#endif
if (serverGeneration == 1)
xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
@ -978,11 +807,7 @@ ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
driScreenInit(pScreen);
#endif
UnmapMem(pScrn);
ms->front = TRUE;
return EnterVT(scrnIndex, 0);
return EnterVT(scrnIndex, 1);
}
static void
@ -1018,7 +843,7 @@ LeaveVT(int scrnIndex, int flags)
for (o = 0; o < config->num_crtc; o++) {
xf86CrtcPtr crtc = config->crtc[o];
cursor_destroy(crtc);
cursor_destroy(crtc);
if (crtc->rotatedPixmap || crtc->rotatedData) {
crtc->funcs->shadow_destroy(crtc, crtc->rotatedPixmap,
@ -1030,12 +855,6 @@ LeaveVT(int scrnIndex, int flags)
drmModeRmFB(ms->fd, ms->fb_id);
/* move old buffer out of the way */
drmBOSetStatus(ms->fd, &ms->bo, 0, 0, 0, 0, 0);
drmBOUnreference(ms->fd, &ms->bo);
ms->front = FALSE;
RestoreHWState(pScrn);
#if 0
@ -1078,14 +897,12 @@ EnterVT(int scrnIndex, int flags)
SaveHWState(pScrn);
}
if (!ms->front)
if (!flags) /* signals startup as we'll do this in CreateScreenResources */
CreateFrontBuffer(pScrn);
if (!xf86SetDesiredModes(pScrn))
return FALSE;
AdjustFrame(pScrn->scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
return TRUE;
}
@ -1104,25 +921,19 @@ CloseScreen(int scrnIndex, ScreenPtr pScreen)
modesettingPtr ms = modesettingPTR(pScrn);
if (pScrn->vtSema) {
LeaveVT(scrnIndex, 0);
LeaveVT(scrnIndex, 0);
#if 0
drmMMUnlock(ms->fd, DRM_BO_MEM_VRAM, 1);
drmMMUnlock(ms->fd, DRM_BO_MEM_TT, 1);
drmMMUnlock(ms->fd, DRM_BO_MEM_VRAM, 1);
drmMMUnlock(ms->fd, DRM_BO_MEM_TT, 1);
#endif
}
#ifdef DRI2
driCloseScreen(pScreen);
#endif
pScreen->CreateScreenResources = ms->createScreenResources;
if (ms->shadowMem) {
xfree(ms->shadowMem);
ms->shadowMem = NULL;
}
if (ms->pExa)
if (ms->exa)
ExaClose(pScrn);
drmClose(ms->fd);

View File

@ -32,7 +32,6 @@
#include <xf86drm.h>
#include <xf86drmMode.h>
#include <xf86mm.h>
#include "shadow.h"
#include "exa.h"
#define DRV_ERROR(msg) xf86DrvMsg(pScrn->scrnIndex, X_ERROR, msg);
@ -49,14 +48,9 @@ typedef struct _modesettingRec
{
int fd;
unsigned int fb_id;
void *virtual;
drmBO bo;
Bool front;
EntPtr entityPrivate;
void (*PointerMoved) (int, int, int);
int Chipset;
EntityInfoPtr pEnt;
#if XSERVER_LIBPCIACCESS
@ -75,15 +69,12 @@ typedef struct _modesettingRec
unsigned int SaveGeneration;
/* shadowfb */
CARD8 *shadowMem;
Bool shadowFB;
CreateScreenResourcesProcPtr createScreenResources;
ShadowUpdateProc update;
/* exa */
ExaDriverPtr pExa;
drmBO exa_bo;
void *exa;
void *driver;
Bool noEvict;
/* dri2 */
drm_context_t context;

View File

@ -31,19 +31,329 @@
#include "config.h"
#endif
/* FIXME ! */
#define DRI_DRIVER_PATH "/ISO/X.Org/modular/i386/lib/dri"
#include "xf86.h"
#include "xf86_OSproc.h"
#include "driver.h"
#include <dlfcn.h>
struct PixmapPriv {
drmBO bo;
#if 0
dri_fence *fence;
#endif
int flags;
#include "pipe/p_winsys.h"
#include "pipe/p_format.h"
#include "pipe/p_context.h"
#include "pipe/p_util.h"
#include "pipe/p_state.h"
#include "pipe/p_inlines.h"
/* EXA winsys */
struct exa_context
{
};
struct exa_winsys
{
struct pipe_winsys base;
modesettingPtr ms;
};
struct exa_buffer
{
struct pipe_buffer base;
drmBO bo;
boolean userBuffer; /** Is this a user-space buffer? */
//void *data;
//void *mapped;
};
struct exa_surface
{
struct pipe_surface surface;
};
struct exa_entity
{
ExaDriverPtr pExa;
struct exa_context *c;
struct pipe_winsys *ws;
struct pipe_context *ctx;
struct pipe_screen *scrn;
};
static INLINE struct exa_winsys *
exa_get_winsys(struct pipe_winsys *ws)
{
return (struct exa_winsys *)ws;
}
static INLINE struct exa_surface *
exa_get_surface(struct pipe_surface *ps)
{
return (struct exa_surface *)ps;
}
static INLINE struct exa_buffer *
exa_get_buffer(struct pipe_buffer *buf)
{
return (struct exa_buffer *)buf;
}
static void *
exa_buffer_map(struct pipe_winsys *pws, struct pipe_buffer *buf,
unsigned flags)
{
struct exa_buffer *exa_buf = exa_get_buffer(buf);
struct exa_winsys *exa_winsys = exa_get_winsys(pws);
void *virtual;
drmBOMap(exa_winsys->ms->fd,
&exa_buf->bo, DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE, 0, &virtual);
return virtual;
}
static void
exa_buffer_unmap(struct pipe_winsys *pws, struct pipe_buffer *buf)
{
struct exa_buffer *exa_buf = exa_get_buffer(buf);
struct exa_winsys *exa_winsys = exa_get_winsys(pws);
drmBOUnmap(exa_winsys->ms->fd, &exa_buf->bo);
}
static void
exa_buffer_destroy(struct pipe_winsys *pws, struct pipe_buffer *buf)
{
struct exa_winsys *exa_winsys = exa_get_winsys(pws);
struct exa_buffer *exa_buf = exa_get_buffer(buf);
drmBOUnreference(exa_winsys->ms->fd, &exa_buf->bo);
free(exa_buf);
}
static void
exa_flush_frontbuffer(struct pipe_winsys *pws,
struct pipe_surface *surf, void *context_private)
{
struct exa_buffer *exa_buf = exa_get_buffer(surf->buffer);
ErrorF("WANT TO FLUSH\n");
}
static const char *
exa_get_name(struct pipe_winsys *pws)
{
return "EXA";
}
static struct pipe_buffer *
exa_buffer_create(struct pipe_winsys *pws,
unsigned alignment, unsigned usage, unsigned size)
{
struct exa_buffer *buffer = xcalloc(1, sizeof(struct exa_buffer));
struct exa_winsys *exa_winsys = exa_get_winsys(pws);
unsigned int flags = 0;
buffer->base.refcount = 1;
buffer->base.alignment = alignment;
buffer->base.usage = usage;
buffer->base.size = size;
if (exa_winsys->ms->noEvict) {
flags = DRM_BO_FLAG_NO_EVICT;
ErrorF("DISPLAY TARGET\n");
}
ErrorF("SIZE %d %d\n", size, alignment);
if (!buffer->bo.handle) {
// buffer->data = align_malloc(size, alignment);
drmBOCreate(exa_winsys->ms->fd, size, 4096, NULL,
DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE |
DRM_BO_FLAG_SHAREABLE | DRM_BO_FLAG_MEM_TT |
DRM_BO_FLAG_MAPPABLE | DRM_BO_FLAG_CACHED_MAPPED | flags,
0, &buffer->bo);
}
return &buffer->base;
}
static struct pipe_buffer *
exa_user_buffer_create(struct pipe_winsys *pws, void *ptr, unsigned bytes)
{
struct exa_buffer *buffer = xcalloc(1, sizeof(struct exa_buffer));
buffer->base.refcount = 1;
buffer->base.size = bytes;
buffer->userBuffer = TRUE;
//buffer->data = ptr;
ErrorF("USERBUFFER\n");
return &buffer->base;
}
/**
* Round n up to next multiple.
*/
static INLINE unsigned
round_up(unsigned n, unsigned multiple)
{
return (n + multiple - 1) & ~(multiple - 1);
}
static int
exa_surface_alloc_storage(struct pipe_winsys *winsys,
struct pipe_surface *surf,
unsigned width, unsigned height,
enum pipe_format format,
unsigned flags, unsigned tex_usage)
{
const unsigned alignment = 64;
surf->width = width;
surf->height = height;
surf->format = format;
surf->cpp = pf_get_size(format);
surf->pitch = round_up(width, alignment / surf->cpp);
assert(!surf->buffer);
surf->buffer = winsys->buffer_create(winsys, alignment,
PIPE_BUFFER_USAGE_PIXEL,
surf->pitch * surf->cpp * height);
if (!surf->buffer)
return -1;
return 0;
}
/**
* Called via winsys->surface_alloc() to create new surfaces.
*/
static struct pipe_surface *
exa_surface_alloc(struct pipe_winsys *ws)
{
struct exa_surface *wms = xcalloc(1, sizeof(struct exa_surface));
assert(ws);
wms->surface.refcount = 1;
wms->surface.winsys = ws;
return &wms->surface;
}
static void
exa_surface_release(struct pipe_winsys *winsys, struct pipe_surface **s)
{
struct pipe_surface *surf = *s;
surf->refcount--;
if (surf->refcount == 0) {
if (surf->buffer)
pipe_buffer_reference(winsys, &surf->buffer, NULL);
free(surf);
}
*s = NULL;
}
/*
* Fence functions - basically nothing to do, as we don't create any actual
* fence objects.
*/
static void
exa_fence_reference(struct pipe_winsys *sws, struct pipe_fence_handle **ptr,
struct pipe_fence_handle *fence)
{
}
static int
exa_fence_signalled(struct pipe_winsys *sws, struct pipe_fence_handle *fence,
unsigned flag)
{
return 0;
}
static int
exa_fence_finish(struct pipe_winsys *sws, struct pipe_fence_handle *fence,
unsigned flag)
{
return 0;
}
struct pipe_winsys *
exa_get_pipe_winsys(modesettingPtr ms)
{
static struct exa_winsys *ws = NULL;
if (!ws) {
ws = xcalloc(1, sizeof(struct exa_winsys));
/* Fill in this struct with callbacks that pipe will need to
* communicate with the window system, buffer manager, etc.
*/
ws->base.buffer_create = exa_buffer_create;
ws->base.user_buffer_create = exa_user_buffer_create;
ws->base.buffer_map = exa_buffer_map;
ws->base.buffer_unmap = exa_buffer_unmap;
ws->base.buffer_destroy = exa_buffer_destroy;
ws->base.surface_alloc = exa_surface_alloc;
ws->base.surface_alloc_storage = exa_surface_alloc_storage;
ws->base.surface_release = exa_surface_release;
ws->base.fence_reference = exa_fence_reference;
ws->base.fence_signalled = exa_fence_signalled;
ws->base.fence_finish = exa_fence_finish;
ws->base.flush_frontbuffer = exa_flush_frontbuffer;
ws->base.get_name = exa_get_name;
ws->ms = ms;
}
return &ws->base;
}
/* EXA functions */
struct PixmapPriv
{
drmBO bo;
#if 0
dri_fence *fence;
#endif
int flags;
struct pipe_texture *tex;
unsigned int color;
struct pipe_surface *src_surf; /* for copies */
};
static enum pipe_format
exa_get_pipe_format(int depth)
{
switch (depth) {
case 32:
case 24:
return PIPE_FORMAT_A8R8G8B8_UNORM;
case 16:
return PIPE_FORMAT_R5G6B5_UNORM;
case 15:
return PIPE_FORMAT_A1R5G5B5_UNORM;
case 8:
case 4:
case 1:
return PIPE_FORMAT_A8R8G8B8_UNORM; /* bad bad bad */
default:
assert(0);
return 0;
}
}
/*
* EXA functions
*/
static void
ExaWaitMarker(ScreenPtr pScreen, int marker)
{
@ -62,6 +372,7 @@ ExaPrepareAccess(PixmapPtr pPix, int index)
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
modesettingPtr ms = modesettingPTR(pScrn);
PixmapPtr rootPixmap = pScreen->GetScreenPixmap(pScreen);
struct exa_entity *exa = ms->exa;
struct PixmapPriv *priv;
int ret;
@ -70,21 +381,20 @@ ExaPrepareAccess(PixmapPtr pPix, int index)
if (!priv)
return FALSE;
if (priv->bo.handle) {
void *virtual;
ret = drmBOMap(ms->fd,
&priv->bo, DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE, 0, &virtual);
if (ret) {
driUnlock(pScreen);
FatalError("Failed to map pixmap: %s\n", strerror(-ret));
return;
}
pPix->devPrivate.ptr = priv->bo.virtual;
if (!priv->tex)
return FALSE;
{
struct pipe_surface *surf =
exa->scrn->get_tex_surface(exa->scrn, priv->tex, 0, 0, 0,
PIPE_BUFFER_USAGE_CPU_READ |
PIPE_BUFFER_USAGE_CPU_WRITE);
pPix->devPrivate.ptr =
exa->scrn->surface_map(exa->scrn, surf,
PIPE_BUFFER_USAGE_CPU_READ |
PIPE_BUFFER_USAGE_CPU_WRITE);
exa->scrn->tex_surface_release(exa->scrn, &surf);
}
return TRUE;
}
@ -96,6 +406,7 @@ ExaFinishAccess(PixmapPtr pPix, int index)
modesettingPtr ms = modesettingPTR(pScrn);
PixmapPtr rootPixmap = pScreen->GetScreenPixmap(pScreen);
struct PixmapPriv *priv;
struct exa_entity *exa = ms->exa;
int ret;
priv = exaGetPixmapDriverPrivate(pPix);
@ -103,14 +414,15 @@ ExaFinishAccess(PixmapPtr pPix, int index)
if (!priv)
return;
if (priv->bo.handle) {
ret = drmBOUnmap(ms->fd, &priv->bo);
if (ret) {
driUnlock(pScreen);
FatalError("Failed to unmap pixmap: %s\n", strerror(-ret));
return;
}
if (!priv->tex)
return;
{
struct pipe_surface *surf =
exa->scrn->get_tex_surface(exa->scrn, priv->tex, 0, 0, 0,
PIPE_BUFFER_USAGE_CPU_READ |
PIPE_BUFFER_USAGE_CPU_WRITE);
exa->scrn->surface_unmap(exa->scrn, surf);
exa->scrn->tex_surface_release(exa->scrn, &surf);
pPix->devPrivate.ptr = NULL;
}
}
@ -119,6 +431,16 @@ static void
ExaDone(PixmapPtr pPixmap)
{
ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
modesettingPtr ms = modesettingPTR(pScrn);
struct PixmapPriv *priv = exaGetPixmapDriverPrivate(pPixmap);
struct exa_entity *exa = ms->exa;
if (!priv)
return;
if (priv->src_surf)
exa->scrn->tex_surface_release(exa->scrn, &priv->src_surf);
priv->src_surf = NULL;
}
static void
@ -131,23 +453,46 @@ static Bool
ExaPrepareSolid(PixmapPtr pPixmap, int alu, Pixel planeMask, Pixel fg)
{
ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
modesettingPtr ms = modesettingPTR(pScrn);
struct PixmapPriv *priv = exaGetPixmapDriverPrivate(pPixmap);
struct exa_entity *exa = ms->exa;
ErrorF("SOLID\n");
if (pPixmap->drawable.depth < 15)
return FALSE;
if (!EXA_PM_IS_SOLID(&pPixmap->drawable, planeMask))
return FALSE;
/* can't do depth 4 */
if (pPixmap->drawable.depth == 4)
if (!priv->tex)
return FALSE;
return FALSE;
if (alu != GXcopy)
return FALSE;
if (!exa->ctx || !exa->ctx->surface_fill)
return FALSE;
priv->color = fg;
return TRUE;
}
static void
ExaSolid(PixmapPtr pPixmap, int x1, int y1, int x2, int y2)
ExaSolid(PixmapPtr pPixmap, int x0, int y0, int x1, int y1)
{
ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
modesettingPtr ms = modesettingPTR(pScrn);
struct exa_entity *exa = ms->exa;
struct PixmapPriv *priv = exaGetPixmapDriverPrivate(pPixmap);
struct pipe_surface *surf =
exa->scrn->get_tex_surface(exa->scrn, priv->tex, 0, 0, 0,
PIPE_BUFFER_USAGE_GPU_READ |
PIPE_BUFFER_USAGE_GPU_WRITE);
exa->ctx->surface_fill(exa->ctx, surf, x0, y0, x1 - x0, y1 - y0,
priv->color);
exa->scrn->tex_surface_release(exa->scrn, &surf);
}
static Bool
@ -155,13 +500,31 @@ ExaPrepareCopy(PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap, int xdir,
int ydir, int alu, Pixel planeMask)
{
ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum];
modesettingPtr ms = modesettingPTR(pScrn);
struct exa_entity *exa = ms->exa;
struct pipe_surface *src_surf;
struct PixmapPriv *priv = exaGetPixmapDriverPrivate(pDstPixmap);
ErrorF("COPY\n");
/* can't do depth 4 */
if (pSrcPixmap->drawable.depth == 4 || pDstPixmap->drawable.depth == 4)
if (alu != GXcopy)
return FALSE;
if (pSrcPixmap->drawable.depth < 15 || pDstPixmap->drawable.depth < 15)
return FALSE;
if (!EXA_PM_IS_SOLID(&pSrcPixmap->drawable, planeMask))
return FALSE;
if (!priv->tex)
return FALSE;
if (!exa->ctx || !exa->ctx->surface_copy)
return FALSE;
priv->src_surf =
exa->scrn->get_tex_surface(exa->scrn, priv->tex, 0, 0, 0,
PIPE_BUFFER_USAGE_GPU_READ |
PIPE_BUFFER_USAGE_GPU_WRITE);
return FALSE;
}
@ -170,6 +533,17 @@ ExaCopy(PixmapPtr pDstPixmap, int srcX, int srcY, int dstX, int dstY,
int width, int height)
{
ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum];
modesettingPtr ms = modesettingPTR(pScrn);
struct exa_entity *exa = ms->exa;
struct PixmapPriv *priv = exaGetPixmapDriverPrivate(pDstPixmap);
struct pipe_surface *surf =
exa->scrn->get_tex_surface(exa->scrn, priv->tex, 0, 0, 0,
PIPE_BUFFER_USAGE_GPU_READ |
PIPE_BUFFER_USAGE_GPU_WRITE);
exa->ctx->surface_copy(exa->ctx, 0, surf, dstX, dstY, priv->src_surf,
srcX, srcY, width, height);
exa->scrn->tex_surface_release(exa->scrn, &surf);
}
static Bool
@ -225,37 +599,29 @@ ExaCreatePixmap(ScreenPtr pScreen, int size, int align)
priv = xcalloc(1, sizeof(struct PixmapPriv));
if (!priv)
return NULL;
if (size == 0)
return priv;
drmBOCreate(ms->fd, size, 4096, NULL,
DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE | DRM_BO_FLAG_SHAREABLE
| DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_MAPPABLE |
DRM_BO_FLAG_CACHED_MAPPED,
0, &priv->bo);
return NULL;
return priv;
}
static void
static void
ExaDestroyPixmap(ScreenPtr pScreen, void *dPriv)
{
struct PixmapPriv *priv = (struct PixmapPriv *)dPriv;
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
modesettingPtr ms = modesettingPTR(pScrn);
struct exa_entity *exa = ms->exa;
if (!priv)
return;
return;
if (priv->bo.handle)
drmBOUnreference(ms->fd, &priv->bo);
if (priv->tex)
exa->scrn->texture_release(exa->scrn, &priv->tex);
xfree(priv);
}
static Bool
static Bool
ExaPixmapIsOffscreen(PixmapPtr pPixmap)
{
struct PixmapPriv *priv;
@ -265,10 +631,10 @@ ExaPixmapIsOffscreen(PixmapPtr pPixmap)
priv = exaGetPixmapDriverPrivate(pPixmap);
if (!priv)
return FALSE;
return FALSE;
if (priv->bo.handle)
return TRUE;
if (priv->tex)
return TRUE;
return FALSE;
}
@ -281,87 +647,146 @@ driGetPixmapHandle(PixmapPtr pPixmap, unsigned int *flags)
PixmapPtr rootPixmap = pScreen->GetScreenPixmap(pScreen);
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
modesettingPtr ms = modesettingPTR(pScrn);
struct exa_entity *exa = ms->exa;
struct exa_buffer *exa_buf;
struct pipe_surface *surf;
struct PixmapPriv *priv;
*flags = 0;
if (rootPixmap == pPixmap)
return ms->bo.handle;
if (!ms->pExa)
return 0;
if (!ms->exa) {
FatalError("NO MS->EXA\n");
return 0;
}
priv = exaGetPixmapDriverPrivate(pPixmap);
if (!priv)
return 0;
if (!priv) {
FatalError("NO PIXMAP PRIVATE\n");
return 0;
}
if (priv->bo.handle)
return priv->bo.handle;
surf =
exa->scrn->get_tex_surface(exa->scrn, priv->tex, 0, 0, 0,
PIPE_BUFFER_USAGE_CPU_READ |
PIPE_BUFFER_USAGE_CPU_WRITE);
exa_buf = exa_get_buffer(surf->buffer);
exa->scrn->tex_surface_release(exa->scrn, &surf);
if (exa_buf->bo.handle)
return exa_buf->bo.handle;
return 0;
}
static Bool
static Bool
ExaModifyPixmapHeader(PixmapPtr pPixmap, int width, int height,
int depth, int bitsPerPixel, int devKind,
pointer pPixData)
{
ScreenPtr pScreen = pPixmap->drawable.pScreen;
ScreenPtr pScreen = pPixmap->drawable.pScreen;
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
struct PixmapPriv *priv = exaGetPixmapDriverPrivate(pPixmap);
modesettingPtr ms = modesettingPTR(pScrn);
PixmapPtr rootPixmap = pScreen->GetScreenPixmap(pScreen);
struct exa_entity *exa = ms->exa;
if (rootPixmap == pPixmap) {
/*if (rootPixmap == pPixmap) */ {
miModifyPixmapHeader(pPixmap, width, height, depth,
bitsPerPixel, devKind, NULL);
return TRUE;
}
return FALSE;
}
if (!priv)
return FALSE;
if (depth <= 0)
depth = pPixmap->drawable.depth;
if (bitsPerPixel <= 0)
bitsPerPixel = pPixmap->drawable.bitsPerPixel;
if (width <= 0)
width = pPixmap->drawable.width;
if (height <= 0)
height = pPixmap->drawable.height;
if (width <= 0 || height <= 0 || depth <= 0)
return FALSE;
/* Deal with screen resize */
if (priv->tex) {
struct pipe_surface *surf =
exa->scrn->get_tex_surface(exa->scrn, priv->tex, 0, 0, 0,
PIPE_BUFFER_USAGE_CPU_READ |
PIPE_BUFFER_USAGE_CPU_WRITE);
ErrorF("RESIZE %d %d to %d %d\n", surf->width, surf->height, width,
height);
if (surf->width != width || surf->height != height) {
exa->scrn->texture_release(exa->scrn, &priv->tex);
priv->tex = NULL;
}
exa->scrn->tex_surface_release(exa->scrn, &surf);
}
if (!priv->tex) {
struct pipe_texture template;
memset(&template, 0, sizeof(template));
template.target = PIPE_TEXTURE_2D;
template.compressed = 0;
template.format = exa_get_pipe_format(depth);
template.cpp = pf_get_size(template.format);
template.width[0] = width;
template.height[0] = height;
template.depth[0] = 1;
template.last_level = 0;
template.tex_usage = PIPE_TEXTURE_USAGE_RENDER_TARGET;
priv->tex = exa->scrn->texture_create(exa->scrn, &template);
}
if (rootPixmap == pPixmap)
return TRUE;
return TRUE;
}
void
ExaClose(ScrnInfoPtr pScrn)
{
modesettingPtr ms = modesettingPTR(pScrn);
struct exa_entity *exa = ms->exa;
exaDriverFini(pScrn->pScreen);
#if 0
drmBOUnreference(ms->fd, &ms->exa_bo);
#endif
dlclose(ms->driver);
}
ExaDriverPtr
void *
ExaInit(ScrnInfoPtr pScrn)
{
modesettingPtr ms = modesettingPTR(pScrn);
ExaDriverPtr pExa;
struct exa_entity *exa;
ExaDriverPtr pExa = exa->pExa;
exa = xcalloc(1, sizeof(struct exa_entity));
if (!exa)
return NULL;
pExa = exaDriverAlloc();
if (!pExa) {
goto out_err;
}
#if 0
/* Create a 256KB offscreen area */
drmBOCreate(ms->fd, 256 * 1024, 0, NULL,
DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE | DRM_BO_FLAG_MEM_TT,
DRM_BO_HINT_DONT_FENCE, &ms->exa_bo);
#endif
memset(pExa, 0, sizeof(*pExa));
pExa->exa_major = 2;
pExa->exa_minor = 4;
pExa->memoryBase = 0; /* ms->exa_bo.virtual; */
pExa->memorySize = 0; /* ms->exa_bo.size; */
pExa->memoryBase = 0;
pExa->memorySize = 0;
pExa->offScreenBase = 0;
pExa->pixmapOffsetAlign = 8;
pExa->pixmapPitchAlign = 32 * 4;
pExa->pixmapOffsetAlign = 0;
pExa->pixmapPitchAlign = 1;
pExa->flags = EXA_OFFSCREEN_PIXMAPS | EXA_HANDLES_PIXMAPS;
pExa->maxX = 8191; /* FIXME */
pExa->maxY = 8191; /* FIXME */
@ -389,7 +814,30 @@ ExaInit(ScrnInfoPtr pScrn)
goto out_err;
}
return pExa;
{
char filename[128];
char dri_driver_path[] = DRI_DRIVER_PATH;
snprintf(filename, sizeof filename,
"%s/%s_dri.so", dri_driver_path, "i915");
ms->driver = dlopen(filename, RTLD_NOW | RTLD_DEEPBIND | RTLD_GLOBAL);
exa->c = xcalloc(1, sizeof(struct exa_context));
exa->ws = exa_get_pipe_winsys(ms);
exa->scrn = softpipe_create_screen(exa->ws);
exa->ctx = softpipe_create(exa->scrn, exa->ws, NULL);
if (!exa->ctx)
ErrorF("BAD CTX\n");
exa->ctx->priv = exa->c;
}
return (void *)exa;
out_err:
ExaClose(pScrn);