コード例 #1
0
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);
}
コード例 #2
0
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;
}
コード例 #3
0
ファイル: radeon_drm_surface.c プロジェクト: chemecse/mesa
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;
}
コード例 #4
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;
}
コード例 #5
0
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;
}
コード例 #6
0
/* 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;
}
コード例 #7
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));

    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;
    }
コード例 #8
0
/* 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;
}