Path: blob/21.2-virgl/src/gallium/drivers/i915/i915_resource_texture.c
4570 views
/**************************************************************************1*2* Copyright 2006 VMware, Inc.3* All Rights Reserved.4*5* Permission is hereby granted, free of charge, to any person obtaining a6* copy of this software and associated documentation files (the7* "Software"), to deal in the Software without restriction, including8* without limitation the rights to use, copy, modify, merge, publish,9* distribute, sub license, and/or sell copies of the Software, and to10* permit persons to whom the Software is furnished to do so, subject to11* the following conditions:12*13* The above copyright notice and this permission notice (including the14* next paragraph) shall be included in all copies or substantial portions15* of the Software.16*17* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS18* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF19* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.20* IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR21* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,22* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE23* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.24*25**************************************************************************/26/*27* Authors:28* Keith Whitwell <[email protected]>29* Michel Dänzer <[email protected]>30*/3132#include "pipe/p_context.h"33#include "pipe/p_defines.h"34#include "pipe/p_state.h"35#include "util/format/u_format.h"36#include "util/u_inlines.h"37#include "util/u_math.h"38#include "util/u_memory.h"39#include "util/u_rect.h"4041#include "i915_context.h"42#include "i915_debug.h"43#include "i915_resource.h"44#include "i915_screen.h"45#include "i915_winsys.h"4647#define DEBUG_TEXTURES 04849/*50* Helper function and arrays51*/5253/**54* Initial offset for Cube map.55*/56static const int initial_offsets[6][2] = {57[PIPE_TEX_FACE_POS_X] = {0, 0}, [PIPE_TEX_FACE_POS_Y] = {1, 0},58[PIPE_TEX_FACE_POS_Z] = {1, 1}, [PIPE_TEX_FACE_NEG_X] = {0, 2},59[PIPE_TEX_FACE_NEG_Y] = {1, 2}, [PIPE_TEX_FACE_NEG_Z] = {1, 3},60};6162/**63* Step offsets for Cube map.64*/65static const int step_offsets[6][2] = {66[PIPE_TEX_FACE_POS_X] = {0, 2}, [PIPE_TEX_FACE_POS_Y] = {-1, 2},67[PIPE_TEX_FACE_POS_Z] = {-1, 1}, [PIPE_TEX_FACE_NEG_X] = {0, 2},68[PIPE_TEX_FACE_NEG_Y] = {-1, 2}, [PIPE_TEX_FACE_NEG_Z] = {-1, 1},69};7071/**72* For compressed level 273*/74static const int bottom_offsets[6] = {75[PIPE_TEX_FACE_POS_X] = 16 + 0 * 8, [PIPE_TEX_FACE_POS_Y] = 16 + 1 * 8,76[PIPE_TEX_FACE_POS_Z] = 16 + 2 * 8, [PIPE_TEX_FACE_NEG_X] = 16 + 3 * 8,77[PIPE_TEX_FACE_NEG_Y] = 16 + 4 * 8, [PIPE_TEX_FACE_NEG_Z] = 16 + 5 * 8,78};7980static inline unsigned81align_nblocksx(enum pipe_format format, unsigned width, unsigned align_to)82{83return align(util_format_get_nblocksx(format, width), align_to);84}8586static inline unsigned87align_nblocksy(enum pipe_format format, unsigned width, unsigned align_to)88{89return align(util_format_get_nblocksy(format, width), align_to);90}9192static inline unsigned93get_pot_stride(enum pipe_format format, unsigned width)94{95return util_next_power_of_two(util_format_get_stride(format, width));96}9798static inline const char *99get_tiling_string(enum i915_winsys_buffer_tile tile)100{101switch (tile) {102case I915_TILE_NONE:103return "none";104case I915_TILE_X:105return "x";106case I915_TILE_Y:107return "y";108default:109assert(false);110return "?";111}112}113114/*115* More advanced helper funcs116*/117118static void119i915_texture_set_level_info(struct i915_texture *tex, unsigned level,120unsigned nr_images)121{122assert(level < ARRAY_SIZE(tex->nr_images));123assert(nr_images);124assert(!tex->image_offset[level]);125126tex->nr_images[level] = nr_images;127tex->image_offset[level] = MALLOC(nr_images * sizeof(struct offset_pair));128tex->image_offset[level][0].nblocksx = 0;129tex->image_offset[level][0].nblocksy = 0;130}131132unsigned133i915_texture_offset(const struct i915_texture *tex, unsigned level,134unsigned layer)135{136unsigned x, y;137x = tex->image_offset[level][layer].nblocksx *138util_format_get_blocksize(tex->b.format);139y = tex->image_offset[level][layer].nblocksy;140141return y * tex->stride + x;142}143144static void145i915_texture_set_image_offset(struct i915_texture *tex, unsigned level,146unsigned img, unsigned nblocksx,147unsigned nblocksy)148{149/* for the first image and level make sure offset is zero */150assert(!(img == 0 && level == 0) || (nblocksx == 0 && nblocksy == 0));151assert(img < tex->nr_images[level]);152153tex->image_offset[level][img].nblocksx = nblocksx;154tex->image_offset[level][img].nblocksy = nblocksy;155156#if DEBUG_TEXTURES157debug_printf("%s: %p level %u, img %u (%u, %u)\n", __FUNCTION__, tex, level,158img, x, y);159#endif160}161162static enum i915_winsys_buffer_tile163i915_texture_tiling(struct i915_screen *is, struct i915_texture *tex)164{165if (!is->debug.tiling)166return I915_TILE_NONE;167168if (tex->b.target == PIPE_TEXTURE_1D)169return I915_TILE_NONE;170171if (util_format_is_s3tc(tex->b.format))172return I915_TILE_X;173174if (is->debug.use_blitter)175return I915_TILE_X;176else177return I915_TILE_Y;178}179180/*181* Shared layout functions182*/183184/**185* Special case to deal with scanout textures.186*/187static bool188i9x5_scanout_layout(struct i915_texture *tex)189{190struct pipe_resource *pt = &tex->b;191192if (pt->last_level > 0 || util_format_get_blocksize(pt->format) != 4)193return false;194195i915_texture_set_level_info(tex, 0, 1);196i915_texture_set_image_offset(tex, 0, 0, 0, 0);197198if (pt->width0 >= 240) {199tex->stride = align(util_format_get_stride(pt->format, pt->width0), 64);200tex->total_nblocksy = align_nblocksy(pt->format, pt->height0, 8);201tex->tiling = I915_TILE_X;202/* special case for cursors */203} else if (pt->width0 == 64 && pt->height0 == 64) {204tex->stride = get_pot_stride(pt->format, pt->width0);205tex->total_nblocksy = align_nblocksy(pt->format, pt->height0, 8);206} else {207return false;208}209210#if DEBUG_TEXTURE211debug_printf("%s size: %d,%d,%d offset %d,%d (0x%x)\n", __FUNCTION__,212pt->width0, pt->height0, util_format_get_blocksize(pt->format),213tex->stride, tex->total_nblocksy,214tex->stride * tex->total_nblocksy);215#endif216217return true;218}219220/**221* Special case to deal with shared textures.222*/223static bool224i9x5_display_target_layout(struct i915_texture *tex)225{226struct pipe_resource *pt = &tex->b;227228if (pt->last_level > 0 || util_format_get_blocksize(pt->format) != 4)229return false;230231/* fallback to normal textures for small textures */232if (pt->width0 < 240)233return false;234235i915_texture_set_level_info(tex, 0, 1);236i915_texture_set_image_offset(tex, 0, 0, 0, 0);237238tex->stride = align(util_format_get_stride(pt->format, pt->width0), 64);239tex->total_nblocksy = align_nblocksy(pt->format, pt->height0, 8);240tex->tiling = I915_TILE_X;241242#if DEBUG_TEXTURE243debug_printf("%s size: %d,%d,%d offset %d,%d (0x%x)\n", __FUNCTION__,244pt->width0, pt->height0, util_format_get_blocksize(pt->format),245tex->stride, tex->total_nblocksy,246tex->stride * tex->total_nblocksy);247#endif248249return true;250}251252/**253* Helper function for special layouts254*/255static bool256i9x5_special_layout(struct i915_texture *tex)257{258struct pipe_resource *pt = &tex->b;259260/* Scanouts needs special care */261if (pt->bind & PIPE_BIND_SCANOUT)262if (i9x5_scanout_layout(tex))263return true;264265/* Shared buffers needs to be compatible with X servers266*267* XXX: need a better name than shared for this if it is to be part268* of core gallium, and probably move the flag to resource.flags,269* rather than bindings.270*/271if (pt->bind & (PIPE_BIND_SHARED | PIPE_BIND_DISPLAY_TARGET))272if (i9x5_display_target_layout(tex))273return true;274275return false;276}277278/**279* Cube layout used on i915 and for non-compressed textures on i945.280*281* Hardware layout looks like:282*283* +-------+-------+284* | | |285* | | |286* | | |287* | +x | +y |288* | | |289* | | |290* | | |291* | | |292* +---+---+-------+293* | | | |294* | +x| +y| |295* | | | |296* | | | |297* +-+-+---+ +z |298* | | | | |299* +-+-+ +z| |300* | | | |301* +-+-+---+-------+302* | | |303* | | |304* | | |305* | -x | -y |306* | | |307* | | |308* | | |309* | | |310* +---+---+-------+311* | | | |312* | -x| -y| |313* | | | |314* | | | |315* +-+-+---+ -z |316* | | | | |317* +-+-+ -z| |318* | | | |319* +-+---+-------+320*321*/322static void323i9x5_texture_layout_cube(struct i915_texture *tex)324{325struct pipe_resource *pt = &tex->b;326unsigned width = util_next_power_of_two(pt->width0);327const unsigned nblocks = util_format_get_nblocksx(pt->format, width);328unsigned level;329unsigned face;330331assert(pt->width0 == pt->height0); /* cubemap images are square */332333/* double pitch for cube layouts */334tex->stride = align(nblocks * util_format_get_blocksize(pt->format) * 2, 4);335tex->total_nblocksy = nblocks * 4;336337for (level = 0; level <= pt->last_level; level++)338i915_texture_set_level_info(tex, level, 6);339340for (face = 0; face < 6; face++) {341unsigned x = initial_offsets[face][0] * nblocks;342unsigned y = initial_offsets[face][1] * nblocks;343unsigned d = nblocks;344345for (level = 0; level <= pt->last_level; level++) {346i915_texture_set_image_offset(tex, level, face, x, y);347d >>= 1;348x += step_offsets[face][0] * d;349y += step_offsets[face][1] * d;350}351}352}353354/*355* i915 layout functions356*/357358static void359i915_texture_layout_2d(struct i915_texture *tex)360{361struct pipe_resource *pt = &tex->b;362unsigned level;363unsigned width = util_next_power_of_two(pt->width0);364unsigned height = util_next_power_of_two(pt->height0);365unsigned nblocksy = util_format_get_nblocksy(pt->format, width);366unsigned align_y = 2;367368if (util_format_is_s3tc(pt->format))369align_y = 1;370371tex->stride = align(util_format_get_stride(pt->format, width), 4);372tex->total_nblocksy = 0;373374for (level = 0; level <= pt->last_level; level++) {375i915_texture_set_level_info(tex, level, 1);376i915_texture_set_image_offset(tex, level, 0, 0, tex->total_nblocksy);377378tex->total_nblocksy += nblocksy;379380width = u_minify(width, 1);381height = u_minify(height, 1);382nblocksy = align_nblocksy(pt->format, height, align_y);383}384}385386static void387i915_texture_layout_3d(struct i915_texture *tex)388{389struct pipe_resource *pt = &tex->b;390unsigned level;391392unsigned width = util_next_power_of_two(pt->width0);393unsigned height = util_next_power_of_two(pt->height0);394unsigned depth = util_next_power_of_two(pt->depth0);395unsigned nblocksy = util_format_get_nblocksy(pt->format, height);396unsigned stack_nblocksy = 0;397398/* Calculate the size of a single slice.399*/400tex->stride = align(util_format_get_stride(pt->format, width), 4);401402/* XXX: hardware expects/requires 9 levels at minimum.403*/404for (level = 0; level <= MAX2(8, pt->last_level); level++) {405i915_texture_set_level_info(tex, level, depth);406407stack_nblocksy += MAX2(2, nblocksy);408409width = u_minify(width, 1);410height = u_minify(height, 1);411nblocksy = util_format_get_nblocksy(pt->format, height);412}413414/* Fixup depth image_offsets:415*/416for (level = 0; level <= pt->last_level; level++) {417unsigned i;418for (i = 0; i < depth; i++)419i915_texture_set_image_offset(tex, level, i, 0, i * stack_nblocksy);420421depth = u_minify(depth, 1);422}423424/* Multiply slice size by texture depth for total size. It's425* remarkable how wasteful of memory the i915 texture layouts426* are. They are largely fixed in the i945.427*/428tex->total_nblocksy = stack_nblocksy * util_next_power_of_two(pt->depth0);429}430431static bool432i915_texture_layout(struct i915_texture *tex)433{434switch (tex->b.target) {435case PIPE_TEXTURE_1D:436case PIPE_TEXTURE_2D:437case PIPE_TEXTURE_RECT:438if (!i9x5_special_layout(tex))439i915_texture_layout_2d(tex);440break;441case PIPE_TEXTURE_3D:442i915_texture_layout_3d(tex);443break;444case PIPE_TEXTURE_CUBE:445i9x5_texture_layout_cube(tex);446break;447default:448assert(0);449return false;450}451452return true;453}454455/*456* i945 layout functions457*/458459static void460i945_texture_layout_2d(struct i915_texture *tex)461{462struct pipe_resource *pt = &tex->b;463int align_x = 4, align_y = 2;464unsigned level;465unsigned x = 0;466unsigned y = 0;467unsigned width = util_next_power_of_two(pt->width0);468unsigned height = util_next_power_of_two(pt->height0);469unsigned nblocksx = util_format_get_nblocksx(pt->format, width);470unsigned nblocksy = util_format_get_nblocksy(pt->format, height);471472if (util_format_is_s3tc(pt->format)) {473align_x = 1;474align_y = 1;475}476477tex->stride = align(util_format_get_stride(pt->format, width), 4);478479/* May need to adjust pitch to accommodate the placement of480* the 2nd mipmap level. This occurs when the alignment481* constraints of mipmap placement push the right edge of the482* 2nd mipmap level out past the width of its parent.483*/484if (pt->last_level > 0) {485unsigned mip1_nblocksx =486align_nblocksx(pt->format, u_minify(width, 1), align_x) +487util_format_get_nblocksx(pt->format, u_minify(width, 2));488489if (mip1_nblocksx > nblocksx)490tex->stride = mip1_nblocksx * util_format_get_blocksize(pt->format);491}492493/* Pitch must be a whole number of dwords494*/495tex->stride = align(tex->stride, 64);496tex->total_nblocksy = 0;497498for (level = 0; level <= pt->last_level; level++) {499i915_texture_set_level_info(tex, level, 1);500i915_texture_set_image_offset(tex, level, 0, x, y);501502/* Because the images are packed better, the final offset503* might not be the maximal one:504*/505tex->total_nblocksy = MAX2(tex->total_nblocksy, y + nblocksy);506507/* Layout_below: step right after second mipmap level.508*/509if (level == 1) {510x += nblocksx;511} else {512y += nblocksy;513}514515width = u_minify(width, 1);516height = u_minify(height, 1);517nblocksx = align_nblocksx(pt->format, width, align_x);518nblocksy = align_nblocksy(pt->format, height, align_y);519}520}521522static void523i945_texture_layout_3d(struct i915_texture *tex)524{525struct pipe_resource *pt = &tex->b;526unsigned width = util_next_power_of_two(pt->width0);527unsigned height = util_next_power_of_two(pt->height0);528unsigned depth = util_next_power_of_two(pt->depth0);529unsigned nblocksy = util_format_get_nblocksy(pt->format, width);530unsigned pack_x_pitch, pack_x_nr;531unsigned pack_y_pitch;532unsigned level;533534tex->stride = align(util_format_get_stride(pt->format, width), 4);535tex->total_nblocksy = 0;536537pack_y_pitch = MAX2(nblocksy, 2);538pack_x_pitch = tex->stride / util_format_get_blocksize(pt->format);539pack_x_nr = 1;540541for (level = 0; level <= pt->last_level; level++) {542int x = 0;543int y = 0;544unsigned q, j;545546i915_texture_set_level_info(tex, level, depth);547548for (q = 0; q < depth;) {549for (j = 0; j < pack_x_nr && q < depth; j++, q++) {550i915_texture_set_image_offset(tex, level, q, x,551y + tex->total_nblocksy);552x += pack_x_pitch;553}554555x = 0;556y += pack_y_pitch;557}558559tex->total_nblocksy += y;560561if (pack_x_pitch > 4) {562pack_x_pitch >>= 1;563pack_x_nr <<= 1;564assert(pack_x_pitch * pack_x_nr *565util_format_get_blocksize(pt->format) <=566tex->stride);567}568569if (pack_y_pitch > 2) {570pack_y_pitch >>= 1;571}572573width = u_minify(width, 1);574height = u_minify(height, 1);575depth = u_minify(depth, 1);576nblocksy = util_format_get_nblocksy(pt->format, height);577}578}579580/**581* Compressed cube texture map layout for i945 and later.582*583* The hardware layout looks like the 830-915 layout, except for the small584* sizes. A zoomed in view of the layout for 945 is:585*586* +-------+-------+587* | 8x8 | 8x8 |588* | | |589* | | |590* | +x | +y |591* | | |592* | | |593* | | |594* | | |595* +---+---+-------+596* |4x4| | 8x8 |597* | +x| | |598* | | | |599* | | | |600* +---+ | +z |601* |4x4| | |602* | +y| | |603* | | | |604* +---+ +-------+605*606* ...607*608* +-------+-------+609* | 8x8 | 8x8 |610* | | |611* | | |612* | -x | -y |613* | | |614* | | |615* | | |616* | | |617* +---+---+-------+618* |4x4| | 8x8 |619* | -x| | |620* | | | |621* | | | |622* +---+ | -z |623* |4x4| | |624* | -y| | |625* | | | |626* +---+ +---+---+---+---+---+---+---+---+---+627* |4x4| |4x4| |2x2| |2x2| |2x2| |2x2|628* | +z| | -z| | +x| | +y| | +z| | -x| ...629* | | | | | | | | | | | |630* +---+ +---+ +---+ +---+ +---+ +---+631*632* The bottom row continues with the remaining 2x2 then the 1x1 mip contents633* in order, with each of them aligned to a 8x8 block boundary. Thus, for634* 32x32 cube maps and smaller, the bottom row layout is going to dictate the635* pitch of the tree. For a tree with 4x4 images, the pitch is at least636* 14 * 8 = 112 texels, for 2x2 it is at least 12 * 8 texels, and for 1x1637* it is 6 * 8 texels.638*/639static void640i945_texture_layout_cube(struct i915_texture *tex)641{642struct pipe_resource *pt = &tex->b;643unsigned width = util_next_power_of_two(pt->width0);644const unsigned nblocks = util_format_get_nblocksx(pt->format, width);645const unsigned dim = width;646unsigned level;647unsigned face;648649assert(pt->width0 == pt->height0); /* cubemap images are square */650assert(util_format_is_s3tc(pt->format)); /* compressed only */651652/*653* Depending on the size of the largest images, pitch can be654* determined either by the old-style packing of cubemap faces,655* or the final row of 4x4, 2x2 and 1x1 faces below this.656*657* 64 * 2 / 4 = 32658* 14 * 2 = 28659*/660if (width >= 64)661tex->stride = nblocks * 2 * util_format_get_blocksize(pt->format);662else663tex->stride = 14 * 2 * util_format_get_blocksize(pt->format);664665/*666* Something similary apply for height as well.667*/668if (width >= 4)669tex->total_nblocksy = nblocks * 4 + 1;670else671tex->total_nblocksy = 1;672673/* Set all the levels to effectively occupy the whole rectangular region */674for (level = 0; level <= pt->last_level; level++)675i915_texture_set_level_info(tex, level, 6);676677for (face = 0; face < 6; face++) {678/* all calculations in pixels */679unsigned total_height = tex->total_nblocksy * 4;680unsigned x = initial_offsets[face][0] * dim;681unsigned y = initial_offsets[face][1] * dim;682unsigned d = dim;683684if (dim == 4 && face >= 4) {685x = (face - 4) * 8;686y = tex->total_nblocksy * 4 - 4; /* 4 = 1 block */687} else if (dim < 4 && (face > 0)) {688x = face * 8;689y = total_height - 4;690}691692for (level = 0; level <= pt->last_level; level++) {693i915_texture_set_image_offset(tex, level, face,694util_format_get_nblocksx(pt->format, x),695util_format_get_nblocksy(pt->format, y));696697d >>= 1;698699switch (d) {700case 4:701switch (face) {702case PIPE_TEX_FACE_POS_X:703case PIPE_TEX_FACE_NEG_X:704x += step_offsets[face][0] * d;705y += step_offsets[face][1] * d;706break;707case PIPE_TEX_FACE_POS_Y:708case PIPE_TEX_FACE_NEG_Y:709y += 12;710x -= 8;711break;712case PIPE_TEX_FACE_POS_Z:713case PIPE_TEX_FACE_NEG_Z:714y = total_height - 4;715x = (face - 4) * 8;716break;717}718break;719case 2:720y = total_height - 4;721x = bottom_offsets[face];722break;723case 1:724x += 48;725break;726default:727x += step_offsets[face][0] * d;728y += step_offsets[face][1] * d;729break;730}731}732}733}734735static bool736i945_texture_layout(struct i915_texture *tex)737{738switch (tex->b.target) {739case PIPE_TEXTURE_1D:740case PIPE_TEXTURE_2D:741case PIPE_TEXTURE_RECT:742if (!i9x5_special_layout(tex))743i945_texture_layout_2d(tex);744break;745case PIPE_TEXTURE_3D:746i945_texture_layout_3d(tex);747break;748case PIPE_TEXTURE_CUBE:749if (!util_format_is_s3tc(tex->b.format))750i9x5_texture_layout_cube(tex);751else752i945_texture_layout_cube(tex);753break;754default:755assert(0);756return false;757}758759return true;760}761762/*763* Screen texture functions764*/765766bool767i915_resource_get_handle(struct pipe_screen *screen,768struct pipe_context *context,769struct pipe_resource *texture,770struct winsys_handle *whandle, unsigned usage)771{772if (texture->target == PIPE_BUFFER)773return false;774775struct i915_screen *is = i915_screen(screen);776struct i915_texture *tex = i915_texture(texture);777struct i915_winsys *iws = is->iws;778779return iws->buffer_get_handle(iws, tex->buffer, whandle, tex->stride);780}781782void *783i915_texture_transfer_map(struct pipe_context *pipe,784struct pipe_resource *resource, unsigned level,785unsigned usage, const struct pipe_box *box,786struct pipe_transfer **ptransfer)787{788struct i915_context *i915 = i915_context(pipe);789struct i915_texture *tex = i915_texture(resource);790struct i915_transfer *transfer = slab_alloc_st(&i915->texture_transfer_pool);791bool use_staging_texture = false;792struct i915_winsys *iws = i915_screen(pipe->screen)->iws;793enum pipe_format format = resource->format;794unsigned offset;795char *map;796797if (!transfer)798return NULL;799800transfer->b.resource = resource;801transfer->b.level = level;802transfer->b.usage = usage;803transfer->b.box = *box;804transfer->b.stride = tex->stride;805transfer->staging_texture = NULL;806/* XXX: handle depth textures everyhwere*/807transfer->b.layer_stride = 0;808809/* if we use staging transfers, only support textures we can render to,810* because we need that for u_blitter */811if (i915->blitter &&812util_blitter_is_copy_supported(i915->blitter, resource, resource) &&813(usage & PIPE_MAP_WRITE) &&814!(usage &815(PIPE_MAP_READ | PIPE_MAP_DONTBLOCK | PIPE_MAP_UNSYNCHRONIZED)))816use_staging_texture = true;817818use_staging_texture = false;819820if (use_staging_texture) {821/*822* Allocate the untiled staging texture.823* If the alloc fails, transfer->staging_texture is NULL and we fallback824* to a map()825*/826transfer->staging_texture =827i915_texture_create(pipe->screen, resource, true);828}829830if (resource->target != PIPE_TEXTURE_3D &&831resource->target != PIPE_TEXTURE_CUBE)832assert(box->z == 0);833834if (transfer->staging_texture) {835tex = i915_texture(transfer->staging_texture);836} else {837/* TODO this is a sledgehammer */838tex = i915_texture(resource);839pipe->flush(pipe, NULL, 0);840}841842offset = i915_texture_offset(tex, transfer->b.level, box->z);843844map = iws->buffer_map(iws, tex->buffer,845(transfer->b.usage & PIPE_MAP_WRITE) ? true : false);846if (!map) {847pipe_resource_reference(&transfer->staging_texture, NULL);848FREE(transfer);849return NULL;850}851852*ptransfer = &transfer->b;853854return map + offset +855box->y / util_format_get_blockheight(format) * transfer->b.stride +856box->x / util_format_get_blockwidth(format) *857util_format_get_blocksize(format);858}859860void861i915_texture_transfer_unmap(struct pipe_context *pipe,862struct pipe_transfer *transfer)863{864struct i915_context *i915 = i915_context(pipe);865struct i915_transfer *itransfer = (struct i915_transfer *)transfer;866struct i915_texture *tex = i915_texture(itransfer->b.resource);867struct i915_winsys *iws = i915_screen(tex->b.screen)->iws;868869if (itransfer->staging_texture)870tex = i915_texture(itransfer->staging_texture);871872iws->buffer_unmap(iws, tex->buffer);873874if ((itransfer->staging_texture) && (transfer->usage & PIPE_MAP_WRITE)) {875struct pipe_box sbox;876877u_box_origin_2d(itransfer->b.box.width, itransfer->b.box.height, &sbox);878pipe->resource_copy_region(pipe, itransfer->b.resource,879itransfer->b.level, itransfer->b.box.x,880itransfer->b.box.y, itransfer->b.box.z,881itransfer->staging_texture, 0, &sbox);882pipe->flush(pipe, NULL, 0);883pipe_resource_reference(&itransfer->staging_texture, NULL);884}885886slab_free_st(&i915->texture_transfer_pool, itransfer);887}888889#if 0890static void i915_texture_subdata(struct pipe_context *pipe,891struct pipe_resource *resource,892unsigned level,893unsigned usage,894const struct pipe_box *box,895const void *data,896unsigned stride,897unsigned layer_stride)898{899struct pipe_transfer *transfer = NULL;900struct i915_transfer *itransfer = NULL;901const uint8_t *src_data = data;902unsigned i;903904transfer = pipe->transfer_get(pipe,905resource,906level,907usage,908box );909if (transfer == NULL)910goto out;911912itransfer = (struct i915_transfer*)transfer;913914if (itransfer->staging_texture) {915struct i915_texture *tex = i915_texture(itransfer->staging_texture);916enum pipe_format format = tex->b.format;917struct i915_winsys *iws = i915_screen(tex->b.screen)->iws;918size_t offset;919size_t size;920921offset = i915_texture_offset(tex, transfer->level, transfer->box.z);922923for (i = 0; i < box->depth; i++) {924if (!tex->b.last_level &&925tex->b.width0 == transfer->box.width) {926unsigned nby = util_format_get_nblocksy(format, transfer->box.y);927assert(!offset);928assert(!transfer->box.x);929assert(tex->stride == transfer->stride);930931offset += tex->stride * nby;932size = util_format_get_2d_size(format, transfer->stride,933transfer->box.height);934iws->buffer_write(iws, tex->buffer, offset, size, transfer->data);935936} else {937unsigned nby = util_format_get_nblocksy(format, transfer->box.y);938int i;939offset += util_format_get_stride(format, transfer->box.x);940size = transfer->stride;941942for (i = 0; i < nby; i++) {943iws->buffer_write(iws, tex->buffer, offset, size, transfer->data);944offset += tex->stride;945}946}947offset += layer_stride;948}949} else {950uint8_t *map = pipe_transfer_map(pipe, &itransfer->b);951if (map == NULL)952goto nomap;953954for (i = 0; i < box->depth; i++) {955util_copy_rect(map,956resource->format,957itransfer->b.stride, /* bytes */9580, 0,959box->width,960box->height,961src_data,962stride, /* bytes */9630, 0);964map += itransfer->b.layer_stride;965src_data += layer_stride;966}967nomap:968if (map)969pipe_transfer_unmap(pipe, &itransfer->b);970}971972out:973if (itransfer)974pipe_transfer_destroy(pipe, &itransfer->b);975}976#endif977978struct pipe_resource *979i915_texture_create(struct pipe_screen *screen,980const struct pipe_resource *template, bool force_untiled)981{982struct i915_screen *is = i915_screen(screen);983struct i915_winsys *iws = is->iws;984struct i915_texture *tex = CALLOC_STRUCT(i915_texture);985unsigned buf_usage = 0;986987if (!tex)988return NULL;989990tex->b = *template;991pipe_reference_init(&tex->b.reference, 1);992tex->b.screen = screen;993994if ((force_untiled) || (template->usage == PIPE_USAGE_STREAM))995tex->tiling = I915_TILE_NONE;996else997tex->tiling = i915_texture_tiling(is, tex);998999if (is->is_i945) {1000if (!i945_texture_layout(tex))1001goto fail;1002} else {1003if (!i915_texture_layout(tex))1004goto fail;1005}10061007/* for scanouts and cursors, cursors arn't scanouts */10081009/* XXX: use a custom flag for cursors, don't rely on magically1010* guessing that this is Xorg asking for a cursor1011*/1012if ((template->bind & PIPE_BIND_SCANOUT) && template->width0 != 64)1013buf_usage = I915_NEW_SCANOUT;1014else1015buf_usage = I915_NEW_TEXTURE;10161017tex->buffer = iws->buffer_create_tiled(1018iws, &tex->stride, tex->total_nblocksy, &tex->tiling, buf_usage);1019if (!tex->buffer)1020goto fail;10211022I915_DBG(DBG_TEXTURE, "%s: %p stride %u, blocks (%u, %u) tiling %s\n",1023__func__, tex, tex->stride,1024tex->stride / util_format_get_blocksize(tex->b.format),1025tex->total_nblocksy, get_tiling_string(tex->tiling));10261027return &tex->b;10281029fail:1030FREE(tex);1031return NULL;1032}10331034struct pipe_resource *1035i915_texture_from_handle(struct pipe_screen *screen,1036const struct pipe_resource *template,1037struct winsys_handle *whandle)1038{1039struct i915_screen *is = i915_screen(screen);1040struct i915_texture *tex;1041struct i915_winsys *iws = is->iws;1042struct i915_winsys_buffer *buffer;1043unsigned stride;1044enum i915_winsys_buffer_tile tiling;10451046assert(screen);10471048buffer = iws->buffer_from_handle(iws, whandle, template->height0, &tiling,1049&stride);10501051/* Only supports one type */1052if ((template->target != PIPE_TEXTURE_2D &&1053template->target != PIPE_TEXTURE_RECT) ||1054template->last_level != 0 || template->depth0 != 1) {1055return NULL;1056}10571058tex = CALLOC_STRUCT(i915_texture);1059if (!tex)1060return NULL;10611062tex->b = *template;1063pipe_reference_init(&tex->b.reference, 1);1064tex->b.screen = screen;10651066tex->stride = stride;1067tex->tiling = tiling;1068tex->total_nblocksy = align_nblocksy(tex->b.format, tex->b.height0, 8);10691070i915_texture_set_level_info(tex, 0, 1);1071i915_texture_set_image_offset(tex, 0, 0, 0, 0);10721073tex->buffer = buffer;10741075I915_DBG(DBG_TEXTURE, "%s: %p stride %u, blocks (%u, %u) tiling %s\n",1076__func__, tex, tex->stride,1077tex->stride / util_format_get_blocksize(tex->b.format),1078tex->total_nblocksy, get_tiling_string(tex->tiling));10791080return &tex->b;1081}108210831084