xf86-video-ati: Branch 'master' - 3 commits
Alex Deucher
agd5f at kemper.freedesktop.org
Mon Aug 1 08:40:24 PDT 2011
src/drmmode_display.c | 52 ++++++++++++++++++++++++++++++--------------------
src/drmmode_display.h | 10 ++++++---
src/radeon_dri2.c | 45 ++++++++++++++++++++++++++++++++++++++-----
3 files changed, 79 insertions(+), 28 deletions(-)
New commits:
commit 104b2d7c071f29266b1bc4184a74e9714d14febc
Author: Alex Deucher <alexander.deucher at amd.com>
Date: Mon Aug 1 10:05:30 2011 -0400
kms: fix possible leak in pageflip code
Signed-off-by: Alex Deucher <alexander.deucher at amd.com>
diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 7f6ce18..f49aa3d 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -1654,7 +1654,7 @@ Bool radeon_do_pageflip(ScrnInfoPtr scrn, struct radeon_bo *new_front, void *dat
unsigned int pitch;
int i, old_fb_id;
uint32_t tiling_flags = 0;
- int height;
+ int height, emitted = 0;
drmmode_flipdata_ptr flipdata;
drmmode_flipevtcarrier_ptr flipcarrier;
@@ -1708,6 +1708,8 @@ Bool radeon_do_pageflip(ScrnInfoPtr scrn, struct radeon_bo *new_front, void *dat
if (!flipcarrier) {
xf86DrvMsg(scrn->scrnIndex, X_WARNING,
"flip queue: carrier alloc failed.\n");
+ if (emitted == 0)
+ free(flipdata);
goto error_undo;
}
@@ -1722,8 +1724,11 @@ Bool radeon_do_pageflip(ScrnInfoPtr scrn, struct radeon_bo *new_front, void *dat
xf86DrvMsg(scrn->scrnIndex, X_WARNING,
"flip queue failed: %s\n", strerror(errno));
free(flipcarrier);
+ if (emitted == 0)
+ free(flipdata);
goto error_undo;
}
+ emitted++;
}
flipdata->old_fb_id = old_fb_id;
commit d29bab632e9ecccba518d4107d52620bf75eb1cf
Author: Ville Syrjala <syrjala at sci.fi>
Date: Wed May 4 23:51:27 2011 +0300
kms: Move flip_count and co. to a per swap structure
If multiple drawables are doing page flipping, the global drmmode
structure can't be used to keep per swap information. For example
flip_count can increase prematurely due to another swap request,
and then the previous swap request never gets completed, leading to a
stuck client. Move the relevant pieces of data to a strucuture that
gets allocated once per swap request and shared by all involved CRTCs.
Signed-off-by: Ville Syrjala <syrjala at sci.fi>
diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index afa4c26..7f6ce18 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -1331,31 +1331,34 @@ drmmode_flip_handler(int fd, unsigned int frame, unsigned int tv_sec,
unsigned int tv_usec, void *event_data)
{
drmmode_flipevtcarrier_ptr flipcarrier = event_data;
- drmmode_ptr drmmode = flipcarrier->drmmode;
+ drmmode_flipdata_ptr flipdata = flipcarrier->flipdata;
+ drmmode_ptr drmmode = flipdata->drmmode;
/* Is this the event whose info shall be delivered to higher level? */
if (flipcarrier->dispatch_me) {
/* Yes: Cache msc, ust for later delivery. */
- drmmode->fe_frame = frame;
- drmmode->fe_tv_sec = tv_sec;
- drmmode->fe_tv_usec = tv_usec;
+ flipdata->fe_frame = frame;
+ flipdata->fe_tv_sec = tv_sec;
+ flipdata->fe_tv_usec = tv_usec;
}
free(flipcarrier);
/* Last crtc completed flip? */
- drmmode->flip_count--;
- if (drmmode->flip_count > 0)
+ flipdata->flip_count--;
+ if (flipdata->flip_count > 0)
return;
/* Release framebuffer */
- drmModeRmFB(drmmode->fd, drmmode->old_fb_id);
+ drmModeRmFB(drmmode->fd, flipdata->old_fb_id);
- if (drmmode->event_data == NULL)
+ if (flipdata->event_data == NULL)
return;
/* Deliver cached msc, ust from reference crtc to flip event handler */
- radeon_dri2_flip_event_handler(drmmode->fe_frame, drmmode->fe_tv_sec,
- drmmode->fe_tv_usec, drmmode->event_data);
+ radeon_dri2_flip_event_handler(flipdata->fe_frame, flipdata->fe_tv_sec,
+ flipdata->fe_tv_usec, flipdata->event_data);
+
+ free(flipdata);
}
@@ -1399,12 +1402,10 @@ Bool drmmode_pre_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int cpp)
xf86InitialConfiguration(pScrn, TRUE);
- drmmode->flip_count = 0;
drmmode->event_context.version = DRM_EVENT_CONTEXT_VERSION;
drmmode->event_context.vblank_handler = drmmode_vblank_handler;
drmmode->event_context.page_flip_handler = drmmode_flip_handler;
if (!pRADEONEnt->fd_wakeup_registered && info->dri->pKernelDRMVersion->version_minor >= 4) {
- drmmode->flip_count = 0;
AddGeneralSocket(drmmode->fd);
RegisterBlockAndWakeupHandlers((BlockHandlerProcPtr)NoopDDA,
drm_wakeup_handler, drmmode);
@@ -1654,6 +1655,7 @@ Bool radeon_do_pageflip(ScrnInfoPtr scrn, struct radeon_bo *new_front, void *dat
int i, old_fb_id;
uint32_t tiling_flags = 0;
int height;
+ drmmode_flipdata_ptr flipdata;
drmmode_flipevtcarrier_ptr flipcarrier;
if (info->allowColorTiling) {
@@ -1676,6 +1678,12 @@ Bool radeon_do_pageflip(ScrnInfoPtr scrn, struct radeon_bo *new_front, void *dat
new_front->handle, &drmmode->fb_id))
goto error_out;
+ flipdata = calloc(1, sizeof(drmmode_flipdata_rec));
+ if (!flipdata) {
+ xf86DrvMsg(scrn->scrnIndex, X_WARNING,
+ "flip queue: data alloc failed.\n");
+ goto error_undo;
+ }
/*
* Queue flips on all enabled CRTCs
* Note that if/when we get per-CRTC buffers, we'll have to update this.
@@ -1685,16 +1693,15 @@ Bool radeon_do_pageflip(ScrnInfoPtr scrn, struct radeon_bo *new_front, void *dat
* Also, flips queued on disabled or incorrectly configured displays
* may never complete; this is a configuration error.
*/
- drmmode->fe_frame = 0;
- drmmode->fe_tv_sec = 0;
- drmmode->fe_tv_usec = 0;
+
+ flipdata->event_data = data;
+ flipdata->drmmode = drmmode;
for (i = 0; i < config->num_crtc; i++) {
if (!config->crtc[i]->enabled)
continue;
- drmmode->event_data = data;
- drmmode->flip_count++;
+ flipdata->flip_count++;
drmmode_crtc = config->crtc[i]->driver_private;
flipcarrier = calloc(1, sizeof(drmmode_flipevtcarrier_rec));
@@ -1708,7 +1715,7 @@ Bool radeon_do_pageflip(ScrnInfoPtr scrn, struct radeon_bo *new_front, void *dat
* completion event. All other crtc's events will be discarded.
*/
flipcarrier->dispatch_me = (drmmode_crtc->hw_id == ref_crtc_hw_id);
- flipcarrier->drmmode = drmmode;
+ flipcarrier->flipdata = flipdata;
if (drmModePageFlip(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
drmmode->fb_id, DRM_MODE_PAGE_FLIP_EVENT, flipcarrier)) {
@@ -1719,7 +1726,7 @@ Bool radeon_do_pageflip(ScrnInfoPtr scrn, struct radeon_bo *new_front, void *dat
}
}
- drmmode->old_fb_id = old_fb_id;
+ flipdata->old_fb_id = old_fb_id;
return TRUE;
error_undo:
diff --git a/src/drmmode_display.h b/src/drmmode_display.h
index 548907b..eb271f5 100644
--- a/src/drmmode_display.h
+++ b/src/drmmode_display.h
@@ -39,7 +39,6 @@
typedef struct {
int fd;
unsigned fb_id;
- unsigned old_fb_id;
drmModeResPtr mode_res;
drmModeFBPtr mode_fb;
int cpp;
@@ -50,15 +49,20 @@ typedef struct {
InputHandlerProc uevent_handler;
#endif
drmEventContext event_context;
+} drmmode_rec, *drmmode_ptr;
+
+typedef struct {
+ drmmode_ptr drmmode;
+ unsigned old_fb_id;
int flip_count;
void *event_data;
unsigned int fe_frame;
unsigned int fe_tv_sec;
unsigned int fe_tv_usec;
-} drmmode_rec, *drmmode_ptr;
+} drmmode_flipdata_rec, *drmmode_flipdata_ptr;
typedef struct {
- drmmode_ptr drmmode;
+ drmmode_flipdata_ptr flipdata;
Bool dispatch_me;
} drmmode_flipevtcarrier_rec, *drmmode_flipevtcarrier_ptr;
commit 9493563c1ef4b51af0ee8a44cb4e7c5bb280347e
Author: Ville Syrjala <syrjala at sci.fi>
Date: Wed May 4 23:51:26 2011 +0300
dri2: Update front buffer pixmap and name before exchanging buffers
Buffer exchange assumes that the front buffer pixmap and name
information is accurate. That may not be the case eg. if the window
has been (un)redirected since the buffer was created.
Signed-off-by: Ville Syrjala <syrjala at sci.fi>
diff --git a/src/radeon_dri2.c b/src/radeon_dri2.c
index 1133319..46573a7 100644
--- a/src/radeon_dri2.c
+++ b/src/radeon_dri2.c
@@ -662,12 +662,42 @@ radeon_dri2_schedule_flip(ScrnInfoPtr scrn, ClientPtr client,
}
static Bool
-can_exchange(ScrnInfoPtr pScrn,
+update_front(DrawablePtr draw, DRI2BufferPtr front)
+{
+ int r;
+ PixmapPtr pixmap;
+ 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);
+
+ pixmap->refcnt++;
+
+ exaMoveInPixmap(pixmap);
+ driver_priv = exaGetPixmapDriverPrivate(pixmap);
+ r = radeon_gem_get_kernel_name(driver_priv->bo, &front->name);
+ if (r) {
+ (*draw->pScreen->DestroyPixmap)(pixmap);
+ return FALSE;
+ }
+ (*draw->pScreen->DestroyPixmap)(priv->pixmap);
+ front->pitch = pixmap->devKind;
+ front->cpp = pixmap->drawable.bitsPerPixel / 8;
+ priv->pixmap = pixmap;
+
+ return TRUE;
+}
+
+static Bool
+can_exchange(ScrnInfoPtr pScrn, DrawablePtr draw,
DRI2BufferPtr front, DRI2BufferPtr back)
{
struct dri2_buffer_priv *front_priv = front->driverPrivate;
struct dri2_buffer_priv *back_priv = back->driverPrivate;
- PixmapPtr front_pixmap = front_priv->pixmap;
+ PixmapPtr front_pixmap;
PixmapPtr back_pixmap = back_priv->pixmap;
xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
int i;
@@ -678,6 +708,11 @@ can_exchange(ScrnInfoPtr pScrn,
return FALSE;
}
+ if (!update_front(draw, front))
+ return FALSE;
+
+ front_pixmap = front_priv->pixmap;
+
if (front_pixmap->drawable.width != back_pixmap->drawable.width)
return FALSE;
@@ -757,7 +792,7 @@ void radeon_dri2_frame_event_handler(unsigned int frame, unsigned int tv_sec,
case DRI2_FLIP:
if (info->allowPageFlip &&
DRI2CanFlip(drawable) &&
- can_exchange(scrn, event->front, event->back) &&
+ can_exchange(scrn, drawable, event->front, event->back) &&
radeon_dri2_schedule_flip(scrn,
event->client,
drawable,
@@ -772,7 +807,7 @@ void radeon_dri2_frame_event_handler(unsigned int frame, unsigned int tv_sec,
/* else fall through to exchange/blit */
case DRI2_SWAP:
if (DRI2CanExchange(drawable) &&
- can_exchange(scrn, event->front, event->back)) {
+ can_exchange(scrn, drawable, event->front, event->back)) {
radeon_dri2_exchange_buffers(drawable, event->front, event->back);
swap_type = DRI2_EXCHANGE_COMPLETE;
} else {
@@ -1134,7 +1169,7 @@ static int radeon_dri2_schedule_swap(ClientPtr client, DrawablePtr draw,
/* Flips need to be submitted one frame before */
if (info->allowPageFlip &&
DRI2CanFlip(draw) &&
- can_exchange(scrn, front, back)) {
+ can_exchange(scrn, draw, front, back)) {
swap_type = DRI2_FLIP;
flip = 1;
}
More information about the xorg-commit
mailing list