Merge branch '7.8'
[mesa.git] / src / gallium / state_trackers / xorg / xorg_driver.c
index 62cf2e0006c74961c46f330ebb2f28afe19d8ab8..8ac5179545a1fb147b9bc2daf8eacaaa76a4710f 100644 (file)
@@ -183,31 +183,66 @@ drv_probe_ddc(ScrnInfoPtr pScrn, int index)
 static Bool
 drv_crtc_resize(ScrnInfoPtr pScrn, int width, int height)
 {
+    xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
     modesettingPtr ms = modesettingPTR(pScrn);
-    PixmapPtr rootPixmap;
     ScreenPtr pScreen = pScrn->pScreen;
+    int old_width, old_height;
+    PixmapPtr rootPixmap;
+    int i;
 
     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);
+
+    if (!ms->create_front_buffer(pScrn) || !ms->bind_front_buffer(pScrn))
+       goto error_create;
+
+    /*
+     * create && bind will turn off all crtc(s) in the kernel so we need to
+     * re-enable all the crtcs again. For real HW we might want to do this
+     * before destroying the old framebuffer.
+     */
+    for (i = 0; i < xf86_config->num_crtc; i++) {
+       xf86CrtcPtr crtc = xf86_config->crtc[i];
+
+       if (!crtc->enabled)
+           continue;
+
+       crtc->funcs->set_mode_major(crtc, &crtc->mode, crtc->rotation, crtc->x, crtc->y);
+    }
+
+    return TRUE;
+
+    /*
+     * This is the error recovery path.
+     */
+error_create:
+    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);
 
-    /* now create new frontbuffer */
-    return ms->create_front_buffer(pScrn) && ms->bind_front_buffer(pScrn);
+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 +847,7 @@ drv_leave_vt(int scrnIndex, int flags)
     }
 
     drmModeRmFB(ms->fd, ms->fb_id);
+    ms->fb_id = -1;
 
     drv_restore_hw_state(pScrn);
 
@@ -886,6 +922,11 @@ drv_close_screen(int scrnIndex, ScreenPtr pScreen)
        drv_leave_vt(scrnIndex, 0);
     }
 
+    if (ms->cursor) {
+       FreeCursor(ms->cursor, None);
+       ms->cursor = NULL;
+    }
+
     if (cust && cust->winsys_screen_close)
        cust->winsys_screen_close(cust);
 
@@ -936,6 +977,15 @@ static Bool
 drv_destroy_front_buffer_ga3d(ScrnInfoPtr pScrn)
 {
     modesettingPtr ms = modesettingPTR(pScrn);
+
+    if (!ms->root_texture)
+       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,8 +994,9 @@ static Bool
 drv_create_front_buffer_ga3d(ScrnInfoPtr pScrn)
 {
     modesettingPtr ms = modesettingPTR(pScrn);
-    unsigned handle, stride;
     struct pipe_texture *tex;
+    struct winsys_handle whandle;
+    unsigned fb_id;
     int ret;
 
     ms->noEvict = TRUE;
@@ -956,10 +1007,10 @@ drv_create_front_buffer_ga3d(ScrnInfoPtr pScrn)
     if (!tex)
        return FALSE;
 
-    if (!ms->api->local_handle_from_texture(ms->api, ms->screen,
-                                           tex,
-                                           &stride,
-                                           &handle))
+    memset(&whandle, 0, sizeof(whandle));
+    whandle.type = DRM_API_HANDLE_TYPE_KMS;
+
+    if (!ms->screen->texture_get_handle(ms->screen, tex, &whandle))
        goto err_destroy;
 
     ret = drmModeAddFB(ms->fd,
@@ -967,21 +1018,25 @@ drv_create_front_buffer_ga3d(ScrnInfoPtr pScrn)
                       pScrn->virtualY,
                       pScrn->depth,
                       pScrn->bitsPerPixel,
-                      stride,
-                      handle,
-                      &ms->fb_id);
+                      whandle.stride,
+                      whandle.handle,
+                      &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 +1084,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 +1101,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 +1132,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;