radeon_glamor.c revision de2362d3
1de2362d3Smrg/* 2de2362d3Smrg * Copyright © 2011 Intel Corporation. 3de2362d3Smrg * 2012 Advanced Micro Devices, Inc. 4de2362d3Smrg * 5de2362d3Smrg * Permission is hereby granted, free of charge, to any person 6de2362d3Smrg * obtaining a copy of this software and associated documentation 7de2362d3Smrg * files (the "Software"), to deal in the Software without 8de2362d3Smrg * restriction, including without limitation the rights to use, copy, 9de2362d3Smrg * modify, merge, publish, distribute, sublicense, and/or sell copies 10de2362d3Smrg * of the Software, and to permit persons to whom the Software is 11de2362d3Smrg * furnished to do so, subject to the following conditions: 12de2362d3Smrg * 13de2362d3Smrg * The above copyright notice and this permission notice (including 14de2362d3Smrg * the next paragraph) shall be included in all copies or substantial 15de2362d3Smrg * portions of the Software. 16de2362d3Smrg * 17de2362d3Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18de2362d3Smrg * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19de2362d3Smrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20de2362d3Smrg * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 21de2362d3Smrg * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 22de2362d3Smrg * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23de2362d3Smrg * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 24de2362d3Smrg * DEALINGS IN THE SOFTWARE. 25de2362d3Smrg */ 26de2362d3Smrg 27de2362d3Smrg#ifdef HAVE_CONFIG_H 28de2362d3Smrg#include "config.h" 29de2362d3Smrg#endif 30de2362d3Smrg 31de2362d3Smrg#include <xf86.h> 32de2362d3Smrg#define GLAMOR_FOR_XORG 1 33de2362d3Smrg#include <glamor.h> 34de2362d3Smrg 35de2362d3Smrg#include "radeon.h" 36de2362d3Smrg#include "radeon_bo_helper.h" 37de2362d3Smrg 38de2362d3Smrg#if HAS_DEVPRIVATEKEYREC 39de2362d3SmrgDevPrivateKeyRec glamor_pixmap_index; 40de2362d3Smrg#else 41de2362d3Smrgint glamor_pixmap_index; 42de2362d3Smrg#endif 43de2362d3Smrg 44de2362d3Smrgvoid 45de2362d3Smrgradeon_glamor_exchange_buffers(PixmapPtr src, 46de2362d3Smrg PixmapPtr dst) 47de2362d3Smrg{ 48de2362d3Smrg RADEONInfoPtr info = RADEONPTR(xf86ScreenToScrn(dst->drawable.pScreen)); 49de2362d3Smrg 50de2362d3Smrg if (!info->use_glamor) 51de2362d3Smrg return; 52de2362d3Smrg glamor_egl_exchange_buffers(src, dst); 53de2362d3Smrg} 54de2362d3Smrg 55de2362d3SmrgBool 56de2362d3Smrgradeon_glamor_create_screen_resources(ScreenPtr screen) 57de2362d3Smrg{ 58de2362d3Smrg ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 59de2362d3Smrg RADEONInfoPtr info = RADEONPTR(scrn); 60de2362d3Smrg 61de2362d3Smrg if (!info->use_glamor) 62de2362d3Smrg return TRUE; 63de2362d3Smrg 64de2362d3Smrg if (!glamor_glyphs_init(screen)) 65de2362d3Smrg return FALSE; 66de2362d3Smrg 67de2362d3Smrg if (!glamor_egl_create_textured_screen_ext(screen, 68de2362d3Smrg info->front_bo->handle, 69de2362d3Smrg scrn->displayWidth * 70de2362d3Smrg info->pixel_bytes, 71de2362d3Smrg NULL)) 72de2362d3Smrg return FALSE; 73de2362d3Smrg 74de2362d3Smrg return TRUE; 75de2362d3Smrg} 76de2362d3Smrg 77de2362d3Smrg 78de2362d3SmrgBool 79de2362d3Smrgradeon_glamor_pre_init(ScrnInfoPtr scrn) 80de2362d3Smrg{ 81de2362d3Smrg RADEONInfoPtr info = RADEONPTR(scrn); 82de2362d3Smrg pointer glamor_module; 83de2362d3Smrg CARD32 version; 84de2362d3Smrg const char *s; 85de2362d3Smrg 86de2362d3Smrg if (!info->dri2.available) 87de2362d3Smrg return FALSE; 88de2362d3Smrg 89de2362d3Smrg s = xf86GetOptValString(info->Options, OPTION_ACCELMETHOD); 90de2362d3Smrg if (s == NULL && info->ChipFamily < CHIP_FAMILY_TAHITI) 91de2362d3Smrg return FALSE; 92de2362d3Smrg 93de2362d3Smrg if (s && strcasecmp(s, "glamor") != 0) { 94de2362d3Smrg if (info->ChipFamily >= CHIP_FAMILY_TAHITI) 95de2362d3Smrg xf86DrvMsg(scrn->scrnIndex, X_WARNING, 96de2362d3Smrg "EXA not supported, using glamor\n"); 97de2362d3Smrg else 98de2362d3Smrg return FALSE; 99de2362d3Smrg } 100de2362d3Smrg 101de2362d3Smrg if (info->ChipFamily < CHIP_FAMILY_R300) { 102de2362d3Smrg xf86DrvMsg(scrn->scrnIndex, X_ERROR, 103de2362d3Smrg "glamor requires R300 or higher GPU, disabling.\n"); 104de2362d3Smrg return FALSE; 105de2362d3Smrg } 106de2362d3Smrg 107de2362d3Smrg if (info->ChipFamily < CHIP_FAMILY_RV515) { 108de2362d3Smrg xf86DrvMsg(scrn->scrnIndex, X_WARNING, 109de2362d3Smrg "glamor may not work (well) with GPUs < RV515.\n"); 110de2362d3Smrg } 111de2362d3Smrg 112de2362d3Smrg if (scrn->depth < 24) { 113de2362d3Smrg xf86DrvMsg(scrn->scrnIndex, s ? X_ERROR : X_WARNING, 114de2362d3Smrg "glamor requires depth >= 24, disabling.\n"); 115de2362d3Smrg return FALSE; 116de2362d3Smrg } 117de2362d3Smrg 118de2362d3Smrg#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1,15,0,0,0) 119de2362d3Smrg if (!xf86LoaderCheckSymbol("glamor_egl_init")) { 120de2362d3Smrg xf86DrvMsg(scrn->scrnIndex, s ? X_ERROR : X_WARNING, 121de2362d3Smrg "glamor requires Load \"glamoregl\" in " 122de2362d3Smrg "Section \"Module\", disabling.\n"); 123de2362d3Smrg return FALSE; 124de2362d3Smrg } 125de2362d3Smrg#endif 126de2362d3Smrg 127de2362d3Smrg /* Load glamor module */ 128de2362d3Smrg if ((glamor_module = xf86LoadSubModule(scrn, GLAMOR_EGL_MODULE_NAME))) { 129de2362d3Smrg version = xf86GetModuleVersion(glamor_module); 130de2362d3Smrg if (version < MODULE_VERSION_NUMERIC(0,3,1)) { 131de2362d3Smrg xf86DrvMsg(scrn->scrnIndex, X_ERROR, 132de2362d3Smrg "Incompatible glamor version, required >= 0.3.0.\n"); 133de2362d3Smrg return FALSE; 134de2362d3Smrg } else { 135de2362d3Smrg if (glamor_egl_init(scrn, info->dri2.drm_fd)) { 136de2362d3Smrg xf86DrvMsg(scrn->scrnIndex, X_INFO, 137de2362d3Smrg "glamor detected, initialising EGL layer.\n"); 138de2362d3Smrg } else { 139de2362d3Smrg xf86DrvMsg(scrn->scrnIndex, X_ERROR, 140de2362d3Smrg "glamor detected, failed to initialize EGL.\n"); 141de2362d3Smrg return FALSE; 142de2362d3Smrg } 143de2362d3Smrg } 144de2362d3Smrg } else { 145de2362d3Smrg xf86DrvMsg(scrn->scrnIndex, X_ERROR, "glamor not available\n"); 146de2362d3Smrg return FALSE; 147de2362d3Smrg } 148de2362d3Smrg 149de2362d3Smrg info->use_glamor = TRUE; 150de2362d3Smrg 151de2362d3Smrg return TRUE; 152de2362d3Smrg} 153de2362d3Smrg 154de2362d3SmrgBool 155de2362d3Smrgradeon_glamor_create_textured_pixmap(PixmapPtr pixmap) 156de2362d3Smrg{ 157de2362d3Smrg ScrnInfoPtr scrn = xf86ScreenToScrn(pixmap->drawable.pScreen); 158de2362d3Smrg RADEONInfoPtr info = RADEONPTR(scrn); 159de2362d3Smrg struct radeon_pixmap *priv; 160de2362d3Smrg 161de2362d3Smrg if ((info->use_glamor) == 0) 162de2362d3Smrg return TRUE; 163de2362d3Smrg 164de2362d3Smrg priv = radeon_get_pixmap_private(pixmap); 165de2362d3Smrg if (!priv->stride) 166de2362d3Smrg priv->stride = pixmap->devKind; 167de2362d3Smrg if (glamor_egl_create_textured_pixmap(pixmap, priv->bo->handle, 168de2362d3Smrg priv->stride)) 169de2362d3Smrg return TRUE; 170de2362d3Smrg else 171de2362d3Smrg return FALSE; 172de2362d3Smrg} 173de2362d3Smrg 174de2362d3SmrgBool radeon_glamor_pixmap_is_offscreen(PixmapPtr pixmap) 175de2362d3Smrg{ 176de2362d3Smrg struct radeon_pixmap *priv = radeon_get_pixmap_private(pixmap); 177de2362d3Smrg return priv && priv->bo; 178de2362d3Smrg} 179de2362d3Smrg 180de2362d3Smrg#ifndef CREATE_PIXMAP_USAGE_SHARED 181de2362d3Smrg#define CREATE_PIXMAP_USAGE_SHARED RADEON_CREATE_PIXMAP_DRI2 182de2362d3Smrg#endif 183de2362d3Smrg 184de2362d3Smrg#define RADEON_CREATE_PIXMAP_SHARED(usage) \ 185de2362d3Smrg (((usage) & ~RADEON_CREATE_PIXMAP_TILING_FLAGS) == RADEON_CREATE_PIXMAP_DRI2 || \ 186de2362d3Smrg (usage) == CREATE_PIXMAP_USAGE_SHARED) 187de2362d3Smrg 188de2362d3Smrgstatic PixmapPtr 189de2362d3Smrgradeon_glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth, 190de2362d3Smrg unsigned usage) 191de2362d3Smrg{ 192de2362d3Smrg ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 193de2362d3Smrg struct radeon_pixmap *priv; 194de2362d3Smrg PixmapPtr pixmap, new_pixmap = NULL; 195de2362d3Smrg 196de2362d3Smrg if (!RADEON_CREATE_PIXMAP_SHARED(usage)) { 197de2362d3Smrg pixmap = glamor_create_pixmap(screen, w, h, depth, usage); 198de2362d3Smrg if (pixmap) 199de2362d3Smrg return pixmap; 200de2362d3Smrg } 201de2362d3Smrg 202de2362d3Smrg if (w > 32767 || h > 32767) 203de2362d3Smrg return NullPixmap; 204de2362d3Smrg 205de2362d3Smrg if (depth == 1) 206de2362d3Smrg return fbCreatePixmap(screen, w, h, depth, usage); 207de2362d3Smrg 208de2362d3Smrg if (usage == CREATE_PIXMAP_USAGE_GLYPH_PICTURE && w <= 32 && h <= 32) 209de2362d3Smrg return fbCreatePixmap(screen, w, h, depth, usage); 210de2362d3Smrg 211de2362d3Smrg pixmap = fbCreatePixmap(screen, 0, 0, depth, usage); 212de2362d3Smrg if (pixmap == NullPixmap) 213de2362d3Smrg return pixmap; 214de2362d3Smrg 215de2362d3Smrg if (w && h) { 216de2362d3Smrg priv = calloc(1, sizeof (struct radeon_pixmap)); 217de2362d3Smrg if (priv == NULL) 218de2362d3Smrg goto fallback_pixmap; 219de2362d3Smrg 220de2362d3Smrg priv->bo = radeon_alloc_pixmap_bo(scrn, w, h, depth, usage, 221de2362d3Smrg pixmap->drawable.bitsPerPixel, 222de2362d3Smrg &priv->stride, 223de2362d3Smrg &priv->surface, 224de2362d3Smrg &priv->tiling_flags); 225de2362d3Smrg if (!priv->bo) 226de2362d3Smrg goto fallback_priv; 227de2362d3Smrg 228de2362d3Smrg radeon_set_pixmap_private(pixmap, priv); 229de2362d3Smrg 230de2362d3Smrg screen->ModifyPixmapHeader(pixmap, w, h, 0, 0, priv->stride, NULL); 231de2362d3Smrg 232de2362d3Smrg if (!radeon_glamor_create_textured_pixmap(pixmap)) 233de2362d3Smrg goto fallback_glamor; 234de2362d3Smrg } 235de2362d3Smrg 236de2362d3Smrg return pixmap; 237de2362d3Smrg 238de2362d3Smrgfallback_glamor: 239de2362d3Smrg if (RADEON_CREATE_PIXMAP_SHARED(usage)) { 240de2362d3Smrg /* XXX need further work to handle the DRI2 failure case. 241de2362d3Smrg * Glamor don't know how to handle a BO only pixmap. Put 242de2362d3Smrg * a warning indicator here. 243de2362d3Smrg */ 244de2362d3Smrg xf86DrvMsg(scrn->scrnIndex, X_WARNING, 245de2362d3Smrg "Failed to create textured DRI2/PRIME pixmap."); 246de2362d3Smrg return pixmap; 247de2362d3Smrg } 248de2362d3Smrg /* Create textured pixmap failed means glamor failed to 249de2362d3Smrg * create a texture from current BO for some reasons. We turn 250de2362d3Smrg * to create a new glamor pixmap and clean up current one. 251de2362d3Smrg * One thing need to be noted, this new pixmap doesn't 252de2362d3Smrg * has a priv and bo attached to it. It's glamor's responsbility 253de2362d3Smrg * to take care of it. Glamor will mark this new pixmap as a 254de2362d3Smrg * texture only pixmap and will never fallback to DDX layer 255de2362d3Smrg * afterwards. 256de2362d3Smrg */ 257de2362d3Smrg new_pixmap = glamor_create_pixmap(screen, w, h, depth, usage); 258de2362d3Smrg radeon_bo_unref(priv->bo); 259de2362d3Smrgfallback_priv: 260de2362d3Smrg free(priv); 261de2362d3Smrgfallback_pixmap: 262de2362d3Smrg fbDestroyPixmap(pixmap); 263de2362d3Smrg if (new_pixmap) 264de2362d3Smrg return new_pixmap; 265de2362d3Smrg else 266de2362d3Smrg return fbCreatePixmap(screen, w, h, depth, usage); 267de2362d3Smrg} 268de2362d3Smrg 269de2362d3Smrgstatic Bool radeon_glamor_destroy_pixmap(PixmapPtr pixmap) 270de2362d3Smrg{ 271de2362d3Smrg if (pixmap->refcnt == 1) { 272de2362d3Smrg glamor_egl_destroy_textured_pixmap(pixmap); 273de2362d3Smrg radeon_set_pixmap_bo(pixmap, NULL); 274de2362d3Smrg } 275de2362d3Smrg fbDestroyPixmap(pixmap); 276de2362d3Smrg return TRUE; 277de2362d3Smrg} 278de2362d3Smrg 279de2362d3Smrg#ifdef RADEON_PIXMAP_SHARING 280de2362d3Smrg 281de2362d3Smrgstatic Bool 282de2362d3Smrgradeon_glamor_share_pixmap_backing(PixmapPtr pixmap, ScreenPtr slave, 283de2362d3Smrg void **handle_p) 284de2362d3Smrg{ 285de2362d3Smrg struct radeon_pixmap *priv = radeon_get_pixmap_private(pixmap); 286de2362d3Smrg 287de2362d3Smrg if (!priv) 288de2362d3Smrg return FALSE; 289de2362d3Smrg 290de2362d3Smrg return radeon_share_pixmap_backing(priv->bo, handle_p); 291de2362d3Smrg} 292de2362d3Smrg 293de2362d3Smrgstatic Bool 294de2362d3Smrgradeon_glamor_set_shared_pixmap_backing(PixmapPtr pixmap, void *handle) 295de2362d3Smrg{ 296de2362d3Smrg ScreenPtr screen = pixmap->drawable.pScreen; 297de2362d3Smrg ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 298de2362d3Smrg struct radeon_surface surface; 299de2362d3Smrg struct radeon_pixmap *priv; 300de2362d3Smrg 301de2362d3Smrg if (!radeon_set_shared_pixmap_backing(pixmap, handle, &surface)) 302de2362d3Smrg return FALSE; 303de2362d3Smrg 304de2362d3Smrg priv = radeon_get_pixmap_private(pixmap); 305de2362d3Smrg priv->stride = pixmap->devKind; 306de2362d3Smrg priv->surface = surface; 307de2362d3Smrg priv->tiling_flags = 0; 308de2362d3Smrg 309de2362d3Smrg if (!radeon_glamor_create_textured_pixmap(pixmap)) { 310de2362d3Smrg xf86DrvMsg(scrn->scrnIndex, X_ERROR, 311de2362d3Smrg "Failed to get PRIME drawable for glamor pixmap.\n"); 312de2362d3Smrg return FALSE; 313de2362d3Smrg } 314de2362d3Smrg 315de2362d3Smrg screen->ModifyPixmapHeader(pixmap, 316de2362d3Smrg pixmap->drawable.width, 317de2362d3Smrg pixmap->drawable.height, 318de2362d3Smrg 0, 0, 319de2362d3Smrg priv->stride, 320de2362d3Smrg NULL); 321de2362d3Smrg 322de2362d3Smrg return TRUE; 323de2362d3Smrg} 324de2362d3Smrg 325de2362d3Smrg#endif /* RADEON_PIXMAP_SHARING */ 326de2362d3Smrg 327de2362d3SmrgBool 328de2362d3Smrgradeon_glamor_init(ScreenPtr screen) 329de2362d3Smrg{ 330de2362d3Smrg ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 331de2362d3Smrg 332de2362d3Smrg if (!glamor_init(screen, GLAMOR_INVERTED_Y_AXIS | GLAMOR_USE_EGL_SCREEN | 333de2362d3Smrg#ifdef GLAMOR_NO_DRI3 334de2362d3Smrg GLAMOR_NO_DRI3 | 335de2362d3Smrg#endif 336de2362d3Smrg GLAMOR_USE_SCREEN | GLAMOR_USE_PICTURE_SCREEN)) { 337de2362d3Smrg xf86DrvMsg(scrn->scrnIndex, X_ERROR, 338de2362d3Smrg "Failed to initialize glamor.\n"); 339de2362d3Smrg return FALSE; 340de2362d3Smrg } 341de2362d3Smrg 342de2362d3Smrg if (!glamor_egl_init_textured_pixmap(screen)) { 343de2362d3Smrg xf86DrvMsg(scrn->scrnIndex, X_ERROR, 344de2362d3Smrg "Failed to initialize textured pixmap of screen for glamor.\n"); 345de2362d3Smrg return FALSE; 346de2362d3Smrg } 347de2362d3Smrg 348de2362d3Smrg#if HAS_DIXREGISTERPRIVATEKEY 349de2362d3Smrg if (!dixRegisterPrivateKey(&glamor_pixmap_index, PRIVATE_PIXMAP, 0)) 350de2362d3Smrg#else 351de2362d3Smrg if (!dixRequestPrivate(&glamor_pixmap_index, 0)) 352de2362d3Smrg#endif 353de2362d3Smrg return FALSE; 354de2362d3Smrg 355de2362d3Smrg screen->CreatePixmap = radeon_glamor_create_pixmap; 356de2362d3Smrg screen->DestroyPixmap = radeon_glamor_destroy_pixmap; 357de2362d3Smrg#ifdef RADEON_PIXMAP_SHARING 358de2362d3Smrg screen->SharePixmapBacking = radeon_glamor_share_pixmap_backing; 359de2362d3Smrg screen->SetSharedPixmapBacking = radeon_glamor_set_shared_pixmap_backing; 360de2362d3Smrg#endif 361de2362d3Smrg 362de2362d3Smrg xf86DrvMsg(scrn->scrnIndex, X_INFO, 363de2362d3Smrg "Use GLAMOR acceleration.\n"); 364de2362d3Smrg return TRUE; 365de2362d3Smrg} 366de2362d3Smrg 367de2362d3Smrgvoid 368de2362d3Smrgradeon_glamor_flush(ScrnInfoPtr pScrn) 369de2362d3Smrg{ 370de2362d3Smrg RADEONInfoPtr info = RADEONPTR(pScrn); 371de2362d3Smrg 372de2362d3Smrg if (info->use_glamor) 373de2362d3Smrg glamor_block_handler(pScrn->pScreen); 374de2362d3Smrg} 375de2362d3Smrg 376de2362d3SmrgXF86VideoAdaptorPtr radeon_glamor_xv_init(ScreenPtr pScreen, int num_adapt) 377de2362d3Smrg{ 378de2362d3Smrg return glamor_xv_init(pScreen, num_adapt); 379de2362d3Smrg} 380