summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMichel Dänzer <michel.daenzer@amd.com>2012-06-20 08:40:07 +0200
committerMichel Dänzer <michel@daenzer.net>2012-07-10 17:14:20 +0200
commite9edd2f5002c642b59f028b3ec076d604ae8ce9d (patch)
tree93c7536fb7292c7d042b6571c548f89e3d4945a3 /src
parent9eac8021f3d33a63156f9f5d43a220e88bb3f8db (diff)
Initial glamor support.
Enable at build time with --enable-glamor and runtime with Option "AccelMethod" "glamor" The most notable lack of functionality is XVideo. Use something like VDPAU for now. Signed-off-by: Michel Dänzer <michel.daenzer@amd.com>
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am8
-rw-r--r--src/drmmode_display.c8
-rw-r--r--src/radeon.h105
-rw-r--r--src/radeon_accel.c7
-rw-r--r--src/radeon_dri2.c240
-rw-r--r--src/radeon_exa.c32
-rw-r--r--src/radeon_glamor.c269
-rw-r--r--src/radeon_glamor.h93
-rw-r--r--src/radeon_kms.c39
9 files changed, 670 insertions, 131 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index e857f21a..da94927f 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -64,6 +64,13 @@ radeon_drv_la_SOURCES = \
$(RADEON_EXA_SOURCES) \
$(RADEON_KMS_SRCS)
+if GLAMOR
+AM_CFLAGS += @LIBGLAMOR_CFLAGS@
+radeon_drv_la_LIBADD += @LIBGLAMOR_LIBS@
+radeon_drv_la_SOURCES += \
+ radeon_glamor.c
+endif
+
EXTRA_DIST = \
radeon_textured_videofuncs.c \
r600_reg.h \
@@ -88,6 +95,7 @@ EXTRA_DIST = \
radeon_exa_render.c \
radeon_exa_funcs.c \
radeon_exa_shared.h \
+ radeon_glamor.h \
radeon.h \
radeon_probe.h \
radeon_reg.h \
diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 27569e51..6a357283 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -101,7 +101,8 @@ static PixmapPtr drmmode_create_bo_pixmap(ScrnInfoPtr pScrn,
return NULL;
}
- exaMoveInPixmap(pixmap);
+ if (!info->use_glamor)
+ exaMoveInPixmap(pixmap);
radeon_set_pixmap_bo(pixmap, bo);
if (info->ChipFamily >= CHIP_FAMILY_R600) {
surface = radeon_get_pixmap_surface(pixmap);
@@ -278,7 +279,7 @@ void drmmode_copy_fb(ScrnInfoPtr pScrn, drmmode_ptr drmmode)
uint32_t tiling_flags = 0;
Bool ret;
- if (info->accelOn == FALSE)
+ if (info->accelOn == FALSE || info->use_glamor)
goto fallback;
for (i = 0; i < xf86_config->num_crtc; i++) {
@@ -1442,6 +1443,9 @@ drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height)
crtc->rotation, crtc->x, crtc->y);
}
+ if (info->use_glamor)
+ radeon_glamor_create_screen_resources(scrn->pScreen);
+
if (old_fb_id)
drmModeRmFB(drmmode->fd, old_fb_id);
if (old_front)
diff --git a/src/radeon.h b/src/radeon.h
index d357dc13..2f05249e 100644
--- a/src/radeon.h
+++ b/src/radeon.h
@@ -51,6 +51,7 @@
#include "exa.h"
+#include "radeon_glamor.h"
/* Exa and Cursor Support */
#include "xf86Cursor.h"
@@ -429,6 +430,7 @@ typedef struct {
Bool allowColorTiling2D;
struct radeon_accel_state *accel_state;
Bool accelOn;
+ Bool use_glamor;
Bool exa_pixmaps;
Bool exa_force_create;
XF86ModReqInfo exaReq;
@@ -522,11 +524,107 @@ extern void radeon_ddx_cs_start(ScrnInfoPtr pScrn,
int num, const char *file,
const char *func, int line);
void radeon_kms_update_vram_limit(ScrnInfoPtr pScrn, int new_fb_size);
-struct radeon_surface *radeon_get_pixmap_surface(PixmapPtr pPix);
-struct radeon_bo *radeon_get_pixmap_bo(PixmapPtr pPix);
-void radeon_set_pixmap_bo(PixmapPtr pPix, struct radeon_bo *bo);
+
+static inline struct radeon_surface *radeon_get_pixmap_surface(PixmapPtr pPix)
+{
+#ifdef USE_GLAMOR
+ RADEONInfoPtr info = RADEONPTR(xf86ScreenToScrn(pPix->drawable.pScreen));
+
+ if (info->use_glamor) {
+ struct radeon_pixmap *priv;
+ priv = radeon_get_pixmap_private(pPix);
+ return priv ? &priv->surface : NULL;
+ } else
+#endif
+ {
+ struct radeon_exa_pixmap_priv *driver_priv;
+ driver_priv = exaGetPixmapDriverPrivate(pPix);
+ return &driver_priv->surface;
+ }
+
+ return NULL;
+}
+
uint32_t radeon_get_pixmap_tiling(PixmapPtr pPix);
+static inline void radeon_set_pixmap_bo(PixmapPtr pPix, struct radeon_bo *bo)
+{
+#ifdef USE_GLAMOR
+ RADEONInfoPtr info = RADEONPTR(xf86ScreenToScrn(pPix->drawable.pScreen));
+
+ if (info->use_glamor) {
+ struct radeon_pixmap *priv;
+
+ priv = radeon_get_pixmap_private(pPix);
+ if (priv == NULL && bo == NULL)
+ return;
+
+ if (priv) {
+ if (priv->bo == bo)
+ return;
+
+ if (priv->bo)
+ radeon_bo_unref(priv->bo);
+
+ free(priv);
+ priv = NULL;
+ }
+
+ if (bo) {
+ uint32_t pitch;
+
+ priv = calloc(1, sizeof (struct radeon_pixmap));
+ if (priv == NULL)
+ goto out;
+
+ radeon_bo_ref(bo);
+ priv->bo = bo;
+
+ radeon_bo_get_tiling(bo, &priv->tiling_flags, &pitch);
+ }
+out:
+ radeon_set_pixmap_private(pPix, priv);
+ } else
+#endif /* USE_GLAMOR */
+ {
+ struct radeon_exa_pixmap_priv *driver_priv;
+
+ driver_priv = exaGetPixmapDriverPrivate(pPix);
+ if (driver_priv) {
+ uint32_t pitch;
+
+ if (driver_priv->bo)
+ radeon_bo_unref(driver_priv->bo);
+
+ radeon_bo_ref(bo);
+ driver_priv->bo = bo;
+
+ radeon_bo_get_tiling(bo, &driver_priv->tiling_flags, &pitch);
+ }
+ }
+}
+
+static inline struct radeon_bo *radeon_get_pixmap_bo(PixmapPtr pPix)
+{
+#ifdef USE_GLAMOR
+ RADEONInfoPtr info = RADEONPTR(xf86ScreenToScrn(pPix->drawable.pScreen));
+
+ if (info->use_glamor) {
+ struct radeon_pixmap *priv;
+ priv = radeon_get_pixmap_private(pPix);
+ return priv ? priv->bo : NULL;
+ } else
+#endif
+ {
+ struct radeon_exa_pixmap_priv *driver_priv;
+ driver_priv = exaGetPixmapDriverPrivate(pPix);
+ return driver_priv->bo;
+ }
+
+ return NULL;
+}
+
+
#define CP_PACKET0(reg, n) \
(RADEON_CP_PACKET0 | ((n) << 16) | ((reg) >> 2))
#define CP_PACKET1(reg0, reg1) \
@@ -659,6 +757,7 @@ static __inline__ void RADEON_SYNC(RADEONInfoPtr info, ScrnInfoPtr pScrn)
}
enum {
+ RADEON_CREATE_PIXMAP_DRI2 = 0x08000000,
RADEON_CREATE_PIXMAP_TILING_MACRO = 0x10000000,
RADEON_CREATE_PIXMAP_TILING_MICRO = 0x20000000,
RADEON_CREATE_PIXMAP_DEPTH = 0x40000000, /* for r200 */
diff --git a/src/radeon_accel.c b/src/radeon_accel.c
index 15cf2bd8..8eff5c52 100644
--- a/src/radeon_accel.c
+++ b/src/radeon_accel.c
@@ -182,7 +182,12 @@ Bool RADEONAccelInit(ScreenPtr pScreen)
RADEONInfoPtr info = RADEONPTR(pScrn);
if (info->directRenderingEnabled) {
- if (info->ChipFamily >= CHIP_FAMILY_CEDAR) {
+ if (info->use_glamor) {
+ if (!radeon_glamor_init(pScreen)) {
+ info->use_glamor = FALSE;
+ return FALSE;
+ }
+ } else if (info->ChipFamily >= CHIP_FAMILY_CEDAR) {
if (!EVERGREENDrawInit(pScreen))
return FALSE;
} else
diff --git a/src/radeon_dri2.c b/src/radeon_dri2.c
index 8c24de90..12b198c5 100644
--- a/src/radeon_dri2.c
+++ b/src/radeon_dri2.c
@@ -73,6 +73,77 @@ struct dri2_buffer_priv {
};
+static PixmapPtr get_drawable_pixmap(DrawablePtr drawable)
+{
+ if (drawable->type == DRAWABLE_PIXMAP)
+ return (PixmapPtr)drawable;
+ else
+ return (*drawable->pScreen->GetWindowPixmap)((WindowPtr)drawable);
+}
+
+
+static PixmapPtr fixup_glamor(DrawablePtr drawable, PixmapPtr pixmap)
+{
+ PixmapPtr old = get_drawable_pixmap(drawable);
+#ifdef USE_GLAMOR
+ ScreenPtr screen = drawable->pScreen;
+ ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+ struct radeon_pixmap *priv = radeon_get_pixmap_private(pixmap);
+ GCPtr gc;
+
+ /* With a glamor pixmap, 2D pixmaps are created in texture
+ * and without a static BO attached to it. To support DRI,
+ * we need to create a new textured-drm pixmap and
+ * need to copy the original content to this new textured-drm
+ * pixmap, and then convert the old pixmap to a coherent
+ * textured-drm pixmap which has a valid BO attached to it
+ * and also has a valid texture, thus both glamor and DRI2
+ * can access it.
+ *
+ */
+
+ /* Copy the current contents of the pixmap to the bo. */
+ gc = GetScratchGC(drawable->depth, screen);
+ if (gc) {
+ ValidateGC(&pixmap->drawable, gc);
+ gc->ops->CopyArea(&old->drawable, &pixmap->drawable,
+ gc,
+ 0, 0,
+ old->drawable.width,
+ old->drawable.height,
+ 0, 0);
+ FreeScratchGC(gc);
+ }
+
+ radeon_set_pixmap_private(pixmap, NULL);
+ screen->DestroyPixmap(pixmap);
+
+ /* And redirect the pixmap to the new bo (for 3D). */
+ radeon_set_pixmap_private(old, priv);
+ old->refcnt++;
+
+ /* This creating should not fail, as we already created its
+ * successfully. But if it happens, we put a warning indicator
+ * here, and the old pixmap will still be a glamor pixmap, and
+ * latter the pixmap_flink will get a 0 name, then the X server
+ * will pass a BadAlloc to the client.*/
+ if (!radeon_glamor_create_textured_pixmap(old))
+ xf86DrvMsg(scrn->scrnIndex, X_WARNING,
+ "Failed to get DRI drawable for glamor pixmap.\n");
+
+ screen->ModifyPixmapHeader(old,
+ old->drawable.width,
+ old->drawable.height,
+ 0, 0,
+ priv->stride,
+ NULL);
+
+#endif /* USE_GLAMOR*/
+
+ return old;
+}
+
+
#ifndef USE_DRI2_1_1_0
static BufferPtr
radeon_dri2_create_buffers(DrawablePtr drawable,
@@ -85,13 +156,13 @@ radeon_dri2_create_buffers(DrawablePtr drawable,
BufferPtr buffers;
struct dri2_buffer_priv *privates;
PixmapPtr pixmap, depth_pixmap;
- struct radeon_exa_pixmap_priv *driver_priv;
+ struct radeon_bo *bo;
int i, r, need_enlarge = 0;
int flags = 0;
unsigned front_width;
uint32_t tiling = 0;
- pixmap = screen->GetScreenPixmap(screen);
+ pixmap = pScreen->GetScreenPixmap(pScreen);
front_width = pixmap->drawable.width;
buffers = calloc(count, sizeof *buffers);
@@ -106,17 +177,25 @@ radeon_dri2_create_buffers(DrawablePtr drawable,
depth_pixmap = NULL;
for (i = 0; i < count; i++) {
+ Bool is_glamor_pixmap = FALSE;
+ unsigned aligned_width = drawable->width;
+ unsigned aligned_height = drawable->height;
+
if (attachments[i] == DRI2BufferFrontLeft) {
- if (drawable->type == DRAWABLE_PIXMAP) {
- pixmap = (Pixmap*)drawable;
- } else {
- pixmap = (*pScreen->GetWindowPixmap)((WindowPtr)drawable);
- }
- pixmap->refcnt++;
+ pixmap = get_drawable_pixmap(drawable);
+ if (info->use_glamor && !radeon_get_pixmap_bo(pixmap)) {
+ is_glamor_pixmap = TRUE;
+ aligned_width = pixmap->drawable.width;
+ aligned_height = pixmap->drawable.height;
+ pixmap = NULL;
+ } else
+ pixmap->refcnt++;
} else if (attachments[i] == DRI2BufferStencil && depth_pixmap) {
pixmap = depth_pixmap;
pixmap->refcnt++;
- } else {
+ }
+
+ if (!pixmap) {
/* tile the back buffer */
switch(attachments[i]) {
case DRI2BufferDepth:
@@ -145,6 +224,8 @@ radeon_dri2_create_buffers(DrawablePtr drawable,
break;
case DRI2BufferBackLeft:
case DRI2BufferBackRight:
+ case DRI2BufferFrontLeft:
+ case DRI2BufferFrontRight:
case DRI2BufferFakeFrontLeft:
case DRI2BufferFakeFrontRight:
if (info->ChipFamily >= CHIP_FAMILY_R600)
@@ -164,14 +245,15 @@ radeon_dri2_create_buffers(DrawablePtr drawable,
if (flags & RADEON_CREATE_PIXMAP_TILING_MACRO)
tiling |= RADEON_TILING_MACRO;
+ if (aligned_width == front_width)
+ aligned_width = pScrn->virtualX;
+
if (need_enlarge) {
/* evergreen uses separate allocations for depth and stencil
* so we make an extra large depth buffer to cover stencil
* as well.
*/
- unsigned aligned_width = drawable->width;
unsigned width_align = drmmode_get_pitch_align(pScrn, drawable->depth / 8, tiling);
- unsigned aligned_height;
unsigned height_align = drmmode_get_height_align(pScrn, tiling);
unsigned base_align = drmmode_get_base_align(pScrn, drawable->depth / 8, tiling);
unsigned pitch_bytes;
@@ -181,42 +263,33 @@ radeon_dri2_create_buffers(DrawablePtr drawable,
aligned_width = pScrn->virtualX;
aligned_width = RADEON_ALIGN(aligned_width, width_align);
pitch_bytes = aligned_width * (drawable->depth / 8);
- aligned_height = RADEON_ALIGN(drawable->height, height_align);
+ aligned_height = RADEON_ALIGN(aligned_height, height_align);
size = pitch_bytes * aligned_height;
size = RADEON_ALIGN(size, base_align);
/* add additional size for stencil */
size += aligned_width * aligned_height;
aligned_height = RADEON_ALIGN(size / pitch_bytes, height_align);
-
- pixmap = (*pScreen->CreatePixmap)(pScreen,
- aligned_width,
- aligned_height,
- drawable->depth,
- flags);
-
- } else {
- unsigned aligned_width = drawable->width;
-
- if (aligned_width == front_width)
- aligned_width = pScrn->virtualX;
-
- pixmap = (*pScreen->CreatePixmap)(pScreen,
- aligned_width,
- drawable->height,
- drawable->depth,
- flags);
}
+
+ pixmap = (*pScreen->CreatePixmap)(pScreen,
+ aligned_width,
+ aligned_height,
+ drawable->depth,
+ flags | RADEON_CREATE_PIXMAP_DRI2);
}
if (attachments[i] == DRI2BufferDepth) {
depth_pixmap = pixmap;
}
- info->exa_force_create = TRUE;
- exaMoveInPixmap(pixmap);
- info->exa_force_create = FALSE;
- driver_priv = exaGetPixmapDriverPrivate(pixmap);
- if (!driver_priv ||
- radeon_gem_get_kernel_name(driver_priv->bo, &buffers[i].name) != 0) {
+ if (!info->use_glamor) {
+ info->exa_force_create = TRUE;
+ exaMoveInPixmap(pixmap);
+ info->exa_force_create = FALSE;
+ }
+ if (is_glamor_pixmap)
+ pixmap = fixup_glamor(drawable, pixmap);
+ bo = radeon_get_pixmap_bo(pixmap);
+ if (!bo || radeon_gem_get_kernel_name(bo, &buffers[i].name) != 0) {
int j;
for (j = 0; j < i; j++)
@@ -249,11 +322,13 @@ radeon_dri2_create_buffer(DrawablePtr drawable,
BufferPtr buffers;
struct dri2_buffer_priv *privates;
PixmapPtr pixmap, depth_pixmap;
- struct radeon_exa_pixmap_priv *driver_priv;
+ struct radeon_bo *bo;
int flags;
unsigned front_width;
uint32_t tiling = 0;
unsigned aligned_width = drawable->width;
+ unsigned height = drawable->height;
+ Bool is_glamor_pixmap = FALSE;
pixmap = pScreen->GetScreenPixmap(pScreen);
front_width = pixmap->drawable.width;
@@ -261,16 +336,20 @@ radeon_dri2_create_buffer(DrawablePtr drawable,
pixmap = depth_pixmap = NULL;
if (attachment == DRI2BufferFrontLeft) {
- if (drawable->type == DRAWABLE_PIXMAP) {
- pixmap = (PixmapPtr)drawable;
- } else {
- pixmap = (*pScreen->GetWindowPixmap)((WindowPtr)drawable);
- }
- pixmap->refcnt++;
+ pixmap = get_drawable_pixmap(drawable);
+ if (info->use_glamor && !radeon_get_pixmap_bo(pixmap)) {
+ is_glamor_pixmap = TRUE;
+ aligned_width = pixmap->drawable.width;
+ height = pixmap->drawable.height;
+ pixmap = NULL;
+ } else
+ pixmap->refcnt++;
} else if (attachment == DRI2BufferStencil && depth_pixmap) {
pixmap = depth_pixmap;
pixmap->refcnt++;
- } else {
+ }
+
+ if (!pixmap) {
/* tile the back buffer */
switch(attachment) {
case DRI2BufferDepth:
@@ -310,6 +389,8 @@ radeon_dri2_create_buffer(DrawablePtr drawable,
break;
case DRI2BufferBackLeft:
case DRI2BufferBackRight:
+ case DRI2BufferFrontLeft:
+ case DRI2BufferFrontRight:
case DRI2BufferFakeFrontLeft:
case DRI2BufferFakeFrontRight:
if (info->ChipFamily >= CHIP_FAMILY_R600) {
@@ -336,9 +417,9 @@ radeon_dri2_create_buffer(DrawablePtr drawable,
pixmap = (*pScreen->CreatePixmap)(pScreen,
aligned_width,
- drawable->height,
+ height,
(format != 0)?format:drawable->depth,
- flags);
+ flags | RADEON_CREATE_PIXMAP_DRI2);
}
if (!pixmap)
@@ -351,12 +432,15 @@ radeon_dri2_create_buffer(DrawablePtr drawable,
if (attachment == DRI2BufferDepth) {
depth_pixmap = pixmap;
}
- info->exa_force_create = TRUE;
- exaMoveInPixmap(pixmap);
- info->exa_force_create = FALSE;
- driver_priv = exaGetPixmapDriverPrivate(pixmap);
- if (!driver_priv ||
- (radeon_gem_get_kernel_name(driver_priv->bo, &buffers->name) != 0))
+ if (!info->use_glamor) {
+ info->exa_force_create = TRUE;
+ exaMoveInPixmap(pixmap);
+ info->exa_force_create = FALSE;
+ }
+ if (is_glamor_pixmap)
+ pixmap = fixup_glamor(drawable, pixmap);
+ bo = radeon_get_pixmap_bo(pixmap);
+ if (!bo || radeon_gem_get_kernel_name(bo, &buffers->name) != 0)
goto error;
privates = calloc(1, sizeof(struct dri2_buffer_priv));
@@ -476,11 +560,10 @@ radeon_dri2_copy_region(DrawablePtr drawable,
if (extents->x1 == 0 && extents->y1 == 0 &&
extents->x2 == drawable->width &&
extents->y2 == drawable->height) {
- struct radeon_exa_pixmap_priv *exa_priv =
- exaGetPixmapDriverPrivate(dst_private->pixmap);
+ struct radeon_bo *bo = radeon_get_pixmap_bo(dst_private->pixmap);
- if (exa_priv && exa_priv->bo)
- radeon_bo_wait(exa_priv->bo);
+ if (bo)
+ radeon_bo_wait(bo);
}
}
}
@@ -643,7 +726,7 @@ radeon_dri2_schedule_flip(ScrnInfoPtr scrn, ClientPtr client,
void *data, unsigned int target_msc)
{
struct dri2_buffer_priv *back_priv;
- struct radeon_exa_pixmap_priv *exa_priv;
+ struct radeon_bo *bo;
DRI2FrameEventPtr flip_info;
/* Main crtc for this drawable shall finally deliver pageflip event. */
@@ -665,9 +748,9 @@ radeon_dri2_schedule_flip(ScrnInfoPtr scrn, ClientPtr client,
/* Page flip the full screen buffer */
back_priv = back->driverPrivate;
- exa_priv = exaGetPixmapDriverPrivate(back_priv->pixmap);
+ bo = radeon_get_pixmap_bo(back_priv->pixmap);
- return radeon_do_pageflip(scrn, exa_priv->bo, flip_info, ref_crtc_hw_id);
+ return radeon_do_pageflip(scrn, bo, flip_info, ref_crtc_hw_id);
}
static Bool
@@ -675,19 +758,17 @@ update_front(DrawablePtr draw, DRI2BufferPtr front)
{
int r;
PixmapPtr pixmap;
+ RADEONInfoPtr info = RADEONPTR(xf86ScreenToScrn(draw->pScreen));
struct dri2_buffer_priv *priv = front->driverPrivate;
- struct radeon_exa_pixmap_priv *driver_priv;
-
- if (draw->type == DRAWABLE_PIXMAP)
- pixmap = (PixmapPtr)draw;
- else
- pixmap = (*draw->pScreen->GetWindowPixmap)((WindowPtr)draw);
+ struct radeon_bo *bo;
+ pixmap = get_drawable_pixmap(draw);
pixmap->refcnt++;
- exaMoveInPixmap(pixmap);
- driver_priv = exaGetPixmapDriverPrivate(pixmap);
- r = radeon_gem_get_kernel_name(driver_priv->bo, &front->name);
+ if (!info->use_glamor)
+ exaMoveInPixmap(pixmap);
+ bo = radeon_get_pixmap_bo(pixmap);
+ r = radeon_gem_get_kernel_name(bo, &front->name);
if (r) {
(*draw->pScreen->DestroyPixmap)(pixmap);
return FALSE;
@@ -753,10 +834,9 @@ radeon_dri2_exchange_buffers(DrawablePtr draw, DRI2BufferPtr front, DRI2BufferPt
{
struct dri2_buffer_priv *front_priv = front->driverPrivate;
struct dri2_buffer_priv *back_priv = back->driverPrivate;
- struct radeon_exa_pixmap_priv *front_radeon, *back_radeon;
+ struct radeon_bo *front_bo, *back_bo;
ScreenPtr screen;
RADEONInfoPtr info;
- struct radeon_bo *bo;
int tmp;
/* Swap BO names so DRI works */
@@ -765,22 +845,22 @@ radeon_dri2_exchange_buffers(DrawablePtr draw, DRI2BufferPtr front, DRI2BufferPt
back->name = tmp;
/* Swap pixmap bos */
- front_radeon = exaGetPixmapDriverPrivate(front_priv->pixmap);
- back_radeon = exaGetPixmapDriverPrivate(back_priv->pixmap);
- bo = back_radeon->bo;
- back_radeon->bo = front_radeon->bo;
- front_radeon->bo = bo;
+ front_bo = radeon_get_pixmap_bo(front_priv->pixmap);
+ back_bo = radeon_get_pixmap_bo(back_priv->pixmap);
+ radeon_set_pixmap_bo(front_priv->pixmap, back_bo);
+ radeon_set_pixmap_bo(back_priv->pixmap, front_bo);
/* Do we need to update the Screen? */
screen = draw->pScreen;
info = RADEONPTR(xf86ScreenToScrn(screen));
- if (front_radeon->bo == info->front_bo) {
+ if (front_bo == info->front_bo) {
+ radeon_bo_ref(back_bo);
radeon_bo_unref(info->front_bo);
- info->front_bo = back_radeon->bo;
- radeon_bo_ref(info->front_bo);
- front_radeon = exaGetPixmapDriverPrivate(screen->GetScreenPixmap(screen));
- front_radeon->bo = bo;
+ info->front_bo = back_bo;
+ radeon_set_pixmap_bo(screen->GetScreenPixmap(screen), back_bo);
}
+
+ radeon_glamor_exchange_buffers(front_priv->pixmap, back_priv->pixmap);
}
void radeon_dri2_frame_event_handler(unsigned int frame, unsigned int tv_sec,
diff --git a/src/radeon_exa.c b/src/radeon_exa.c
index d80c7e4f..5c5d9979 100644
--- a/src/radeon_exa.c
+++ b/src/radeon_exa.c
@@ -325,20 +325,6 @@ void RADEONEXADestroyPixmap(ScreenPtr pScreen, void *driverPriv)
free(driverPriv);
}
-struct radeon_bo *radeon_get_pixmap_bo(PixmapPtr pPix)
-{
- struct radeon_exa_pixmap_priv *driver_priv;
- driver_priv = exaGetPixmapDriverPrivate(pPix);
- return driver_priv->bo;
-}
-
-struct radeon_surface *radeon_get_pixmap_surface(PixmapPtr pPix)
-{
- struct radeon_exa_pixmap_priv *driver_priv;
- driver_priv = exaGetPixmapDriverPrivate(pPix);
- return &driver_priv->surface;
-}
-
uint32_t radeon_get_pixmap_tiling(PixmapPtr pPix)
{
struct radeon_exa_pixmap_priv *driver_priv;
@@ -346,24 +332,6 @@ uint32_t radeon_get_pixmap_tiling(PixmapPtr pPix)
return driver_priv->tiling_flags;
}
-void radeon_set_pixmap_bo(PixmapPtr pPix, struct radeon_bo *bo)
-{
- struct radeon_exa_pixmap_priv *driver_priv;
-
- driver_priv = exaGetPixmapDriverPrivate(pPix);
- if (driver_priv) {
- uint32_t pitch;
-
- if (driver_priv->bo)
- radeon_bo_unref(driver_priv->bo);
-
- radeon_bo_ref(bo);
- driver_priv->bo = bo;
-
- radeon_bo_get_tiling(bo, &driver_priv->tiling_flags, &pitch);
- }
-}
-
Bool RADEONEXAPixmapIsOffscreen(PixmapPtr pPix)
{
struct radeon_exa_pixmap_priv *driver_priv;
diff --git a/src/radeon_glamor.c b/src/radeon_glamor.c
new file mode 100644
index 00000000..232332e3
--- /dev/null
+++ b/src/radeon_glamor.c
@@ -0,0 +1,269 @@
+/*
+ * Copyright © 2011 Intel Corporation.
+ * 2012 Advanced Micro Devices, Inc.
+ *
+ * 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <xf86.h>
+#define GLAMOR_FOR_XORG 1
+#include <glamor.h>
+
+#include "radeon.h"
+#include "radeon_bo_helper.h"
+
+#if HAS_DEVPRIVATEKEYREC
+DevPrivateKeyRec glamor_pixmap_index;
+#else
+int glamor_pixmap_index;
+#endif
+
+void
+radeon_glamor_exchange_buffers(PixmapPtr src,
+ PixmapPtr dst)
+{
+ RADEONInfoPtr info = RADEONPTR(xf86ScreenToScrn(dst->drawable.pScreen));
+
+ if (!info->use_glamor)
+ return;
+ glamor_egl_exchange_buffers(src, dst);
+}
+
+Bool
+radeon_glamor_create_screen_resources(ScreenPtr screen)
+{
+ ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+ RADEONInfoPtr info = RADEONPTR(scrn);
+
+ if (!info->use_glamor)
+ return TRUE;
+
+ if (!glamor_glyphs_init(screen))
+ return FALSE;
+
+ if (!glamor_egl_create_textured_screen_ext(screen,
+ info->front_bo->handle,
+ scrn->displayWidth *
+ info->pixel_bytes,
+ NULL))
+ return FALSE;
+
+ return TRUE;
+}
+
+
+Bool
+radeon_glamor_pre_init(ScrnInfoPtr scrn)
+{
+ RADEONInfoPtr info = RADEONPTR(scrn);
+ pointer glamor_module;
+ CARD32 version;
+ const char *s;
+
+ s = xf86GetOptValString(info->Options, OPTION_ACCELMETHOD);
+ if (s == NULL)
+ return FALSE;
+
+ if (strcasecmp(s, "glamor") != 0)
+ return FALSE;
+
+ /* Load glamor module */
+ if ((glamor_module = xf86LoadSubModule(scrn, GLAMOR_EGL_MODULE_NAME))) {
+ version = xf86GetModuleVersion(glamor_module);
+ if (version < MODULE_VERSION_NUMERIC(0,3,1)) {
+ xf86DrvMsg(scrn->scrnIndex, X_ERROR,
+ "Incompatible glamor version, required >= 0.3.0.\n");
+ return FALSE;
+ } else {
+ if (glamor_egl_init(scrn, info->dri2.drm_fd)) {
+ xf86DrvMsg(scrn->scrnIndex, X_INFO,
+ "glamor detected, initialising EGL layer.\n");
+ } else {
+ xf86DrvMsg(scrn->scrnIndex, X_ERROR,
+ "glamor detected, failed to initialize EGL.\n");
+ return FALSE;
+ }
+ }
+ } else {
+ xf86DrvMsg(scrn->scrnIndex, X_ERROR, "glamor not available\n");
+ return FALSE;
+ }
+
+ info->use_glamor = TRUE;
+
+ return TRUE;
+}
+
+Bool
+radeon_glamor_create_textured_pixmap(PixmapPtr pixmap)
+{
+ ScrnInfoPtr scrn = xf86ScreenToScrn(pixmap->drawable.pScreen);
+ RADEONInfoPtr info = RADEONPTR(scrn);
+ struct radeon_pixmap *priv;
+
+ if ((info->use_glamor) == 0)
+ return TRUE;
+
+ priv = radeon_get_pixmap_private(pixmap);
+ if (glamor_egl_create_textured_pixmap(pixmap, priv->bo->handle,
+ priv->stride))
+ return TRUE;
+ else
+ return FALSE;
+}
+
+static PixmapPtr
+radeon_glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth,
+ unsigned usage)
+{
+ ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+ struct radeon_pixmap *priv;
+ PixmapPtr pixmap, new_pixmap = NULL;
+
+ if (!(usage & RADEON_CREATE_PIXMAP_DRI2)) {
+ pixmap = glamor_create_pixmap(screen, w, h, depth, usage);
+ if (pixmap)
+ return pixmap;
+ }
+
+ if (w > 32767 || h > 32767)
+ return NullPixmap;
+
+ if (depth == 1)
+ return fbCreatePixmap(screen, w, h, depth, usage);
+
+ if (usage == CREATE_PIXMAP_USAGE_GLYPH_PICTURE && w <= 32 && h <= 32)
+ return fbCreatePixmap(screen, w, h, depth, usage);
+
+ pixmap = fbCreatePixmap(screen, 0, 0, depth, usage);
+ if (pixmap == NullPixmap)
+ return pixmap;
+
+ if (w && h) {
+ priv = calloc(1, sizeof (struct radeon_pixmap));
+ if (priv == NULL)
+ goto fallback_pixmap;
+
+ priv->bo = radeon_alloc_pixmap_bo(scrn, w, h, depth, usage,
+ pixmap->drawable.bitsPerPixel,
+ &priv->stride,
+ &priv->surface,
+ &priv->tiling_flags);
+ if (!priv->bo)
+ goto fallback_priv;
+
+ radeon_set_pixmap_private(pixmap, priv);
+
+ screen->ModifyPixmapHeader(pixmap, w, h, 0, 0, priv->stride, NULL);
+
+ if (!radeon_glamor_create_textured_pixmap(pixmap))
+ goto fallback_glamor;
+ }
+
+ return pixmap;
+
+fallback_glamor:
+ if (usage & RADEON_CREATE_PIXMAP_DRI2) {
+ /* XXX need further work to handle the DRI2 failure case.
+ * Glamor don't know how to handle a BO only pixmap. Put
+ * a warning indicator here.
+ */
+ xf86DrvMsg(scrn->scrnIndex, X_WARNING,
+ "Failed to create textured DRI2 pixmap.");
+ return pixmap;
+ }
+ /* Create textured pixmap failed means glamor failed to
+ * create a texture from current BO for some reasons. We turn
+ * to create a new glamor pixmap and clean up current one.
+ * One thing need to be noted, this new pixmap doesn't
+ * has a priv and bo attached to it. It's glamor's responsbility
+ * to take care of it. Glamor will mark this new pixmap as a
+ * texture only pixmap and will never fallback to DDX layer
+ * afterwards.
+ */
+ new_pixmap = glamor_create_pixmap(screen, w, h, depth, usage);
+ radeon_bo_unref(priv->bo);
+fallback_priv:
+ free(priv);
+fallback_pixmap:
+ fbDestroyPixmap(pixmap);
+ if (new_pixmap)
+ return new_pixmap;
+ else
+ return fbCreatePixmap(screen, w, h, depth, usage);
+}
+
+static Bool radeon_glamor_destroy_pixmap(PixmapPtr pixmap)
+{
+ if (pixmap->refcnt == 1) {
+ glamor_egl_destroy_textured_pixmap(pixmap);
+ radeon_set_pixmap_bo(pixmap, NULL);
+ }
+ fbDestroyPixmap(pixmap);
+ return TRUE;
+}
+
+Bool
+radeon_glamor_init(ScreenPtr screen)
+{
+ ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+
+ if (!glamor_init(screen, GLAMOR_INVERTED_Y_AXIS | GLAMOR_USE_EGL_SCREEN |
+ GLAMOR_USE_SCREEN | GLAMOR_USE_PICTURE_SCREEN)) {
+ xf86DrvMsg(scrn->scrnIndex, X_ERROR,
+ "Failed to initialize glamor.\n");
+ return FALSE;
+ }
+
+ if (!glamor_egl_init_textured_pixmap(screen)) {
+ xf86DrvMsg(scrn->scrnIndex, X_ERROR,
+ "Failed to initialize textured pixmap of screen for glamor.\n");
+ return FALSE;
+ }
+
+#if HAS_DIXREGISTERPRIVATEKEY
+ if (!dixRegisterPrivateKey(&glamor_pixmap_index, PRIVATE_PIXMAP, 0))
+#else
+ if (!dixRequestPrivate(&glamor_pixmap_index, 0))
+#endif
+ return FALSE;
+
+ screen->CreatePixmap = radeon_glamor_create_pixmap;
+ screen->DestroyPixmap = radeon_glamor_destroy_pixmap;
+
+ xf86DrvMsg(scrn->scrnIndex, X_INFO,
+ "Use GLAMOR acceleration.\n");
+ return TRUE;
+}
+
+void
+radeon_glamor_flush(ScrnInfoPtr pScrn)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+
+ if (info->use_glamor)
+ glamor_block_handler(pScrn->pScreen);
+}
diff --git a/src/radeon_glamor.h b/src/radeon_glamor.h
new file mode 100644
index 00000000..40c9092b
--- /dev/null
+++ b/src/radeon_glamor.h
@@ -0,0 +1,93 @@
+/*
+ * Copyright © 2011 Intel Corporation.
+ * 2012 Advanced Micro Devices, Inc.
+ *
+ * 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.
+ */
+
+#ifndef RADEON_GLAMOR_H
+#define RADEON_GLAMOR_H
+
+#ifdef USE_GLAMOR
+
+#include "radeon_surface.h"
+
+Bool radeon_glamor_pre_init(ScrnInfoPtr scrn);
+Bool radeon_glamor_init(ScreenPtr screen);
+Bool radeon_glamor_create_screen_resources(ScreenPtr screen);
+void radeon_glamor_free_screen(int scrnIndex, int flags);
+
+void radeon_glamor_flush(ScrnInfoPtr pScrn);
+
+Bool radeon_glamor_create_textured_pixmap(PixmapPtr pixmap);
+void radeon_glamor_exchange_buffers(PixmapPtr src, PixmapPtr dst);
+
+Bool radeon_glamor_pixmap_is_offscreen(PixmapPtr pixmap);
+
+struct radeon_pixmap {
+ struct radeon_surface surface;
+ struct radeon_bo *bo;
+
+ uint32_t tiling_flags;
+ int stride;
+};
+
+#if HAS_DEVPRIVATEKEYREC
+extern DevPrivateKeyRec glamor_pixmap_index;
+#else
+extern int glamor_pixmap_index;
+#endif
+
+static inline struct radeon_pixmap *radeon_get_pixmap_private(PixmapPtr pixmap)
+{
+#if HAS_DEVPRIVATEKEYREC
+ return dixGetPrivate(&pixmap->devPrivates, &glamor_pixmap_index);
+#else
+ return dixLookupPrivate(&pixmap->devPrivates, &glamor_pixmap_index);
+#endif
+}
+
+static inline void radeon_set_pixmap_private(PixmapPtr pixmap, struct radeon_pixmap *priv)
+{
+ dixSetPrivate(&pixmap->devPrivates, &glamor_pixmap_index, priv);
+}
+
+#else
+
+static inline Bool radeon_glamor_pre_init(ScrnInfoPtr scrn) { return FALSE; }
+static inline Bool radeon_glamor_init(ScreenPtr screen) { return FALSE; }
+static inline Bool radeon_glamor_create_screen_resources(ScreenPtr screen) { return FALSE; }
+static inline void radeon_glamor_free_screen(int scrnIndex, int flags) { }
+
+static inline void radeon_glamor_flush(ScrnInfoPtr pScrn) { }
+
+static inline Bool radeon_glamor_create_textured_pixmap(PixmapPtr pixmap) { return FALSE; }
+
+static inline void radeon_glamor_exchange_buffers(PixmapPtr src, PixmapPtr dst) {}
+
+static inline Bool radeon_glamor_pixmap_is_offscreen(PixmapPtr pixmap) { return FALSE; }
+
+static inline struct radeon_pixmap *radeon_get_pixmap_private(PixmapPtr pixmap) { return NULL; }
+
+#endif
+
+#endif /* RADEON_GLAMOR_H */
diff --git a/src/radeon_kms.c b/src/radeon_kms.c
index 61d6419b..5d9ccff6 100644
--- a/src/radeon_kms.c
+++ b/src/radeon_kms.c
@@ -224,7 +224,7 @@ static Bool RADEONCreateScreenResources_KMS(ScreenPtr pScreen)
return FALSE;
}
- if (info->dri2.enabled) {
+ if (info->dri2.enabled || info->use_glamor) {
if (info->front_bo) {
PixmapPtr pPix = pScreen->GetScreenPixmap(pScreen);
radeon_set_pixmap_bo(pPix, info->front_bo);
@@ -234,6 +234,10 @@ static Bool RADEONCreateScreenResources_KMS(ScreenPtr pScreen)
}
}
}
+
+ if (info->use_glamor)
+ radeon_glamor_create_screen_resources(pScreen);
+
return TRUE;
}
@@ -247,6 +251,9 @@ static void RADEONBlockHandler_KMS(BLOCKHANDLER_ARGS_DECL)
(*pScreen->BlockHandler) (BLOCKHANDLER_ARGS);
pScreen->BlockHandler = RADEONBlockHandler_KMS;
+ if (info->use_glamor)
+ radeon_glamor_flush(pScrn);
+
radeon_cs_flush_indirect(pScrn);
}
@@ -258,6 +265,7 @@ radeon_flush_callback(CallbackListPtr *list,
if (pScrn->vtSema) {
radeon_cs_flush_indirect(pScrn);
+ radeon_glamor_flush(pScrn);
}
}
@@ -416,6 +424,9 @@ static Bool RADEONPreInitAccel_KMS(ScrnInfoPtr pScrn)
return TRUE;
}
+ if (radeon_glamor_pre_init(pScrn))
+ return TRUE;
+
if (info->ChipFamily == CHIP_FAMILY_PALM) {
info->accel_state->allowHWDFS = RADEONIsFusionGARTWorking(pScrn);
} else
@@ -838,16 +849,18 @@ Bool RADEONPreInit_KMS(ScrnInfoPtr pScrn, int flags)
}
}
- info->exa_pixmaps = xf86ReturnOptValBool(info->Options,
- OPTION_EXA_PIXMAPS,
- ((info->vram_size > (32 * 1024 * 1024) &&
- info->RenderAccel)));
- if (info->exa_pixmaps)
- xf86DrvMsg(pScrn->scrnIndex, X_INFO,
- "EXA: Driver will allow EXA pixmaps in VRAM\n");
- else
- xf86DrvMsg(pScrn->scrnIndex, X_INFO,
- "EXA: Driver will not allow EXA pixmaps in VRAM\n");
+ if (!info->use_glamor) {
+ info->exa_pixmaps = xf86ReturnOptValBool(info->Options,
+ OPTION_EXA_PIXMAPS,
+ ((info->vram_size > (32 * 1024 * 1024) &&
+ info->RenderAccel)));
+ if (info->exa_pixmaps)
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "EXA: Driver will allow EXA pixmaps in VRAM\n");
+ else
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "EXA: Driver will not allow EXA pixmaps in VRAM\n");
+ }
/* no tiled scanout on r6xx+ yet */
if (info->allowColorTiling) {
@@ -1186,7 +1199,7 @@ Bool RADEONScreenInit_KMS(SCREEN_INIT_ARGS_DECL)
*/
/* xf86DiDGAInit(pScreen, info->LinearAddr + pScrn->fbOffset); */
#endif
- if (info->r600_shadow_fb == FALSE) {
+ if (!info->use_glamor && info->r600_shadow_fb == FALSE) {
/* Init Xv */
xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
"Initializing Xv\n");
@@ -1322,7 +1335,7 @@ static Bool radeon_setup_kernel_mem(ScreenPtr pScreen)
xf86DrvMsg(pScreen->myNum, X_ERROR, "Memory map already initialized\n");
return FALSE;
}
- if (info->r600_shadow_fb == FALSE) {
+ if (!info->use_glamor && info->r600_shadow_fb == FALSE) {
info->accel_state->exa = exaDriverAlloc();
if (info->accel_state->exa == NULL) {
xf86DrvMsg(pScreen->myNum, X_ERROR, "exaDriverAlloc failed\n");