amdgpu_kms.c revision 46845023
1/*
2 * Copyright © 2009 Red Hat, Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 * SOFTWARE.
22 *
23 * Authors:
24 *    Dave Airlie <airlied@redhat.com>
25 *
26 */
27#ifdef HAVE_CONFIG_H
28#include "config.h"
29#endif
30
31#include <errno.h>
32#include <sys/ioctl.h>
33/* Driver data structures */
34#include "amdgpu_drv.h"
35#include "amdgpu_bo_helper.h"
36#include "amdgpu_drm_queue.h"
37#include "amdgpu_glamor.h"
38#include "amdgpu_probe.h"
39#include "micmap.h"
40#include "mipointrst.h"
41
42#include "amdgpu_version.h"
43#include "shadow.h"
44#include <xf86Priv.h>
45
46#if HAVE_PRESENT_H
47#include <present.h>
48#endif
49
50/* DPMS */
51#ifdef HAVE_XEXTPROTO_71
52#include <X11/extensions/dpmsconst.h>
53#else
54#define DPMS_SERVER
55#include <X11/extensions/dpms.h>
56#endif
57
58#include <X11/extensions/damageproto.h>
59
60#include "amdgpu_bo_helper.h"
61#include "amdgpu_pixmap.h"
62
63#include <gbm.h>
64
65static DevPrivateKeyRec amdgpu_window_private_key;
66static DevScreenPrivateKeyRec amdgpu_client_private_key;
67DevScreenPrivateKeyRec amdgpu_device_private_key;
68
69static Atom amdgpu_vrr_atom;
70static Bool amdgpu_property_vectors_wrapped;
71static Bool restore_property_vector;
72static int (*saved_change_property) (ClientPtr client);
73static int (*saved_delete_property) (ClientPtr client);
74
75static Bool amdgpu_setup_kernel_mem(ScreenPtr pScreen);
76
77const OptionInfoRec AMDGPUOptions_KMS[] = {
78	{OPTION_ACCEL, "Accel", OPTV_BOOLEAN, {0}, FALSE},
79	{OPTION_SW_CURSOR, "SWcursor", OPTV_BOOLEAN, {0}, FALSE},
80	{OPTION_PAGE_FLIP, "EnablePageFlip", OPTV_BOOLEAN, {0}, FALSE},
81	{OPTION_SUBPIXEL_ORDER, "SubPixelOrder", OPTV_ANYSTR, {0}, FALSE},
82	{OPTION_ZAPHOD_HEADS, "ZaphodHeads", OPTV_STRING, {0}, FALSE},
83	{OPTION_ACCEL_METHOD, "AccelMethod", OPTV_STRING, {0}, FALSE},
84	{OPTION_DRI3, "DRI3", OPTV_BOOLEAN, {0}, FALSE},
85	{OPTION_DRI, "DRI", OPTV_INTEGER, {0}, FALSE},
86	{OPTION_SHADOW_PRIMARY, "ShadowPrimary", OPTV_BOOLEAN, {0}, FALSE},
87	{OPTION_TEAR_FREE, "TearFree", OPTV_BOOLEAN, {0}, FALSE},
88	{OPTION_DELETE_DP12, "DeleteUnusedDP12Displays", OPTV_BOOLEAN, {0}, FALSE},
89	{OPTION_VARIABLE_REFRESH, "VariableRefresh", OPTV_BOOLEAN, {0}, FALSE },
90	{-1, NULL, OPTV_NONE, {0}, FALSE}
91};
92
93const OptionInfoRec *AMDGPUOptionsWeak(void)
94{
95	return AMDGPUOptions_KMS;
96}
97
98static inline struct amdgpu_window_priv *get_window_priv(WindowPtr win) {
99	return dixLookupPrivate(&win->devPrivates, &amdgpu_window_private_key);
100}
101
102static void
103amdgpu_vrr_property_update(WindowPtr window, Bool variable_refresh)
104{
105	ScrnInfoPtr scrn = xf86ScreenToScrn(window->drawable.pScreen);
106	AMDGPUInfoPtr info = AMDGPUPTR(scrn);
107
108	get_window_priv(window)->variable_refresh = variable_refresh;
109
110	if (info->flip_window == window &&
111	    info->drmmode.present_flipping)
112		amdgpu_present_set_screen_vrr(scrn, variable_refresh);
113}
114
115/* Wrapper for xserver/dix/property.c:ProcChangeProperty */
116static int
117amdgpu_change_property(ClientPtr client)
118{
119	WindowPtr window;
120	int ret;
121
122	REQUEST(xChangePropertyReq);
123
124	client->requestVector[X_ChangeProperty] = saved_change_property;
125	ret = saved_change_property(client);
126
127	if (restore_property_vector)
128		return ret;
129
130	client->requestVector[X_ChangeProperty] = amdgpu_change_property;
131
132	if (ret != Success)
133		return ret;
134
135	ret = dixLookupWindow(&window, stuff->window, client, DixSetPropAccess);
136	if (ret != Success)
137		return ret;
138
139	if (stuff->property == amdgpu_vrr_atom &&
140	    xf86ScreenToScrn(window->drawable.pScreen)->PreInit ==
141	    AMDGPUPreInit_KMS && stuff->format == 32 && stuff->nUnits == 1) {
142		uint32_t *value = (uint32_t*)(stuff + 1);
143
144		amdgpu_vrr_property_update(window, *value != 0);
145	}
146
147	return ret;
148}
149
150/* Wrapper for xserver/dix/property.c:ProcDeleteProperty */
151static int
152amdgpu_delete_property(ClientPtr client)
153{
154	WindowPtr window;
155	int ret;
156
157	REQUEST(xDeletePropertyReq);
158
159	client->requestVector[X_DeleteProperty] = saved_delete_property;
160	ret = saved_delete_property(client);
161
162	if (restore_property_vector)
163		return ret;
164
165	client->requestVector[X_DeleteProperty] = amdgpu_delete_property;
166
167	if (ret != Success)
168		return ret;
169
170	ret = dixLookupWindow(&window, stuff->window, client, DixSetPropAccess);
171	if (ret != Success)
172		return ret;
173
174	if (stuff->property == amdgpu_vrr_atom &&
175	    xf86ScreenToScrn(window->drawable.pScreen)->PreInit ==
176	    AMDGPUPreInit_KMS)
177		amdgpu_vrr_property_update(window, FALSE);
178
179	return ret;
180}
181
182static void
183amdgpu_unwrap_property_requests(ScrnInfoPtr scrn)
184{
185	int i;
186
187	if (!amdgpu_property_vectors_wrapped)
188		return;
189
190	if (ProcVector[X_ChangeProperty] == amdgpu_change_property)
191		ProcVector[X_ChangeProperty] = saved_change_property;
192	else
193		restore_property_vector = TRUE;
194
195	if (ProcVector[X_DeleteProperty] == amdgpu_delete_property)
196		ProcVector[X_DeleteProperty] = saved_delete_property;
197	else
198		restore_property_vector = TRUE;
199
200	for (i = 0; i < currentMaxClients; i++) {
201		if (clients[i]->requestVector[X_ChangeProperty] ==
202		    amdgpu_change_property) {
203			clients[i]->requestVector[X_ChangeProperty] =
204				saved_change_property;
205		} else {
206			restore_property_vector = TRUE;
207		}
208
209		if (clients[i]->requestVector[X_DeleteProperty] ==
210		    amdgpu_delete_property) {
211			clients[i]->requestVector[X_DeleteProperty] =
212				saved_delete_property;
213		} else {
214			restore_property_vector = TRUE;
215		}
216	}
217
218	if (restore_property_vector) {
219		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
220			   "Couldn't unwrap some window property request vectors\n");
221	}
222
223	amdgpu_property_vectors_wrapped = FALSE;
224}
225
226extern _X_EXPORT int gAMDGPUEntityIndex;
227
228static int getAMDGPUEntityIndex(void)
229{
230	return gAMDGPUEntityIndex;
231}
232
233AMDGPUEntPtr AMDGPUEntPriv(ScrnInfoPtr pScrn)
234{
235	DevUnion *pPriv;
236	AMDGPUInfoPtr info = AMDGPUPTR(pScrn);
237	pPriv = xf86GetEntityPrivate(info->pEnt->index, getAMDGPUEntityIndex());
238	return pPriv->ptr;
239}
240
241/* Allocate our private AMDGPUInfoRec */
242static Bool AMDGPUGetRec(ScrnInfoPtr pScrn)
243{
244	if (pScrn->driverPrivate)
245		return TRUE;
246
247	pScrn->driverPrivate = xnfcalloc(sizeof(AMDGPUInfoRec), 1);
248	return TRUE;
249}
250
251/* Free our private AMDGPUInfoRec */
252static void AMDGPUFreeRec(ScrnInfoPtr pScrn)
253{
254	DevUnion *pPriv;
255	AMDGPUEntPtr pAMDGPUEnt;
256	AMDGPUInfoPtr info;
257	EntityInfoPtr pEnt;
258
259	if (!pScrn)
260		return;
261
262	pEnt = xf86GetEntityInfo(pScrn->entityList[pScrn->numEntities - 1]);
263	pPriv = xf86GetEntityPrivate(pEnt->index, gAMDGPUEntityIndex);
264	pAMDGPUEnt = pPriv->ptr;
265
266	info = AMDGPUPTR(pScrn);
267	if (info) {
268		pAMDGPUEnt->scrn[info->instance_id] = NULL;
269		pAMDGPUEnt->num_scrns--;
270		free(pScrn->driverPrivate);
271		pScrn->driverPrivate = NULL;
272	}
273
274	if (pAMDGPUEnt->fd > 0) {
275		DevUnion *pPriv;
276		AMDGPUEntPtr pAMDGPUEnt;
277		pPriv = xf86GetEntityPrivate(pScrn->entityList[0],
278					     getAMDGPUEntityIndex());
279
280		pAMDGPUEnt = pPriv->ptr;
281		pAMDGPUEnt->fd_ref--;
282		if (!pAMDGPUEnt->fd_ref) {
283			amdgpu_unwrap_property_requests(pScrn);
284			amdgpu_device_deinitialize(pAMDGPUEnt->pDev);
285			amdgpu_kernel_close_fd(pAMDGPUEnt);
286			free(pAMDGPUEnt->busid);
287			free(pPriv->ptr);
288			pPriv->ptr = NULL;
289		}
290	}
291
292	free(pEnt);
293}
294
295Bool amdgpu_window_has_variable_refresh(WindowPtr win) {
296	struct amdgpu_window_priv *priv = get_window_priv(win);
297
298	return priv->variable_refresh;
299}
300
301static void *amdgpuShadowWindow(ScreenPtr screen, CARD32 row, CARD32 offset,
302				int mode, CARD32 * size, void *closure)
303{
304	ScrnInfoPtr pScrn = xf86ScreenToScrn(screen);
305	AMDGPUInfoPtr info = AMDGPUPTR(pScrn);
306	int stride;
307
308	stride = (pScrn->displayWidth * pScrn->bitsPerPixel) / 8;
309	*size = stride;
310
311	return ((uint8_t *) info->front_buffer->cpu_ptr + row * stride + offset);
312}
313
314static void
315amdgpuUpdatePacked(ScreenPtr pScreen, shadowBufPtr pBuf)
316{
317	shadowUpdatePacked(pScreen, pBuf);
318}
319
320static Bool
321callback_needs_flush(AMDGPUInfoPtr info, struct amdgpu_client_priv *client_priv)
322{
323	return (int)(client_priv->needs_flush - info->gpu_flushed) > 0;
324}
325
326static void
327amdgpu_event_callback(CallbackListPtr *list,
328		      pointer user_data, pointer call_data)
329{
330	EventInfoRec *eventinfo = call_data;
331	ScrnInfoPtr pScrn = user_data;
332	ScreenPtr pScreen = pScrn->pScreen;
333	struct amdgpu_client_priv *client_priv =
334		dixLookupScreenPrivate(&eventinfo->client->devPrivates,
335				       &amdgpu_client_private_key, pScreen);
336	struct amdgpu_client_priv *server_priv =
337		dixLookupScreenPrivate(&serverClient->devPrivates,
338				       &amdgpu_client_private_key, pScreen);
339	AMDGPUInfoPtr info = AMDGPUPTR(pScrn);
340	int i;
341
342	if (callback_needs_flush(info, client_priv) ||
343	    callback_needs_flush(info, server_priv))
344		return;
345
346	/* Don't let gpu_flushed get too far ahead of needs_flush, in order
347	 * to prevent false positives in callback_needs_flush()
348	 */
349	client_priv->needs_flush = info->gpu_flushed;
350	server_priv->needs_flush = info->gpu_flushed;
351
352	for (i = 0; i < eventinfo->count; i++) {
353		if (eventinfo->events[i].u.u.type == info->callback_event_type) {
354			client_priv->needs_flush++;
355			server_priv->needs_flush++;
356			return;
357		}
358	}
359}
360
361static void
362amdgpu_flush_callback(CallbackListPtr *list,
363		      pointer user_data, pointer call_data)
364{
365	ScrnInfoPtr pScrn = user_data;
366	ScreenPtr pScreen = pScrn->pScreen;
367	ClientPtr client = call_data ? call_data : serverClient;
368	struct amdgpu_client_priv *client_priv =
369		dixLookupScreenPrivate(&client->devPrivates,
370				       &amdgpu_client_private_key, pScreen);
371	AMDGPUInfoPtr info = AMDGPUPTR(pScrn);
372
373	if (pScrn->vtSema && callback_needs_flush(info, client_priv))
374		amdgpu_glamor_flush(pScrn);
375}
376
377static Bool AMDGPUCreateScreenResources_KMS(ScreenPtr pScreen)
378{
379	ExtensionEntry *damage_ext;
380	ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
381	AMDGPUInfoPtr info = AMDGPUPTR(pScrn);
382	PixmapPtr pixmap;
383
384	pScreen->CreateScreenResources = info->CreateScreenResources;
385	if (!(*pScreen->CreateScreenResources) (pScreen))
386		return FALSE;
387	pScreen->CreateScreenResources = AMDGPUCreateScreenResources_KMS;
388
389	/* Set the RandR primary output if Xorg hasn't */
390	if (dixPrivateKeyRegistered(rrPrivKey)) {
391		rrScrPrivPtr rrScrPriv = rrGetScrPriv(pScreen);
392
393		if (!pScreen->isGPU && !rrScrPriv->primaryOutput) {
394			xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
395
396			rrScrPriv->primaryOutput = xf86_config->output[0]->randr_output;
397			RROutputChanged(rrScrPriv->primaryOutput, FALSE);
398			rrScrPriv->layoutChanged = TRUE;
399		}
400
401		drmmode_uevent_init(pScrn, &info->drmmode);
402	}
403
404	if (!drmmode_set_desired_modes(pScrn, &info->drmmode, pScreen->isGPU))
405		return FALSE;
406
407	if (info->shadow_fb) {
408		pixmap = pScreen->GetScreenPixmap(pScreen);
409
410		if (!shadowAdd(pScreen, pixmap, amdgpuUpdatePacked,
411			       amdgpuShadowWindow, 0, NULL))
412			return FALSE;
413	}
414
415	if (info->dri2.enabled || info->use_glamor) {
416		if (info->front_buffer) {
417			PixmapPtr pPix = pScreen->GetScreenPixmap(pScreen);
418
419			if (!amdgpu_set_pixmap_bo(pPix, info->front_buffer))
420				return FALSE;
421		}
422	}
423
424	if (info->use_glamor)
425		amdgpu_glamor_create_screen_resources(pScreen);
426
427	info->callback_event_type = -1;
428	if (!pScreen->isGPU && (damage_ext = CheckExtension("DAMAGE"))) {
429		info->callback_event_type = damage_ext->eventBase + XDamageNotify;
430
431		if (!AddCallback(&FlushCallback, amdgpu_flush_callback, pScrn))
432			return FALSE;
433
434		if (!AddCallback(&EventCallback, amdgpu_event_callback, pScrn)) {
435			DeleteCallback(&FlushCallback, amdgpu_flush_callback, pScrn);
436			return FALSE;
437		}
438
439		if (!dixRegisterScreenPrivateKey(&amdgpu_client_private_key, pScreen,
440						 PRIVATE_CLIENT, sizeof(struct amdgpu_client_priv))) {
441			DeleteCallback(&FlushCallback, amdgpu_flush_callback, pScrn);
442			DeleteCallback(&EventCallback, amdgpu_event_callback, pScrn);
443			return FALSE;
444		}
445	}
446
447	if (info->vrr_support &&
448	    !dixRegisterPrivateKey(&amdgpu_window_private_key,
449				   PRIVATE_WINDOW,
450				   sizeof(struct amdgpu_window_priv)))
451		return FALSE;
452
453	return TRUE;
454}
455
456static Bool
457amdgpu_scanout_extents_intersect(xf86CrtcPtr xf86_crtc, BoxPtr extents)
458{
459	if (xf86_crtc->scrn->is_gpu) {
460		extents->x1 -= xf86_crtc->x;
461		extents->y1 -= xf86_crtc->y;
462		extents->x2 -= xf86_crtc->x;
463		extents->y2 -= xf86_crtc->y;
464	} else {
465		extents->x1 -= xf86_crtc->filter_width >> 1;
466		extents->x2 += xf86_crtc->filter_width >> 1;
467		extents->y1 -= xf86_crtc->filter_height >> 1;
468		extents->y2 += xf86_crtc->filter_height >> 1;
469		pixman_f_transform_bounds(&xf86_crtc->f_framebuffer_to_crtc, extents);
470	}
471
472	extents->x1 = max(extents->x1, 0);
473	extents->y1 = max(extents->y1, 0);
474	extents->x2 = min(extents->x2, xf86_crtc->mode.HDisplay);
475	extents->y2 = min(extents->y2, xf86_crtc->mode.VDisplay);
476
477	return (extents->x1 < extents->x2 && extents->y1 < extents->y2);
478}
479
480static RegionPtr
481transform_region(RegionPtr region, struct pict_f_transform *transform,
482		 int w, int h)
483{
484	BoxPtr boxes = RegionRects(region);
485	int nboxes = RegionNumRects(region);
486	xRectanglePtr rects = malloc(nboxes * sizeof(*rects));
487	RegionPtr transformed;
488	int nrects = 0;
489	BoxRec box;
490	int i;
491
492	for (i = 0; i < nboxes; i++) {
493		box.x1 = boxes[i].x1;
494		box.x2 = boxes[i].x2;
495		box.y1 = boxes[i].y1;
496		box.y2 = boxes[i].y2;
497		pixman_f_transform_bounds(transform, &box);
498
499		box.x1 = max(box.x1, 0);
500		box.y1 = max(box.y1, 0);
501		box.x2 = min(box.x2, w);
502		box.y2 = min(box.y2, h);
503		if (box.x1 >= box.x2 || box.y1 >= box.y2)
504			continue;
505
506		rects[nrects].x = box.x1;
507		rects[nrects].y = box.y1;
508		rects[nrects].width = box.x2 - box.x1;
509		rects[nrects].height = box.y2 - box.y1;
510		nrects++;
511	}
512
513	transformed = RegionFromRects(nrects, rects, CT_UNSORTED);
514	free(rects);
515	return transformed;
516}
517
518static void
519amdgpu_sync_scanout_pixmaps(xf86CrtcPtr xf86_crtc, RegionPtr new_region,
520							int scanout_id)
521{
522	drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private;
523	DrawablePtr dst = &drmmode_crtc->scanout[scanout_id]->drawable;
524	DrawablePtr src = &drmmode_crtc->scanout[scanout_id ^ 1]->drawable;
525	RegionPtr last_region = &drmmode_crtc->scanout_last_region;
526	ScrnInfoPtr scrn = xf86_crtc->scrn;
527	ScreenPtr pScreen = scrn->pScreen;
528	RegionRec remaining;
529	RegionPtr sync_region = NULL;
530	BoxRec extents;
531	GCPtr gc;
532
533	if (RegionNil(last_region))
534		return;
535
536	RegionNull(&remaining);
537	RegionSubtract(&remaining, last_region, new_region);
538	if (RegionNil(&remaining))
539		goto uninit;
540
541	extents = *RegionExtents(&remaining);
542	if (!amdgpu_scanout_extents_intersect(xf86_crtc, &extents))
543		goto uninit;
544
545	if (xf86_crtc->driverIsPerformingTransform) {
546		sync_region = transform_region(&remaining,
547					       &xf86_crtc->f_framebuffer_to_crtc,
548					       dst->width, dst->height);
549	} else {
550		sync_region = RegionDuplicate(&remaining);
551		RegionTranslate(sync_region, -xf86_crtc->x, -xf86_crtc->y);
552	}
553
554	gc = GetScratchGC(dst->depth, pScreen);
555	if (gc) {
556		gc->funcs->ChangeClip(gc, CT_REGION, sync_region, 0);
557		ValidateGC(dst, gc);
558		sync_region = NULL;
559		gc->ops->CopyArea(src, dst, gc, 0, 0, dst->width, dst->height, 0, 0);
560		FreeScratchGC(gc);
561	}
562
563 uninit:
564	if (sync_region)
565		RegionDestroy(sync_region);
566	RegionUninit(&remaining);
567}
568
569static void
570amdgpu_scanout_flip_abort(xf86CrtcPtr crtc, void *event_data)
571{
572	AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(crtc->scrn);
573	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
574	struct drmmode_fb *fb = event_data;
575
576	drmmode_crtc->scanout_update_pending = 0;
577
578	if (drmmode_crtc->flip_pending == fb) {
579		drmmode_fb_reference(pAMDGPUEnt->fd, &drmmode_crtc->flip_pending,
580				     NULL);
581	}
582}
583
584static void
585amdgpu_scanout_flip_handler(xf86CrtcPtr crtc, uint32_t msc, uint64_t usec,
586			    void *event_data)
587{
588	AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(crtc->scrn);
589	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
590	struct drmmode_fb *fb = event_data;
591
592	drmmode_fb_reference(pAMDGPUEnt->fd, &drmmode_crtc->fb, fb);
593	amdgpu_scanout_flip_abort(crtc, event_data);
594}
595
596
597static RegionPtr
598dirty_region(PixmapDirtyUpdatePtr dirty)
599{
600	RegionPtr damageregion = DamageRegion(dirty->damage);
601	RegionPtr dstregion;
602
603#ifdef HAS_DIRTYTRACKING_ROTATION
604	if (dirty->rotation != RR_Rotate_0) {
605		dstregion = transform_region(damageregion,
606					     &dirty->f_inverse,
607					     dirty->secondary_dst->drawable.width,
608					     dirty->secondary_dst->drawable.height);
609	} else
610#endif
611	{
612		RegionRec pixregion;
613
614		dstregion = RegionDuplicate(damageregion);
615		RegionTranslate(dstregion, -dirty->x, -dirty->y);
616		PixmapRegionInit(&pixregion, dirty->secondary_dst);
617		RegionIntersect(dstregion, dstregion, &pixregion);
618		RegionUninit(&pixregion);
619	}
620
621	return dstregion;
622}
623
624static void
625redisplay_dirty(PixmapDirtyUpdatePtr dirty, RegionPtr region)
626{
627	ScrnInfoPtr src_scrn =
628		xf86ScreenToScrn(amdgpu_dirty_src_drawable(dirty)->pScreen);
629
630	if (RegionNil(region))
631		goto out;
632
633	if (dirty->secondary_dst->primary_pixmap)
634		DamageRegionAppend(&dirty->secondary_dst->drawable, region);
635
636#ifdef HAS_DIRTYTRACKING_ROTATION
637	PixmapSyncDirtyHelper(dirty);
638#else
639	PixmapSyncDirtyHelper(dirty, region);
640#endif
641
642	amdgpu_glamor_flush(src_scrn);
643	if (dirty->secondary_dst->primary_pixmap)
644		DamageRegionProcessPending(&dirty->secondary_dst->drawable);
645
646out:
647	DamageEmpty(dirty->damage);
648}
649
650static void
651amdgpu_prime_scanout_update_abort(xf86CrtcPtr crtc, void *event_data)
652{
653	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
654
655	drmmode_crtc->scanout_update_pending = 0;
656}
657
658void
659amdgpu_sync_shared_pixmap(PixmapDirtyUpdatePtr dirty)
660{
661	ScreenPtr primary_screen = amdgpu_dirty_primary(dirty);
662	PixmapDirtyUpdatePtr ent;
663	RegionPtr region;
664
665	xorg_list_for_each_entry(ent, &primary_screen->pixmap_dirty_list, ent) {
666		if (!amdgpu_dirty_src_equals(dirty, ent->secondary_dst))
667			continue;
668
669		region = dirty_region(ent);
670		redisplay_dirty(ent, region);
671		RegionDestroy(region);
672	}
673}
674
675
676#if HAS_SYNC_SHARED_PIXMAP
677
678static Bool
679primary_has_sync_shared_pixmap(ScrnInfoPtr scrn, PixmapDirtyUpdatePtr dirty)
680{
681	ScreenPtr primary_screen = amdgpu_dirty_primary(dirty);
682
683	return primary_screen->SyncSharedPixmap != NULL;
684}
685
686static Bool
687secondary_has_sync_shared_pixmap(ScrnInfoPtr scrn, PixmapDirtyUpdatePtr dirty)
688{
689	ScreenPtr secondary_screen = dirty->secondary_dst->drawable.pScreen;
690
691	return secondary_screen->SyncSharedPixmap != NULL;
692}
693
694static void
695call_sync_shared_pixmap(PixmapDirtyUpdatePtr dirty)
696{
697	ScreenPtr primary_screen = amdgpu_dirty_primary(dirty);
698
699	primary_screen->SyncSharedPixmap(dirty);
700}
701
702#else /* !HAS_SYNC_SHARED_PIXMAP */
703
704static Bool
705primary_has_sync_shared_pixmap(ScrnInfoPtr scrn, PixmapDirtyUpdatePtr dirty)
706{
707	ScrnInfoPtr primary_scrn = xf86ScreenToScrn(amdgpu_dirty_primary(dirty));
708
709	return primary_scrn->driverName == scrn->driverName;
710}
711
712static Bool
713secondary_has_sync_shared_pixmap(ScrnInfoPtr scrn, PixmapDirtyUpdatePtr dirty)
714{
715	ScrnInfoPtr secondary_scrn = xf86ScreenToScrn(dirty->secondary_dst->drawable.pScreen);
716
717	return secondary_scrn->driverName == scrn->driverName;
718}
719
720static void
721call_sync_shared_pixmap(PixmapDirtyUpdatePtr dirty)
722{
723	amdgpu_sync_shared_pixmap(dirty);
724}
725
726#endif /* HAS_SYNC_SHARED_PIXMAPS */
727
728
729static xf86CrtcPtr
730amdgpu_prime_dirty_to_crtc(PixmapDirtyUpdatePtr dirty)
731{
732	ScreenPtr screen = dirty->secondary_dst->drawable.pScreen;
733	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
734	xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
735	int c;
736
737	/* Find the CRTC which is scanning out from this secondary pixmap */
738	for (c = 0; c < xf86_config->num_crtc; c++) {
739		xf86CrtcPtr xf86_crtc = xf86_config->crtc[c];
740		drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private;
741
742		if (amdgpu_dirty_src_equals(dirty, drmmode_crtc->prime_scanout_pixmap))
743			return xf86_crtc;
744	}
745
746	return NULL;
747}
748
749static Bool
750amdgpu_prime_scanout_do_update(xf86CrtcPtr crtc, unsigned scanout_id)
751{
752	ScrnInfoPtr scrn = crtc->scrn;
753	ScreenPtr screen = scrn->pScreen;
754	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
755	PixmapDirtyUpdatePtr dirty;
756	Bool ret = FALSE;
757
758	xorg_list_for_each_entry(dirty, &screen->pixmap_dirty_list, ent) {
759		if (amdgpu_dirty_src_equals(dirty, drmmode_crtc->prime_scanout_pixmap)) {
760			RegionPtr region;
761
762			if (primary_has_sync_shared_pixmap(scrn, dirty))
763				call_sync_shared_pixmap(dirty);
764
765			region = dirty_region(dirty);
766			if (RegionNil(region))
767				goto destroy;
768
769			if (drmmode_crtc->tear_free) {
770				RegionTranslate(region, crtc->x, crtc->y);
771				amdgpu_sync_scanout_pixmaps(crtc, region, scanout_id);
772				amdgpu_glamor_flush(scrn);
773				RegionCopy(&drmmode_crtc->scanout_last_region, region);
774				RegionTranslate(region, -crtc->x, -crtc->y);
775				dirty->secondary_dst = drmmode_crtc->scanout[scanout_id];
776			}
777
778			redisplay_dirty(dirty, region);
779			ret = TRUE;
780		destroy:
781			RegionDestroy(region);
782			break;
783		}
784	}
785
786	return ret;
787}
788
789static void
790amdgpu_prime_scanout_update_handler(xf86CrtcPtr crtc, uint32_t frame, uint64_t usec,
791				     void *event_data)
792{
793	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
794
795	amdgpu_prime_scanout_do_update(crtc, 0);
796	drmmode_crtc->scanout_update_pending = 0;
797}
798
799static void
800amdgpu_prime_scanout_update(PixmapDirtyUpdatePtr dirty)
801{
802	ScreenPtr screen = dirty->secondary_dst->drawable.pScreen;
803	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
804	AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(scrn);
805	xf86CrtcPtr xf86_crtc = amdgpu_prime_dirty_to_crtc(dirty);
806	drmmode_crtc_private_ptr drmmode_crtc;
807	uintptr_t drm_queue_seq;
808
809	if (!xf86_crtc || !xf86_crtc->enabled)
810		return;
811
812	drmmode_crtc = xf86_crtc->driver_private;
813	if (drmmode_crtc->scanout_update_pending ||
814	    !drmmode_crtc->scanout[drmmode_crtc->scanout_id] ||
815	    drmmode_crtc->dpms_mode != DPMSModeOn)
816		return;
817
818	drm_queue_seq = amdgpu_drm_queue_alloc(xf86_crtc,
819					       AMDGPU_DRM_QUEUE_CLIENT_DEFAULT,
820					       AMDGPU_DRM_QUEUE_ID_DEFAULT, NULL,
821					       amdgpu_prime_scanout_update_handler,
822					       amdgpu_prime_scanout_update_abort,
823					       FALSE);
824	if (drm_queue_seq == AMDGPU_DRM_QUEUE_ERROR) {
825		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
826			   "amdgpu_drm_queue_alloc failed for PRIME update\n");
827		amdgpu_prime_scanout_update_handler(xf86_crtc, 0, 0, NULL);
828		return;
829	}
830
831	drmmode_crtc->scanout_update_pending = drm_queue_seq;
832
833	if (!drmmode_wait_vblank(xf86_crtc, DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT,
834				 1, drm_queue_seq, NULL, NULL)) {
835		if (!(drmmode_crtc->scanout_status & DRMMODE_SCANOUT_VBLANK_FAILED)) {
836			xf86DrvMsg(scrn->scrnIndex, X_WARNING,
837				   "drmmode_wait_vblank failed for PRIME update: %s\n",
838				   strerror(errno));
839			drmmode_crtc->scanout_status |= DRMMODE_SCANOUT_VBLANK_FAILED;
840		}
841
842		drmmode_crtc->drmmode->event_context.vblank_handler(pAMDGPUEnt->fd,
843								    0, 0, 0,
844								    (void*)drm_queue_seq);
845		drmmode_crtc->wait_flip_nesting_level++;
846		amdgpu_drm_queue_handle_deferred(xf86_crtc);
847		return;
848	}
849
850	if (drmmode_crtc->scanout_status ==
851	    (DRMMODE_SCANOUT_FLIP_FAILED | DRMMODE_SCANOUT_VBLANK_FAILED)) {
852		/* The page flip and vblank ioctls failed before, but the vblank
853		 * ioctl is working again, so we can try re-enabling TearFree
854		 */
855		xf86_crtc->funcs->set_mode_major(xf86_crtc, &xf86_crtc->mode,
856						 xf86_crtc->rotation,
857						 xf86_crtc->x, xf86_crtc->y);
858	}
859
860	drmmode_crtc->scanout_status &= ~DRMMODE_SCANOUT_VBLANK_FAILED;
861}
862
863static void
864amdgpu_prime_scanout_flip(PixmapDirtyUpdatePtr ent)
865{
866	ScreenPtr screen = ent->secondary_dst->drawable.pScreen;
867	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
868	AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(scrn);
869	xf86CrtcPtr crtc = amdgpu_prime_dirty_to_crtc(ent);
870	drmmode_crtc_private_ptr drmmode_crtc;
871	uintptr_t drm_queue_seq;
872	unsigned scanout_id;
873	struct drmmode_fb *fb;
874
875	if (!crtc || !crtc->enabled)
876		return;
877
878	drmmode_crtc = crtc->driver_private;
879	scanout_id = drmmode_crtc->scanout_id ^ 1;
880	if (drmmode_crtc->scanout_update_pending ||
881	    !drmmode_crtc->scanout[scanout_id] ||
882	    drmmode_crtc->dpms_mode != DPMSModeOn)
883		return;
884
885	if (!amdgpu_prime_scanout_do_update(crtc, scanout_id))
886		return;
887
888	fb = amdgpu_pixmap_get_fb(drmmode_crtc->scanout[scanout_id]);
889	if (!fb) {
890		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
891			   "Failed to get FB for PRIME flip.\n");
892		return;
893	}
894
895	drm_queue_seq = amdgpu_drm_queue_alloc(crtc,
896					       AMDGPU_DRM_QUEUE_CLIENT_DEFAULT,
897					       AMDGPU_DRM_QUEUE_ID_DEFAULT, fb,
898					       amdgpu_scanout_flip_handler,
899					       amdgpu_scanout_flip_abort, TRUE);
900	if (drm_queue_seq == AMDGPU_DRM_QUEUE_ERROR) {
901		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
902			   "Allocating DRM event queue entry failed for PRIME flip.\n");
903		return;
904	}
905
906	if (drmmode_page_flip_target_relative(pAMDGPUEnt, drmmode_crtc,
907					      fb->handle, 0, drm_queue_seq, 1)
908	    != 0) {
909		if (!(drmmode_crtc->scanout_status & DRMMODE_SCANOUT_FLIP_FAILED)) {
910			xf86DrvMsg(scrn->scrnIndex, X_WARNING,
911				   "flip queue failed in %s: %s, TearFree inactive\n",
912				   __func__, strerror(errno));
913			drmmode_crtc->scanout_status |= DRMMODE_SCANOUT_FLIP_FAILED;
914		}
915
916		amdgpu_drm_abort_entry(drm_queue_seq);
917		return;
918	}
919
920	if (drmmode_crtc->scanout_status & DRMMODE_SCANOUT_FLIP_FAILED) {
921		xf86DrvMsg(scrn->scrnIndex, X_INFO, "TearFree active again\n");
922		drmmode_crtc->scanout_status &= ~DRMMODE_SCANOUT_FLIP_FAILED;
923	}
924
925	drmmode_crtc->scanout_id = scanout_id;
926	drmmode_crtc->scanout_update_pending = drm_queue_seq;
927	drmmode_fb_reference(pAMDGPUEnt->fd, &drmmode_crtc->flip_pending, fb);
928}
929
930static void
931amdgpu_dirty_update(ScrnInfoPtr scrn)
932{
933	ScreenPtr screen = scrn->pScreen;
934	PixmapDirtyUpdatePtr ent;
935	RegionPtr region;
936
937	xorg_list_for_each_entry(ent, &screen->pixmap_dirty_list, ent) {
938		if (screen->isGPU) {
939			PixmapDirtyUpdatePtr region_ent = ent;
940
941			if (primary_has_sync_shared_pixmap(scrn, ent)) {
942				ScreenPtr primary_screen = amdgpu_dirty_primary(ent);
943
944				xorg_list_for_each_entry(region_ent, &primary_screen->pixmap_dirty_list, ent) {
945					if (amdgpu_dirty_src_equals(ent, region_ent->secondary_dst))
946						break;
947				}
948			}
949
950			region = dirty_region(region_ent);
951
952			if (RegionNotEmpty(region)) {
953				xf86CrtcPtr crtc = amdgpu_prime_dirty_to_crtc(ent);
954				drmmode_crtc_private_ptr drmmode_crtc = NULL;
955
956				if (crtc)
957					drmmode_crtc = crtc->driver_private;
958
959				if (drmmode_crtc && drmmode_crtc->tear_free)
960					amdgpu_prime_scanout_flip(ent);
961				else
962					amdgpu_prime_scanout_update(ent);
963			} else {
964				DamageEmpty(region_ent->damage);
965			}
966
967			RegionDestroy(region);
968		} else {
969			if (secondary_has_sync_shared_pixmap(scrn, ent))
970				continue;
971
972			region = dirty_region(ent);
973			redisplay_dirty(ent, region);
974			RegionDestroy(region);
975		}
976	}
977}
978
979static void
980amdgpuSourceValidate(DrawablePtr draw, int x, int y, int w, int h,
981		     unsigned int subWindowMode)
982{
983}
984
985Bool
986amdgpu_scanout_do_update(xf86CrtcPtr xf86_crtc, int scanout_id,
987			 PixmapPtr src_pix, BoxRec extents)
988{
989	drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private;
990	RegionRec region = { .extents = extents, .data = NULL };
991	ScrnInfoPtr scrn = xf86_crtc->scrn;
992	ScreenPtr pScreen = scrn->pScreen;
993	DrawablePtr pDraw;
994
995	if (!xf86_crtc->enabled ||
996	    !drmmode_crtc->scanout[scanout_id] ||
997	    extents.x1 >= extents.x2 || extents.y1 >= extents.y2)
998		return FALSE;
999
1000	pDraw = &drmmode_crtc->scanout[scanout_id]->drawable;
1001	if (!amdgpu_scanout_extents_intersect(xf86_crtc, &extents))
1002		return FALSE;
1003
1004	if (drmmode_crtc->tear_free) {
1005		amdgpu_sync_scanout_pixmaps(xf86_crtc, &region, scanout_id);
1006		RegionCopy(&drmmode_crtc->scanout_last_region, &region);
1007	}
1008
1009	if (xf86_crtc->driverIsPerformingTransform) {
1010		SourceValidateProcPtr SourceValidate = pScreen->SourceValidate;
1011		PictFormatPtr format = PictureWindowFormat(pScreen->root);
1012		int error;
1013		PicturePtr src, dst;
1014
1015		src = CreatePicture(None, &src_pix->drawable, format, 0L, NULL,
1016				    serverClient, &error);
1017		if (!src) {
1018			ErrorF("Failed to create source picture for transformed scanout "
1019			       "update\n");
1020			goto out;
1021		}
1022
1023		dst = CreatePicture(None, pDraw, format, 0L, NULL, serverClient, &error);
1024		if (!dst) {
1025			ErrorF("Failed to create destination picture for transformed scanout "
1026			       "update\n");
1027			goto free_src;
1028		}
1029		error = SetPictureTransform(src, &xf86_crtc->crtc_to_framebuffer);
1030		if (error) {
1031			ErrorF("SetPictureTransform failed for transformed scanout "
1032			       "update\n");
1033			goto free_dst;
1034		}
1035
1036		if (xf86_crtc->filter)
1037			SetPicturePictFilter(src, xf86_crtc->filter, xf86_crtc->params,
1038					     xf86_crtc->nparams);
1039
1040		pScreen->SourceValidate = amdgpuSourceValidate;
1041		CompositePicture(PictOpSrc,
1042				 src, NULL, dst,
1043				 extents.x1, extents.y1, 0, 0, extents.x1,
1044				 extents.y1, extents.x2 - extents.x1,
1045				 extents.y2 - extents.y1);
1046		pScreen->SourceValidate = SourceValidate;
1047
1048 free_dst:
1049		FreePicture(dst, None);
1050 free_src:
1051		FreePicture(src, None);
1052	} else
1053 out:
1054	{
1055		GCPtr gc = GetScratchGC(pDraw->depth, pScreen);
1056
1057		ValidateGC(pDraw, gc);
1058		(*gc->ops->CopyArea)(&src_pix->drawable, pDraw, gc,
1059				     xf86_crtc->x + extents.x1, xf86_crtc->y + extents.y1,
1060				     extents.x2 - extents.x1, extents.y2 - extents.y1,
1061				     extents.x1, extents.y1);
1062		FreeScratchGC(gc);
1063	}
1064
1065	return TRUE;
1066}
1067
1068static void
1069amdgpu_scanout_update_abort(xf86CrtcPtr crtc, void *event_data)
1070{
1071	drmmode_crtc_private_ptr drmmode_crtc = event_data;
1072
1073	drmmode_crtc->scanout_update_pending = 0;
1074}
1075
1076static void
1077amdgpu_scanout_update_handler(xf86CrtcPtr crtc, uint32_t frame, uint64_t usec,
1078							  void *event_data)
1079{
1080	drmmode_crtc_private_ptr drmmode_crtc = event_data;
1081	ScreenPtr screen = crtc->scrn->pScreen;
1082	RegionPtr region = DamageRegion(drmmode_crtc->scanout_damage);
1083
1084	if (crtc->enabled &&
1085	    !drmmode_crtc->flip_pending &&
1086	    drmmode_crtc->dpms_mode == DPMSModeOn) {
1087		if (amdgpu_scanout_do_update(crtc, drmmode_crtc->scanout_id,
1088					     screen->GetWindowPixmap(screen->root),
1089					     region->extents)) {
1090			amdgpu_glamor_flush(crtc->scrn);
1091			RegionEmpty(region);
1092		}
1093	}
1094
1095	amdgpu_scanout_update_abort(crtc, event_data);
1096}
1097
1098static void
1099amdgpu_scanout_update(xf86CrtcPtr xf86_crtc)
1100{
1101	drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private;
1102	ScrnInfoPtr scrn = xf86_crtc->scrn;
1103	AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(scrn);
1104	uintptr_t drm_queue_seq;
1105	DamagePtr pDamage;
1106	RegionPtr pRegion;
1107	BoxRec extents;
1108
1109	if (!xf86_crtc->enabled ||
1110	    drmmode_crtc->scanout_update_pending ||
1111	    drmmode_crtc->flip_pending ||
1112	    drmmode_crtc->dpms_mode != DPMSModeOn)
1113		return;
1114
1115	pDamage = drmmode_crtc->scanout_damage;
1116	if (!pDamage)
1117		return;
1118
1119	pRegion = DamageRegion(pDamage);
1120	if (!RegionNotEmpty(pRegion))
1121		return;
1122
1123	extents = *RegionExtents(pRegion);
1124	if (!amdgpu_scanout_extents_intersect(xf86_crtc, &extents)) {
1125		RegionEmpty(pRegion);
1126		return;
1127	}
1128
1129	drm_queue_seq = amdgpu_drm_queue_alloc(xf86_crtc,
1130					       AMDGPU_DRM_QUEUE_CLIENT_DEFAULT,
1131					       AMDGPU_DRM_QUEUE_ID_DEFAULT,
1132					       drmmode_crtc,
1133					       amdgpu_scanout_update_handler,
1134					       amdgpu_scanout_update_abort,
1135					       FALSE);
1136	if (drm_queue_seq == AMDGPU_DRM_QUEUE_ERROR) {
1137		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
1138			   "amdgpu_drm_queue_alloc failed for scanout update\n");
1139		amdgpu_scanout_update_handler(xf86_crtc, 0, 0, drmmode_crtc);
1140		return;
1141	}
1142
1143	drmmode_crtc->scanout_update_pending = drm_queue_seq;
1144
1145	if (!drmmode_wait_vblank(xf86_crtc, DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT,
1146				 1, drm_queue_seq, NULL, NULL)) {
1147		if (!(drmmode_crtc->scanout_status & DRMMODE_SCANOUT_VBLANK_FAILED)) {
1148			xf86DrvMsg(scrn->scrnIndex, X_WARNING,
1149				   "drmmode_wait_vblank failed for scanout update: %s\n",
1150				   strerror(errno));
1151			drmmode_crtc->scanout_status |= DRMMODE_SCANOUT_VBLANK_FAILED;
1152		}
1153
1154		drmmode_crtc->drmmode->event_context.vblank_handler(pAMDGPUEnt->fd,
1155								    0, 0, 0,
1156								    (void*)drm_queue_seq);
1157		drmmode_crtc->wait_flip_nesting_level++;
1158		amdgpu_drm_queue_handle_deferred(xf86_crtc);
1159		return;
1160	}
1161
1162	if (drmmode_crtc->scanout_status ==
1163	    (DRMMODE_SCANOUT_FLIP_FAILED | DRMMODE_SCANOUT_VBLANK_FAILED)) {
1164		/* The page flip and vblank ioctls failed before, but the vblank
1165		 * ioctl is working again, so we can try re-enabling TearFree
1166		 */
1167		xf86_crtc->funcs->set_mode_major(xf86_crtc, &xf86_crtc->mode,
1168						 xf86_crtc->rotation,
1169						 xf86_crtc->x, xf86_crtc->y);
1170	}
1171
1172	drmmode_crtc->scanout_status &= ~DRMMODE_SCANOUT_VBLANK_FAILED;
1173}
1174
1175static void
1176amdgpu_scanout_flip(ScreenPtr pScreen, AMDGPUInfoPtr info,
1177					xf86CrtcPtr xf86_crtc)
1178{
1179	drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private;
1180	RegionPtr region = DamageRegion(drmmode_crtc->scanout_damage);
1181	ScrnInfoPtr scrn = xf86_crtc->scrn;
1182	AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(scrn);
1183	uintptr_t drm_queue_seq;
1184	unsigned scanout_id;
1185	struct drmmode_fb *fb;
1186
1187	if (drmmode_crtc->scanout_update_pending ||
1188	    drmmode_crtc->flip_pending ||
1189	    drmmode_crtc->dpms_mode != DPMSModeOn)
1190		return;
1191
1192	scanout_id = drmmode_crtc->scanout_id ^ 1;
1193	if (!amdgpu_scanout_do_update(xf86_crtc, scanout_id,
1194				      pScreen->GetWindowPixmap(pScreen->root),
1195				      region->extents))
1196		return;
1197
1198	amdgpu_glamor_flush(scrn);
1199	RegionEmpty(region);
1200
1201	fb = amdgpu_pixmap_get_fb(drmmode_crtc->scanout[scanout_id]);
1202	if (!fb) {
1203		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
1204			   "Failed to get FB for scanout flip.\n");
1205		return;
1206	}
1207
1208	drm_queue_seq = amdgpu_drm_queue_alloc(xf86_crtc,
1209					       AMDGPU_DRM_QUEUE_CLIENT_DEFAULT,
1210					       AMDGPU_DRM_QUEUE_ID_DEFAULT, fb,
1211					       amdgpu_scanout_flip_handler,
1212					       amdgpu_scanout_flip_abort, TRUE);
1213	if (drm_queue_seq == AMDGPU_DRM_QUEUE_ERROR) {
1214		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
1215			   "Allocating DRM event queue entry failed.\n");
1216		return;
1217	}
1218
1219	if (drmmode_page_flip_target_relative(pAMDGPUEnt, drmmode_crtc,
1220					      fb->handle, 0, drm_queue_seq, 1)
1221	    != 0) {
1222		if (!(drmmode_crtc->scanout_status & DRMMODE_SCANOUT_FLIP_FAILED)) {
1223			xf86DrvMsg(scrn->scrnIndex, X_WARNING,
1224				   "flip queue failed in %s: %s, TearFree inactive\n",
1225				   __func__, strerror(errno));
1226			drmmode_crtc->scanout_status |= DRMMODE_SCANOUT_FLIP_FAILED;
1227		}
1228
1229		amdgpu_drm_abort_entry(drm_queue_seq);
1230		RegionCopy(DamageRegion(drmmode_crtc->scanout_damage),
1231			   &drmmode_crtc->scanout_last_region);
1232		RegionEmpty(&drmmode_crtc->scanout_last_region);
1233		amdgpu_scanout_update(xf86_crtc);
1234		drmmode_crtc_scanout_destroy(&drmmode_crtc->scanout[scanout_id]);
1235		drmmode_crtc->tear_free = FALSE;
1236		return;
1237	}
1238
1239	if (drmmode_crtc->scanout_status & DRMMODE_SCANOUT_FLIP_FAILED) {
1240		xf86DrvMsg(scrn->scrnIndex, X_INFO, "TearFree active again\n");
1241		drmmode_crtc->scanout_status &= ~DRMMODE_SCANOUT_FLIP_FAILED;
1242	}
1243
1244	drmmode_crtc->scanout_id = scanout_id;
1245	drmmode_crtc->scanout_update_pending = drm_queue_seq;
1246	drmmode_fb_reference(pAMDGPUEnt->fd, &drmmode_crtc->flip_pending, fb);
1247}
1248
1249static void AMDGPUBlockHandler_KMS(BLOCKHANDLER_ARGS_DECL)
1250{
1251	ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
1252	AMDGPUInfoPtr info = AMDGPUPTR(pScrn);
1253	xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
1254	int c;
1255
1256	pScreen->BlockHandler = info->BlockHandler;
1257	(*pScreen->BlockHandler) (BLOCKHANDLER_ARGS);
1258	pScreen->BlockHandler = AMDGPUBlockHandler_KMS;
1259
1260	if (!xf86ScreenToScrn(amdgpu_primary_screen(pScreen))->vtSema)
1261		return;
1262
1263	if (!pScreen->isGPU)
1264	{
1265		for (c = 0; c < xf86_config->num_crtc; c++) {
1266			xf86CrtcPtr crtc = xf86_config->crtc[c];
1267			drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
1268
1269			if (drmmode_crtc->rotate)
1270				continue;
1271
1272			if (drmmode_crtc->tear_free)
1273				amdgpu_scanout_flip(pScreen, info, crtc);
1274			else if (drmmode_crtc->scanout[drmmode_crtc->scanout_id])
1275				amdgpu_scanout_update(crtc);
1276		}
1277	}
1278
1279#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1,19,0,0,0)
1280	if (info->use_glamor)
1281		amdgpu_glamor_flush(pScrn);
1282#endif
1283
1284	amdgpu_dirty_update(pScrn);
1285}
1286
1287/* This is called by AMDGPUPreInit to set up the default visual */
1288static Bool AMDGPUPreInitVisual(ScrnInfoPtr pScrn)
1289{
1290	AMDGPUInfoPtr info = AMDGPUPTR(pScrn);
1291
1292	if (!xf86SetDepthBpp(pScrn, 0, 0, 0, Support32bppFb))
1293		return FALSE;
1294
1295	switch (pScrn->depth) {
1296	case 8:
1297	case 15:
1298	case 16:
1299	case 24:
1300	case 30:
1301		break;
1302
1303	default:
1304		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1305			   "Given depth (%d) is not supported by %s driver\n",
1306			   pScrn->depth, AMDGPU_DRIVER_NAME);
1307		return FALSE;
1308	}
1309
1310	xf86PrintDepthBpp(pScrn);
1311
1312	info->pix24bpp = xf86GetBppFromDepth(pScrn, pScrn->depth);
1313	info->pixel_bytes = pScrn->bitsPerPixel / 8;
1314
1315	if (info->pix24bpp == 24) {
1316		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1317			   "Amdgpu does NOT support 24bpp\n");
1318		return FALSE;
1319	}
1320
1321	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1322		   "Pixel depth = %d bits stored in %d byte%s (%d bpp pixmaps)\n",
1323		   pScrn->depth,
1324		   info->pixel_bytes,
1325		   info->pixel_bytes > 1 ? "s" : "", info->pix24bpp);
1326
1327	if (!xf86SetDefaultVisual(pScrn, -1))
1328		return FALSE;
1329
1330	if (pScrn->depth > 8 && pScrn->defaultVisual != TrueColor) {
1331		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1332			   "Default visual (%s) is not supported at depth %d\n",
1333			   xf86GetVisualName(pScrn->defaultVisual),
1334			   pScrn->depth);
1335		return FALSE;
1336	}
1337	return TRUE;
1338}
1339
1340/* This is called by AMDGPUPreInit to handle all color weight issues */
1341static Bool AMDGPUPreInitWeight(ScrnInfoPtr pScrn)
1342{
1343	AMDGPUInfoPtr info = AMDGPUPTR(pScrn);
1344
1345	/* Save flag for 6 bit DAC to use for
1346	   setting CRTC registers.  Otherwise use
1347	   an 8 bit DAC, even if xf86SetWeight sets
1348	   pScrn->rgbBits to some value other than
1349	   8. */
1350	info->dac6bits = FALSE;
1351
1352	if (pScrn->depth > 8) {
1353		rgb defaultWeight = { 0, 0, 0 };
1354
1355		if (!xf86SetWeight(pScrn, defaultWeight, defaultWeight))
1356			return FALSE;
1357	} else {
1358		pScrn->rgbBits = 8;
1359	}
1360
1361	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1362		   "Using %d bits per RGB (%d bit DAC)\n",
1363		   pScrn->rgbBits, info->dac6bits ? 6 : 8);
1364
1365	return TRUE;
1366}
1367
1368static Bool AMDGPUPreInitAccel_KMS(ScrnInfoPtr pScrn)
1369{
1370	AMDGPUInfoPtr info = AMDGPUPTR(pScrn);
1371
1372	if (xf86ReturnOptValBool(info->Options, OPTION_ACCEL, TRUE)) {
1373		AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(pScrn);
1374		Bool use_glamor = TRUE;
1375#ifdef HAVE_GBM_BO_USE_LINEAR
1376		const char *accel_method;
1377
1378		accel_method = xf86GetOptValString(info->Options, OPTION_ACCEL_METHOD);
1379		if ((accel_method && !strcmp(accel_method, "none")))
1380			use_glamor = FALSE;
1381#endif
1382
1383#ifdef DRI2
1384		info->dri2.available = ! !xf86LoadSubModule(pScrn, "dri2");
1385#endif
1386
1387		if (info->dri2.available)
1388			info->gbm = gbm_create_device(pAMDGPUEnt->fd);
1389
1390		if (info->gbm) {
1391			if (use_glamor) {
1392				if (amdgpu_glamor_pre_init(pScrn))
1393					return TRUE;
1394
1395				xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
1396					   "amdgpu_glamor_pre_init returned "
1397					   "FALSE, using ShadowFB\n");
1398			}
1399		} else {
1400			xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
1401				   "gbm_create_device returned NULL, using "
1402				   "ShadowFB\n");
1403		}
1404	} else {
1405		xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
1406			   "GPU acceleration disabled, using ShadowFB\n");
1407	}
1408
1409	if (!xf86LoadSubModule(pScrn, "shadow"))
1410		return FALSE;
1411
1412	info->dri2.available = FALSE;
1413	info->shadow_fb = TRUE;
1414	return TRUE;
1415}
1416
1417static Bool AMDGPUPreInitChipType_KMS(ScrnInfoPtr pScrn,
1418				      struct amdgpu_gpu_info *gpu_info)
1419{
1420	AMDGPUInfoPtr info = AMDGPUPTR(pScrn);
1421	AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(pScrn);
1422
1423	pScrn->chipset = (char*)amdgpu_get_marketing_name(pAMDGPUEnt->pDev);
1424	if (!pScrn->chipset)
1425		pScrn->chipset = "Unknown AMD Radeon GPU";
1426
1427	xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
1428		   "Chipset: \"%s\" (ChipID = 0x%04x)\n",
1429		   pScrn->chipset, gpu_info->asic_id);
1430
1431	info->family = gpu_info->family_id;
1432
1433	return TRUE;
1434}
1435
1436static Bool amdgpu_get_tile_config(AMDGPUInfoPtr info,
1437				   struct amdgpu_gpu_info *gpu_info)
1438{
1439	switch ((gpu_info->gb_addr_cfg & 0x70) >> 4) {
1440	case 0:
1441		info->group_bytes = 256;
1442		break;
1443	case 1:
1444		info->group_bytes = 512;
1445		break;
1446	default:
1447		return FALSE;
1448	}
1449
1450	info->have_tiling_info = TRUE;
1451	return TRUE;
1452}
1453
1454static void AMDGPUSetupCapabilities(ScrnInfoPtr pScrn)
1455{
1456	AMDGPUInfoPtr info = AMDGPUPTR(pScrn);
1457	AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(pScrn);
1458	uint64_t value;
1459	int ret;
1460
1461	pScrn->capabilities = 0;
1462
1463	/* PRIME offloading requires acceleration */
1464	if (!info->use_glamor)
1465		return;
1466
1467	ret = drmGetCap(pAMDGPUEnt->fd, DRM_CAP_PRIME, &value);
1468	if (ret == 0) {
1469		if (value & DRM_PRIME_CAP_EXPORT)
1470			pScrn->capabilities |= RR_Capability_SourceOutput | RR_Capability_SourceOffload;
1471		if (value & DRM_PRIME_CAP_IMPORT) {
1472			pScrn->capabilities |= RR_Capability_SinkOffload;
1473			if (info->drmmode.count_crtcs)
1474				pScrn->capabilities |= RR_Capability_SinkOutput;
1475		}
1476	}
1477}
1478
1479/* When the root window is created, initialize the screen contents from
1480 * console if -background none was specified on the command line
1481 */
1482static Bool AMDGPUCreateWindow_oneshot(WindowPtr pWin)
1483{
1484	ScreenPtr pScreen = pWin->drawable.pScreen;
1485	ScrnInfoPtr pScrn;
1486	AMDGPUInfoPtr info;
1487	Bool ret;
1488
1489	if (pWin != pScreen->root)
1490		ErrorF("%s called for non-root window %p\n", __func__, pWin);
1491
1492	pScrn = xf86ScreenToScrn(pScreen);
1493	info = AMDGPUPTR(pScrn);
1494	pScreen->CreateWindow = info->CreateWindow;
1495	ret = pScreen->CreateWindow(pWin);
1496
1497	if (ret)
1498		drmmode_copy_fb(pScrn, &info->drmmode);
1499
1500	return ret;
1501}
1502
1503/* When the root window is mapped, set the initial modes */
1504void AMDGPUWindowExposures_oneshot(WindowPtr pWin, RegionPtr pRegion
1505#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1,16,99,901,0)
1506				   , RegionPtr pBSRegion
1507#endif
1508				   )
1509{
1510	ScreenPtr pScreen = pWin->drawable.pScreen;
1511	ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
1512	AMDGPUInfoPtr info = AMDGPUPTR(pScrn);
1513
1514	if (pWin != pScreen->root)
1515		ErrorF("%s called for non-root window %p\n", __func__, pWin);
1516
1517	pScreen->WindowExposures = info->WindowExposures;
1518#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1,16,99,901,0)
1519	pScreen->WindowExposures(pWin, pRegion, pBSRegion);
1520#else
1521	pScreen->WindowExposures(pWin, pRegion);
1522#endif
1523
1524	amdgpu_glamor_finish(pScrn);
1525	drmmode_set_desired_modes(pScrn, &info->drmmode, TRUE);
1526}
1527
1528Bool AMDGPUPreInit_KMS(ScrnInfoPtr pScrn, int flags)
1529{
1530	AMDGPUInfoPtr info;
1531	AMDGPUEntPtr pAMDGPUEnt;
1532	struct amdgpu_gpu_info gpu_info;
1533	MessageType from;
1534	Gamma zeros = { 0.0, 0.0, 0.0 };
1535	int cpp;
1536	uint64_t heap_size = 0;
1537	uint64_t max_allocation = 0;
1538
1539	if (flags & PROBE_DETECT)
1540		return TRUE;
1541
1542	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG,
1543		       "AMDGPUPreInit_KMS\n");
1544	if (pScrn->numEntities != 1)
1545		return FALSE;
1546
1547	pAMDGPUEnt = xf86GetEntityPrivate(pScrn->entityList[0],
1548					  getAMDGPUEntityIndex())->ptr;
1549
1550	if (!AMDGPUGetRec(pScrn))
1551		return FALSE;
1552
1553	info = AMDGPUPTR(pScrn);
1554	info->instance_id = pAMDGPUEnt->num_scrns++;
1555	pAMDGPUEnt->scrn[info->instance_id] = pScrn;
1556
1557	info->pEnt =
1558	    xf86GetEntityInfo(pScrn->entityList[pScrn->numEntities - 1]);
1559	if (info->pEnt->location.type != BUS_PCI
1560#ifdef XSERVER_PLATFORM_BUS
1561	    && info->pEnt->location.type != BUS_PLATFORM
1562#endif
1563	    )
1564		return FALSE;
1565
1566	if (xf86IsEntityShared(pScrn->entityList[0]) &&
1567	    info->instance_id == 0) {
1568		xf86SetPrimInitDone(pScrn->entityList[0]);
1569	}
1570
1571	pScrn->monitor = pScrn->confScreen->monitor;
1572
1573	if (!AMDGPUPreInitVisual(pScrn))
1574		return FALSE;
1575
1576	xf86CollectOptions(pScrn, NULL);
1577	if (!(info->Options = malloc(sizeof(AMDGPUOptions_KMS))))
1578		return FALSE;
1579
1580	memcpy(info->Options, AMDGPUOptions_KMS, sizeof(AMDGPUOptions_KMS));
1581	xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, info->Options);
1582
1583	if (!AMDGPUPreInitWeight(pScrn))
1584		return FALSE;
1585
1586	memset(&gpu_info, 0, sizeof(gpu_info));
1587	amdgpu_query_gpu_info(pAMDGPUEnt->pDev, &gpu_info);
1588
1589	if (!AMDGPUPreInitChipType_KMS(pScrn, &gpu_info))
1590		return FALSE;
1591
1592	info->dri2.available = FALSE;
1593	info->dri2.enabled = FALSE;
1594	info->dri2.pKernelDRMVersion = drmGetVersion(pAMDGPUEnt->fd);
1595	if (info->dri2.pKernelDRMVersion == NULL) {
1596		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1597			   "AMDGPUDRIGetVersion failed to get the DRM version\n");
1598		return FALSE;
1599	}
1600
1601	/* Get ScreenInit function */
1602	if (!xf86LoadSubModule(pScrn, "fb"))
1603		return FALSE;
1604
1605	if (!AMDGPUPreInitAccel_KMS(pScrn))
1606		return FALSE;
1607
1608	amdgpu_drm_queue_init(pScrn);
1609
1610	/* don't enable tiling if accel is not enabled */
1611	if (info->use_glamor) {
1612		/* set default group bytes, overridden by kernel info below */
1613		info->group_bytes = 256;
1614		info->have_tiling_info = FALSE;
1615		amdgpu_get_tile_config(info, &gpu_info);
1616	}
1617
1618	if (info->use_glamor) {
1619		from = X_DEFAULT;
1620
1621		info->tear_free = 2;
1622		if (xf86GetOptValBool(info->Options, OPTION_TEAR_FREE,
1623				      &info->tear_free))
1624			from = X_CONFIG;
1625		xf86DrvMsg(pScrn->scrnIndex, from, "TearFree property default: %s\n",
1626			   info->tear_free == 2 ? "auto" : (info->tear_free ? "on" : "off"));
1627
1628		info->shadow_primary =
1629			xf86ReturnOptValBool(info->Options, OPTION_SHADOW_PRIMARY, FALSE);
1630
1631		if (info->shadow_primary)
1632			xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ShadowPrimary enabled\n");
1633
1634		if (!pScrn->is_gpu) {
1635			from = xf86GetOptValBool(info->Options, OPTION_VARIABLE_REFRESH,
1636						 &info->vrr_support) ? X_CONFIG : X_DEFAULT;
1637
1638			xf86DrvMsg(pScrn->scrnIndex, from, "VariableRefresh: %sabled\n",
1639				   info->vrr_support ? "en" : "dis");
1640		}
1641	}
1642
1643	if (!pScrn->is_gpu) {
1644		info->allowPageFlip = xf86ReturnOptValBool(info->Options,
1645							   OPTION_PAGE_FLIP,
1646							   TRUE);
1647		if (info->shadow_primary) {
1648			xf86DrvMsg(pScrn->scrnIndex,
1649				   info->allowPageFlip ? X_WARNING : X_DEFAULT,
1650				   "KMS Pageflipping: disabled%s\n",
1651				   info->allowPageFlip ?
1652				   " because of ShadowPrimary" : "");
1653			info->allowPageFlip = FALSE;
1654		} else {
1655			xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1656				   "KMS Pageflipping: %sabled\n",
1657				   info->allowPageFlip ? "en" : "dis");
1658		}
1659	}
1660
1661	if (xf86ReturnOptValBool(info->Options, OPTION_DELETE_DP12, FALSE)) {
1662		info->drmmode.delete_dp_12_displays = TRUE;
1663	}
1664
1665	if (drmmode_pre_init(pScrn, &info->drmmode, pScrn->bitsPerPixel / 8) ==
1666	    FALSE) {
1667		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1668			   "Kernel modesetting setup failed\n");
1669		return FALSE;
1670	}
1671
1672	AMDGPUSetupCapabilities(pScrn);
1673
1674	if (info->drmmode.count_crtcs == 1)
1675		pAMDGPUEnt->HasCRTC2 = FALSE;
1676	else
1677		pAMDGPUEnt->HasCRTC2 = TRUE;
1678
1679	if (info->family < AMDGPU_FAMILY_CI) {
1680		info->cursor_w = CURSOR_WIDTH;
1681		info->cursor_h = CURSOR_HEIGHT;
1682	} else {
1683		info->cursor_w = CURSOR_WIDTH_CIK;
1684		info->cursor_h = CURSOR_HEIGHT_CIK;
1685	}
1686
1687	amdgpu_query_heap_size(pAMDGPUEnt->pDev, AMDGPU_GEM_DOMAIN_GTT,
1688				&heap_size, &max_allocation);
1689	info->gart_size = heap_size;
1690	amdgpu_query_heap_size(pAMDGPUEnt->pDev, AMDGPU_GEM_DOMAIN_VRAM,
1691				&heap_size, &max_allocation);
1692	info->vram_size = max_allocation;
1693
1694	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1695		   "mem size init: gart size :%llx vram size: s:%llx visible:%llx\n",
1696		   (unsigned long long)info->gart_size,
1697		   (unsigned long long)heap_size,
1698		   (unsigned long long)max_allocation);
1699
1700	cpp = pScrn->bitsPerPixel / 8;
1701	pScrn->displayWidth =
1702	    AMDGPU_ALIGN(pScrn->virtualX, drmmode_get_pitch_align(pScrn, cpp));
1703
1704	/* Set display resolution */
1705	xf86SetDpi(pScrn, 0, 0);
1706
1707	if (!xf86SetGamma(pScrn, zeros))
1708		return FALSE;
1709
1710	if (!xf86ReturnOptValBool(info->Options, OPTION_SW_CURSOR, FALSE)) {
1711		if (!xf86LoadSubModule(pScrn, "ramdac"))
1712			return FALSE;
1713	}
1714
1715	if (!pScrn->modes
1716#ifdef XSERVER_PLATFORM_BUS
1717	    && !pScrn->is_gpu
1718#endif
1719	    ) {
1720		xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No modes.\n");
1721		return FALSE;
1722	}
1723
1724	return TRUE;
1725}
1726
1727static Bool AMDGPUCursorInit_KMS(ScreenPtr pScreen)
1728{
1729	ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
1730	AMDGPUInfoPtr info = AMDGPUPTR(pScrn);
1731
1732	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG,
1733		       "Initializing Cursor\n");
1734
1735	/* Set Silken Mouse */
1736	xf86SetSilkenMouse(pScreen);
1737
1738	/* Cursor setup */
1739	miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
1740
1741	if (info->allowPageFlip) {
1742		miPointerScreenPtr PointPriv =
1743			dixLookupPrivate(&pScreen->devPrivates, miPointerScreenKey);
1744
1745		if (!dixRegisterScreenPrivateKey(&amdgpu_device_private_key, pScreen,
1746						 PRIVATE_DEVICE,
1747						 sizeof(struct amdgpu_device_priv))) {
1748			xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "dixRegisterScreenPrivateKey failed\n");
1749			return FALSE;
1750		}
1751
1752		info->SpriteFuncs = PointPriv->spriteFuncs;
1753		PointPriv->spriteFuncs = &drmmode_sprite_funcs;
1754	}
1755
1756	if (xf86ReturnOptValBool(info->Options, OPTION_SW_CURSOR, FALSE))
1757		return TRUE;
1758
1759	if (!xf86_cursors_init(pScreen, info->cursor_w, info->cursor_h,
1760			       HARDWARE_CURSOR_TRUECOLOR_AT_8BPP |
1761			       HARDWARE_CURSOR_AND_SOURCE_WITH_MASK |
1762			       HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_1 |
1763			       HARDWARE_CURSOR_UPDATE_UNHIDDEN |
1764			       HARDWARE_CURSOR_ARGB)) {
1765		xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "xf86_cursors_init failed\n");
1766		return FALSE;
1767	}
1768
1769	return TRUE;
1770}
1771
1772void AMDGPUBlank(ScrnInfoPtr pScrn)
1773{
1774	xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
1775	xf86OutputPtr output;
1776	xf86CrtcPtr crtc;
1777	int o, c;
1778
1779	for (c = 0; c < xf86_config->num_crtc; c++) {
1780		crtc = xf86_config->crtc[c];
1781		for (o = 0; o < xf86_config->num_output; o++) {
1782			output = xf86_config->output[o];
1783			if (output->crtc != crtc)
1784				continue;
1785
1786			output->funcs->dpms(output, DPMSModeOff);
1787		}
1788		crtc->funcs->dpms(crtc, DPMSModeOff);
1789	}
1790}
1791
1792void AMDGPUUnblank(ScrnInfoPtr pScrn)
1793{
1794	xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
1795	xf86OutputPtr output;
1796	xf86CrtcPtr crtc;
1797	int o, c;
1798	for (c = 0; c < xf86_config->num_crtc; c++) {
1799		crtc = xf86_config->crtc[c];
1800		if (!crtc->enabled)
1801			continue;
1802		crtc->funcs->dpms(crtc, DPMSModeOn);
1803		for (o = 0; o < xf86_config->num_output; o++) {
1804			output = xf86_config->output[o];
1805			if (output->crtc != crtc)
1806				continue;
1807			output->funcs->dpms(output, DPMSModeOn);
1808		}
1809	}
1810}
1811
1812static Bool amdgpu_set_drm_master(ScrnInfoPtr pScrn)
1813{
1814	AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(pScrn);
1815	int err;
1816
1817#ifdef XF86_PDEV_SERVER_FD
1818	if (pAMDGPUEnt->platform_dev &&
1819	    (pAMDGPUEnt->platform_dev->flags & XF86_PDEV_SERVER_FD))
1820		return TRUE;
1821#endif
1822
1823	err = drmSetMaster(pAMDGPUEnt->fd);
1824	if (err)
1825		ErrorF("Unable to retrieve master\n");
1826
1827	return err == 0;
1828}
1829
1830static void amdgpu_drop_drm_master(ScrnInfoPtr pScrn)
1831{
1832	AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(pScrn);
1833
1834#ifdef XF86_PDEV_SERVER_FD
1835	if (pAMDGPUEnt->platform_dev &&
1836	    (pAMDGPUEnt->platform_dev->flags & XF86_PDEV_SERVER_FD))
1837		return;
1838#endif
1839
1840	drmDropMaster(pAMDGPUEnt->fd);
1841}
1842
1843
1844static
1845CARD32 cleanup_black_fb(OsTimerPtr timer, CARD32 now, pointer data)
1846{
1847	ScreenPtr screen = data;
1848	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
1849	AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(scrn);
1850	xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
1851	int c;
1852
1853	if (xf86ScreenToScrn(amdgpu_primary_screen(screen))->vtSema)
1854		return 0;
1855
1856	/* Unreference the all-black FB created by AMDGPULeaveVT_KMS. After
1857	 * this, there should be no FB left created by this driver.
1858	 */
1859	for (c = 0; c < xf86_config->num_crtc; c++) {
1860		drmmode_crtc_private_ptr drmmode_crtc =
1861			xf86_config->crtc[c]->driver_private;
1862
1863		drmmode_fb_reference(pAMDGPUEnt->fd, &drmmode_crtc->fb, NULL);
1864	}
1865
1866	TimerFree(timer);
1867	return 0;
1868}
1869
1870static Bool AMDGPUSaveScreen_KMS(ScreenPtr pScreen, int mode)
1871{
1872	ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
1873	Bool unblank;
1874
1875	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG,
1876		       "AMDGPUSaveScreen(%d)\n", mode);
1877
1878	unblank = xf86IsUnblank(mode);
1879	if (unblank)
1880		SetTimeSinceLastInputEvent();
1881
1882	if ((pScrn != NULL) && pScrn->vtSema) {
1883		if (unblank)
1884			AMDGPUUnblank(pScrn);
1885		else
1886			AMDGPUBlank(pScrn);
1887	}
1888	return TRUE;
1889}
1890
1891/* Called at the end of each server generation.  Restore the original
1892 * text mode, unmap video memory, and unwrap and call the saved
1893 * CloseScreen function.
1894 */
1895static Bool AMDGPUCloseScreen_KMS(ScreenPtr pScreen)
1896{
1897	ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
1898	AMDGPUInfoPtr info = AMDGPUPTR(pScrn);
1899	AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(pScrn);
1900
1901	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG,
1902		       "AMDGPUCloseScreen\n");
1903
1904	/* Clear mask of assigned crtc's in this generation */
1905	pAMDGPUEnt->assigned_crtcs = 0;
1906
1907	drmmode_uevent_fini(pScrn, &info->drmmode);
1908	amdgpu_drm_queue_close(pScrn);
1909
1910	if (info->callback_event_type != -1) {
1911		DeleteCallback(&EventCallback, amdgpu_event_callback, pScrn);
1912		DeleteCallback(&FlushCallback, amdgpu_flush_callback, pScrn);
1913	}
1914
1915	amdgpu_sync_close(pScreen);
1916	amdgpu_drop_drm_master(pScrn);
1917
1918	drmmode_fini(pScrn, &info->drmmode);
1919	if (info->dri2.enabled) {
1920		amdgpu_dri2_close_screen(pScreen);
1921	}
1922	amdgpu_glamor_fini(pScreen);
1923	pScrn->vtSema = FALSE;
1924	xf86ClearPrimInitDone(info->pEnt->index);
1925
1926	if (info->allowPageFlip) {
1927		miPointerScreenPtr PointPriv =
1928			dixLookupPrivate(&pScreen->devPrivates, miPointerScreenKey);
1929
1930		if (PointPriv->spriteFuncs == &drmmode_sprite_funcs)
1931			PointPriv->spriteFuncs = info->SpriteFuncs;
1932	}
1933
1934	pScreen->BlockHandler = info->BlockHandler;
1935	pScreen->CloseScreen = info->CloseScreen;
1936	return pScreen->CloseScreen(pScreen);
1937}
1938
1939void AMDGPUFreeScreen_KMS(ScrnInfoPtr pScrn)
1940{
1941	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG,
1942		       "AMDGPUFreeScreen\n");
1943
1944	AMDGPUFreeRec(pScrn);
1945}
1946
1947Bool AMDGPUScreenInit_KMS(ScreenPtr pScreen, int argc, char **argv)
1948{
1949	ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
1950	AMDGPUInfoPtr info = AMDGPUPTR(pScrn);
1951	int subPixelOrder = SubPixelUnknown;
1952	MessageType from;
1953	Bool value;
1954	int driLevel;
1955	const char *s;
1956	void *front_ptr;
1957
1958	pScrn->fbOffset = 0;
1959
1960	miClearVisualTypes();
1961	if (!miSetVisualTypes(pScrn->depth,
1962			      miGetDefaultVisualMask(pScrn->depth),
1963			      pScrn->rgbBits, pScrn->defaultVisual))
1964		return FALSE;
1965	miSetPixmapDepths();
1966
1967	if (!amdgpu_set_drm_master(pScrn))
1968		return FALSE;
1969
1970	info->directRenderingEnabled = FALSE;
1971	if (info->shadow_fb == FALSE)
1972		info->directRenderingEnabled = amdgpu_dri2_screen_init(pScreen);
1973
1974	if (!amdgpu_setup_kernel_mem(pScreen)) {
1975		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1976			   "amdgpu_setup_kernel_mem failed\n");
1977		return FALSE;
1978	}
1979	front_ptr = info->front_buffer->cpu_ptr;
1980
1981	if (info->shadow_fb) {
1982		info->fb_shadow = calloc(1,
1983					 pScrn->displayWidth * pScrn->virtualY *
1984					 ((pScrn->bitsPerPixel + 7) >> 3));
1985		if (!info->fb_shadow) {
1986			xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1987				   "Failed to allocate shadow framebuffer\n");
1988			return FALSE;
1989		} else {
1990			if (!fbScreenInit(pScreen, info->fb_shadow,
1991					  pScrn->virtualX, pScrn->virtualY,
1992					  pScrn->xDpi, pScrn->yDpi,
1993					  pScrn->displayWidth,
1994					  pScrn->bitsPerPixel))
1995				return FALSE;
1996		}
1997	}
1998
1999	if (info->shadow_fb == FALSE) {
2000		/* Init fb layer */
2001		if (!fbScreenInit(pScreen, front_ptr,
2002				  pScrn->virtualX, pScrn->virtualY,
2003				  pScrn->xDpi, pScrn->yDpi, pScrn->displayWidth,
2004				  pScrn->bitsPerPixel))
2005			return FALSE;
2006	}
2007
2008	xf86SetBlackWhitePixels(pScreen);
2009
2010	if (pScrn->bitsPerPixel > 8) {
2011		VisualPtr visual;
2012
2013		visual = pScreen->visuals + pScreen->numVisuals;
2014		while (--visual >= pScreen->visuals) {
2015			if ((visual->class | DynamicClass) == DirectColor) {
2016				visual->offsetRed = pScrn->offset.red;
2017				visual->offsetGreen = pScrn->offset.green;
2018				visual->offsetBlue = pScrn->offset.blue;
2019				visual->redMask = pScrn->mask.red;
2020				visual->greenMask = pScrn->mask.green;
2021				visual->blueMask = pScrn->mask.blue;
2022			}
2023		}
2024	}
2025
2026	/* Must be after RGB order fixed */
2027	fbPictureInit(pScreen, 0, 0);
2028
2029#ifdef RENDER
2030	if ((s = xf86GetOptValString(info->Options, OPTION_SUBPIXEL_ORDER))) {
2031		if (strcmp(s, "RGB") == 0)
2032			subPixelOrder = SubPixelHorizontalRGB;
2033		else if (strcmp(s, "BGR") == 0)
2034			subPixelOrder = SubPixelHorizontalBGR;
2035		else if (strcmp(s, "NONE") == 0)
2036			subPixelOrder = SubPixelNone;
2037		PictureSetSubpixelOrder(pScreen, subPixelOrder);
2038	}
2039#endif
2040
2041	if (!pScreen->isGPU) {
2042		if (xorgGetVersion() >= XORG_VERSION_NUMERIC(1,18,3,0,0))
2043			value = info->use_glamor;
2044		else
2045			value = FALSE;
2046		from = X_DEFAULT;
2047
2048		if (info->use_glamor) {
2049			if (xf86GetOptValBool(info->Options, OPTION_DRI3, &value))
2050				from = X_CONFIG;
2051
2052			if (xf86GetOptValInteger(info->Options, OPTION_DRI, &driLevel) &&
2053			    (driLevel == 2 || driLevel == 3)) {
2054				from = X_CONFIG;
2055				value = driLevel == 3;
2056			}
2057		}
2058
2059		if (value) {
2060			value = amdgpu_sync_init(pScreen) &&
2061				amdgpu_present_screen_init(pScreen) &&
2062				amdgpu_dri3_screen_init(pScreen);
2063
2064			if (!value)
2065				from = X_WARNING;
2066		}
2067
2068		xf86DrvMsg(pScrn->scrnIndex, from, "DRI3 %sabled\n", value ? "en" : "dis");
2069	}
2070
2071	pScrn->vtSema = TRUE;
2072	xf86SetBackingStore(pScreen);
2073
2074	if (info->directRenderingEnabled) {
2075		xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2076			   "Direct rendering enabled\n");
2077	} else {
2078		xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
2079			   "Direct rendering disabled\n");
2080	}
2081
2082	if (info->use_glamor && info->directRenderingEnabled) {
2083		xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG,
2084			       "Initializing Acceleration\n");
2085		if (amdgpu_glamor_init(pScreen)) {
2086			xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2087				   "Acceleration enabled\n");
2088		} else {
2089			xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
2090				   "Acceleration initialization failed\n");
2091			xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2092				   "2D and 3D acceleration disabled\n");
2093			info->use_glamor = FALSE;
2094		}
2095	} else if (info->directRenderingEnabled) {
2096		if (!amdgpu_pixmap_init(pScreen))
2097			xf86DrvMsg(pScrn->scrnIndex, X_INFO, "3D acceleration disabled\n");
2098		xf86DrvMsg(pScrn->scrnIndex, X_INFO, "2D acceleration disabled\n");
2099	} else {
2100		xf86DrvMsg(pScrn->scrnIndex, X_INFO, "2D and 3D acceleration disabled\n");
2101	}
2102
2103	/* Init DPMS */
2104	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG,
2105		       "Initializing DPMS\n");
2106	xf86DPMSInit(pScreen, xf86DPMSSet, 0);
2107
2108	if (!AMDGPUCursorInit_KMS(pScreen))
2109		return FALSE;
2110
2111	/* DGA setup */
2112#ifdef XFreeXDGA
2113	/* DGA is dangerous on kms as the base and framebuffer location may change:
2114	 * http://lists.freedesktop.org/archives/xorg-devel/2009-September/002113.html
2115	 */
2116	/* xf86DiDGAInit(pScreen, info->LinearAddr + pScrn->fbOffset); */
2117#endif
2118	if (info->shadow_fb == FALSE && !pScreen->isGPU) {
2119		/* Init Xv */
2120		xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG,
2121			       "Initializing Xv\n");
2122		AMDGPUInitVideo(pScreen);
2123	}
2124
2125	if (info->shadow_fb == TRUE) {
2126		if (!shadowSetup(pScreen)) {
2127			xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
2128				   "Shadowfb initialization failed\n");
2129			return FALSE;
2130		}
2131	}
2132	pScrn->pScreen = pScreen;
2133
2134	if (!pScreen->isGPU) {
2135		if (serverGeneration == 1 && bgNoneRoot && info->use_glamor) {
2136			info->CreateWindow = pScreen->CreateWindow;
2137			pScreen->CreateWindow = AMDGPUCreateWindow_oneshot;
2138		}
2139		info->WindowExposures = pScreen->WindowExposures;
2140		pScreen->WindowExposures = AMDGPUWindowExposures_oneshot;
2141	}
2142
2143	/* Provide SaveScreen & wrap BlockHandler and CloseScreen */
2144	/* Wrap CloseScreen */
2145	info->CloseScreen = pScreen->CloseScreen;
2146	pScreen->CloseScreen = AMDGPUCloseScreen_KMS;
2147	pScreen->SaveScreen = AMDGPUSaveScreen_KMS;
2148	info->BlockHandler = pScreen->BlockHandler;
2149	pScreen->BlockHandler = AMDGPUBlockHandler_KMS;
2150
2151	info->CreateScreenResources = pScreen->CreateScreenResources;
2152	pScreen->CreateScreenResources = AMDGPUCreateScreenResources_KMS;
2153
2154	pScreen->StartPixmapTracking = PixmapStartDirtyTracking;
2155	pScreen->StopPixmapTracking = PixmapStopDirtyTracking;
2156#if HAS_SYNC_SHARED_PIXMAP
2157	pScreen->SyncSharedPixmap = amdgpu_sync_shared_pixmap;
2158#endif
2159
2160	if (!xf86CrtcScreenInit(pScreen))
2161		return FALSE;
2162
2163	/* Wrap pointer motion to flip touch screen around */
2164//    info->PointerMoved = pScrn->PointerMoved;
2165//    pScrn->PointerMoved = AMDGPUPointerMoved;
2166
2167	if (!drmmode_setup_colormap(pScreen, pScrn))
2168		return FALSE;
2169
2170	/* Note unused options */
2171	if (serverGeneration == 1)
2172		xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
2173
2174	if (info->vrr_support) {
2175		if (!amdgpu_property_vectors_wrapped) {
2176			saved_change_property = ProcVector[X_ChangeProperty];
2177			ProcVector[X_ChangeProperty] = amdgpu_change_property;
2178			saved_delete_property = ProcVector[X_DeleteProperty];
2179			ProcVector[X_DeleteProperty] = amdgpu_delete_property;
2180			amdgpu_property_vectors_wrapped = TRUE;
2181		}
2182
2183		amdgpu_vrr_atom = MakeAtom("_VARIABLE_REFRESH",
2184					   strlen("_VARIABLE_REFRESH"), TRUE);
2185	}
2186
2187	drmmode_init(pScrn, &info->drmmode);
2188
2189	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG,
2190		       "AMDGPUScreenInit finished\n");
2191
2192	return TRUE;
2193}
2194
2195Bool AMDGPUEnterVT_KMS(ScrnInfoPtr pScrn)
2196{
2197	AMDGPUInfoPtr info = AMDGPUPTR(pScrn);
2198
2199	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG,
2200		       "AMDGPUEnterVT_KMS\n");
2201
2202	amdgpu_set_drm_master(pScrn);
2203
2204	if (info->shadow_fb) {
2205		int pitch;
2206		struct amdgpu_buffer *front_buffer =
2207			amdgpu_alloc_pixmap_bo(pScrn, pScrn->virtualX,
2208					       pScrn->virtualY, pScrn->depth,
2209					       AMDGPU_CREATE_PIXMAP_SCANOUT |
2210					       AMDGPU_CREATE_PIXMAP_LINEAR,
2211					       pScrn->bitsPerPixel,
2212					       &pitch);
2213
2214		if (front_buffer) {
2215			if (amdgpu_bo_map(pScrn, front_buffer) == 0) {
2216				memset(front_buffer->cpu_ptr, 0, pitch * pScrn->virtualY);
2217				amdgpu_bo_unref(&info->front_buffer);
2218				info->front_buffer = front_buffer;
2219			} else {
2220				amdgpu_bo_unref(&front_buffer);
2221				front_buffer = NULL;
2222			}
2223		}
2224
2225		if (!front_buffer) {
2226			xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
2227				   "Failed to allocate new scanout BO after VT switch, "
2228				   "other DRM masters may see screen contents\n");
2229		}
2230	}
2231
2232	pScrn->vtSema = TRUE;
2233
2234	if (!drmmode_set_desired_modes(pScrn, &info->drmmode, TRUE))
2235		return FALSE;
2236
2237	return TRUE;
2238}
2239
2240static void
2241pixmap_unref_fb(PixmapPtr pixmap)
2242{
2243	ScrnInfoPtr scrn = xf86ScreenToScrn(pixmap->drawable.pScreen);
2244	struct drmmode_fb **fb_ptr = amdgpu_pixmap_get_fb_ptr(pixmap);
2245	AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(scrn);
2246
2247	if (fb_ptr)
2248		drmmode_fb_reference(pAMDGPUEnt->fd, fb_ptr, NULL);
2249}
2250
2251static void
2252client_pixmap_unref_fb(void *value, XID id, void *pScreen)
2253{
2254	PixmapPtr pixmap = value;
2255
2256	if (pixmap->drawable.pScreen == pScreen)
2257		pixmap_unref_fb(pixmap);
2258}
2259
2260void AMDGPULeaveVT_KMS(ScrnInfoPtr pScrn)
2261{
2262	AMDGPUInfoPtr info = AMDGPUPTR(pScrn);
2263	ScreenPtr pScreen = pScrn->pScreen;
2264
2265	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG,
2266		       "AMDGPULeaveVT_KMS\n");
2267
2268	if (!info->shadow_fb) {
2269		AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(pScrn);
2270		xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
2271		xf86CrtcPtr crtc;
2272		drmmode_crtc_private_ptr drmmode_crtc;
2273		unsigned w = 0, h = 0;
2274		int i;
2275
2276		/* If we're called from CloseScreen, trying to clear the black
2277		 * scanout BO will likely crash and burn
2278		 */
2279		if (!pScreen->GCperDepth[0])
2280			goto hide_cursors;
2281
2282		/* Compute maximum scanout dimensions of active CRTCs */
2283		for (i = 0; i < xf86_config->num_crtc; i++) {
2284			crtc = xf86_config->crtc[i];
2285			drmmode_crtc = crtc->driver_private;
2286
2287			if (!drmmode_crtc->fb)
2288				continue;
2289
2290			w = max(w, crtc->mode.HDisplay);
2291			h = max(h, crtc->mode.VDisplay);
2292		}
2293
2294		/* Make all active CRTCs scan out from an all-black framebuffer */
2295		if (w > 0 && h > 0) {
2296			PixmapPtr black_scanout =
2297				pScreen->CreatePixmap(pScreen, w, h, pScrn->depth,
2298						      AMDGPU_CREATE_PIXMAP_SCANOUT);
2299
2300			if (black_scanout) {
2301				struct drmmode_fb *black_fb =
2302					amdgpu_pixmap_get_fb(black_scanout);
2303
2304				amdgpu_pixmap_clear(black_scanout);
2305				amdgpu_glamor_finish(pScrn);
2306
2307				for (i = 0; i < xf86_config->num_crtc; i++) {
2308					crtc = xf86_config->crtc[i];
2309					drmmode_crtc = crtc->driver_private;
2310
2311					if (drmmode_crtc->fb) {
2312						if (black_fb) {
2313							drmmode_set_mode(crtc, black_fb, &crtc->mode, 0, 0);
2314						} else {
2315							drmModeSetCrtc(pAMDGPUEnt->fd,
2316								       drmmode_crtc->mode_crtc->crtc_id, 0,
2317								       0, 0, NULL, 0, NULL);
2318							drmmode_fb_reference(pAMDGPUEnt->fd,
2319									     &drmmode_crtc->fb, NULL);
2320						}
2321
2322						if (pScrn->is_gpu) {
2323							if (drmmode_crtc->scanout[0])
2324								pixmap_unref_fb(drmmode_crtc->scanout[0]);
2325							if (drmmode_crtc->scanout[1])
2326								pixmap_unref_fb(drmmode_crtc->scanout[1]);
2327						} else {
2328							drmmode_crtc_scanout_free(crtc);
2329						}
2330					}
2331				}
2332
2333				pScreen->DestroyPixmap(black_scanout);
2334			}
2335		}
2336
2337		xf86RotateFreeShadow(pScrn);
2338
2339		/* Unreference FBs of all pixmaps. After this, the only FB remaining
2340		 * should be the all-black one being scanned out by active CRTCs
2341		 */
2342		for (i = 0; i < currentMaxClients; i++) {
2343			if (i > 0 &&
2344			    (!clients[i] || clients[i]->clientState != ClientStateRunning))
2345				continue;
2346
2347			FindClientResourcesByType(clients[i], RT_PIXMAP,
2348						  client_pixmap_unref_fb, pScreen);
2349		}
2350
2351		pixmap_unref_fb(pScreen->GetScreenPixmap(pScreen));
2352	} else {
2353		memset(info->front_buffer->cpu_ptr, 0, pScrn->virtualX *
2354		       info->pixel_bytes * pScrn->virtualY);
2355	}
2356
2357	if (pScreen->GCperDepth[0])
2358		TimerSet(NULL, 0, 1000, cleanup_black_fb, pScreen);
2359
2360 hide_cursors:
2361	xf86_hide_cursors(pScrn);
2362
2363	amdgpu_drop_drm_master(pScrn);
2364
2365	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG,
2366		       "Ok, leaving now...\n");
2367}
2368
2369Bool AMDGPUSwitchMode_KMS(ScrnInfoPtr pScrn, DisplayModePtr mode)
2370{
2371	Bool ret;
2372	ret = xf86SetSingleMode(pScrn, mode, RR_Rotate_0);
2373	return ret;
2374
2375}
2376
2377void AMDGPUAdjustFrame_KMS(ScrnInfoPtr pScrn, int x, int y)
2378{
2379	AMDGPUInfoPtr info = AMDGPUPTR(pScrn);
2380	drmmode_adjust_frame(pScrn, &info->drmmode, x, y);
2381	return;
2382}
2383
2384static Bool amdgpu_setup_kernel_mem(ScreenPtr pScreen)
2385{
2386	ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
2387	AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(pScrn);
2388	AMDGPUInfoPtr info = AMDGPUPTR(pScrn);
2389	xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
2390	int cpp = info->pixel_bytes;
2391	int cursor_size;
2392	int c, i;
2393
2394	cursor_size = info->cursor_w * info->cursor_h * 4;
2395	cursor_size = AMDGPU_ALIGN(cursor_size, AMDGPU_GPU_PAGE_SIZE);
2396	for (c = 0; c < xf86_config->num_crtc; c++) {
2397		drmmode_crtc_private_ptr drmmode_crtc = xf86_config->crtc[c]->driver_private;
2398
2399		for (i = 0; i < 2; i++) {
2400			if (!drmmode_crtc->cursor_buffer[i]) {
2401				drmmode_crtc->cursor_buffer[i] =
2402					amdgpu_bo_open(pAMDGPUEnt->pDev,
2403						       cursor_size, 0,
2404						       AMDGPU_GEM_DOMAIN_VRAM);
2405
2406				if (!(drmmode_crtc->cursor_buffer[i])) {
2407					ErrorF("Failed to allocate cursor buffer memory\n");
2408					return FALSE;
2409				}
2410
2411				if (amdgpu_bo_cpu_map(drmmode_crtc->cursor_buffer[i]->bo.amdgpu,
2412						      &drmmode_crtc->cursor_buffer[i]->cpu_ptr))
2413					ErrorF("Failed to map cursor buffer memory\n");
2414			}
2415		}
2416	}
2417
2418	if (!info->front_buffer) {
2419		int pitch;
2420		int hint = AMDGPU_CREATE_PIXMAP_SCANOUT;
2421
2422		if (info->shadow_primary)
2423			hint |= AMDGPU_CREATE_PIXMAP_LINEAR | AMDGPU_CREATE_PIXMAP_GTT;
2424		else if (!info->use_glamor)
2425			hint |= AMDGPU_CREATE_PIXMAP_LINEAR;
2426
2427		info->front_buffer =
2428			amdgpu_alloc_pixmap_bo(pScrn, pScrn->virtualX,
2429					       pScrn->virtualY, pScrn->depth,
2430					       hint, pScrn->bitsPerPixel,
2431					       &pitch);
2432		if (!(info->front_buffer)) {
2433			ErrorF("Failed to allocate front buffer memory\n");
2434			return FALSE;
2435		}
2436
2437		if (!info->use_glamor &&
2438		    amdgpu_bo_map(pScrn, info->front_buffer) != 0) {
2439			ErrorF("Failed to map front buffer memory\n");
2440			return FALSE;
2441		}
2442
2443		pScrn->displayWidth = pitch / cpp;
2444	}
2445
2446	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Front buffer pitch: %d bytes\n",
2447		   pScrn->displayWidth * cpp);
2448	return TRUE;
2449}
2450
2451/* Used to disallow modes that are not supported by the hardware */
2452ModeStatus AMDGPUValidMode(ScrnInfoPtr pScrn, DisplayModePtr mode,
2453			   Bool verbose, int flag)
2454{
2455	/* There are problems with double scan mode at high clocks
2456	 * They're likely related PLL and display buffer settings.
2457	 * Disable these modes for now.
2458	 */
2459	if (mode->Flags & V_DBLSCAN) {
2460		if ((mode->CrtcHDisplay >= 1024) || (mode->CrtcVDisplay >= 768))
2461			return MODE_CLOCK_RANGE;
2462	}
2463	return MODE_OK;
2464}
2465