drm_intel_bo *intel_allocate_framebuffer(ScrnInfoPtr scrn,
					 int width, int height, int cpp,
					 int *out_stride,
					 uint32_t *out_tiling)
{
	intel_screen_private *intel = intel_get_screen_private(scrn);
	uint32_t tiling;
	int stride, size;
	drm_intel_bo *bo;

	intel_set_gem_max_sizes(scrn);

	if (intel->tiling & INTEL_TILING_FB)
		tiling = I915_TILING_X;
	else
		tiling = I915_TILING_NONE;

retry:
	size = intel_compute_size(intel,
                                  width, height,
                                  intel->cpp*8, 0,
                                  &tiling, &stride);
	if (!intel_check_display_stride(scrn, stride, tiling)) {
		if (tiling != I915_TILING_NONE) {
			tiling = I915_TILING_NONE;
			goto retry;
		}

		xf86DrvMsg(scrn->scrnIndex, X_ERROR,
			   "Front buffer stride %d kB "
			   "exceeds display limit\n", stride / 1024);
		return NULL;
	}

	bo = drm_intel_bo_alloc(intel->bufmgr, "front buffer", size, 0);
	if (bo == NULL)
		return FALSE;

	if (tiling != I915_TILING_NONE)
		drm_intel_bo_set_tiling(bo, &tiling, stride);

	xf86DrvMsg(scrn->scrnIndex, X_INFO,
		   "Allocated new frame buffer %dx%d stride %d, %s\n",
		   width, height, stride,
		   tiling == I915_TILING_NONE ? "untiled" : "tiled");

	drm_intel_bo_disable_reuse(bo);

	*out_stride = stride;
	*out_tiling = tiling;
	return bo;
}
static Bool
drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
		       Rotation rotation, int x, int y)
{
	ScrnInfoPtr scrn = crtc->scrn;
	intel_screen_private *intel = intel_get_screen_private(scrn);
	xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
	drmmode_ptr drmmode = drmmode_crtc->drmmode;
	int saved_x, saved_y;
	Rotation saved_rotation;
	DisplayModeRec saved_mode;
	uint32_t *output_ids;
	int output_count = 0;
	int ret = TRUE;
	int i;
	int fb_id;
	drmModeModeInfo kmode;
	unsigned int pitch = scrn->displayWidth * intel->cpp;

	if (drmmode->fb_id == 0) {
		ret = drmModeAddFB(drmmode->fd,
				   scrn->virtualX, scrn->virtualY,
				   scrn->depth, scrn->bitsPerPixel,
				   pitch, intel->front_buffer->handle,
				   &drmmode->fb_id);
		if (ret < 0) {
			ErrorF("failed to add fb\n");
			return FALSE;
		}
	}

	saved_mode = crtc->mode;
	saved_x = crtc->x;
	saved_y = crtc->y;
	saved_rotation = crtc->rotation;

	crtc->mode = *mode;
	crtc->x = x;
	crtc->y = y;
	crtc->rotation = rotation;

	output_ids = calloc(sizeof(uint32_t), xf86_config->num_output);
	if (!output_ids) {
		ret = FALSE;
		goto done;
	}

	for (i = 0; i < xf86_config->num_output; i++) {
		xf86OutputPtr output = xf86_config->output[i];
		drmmode_output_private_ptr drmmode_output;

		if (output->crtc != crtc)
			continue;

		drmmode_output = output->driver_private;
		output_ids[output_count] =
			drmmode_output->mode_output->connector_id;
		output_count++;
	}

#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1,5,99,0,0)
	if (!xf86CrtcRotate(crtc, mode, rotation))
		goto done;
#else
	if (!xf86CrtcRotate(crtc))
		goto done;
#endif

#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,7,0,0,0)
	crtc->funcs->gamma_set(crtc, crtc->gamma_red, crtc->gamma_green,
			       crtc->gamma_blue, crtc->gamma_size);
#endif

	drmmode_ConvertToKMode(crtc->scrn, &kmode, mode);


	fb_id = drmmode->fb_id;
	if (drmmode_crtc->rotate_fb_id) {
		fb_id = drmmode_crtc->rotate_fb_id;
		x = 0;
		y = 0;
	}
	ret = drmModeSetCrtc(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
			     fb_id, x, y, output_ids, output_count, &kmode);
	if (ret)
		xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR,
			   "failed to set mode: %s", strerror(-ret));
	else
		ret = TRUE;

	/* Turn on any outputs on this crtc that may have been disabled */
	for (i = 0; i < xf86_config->num_output; i++) {
		xf86OutputPtr output = xf86_config->output[i];

		if (output->crtc != crtc)
			continue;

		drmmode_output_dpms(output, DPMSModeOn);
	}

	intel_set_gem_max_sizes(scrn);

	if (scrn->pScreen)
		xf86_reload_cursors(scrn->pScreen);
done:
	if (!ret) {
		crtc->x = saved_x;
		crtc->y = saved_y;
		crtc->rotation = saved_rotation;
		crtc->mode = saved_mode;
	}
	return ret;
}