summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakob Bornecrantz <jakob@vmware.com>2010-02-22 14:47:15 +0100
committerJakob Bornecrantz <jakob@vmware.com>2010-02-22 19:34:56 +0100
commit1702db3a35e0be1934a78bea80bb0691eb0b773a (patch)
tree31d0eca067b34e314917d2f016bc5960a167a8ed
parentfa6eee135e2bc055c0a2b9a37b7e2dcdda316c03 (diff)
st/xorg: Make resize fail gracefully
-rw-r--r--src/gallium/state_trackers/xorg/xorg_driver.c69
1 files changed, 55 insertions, 14 deletions
diff --git a/src/gallium/state_trackers/xorg/xorg_driver.c b/src/gallium/state_trackers/xorg/xorg_driver.c
index 62cf2e0006..4f99e0001b 100644
--- a/src/gallium/state_trackers/xorg/xorg_driver.c
+++ b/src/gallium/state_trackers/xorg/xorg_driver.c
@@ -184,30 +184,47 @@ static Bool
drv_crtc_resize(ScrnInfoPtr pScrn, int width, int height)
{
modesettingPtr ms = modesettingPTR(pScrn);
- PixmapPtr rootPixmap;
ScreenPtr pScreen = pScrn->pScreen;
+ int old_width, old_height;
+ PixmapPtr rootPixmap;
if (width == pScrn->virtualX && height == pScrn->virtualY)
return TRUE;
+ old_width = pScrn->virtualX;
+ old_height = pScrn->virtualY;
pScrn->virtualX = width;
pScrn->virtualY = height;
- /*
- * Remove the old framebuffer & texture.
- */
- drmModeRmFB(ms->fd, ms->fb_id);
- if (!ms->destroy_front_buffer(pScrn))
- FatalError("failed to destroy front buffer\n");
+ /* ms->create_front_buffer will remove the old front buffer */
rootPixmap = pScreen->GetScreenPixmap(pScreen);
if (!pScreen->ModifyPixmapHeader(rootPixmap, width, height, -1, -1, -1, NULL))
- return FALSE;
+ goto error_modify;
pScrn->displayWidth = rootPixmap->devKind / (rootPixmap->drawable.bitsPerPixel / 8);
- /* now create new frontbuffer */
- return ms->create_front_buffer(pScrn) && ms->bind_front_buffer(pScrn);
+ if (ms->create_front_buffer(pScrn) && ms->bind_front_buffer(pScrn))
+ return TRUE;
+
+ /*
+ * This is the error recovery path.
+ */
+
+ if (!pScreen->ModifyPixmapHeader(rootPixmap, old_width, old_height, -1, -1, -1, NULL))
+ FatalError("failed to resize rootPixmap error path\n");
+
+ pScrn->displayWidth = rootPixmap->devKind / (rootPixmap->drawable.bitsPerPixel / 8);
+
+error_modify:
+ pScrn->virtualX = old_width;
+ pScrn->virtualY = old_height;
+
+ if (ms->create_front_buffer(pScrn) && ms->bind_front_buffer(pScrn))
+ return FALSE;
+
+ FatalError("failed to setup old framebuffer\n");
+ return FALSE;
}
static const xf86CrtcConfigFuncsRec crtc_config_funcs = {
@@ -812,6 +829,7 @@ drv_leave_vt(int scrnIndex, int flags)
}
drmModeRmFB(ms->fd, ms->fb_id);
+ ms->fb_id = -1;
drv_restore_hw_state(pScrn);
@@ -936,6 +954,15 @@ static Bool
drv_destroy_front_buffer_ga3d(ScrnInfoPtr pScrn)
{
modesettingPtr ms = modesettingPTR(pScrn);
+
+ if (!ms->root_bo)
+ return TRUE;
+
+ if (ms->fb_id != -1) {
+ drmModeRmFB(ms->fd, ms->fb_id);
+ ms->fb_id = -1;
+ }
+
pipe_texture_reference(&ms->root_texture, NULL);
return TRUE;
}
@@ -944,7 +971,7 @@ static Bool
drv_create_front_buffer_ga3d(ScrnInfoPtr pScrn)
{
modesettingPtr ms = modesettingPTR(pScrn);
- unsigned handle, stride;
+ unsigned handle, stride, fb_id;
struct pipe_texture *tex;
int ret;
@@ -969,19 +996,23 @@ drv_create_front_buffer_ga3d(ScrnInfoPtr pScrn)
pScrn->bitsPerPixel,
stride,
handle,
- &ms->fb_id);
+ &fb_id);
if (ret) {
- debug_printf("%s: failed to create framebuffer (%i, %s)",
+ debug_printf("%s: failed to create framebuffer (%i, %s)\n",
__func__, ret, strerror(-ret));
goto err_destroy;
}
+ if (!drv_destroy_front_buffer_ga3d(pScrn))
+ FatalError("%s: failed to take down old framebuffer\n", __func__);
+
pScrn->frameX0 = 0;
pScrn->frameY0 = 0;
drv_adjust_frame(pScrn->scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
pipe_texture_reference(&ms->root_texture, tex);
pipe_texture_reference(&tex, NULL);
+ ms->fb_id = fb_id;
return TRUE;
@@ -1029,6 +1060,11 @@ drv_destroy_front_buffer_kms(ScrnInfoPtr pScrn)
if (!ms->root_bo)
return TRUE;
+ if (ms->fb_id != -1) {
+ drmModeRmFB(ms->fd, ms->fb_id);
+ ms->fb_id = -1;
+ }
+
kms_bo_unmap(ms->root_bo);
kms_bo_destroy(&ms->root_bo);
return TRUE;
@@ -1041,6 +1077,7 @@ drv_create_front_buffer_kms(ScrnInfoPtr pScrn)
unsigned handle, stride;
struct kms_bo *bo;
unsigned attr[8];
+ unsigned fb_id;
int ret;
attr[0] = KMS_BO_TYPE;
@@ -1071,17 +1108,21 @@ drv_create_front_buffer_kms(ScrnInfoPtr pScrn)
pScrn->bitsPerPixel,
stride,
handle,
- &ms->fb_id);
+ &fb_id);
if (ret) {
debug_printf("%s: failed to create framebuffer (%i, %s)",
__func__, ret, strerror(-ret));
goto err_destroy;
}
+ if (!drv_destroy_front_buffer_kms(pScrn))
+ FatalError("%s: could not takedown old bo", __func__);
+
pScrn->frameX0 = 0;
pScrn->frameY0 = 0;
drv_adjust_frame(pScrn->scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
ms->root_bo = bo;
+ ms->fb_id = fb_id;
return TRUE;