Back to index

libdrm  2.4.37
Classes | Defines | Typedefs | Enumerations | Functions
radeon_surface.c File Reference
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include "drm.h"
#include "xf86drm.h"
#include "radeon_drm.h"
#include "radeon_surface.h"
#include "r600_pci_ids.h"

Go to the source code of this file.

Classes

struct  radeon_hw_info
struct  radeon_surface_manager

Defines

#define ALIGN(value, alignment)   (((value) + alignment - 1) & ~(alignment - 1))
#define MAX2(A, B)   ((A) > (B) ? (A) : (B))
#define MIN2(A, B)   ((A) < (B) ? (A) : (B))
#define CHIPSET(pci_id, name, fam)   case pci_id: surf_man->family = CHIP_##fam; break;

Typedefs

typedef int(* hw_init_surface_t )(struct radeon_surface_manager *surf_man, struct radeon_surface *surf)
typedef int(* hw_best_surface_t )(struct radeon_surface_manager *surf_man, struct radeon_surface *surf)

Enumerations

enum  radeon_family {
  CHIP_UNKNOWN, CHIP_R600, CHIP_RV610, CHIP_RV630,
  CHIP_RV670, CHIP_RV620, CHIP_RV635, CHIP_RS780,
  CHIP_RS880, CHIP_RV770, CHIP_RV730, CHIP_RV710,
  CHIP_RV740, CHIP_CEDAR, CHIP_REDWOOD, CHIP_JUNIPER,
  CHIP_CYPRESS, CHIP_HEMLOCK, CHIP_PALM, CHIP_SUMO,
  CHIP_SUMO2, CHIP_BARTS, CHIP_TURKS, CHIP_CAICOS,
  CHIP_CAYMAN, CHIP_ARUBA, CHIP_TAHITI, CHIP_PITCAIRN,
  CHIP_VERDE, CHIP_LAST
}

Functions

static int radeon_get_value (int fd, unsigned req, uint32_t *value)
static int radeon_get_family (struct radeon_surface_manager *surf_man)
static unsigned next_power_of_two (unsigned x)
static unsigned mip_minify (unsigned size, unsigned level)
static void surf_minify (struct radeon_surface *surf, unsigned level, uint32_t xalign, uint32_t yalign, uint32_t zalign, unsigned offset)
static int r6_init_hw_info (struct radeon_surface_manager *surf_man)
static int r6_surface_init_linear (struct radeon_surface_manager *surf_man, struct radeon_surface *surf, uint64_t offset, unsigned start_level)
static int r6_surface_init_linear_aligned (struct radeon_surface_manager *surf_man, struct radeon_surface *surf, uint64_t offset, unsigned start_level)
static int r6_surface_init_1d (struct radeon_surface_manager *surf_man, struct radeon_surface *surf, uint64_t offset, unsigned start_level)
static int r6_surface_init_2d (struct radeon_surface_manager *surf_man, struct radeon_surface *surf, uint64_t offset, unsigned start_level)
static int r6_surface_init (struct radeon_surface_manager *surf_man, struct radeon_surface *surf)
static int r6_surface_best (struct radeon_surface_manager *surf_man, struct radeon_surface *surf)
static int eg_init_hw_info (struct radeon_surface_manager *surf_man)
static void eg_surf_minify (struct radeon_surface *surf, unsigned level, unsigned slice_pt, unsigned mtilew, unsigned mtileh, unsigned mtileb, unsigned offset)
static int eg_surface_init_1d (struct radeon_surface_manager *surf_man, struct radeon_surface *surf, uint64_t offset, unsigned start_level)
static int eg_surface_init_2d (struct radeon_surface_manager *surf_man, struct radeon_surface *surf, uint64_t offset, unsigned start_level)
static int eg_surface_sanity (struct radeon_surface_manager *surf_man, struct radeon_surface *surf, unsigned mode)
static int eg_surface_init (struct radeon_surface_manager *surf_man, struct radeon_surface *surf)
static unsigned log2_int (unsigned x)
static int eg_surface_best (struct radeon_surface_manager *surf_man, struct radeon_surface *surf)
struct radeon_surface_managerradeon_surface_manager_new (int fd)
void radeon_surface_manager_free (struct radeon_surface_manager *surf_man)
static int radeon_surface_sanity (struct radeon_surface_manager *surf_man, struct radeon_surface *surf, unsigned type, unsigned mode)
int radeon_surface_init (struct radeon_surface_manager *surf_man, struct radeon_surface *surf)
int radeon_surface_best (struct radeon_surface_manager *surf_man, struct radeon_surface *surf)

Class Documentation

struct radeon_hw_info

Definition at line 83 of file radeon_surface.c.

Class Members
unsigned allow_2d
uint32_t group_bytes
uint32_t num_banks
uint32_t num_pipes
uint32_t row_size
struct radeon_surface_manager

Definition at line 93 of file radeon_surface.c.

Collaboration diagram for radeon_surface_manager:
Class Members
uint32_t device_id
unsigned family
int fd
hw_best_surface_t surface_best
hw_init_surface_t surface_init

Define Documentation

#define ALIGN (   value,
  alignment 
)    (((value) + alignment - 1) & ~(alignment - 1))

Definition at line 40 of file radeon_surface.c.

#define CHIPSET (   pci_id,
  name,
  fam 
)    case pci_id: surf_man->family = CHIP_##fam; break;
#define MAX2 (   A,
 
)    ((A) > (B) ? (A) : (B))

Definition at line 41 of file radeon_surface.c.

#define MIN2 (   A,
 
)    ((A) < (B) ? (A) : (B))

Definition at line 42 of file radeon_surface.c.


Typedef Documentation

typedef int(* hw_best_surface_t)(struct radeon_surface_manager *surf_man, struct radeon_surface *surf)

Definition at line 80 of file radeon_surface.c.

typedef int(* hw_init_surface_t)(struct radeon_surface_manager *surf_man, struct radeon_surface *surf)

Definition at line 78 of file radeon_surface.c.


Enumeration Type Documentation

Enumerator:
CHIP_UNKNOWN 
CHIP_R600 
CHIP_RV610 
CHIP_RV630 
CHIP_RV670 
CHIP_RV620 
CHIP_RV635 
CHIP_RS780 
CHIP_RS880 
CHIP_RV770 
CHIP_RV730 
CHIP_RV710 
CHIP_RV740 
CHIP_CEDAR 
CHIP_REDWOOD 
CHIP_JUNIPER 
CHIP_CYPRESS 
CHIP_HEMLOCK 
CHIP_PALM 
CHIP_SUMO 
CHIP_SUMO2 
CHIP_BARTS 
CHIP_TURKS 
CHIP_CAICOS 
CHIP_CAYMAN 
CHIP_ARUBA 
CHIP_TAHITI 
CHIP_PITCAIRN 
CHIP_VERDE 
CHIP_LAST 

Definition at line 45 of file radeon_surface.c.


Function Documentation

static int eg_init_hw_info ( struct radeon_surface_manager surf_man) [static]

Definition at line 457 of file radeon_surface.c.

{
    uint32_t tiling_config;
    drmVersionPtr version;
    int r;

    r = radeon_get_value(surf_man->fd, RADEON_INFO_TILING_CONFIG,
                         &tiling_config);
    if (r) {
        return r;
    }

    surf_man->hw_info.allow_2d = 0;
    version = drmGetVersion(surf_man->fd);
    if (version && version->version_minor >= 16) {
        surf_man->hw_info.allow_2d = 1;
    }
    drmFreeVersion(version);

    switch (tiling_config & 0xf) {
    case 0:
        surf_man->hw_info.num_pipes = 1;
        break;
    case 1:
        surf_man->hw_info.num_pipes = 2;
        break;
    case 2:
        surf_man->hw_info.num_pipes = 4;
        break;
    case 3:
        surf_man->hw_info.num_pipes = 8;
        break;
    default:
        surf_man->hw_info.num_pipes = 8;
        surf_man->hw_info.allow_2d = 0;
        break;
    }

    switch ((tiling_config & 0xf0) >> 4) {
    case 0:
        surf_man->hw_info.num_banks = 4;
        break;
    case 1:
        surf_man->hw_info.num_banks = 8;
        break;
    case 2:
        surf_man->hw_info.num_banks = 16;
        break;
    default:
        surf_man->hw_info.num_banks = 8;
        surf_man->hw_info.allow_2d = 0;
        break;
    }

    switch ((tiling_config & 0xf00) >> 8) {
    case 0:
        surf_man->hw_info.group_bytes = 256;
        break;
    case 1:
        surf_man->hw_info.group_bytes = 512;
        break;
    default:
        surf_man->hw_info.group_bytes = 256;
        surf_man->hw_info.allow_2d = 0;
        break;
    }

    switch ((tiling_config & 0xf000) >> 12) {
    case 0:
        surf_man->hw_info.row_size = 1024;
        break;
    case 1:
        surf_man->hw_info.row_size = 2048;
        break;
    case 2:
        surf_man->hw_info.row_size = 4096;
        break;
    default:
        surf_man->hw_info.row_size = 4096;
        surf_man->hw_info.allow_2d = 0;
        break;
    }
    return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void eg_surf_minify ( struct radeon_surface surf,
unsigned  level,
unsigned  slice_pt,
unsigned  mtilew,
unsigned  mtileh,
unsigned  mtileb,
unsigned  offset 
) [static]

Definition at line 542 of file radeon_surface.c.

{
    unsigned mtile_pr, mtile_ps;

    surf->level[level].npix_x = mip_minify(surf->npix_x, level);
    surf->level[level].npix_y = mip_minify(surf->npix_y, level);
    surf->level[level].npix_z = mip_minify(surf->npix_z, level);
    surf->level[level].nblk_x = (surf->level[level].npix_x + surf->blk_w - 1) / surf->blk_w;
    surf->level[level].nblk_y = (surf->level[level].npix_y + surf->blk_h - 1) / surf->blk_h;
    surf->level[level].nblk_z = (surf->level[level].npix_z + surf->blk_d - 1) / surf->blk_d;
    if (surf->level[level].mode == RADEON_SURF_MODE_2D) {
        if (surf->level[level].nblk_x < mtilew || surf->level[level].nblk_y < mtileh) {
            surf->level[level].mode = RADEON_SURF_MODE_1D;
            return;
        }
    }
    surf->level[level].nblk_x  = ALIGN(surf->level[level].nblk_x, mtilew);
    surf->level[level].nblk_y  = ALIGN(surf->level[level].nblk_y, mtileh);
    surf->level[level].nblk_z  = ALIGN(surf->level[level].nblk_z, 1);

    /* macro tile per row */
    mtile_pr = surf->level[level].nblk_x / mtilew;
    /* macro tile per slice */
    mtile_ps = (mtile_pr * surf->level[level].nblk_y) / mtileh;

    surf->level[level].offset = offset;
    surf->level[level].pitch_bytes = surf->level[level].nblk_x * surf->bpe * slice_pt;
    surf->level[level].slice_size = mtile_ps * mtileb * slice_pt;

    surf->bo_size = offset + surf->level[level].slice_size * surf->level[level].nblk_z * surf->array_size;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int eg_surface_best ( struct radeon_surface_manager surf_man,
struct radeon_surface surf 
) [static]

Definition at line 829 of file radeon_surface.c.

{
    unsigned mode, tileb, h_over_w;
    int r;

    /* tiling mode */
    mode = (surf->flags >> RADEON_SURF_MODE_SHIFT) & RADEON_SURF_MODE_MASK;

    /* for some reason eg need to have room for stencil right after depth */
    if (surf->flags & RADEON_SURF_ZBUFFER) {
        surf->flags |= RADEON_SURF_SBUFFER;
    }

    /* set some default value to avoid sanity check choking on them */
    surf->tile_split = 1024;
    surf->bankw = 1;
    surf->bankh = 1;
    surf->mtilea = surf_man->hw_info.num_banks;
    tileb = MIN2(surf->tile_split, 64 * surf->bpe * surf->nsamples);
    for (; surf->bankh <= 8; surf->bankh *= 2) {
        if ((tileb * surf->bankh * surf->bankw) >= surf_man->hw_info.group_bytes) {
            break;
        }
    }
    if (surf->mtilea > 8) {
        surf->mtilea = 8;
    }

    r = eg_surface_sanity(surf_man, surf, mode);
    if (r) {
        return r;
    }

    if (mode != RADEON_SURF_MODE_2D) {
        /* nothing to do for non 2D tiled surface */
        return 0;
    }

    /* set tile split to row size, optimize latter for multi-sample surface
     * tile split >= 256 for render buffer surface. Also depth surface want
     * smaller value for optimal performances.
     */
    surf->tile_split = surf_man->hw_info.row_size;
    surf->stencil_tile_split = surf_man->hw_info.row_size / 2;

    /* bankw or bankh greater than 1 increase alignment requirement, not
     * sure if it's worth using smaller bankw & bankh to stick with 2D
     * tiling on small surface rather than falling back to 1D tiling.
     * Use recommanded value based on tile size for now.
     *
     * fmask buffer has different optimal value figure them out once we
     * use it.
     */
    if (surf->flags & (RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER)) {
        /* assume 1 bytes for stencil, we optimize for stencil as stencil
         * and depth shares surface values
         */
        tileb = MIN2(surf->tile_split, 64 * surf->nsamples);
    } else {
        tileb = MIN2(surf->tile_split, 64 * surf->bpe * surf->nsamples);
    }

    /* use bankw of 1 to minimize width alignment, might be interesting to
     * increase it for large surface
     */
    surf->bankw = 1;
    switch (tileb) {
    case 64:
        surf->bankh = 4;
        break;
    case 128:
    case 256:
        surf->bankh = 2;
        break;
    default:
        surf->bankh = 1;
        break;
    }
    /* double check the constraint */
    for (; surf->bankh <= 8; surf->bankh *= 2) {
        if ((tileb * surf->bankh * surf->bankw) >= surf_man->hw_info.group_bytes) {
            break;
        }
    }

    h_over_w = (((surf->bankh * surf_man->hw_info.num_banks) << 16) /
                (surf->bankw * surf_man->hw_info.num_pipes)) >> 16;
    surf->mtilea = 1 << (log2_int(h_over_w) >> 1);

    return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int eg_surface_init ( struct radeon_surface_manager surf_man,
struct radeon_surface surf 
) [static]

Definition at line 753 of file radeon_surface.c.

{
    unsigned mode;
    int r;

    /* tiling mode */
    mode = (surf->flags >> RADEON_SURF_MODE_SHIFT) & RADEON_SURF_MODE_MASK;

    /* for some reason eg need to have room for stencil right after depth */
    if (surf->flags & RADEON_SURF_ZBUFFER) {
        surf->flags |= RADEON_SURF_SBUFFER;
    }
    if (surf->flags & RADEON_SURF_SBUFFER) {
        surf->flags |= RADEON_SURF_ZBUFFER;
    }
    if (surf->flags & RADEON_SURF_ZBUFFER) {
        /* zbuffer only support 1D or 2D tiled surface */
        switch (mode) {
        case RADEON_SURF_MODE_1D:
        case RADEON_SURF_MODE_2D:
            break;
        default:
            mode = RADEON_SURF_MODE_1D;
            surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
            surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE);
            break;
        }
    }

    r = eg_surface_sanity(surf_man, surf, mode);
    if (r) {
        return r;
    }

    surf->stencil_offset = 0;
    surf->stencil_tile_split = 0;

    /* check tiling mode */
    switch (mode) {
    case RADEON_SURF_MODE_LINEAR:
        r = r6_surface_init_linear(surf_man, surf, 0, 0);
        break;
    case RADEON_SURF_MODE_LINEAR_ALIGNED:
        r = r6_surface_init_linear_aligned(surf_man, surf, 0, 0);
        break;
    case RADEON_SURF_MODE_1D:
        r = eg_surface_init_1d(surf_man, surf, 0, 0);
        break;
    case RADEON_SURF_MODE_2D:
        r = eg_surface_init_2d(surf_man, surf, 0, 0);
        break;
    default:
        return -EINVAL;
    }
    return r;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int eg_surface_init_1d ( struct radeon_surface_manager surf_man,
struct radeon_surface surf,
uint64_t  offset,
unsigned  start_level 
) [static]

Definition at line 580 of file radeon_surface.c.

{
    uint32_t xalign, yalign, zalign, tilew;
    unsigned i;

    /* compute alignment */
    tilew = 8;
    xalign = surf_man->hw_info.group_bytes / (tilew * surf->bpe * surf->nsamples);
    if (surf->flags & RADEON_SURF_SBUFFER) {
        xalign = surf_man->hw_info.group_bytes / (tilew * surf->nsamples);
    }
    xalign = MAX2(tilew, xalign);
    yalign = tilew;
    zalign = 1;
    if (surf->flags & RADEON_SURF_SCANOUT) {
        xalign = MAX2((surf->bpe == 1) ? 64 : 32, xalign);
    }
    if (!start_level) {
        surf->bo_alignment = MAX2(256, surf_man->hw_info.group_bytes);
    }

    /* build mipmap tree */
    for (i = start_level; i <= surf->last_level; i++) {
        surf->level[i].mode = RADEON_SURF_MODE_1D;
        surf_minify(surf, i, xalign, yalign, zalign, offset);
        /* level0 and first mipmap need to have alignment */
        offset = surf->bo_size;
        if ((i == 0)) {
            offset = ALIGN(offset, surf->bo_alignment);
        }
    }

    if (surf->flags & RADEON_SURF_SBUFFER) {
        surf->stencil_offset = ALIGN(surf->bo_size, surf->bo_alignment);
        surf->bo_size = surf->stencil_offset + surf->bo_size / 4;
    }

    return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int eg_surface_init_2d ( struct radeon_surface_manager surf_man,
struct radeon_surface surf,
uint64_t  offset,
unsigned  start_level 
) [static]

Definition at line 622 of file radeon_surface.c.

{
    unsigned tilew, tileh, tileb;
    unsigned mtilew, mtileh, mtileb;
    unsigned slice_pt;
    unsigned i;

    /* compute tile values */
    tilew = 8;
    tileh = 8;
    tileb = tilew * tileh * surf->bpe * surf->nsamples;
    /* slices per tile */
    slice_pt = 1;
    if (tileb > surf->tile_split) {
        slice_pt = tileb / surf->tile_split;
    }
    tileb = tileb / slice_pt;

    /* macro tile width & height */
    mtilew = (tilew * surf->bankw * surf_man->hw_info.num_pipes) * surf->mtilea;
    mtileh = (tileh * surf->bankh * surf_man->hw_info.num_banks) / surf->mtilea;
    /* macro tile bytes */
    mtileb = (mtilew / tilew) * (mtileh / tileh) * tileb;

    if (!start_level) {
        surf->bo_alignment = MAX2(256, mtileb);
    }

    /* build mipmap tree */
    for (i = start_level; i <= surf->last_level; i++) {
        surf->level[i].mode = RADEON_SURF_MODE_2D;
        eg_surf_minify(surf, i, slice_pt, mtilew, mtileh, mtileb, offset);
        if (surf->level[i].mode == RADEON_SURF_MODE_1D) {
            return eg_surface_init_1d(surf_man, surf, offset, i);
        }
        /* level0 and first mipmap need to have alignment */
        offset = surf->bo_size;
        if ((i == 0)) {
            offset = ALIGN(offset, surf->bo_alignment);
        }
    }

    if (surf->flags & RADEON_SURF_SBUFFER) {
        surf->stencil_offset = ALIGN(surf->bo_size, surf->bo_alignment);
        surf->bo_size = surf->stencil_offset + surf->bo_size / 4;
    }

    return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int eg_surface_sanity ( struct radeon_surface_manager surf_man,
struct radeon_surface surf,
unsigned  mode 
) [static]

Definition at line 674 of file radeon_surface.c.

{
    unsigned tileb;

    /* check surface dimension */
    if (surf->npix_x > 16384 || surf->npix_y > 16384 || surf->npix_z > 16384) {
        return -EINVAL;
    }

    /* check mipmap last_level */
    if (surf->last_level > 15) {
        return -EINVAL;
    }

    /* force 1d on kernel that can't do 2d */
    if (!surf_man->hw_info.allow_2d && mode > RADEON_SURF_MODE_1D) {
        mode = RADEON_SURF_MODE_1D;
        surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
        surf->flags |= RADEON_SURF_SET(mode, MODE);
    }

    /* check tile split */
    if (mode == RADEON_SURF_MODE_2D) {
        switch (surf->tile_split) {
        case 64:
        case 128:
        case 256:
        case 512:
        case 1024:
        case 2048:
        case 4096:
            break;
        default:
            return -EINVAL;
        }
        switch (surf->mtilea) {
        case 1:
        case 2:
        case 4:
        case 8:
            break;
        default:
            return -EINVAL;
        }
        /* check aspect ratio */
        if (surf_man->hw_info.num_banks < surf->mtilea) {
            return -EINVAL;
        }
        /* check bank width */
        switch (surf->bankw) {
        case 1:
        case 2:
        case 4:
        case 8:
            break;
        default:
            return -EINVAL;
        }
        /* check bank height */
        switch (surf->bankh) {
        case 1:
        case 2:
        case 4:
        case 8:
            break;
        default:
            return -EINVAL;
        }
        tileb = MIN2(surf->tile_split, 64 * surf->bpe * surf->nsamples);
        if ((tileb * surf->bankh * surf->bankw) < surf_man->hw_info.group_bytes) {
            return -EINVAL;
        }
    }

    return 0;
}

Here is the caller graph for this function:

static unsigned log2_int ( unsigned  x) [static]

Definition at line 811 of file radeon_surface.c.

{
    unsigned l;

    if (x < 2) {
        return 0;
    }
    for (l = 2; ; l++) {
        if ((unsigned)(1 << l) > x) {
            return l - 1;
        }
    }
    return 0;
}

Here is the caller graph for this function:

static unsigned mip_minify ( unsigned  size,
unsigned  level 
) [static]

Definition at line 136 of file radeon_surface.c.

{
    unsigned val;

    val = MAX2(1, size >> level);
    if (level > 0)
        val = next_power_of_two(val);
    return val;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static unsigned next_power_of_two ( unsigned  x) [static]

Definition at line 128 of file radeon_surface.c.

{
   if (x <= 1)
       return 1;

   return (1 << ((sizeof(unsigned) * 8) - __builtin_clz(x - 1)));
}

Here is the caller graph for this function:

static int r6_init_hw_info ( struct radeon_surface_manager surf_man) [static]

Definition at line 177 of file radeon_surface.c.

{
    uint32_t tiling_config;
    drmVersionPtr version;
    int r;

    r = radeon_get_value(surf_man->fd, RADEON_INFO_TILING_CONFIG,
                         &tiling_config);
    if (r) {
        return r;
    }

    surf_man->hw_info.allow_2d = 0;
    version = drmGetVersion(surf_man->fd);
    if (version && version->version_minor >= 14) {
        surf_man->hw_info.allow_2d = 1;
    }
    drmFreeVersion(version);

    switch ((tiling_config & 0xe) >> 1) {
    case 0:
        surf_man->hw_info.num_pipes = 1;
        break;
    case 1:
        surf_man->hw_info.num_pipes = 2;
        break;
    case 2:
        surf_man->hw_info.num_pipes = 4;
        break;
    case 3:
        surf_man->hw_info.num_pipes = 8;
        break;
    default:
        surf_man->hw_info.num_pipes = 8;
        surf_man->hw_info.allow_2d = 0;
        break;
    }

    switch ((tiling_config & 0x30) >> 4) {
    case 0:
        surf_man->hw_info.num_banks = 4;
        break;
    case 1:
        surf_man->hw_info.num_banks = 8;
        break;
    default:
        surf_man->hw_info.num_banks = 8;
        surf_man->hw_info.allow_2d = 0;
        break;
    }

    switch ((tiling_config & 0xc0) >> 6) {
    case 0:
        surf_man->hw_info.group_bytes = 256;
        break;
    case 1:
        surf_man->hw_info.group_bytes = 512;
        break;
    default:
        surf_man->hw_info.group_bytes = 256;
        surf_man->hw_info.allow_2d = 0;
        break;
    }
    return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int r6_surface_best ( struct radeon_surface_manager surf_man,
struct radeon_surface surf 
) [static]

Definition at line 446 of file radeon_surface.c.

{
    /* no value to optimize for r6xx/r7xx */
    return 0;
}

Here is the caller graph for this function:

static int r6_surface_init ( struct radeon_surface_manager surf_man,
struct radeon_surface surf 
) [static]

Definition at line 379 of file radeon_surface.c.

{
    unsigned mode;
    int r;

    /* tiling mode */
    mode = (surf->flags >> RADEON_SURF_MODE_SHIFT) & RADEON_SURF_MODE_MASK;

    /* always enable z & stencil together */
    if (surf->flags & RADEON_SURF_ZBUFFER) {
        surf->flags |= RADEON_SURF_SBUFFER;
    }
    if (surf->flags & RADEON_SURF_SBUFFER) {
        surf->flags |= RADEON_SURF_ZBUFFER;
    }
    if (surf->flags & RADEON_SURF_ZBUFFER) {
        /* zbuffer only support 1D or 2D tiled surface */
        switch (mode) {
        case RADEON_SURF_MODE_1D:
        case RADEON_SURF_MODE_2D:
            break;
        default:
            mode = RADEON_SURF_MODE_1D;
            surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
            surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE);
            break;
        }
    }

    /* force 1d on kernel that can't do 2d */
    if (!surf_man->hw_info.allow_2d && mode > RADEON_SURF_MODE_1D) {
        mode = RADEON_SURF_MODE_1D;
        surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
        surf->flags |= RADEON_SURF_SET(mode, MODE);
    }

    /* check surface dimension */
    if (surf->npix_x > 8192 || surf->npix_y > 8192 || surf->npix_z > 8192) {
        return -EINVAL;
    }

    /* check mipmap last_level */
    if (surf->last_level > 14) {
        return -EINVAL;
    }

    /* check tiling mode */
    switch (mode) {
    case RADEON_SURF_MODE_LINEAR:
        r = r6_surface_init_linear(surf_man, surf, 0, 0);
        break;
    case RADEON_SURF_MODE_LINEAR_ALIGNED:
        r = r6_surface_init_linear_aligned(surf_man, surf, 0, 0);
        break;
    case RADEON_SURF_MODE_1D:
        r = r6_surface_init_1d(surf_man, surf, 0, 0);
        break;
    case RADEON_SURF_MODE_2D:
        r = r6_surface_init_2d(surf_man, surf, 0, 0);
        break;
    default:
        return -EINVAL;
    }
    return r;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int r6_surface_init_1d ( struct radeon_surface_manager surf_man,
struct radeon_surface surf,
uint64_t  offset,
unsigned  start_level 
) [static]

Definition at line 305 of file radeon_surface.c.

{
    uint32_t xalign, yalign, zalign, tilew;
    unsigned i;

    /* compute alignment */
    tilew = 8;
    xalign = surf_man->hw_info.group_bytes / (tilew * surf->bpe * surf->nsamples);
    xalign = MAX2(tilew, xalign);
    yalign = tilew;
    zalign = 1;
    if (surf->flags & RADEON_SURF_SCANOUT) {
        xalign = MAX2((surf->bpe == 1) ? 64 : 32, xalign);
    }
    if (!start_level) {
        surf->bo_alignment = MAX2(256, surf_man->hw_info.group_bytes);
    }

    /* build mipmap tree */
    for (i = start_level; i <= surf->last_level; i++) {
        surf->level[i].mode = RADEON_SURF_MODE_1D;
        surf_minify(surf, i, xalign, yalign, zalign, offset);
        /* level0 and first mipmap need to have alignment */
        offset = surf->bo_size;
        if ((i == 0)) {
            offset = ALIGN(offset, surf->bo_alignment);
        }
    }
    return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int r6_surface_init_2d ( struct radeon_surface_manager surf_man,
struct radeon_surface surf,
uint64_t  offset,
unsigned  start_level 
) [static]

Definition at line 338 of file radeon_surface.c.

{
    uint32_t xalign, yalign, zalign, tilew;
    unsigned i;

    /* compute alignment */
    tilew = 8;
    zalign = 1;
    xalign = (surf_man->hw_info.group_bytes * surf_man->hw_info.num_banks) /
             (tilew * surf->bpe * surf->nsamples);
    xalign = MAX2(tilew * surf_man->hw_info.num_banks, xalign);
    yalign = tilew * surf_man->hw_info.num_pipes;
    if (surf->flags & RADEON_SURF_SCANOUT) {
        xalign = MAX2((surf->bpe == 1) ? 64 : 32, xalign);
    }
    if (!start_level) {
        surf->bo_alignment =
            MAX2(surf_man->hw_info.num_pipes *
                 surf_man->hw_info.num_banks *
                 surf->bpe * 64,
                 xalign * yalign * surf->nsamples * surf->bpe);
    }

    /* build mipmap tree */
    for (i = start_level; i <= surf->last_level; i++) {
        surf->level[i].mode = RADEON_SURF_MODE_2D;
        surf_minify(surf, i, xalign, yalign, zalign, offset);
        if (surf->level[i].mode == RADEON_SURF_MODE_1D) {
            return r6_surface_init_1d(surf_man, surf, offset, i);
        }
        /* level0 and first mipmap need to have alignment */
        offset = surf->bo_size;
        if ((i == 0)) {
            offset = ALIGN(offset, surf->bo_alignment);
        }
    }
    return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int r6_surface_init_linear ( struct radeon_surface_manager surf_man,
struct radeon_surface surf,
uint64_t  offset,
unsigned  start_level 
) [static]

Definition at line 243 of file radeon_surface.c.

{
    uint32_t xalign, yalign, zalign;
    unsigned i;

    /* compute alignment */
    if (!start_level) {
        surf->bo_alignment = MAX2(256, surf_man->hw_info.group_bytes);
    }
    /* the 32 alignment is for scanout, cb or db but to allow texture to be
     * easily bound as such we force this alignment to all surface
     */
    xalign = MAX2(1, surf_man->hw_info.group_bytes / surf->bpe);
    yalign = 1;
    zalign = 1;
    if (surf->flags & RADEON_SURF_SCANOUT) {
        xalign = MAX2((surf->bpe == 1) ? 64 : 32, xalign);
    }

    /* build mipmap tree */
    for (i = start_level; i <= surf->last_level; i++) {
        surf->level[i].mode = RADEON_SURF_MODE_LINEAR;
        surf_minify(surf, i, xalign, yalign, zalign, offset);
        /* level0 and first mipmap need to have alignment */
        offset = surf->bo_size;
        if ((i == 0)) {
            offset = ALIGN(offset, surf->bo_alignment);
        }
    }
    return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int r6_surface_init_linear_aligned ( struct radeon_surface_manager surf_man,
struct radeon_surface surf,
uint64_t  offset,
unsigned  start_level 
) [static]

Definition at line 277 of file radeon_surface.c.

{
    uint32_t xalign, yalign, zalign;
    unsigned i;

    /* compute alignment */
    if (!start_level) {
        surf->bo_alignment = MAX2(256, surf_man->hw_info.group_bytes);
    }
    xalign = MAX2(64, surf_man->hw_info.group_bytes / surf->bpe);
    yalign = 1;
    zalign = 1;

    /* build mipmap tree */
    for (i = start_level; i <= surf->last_level; i++) {
        surf->level[i].mode = RADEON_SURF_MODE_LINEAR_ALIGNED;
        surf_minify(surf, i, xalign, yalign, zalign, offset);
        /* level0 and first mipmap need to have alignment */
        offset = surf->bo_size;
        if ((i == 0)) {
            offset = ALIGN(offset, surf->bo_alignment);
        }
    }
    return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int radeon_get_family ( struct radeon_surface_manager surf_man) [static]

Definition at line 116 of file radeon_surface.c.

{
    switch (surf_man->device_id) {
#define CHIPSET(pci_id, name, fam) case pci_id: surf_man->family = CHIP_##fam; break;
#include "r600_pci_ids.h"
#undef CHIPSET
    default:
        return -EINVAL;
    }
    return 0;
}

Here is the caller graph for this function:

static int radeon_get_value ( int  fd,
unsigned  req,
uint32_t *  value 
) [static]

Definition at line 103 of file radeon_surface.c.

{
    struct drm_radeon_info info = {};
    int r;

    *value = 0;
    info.request = req;
    info.value = (uintptr_t)value;
    r = drmCommandWriteRead(fd, DRM_RADEON_INFO, &info,
                            sizeof(struct drm_radeon_info));
    return r;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int radeon_surface_best ( struct radeon_surface_manager surf_man,
struct radeon_surface surf 
)

Definition at line 1050 of file radeon_surface.c.

{
    unsigned mode, type;
    int r;

    type = RADEON_SURF_GET(surf->flags, TYPE);
    mode = RADEON_SURF_GET(surf->flags, MODE);

    r = radeon_surface_sanity(surf_man, surf, type, mode);
    if (r) {
        return r;
    }
    return surf_man->surface_best(surf_man, surf);
}

Here is the call graph for this function:

int radeon_surface_init ( struct radeon_surface_manager surf_man,
struct radeon_surface surf 
)

Definition at line 1034 of file radeon_surface.c.

{
    unsigned mode, type;
    int r;

    type = RADEON_SURF_GET(surf->flags, TYPE);
    mode = RADEON_SURF_GET(surf->flags, MODE);

    r = radeon_surface_sanity(surf_man, surf, type, mode);
    if (r) {
        return r;
    }
    return surf_man->surface_init(surf_man, surf);
}

Here is the call graph for this function:

Definition at line 962 of file radeon_surface.c.

{
    free(surf_man);
}

Definition at line 926 of file radeon_surface.c.

{
    struct radeon_surface_manager *surf_man;

    surf_man = calloc(1, sizeof(struct radeon_surface_manager));
    if (surf_man == NULL) {
        return NULL;
    }
    surf_man->fd = fd;
    if (radeon_get_value(fd, RADEON_INFO_DEVICE_ID, &surf_man->device_id)) {
        goto out_err;
    }
    if (radeon_get_family(surf_man)) {
        goto out_err;
    }

    if (surf_man->family <= CHIP_RV740) {
        if (r6_init_hw_info(surf_man)) {
            goto out_err;
        }
        surf_man->surface_init = &r6_surface_init;
        surf_man->surface_best = &r6_surface_best;
    } else {
        if (eg_init_hw_info(surf_man)) {
            goto out_err;
        }
        surf_man->surface_init = &eg_surface_init;
        surf_man->surface_best = &eg_surface_best;
    }

    return surf_man;
out_err:
    free(surf_man);
    return NULL;
}

Here is the call graph for this function:

static int radeon_surface_sanity ( struct radeon_surface_manager surf_man,
struct radeon_surface surf,
unsigned  type,
unsigned  mode 
) [static]

Definition at line 967 of file radeon_surface.c.

{
    if (surf_man == NULL || surf_man->surface_init == NULL || surf == NULL) {
        return -EINVAL;
    }

    /* all dimension must be at least 1 ! */
    if (!surf->npix_x || !surf->npix_y || !surf->npix_z) {
        return -EINVAL;
    }
    if (!surf->blk_w || !surf->blk_h || !surf->blk_d) {
        return -EINVAL;
    }
    if (!surf->array_size) {
        return -EINVAL;
    }
    /* array size must be a power of 2 */
    surf->array_size = next_power_of_two(surf->array_size);

    switch (surf->nsamples) {
    case 1:
    case 2:
    case 4:
    case 8:
        break;
    default:
        return -EINVAL;
    }
    /* check type */
    switch (type) {
    case RADEON_SURF_TYPE_1D:
        if (surf->npix_y > 1) {
            return -EINVAL;
        }
    case RADEON_SURF_TYPE_2D:
        if (surf->npix_z > 1) {
            return -EINVAL;
        }
        break;
    case RADEON_SURF_TYPE_CUBEMAP:
        if (surf->npix_z > 1) {
            return -EINVAL;
        }
        /* deal with cubemap as they were texture array */
        if (surf_man->family >= CHIP_RV770) {
            surf->array_size = 8;
        } else {
            surf->array_size = 6;
        }
        break;
    case RADEON_SURF_TYPE_3D:
        break;
    case RADEON_SURF_TYPE_1D_ARRAY:
        if (surf->npix_y > 1) {
            return -EINVAL;
        }
    case RADEON_SURF_TYPE_2D_ARRAY:
        break;
    default:
        return -EINVAL;
    }
    return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void surf_minify ( struct radeon_surface surf,
unsigned  level,
uint32_t  xalign,
uint32_t  yalign,
uint32_t  zalign,
unsigned  offset 
) [static]

Definition at line 146 of file radeon_surface.c.

{
    surf->level[level].npix_x = mip_minify(surf->npix_x, level);
    surf->level[level].npix_y = mip_minify(surf->npix_y, level);
    surf->level[level].npix_z = mip_minify(surf->npix_z, level);
    surf->level[level].nblk_x = (surf->level[level].npix_x + surf->blk_w - 1) / surf->blk_w;
    surf->level[level].nblk_y = (surf->level[level].npix_y + surf->blk_h - 1) / surf->blk_h;
    surf->level[level].nblk_z = (surf->level[level].npix_z + surf->blk_d - 1) / surf->blk_d;
    if (surf->level[level].mode == RADEON_SURF_MODE_2D) {
        if (surf->level[level].nblk_x < xalign || surf->level[level].nblk_y < yalign) {
            surf->level[level].mode = RADEON_SURF_MODE_1D;
            return;
        }
    }
    surf->level[level].nblk_x  = ALIGN(surf->level[level].nblk_x, xalign);
    surf->level[level].nblk_y  = ALIGN(surf->level[level].nblk_y, yalign);
    surf->level[level].nblk_z  = ALIGN(surf->level[level].nblk_z, zalign);

    surf->level[level].offset = offset;
    surf->level[level].pitch_bytes = surf->level[level].nblk_x * surf->bpe;
    surf->level[level].slice_size = surf->level[level].pitch_bytes * surf->level[level].nblk_y;

    surf->bo_size = offset + surf->level[level].slice_size * surf->level[level].nblk_z * surf->array_size;
}

Here is the call graph for this function:

Here is the caller graph for this function: