diff options
author | Chia-I Wu <[email protected]> | 2012-12-13 04:44:21 +0800 |
---|---|---|
committer | Chia-I Wu <[email protected]> | 2013-04-26 16:16:42 +0800 |
commit | 3a4a570c34eb20d28c24d1fd18c9781740abf6e5 (patch) | |
tree | 0bc6645f379858152ff48d53c8cd54c1a2d79ccf /src/gallium/drivers/ilo | |
parent | b50e68cb67534bd9e648b5cb687949d9327ee011 (diff) |
ilo: hook up pipe screen resource functions
Diffstat (limited to 'src/gallium/drivers/ilo')
-rw-r--r-- | src/gallium/drivers/ilo/ilo_resource.c | 815 | ||||
-rw-r--r-- | src/gallium/drivers/ilo/ilo_resource.h | 46 |
2 files changed, 856 insertions, 5 deletions
diff --git a/src/gallium/drivers/ilo/ilo_resource.c b/src/gallium/drivers/ilo/ilo_resource.c index cfc29586bd9..7d5af3d297a 100644 --- a/src/gallium/drivers/ilo/ilo_resource.c +++ b/src/gallium/drivers/ilo/ilo_resource.c @@ -29,17 +29,822 @@ #include "ilo_screen.h" #include "ilo_resource.h" +static struct intel_bo * +alloc_buf_bo(const struct ilo_resource *res) +{ + struct ilo_screen *is = ilo_screen(res->base.screen); + struct intel_bo *bo; + const char *name; + const unsigned size = res->bo_width; + + switch (res->base.bind) { + case PIPE_BIND_VERTEX_BUFFER: + name = "vertex buffer"; + break; + case PIPE_BIND_INDEX_BUFFER: + name = "index buffer"; + break; + case PIPE_BIND_CONSTANT_BUFFER: + name = "constant buffer"; + break; + case PIPE_BIND_STREAM_OUTPUT: + name = "stream output"; + break; + default: + name = "unknown buffer"; + break; + } + + /* this is what a buffer supposed to be like */ + assert(res->bo_width * res->bo_height * res->bo_cpp == size); + assert(res->tiling == INTEL_TILING_NONE); + assert(res->bo_stride == 0); + + if (res->handle) { + bo = is->winsys->import_handle(is->winsys, name, + res->bo_width, res->bo_height, res->bo_cpp, res->handle); + + /* since the bo is shared to us, make sure it meets the expectations */ + if (bo) { + assert(bo->get_size(res->bo) == size); + assert(bo->get_tiling(res->bo) == res->tiling); + assert(bo->get_pitch(res->bo) == res->bo_stride); + } + } + else { + bo = is->winsys->alloc_buffer(is->winsys, name, size, 0); + } + + return bo; +} + +static struct intel_bo * +alloc_tex_bo(const struct ilo_resource *res) +{ + struct ilo_screen *is = ilo_screen(res->base.screen); + struct intel_bo *bo; + const char *name; + + switch (res->base.target) { + case PIPE_TEXTURE_1D: + name = "1D texture"; + break; + case PIPE_TEXTURE_2D: + name = "2D texture"; + break; + case PIPE_TEXTURE_3D: + name = "3D texture"; + break; + case PIPE_TEXTURE_CUBE: + name = "cube texture"; + break; + case PIPE_TEXTURE_RECT: + name = "rectangle texture"; + break; + case PIPE_TEXTURE_1D_ARRAY: + name = "1D array texture"; + break; + case PIPE_TEXTURE_2D_ARRAY: + name = "2D array texture"; + break; + case PIPE_TEXTURE_CUBE_ARRAY: + name = "cube array texture"; + break; + default: + name ="unknown texture"; + break; + } + + if (res->handle) { + bo = is->winsys->import_handle(is->winsys, name, + res->bo_width, res->bo_height, res->bo_cpp, res->handle); + } + else { + const bool for_render = + (res->base.bind & (PIPE_BIND_DEPTH_STENCIL | + PIPE_BIND_RENDER_TARGET)); + const unsigned long flags = + (for_render) ? INTEL_ALLOC_FOR_RENDER : 0; + + bo = is->winsys->alloc(is->winsys, name, + res->bo_width, res->bo_height, res->bo_cpp, + res->tiling, flags); + } + + return bo; +} + +static bool +realloc_bo(struct ilo_resource *res) +{ + struct intel_bo *old_bo = res->bo; + + /* a shared bo cannot be reallocated */ + if (old_bo && res->handle) + return false; + + if (res->base.target == PIPE_BUFFER) + res->bo = alloc_buf_bo(res); + else + res->bo = alloc_tex_bo(res); + + if (!res->bo) { + res->bo = old_bo; + return false; + } + + /* winsys may decide to use a different tiling */ + res->tiling = res->bo->get_tiling(res->bo); + res->bo_stride = res->bo->get_pitch(res->bo); + + if (old_bo) + old_bo->unreference(old_bo); + + return true; +} + +static bool +alloc_slice_offsets(struct ilo_resource *res) +{ + int depth, lv; + + /* sum the depths of all levels */ + depth = 0; + for (lv = 0; lv <= res->base.last_level; lv++) + depth += u_minify(res->base.depth0, lv); + + /* + * There are (depth * res->base.array_size) slices. Either depth is one + * (non-3D) or res->base.array_size is one (non-array), but it does not + * matter. + */ + res->slice_offsets[0] = + CALLOC(depth * res->base.array_size, sizeof(res->slice_offsets[0][0])); + if (!res->slice_offsets[0]) + return false; + + /* point to the respective positions in the buffer */ + for (lv = 1; lv <= res->base.last_level; lv++) { + res->slice_offsets[lv] = res->slice_offsets[lv - 1] + + u_minify(res->base.depth0, lv - 1) * res->base.array_size; + } + + return true; +} + +static void +free_slice_offsets(struct ilo_resource *res) +{ + int lv; + + FREE(res->slice_offsets[0]); + for (lv = 0; lv <= res->base.last_level; lv++) + res->slice_offsets[lv] = NULL; +} + +struct layout_tex_info { + bool compressed; + int block_width, block_height; + int align_i, align_j; + int qpitch; + + struct { + int w, h, d; + } sizes[PIPE_MAX_TEXTURE_LEVELS]; +}; + +/** + * Prepare for texture layout. + */ +static void +layout_tex_init(const struct ilo_resource *res, struct layout_tex_info *info) +{ + struct ilo_screen *is = ilo_screen(res->base.screen); + const enum intel_tiling_mode tiling = res->tiling; + const struct pipe_resource *templ = &res->base; + int last_level, lv; + + memset(info, 0, sizeof(*info)); + + info->compressed = util_format_is_compressed(templ->format); + info->block_width = util_format_get_blockwidth(templ->format); + info->block_height = util_format_get_blockheight(templ->format); + + /* + * From the Sandy Bridge PRM, volume 1 part 1, page 113: + * + * "surface format align_i align_j + * YUV 4:2:2 formats 4 *see below + * BC1-5 4 4 + * FXT1 8 4 + * all other formats 4 *see below" + * + * "- align_j = 4 for any depth buffer + * - align_j = 2 for separate stencil buffer + * - align_j = 4 for any render target surface is multisampled (4x) + * - align_j = 4 for any render target surface with Surface Vertical + * Alignment = VALIGN_4 + * - align_j = 2 for any render target surface with Surface Vertical + * Alignment = VALIGN_2 + * - align_j = 2 for all other render target surface + * - align_j = 2 for any sampling engine surface with Surface Vertical + * Alignment = VALIGN_2 + * - align_j = 4 for any sampling engine surface with Surface Vertical + * Alignment = VALIGN_4" + * + * From the Sandy Bridge PRM, volume 4 part 1, page 86: + * + * "This field (Surface Vertical Alignment) must be set to VALIGN_2 if + * the Surface Format is 96 bits per element (BPE)." + * + * They can be rephrased as + * + * align_i align_j + * compressed formats block width block height + * PIPE_FORMAT_S8_UINT 4 2 + * other depth/stencil formats 4 4 + * 4x multisampled 4 4 + * bpp 96 4 2 + * others 4 2 or 4 + */ + + /* + * From the Ivy Bridge PRM, volume 1 part 1, page 110: + * + * "surface defined by surface format align_i align_j + * 3DSTATE_DEPTH_BUFFER D16_UNORM 8 4 + * not D16_UNORM 4 4 + * 3DSTATE_STENCIL_BUFFER N/A 8 8 + * SURFACE_STATE BC*, ETC*, EAC* 4 4 + * FXT1 8 4 + * all others (set by SURFACE_STATE)" + * + * From the Ivy Bridge PRM, volume 4 part 1, page 63: + * + * "- This field (Surface Vertical Aligment) is intended to be set to + * VALIGN_4 if the surface was rendered as a depth buffer, for a + * multisampled (4x) render target, or for a multisampled (8x) + * render target, since these surfaces support only alignment of 4. + * - Use of VALIGN_4 for other surfaces is supported, but uses more + * memory. + * - This field must be set to VALIGN_4 for all tiled Y Render Target + * surfaces. + * - Value of 1 is not supported for format YCRCB_NORMAL (0x182), + * YCRCB_SWAPUVY (0x183), YCRCB_SWAPUV (0x18f), YCRCB_SWAPY (0x190) + * - If Number of Multisamples is not MULTISAMPLECOUNT_1, this field + * must be set to VALIGN_4." + * - VALIGN_4 is not supported for surface format R32G32B32_FLOAT." + * + * "- This field (Surface Horizontal Aligment) is intended to be set to + * HALIGN_8 only if the surface was rendered as a depth buffer with + * Z16 format or a stencil buffer, since these surfaces support only + * alignment of 8. + * - Use of HALIGN_8 for other surfaces is supported, but uses more + * memory. + * - This field must be set to HALIGN_4 if the Surface Format is BC*. + * - This field must be set to HALIGN_8 if the Surface Format is + * FXT1." + * + * They can be rephrased as + * + * align_i align_j + * compressed formats block width block height + * PIPE_FORMAT_Z16_UNORM 8 4 + * PIPE_FORMAT_S8_UINT 8 8 + * other depth/stencil formats 4 or 8 4 + * 2x or 4x multisampled 4 or 8 4 + * tiled Y 4 or 8 4 (if rt) + * PIPE_FORMAT_R32G32B32_FLOAT 4 or 8 2 + * others 4 or 8 2 or 4 + */ + + if (info->compressed) { + /* this happens to be the case */ + info->align_i = info->block_width; + info->align_j = info->block_height; + } + else if (util_format_is_depth_or_stencil(templ->format)) { + if (is->gen >= ILO_GEN(7)) { + switch (templ->format) { + case PIPE_FORMAT_Z16_UNORM: + info->align_i = 8; + info->align_j = 4; + break; + case PIPE_FORMAT_S8_UINT: + info->align_i = 8; + info->align_j = 8; + break; + default: + /* + * From the Ivy Bridge PRM, volume 2 part 1, page 319: + * + * "The 3 LSBs of both offsets (Depth Coordinate Offset Y and + * Depth Coordinate Offset X) must be zero to ensure correct + * alignment" + * + * We will make use of them and setting align_i to 8 help us meet + * the requirement. + */ + info->align_i = (templ->last_level > 0) ? 8 : 4; + info->align_j = 4; + break; + } + } + else { + switch (templ->format) { + case PIPE_FORMAT_S8_UINT: + info->align_i = 4; + info->align_j = 2; + break; + default: + info->align_i = 4; + info->align_j = 4; + break; + } + } + } + else { + const bool valign_4 = (templ->nr_samples > 1) || + (is->gen >= ILO_GEN(7) && + (templ->bind & PIPE_BIND_RENDER_TARGET) && + tiling == INTEL_TILING_Y); + + if (valign_4) + assert(util_format_get_blocksizebits(templ->format) != 96); + + info->align_i = 4; + info->align_j = (valign_4) ? 4 : 2; + } + + /* + * the fact that align i and j are multiples of block width and height + * respectively is what makes the size of the bo a multiple of the block + * size, slices start at block boundaries, and many of the computations + * work. + */ + assert(info->align_i % info->block_width == 0); + assert(info->align_j % info->block_height == 0); + + /* make sure align() works */ + assert(util_is_power_of_two(info->align_i) && + util_is_power_of_two(info->align_j)); + assert(util_is_power_of_two(info->block_width) && + util_is_power_of_two(info->block_height)); + + last_level = templ->last_level; + /* need at least 2 levels to compute qpitch below */ + if (templ->array_size > 1 && last_level == 0 && + templ->format != PIPE_FORMAT_S8_UINT) + last_level++; + + /* compute mip level sizes */ + for (lv = 0; lv <= last_level; lv++) { + int w, h, d; + + w = u_minify(templ->width0, lv); + h = u_minify(templ->height0, lv); + d = u_minify(templ->depth0, lv); + + /* + * From the Sandy Bridge PRM, volume 1 part 1, page 114: + * + * "The dimensions of the mip maps are first determined by applying + * the sizing algorithm presented in Non-Power-of-Two Mipmaps + * above. Then, if necessary, they are padded out to compression + * block boundaries." + */ + w = align(w, info->block_width); + h = align(h, info->block_height); + + /* + * From the Sandy Bridge PRM, volume 1 part 1, page 111: + * + * "If the surface is multisampled (4x), these values must be + * adjusted as follows before proceeding: + * + * W_L = ceiling(W_L / 2) * 4 + * H_L = ceiling(H_L / 2) * 4" + */ + if (templ->nr_samples > 1) { + w = align(w, 2) * 2; + h = align(h, 2) * 2; + } + + info->sizes[lv].w = w; + info->sizes[lv].h = h; + info->sizes[lv].d = d; + } + + if (templ->array_size > 1) { + const int h0 = align(info->sizes[0].h, info->align_j); + + if (templ->format == PIPE_FORMAT_S8_UINT) { + info->qpitch = h0; + } + else { + const int h1 = align(info->sizes[1].h, info->align_j); + + /* + * From the Sandy Bridge PRM, volume 1 part 1, page 115: + * + * "The following equation is used for surface formats other than + * compressed textures: + * + * QPitch = (h0 + h1 + 11j)" + * + * "The equation for compressed textures (BC* and FXT1 surface + * formats) follows: + * + * QPitch = (h0 + h1 + 11j) / 4" + * + * "[DevSNB] Errata: Sampler MSAA Qpitch will be 4 greater than + * the value calculated in the equation above, for every other + * odd Surface Height starting from 1 i.e. 1,5,9,13" + * + * To access the N-th slice, an offset of (Stride * QPitch * N) is + * added to the base address. The PRM divides QPitch by 4 for + * compressed formats because the block height for those formats are + * 4, and it wants QPitch to mean the number of memory rows, as + * opposed to texel rows, between slices. Since we use texel rows in + * res->slice_offsets, we do not need to divide QPitch by 4. + */ + info->qpitch = h0 + h1 + + ((is->gen >= ILO_GEN(7)) ? 12 : 11) * info->align_j; + + if (is->gen == ILO_GEN(6) && templ->nr_samples > 1 && + templ->height0 % 4 == 1) + info->qpitch += 4; + } + } +} + +/** + * Layout a 2D texture. + */ +static void +layout_tex_2d(struct ilo_resource *res, const struct layout_tex_info *info) +{ + const struct pipe_resource *templ = &res->base; + unsigned int level_x, level_y; + int lv; + + res->bo_width = 0; + res->bo_height = 0; + + level_x = 0; + level_y = 0; + for (lv = 0; lv <= templ->last_level; lv++) { + const unsigned int level_w = info->sizes[lv].w; + const unsigned int level_h = info->sizes[lv].h; + int slice; + + for (slice = 0; slice < templ->array_size; slice++) { + res->slice_offsets[lv][slice].x = level_x; + /* slices are qpitch apart in Y-direction */ + res->slice_offsets[lv][slice].y = level_y + info->qpitch * slice; + } + + /* extend the size of the monolithic bo to cover this mip level */ + if (res->bo_width < level_x + level_w) + res->bo_width = level_x + level_w; + if (res->bo_height < level_y + level_h) + res->bo_height = level_y + level_h; + + /* MIPLAYOUT_BELOW */ + if (lv == 1) + level_x += align(level_w, info->align_i); + else + level_y += align(level_h, info->align_j); + } + + /* we did not take slices into consideration in the computation above */ + res->bo_height += info->qpitch * (templ->array_size - 1); +} + +/** + * Layout a 3D texture. + */ +static void +layout_tex_3d(struct ilo_resource *res, const struct layout_tex_info *info) +{ + const struct pipe_resource *templ = &res->base; + unsigned int level_y; + int lv; + + res->bo_width = 0; + res->bo_height = 0; + + level_y = 0; + for (lv = 0; lv <= templ->last_level; lv++) { + const unsigned int level_w = info->sizes[lv].w; + const unsigned int level_h = info->sizes[lv].h; + const unsigned int level_d = info->sizes[lv].d; + const unsigned int slice_pitch = align(level_w, info->align_i); + const unsigned int slice_qpitch = align(level_h, info->align_j); + const unsigned int num_slices_per_row = 1 << lv; + int slice; + + for (slice = 0; slice < level_d; slice += num_slices_per_row) { + int i; + + for (i = 0; i < num_slices_per_row && slice + i < level_d; i++) { + res->slice_offsets[lv][slice + i].x = slice_pitch * i; + res->slice_offsets[lv][slice + i].y = level_y; + } + + /* move on to the next slice row */ + level_y += slice_qpitch; + } + + /* rightmost slice */ + slice = MIN2(num_slices_per_row, level_d) - 1; + + /* extend the size of the monolithic bo to cover this slice */ + if (res->bo_width < slice_pitch * slice + level_w) + res->bo_width = slice_pitch * slice + level_w; + if (lv == templ->last_level) + res->bo_height = (level_y - slice_qpitch) + level_h; + } +} + +/** + * Guess the texture size. For large textures, the errors are relative small. + */ +static size_t +guess_tex_size(const struct pipe_resource *templ, + enum intel_tiling_mode tiling) +{ + int bo_width, bo_height, bo_stride; + + /* HALIGN_8 and VALIGN_4 */ + bo_width = align(templ->width0, 8); + bo_height = align(templ->height0, 4); + + if (templ->target == PIPE_TEXTURE_3D) { + const int num_rows = util_next_power_of_two(templ->depth0); + int lv, sum; + + sum = bo_height * templ->depth0; + for (lv = 1; lv <= templ->last_level; lv++) + sum += u_minify(bo_height, lv) * u_minify(num_rows, lv); + + bo_height = sum; + } + else if (templ->last_level > 0) { + /* MIPLAYOUT_BELOW, ignore qpich */ + bo_height = (bo_height + u_minify(bo_height, 1)) * templ->array_size; + } + + bo_stride = util_format_get_stride(templ->format, bo_width); + + switch (tiling) { + case INTEL_TILING_X: + bo_stride = align(bo_stride, 512); + bo_height = align(bo_height, 8); + break; + case INTEL_TILING_Y: + bo_stride = align(bo_stride, 128); + bo_height = align(bo_height, 32); + break; + default: + bo_height = align(bo_height, 2); + break; + } + + return util_format_get_2d_size(templ->format, bo_stride, bo_height); +} + +static enum intel_tiling_mode +get_tex_tiling(const struct ilo_resource *res) +{ + const struct pipe_resource *templ = &res->base; + + /* + * From the Sandy Bridge PRM, volume 1 part 2, page 32: + * + * "Display/Overlay Y-Major not supported. + * X-Major required for Async Flips" + */ + if (unlikely(templ->bind & PIPE_BIND_SCANOUT)) + return INTEL_TILING_X; + + /* + * From the Sandy Bridge PRM, volume 3 part 2, page 158: + * + * "The cursor surface address must be 4K byte aligned. The cursor must + * be in linear memory, it cannot be tiled." + */ + if (unlikely(templ->bind & PIPE_BIND_CURSOR)) + return INTEL_TILING_NONE; + + /* + * From the Sandy Bridge PRM, volume 2 part 1, page 318: + * + * "[DevSNB+]: This field (Tiled Surface) must be set to TRUE. Linear + * Depth Buffer is not supported." + * + * "The Depth Buffer, if tiled, must use Y-Major tiling." + */ + if (templ->bind & PIPE_BIND_DEPTH_STENCIL) + return INTEL_TILING_Y; + + if (templ->bind & (PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW)) { + enum intel_tiling_mode tiling = INTEL_TILING_NONE; + + /* + * From the Sandy Bridge PRM, volume 1 part 2, page 32: + * + * "NOTE: 128BPE Format Color buffer ( render target ) MUST be + * either TileX or Linear." + * + * Also, heuristically set a minimum width/height for enabling tiling. + */ + if (util_format_get_blocksizebits(templ->format) == 128 && + (templ->bind & PIPE_BIND_RENDER_TARGET) && templ->width0 >= 64) + tiling = INTEL_TILING_X; + else if ((templ->width0 >= 32 && templ->height0 >= 16) || + (templ->width0 >= 16 && templ->height0 >= 32)) + tiling = INTEL_TILING_Y; + + /* make sure the bo can be mapped through GTT if tiled */ + if (tiling != INTEL_TILING_NONE) { + /* + * Usually only the first 256MB of the GTT is mappable. + * + * See also how intel_context::max_gtt_map_object_size is calculated. + */ + const size_t mappable_gtt_size = 256 * 1024 * 1024; + const size_t size = guess_tex_size(templ, tiling); + + /* be conservative */ + if (size > mappable_gtt_size / 4) + tiling = INTEL_TILING_NONE; + } + + return tiling; + } + + return INTEL_TILING_NONE; +} + +static void +init_texture(struct ilo_resource *res) +{ + const enum pipe_format format = res->base.format; + struct layout_tex_info info; + + /* determine tiling first as it may affect the layout */ + res->tiling = get_tex_tiling(res); + + layout_tex_init(res, &info); + + res->compressed = info.compressed; + res->block_width = info.block_width; + res->block_height = info.block_height; + res->halign_8 = (info.align_i == 8); + res->valign_4 = (info.align_j == 4); + + switch (res->base.target) { + case PIPE_TEXTURE_1D: + case PIPE_TEXTURE_2D: + case PIPE_TEXTURE_CUBE: + case PIPE_TEXTURE_RECT: + case PIPE_TEXTURE_1D_ARRAY: + case PIPE_TEXTURE_2D_ARRAY: + case PIPE_TEXTURE_CUBE_ARRAY: + layout_tex_2d(res, &info); + break; + case PIPE_TEXTURE_3D: + layout_tex_3d(res, &info); + break; + default: + assert(!"unknown resource target"); + break; + } + + /* in blocks */ + assert(res->bo_width % info.block_width == 0); + assert(res->bo_height % info.block_height == 0); + res->bo_width /= info.block_width; + res->bo_height /= info.block_height; + res->bo_cpp = util_format_get_blocksize(format); +} + +static void +init_buffer(struct ilo_resource *res) +{ + res->compressed = false; + res->block_width = 1; + res->block_height = 1; + res->halign_8 = false; + res->valign_4 = false; + + res->bo_width = res->base.width0; + res->bo_height = 1; + res->bo_cpp = 1; + res->bo_stride = 0; + res->tiling = INTEL_TILING_NONE; +} + +static struct pipe_resource * +create_resource(struct pipe_screen *screen, + const struct pipe_resource *templ, + struct winsys_handle *handle) +{ + struct ilo_resource *res; + + res = CALLOC_STRUCT(ilo_resource); + if (!res) + return NULL; + + res->base = *templ; + res->base.screen = screen; + pipe_reference_init(&res->base.reference, 1); + res->handle = handle; + + if (!alloc_slice_offsets(res)) { + FREE(res); + return NULL; + } + + if (templ->target == PIPE_BUFFER) + init_buffer(res); + else + init_texture(res); + + if (!realloc_bo(res)) { + free_slice_offsets(res); + FREE(res); + return NULL; + } + + return &res->base; +} + +static boolean +ilo_can_create_resource(struct pipe_screen *screen, + const struct pipe_resource *templ) +{ + /* + * We do not know if we will fail until we try to allocate the bo. + * So just set a limit on the texture size. + */ + const size_t max_size = 1 * 1024 * 1024 * 1024; + const size_t size = guess_tex_size(templ, INTEL_TILING_Y); + + return (size <= max_size); +} + +static struct pipe_resource * +ilo_resource_create(struct pipe_screen *screen, + const struct pipe_resource *templ) +{ + return create_resource(screen, templ, NULL); +} + +static struct pipe_resource * +ilo_resource_from_handle(struct pipe_screen *screen, + const struct pipe_resource *templ, + struct winsys_handle *handle) +{ + return create_resource(screen, templ, handle); +} + +static boolean +ilo_resource_get_handle(struct pipe_screen *screen, + struct pipe_resource *r, + struct winsys_handle *handle) +{ + struct ilo_resource *res = ilo_resource(r); + int err; + + err = res->bo->export_handle(res->bo, handle); + + return !err; +} + +static void +ilo_resource_destroy(struct pipe_screen *screen, + struct pipe_resource *r) +{ + struct ilo_resource *res = ilo_resource(r); + + free_slice_offsets(res); + res->bo->unreference(res->bo); + FREE(res); +} + /** * Initialize resource-related functions. */ void ilo_init_resource_functions(struct ilo_screen *is) { - is->base.can_create_resource = NULL; - is->base.resource_create = NULL; - is->base.resource_from_handle = NULL; - is->base.resource_get_handle = NULL; - is->base.resource_destroy = NULL; + is->base.can_create_resource = ilo_can_create_resource; + is->base.resource_create = ilo_resource_create; + is->base.resource_from_handle = ilo_resource_from_handle; + is->base.resource_get_handle = ilo_resource_get_handle; + is->base.resource_destroy = ilo_resource_destroy; } /** diff --git a/src/gallium/drivers/ilo/ilo_resource.h b/src/gallium/drivers/ilo/ilo_resource.h index bfc506de711..ed9a2fa6798 100644 --- a/src/gallium/drivers/ilo/ilo_resource.h +++ b/src/gallium/drivers/ilo/ilo_resource.h @@ -28,10 +28,56 @@ #ifndef ILO_RESOURCE_H #define ILO_RESOURCE_H +#include "intel_winsys.h" + #include "ilo_common.h" struct ilo_screen; struct ilo_context; +struct winsys_handle; + +/* + * TODO we should have + * + * ilo_resource, inherited by + * - ilo_buffer + * - ilo_texture + * - ilo_global_binding + */ +struct ilo_resource { + struct pipe_resource base; + struct winsys_handle *handle; + + struct intel_bo *bo; + + /* + * These are the values passed to or returned from winsys for bo + * allocation. As such, + * + * - width and height are in blocks, + * - cpp is the block size in bytes, and + * - stride is the distance in bytes between two block rows. + */ + int bo_width, bo_height, bo_cpp, bo_stride; + enum intel_tiling_mode tiling; + + bool compressed; + unsigned block_width; + unsigned block_height; + bool halign_8, valign_4; + + /* 2D offsets into a layer/slice/face */ + struct { + unsigned x; + unsigned y; + } *slice_offsets[PIPE_MAX_TEXTURE_LEVELS]; +}; + +static inline struct ilo_resource * +ilo_resource(struct pipe_resource *res) +{ + return (struct ilo_resource *) res; +} void ilo_init_resource_functions(struct ilo_screen *is); |