amdgpu_kms.c revision 24b90cf4
1d6c0b56eSmrg/* 2d6c0b56eSmrg * Copyright © 2009 Red Hat, Inc. 3d6c0b56eSmrg * 4d6c0b56eSmrg * Permission is hereby granted, free of charge, to any person obtaining a 5d6c0b56eSmrg * copy of this software and associated documentation files (the "Software"), 6d6c0b56eSmrg * to deal in the Software without restriction, including without limitation 7d6c0b56eSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8d6c0b56eSmrg * and/or sell copies of the Software, and to permit persons to whom the 9d6c0b56eSmrg * Software is furnished to do so, subject to the following conditions: 10d6c0b56eSmrg * 11d6c0b56eSmrg * The above copyright notice and this permission notice (including the next 12d6c0b56eSmrg * paragraph) shall be included in all copies or substantial portions of the 13d6c0b56eSmrg * Software. 14d6c0b56eSmrg * 15d6c0b56eSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16d6c0b56eSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17d6c0b56eSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18d6c0b56eSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19d6c0b56eSmrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20d6c0b56eSmrg * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21d6c0b56eSmrg * SOFTWARE. 22d6c0b56eSmrg * 23d6c0b56eSmrg * Authors: 24d6c0b56eSmrg * Dave Airlie <airlied@redhat.com> 25d6c0b56eSmrg * 26d6c0b56eSmrg */ 27d6c0b56eSmrg#ifdef HAVE_CONFIG_H 28d6c0b56eSmrg#include "config.h" 29d6c0b56eSmrg#endif 30d6c0b56eSmrg 31d6c0b56eSmrg#include <errno.h> 32d6c0b56eSmrg#include <sys/ioctl.h> 33d6c0b56eSmrg/* Driver data structures */ 34d6c0b56eSmrg#include "amdgpu_drv.h" 3524b90cf4Smrg#include "amdgpu_bo_helper.h" 36d6c0b56eSmrg#include "amdgpu_drm_queue.h" 37d6c0b56eSmrg#include "amdgpu_glamor.h" 38d6c0b56eSmrg#include "amdgpu_probe.h" 39d6c0b56eSmrg#include "micmap.h" 4024b90cf4Smrg#include "mipointrst.h" 41d6c0b56eSmrg 42d6c0b56eSmrg#include "amdgpu_version.h" 43d6c0b56eSmrg#include "shadow.h" 44504d986fSmrg#include <xf86Priv.h> 45d6c0b56eSmrg 4624b90cf4Smrg#if HAVE_PRESENT_H 4724b90cf4Smrg#include <present.h> 4824b90cf4Smrg#endif 4924b90cf4Smrg 50d6c0b56eSmrg/* DPMS */ 51d6c0b56eSmrg#ifdef HAVE_XEXTPROTO_71 52d6c0b56eSmrg#include <X11/extensions/dpmsconst.h> 53d6c0b56eSmrg#else 54d6c0b56eSmrg#define DPMS_SERVER 55d6c0b56eSmrg#include <X11/extensions/dpms.h> 56d6c0b56eSmrg#endif 57d6c0b56eSmrg 58504d986fSmrg#include <X11/extensions/damageproto.h> 59504d986fSmrg 60d6c0b56eSmrg#include "amdgpu_bo_helper.h" 61d6c0b56eSmrg#include "amdgpu_pixmap.h" 62d6c0b56eSmrg 63d6c0b56eSmrg#include <gbm.h> 64d6c0b56eSmrg 65504d986fSmrgstatic DevScreenPrivateKeyRec amdgpu_client_private_key; 6624b90cf4SmrgDevScreenPrivateKeyRec amdgpu_device_private_key; 67504d986fSmrg 68d6c0b56eSmrgstatic Bool amdgpu_setup_kernel_mem(ScreenPtr pScreen); 69d6c0b56eSmrg 70d6c0b56eSmrgconst OptionInfoRec AMDGPUOptions_KMS[] = { 71d6c0b56eSmrg {OPTION_ACCEL, "Accel", OPTV_BOOLEAN, {0}, FALSE}, 72d6c0b56eSmrg {OPTION_SW_CURSOR, "SWcursor", OPTV_BOOLEAN, {0}, FALSE}, 73d6c0b56eSmrg {OPTION_PAGE_FLIP, "EnablePageFlip", OPTV_BOOLEAN, {0}, FALSE}, 74d6c0b56eSmrg {OPTION_SUBPIXEL_ORDER, "SubPixelOrder", OPTV_ANYSTR, {0}, FALSE}, 75d6c0b56eSmrg {OPTION_ZAPHOD_HEADS, "ZaphodHeads", OPTV_STRING, {0}, FALSE}, 76d6c0b56eSmrg {OPTION_ACCEL_METHOD, "AccelMethod", OPTV_STRING, {0}, FALSE}, 77d6c0b56eSmrg {OPTION_DRI3, "DRI3", OPTV_BOOLEAN, {0}, FALSE}, 78d6c0b56eSmrg {OPTION_DRI, "DRI", OPTV_INTEGER, {0}, FALSE}, 79d6c0b56eSmrg {OPTION_SHADOW_PRIMARY, "ShadowPrimary", OPTV_BOOLEAN, {0}, FALSE}, 80d6c0b56eSmrg {OPTION_TEAR_FREE, "TearFree", OPTV_BOOLEAN, {0}, FALSE}, 81d6c0b56eSmrg {OPTION_DELETE_DP12, "DeleteUnusedDP12Displays", OPTV_BOOLEAN, {0}, FALSE}, 82d6c0b56eSmrg {-1, NULL, OPTV_NONE, {0}, FALSE} 83d6c0b56eSmrg}; 84d6c0b56eSmrg 85d6c0b56eSmrgconst OptionInfoRec *AMDGPUOptionsWeak(void) 86d6c0b56eSmrg{ 87d6c0b56eSmrg return AMDGPUOptions_KMS; 88d6c0b56eSmrg} 89d6c0b56eSmrg 90d6c0b56eSmrgextern _X_EXPORT int gAMDGPUEntityIndex; 91d6c0b56eSmrg 92d6c0b56eSmrgstatic int getAMDGPUEntityIndex(void) 93d6c0b56eSmrg{ 94d6c0b56eSmrg return gAMDGPUEntityIndex; 95d6c0b56eSmrg} 96d6c0b56eSmrg 97d6c0b56eSmrgAMDGPUEntPtr AMDGPUEntPriv(ScrnInfoPtr pScrn) 98d6c0b56eSmrg{ 99d6c0b56eSmrg DevUnion *pPriv; 100d6c0b56eSmrg AMDGPUInfoPtr info = AMDGPUPTR(pScrn); 101d6c0b56eSmrg pPriv = xf86GetEntityPrivate(info->pEnt->index, getAMDGPUEntityIndex()); 102d6c0b56eSmrg return pPriv->ptr; 103d6c0b56eSmrg} 104d6c0b56eSmrg 105d6c0b56eSmrg/* Allocate our private AMDGPUInfoRec */ 106d6c0b56eSmrgstatic Bool AMDGPUGetRec(ScrnInfoPtr pScrn) 107d6c0b56eSmrg{ 108d6c0b56eSmrg if (pScrn->driverPrivate) 109d6c0b56eSmrg return TRUE; 110d6c0b56eSmrg 111d6c0b56eSmrg pScrn->driverPrivate = xnfcalloc(sizeof(AMDGPUInfoRec), 1); 112d6c0b56eSmrg return TRUE; 113d6c0b56eSmrg} 114d6c0b56eSmrg 115d6c0b56eSmrg/* Free our private AMDGPUInfoRec */ 116d6c0b56eSmrgstatic void AMDGPUFreeRec(ScrnInfoPtr pScrn) 117d6c0b56eSmrg{ 118d6c0b56eSmrg DevUnion *pPriv; 119d6c0b56eSmrg AMDGPUEntPtr pAMDGPUEnt; 120d6c0b56eSmrg AMDGPUInfoPtr info; 12124b90cf4Smrg EntityInfoPtr pEnt; 122d6c0b56eSmrg 123d6c0b56eSmrg if (!pScrn) 124d6c0b56eSmrg return; 125d6c0b56eSmrg 126d6c0b56eSmrg info = AMDGPUPTR(pScrn); 12724b90cf4Smrg if (info) { 12824b90cf4Smrg if (info->fbcon_pixmap) 12924b90cf4Smrg pScrn->pScreen->DestroyPixmap(info->fbcon_pixmap); 130d6c0b56eSmrg 13124b90cf4Smrg pEnt = info->pEnt; 13224b90cf4Smrg free(pScrn->driverPrivate); 13324b90cf4Smrg pScrn->driverPrivate = NULL; 13424b90cf4Smrg } else { 13524b90cf4Smrg pEnt = xf86GetEntityInfo(pScrn->entityList[pScrn->numEntities - 1]); 13624b90cf4Smrg } 13724b90cf4Smrg 13824b90cf4Smrg pPriv = xf86GetEntityPrivate(pEnt->index, gAMDGPUEntityIndex); 139d6c0b56eSmrg pAMDGPUEnt = pPriv->ptr; 140d6c0b56eSmrg if (pAMDGPUEnt->fd > 0) { 141d6c0b56eSmrg DevUnion *pPriv; 142d6c0b56eSmrg AMDGPUEntPtr pAMDGPUEnt; 143d6c0b56eSmrg pPriv = xf86GetEntityPrivate(pScrn->entityList[0], 144d6c0b56eSmrg getAMDGPUEntityIndex()); 145d6c0b56eSmrg 146d6c0b56eSmrg pAMDGPUEnt = pPriv->ptr; 147d6c0b56eSmrg pAMDGPUEnt->fd_ref--; 148d6c0b56eSmrg if (!pAMDGPUEnt->fd_ref) { 149d6c0b56eSmrg amdgpu_device_deinitialize(pAMDGPUEnt->pDev); 15011bf0794Smrg amdgpu_kernel_close_fd(pAMDGPUEnt); 15124b90cf4Smrg free(pPriv->ptr); 15224b90cf4Smrg pPriv->ptr = NULL; 153d6c0b56eSmrg } 154d6c0b56eSmrg } 155d6c0b56eSmrg 15624b90cf4Smrg free(pEnt); 157d6c0b56eSmrg} 158d6c0b56eSmrg 159d6c0b56eSmrgstatic void *amdgpuShadowWindow(ScreenPtr screen, CARD32 row, CARD32 offset, 160d6c0b56eSmrg int mode, CARD32 * size, void *closure) 161d6c0b56eSmrg{ 162d6c0b56eSmrg ScrnInfoPtr pScrn = xf86ScreenToScrn(screen); 163d6c0b56eSmrg AMDGPUInfoPtr info = AMDGPUPTR(pScrn); 164d6c0b56eSmrg int stride; 165d6c0b56eSmrg 166d6c0b56eSmrg stride = (pScrn->displayWidth * pScrn->bitsPerPixel) / 8; 167d6c0b56eSmrg *size = stride; 168d6c0b56eSmrg 169d6c0b56eSmrg return ((uint8_t *) info->front_buffer->cpu_ptr + row * stride + offset); 170d6c0b56eSmrg} 171d6c0b56eSmrg 172d6c0b56eSmrgstatic void 173d6c0b56eSmrgamdgpuUpdatePacked(ScreenPtr pScreen, shadowBufPtr pBuf) 174d6c0b56eSmrg{ 175d6c0b56eSmrg shadowUpdatePacked(pScreen, pBuf); 176d6c0b56eSmrg} 177d6c0b56eSmrg 178504d986fSmrgstatic Bool 179504d986fSmrgcallback_needs_flush(AMDGPUInfoPtr info, struct amdgpu_client_priv *client_priv) 180504d986fSmrg{ 181504d986fSmrg return (int)(client_priv->needs_flush - info->gpu_flushed) > 0; 182504d986fSmrg} 183504d986fSmrg 184504d986fSmrgstatic void 185504d986fSmrgamdgpu_event_callback(CallbackListPtr *list, 186504d986fSmrg pointer user_data, pointer call_data) 187504d986fSmrg{ 188504d986fSmrg EventInfoRec *eventinfo = call_data; 189504d986fSmrg ScrnInfoPtr pScrn = user_data; 190504d986fSmrg ScreenPtr pScreen = pScrn->pScreen; 191504d986fSmrg struct amdgpu_client_priv *client_priv = 192504d986fSmrg dixLookupScreenPrivate(&eventinfo->client->devPrivates, 193504d986fSmrg &amdgpu_client_private_key, pScreen); 194504d986fSmrg struct amdgpu_client_priv *server_priv = 195504d986fSmrg dixLookupScreenPrivate(&serverClient->devPrivates, 196504d986fSmrg &amdgpu_client_private_key, pScreen); 197504d986fSmrg AMDGPUInfoPtr info = AMDGPUPTR(pScrn); 198504d986fSmrg int i; 199504d986fSmrg 200504d986fSmrg if (callback_needs_flush(info, client_priv) || 201504d986fSmrg callback_needs_flush(info, server_priv)) 202504d986fSmrg return; 203504d986fSmrg 204504d986fSmrg /* Don't let gpu_flushed get too far ahead of needs_flush, in order 205504d986fSmrg * to prevent false positives in callback_needs_flush() 206504d986fSmrg */ 207504d986fSmrg client_priv->needs_flush = info->gpu_flushed; 208504d986fSmrg server_priv->needs_flush = info->gpu_flushed; 209504d986fSmrg 210504d986fSmrg for (i = 0; i < eventinfo->count; i++) { 211504d986fSmrg if (eventinfo->events[i].u.u.type == info->callback_event_type) { 212504d986fSmrg client_priv->needs_flush++; 213504d986fSmrg server_priv->needs_flush++; 214504d986fSmrg return; 215504d986fSmrg } 216504d986fSmrg } 217504d986fSmrg} 218504d986fSmrg 219504d986fSmrgstatic void 220504d986fSmrgamdgpu_flush_callback(CallbackListPtr *list, 221504d986fSmrg pointer user_data, pointer call_data) 222504d986fSmrg{ 223504d986fSmrg ScrnInfoPtr pScrn = user_data; 224504d986fSmrg ScreenPtr pScreen = pScrn->pScreen; 225504d986fSmrg ClientPtr client = call_data ? call_data : serverClient; 226504d986fSmrg struct amdgpu_client_priv *client_priv = 227504d986fSmrg dixLookupScreenPrivate(&client->devPrivates, 228504d986fSmrg &amdgpu_client_private_key, pScreen); 229504d986fSmrg AMDGPUInfoPtr info = AMDGPUPTR(pScrn); 230504d986fSmrg 231504d986fSmrg if (pScrn->vtSema && callback_needs_flush(info, client_priv)) 232504d986fSmrg amdgpu_glamor_flush(pScrn); 233504d986fSmrg} 234504d986fSmrg 235d6c0b56eSmrgstatic Bool AMDGPUCreateScreenResources_KMS(ScreenPtr pScreen) 236d6c0b56eSmrg{ 23711bf0794Smrg ExtensionEntry *damage_ext; 238d6c0b56eSmrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 239d6c0b56eSmrg AMDGPUInfoPtr info = AMDGPUPTR(pScrn); 240d6c0b56eSmrg PixmapPtr pixmap; 241d6c0b56eSmrg 242d6c0b56eSmrg pScreen->CreateScreenResources = info->CreateScreenResources; 243d6c0b56eSmrg if (!(*pScreen->CreateScreenResources) (pScreen)) 244d6c0b56eSmrg return FALSE; 245d6c0b56eSmrg pScreen->CreateScreenResources = AMDGPUCreateScreenResources_KMS; 246d6c0b56eSmrg 247d6c0b56eSmrg /* Set the RandR primary output if Xorg hasn't */ 248504d986fSmrg if (dixPrivateKeyRegistered(rrPrivKey)) { 249504d986fSmrg rrScrPrivPtr rrScrPriv = rrGetScrPriv(pScreen); 250504d986fSmrg 25124b90cf4Smrg if (!pScreen->isGPU && !rrScrPriv->primaryOutput) { 252504d986fSmrg xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); 253d6c0b56eSmrg 254504d986fSmrg rrScrPriv->primaryOutput = xf86_config->output[0]->randr_output; 255504d986fSmrg RROutputChanged(rrScrPriv->primaryOutput, FALSE); 256504d986fSmrg rrScrPriv->layoutChanged = TRUE; 257504d986fSmrg } 258d6c0b56eSmrg } 259d6c0b56eSmrg 26024b90cf4Smrg if (!drmmode_set_desired_modes(pScrn, &info->drmmode, pScreen->isGPU)) 261d6c0b56eSmrg return FALSE; 262d6c0b56eSmrg 263d6c0b56eSmrg drmmode_uevent_init(pScrn, &info->drmmode); 264d6c0b56eSmrg 265d6c0b56eSmrg if (info->shadow_fb) { 266d6c0b56eSmrg pixmap = pScreen->GetScreenPixmap(pScreen); 267d6c0b56eSmrg 268d6c0b56eSmrg if (!shadowAdd(pScreen, pixmap, amdgpuUpdatePacked, 269d6c0b56eSmrg amdgpuShadowWindow, 0, NULL)) 270d6c0b56eSmrg return FALSE; 271d6c0b56eSmrg } 272d6c0b56eSmrg 273d6c0b56eSmrg if (info->dri2.enabled || info->use_glamor) { 274d6c0b56eSmrg if (info->front_buffer) { 275d6c0b56eSmrg PixmapPtr pPix = pScreen->GetScreenPixmap(pScreen); 276504d986fSmrg 277504d986fSmrg if (!amdgpu_set_pixmap_bo(pPix, info->front_buffer)) 278504d986fSmrg return FALSE; 279d6c0b56eSmrg } 280d6c0b56eSmrg } 281d6c0b56eSmrg 282d6c0b56eSmrg if (info->use_glamor) 283d6c0b56eSmrg amdgpu_glamor_create_screen_resources(pScreen); 284d6c0b56eSmrg 285504d986fSmrg info->callback_event_type = -1; 28624b90cf4Smrg if (!pScreen->isGPU && (damage_ext = CheckExtension("DAMAGE"))) { 287504d986fSmrg info->callback_event_type = damage_ext->eventBase + XDamageNotify; 288504d986fSmrg 289504d986fSmrg if (!AddCallback(&FlushCallback, amdgpu_flush_callback, pScrn)) 290504d986fSmrg return FALSE; 291504d986fSmrg 292504d986fSmrg if (!AddCallback(&EventCallback, amdgpu_event_callback, pScrn)) { 293504d986fSmrg DeleteCallback(&FlushCallback, amdgpu_flush_callback, pScrn); 294504d986fSmrg return FALSE; 295504d986fSmrg } 296504d986fSmrg 297504d986fSmrg if (!dixRegisterScreenPrivateKey(&amdgpu_client_private_key, pScreen, 298504d986fSmrg PRIVATE_CLIENT, sizeof(struct amdgpu_client_priv))) { 299504d986fSmrg DeleteCallback(&FlushCallback, amdgpu_flush_callback, pScrn); 300504d986fSmrg DeleteCallback(&EventCallback, amdgpu_event_callback, pScrn); 301504d986fSmrg return FALSE; 302504d986fSmrg } 303504d986fSmrg } 304504d986fSmrg 305d6c0b56eSmrg return TRUE; 306d6c0b56eSmrg} 307d6c0b56eSmrg 308504d986fSmrgstatic Bool 309504d986fSmrgamdgpu_scanout_extents_intersect(xf86CrtcPtr xf86_crtc, BoxPtr extents) 310504d986fSmrg{ 31111bf0794Smrg if (xf86_crtc->scrn->is_gpu) { 31211bf0794Smrg extents->x1 -= xf86_crtc->x; 31311bf0794Smrg extents->y1 -= xf86_crtc->y; 31411bf0794Smrg extents->x2 -= xf86_crtc->x; 31511bf0794Smrg extents->y2 -= xf86_crtc->y; 31624b90cf4Smrg } else { 31711bf0794Smrg extents->x1 -= xf86_crtc->filter_width >> 1; 31811bf0794Smrg extents->x2 += xf86_crtc->filter_width >> 1; 31911bf0794Smrg extents->y1 -= xf86_crtc->filter_height >> 1; 32011bf0794Smrg extents->y2 += xf86_crtc->filter_height >> 1; 32111bf0794Smrg pixman_f_transform_bounds(&xf86_crtc->f_framebuffer_to_crtc, extents); 32211bf0794Smrg } 323504d986fSmrg 324504d986fSmrg extents->x1 = max(extents->x1, 0); 325504d986fSmrg extents->y1 = max(extents->y1, 0); 326504d986fSmrg extents->x2 = min(extents->x2, xf86_crtc->mode.HDisplay); 327504d986fSmrg extents->y2 = min(extents->y2, xf86_crtc->mode.VDisplay); 328504d986fSmrg 329504d986fSmrg return (extents->x1 < extents->x2 && extents->y1 < extents->y2); 330504d986fSmrg} 331504d986fSmrg 332504d986fSmrgstatic RegionPtr 333504d986fSmrgtransform_region(RegionPtr region, struct pict_f_transform *transform, 334504d986fSmrg int w, int h) 335504d986fSmrg{ 336504d986fSmrg BoxPtr boxes = RegionRects(region); 337504d986fSmrg int nboxes = RegionNumRects(region); 338504d986fSmrg xRectanglePtr rects = malloc(nboxes * sizeof(*rects)); 339504d986fSmrg RegionPtr transformed; 340504d986fSmrg int nrects = 0; 341504d986fSmrg BoxRec box; 342504d986fSmrg int i; 343504d986fSmrg 344504d986fSmrg for (i = 0; i < nboxes; i++) { 345504d986fSmrg box.x1 = boxes[i].x1; 346504d986fSmrg box.x2 = boxes[i].x2; 347504d986fSmrg box.y1 = boxes[i].y1; 348504d986fSmrg box.y2 = boxes[i].y2; 349504d986fSmrg pixman_f_transform_bounds(transform, &box); 350504d986fSmrg 351504d986fSmrg box.x1 = max(box.x1, 0); 352504d986fSmrg box.y1 = max(box.y1, 0); 353504d986fSmrg box.x2 = min(box.x2, w); 354504d986fSmrg box.y2 = min(box.y2, h); 355504d986fSmrg if (box.x1 >= box.x2 || box.y1 >= box.y2) 356504d986fSmrg continue; 357504d986fSmrg 358504d986fSmrg rects[nrects].x = box.x1; 359504d986fSmrg rects[nrects].y = box.y1; 360504d986fSmrg rects[nrects].width = box.x2 - box.x1; 361504d986fSmrg rects[nrects].height = box.y2 - box.y1; 362504d986fSmrg nrects++; 363504d986fSmrg } 364504d986fSmrg 365504d986fSmrg transformed = RegionFromRects(nrects, rects, CT_UNSORTED); 366504d986fSmrg free(rects); 367504d986fSmrg return transformed; 368504d986fSmrg} 369504d986fSmrg 370504d986fSmrgstatic void 371504d986fSmrgamdgpu_sync_scanout_pixmaps(xf86CrtcPtr xf86_crtc, RegionPtr new_region, 372504d986fSmrg int scanout_id) 373504d986fSmrg{ 374504d986fSmrg drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private; 375504d986fSmrg DrawablePtr dst = &drmmode_crtc->scanout[scanout_id].pixmap->drawable; 376504d986fSmrg DrawablePtr src = &drmmode_crtc->scanout[scanout_id ^ 1].pixmap->drawable; 377504d986fSmrg RegionPtr last_region = &drmmode_crtc->scanout_last_region; 378504d986fSmrg ScrnInfoPtr scrn = xf86_crtc->scrn; 379504d986fSmrg ScreenPtr pScreen = scrn->pScreen; 380504d986fSmrg RegionRec remaining; 381504d986fSmrg RegionPtr sync_region = NULL; 382504d986fSmrg BoxRec extents; 383504d986fSmrg GCPtr gc; 384504d986fSmrg 385504d986fSmrg if (RegionNil(last_region)) 386504d986fSmrg return; 387504d986fSmrg 388504d986fSmrg RegionNull(&remaining); 389504d986fSmrg RegionSubtract(&remaining, last_region, new_region); 390504d986fSmrg if (RegionNil(&remaining)) 391504d986fSmrg goto uninit; 392504d986fSmrg 393504d986fSmrg extents = *RegionExtents(&remaining); 394504d986fSmrg if (!amdgpu_scanout_extents_intersect(xf86_crtc, &extents)) 395504d986fSmrg goto uninit; 396504d986fSmrg 397504d986fSmrg if (xf86_crtc->driverIsPerformingTransform) { 398504d986fSmrg sync_region = transform_region(&remaining, 399504d986fSmrg &xf86_crtc->f_framebuffer_to_crtc, 400504d986fSmrg dst->width, dst->height); 40124b90cf4Smrg } else { 402504d986fSmrg sync_region = RegionDuplicate(&remaining); 403504d986fSmrg RegionTranslate(sync_region, -xf86_crtc->x, -xf86_crtc->y); 404504d986fSmrg } 405504d986fSmrg 406504d986fSmrg gc = GetScratchGC(dst->depth, pScreen); 407504d986fSmrg if (gc) { 408504d986fSmrg gc->funcs->ChangeClip(gc, CT_REGION, sync_region, 0); 40911bf0794Smrg ValidateGC(dst, gc); 410504d986fSmrg sync_region = NULL; 411504d986fSmrg gc->ops->CopyArea(src, dst, gc, 0, 0, dst->width, dst->height, 0, 0); 412504d986fSmrg FreeScratchGC(gc); 413504d986fSmrg } 414504d986fSmrg 415504d986fSmrg uninit: 416504d986fSmrg if (sync_region) 417504d986fSmrg RegionDestroy(sync_region); 418504d986fSmrg RegionUninit(&remaining); 419504d986fSmrg} 420504d986fSmrg 42124b90cf4Smrgstatic void 42224b90cf4Smrgamdgpu_scanout_flip_abort(xf86CrtcPtr crtc, void *event_data) 42324b90cf4Smrg{ 42424b90cf4Smrg AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(crtc->scrn); 42524b90cf4Smrg drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 42624b90cf4Smrg 42724b90cf4Smrg drmmode_crtc->scanout_update_pending = FALSE; 42824b90cf4Smrg drmmode_fb_reference(pAMDGPUEnt->fd, &drmmode_crtc->flip_pending, 42924b90cf4Smrg NULL); 43024b90cf4Smrg} 43124b90cf4Smrg 43224b90cf4Smrgstatic void 43324b90cf4Smrgamdgpu_scanout_flip_handler(xf86CrtcPtr crtc, uint32_t msc, uint64_t usec, 43424b90cf4Smrg void *event_data) 43524b90cf4Smrg{ 43624b90cf4Smrg AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(crtc->scrn); 43724b90cf4Smrg drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 43824b90cf4Smrg 43924b90cf4Smrg drmmode_fb_reference(pAMDGPUEnt->fd, &drmmode_crtc->fb, 44024b90cf4Smrg drmmode_crtc->flip_pending); 44124b90cf4Smrg amdgpu_scanout_flip_abort(crtc, event_data); 44224b90cf4Smrg 44324b90cf4Smrg#ifdef HAVE_PRESENT_H 44424b90cf4Smrg if (drmmode_crtc->present_vblank_event_id) { 44524b90cf4Smrg present_event_notify(drmmode_crtc->present_vblank_event_id, 44624b90cf4Smrg drmmode_crtc->present_vblank_usec, 44724b90cf4Smrg drmmode_crtc->present_vblank_msc); 44824b90cf4Smrg drmmode_crtc->present_vblank_event_id = 0; 44924b90cf4Smrg } 45024b90cf4Smrg#endif 45124b90cf4Smrg} 45224b90cf4Smrg 453504d986fSmrg 454504d986fSmrgstatic RegionPtr 455504d986fSmrgdirty_region(PixmapDirtyUpdatePtr dirty) 456d6c0b56eSmrg{ 457504d986fSmrg RegionPtr damageregion = DamageRegion(dirty->damage); 458504d986fSmrg RegionPtr dstregion; 459504d986fSmrg 460504d986fSmrg#ifdef HAS_DIRTYTRACKING_ROTATION 461504d986fSmrg if (dirty->rotation != RR_Rotate_0) { 462504d986fSmrg dstregion = transform_region(damageregion, 463504d986fSmrg &dirty->f_inverse, 464504d986fSmrg dirty->slave_dst->drawable.width, 465504d986fSmrg dirty->slave_dst->drawable.height); 466504d986fSmrg } else 467504d986fSmrg#endif 468504d986fSmrg { 469504d986fSmrg RegionRec pixregion; 470504d986fSmrg 471504d986fSmrg dstregion = RegionDuplicate(damageregion); 472504d986fSmrg RegionTranslate(dstregion, -dirty->x, -dirty->y); 473504d986fSmrg PixmapRegionInit(&pixregion, dirty->slave_dst); 474504d986fSmrg RegionIntersect(dstregion, dstregion, &pixregion); 475504d986fSmrg RegionUninit(&pixregion); 476504d986fSmrg } 477504d986fSmrg 478504d986fSmrg return dstregion; 479504d986fSmrg} 480504d986fSmrg 481504d986fSmrgstatic void 482504d986fSmrgredisplay_dirty(PixmapDirtyUpdatePtr dirty, RegionPtr region) 483504d986fSmrg{ 48424b90cf4Smrg ScrnInfoPtr src_scrn = 48524b90cf4Smrg xf86ScreenToScrn(amdgpu_dirty_src_drawable(dirty)->pScreen); 486504d986fSmrg 487504d986fSmrg if (RegionNil(region)) 488504d986fSmrg goto out; 489504d986fSmrg 490504d986fSmrg if (dirty->slave_dst->master_pixmap) 491504d986fSmrg DamageRegionAppend(&dirty->slave_dst->drawable, region); 492d6c0b56eSmrg 493d6c0b56eSmrg#ifdef HAS_DIRTYTRACKING_ROTATION 494d6c0b56eSmrg PixmapSyncDirtyHelper(dirty); 495d6c0b56eSmrg#else 496504d986fSmrg PixmapSyncDirtyHelper(dirty, region); 497d6c0b56eSmrg#endif 498d6c0b56eSmrg 49924b90cf4Smrg amdgpu_glamor_flush(src_scrn); 500504d986fSmrg if (dirty->slave_dst->master_pixmap) 501504d986fSmrg DamageRegionProcessPending(&dirty->slave_dst->drawable); 502504d986fSmrg 503504d986fSmrgout: 504504d986fSmrg DamageEmpty(dirty->damage); 505d6c0b56eSmrg} 506d6c0b56eSmrg 507504d986fSmrgstatic void 508504d986fSmrgamdgpu_prime_scanout_update_abort(xf86CrtcPtr crtc, void *event_data) 509d6c0b56eSmrg{ 510504d986fSmrg drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 511504d986fSmrg 512504d986fSmrg drmmode_crtc->scanout_update_pending = FALSE; 513504d986fSmrg} 514504d986fSmrg 515504d986fSmrgvoid 516504d986fSmrgamdgpu_sync_shared_pixmap(PixmapDirtyUpdatePtr dirty) 517504d986fSmrg{ 51824b90cf4Smrg ScreenPtr master_screen = amdgpu_dirty_master(dirty); 519d6c0b56eSmrg PixmapDirtyUpdatePtr ent; 520504d986fSmrg RegionPtr region; 521d6c0b56eSmrg 522504d986fSmrg xorg_list_for_each_entry(ent, &master_screen->pixmap_dirty_list, ent) { 52324b90cf4Smrg if (!amdgpu_dirty_src_equals(dirty, ent->slave_dst)) 524504d986fSmrg continue; 525d6c0b56eSmrg 526504d986fSmrg region = dirty_region(ent); 527504d986fSmrg redisplay_dirty(ent, region); 528504d986fSmrg RegionDestroy(region); 529d6c0b56eSmrg } 530d6c0b56eSmrg} 531504d986fSmrg 532504d986fSmrg 533504d986fSmrg#if HAS_SYNC_SHARED_PIXMAP 534d6c0b56eSmrg 535d6c0b56eSmrgstatic Bool 536504d986fSmrgmaster_has_sync_shared_pixmap(ScrnInfoPtr scrn, PixmapDirtyUpdatePtr dirty) 537d6c0b56eSmrg{ 53824b90cf4Smrg ScreenPtr master_screen = amdgpu_dirty_master(dirty); 539504d986fSmrg 540504d986fSmrg return master_screen->SyncSharedPixmap != NULL; 541504d986fSmrg} 542504d986fSmrg 543504d986fSmrgstatic Bool 544504d986fSmrgslave_has_sync_shared_pixmap(ScrnInfoPtr scrn, PixmapDirtyUpdatePtr dirty) 545504d986fSmrg{ 546504d986fSmrg ScreenPtr slave_screen = dirty->slave_dst->drawable.pScreen; 547504d986fSmrg 548504d986fSmrg return slave_screen->SyncSharedPixmap != NULL; 549504d986fSmrg} 550504d986fSmrg 551504d986fSmrgstatic void 552504d986fSmrgcall_sync_shared_pixmap(PixmapDirtyUpdatePtr dirty) 553504d986fSmrg{ 55424b90cf4Smrg ScreenPtr master_screen = amdgpu_dirty_master(dirty); 555504d986fSmrg 556504d986fSmrg master_screen->SyncSharedPixmap(dirty); 557504d986fSmrg} 558504d986fSmrg 559504d986fSmrg#else /* !HAS_SYNC_SHARED_PIXMAP */ 560504d986fSmrg 561504d986fSmrgstatic Bool 562504d986fSmrgmaster_has_sync_shared_pixmap(ScrnInfoPtr scrn, PixmapDirtyUpdatePtr dirty) 563504d986fSmrg{ 56424b90cf4Smrg ScrnInfoPtr master_scrn = xf86ScreenToScrn(amdgpu_dirty_master(dirty)); 565504d986fSmrg 566504d986fSmrg return master_scrn->driverName == scrn->driverName; 567504d986fSmrg} 568504d986fSmrg 569504d986fSmrgstatic Bool 570504d986fSmrgslave_has_sync_shared_pixmap(ScrnInfoPtr scrn, PixmapDirtyUpdatePtr dirty) 571504d986fSmrg{ 572504d986fSmrg ScrnInfoPtr slave_scrn = xf86ScreenToScrn(dirty->slave_dst->drawable.pScreen); 573504d986fSmrg 574504d986fSmrg return slave_scrn->driverName == scrn->driverName; 575504d986fSmrg} 576504d986fSmrg 577504d986fSmrgstatic void 578504d986fSmrgcall_sync_shared_pixmap(PixmapDirtyUpdatePtr dirty) 579504d986fSmrg{ 580504d986fSmrg amdgpu_sync_shared_pixmap(dirty); 581504d986fSmrg} 582504d986fSmrg 583504d986fSmrg#endif /* HAS_SYNC_SHARED_PIXMAPS */ 584504d986fSmrg 585504d986fSmrg 58611bf0794Smrgstatic xf86CrtcPtr 58711bf0794Smrgamdgpu_prime_dirty_to_crtc(PixmapDirtyUpdatePtr dirty) 58811bf0794Smrg{ 58911bf0794Smrg ScreenPtr screen = dirty->slave_dst->drawable.pScreen; 59011bf0794Smrg ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 59111bf0794Smrg xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); 59211bf0794Smrg int c; 59311bf0794Smrg 59411bf0794Smrg /* Find the CRTC which is scanning out from this slave pixmap */ 59511bf0794Smrg for (c = 0; c < xf86_config->num_crtc; c++) { 59611bf0794Smrg xf86CrtcPtr xf86_crtc = xf86_config->crtc[c]; 59711bf0794Smrg drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private; 59811bf0794Smrg 59924b90cf4Smrg if (amdgpu_dirty_src_equals(dirty, drmmode_crtc->prime_scanout_pixmap)) 60011bf0794Smrg return xf86_crtc; 60111bf0794Smrg } 60211bf0794Smrg 60311bf0794Smrg return NULL; 60411bf0794Smrg} 60511bf0794Smrg 606504d986fSmrgstatic Bool 607504d986fSmrgamdgpu_prime_scanout_do_update(xf86CrtcPtr crtc, unsigned scanout_id) 608504d986fSmrg{ 609504d986fSmrg ScrnInfoPtr scrn = crtc->scrn; 610504d986fSmrg ScreenPtr screen = scrn->pScreen; 611504d986fSmrg drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 612504d986fSmrg PixmapDirtyUpdatePtr dirty; 613504d986fSmrg Bool ret = FALSE; 614504d986fSmrg 615504d986fSmrg xorg_list_for_each_entry(dirty, &screen->pixmap_dirty_list, ent) { 61624b90cf4Smrg if (amdgpu_dirty_src_equals(dirty, drmmode_crtc->prime_scanout_pixmap)) { 617504d986fSmrg RegionPtr region; 618504d986fSmrg 619504d986fSmrg if (master_has_sync_shared_pixmap(scrn, dirty)) 620504d986fSmrg call_sync_shared_pixmap(dirty); 621504d986fSmrg 622504d986fSmrg region = dirty_region(dirty); 623504d986fSmrg if (RegionNil(region)) 624504d986fSmrg goto destroy; 625504d986fSmrg 62611bf0794Smrg if (drmmode_crtc->tear_free) { 627504d986fSmrg RegionTranslate(region, crtc->x, crtc->y); 628504d986fSmrg amdgpu_sync_scanout_pixmaps(crtc, region, scanout_id); 629504d986fSmrg amdgpu_glamor_flush(scrn); 630504d986fSmrg RegionCopy(&drmmode_crtc->scanout_last_region, region); 631504d986fSmrg RegionTranslate(region, -crtc->x, -crtc->y); 632504d986fSmrg dirty->slave_dst = drmmode_crtc->scanout[scanout_id].pixmap; 633504d986fSmrg } 634504d986fSmrg 635504d986fSmrg redisplay_dirty(dirty, region); 636504d986fSmrg ret = TRUE; 637504d986fSmrg destroy: 638504d986fSmrg RegionDestroy(region); 639504d986fSmrg break; 640504d986fSmrg } 641d6c0b56eSmrg } 642d6c0b56eSmrg 643504d986fSmrg return ret; 644504d986fSmrg} 645504d986fSmrg 64611bf0794Smrgstatic void 647504d986fSmrgamdgpu_prime_scanout_update_handler(xf86CrtcPtr crtc, uint32_t frame, uint64_t usec, 648504d986fSmrg void *event_data) 649504d986fSmrg{ 650504d986fSmrg drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 651504d986fSmrg 652504d986fSmrg amdgpu_prime_scanout_do_update(crtc, 0); 653504d986fSmrg drmmode_crtc->scanout_update_pending = FALSE; 654504d986fSmrg} 655504d986fSmrg 656504d986fSmrgstatic void 657504d986fSmrgamdgpu_prime_scanout_update(PixmapDirtyUpdatePtr dirty) 658504d986fSmrg{ 659504d986fSmrg ScreenPtr screen = dirty->slave_dst->drawable.pScreen; 660504d986fSmrg ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 66111bf0794Smrg xf86CrtcPtr xf86_crtc = amdgpu_prime_dirty_to_crtc(dirty); 66211bf0794Smrg drmmode_crtc_private_ptr drmmode_crtc; 663504d986fSmrg uintptr_t drm_queue_seq; 664504d986fSmrg 66511bf0794Smrg if (!xf86_crtc || !xf86_crtc->enabled) 66611bf0794Smrg return; 667504d986fSmrg 66811bf0794Smrg drmmode_crtc = xf86_crtc->driver_private; 66911bf0794Smrg if (drmmode_crtc->scanout_update_pending || 67024b90cf4Smrg !drmmode_crtc->scanout[drmmode_crtc->scanout_id].pixmap || 67124b90cf4Smrg drmmode_crtc->dpms_mode != DPMSModeOn) 672504d986fSmrg return; 673504d986fSmrg 674504d986fSmrg drm_queue_seq = amdgpu_drm_queue_alloc(xf86_crtc, 675504d986fSmrg AMDGPU_DRM_QUEUE_CLIENT_DEFAULT, 676504d986fSmrg AMDGPU_DRM_QUEUE_ID_DEFAULT, NULL, 677504d986fSmrg amdgpu_prime_scanout_update_handler, 678504d986fSmrg amdgpu_prime_scanout_update_abort); 679504d986fSmrg if (drm_queue_seq == AMDGPU_DRM_QUEUE_ERROR) { 680504d986fSmrg xf86DrvMsg(scrn->scrnIndex, X_WARNING, 681504d986fSmrg "amdgpu_drm_queue_alloc failed for PRIME update\n"); 682504d986fSmrg return; 683504d986fSmrg } 684504d986fSmrg 68524b90cf4Smrg if (!drmmode_wait_vblank(xf86_crtc, DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT, 68624b90cf4Smrg 1, drm_queue_seq, NULL, NULL)) { 687504d986fSmrg xf86DrvMsg(scrn->scrnIndex, X_WARNING, 68824b90cf4Smrg "drmmode_wait_vblank failed for PRIME update: %s\n", 689504d986fSmrg strerror(errno)); 690504d986fSmrg amdgpu_drm_abort_entry(drm_queue_seq); 691504d986fSmrg return; 692504d986fSmrg } 693504d986fSmrg 694504d986fSmrg drmmode_crtc->scanout_update_pending = TRUE; 695504d986fSmrg} 696504d986fSmrg 697504d986fSmrgstatic void 698504d986fSmrgamdgpu_prime_scanout_flip(PixmapDirtyUpdatePtr ent) 699504d986fSmrg{ 700504d986fSmrg ScreenPtr screen = ent->slave_dst->drawable.pScreen; 701504d986fSmrg ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 702504d986fSmrg AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(scrn); 70311bf0794Smrg xf86CrtcPtr crtc = amdgpu_prime_dirty_to_crtc(ent); 70411bf0794Smrg drmmode_crtc_private_ptr drmmode_crtc; 705504d986fSmrg uintptr_t drm_queue_seq; 706504d986fSmrg unsigned scanout_id; 707504d986fSmrg 70811bf0794Smrg if (!crtc || !crtc->enabled) 70911bf0794Smrg return; 710504d986fSmrg 71111bf0794Smrg drmmode_crtc = crtc->driver_private; 71211bf0794Smrg if (drmmode_crtc->scanout_update_pending || 713504d986fSmrg !drmmode_crtc->scanout[drmmode_crtc->scanout_id].pixmap || 71424b90cf4Smrg drmmode_crtc->dpms_mode != DPMSModeOn) 715504d986fSmrg return; 716504d986fSmrg 717504d986fSmrg scanout_id = drmmode_crtc->scanout_id ^ 1; 718504d986fSmrg if (!amdgpu_prime_scanout_do_update(crtc, scanout_id)) 719504d986fSmrg return; 720504d986fSmrg 721504d986fSmrg drm_queue_seq = amdgpu_drm_queue_alloc(crtc, 722504d986fSmrg AMDGPU_DRM_QUEUE_CLIENT_DEFAULT, 723504d986fSmrg AMDGPU_DRM_QUEUE_ID_DEFAULT, 72424b90cf4Smrg NULL, 72524b90cf4Smrg amdgpu_scanout_flip_handler, 72624b90cf4Smrg amdgpu_scanout_flip_abort); 727504d986fSmrg if (drm_queue_seq == AMDGPU_DRM_QUEUE_ERROR) { 728504d986fSmrg xf86DrvMsg(scrn->scrnIndex, X_WARNING, 729504d986fSmrg "Allocating DRM event queue entry failed for PRIME flip.\n"); 730504d986fSmrg return; 731504d986fSmrg } 732504d986fSmrg 73324b90cf4Smrg drmmode_fb_reference(pAMDGPUEnt->fd, &drmmode_crtc->flip_pending, 73424b90cf4Smrg amdgpu_pixmap_get_fb(drmmode_crtc->scanout[scanout_id].pixmap)); 73524b90cf4Smrg if (!drmmode_crtc->flip_pending) { 73624b90cf4Smrg xf86DrvMsg(scrn->scrnIndex, X_WARNING, 73724b90cf4Smrg "Failed to get FB for PRIME flip.\n"); 73824b90cf4Smrg amdgpu_drm_abort_entry(drm_queue_seq); 73924b90cf4Smrg return; 74024b90cf4Smrg } 74124b90cf4Smrg 74211bf0794Smrg if (drmmode_page_flip_target_relative(pAMDGPUEnt, drmmode_crtc, 74324b90cf4Smrg drmmode_crtc->flip_pending->handle, 74411bf0794Smrg 0, drm_queue_seq, 0) != 0) { 745504d986fSmrg xf86DrvMsg(scrn->scrnIndex, X_WARNING, "flip queue failed in %s: %s\n", 746504d986fSmrg __func__, strerror(errno)); 74711bf0794Smrg amdgpu_drm_abort_entry(drm_queue_seq); 748504d986fSmrg return; 749504d986fSmrg } 750504d986fSmrg 751504d986fSmrg drmmode_crtc->scanout_id = scanout_id; 752504d986fSmrg drmmode_crtc->scanout_update_pending = TRUE; 753504d986fSmrg} 754504d986fSmrg 755504d986fSmrgstatic void 756504d986fSmrgamdgpu_dirty_update(ScrnInfoPtr scrn) 757504d986fSmrg{ 758504d986fSmrg ScreenPtr screen = scrn->pScreen; 759504d986fSmrg PixmapDirtyUpdatePtr ent; 760504d986fSmrg RegionPtr region; 761504d986fSmrg 762504d986fSmrg xorg_list_for_each_entry(ent, &screen->pixmap_dirty_list, ent) { 763504d986fSmrg if (screen->isGPU) { 764504d986fSmrg PixmapDirtyUpdatePtr region_ent = ent; 765504d986fSmrg 766504d986fSmrg if (master_has_sync_shared_pixmap(scrn, ent)) { 76724b90cf4Smrg ScreenPtr master_screen = amdgpu_dirty_master(ent); 768504d986fSmrg 769504d986fSmrg xorg_list_for_each_entry(region_ent, &master_screen->pixmap_dirty_list, ent) { 77024b90cf4Smrg if (amdgpu_dirty_src_equals(ent, region_ent->slave_dst)) 771504d986fSmrg break; 772504d986fSmrg } 773504d986fSmrg } 774504d986fSmrg 775504d986fSmrg region = dirty_region(region_ent); 776504d986fSmrg 777504d986fSmrg if (RegionNotEmpty(region)) { 77811bf0794Smrg xf86CrtcPtr crtc = amdgpu_prime_dirty_to_crtc(ent); 77911bf0794Smrg drmmode_crtc_private_ptr drmmode_crtc = NULL; 78011bf0794Smrg 78111bf0794Smrg if (crtc) 78211bf0794Smrg drmmode_crtc = crtc->driver_private; 78311bf0794Smrg 78411bf0794Smrg if (drmmode_crtc && drmmode_crtc->tear_free) 785504d986fSmrg amdgpu_prime_scanout_flip(ent); 786504d986fSmrg else 787504d986fSmrg amdgpu_prime_scanout_update(ent); 788504d986fSmrg } else { 789504d986fSmrg DamageEmpty(region_ent->damage); 790504d986fSmrg } 791504d986fSmrg 792504d986fSmrg RegionDestroy(region); 793504d986fSmrg } else { 794504d986fSmrg if (slave_has_sync_shared_pixmap(scrn, ent)) 795504d986fSmrg continue; 796504d986fSmrg 797504d986fSmrg region = dirty_region(ent); 798504d986fSmrg redisplay_dirty(ent, region); 799504d986fSmrg RegionDestroy(region); 800504d986fSmrg } 801504d986fSmrg } 802504d986fSmrg} 80324b90cf4Smrg 804504d986fSmrg 80511bf0794SmrgBool 80624b90cf4Smrgamdgpu_scanout_do_update(xf86CrtcPtr xf86_crtc, int scanout_id, 80724b90cf4Smrg PixmapPtr src_pix, BoxPtr extents) 808d6c0b56eSmrg{ 809d6c0b56eSmrg drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private; 81024b90cf4Smrg RegionRec region = { .extents = *extents, .data = NULL }; 811504d986fSmrg ScrnInfoPtr scrn = xf86_crtc->scrn; 812504d986fSmrg ScreenPtr pScreen = scrn->pScreen; 813d6c0b56eSmrg DrawablePtr pDraw; 814d6c0b56eSmrg 815d6c0b56eSmrg if (!xf86_crtc->enabled || 81624b90cf4Smrg !drmmode_crtc->scanout[scanout_id].pixmap || 81724b90cf4Smrg extents->x1 >= extents->x2 || extents->y1 >= extents->y2) 818d6c0b56eSmrg return FALSE; 819d6c0b56eSmrg 820d6c0b56eSmrg pDraw = &drmmode_crtc->scanout[scanout_id].pixmap->drawable; 82124b90cf4Smrg if (!amdgpu_scanout_extents_intersect(xf86_crtc, extents)) 822d6c0b56eSmrg return FALSE; 823d6c0b56eSmrg 82411bf0794Smrg if (drmmode_crtc->tear_free) { 82524b90cf4Smrg amdgpu_sync_scanout_pixmaps(xf86_crtc, ®ion, scanout_id); 82624b90cf4Smrg RegionCopy(&drmmode_crtc->scanout_last_region, ®ion); 827504d986fSmrg } 828504d986fSmrg 829d6c0b56eSmrg if (xf86_crtc->driverIsPerformingTransform) { 830d6c0b56eSmrg SourceValidateProcPtr SourceValidate = pScreen->SourceValidate; 831d6c0b56eSmrg PictFormatPtr format = PictureWindowFormat(pScreen->root); 832d6c0b56eSmrg int error; 833d6c0b56eSmrg PicturePtr src, dst; 834d6c0b56eSmrg 83524b90cf4Smrg src = CreatePicture(None, &src_pix->drawable, format, 0L, NULL, 83624b90cf4Smrg serverClient, &error); 837d6c0b56eSmrg if (!src) { 838d6c0b56eSmrg ErrorF("Failed to create source picture for transformed scanout " 839d6c0b56eSmrg "update\n"); 840d6c0b56eSmrg goto out; 841d6c0b56eSmrg } 842d6c0b56eSmrg 843d6c0b56eSmrg dst = CreatePicture(None, pDraw, format, 0L, NULL, serverClient, &error); 844d6c0b56eSmrg if (!dst) { 845d6c0b56eSmrg ErrorF("Failed to create destination picture for transformed scanout " 846d6c0b56eSmrg "update\n"); 847d6c0b56eSmrg goto free_src; 848d6c0b56eSmrg } 849d6c0b56eSmrg error = SetPictureTransform(src, &xf86_crtc->crtc_to_framebuffer); 850d6c0b56eSmrg if (error) { 851d6c0b56eSmrg ErrorF("SetPictureTransform failed for transformed scanout " 852d6c0b56eSmrg "update\n"); 853d6c0b56eSmrg goto free_dst; 854d6c0b56eSmrg } 855d6c0b56eSmrg 856d6c0b56eSmrg if (xf86_crtc->filter) 857d6c0b56eSmrg SetPicturePictFilter(src, xf86_crtc->filter, xf86_crtc->params, 858d6c0b56eSmrg xf86_crtc->nparams); 859d6c0b56eSmrg 860d6c0b56eSmrg pScreen->SourceValidate = NULL; 861d6c0b56eSmrg CompositePicture(PictOpSrc, 862d6c0b56eSmrg src, NULL, dst, 86324b90cf4Smrg extents->x1, extents->y1, 0, 0, extents->x1, 86424b90cf4Smrg extents->y1, extents->x2 - extents->x1, 86524b90cf4Smrg extents->y2 - extents->y1); 866d6c0b56eSmrg pScreen->SourceValidate = SourceValidate; 867d6c0b56eSmrg 868d6c0b56eSmrg free_dst: 869d6c0b56eSmrg FreePicture(dst, None); 870d6c0b56eSmrg free_src: 871d6c0b56eSmrg FreePicture(src, None); 872d6c0b56eSmrg } else 873d6c0b56eSmrg out: 874d6c0b56eSmrg { 875d6c0b56eSmrg GCPtr gc = GetScratchGC(pDraw->depth, pScreen); 876d6c0b56eSmrg 877d6c0b56eSmrg ValidateGC(pDraw, gc); 87824b90cf4Smrg (*gc->ops->CopyArea)(&src_pix->drawable, pDraw, gc, 87924b90cf4Smrg xf86_crtc->x + extents->x1, xf86_crtc->y + extents->y1, 88024b90cf4Smrg extents->x2 - extents->x1, extents->y2 - extents->y1, 88124b90cf4Smrg extents->x1, extents->y1); 882d6c0b56eSmrg FreeScratchGC(gc); 883d6c0b56eSmrg } 884d6c0b56eSmrg 885d6c0b56eSmrg amdgpu_glamor_flush(xf86_crtc->scrn); 886d6c0b56eSmrg 887d6c0b56eSmrg return TRUE; 888d6c0b56eSmrg} 889d6c0b56eSmrg 890d6c0b56eSmrgstatic void 891d6c0b56eSmrgamdgpu_scanout_update_abort(xf86CrtcPtr crtc, void *event_data) 892d6c0b56eSmrg{ 893d6c0b56eSmrg drmmode_crtc_private_ptr drmmode_crtc = event_data; 894d6c0b56eSmrg 895d6c0b56eSmrg drmmode_crtc->scanout_update_pending = FALSE; 896d6c0b56eSmrg} 897d6c0b56eSmrg 89811bf0794Smrgstatic void 899d6c0b56eSmrgamdgpu_scanout_update_handler(xf86CrtcPtr crtc, uint32_t frame, uint64_t usec, 900d6c0b56eSmrg void *event_data) 901d6c0b56eSmrg{ 90224b90cf4Smrg drmmode_crtc_private_ptr drmmode_crtc = event_data; 90324b90cf4Smrg ScreenPtr screen = crtc->scrn->pScreen; 90424b90cf4Smrg RegionPtr region = DamageRegion(drmmode_crtc->scanout_damage); 90524b90cf4Smrg 90624b90cf4Smrg if (crtc->enabled && 90724b90cf4Smrg !drmmode_crtc->flip_pending && 90824b90cf4Smrg drmmode_crtc->dpms_mode == DPMSModeOn) { 90924b90cf4Smrg if (amdgpu_scanout_do_update(crtc, drmmode_crtc->scanout_id, 91024b90cf4Smrg screen->GetWindowPixmap(screen->root), 91124b90cf4Smrg ®ion->extents)) 91224b90cf4Smrg RegionEmpty(region); 91324b90cf4Smrg } 914d6c0b56eSmrg 915d6c0b56eSmrg amdgpu_scanout_update_abort(crtc, event_data); 916d6c0b56eSmrg} 917d6c0b56eSmrg 918d6c0b56eSmrgstatic void 919d6c0b56eSmrgamdgpu_scanout_update(xf86CrtcPtr xf86_crtc) 920d6c0b56eSmrg{ 921d6c0b56eSmrg drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private; 922d6c0b56eSmrg uintptr_t drm_queue_seq; 923d6c0b56eSmrg ScrnInfoPtr scrn; 924d6c0b56eSmrg DamagePtr pDamage; 925d6c0b56eSmrg RegionPtr pRegion; 926d6c0b56eSmrg BoxRec extents; 927d6c0b56eSmrg 928d6c0b56eSmrg if (!xf86_crtc->enabled || 929d6c0b56eSmrg drmmode_crtc->scanout_update_pending || 93024b90cf4Smrg drmmode_crtc->flip_pending || 93124b90cf4Smrg drmmode_crtc->dpms_mode != DPMSModeOn) 932d6c0b56eSmrg return; 933d6c0b56eSmrg 934504d986fSmrg pDamage = drmmode_crtc->scanout_damage; 935d6c0b56eSmrg if (!pDamage) 936d6c0b56eSmrg return; 937d6c0b56eSmrg 938d6c0b56eSmrg pRegion = DamageRegion(pDamage); 939d6c0b56eSmrg if (!RegionNotEmpty(pRegion)) 940d6c0b56eSmrg return; 941d6c0b56eSmrg 942d6c0b56eSmrg extents = *RegionExtents(pRegion); 943504d986fSmrg if (!amdgpu_scanout_extents_intersect(xf86_crtc, &extents)) { 944504d986fSmrg RegionEmpty(pRegion); 945d6c0b56eSmrg return; 946504d986fSmrg } 947d6c0b56eSmrg 948d6c0b56eSmrg scrn = xf86_crtc->scrn; 949d6c0b56eSmrg drm_queue_seq = amdgpu_drm_queue_alloc(xf86_crtc, 950d6c0b56eSmrg AMDGPU_DRM_QUEUE_CLIENT_DEFAULT, 951d6c0b56eSmrg AMDGPU_DRM_QUEUE_ID_DEFAULT, 952d6c0b56eSmrg drmmode_crtc, 953d6c0b56eSmrg amdgpu_scanout_update_handler, 954d6c0b56eSmrg amdgpu_scanout_update_abort); 955504d986fSmrg if (drm_queue_seq == AMDGPU_DRM_QUEUE_ERROR) { 956d6c0b56eSmrg xf86DrvMsg(scrn->scrnIndex, X_WARNING, 957d6c0b56eSmrg "amdgpu_drm_queue_alloc failed for scanout update\n"); 958d6c0b56eSmrg return; 959d6c0b56eSmrg } 960d6c0b56eSmrg 96124b90cf4Smrg if (!drmmode_wait_vblank(xf86_crtc, DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT, 96224b90cf4Smrg 1, drm_queue_seq, NULL, NULL)) { 963d6c0b56eSmrg xf86DrvMsg(scrn->scrnIndex, X_WARNING, 96424b90cf4Smrg "drmmode_wait_vblank failed for scanout update: %s\n", 965d6c0b56eSmrg strerror(errno)); 966d6c0b56eSmrg amdgpu_drm_abort_entry(drm_queue_seq); 967d6c0b56eSmrg return; 968d6c0b56eSmrg } 969d6c0b56eSmrg 970d6c0b56eSmrg drmmode_crtc->scanout_update_pending = TRUE; 971d6c0b56eSmrg} 972d6c0b56eSmrg 973d6c0b56eSmrgstatic void 974d6c0b56eSmrgamdgpu_scanout_flip(ScreenPtr pScreen, AMDGPUInfoPtr info, 975d6c0b56eSmrg xf86CrtcPtr xf86_crtc) 976d6c0b56eSmrg{ 977d6c0b56eSmrg drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private; 97824b90cf4Smrg RegionPtr region = DamageRegion(drmmode_crtc->scanout_damage); 97911bf0794Smrg ScrnInfoPtr scrn = xf86_crtc->scrn; 98011bf0794Smrg AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(scrn); 981d6c0b56eSmrg uintptr_t drm_queue_seq; 982d6c0b56eSmrg unsigned scanout_id; 983d6c0b56eSmrg 98411bf0794Smrg if (drmmode_crtc->scanout_update_pending || 98524b90cf4Smrg drmmode_crtc->flip_pending || 98624b90cf4Smrg drmmode_crtc->dpms_mode != DPMSModeOn) 987d6c0b56eSmrg return; 988d6c0b56eSmrg 989d6c0b56eSmrg scanout_id = drmmode_crtc->scanout_id ^ 1; 99024b90cf4Smrg if (!amdgpu_scanout_do_update(xf86_crtc, scanout_id, 99124b90cf4Smrg pScreen->GetWindowPixmap(pScreen->root), 99224b90cf4Smrg ®ion->extents)) 993d6c0b56eSmrg return; 99424b90cf4Smrg RegionEmpty(region); 995d6c0b56eSmrg 996d6c0b56eSmrg drm_queue_seq = amdgpu_drm_queue_alloc(xf86_crtc, 997d6c0b56eSmrg AMDGPU_DRM_QUEUE_CLIENT_DEFAULT, 998d6c0b56eSmrg AMDGPU_DRM_QUEUE_ID_DEFAULT, 99924b90cf4Smrg NULL, 100024b90cf4Smrg amdgpu_scanout_flip_handler, 1001d6c0b56eSmrg amdgpu_scanout_flip_abort); 1002504d986fSmrg if (drm_queue_seq == AMDGPU_DRM_QUEUE_ERROR) { 1003d6c0b56eSmrg xf86DrvMsg(scrn->scrnIndex, X_WARNING, 1004d6c0b56eSmrg "Allocating DRM event queue entry failed.\n"); 1005d6c0b56eSmrg return; 1006d6c0b56eSmrg } 1007d6c0b56eSmrg 100824b90cf4Smrg drmmode_fb_reference(pAMDGPUEnt->fd, &drmmode_crtc->flip_pending, 100924b90cf4Smrg amdgpu_pixmap_get_fb(drmmode_crtc->scanout[scanout_id].pixmap)); 101024b90cf4Smrg if (!drmmode_crtc->flip_pending) { 101124b90cf4Smrg xf86DrvMsg(scrn->scrnIndex, X_WARNING, 101224b90cf4Smrg "Failed to get FB for scanout flip.\n"); 101324b90cf4Smrg amdgpu_drm_abort_entry(drm_queue_seq); 101424b90cf4Smrg return; 101524b90cf4Smrg } 101624b90cf4Smrg 101711bf0794Smrg if (drmmode_page_flip_target_relative(pAMDGPUEnt, drmmode_crtc, 101824b90cf4Smrg drmmode_crtc->flip_pending->handle, 101911bf0794Smrg 0, drm_queue_seq, 0) != 0) { 102024b90cf4Smrg xf86DrvMsg(scrn->scrnIndex, X_WARNING, "flip queue failed in %s: %s, " 102124b90cf4Smrg "TearFree inactive until next modeset\n", 1022d6c0b56eSmrg __func__, strerror(errno)); 102311bf0794Smrg amdgpu_drm_abort_entry(drm_queue_seq); 102424b90cf4Smrg RegionCopy(DamageRegion(drmmode_crtc->scanout_damage), 102524b90cf4Smrg &drmmode_crtc->scanout_last_region); 102624b90cf4Smrg RegionEmpty(&drmmode_crtc->scanout_last_region); 102724b90cf4Smrg amdgpu_scanout_update(xf86_crtc); 102824b90cf4Smrg drmmode_crtc_scanout_destroy(drmmode_crtc->drmmode, 102924b90cf4Smrg &drmmode_crtc->scanout[scanout_id]); 103024b90cf4Smrg drmmode_crtc->tear_free = FALSE; 1031d6c0b56eSmrg return; 1032d6c0b56eSmrg } 1033d6c0b56eSmrg 1034d6c0b56eSmrg drmmode_crtc->scanout_id = scanout_id; 1035d6c0b56eSmrg drmmode_crtc->scanout_update_pending = TRUE; 1036d6c0b56eSmrg} 1037d6c0b56eSmrg 1038d6c0b56eSmrgstatic void AMDGPUBlockHandler_KMS(BLOCKHANDLER_ARGS_DECL) 1039d6c0b56eSmrg{ 1040d6c0b56eSmrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 1041d6c0b56eSmrg AMDGPUInfoPtr info = AMDGPUPTR(pScrn); 1042d6c0b56eSmrg xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); 1043d6c0b56eSmrg int c; 1044d6c0b56eSmrg 1045d6c0b56eSmrg pScreen->BlockHandler = info->BlockHandler; 1046d6c0b56eSmrg (*pScreen->BlockHandler) (BLOCKHANDLER_ARGS); 1047d6c0b56eSmrg pScreen->BlockHandler = AMDGPUBlockHandler_KMS; 1048d6c0b56eSmrg 104924b90cf4Smrg if (!xf86ScreenToScrn(amdgpu_master_screen(pScreen))->vtSema) 105024b90cf4Smrg return; 105124b90cf4Smrg 105224b90cf4Smrg if (!pScreen->isGPU) 1053504d986fSmrg { 1054504d986fSmrg for (c = 0; c < xf86_config->num_crtc; c++) { 105511bf0794Smrg xf86CrtcPtr crtc = xf86_config->crtc[c]; 105611bf0794Smrg drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 105711bf0794Smrg 105811bf0794Smrg if (drmmode_crtc->tear_free) 105911bf0794Smrg amdgpu_scanout_flip(pScreen, info, crtc); 106024b90cf4Smrg else if (drmmode_crtc->scanout[drmmode_crtc->scanout_id].pixmap) 106111bf0794Smrg amdgpu_scanout_update(crtc); 1062504d986fSmrg } 1063d6c0b56eSmrg } 1064d6c0b56eSmrg 106511bf0794Smrg#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1,19,0,0,0) 1066d6c0b56eSmrg if (info->use_glamor) 1067d6c0b56eSmrg amdgpu_glamor_flush(pScrn); 106811bf0794Smrg#endif 1069d6c0b56eSmrg 1070504d986fSmrg amdgpu_dirty_update(pScrn); 1071d6c0b56eSmrg} 1072d6c0b56eSmrg 1073d6c0b56eSmrg/* This is called by AMDGPUPreInit to set up the default visual */ 1074d6c0b56eSmrgstatic Bool AMDGPUPreInitVisual(ScrnInfoPtr pScrn) 1075d6c0b56eSmrg{ 1076d6c0b56eSmrg AMDGPUInfoPtr info = AMDGPUPTR(pScrn); 1077d6c0b56eSmrg 1078d6c0b56eSmrg if (!xf86SetDepthBpp(pScrn, 0, 0, 0, Support32bppFb)) 1079d6c0b56eSmrg return FALSE; 1080d6c0b56eSmrg 1081d6c0b56eSmrg switch (pScrn->depth) { 1082d6c0b56eSmrg case 8: 1083d6c0b56eSmrg case 15: 1084d6c0b56eSmrg case 16: 1085d6c0b56eSmrg case 24: 108624b90cf4Smrg case 30: 1087d6c0b56eSmrg break; 1088d6c0b56eSmrg 1089d6c0b56eSmrg default: 1090d6c0b56eSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1091d6c0b56eSmrg "Given depth (%d) is not supported by %s driver\n", 1092d6c0b56eSmrg pScrn->depth, AMDGPU_DRIVER_NAME); 1093d6c0b56eSmrg return FALSE; 1094d6c0b56eSmrg } 1095d6c0b56eSmrg 1096d6c0b56eSmrg xf86PrintDepthBpp(pScrn); 1097d6c0b56eSmrg 1098d6c0b56eSmrg info->pix24bpp = xf86GetBppFromDepth(pScrn, pScrn->depth); 1099d6c0b56eSmrg info->pixel_bytes = pScrn->bitsPerPixel / 8; 1100d6c0b56eSmrg 1101d6c0b56eSmrg if (info->pix24bpp == 24) { 1102d6c0b56eSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1103d6c0b56eSmrg "Amdgpu does NOT support 24bpp\n"); 1104d6c0b56eSmrg return FALSE; 1105d6c0b56eSmrg } 1106d6c0b56eSmrg 1107d6c0b56eSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1108d6c0b56eSmrg "Pixel depth = %d bits stored in %d byte%s (%d bpp pixmaps)\n", 1109d6c0b56eSmrg pScrn->depth, 1110d6c0b56eSmrg info->pixel_bytes, 1111d6c0b56eSmrg info->pixel_bytes > 1 ? "s" : "", info->pix24bpp); 1112d6c0b56eSmrg 1113d6c0b56eSmrg if (!xf86SetDefaultVisual(pScrn, -1)) 1114d6c0b56eSmrg return FALSE; 1115d6c0b56eSmrg 1116d6c0b56eSmrg if (pScrn->depth > 8 && pScrn->defaultVisual != TrueColor) { 1117d6c0b56eSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1118d6c0b56eSmrg "Default visual (%s) is not supported at depth %d\n", 1119d6c0b56eSmrg xf86GetVisualName(pScrn->defaultVisual), 1120d6c0b56eSmrg pScrn->depth); 1121d6c0b56eSmrg return FALSE; 1122d6c0b56eSmrg } 1123d6c0b56eSmrg return TRUE; 1124d6c0b56eSmrg} 1125d6c0b56eSmrg 1126d6c0b56eSmrg/* This is called by AMDGPUPreInit to handle all color weight issues */ 1127d6c0b56eSmrgstatic Bool AMDGPUPreInitWeight(ScrnInfoPtr pScrn) 1128d6c0b56eSmrg{ 1129d6c0b56eSmrg AMDGPUInfoPtr info = AMDGPUPTR(pScrn); 1130d6c0b56eSmrg 1131d6c0b56eSmrg /* Save flag for 6 bit DAC to use for 1132d6c0b56eSmrg setting CRTC registers. Otherwise use 1133d6c0b56eSmrg an 8 bit DAC, even if xf86SetWeight sets 1134d6c0b56eSmrg pScrn->rgbBits to some value other than 1135d6c0b56eSmrg 8. */ 1136d6c0b56eSmrg info->dac6bits = FALSE; 1137d6c0b56eSmrg 1138d6c0b56eSmrg if (pScrn->depth > 8) { 1139d6c0b56eSmrg rgb defaultWeight = { 0, 0, 0 }; 1140d6c0b56eSmrg 1141d6c0b56eSmrg if (!xf86SetWeight(pScrn, defaultWeight, defaultWeight)) 1142d6c0b56eSmrg return FALSE; 1143d6c0b56eSmrg } else { 1144d6c0b56eSmrg pScrn->rgbBits = 8; 1145d6c0b56eSmrg } 1146d6c0b56eSmrg 1147d6c0b56eSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1148d6c0b56eSmrg "Using %d bits per RGB (%d bit DAC)\n", 1149d6c0b56eSmrg pScrn->rgbBits, info->dac6bits ? 6 : 8); 1150d6c0b56eSmrg 1151d6c0b56eSmrg return TRUE; 1152d6c0b56eSmrg} 1153d6c0b56eSmrg 1154d6c0b56eSmrgstatic Bool AMDGPUPreInitAccel_KMS(ScrnInfoPtr pScrn) 1155d6c0b56eSmrg{ 1156d6c0b56eSmrg AMDGPUInfoPtr info = AMDGPUPTR(pScrn); 1157d6c0b56eSmrg 1158d6c0b56eSmrg if (xf86ReturnOptValBool(info->Options, OPTION_ACCEL, TRUE)) { 1159d6c0b56eSmrg AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(pScrn); 1160d6c0b56eSmrg Bool use_glamor = TRUE; 1161d6c0b56eSmrg#ifdef HAVE_GBM_BO_USE_LINEAR 1162d6c0b56eSmrg const char *accel_method; 1163d6c0b56eSmrg 1164d6c0b56eSmrg accel_method = xf86GetOptValString(info->Options, OPTION_ACCEL_METHOD); 1165d6c0b56eSmrg if ((accel_method && !strcmp(accel_method, "none"))) 1166d6c0b56eSmrg use_glamor = FALSE; 1167d6c0b56eSmrg#endif 1168d6c0b56eSmrg 116924b90cf4Smrg if (pScrn->depth == 30 && use_glamor && 117024b90cf4Smrg xorgGetVersion() < XORG_VERSION_NUMERIC(1,19,99,1,0)) { 117124b90cf4Smrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 117224b90cf4Smrg "Depth 30 is not supported by GLAMOR with " 117324b90cf4Smrg "Xorg < 1.19.99.1\n"); 117424b90cf4Smrg goto shadowfb; 117524b90cf4Smrg } 117624b90cf4Smrg 1177d6c0b56eSmrg#ifdef DRI2 1178d6c0b56eSmrg info->dri2.available = ! !xf86LoadSubModule(pScrn, "dri2"); 1179d6c0b56eSmrg#endif 1180d6c0b56eSmrg 1181d6c0b56eSmrg if (info->dri2.available) 1182d6c0b56eSmrg info->gbm = gbm_create_device(pAMDGPUEnt->fd); 1183d6c0b56eSmrg 118424b90cf4Smrg if (info->gbm) { 118524b90cf4Smrg if (!use_glamor || 118624b90cf4Smrg amdgpu_glamor_pre_init(pScrn)) 118724b90cf4Smrg return TRUE; 118824b90cf4Smrg } else { 118924b90cf4Smrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 119024b90cf4Smrg "gbm_create_device returned NULL, using " 119124b90cf4Smrg "ShadowFB\n"); 119224b90cf4Smrg } 119324b90cf4Smrg } else { 119424b90cf4Smrgshadowfb: 119524b90cf4Smrg xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 119624b90cf4Smrg "GPU acceleration disabled, using ShadowFB\n"); 1197d6c0b56eSmrg } 1198d6c0b56eSmrg 1199d6c0b56eSmrg if (!xf86LoadSubModule(pScrn, "shadow")) 120024b90cf4Smrg return FALSE; 1201d6c0b56eSmrg 120224b90cf4Smrg info->dri2.available = FALSE; 120324b90cf4Smrg info->shadow_fb = TRUE; 1204d6c0b56eSmrg return TRUE; 1205d6c0b56eSmrg} 1206d6c0b56eSmrg 120711bf0794Smrgstatic Bool AMDGPUPreInitChipType_KMS(ScrnInfoPtr pScrn, 120811bf0794Smrg struct amdgpu_gpu_info *gpu_info) 1209d6c0b56eSmrg{ 1210d6c0b56eSmrg AMDGPUInfoPtr info = AMDGPUPTR(pScrn); 121111bf0794Smrg AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(pScrn); 1212d6c0b56eSmrg 121311bf0794Smrg info->Chipset = info->PciInfo->device_id; 121411bf0794Smrg pScrn->chipset = amdgpu_get_marketing_name(pAMDGPUEnt->pDev); 121511bf0794Smrg if (!pScrn->chipset) 121611bf0794Smrg pScrn->chipset = "Unknown AMD Radeon GPU"; 1217d6c0b56eSmrg 1218d6c0b56eSmrg if (info->Chipset < 0) { 1219d6c0b56eSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1220d6c0b56eSmrg "Chipset \"%s\" is not recognized\n", 1221d6c0b56eSmrg pScrn->chipset); 1222d6c0b56eSmrg return FALSE; 1223d6c0b56eSmrg } 1224d6c0b56eSmrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 1225d6c0b56eSmrg "Chipset: \"%s\" (ChipID = 0x%04x)\n", 1226d6c0b56eSmrg pScrn->chipset, info->Chipset); 1227d6c0b56eSmrg 122811bf0794Smrg info->family = gpu_info->family_id; 1229d6c0b56eSmrg 1230d6c0b56eSmrg return TRUE; 1231d6c0b56eSmrg} 1232d6c0b56eSmrg 123311bf0794Smrgstatic Bool amdgpu_get_tile_config(AMDGPUInfoPtr info, 123411bf0794Smrg struct amdgpu_gpu_info *gpu_info) 1235d6c0b56eSmrg{ 123611bf0794Smrg switch ((gpu_info->gb_addr_cfg & 0x70) >> 4) { 1237d6c0b56eSmrg case 0: 1238d6c0b56eSmrg info->group_bytes = 256; 1239d6c0b56eSmrg break; 1240d6c0b56eSmrg case 1: 1241d6c0b56eSmrg info->group_bytes = 512; 1242d6c0b56eSmrg break; 1243d6c0b56eSmrg default: 1244d6c0b56eSmrg return FALSE; 1245d6c0b56eSmrg } 1246d6c0b56eSmrg 1247d6c0b56eSmrg info->have_tiling_info = TRUE; 1248d6c0b56eSmrg return TRUE; 1249d6c0b56eSmrg} 1250d6c0b56eSmrg 1251d6c0b56eSmrgstatic void AMDGPUSetupCapabilities(ScrnInfoPtr pScrn) 1252d6c0b56eSmrg{ 1253d6c0b56eSmrg AMDGPUInfoPtr info = AMDGPUPTR(pScrn); 1254d6c0b56eSmrg AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(pScrn); 1255d6c0b56eSmrg uint64_t value; 1256d6c0b56eSmrg int ret; 1257d6c0b56eSmrg 1258d6c0b56eSmrg pScrn->capabilities = 0; 1259d6c0b56eSmrg 1260d6c0b56eSmrg /* PRIME offloading requires acceleration */ 1261d6c0b56eSmrg if (!info->use_glamor) 1262d6c0b56eSmrg return; 1263d6c0b56eSmrg 1264d6c0b56eSmrg ret = drmGetCap(pAMDGPUEnt->fd, DRM_CAP_PRIME, &value); 1265d6c0b56eSmrg if (ret == 0) { 1266d6c0b56eSmrg if (value & DRM_PRIME_CAP_EXPORT) 1267504d986fSmrg pScrn->capabilities |= RR_Capability_SourceOutput | RR_Capability_SourceOffload; 1268504d986fSmrg if (value & DRM_PRIME_CAP_IMPORT) { 1269504d986fSmrg pScrn->capabilities |= RR_Capability_SinkOffload; 1270504d986fSmrg if (info->drmmode.count_crtcs) 1271504d986fSmrg pScrn->capabilities |= RR_Capability_SinkOutput; 1272504d986fSmrg } 1273d6c0b56eSmrg } 1274d6c0b56eSmrg} 1275d6c0b56eSmrg 1276d6c0b56eSmrg/* When the root window is created, initialize the screen contents from 1277d6c0b56eSmrg * console if -background none was specified on the command line 1278d6c0b56eSmrg */ 1279d6c0b56eSmrgstatic Bool AMDGPUCreateWindow_oneshot(WindowPtr pWin) 1280d6c0b56eSmrg{ 1281d6c0b56eSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 1282d6c0b56eSmrg ScrnInfoPtr pScrn; 1283d6c0b56eSmrg AMDGPUInfoPtr info; 1284d6c0b56eSmrg Bool ret; 1285d6c0b56eSmrg 1286d6c0b56eSmrg if (pWin != pScreen->root) 1287d6c0b56eSmrg ErrorF("%s called for non-root window %p\n", __func__, pWin); 1288d6c0b56eSmrg 1289d6c0b56eSmrg pScrn = xf86ScreenToScrn(pScreen); 1290d6c0b56eSmrg info = AMDGPUPTR(pScrn); 1291d6c0b56eSmrg pScreen->CreateWindow = info->CreateWindow; 1292d6c0b56eSmrg ret = pScreen->CreateWindow(pWin); 1293d6c0b56eSmrg 1294d6c0b56eSmrg if (ret) 1295d6c0b56eSmrg drmmode_copy_fb(pScrn, &info->drmmode); 1296d6c0b56eSmrg 1297d6c0b56eSmrg return ret; 1298d6c0b56eSmrg} 1299d6c0b56eSmrg 130011bf0794Smrg/* When the root window is mapped, set the initial modes */ 130124b90cf4Smrgvoid AMDGPUWindowExposures_oneshot(WindowPtr pWin, RegionPtr pRegion 130211bf0794Smrg#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1,16,99,901,0) 130324b90cf4Smrg , RegionPtr pBSRegion 130411bf0794Smrg#endif 130524b90cf4Smrg ) 130611bf0794Smrg{ 130711bf0794Smrg ScreenPtr pScreen = pWin->drawable.pScreen; 130811bf0794Smrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 130911bf0794Smrg AMDGPUInfoPtr info = AMDGPUPTR(pScrn); 131011bf0794Smrg 131111bf0794Smrg if (pWin != pScreen->root) 131211bf0794Smrg ErrorF("%s called for non-root window %p\n", __func__, pWin); 131311bf0794Smrg 131411bf0794Smrg pScreen->WindowExposures = info->WindowExposures; 131511bf0794Smrg#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1,16,99,901,0) 131611bf0794Smrg pScreen->WindowExposures(pWin, pRegion, pBSRegion); 131711bf0794Smrg#else 131811bf0794Smrg pScreen->WindowExposures(pWin, pRegion); 131911bf0794Smrg#endif 132011bf0794Smrg 132111bf0794Smrg amdgpu_glamor_finish(pScrn); 132211bf0794Smrg drmmode_set_desired_modes(pScrn, &info->drmmode, TRUE); 132311bf0794Smrg} 132411bf0794Smrg 1325d6c0b56eSmrgBool AMDGPUPreInit_KMS(ScrnInfoPtr pScrn, int flags) 1326d6c0b56eSmrg{ 1327d6c0b56eSmrg AMDGPUInfoPtr info; 1328d6c0b56eSmrg AMDGPUEntPtr pAMDGPUEnt; 132911bf0794Smrg struct amdgpu_gpu_info gpu_info; 133011bf0794Smrg MessageType from; 1331d6c0b56eSmrg DevUnion *pPriv; 1332d6c0b56eSmrg Gamma zeros = { 0.0, 0.0, 0.0 }; 1333d6c0b56eSmrg int cpp; 1334d6c0b56eSmrg uint64_t heap_size = 0; 1335d6c0b56eSmrg uint64_t max_allocation = 0; 1336d6c0b56eSmrg Bool sw_cursor; 1337d6c0b56eSmrg 1338d6c0b56eSmrg if (flags & PROBE_DETECT) 1339d6c0b56eSmrg return TRUE; 1340d6c0b56eSmrg 1341d6c0b56eSmrg xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG, 1342d6c0b56eSmrg "AMDGPUPreInit_KMS\n"); 1343d6c0b56eSmrg if (pScrn->numEntities != 1) 1344d6c0b56eSmrg return FALSE; 1345d6c0b56eSmrg if (!AMDGPUGetRec(pScrn)) 1346d6c0b56eSmrg return FALSE; 1347d6c0b56eSmrg 1348d6c0b56eSmrg info = AMDGPUPTR(pScrn); 1349d6c0b56eSmrg info->IsSecondary = FALSE; 1350d6c0b56eSmrg info->pEnt = 1351d6c0b56eSmrg xf86GetEntityInfo(pScrn->entityList[pScrn->numEntities - 1]); 1352d6c0b56eSmrg if (info->pEnt->location.type != BUS_PCI 1353d6c0b56eSmrg#ifdef XSERVER_PLATFORM_BUS 1354d6c0b56eSmrg && info->pEnt->location.type != BUS_PLATFORM 1355d6c0b56eSmrg#endif 1356d6c0b56eSmrg ) 135724b90cf4Smrg return FALSE; 1358d6c0b56eSmrg 1359d6c0b56eSmrg pPriv = xf86GetEntityPrivate(pScrn->entityList[0], 1360d6c0b56eSmrg getAMDGPUEntityIndex()); 1361d6c0b56eSmrg pAMDGPUEnt = pPriv->ptr; 1362d6c0b56eSmrg 1363d6c0b56eSmrg if (xf86IsEntityShared(pScrn->entityList[0])) { 1364d6c0b56eSmrg if (xf86IsPrimInitDone(pScrn->entityList[0])) { 1365d6c0b56eSmrg info->IsSecondary = TRUE; 1366d6c0b56eSmrg } else { 1367d6c0b56eSmrg xf86SetPrimInitDone(pScrn->entityList[0]); 1368d6c0b56eSmrg } 1369d6c0b56eSmrg } 1370d6c0b56eSmrg 1371504d986fSmrg if (info->IsSecondary) 1372504d986fSmrg pAMDGPUEnt->secondary_scrn = pScrn; 1373504d986fSmrg else 1374504d986fSmrg pAMDGPUEnt->primary_scrn = pScrn; 1375504d986fSmrg 1376d6c0b56eSmrg info->PciInfo = xf86GetPciInfoForEntity(info->pEnt->index); 1377d6c0b56eSmrg pScrn->monitor = pScrn->confScreen->monitor; 1378d6c0b56eSmrg 1379d6c0b56eSmrg if (!AMDGPUPreInitVisual(pScrn)) 138024b90cf4Smrg return FALSE; 1381d6c0b56eSmrg 1382d6c0b56eSmrg xf86CollectOptions(pScrn, NULL); 1383d6c0b56eSmrg if (!(info->Options = malloc(sizeof(AMDGPUOptions_KMS)))) 138424b90cf4Smrg return FALSE; 1385d6c0b56eSmrg 1386d6c0b56eSmrg memcpy(info->Options, AMDGPUOptions_KMS, sizeof(AMDGPUOptions_KMS)); 1387d6c0b56eSmrg xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, info->Options); 1388d6c0b56eSmrg 1389d6c0b56eSmrg if (!AMDGPUPreInitWeight(pScrn)) 139024b90cf4Smrg return FALSE; 1391d6c0b56eSmrg 139211bf0794Smrg memset(&gpu_info, 0, sizeof(gpu_info)); 139311bf0794Smrg amdgpu_query_gpu_info(pAMDGPUEnt->pDev, &gpu_info); 139411bf0794Smrg 139511bf0794Smrg if (!AMDGPUPreInitChipType_KMS(pScrn, &gpu_info)) 139624b90cf4Smrg return FALSE; 1397d6c0b56eSmrg 1398d6c0b56eSmrg info->dri2.available = FALSE; 1399d6c0b56eSmrg info->dri2.enabled = FALSE; 1400d6c0b56eSmrg info->dri2.pKernelDRMVersion = drmGetVersion(pAMDGPUEnt->fd); 1401d6c0b56eSmrg if (info->dri2.pKernelDRMVersion == NULL) { 1402d6c0b56eSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1403d6c0b56eSmrg "AMDGPUDRIGetVersion failed to get the DRM version\n"); 140424b90cf4Smrg return FALSE; 1405d6c0b56eSmrg } 1406d6c0b56eSmrg 1407d6c0b56eSmrg /* Get ScreenInit function */ 1408d6c0b56eSmrg if (!xf86LoadSubModule(pScrn, "fb")) 1409d6c0b56eSmrg return FALSE; 1410d6c0b56eSmrg 1411d6c0b56eSmrg if (!AMDGPUPreInitAccel_KMS(pScrn)) 141224b90cf4Smrg return FALSE; 1413d6c0b56eSmrg 1414d6c0b56eSmrg amdgpu_drm_queue_init(); 1415d6c0b56eSmrg 1416d6c0b56eSmrg /* don't enable tiling if accel is not enabled */ 1417d6c0b56eSmrg if (info->use_glamor) { 1418d6c0b56eSmrg /* set default group bytes, overridden by kernel info below */ 1419d6c0b56eSmrg info->group_bytes = 256; 1420d6c0b56eSmrg info->have_tiling_info = FALSE; 142111bf0794Smrg amdgpu_get_tile_config(info, &gpu_info); 1422d6c0b56eSmrg } 1423d6c0b56eSmrg 1424d6c0b56eSmrg if (info->use_glamor) { 142511bf0794Smrg from = X_DEFAULT; 1426d6c0b56eSmrg 142711bf0794Smrg info->tear_free = 2; 142811bf0794Smrg if (xf86GetOptValBool(info->Options, OPTION_TEAR_FREE, 142911bf0794Smrg &info->tear_free)) 143011bf0794Smrg from = X_CONFIG; 143111bf0794Smrg xf86DrvMsg(pScrn->scrnIndex, from, "TearFree property default: %s\n", 143211bf0794Smrg info->tear_free == 2 ? "auto" : (info->tear_free ? "on" : "off")); 1433d6c0b56eSmrg 1434d6c0b56eSmrg info->shadow_primary = 1435d6c0b56eSmrg xf86ReturnOptValBool(info->Options, OPTION_SHADOW_PRIMARY, FALSE); 1436d6c0b56eSmrg 1437d6c0b56eSmrg if (info->shadow_primary) 1438d6c0b56eSmrg xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ShadowPrimary enabled\n"); 1439d6c0b56eSmrg } 1440d6c0b56eSmrg 144124b90cf4Smrg if (!pScrn->is_gpu) { 144211bf0794Smrg sw_cursor = xf86ReturnOptValBool(info->Options, 144311bf0794Smrg OPTION_SW_CURSOR, FALSE); 144411bf0794Smrg 144511bf0794Smrg info->allowPageFlip = xf86ReturnOptValBool(info->Options, 144611bf0794Smrg OPTION_PAGE_FLIP, 144711bf0794Smrg TRUE); 144811bf0794Smrg if (sw_cursor || info->shadow_primary) { 144911bf0794Smrg xf86DrvMsg(pScrn->scrnIndex, 145011bf0794Smrg info->allowPageFlip ? X_WARNING : X_DEFAULT, 145111bf0794Smrg "KMS Pageflipping: disabled%s\n", 145211bf0794Smrg info->allowPageFlip ? 145311bf0794Smrg (sw_cursor ? " because of SWcursor" : 145411bf0794Smrg " because of ShadowPrimary") : ""); 145511bf0794Smrg info->allowPageFlip = FALSE; 145611bf0794Smrg } else { 145711bf0794Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 145811bf0794Smrg "KMS Pageflipping: %sabled\n", 145911bf0794Smrg info->allowPageFlip ? "en" : "dis"); 146011bf0794Smrg } 1461d6c0b56eSmrg } 1462d6c0b56eSmrg 1463d6c0b56eSmrg if (xf86ReturnOptValBool(info->Options, OPTION_DELETE_DP12, FALSE)) { 1464d6c0b56eSmrg info->drmmode.delete_dp_12_displays = TRUE; 1465d6c0b56eSmrg } 1466d6c0b56eSmrg 1467d6c0b56eSmrg if (drmmode_pre_init(pScrn, &info->drmmode, pScrn->bitsPerPixel / 8) == 1468d6c0b56eSmrg FALSE) { 1469d6c0b56eSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1470d6c0b56eSmrg "Kernel modesetting setup failed\n"); 147124b90cf4Smrg return FALSE; 1472d6c0b56eSmrg } 1473d6c0b56eSmrg 1474504d986fSmrg AMDGPUSetupCapabilities(pScrn); 1475504d986fSmrg 1476d6c0b56eSmrg if (info->drmmode.count_crtcs == 1) 1477d6c0b56eSmrg pAMDGPUEnt->HasCRTC2 = FALSE; 1478d6c0b56eSmrg else 1479d6c0b56eSmrg pAMDGPUEnt->HasCRTC2 = TRUE; 1480d6c0b56eSmrg 148111bf0794Smrg if (info->family < AMDGPU_FAMILY_CI) { 1482504d986fSmrg info->cursor_w = CURSOR_WIDTH; 1483504d986fSmrg info->cursor_h = CURSOR_HEIGHT; 1484504d986fSmrg } else { 1485504d986fSmrg info->cursor_w = CURSOR_WIDTH_CIK; 1486504d986fSmrg info->cursor_h = CURSOR_HEIGHT_CIK; 1487504d986fSmrg } 1488d6c0b56eSmrg 1489d6c0b56eSmrg amdgpu_query_heap_size(pAMDGPUEnt->pDev, AMDGPU_GEM_DOMAIN_GTT, 1490d6c0b56eSmrg &heap_size, &max_allocation); 1491d6c0b56eSmrg info->gart_size = heap_size; 1492d6c0b56eSmrg amdgpu_query_heap_size(pAMDGPUEnt->pDev, AMDGPU_GEM_DOMAIN_VRAM, 1493d6c0b56eSmrg &heap_size, &max_allocation); 1494d6c0b56eSmrg info->vram_size = max_allocation; 1495d6c0b56eSmrg 1496d6c0b56eSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1497d6c0b56eSmrg "mem size init: gart size :%llx vram size: s:%llx visible:%llx\n", 1498d6c0b56eSmrg (unsigned long long)info->gart_size, 1499d6c0b56eSmrg (unsigned long long)heap_size, 1500d6c0b56eSmrg (unsigned long long)max_allocation); 1501d6c0b56eSmrg 1502d6c0b56eSmrg cpp = pScrn->bitsPerPixel / 8; 1503d6c0b56eSmrg pScrn->displayWidth = 1504d6c0b56eSmrg AMDGPU_ALIGN(pScrn->virtualX, drmmode_get_pitch_align(pScrn, cpp)); 1505d6c0b56eSmrg 1506d6c0b56eSmrg /* Set display resolution */ 1507d6c0b56eSmrg xf86SetDpi(pScrn, 0, 0); 1508d6c0b56eSmrg 1509d6c0b56eSmrg if (!xf86SetGamma(pScrn, zeros)) 1510d6c0b56eSmrg return FALSE; 1511d6c0b56eSmrg 1512d6c0b56eSmrg if (!xf86ReturnOptValBool(info->Options, OPTION_SW_CURSOR, FALSE)) { 1513d6c0b56eSmrg if (!xf86LoadSubModule(pScrn, "ramdac")) 1514d6c0b56eSmrg return FALSE; 1515d6c0b56eSmrg } 1516d6c0b56eSmrg 1517d6c0b56eSmrg if (pScrn->modes == NULL 1518d6c0b56eSmrg#ifdef XSERVER_PLATFORM_BUS 1519d6c0b56eSmrg && !pScrn->is_gpu 1520d6c0b56eSmrg#endif 1521d6c0b56eSmrg ) { 1522d6c0b56eSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No modes.\n"); 152324b90cf4Smrg return FALSE; 1524d6c0b56eSmrg } 1525d6c0b56eSmrg 1526d6c0b56eSmrg return TRUE; 1527d6c0b56eSmrg} 1528d6c0b56eSmrg 1529d6c0b56eSmrgstatic Bool AMDGPUCursorInit_KMS(ScreenPtr pScreen) 1530d6c0b56eSmrg{ 1531d6c0b56eSmrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 1532d6c0b56eSmrg AMDGPUInfoPtr info = AMDGPUPTR(pScrn); 1533d6c0b56eSmrg 153424b90cf4Smrg xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG, 153524b90cf4Smrg "Initializing Cursor\n"); 153624b90cf4Smrg 153724b90cf4Smrg /* Set Silken Mouse */ 153824b90cf4Smrg xf86SetSilkenMouse(pScreen); 153924b90cf4Smrg 154024b90cf4Smrg /* Cursor setup */ 154124b90cf4Smrg miDCInitialize(pScreen, xf86GetPointerScreenFuncs()); 154224b90cf4Smrg 154324b90cf4Smrg if (info->allowPageFlip) { 154424b90cf4Smrg miPointerScreenPtr PointPriv = 154524b90cf4Smrg dixLookupPrivate(&pScreen->devPrivates, miPointerScreenKey); 154624b90cf4Smrg 154724b90cf4Smrg if (!dixRegisterScreenPrivateKey(&amdgpu_device_private_key, pScreen, 154824b90cf4Smrg PRIVATE_DEVICE, 154924b90cf4Smrg sizeof(struct amdgpu_device_priv))) { 155024b90cf4Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "dixRegisterScreenPrivateKey failed\n"); 155124b90cf4Smrg return FALSE; 155224b90cf4Smrg } 155324b90cf4Smrg 155424b90cf4Smrg info->SetCursor = PointPriv->spriteFuncs->SetCursor; 155524b90cf4Smrg info->MoveCursor = PointPriv->spriteFuncs->MoveCursor; 155624b90cf4Smrg PointPriv->spriteFuncs->SetCursor = drmmode_sprite_set_cursor; 155724b90cf4Smrg PointPriv->spriteFuncs->MoveCursor = drmmode_sprite_move_cursor; 155824b90cf4Smrg } 155924b90cf4Smrg 156024b90cf4Smrg if (xf86ReturnOptValBool(info->Options, OPTION_SW_CURSOR, FALSE)) 156124b90cf4Smrg return TRUE; 156224b90cf4Smrg 156324b90cf4Smrg if (!xf86_cursors_init(pScreen, info->cursor_w, info->cursor_h, 156424b90cf4Smrg HARDWARE_CURSOR_TRUECOLOR_AT_8BPP | 156524b90cf4Smrg HARDWARE_CURSOR_AND_SOURCE_WITH_MASK | 156624b90cf4Smrg HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_1 | 156724b90cf4Smrg HARDWARE_CURSOR_UPDATE_UNHIDDEN | 156824b90cf4Smrg HARDWARE_CURSOR_ARGB)) { 156924b90cf4Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "xf86_cursors_init failed\n"); 157024b90cf4Smrg return FALSE; 157124b90cf4Smrg } 157224b90cf4Smrg 157324b90cf4Smrg return TRUE; 1574d6c0b56eSmrg} 1575d6c0b56eSmrg 1576d6c0b56eSmrgvoid AMDGPUBlank(ScrnInfoPtr pScrn) 1577d6c0b56eSmrg{ 1578d6c0b56eSmrg xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); 1579d6c0b56eSmrg xf86OutputPtr output; 1580d6c0b56eSmrg xf86CrtcPtr crtc; 1581d6c0b56eSmrg int o, c; 1582d6c0b56eSmrg 1583d6c0b56eSmrg for (c = 0; c < xf86_config->num_crtc; c++) { 1584d6c0b56eSmrg crtc = xf86_config->crtc[c]; 1585d6c0b56eSmrg for (o = 0; o < xf86_config->num_output; o++) { 1586d6c0b56eSmrg output = xf86_config->output[o]; 1587d6c0b56eSmrg if (output->crtc != crtc) 1588d6c0b56eSmrg continue; 1589d6c0b56eSmrg 1590d6c0b56eSmrg output->funcs->dpms(output, DPMSModeOff); 1591d6c0b56eSmrg } 1592d6c0b56eSmrg crtc->funcs->dpms(crtc, DPMSModeOff); 1593d6c0b56eSmrg } 1594d6c0b56eSmrg} 1595d6c0b56eSmrg 1596d6c0b56eSmrgvoid AMDGPUUnblank(ScrnInfoPtr pScrn) 1597d6c0b56eSmrg{ 1598d6c0b56eSmrg xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); 1599d6c0b56eSmrg xf86OutputPtr output; 1600d6c0b56eSmrg xf86CrtcPtr crtc; 1601d6c0b56eSmrg int o, c; 1602d6c0b56eSmrg for (c = 0; c < xf86_config->num_crtc; c++) { 1603d6c0b56eSmrg crtc = xf86_config->crtc[c]; 1604d6c0b56eSmrg if (!crtc->enabled) 1605d6c0b56eSmrg continue; 1606d6c0b56eSmrg crtc->funcs->dpms(crtc, DPMSModeOn); 1607d6c0b56eSmrg for (o = 0; o < xf86_config->num_output; o++) { 1608d6c0b56eSmrg output = xf86_config->output[o]; 1609d6c0b56eSmrg if (output->crtc != crtc) 1610d6c0b56eSmrg continue; 1611d6c0b56eSmrg output->funcs->dpms(output, DPMSModeOn); 1612d6c0b56eSmrg } 1613d6c0b56eSmrg } 1614d6c0b56eSmrg} 1615d6c0b56eSmrg 1616d6c0b56eSmrgstatic Bool amdgpu_set_drm_master(ScrnInfoPtr pScrn) 1617d6c0b56eSmrg{ 1618d6c0b56eSmrg AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(pScrn); 1619d6c0b56eSmrg int err; 1620d6c0b56eSmrg 1621d6c0b56eSmrg#ifdef XF86_PDEV_SERVER_FD 1622d6c0b56eSmrg if (pAMDGPUEnt->platform_dev && 1623d6c0b56eSmrg (pAMDGPUEnt->platform_dev->flags & XF86_PDEV_SERVER_FD)) 1624d6c0b56eSmrg return TRUE; 1625d6c0b56eSmrg#endif 1626d6c0b56eSmrg 1627d6c0b56eSmrg err = drmSetMaster(pAMDGPUEnt->fd); 1628d6c0b56eSmrg if (err) 1629d6c0b56eSmrg ErrorF("Unable to retrieve master\n"); 1630d6c0b56eSmrg 1631d6c0b56eSmrg return err == 0; 1632d6c0b56eSmrg} 1633d6c0b56eSmrg 1634d6c0b56eSmrgstatic void amdgpu_drop_drm_master(ScrnInfoPtr pScrn) 1635d6c0b56eSmrg{ 1636d6c0b56eSmrg AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(pScrn); 1637d6c0b56eSmrg 1638d6c0b56eSmrg#ifdef XF86_PDEV_SERVER_FD 1639d6c0b56eSmrg if (pAMDGPUEnt->platform_dev && 1640d6c0b56eSmrg (pAMDGPUEnt->platform_dev->flags & XF86_PDEV_SERVER_FD)) 1641d6c0b56eSmrg return; 1642d6c0b56eSmrg#endif 1643d6c0b56eSmrg 1644d6c0b56eSmrg drmDropMaster(pAMDGPUEnt->fd); 1645d6c0b56eSmrg} 1646d6c0b56eSmrg 1647d6c0b56eSmrg 164824b90cf4Smrgstatic 164924b90cf4SmrgCARD32 cleanup_black_fb(OsTimerPtr timer, CARD32 now, pointer data) 165024b90cf4Smrg{ 165124b90cf4Smrg ScreenPtr screen = data; 165224b90cf4Smrg ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 165324b90cf4Smrg AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(scrn); 165424b90cf4Smrg xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); 165524b90cf4Smrg int c; 165624b90cf4Smrg 165724b90cf4Smrg if (xf86ScreenToScrn(amdgpu_master_screen(screen))->vtSema) 165824b90cf4Smrg return 0; 165924b90cf4Smrg 166024b90cf4Smrg /* Unreference the all-black FB created by AMDGPULeaveVT_KMS. After 166124b90cf4Smrg * this, there should be no FB left created by this driver. 166224b90cf4Smrg */ 166324b90cf4Smrg for (c = 0; c < xf86_config->num_crtc; c++) { 166424b90cf4Smrg drmmode_crtc_private_ptr drmmode_crtc = 166524b90cf4Smrg xf86_config->crtc[c]->driver_private; 166624b90cf4Smrg 166724b90cf4Smrg drmmode_fb_reference(pAMDGPUEnt->fd, &drmmode_crtc->fb, NULL); 166824b90cf4Smrg } 166924b90cf4Smrg 167024b90cf4Smrg TimerFree(timer); 167124b90cf4Smrg return 0; 167224b90cf4Smrg} 1673d6c0b56eSmrg 1674d6c0b56eSmrgstatic Bool AMDGPUSaveScreen_KMS(ScreenPtr pScreen, int mode) 1675d6c0b56eSmrg{ 1676d6c0b56eSmrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 1677d6c0b56eSmrg Bool unblank; 1678d6c0b56eSmrg 1679d6c0b56eSmrg xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG, 1680d6c0b56eSmrg "AMDGPUSaveScreen(%d)\n", mode); 1681d6c0b56eSmrg 1682d6c0b56eSmrg unblank = xf86IsUnblank(mode); 1683d6c0b56eSmrg if (unblank) 1684d6c0b56eSmrg SetTimeSinceLastInputEvent(); 1685d6c0b56eSmrg 1686d6c0b56eSmrg if ((pScrn != NULL) && pScrn->vtSema) { 1687d6c0b56eSmrg if (unblank) 1688d6c0b56eSmrg AMDGPUUnblank(pScrn); 1689d6c0b56eSmrg else 1690d6c0b56eSmrg AMDGPUBlank(pScrn); 1691d6c0b56eSmrg } 1692d6c0b56eSmrg return TRUE; 1693d6c0b56eSmrg} 1694d6c0b56eSmrg 1695d6c0b56eSmrg/* Called at the end of each server generation. Restore the original 1696d6c0b56eSmrg * text mode, unmap video memory, and unwrap and call the saved 1697d6c0b56eSmrg * CloseScreen function. 1698d6c0b56eSmrg */ 169924b90cf4Smrgstatic Bool AMDGPUCloseScreen_KMS(ScreenPtr pScreen) 1700d6c0b56eSmrg{ 1701d6c0b56eSmrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 1702d6c0b56eSmrg AMDGPUInfoPtr info = AMDGPUPTR(pScrn); 1703d6c0b56eSmrg AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(pScrn); 1704d6c0b56eSmrg 1705d6c0b56eSmrg xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG, 1706d6c0b56eSmrg "AMDGPUCloseScreen\n"); 1707d6c0b56eSmrg 1708d6c0b56eSmrg /* Clear mask of assigned crtc's in this generation */ 1709d6c0b56eSmrg pAMDGPUEnt->assigned_crtcs = 0; 1710d6c0b56eSmrg 1711d6c0b56eSmrg drmmode_uevent_fini(pScrn, &info->drmmode); 1712d6c0b56eSmrg amdgpu_drm_queue_close(pScrn); 1713d6c0b56eSmrg 1714504d986fSmrg if (info->callback_event_type != -1) { 1715504d986fSmrg DeleteCallback(&EventCallback, amdgpu_event_callback, pScrn); 1716504d986fSmrg DeleteCallback(&FlushCallback, amdgpu_flush_callback, pScrn); 1717504d986fSmrg } 1718d6c0b56eSmrg 1719d6c0b56eSmrg amdgpu_sync_close(pScreen); 1720d6c0b56eSmrg amdgpu_drop_drm_master(pScrn); 1721d6c0b56eSmrg 1722d6c0b56eSmrg drmmode_fini(pScrn, &info->drmmode); 1723d6c0b56eSmrg if (info->dri2.enabled) { 1724d6c0b56eSmrg amdgpu_dri2_close_screen(pScreen); 1725d6c0b56eSmrg } 1726d6c0b56eSmrg amdgpu_glamor_fini(pScreen); 1727d6c0b56eSmrg pScrn->vtSema = FALSE; 1728d6c0b56eSmrg xf86ClearPrimInitDone(info->pEnt->index); 172924b90cf4Smrg 173024b90cf4Smrg if (info->allowPageFlip) { 173124b90cf4Smrg miPointerScreenPtr PointPriv = 173224b90cf4Smrg dixLookupPrivate(&pScreen->devPrivates, miPointerScreenKey); 173324b90cf4Smrg 173424b90cf4Smrg PointPriv->spriteFuncs->SetCursor = info->SetCursor; 173524b90cf4Smrg PointPriv->spriteFuncs->MoveCursor = info->MoveCursor; 173624b90cf4Smrg } 173724b90cf4Smrg 1738d6c0b56eSmrg pScreen->BlockHandler = info->BlockHandler; 1739d6c0b56eSmrg pScreen->CloseScreen = info->CloseScreen; 174024b90cf4Smrg return pScreen->CloseScreen(pScreen); 1741d6c0b56eSmrg} 1742d6c0b56eSmrg 174324b90cf4Smrgvoid AMDGPUFreeScreen_KMS(ScrnInfoPtr pScrn) 1744d6c0b56eSmrg{ 1745d6c0b56eSmrg xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG, 1746d6c0b56eSmrg "AMDGPUFreeScreen\n"); 1747d6c0b56eSmrg 1748d6c0b56eSmrg AMDGPUFreeRec(pScrn); 1749d6c0b56eSmrg} 1750d6c0b56eSmrg 175124b90cf4SmrgBool AMDGPUScreenInit_KMS(ScreenPtr pScreen, int argc, char **argv) 1752d6c0b56eSmrg{ 1753d6c0b56eSmrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 1754d6c0b56eSmrg AMDGPUInfoPtr info = AMDGPUPTR(pScrn); 1755d6c0b56eSmrg int subPixelOrder = SubPixelUnknown; 1756d6c0b56eSmrg MessageType from; 1757d6c0b56eSmrg Bool value; 1758d6c0b56eSmrg int driLevel; 1759d6c0b56eSmrg const char *s; 1760d6c0b56eSmrg void *front_ptr; 1761d6c0b56eSmrg 1762d6c0b56eSmrg pScrn->fbOffset = 0; 1763d6c0b56eSmrg 1764d6c0b56eSmrg miClearVisualTypes(); 1765d6c0b56eSmrg if (!miSetVisualTypes(pScrn->depth, 1766d6c0b56eSmrg miGetDefaultVisualMask(pScrn->depth), 1767d6c0b56eSmrg pScrn->rgbBits, pScrn->defaultVisual)) 1768d6c0b56eSmrg return FALSE; 1769d6c0b56eSmrg miSetPixmapDepths(); 1770d6c0b56eSmrg 1771d6c0b56eSmrg if (!amdgpu_set_drm_master(pScrn)) 1772d6c0b56eSmrg return FALSE; 1773d6c0b56eSmrg 1774d6c0b56eSmrg info->directRenderingEnabled = FALSE; 1775d6c0b56eSmrg if (info->shadow_fb == FALSE) 1776d6c0b56eSmrg info->directRenderingEnabled = amdgpu_dri2_screen_init(pScreen); 1777d6c0b56eSmrg 1778d6c0b56eSmrg if (!amdgpu_setup_kernel_mem(pScreen)) { 1779d6c0b56eSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1780d6c0b56eSmrg "amdgpu_setup_kernel_mem failed\n"); 1781d6c0b56eSmrg return FALSE; 1782d6c0b56eSmrg } 1783d6c0b56eSmrg front_ptr = info->front_buffer->cpu_ptr; 1784d6c0b56eSmrg 1785d6c0b56eSmrg if (info->shadow_fb) { 1786d6c0b56eSmrg info->fb_shadow = calloc(1, 1787d6c0b56eSmrg pScrn->displayWidth * pScrn->virtualY * 1788d6c0b56eSmrg ((pScrn->bitsPerPixel + 7) >> 3)); 1789d6c0b56eSmrg if (info->fb_shadow == NULL) { 1790d6c0b56eSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1791d6c0b56eSmrg "Failed to allocate shadow framebuffer\n"); 179224b90cf4Smrg return FALSE; 1793d6c0b56eSmrg } else { 1794d6c0b56eSmrg if (!fbScreenInit(pScreen, info->fb_shadow, 1795d6c0b56eSmrg pScrn->virtualX, pScrn->virtualY, 1796d6c0b56eSmrg pScrn->xDpi, pScrn->yDpi, 1797d6c0b56eSmrg pScrn->displayWidth, 1798d6c0b56eSmrg pScrn->bitsPerPixel)) 1799d6c0b56eSmrg return FALSE; 1800d6c0b56eSmrg } 1801d6c0b56eSmrg } 1802d6c0b56eSmrg 1803d6c0b56eSmrg if (info->shadow_fb == FALSE) { 1804d6c0b56eSmrg /* Init fb layer */ 1805d6c0b56eSmrg if (!fbScreenInit(pScreen, front_ptr, 1806d6c0b56eSmrg pScrn->virtualX, pScrn->virtualY, 1807d6c0b56eSmrg pScrn->xDpi, pScrn->yDpi, pScrn->displayWidth, 1808d6c0b56eSmrg pScrn->bitsPerPixel)) 1809d6c0b56eSmrg return FALSE; 1810d6c0b56eSmrg } 1811d6c0b56eSmrg 1812d6c0b56eSmrg xf86SetBlackWhitePixels(pScreen); 1813d6c0b56eSmrg 1814d6c0b56eSmrg if (pScrn->bitsPerPixel > 8) { 1815d6c0b56eSmrg VisualPtr visual; 1816d6c0b56eSmrg 1817d6c0b56eSmrg visual = pScreen->visuals + pScreen->numVisuals; 1818d6c0b56eSmrg while (--visual >= pScreen->visuals) { 1819d6c0b56eSmrg if ((visual->class | DynamicClass) == DirectColor) { 1820d6c0b56eSmrg visual->offsetRed = pScrn->offset.red; 1821d6c0b56eSmrg visual->offsetGreen = pScrn->offset.green; 1822d6c0b56eSmrg visual->offsetBlue = pScrn->offset.blue; 1823d6c0b56eSmrg visual->redMask = pScrn->mask.red; 1824d6c0b56eSmrg visual->greenMask = pScrn->mask.green; 1825d6c0b56eSmrg visual->blueMask = pScrn->mask.blue; 1826d6c0b56eSmrg } 1827d6c0b56eSmrg } 1828d6c0b56eSmrg } 1829d6c0b56eSmrg 1830d6c0b56eSmrg /* Must be after RGB order fixed */ 1831d6c0b56eSmrg fbPictureInit(pScreen, 0, 0); 1832d6c0b56eSmrg 1833d6c0b56eSmrg#ifdef RENDER 1834d6c0b56eSmrg if ((s = xf86GetOptValString(info->Options, OPTION_SUBPIXEL_ORDER))) { 1835d6c0b56eSmrg if (strcmp(s, "RGB") == 0) 1836d6c0b56eSmrg subPixelOrder = SubPixelHorizontalRGB; 1837d6c0b56eSmrg else if (strcmp(s, "BGR") == 0) 1838d6c0b56eSmrg subPixelOrder = SubPixelHorizontalBGR; 1839d6c0b56eSmrg else if (strcmp(s, "NONE") == 0) 1840d6c0b56eSmrg subPixelOrder = SubPixelNone; 1841d6c0b56eSmrg PictureSetSubpixelOrder(pScreen, subPixelOrder); 1842d6c0b56eSmrg } 1843d6c0b56eSmrg#endif 1844d6c0b56eSmrg 184524b90cf4Smrg if (!pScreen->isGPU) { 184624b90cf4Smrg if (xorgGetVersion() >= XORG_VERSION_NUMERIC(1,18,3,0,0)) 184724b90cf4Smrg value = info->use_glamor; 184824b90cf4Smrg else 184924b90cf4Smrg value = FALSE; 185011bf0794Smrg from = X_DEFAULT; 1851d6c0b56eSmrg 185211bf0794Smrg if (info->use_glamor) { 185311bf0794Smrg if (xf86GetOptValBool(info->Options, OPTION_DRI3, &value)) 185411bf0794Smrg from = X_CONFIG; 1855d6c0b56eSmrg 185611bf0794Smrg if (xf86GetOptValInteger(info->Options, OPTION_DRI, &driLevel) && 185711bf0794Smrg (driLevel == 2 || driLevel == 3)) { 185811bf0794Smrg from = X_CONFIG; 185911bf0794Smrg value = driLevel == 3; 186011bf0794Smrg } 1861d6c0b56eSmrg } 1862d6c0b56eSmrg 186311bf0794Smrg if (value) { 186411bf0794Smrg value = amdgpu_sync_init(pScreen) && 186511bf0794Smrg amdgpu_present_screen_init(pScreen) && 186611bf0794Smrg amdgpu_dri3_screen_init(pScreen); 1867d6c0b56eSmrg 186811bf0794Smrg if (!value) 186911bf0794Smrg from = X_WARNING; 187011bf0794Smrg } 1871d6c0b56eSmrg 187211bf0794Smrg xf86DrvMsg(pScrn->scrnIndex, from, "DRI3 %sabled\n", value ? "en" : "dis"); 187311bf0794Smrg } 1874d6c0b56eSmrg 1875d6c0b56eSmrg pScrn->vtSema = TRUE; 1876d6c0b56eSmrg xf86SetBackingStore(pScreen); 1877d6c0b56eSmrg 1878d6c0b56eSmrg if (info->directRenderingEnabled) { 1879d6c0b56eSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1880d6c0b56eSmrg "Direct rendering enabled\n"); 1881d6c0b56eSmrg } else { 1882d6c0b56eSmrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1883d6c0b56eSmrg "Direct rendering disabled\n"); 1884d6c0b56eSmrg } 1885d6c0b56eSmrg 1886d6c0b56eSmrg if (info->use_glamor && info->directRenderingEnabled) { 1887d6c0b56eSmrg xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG, 1888d6c0b56eSmrg "Initializing Acceleration\n"); 1889d6c0b56eSmrg if (amdgpu_glamor_init(pScreen)) { 1890d6c0b56eSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1891d6c0b56eSmrg "Acceleration enabled\n"); 1892d6c0b56eSmrg } else { 1893d6c0b56eSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1894d6c0b56eSmrg "Acceleration initialization failed\n"); 1895d6c0b56eSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1896d6c0b56eSmrg "2D and 3D acceleration disabled\n"); 1897d6c0b56eSmrg info->use_glamor = FALSE; 1898d6c0b56eSmrg } 1899d6c0b56eSmrg } else if (info->directRenderingEnabled) { 1900d6c0b56eSmrg if (!amdgpu_pixmap_init(pScreen)) 1901d6c0b56eSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "3D acceleration disabled\n"); 1902d6c0b56eSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "2D acceleration disabled\n"); 1903d6c0b56eSmrg } else { 190424b90cf4Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "2D and 3D acceleration disabled\n"); 1905d6c0b56eSmrg } 1906d6c0b56eSmrg 1907d6c0b56eSmrg /* Init DPMS */ 1908d6c0b56eSmrg xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG, 1909d6c0b56eSmrg "Initializing DPMS\n"); 1910d6c0b56eSmrg xf86DPMSInit(pScreen, xf86DPMSSet, 0); 1911d6c0b56eSmrg 191224b90cf4Smrg if (!AMDGPUCursorInit_KMS(pScreen)) 191324b90cf4Smrg return FALSE; 1914d6c0b56eSmrg 1915d6c0b56eSmrg /* DGA setup */ 1916d6c0b56eSmrg#ifdef XFreeXDGA 1917d6c0b56eSmrg /* DGA is dangerous on kms as the base and framebuffer location may change: 1918d6c0b56eSmrg * http://lists.freedesktop.org/archives/xorg-devel/2009-September/002113.html 1919d6c0b56eSmrg */ 1920d6c0b56eSmrg /* xf86DiDGAInit(pScreen, info->LinearAddr + pScrn->fbOffset); */ 1921d6c0b56eSmrg#endif 192224b90cf4Smrg if (info->shadow_fb == FALSE && !pScreen->isGPU) { 1923d6c0b56eSmrg /* Init Xv */ 1924d6c0b56eSmrg xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG, 1925d6c0b56eSmrg "Initializing Xv\n"); 1926d6c0b56eSmrg AMDGPUInitVideo(pScreen); 1927d6c0b56eSmrg } 1928d6c0b56eSmrg 1929d6c0b56eSmrg if (info->shadow_fb == TRUE) { 1930d6c0b56eSmrg if (!shadowSetup(pScreen)) { 1931d6c0b56eSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1932d6c0b56eSmrg "Shadowfb initialization failed\n"); 1933d6c0b56eSmrg return FALSE; 1934d6c0b56eSmrg } 1935d6c0b56eSmrg } 1936d6c0b56eSmrg pScrn->pScreen = pScreen; 1937d6c0b56eSmrg 193824b90cf4Smrg if (!pScreen->isGPU) { 193911bf0794Smrg if (serverGeneration == 1 && bgNoneRoot && info->use_glamor) { 194011bf0794Smrg info->CreateWindow = pScreen->CreateWindow; 194111bf0794Smrg pScreen->CreateWindow = AMDGPUCreateWindow_oneshot; 194211bf0794Smrg } 194311bf0794Smrg info->WindowExposures = pScreen->WindowExposures; 194411bf0794Smrg pScreen->WindowExposures = AMDGPUWindowExposures_oneshot; 1945d6c0b56eSmrg } 1946d6c0b56eSmrg 1947d6c0b56eSmrg /* Provide SaveScreen & wrap BlockHandler and CloseScreen */ 1948d6c0b56eSmrg /* Wrap CloseScreen */ 1949d6c0b56eSmrg info->CloseScreen = pScreen->CloseScreen; 1950d6c0b56eSmrg pScreen->CloseScreen = AMDGPUCloseScreen_KMS; 1951d6c0b56eSmrg pScreen->SaveScreen = AMDGPUSaveScreen_KMS; 1952d6c0b56eSmrg info->BlockHandler = pScreen->BlockHandler; 195311bf0794Smrg pScreen->BlockHandler = AMDGPUBlockHandler_KMS; 1954d6c0b56eSmrg 1955d6c0b56eSmrg info->CreateScreenResources = pScreen->CreateScreenResources; 1956d6c0b56eSmrg pScreen->CreateScreenResources = AMDGPUCreateScreenResources_KMS; 1957d6c0b56eSmrg 1958d6c0b56eSmrg pScreen->StartPixmapTracking = PixmapStartDirtyTracking; 1959d6c0b56eSmrg pScreen->StopPixmapTracking = PixmapStopDirtyTracking; 1960504d986fSmrg#if HAS_SYNC_SHARED_PIXMAP 1961504d986fSmrg pScreen->SyncSharedPixmap = amdgpu_sync_shared_pixmap; 1962d6c0b56eSmrg#endif 1963d6c0b56eSmrg 1964d6c0b56eSmrg if (!xf86CrtcScreenInit(pScreen)) 1965d6c0b56eSmrg return FALSE; 1966d6c0b56eSmrg 1967d6c0b56eSmrg /* Wrap pointer motion to flip touch screen around */ 1968d6c0b56eSmrg// info->PointerMoved = pScrn->PointerMoved; 1969d6c0b56eSmrg// pScrn->PointerMoved = AMDGPUPointerMoved; 1970d6c0b56eSmrg 1971d6c0b56eSmrg if (!drmmode_setup_colormap(pScreen, pScrn)) 1972d6c0b56eSmrg return FALSE; 1973d6c0b56eSmrg 1974d6c0b56eSmrg /* Note unused options */ 1975d6c0b56eSmrg if (serverGeneration == 1) 1976d6c0b56eSmrg xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options); 1977d6c0b56eSmrg 1978d6c0b56eSmrg drmmode_init(pScrn, &info->drmmode); 1979d6c0b56eSmrg 1980d6c0b56eSmrg xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG, 1981d6c0b56eSmrg "AMDGPUScreenInit finished\n"); 1982d6c0b56eSmrg 1983d6c0b56eSmrg return TRUE; 1984d6c0b56eSmrg} 1985d6c0b56eSmrg 198624b90cf4SmrgBool AMDGPUEnterVT_KMS(ScrnInfoPtr pScrn) 1987d6c0b56eSmrg{ 1988d6c0b56eSmrg AMDGPUInfoPtr info = AMDGPUPTR(pScrn); 1989d6c0b56eSmrg 1990d6c0b56eSmrg xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG, 1991d6c0b56eSmrg "AMDGPUEnterVT_KMS\n"); 1992d6c0b56eSmrg 1993d6c0b56eSmrg amdgpu_set_drm_master(pScrn); 1994d6c0b56eSmrg 199524b90cf4Smrg if (info->shadow_fb) { 199624b90cf4Smrg int pitch; 199724b90cf4Smrg struct amdgpu_buffer *front_buffer = 199824b90cf4Smrg amdgpu_alloc_pixmap_bo(pScrn, pScrn->virtualX, 199924b90cf4Smrg pScrn->virtualY, pScrn->depth, 200024b90cf4Smrg AMDGPU_CREATE_PIXMAP_LINEAR, 200124b90cf4Smrg pScrn->bitsPerPixel, 200224b90cf4Smrg &pitch); 200324b90cf4Smrg 200424b90cf4Smrg if (front_buffer) { 200524b90cf4Smrg if (amdgpu_bo_map(pScrn, front_buffer) == 0) { 200624b90cf4Smrg memset(front_buffer->cpu_ptr, 0, pitch * pScrn->virtualY); 200724b90cf4Smrg amdgpu_bo_unref(&info->front_buffer); 200824b90cf4Smrg info->front_buffer = front_buffer; 200924b90cf4Smrg } else { 201024b90cf4Smrg amdgpu_bo_unref(&front_buffer); 201124b90cf4Smrg front_buffer = NULL; 201224b90cf4Smrg } 201324b90cf4Smrg } 201424b90cf4Smrg 201524b90cf4Smrg if (!front_buffer) { 201624b90cf4Smrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 201724b90cf4Smrg "Failed to allocate new scanout BO after VT switch, " 201824b90cf4Smrg "other DRM masters may see screen contents\n"); 201924b90cf4Smrg } 202024b90cf4Smrg } 202124b90cf4Smrg 2022d6c0b56eSmrg pScrn->vtSema = TRUE; 2023d6c0b56eSmrg 2024d6c0b56eSmrg if (!drmmode_set_desired_modes(pScrn, &info->drmmode, TRUE)) 2025d6c0b56eSmrg return FALSE; 2026d6c0b56eSmrg 2027d6c0b56eSmrg return TRUE; 2028d6c0b56eSmrg} 2029d6c0b56eSmrg 203024b90cf4Smrgstatic void 203124b90cf4Smrgpixmap_unref_fb(void *value, XID id, void *cdata) 203224b90cf4Smrg{ 203324b90cf4Smrg PixmapPtr pixmap = value; 203424b90cf4Smrg AMDGPUEntPtr pAMDGPUEnt = cdata; 203524b90cf4Smrg struct drmmode_fb **fb_ptr = amdgpu_pixmap_get_fb_ptr(pixmap); 203624b90cf4Smrg 203724b90cf4Smrg if (fb_ptr) 203824b90cf4Smrg drmmode_fb_reference(pAMDGPUEnt->fd, fb_ptr, NULL); 203924b90cf4Smrg} 204024b90cf4Smrg 204124b90cf4Smrgvoid AMDGPULeaveVT_KMS(ScrnInfoPtr pScrn) 2042d6c0b56eSmrg{ 204324b90cf4Smrg AMDGPUInfoPtr info = AMDGPUPTR(pScrn); 204424b90cf4Smrg ScreenPtr pScreen = pScrn->pScreen; 2045d6c0b56eSmrg 2046d6c0b56eSmrg xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG, 2047d6c0b56eSmrg "AMDGPULeaveVT_KMS\n"); 2048d6c0b56eSmrg 204924b90cf4Smrg if (!info->shadow_fb) { 205024b90cf4Smrg AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(pScrn); 205124b90cf4Smrg xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); 205224b90cf4Smrg struct drmmode_scanout black_scanout = { .pixmap = NULL, .bo = NULL }; 205324b90cf4Smrg xf86CrtcPtr crtc; 205424b90cf4Smrg drmmode_crtc_private_ptr drmmode_crtc; 205524b90cf4Smrg unsigned w = 0, h = 0; 205624b90cf4Smrg int i; 205724b90cf4Smrg 205824b90cf4Smrg /* Compute maximum scanout dimensions of active CRTCs */ 205924b90cf4Smrg for (i = 0; i < xf86_config->num_crtc; i++) { 206024b90cf4Smrg crtc = xf86_config->crtc[i]; 206124b90cf4Smrg drmmode_crtc = crtc->driver_private; 206224b90cf4Smrg 206324b90cf4Smrg if (!drmmode_crtc->fb) 206424b90cf4Smrg continue; 206524b90cf4Smrg 206624b90cf4Smrg w = max(w, crtc->mode.HDisplay); 206724b90cf4Smrg h = max(h, crtc->mode.VDisplay); 206824b90cf4Smrg } 2069d6c0b56eSmrg 207024b90cf4Smrg /* Make all active CRTCs scan out from an all-black framebuffer */ 207124b90cf4Smrg if (w > 0 && h > 0) { 207224b90cf4Smrg if (drmmode_crtc_scanout_create(crtc, &black_scanout, w, h)) { 207324b90cf4Smrg struct drmmode_fb *black_fb = 207424b90cf4Smrg amdgpu_pixmap_get_fb(black_scanout.pixmap); 207524b90cf4Smrg 207624b90cf4Smrg amdgpu_pixmap_clear(black_scanout.pixmap); 207724b90cf4Smrg amdgpu_glamor_finish(pScrn); 207824b90cf4Smrg 207924b90cf4Smrg for (i = 0; i < xf86_config->num_crtc; i++) { 208024b90cf4Smrg crtc = xf86_config->crtc[i]; 208124b90cf4Smrg drmmode_crtc = crtc->driver_private; 208224b90cf4Smrg 208324b90cf4Smrg if (drmmode_crtc->fb) { 208424b90cf4Smrg if (black_fb) { 208524b90cf4Smrg drmmode_set_mode(crtc, black_fb, &crtc->mode, 0, 0); 208624b90cf4Smrg } else { 208724b90cf4Smrg drmModeSetCrtc(pAMDGPUEnt->fd, 208824b90cf4Smrg drmmode_crtc->mode_crtc->crtc_id, 0, 208924b90cf4Smrg 0, 0, NULL, 0, NULL); 209024b90cf4Smrg drmmode_fb_reference(pAMDGPUEnt->fd, 209124b90cf4Smrg &drmmode_crtc->fb, NULL); 209224b90cf4Smrg } 209324b90cf4Smrg 209424b90cf4Smrg if (pScrn->is_gpu) { 209524b90cf4Smrg if (drmmode_crtc->scanout[0].pixmap) 209624b90cf4Smrg pixmap_unref_fb(drmmode_crtc->scanout[0].pixmap, 209724b90cf4Smrg None, pAMDGPUEnt); 209824b90cf4Smrg if (drmmode_crtc->scanout[1].pixmap) 209924b90cf4Smrg pixmap_unref_fb(drmmode_crtc->scanout[1].pixmap, 210024b90cf4Smrg None, pAMDGPUEnt); 210124b90cf4Smrg } else { 210224b90cf4Smrg drmmode_crtc_scanout_free(drmmode_crtc); 210324b90cf4Smrg } 210424b90cf4Smrg } 210524b90cf4Smrg } 210624b90cf4Smrg } 210724b90cf4Smrg } 210824b90cf4Smrg 210924b90cf4Smrg xf86RotateFreeShadow(pScrn); 211024b90cf4Smrg drmmode_crtc_scanout_destroy(&info->drmmode, &black_scanout); 211124b90cf4Smrg 211224b90cf4Smrg /* Unreference FBs of all pixmaps. After this, the only FB remaining 211324b90cf4Smrg * should be the all-black one being scanned out by active CRTCs 211424b90cf4Smrg */ 211524b90cf4Smrg for (i = 0; i < currentMaxClients; i++) { 211624b90cf4Smrg if (i > 0 && 211724b90cf4Smrg (!clients[i] || clients[i]->clientState != ClientStateRunning)) 211824b90cf4Smrg continue; 211924b90cf4Smrg 212024b90cf4Smrg FindClientResourcesByType(clients[i], RT_PIXMAP, pixmap_unref_fb, 212124b90cf4Smrg pAMDGPUEnt); 212224b90cf4Smrg } 212324b90cf4Smrg 212424b90cf4Smrg pixmap_unref_fb(pScreen->GetScreenPixmap(pScreen), None, pAMDGPUEnt); 212524b90cf4Smrg } else { 212624b90cf4Smrg memset(info->front_buffer->cpu_ptr, 0, pScrn->virtualX * 212724b90cf4Smrg info->pixel_bytes * pScrn->virtualY); 212824b90cf4Smrg } 212924b90cf4Smrg 213024b90cf4Smrg TimerSet(NULL, 0, 1000, cleanup_black_fb, pScreen); 2131d6c0b56eSmrg 2132d6c0b56eSmrg xf86_hide_cursors(pScrn); 2133d6c0b56eSmrg 213424b90cf4Smrg amdgpu_drop_drm_master(pScrn); 213524b90cf4Smrg 2136d6c0b56eSmrg xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG, 2137d6c0b56eSmrg "Ok, leaving now...\n"); 2138d6c0b56eSmrg} 2139d6c0b56eSmrg 214024b90cf4SmrgBool AMDGPUSwitchMode_KMS(ScrnInfoPtr pScrn, DisplayModePtr mode) 2141d6c0b56eSmrg{ 2142d6c0b56eSmrg Bool ret; 2143d6c0b56eSmrg ret = xf86SetSingleMode(pScrn, mode, RR_Rotate_0); 2144d6c0b56eSmrg return ret; 2145d6c0b56eSmrg 2146d6c0b56eSmrg} 2147d6c0b56eSmrg 214824b90cf4Smrgvoid AMDGPUAdjustFrame_KMS(ScrnInfoPtr pScrn, int x, int y) 2149d6c0b56eSmrg{ 2150d6c0b56eSmrg AMDGPUInfoPtr info = AMDGPUPTR(pScrn); 2151d6c0b56eSmrg drmmode_adjust_frame(pScrn, &info->drmmode, x, y); 2152d6c0b56eSmrg return; 2153d6c0b56eSmrg} 2154d6c0b56eSmrg 2155d6c0b56eSmrgstatic Bool amdgpu_setup_kernel_mem(ScreenPtr pScreen) 2156d6c0b56eSmrg{ 2157d6c0b56eSmrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 2158d6c0b56eSmrg AMDGPUInfoPtr info = AMDGPUPTR(pScrn); 2159d6c0b56eSmrg xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); 2160d6c0b56eSmrg int cpp = info->pixel_bytes; 2161d6c0b56eSmrg int cursor_size; 2162d6c0b56eSmrg int c; 2163d6c0b56eSmrg 2164d6c0b56eSmrg cursor_size = info->cursor_w * info->cursor_h * 4; 2165d6c0b56eSmrg cursor_size = AMDGPU_ALIGN(cursor_size, AMDGPU_GPU_PAGE_SIZE); 2166d6c0b56eSmrg for (c = 0; c < xf86_config->num_crtc; c++) { 2167d6c0b56eSmrg /* cursor objects */ 2168d6c0b56eSmrg if (info->cursor_buffer[c] == NULL) { 2169d6c0b56eSmrg if (info->gbm) { 2170d6c0b56eSmrg info->cursor_buffer[c] = (struct amdgpu_buffer *)calloc(1, sizeof(struct amdgpu_buffer)); 2171d6c0b56eSmrg if (!info->cursor_buffer[c]) { 2172d6c0b56eSmrg return FALSE; 2173d6c0b56eSmrg } 2174d6c0b56eSmrg info->cursor_buffer[c]->ref_count = 1; 2175d6c0b56eSmrg info->cursor_buffer[c]->flags = AMDGPU_BO_FLAGS_GBM; 2176d6c0b56eSmrg 2177d6c0b56eSmrg info->cursor_buffer[c]->bo.gbm = gbm_bo_create(info->gbm, 2178d6c0b56eSmrg info->cursor_w, 2179d6c0b56eSmrg info->cursor_h, 2180d6c0b56eSmrg GBM_FORMAT_ARGB8888, 2181d6c0b56eSmrg GBM_BO_USE_CURSOR | GBM_BO_USE_WRITE); 2182d6c0b56eSmrg if (!info->cursor_buffer[c]->bo.gbm) { 2183d6c0b56eSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 2184d6c0b56eSmrg "Failed to allocate cursor buffer memory\n"); 2185d6c0b56eSmrg free(info->cursor_buffer[c]); 2186d6c0b56eSmrg return FALSE; 2187d6c0b56eSmrg } 2188d6c0b56eSmrg } else { 2189d6c0b56eSmrg AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(pScrn); 2190d6c0b56eSmrg info->cursor_buffer[c] = amdgpu_bo_open(pAMDGPUEnt->pDev, 2191d6c0b56eSmrg cursor_size, 2192d6c0b56eSmrg 0, 2193d6c0b56eSmrg AMDGPU_GEM_DOMAIN_VRAM); 2194d6c0b56eSmrg if (!(info->cursor_buffer[c])) { 2195d6c0b56eSmrg ErrorF("Failed to allocate cursor buffer memory\n"); 2196d6c0b56eSmrg return FALSE; 2197d6c0b56eSmrg } 2198d6c0b56eSmrg 2199d6c0b56eSmrg if (amdgpu_bo_cpu_map(info->cursor_buffer[c]->bo.amdgpu, 2200d6c0b56eSmrg &info->cursor_buffer[c]->cpu_ptr)) { 2201d6c0b56eSmrg ErrorF("Failed to map cursor buffer memory\n"); 2202d6c0b56eSmrg } 2203d6c0b56eSmrg } 2204d6c0b56eSmrg 2205d6c0b56eSmrg drmmode_set_cursor(pScrn, &info->drmmode, c, 2206d6c0b56eSmrg info->cursor_buffer[c]); 2207d6c0b56eSmrg } 2208d6c0b56eSmrg } 2209d6c0b56eSmrg 2210d6c0b56eSmrg if (info->front_buffer == NULL) { 2211d6c0b56eSmrg int pitch; 2212d6c0b56eSmrg int hint = 0; 2213d6c0b56eSmrg 2214d6c0b56eSmrg if (info->shadow_primary) 2215d6c0b56eSmrg hint = AMDGPU_CREATE_PIXMAP_LINEAR | AMDGPU_CREATE_PIXMAP_GTT; 2216d6c0b56eSmrg else if (!info->use_glamor) 2217d6c0b56eSmrg hint = AMDGPU_CREATE_PIXMAP_LINEAR; 2218d6c0b56eSmrg 2219d6c0b56eSmrg info->front_buffer = 2220d6c0b56eSmrg amdgpu_alloc_pixmap_bo(pScrn, pScrn->virtualX, 2221d6c0b56eSmrg pScrn->virtualY, pScrn->depth, 2222d6c0b56eSmrg hint, pScrn->bitsPerPixel, 2223d6c0b56eSmrg &pitch); 2224d6c0b56eSmrg if (!(info->front_buffer)) { 2225d6c0b56eSmrg ErrorF("Failed to allocate front buffer memory\n"); 2226d6c0b56eSmrg return FALSE; 2227d6c0b56eSmrg } 2228d6c0b56eSmrg 2229d6c0b56eSmrg if (!info->use_glamor && 2230d6c0b56eSmrg amdgpu_bo_map(pScrn, info->front_buffer) != 0) { 2231d6c0b56eSmrg ErrorF("Failed to map front buffer memory\n"); 2232d6c0b56eSmrg return FALSE; 2233d6c0b56eSmrg } 2234d6c0b56eSmrg 2235d6c0b56eSmrg pScrn->displayWidth = pitch / cpp; 2236d6c0b56eSmrg } 2237d6c0b56eSmrg 2238d6c0b56eSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Front buffer pitch: %d bytes\n", 2239d6c0b56eSmrg pScrn->displayWidth * cpp); 2240d6c0b56eSmrg return TRUE; 2241d6c0b56eSmrg} 2242d6c0b56eSmrg 2243d6c0b56eSmrg/* Used to disallow modes that are not supported by the hardware */ 224424b90cf4SmrgModeStatus AMDGPUValidMode(ScrnInfoPtr pScrn, DisplayModePtr mode, 2245d6c0b56eSmrg Bool verbose, int flag) 2246d6c0b56eSmrg{ 2247d6c0b56eSmrg /* There are problems with double scan mode at high clocks 2248d6c0b56eSmrg * They're likely related PLL and display buffer settings. 2249d6c0b56eSmrg * Disable these modes for now. 2250d6c0b56eSmrg */ 2251d6c0b56eSmrg if (mode->Flags & V_DBLSCAN) { 2252d6c0b56eSmrg if ((mode->CrtcHDisplay >= 1024) || (mode->CrtcVDisplay >= 768)) 2253d6c0b56eSmrg return MODE_CLOCK_RANGE; 2254d6c0b56eSmrg } 2255d6c0b56eSmrg return MODE_OK; 2256d6c0b56eSmrg} 2257