1bf215546Sopenharmony_ci/************************************************************************** 2bf215546Sopenharmony_ci * 3bf215546Sopenharmony_ci * Copyright 2009 VMware, Inc. All Rights Reserved. 4bf215546Sopenharmony_ci * 5bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 6bf215546Sopenharmony_ci * copy of this software and associated documentation files (the 7bf215546Sopenharmony_ci * "Software"), to deal in the Software without restriction, including 8bf215546Sopenharmony_ci * without limitation the rights to use, copy, modify, merge, publish, 9bf215546Sopenharmony_ci * distribute, sub license, and/or sell copies of the Software, and to 10bf215546Sopenharmony_ci * permit persons to whom the Software is furnished to do so, subject to 11bf215546Sopenharmony_ci * the following conditions: 12bf215546Sopenharmony_ci * 13bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the 14bf215546Sopenharmony_ci * next paragraph) shall be included in all copies or substantial portions 15bf215546Sopenharmony_ci * of the Software. 16bf215546Sopenharmony_ci * 17bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18bf215546Sopenharmony_ci * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19bf215546Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 20bf215546Sopenharmony_ci * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR 21bf215546Sopenharmony_ci * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22bf215546Sopenharmony_ci * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23bf215546Sopenharmony_ci * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24bf215546Sopenharmony_ci * 25bf215546Sopenharmony_ci **************************************************************************/ 26bf215546Sopenharmony_ci 27bf215546Sopenharmony_ci/** 28bf215546Sopenharmony_ci * @file 29bf215546Sopenharmony_ci * Surface utility functions. 30bf215546Sopenharmony_ci * 31bf215546Sopenharmony_ci * @author Brian Paul 32bf215546Sopenharmony_ci */ 33bf215546Sopenharmony_ci 34bf215546Sopenharmony_ci 35bf215546Sopenharmony_ci#include "pipe/p_defines.h" 36bf215546Sopenharmony_ci#include "pipe/p_screen.h" 37bf215546Sopenharmony_ci#include "pipe/p_state.h" 38bf215546Sopenharmony_ci 39bf215546Sopenharmony_ci#include "util/format/u_format.h" 40bf215546Sopenharmony_ci#include "util/u_inlines.h" 41bf215546Sopenharmony_ci#include "util/u_rect.h" 42bf215546Sopenharmony_ci#include "util/u_surface.h" 43bf215546Sopenharmony_ci#include "util/u_pack_color.h" 44bf215546Sopenharmony_ci#include "util/u_memset.h" 45bf215546Sopenharmony_ci 46bf215546Sopenharmony_ci/** 47bf215546Sopenharmony_ci * Initialize a pipe_surface object. 'view' is considered to have 48bf215546Sopenharmony_ci * uninitialized contents. 49bf215546Sopenharmony_ci */ 50bf215546Sopenharmony_civoid 51bf215546Sopenharmony_ciu_surface_default_template(struct pipe_surface *surf, 52bf215546Sopenharmony_ci const struct pipe_resource *texture) 53bf215546Sopenharmony_ci{ 54bf215546Sopenharmony_ci memset(surf, 0, sizeof(*surf)); 55bf215546Sopenharmony_ci 56bf215546Sopenharmony_ci surf->format = texture->format; 57bf215546Sopenharmony_ci} 58bf215546Sopenharmony_ci 59bf215546Sopenharmony_ci 60bf215546Sopenharmony_ci/** 61bf215546Sopenharmony_ci * Copy 3D box from one place to another. 62bf215546Sopenharmony_ci * Position and sizes are in pixels. 63bf215546Sopenharmony_ci */ 64bf215546Sopenharmony_civoid 65bf215546Sopenharmony_ciutil_copy_box(ubyte * dst, 66bf215546Sopenharmony_ci enum pipe_format format, 67bf215546Sopenharmony_ci unsigned dst_stride, unsigned dst_slice_stride, 68bf215546Sopenharmony_ci unsigned dst_x, unsigned dst_y, unsigned dst_z, 69bf215546Sopenharmony_ci unsigned width, unsigned height, unsigned depth, 70bf215546Sopenharmony_ci const ubyte * src, 71bf215546Sopenharmony_ci int src_stride, unsigned src_slice_stride, 72bf215546Sopenharmony_ci unsigned src_x, unsigned src_y, unsigned src_z) 73bf215546Sopenharmony_ci{ 74bf215546Sopenharmony_ci unsigned z; 75bf215546Sopenharmony_ci dst += dst_z * dst_slice_stride; 76bf215546Sopenharmony_ci src += src_z * src_slice_stride; 77bf215546Sopenharmony_ci for (z = 0; z < depth; ++z) { 78bf215546Sopenharmony_ci util_copy_rect(dst, 79bf215546Sopenharmony_ci format, 80bf215546Sopenharmony_ci dst_stride, 81bf215546Sopenharmony_ci dst_x, dst_y, 82bf215546Sopenharmony_ci width, height, 83bf215546Sopenharmony_ci src, 84bf215546Sopenharmony_ci src_stride, 85bf215546Sopenharmony_ci src_x, src_y); 86bf215546Sopenharmony_ci 87bf215546Sopenharmony_ci dst += dst_slice_stride; 88bf215546Sopenharmony_ci src += src_slice_stride; 89bf215546Sopenharmony_ci } 90bf215546Sopenharmony_ci} 91bf215546Sopenharmony_ci 92bf215546Sopenharmony_ci 93bf215546Sopenharmony_civoid 94bf215546Sopenharmony_ciutil_fill_rect(ubyte * dst, 95bf215546Sopenharmony_ci enum pipe_format format, 96bf215546Sopenharmony_ci unsigned dst_stride, 97bf215546Sopenharmony_ci unsigned dst_x, 98bf215546Sopenharmony_ci unsigned dst_y, 99bf215546Sopenharmony_ci unsigned width, 100bf215546Sopenharmony_ci unsigned height, 101bf215546Sopenharmony_ci union util_color *uc) 102bf215546Sopenharmony_ci{ 103bf215546Sopenharmony_ci const struct util_format_description *desc = util_format_description(format); 104bf215546Sopenharmony_ci unsigned i, j; 105bf215546Sopenharmony_ci unsigned width_size; 106bf215546Sopenharmony_ci int blocksize = desc->block.bits / 8; 107bf215546Sopenharmony_ci int blockwidth = desc->block.width; 108bf215546Sopenharmony_ci int blockheight = desc->block.height; 109bf215546Sopenharmony_ci 110bf215546Sopenharmony_ci assert(blocksize > 0); 111bf215546Sopenharmony_ci assert(blockwidth > 0); 112bf215546Sopenharmony_ci assert(blockheight > 0); 113bf215546Sopenharmony_ci 114bf215546Sopenharmony_ci dst_x /= blockwidth; 115bf215546Sopenharmony_ci dst_y /= blockheight; 116bf215546Sopenharmony_ci width = (width + blockwidth - 1)/blockwidth; 117bf215546Sopenharmony_ci height = (height + blockheight - 1)/blockheight; 118bf215546Sopenharmony_ci 119bf215546Sopenharmony_ci dst += dst_x * blocksize; 120bf215546Sopenharmony_ci dst += dst_y * dst_stride; 121bf215546Sopenharmony_ci width_size = width * blocksize; 122bf215546Sopenharmony_ci 123bf215546Sopenharmony_ci switch (blocksize) { 124bf215546Sopenharmony_ci case 1: 125bf215546Sopenharmony_ci if(dst_stride == width_size) 126bf215546Sopenharmony_ci memset(dst, uc->ub, height * width_size); 127bf215546Sopenharmony_ci else { 128bf215546Sopenharmony_ci for (i = 0; i < height; i++) { 129bf215546Sopenharmony_ci memset(dst, uc->ub, width_size); 130bf215546Sopenharmony_ci dst += dst_stride; 131bf215546Sopenharmony_ci } 132bf215546Sopenharmony_ci } 133bf215546Sopenharmony_ci break; 134bf215546Sopenharmony_ci case 2: 135bf215546Sopenharmony_ci for (i = 0; i < height; i++) { 136bf215546Sopenharmony_ci uint16_t *row = (uint16_t *)dst; 137bf215546Sopenharmony_ci for (j = 0; j < width; j++) 138bf215546Sopenharmony_ci *row++ = uc->us; 139bf215546Sopenharmony_ci dst += dst_stride; 140bf215546Sopenharmony_ci } 141bf215546Sopenharmony_ci break; 142bf215546Sopenharmony_ci case 4: 143bf215546Sopenharmony_ci for (i = 0; i < height; i++) { 144bf215546Sopenharmony_ci util_memset32(dst, uc->ui[0], width); 145bf215546Sopenharmony_ci dst += dst_stride; 146bf215546Sopenharmony_ci } 147bf215546Sopenharmony_ci break; 148bf215546Sopenharmony_ci case 8: 149bf215546Sopenharmony_ci for (i = 0; i < height; i++) { 150bf215546Sopenharmony_ci util_memset64(dst, ((uint64_t *)uc)[0], width); 151bf215546Sopenharmony_ci dst += dst_stride; 152bf215546Sopenharmony_ci } 153bf215546Sopenharmony_ci break; 154bf215546Sopenharmony_ci default: 155bf215546Sopenharmony_ci for (i = 0; i < height; i++) { 156bf215546Sopenharmony_ci ubyte *row = dst; 157bf215546Sopenharmony_ci for (j = 0; j < width; j++) { 158bf215546Sopenharmony_ci memcpy(row, uc, blocksize); 159bf215546Sopenharmony_ci row += blocksize; 160bf215546Sopenharmony_ci } 161bf215546Sopenharmony_ci dst += dst_stride; 162bf215546Sopenharmony_ci } 163bf215546Sopenharmony_ci break; 164bf215546Sopenharmony_ci } 165bf215546Sopenharmony_ci} 166bf215546Sopenharmony_ci 167bf215546Sopenharmony_ci 168bf215546Sopenharmony_civoid 169bf215546Sopenharmony_ciutil_fill_box(ubyte * dst, 170bf215546Sopenharmony_ci enum pipe_format format, 171bf215546Sopenharmony_ci unsigned stride, 172bf215546Sopenharmony_ci unsigned layer_stride, 173bf215546Sopenharmony_ci unsigned x, 174bf215546Sopenharmony_ci unsigned y, 175bf215546Sopenharmony_ci unsigned z, 176bf215546Sopenharmony_ci unsigned width, 177bf215546Sopenharmony_ci unsigned height, 178bf215546Sopenharmony_ci unsigned depth, 179bf215546Sopenharmony_ci union util_color *uc) 180bf215546Sopenharmony_ci{ 181bf215546Sopenharmony_ci unsigned layer; 182bf215546Sopenharmony_ci dst += z * layer_stride; 183bf215546Sopenharmony_ci for (layer = z; layer < depth; layer++) { 184bf215546Sopenharmony_ci util_fill_rect(dst, format, 185bf215546Sopenharmony_ci stride, 186bf215546Sopenharmony_ci x, y, width, height, uc); 187bf215546Sopenharmony_ci dst += layer_stride; 188bf215546Sopenharmony_ci } 189bf215546Sopenharmony_ci} 190bf215546Sopenharmony_ci 191bf215546Sopenharmony_ci 192bf215546Sopenharmony_ci/** 193bf215546Sopenharmony_ci * Fallback function for pipe->resource_copy_region(). 194bf215546Sopenharmony_ci * We support copying between different formats (including compressed/ 195bf215546Sopenharmony_ci * uncompressed) if the bytes per block or pixel matches. If copying 196bf215546Sopenharmony_ci * compressed -> uncompressed, the dst region is reduced by the block 197bf215546Sopenharmony_ci * width, height. If copying uncompressed -> compressed, the dest region 198bf215546Sopenharmony_ci * is expanded by the block width, height. See GL_ARB_copy_image. 199bf215546Sopenharmony_ci * Note: (X,Y)=(0,0) is always the upper-left corner. 200bf215546Sopenharmony_ci */ 201bf215546Sopenharmony_civoid 202bf215546Sopenharmony_ciutil_resource_copy_region(struct pipe_context *pipe, 203bf215546Sopenharmony_ci struct pipe_resource *dst, 204bf215546Sopenharmony_ci unsigned dst_level, 205bf215546Sopenharmony_ci unsigned dst_x, unsigned dst_y, unsigned dst_z, 206bf215546Sopenharmony_ci struct pipe_resource *src, 207bf215546Sopenharmony_ci unsigned src_level, 208bf215546Sopenharmony_ci const struct pipe_box *src_box_in) 209bf215546Sopenharmony_ci{ 210bf215546Sopenharmony_ci struct pipe_transfer *src_trans, *dst_trans; 211bf215546Sopenharmony_ci uint8_t *dst_map; 212bf215546Sopenharmony_ci const uint8_t *src_map; 213bf215546Sopenharmony_ci enum pipe_format src_format; 214bf215546Sopenharmony_ci enum pipe_format dst_format; 215bf215546Sopenharmony_ci struct pipe_box src_box, dst_box; 216bf215546Sopenharmony_ci unsigned src_bs, dst_bs, src_bw, dst_bw, src_bh, dst_bh; 217bf215546Sopenharmony_ci 218bf215546Sopenharmony_ci assert(src && dst); 219bf215546Sopenharmony_ci if (!src || !dst) 220bf215546Sopenharmony_ci return; 221bf215546Sopenharmony_ci 222bf215546Sopenharmony_ci assert((src->target == PIPE_BUFFER && dst->target == PIPE_BUFFER) || 223bf215546Sopenharmony_ci (src->target != PIPE_BUFFER && dst->target != PIPE_BUFFER)); 224bf215546Sopenharmony_ci 225bf215546Sopenharmony_ci src_format = src->format; 226bf215546Sopenharmony_ci dst_format = dst->format; 227bf215546Sopenharmony_ci 228bf215546Sopenharmony_ci /* init src box */ 229bf215546Sopenharmony_ci src_box = *src_box_in; 230bf215546Sopenharmony_ci 231bf215546Sopenharmony_ci /* init dst box */ 232bf215546Sopenharmony_ci dst_box.x = dst_x; 233bf215546Sopenharmony_ci dst_box.y = dst_y; 234bf215546Sopenharmony_ci dst_box.z = dst_z; 235bf215546Sopenharmony_ci dst_box.width = src_box.width; 236bf215546Sopenharmony_ci dst_box.height = src_box.height; 237bf215546Sopenharmony_ci dst_box.depth = src_box.depth; 238bf215546Sopenharmony_ci 239bf215546Sopenharmony_ci src_bs = util_format_get_blocksize(src_format); 240bf215546Sopenharmony_ci src_bw = util_format_get_blockwidth(src_format); 241bf215546Sopenharmony_ci src_bh = util_format_get_blockheight(src_format); 242bf215546Sopenharmony_ci dst_bs = util_format_get_blocksize(dst_format); 243bf215546Sopenharmony_ci dst_bw = util_format_get_blockwidth(dst_format); 244bf215546Sopenharmony_ci dst_bh = util_format_get_blockheight(dst_format); 245bf215546Sopenharmony_ci 246bf215546Sopenharmony_ci /* Note: all box positions and sizes are in pixels */ 247bf215546Sopenharmony_ci if (src_bw > 1 && dst_bw == 1) { 248bf215546Sopenharmony_ci /* Copy from compressed to uncompressed. 249bf215546Sopenharmony_ci * Shrink dest box by the src block size. 250bf215546Sopenharmony_ci */ 251bf215546Sopenharmony_ci dst_box.width /= src_bw; 252bf215546Sopenharmony_ci dst_box.height /= src_bh; 253bf215546Sopenharmony_ci } 254bf215546Sopenharmony_ci else if (src_bw == 1 && dst_bw > 1) { 255bf215546Sopenharmony_ci /* Copy from uncompressed to compressed. 256bf215546Sopenharmony_ci * Expand dest box by the dest block size. 257bf215546Sopenharmony_ci */ 258bf215546Sopenharmony_ci dst_box.width *= dst_bw; 259bf215546Sopenharmony_ci dst_box.height *= dst_bh; 260bf215546Sopenharmony_ci } 261bf215546Sopenharmony_ci else { 262bf215546Sopenharmony_ci /* compressed -> compressed or uncompressed -> uncompressed copy */ 263bf215546Sopenharmony_ci assert(src_bw == dst_bw); 264bf215546Sopenharmony_ci assert(src_bh == dst_bh); 265bf215546Sopenharmony_ci } 266bf215546Sopenharmony_ci 267bf215546Sopenharmony_ci assert(src_bs == dst_bs); 268bf215546Sopenharmony_ci if (src_bs != dst_bs) { 269bf215546Sopenharmony_ci /* This can happen if we fail to do format checking before hand. 270bf215546Sopenharmony_ci * Don't crash below. 271bf215546Sopenharmony_ci */ 272bf215546Sopenharmony_ci return; 273bf215546Sopenharmony_ci } 274bf215546Sopenharmony_ci 275bf215546Sopenharmony_ci /* check that region boxes are block aligned */ 276bf215546Sopenharmony_ci assert(src_box.x % src_bw == 0); 277bf215546Sopenharmony_ci assert(src_box.y % src_bh == 0); 278bf215546Sopenharmony_ci assert(dst_box.x % dst_bw == 0); 279bf215546Sopenharmony_ci assert(dst_box.y % dst_bh == 0); 280bf215546Sopenharmony_ci 281bf215546Sopenharmony_ci /* check that region boxes are not out of bounds */ 282bf215546Sopenharmony_ci assert(src_box.x + src_box.width <= (int)u_minify(src->width0, src_level)); 283bf215546Sopenharmony_ci assert(src_box.y + src_box.height <= (int)u_minify(src->height0, src_level)); 284bf215546Sopenharmony_ci assert(dst_box.x + dst_box.width <= (int)u_minify(dst->width0, dst_level)); 285bf215546Sopenharmony_ci assert(dst_box.y + dst_box.height <= (int)u_minify(dst->height0, dst_level)); 286bf215546Sopenharmony_ci 287bf215546Sopenharmony_ci /* check that total number of src, dest bytes match */ 288bf215546Sopenharmony_ci assert((src_box.width / src_bw) * (src_box.height / src_bh) * src_bs == 289bf215546Sopenharmony_ci (dst_box.width / dst_bw) * (dst_box.height / dst_bh) * dst_bs); 290bf215546Sopenharmony_ci 291bf215546Sopenharmony_ci if (dst->target == PIPE_BUFFER && src->target == PIPE_BUFFER) { 292bf215546Sopenharmony_ci src_map = pipe->buffer_map(pipe, 293bf215546Sopenharmony_ci src, 294bf215546Sopenharmony_ci src_level, 295bf215546Sopenharmony_ci PIPE_MAP_READ, 296bf215546Sopenharmony_ci &src_box, &src_trans); 297bf215546Sopenharmony_ci assert(src_map); 298bf215546Sopenharmony_ci if (!src_map) { 299bf215546Sopenharmony_ci goto no_src_map_buf; 300bf215546Sopenharmony_ci } 301bf215546Sopenharmony_ci 302bf215546Sopenharmony_ci dst_map = pipe->buffer_map(pipe, 303bf215546Sopenharmony_ci dst, 304bf215546Sopenharmony_ci dst_level, 305bf215546Sopenharmony_ci PIPE_MAP_WRITE | 306bf215546Sopenharmony_ci PIPE_MAP_DISCARD_RANGE, &dst_box, 307bf215546Sopenharmony_ci &dst_trans); 308bf215546Sopenharmony_ci assert(dst_map); 309bf215546Sopenharmony_ci if (!dst_map) { 310bf215546Sopenharmony_ci goto no_dst_map_buf; 311bf215546Sopenharmony_ci } 312bf215546Sopenharmony_ci 313bf215546Sopenharmony_ci assert(src_box.height == 1); 314bf215546Sopenharmony_ci assert(src_box.depth == 1); 315bf215546Sopenharmony_ci memcpy(dst_map, src_map, src_box.width); 316bf215546Sopenharmony_ci 317bf215546Sopenharmony_ci pipe->buffer_unmap(pipe, dst_trans); 318bf215546Sopenharmony_ci no_dst_map_buf: 319bf215546Sopenharmony_ci pipe->buffer_unmap(pipe, src_trans); 320bf215546Sopenharmony_ci no_src_map_buf: 321bf215546Sopenharmony_ci ; 322bf215546Sopenharmony_ci } else { 323bf215546Sopenharmony_ci src_map = pipe->texture_map(pipe, 324bf215546Sopenharmony_ci src, 325bf215546Sopenharmony_ci src_level, 326bf215546Sopenharmony_ci PIPE_MAP_READ, 327bf215546Sopenharmony_ci &src_box, &src_trans); 328bf215546Sopenharmony_ci assert(src_map); 329bf215546Sopenharmony_ci if (!src_map) { 330bf215546Sopenharmony_ci goto no_src_map; 331bf215546Sopenharmony_ci } 332bf215546Sopenharmony_ci 333bf215546Sopenharmony_ci dst_map = pipe->texture_map(pipe, 334bf215546Sopenharmony_ci dst, 335bf215546Sopenharmony_ci dst_level, 336bf215546Sopenharmony_ci PIPE_MAP_WRITE | 337bf215546Sopenharmony_ci PIPE_MAP_DISCARD_RANGE, &dst_box, 338bf215546Sopenharmony_ci &dst_trans); 339bf215546Sopenharmony_ci assert(dst_map); 340bf215546Sopenharmony_ci if (!dst_map) { 341bf215546Sopenharmony_ci goto no_dst_map; 342bf215546Sopenharmony_ci } 343bf215546Sopenharmony_ci 344bf215546Sopenharmony_ci util_copy_box(dst_map, 345bf215546Sopenharmony_ci src_format, 346bf215546Sopenharmony_ci dst_trans->stride, dst_trans->layer_stride, 347bf215546Sopenharmony_ci 0, 0, 0, 348bf215546Sopenharmony_ci src_box.width, src_box.height, src_box.depth, 349bf215546Sopenharmony_ci src_map, 350bf215546Sopenharmony_ci src_trans->stride, src_trans->layer_stride, 351bf215546Sopenharmony_ci 0, 0, 0); 352bf215546Sopenharmony_ci 353bf215546Sopenharmony_ci pipe->texture_unmap(pipe, dst_trans); 354bf215546Sopenharmony_ci no_dst_map: 355bf215546Sopenharmony_ci pipe->texture_unmap(pipe, src_trans); 356bf215546Sopenharmony_ci no_src_map: 357bf215546Sopenharmony_ci ; 358bf215546Sopenharmony_ci } 359bf215546Sopenharmony_ci} 360bf215546Sopenharmony_ci 361bf215546Sopenharmony_cistatic void 362bf215546Sopenharmony_ciutil_clear_color_texture_helper(struct pipe_transfer *dst_trans, 363bf215546Sopenharmony_ci ubyte *dst_map, 364bf215546Sopenharmony_ci enum pipe_format format, 365bf215546Sopenharmony_ci const union pipe_color_union *color, 366bf215546Sopenharmony_ci unsigned width, unsigned height, unsigned depth) 367bf215546Sopenharmony_ci{ 368bf215546Sopenharmony_ci union util_color uc; 369bf215546Sopenharmony_ci 370bf215546Sopenharmony_ci assert(dst_trans->stride > 0); 371bf215546Sopenharmony_ci 372bf215546Sopenharmony_ci util_pack_color_union(format, &uc, color); 373bf215546Sopenharmony_ci 374bf215546Sopenharmony_ci util_fill_box(dst_map, format, 375bf215546Sopenharmony_ci dst_trans->stride, dst_trans->layer_stride, 376bf215546Sopenharmony_ci 0, 0, 0, width, height, depth, &uc); 377bf215546Sopenharmony_ci} 378bf215546Sopenharmony_ci 379bf215546Sopenharmony_cistatic void 380bf215546Sopenharmony_ciutil_clear_color_texture(struct pipe_context *pipe, 381bf215546Sopenharmony_ci struct pipe_resource *texture, 382bf215546Sopenharmony_ci enum pipe_format format, 383bf215546Sopenharmony_ci const union pipe_color_union *color, 384bf215546Sopenharmony_ci unsigned level, 385bf215546Sopenharmony_ci unsigned dstx, unsigned dsty, unsigned dstz, 386bf215546Sopenharmony_ci unsigned width, unsigned height, unsigned depth) 387bf215546Sopenharmony_ci{ 388bf215546Sopenharmony_ci struct pipe_transfer *dst_trans; 389bf215546Sopenharmony_ci ubyte *dst_map; 390bf215546Sopenharmony_ci 391bf215546Sopenharmony_ci dst_map = pipe_texture_map_3d(pipe, 392bf215546Sopenharmony_ci texture, 393bf215546Sopenharmony_ci level, 394bf215546Sopenharmony_ci PIPE_MAP_WRITE, 395bf215546Sopenharmony_ci dstx, dsty, dstz, 396bf215546Sopenharmony_ci width, height, depth, 397bf215546Sopenharmony_ci &dst_trans); 398bf215546Sopenharmony_ci if (!dst_map) 399bf215546Sopenharmony_ci return; 400bf215546Sopenharmony_ci 401bf215546Sopenharmony_ci if (dst_trans->stride > 0) { 402bf215546Sopenharmony_ci util_clear_color_texture_helper(dst_trans, dst_map, format, color, 403bf215546Sopenharmony_ci width, height, depth); 404bf215546Sopenharmony_ci } 405bf215546Sopenharmony_ci pipe->texture_unmap(pipe, dst_trans); 406bf215546Sopenharmony_ci} 407bf215546Sopenharmony_ci 408bf215546Sopenharmony_ci 409bf215546Sopenharmony_ci#define UBYTE_TO_USHORT(B) ((B) | ((B) << 8)) 410bf215546Sopenharmony_ci 411bf215546Sopenharmony_ci 412bf215546Sopenharmony_ci/** 413bf215546Sopenharmony_ci * Fallback for pipe->clear_render_target() function. 414bf215546Sopenharmony_ci * XXX this looks too hackish to be really useful. 415bf215546Sopenharmony_ci * cpp > 4 looks like a gross hack at best... 416bf215546Sopenharmony_ci * Plus can't use these transfer fallbacks when clearing 417bf215546Sopenharmony_ci * multisampled surfaces for instance. 418bf215546Sopenharmony_ci * Clears all bound layers. 419bf215546Sopenharmony_ci */ 420bf215546Sopenharmony_civoid 421bf215546Sopenharmony_ciutil_clear_render_target(struct pipe_context *pipe, 422bf215546Sopenharmony_ci struct pipe_surface *dst, 423bf215546Sopenharmony_ci const union pipe_color_union *color, 424bf215546Sopenharmony_ci unsigned dstx, unsigned dsty, 425bf215546Sopenharmony_ci unsigned width, unsigned height) 426bf215546Sopenharmony_ci{ 427bf215546Sopenharmony_ci struct pipe_transfer *dst_trans; 428bf215546Sopenharmony_ci ubyte *dst_map; 429bf215546Sopenharmony_ci 430bf215546Sopenharmony_ci assert(dst->texture); 431bf215546Sopenharmony_ci if (!dst->texture) 432bf215546Sopenharmony_ci return; 433bf215546Sopenharmony_ci 434bf215546Sopenharmony_ci if (dst->texture->target == PIPE_BUFFER) { 435bf215546Sopenharmony_ci /* 436bf215546Sopenharmony_ci * The fill naturally works on the surface format, however 437bf215546Sopenharmony_ci * the transfer uses resource format which is just bytes for buffers. 438bf215546Sopenharmony_ci */ 439bf215546Sopenharmony_ci unsigned dx, w; 440bf215546Sopenharmony_ci unsigned pixstride = util_format_get_blocksize(dst->format); 441bf215546Sopenharmony_ci dx = (dst->u.buf.first_element + dstx) * pixstride; 442bf215546Sopenharmony_ci w = width * pixstride; 443bf215546Sopenharmony_ci dst_map = pipe_texture_map(pipe, 444bf215546Sopenharmony_ci dst->texture, 445bf215546Sopenharmony_ci 0, 0, 446bf215546Sopenharmony_ci PIPE_MAP_WRITE, 447bf215546Sopenharmony_ci dx, 0, w, 1, 448bf215546Sopenharmony_ci &dst_trans); 449bf215546Sopenharmony_ci if (dst_map) { 450bf215546Sopenharmony_ci util_clear_color_texture_helper(dst_trans, dst_map, dst->format, 451bf215546Sopenharmony_ci color, width, height, 1); 452bf215546Sopenharmony_ci pipe->texture_unmap(pipe, dst_trans); 453bf215546Sopenharmony_ci } 454bf215546Sopenharmony_ci } 455bf215546Sopenharmony_ci else { 456bf215546Sopenharmony_ci unsigned depth = dst->u.tex.last_layer - dst->u.tex.first_layer + 1; 457bf215546Sopenharmony_ci util_clear_color_texture(pipe, dst->texture, dst->format, color, 458bf215546Sopenharmony_ci dst->u.tex.level, dstx, dsty, 459bf215546Sopenharmony_ci dst->u.tex.first_layer, width, height, depth); 460bf215546Sopenharmony_ci } 461bf215546Sopenharmony_ci} 462bf215546Sopenharmony_ci 463bf215546Sopenharmony_cistatic void 464bf215546Sopenharmony_ciutil_fill_zs_rect(ubyte *dst_map, 465bf215546Sopenharmony_ci enum pipe_format format, 466bf215546Sopenharmony_ci bool need_rmw, 467bf215546Sopenharmony_ci unsigned clear_flags, 468bf215546Sopenharmony_ci unsigned dst_stride, 469bf215546Sopenharmony_ci unsigned width, 470bf215546Sopenharmony_ci unsigned height, 471bf215546Sopenharmony_ci uint64_t zstencil) 472bf215546Sopenharmony_ci{ 473bf215546Sopenharmony_ci unsigned i, j; 474bf215546Sopenharmony_ci switch (util_format_get_blocksize(format)) { 475bf215546Sopenharmony_ci case 1: 476bf215546Sopenharmony_ci assert(format == PIPE_FORMAT_S8_UINT); 477bf215546Sopenharmony_ci if(dst_stride == width) 478bf215546Sopenharmony_ci memset(dst_map, (uint8_t) zstencil, height * width); 479bf215546Sopenharmony_ci else { 480bf215546Sopenharmony_ci for (i = 0; i < height; i++) { 481bf215546Sopenharmony_ci memset(dst_map, (uint8_t) zstencil, width); 482bf215546Sopenharmony_ci dst_map += dst_stride; 483bf215546Sopenharmony_ci } 484bf215546Sopenharmony_ci } 485bf215546Sopenharmony_ci break; 486bf215546Sopenharmony_ci case 2: 487bf215546Sopenharmony_ci assert(format == PIPE_FORMAT_Z16_UNORM); 488bf215546Sopenharmony_ci for (i = 0; i < height; i++) { 489bf215546Sopenharmony_ci uint16_t *row = (uint16_t *)dst_map; 490bf215546Sopenharmony_ci for (j = 0; j < width; j++) 491bf215546Sopenharmony_ci *row++ = (uint16_t) zstencil; 492bf215546Sopenharmony_ci dst_map += dst_stride; 493bf215546Sopenharmony_ci } 494bf215546Sopenharmony_ci break; 495bf215546Sopenharmony_ci case 4: 496bf215546Sopenharmony_ci if (!need_rmw) { 497bf215546Sopenharmony_ci for (i = 0; i < height; i++) { 498bf215546Sopenharmony_ci util_memset32(dst_map, (uint32_t)zstencil, width); 499bf215546Sopenharmony_ci dst_map += dst_stride; 500bf215546Sopenharmony_ci } 501bf215546Sopenharmony_ci } 502bf215546Sopenharmony_ci else { 503bf215546Sopenharmony_ci uint32_t dst_mask; 504bf215546Sopenharmony_ci if (format == PIPE_FORMAT_Z24_UNORM_S8_UINT) 505bf215546Sopenharmony_ci dst_mask = 0x00ffffff; 506bf215546Sopenharmony_ci else { 507bf215546Sopenharmony_ci assert(format == PIPE_FORMAT_S8_UINT_Z24_UNORM); 508bf215546Sopenharmony_ci dst_mask = 0xffffff00; 509bf215546Sopenharmony_ci } 510bf215546Sopenharmony_ci if (clear_flags & PIPE_CLEAR_DEPTH) 511bf215546Sopenharmony_ci dst_mask = ~dst_mask; 512bf215546Sopenharmony_ci for (i = 0; i < height; i++) { 513bf215546Sopenharmony_ci uint32_t *row = (uint32_t *)dst_map; 514bf215546Sopenharmony_ci for (j = 0; j < width; j++) { 515bf215546Sopenharmony_ci uint32_t tmp = *row & dst_mask; 516bf215546Sopenharmony_ci *row++ = tmp | ((uint32_t) zstencil & ~dst_mask); 517bf215546Sopenharmony_ci } 518bf215546Sopenharmony_ci dst_map += dst_stride; 519bf215546Sopenharmony_ci } 520bf215546Sopenharmony_ci } 521bf215546Sopenharmony_ci break; 522bf215546Sopenharmony_ci case 8: 523bf215546Sopenharmony_ci if (!need_rmw) { 524bf215546Sopenharmony_ci for (i = 0; i < height; i++) { 525bf215546Sopenharmony_ci util_memset64(dst_map, zstencil, width); 526bf215546Sopenharmony_ci dst_map += dst_stride; 527bf215546Sopenharmony_ci } 528bf215546Sopenharmony_ci } 529bf215546Sopenharmony_ci else { 530bf215546Sopenharmony_ci uint64_t src_mask; 531bf215546Sopenharmony_ci 532bf215546Sopenharmony_ci if (clear_flags & PIPE_CLEAR_DEPTH) 533bf215546Sopenharmony_ci src_mask = 0x00000000ffffffffull; 534bf215546Sopenharmony_ci else 535bf215546Sopenharmony_ci src_mask = 0x000000ff00000000ull; 536bf215546Sopenharmony_ci 537bf215546Sopenharmony_ci for (i = 0; i < height; i++) { 538bf215546Sopenharmony_ci uint64_t *row = (uint64_t *)dst_map; 539bf215546Sopenharmony_ci for (j = 0; j < width; j++) { 540bf215546Sopenharmony_ci uint64_t tmp = *row & ~src_mask; 541bf215546Sopenharmony_ci *row++ = tmp | (zstencil & src_mask); 542bf215546Sopenharmony_ci } 543bf215546Sopenharmony_ci dst_map += dst_stride; 544bf215546Sopenharmony_ci } 545bf215546Sopenharmony_ci } 546bf215546Sopenharmony_ci break; 547bf215546Sopenharmony_ci default: 548bf215546Sopenharmony_ci assert(0); 549bf215546Sopenharmony_ci break; 550bf215546Sopenharmony_ci } 551bf215546Sopenharmony_ci} 552bf215546Sopenharmony_ci 553bf215546Sopenharmony_civoid 554bf215546Sopenharmony_ciutil_fill_zs_box(ubyte *dst, 555bf215546Sopenharmony_ci enum pipe_format format, 556bf215546Sopenharmony_ci bool need_rmw, 557bf215546Sopenharmony_ci unsigned clear_flags, 558bf215546Sopenharmony_ci unsigned stride, 559bf215546Sopenharmony_ci unsigned layer_stride, 560bf215546Sopenharmony_ci unsigned width, 561bf215546Sopenharmony_ci unsigned height, 562bf215546Sopenharmony_ci unsigned depth, 563bf215546Sopenharmony_ci uint64_t zstencil) 564bf215546Sopenharmony_ci{ 565bf215546Sopenharmony_ci unsigned layer; 566bf215546Sopenharmony_ci 567bf215546Sopenharmony_ci for (layer = 0; layer < depth; layer++) { 568bf215546Sopenharmony_ci util_fill_zs_rect(dst, format, need_rmw, clear_flags, stride, 569bf215546Sopenharmony_ci width, height, zstencil); 570bf215546Sopenharmony_ci dst += layer_stride; 571bf215546Sopenharmony_ci } 572bf215546Sopenharmony_ci} 573bf215546Sopenharmony_ci 574bf215546Sopenharmony_cistatic void 575bf215546Sopenharmony_ciutil_clear_depth_stencil_texture(struct pipe_context *pipe, 576bf215546Sopenharmony_ci struct pipe_resource *texture, 577bf215546Sopenharmony_ci enum pipe_format format, 578bf215546Sopenharmony_ci unsigned clear_flags, 579bf215546Sopenharmony_ci uint64_t zstencil, unsigned level, 580bf215546Sopenharmony_ci unsigned dstx, unsigned dsty, unsigned dstz, 581bf215546Sopenharmony_ci unsigned width, unsigned height, unsigned depth) 582bf215546Sopenharmony_ci{ 583bf215546Sopenharmony_ci struct pipe_transfer *dst_trans; 584bf215546Sopenharmony_ci ubyte *dst_map; 585bf215546Sopenharmony_ci boolean need_rmw = FALSE; 586bf215546Sopenharmony_ci 587bf215546Sopenharmony_ci if ((clear_flags & PIPE_CLEAR_DEPTHSTENCIL) && 588bf215546Sopenharmony_ci ((clear_flags & PIPE_CLEAR_DEPTHSTENCIL) != PIPE_CLEAR_DEPTHSTENCIL) && 589bf215546Sopenharmony_ci util_format_is_depth_and_stencil(format)) 590bf215546Sopenharmony_ci need_rmw = TRUE; 591bf215546Sopenharmony_ci 592bf215546Sopenharmony_ci dst_map = pipe_texture_map_3d(pipe, 593bf215546Sopenharmony_ci texture, 594bf215546Sopenharmony_ci level, 595bf215546Sopenharmony_ci (need_rmw ? PIPE_MAP_READ_WRITE : 596bf215546Sopenharmony_ci PIPE_MAP_WRITE), 597bf215546Sopenharmony_ci dstx, dsty, dstz, 598bf215546Sopenharmony_ci width, height, depth, &dst_trans); 599bf215546Sopenharmony_ci assert(dst_map); 600bf215546Sopenharmony_ci if (!dst_map) 601bf215546Sopenharmony_ci return; 602bf215546Sopenharmony_ci 603bf215546Sopenharmony_ci assert(dst_trans->stride > 0); 604bf215546Sopenharmony_ci 605bf215546Sopenharmony_ci util_fill_zs_box(dst_map, format, need_rmw, clear_flags, 606bf215546Sopenharmony_ci dst_trans->stride, 607bf215546Sopenharmony_ci dst_trans->layer_stride, width, height, 608bf215546Sopenharmony_ci depth, zstencil); 609bf215546Sopenharmony_ci 610bf215546Sopenharmony_ci pipe->texture_unmap(pipe, dst_trans); 611bf215546Sopenharmony_ci} 612bf215546Sopenharmony_ci 613bf215546Sopenharmony_ci 614bf215546Sopenharmony_civoid 615bf215546Sopenharmony_ciutil_clear_texture(struct pipe_context *pipe, 616bf215546Sopenharmony_ci struct pipe_resource *tex, 617bf215546Sopenharmony_ci unsigned level, 618bf215546Sopenharmony_ci const struct pipe_box *box, 619bf215546Sopenharmony_ci const void *data) 620bf215546Sopenharmony_ci{ 621bf215546Sopenharmony_ci const struct util_format_description *desc = 622bf215546Sopenharmony_ci util_format_description(tex->format); 623bf215546Sopenharmony_ci 624bf215546Sopenharmony_ci if (level > tex->last_level) 625bf215546Sopenharmony_ci return; 626bf215546Sopenharmony_ci 627bf215546Sopenharmony_ci if (util_format_is_depth_or_stencil(tex->format)) { 628bf215546Sopenharmony_ci unsigned clear = 0; 629bf215546Sopenharmony_ci float depth = 0.0f; 630bf215546Sopenharmony_ci uint8_t stencil = 0; 631bf215546Sopenharmony_ci uint64_t zstencil; 632bf215546Sopenharmony_ci 633bf215546Sopenharmony_ci if (util_format_has_depth(desc)) { 634bf215546Sopenharmony_ci clear |= PIPE_CLEAR_DEPTH; 635bf215546Sopenharmony_ci util_format_unpack_z_float(tex->format, &depth, data, 1); 636bf215546Sopenharmony_ci } 637bf215546Sopenharmony_ci 638bf215546Sopenharmony_ci if (util_format_has_stencil(desc)) { 639bf215546Sopenharmony_ci clear |= PIPE_CLEAR_STENCIL; 640bf215546Sopenharmony_ci util_format_unpack_s_8uint(tex->format, &stencil, data, 1); 641bf215546Sopenharmony_ci } 642bf215546Sopenharmony_ci 643bf215546Sopenharmony_ci zstencil = util_pack64_z_stencil(tex->format, depth, stencil); 644bf215546Sopenharmony_ci 645bf215546Sopenharmony_ci util_clear_depth_stencil_texture(pipe, tex, tex->format, clear, zstencil, 646bf215546Sopenharmony_ci level, box->x, box->y, box->z, 647bf215546Sopenharmony_ci box->width, box->height, box->depth); 648bf215546Sopenharmony_ci } else { 649bf215546Sopenharmony_ci union pipe_color_union color; 650bf215546Sopenharmony_ci util_format_unpack_rgba(tex->format, color.ui, data, 1); 651bf215546Sopenharmony_ci 652bf215546Sopenharmony_ci util_clear_color_texture(pipe, tex, tex->format, &color, level, 653bf215546Sopenharmony_ci box->x, box->y, box->z, 654bf215546Sopenharmony_ci box->width, box->height, box->depth); 655bf215546Sopenharmony_ci } 656bf215546Sopenharmony_ci} 657bf215546Sopenharmony_ci 658bf215546Sopenharmony_ci 659bf215546Sopenharmony_ci/** 660bf215546Sopenharmony_ci * Fallback for pipe->clear_stencil() function. 661bf215546Sopenharmony_ci * sw fallback doesn't look terribly useful here. 662bf215546Sopenharmony_ci * Plus can't use these transfer fallbacks when clearing 663bf215546Sopenharmony_ci * multisampled surfaces for instance. 664bf215546Sopenharmony_ci * Clears all bound layers. 665bf215546Sopenharmony_ci */ 666bf215546Sopenharmony_civoid 667bf215546Sopenharmony_ciutil_clear_depth_stencil(struct pipe_context *pipe, 668bf215546Sopenharmony_ci struct pipe_surface *dst, 669bf215546Sopenharmony_ci unsigned clear_flags, 670bf215546Sopenharmony_ci double depth, 671bf215546Sopenharmony_ci unsigned stencil, 672bf215546Sopenharmony_ci unsigned dstx, unsigned dsty, 673bf215546Sopenharmony_ci unsigned width, unsigned height) 674bf215546Sopenharmony_ci{ 675bf215546Sopenharmony_ci uint64_t zstencil; 676bf215546Sopenharmony_ci unsigned max_layer; 677bf215546Sopenharmony_ci 678bf215546Sopenharmony_ci assert(dst->texture); 679bf215546Sopenharmony_ci if (!dst->texture) 680bf215546Sopenharmony_ci return; 681bf215546Sopenharmony_ci 682bf215546Sopenharmony_ci zstencil = util_pack64_z_stencil(dst->format, depth, stencil); 683bf215546Sopenharmony_ci max_layer = dst->u.tex.last_layer - dst->u.tex.first_layer; 684bf215546Sopenharmony_ci util_clear_depth_stencil_texture(pipe, dst->texture, dst->format, 685bf215546Sopenharmony_ci clear_flags, zstencil, dst->u.tex.level, 686bf215546Sopenharmony_ci dstx, dsty, dst->u.tex.first_layer, 687bf215546Sopenharmony_ci width, height, max_layer + 1); 688bf215546Sopenharmony_ci} 689bf215546Sopenharmony_ci 690bf215546Sopenharmony_ci 691bf215546Sopenharmony_ci/* Return if the box is totally inside the resource. 692bf215546Sopenharmony_ci */ 693bf215546Sopenharmony_cistatic boolean 694bf215546Sopenharmony_ciis_box_inside_resource(const struct pipe_resource *res, 695bf215546Sopenharmony_ci const struct pipe_box *box, 696bf215546Sopenharmony_ci unsigned level) 697bf215546Sopenharmony_ci{ 698bf215546Sopenharmony_ci unsigned width = 1, height = 1, depth = 1; 699bf215546Sopenharmony_ci 700bf215546Sopenharmony_ci switch (res->target) { 701bf215546Sopenharmony_ci case PIPE_BUFFER: 702bf215546Sopenharmony_ci width = res->width0; 703bf215546Sopenharmony_ci height = 1; 704bf215546Sopenharmony_ci depth = 1; 705bf215546Sopenharmony_ci break; 706bf215546Sopenharmony_ci case PIPE_TEXTURE_1D: 707bf215546Sopenharmony_ci width = u_minify(res->width0, level); 708bf215546Sopenharmony_ci height = 1; 709bf215546Sopenharmony_ci depth = 1; 710bf215546Sopenharmony_ci break; 711bf215546Sopenharmony_ci case PIPE_TEXTURE_2D: 712bf215546Sopenharmony_ci case PIPE_TEXTURE_RECT: 713bf215546Sopenharmony_ci width = u_minify(res->width0, level); 714bf215546Sopenharmony_ci height = u_minify(res->height0, level); 715bf215546Sopenharmony_ci depth = 1; 716bf215546Sopenharmony_ci break; 717bf215546Sopenharmony_ci case PIPE_TEXTURE_3D: 718bf215546Sopenharmony_ci width = u_minify(res->width0, level); 719bf215546Sopenharmony_ci height = u_minify(res->height0, level); 720bf215546Sopenharmony_ci depth = u_minify(res->depth0, level); 721bf215546Sopenharmony_ci break; 722bf215546Sopenharmony_ci case PIPE_TEXTURE_CUBE: 723bf215546Sopenharmony_ci width = u_minify(res->width0, level); 724bf215546Sopenharmony_ci height = u_minify(res->height0, level); 725bf215546Sopenharmony_ci depth = 6; 726bf215546Sopenharmony_ci break; 727bf215546Sopenharmony_ci case PIPE_TEXTURE_1D_ARRAY: 728bf215546Sopenharmony_ci width = u_minify(res->width0, level); 729bf215546Sopenharmony_ci height = 1; 730bf215546Sopenharmony_ci depth = res->array_size; 731bf215546Sopenharmony_ci break; 732bf215546Sopenharmony_ci case PIPE_TEXTURE_2D_ARRAY: 733bf215546Sopenharmony_ci width = u_minify(res->width0, level); 734bf215546Sopenharmony_ci height = u_minify(res->height0, level); 735bf215546Sopenharmony_ci depth = res->array_size; 736bf215546Sopenharmony_ci break; 737bf215546Sopenharmony_ci case PIPE_TEXTURE_CUBE_ARRAY: 738bf215546Sopenharmony_ci width = u_minify(res->width0, level); 739bf215546Sopenharmony_ci height = u_minify(res->height0, level); 740bf215546Sopenharmony_ci depth = res->array_size; 741bf215546Sopenharmony_ci assert(res->array_size % 6 == 0); 742bf215546Sopenharmony_ci break; 743bf215546Sopenharmony_ci case PIPE_MAX_TEXTURE_TYPES: 744bf215546Sopenharmony_ci break; 745bf215546Sopenharmony_ci } 746bf215546Sopenharmony_ci 747bf215546Sopenharmony_ci return box->x >= 0 && 748bf215546Sopenharmony_ci box->x + box->width <= (int) width && 749bf215546Sopenharmony_ci box->y >= 0 && 750bf215546Sopenharmony_ci box->y + box->height <= (int) height && 751bf215546Sopenharmony_ci box->z >= 0 && 752bf215546Sopenharmony_ci box->z + box->depth <= (int) depth; 753bf215546Sopenharmony_ci} 754bf215546Sopenharmony_ci 755bf215546Sopenharmony_cistatic unsigned 756bf215546Sopenharmony_ciget_sample_count(const struct pipe_resource *res) 757bf215546Sopenharmony_ci{ 758bf215546Sopenharmony_ci return res->nr_samples ? res->nr_samples : 1; 759bf215546Sopenharmony_ci} 760bf215546Sopenharmony_ci 761bf215546Sopenharmony_ci 762bf215546Sopenharmony_ci/** 763bf215546Sopenharmony_ci * Check if a blit() command can be implemented with a resource_copy_region(). 764bf215546Sopenharmony_ci * If tight_format_check is true, only allow the resource_copy_region() if 765bf215546Sopenharmony_ci * the blit src/dst formats are identical, ignoring the resource formats. 766bf215546Sopenharmony_ci * Otherwise, check for format casting and compatibility. 767bf215546Sopenharmony_ci */ 768bf215546Sopenharmony_cibool 769bf215546Sopenharmony_ciutil_can_blit_via_copy_region(const struct pipe_blit_info *blit, 770bf215546Sopenharmony_ci bool tight_format_check, 771bf215546Sopenharmony_ci bool render_condition_bound) 772bf215546Sopenharmony_ci{ 773bf215546Sopenharmony_ci const struct util_format_description *src_desc, *dst_desc; 774bf215546Sopenharmony_ci 775bf215546Sopenharmony_ci src_desc = util_format_description(blit->src.resource->format); 776bf215546Sopenharmony_ci dst_desc = util_format_description(blit->dst.resource->format); 777bf215546Sopenharmony_ci 778bf215546Sopenharmony_ci if (tight_format_check) { 779bf215546Sopenharmony_ci /* no format conversions allowed */ 780bf215546Sopenharmony_ci if (blit->src.format != blit->dst.format) { 781bf215546Sopenharmony_ci return FALSE; 782bf215546Sopenharmony_ci } 783bf215546Sopenharmony_ci } 784bf215546Sopenharmony_ci else { 785bf215546Sopenharmony_ci /* do loose format compatibility checking */ 786bf215546Sopenharmony_ci if (blit->src.resource->format != blit->src.format || 787bf215546Sopenharmony_ci blit->dst.resource->format != blit->dst.format || 788bf215546Sopenharmony_ci !util_is_format_compatible(src_desc, dst_desc)) { 789bf215546Sopenharmony_ci return FALSE; 790bf215546Sopenharmony_ci } 791bf215546Sopenharmony_ci } 792bf215546Sopenharmony_ci 793bf215546Sopenharmony_ci unsigned mask = util_format_get_mask(blit->dst.format); 794bf215546Sopenharmony_ci 795bf215546Sopenharmony_ci /* No masks, no filtering, no scissor, no blending */ 796bf215546Sopenharmony_ci if ((blit->mask & mask) != mask || 797bf215546Sopenharmony_ci blit->filter != PIPE_TEX_FILTER_NEAREST || 798bf215546Sopenharmony_ci blit->scissor_enable || 799bf215546Sopenharmony_ci blit->num_window_rectangles > 0 || 800bf215546Sopenharmony_ci blit->alpha_blend || 801bf215546Sopenharmony_ci (blit->render_condition_enable && render_condition_bound)) { 802bf215546Sopenharmony_ci return FALSE; 803bf215546Sopenharmony_ci } 804bf215546Sopenharmony_ci 805bf215546Sopenharmony_ci /* Only the src box can have negative dims for flipping */ 806bf215546Sopenharmony_ci assert(blit->dst.box.width >= 1); 807bf215546Sopenharmony_ci assert(blit->dst.box.height >= 1); 808bf215546Sopenharmony_ci assert(blit->dst.box.depth >= 1); 809bf215546Sopenharmony_ci 810bf215546Sopenharmony_ci /* No scaling or flipping */ 811bf215546Sopenharmony_ci if (blit->src.box.width != blit->dst.box.width || 812bf215546Sopenharmony_ci blit->src.box.height != blit->dst.box.height || 813bf215546Sopenharmony_ci blit->src.box.depth != blit->dst.box.depth) { 814bf215546Sopenharmony_ci return FALSE; 815bf215546Sopenharmony_ci } 816bf215546Sopenharmony_ci 817bf215546Sopenharmony_ci /* No out-of-bounds access. */ 818bf215546Sopenharmony_ci if (!is_box_inside_resource(blit->src.resource, &blit->src.box, 819bf215546Sopenharmony_ci blit->src.level) || 820bf215546Sopenharmony_ci !is_box_inside_resource(blit->dst.resource, &blit->dst.box, 821bf215546Sopenharmony_ci blit->dst.level)) { 822bf215546Sopenharmony_ci return FALSE; 823bf215546Sopenharmony_ci } 824bf215546Sopenharmony_ci 825bf215546Sopenharmony_ci /* Sample counts must match. */ 826bf215546Sopenharmony_ci if (get_sample_count(blit->src.resource) != 827bf215546Sopenharmony_ci get_sample_count(blit->dst.resource)) { 828bf215546Sopenharmony_ci return FALSE; 829bf215546Sopenharmony_ci } 830bf215546Sopenharmony_ci 831bf215546Sopenharmony_ci return TRUE; 832bf215546Sopenharmony_ci} 833bf215546Sopenharmony_ci 834bf215546Sopenharmony_ci 835bf215546Sopenharmony_ci/** 836bf215546Sopenharmony_ci * Try to do a blit using resource_copy_region. The function calls 837bf215546Sopenharmony_ci * resource_copy_region if the blit description is compatible with it. 838bf215546Sopenharmony_ci * 839bf215546Sopenharmony_ci * It returns TRUE if the blit was done using resource_copy_region. 840bf215546Sopenharmony_ci * 841bf215546Sopenharmony_ci * It returns FALSE otherwise and the caller must fall back to a more generic 842bf215546Sopenharmony_ci * codepath for the blit operation. (e.g. by using u_blitter) 843bf215546Sopenharmony_ci */ 844bf215546Sopenharmony_cibool 845bf215546Sopenharmony_ciutil_try_blit_via_copy_region(struct pipe_context *ctx, 846bf215546Sopenharmony_ci const struct pipe_blit_info *blit, 847bf215546Sopenharmony_ci bool render_condition_bound) 848bf215546Sopenharmony_ci{ 849bf215546Sopenharmony_ci if (util_can_blit_via_copy_region(blit, FALSE, render_condition_bound)) { 850bf215546Sopenharmony_ci ctx->resource_copy_region(ctx, blit->dst.resource, blit->dst.level, 851bf215546Sopenharmony_ci blit->dst.box.x, blit->dst.box.y, 852bf215546Sopenharmony_ci blit->dst.box.z, 853bf215546Sopenharmony_ci blit->src.resource, blit->src.level, 854bf215546Sopenharmony_ci &blit->src.box); 855bf215546Sopenharmony_ci return TRUE; 856bf215546Sopenharmony_ci } 857bf215546Sopenharmony_ci else { 858bf215546Sopenharmony_ci return FALSE; 859bf215546Sopenharmony_ci } 860bf215546Sopenharmony_ci} 861