1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
|
#include "nv_include.h"
#include "dri2.h"
struct nouveau_dri2_buffer {
PixmapPtr pPixmap;
};
DRI2BufferPtr
nouveau_dri2_create_buffers(DrawablePtr pDraw, unsigned int *attachments,
int count)
{
ScreenPtr pScreen = pDraw->pScreen;
DRI2BufferPtr dri2_bufs;
struct nouveau_dri2_buffer *nv_bufs;
PixmapPtr ppix, pzpix;
int i;
dri2_bufs = xcalloc(count, sizeof(*dri2_bufs));
if (!dri2_bufs)
return NULL;
nv_bufs = xcalloc(count, sizeof(*nv_bufs));
if (!nv_bufs) {
xfree(dri2_bufs);
return NULL;
}
pzpix = NULL;
for (i = 0; i < count; i++) {
if (attachments[i] == DRI2BufferFrontLeft) {
if (pDraw->type == DRAWABLE_PIXMAP) {
ppix = (PixmapPtr)pDraw;
} else {
WindowPtr pwin = (WindowPtr)pDraw;
ppix = pScreen->GetWindowPixmap(pwin);
}
ppix->refcnt++;
} else
if (attachments[i] == DRI2BufferStencil && pzpix) {
ppix = pzpix;
ppix->refcnt++;
} else {
ppix = pScreen->CreatePixmap(pScreen, pDraw->width,
pDraw->height,
pDraw->depth, 0);
}
if (attachments[i] == DRI2BufferDepth)
pzpix = ppix;
dri2_bufs[i].attachment = attachments[i];
dri2_bufs[i].pitch = ppix->devKind;
dri2_bufs[i].cpp = ppix->drawable.bitsPerPixel / 8;
dri2_bufs[i].driverPrivate = &nv_bufs[i];
dri2_bufs[i].flags = 0;
nv_bufs[i].pPixmap = ppix;
nouveau_bo_handle_get(nouveau_pixmap(ppix)->bo,
&dri2_bufs[i].name);
}
return dri2_bufs;
}
void
nouveau_dri2_destroy_buffers(DrawablePtr pDraw, DRI2BufferPtr buffers,
int count)
{
struct nouveau_dri2_buffer *nvbuf;
while (count--) {
nvbuf = buffers[count].driverPrivate;
pDraw->pScreen->DestroyPixmap(nvbuf->pPixmap);
}
if (buffers) {
xfree(buffers[0].driverPrivate);
xfree(buffers);
}
}
void
nouveau_dri2_copy_region(DrawablePtr pDraw, RegionPtr pRegion,
DRI2BufferPtr pDstBuffer, DRI2BufferPtr pSrcBuffer)
{
struct nouveau_dri2_buffer *nvbuf = pSrcBuffer->driverPrivate;
ScreenPtr pScreen = pDraw->pScreen;
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
NVPtr pNv = NVPTR(pScrn);
RegionPtr pCopyClip;
GCPtr pGC;
pGC = GetScratchGC(pDraw->depth, pScreen);
pCopyClip = REGION_CREATE(pScreen, NULL, 0);
REGION_COPY(pScreen, pCopyClip, pRegion);
pGC->funcs->ChangeClip(pGC, CT_REGION, pCopyClip, 0);
ValidateGC(pDraw, pGC);
pGC->ops->CopyArea(&nvbuf->pPixmap->drawable, pDraw, pGC, 0, 0,
pDraw->width, pDraw->height, 0, 0);
FreeScratchGC(pGC);
FIRE_RING(pNv->chan);
}
Bool
nouveau_dri2_init(ScreenPtr pScreen)
{
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
NVPtr pNv = NVPTR(pScrn);
DRI2InfoRec dri2;
dri2.version = 1;
dri2.fd = nouveau_device(pNv->dev)->fd;
dri2.driverName = "nouveau";
dri2.deviceName = "/dev/dri/card0";
dri2.CreateBuffers = nouveau_dri2_create_buffers;
dri2.DestroyBuffers = nouveau_dri2_destroy_buffers;
dri2.CopyRegion = nouveau_dri2_copy_region;
return DRI2ScreenInit(pScreen, &dri2);
}
void
nouveau_dri2_takedown(ScreenPtr pScreen)
{
DRI2CloseScreen(pScreen);
}
|