1/************************************************************************** 2 * 3 * Copyright 2011 Christian König 4 * All Rights Reserved. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the 8 * "Software"), to deal in the Software without restriction, including 9 * without limitation the rights to use, copy, modify, merge, publish, 10 * distribute, sub license, and/or sell copies of the Software, and to 11 * permit persons to whom the Software is furnished to do so, subject to 12 * the following conditions: 13 * 14 * The above copyright notice and this permission notice (including the 15 * next paragraph) shall be included in all copies or substantial portions 16 * of the Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR 22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 * 26 **************************************************************************/ 27 28#include <assert.h> 29 30#include "pipe/p_screen.h" 31#include "pipe/p_context.h" 32 33#include "util/u_draw.h" 34#include "util/u_sampler.h" 35#include "util/u_inlines.h" 36#include "util/u_memory.h" 37 38#include "tgsi/tgsi_ureg.h" 39 40#include "vl_defines.h" 41#include "vl_types.h" 42 43#include "vl_zscan.h" 44#include "vl_vertex_buffers.h" 45 46enum VS_OUTPUT 47{ 48 VS_O_VPOS = 0, 49 VS_O_VTEX = 0 50}; 51 52const int vl_zscan_normal_16[] = 53{ 54 /* Zig-Zag scan pattern */ 55 0, 1, 4, 8, 5, 2, 3, 6, 56 9,12,13,10, 7,11,14,15 57}; 58 59const int vl_zscan_linear[] = 60{ 61 /* Linear scan pattern */ 62 0, 1, 2, 3, 4, 5, 6, 7, 63 8, 9,10,11,12,13,14,15, 64 16,17,18,19,20,21,22,23, 65 24,25,26,27,28,29,30,31, 66 32,33,34,35,36,37,38,39, 67 40,41,42,43,44,45,46,47, 68 48,49,50,51,52,53,54,55, 69 56,57,58,59,60,61,62,63 70}; 71 72const int vl_zscan_normal[] = 73{ 74 /* Zig-Zag scan pattern */ 75 0, 1, 8,16, 9, 2, 3,10, 76 17,24,32,25,18,11, 4, 5, 77 12,19,26,33,40,48,41,34, 78 27,20,13, 6, 7,14,21,28, 79 35,42,49,56,57,50,43,36, 80 29,22,15,23,30,37,44,51, 81 58,59,52,45,38,31,39,46, 82 53,60,61,54,47,55,62,63 83}; 84 85const int vl_zscan_alternate[] = 86{ 87 /* Alternate scan pattern */ 88 0, 8,16,24, 1, 9, 2,10, 89 17,25,32,40,48,56,57,49, 90 41,33,26,18, 3,11, 4,12, 91 19,27,34,42,50,58,35,43, 92 51,59,20,28, 5,13, 6,14, 93 21,29,36,44,52,60,37,45, 94 53,61,22,30, 7,15,23,31, 95 38,46,54,62,39,47,55,63 96}; 97 98const int vl_zscan_h265_up_right_diagonal_16[] = 99{ 100 /* Up-right diagonal scan order for 4x4 blocks - see H.265 section 6.5.3. */ 101 0, 4, 1, 8, 5, 2, 12, 9, 102 6, 3, 13, 10, 7, 14, 11, 15, 103}; 104 105const int vl_zscan_h265_up_right_diagonal[] = 106{ 107 /* Up-right diagonal scan order for 8x8 blocks - see H.265 section 6.5.3. */ 108 0, 8, 1, 16, 9, 2, 24, 17, 109 10, 3, 32, 25, 18, 11, 4, 40, 110 33, 26, 19, 12, 5, 48, 41, 34, 111 27, 20, 13, 6, 56, 49, 42, 35, 112 28, 21, 14, 7, 57, 50, 43, 36, 113 29, 22, 15, 58, 51, 44, 37, 30, 114 23, 59, 52, 45, 38, 31, 60, 53, 115 46, 39, 61, 54, 47, 62, 55, 63, 116}; 117 118 119static void * 120create_vert_shader(struct vl_zscan *zscan) 121{ 122 struct ureg_program *shader; 123 struct ureg_src scale; 124 struct ureg_src vrect, vpos, block_num; 125 struct ureg_dst tmp; 126 struct ureg_dst o_vpos; 127 struct ureg_dst *o_vtex; 128 unsigned i; 129 130 shader = ureg_create(PIPE_SHADER_VERTEX); 131 if (!shader) 132 return NULL; 133 134 o_vtex = MALLOC(zscan->num_channels * sizeof(struct ureg_dst)); 135 136 scale = ureg_imm2f(shader, 137 (float)VL_BLOCK_WIDTH / zscan->buffer_width, 138 (float)VL_BLOCK_HEIGHT / zscan->buffer_height); 139 140 vrect = ureg_DECL_vs_input(shader, VS_I_RECT); 141 vpos = ureg_DECL_vs_input(shader, VS_I_VPOS); 142 block_num = ureg_DECL_vs_input(shader, VS_I_BLOCK_NUM); 143 144 tmp = ureg_DECL_temporary(shader); 145 146 o_vpos = ureg_DECL_output(shader, TGSI_SEMANTIC_POSITION, VS_O_VPOS); 147 148 for (i = 0; i < zscan->num_channels; ++i) 149 o_vtex[i] = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, VS_O_VTEX + i); 150 151 /* 152 * o_vpos.xy = (vpos + vrect) * scale 153 * o_vpos.zw = 1.0f 154 * 155 * tmp.xy = InstanceID / blocks_per_line 156 * tmp.x = frac(tmp.x) 157 * tmp.y = floor(tmp.y) 158 * 159 * o_vtex.x = vrect.x / blocks_per_line + tmp.x 160 * o_vtex.y = vrect.y 161 * o_vtex.z = tmp.z * blocks_per_line / blocks_total 162 */ 163 ureg_ADD(shader, ureg_writemask(tmp, TGSI_WRITEMASK_XY), vpos, vrect); 164 ureg_MUL(shader, ureg_writemask(o_vpos, TGSI_WRITEMASK_XY), ureg_src(tmp), scale); 165 ureg_MOV(shader, ureg_writemask(o_vpos, TGSI_WRITEMASK_ZW), ureg_imm1f(shader, 1.0f)); 166 167 ureg_MUL(shader, ureg_writemask(tmp, TGSI_WRITEMASK_XW), ureg_scalar(block_num, TGSI_SWIZZLE_X), 168 ureg_imm1f(shader, 1.0f / zscan->blocks_per_line)); 169 170 ureg_FRC(shader, ureg_writemask(tmp, TGSI_WRITEMASK_Y), ureg_scalar(ureg_src(tmp), TGSI_SWIZZLE_X)); 171 ureg_FLR(shader, ureg_writemask(tmp, TGSI_WRITEMASK_W), ureg_src(tmp)); 172 173 for (i = 0; i < zscan->num_channels; ++i) { 174 ureg_ADD(shader, ureg_writemask(tmp, TGSI_WRITEMASK_X), ureg_scalar(ureg_src(tmp), TGSI_SWIZZLE_Y), 175 ureg_imm1f(shader, 1.0f / (zscan->blocks_per_line * VL_BLOCK_WIDTH) 176 * ((signed)i - (signed)zscan->num_channels / 2))); 177 178 ureg_MAD(shader, ureg_writemask(o_vtex[i], TGSI_WRITEMASK_X), vrect, 179 ureg_imm1f(shader, 1.0f / zscan->blocks_per_line), ureg_src(tmp)); 180 ureg_MOV(shader, ureg_writemask(o_vtex[i], TGSI_WRITEMASK_Y), vrect); 181 ureg_MOV(shader, ureg_writemask(o_vtex[i], TGSI_WRITEMASK_Z), vpos); 182 ureg_MUL(shader, ureg_writemask(o_vtex[i], TGSI_WRITEMASK_W), ureg_src(tmp), 183 ureg_imm1f(shader, (float)zscan->blocks_per_line / zscan->blocks_total)); 184 } 185 186 ureg_release_temporary(shader, tmp); 187 ureg_END(shader); 188 189 FREE(o_vtex); 190 191 return ureg_create_shader_and_destroy(shader, zscan->pipe); 192} 193 194static void * 195create_frag_shader(struct vl_zscan *zscan) 196{ 197 struct ureg_program *shader; 198 struct ureg_src *vtex; 199 200 struct ureg_src samp_src, samp_scan, samp_quant; 201 202 struct ureg_dst *tmp; 203 struct ureg_dst quant, fragment; 204 205 unsigned i; 206 207 shader = ureg_create(PIPE_SHADER_FRAGMENT); 208 if (!shader) 209 return NULL; 210 211 vtex = MALLOC(zscan->num_channels * sizeof(struct ureg_src)); 212 tmp = MALLOC(zscan->num_channels * sizeof(struct ureg_dst)); 213 214 for (i = 0; i < zscan->num_channels; ++i) 215 vtex[i] = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_VTEX + i, TGSI_INTERPOLATE_LINEAR); 216 217 samp_src = ureg_DECL_sampler(shader, 0); 218 samp_scan = ureg_DECL_sampler(shader, 1); 219 samp_quant = ureg_DECL_sampler(shader, 2); 220 221 for (i = 0; i < zscan->num_channels; ++i) 222 tmp[i] = ureg_DECL_temporary(shader); 223 quant = ureg_DECL_temporary(shader); 224 225 fragment = ureg_DECL_output(shader, TGSI_SEMANTIC_COLOR, 0); 226 227 /* 228 * tmp.x = tex(vtex, 1) 229 * tmp.y = vtex.z 230 * fragment = tex(tmp, 0) * quant 231 */ 232 for (i = 0; i < zscan->num_channels; ++i) 233 ureg_TEX(shader, ureg_writemask(tmp[i], TGSI_WRITEMASK_X), TGSI_TEXTURE_2D, vtex[i], samp_scan); 234 235 for (i = 0; i < zscan->num_channels; ++i) 236 ureg_MOV(shader, ureg_writemask(tmp[i], TGSI_WRITEMASK_Y), ureg_scalar(vtex[i], TGSI_SWIZZLE_W)); 237 238 for (i = 0; i < zscan->num_channels; ++i) { 239 ureg_TEX(shader, ureg_writemask(tmp[0], TGSI_WRITEMASK_X << i), TGSI_TEXTURE_2D, ureg_src(tmp[i]), samp_src); 240 ureg_TEX(shader, ureg_writemask(quant, TGSI_WRITEMASK_X << i), TGSI_TEXTURE_3D, vtex[i], samp_quant); 241 } 242 243 ureg_MUL(shader, quant, ureg_src(quant), ureg_imm1f(shader, 16.0f)); 244 ureg_MUL(shader, fragment, ureg_src(tmp[0]), ureg_src(quant)); 245 246 for (i = 0; i < zscan->num_channels; ++i) 247 ureg_release_temporary(shader, tmp[i]); 248 ureg_END(shader); 249 250 FREE(vtex); 251 FREE(tmp); 252 253 return ureg_create_shader_and_destroy(shader, zscan->pipe); 254} 255 256static bool 257init_shaders(struct vl_zscan *zscan) 258{ 259 assert(zscan); 260 261 zscan->vs = create_vert_shader(zscan); 262 if (!zscan->vs) 263 goto error_vs; 264 265 zscan->fs = create_frag_shader(zscan); 266 if (!zscan->fs) 267 goto error_fs; 268 269 return true; 270 271error_fs: 272 zscan->pipe->delete_vs_state(zscan->pipe, zscan->vs); 273 274error_vs: 275 return false; 276} 277 278static void 279cleanup_shaders(struct vl_zscan *zscan) 280{ 281 assert(zscan); 282 283 zscan->pipe->delete_vs_state(zscan->pipe, zscan->vs); 284 zscan->pipe->delete_fs_state(zscan->pipe, zscan->fs); 285} 286 287static bool 288init_state(struct vl_zscan *zscan) 289{ 290 struct pipe_blend_state blend; 291 struct pipe_rasterizer_state rs_state; 292 struct pipe_sampler_state sampler; 293 unsigned i; 294 295 assert(zscan); 296 297 memset(&rs_state, 0, sizeof(rs_state)); 298 rs_state.half_pixel_center = true; 299 rs_state.bottom_edge_rule = true; 300 rs_state.depth_clip_near = 1; 301 rs_state.depth_clip_far = 1; 302 303 zscan->rs_state = zscan->pipe->create_rasterizer_state(zscan->pipe, &rs_state); 304 if (!zscan->rs_state) 305 goto error_rs_state; 306 307 memset(&blend, 0, sizeof blend); 308 309 blend.independent_blend_enable = 0; 310 blend.rt[0].blend_enable = 0; 311 blend.rt[0].rgb_func = PIPE_BLEND_ADD; 312 blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE; 313 blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ONE; 314 blend.rt[0].alpha_func = PIPE_BLEND_ADD; 315 blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE; 316 blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ONE; 317 blend.logicop_enable = 0; 318 blend.logicop_func = PIPE_LOGICOP_CLEAR; 319 /* Needed to allow color writes to FB, even if blending disabled */ 320 blend.rt[0].colormask = PIPE_MASK_RGBA; 321 blend.dither = 0; 322 zscan->blend = zscan->pipe->create_blend_state(zscan->pipe, &blend); 323 if (!zscan->blend) 324 goto error_blend; 325 326 for (i = 0; i < 3; ++i) { 327 memset(&sampler, 0, sizeof(sampler)); 328 sampler.wrap_s = PIPE_TEX_WRAP_REPEAT; 329 sampler.wrap_t = PIPE_TEX_WRAP_REPEAT; 330 sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE; 331 sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST; 332 sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE; 333 sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST; 334 sampler.compare_mode = PIPE_TEX_COMPARE_NONE; 335 sampler.compare_func = PIPE_FUNC_ALWAYS; 336 sampler.normalized_coords = 1; 337 zscan->samplers[i] = zscan->pipe->create_sampler_state(zscan->pipe, &sampler); 338 if (!zscan->samplers[i]) 339 goto error_samplers; 340 } 341 342 return true; 343 344error_samplers: 345 for (i = 0; i < 2; ++i) 346 if (zscan->samplers[i]) 347 zscan->pipe->delete_sampler_state(zscan->pipe, zscan->samplers[i]); 348 349 zscan->pipe->delete_rasterizer_state(zscan->pipe, zscan->rs_state); 350 351error_blend: 352 zscan->pipe->delete_blend_state(zscan->pipe, zscan->blend); 353 354error_rs_state: 355 return false; 356} 357 358static void 359cleanup_state(struct vl_zscan *zscan) 360{ 361 unsigned i; 362 363 assert(zscan); 364 365 for (i = 0; i < 3; ++i) 366 zscan->pipe->delete_sampler_state(zscan->pipe, zscan->samplers[i]); 367 368 zscan->pipe->delete_rasterizer_state(zscan->pipe, zscan->rs_state); 369 zscan->pipe->delete_blend_state(zscan->pipe, zscan->blend); 370} 371 372struct pipe_sampler_view * 373vl_zscan_layout(struct pipe_context *pipe, const int layout[64], unsigned blocks_per_line) 374{ 375 const unsigned total_size = blocks_per_line * VL_BLOCK_WIDTH * VL_BLOCK_HEIGHT; 376 377 int patched_layout[64]; 378 379 struct pipe_resource res_tmpl, *res; 380 struct pipe_sampler_view sv_tmpl, *sv; 381 struct pipe_transfer *buf_transfer; 382 unsigned x, y, i, pitch; 383 float *f; 384 385 struct pipe_box rect = 386 { 387 0, 0, 0, 388 VL_BLOCK_WIDTH * blocks_per_line, 389 VL_BLOCK_HEIGHT, 390 1 391 }; 392 393 assert(pipe && layout && blocks_per_line); 394 395 for (i = 0; i < 64; ++i) 396 patched_layout[layout[i]] = i; 397 398 memset(&res_tmpl, 0, sizeof(res_tmpl)); 399 res_tmpl.target = PIPE_TEXTURE_2D; 400 res_tmpl.format = PIPE_FORMAT_R32_FLOAT; 401 res_tmpl.width0 = VL_BLOCK_WIDTH * blocks_per_line; 402 res_tmpl.height0 = VL_BLOCK_HEIGHT; 403 res_tmpl.depth0 = 1; 404 res_tmpl.array_size = 1; 405 res_tmpl.usage = PIPE_USAGE_IMMUTABLE; 406 res_tmpl.bind = PIPE_BIND_SAMPLER_VIEW; 407 408 res = pipe->screen->resource_create(pipe->screen, &res_tmpl); 409 if (!res) 410 goto error_resource; 411 412 f = pipe->texture_map(pipe, res, 413 0, PIPE_MAP_WRITE | PIPE_MAP_DISCARD_RANGE, 414 &rect, &buf_transfer); 415 if (!f) 416 goto error_map; 417 418 pitch = buf_transfer->stride / sizeof(float); 419 420 for (i = 0; i < blocks_per_line; ++i) 421 for (y = 0; y < VL_BLOCK_HEIGHT; ++y) 422 for (x = 0; x < VL_BLOCK_WIDTH; ++x) { 423 float addr = patched_layout[x + y * VL_BLOCK_WIDTH] + 424 i * VL_BLOCK_WIDTH * VL_BLOCK_HEIGHT; 425 426 addr /= total_size; 427 428 f[i * VL_BLOCK_WIDTH + y * pitch + x] = addr; 429 } 430 431 pipe->texture_unmap(pipe, buf_transfer); 432 433 memset(&sv_tmpl, 0, sizeof(sv_tmpl)); 434 u_sampler_view_default_template(&sv_tmpl, res, res->format); 435 sv = pipe->create_sampler_view(pipe, res, &sv_tmpl); 436 pipe_resource_reference(&res, NULL); 437 if (!sv) 438 goto error_map; 439 440 return sv; 441 442error_map: 443 pipe_resource_reference(&res, NULL); 444 445error_resource: 446 return NULL; 447} 448 449bool 450vl_zscan_init(struct vl_zscan *zscan, struct pipe_context *pipe, 451 unsigned buffer_width, unsigned buffer_height, 452 unsigned blocks_per_line, unsigned blocks_total, 453 unsigned num_channels) 454{ 455 assert(zscan && pipe); 456 457 zscan->pipe = pipe; 458 zscan->buffer_width = buffer_width; 459 zscan->buffer_height = buffer_height; 460 zscan->num_channels = num_channels; 461 zscan->blocks_per_line = blocks_per_line; 462 zscan->blocks_total = blocks_total; 463 464 if(!init_shaders(zscan)) 465 return false; 466 467 if(!init_state(zscan)) { 468 cleanup_shaders(zscan); 469 return false; 470 } 471 472 return true; 473} 474 475void 476vl_zscan_cleanup(struct vl_zscan *zscan) 477{ 478 assert(zscan); 479 480 cleanup_shaders(zscan); 481 cleanup_state(zscan); 482} 483 484bool 485vl_zscan_init_buffer(struct vl_zscan *zscan, struct vl_zscan_buffer *buffer, 486 struct pipe_sampler_view *src, struct pipe_surface *dst) 487{ 488 struct pipe_resource res_tmpl, *res; 489 struct pipe_sampler_view sv_tmpl; 490 491 assert(zscan && buffer); 492 493 memset(buffer, 0, sizeof(struct vl_zscan_buffer)); 494 495 pipe_sampler_view_reference(&buffer->src, src); 496 497 buffer->viewport.scale[0] = dst->width; 498 buffer->viewport.scale[1] = dst->height; 499 buffer->viewport.scale[2] = 1; 500 buffer->viewport.translate[0] = 0; 501 buffer->viewport.translate[1] = 0; 502 buffer->viewport.translate[2] = 0; 503 buffer->viewport.swizzle_x = PIPE_VIEWPORT_SWIZZLE_POSITIVE_X; 504 buffer->viewport.swizzle_y = PIPE_VIEWPORT_SWIZZLE_POSITIVE_Y; 505 buffer->viewport.swizzle_z = PIPE_VIEWPORT_SWIZZLE_POSITIVE_Z; 506 buffer->viewport.swizzle_w = PIPE_VIEWPORT_SWIZZLE_POSITIVE_W; 507 508 buffer->fb_state.width = dst->width; 509 buffer->fb_state.height = dst->height; 510 buffer->fb_state.nr_cbufs = 1; 511 pipe_surface_reference(&buffer->fb_state.cbufs[0], dst); 512 513 memset(&res_tmpl, 0, sizeof(res_tmpl)); 514 res_tmpl.target = PIPE_TEXTURE_3D; 515 res_tmpl.format = PIPE_FORMAT_R8_UNORM; 516 res_tmpl.width0 = VL_BLOCK_WIDTH * zscan->blocks_per_line; 517 res_tmpl.height0 = VL_BLOCK_HEIGHT; 518 res_tmpl.depth0 = 2; 519 res_tmpl.array_size = 1; 520 res_tmpl.usage = PIPE_USAGE_IMMUTABLE; 521 res_tmpl.bind = PIPE_BIND_SAMPLER_VIEW; 522 523 res = zscan->pipe->screen->resource_create(zscan->pipe->screen, &res_tmpl); 524 if (!res) 525 return false; 526 527 memset(&sv_tmpl, 0, sizeof(sv_tmpl)); 528 u_sampler_view_default_template(&sv_tmpl, res, res->format); 529 sv_tmpl.swizzle_r = sv_tmpl.swizzle_g = sv_tmpl.swizzle_b = sv_tmpl.swizzle_a = TGSI_SWIZZLE_X; 530 buffer->quant = zscan->pipe->create_sampler_view(zscan->pipe, res, &sv_tmpl); 531 pipe_resource_reference(&res, NULL); 532 if (!buffer->quant) 533 return false; 534 535 return true; 536} 537 538void 539vl_zscan_cleanup_buffer(struct vl_zscan_buffer *buffer) 540{ 541 assert(buffer); 542 543 pipe_sampler_view_reference(&buffer->src, NULL); 544 pipe_sampler_view_reference(&buffer->layout, NULL); 545 pipe_sampler_view_reference(&buffer->quant, NULL); 546 pipe_surface_reference(&buffer->fb_state.cbufs[0], NULL); 547} 548 549void 550vl_zscan_set_layout(struct vl_zscan_buffer *buffer, struct pipe_sampler_view *layout) 551{ 552 assert(buffer); 553 assert(layout); 554 555 pipe_sampler_view_reference(&buffer->layout, layout); 556} 557 558void 559vl_zscan_upload_quant(struct vl_zscan *zscan, struct vl_zscan_buffer *buffer, 560 const uint8_t matrix[64], bool intra) 561{ 562 struct pipe_context *pipe; 563 struct pipe_transfer *buf_transfer; 564 unsigned x, y, i, pitch; 565 uint8_t *data; 566 567 struct pipe_box rect = 568 { 569 0, 0, intra ? 1 : 0, 570 VL_BLOCK_WIDTH, 571 VL_BLOCK_HEIGHT, 572 1 573 }; 574 575 assert(buffer); 576 assert(matrix); 577 578 pipe = zscan->pipe; 579 580 rect.width *= zscan->blocks_per_line; 581 582 data = pipe->texture_map(pipe, buffer->quant->texture, 583 0, PIPE_MAP_WRITE | 584 PIPE_MAP_DISCARD_RANGE, 585 &rect, &buf_transfer); 586 if (!data) 587 return; 588 589 pitch = buf_transfer->stride; 590 591 for (i = 0; i < zscan->blocks_per_line; ++i) 592 for (y = 0; y < VL_BLOCK_HEIGHT; ++y) 593 for (x = 0; x < VL_BLOCK_WIDTH; ++x) 594 data[i * VL_BLOCK_WIDTH + y * pitch + x] = matrix[x + y * VL_BLOCK_WIDTH]; 595 596 pipe->texture_unmap(pipe, buf_transfer); 597} 598 599void 600vl_zscan_render(struct vl_zscan *zscan, struct vl_zscan_buffer *buffer, unsigned num_instances) 601{ 602 assert(buffer); 603 604 zscan->pipe->bind_rasterizer_state(zscan->pipe, zscan->rs_state); 605 zscan->pipe->bind_blend_state(zscan->pipe, zscan->blend); 606 zscan->pipe->bind_sampler_states(zscan->pipe, PIPE_SHADER_FRAGMENT, 607 0, 3, zscan->samplers); 608 zscan->pipe->set_framebuffer_state(zscan->pipe, &buffer->fb_state); 609 zscan->pipe->set_viewport_states(zscan->pipe, 0, 1, &buffer->viewport); 610 zscan->pipe->set_sampler_views(zscan->pipe, PIPE_SHADER_FRAGMENT, 611 0, 3, 0, false, &buffer->src); 612 zscan->pipe->bind_vs_state(zscan->pipe, zscan->vs); 613 zscan->pipe->bind_fs_state(zscan->pipe, zscan->fs); 614 util_draw_arrays_instanced(zscan->pipe, PIPE_PRIM_QUADS, 0, 4, 0, num_instances); 615} 616