summaryrefslogtreecommitdiff
path: root/src/gallium/state_trackers/xorg
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/state_trackers/xorg')
-rw-r--r--src/gallium/state_trackers/xorg/xorg_dri2.c77
-rw-r--r--src/gallium/state_trackers/xorg/xorg_driver.c33
-rw-r--r--src/gallium/state_trackers/xorg/xorg_exa.c52
-rw-r--r--src/gallium/state_trackers/xorg/xorg_exa.h2
-rw-r--r--src/gallium/state_trackers/xorg/xorg_tracker.h9
5 files changed, 139 insertions, 34 deletions
diff --git a/src/gallium/state_trackers/xorg/xorg_dri2.c b/src/gallium/state_trackers/xorg/xorg_dri2.c
index ae3338ffef..3fbab4dc51 100644
--- a/src/gallium/state_trackers/xorg/xorg_dri2.c
+++ b/src/gallium/state_trackers/xorg/xorg_dri2.c
@@ -39,10 +39,13 @@
#include "pipe/p_state.h"
#include "pipe/p_inlines.h"
+#include "util/u_rect.h"
+
typedef struct {
PixmapPtr pPixmap;
struct pipe_texture *tex;
struct pipe_buffer *buf;
+ struct pipe_fence_handle *fence;
} *BufferPrivatePtr;
static DRI2BufferPtr
@@ -83,7 +86,6 @@ driCreateBuffers(DrawablePtr pDraw, unsigned int *attachments, int count)
pipe_texture_reference(&tex, depth);
} else if (attachments[i] == DRI2BufferDepth) {
struct pipe_texture template;
-
memset(&template, 0, sizeof(template));
template.target = PIPE_TEXTURE_2D;
template.format = PIPE_FORMAT_S8Z24_UNORM;
@@ -92,22 +94,20 @@ driCreateBuffers(DrawablePtr pDraw, unsigned int *attachments, int count)
template.height[0] = pDraw->height;
template.depth[0] = 1;
template.last_level = 0;
- template.tex_usage = PIPE_TEXTURE_USAGE_RENDER_TARGET;
+ template.tex_usage = PIPE_TEXTURE_USAGE_DEPTH_STENCIL;
tex = ms->screen->texture_create(ms->screen, &template);
+ depth = tex;
} else {
- struct pipe_texture template;
- memset(&template, 0, sizeof(template));
- template.target = PIPE_TEXTURE_2D;
- template.format = PIPE_FORMAT_A8R8G8B8_UNORM;
- pf_get_block(template.format, &template.block);
- template.width[0] = pDraw->width;
- template.height[0] = pDraw->height;
- template.depth[0] = 1;
- template.last_level = 0;
- template.tex_usage = PIPE_TEXTURE_USAGE_RENDER_TARGET;
- tex = ms->screen->texture_create(ms->screen, &template);
+ pPixmap = (*pScreen->CreatePixmap)(pScreen, pDraw->width,
+ pDraw->height,
+ pDraw->depth,
+ 0);
+ tex = xorg_exa_get_texture(pPixmap);
}
+ if (!tex)
+ FatalError("NO TEXTURE IN DRI2\n");
+
ms->api->buffer_from_texture(ms->api, tex, &buf, &stride);
ms->api->global_handle_from_buffer(ms->api, ms->screen, buf, &handle);
@@ -138,15 +138,17 @@ driDestroyBuffers(DrawablePtr pDraw, DRI2BufferPtr buffers, int count)
modesettingPtr ms = modesettingPTR(pScrn);
BufferPrivatePtr private;
int i;
+ (void)ms;
for (i = 0; i < count; i++) {
private = buffers[i].driverPrivate;
- if (private->pPixmap)
- (*pScreen->DestroyPixmap)(private->pPixmap);
-
pipe_texture_reference(&private->tex, NULL);
pipe_buffer_reference(&private->buf, NULL);
+ ms->screen->fence_reference(ms->screen, &private->fence, NULL);
+
+ if (private->pPixmap)
+ (*pScreen->DestroyPixmap)(private->pPixmap);
}
if (buffers) {
@@ -164,19 +166,42 @@ driCopyRegion(DrawablePtr pDraw, RegionPtr pRegion,
modesettingPtr ms = modesettingPTR(pScrn);
BufferPrivatePtr dst_priv = pDestBuffer->driverPrivate;
BufferPrivatePtr src_priv = pSrcBuffer->driverPrivate;
+ PixmapPtr src_pixmap;
+ PixmapPtr dst_pixmap;
+ GCPtr gc;
+ RegionPtr copy_clip;
+
+ src_pixmap = src_priv->pPixmap;
+ dst_pixmap = dst_priv->pPixmap;
+ if (pSrcBuffer->attachment == DRI2BufferFrontLeft)
+ src_pixmap = (PixmapPtr)pDraw;
+ if (pDestBuffer->attachment == DRI2BufferFrontLeft)
+ dst_pixmap = (PixmapPtr)pDraw;
+ gc = GetScratchGC(pDraw->depth, pScreen);
+ copy_clip = REGION_CREATE(pScreen, NULL, 0);
+ REGION_COPY(pScreen, copy_clip, pRegion);
+ (*gc->funcs->ChangeClip) (gc, CT_REGION, copy_clip, 0);
+ ValidateGC(&dst_pixmap->drawable, gc);
+
+ /* If this is a full buffer swap, throttle on the previous one */
+ if (dst_priv->fence && REGION_NUM_RECTS(pRegion) == 1) {
+ BoxPtr extents = REGION_EXTENTS(pScreen, pRegion);
+
+ if (extents->x1 == 0 && extents->y1 == 0 &&
+ extents->x2 == pDraw->width && extents->y2 == pDraw->height) {
+ ms->screen->fence_finish(ms->screen, dst_priv->fence, 0);
+ ms->screen->fence_reference(ms->screen, &dst_priv->fence, NULL);
+ }
+ }
- struct pipe_surface *dst_surf =
- ms->screen->get_tex_surface(ms->screen, dst_priv->tex, 0, 0, 0,
- PIPE_BUFFER_USAGE_GPU_WRITE);
- struct pipe_surface *src_surf =
- ms->screen->get_tex_surface(ms->screen, src_priv->tex, 0, 0, 0,
- PIPE_BUFFER_USAGE_GPU_READ);
+ (*gc->ops->CopyArea)(&src_pixmap->drawable, &dst_pixmap->drawable, gc,
+ 0, 0, pDraw->width, pDraw->height, 0, 0);
- ms->ctx->surface_copy(ms->ctx, dst_surf, 0, 0, src_surf,
- 0, 0, pDraw->width, pDraw->height);
+ FreeScratchGC(gc);
- pipe_surface_reference(&dst_surf, NULL);
- pipe_surface_reference(&src_surf, NULL);
+ ms->ctx->flush(ms->ctx, PIPE_FLUSH_SWAPBUFFERS,
+ pDestBuffer->attachment == DRI2BufferFrontLeft ?
+ &dst_priv->fence : NULL);
}
Bool
diff --git a/src/gallium/state_trackers/xorg/xorg_driver.c b/src/gallium/state_trackers/xorg/xorg_driver.c
index e01e5294b1..53d1a33095 100644
--- a/src/gallium/state_trackers/xorg/xorg_driver.c
+++ b/src/gallium/state_trackers/xorg/xorg_driver.c
@@ -179,8 +179,10 @@ CreateFrontBuffer(ScrnInfoPtr pScrn)
modesettingPtr ms = modesettingPTR(pScrn);
ScreenPtr pScreen = pScrn->pScreen;
PixmapPtr rootPixmap = pScreen->GetScreenPixmap(pScreen);
+ unsigned handle, stride;
ms->noEvict = TRUE;
+ xorg_exa_set_displayed_usage(rootPixmap);
pScreen->ModifyPixmapHeader(rootPixmap,
pScrn->virtualX, pScrn->virtualY,
pScrn->depth, pScrn->bitsPerPixel,
@@ -188,13 +190,16 @@ CreateFrontBuffer(ScrnInfoPtr pScrn)
NULL);
ms->noEvict = FALSE;
+ handle = xorg_exa_get_pixmap_handle(rootPixmap, &stride);
+
drmModeAddFB(ms->fd,
pScrn->virtualX,
pScrn->virtualY,
pScrn->depth,
pScrn->bitsPerPixel,
- pScrn->displayWidth * pScrn->bitsPerPixel / 8,
- xorg_exa_get_pixmap_handle(rootPixmap), &ms->fb_id);
+ stride,
+ handle,
+ &ms->fb_id);
pScrn->frameX0 = 0;
pScrn->frameY0 = 0;
@@ -426,6 +431,7 @@ CreateScreenResources(ScreenPtr pScreen)
modesettingPtr ms = modesettingPTR(pScrn);
PixmapPtr rootPixmap;
Bool ret;
+ unsigned handle, stride;
ms->noEvict = TRUE;
@@ -435,18 +441,22 @@ CreateScreenResources(ScreenPtr pScreen)
rootPixmap = pScreen->GetScreenPixmap(pScreen);
+ xorg_exa_set_displayed_usage(rootPixmap);
if (!pScreen->ModifyPixmapHeader(rootPixmap, -1, -1, -1, -1, -1, NULL))
FatalError("Couldn't adjust screen pixmap\n");
ms->noEvict = FALSE;
+ handle = xorg_exa_get_pixmap_handle(rootPixmap, &stride);
+
drmModeAddFB(ms->fd,
pScrn->virtualX,
pScrn->virtualY,
pScrn->depth,
pScrn->bitsPerPixel,
- pScrn->displayWidth * pScrn->bitsPerPixel / 8,
- xorg_exa_get_pixmap_handle(rootPixmap), &ms->fb_id);
+ stride,
+ handle,
+ &ms->fb_id);
AdjustFrame(pScrn->scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
@@ -623,6 +633,10 @@ LeaveVT(int scrnIndex, int flags)
RestoreHWState(pScrn);
+ if (drmDropMaster(ms->fd))
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "drmDropMaster failed: %s\n", strerror(errno));
+
pScrn->vtSema = FALSE;
}
@@ -635,6 +649,17 @@ EnterVT(int scrnIndex, int flags)
ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
modesettingPtr ms = modesettingPTR(pScrn);
+ if (drmSetMaster(ms->fd)) {
+ if (errno == EINVAL) {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "drmSetMaster failed: 2.6.29 or newer kernel required for "
+ "multi-server DRI\n");
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "drmSetMaster failed: %s\n", strerror(errno));
+ }
+ }
+
/*
* Only save state once per server generation since that's what most
* drivers do. Could change this to save state at each VT enter.
diff --git a/src/gallium/state_trackers/xorg/xorg_exa.c b/src/gallium/state_trackers/xorg/xorg_exa.c
index 2c4291aa4e..f2dac73e90 100644
--- a/src/gallium/state_trackers/xorg/xorg_exa.c
+++ b/src/gallium/state_trackers/xorg/xorg_exa.c
@@ -359,8 +359,48 @@ ExaPixmapIsOffscreen(PixmapPtr pPixmap)
return FALSE;
}
+int
+xorg_exa_set_displayed_usage(PixmapPtr pPixmap)
+{
+ struct exa_pixmap_priv *priv;
+ priv = exaGetPixmapDriverPrivate(pPixmap);
+
+ if (!priv) {
+ FatalError("NO PIXMAP PRIVATE\n");
+ return 0;
+ }
+
+ if (priv->flags & ~PIPE_TEXTURE_USAGE_PRIMARY) {
+ FatalError("BAD FLAGS\n");
+ return 0;
+ }
+ priv->flags = PIPE_TEXTURE_USAGE_PRIMARY;
+
+ return 0;
+}
+
+int
+xorg_exa_set_shared_usage(PixmapPtr pPixmap)
+{
+ struct exa_pixmap_priv *priv;
+ priv = exaGetPixmapDriverPrivate(pPixmap);
+
+ if (!priv) {
+ FatalError("NO PIXMAP PRIVATE\n");
+ return 0;
+ }
+
+ if (priv->flags & ~PIPE_TEXTURE_USAGE_DISPLAY_TARGET) {
+ FatalError("BAD FLAGS\n");
+ return 0;
+ }
+ priv->flags = PIPE_TEXTURE_USAGE_DISPLAY_TARGET;
+
+ return 0;
+}
+
unsigned
-xorg_exa_get_pixmap_handle(PixmapPtr pPixmap)
+xorg_exa_get_pixmap_handle(PixmapPtr pPixmap, unsigned *stride_out)
{
ScreenPtr pScreen = pPixmap->drawable.pScreen;
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
@@ -385,6 +425,9 @@ xorg_exa_get_pixmap_handle(PixmapPtr pPixmap)
ms->api->buffer_from_texture(ms->api, priv->tex, &buffer, &stride);
ms->api->handle_from_buffer(ms->api, ms->screen, buffer, &handle);
pipe_buffer_reference(&buffer, NULL);
+ if (stride_out)
+ *stride_out = stride;
+
return handle;
}
@@ -421,7 +464,9 @@ ExaModifyPixmapHeader(PixmapPtr pPixmap, int width, int height,
bitsPerPixel, devKind, NULL);
/* Deal with screen resize */
- if (priv->tex && (priv->tex->width[0] != width || priv->tex->height[0] != height)) {
+ if (priv->tex && (priv->tex->width[0] != width ||
+ priv->tex->height[0] != height ||
+ priv->tex_flags != priv->flags)) {
pipe_texture_reference(&priv->tex, NULL);
}
@@ -436,7 +481,8 @@ ExaModifyPixmapHeader(PixmapPtr pPixmap, int width, int height,
template.height[0] = height;
template.depth[0] = 1;
template.last_level = 0;
- template.tex_usage = PIPE_TEXTURE_USAGE_RENDER_TARGET;
+ template.tex_usage = PIPE_TEXTURE_USAGE_RENDER_TARGET | priv->flags;
+ priv->tex_flags = priv->flags;
priv->tex = exa->scrn->texture_create(exa->scrn, &template);
}
diff --git a/src/gallium/state_trackers/xorg/xorg_exa.h b/src/gallium/state_trackers/xorg/xorg_exa.h
index 650997aec6..f0508eb2d5 100644
--- a/src/gallium/state_trackers/xorg/xorg_exa.h
+++ b/src/gallium/state_trackers/xorg/xorg_exa.h
@@ -14,6 +14,8 @@ struct exa_context
struct exa_pixmap_priv
{
int flags;
+ int tex_flags;
+
struct pipe_texture *tex;
unsigned int color;
struct pipe_surface *src_surf; /* for copies */
diff --git a/src/gallium/state_trackers/xorg/xorg_tracker.h b/src/gallium/state_trackers/xorg/xorg_tracker.h
index b4742bdbf5..910782dbc4 100644
--- a/src/gallium/state_trackers/xorg/xorg_tracker.h
+++ b/src/gallium/state_trackers/xorg/xorg_tracker.h
@@ -31,6 +31,7 @@
#ifndef _XORG_TRACKER_H_
#define _XORG_TRACKER_H_
+#include <stddef.h>
#include <stdint.h>
#include <errno.h>
#include <drm.h>
@@ -98,7 +99,13 @@ struct pipe_texture *
xorg_exa_get_texture(PixmapPtr pPixmap);
unsigned
-xorg_exa_get_pixmap_handle(PixmapPtr pPixmap);
+xorg_exa_get_pixmap_handle(PixmapPtr pPixmap, unsigned *stride);
+
+int
+xorg_exa_set_displayed_usage(PixmapPtr pPixmap);
+
+int
+xorg_exa_set_shared_usage(PixmapPtr pPixmap);
void *
xorg_exa_init(ScrnInfoPtr pScrn);