static int radeon_drm_winsys_surface_init(struct radeon_winsys *rws, struct radeon_surface *surf) { struct radeon_drm_winsys *ws = (struct radeon_drm_winsys*)rws; return radeon_surface_init(ws->surf_man, surf); }
static cairo_surface_t * radeon_surface_create_internal (cairo_drm_device_t *device, cairo_format_t format, int width, int height) { radeon_surface_t *surface; cairo_status_t status; surface = malloc (sizeof (radeon_surface_t)); if (unlikely (surface == NULL)) return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); radeon_surface_init (surface, device, format, width, height); if (width && height) { surface->base.stride = cairo_format_stride_for_width (surface->base.format, width); surface->base.bo = radeon_bo_create (to_radeon_device (&device->base), surface->base.stride * height, RADEON_GEM_DOMAIN_GTT); if (unlikely (surface->base.bo == NULL)) { status = _cairo_drm_surface_finish (&surface->base); free (surface); return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); } } return &surface->base.base; }
static int radeon_winsys_surface_init(struct radeon_winsys *rws, const struct pipe_resource *tex, unsigned flags, unsigned bpe, enum radeon_surf_mode mode, struct radeon_surf *surf_ws) { struct radeon_drm_winsys *ws = (struct radeon_drm_winsys*)rws; struct radeon_surface surf_drm; int r; surf_winsys_to_drm(&surf_drm, tex, flags, bpe, mode, surf_ws); if (!(flags & (RADEON_SURF_IMPORTED | RADEON_SURF_FMASK))) { r = radeon_surface_best(ws->surf_man, &surf_drm); if (r) return r; } r = radeon_surface_init(ws->surf_man, &surf_drm); if (r) return r; surf_drm_to_winsys(ws, surf_ws, &surf_drm); return 0; }
Bool radeon_set_shared_pixmap_backing(PixmapPtr ppix, void *fd_handle, struct radeon_surface *surface) { ScrnInfoPtr pScrn = xf86ScreenToScrn(ppix->drawable.pScreen); RADEONInfoPtr info = RADEONPTR(pScrn); struct radeon_bo *bo; int ihandle = (int)(long)fd_handle; uint32_t size = ppix->devKind * ppix->drawable.height; bo = radeon_gem_bo_open_prime(info->bufmgr, ihandle, size); if (!bo) return FALSE; memset(surface, 0, sizeof(struct radeon_surface)); if (info->ChipFamily >= CHIP_FAMILY_R600 && info->surf_man) { surface->npix_x = ppix->drawable.width; surface->npix_y = ppix->drawable.height; surface->npix_z = 1; surface->blk_w = 1; surface->blk_h = 1; surface->blk_d = 1; surface->array_size = 1; surface->bpe = ppix->drawable.bitsPerPixel / 8; surface->nsamples = 1; /* we are requiring a recent enough libdrm version */ surface->flags |= RADEON_SURF_HAS_TILE_MODE_INDEX; surface->flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_2D, TYPE); surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_LINEAR, MODE); if (radeon_surface_best(info->surf_man, surface)) { return FALSE; } if (radeon_surface_init(info->surf_man, surface)) { return FALSE; } /* we have to post hack the surface to reflect the actual size of the shared pixmap */ surface->level[0].pitch_bytes = ppix->devKind; surface->level[0].nblk_x = ppix->devKind / surface->bpe; } radeon_set_pixmap_bo(ppix, bo); close(ihandle); /* we have a reference from the alloc and one from set pixmap bo, drop one */ radeon_bo_unref(bo); return TRUE; }
static cairo_surface_t * radeon_surface_create_for_name (cairo_drm_device_t *device, unsigned int name, cairo_format_t format, int width, int height, int stride) { radeon_surface_t *surface; cairo_status_t status; switch (format) { default: case CAIRO_FORMAT_INVALID: case CAIRO_FORMAT_A1: case CAIRO_FORMAT_RGB16_565: return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT)); case CAIRO_FORMAT_ARGB32: case CAIRO_FORMAT_RGB24: case CAIRO_FORMAT_A8: break; } if (stride < cairo_format_stride_for_width (format, width)) return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_STRIDE)); surface = malloc (sizeof (radeon_surface_t)); if (unlikely (surface == NULL)) return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); radeon_surface_init (surface, device, format, width, height); if (width && height) { surface->base.stride = stride; surface->base.bo = radeon_bo_create_for_name (to_radeon_device (&device->base), name); if (unlikely (surface->base.bo == NULL)) { status = _cairo_drm_surface_finish (&surface->base); free (surface); return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); } } return &surface->base.base; }
/* Calculate appropriate tiling and pitch for a pixmap and allocate a BO that * can hold it. */ struct radeon_bo* radeon_alloc_pixmap_bo(ScrnInfoPtr pScrn, int width, int height, int depth, int usage_hint, int bitsPerPixel, int *new_pitch, struct radeon_surface *new_surface, uint32_t *new_tiling) { RADEONInfoPtr info = RADEONPTR(pScrn); int pitch, base_align; uint32_t size, heighta; int cpp = bitsPerPixel / 8; uint32_t tiling = 0; struct radeon_surface surface; struct radeon_bo *bo; int domain = RADEON_GEM_DOMAIN_VRAM; if (usage_hint) { if (info->allowColorTiling) { if (usage_hint & RADEON_CREATE_PIXMAP_TILING_MACRO) tiling |= RADEON_TILING_MACRO; if (usage_hint & RADEON_CREATE_PIXMAP_TILING_MICRO) tiling |= RADEON_TILING_MICRO; } if (usage_hint & RADEON_CREATE_PIXMAP_DEPTH) tiling |= RADEON_TILING_MACRO | RADEON_TILING_MICRO; #ifdef CREATE_PIXMAP_USAGE_SHARED if ((usage_hint & 0xffff) == CREATE_PIXMAP_USAGE_SHARED) { tiling = 0; domain = RADEON_GEM_DOMAIN_GTT; } #endif } /* Small pixmaps must not be macrotiled on R300, hw cannot sample them * correctly because samplers automatically switch to macrolinear. */ if (info->ChipFamily >= CHIP_FAMILY_R300 && info->ChipFamily <= CHIP_FAMILY_RS740 && (tiling & RADEON_TILING_MACRO) && !RADEONMacroSwitch(width, height, bitsPerPixel, tiling, info->ChipFamily >= CHIP_FAMILY_RV350)) { tiling &= ~RADEON_TILING_MACRO; } heighta = RADEON_ALIGN(height, drmmode_get_height_align(pScrn, tiling)); pitch = RADEON_ALIGN(width, drmmode_get_pitch_align(pScrn, cpp, tiling)) * cpp; base_align = drmmode_get_base_align(pScrn, cpp, tiling); size = RADEON_ALIGN(heighta * pitch, RADEON_GPU_PAGE_SIZE); memset(&surface, 0, sizeof(struct radeon_surface)); if (info->ChipFamily >= CHIP_FAMILY_R600 && info->surf_man) { if (width) { surface.npix_x = width; /* need to align height to 8 for old kernel */ surface.npix_y = RADEON_ALIGN(height, 8); surface.npix_z = 1; surface.blk_w = 1; surface.blk_h = 1; surface.blk_d = 1; surface.array_size = 1; surface.last_level = 0; surface.bpe = cpp; surface.nsamples = 1; if (height < 128) { /* disable 2d tiling for small surface to work around * the fact that ddx align height to 8 pixel for old * obscure reason i can't remember */ tiling &= ~RADEON_TILING_MACRO; } surface.flags = RADEON_SURF_SCANOUT; /* we are requiring a recent enough libdrm version */ surface.flags |= RADEON_SURF_HAS_TILE_MODE_INDEX; surface.flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_2D, TYPE); surface.flags |= RADEON_SURF_SET(RADEON_SURF_MODE_LINEAR, MODE); if ((tiling & RADEON_TILING_MICRO)) { surface.flags = RADEON_SURF_CLR(surface.flags, MODE); surface.flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE); } if ((tiling & RADEON_TILING_MACRO)) { surface.flags = RADEON_SURF_CLR(surface.flags, MODE); surface.flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE); } if (usage_hint & RADEON_CREATE_PIXMAP_SZBUFFER) { surface.flags |= RADEON_SURF_ZBUFFER; surface.flags |= RADEON_SURF_SBUFFER; } if (radeon_surface_best(info->surf_man, &surface)) { return NULL; } if (radeon_surface_init(info->surf_man, &surface)) { return NULL; } size = surface.bo_size; base_align = surface.bo_alignment; pitch = surface.level[0].pitch_bytes; tiling = 0; switch (surface.level[0].mode) { case RADEON_SURF_MODE_2D: tiling |= RADEON_TILING_MACRO; tiling |= surface.bankw << RADEON_TILING_EG_BANKW_SHIFT; tiling |= surface.bankh << RADEON_TILING_EG_BANKH_SHIFT; tiling |= surface.mtilea << RADEON_TILING_EG_MACRO_TILE_ASPECT_SHIFT; tiling |= eg_tile_split(surface.tile_split) << RADEON_TILING_EG_TILE_SPLIT_SHIFT; tiling |= eg_tile_split(surface.stencil_tile_split) << RADEON_TILING_EG_STENCIL_TILE_SPLIT_SHIFT; break; case RADEON_SURF_MODE_1D: tiling |= RADEON_TILING_MICRO; break; default: break; } } } bo = radeon_bo_open(info->bufmgr, 0, size, base_align, domain, 0); if (bo && tiling && radeon_bo_set_tiling(bo, tiling, pitch) == 0) *new_tiling = tiling; *new_surface = surface; *new_pitch = pitch; return bo; }
Bool radeon_set_shared_pixmap_backing(PixmapPtr ppix, void *fd_handle, struct radeon_surface *surface) { ScrnInfoPtr pScrn = xf86ScreenToScrn(ppix->drawable.pScreen); RADEONInfoPtr info = RADEONPTR(pScrn); struct radeon_bo *bo; int ihandle = (int)(long)fd_handle; uint32_t size = ppix->devKind * ppix->drawable.height; bo = radeon_gem_bo_open_prime(info->bufmgr, ihandle, size); if (!bo) return FALSE; memset(surface, 0, sizeof(struct radeon_surface)); radeon_set_pixmap_bo(ppix, bo); if (info->ChipFamily >= CHIP_FAMILY_R600 && info->surf_man) { uint32_t tiling_flags; #ifdef USE_GLAMOR if (info->use_glamor) { tiling_flags = radeon_get_pixmap_private(ppix)->tiling_flags; } else #endif { struct radeon_exa_pixmap_priv *driver_priv; driver_priv = exaGetPixmapDriverPrivate(ppix); tiling_flags = driver_priv->tiling_flags; } surface->npix_x = ppix->drawable.width; surface->npix_y = ppix->drawable.height; surface->npix_z = 1; surface->blk_w = 1; surface->blk_h = 1; surface->blk_d = 1; surface->array_size = 1; surface->bpe = ppix->drawable.bitsPerPixel / 8; surface->nsamples = 1; /* we are requiring a recent enough libdrm version */ surface->flags |= RADEON_SURF_HAS_TILE_MODE_INDEX; surface->flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_2D, TYPE); if (tiling_flags & RADEON_TILING_MACRO) surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE); else if (tiling_flags & RADEON_TILING_MICRO) surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE); else surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_LINEAR_ALIGNED, MODE); surface->bankw = (tiling_flags >> RADEON_TILING_EG_BANKW_SHIFT) & RADEON_TILING_EG_BANKW_MASK; surface->bankh = (tiling_flags >> RADEON_TILING_EG_BANKH_SHIFT) & RADEON_TILING_EG_BANKH_MASK; surface->tile_split = eg_tile_split_opp((tiling_flags >> RADEON_TILING_EG_TILE_SPLIT_SHIFT) & RADEON_TILING_EG_TILE_SPLIT_MASK); surface->stencil_tile_split = (tiling_flags >> RADEON_TILING_EG_STENCIL_TILE_SPLIT_SHIFT) & RADEON_TILING_EG_STENCIL_TILE_SPLIT_MASK; surface->mtilea = (tiling_flags >> RADEON_TILING_EG_MACRO_TILE_ASPECT_SHIFT) & RADEON_TILING_EG_MACRO_TILE_ASPECT_MASK; if (radeon_surface_best(info->surf_man, surface)) { return FALSE; } if (radeon_surface_init(info->surf_man, surface)) { return FALSE; } /* we have to post hack the surface to reflect the actual size of the shared pixmap */ surface->level[0].pitch_bytes = ppix->devKind; surface->level[0].nblk_x = ppix->devKind / surface->bpe; }
/* Plan is to move initialization in that function and use * helper function so that radeon_device_init pretty much * do nothing more than calling asic specific function. This * should also allow to remove a bunch of callback function * like vram_info. */ int cayman_init(struct radeon_device *rdev) { struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; int r; /* Read BIOS */ if (!radeon_get_bios(rdev)) { if (ASIC_IS_AVIVO(rdev)) return -EINVAL; } /* Must be an ATOMBIOS */ if (!rdev->is_atom_bios) { dev_err(rdev->dev, "Expecting atombios for cayman GPU\n"); return -EINVAL; } r = radeon_atombios_init(rdev); if (r) return r; /* Post card if necessary */ if (!radeon_card_posted(rdev)) { if (!rdev->bios) { dev_err(rdev->dev, "Card not posted and no BIOS - ignoring\n"); return -EINVAL; } DRM_INFO("GPU not posted. posting now...\n"); atom_asic_init(rdev->mode_info.atom_context); } /* Initialize scratch registers */ r600_scratch_init(rdev); /* Initialize surface registers */ radeon_surface_init(rdev); /* Initialize clocks */ radeon_get_clock_info(rdev->ddev); /* Fence driver */ r = radeon_fence_driver_init(rdev); if (r) return r; /* initialize memory controller */ r = evergreen_mc_init(rdev); if (r) return r; /* Memory manager */ r = radeon_bo_init(rdev); if (r) return r; r = radeon_irq_kms_init(rdev); if (r) return r; ring->ring_obj = NULL; r600_ring_init(rdev, ring, 1024 * 1024); rdev->ih.ring_obj = NULL; r600_ih_ring_init(rdev, 64 * 1024); r = r600_pcie_gart_init(rdev); if (r) return r; r = radeon_ib_pool_init(rdev); rdev->accel_working = true; if (r) { dev_err(rdev->dev, "IB initialization failed (%d).\n", r); rdev->accel_working = false; } r = radeon_vm_manager_init(rdev); if (r) { dev_err(rdev->dev, "vm manager initialization failed (%d).\n", r); } r = cayman_startup(rdev); if (r) { dev_err(rdev->dev, "disabling GPU acceleration\n"); cayman_cp_fini(rdev); r600_irq_fini(rdev); if (rdev->flags & RADEON_IS_IGP) si_rlc_fini(rdev); radeon_wb_fini(rdev); r100_ib_fini(rdev); radeon_vm_manager_fini(rdev); radeon_irq_kms_fini(rdev); cayman_pcie_gart_fini(rdev); rdev->accel_working = false; } /* Don't start up if the MC ucode is missing. * The default clocks and voltages before the MC ucode * is loaded are not suffient for advanced operations. * * We can skip this check for TN, because there is no MC * ucode. */ if (!rdev->mc_fw && !(rdev->flags & RADEON_IS_IGP)) { DRM_ERROR("radeon: MC ucode required for NI+.\n"); return -EINVAL; } return 0; }