/** * Special case to deal with scanout textures. */ static boolean i915_scanout_layout(struct i915_texture *tex) { struct pipe_texture *pt = &tex->base; if (pt->last_level > 0 || util_format_get_blocksize(pt->format) != 4) return FALSE; i915_miptree_set_level_info(tex, 0, 1, pt->width0, pt->height0, 1); i915_miptree_set_image_offset(tex, 0, 0, 0, 0); if (pt->width0 >= 240) { tex->stride = power_of_two(util_format_get_stride(pt->format, pt->width0)); tex->total_nblocksy = align(util_format_get_nblocksy(pt->format, pt->height0), 8); tex->hw_tiled = INTEL_TILE_X; } else if (pt->width0 == 64 && pt->height0 == 64) { tex->stride = power_of_two(util_format_get_stride(pt->format, pt->width0)); tex->total_nblocksy = align(util_format_get_nblocksy(pt->format, pt->height0), 8); } else { return FALSE; } debug_printf("%s size: %d,%d,%d offset %d,%d (0x%x)\n", __FUNCTION__, pt->width0, pt->height0, util_format_get_blocksize(pt->format), tex->stride, tex->total_nblocksy, tex->stride * tex->total_nblocksy); return TRUE; }
static void i915_miptree_layout_2d(struct i915_texture *tex) { struct pipe_texture *pt = &tex->base; unsigned level; unsigned width = pt->width0; unsigned height = pt->height0; unsigned nblocksy = util_format_get_nblocksy(pt->format, pt->width0); /* used for scanouts that need special layouts */ if (pt->tex_usage & PIPE_TEXTURE_USAGE_PRIMARY) if (i915_scanout_layout(tex)) return; /* for shared buffers we use something very like scanout */ if (pt->tex_usage & PIPE_TEXTURE_USAGE_DISPLAY_TARGET) if (i915_display_target_layout(tex)) return; tex->stride = align(util_format_get_stride(pt->format, pt->width0), 4); tex->total_nblocksy = 0; for (level = 0; level <= pt->last_level; level++) { i915_miptree_set_level_info(tex, level, 1, width, height, 1); i915_miptree_set_image_offset(tex, level, 0, 0, tex->total_nblocksy); nblocksy = align(MAX2(2, nblocksy), 2); tex->total_nblocksy += nblocksy; width = u_minify(width, 1); height = u_minify(height, 1); nblocksy = util_format_get_nblocksy(pt->format, height); } }
static void r600_compressed_to_blittable(struct pipe_resource *tex, unsigned level, struct texture_orig_info *orig) { struct r600_resource_texture *rtex = (struct r600_resource_texture*)tex; struct r600_screen *rscreen = (struct r600_screen *)tex->screen; unsigned pixsize = util_format_get_blocksize(rtex->real_format); int new_format; int new_height, new_width; orig->format = tex->format; orig->width0 = tex->width0; orig->height0 = tex->height0; orig->npix0_x = rtex->surface.level[0].npix_x; orig->npix0_y = rtex->surface.level[0].npix_y; orig->npix_x = rtex->surface.level[level].npix_x; orig->npix_y = rtex->surface.level[level].npix_y; if (pixsize == 8) new_format = PIPE_FORMAT_R16G16B16A16_UINT; /* 64-bit block */ else new_format = PIPE_FORMAT_R32G32B32A32_UINT; /* 128-bit block */ new_width = util_format_get_nblocksx(tex->format, orig->width0); new_height = util_format_get_nblocksy(tex->format, orig->height0); tex->width0 = new_width; tex->height0 = new_height; tex->format = new_format; rtex->surface.level[0].npix_x = util_format_get_nblocksx(orig->format, orig->npix0_x); rtex->surface.level[0].npix_y = util_format_get_nblocksy(orig->format, orig->npix0_y); rtex->surface.level[level].npix_x = util_format_get_nblocksx(orig->format, orig->npix_x); rtex->surface.level[level].npix_y = util_format_get_nblocksy(orig->format, orig->npix_y); }
static INLINE void define_rect(struct pipe_resource *pt, unsigned level, unsigned z, unsigned x, unsigned y, unsigned w, unsigned h, struct nv30_rect *rect) { struct nv30_miptree *mt = nv30_miptree(pt); struct nv30_miptree_level *lvl = &mt->level[level]; rect->w = u_minify(pt->width0, level) << mt->ms_x; rect->w = util_format_get_nblocksx(pt->format, rect->w); rect->h = u_minify(pt->height0, level) << mt->ms_y; rect->h = util_format_get_nblocksy(pt->format, rect->h); rect->d = 1; rect->z = 0; if (mt->swizzled) { if (pt->target == PIPE_TEXTURE_3D) { rect->d = u_minify(pt->depth0, level); rect->z = z; z = 0; } rect->pitch = 0; } else { rect->pitch = lvl->pitch; } rect->bo = mt->base.bo; rect->domain = NOUVEAU_BO_VRAM; rect->offset = layer_offset(pt, level, z); rect->cpp = util_format_get_blocksize(pt->format); rect->x0 = util_format_get_nblocksx(pt->format, x) << mt->ms_x; rect->y0 = util_format_get_nblocksy(pt->format, y) << mt->ms_y; rect->x1 = rect->x0 + (w << mt->ms_x); rect->y1 = rect->y0 + (h << mt->ms_y); }
static void r600_resource_copy_region(struct pipe_context *ctx, struct pipe_resource *dst, unsigned dst_level, unsigned dstx, unsigned dsty, unsigned dstz, struct pipe_resource *src, unsigned src_level, const struct pipe_box *src_box) { struct r600_resource_texture *rsrc = (struct r600_resource_texture*)src; struct texture_orig_info orig_info[2]; struct pipe_box sbox; const struct pipe_box *psbox; boolean restore_orig[2]; memset(orig_info, 0, sizeof(orig_info)); /* Fallback for buffers. */ if (dst->target == PIPE_BUFFER && src->target == PIPE_BUFFER) { util_resource_copy_region(ctx, dst, dst_level, dstx, dsty, dstz, src, src_level, src_box); return; } if (rsrc->depth && !rsrc->is_flushing_texture) r600_texture_depth_flush(ctx, src, FALSE); restore_orig[0] = restore_orig[1] = FALSE; if (util_format_is_compressed(src->format)) { r600_compressed_to_blittable(src, src_level, &orig_info[0]); restore_orig[0] = TRUE; sbox.x = util_format_get_nblocksx(orig_info[0].format, src_box->x); sbox.y = util_format_get_nblocksy(orig_info[0].format, src_box->y); sbox.z = src_box->z; sbox.width = util_format_get_nblocksx(orig_info[0].format, src_box->width); sbox.height = util_format_get_nblocksy(orig_info[0].format, src_box->height); sbox.depth = src_box->depth; psbox=&sbox; } else psbox=src_box; if (util_format_is_compressed(dst->format)) { r600_compressed_to_blittable(dst, dst_level, &orig_info[1]); restore_orig[1] = TRUE; /* translate the dst box as well */ dstx = util_format_get_nblocksx(orig_info[1].format, dstx); dsty = util_format_get_nblocksy(orig_info[1].format, dsty); } r600_hw_copy_region(ctx, dst, dst_level, dstx, dsty, dstz, src, src_level, psbox); if (restore_orig[0]) r600_reset_blittable_to_compressed(src, src_level, &orig_info[0]); if (restore_orig[1]) r600_reset_blittable_to_compressed(dst, dst_level, &orig_info[1]); }
static struct pipe_transfer * nv30_miptree_transfer_new(struct pipe_context *pipe, struct pipe_resource *pt, unsigned level, unsigned usage, const struct pipe_box *box) { struct nv30_context *nv30 = nv30_context(pipe); struct nouveau_device *dev = nv30->screen->base.device; struct nv30_transfer *tx; int ret; tx = CALLOC_STRUCT(nv30_transfer); if (!tx) return NULL; pipe_resource_reference(&tx->base.resource, pt); tx->base.level = level; tx->base.usage = usage; tx->base.box = *box; tx->base.stride = util_format_get_nblocksx(pt->format, box->width) * util_format_get_blocksize(pt->format); tx->base.layer_stride = util_format_get_nblocksy(pt->format, box->height) * tx->base.stride; tx->nblocksx = util_format_get_nblocksx(pt->format, box->width); tx->nblocksy = util_format_get_nblocksy(pt->format, box->height); define_rect(pt, level, box->z, box->x, box->y, tx->nblocksx, tx->nblocksy, &tx->img); ret = nouveau_bo_new(dev, NOUVEAU_BO_GART | NOUVEAU_BO_MAP, 0, tx->base.layer_stride, NULL, &tx->tmp.bo); if (ret) { pipe_resource_reference(&tx->base.resource, NULL); FREE(tx); return NULL; } tx->tmp.domain = NOUVEAU_BO_GART; tx->tmp.offset = 0; tx->tmp.pitch = tx->base.stride; tx->tmp.cpp = tx->img.cpp; tx->tmp.w = tx->nblocksx; tx->tmp.h = tx->nblocksy; tx->tmp.d = 1; tx->tmp.x0 = 0; tx->tmp.y0 = 0; tx->tmp.x1 = tx->tmp.w; tx->tmp.y1 = tx->tmp.h; tx->tmp.z = 0; if (usage & PIPE_TRANSFER_READ) nv30_transfer_rect(nv30, NEAREST, &tx->img, &tx->tmp); return &tx->base; }
static void si_compressed_to_blittable(struct pipe_resource *tex, unsigned level, struct texture_orig_info *orig) { struct r600_texture *rtex = (struct r600_texture*)tex; unsigned pixsize = util_format_get_blocksize(rtex->resource.b.b.format); int new_format; int new_height, new_width; orig->format = tex->format; orig->width0 = tex->width0; orig->height0 = tex->height0; orig->npix0_x = rtex->surface.level[0].npix_x; orig->npix0_y = rtex->surface.level[0].npix_y; orig->npix_x = rtex->surface.level[level].npix_x; orig->npix_y = rtex->surface.level[level].npix_y; if (pixsize == 8) new_format = PIPE_FORMAT_R16G16B16A16_UINT; /* 64-bit block */ else new_format = PIPE_FORMAT_R32G32B32A32_UINT; /* 128-bit block */ new_width = util_format_get_nblocksx(tex->format, orig->width0); new_height = util_format_get_nblocksy(tex->format, orig->height0); tex->width0 = new_width; tex->height0 = new_height; tex->format = new_format; rtex->surface.level[0].npix_x = util_format_get_nblocksx(orig->format, orig->npix0_x); rtex->surface.level[0].npix_y = util_format_get_nblocksy(orig->format, orig->npix0_y); rtex->surface.level[level].npix_x = util_format_get_nblocksx(orig->format, orig->npix_x); rtex->surface.level[level].npix_y = util_format_get_nblocksy(orig->format, orig->npix_y); /* By dividing the dimensions by 4, we effectively decrement * last_level by 2, therefore the last 2 mipmap levels disappear and * aren't blittable. Note that the last 3 mipmap levels (4x4, 2x2, * 1x1) have equal slice sizes, which is an important assumption * for this to work. * * In order to make the last 2 mipmap levels blittable, we have to * add the slice size of the last mipmap level to the texture * address, so that even though the hw thinks it reads last_level-2, * it will actually read last_level-1, and if we add the slice size*2, * it will read last_level. That's how this workaround works. */ if (level > rtex->resource.b.b.last_level-2) rtex->mipmap_shift = level - (rtex->resource.b.b.last_level-2); }
void trace_dump_box_bytes(const void *data, struct pipe_resource *resource, const struct pipe_box *box, unsigned stride, unsigned slice_stride) { size_t size; /* * Only dump buffer transfers to avoid huge files. * TODO: Make this run-time configurable */ if (resource->target != PIPE_BUFFER) { size = 0; } else { enum pipe_format format = resource->format; if (slice_stride) size = box->depth * slice_stride; else if (stride) size = util_format_get_nblocksy(format, box->height) * stride; else { size = util_format_get_nblocksx(format, box->width) * util_format_get_blocksize(format); } } trace_dump_bytes(data, size); }
void debug_dump_surface(const char *prefix, struct pipe_surface *surface) { struct pipe_texture *texture; struct pipe_screen *screen; struct pipe_transfer *transfer; void *data; if (!surface) return; texture = surface->texture; screen = texture->screen; transfer = screen->get_tex_transfer(screen, texture, surface->face, surface->level, surface->zslice, PIPE_TRANSFER_READ, 0, 0, surface->width, surface->height); data = screen->transfer_map(screen, transfer); if(!data) goto error; debug_dump_image(prefix, texture->format, util_format_get_blocksize(texture->format), util_format_get_nblocksx(texture->format, transfer->width), util_format_get_nblocksy(texture->format, transfer->height), transfer->stride, data); screen->transfer_unmap(screen, transfer); error: screen->tex_transfer_destroy(transfer); }
void nv50_miptree_transfer_del(struct pipe_context *pcontext, struct pipe_transfer *ptx) { struct nv50_transfer *tx = (struct nv50_transfer *)ptx; struct nv50_miptree *mt = nv50_miptree(ptx->resource); struct pipe_resource *pt = ptx->resource; unsigned nx = util_format_get_nblocksx(pt->format, tx->base.box.width); unsigned ny = util_format_get_nblocksy(pt->format, tx->base.box.height); if (ptx->usage & PIPE_TRANSFER_WRITE) { struct pipe_screen *pscreen = pcontext->screen; nv50_transfer_rect_m2mf(pscreen, tx->bo, 0, tx->base.stride, tx->bo->tile_mode, 0, 0, 0, tx->nblocksx, tx->nblocksy, 1, mt->base.bo, tx->level_offset, tx->level_pitch, tx->level_tiling, tx->level_x, tx->level_y, tx->level_z, tx->nblocksx, tx->nblocksy, tx->level_depth, util_format_get_blocksize(pt->format), nx, ny, NOUVEAU_BO_GART, NOUVEAU_BO_VRAM | NOUVEAU_BO_GART); } nouveau_bo_ref(NULL, &tx->bo); pipe_resource_reference(&ptx->resource, NULL); FREE(ptx); }
/** * Return the size of the resource in bytes. */ unsigned util_resource_size(const struct pipe_resource *res) { unsigned width = res->width0; unsigned height = res->height0; unsigned depth = res->depth0; unsigned size = 0; unsigned level; for (level = 0; level <= res->last_level; level++) { unsigned slices; if (res->target == PIPE_TEXTURE_CUBE) slices = 6; else if (res->target == PIPE_TEXTURE_3D) slices = depth; else slices = res->array_size; size += (util_format_get_nblocksy(res->format, height) * util_format_get_stride(res->format, width) * slices); width = u_minify(width, 1); height = u_minify(height, 1); depth = u_minify(depth, 1); } return size; }
static struct pipe_surface * nv50_miptree_surface_new(struct pipe_screen *pscreen, struct pipe_texture *pt, unsigned face, unsigned level, unsigned zslice, unsigned flags) { struct nv50_miptree *mt = nv50_miptree(pt); struct nv50_miptree_level *lvl = &mt->level[level]; struct pipe_surface *ps; unsigned img = 0; if (pt->target == PIPE_TEXTURE_CUBE) img = face; ps = CALLOC_STRUCT(pipe_surface); if (!ps) return NULL; pipe_texture_reference(&ps->texture, pt); ps->format = pt->format; ps->width = u_minify(pt->width0, level); ps->height = u_minify(pt->height0, level); ps->usage = flags; pipe_reference_init(&ps->reference, 1); ps->face = face; ps->level = level; ps->zslice = zslice; ps->offset = lvl->image_offset[img]; if (pt->target == PIPE_TEXTURE_3D) { unsigned nb_h = util_format_get_nblocksy(pt->format, ps->height); ps->offset += get_zslice_offset(lvl->tile_mode, zslice, lvl->pitch, nb_h); } return ps; }
static struct sw_displaytarget * wayland_displaytarget_from_handle(struct sw_winsys *ws, const struct pipe_resource *templet, struct winsys_handle *whandle, unsigned *stride) { struct wayland_sw_displaytarget *wldt; unsigned nblocksy; if (!wayland_is_displaytarget_format_supported(ws, 0, templet->format)) return NULL; wldt = CALLOC_STRUCT(wayland_sw_displaytarget); if (!wldt) return NULL; wldt->fd = whandle->fd; wldt->stride = whandle->stride; wldt->width = templet->width0; wldt->height = templet->height0; wldt->format = templet->format; nblocksy = util_format_get_nblocksy(wldt->format, wldt->height); wldt->size = wldt->stride * nblocksy; wldt->map = NULL; *stride = wldt->stride; return (struct sw_displaytarget *) wldt; }
static unsigned setup_miptree(struct etna_resource *rsc, unsigned paddingX, unsigned paddingY, unsigned msaa_xscale, unsigned msaa_yscale) { struct pipe_resource *prsc = &rsc->base; unsigned level, size = 0; unsigned width = prsc->width0; unsigned height = prsc->height0; unsigned depth = prsc->depth0; for (level = 0; level <= prsc->last_level; level++) { struct etna_resource_level *mip = &rsc->levels[level]; mip->width = width; mip->height = height; mip->padded_width = align(width * msaa_xscale, paddingX); mip->padded_height = align(height * msaa_yscale, paddingY); mip->stride = util_format_get_stride(prsc->format, mip->padded_width); mip->offset = size; mip->layer_stride = mip->stride * util_format_get_nblocksy(prsc->format, mip->padded_height); mip->size = prsc->array_size * mip->layer_stride; /* align levels to 64 bytes to be able to render to them */ size += align(mip->size, ETNA_PE_ALIGNMENT) * depth; width = u_minify(width, 1); height = u_minify(height, 1); depth = u_minify(depth, 1); } return size; }
static void i915_texture_layout_2d(struct i915_texture *tex) { struct pipe_resource *pt = &tex->b.b; unsigned level; unsigned width = util_next_power_of_two(pt->width0); unsigned height = util_next_power_of_two(pt->height0); unsigned nblocksy = util_format_get_nblocksy(pt->format, width); unsigned align_y = 2; if (util_format_is_s3tc(pt->format)) align_y = 1; tex->stride = align(util_format_get_stride(pt->format, width), 4); tex->total_nblocksy = 0; for (level = 0; level <= pt->last_level; level++) { i915_texture_set_level_info(tex, level, 1); i915_texture_set_image_offset(tex, level, 0, 0, tex->total_nblocksy); tex->total_nblocksy += nblocksy; width = u_minify(width, 1); height = u_minify(height, 1); nblocksy = align_nblocksy(pt->format, height, align_y); } }
static void i915_texture_layout_3d(struct i915_texture *tex) { struct pipe_resource *pt = &tex->b.b; unsigned level; unsigned width = util_next_power_of_two(pt->width0); unsigned height = util_next_power_of_two(pt->height0); unsigned depth = util_next_power_of_two(pt->depth0); unsigned nblocksy = util_format_get_nblocksy(pt->format, height); unsigned stack_nblocksy = 0; /* Calculate the size of a single slice. */ tex->stride = align(util_format_get_stride(pt->format, width), 4); /* XXX: hardware expects/requires 9 levels at minimum. */ for (level = 0; level <= MAX2(8, pt->last_level); level++) { i915_texture_set_level_info(tex, level, depth); stack_nblocksy += MAX2(2, nblocksy); width = u_minify(width, 1); height = u_minify(height, 1); nblocksy = util_format_get_nblocksy(pt->format, height); } /* Fixup depth image_offsets: */ for (level = 0; level <= pt->last_level; level++) { unsigned i; for (i = 0; i < depth; i++) i915_texture_set_image_offset(tex, level, i, 0, i * stack_nblocksy); depth = u_minify(depth, 1); } /* Multiply slice size by texture depth for total size. It's * remarkable how wasteful of memory the i915 texture layouts * are. They are largely fixed in the i945. */ tex->total_nblocksy = stack_nblocksy * util_next_power_of_two(pt->depth0); }
static inline uint8_t * NineSurface9_GetSystemMemPointer(struct NineSurface9 *This, int x, int y) { unsigned x_offset = util_format_get_stride(This->base.info.format, x); y = util_format_get_nblocksy(This->base.info.format, y); assert(This->data); return This->data + (y * This->stride + x_offset); }
static inline uint8_t * NineVolume9_GetSystemMemPointer(struct NineVolume9 *This, int x, int y, int z) { unsigned x_offset = util_format_get_stride(This->info.format, x); y = util_format_get_nblocksy(This->info.format, y); assert(This->data); return This->data + (z * This->layer_stride + y * This->stride + x_offset); }
/** * Conventional allocation path for non-display textures: * Use a simple, maximally packed layout. */ static boolean softpipe_resource_layout(struct pipe_screen *screen, struct softpipe_resource *spr, boolean allocate) { struct pipe_resource *pt = &spr->base; unsigned level; unsigned width = pt->width0; unsigned height = pt->height0; unsigned depth = pt->depth0; uint64_t buffer_size = 0; for (level = 0; level <= pt->last_level; level++) { unsigned slices, nblocksy; nblocksy = util_format_get_nblocksy(pt->format, height); if (pt->target == PIPE_TEXTURE_CUBE) assert(pt->array_size == 6); if (pt->target == PIPE_TEXTURE_3D) slices = depth; else slices = pt->array_size; spr->stride[level] = util_format_get_stride(pt->format, width); spr->level_offset[level] = buffer_size; /* if row_stride * height > SP_MAX_TEXTURE_SIZE */ if ((uint64_t)spr->stride[level] * nblocksy > SP_MAX_TEXTURE_SIZE) { /* image too large */ return FALSE; } spr->img_stride[level] = spr->stride[level] * nblocksy; buffer_size += (uint64_t) spr->img_stride[level] * slices; width = u_minify(width, 1); height = u_minify(height, 1); depth = u_minify(depth, 1); } if (buffer_size > SP_MAX_TEXTURE_SIZE) return FALSE; if (allocate) { spr->data = align_malloc(buffer_size, 64); return spr->data != NULL; } else { return TRUE; } }
static unsigned r300_texture_get_nblocksy(struct r300_resource *tex, unsigned level, boolean *out_aligned_for_cbzb) { unsigned height, tile_height; height = u_minify(tex->tex.height0, level); /* Mipmapped and 3D textures must have their height aligned to POT. */ if ((tex->b.b.b.target != PIPE_TEXTURE_1D && tex->b.b.b.target != PIPE_TEXTURE_2D && tex->b.b.b.target != PIPE_TEXTURE_RECT) || tex->b.b.b.last_level != 0) { height = util_next_power_of_two(height); } if (util_format_is_plain(tex->b.b.b.format)) { tile_height = r300_get_pixel_alignment(tex->b.b.b.format, tex->b.b.b.nr_samples, tex->tex.microtile, tex->tex.macrotile[level], DIM_HEIGHT, 0); height = align(height, tile_height); /* See if the CBZB clear can be used on the buffer, * taking the texture size into account. */ if (out_aligned_for_cbzb) { if (tex->tex.macrotile[level]) { /* When clearing, the layer (width*height) is horizontally split * into two, and the upper and lower halves are cleared by the CB * and ZB units, respectively. Therefore, the number of macrotiles * in the Y direction must be even. */ /* Align the height so that there is an even number of macrotiles. * Do so for 3 or more macrotiles in the Y direction. */ if (level == 0 && tex->b.b.b.last_level == 0 && (tex->b.b.b.target == PIPE_TEXTURE_1D || tex->b.b.b.target == PIPE_TEXTURE_2D || tex->b.b.b.target == PIPE_TEXTURE_RECT) && height >= tile_height * 3) { height = align(height, tile_height * 2); } *out_aligned_for_cbzb = height % (tile_height * 2) == 0; } else { *out_aligned_for_cbzb = FALSE; } } } return util_format_get_nblocksy(tex->b.b.b.format, height); }
static struct sw_displaytarget * wayland_displaytarget_create(struct sw_winsys *ws, unsigned tex_usage, enum pipe_format format, unsigned width, unsigned height, unsigned alignment, unsigned *stride) { struct wayland_sw_displaytarget *wldt; unsigned nblocksy, format_stride; char filename[] = "/tmp/wayland-shm-XXXXXX"; if (!wayland_is_displaytarget_format_supported(ws, tex_usage, format)) return NULL; wldt = CALLOC_STRUCT(wayland_sw_displaytarget); if (!wldt) return NULL; wldt->map = NULL; wldt->format = format; wldt->width = width; wldt->height = height; format_stride = util_format_get_stride(format, width); wldt->stride = align(format_stride, alignment); nblocksy = util_format_get_nblocksy(format, height); wldt->size = wldt->stride * nblocksy; wldt->fd = mkstemp(filename); if (wldt->fd < 0) { FREE(wldt); return NULL; } if (ftruncate(wldt->fd, wldt->size) < 0) { unlink(filename); close(wldt->fd); FREE(wldt); return NULL; } unlink(filename); *stride = wldt->stride; return (struct sw_displaytarget *) wldt; }
static unsigned r300_texture_get_nblocksy(struct r300_texture* tex, unsigned level) { unsigned height, tile_height; height = u_minify(tex->tex.height0, level); if (!util_format_is_compressed(tex->tex.format)) { tile_height = r300_texture_get_tile_size(tex, TILE_HEIGHT, tex->mip_macrotile[level]); height = align(height, tile_height); } return util_format_get_nblocksy(tex->tex.format, height); }
static void i945_texture_layout_3d(struct i915_texture *tex) { struct pipe_resource *pt = &tex->b.b; unsigned width = util_next_power_of_two(pt->width0); unsigned height = util_next_power_of_two(pt->height0); unsigned depth = util_next_power_of_two(pt->depth0); unsigned nblocksy = util_format_get_nblocksy(pt->format, width); unsigned pack_x_pitch, pack_x_nr; unsigned pack_y_pitch; unsigned level; tex->stride = align(util_format_get_stride(pt->format, width), 4); tex->total_nblocksy = 0; pack_y_pitch = MAX2(nblocksy, 2); pack_x_pitch = tex->stride / util_format_get_blocksize(pt->format); pack_x_nr = 1; for (level = 0; level <= pt->last_level; level++) { int x = 0; int y = 0; unsigned q, j; i915_texture_set_level_info(tex, level, depth); for (q = 0; q < depth;) { for (j = 0; j < pack_x_nr && q < depth; j++, q++) { i915_texture_set_image_offset(tex, level, q, x, y + tex->total_nblocksy); x += pack_x_pitch; } x = 0; y += pack_y_pitch; } tex->total_nblocksy += y; if (pack_x_pitch > 4) { pack_x_pitch >>= 1; pack_x_nr <<= 1; assert(pack_x_pitch * pack_x_nr * util_format_get_blocksize(pt->format) <= tex->stride); } if (pack_y_pitch > 2) { pack_y_pitch >>= 1; }
static struct sw_displaytarget * xlib_displaytarget_create(struct sw_winsys *winsys, unsigned tex_usage, enum pipe_format format, unsigned width, unsigned height, unsigned alignment, unsigned *stride) { struct xlib_displaytarget *xlib_dt; unsigned nblocksy, size; xlib_dt = CALLOC_STRUCT(xlib_displaytarget); if (!xlib_dt) goto no_xlib_dt; xlib_dt->display = ((struct xlib_sw_winsys *)winsys)->display; xlib_dt->format = format; xlib_dt->width = width; xlib_dt->height = height; nblocksy = util_format_get_nblocksy(format, height); xlib_dt->stride = align(util_format_get_stride(format, width), alignment); size = xlib_dt->stride * nblocksy; if (!debug_get_option_xlib_no_shm()) { xlib_dt->data = alloc_shm(xlib_dt, size); if (xlib_dt->data) { xlib_dt->shm = True; } } if (!xlib_dt->data) { xlib_dt->data = align_malloc(size, alignment); if (!xlib_dt->data) goto no_data; } *stride = xlib_dt->stride; return (struct sw_displaytarget *)xlib_dt; no_data: FREE(xlib_dt); no_xlib_dt: return NULL; }
void trace_dump_box_bytes(const void *data, enum pipe_format format, const struct pipe_box *box, unsigned stride, unsigned slice_stride) { size_t size; if (slice_stride) size = box->depth * slice_stride; else if (stride) size = util_format_get_nblocksy(format, box->height) * stride; else { size = util_format_get_nblocksx(format, box->width) * util_format_get_blocksize(format); } trace_dump_bytes(data, size); }
static struct pipe_buffer* xsp_surface_buffer_create ( struct pipe_winsys *pws, unsigned width, unsigned height, enum pipe_format format, unsigned usage, unsigned tex_usage, unsigned *stride ) { const unsigned int ALIGNMENT = 1; unsigned nblocksy; nblocksy = util_format_get_nblocksy(format, height); *stride = align(util_format_get_stride(format, width), ALIGNMENT); return pws->buffer_create(pws, ALIGNMENT, usage, *stride * nblocksy); }
int virgl_vtest_recv_transfer_get_data(struct virgl_vtest_winsys *vws, void *data, uint32_t data_size, uint32_t stride, const struct pipe_box *box, uint32_t format) { void *line; void *ptr = data; int hblocks = util_format_get_nblocksy(format, box->height); line = malloc(stride); while (hblocks) { virgl_block_read(vws->sock_fd, line, stride); memcpy(ptr, line, util_format_get_stride(format, box->width)); ptr += stride; hblocks--; } free(line); return 0; }
/* FIXME: dump resources, not surfaces... */ void debug_dump_surface(struct pipe_context *pipe, const char *prefix, struct pipe_surface *surface) { struct pipe_resource *texture; struct pipe_transfer *transfer; void *data; if (!surface) return; /* XXX: this doesn't necessarily work, as the driver may be using * temporary storage for the surface which hasn't been propagated * back into the texture. Need to nail down the semantics of views * and transfers a bit better before we can say if extra work needs * to be done here: */ texture = surface->texture; transfer = pipe_get_transfer(pipe, texture, surface->u.tex.level, surface->u.tex.first_layer, PIPE_TRANSFER_READ, 0, 0, surface->width, surface->height); data = pipe->transfer_map(pipe, transfer); if(!data) goto error; debug_dump_image(prefix, texture->format, util_format_get_blocksize(texture->format), util_format_get_nblocksx(texture->format, surface->width), util_format_get_nblocksy(texture->format, surface->height), transfer->stride, data); pipe->transfer_unmap(pipe, transfer); error: pipe->transfer_destroy(pipe, transfer); }
static void fd_resource_flush_rgtc(struct fd_transfer *trans, const struct pipe_box *box) { struct fd_resource *rsc = fd_resource(trans->base.resource); struct fd_resource_slice *slice = fd_resource_slice(rsc, trans->base.level); enum pipe_format format = trans->base.resource->format; uint8_t *data = fd_bo_map(rsc->bo) + slice->offset + fd_resource_layer_offset(rsc, slice, trans->base.box.z) + ((trans->base.box.y + box->y) * slice->pitch + trans->base.box.x + box->x) * rsc->cpp; uint8_t *source = trans->staging + util_format_get_nblocksy(format, box->y) * trans->base.stride + util_format_get_stride(format, box->x); switch (format) { case PIPE_FORMAT_RGTC1_UNORM: case PIPE_FORMAT_RGTC1_SNORM: case PIPE_FORMAT_LATC1_UNORM: case PIPE_FORMAT_LATC1_SNORM: util_format_rgtc1_unorm_unpack_rgba_8unorm( data, slice->pitch * rsc->cpp, source, trans->base.stride, box->width, box->height); break; case PIPE_FORMAT_RGTC2_UNORM: case PIPE_FORMAT_RGTC2_SNORM: case PIPE_FORMAT_LATC2_UNORM: case PIPE_FORMAT_LATC2_SNORM: util_format_rgtc2_unorm_unpack_rgba_8unorm( data, slice->pitch * rsc->cpp, source, trans->base.stride, box->width, box->height); break; default: assert(!"Unexpected format\n"); break; } }
/** * Helper function to compute offset (in bytes) for a particular * texture level/face/slice from the start of the buffer. */ static unsigned sp_get_tex_image_offset(const struct softpipe_resource *spr, unsigned level, unsigned layer) { const unsigned hgt = u_minify(spr->base.height0, level); const unsigned nblocksy = util_format_get_nblocksy(spr->base.format, hgt); unsigned offset = spr->level_offset[level]; if (spr->base.target == PIPE_TEXTURE_CUBE || spr->base.target == PIPE_TEXTURE_3D || spr->base.target == PIPE_TEXTURE_2D_ARRAY) { offset += layer * nblocksy * spr->stride[level]; } else if (spr->base.target == PIPE_TEXTURE_1D_ARRAY) { offset += layer * spr->stride[level]; } else { assert(layer == 0); } return offset; }