static int r600_init_surface(struct radeon_surface *surface, const struct pipe_resource *ptex, unsigned array_mode) { surface->npix_x = ptex->width0; surface->npix_y = ptex->height0; surface->npix_z = ptex->depth0; surface->blk_w = util_format_get_blockwidth(ptex->format); surface->blk_h = util_format_get_blockheight(ptex->format); surface->blk_d = 1; surface->array_size = 1; surface->last_level = ptex->last_level; surface->bpe = util_format_get_blocksize(ptex->format); /* align byte per element on dword */ if (surface->bpe == 3) { surface->bpe = 4; } surface->nsamples = 1; surface->flags = 0; switch (array_mode) { case V_009910_ARRAY_1D_TILED_THIN1: surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE); break; case V_009910_ARRAY_2D_TILED_THIN1: surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE); break; case V_009910_ARRAY_LINEAR_ALIGNED: surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_LINEAR_ALIGNED, MODE); break; case V_009910_ARRAY_LINEAR_GENERAL: default: surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_LINEAR, MODE); break; } switch (ptex->target) { case PIPE_TEXTURE_1D: surface->flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_1D, TYPE); break; case PIPE_TEXTURE_RECT: case PIPE_TEXTURE_2D: surface->flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_2D, TYPE); break; case PIPE_TEXTURE_3D: surface->flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_3D, TYPE); break; case PIPE_TEXTURE_1D_ARRAY: surface->flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_1D_ARRAY, TYPE); surface->array_size = ptex->array_size; break; case PIPE_TEXTURE_2D_ARRAY: surface->flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_2D_ARRAY, TYPE); surface->array_size = ptex->array_size; break; case PIPE_TEXTURE_CUBE: surface->flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_CUBEMAP, TYPE); break; case PIPE_BUFFER: default: return -EINVAL; } if (ptex->bind & PIPE_BIND_SCANOUT) { surface->flags |= RADEON_SURF_SCANOUT; } if (util_format_is_depth_and_stencil(ptex->format)) { surface->flags |= RADEON_SURF_ZBUFFER; surface->flags |= RADEON_SURF_SBUFFER; } return 0; }
/* XXX: Still implementing this as if it was a screen function, but * can now modify it to queue transfers on the context. */ static struct pipe_transfer * svga_texture_get_transfer(struct pipe_context *pipe, struct pipe_resource *texture, unsigned level, unsigned usage, const struct pipe_box *box) { struct svga_context *svga = svga_context(pipe); struct svga_screen *ss = svga_screen(pipe->screen); struct svga_winsys_screen *sws = ss->sws; struct svga_transfer *st; unsigned nblocksx = util_format_get_nblocksx(texture->format, box->width); unsigned nblocksy = util_format_get_nblocksy(texture->format, box->height); /* We can't map texture storage directly */ if (usage & PIPE_TRANSFER_MAP_DIRECTLY) return NULL; assert(box->depth == 1); st = CALLOC_STRUCT(svga_transfer); if (!st) return NULL; pipe_resource_reference(&st->base.resource, texture); st->base.level = level; st->base.usage = usage; st->base.box = *box; st->base.stride = nblocksx*util_format_get_blocksize(texture->format); st->base.layer_stride = 0; st->hw_nblocksy = nblocksy; st->hwbuf = svga_winsys_buffer_create(svga, 1, 0, st->hw_nblocksy*st->base.stride); while(!st->hwbuf && (st->hw_nblocksy /= 2)) { st->hwbuf = svga_winsys_buffer_create(svga, 1, 0, st->hw_nblocksy*st->base.stride); } if(!st->hwbuf) goto no_hwbuf; if(st->hw_nblocksy < nblocksy) { /* We couldn't allocate a hardware buffer big enough for the transfer, * so allocate regular malloc memory instead */ if (0) { debug_printf("%s: failed to allocate %u KB of DMA, " "splitting into %u x %u KB DMA transfers\n", __FUNCTION__, (nblocksy*st->base.stride + 1023)/1024, (nblocksy + st->hw_nblocksy - 1)/st->hw_nblocksy, (st->hw_nblocksy*st->base.stride + 1023)/1024); } st->swbuf = MALLOC(nblocksy*st->base.stride); if(!st->swbuf) goto no_swbuf; } if (usage & PIPE_TRANSFER_READ) { SVGA3dSurfaceDMAFlags flags; memset(&flags, 0, sizeof flags); svga_transfer_dma(svga, st, SVGA3D_READ_HOST_VRAM, flags); } return &st->base; no_swbuf: sws->buffer_destroy(sws, st->hwbuf); no_hwbuf: FREE(st); return NULL; }
/** * Called during state validation when LP_NEW_SAMPLER_VIEW is set. */ void lp_setup_set_fragment_sampler_views(struct lp_setup_context *setup, unsigned num, struct pipe_sampler_view **views) { unsigned i; LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__); assert(num <= PIPE_MAX_SHADER_SAMPLER_VIEWS); for (i = 0; i < PIPE_MAX_SHADER_SAMPLER_VIEWS; i++) { struct pipe_sampler_view *view = i < num ? views[i] : NULL; if (view) { struct pipe_resource *res = view->texture; struct llvmpipe_resource *lp_tex = llvmpipe_resource(res); struct lp_jit_texture *jit_tex; jit_tex = &setup->fs.current.jit_context.textures[i]; /* We're referencing the texture's internal data, so save a * reference to it. */ pipe_resource_reference(&setup->fs.current_tex[i], res); if (!lp_tex->dt) { /* regular texture - setup array of mipmap level offsets */ int j; unsigned first_level = 0; unsigned last_level = 0; if (llvmpipe_resource_is_texture(res)) { first_level = view->u.tex.first_level; last_level = view->u.tex.last_level; assert(first_level <= last_level); assert(last_level <= res->last_level); jit_tex->base = lp_tex->tex_data; } else { jit_tex->base = lp_tex->data; } if (LP_PERF & PERF_TEX_MEM) { /* use dummy tile memory */ jit_tex->base = lp_dummy_tile; jit_tex->width = TILE_SIZE/8; jit_tex->height = TILE_SIZE/8; jit_tex->depth = 1; jit_tex->first_level = 0; jit_tex->last_level = 0; jit_tex->mip_offsets[0] = 0; jit_tex->row_stride[0] = 0; jit_tex->img_stride[0] = 0; } else { jit_tex->width = res->width0; jit_tex->height = res->height0; jit_tex->depth = res->depth0; jit_tex->first_level = first_level; jit_tex->last_level = last_level; if (llvmpipe_resource_is_texture(res)) { for (j = first_level; j <= last_level; j++) { jit_tex->mip_offsets[j] = lp_tex->mip_offsets[j]; jit_tex->row_stride[j] = lp_tex->row_stride[j]; jit_tex->img_stride[j] = lp_tex->img_stride[j]; } if (res->target == PIPE_TEXTURE_1D_ARRAY || res->target == PIPE_TEXTURE_2D_ARRAY || res->target == PIPE_TEXTURE_CUBE || res->target == PIPE_TEXTURE_CUBE_ARRAY) { /* * For array textures, we don't have first_layer, instead * adjust last_layer (stored as depth) plus the mip level offsets * (as we have mip-first layout can't just adjust base ptr). * XXX For mip levels, could do something similar. */ jit_tex->depth = view->u.tex.last_layer - view->u.tex.first_layer + 1; for (j = first_level; j <= last_level; j++) { jit_tex->mip_offsets[j] += view->u.tex.first_layer * lp_tex->img_stride[j]; } if (view->target == PIPE_TEXTURE_CUBE || view->target == PIPE_TEXTURE_CUBE_ARRAY) { assert(jit_tex->depth % 6 == 0); } assert(view->u.tex.first_layer <= view->u.tex.last_layer); assert(view->u.tex.last_layer < res->array_size); } } else { /* * For buffers, we don't have first_element, instead adjust * last_element (stored as width) plus the base pointer. */ unsigned view_blocksize = util_format_get_blocksize(view->format); /* probably don't really need to fill that out */ jit_tex->mip_offsets[0] = 0; jit_tex->row_stride[0] = 0; jit_tex->img_stride[0] = 0; /* everything specified in number of elements here. */ jit_tex->width = view->u.buf.last_element - view->u.buf.first_element + 1; jit_tex->base = (uint8_t *)jit_tex->base + view->u.buf.first_element * view_blocksize; /* XXX Unsure if we need to sanitize parameters? */ assert(view->u.buf.first_element <= view->u.buf.last_element); assert(view->u.buf.last_element * view_blocksize < res->width0); } } } else { /* display target texture/surface */ /* * XXX: Where should this be unmapped? */ struct llvmpipe_screen *screen = llvmpipe_screen(res->screen); struct sw_winsys *winsys = screen->winsys; jit_tex->base = winsys->displaytarget_map(winsys, lp_tex->dt, PIPE_TRANSFER_READ); jit_tex->row_stride[0] = lp_tex->row_stride[0]; jit_tex->img_stride[0] = lp_tex->img_stride[0]; jit_tex->mip_offsets[0] = 0; jit_tex->width = res->width0; jit_tex->height = res->height0; jit_tex->depth = res->depth0; jit_tex->first_level = jit_tex->last_level = 0; assert(jit_tex->base); } } } setup->dirty |= LP_SETUP_NEW_FS; }
/** * Display/copy the image in the surface into the X window specified * by the display target. */ static void xlib_sw_display(struct xlib_drawable *xlib_drawable, struct sw_displaytarget *dt) { static boolean no_swap = 0; static boolean firsttime = 1; struct xlib_displaytarget *xlib_dt = xlib_displaytarget(dt); Display *display = xlib_dt->display; XImage *ximage; if (firsttime) { no_swap = getenv("SP_NO_RAST") != NULL; firsttime = 0; } if (no_swap) return; if (xlib_dt->drawable != xlib_drawable->drawable) { if (xlib_dt->gc) { XFreeGC(display, xlib_dt->gc); xlib_dt->gc = NULL; } if (xlib_dt->tempImage) { XDestroyImage(xlib_dt->tempImage); xlib_dt->tempImage = NULL; } xlib_dt->drawable = xlib_drawable->drawable; } if (xlib_dt->tempImage == NULL) { assert(util_format_get_blockwidth(xlib_dt->format) == 1); assert(util_format_get_blockheight(xlib_dt->format) == 1); alloc_ximage(xlib_dt, xlib_drawable, xlib_dt->stride / util_format_get_blocksize(xlib_dt->format), xlib_dt->height); if (!xlib_dt->tempImage) return; } if (xlib_dt->gc == NULL) { xlib_dt->gc = XCreateGC(display, xlib_drawable->drawable, 0, NULL); XSetFunction(display, xlib_dt->gc, GXcopy); } if (xlib_dt->shm) { ximage = xlib_dt->tempImage; ximage->data = xlib_dt->data; /* _debug_printf("XSHM\n"); */ XShmPutImage(xlib_dt->display, xlib_drawable->drawable, xlib_dt->gc, ximage, 0, 0, 0, 0, xlib_dt->width, xlib_dt->height, False); } else { /* display image in Window */ ximage = xlib_dt->tempImage; ximage->data = xlib_dt->data; /* check that the XImage has been previously initialized */ assert(ximage->format); assert(ximage->bitmap_unit); /* update XImage's fields */ ximage->width = xlib_dt->width; ximage->height = xlib_dt->height; ximage->bytes_per_line = xlib_dt->stride; /* _debug_printf("XPUT\n"); */ XPutImage(xlib_dt->display, xlib_drawable->drawable, xlib_dt->gc, ximage, 0, 0, 0, 0, xlib_dt->width, xlib_dt->height); } XFlush(xlib_dt->display); }
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_context *rctx = (struct r600_context *)ctx; struct texture_orig_info orig_info[2]; struct pipe_box sbox; const struct pipe_box *psbox = src_box; 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; } /* The driver doesn't decompress resources automatically while * u_blitter is rendering. */ r600_decompress_subresource(ctx, src, src_level, src_box->z, src_box->z + src_box->depth - 1); restore_orig[0] = restore_orig[1] = FALSE; if (util_format_is_compressed(src->format) && util_format_is_compressed(dst->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; 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); } else if (!util_blitter_is_copy_supported(rctx->blitter, dst, src, PIPE_MASK_RGBAZS)) { unsigned blocksize = util_format_get_blocksize(src->format); switch (blocksize) { case 1: r600_change_format(src, src_level, &orig_info[0], PIPE_FORMAT_R8_UNORM); r600_change_format(dst, dst_level, &orig_info[1], PIPE_FORMAT_R8_UNORM); break; case 2: r600_change_format(src, src_level, &orig_info[0], PIPE_FORMAT_R8G8_UNORM); r600_change_format(dst, dst_level, &orig_info[1], PIPE_FORMAT_R8G8_UNORM); break; case 4: r600_change_format(src, src_level, &orig_info[0], PIPE_FORMAT_R8G8B8A8_UNORM); r600_change_format(dst, dst_level, &orig_info[1], PIPE_FORMAT_R8G8B8A8_UNORM); break; case 8: r600_change_format(src, src_level, &orig_info[0], PIPE_FORMAT_R16G16B16A16_UINT); r600_change_format(dst, dst_level, &orig_info[1], PIPE_FORMAT_R16G16B16A16_UINT); break; case 16: r600_change_format(src, src_level, &orig_info[0], PIPE_FORMAT_R32G32B32A32_UINT); r600_change_format(dst, dst_level, &orig_info[1], PIPE_FORMAT_R32G32B32A32_UINT); break; default: fprintf(stderr, "Unhandled format %s with blocksize %u\n", util_format_short_name(src->format), blocksize); assert(0); } restore_orig[0] = TRUE; restore_orig[1] = TRUE; } r600_blitter_begin(ctx, R600_COPY); util_blitter_copy_texture(rctx->blitter, dst, dst_level, dstx, dsty, dstz, src, src_level, psbox, PIPE_MASK_RGBAZS, TRUE); r600_blitter_end(ctx); if (restore_orig[0]) r600_reset_blittable_to_orig(src, src_level, &orig_info[0]); if (restore_orig[1]) r600_reset_blittable_to_orig(dst, dst_level, &orig_info[1]); }
static struct pipe_sampler_view * fd3_sampler_view_create(struct pipe_context *pctx, struct pipe_resource *prsc, const struct pipe_sampler_view *cso) { struct fd3_pipe_sampler_view *so = CALLOC_STRUCT(fd3_pipe_sampler_view); struct fd_resource *rsc = fd_resource(prsc); unsigned lvl; uint32_t sz2 = 0; if (!so) return NULL; so->base = *cso; pipe_reference(NULL, &prsc->reference); so->base.texture = prsc; so->base.reference.count = 1; so->base.context = pctx; so->texconst0 = A3XX_TEX_CONST_0_TYPE(tex_type(prsc->target)) | A3XX_TEX_CONST_0_FMT(fd3_pipe2tex(cso->format)) | fd3_tex_swiz(cso->format, cso->swizzle_r, cso->swizzle_g, cso->swizzle_b, cso->swizzle_a); if (prsc->target == PIPE_BUFFER || util_format_is_pure_integer(cso->format)) so->texconst0 |= A3XX_TEX_CONST_0_NOCONVERT; if (util_format_is_srgb(cso->format)) so->texconst0 |= A3XX_TEX_CONST_0_SRGB; if (prsc->target == PIPE_BUFFER) { lvl = 0; so->texconst1 = A3XX_TEX_CONST_1_FETCHSIZE(fd3_pipe2fetchsize(cso->format)) | A3XX_TEX_CONST_1_WIDTH(cso->u.buf.size / util_format_get_blocksize(cso->format)) | A3XX_TEX_CONST_1_HEIGHT(1); } else { unsigned miplevels; lvl = fd_sampler_first_level(cso); miplevels = fd_sampler_last_level(cso) - lvl; so->texconst0 |= A3XX_TEX_CONST_0_MIPLVLS(miplevels); so->texconst1 = A3XX_TEX_CONST_1_FETCHSIZE(fd3_pipe2fetchsize(cso->format)) | A3XX_TEX_CONST_1_WIDTH(u_minify(prsc->width0, lvl)) | A3XX_TEX_CONST_1_HEIGHT(u_minify(prsc->height0, lvl)); } /* when emitted, A3XX_TEX_CONST_2_INDX() must be OR'd in: */ so->texconst2 = A3XX_TEX_CONST_2_PITCH(fd3_pipe2nblocksx(cso->format, rsc->slices[lvl].pitch) * rsc->cpp); switch (prsc->target) { case PIPE_TEXTURE_1D_ARRAY: case PIPE_TEXTURE_2D_ARRAY: so->texconst3 = A3XX_TEX_CONST_3_DEPTH(prsc->array_size - 1) | A3XX_TEX_CONST_3_LAYERSZ1(rsc->slices[0].size0); break; case PIPE_TEXTURE_3D: so->texconst3 = A3XX_TEX_CONST_3_DEPTH(u_minify(prsc->depth0, lvl)) | A3XX_TEX_CONST_3_LAYERSZ1(rsc->slices[lvl].size0); while (lvl < cso->u.tex.last_level && sz2 != rsc->slices[lvl+1].size0) sz2 = rsc->slices[++lvl].size0; so->texconst3 |= A3XX_TEX_CONST_3_LAYERSZ2(sz2); break; default: so->texconst3 = 0x00000000; break; } return &so->base; }
static __DRIimage * dri2_create_image_from_name(__DRIscreen *_screen, int width, int height, int format, int name, int pitch, void *loaderPrivate) { struct dri_screen *screen = dri_screen(_screen); __DRIimage *img; struct pipe_resource templ; struct winsys_handle whandle; unsigned tex_usage; enum pipe_format pf; tex_usage = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW; switch (format) { case __DRI_IMAGE_FORMAT_RGB565: pf = PIPE_FORMAT_B5G6R5_UNORM; break; case __DRI_IMAGE_FORMAT_XRGB8888: pf = PIPE_FORMAT_B8G8R8X8_UNORM; break; case __DRI_IMAGE_FORMAT_ARGB8888: pf = PIPE_FORMAT_B8G8R8A8_UNORM; break; case __DRI_IMAGE_FORMAT_ABGR8888: pf = PIPE_FORMAT_R8G8B8A8_UNORM; break; default: pf = PIPE_FORMAT_NONE; break; } if (pf == PIPE_FORMAT_NONE) return NULL; img = CALLOC_STRUCT(__DRIimageRec); if (!img) return NULL; memset(&templ, 0, sizeof(templ)); templ.bind = tex_usage; templ.format = pf; templ.target = screen->target; templ.last_level = 0; templ.width0 = width; templ.height0 = height; templ.depth0 = 1; templ.array_size = 1; memset(&whandle, 0, sizeof(whandle)); whandle.handle = name; whandle.stride = pitch * util_format_get_blocksize(pf); img->texture = screen->base.screen->resource_from_handle(screen->base.screen, &templ, &whandle); if (!img->texture) { FREE(img); return NULL; } img->level = 0; img->layer = 0; img->loader_private = loaderPrivate; return img; }
/** * Fallback for pipe->clear_stencil() function. * sw fallback doesn't look terribly useful here. * Plus can't use these transfer fallbacks when clearing * multisampled surfaces for instance. */ void util_clear_depth_stencil(struct pipe_context *pipe, struct pipe_surface *dst, unsigned clear_flags, double depth, unsigned stencil, unsigned dstx, unsigned dsty, unsigned width, unsigned height) { enum pipe_format format = dst->format; struct pipe_transfer *dst_trans; ubyte *dst_map; boolean need_rmw = FALSE; if ((clear_flags & PIPE_CLEAR_DEPTHSTENCIL) && ((clear_flags & PIPE_CLEAR_DEPTHSTENCIL) != PIPE_CLEAR_DEPTHSTENCIL) && util_format_is_depth_and_stencil(format)) need_rmw = TRUE; assert(dst->texture); if (!dst->texture) return; dst_map = pipe_transfer_map(pipe, dst->texture, dst->u.tex.level, dst->u.tex.first_layer, (need_rmw ? PIPE_TRANSFER_READ_WRITE : PIPE_TRANSFER_WRITE), dstx, dsty, width, height, &dst_trans); assert(dst_map); if (dst_map) { unsigned dst_stride = dst_trans->stride; uint64_t zstencil = util_pack64_z_stencil(format, depth, stencil); unsigned i, j; assert(dst_trans->stride > 0); switch (util_format_get_blocksize(format)) { case 1: assert(format == PIPE_FORMAT_S8_UINT); if(dst_stride == width) memset(dst_map, (uint8_t) zstencil, height * width); else { for (i = 0; i < height; i++) { memset(dst_map, (uint8_t) zstencil, width); dst_map += dst_stride; } } break; case 2: assert(format == PIPE_FORMAT_Z16_UNORM); for (i = 0; i < height; i++) { uint16_t *row = (uint16_t *)dst_map; for (j = 0; j < width; j++) *row++ = (uint16_t) zstencil; dst_map += dst_stride; } break; case 4: if (!need_rmw) { for (i = 0; i < height; i++) { uint32_t *row = (uint32_t *)dst_map; for (j = 0; j < width; j++) *row++ = (uint32_t) zstencil; dst_map += dst_stride; } } else { uint32_t dst_mask; if (format == PIPE_FORMAT_Z24_UNORM_S8_UINT) dst_mask = 0x00ffffff; else { assert(format == PIPE_FORMAT_S8_UINT_Z24_UNORM); dst_mask = 0xffffff00; } if (clear_flags & PIPE_CLEAR_DEPTH) dst_mask = ~dst_mask; for (i = 0; i < height; i++) { uint32_t *row = (uint32_t *)dst_map; for (j = 0; j < width; j++) { uint32_t tmp = *row & dst_mask; *row++ = tmp | ((uint32_t) zstencil & ~dst_mask); } dst_map += dst_stride; } } break; case 8: if (!need_rmw) { for (i = 0; i < height; i++) { uint64_t *row = (uint64_t *)dst_map; for (j = 0; j < width; j++) *row++ = zstencil; dst_map += dst_stride; } } else { uint64_t src_mask; if (clear_flags & PIPE_CLEAR_DEPTH) src_mask = 0x00000000ffffffffull; else src_mask = 0x000000ff00000000ull; for (i = 0; i < height; i++) { uint64_t *row = (uint64_t *)dst_map; for (j = 0; j < width; j++) { uint64_t tmp = *row & ~src_mask; *row++ = tmp | (zstencil & src_mask); } dst_map += dst_stride; } } break; default: assert(0); break; } pipe->transfer_unmap(pipe, dst_trans); } }
void * nvc0_miptree_transfer_map(struct pipe_context *pctx, struct pipe_resource *res, unsigned level, unsigned usage, const struct pipe_box *box, struct pipe_transfer **ptransfer) { struct nvc0_context *nvc0 = nvc0_context(pctx); struct nouveau_device *dev = nvc0->screen->base.device; struct nv50_miptree *mt = nv50_miptree(res); struct nvc0_transfer *tx; uint32_t size; int ret; unsigned flags = 0; if (usage & PIPE_TRANSFER_MAP_DIRECTLY) return NULL; tx = CALLOC_STRUCT(nvc0_transfer); if (!tx) return NULL; pipe_resource_reference(&tx->base.resource, res); tx->base.level = level; tx->base.usage = usage; tx->base.box = *box; if (util_format_is_plain(res->format)) { tx->nblocksx = box->width << mt->ms_x; tx->nblocksy = box->height << mt->ms_y; } else { tx->nblocksx = util_format_get_nblocksx(res->format, box->width); tx->nblocksy = util_format_get_nblocksy(res->format, box->height); } tx->nlayers = box->depth; tx->base.stride = tx->nblocksx * util_format_get_blocksize(res->format); tx->base.layer_stride = tx->nblocksy * tx->base.stride; nv50_m2mf_rect_setup(&tx->rect[0], res, level, box->x, box->y, box->z); size = tx->base.layer_stride; ret = nouveau_bo_new(dev, NOUVEAU_BO_GART | NOUVEAU_BO_MAP, 0, size * tx->nlayers, NULL, &tx->rect[1].bo); if (ret) { pipe_resource_reference(&tx->base.resource, NULL); FREE(tx); return NULL; } tx->rect[1].cpp = tx->rect[0].cpp; tx->rect[1].width = tx->nblocksx; tx->rect[1].height = tx->nblocksy; tx->rect[1].depth = 1; tx->rect[1].pitch = tx->base.stride; tx->rect[1].domain = NOUVEAU_BO_GART; if (usage & PIPE_TRANSFER_READ) { unsigned base = tx->rect[0].base; unsigned z = tx->rect[0].z; unsigned i; for (i = 0; i < tx->nlayers; ++i) { nvc0->m2mf_copy_rect(nvc0, &tx->rect[1], &tx->rect[0], tx->nblocksx, tx->nblocksy); if (mt->layout_3d) tx->rect[0].z++; else tx->rect[0].base += mt->layer_stride; tx->rect[1].base += size; } tx->rect[0].z = z; tx->rect[0].base = base; tx->rect[1].base = 0; } if (tx->rect[1].bo->map) { *ptransfer = &tx->base; return tx->rect[1].bo->map; } if (usage & PIPE_TRANSFER_READ) flags = NOUVEAU_BO_RD; if (usage & PIPE_TRANSFER_WRITE) flags |= NOUVEAU_BO_WR; ret = nouveau_bo_map(tx->rect[1].bo, flags, nvc0->screen->base.client); if (ret) { pipe_resource_reference(&tx->base.resource, NULL); nouveau_bo_ref(NULL, &tx->rect[1].bo); FREE(tx); return NULL; } *ptransfer = &tx->base; return tx->rect[1].bo->map; }
/** * Fallback function for pipe->resource_copy_region(). * Note: (X,Y)=(0,0) is always the upper-left corner. */ void util_resource_copy_region(struct pipe_context *pipe, struct pipe_resource *dst, unsigned dst_level, unsigned dst_x, unsigned dst_y, unsigned dst_z, struct pipe_resource *src, unsigned src_level, const struct pipe_box *src_box) { struct pipe_transfer *src_trans, *dst_trans; uint8_t *dst_map; const uint8_t *src_map; enum pipe_format src_format, dst_format; struct pipe_box dst_box; assert(src && dst); if (!src || !dst) return; assert((src->target == PIPE_BUFFER && dst->target == PIPE_BUFFER) || (src->target != PIPE_BUFFER && dst->target != PIPE_BUFFER)); src_format = src->format; dst_format = dst->format; assert(util_format_get_blocksize(dst_format) == util_format_get_blocksize(src_format)); assert(util_format_get_blockwidth(dst_format) == util_format_get_blockwidth(src_format)); assert(util_format_get_blockheight(dst_format) == util_format_get_blockheight(src_format)); src_map = pipe->transfer_map(pipe, src, src_level, PIPE_TRANSFER_READ, src_box, &src_trans); assert(src_map); if (!src_map) { goto no_src_map; } dst_box.x = dst_x; dst_box.y = dst_y; dst_box.z = dst_z; dst_box.width = src_box->width; dst_box.height = src_box->height; dst_box.depth = src_box->depth; dst_map = pipe->transfer_map(pipe, dst, dst_level, PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD_RANGE, &dst_box, &dst_trans); assert(dst_map); if (!dst_map) { goto no_dst_map; } if (dst->target == PIPE_BUFFER && src->target == PIPE_BUFFER) { assert(src_box->height == 1); assert(src_box->depth == 1); memcpy(dst_map, src_map, src_box->width); } else { util_copy_box(dst_map, dst_format, dst_trans->stride, dst_trans->layer_stride, 0, 0, 0, src_box->width, src_box->height, src_box->depth, src_map, src_trans->stride, src_trans->layer_stride, 0, 0, 0); } pipe->transfer_unmap(pipe, dst_trans); no_dst_map: pipe->transfer_unmap(pipe, src_trans); no_src_map: ; }
/** * Fallback for pipe->clear_render_target() function. * XXX this looks too hackish to be really useful. * cpp > 4 looks like a gross hack at best... * Plus can't use these transfer fallbacks when clearing * multisampled surfaces for instance. */ void util_clear_render_target(struct pipe_context *pipe, struct pipe_surface *dst, const union pipe_color_union *color, unsigned dstx, unsigned dsty, unsigned width, unsigned height) { struct pipe_transfer *dst_trans; void *dst_map; union util_color uc; assert(dst->texture); if (!dst->texture) return; if (dst->texture->target == PIPE_BUFFER) { /* * The fill naturally works on the surface format, however * the transfer uses resource format which is just bytes for buffers. */ unsigned dx, w; unsigned pixstride = util_format_get_blocksize(dst->format); dx = (dst->u.buf.first_element + dstx) * pixstride; w = width * pixstride; dst_map = pipe_transfer_map(pipe, dst->texture, 0, 0, PIPE_TRANSFER_WRITE, dx, 0, w, 1, &dst_trans); } else { /* XXX: should handle multiple layers */ dst_map = pipe_transfer_map(pipe, dst->texture, dst->u.tex.level, dst->u.tex.first_layer, PIPE_TRANSFER_WRITE, dstx, dsty, width, height, &dst_trans); } assert(dst_map); if (dst_map) { enum pipe_format format = dst->format; assert(dst_trans->stride > 0); if (util_format_is_pure_integer(format)) { /* * We expect int/uint clear values here, though some APIs * might disagree (but in any case util_pack_color() * couldn't handle it)... */ if (util_format_is_pure_sint(format)) { util_format_write_4i(format, color->i, 0, &uc, 0, 0, 0, 1, 1); } else { assert(util_format_is_pure_uint(format)); util_format_write_4ui(format, color->ui, 0, &uc, 0, 0, 0, 1, 1); } } else { util_pack_color(color->f, dst->format, &uc); } util_fill_rect(dst_map, dst->format, dst_trans->stride, 0, 0, width, height, &uc); pipe->transfer_unmap(pipe, dst_trans); } }
static void * svga_texture_transfer_map(struct pipe_context *pipe, struct pipe_resource *texture, unsigned level, unsigned usage, const struct pipe_box *box, struct pipe_transfer **ptransfer) { struct svga_context *svga = svga_context(pipe); struct svga_screen *ss = svga_screen(pipe->screen); struct svga_winsys_screen *sws = ss->sws; struct svga_texture *tex = svga_texture(texture); struct svga_transfer *st; unsigned nblocksx, nblocksy; boolean use_direct_map = svga_have_gb_objects(svga) && !svga_have_gb_dma(svga); unsigned d; void *returnVal; int64_t begin = os_time_get(); /* We can't map texture storage directly unless we have GB objects */ if (usage & PIPE_TRANSFER_MAP_DIRECTLY) { if (svga_have_gb_objects(svga)) use_direct_map = TRUE; else return NULL; } st = CALLOC_STRUCT(svga_transfer); if (!st) return NULL; st->base.level = level; st->base.usage = usage; st->base.box = *box; switch (tex->b.b.target) { case PIPE_TEXTURE_CUBE: st->slice = st->base.box.z; st->base.box.z = 0; /* so we don't apply double offsets below */ break; case PIPE_TEXTURE_2D_ARRAY: case PIPE_TEXTURE_1D_ARRAY: st->slice = st->base.box.z; st->base.box.z = 0; /* so we don't apply double offsets below */ /* Force direct map for transfering multiple slices */ if (st->base.box.depth > 1) use_direct_map = svga_have_gb_objects(svga); break; default: st->slice = 0; break; } { unsigned w, h; if (use_direct_map) { /* we'll directly access the guest-backed surface */ w = u_minify(texture->width0, level); h = u_minify(texture->height0, level); d = u_minify(texture->depth0, level); } else { /* we'll put the data into a tightly packed buffer */ w = box->width; h = box->height; d = box->depth; } nblocksx = util_format_get_nblocksx(texture->format, w); nblocksy = util_format_get_nblocksy(texture->format, h); } pipe_resource_reference(&st->base.resource, texture); st->base.stride = nblocksx*util_format_get_blocksize(texture->format); st->base.layer_stride = st->base.stride * nblocksy; if (usage & PIPE_TRANSFER_WRITE) { /* record texture upload for HUD */ svga->hud.num_bytes_uploaded += nblocksx * nblocksy * d * util_format_get_blocksize(texture->format); } if (!use_direct_map) { /* Use a DMA buffer */ st->hw_nblocksy = nblocksy; st->hwbuf = svga_winsys_buffer_create(svga, 1, 0, st->hw_nblocksy * st->base.stride * d); while(!st->hwbuf && (st->hw_nblocksy /= 2)) { st->hwbuf = svga_winsys_buffer_create(svga, 1, 0, st->hw_nblocksy * st->base.stride * d); } if (!st->hwbuf) { FREE(st); return NULL; } if (st->hw_nblocksy < nblocksy) { /* We couldn't allocate a hardware buffer big enough for the transfer, * so allocate regular malloc memory instead */ if (0) { debug_printf("%s: failed to allocate %u KB of DMA, " "splitting into %u x %u KB DMA transfers\n", __FUNCTION__, (nblocksy*st->base.stride + 1023)/1024, (nblocksy + st->hw_nblocksy - 1)/st->hw_nblocksy, (st->hw_nblocksy*st->base.stride + 1023)/1024); } st->swbuf = MALLOC(nblocksy * st->base.stride * d); if (!st->swbuf) { sws->buffer_destroy(sws, st->hwbuf); FREE(st); return NULL; } } if (usage & PIPE_TRANSFER_READ) { SVGA3dSurfaceDMAFlags flags; memset(&flags, 0, sizeof flags); svga_transfer_dma(svga, st, SVGA3D_READ_HOST_VRAM, flags); } } else { struct pipe_transfer *transfer = &st->base; struct svga_winsys_surface *surf = tex->handle; if (!surf) { FREE(st); return NULL; } /* If this is the first time mapping to the surface in this * command buffer, clear the dirty masks of this surface. */ if (sws->surface_is_flushed(sws, surf)) { svga_clear_texture_dirty(tex); } if (need_tex_readback(transfer)) { enum pipe_error ret; svga_surfaces_flush(svga); if (svga_have_vgpu10(svga)) { ret = readback_image_vgpu10(svga, surf, st->slice, transfer->level, tex->b.b.last_level + 1); } else { ret = readback_image_vgpu9(svga, surf, st->slice, transfer->level); } svga->hud.num_readbacks++; assert(ret == PIPE_OK); (void) ret; svga_context_flush(svga, NULL); /* * Note: if PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE were specified * we could potentially clear the flag for all faces/layers/mips. */ svga_clear_texture_rendered_to(tex, st->slice, transfer->level); } else { assert(transfer->usage & PIPE_TRANSFER_WRITE); if ((transfer->usage & PIPE_TRANSFER_UNSYNCHRONIZED) == 0) { if (svga_is_texture_dirty(tex, st->slice, transfer->level)) { /* * do a surface flush if the subresource has been modified * in this command buffer. */ svga_surfaces_flush(svga); if (!sws->surface_is_flushed(sws, surf)) { svga->hud.surface_write_flushes++; svga_context_flush(svga, NULL); } } } } if (transfer->usage & PIPE_TRANSFER_WRITE) { /* mark this texture level as dirty */ svga_set_texture_dirty(tex, st->slice, transfer->level); } } st->use_direct_map = use_direct_map; *ptransfer = &st->base; /* * Begin mapping code */ if (st->swbuf) { returnVal = st->swbuf; } else if (!st->use_direct_map) { returnVal = sws->buffer_map(sws, st->hwbuf, usage); } else { SVGA3dSize baseLevelSize; struct svga_texture *tex = svga_texture(texture); struct svga_winsys_surface *surf = tex->handle; uint8_t *map; boolean retry; unsigned offset, mip_width, mip_height; unsigned xoffset = st->base.box.x; unsigned yoffset = st->base.box.y; unsigned zoffset = st->base.box.z; map = svga->swc->surface_map(svga->swc, surf, usage, &retry); if (map == NULL && retry) { /* * At this point, the svga_surfaces_flush() should already have * called in svga_texture_get_transfer(). */ svga_context_flush(svga, NULL); map = svga->swc->surface_map(svga->swc, surf, usage, &retry); } /* * Make sure we return NULL if the map fails */ if (!map) { FREE(st); return map; } /** * Compute the offset to the specific texture slice in the buffer. */ baseLevelSize.width = tex->b.b.width0; baseLevelSize.height = tex->b.b.height0; baseLevelSize.depth = tex->b.b.depth0; if ((tex->b.b.target == PIPE_TEXTURE_1D_ARRAY) || (tex->b.b.target == PIPE_TEXTURE_2D_ARRAY)) { st->base.layer_stride = svga3dsurface_get_image_offset(tex->key.format, baseLevelSize, tex->b.b.last_level + 1, 1, 0); } offset = svga3dsurface_get_image_offset(tex->key.format, baseLevelSize, tex->b.b.last_level + 1, /* numMips */ st->slice, level); if (level > 0) { assert(offset > 0); } mip_width = u_minify(tex->b.b.width0, level); mip_height = u_minify(tex->b.b.height0, level); offset += svga3dsurface_get_pixel_offset(tex->key.format, mip_width, mip_height, xoffset, yoffset, zoffset); returnVal = (void *) (map + offset); } svga->hud.map_buffer_time += (os_time_get() - begin); svga->hud.num_resources_mapped++; return returnVal; }
static struct pipe_sampler_view * fd5_sampler_view_create(struct pipe_context *pctx, struct pipe_resource *prsc, const struct pipe_sampler_view *cso) { struct fd5_pipe_sampler_view *so = CALLOC_STRUCT(fd5_pipe_sampler_view); struct fd_resource *rsc = fd_resource(prsc); enum pipe_format format = cso->format; unsigned lvl, layers; if (!so) return NULL; if (format == PIPE_FORMAT_X32_S8X24_UINT) { rsc = rsc->stencil; format = rsc->base.format; } so->base = *cso; pipe_reference(NULL, &prsc->reference); so->base.texture = prsc; so->base.reference.count = 1; so->base.context = pctx; so->texconst0 = A5XX_TEX_CONST_0_FMT(fd5_pipe2tex(format)) | A5XX_TEX_CONST_0_SAMPLES(fd_msaa_samples(prsc->nr_samples)) | fd5_tex_swiz(format, cso->swizzle_r, cso->swizzle_g, cso->swizzle_b, cso->swizzle_a); /* NOTE: since we sample z24s8 using 8888_UINT format, the swizzle * we get isn't quite right. Use SWAP(XYZW) as a cheap and cheerful * way to re-arrange things so stencil component is where the swiz * expects. * * Note that gallium expects stencil sampler to return (s,s,s,s) * which isn't quite true. To make that happen we'd have to massage * the swizzle. But in practice only the .x component is used. */ if (format == PIPE_FORMAT_X24S8_UINT) { so->texconst0 |= A5XX_TEX_CONST_0_SWAP(XYZW); } if (util_format_is_srgb(format)) { if (use_astc_srgb_workaround(pctx, format)) so->astc_srgb = true; so->texconst0 |= A5XX_TEX_CONST_0_SRGB; } if (cso->target == PIPE_BUFFER) { unsigned elements = cso->u.buf.size / util_format_get_blocksize(format); lvl = 0; so->texconst1 = A5XX_TEX_CONST_1_WIDTH(elements) | A5XX_TEX_CONST_1_HEIGHT(1); so->texconst2 = A5XX_TEX_CONST_2_FETCHSIZE(fd5_pipe2fetchsize(format)) | A5XX_TEX_CONST_2_PITCH(elements * rsc->cpp); so->offset = cso->u.buf.offset; } else { unsigned miplevels; lvl = fd_sampler_first_level(cso); miplevels = fd_sampler_last_level(cso) - lvl; layers = cso->u.tex.last_layer - cso->u.tex.first_layer + 1; so->texconst0 |= A5XX_TEX_CONST_0_MIPLVLS(miplevels); so->texconst1 = A5XX_TEX_CONST_1_WIDTH(u_minify(prsc->width0, lvl)) | A5XX_TEX_CONST_1_HEIGHT(u_minify(prsc->height0, lvl)); so->texconst2 = A5XX_TEX_CONST_2_FETCHSIZE(fd5_pipe2fetchsize(format)) | A5XX_TEX_CONST_2_PITCH( util_format_get_nblocksx( format, rsc->slices[lvl].pitch) * rsc->cpp); so->offset = fd_resource_offset(rsc, lvl, cso->u.tex.first_layer); } so->texconst2 |= A5XX_TEX_CONST_2_TYPE(fd5_tex_type(cso->target)); switch (cso->target) { case PIPE_TEXTURE_RECT: case PIPE_TEXTURE_1D: case PIPE_TEXTURE_2D: so->texconst3 = A5XX_TEX_CONST_3_ARRAY_PITCH(rsc->layer_size); so->texconst5 = A5XX_TEX_CONST_5_DEPTH(1); break; case PIPE_TEXTURE_1D_ARRAY: case PIPE_TEXTURE_2D_ARRAY: so->texconst3 = A5XX_TEX_CONST_3_ARRAY_PITCH(rsc->layer_size); so->texconst5 = A5XX_TEX_CONST_5_DEPTH(layers); break; case PIPE_TEXTURE_CUBE: case PIPE_TEXTURE_CUBE_ARRAY: so->texconst3 = A5XX_TEX_CONST_3_ARRAY_PITCH(rsc->layer_size); so->texconst5 = A5XX_TEX_CONST_5_DEPTH(layers / 6); break; case PIPE_TEXTURE_3D: so->texconst3 = A5XX_TEX_CONST_3_ARRAY_PITCH(rsc->slices[lvl].size0); so->texconst5 = A5XX_TEX_CONST_5_DEPTH(u_minify(prsc->depth0, lvl)); break; default: so->texconst3 = 0x00000000; break; } return &so->base; }
void fd4_emit_vertex_bufs(struct fd_ringbuffer *ring, struct fd4_emit *emit) { int32_t i, j, last = -1; uint32_t total_in = 0; const struct fd_vertex_state *vtx = emit->vtx; struct ir3_shader_variant *vp = fd4_emit_get_vp(emit); unsigned vertex_regid = regid(63, 0), instance_regid = regid(63, 0); for (i = 0; i < vp->inputs_count; i++) { uint8_t semantic = sem2name(vp->inputs[i].semantic); if (semantic == TGSI_SEMANTIC_VERTEXID_NOBASE) vertex_regid = vp->inputs[i].regid; else if (semantic == TGSI_SEMANTIC_INSTANCEID) instance_regid = vp->inputs[i].regid; else if ((i < vtx->vtx->num_elements) && vp->inputs[i].compmask) last = i; } /* hw doesn't like to be configured for zero vbo's, it seems: */ if ((vtx->vtx->num_elements == 0) && (vertex_regid == regid(63, 0)) && (instance_regid == regid(63, 0))) return; for (i = 0, j = 0; i <= last; i++) { assert(sem2name(vp->inputs[i].semantic) == 0); if (vp->inputs[i].compmask) { struct pipe_vertex_element *elem = &vtx->vtx->pipe[i]; const struct pipe_vertex_buffer *vb = &vtx->vertexbuf.vb[elem->vertex_buffer_index]; struct fd_resource *rsc = fd_resource(vb->buffer); enum pipe_format pfmt = elem->src_format; enum a4xx_vtx_fmt fmt = fd4_pipe2vtx(pfmt); bool switchnext = (i != last) || (vertex_regid != regid(63, 0)) || (instance_regid != regid(63, 0)); bool isint = util_format_is_pure_integer(pfmt); uint32_t fs = util_format_get_blocksize(pfmt); uint32_t off = vb->buffer_offset + elem->src_offset; uint32_t size = fd_bo_size(rsc->bo) - off; debug_assert(fmt != ~0); OUT_PKT0(ring, REG_A4XX_VFD_FETCH(j), 4); OUT_RING(ring, A4XX_VFD_FETCH_INSTR_0_FETCHSIZE(fs - 1) | A4XX_VFD_FETCH_INSTR_0_BUFSTRIDE(vb->stride) | COND(elem->instance_divisor, A4XX_VFD_FETCH_INSTR_0_INSTANCED) | COND(switchnext, A4XX_VFD_FETCH_INSTR_0_SWITCHNEXT)); OUT_RELOC(ring, rsc->bo, off, 0, 0); OUT_RING(ring, A4XX_VFD_FETCH_INSTR_2_SIZE(size)); OUT_RING(ring, A4XX_VFD_FETCH_INSTR_3_STEPRATE(MAX2(1, elem->instance_divisor))); OUT_PKT0(ring, REG_A4XX_VFD_DECODE_INSTR(j), 1); OUT_RING(ring, A4XX_VFD_DECODE_INSTR_CONSTFILL | A4XX_VFD_DECODE_INSTR_WRITEMASK(vp->inputs[i].compmask) | A4XX_VFD_DECODE_INSTR_FORMAT(fmt) | A4XX_VFD_DECODE_INSTR_SWAP(fd4_pipe2swap(pfmt)) | A4XX_VFD_DECODE_INSTR_REGID(vp->inputs[i].regid) | A4XX_VFD_DECODE_INSTR_SHIFTCNT(fs) | A4XX_VFD_DECODE_INSTR_LASTCOMPVALID | COND(isint, A4XX_VFD_DECODE_INSTR_INT) | COND(switchnext, A4XX_VFD_DECODE_INSTR_SWITCHNEXT)); total_in += vp->inputs[i].ncomp; j++; } } OUT_PKT0(ring, REG_A4XX_VFD_CONTROL_0, 5); OUT_RING(ring, A4XX_VFD_CONTROL_0_TOTALATTRTOVS(total_in) | 0xa0000 | /* XXX */ A4XX_VFD_CONTROL_0_STRMDECINSTRCNT(j) | A4XX_VFD_CONTROL_0_STRMFETCHINSTRCNT(j)); OUT_RING(ring, A4XX_VFD_CONTROL_1_MAXSTORAGE(129) | // XXX A4XX_VFD_CONTROL_1_REGID4VTX(vertex_regid) | A4XX_VFD_CONTROL_1_REGID4INST(instance_regid)); OUT_RING(ring, 0x00000000); /* XXX VFD_CONTROL_2 */ OUT_RING(ring, A4XX_VFD_CONTROL_3_REGID_VTXCNT(regid(63, 0))); OUT_RING(ring, 0x00000000); /* XXX VFD_CONTROL_4 */ /* cache invalidate, otherwise vertex fetch could see * stale vbo contents: */ OUT_PKT0(ring, REG_A4XX_UCHE_INVALIDATE0, 2); OUT_RING(ring, 0x00000000); OUT_RING(ring, 0x00000012); }
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_context *rctx = (struct r600_context *)ctx; struct pipe_surface *dst_view, dst_templ; struct pipe_sampler_view src_templ, *src_view; unsigned dst_width, dst_height, src_width0, src_height0, src_widthFL, src_heightFL; unsigned src_force_level = 0; struct pipe_box sbox, dstbox; /* Handle buffers first. */ if (dst->target == PIPE_BUFFER && src->target == PIPE_BUFFER) { if ((src->bind & PIPE_BIND_GLOBAL) || (dst->bind & PIPE_BIND_GLOBAL)) { r600_copy_global_buffer(ctx, dst, dstx, src, src_box); } else { r600_copy_buffer(ctx, dst, dstx, src, src_box); } return; } assert(u_max_sample(dst) == u_max_sample(src)); /* The driver doesn't decompress resources automatically while * u_blitter is rendering. */ if (!r600_decompress_subresource(ctx, src, src_level, src_box->z, src_box->z + src_box->depth - 1)) { return; /* error */ } dst_width = u_minify(dst->width0, dst_level); dst_height = u_minify(dst->height0, dst_level); src_width0 = src->width0; src_height0 = src->height0; src_widthFL = u_minify(src->width0, src_level); src_heightFL = u_minify(src->height0, src_level); util_blitter_default_dst_texture(&dst_templ, dst, dst_level, dstz); util_blitter_default_src_texture(&src_templ, src, src_level); if (util_format_is_compressed(src->format)) { unsigned blocksize = util_format_get_blocksize(src->format); if (blocksize == 8) src_templ.format = PIPE_FORMAT_R16G16B16A16_UINT; /* 64-bit block */ else src_templ.format = PIPE_FORMAT_R32G32B32A32_UINT; /* 128-bit block */ dst_templ.format = src_templ.format; dst_width = util_format_get_nblocksx(dst->format, dst_width); dst_height = util_format_get_nblocksy(dst->format, dst_height); src_width0 = util_format_get_nblocksx(src->format, src_width0); src_height0 = util_format_get_nblocksy(src->format, src_height0); src_widthFL = util_format_get_nblocksx(src->format, src_widthFL); src_heightFL = util_format_get_nblocksy(src->format, src_heightFL); dstx = util_format_get_nblocksx(dst->format, dstx); dsty = util_format_get_nblocksy(dst->format, dsty); sbox.x = util_format_get_nblocksx(src->format, src_box->x); sbox.y = util_format_get_nblocksy(src->format, src_box->y); sbox.z = src_box->z; sbox.width = util_format_get_nblocksx(src->format, src_box->width); sbox.height = util_format_get_nblocksy(src->format, src_box->height); sbox.depth = src_box->depth; src_box = &sbox; src_force_level = src_level; } else if (!util_blitter_is_copy_supported(rctx->blitter, dst, src)) { if (util_format_is_subsampled_422(src->format)) { src_templ.format = PIPE_FORMAT_R8G8B8A8_UINT; dst_templ.format = PIPE_FORMAT_R8G8B8A8_UINT; dst_width = util_format_get_nblocksx(dst->format, dst_width); src_width0 = util_format_get_nblocksx(src->format, src_width0); src_widthFL = util_format_get_nblocksx(src->format, src_widthFL); dstx = util_format_get_nblocksx(dst->format, dstx); sbox = *src_box; sbox.x = util_format_get_nblocksx(src->format, src_box->x); sbox.width = util_format_get_nblocksx(src->format, src_box->width); src_box = &sbox; } else { unsigned blocksize = util_format_get_blocksize(src->format); switch (blocksize) { case 1: dst_templ.format = PIPE_FORMAT_R8_UNORM; src_templ.format = PIPE_FORMAT_R8_UNORM; break; case 2: dst_templ.format = PIPE_FORMAT_R8G8_UNORM; src_templ.format = PIPE_FORMAT_R8G8_UNORM; break; case 4: dst_templ.format = PIPE_FORMAT_R8G8B8A8_UNORM; src_templ.format = PIPE_FORMAT_R8G8B8A8_UNORM; break; case 8: dst_templ.format = PIPE_FORMAT_R16G16B16A16_UINT; src_templ.format = PIPE_FORMAT_R16G16B16A16_UINT; break; case 16: dst_templ.format = PIPE_FORMAT_R32G32B32A32_UINT; src_templ.format = PIPE_FORMAT_R32G32B32A32_UINT; break; default: fprintf(stderr, "Unhandled format %s with blocksize %u\n", util_format_short_name(src->format), blocksize); assert(0); } } } dst_view = r600_create_surface_custom(ctx, dst, &dst_templ, dst_width, dst_height); if (rctx->b.chip_class >= EVERGREEN) { src_view = evergreen_create_sampler_view_custom(ctx, src, &src_templ, src_width0, src_height0, src_force_level); } else { src_view = r600_create_sampler_view_custom(ctx, src, &src_templ, src_widthFL, src_heightFL); } u_box_3d(dstx, dsty, dstz, abs(src_box->width), abs(src_box->height), abs(src_box->depth), &dstbox); /* Copy. */ r600_blitter_begin(ctx, R600_COPY_TEXTURE); util_blitter_blit_generic(rctx->blitter, dst_view, &dstbox, src_view, src_box, src_width0, src_height0, PIPE_MASK_RGBAZS, PIPE_TEX_FILTER_NEAREST, NULL, FALSE); r600_blitter_end(ctx); pipe_surface_reference(&dst_view, NULL); pipe_sampler_view_reference(&src_view, NULL); }
void si_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 si_context *sctx = (struct si_context *)ctx; struct pipe_surface *dst_view, dst_templ; struct pipe_sampler_view src_templ, *src_view; unsigned dst_width, dst_height, src_width0, src_height0; unsigned src_force_level = 0; struct pipe_box sbox, dstbox; /* Handle buffers first. */ if (dst->target == PIPE_BUFFER && src->target == PIPE_BUFFER) { si_copy_buffer(sctx, dst, src, dstx, src_box->x, src_box->width); return; } assert(u_max_sample(dst) == u_max_sample(src)); /* The driver doesn't decompress resources automatically while * u_blitter is rendering. */ si_decompress_subresource(ctx, src, PIPE_MASK_RGBAZS, src_level, src_box->z, src_box->z + src_box->depth - 1); dst_width = u_minify(dst->width0, dst_level); dst_height = u_minify(dst->height0, dst_level); src_width0 = src->width0; src_height0 = src->height0; util_blitter_default_dst_texture(&dst_templ, dst, dst_level, dstz); util_blitter_default_src_texture(&src_templ, src, src_level); if (util_format_is_compressed(src->format) || util_format_is_compressed(dst->format)) { unsigned blocksize = util_format_get_blocksize(src->format); if (blocksize == 8) src_templ.format = PIPE_FORMAT_R16G16B16A16_UINT; /* 64-bit block */ else src_templ.format = PIPE_FORMAT_R32G32B32A32_UINT; /* 128-bit block */ dst_templ.format = src_templ.format; dst_width = util_format_get_nblocksx(dst->format, dst_width); dst_height = util_format_get_nblocksy(dst->format, dst_height); src_width0 = util_format_get_nblocksx(src->format, src_width0); src_height0 = util_format_get_nblocksy(src->format, src_height0); dstx = util_format_get_nblocksx(dst->format, dstx); dsty = util_format_get_nblocksy(dst->format, dsty); sbox.x = util_format_get_nblocksx(src->format, src_box->x); sbox.y = util_format_get_nblocksy(src->format, src_box->y); sbox.z = src_box->z; sbox.width = util_format_get_nblocksx(src->format, src_box->width); sbox.height = util_format_get_nblocksy(src->format, src_box->height); sbox.depth = src_box->depth; src_box = &sbox; src_force_level = src_level; } else if (!util_blitter_is_copy_supported(sctx->blitter, dst, src) || /* also *8_SNORM has precision issues, use UNORM instead */ util_format_is_snorm8(src->format)) { if (util_format_is_subsampled_422(src->format)) { src_templ.format = PIPE_FORMAT_R8G8B8A8_UINT; dst_templ.format = PIPE_FORMAT_R8G8B8A8_UINT; dst_width = util_format_get_nblocksx(dst->format, dst_width); src_width0 = util_format_get_nblocksx(src->format, src_width0); dstx = util_format_get_nblocksx(dst->format, dstx); sbox = *src_box; sbox.x = util_format_get_nblocksx(src->format, src_box->x); sbox.width = util_format_get_nblocksx(src->format, src_box->width); src_box = &sbox; } else { unsigned blocksize = util_format_get_blocksize(src->format); switch (blocksize) { case 1: dst_templ.format = PIPE_FORMAT_R8_UNORM; src_templ.format = PIPE_FORMAT_R8_UNORM; break; case 2: dst_templ.format = PIPE_FORMAT_R8G8_UNORM; src_templ.format = PIPE_FORMAT_R8G8_UNORM; break; case 4: dst_templ.format = PIPE_FORMAT_R8G8B8A8_UNORM; src_templ.format = PIPE_FORMAT_R8G8B8A8_UNORM; break; case 8: dst_templ.format = PIPE_FORMAT_R16G16B16A16_UINT; src_templ.format = PIPE_FORMAT_R16G16B16A16_UINT; break; case 16: dst_templ.format = PIPE_FORMAT_R32G32B32A32_UINT; src_templ.format = PIPE_FORMAT_R32G32B32A32_UINT; break; default: fprintf(stderr, "Unhandled format %s with blocksize %u\n", util_format_short_name(src->format), blocksize); assert(0); } } } /* Initialize the surface. */ dst_view = r600_create_surface_custom(ctx, dst, &dst_templ, dst_width, dst_height); /* Initialize the sampler view. */ src_view = si_create_sampler_view_custom(ctx, src, &src_templ, src_width0, src_height0, src_force_level); u_box_3d(dstx, dsty, dstz, abs(src_box->width), abs(src_box->height), abs(src_box->depth), &dstbox); /* Copy. */ si_blitter_begin(ctx, SI_COPY); util_blitter_blit_generic(sctx->blitter, dst_view, &dstbox, src_view, src_box, src_width0, src_height0, PIPE_MASK_RGBAZS, PIPE_TEX_FILTER_NEAREST, NULL, FALSE); si_blitter_end(ctx); pipe_surface_reference(&dst_view, NULL); pipe_sampler_view_reference(&src_view, NULL); }
static void prepare_shader_sampling( struct softpipe_context *sp, unsigned num, struct pipe_sampler_view **views, unsigned shader_type, struct pipe_resource *mapped_tex[PIPE_MAX_SHADER_SAMPLER_VIEWS]) { unsigned i; uint32_t row_stride[PIPE_MAX_TEXTURE_LEVELS]; uint32_t img_stride[PIPE_MAX_TEXTURE_LEVELS]; uint32_t mip_offsets[PIPE_MAX_TEXTURE_LEVELS]; const void *addr; assert(num <= PIPE_MAX_SHADER_SAMPLER_VIEWS); if (!num) return; for (i = 0; i < PIPE_MAX_SHADER_SAMPLER_VIEWS; i++) { struct pipe_sampler_view *view = i < num ? views[i] : NULL; if (view) { struct pipe_resource *tex = view->texture; struct softpipe_resource *sp_tex = softpipe_resource(tex); unsigned width0 = tex->width0; unsigned num_layers = tex->depth0; unsigned first_level = 0; unsigned last_level = 0; /* We're referencing the texture's internal data, so save a * reference to it. */ pipe_resource_reference(&mapped_tex[i], tex); if (!sp_tex->dt) { /* regular texture - setup array of mipmap level offsets */ MAYBE_UNUSED struct pipe_resource *res = view->texture; int j; if (view->target != PIPE_BUFFER) { first_level = view->u.tex.first_level; last_level = view->u.tex.last_level; assert(first_level <= last_level); assert(last_level <= res->last_level); addr = sp_tex->data; for (j = first_level; j <= last_level; j++) { mip_offsets[j] = sp_tex->level_offset[j]; row_stride[j] = sp_tex->stride[j]; img_stride[j] = sp_tex->img_stride[j]; } if (tex->target == PIPE_TEXTURE_1D_ARRAY || tex->target == PIPE_TEXTURE_2D_ARRAY || tex->target == PIPE_TEXTURE_CUBE || tex->target == PIPE_TEXTURE_CUBE_ARRAY) { num_layers = view->u.tex.last_layer - view->u.tex.first_layer + 1; for (j = first_level; j <= last_level; j++) { mip_offsets[j] += view->u.tex.first_layer * sp_tex->img_stride[j]; } if (view->target == PIPE_TEXTURE_CUBE || view->target == PIPE_TEXTURE_CUBE_ARRAY) { assert(num_layers % 6 == 0); } assert(view->u.tex.first_layer <= view->u.tex.last_layer); assert(view->u.tex.last_layer < res->array_size); } } else { unsigned view_blocksize = util_format_get_blocksize(view->format); addr = sp_tex->data; /* probably don't really need to fill that out */ mip_offsets[0] = 0; row_stride[0] = 0; img_stride[0] = 0; /* everything specified in number of elements here. */ width0 = view->u.buf.last_element - view->u.buf.first_element + 1; addr = (uint8_t *)addr + view->u.buf.first_element * view_blocksize; assert(view->u.buf.first_element <= view->u.buf.last_element); assert(view->u.buf.last_element * view_blocksize < res->width0); } } else { /* display target texture/surface */ /* * XXX: Where should this be unmapped? */ struct softpipe_screen *screen = softpipe_screen(tex->screen); struct sw_winsys *winsys = screen->winsys; addr = winsys->displaytarget_map(winsys, sp_tex->dt, PIPE_TRANSFER_READ); row_stride[0] = sp_tex->stride[0]; img_stride[0] = sp_tex->img_stride[0]; mip_offsets[0] = 0; assert(addr); } draw_set_mapped_texture(sp->draw, shader_type, i, width0, tex->height0, num_layers, first_level, last_level, addr, row_stride, img_stride, mip_offsets); } } }
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_context *rctx = (struct r600_context *)ctx; struct r600_texture *rsrc = (struct r600_texture*)src; struct texture_orig_info orig_info[2]; struct pipe_box sbox; const struct pipe_box *psbox = src_box; boolean restore_orig[2]; unsigned last_sample, i; memset(orig_info, 0, sizeof(orig_info)); /* Handle buffers first. */ if (dst->target == PIPE_BUFFER && src->target == PIPE_BUFFER) { r600_copy_buffer(ctx, dst, dstx, src, src_box); return; } assert(u_max_sample(dst) == u_max_sample(src)); last_sample = u_max_sample(dst); /* This must be done before entering u_blitter to avoid recursion. */ if (rsrc->is_depth && !rsrc->is_flushing_texture) { if (!r600_init_flushed_depth_texture(ctx, src, NULL)) return; /* error */ r600_blit_uncompress_depth(ctx, rsrc, NULL, src_level, src_level, src_box->z, src_box->z + src_box->depth - 1, 0, u_max_sample(src)); } restore_orig[0] = restore_orig[1] = FALSE; if (util_format_is_compressed(src->format) && util_format_is_compressed(dst->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; 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); } else if (!util_blitter_is_copy_supported(rctx->blitter, dst, src, PIPE_MASK_RGBAZS)) { if (util_format_is_subsampled_2x1_32bpp(src->format) && util_format_is_subsampled_2x1_32bpp(dst->format)) { r600_subsampled_2x1_32bpp_to_blittable(src, src_level, &orig_info[0]); r600_subsampled_2x1_32bpp_to_blittable(dst, dst_level, &orig_info[1]); sbox = *src_box; sbox.x = util_format_get_nblocksx(orig_info[0].format, src_box->x); sbox.width = util_format_get_nblocksx(orig_info[0].format, src_box->width); psbox = &sbox; dstx = util_format_get_nblocksx(orig_info[1].format, dstx); } else { unsigned blocksize = util_format_get_blocksize(src->format); switch (blocksize) { case 1: r600_change_format(src, src_level, &orig_info[0], PIPE_FORMAT_R8_UNORM); r600_change_format(dst, dst_level, &orig_info[1], PIPE_FORMAT_R8_UNORM); break; case 4: r600_change_format(src, src_level, &orig_info[0], PIPE_FORMAT_R8G8B8A8_UNORM); r600_change_format(dst, dst_level, &orig_info[1], PIPE_FORMAT_R8G8B8A8_UNORM); break; default: fprintf(stderr, "Unhandled format %s with blocksize %u\n", util_format_short_name(src->format), blocksize); assert(0); } } restore_orig[0] = TRUE; restore_orig[1] = TRUE; } for (i = 0; i <= last_sample; i++) { r600_blitter_begin(ctx, R600_COPY_TEXTURE); util_blitter_copy_texture(rctx->blitter, dst, dst_level, 1 << i, dstx, dsty, dstz, src, src_level, i, psbox); r600_blitter_end(ctx); } if (restore_orig[0]) r600_reset_blittable_to_orig(src, src_level, &orig_info[0]); if (restore_orig[1]) r600_reset_blittable_to_orig(dst, dst_level, &orig_info[1]); }
static __DRIbuffer * dri2_allocate_buffer(__DRIscreen *sPriv, unsigned attachment, unsigned format, int width, int height) { struct dri_screen *screen = dri_screen(sPriv); struct dri2_buffer *buffer; struct pipe_resource templ; enum pipe_format pf; unsigned bind = 0; struct winsys_handle whandle; switch (attachment) { case __DRI_BUFFER_FRONT_LEFT: case __DRI_BUFFER_FAKE_FRONT_LEFT: bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW; break; case __DRI_BUFFER_BACK_LEFT: bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW; break; case __DRI_BUFFER_DEPTH: case __DRI_BUFFER_DEPTH_STENCIL: case __DRI_BUFFER_STENCIL: bind = PIPE_BIND_DEPTH_STENCIL; /* XXX sampler? */ break; } switch (format) { case 32: pf = PIPE_FORMAT_B8G8R8X8_UNORM; break; case 16: pf = PIPE_FORMAT_Z16_UNORM; break; default: return NULL; } buffer = CALLOC_STRUCT(dri2_buffer); if (!buffer) return NULL; memset(&templ, 0, sizeof(templ)); templ.bind = bind; templ.format = pf; templ.target = PIPE_TEXTURE_2D; templ.last_level = 0; templ.width0 = width; templ.height0 = height; templ.depth0 = 1; templ.array_size = 1; buffer->resource = screen->base.screen->resource_create(screen->base.screen, &templ); if (!buffer->resource) { FREE(buffer); return NULL; } memset(&whandle, 0, sizeof(whandle)); whandle.type = DRM_API_HANDLE_TYPE_SHARED; screen->base.screen->resource_get_handle(screen->base.screen, buffer->resource, &whandle); buffer->base.attachment = attachment; buffer->base.name = whandle.handle; buffer->base.cpp = util_format_get_blocksize(pf); buffer->base.pitch = whandle.stride; return &buffer->base; }
/** * glGetTexImage() helper: decompress a compressed texture by rendering * a textured quad. Store the results in the user's buffer. */ static void decompress_with_blit(struct gl_context * ctx, GLenum format, GLenum type, GLvoid *pixels, struct gl_texture_image *texImage) { struct st_context *st = st_context(ctx); struct pipe_context *pipe = st->pipe; struct st_texture_image *stImage = st_texture_image(texImage); struct st_texture_object *stObj = st_texture_object(texImage->TexObject); struct pipe_sampler_view *src_view; const GLuint width = texImage->Width; const GLuint height = texImage->Height; struct pipe_surface *dst_surface; struct pipe_resource *dst_texture; struct pipe_transfer *tex_xfer; unsigned bind = (PIPE_BIND_RENDER_TARGET | /* util_blit may choose to render */ PIPE_BIND_TRANSFER_READ); /* create temp / dest surface */ if (!util_create_rgba_surface(pipe, width, height, bind, &dst_texture, &dst_surface)) { _mesa_problem(ctx, "util_create_rgba_surface() failed " "in decompress_with_blit()"); return; } /* Disable conditional rendering. */ if (st->render_condition) { pipe->render_condition(pipe, NULL, 0); } /* Create sampler view that limits fetches to the source mipmap level */ { struct pipe_sampler_view sv_temp; u_sampler_view_default_template(&sv_temp, stObj->pt, stObj->pt->format); sv_temp.format = util_format_linear(sv_temp.format); sv_temp.u.tex.first_level = sv_temp.u.tex.last_level = texImage->Level; src_view = pipe->create_sampler_view(pipe, stObj->pt, &sv_temp); if (!src_view) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage"); return; } } /* blit/render/decompress */ util_blit_pixels_tex(st->blit, src_view, /* pipe_resource (src) */ 0, 0, /* src x0, y0 */ width, height, /* src x1, y1 */ dst_surface, /* pipe_surface (dst) */ 0, 0, /* dst x0, y0 */ width, height, /* dst x1, y1 */ 0.0, /* z */ PIPE_TEX_MIPFILTER_NEAREST); /* Restore conditional rendering state. */ if (st->render_condition) { pipe->render_condition(pipe, st->render_condition, st->condition_mode); } /* map the dst_surface so we can read from it */ tex_xfer = pipe_get_transfer(pipe, dst_texture, 0, 0, PIPE_TRANSFER_READ, 0, 0, width, height); pixels = _mesa_map_pbo_dest(ctx, &ctx->Pack, pixels); /* copy/pack data into user buffer */ if (_mesa_format_matches_format_and_type(stImage->base.TexFormat, format, type, ctx->Pack.SwapBytes)) { /* memcpy */ const uint bytesPerRow = width * util_format_get_blocksize(stImage->pt->format); ubyte *map = pipe_transfer_map(pipe, tex_xfer); GLuint row; for (row = 0; row < height; row++) { GLvoid *dest = _mesa_image_address2d(&ctx->Pack, pixels, width, height, format, type, row, 0); memcpy(dest, map, bytesPerRow); map += tex_xfer->stride; } pipe_transfer_unmap(pipe, tex_xfer); } else { /* format translation via floats */ GLuint row; enum pipe_format pformat = util_format_linear(dst_texture->format); GLfloat *rgba; rgba = (GLfloat *) malloc(width * 4 * sizeof(GLfloat)); if (!rgba) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage()"); goto end; } for (row = 0; row < height; row++) { const GLbitfield transferOps = 0x0; /* bypassed for glGetTexImage() */ GLvoid *dest = _mesa_image_address2d(&ctx->Pack, pixels, width, height, format, type, row, 0); if (ST_DEBUG & DEBUG_FALLBACK) debug_printf("%s: fallback format translation\n", __FUNCTION__); /* get float[4] rgba row from surface */ pipe_get_tile_rgba_format(pipe, tex_xfer, 0, row, width, 1, pformat, rgba); _mesa_pack_rgba_span_float(ctx, width, (GLfloat (*)[4]) rgba, format, type, dest, &ctx->Pack, transferOps); } free(rgba); } end: _mesa_unmap_pbo_dest(ctx, &ctx->Pack); pipe->transfer_destroy(pipe, tex_xfer); /* destroy the temp / dest surface */ util_destroy_rgba_surface(dst_texture, dst_surface); pipe_sampler_view_release(pipe, &src_view); }
struct pipe_resource * nv30_miptree_create(struct pipe_screen *pscreen, const struct pipe_resource *tmpl) { struct nouveau_device *dev = nouveau_screen(pscreen)->device; struct nv30_miptree *mt = CALLOC_STRUCT(nv30_miptree); struct pipe_resource *pt = &mt->base.base; unsigned blocksz, size; unsigned w, h, d, l; int ret; switch (tmpl->nr_samples) { case 4: mt->ms_mode = 0x00004000; mt->ms_x = 1; mt->ms_y = 1; break; case 2: mt->ms_mode = 0x00003000; mt->ms_x = 1; mt->ms_y = 0; break; default: mt->ms_mode = 0x00000000; mt->ms_x = 0; mt->ms_y = 0; break; } mt->base.vtbl = &nv30_miptree_vtbl; *pt = *tmpl; pipe_reference_init(&pt->reference, 1); pt->screen = pscreen; w = pt->width0 << mt->ms_x; h = pt->height0 << mt->ms_y; d = (pt->target == PIPE_TEXTURE_3D) ? pt->depth0 : 1; blocksz = util_format_get_blocksize(pt->format); if ((pt->target == PIPE_TEXTURE_RECT) || !util_is_power_of_two(pt->width0) || !util_is_power_of_two(pt->height0) || !util_is_power_of_two(pt->depth0) || util_format_is_compressed(pt->format) || util_format_is_float(pt->format) || mt->ms_mode) { mt->uniform_pitch = util_format_get_nblocksx(pt->format, w) * blocksz; mt->uniform_pitch = align(mt->uniform_pitch, 64); } if (!mt->uniform_pitch) mt->swizzled = TRUE; size = 0; for (l = 0; l <= pt->last_level; l++) { struct nv30_miptree_level *lvl = &mt->level[l]; unsigned nbx = util_format_get_nblocksx(pt->format, w); unsigned nby = util_format_get_nblocksx(pt->format, h); lvl->offset = size; lvl->pitch = mt->uniform_pitch; if (!lvl->pitch) lvl->pitch = nbx * blocksz; lvl->zslice_size = lvl->pitch * nby; size += lvl->zslice_size * d; w = u_minify(w, 1); h = u_minify(h, 1); d = u_minify(d, 1); } mt->layer_size = size; if (pt->target == PIPE_TEXTURE_CUBE) { if (!mt->uniform_pitch) mt->layer_size = align(mt->layer_size, 128); size = mt->layer_size * 6; } ret = nouveau_bo_new(dev, NOUVEAU_BO_VRAM, 256, size, NULL, &mt->base.bo); if (ret) { FREE(mt); return NULL; } mt->base.domain = NOUVEAU_BO_VRAM; return &mt->base.base; }
/* Copy a block of pixels from one surface to another. */ static void r300_resource_copy_region(struct pipe_context *pipe, 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 pipe_screen *screen = pipe->screen; struct r300_context *r300 = r300_context(pipe); struct pipe_framebuffer_state *fb = (struct pipe_framebuffer_state*)r300->fb_state.state; unsigned src_width0 = r300_resource(src)->tex.width0; unsigned src_height0 = r300_resource(src)->tex.height0; unsigned dst_width0 = r300_resource(dst)->tex.width0; unsigned dst_height0 = r300_resource(dst)->tex.height0; unsigned layout; struct pipe_box box, dstbox; struct pipe_sampler_view src_templ, *src_view; struct pipe_surface dst_templ, *dst_view; /* Fallback for buffers. */ if ((dst->target == PIPE_BUFFER && src->target == PIPE_BUFFER) || !r300_is_blit_supported(dst->format)) { util_resource_copy_region(pipe, dst, dst_level, dstx, dsty, dstz, src, src_level, src_box); return; } /* Can't read MSAA textures. */ if (src->nr_samples > 1 || dst->nr_samples > 1) { return; } /* The code below changes the texture format so that the copy can be done * on hardware. E.g. depth-stencil surfaces are copied as RGBA * colorbuffers. */ util_blitter_default_dst_texture(&dst_templ, dst, dst_level, dstz); util_blitter_default_src_texture(&src_templ, src, src_level); layout = util_format_description(dst_templ.format)->layout; /* Handle non-renderable plain formats. */ if (layout == UTIL_FORMAT_LAYOUT_PLAIN && (!screen->is_format_supported(screen, src_templ.format, src->target, src->nr_samples, PIPE_BIND_SAMPLER_VIEW) || !screen->is_format_supported(screen, dst_templ.format, dst->target, dst->nr_samples, PIPE_BIND_RENDER_TARGET))) { switch (util_format_get_blocksize(dst_templ.format)) { case 1: dst_templ.format = PIPE_FORMAT_I8_UNORM; break; case 2: dst_templ.format = PIPE_FORMAT_B4G4R4A4_UNORM; break; case 4: dst_templ.format = PIPE_FORMAT_B8G8R8A8_UNORM; break; case 8: dst_templ.format = PIPE_FORMAT_R16G16B16A16_UNORM; break; default: debug_printf("r300: copy_region: Unhandled format: %s. Falling back to software.\n" "r300: copy_region: Software fallback doesn't work for tiled textures.\n", util_format_short_name(dst_templ.format)); } src_templ.format = dst_templ.format; } /* Handle compressed formats. */ if (layout == UTIL_FORMAT_LAYOUT_S3TC || layout == UTIL_FORMAT_LAYOUT_RGTC) { assert(src_templ.format == dst_templ.format); box = *src_box; src_box = &box; dst_width0 = align(dst_width0, 4); dst_height0 = align(dst_height0, 4); src_width0 = align(src_width0, 4); src_height0 = align(src_height0, 4); box.width = align(box.width, 4); box.height = align(box.height, 4); switch (util_format_get_blocksize(dst_templ.format)) { case 8: /* one 4x4 pixel block has 8 bytes. * we set 1 pixel = 4 bytes ===> 1 block corrensponds to 2 pixels. */ dst_templ.format = PIPE_FORMAT_R8G8B8A8_UNORM; dst_width0 = dst_width0 / 2; src_width0 = src_width0 / 2; dstx /= 2; box.x /= 2; box.width /= 2; break; case 16: /* one 4x4 pixel block has 16 bytes. * we set 1 pixel = 4 bytes ===> 1 block corresponds to 4 pixels. */ dst_templ.format = PIPE_FORMAT_R8G8B8A8_UNORM; break; } src_templ.format = dst_templ.format; dst_height0 = dst_height0 / 4; src_height0 = src_height0 / 4; dsty /= 4; box.y /= 4; box.height /= 4; } /* Fallback for textures. */ if (!screen->is_format_supported(screen, dst_templ.format, dst->target, dst->nr_samples, PIPE_BIND_RENDER_TARGET) || !screen->is_format_supported(screen, src_templ.format, src->target, src->nr_samples, PIPE_BIND_SAMPLER_VIEW)) { assert(0 && "this shouldn't happen, update r300_is_blit_supported"); util_resource_copy_region(pipe, dst, dst_level, dstx, dsty, dstz, src, src_level, src_box); return; } /* Decompress ZMASK. */ if (r300->zmask_in_use && !r300->locked_zbuffer) { if (fb->zsbuf->texture == src || fb->zsbuf->texture == dst) { r300_decompress_zmask(r300); } } dst_view = r300_create_surface_custom(pipe, dst, &dst_templ, dst_width0, dst_height0); src_view = r300_create_sampler_view_custom(pipe, src, &src_templ, src_width0, src_height0); u_box_3d(dstx, dsty, dstz, abs(src_box->width), abs(src_box->height), abs(src_box->depth), &dstbox); r300_blitter_begin(r300, R300_COPY); util_blitter_blit_generic(r300->blitter, dst_view, &dstbox, src_view, src_box, src_width0, src_height0, PIPE_MASK_RGBAZS, PIPE_TEX_FILTER_NEAREST, NULL, FALSE); r300_blitter_end(r300); pipe_surface_reference(&dst_view, NULL); pipe_sampler_view_reference(&src_view, NULL); }
static void i945_texture_layout_2d(struct i915_texture *tex) { struct pipe_resource *pt = &tex->b.b; int align_x = 4, align_y = 2; unsigned level; unsigned x = 0; unsigned y = 0; unsigned width = pt->width0; unsigned height = pt->height0; unsigned nblocksx = util_format_get_nblocksx(pt->format, pt->width0); unsigned nblocksy = util_format_get_nblocksy(pt->format, pt->height0); if (util_format_is_s3tc(pt->format)) { align_x = 1; align_y = 1; } tex->stride = align(util_format_get_stride(pt->format, pt->width0), 4); /* May need to adjust pitch to accomodate the placement of * the 2nd mipmap level. This occurs when the alignment * constraints of mipmap placement push the right edge of the * 2nd mipmap level out past the width of its parent. */ if (pt->last_level > 0) { unsigned mip1_nblocksx = align_nblocksx(pt->format, u_minify(pt->width0, 1), align_x) + util_format_get_nblocksx(pt->format, u_minify(pt->width0, 2)); if (mip1_nblocksx > nblocksx) tex->stride = mip1_nblocksx * util_format_get_blocksize(pt->format); } /* Pitch must be a whole number of dwords */ tex->stride = align(tex->stride, 64); 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, x, y); /* Because the images are packed better, the final offset * might not be the maximal one: */ tex->total_nblocksy = MAX2(tex->total_nblocksy, y + nblocksy); /* Layout_below: step right after second mipmap level. */ if (level == 1) { x += nblocksx; } else { y += nblocksy; } width = u_minify(width, 1); height = u_minify(height, 1); nblocksx = align_nblocksx(pt->format, width, align_x); nblocksy = align_nblocksy(pt->format, height, align_y); } }
static void i945_miptree_layout_2d(struct i915_texture *tex) { struct pipe_texture *pt = &tex->base; const int align_x = 2, align_y = 4; unsigned level; unsigned x = 0; unsigned y = 0; unsigned width = pt->width0; unsigned height = pt->height0; unsigned nblocksx = util_format_get_nblocksx(pt->format, pt->width0); unsigned nblocksy = util_format_get_nblocksy(pt->format, pt->height0); /* used for scanouts that need special layouts */ if (tex->base.tex_usage & PIPE_TEXTURE_USAGE_PRIMARY) if (i915_scanout_layout(tex)) return; /* for shared buffers we use some very like scanout */ if (tex->base.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); /* May need to adjust pitch to accomodate the placement of * the 2nd mipmap level. This occurs when the alignment * constraints of mipmap placement push the right edge of the * 2nd mipmap level out past the width of its parent. */ if (pt->last_level > 0) { unsigned mip1_nblocksx = align(util_format_get_nblocksx(pt->format, u_minify(width, 1)), align_x) + util_format_get_nblocksx(pt->format, u_minify(width, 2)); if (mip1_nblocksx > nblocksx) tex->stride = mip1_nblocksx * util_format_get_blocksize(pt->format); } /* Pitch must be a whole number of dwords */ tex->stride = align(tex->stride, 64); 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, x, y); nblocksy = align(nblocksy, align_y); /* Because the images are packed better, the final offset * might not be the maximal one: */ tex->total_nblocksy = MAX2(tex->total_nblocksy, y + nblocksy); /* Layout_below: step right after second mipmap level. */ if (level == 1) { x += align(nblocksx, align_x); } else { y += nblocksy; } width = u_minify(width, 1); height = u_minify(height, 1); nblocksx = util_format_get_nblocksx(pt->format, width); nblocksy = util_format_get_nblocksy(pt->format, height); } }
void i915_clear_emit(struct pipe_context *pipe, unsigned buffers, const union pipe_color_union *color, double depth, unsigned stencil, unsigned destx, unsigned desty, unsigned width, unsigned height) { struct i915_context *i915 = i915_context(pipe); uint32_t clear_params, clear_color, clear_depth, clear_stencil, clear_color8888, packed_z_stencil; union util_color u_color; float f_depth = depth; struct i915_texture *cbuf_tex, *depth_tex; int depth_clear_bbp, color_clear_bbp; cbuf_tex = depth_tex = NULL; clear_params = 0; depth_clear_bbp = color_clear_bbp = 0; if (buffers & PIPE_CLEAR_COLOR) { struct pipe_surface *cbuf = i915->framebuffer.cbufs[0]; clear_params |= CLEARPARAM_WRITE_COLOR; cbuf_tex = i915_texture(cbuf->texture); util_pack_color(color->f, cbuf->format, &u_color); if (util_format_get_blocksize(cbuf_tex->b.b.format) == 4) { clear_color = u_color.ui; color_clear_bbp = 32; } else { clear_color = (u_color.ui & 0xffff) | (u_color.ui << 16); color_clear_bbp = 16; } /* correctly swizzle clear value */ if (i915->current.target_fixup_format) util_pack_color(color->f, cbuf->format, &u_color); else util_pack_color(color->f, PIPE_FORMAT_B8G8R8A8_UNORM, &u_color); clear_color8888 = u_color.ui; } else clear_color = clear_color8888 = 0; clear_depth = clear_stencil = 0; if (buffers & PIPE_CLEAR_DEPTH) { struct pipe_surface *zbuf = i915->framebuffer.zsbuf; clear_params |= CLEARPARAM_WRITE_DEPTH; depth_tex = i915_texture(zbuf->texture); packed_z_stencil = util_pack_z_stencil(depth_tex->b.b.format, depth, stencil); if (util_format_get_blocksize(depth_tex->b.b.format) == 4) { /* Avoid read-modify-write if there's no stencil. */ if (buffers & PIPE_CLEAR_STENCIL || depth_tex->b.b.format != PIPE_FORMAT_Z24_UNORM_S8_UINT) { clear_params |= CLEARPARAM_WRITE_STENCIL; clear_stencil = packed_z_stencil >> 24; } clear_depth = packed_z_stencil & 0xffffff; depth_clear_bbp = 32; } else {
static int update_zero_stride( struct svga_context *svga, unsigned dirty ) { unsigned i; svga->curr.zero_stride_vertex_elements = 0; svga->curr.num_zero_stride_vertex_elements = 0; for (i = 0; i < svga->curr.num_vertex_elements; i++) { const struct pipe_vertex_element *vel = &svga->curr.ve[i]; const struct pipe_vertex_buffer *vbuffer = &svga->curr.vb[ vel->vertex_buffer_index]; if (vbuffer->stride == 0) { unsigned const_idx = svga->curr.num_zero_stride_vertex_elements; struct translate *translate; struct translate_key key; void *mapped_buffer; svga->curr.zero_stride_vertex_elements |= (1 << i); ++svga->curr.num_zero_stride_vertex_elements; key.output_stride = 4 * sizeof(float); key.nr_elements = 1; key.element[0].type = TRANSLATE_ELEMENT_NORMAL; key.element[0].input_format = vel->src_format; key.element[0].output_format = PIPE_FORMAT_R32G32B32A32_FLOAT; key.element[0].input_buffer = vel->vertex_buffer_index; key.element[0].input_offset = vel->src_offset; key.element[0].instance_divisor = vel->instance_divisor; key.element[0].output_offset = const_idx * 4 * sizeof(float); translate_key_sanitize(&key); /* translate_generic_create is technically private but * we don't want to code-generate, just want generic * translation */ translate = translate_generic_create(&key); assert(vel->src_offset == 0); mapped_buffer = pipe_buffer_map_range(svga->pipe.screen, vbuffer->buffer, vel->src_offset, util_format_get_blocksize(vel->src_format), PIPE_BUFFER_USAGE_CPU_READ); translate->set_buffer(translate, vel->vertex_buffer_index, mapped_buffer, vbuffer->stride); translate->run(translate, 0, 1, 0, svga->curr.zero_stride_constants); pipe_buffer_unmap(svga->pipe.screen, vbuffer->buffer); translate->release(translate); } } if (svga->curr.num_zero_stride_vertex_elements) svga->dirty |= SVGA_NEW_ZERO_STRIDE; return 0; }
static void si_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 si_context *sctx = (struct si_context *)ctx; struct r600_texture *rdst = (struct r600_texture*)dst; struct pipe_surface *dst_view, dst_templ; struct pipe_sampler_view src_templ, *src_view; struct texture_orig_info orig_info[2]; struct pipe_box sbox, dstbox; boolean restore_orig[2]; /* Fallback for buffers. */ if (dst->target == PIPE_BUFFER && src->target == PIPE_BUFFER) { si_copy_buffer(sctx, dst, src, dstx, src_box->x, src_box->width); return; } memset(orig_info, 0, sizeof(orig_info)); /* The driver doesn't decompress resources automatically while * u_blitter is rendering. */ si_decompress_subresource(ctx, src, src_level, src_box->z, src_box->z + src_box->depth - 1); restore_orig[0] = restore_orig[1] = FALSE; if (util_format_is_compressed(src->format) && util_format_is_compressed(dst->format)) { si_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; src_box = &sbox; si_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); } else if (!util_blitter_is_copy_supported(sctx->blitter, dst, src)) { if (util_format_is_subsampled_422(src->format)) { /* XXX untested */ si_change_format(src, src_level, &orig_info[0], PIPE_FORMAT_R8G8B8A8_UINT); si_change_format(dst, dst_level, &orig_info[1], PIPE_FORMAT_R8G8B8A8_UINT); sbox = *src_box; sbox.x = util_format_get_nblocksx(orig_info[0].format, src_box->x); sbox.width = util_format_get_nblocksx(orig_info[0].format, src_box->width); src_box = &sbox; dstx = util_format_get_nblocksx(orig_info[1].format, dstx); restore_orig[0] = TRUE; restore_orig[1] = TRUE; } else { unsigned blocksize = util_format_get_blocksize(src->format); switch (blocksize) { case 1: si_change_format(src, src_level, &orig_info[0], PIPE_FORMAT_R8_UNORM); si_change_format(dst, dst_level, &orig_info[1], PIPE_FORMAT_R8_UNORM); break; case 2: si_change_format(src, src_level, &orig_info[0], PIPE_FORMAT_R8G8_UNORM); si_change_format(dst, dst_level, &orig_info[1], PIPE_FORMAT_R8G8_UNORM); break; case 4: si_change_format(src, src_level, &orig_info[0], PIPE_FORMAT_R8G8B8A8_UNORM); si_change_format(dst, dst_level, &orig_info[1], PIPE_FORMAT_R8G8B8A8_UNORM); break; case 8: si_change_format(src, src_level, &orig_info[0], PIPE_FORMAT_R16G16B16A16_UINT); si_change_format(dst, dst_level, &orig_info[1], PIPE_FORMAT_R16G16B16A16_UINT); break; case 16: si_change_format(src, src_level, &orig_info[0], PIPE_FORMAT_R32G32B32A32_UINT); si_change_format(dst, dst_level, &orig_info[1], PIPE_FORMAT_R32G32B32A32_UINT); break; default: fprintf(stderr, "Unhandled format %s with blocksize %u\n", util_format_short_name(src->format), blocksize); assert(0); } restore_orig[0] = TRUE; restore_orig[1] = TRUE; } } /* Initialize the surface. */ util_blitter_default_dst_texture(&dst_templ, dst, dst_level, dstz); dst_view = r600_create_surface_custom(ctx, dst, &dst_templ, rdst->surface.level[dst_level].npix_x, rdst->surface.level[dst_level].npix_y); /* Initialize the sampler view. */ util_blitter_default_src_texture(&src_templ, src, src_level); src_view = ctx->create_sampler_view(ctx, src, &src_templ); u_box_3d(dstx, dsty, dstz, abs(src_box->width), abs(src_box->height), abs(src_box->depth), &dstbox); /* Copy. */ si_blitter_begin(ctx, SI_COPY); util_blitter_blit_generic(sctx->blitter, dst_view, &dstbox, src_view, src_box, src->width0, src->height0, PIPE_MASK_RGBAZS, PIPE_TEX_FILTER_NEAREST, NULL); si_blitter_end(ctx); pipe_surface_reference(&dst_view, NULL); pipe_sampler_view_reference(&src_view, NULL); if (restore_orig[0]) si_reset_blittable_to_orig(src, src_level, &orig_info[0]); if (restore_orig[1]) si_reset_blittable_to_orig(dst, dst_level, &orig_info[1]); }
/** * glGetTexImage() helper: decompress a compressed texture by rendering * a textured quad. Store the results in the user's buffer. */ static void decompress_with_blit(struct gl_context * ctx, GLenum format, GLenum type, GLvoid *pixels, struct gl_texture_image *texImage) { struct st_context *st = st_context(ctx); struct pipe_context *pipe = st->pipe; struct st_texture_image *stImage = st_texture_image(texImage); struct st_texture_object *stObj = st_texture_object(texImage->TexObject); const GLuint width = texImage->Width; const GLuint height = texImage->Height; struct pipe_resource *dst_texture; struct pipe_blit_info blit; unsigned bind = (PIPE_BIND_RENDER_TARGET | PIPE_BIND_TRANSFER_READ); struct pipe_transfer *tex_xfer; ubyte *map; /* create temp / dest surface */ if (!util_create_rgba_texture(pipe, width, height, bind, &dst_texture)) { _mesa_problem(ctx, "util_create_rgba_texture() failed " "in decompress_with_blit()"); return; } blit.src.resource = stObj->pt; blit.src.level = texImage->Level; blit.src.format = util_format_linear(stObj->pt->format); blit.dst.resource = dst_texture; blit.dst.level = 0; blit.dst.format = dst_texture->format; blit.src.box.x = blit.dst.box.x = 0; blit.src.box.y = blit.dst.box.y = 0; blit.src.box.z = 0; /* XXX compressed array textures? */ blit.dst.box.z = 0; blit.src.box.width = blit.dst.box.width = width; blit.src.box.height = blit.dst.box.height = height; blit.src.box.depth = blit.dst.box.depth = 1; blit.mask = PIPE_MASK_RGBA; blit.filter = PIPE_TEX_FILTER_NEAREST; blit.scissor_enable = FALSE; /* blit/render/decompress */ st->pipe->blit(st->pipe, &blit); pixels = _mesa_map_pbo_dest(ctx, &ctx->Pack, pixels); map = pipe_transfer_map(pipe, dst_texture, 0, 0, PIPE_TRANSFER_READ, 0, 0, width, height, &tex_xfer); if (!map) { goto end; } /* copy/pack data into user buffer */ if (_mesa_format_matches_format_and_type(stImage->base.TexFormat, format, type, ctx->Pack.SwapBytes)) { /* memcpy */ const uint bytesPerRow = width * util_format_get_blocksize(stImage->pt->format); /* map the dst_surface so we can read from it */ GLuint row; for (row = 0; row < height; row++) { GLvoid *dest = _mesa_image_address2d(&ctx->Pack, pixels, width, height, format, type, row, 0); memcpy(dest, map, bytesPerRow); map += tex_xfer->stride; } pipe_transfer_unmap(pipe, tex_xfer); } else { /* format translation via floats */ GLuint row; enum pipe_format pformat = util_format_linear(dst_texture->format); GLfloat *rgba; rgba = malloc(width * 4 * sizeof(GLfloat)); if (!rgba) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage()"); goto end; } for (row = 0; row < height; row++) { const GLbitfield transferOps = 0x0; /* bypassed for glGetTexImage() */ GLvoid *dest = _mesa_image_address2d(&ctx->Pack, pixels, width, height, format, type, row, 0); if (ST_DEBUG & DEBUG_FALLBACK) debug_printf("%s: fallback format translation\n", __FUNCTION__); /* get float[4] rgba row from surface */ pipe_get_tile_rgba_format(tex_xfer, map, 0, row, width, 1, pformat, rgba); _mesa_pack_rgba_span_float(ctx, width, (GLfloat (*)[4]) rgba, format, type, dest, &ctx->Pack, transferOps); } free(rgba); } end: if (map) pipe_transfer_unmap(pipe, tex_xfer); _mesa_unmap_pbo_dest(ctx, &ctx->Pack); pipe_resource_reference(&dst_texture, NULL); }
/* Get a width in pixels from a stride in bytes. */ static unsigned stride_to_width(enum pipe_format format, unsigned stride_in_bytes) { return (stride_in_bytes / util_format_get_blocksize(format)) * util_format_get_blockwidth(format); }
/** * Clear the rasterizer's current z/stencil tile. * This is a bin command called during bin processing. * Clear commands always clear all bound layers. */ static void lp_rast_clear_zstencil(struct lp_rasterizer_task *task, const union lp_rast_cmd_arg arg) { const struct lp_scene *scene = task->scene; uint64_t clear_value64 = arg.clear_zstencil.value; uint64_t clear_mask64 = arg.clear_zstencil.mask; uint32_t clear_value = (uint32_t) clear_value64; uint32_t clear_mask = (uint32_t) clear_mask64; const unsigned height = task->height; const unsigned width = task->width; const unsigned dst_stride = scene->zsbuf.stride; uint8_t *dst; unsigned i, j; unsigned block_size; LP_DBG(DEBUG_RAST, "%s: value=0x%08x, mask=0x%08x\n", __FUNCTION__, clear_value, clear_mask); /* * Clear the area of the depth/depth buffer matching this tile. */ if (scene->fb.zsbuf) { unsigned layer; uint8_t *dst_layer = task->depth_tile; block_size = util_format_get_blocksize(scene->fb.zsbuf->format); clear_value &= clear_mask; for (layer = 0; layer <= scene->fb_max_layer; layer++) { dst = dst_layer; switch (block_size) { case 1: assert(clear_mask == 0xff); memset(dst, (uint8_t) clear_value, height * width); break; case 2: if (clear_mask == 0xffff) { for (i = 0; i < height; i++) { uint16_t *row = (uint16_t *)dst; for (j = 0; j < width; j++) *row++ = (uint16_t) clear_value; dst += dst_stride; } } else { for (i = 0; i < height; i++) { uint16_t *row = (uint16_t *)dst; for (j = 0; j < width; j++) { uint16_t tmp = ~clear_mask & *row; *row++ = clear_value | tmp; } dst += dst_stride; } } break; case 4: if (clear_mask == 0xffffffff) { for (i = 0; i < height; i++) { uint32_t *row = (uint32_t *)dst; for (j = 0; j < width; j++) *row++ = clear_value; dst += dst_stride; } } else { for (i = 0; i < height; i++) { uint32_t *row = (uint32_t *)dst; for (j = 0; j < width; j++) { uint32_t tmp = ~clear_mask & *row; *row++ = clear_value | tmp; } dst += dst_stride; } } break; case 8: clear_value64 &= clear_mask64; if (clear_mask64 == 0xffffffffffULL) { for (i = 0; i < height; i++) { uint64_t *row = (uint64_t *)dst; for (j = 0; j < width; j++) *row++ = clear_value64; dst += dst_stride; } } else { for (i = 0; i < height; i++) { uint64_t *row = (uint64_t *)dst; for (j = 0; j < width; j++) { uint64_t tmp = ~clear_mask64 & *row; *row++ = clear_value64 | tmp; } dst += dst_stride; } } break; default: assert(0); break; } dst_layer += scene->zsbuf.layer_stride; } } }