1/* 2 * Copyright 2012 Advanced Micro Devices, Inc. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included in 12 * all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 * OTHER DEALINGS IN THE SOFTWARE. 21 */ 22 23#ifdef HAVE_CONFIG_H 24# include "config.h" 25#endif 26 27#include "radeon.h" 28#include "radeon_glamor.h" 29#include "radeon_bo_gem.h" 30 31 32#ifdef USE_GLAMOR 33 34static uint32_t 35radeon_get_gbm_format(int depth, int bitsPerPixel) 36{ 37 switch (depth) { 38#ifdef GBM_FORMAT_R8 39 case 8: 40 return GBM_FORMAT_R8; 41#endif 42 case 15: 43 return GBM_FORMAT_ARGB1555; 44 case 16: 45 return GBM_FORMAT_RGB565; 46 case 32: 47 return GBM_FORMAT_ARGB8888; 48 case 30: 49 return GBM_FORMAT_XRGB2101010; 50 case 24: 51 if (bitsPerPixel == 32) 52 return GBM_FORMAT_XRGB8888; 53 /* fall through */ 54 default: 55 ErrorF("%s: Unsupported depth/bpp %d/%d\n", __func__, depth, 56 bitsPerPixel); 57 return ~0U; 58 } 59} 60 61#endif /* USE_GLAMOR */ 62 63 64static const unsigned MicroBlockTable[5][3][2] = { 65 /*linear tiled square-tiled */ 66 {{32, 1}, {8, 4}, {0, 0}}, /* 8 bits per pixel */ 67 {{16, 1}, {8, 2}, {4, 4}}, /* 16 bits per pixel */ 68 {{ 8, 1}, {4, 2}, {0, 0}}, /* 32 bits per pixel */ 69 {{ 4, 1}, {0, 0}, {2, 2}}, /* 64 bits per pixel */ 70 {{ 2, 1}, {0, 0}, {0, 0}} /* 128 bits per pixel */ 71}; 72 73/* Return true if macrotiling can be enabled */ 74static Bool RADEONMacroSwitch(int width, int height, int bpp, 75 uint32_t flags, Bool rv350_mode) 76{ 77 unsigned tilew, tileh, microtiled, logbpp; 78 79 logbpp = RADEONLog2(bpp / 8); 80 if (logbpp > 4) 81 return 0; 82 83 microtiled = !!(flags & RADEON_TILING_MICRO); 84 tilew = MicroBlockTable[logbpp][microtiled][0] * 8; 85 tileh = MicroBlockTable[logbpp][microtiled][1] * 8; 86 87 /* See TX_FILTER1_n.MACRO_SWITCH. */ 88 if (rv350_mode) { 89 return width >= tilew && height >= tileh; 90 } else { 91 return width > tilew && height > tileh; 92 } 93} 94 95static unsigned eg_tile_split_opp(unsigned tile_split) 96{ 97 switch (tile_split) { 98 case 0: tile_split = 64; break; 99 case 1: tile_split = 128; break; 100 case 2: tile_split = 256; break; 101 case 3: tile_split = 512; break; 102 default: 103 case 4: tile_split = 1024; break; 104 case 5: tile_split = 2048; break; 105 case 6: tile_split = 4096; break; 106 } 107 return tile_split; 108} 109 110Bool 111radeon_surface_initialize(RADEONInfoPtr info, struct radeon_surface *surface, 112 int width, int height, int cpp, uint32_t tiling_flags, 113 int usage_hint) 114{ 115 memset(surface, 0, sizeof(struct radeon_surface)); 116 117 surface->npix_x = width; 118 /* need to align height to 8 for old kernel */ 119 surface->npix_y = RADEON_ALIGN(height, 8); 120 surface->npix_z = 1; 121 surface->blk_w = 1; 122 surface->blk_h = 1; 123 surface->blk_d = 1; 124 surface->array_size = 1; 125 surface->last_level = 0; 126 surface->bpe = cpp; 127 surface->nsamples = 1; 128 if (height < 128) { 129 /* disable 2d tiling for small surface to work around 130 * the fact that ddx align height to 8 pixel for old 131 * obscure reason i can't remember 132 */ 133 tiling_flags &= ~RADEON_TILING_MACRO; 134 } 135 136 surface->flags = RADEON_SURF_SCANOUT | RADEON_SURF_HAS_TILE_MODE_INDEX | 137 RADEON_SURF_SET(RADEON_SURF_TYPE_2D, TYPE); 138 139 if (usage_hint & RADEON_CREATE_PIXMAP_SZBUFFER) { 140 surface->flags |= RADEON_SURF_ZBUFFER; 141 surface->flags |= RADEON_SURF_SBUFFER; 142 } 143 144 if ((tiling_flags & RADEON_TILING_MACRO)) { 145 surface->flags = RADEON_SURF_CLR(surface->flags, MODE); 146 surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE); 147 } else if ((tiling_flags & RADEON_TILING_MICRO)) { 148 surface->flags = RADEON_SURF_CLR(surface->flags, MODE); 149 surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE); 150 } else 151 surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_LINEAR, MODE); 152 153 if (info->ChipFamily >= CHIP_FAMILY_CEDAR) { 154 surface->bankw = (tiling_flags >> RADEON_TILING_EG_BANKW_SHIFT) & 155 RADEON_TILING_EG_BANKW_MASK; 156 surface->bankh = (tiling_flags >> RADEON_TILING_EG_BANKH_SHIFT) & 157 RADEON_TILING_EG_BANKH_MASK; 158 surface->tile_split = eg_tile_split_opp((tiling_flags >> RADEON_TILING_EG_TILE_SPLIT_SHIFT) & 159 RADEON_TILING_EG_TILE_SPLIT_MASK); 160 if (surface->flags & RADEON_SURF_SBUFFER) { 161 surface->stencil_tile_split = 162 (tiling_flags >> RADEON_TILING_EG_STENCIL_TILE_SPLIT_SHIFT) & 163 RADEON_TILING_EG_STENCIL_TILE_SPLIT_MASK; 164 } 165 surface->mtilea = (tiling_flags >> RADEON_TILING_EG_MACRO_TILE_ASPECT_SHIFT) & 166 RADEON_TILING_EG_MACRO_TILE_ASPECT_MASK; 167 } 168 169 if (radeon_surface_best(info->surf_man, surface)) 170 return FALSE; 171 172 if (radeon_surface_init(info->surf_man, surface)) 173 return FALSE; 174 175 return TRUE; 176} 177 178/* Calculate appropriate tiling and pitch for a pixmap and allocate a BO that 179 * can hold it. 180 */ 181struct radeon_buffer * 182radeon_alloc_pixmap_bo(ScrnInfoPtr pScrn, int width, int height, int depth, 183 int usage_hint, int bitsPerPixel, int *new_pitch, 184 struct radeon_surface *new_surface, uint32_t *new_tiling) 185{ 186 RADEONInfoPtr info = RADEONPTR(pScrn); 187 int pitch, base_align; 188 uint32_t size, heighta; 189 int cpp = bitsPerPixel / 8; 190 uint32_t tiling = 0, flags = 0; 191 struct radeon_surface surface; 192 struct radeon_buffer *bo; 193 int domain = RADEON_GEM_DOMAIN_VRAM; 194 195#ifdef USE_GLAMOR 196 if (info->use_glamor && 197 !(usage_hint == CREATE_PIXMAP_USAGE_BACKING_PIXMAP && 198 info->shadow_primary)) { 199 uint32_t bo_use = GBM_BO_USE_RENDERING; 200 uint32_t gbm_format = radeon_get_gbm_format(depth, bitsPerPixel); 201 202 if (gbm_format == ~0U) 203 return NULL; 204 205 bo = calloc(1, sizeof(struct radeon_buffer)); 206 if (!bo) 207 return NULL; 208 209 bo->ref_count = 1; 210 211 if (bitsPerPixel == pScrn->bitsPerPixel) 212 bo_use |= GBM_BO_USE_SCANOUT; 213 214#ifdef GBM_BO_USE_LINEAR 215 if ((usage_hint == CREATE_PIXMAP_USAGE_BACKING_PIXMAP && 216 info->shadow_primary) || 217 (usage_hint & 0xffff) == CREATE_PIXMAP_USAGE_SHARED) 218 bo_use |= GBM_BO_USE_LINEAR; 219#endif 220 221 bo->bo.gbm = gbm_bo_create(info->gbm, width, height, gbm_format, bo_use); 222 if (!bo->bo.gbm) { 223 free(bo); 224 return NULL; 225 } 226 227 bo->flags |= RADEON_BO_FLAGS_GBM; 228 229 if (new_pitch) 230 *new_pitch = gbm_bo_get_stride(bo->bo.gbm); 231 232 return bo; 233 } 234#endif 235 236 if (usage_hint) { 237 if (info->allowColorTiling) { 238 if (usage_hint & RADEON_CREATE_PIXMAP_TILING_MACRO) 239 tiling |= RADEON_TILING_MACRO; 240 if (usage_hint & RADEON_CREATE_PIXMAP_TILING_MICRO) 241 tiling |= RADEON_TILING_MICRO; 242 } 243 if (usage_hint & RADEON_CREATE_PIXMAP_DEPTH) 244 tiling |= RADEON_TILING_MACRO | RADEON_TILING_MICRO; 245 246 if ((usage_hint == CREATE_PIXMAP_USAGE_BACKING_PIXMAP && 247 info->shadow_primary) || 248 (usage_hint & 0xffff) == CREATE_PIXMAP_USAGE_SHARED) { 249 tiling = 0; 250 domain = RADEON_GEM_DOMAIN_GTT; 251 } 252 } 253 254 /* Small pixmaps must not be macrotiled on R300, hw cannot sample them 255 * correctly because samplers automatically switch to macrolinear. */ 256 if (info->ChipFamily >= CHIP_FAMILY_R300 && 257 info->ChipFamily <= CHIP_FAMILY_RS740 && 258 (tiling & RADEON_TILING_MACRO) && 259 !RADEONMacroSwitch(width, height, bitsPerPixel, tiling, 260 info->ChipFamily >= CHIP_FAMILY_RV350)) { 261 tiling &= ~RADEON_TILING_MACRO; 262 } 263 264 heighta = RADEON_ALIGN(height, drmmode_get_height_align(pScrn, tiling)); 265 pitch = RADEON_ALIGN(width, drmmode_get_pitch_align(pScrn, cpp, tiling)) * cpp; 266 base_align = drmmode_get_base_align(pScrn, cpp, tiling); 267 size = RADEON_ALIGN(heighta * pitch, RADEON_GPU_PAGE_SIZE); 268 269 if (width && info->surf_man) { 270 if (!radeon_surface_initialize(info, &surface, width, height, cpp, 271 tiling, usage_hint)) 272 return NULL; 273 274 size = surface.bo_size; 275 base_align = surface.bo_alignment; 276 pitch = surface.level[0].pitch_bytes; 277 tiling = 0; 278 switch (surface.level[0].mode) { 279 case RADEON_SURF_MODE_2D: 280 tiling |= RADEON_TILING_MACRO; 281 tiling |= surface.bankw << RADEON_TILING_EG_BANKW_SHIFT; 282 tiling |= surface.bankh << RADEON_TILING_EG_BANKH_SHIFT; 283 tiling |= surface.mtilea << RADEON_TILING_EG_MACRO_TILE_ASPECT_SHIFT; 284 if (surface.tile_split) 285 tiling |= eg_tile_split(surface.tile_split) << RADEON_TILING_EG_TILE_SPLIT_SHIFT; 286 if (surface.flags & RADEON_SURF_SBUFFER) 287 tiling |= eg_tile_split(surface.stencil_tile_split) << RADEON_TILING_EG_STENCIL_TILE_SPLIT_SHIFT; 288 break; 289 case RADEON_SURF_MODE_1D: 290 tiling |= RADEON_TILING_MICRO; 291 break; 292 default: 293 break; 294 } 295 296 if (new_surface) 297 *new_surface = surface; 298 } 299 300 if (tiling) 301 flags |= RADEON_GEM_NO_CPU_ACCESS; 302 303 bo = calloc(1, sizeof(struct radeon_buffer)); 304 if (!bo) 305 return NULL; 306 307 bo->ref_count = 1; 308 bo->bo.radeon = radeon_bo_open(info->bufmgr, 0, size, base_align, 309 domain, flags); 310 311 if (bo->bo.radeon && tiling && radeon_bo_set_tiling(bo->bo.radeon, tiling, pitch) == 0) 312 *new_tiling = tiling; 313 314 *new_pitch = pitch; 315 return bo; 316} 317 318 319/* Flush and wait for the BO to become idle */ 320void 321radeon_finish(ScrnInfoPtr scrn, struct radeon_buffer *bo) 322{ 323 RADEONInfoPtr info = RADEONPTR(scrn); 324 325 if (info->use_glamor) { 326 radeon_glamor_finish(scrn); 327 return; 328 } 329 330 radeon_cs_flush_indirect(scrn); 331 radeon_bo_wait(bo->bo.radeon); 332} 333 334 335/* Clear the pixmap contents to black */ 336void 337radeon_pixmap_clear(PixmapPtr pixmap) 338{ 339 ScreenPtr screen = pixmap->drawable.pScreen; 340 RADEONInfoPtr info = RADEONPTR(xf86ScreenToScrn(screen)); 341 GCPtr gc = GetScratchGC(pixmap->drawable.depth, screen); 342 Bool force = info->accel_state->force; 343 xRectangle rect; 344 345 info->accel_state->force = TRUE; 346 ValidateGC(&pixmap->drawable, gc); 347 rect.x = 0; 348 rect.y = 0; 349 rect.width = pixmap->drawable.width; 350 rect.height = pixmap->drawable.height; 351 gc->ops->PolyFillRect(&pixmap->drawable, gc, 1, &rect); 352 FreeScratchGC(gc); 353 info->accel_state->force = force; 354} 355 356/* Get GEM handle for the pixmap */ 357Bool radeon_get_pixmap_handle(PixmapPtr pixmap, uint32_t *handle) 358{ 359 struct radeon_buffer *bo = radeon_get_pixmap_bo(pixmap); 360#ifdef USE_GLAMOR 361 ScreenPtr screen = pixmap->drawable.pScreen; 362 ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 363 RADEONEntPtr pRADEONEnt = RADEONEntPriv(scrn); 364 RADEONInfoPtr info = RADEONPTR(scrn); 365#endif 366 367 if (bo && !(bo->flags & RADEON_BO_FLAGS_GBM)) { 368 *handle = bo->bo.radeon->handle; 369 return TRUE; 370 } 371 372#ifdef USE_GLAMOR 373 if (info->use_glamor) { 374 struct radeon_pixmap *priv = radeon_get_pixmap_private(pixmap); 375 CARD16 stride; 376 CARD32 size; 377 int fd, r; 378 379 if (!priv) { 380 priv = calloc(1, sizeof(*priv)); 381 radeon_set_pixmap_private(pixmap, priv); 382 } 383 384 if (priv->handle_valid) { 385 *handle = priv->handle; 386 return TRUE; 387 } 388 389 fd = glamor_fd_from_pixmap(screen, pixmap, &stride, &size); 390 if (fd < 0) 391 return FALSE; 392 393 r = drmPrimeFDToHandle(pRADEONEnt->fd, fd, &priv->handle); 394 close(fd); 395 if (r == 0) { 396 struct drm_radeon_gem_set_tiling args = { .handle = priv->handle }; 397 398 priv->handle_valid = TRUE; 399 *handle = priv->handle; 400 401 if (drmCommandWriteRead(pRADEONEnt->fd, 402 DRM_RADEON_GEM_GET_TILING, &args, 403 sizeof(args)) == 0) 404 priv->tiling_flags = args.tiling_flags; 405 406 return TRUE; 407 } 408 } 409#endif 410 411 return FALSE; 412} 413 414uint32_t radeon_get_pixmap_tiling_flags(PixmapPtr pPix) 415{ 416#ifdef USE_GLAMOR 417 RADEONInfoPtr info = RADEONPTR(xf86ScreenToScrn(pPix->drawable.pScreen)); 418 419 if (info->use_glamor) { 420 struct radeon_pixmap *priv = radeon_get_pixmap_private(pPix); 421 422 if (!priv || (!priv->bo && !priv->handle_valid)) { 423 uint32_t handle; 424 425 radeon_get_pixmap_handle(pPix, &handle); 426 priv = radeon_get_pixmap_private(pPix); 427 } 428 429 return priv ? priv->tiling_flags : 0; 430 } else 431#endif 432 { 433 struct radeon_exa_pixmap_priv *driver_priv; 434 driver_priv = exaGetPixmapDriverPrivate(pPix); 435 return driver_priv ? driver_priv->tiling_flags : 0; 436 } 437} 438 439 440Bool radeon_share_pixmap_backing(struct radeon_bo *bo, void **handle_p) 441{ 442 int handle; 443 444 if (radeon_gem_prime_share_bo(bo, &handle) != 0) 445 return FALSE; 446 447 *handle_p = (void *)(long)handle; 448 return TRUE; 449} 450 451Bool radeon_set_shared_pixmap_backing(PixmapPtr ppix, void *fd_handle, 452 struct radeon_surface *surface) 453{ 454 ScrnInfoPtr pScrn = xf86ScreenToScrn(ppix->drawable.pScreen); 455 RADEONInfoPtr info = RADEONPTR(pScrn); 456 struct radeon_buffer *bo; 457 int ihandle = (int)(long)fd_handle; 458 uint32_t size = ppix->devKind * ppix->drawable.height; 459 Bool ret = FALSE; 460 461 if (ihandle == -1) 462 return radeon_set_pixmap_bo(ppix, NULL); 463 464 bo = (struct radeon_buffer *)calloc(1, sizeof(struct radeon_buffer)); 465 if (!bo) 466 goto error; 467 468#ifdef USE_GLAMOR 469 if (info->use_glamor) { 470 struct gbm_import_fd_data data; 471 uint32_t bo_use = GBM_BO_USE_RENDERING; 472 473 data.format = radeon_get_gbm_format(ppix->drawable.depth, 474 ppix->drawable.bitsPerPixel); 475 if (data.format == ~0U) 476 goto error; 477 478 bo->ref_count = 1; 479 480 data.fd = ihandle; 481 data.width = ppix->drawable.width; 482 data.height = ppix->drawable.height; 483 data.stride = ppix->devKind; 484 485 if (ppix->drawable.bitsPerPixel == pScrn->bitsPerPixel) 486 bo_use |= GBM_BO_USE_SCANOUT; 487 488 bo->bo.gbm = gbm_bo_import(info->gbm, GBM_BO_IMPORT_FD, &data, bo_use); 489 if (!bo->bo.gbm) 490 goto error; 491 492 bo->flags |= RADEON_BO_FLAGS_GBM; 493 494 if (!radeon_glamor_create_textured_pixmap(ppix, bo)) { 495 radeon_buffer_unref(&bo); 496 return FALSE; 497 } 498 499 ret = radeon_set_pixmap_bo(ppix, bo); 500 /* radeon_set_pixmap_bo increments ref_count if it succeeds */ 501 radeon_buffer_unref(&bo); 502 return ret; 503 } 504#endif 505 506 bo->bo.radeon = radeon_gem_bo_open_prime(info->bufmgr, ihandle, size); 507 if (!bo->bo.radeon) 508 goto error; 509 510 bo->ref_count = 1; 511 ret = radeon_set_pixmap_bo(ppix, bo); 512 if (!ret) 513 goto error; 514 515 if (surface) { 516 struct radeon_exa_pixmap_priv *driver_priv; 517 uint32_t tiling_flags; 518 519 driver_priv = exaGetPixmapDriverPrivate(ppix); 520 tiling_flags = driver_priv->tiling_flags; 521 522 if (!radeon_surface_initialize(info, surface, ppix->drawable.width, 523 ppix->drawable.height, 524 ppix->drawable.bitsPerPixel / 8, 525 tiling_flags, 0)) { 526 ret = FALSE; 527 goto error; 528 } 529 530 /* we have to post hack the surface to reflect the actual size 531 of the shared pixmap */ 532 surface->level[0].pitch_bytes = ppix->devKind; 533 surface->level[0].nblk_x = ppix->devKind / surface->bpe; 534 } 535 536 error: 537 close(ihandle); 538 /* we have a reference from the alloc and one from set pixmap bo, 539 drop one */ 540 radeon_buffer_unref(&bo); 541 return ret; 542} 543