#include <pciaccess.h>
+#include "state_tracker/drm_driver.h"
#include "pipe/p_context.h"
#include "xorg_tracker.h"
#include "xorg_winsys.h"
OPTION_SW_CURSOR,
OPTION_2D_ACCEL,
OPTION_DEBUG_FALLBACK,
+ OPTION_THROTTLE_SWAP,
+ OPTION_THROTTLE_DIRTY,
+ OPTION_3D_ACCEL
} drv_option_enums;
static const OptionInfoRec drv_options[] = {
{OPTION_SW_CURSOR, "SWcursor", OPTV_BOOLEAN, {0}, FALSE},
{OPTION_2D_ACCEL, "2DAccel", OPTV_BOOLEAN, {0}, FALSE},
{OPTION_DEBUG_FALLBACK, "DebugFallback", OPTV_BOOLEAN, {0}, FALSE},
+ {OPTION_THROTTLE_SWAP, "SwapThrottling", OPTV_BOOLEAN, {0}, FALSE},
+ {OPTION_THROTTLE_DIRTY, "DirtyThrottling", OPTV_BOOLEAN, {0}, FALSE},
+ {OPTION_3D_ACCEL, "3DAccel", OPTV_BOOLEAN, {0}, FALSE},
{-1, NULL, OPTV_NONE, {0}, FALSE}
};
static Bool drv_init_front_buffer_functions(ScrnInfoPtr pScrn);
static Bool drv_close_screen(int scrnIndex, ScreenPtr pScreen);
-static Bool drv_save_hw_state(ScrnInfoPtr pScrn);
-static Bool drv_restore_hw_state(ScrnInfoPtr pScrn);
/*
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;
+ CustomizerPtr cust = ms->cust;
ScreenPtr pScreen = pScrn->pScreen;
+ int old_width, old_height;
+ PixmapPtr rootPixmap;
+ int i;
if (width == pScrn->virtualX && height == pScrn->virtualY)
return TRUE;
+ if (cust && cust->winsys_check_fb_size &&
+ !cust->winsys_check_fb_size(cust, width*pScrn->bitsPerPixel / 8,
+ height)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Requested framebuffer size %dx%dx%d will not fit "
+ "in display memory.\n",
+ width, height, pScrn->bitsPerPixel);
+ return FALSE;
+ }
+
+ 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))
+ 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);
+
+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 = {
);
- ms->api = drm_api_create();
- ms->fd = drmOpen(ms->api ? ms->api->driver_name : NULL, BusID);
+ ms->fd = drmOpen(driver_descriptor.driver_name, BusID);
+ ms->isMaster = TRUE;
xfree(BusID);
if (ms->fd >= 0)
return TRUE;
- if (ms->api && ms->api->destroy)
- ms->api->destroy(ms->api);
-
- ms->api = NULL;
-
return FALSE;
}
return TRUE;
}
-static Bool
-drv_close_drm(ScrnInfoPtr pScrn)
-{
- modesettingPtr ms = modesettingPTR(pScrn);
-
- if (ms->api && ms->api->destroy)
- ms->api->destroy(ms->api);
- ms->api = NULL;
-
- drmClose(ms->fd);
- ms->fd = -1;
-
- return TRUE;
-}
-
static Bool
drv_init_resource_management(ScrnInfoPtr pScrn)
{
if (ms->screen || ms->kms)
return TRUE;
- if (ms->api) {
- ms->screen = ms->api->create_screen(ms->api, ms->fd, NULL);
-
- if (ms->screen)
- return TRUE;
-
- if (ms->api->destroy)
- ms->api->destroy(ms->api);
+ if (!ms->no3D)
+ ms->screen = driver_descriptor.create_screen(ms->fd);
- ms->api = NULL;
- }
+ if (ms->screen)
+ return TRUE;
#ifdef HAVE_LIBKMS
if (!kms_create(ms->fd, &ms->kms))
return FALSE;
}
-static Bool
-drv_close_resource_management(ScrnInfoPtr pScrn)
+static void
+drv_cleanup_fences(ScrnInfoPtr pScrn)
{
modesettingPtr ms = modesettingPTR(pScrn);
int i;
- if (ms->screen) {
- assert(ms->ctx == NULL);
+ assert(ms->screen);
- for (i = 0; i < XORG_NR_FENCES; i++) {
- if (ms->fence[i]) {
- ms->screen->fence_finish(ms->screen, ms->fence[i], 0);
- ms->screen->fence_reference(ms->screen, &ms->fence[i], NULL);
- }
+ for (i = 0; i < XORG_NR_FENCES; i++) {
+ if (ms->fence[i]) {
+ ms->screen->fence_finish(ms->screen, ms->fence[i], 0);
+ ms->screen->fence_reference(ms->screen, &ms->fence[i], NULL);
}
- ms->screen->destroy(ms->screen);
}
- ms->screen = NULL;
-
-#ifdef HAVE_LIBKMS
- if (ms->kms)
- kms_destroy(&ms->kms);
-#endif
-
- return TRUE;
}
static Bool
rgb defaultWeight = { 0, 0, 0 };
EntityInfoPtr pEnt;
EntPtr msEnt = NULL;
- int max_width, max_height;
CustomizerPtr cust;
+ Bool use3D;
if (pScrn->numEntities != 1)
return FALSE;
return FALSE;
ms = modesettingPTR(pScrn);
- ms->SaveGeneration = -1;
ms->pEnt = pEnt;
ms->cust = cust;
}
ms->fd = -1;
- ms->api = NULL;
if (!drv_init_drm(pScrn))
return FALSE;
+ use3D = cust ? !cust->no_3d : TRUE;
+ ms->from_3D = xf86GetOptValBool(ms->Options, OPTION_3D_ACCEL,
+ &use3D) ?
+ X_CONFIG : X_PROBED;
+
+ ms->no3D = !use3D;
+
+ if (!drv_init_resource_management(pScrn)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Could not init "
+ "Gallium3D or libKMS.");
+ return FALSE;
+ }
+
pScrn->monitor = pScrn->confScreen->monitor;
pScrn->progClock = TRUE;
pScrn->rgbBits = 8;
xf86CrtcConfigInit(pScrn, &crtc_config_funcs);
xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
- max_width = 8192;
- max_height = 8192;
- xf86CrtcSetSizeRange(pScrn, 320, 200, max_width, max_height);
+ /* get max width and height */
+ {
+ drmModeResPtr res;
+ int max_width, max_height;
+
+ res = drmModeGetResources(ms->fd);
+ max_width = res->max_width;
+ max_height = res->max_height;
+
+ if (ms->screen) {
+ int max;
+
+ max = ms->screen->get_param(ms->screen,
+ PIPE_CAP_MAX_TEXTURE_2D_LEVELS);
+ max = 1 << (max - 1);
+ max_width = max < max_width ? max : max_width;
+ max_height = max < max_height ? max : max_height;
+ }
+
+ drmModeFreeResources(res);
+ xf86CrtcSetSizeRange(pScrn, res->min_width,
+ res->min_height, max_width, max_height);
+ xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
+ "Min width %d, Max Width %d.\n",
+ res->min_width, max_width);
+ xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
+ "Min height %d, Max Height %d.\n",
+ res->min_height, max_height);
+ }
+
if (xf86ReturnOptValBool(ms->Options, OPTION_SW_CURSOR, FALSE)) {
ms->SWCursor = TRUE;
}
- drv_save_hw_state(pScrn);
-
xorg_crtc_init(pScrn);
xorg_output_init(pScrn);
+ if (cust && cust->winsys_pre_init && !cust->winsys_pre_init(cust, ms->fd))
+ return FALSE;
+
if (!xf86InitialConfiguration(pScrn, TRUE)) {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes.\n");
- drv_restore_hw_state(pScrn);
return FALSE;
}
- drv_restore_hw_state(pScrn);
-
/*
* If the driver can do gamma correction, it should call xf86SetGamma() here.
*/
return TRUE;
}
-static Bool
-drv_save_hw_state(ScrnInfoPtr pScrn)
-{
- /*xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);*/
-
- return TRUE;
-}
-
-static Bool
-drv_restore_hw_state(ScrnInfoPtr pScrn)
-{
- /*xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);*/
-
- return TRUE;
-}
-
static void drv_block_handler(int i, pointer blockData, pointer pTimeout,
pointer pReadmask)
{
if (ms->ctx) {
int j;
- ms->ctx->flush(ms->ctx, PIPE_FLUSH_RENDER_CACHE, &ms->fence[XORG_NR_FENCES-1]);
+ ms->ctx->flush(ms->ctx, PIPE_FLUSH_RENDER_CACHE,
+ ms->dirtyThrottling ?
+ &ms->fence[XORG_NR_FENCES-1] :
+ NULL);
- if (ms->fence[0])
- ms->ctx->screen->fence_finish(ms->ctx->screen, ms->fence[0], 0);
+ if (ms->dirtyThrottling) {
+ if (ms->fence[0])
+ ms->ctx->screen->fence_finish(ms->ctx->screen,
+ ms->fence[0], 0);
- /* The amount of rendering generated by a block handler can be
- * quite small. Let us get a fair way ahead of hardware before
- * throttling.
- */
- for (j = 0; j < XORG_NR_FENCES - 1; j++)
- ms->screen->fence_reference(ms->screen,
- &ms->fence[j],
- ms->fence[j+1]);
-
- ms->screen->fence_reference(ms->screen,
- &ms->fence[XORG_NR_FENCES-1],
- NULL);
+ /* The amount of rendering generated by a block handler can be
+ * quite small. Let us get a fair way ahead of hardware before
+ * throttling.
+ */
+ for (j = 0; j < XORG_NR_FENCES - 1; j++)
+ ms->screen->fence_reference(ms->screen,
+ &ms->fence[j],
+ ms->fence[j+1]);
+
+ ms->screen->fence_reference(ms->screen,
+ &ms->fence[XORG_NR_FENCES-1],
+ NULL);
+ }
}
return ret;
}
+static Bool
+drv_set_master(ScrnInfoPtr pScrn)
+{
+ modesettingPtr ms = modesettingPTR(pScrn);
+
+ if (!ms->isMaster && drmSetMaster(ms->fd) != 0) {
+ 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));
+ }
+ return FALSE;
+ }
+
+ ms->isMaster = TRUE;
+ return TRUE;
+}
+
+
static Bool
drv_screen_init(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
{
modesettingPtr ms = modesettingPTR(pScrn);
VisualPtr visual;
CustomizerPtr cust = ms->cust;
+ MessageType from_st;
+ MessageType from_dt;
- if (!drv_init_drm(pScrn)) {
- FatalError("Could not init DRM");
+ if (!drv_set_master(pScrn))
return FALSE;
- }
-
- if (!drv_init_resource_management(pScrn)) {
- FatalError("Could not init resource management (!pipe_screen && !libkms)");
- return FALSE;
- }
if (!drv_init_front_buffer_functions(pScrn)) {
FatalError("Could not init front buffer manager");
ms->accelerate_2d = xf86ReturnOptValBool(ms->Options, OPTION_2D_ACCEL, FALSE);
ms->debug_fallback = xf86ReturnOptValBool(ms->Options, OPTION_DEBUG_FALLBACK, ms->accelerate_2d);
+ if (cust && cust->winsys_screen_init)
+ cust->winsys_screen_init(cust);
+
+ ms->swapThrottling = cust ? cust->swap_throttling : TRUE;
+ from_st = xf86GetOptValBool(ms->Options, OPTION_THROTTLE_SWAP,
+ &ms->swapThrottling) ?
+ X_CONFIG : X_DEFAULT;
+
+ ms->dirtyThrottling = cust ? cust->dirty_throttling : TRUE;
+ from_dt = xf86GetOptValBool(ms->Options, OPTION_THROTTLE_DIRTY,
+ &ms->dirtyThrottling) ?
+ X_CONFIG : X_DEFAULT;
+
if (ms->screen) {
ms->exa = xorg_exa_init(pScrn, ms->accelerate_2d);
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Fallback debugging is %s\n",
ms->debug_fallback ? "enabled" : "disabled");
#ifdef DRI2
- xf86DrvMsg(pScrn->scrnIndex, X_INFO, "3D Acceleration is %s\n",
+ xf86DrvMsg(pScrn->scrnIndex, ms->from_3D, "3D Acceleration is %s\n",
ms->screen ? "enabled" : "disabled");
#else
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "3D Acceleration is disabled\n");
#endif
+ xf86DrvMsg(pScrn->scrnIndex, from_st, "Swap Throttling is %s.\n",
+ ms->swapThrottling ? "enabled" : "disabled");
+ xf86DrvMsg(pScrn->scrnIndex, from_dt, "Dirty Throttling is %s.\n",
+ ms->dirtyThrottling ? "enabled" : "disabled");
+
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "##################################\n");
miInitializeBackingStore(pScreen);
if (serverGeneration == 1)
xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
- if (cust && cust->winsys_screen_init)
- cust->winsys_screen_init(cust, ms->fd);
-
return drv_enter_vt(scrnIndex, 1);
}
}
drmModeRmFB(ms->fd, ms->fb_id);
+ ms->fb_id = -1;
- drv_restore_hw_state(pScrn);
+ /* idle hardware */
+ if (!ms->kms)
+ drv_cleanup_fences(pScrn);
if (drmDropMaster(ms->fd))
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
"drmDropMaster failed: %s\n", strerror(errno));
+ ms->isMaster = FALSE;
pScrn->vtSema = FALSE;
}
modesettingPtr ms = modesettingPTR(pScrn);
CustomizerPtr cust = ms->cust;
- 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.
- */
- if (ms->SaveGeneration != serverGeneration) {
- ms->SaveGeneration = serverGeneration;
- drv_save_hw_state(pScrn);
- }
+ if (!drv_set_master(pScrn))
+ return FALSE;
if (!ms->create_front_buffer(pScrn))
return FALSE;
modesettingPtr ms = modesettingPTR(pScrn);
CustomizerPtr cust = ms->cust;
- if (pScrn->vtSema) {
- drv_leave_vt(scrnIndex, 0);
+ if (ms->cursor) {
+ FreeCursor(ms->cursor, None);
+ ms->cursor = NULL;
}
if (cust && cust->winsys_screen_close)
xorg_exa_close(pScrn);
ms->exa = NULL;
- drv_close_resource_management(pScrn);
-
- drv_close_drm(pScrn);
+ /* calls drop master make sure we don't talk to 3D HW after that */
+ if (pScrn->vtSema) {
+ drv_leave_vt(scrnIndex, 0);
+ }
pScrn->vtSema = FALSE;
pScreen->CloseScreen = ms->CloseScreen;
+
return (*pScreen->CloseScreen) (scrnIndex, pScreen);
}
drv_destroy_front_buffer_ga3d(ScrnInfoPtr pScrn)
{
modesettingPtr ms = modesettingPTR(pScrn);
- pipe_texture_reference(&ms->root_texture, NULL);
+
+ if (!ms->root_texture)
+ return TRUE;
+
+ if (ms->fb_id != -1) {
+ drmModeRmFB(ms->fd, ms->fb_id);
+ ms->fb_id = -1;
+ }
+
+ pipe_resource_reference(&ms->root_texture, NULL);
return TRUE;
}
drv_create_front_buffer_ga3d(ScrnInfoPtr pScrn)
{
modesettingPtr ms = modesettingPTR(pScrn);
- unsigned handle, stride;
- struct pipe_texture *tex;
+ struct pipe_resource *tex;
+ struct winsys_handle whandle;
+ unsigned fb_id;
int ret;
ms->noEvict = TRUE;
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->resource_get_handle(ms->screen, tex, &whandle))
goto err_destroy;
ret = drmModeAddFB(ms->fd,
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);
+ pipe_resource_reference(&ms->root_texture, tex);
+ pipe_resource_reference(&tex, NULL);
+ ms->fb_id = fb_id;
return TRUE;
err_destroy:
- pipe_texture_reference(&tex, NULL);
+ pipe_resource_reference(&tex, NULL);
return FALSE;
}
modesettingPtr ms = modesettingPTR(pScrn);
ScreenPtr pScreen = pScrn->pScreen;
PixmapPtr rootPixmap = pScreen->GetScreenPixmap(pScreen);
- struct pipe_texture *check;
+ struct pipe_resource *check;
xorg_exa_set_displayed_usage(rootPixmap);
xorg_exa_set_shared_usage(rootPixmap);
if (ms->root_texture != check)
FatalError("Created new root texture\n");
- pipe_texture_reference(&check, NULL);
+ pipe_resource_reference(&check, NULL);
return TRUE;
}
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;
unsigned handle, stride;
struct kms_bo *bo;
unsigned attr[8];
+ unsigned fb_id;
int ret;
attr[0] = KMS_BO_TYPE;
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;