st/va: Fix scaling list ordering for H.265
[mesa.git] / src / gallium / auxiliary / vl / vl_zscan.c
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
46 enum VS_OUTPUT
47 {
48 VS_O_VPOS = 0,
49 VS_O_VTEX = 0
50 };
51
52 const 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
59 const 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
72 const 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
85 const 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
98 const 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
105 const 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
119 static void *
120 create_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
194 static void *
195 create_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
256 static bool
257 init_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
271 error_fs:
272 zscan->pipe->delete_vs_state(zscan->pipe, zscan->vs);
273
274 error_vs:
275 return false;
276 }
277
278 static void
279 cleanup_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
287 static bool
288 init_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 = 1;
301 zscan->rs_state = zscan->pipe->create_rasterizer_state(zscan->pipe, &rs_state);
302 if (!zscan->rs_state)
303 goto error_rs_state;
304
305 memset(&blend, 0, sizeof blend);
306
307 blend.independent_blend_enable = 0;
308 blend.rt[0].blend_enable = 0;
309 blend.rt[0].rgb_func = PIPE_BLEND_ADD;
310 blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE;
311 blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ONE;
312 blend.rt[0].alpha_func = PIPE_BLEND_ADD;
313 blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
314 blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ONE;
315 blend.logicop_enable = 0;
316 blend.logicop_func = PIPE_LOGICOP_CLEAR;
317 /* Needed to allow color writes to FB, even if blending disabled */
318 blend.rt[0].colormask = PIPE_MASK_RGBA;
319 blend.dither = 0;
320 zscan->blend = zscan->pipe->create_blend_state(zscan->pipe, &blend);
321 if (!zscan->blend)
322 goto error_blend;
323
324 for (i = 0; i < 3; ++i) {
325 memset(&sampler, 0, sizeof(sampler));
326 sampler.wrap_s = PIPE_TEX_WRAP_REPEAT;
327 sampler.wrap_t = PIPE_TEX_WRAP_REPEAT;
328 sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
329 sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST;
330 sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
331 sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
332 sampler.compare_mode = PIPE_TEX_COMPARE_NONE;
333 sampler.compare_func = PIPE_FUNC_ALWAYS;
334 sampler.normalized_coords = 1;
335 zscan->samplers[i] = zscan->pipe->create_sampler_state(zscan->pipe, &sampler);
336 if (!zscan->samplers[i])
337 goto error_samplers;
338 }
339
340 return true;
341
342 error_samplers:
343 for (i = 0; i < 2; ++i)
344 if (zscan->samplers[i])
345 zscan->pipe->delete_sampler_state(zscan->pipe, zscan->samplers[i]);
346
347 zscan->pipe->delete_rasterizer_state(zscan->pipe, zscan->rs_state);
348
349 error_blend:
350 zscan->pipe->delete_blend_state(zscan->pipe, zscan->blend);
351
352 error_rs_state:
353 return false;
354 }
355
356 static void
357 cleanup_state(struct vl_zscan *zscan)
358 {
359 unsigned i;
360
361 assert(zscan);
362
363 for (i = 0; i < 3; ++i)
364 zscan->pipe->delete_sampler_state(zscan->pipe, zscan->samplers[i]);
365
366 zscan->pipe->delete_rasterizer_state(zscan->pipe, zscan->rs_state);
367 zscan->pipe->delete_blend_state(zscan->pipe, zscan->blend);
368 }
369
370 struct pipe_sampler_view *
371 vl_zscan_layout(struct pipe_context *pipe, const int layout[64], unsigned blocks_per_line)
372 {
373 const unsigned total_size = blocks_per_line * VL_BLOCK_WIDTH * VL_BLOCK_HEIGHT;
374
375 int patched_layout[64];
376
377 struct pipe_resource res_tmpl, *res;
378 struct pipe_sampler_view sv_tmpl, *sv;
379 struct pipe_transfer *buf_transfer;
380 unsigned x, y, i, pitch;
381 float *f;
382
383 struct pipe_box rect =
384 {
385 0, 0, 0,
386 VL_BLOCK_WIDTH * blocks_per_line,
387 VL_BLOCK_HEIGHT,
388 1
389 };
390
391 assert(pipe && layout && blocks_per_line);
392
393 for (i = 0; i < 64; ++i)
394 patched_layout[layout[i]] = i;
395
396 memset(&res_tmpl, 0, sizeof(res_tmpl));
397 res_tmpl.target = PIPE_TEXTURE_2D;
398 res_tmpl.format = PIPE_FORMAT_R32_FLOAT;
399 res_tmpl.width0 = VL_BLOCK_WIDTH * blocks_per_line;
400 res_tmpl.height0 = VL_BLOCK_HEIGHT;
401 res_tmpl.depth0 = 1;
402 res_tmpl.array_size = 1;
403 res_tmpl.usage = PIPE_USAGE_IMMUTABLE;
404 res_tmpl.bind = PIPE_BIND_SAMPLER_VIEW;
405
406 res = pipe->screen->resource_create(pipe->screen, &res_tmpl);
407 if (!res)
408 goto error_resource;
409
410 f = pipe->transfer_map(pipe, res,
411 0, PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD_RANGE,
412 &rect, &buf_transfer);
413 if (!f)
414 goto error_map;
415
416 pitch = buf_transfer->stride / sizeof(float);
417
418 for (i = 0; i < blocks_per_line; ++i)
419 for (y = 0; y < VL_BLOCK_HEIGHT; ++y)
420 for (x = 0; x < VL_BLOCK_WIDTH; ++x) {
421 float addr = patched_layout[x + y * VL_BLOCK_WIDTH] +
422 i * VL_BLOCK_WIDTH * VL_BLOCK_HEIGHT;
423
424 addr /= total_size;
425
426 f[i * VL_BLOCK_WIDTH + y * pitch + x] = addr;
427 }
428
429 pipe->transfer_unmap(pipe, buf_transfer);
430
431 memset(&sv_tmpl, 0, sizeof(sv_tmpl));
432 u_sampler_view_default_template(&sv_tmpl, res, res->format);
433 sv = pipe->create_sampler_view(pipe, res, &sv_tmpl);
434 pipe_resource_reference(&res, NULL);
435 if (!sv)
436 goto error_map;
437
438 return sv;
439
440 error_map:
441 pipe_resource_reference(&res, NULL);
442
443 error_resource:
444 return NULL;
445 }
446
447 bool
448 vl_zscan_init(struct vl_zscan *zscan, struct pipe_context *pipe,
449 unsigned buffer_width, unsigned buffer_height,
450 unsigned blocks_per_line, unsigned blocks_total,
451 unsigned num_channels)
452 {
453 assert(zscan && pipe);
454
455 zscan->pipe = pipe;
456 zscan->buffer_width = buffer_width;
457 zscan->buffer_height = buffer_height;
458 zscan->num_channels = num_channels;
459 zscan->blocks_per_line = blocks_per_line;
460 zscan->blocks_total = blocks_total;
461
462 if(!init_shaders(zscan))
463 return false;
464
465 if(!init_state(zscan)) {
466 cleanup_shaders(zscan);
467 return false;
468 }
469
470 return true;
471 }
472
473 void
474 vl_zscan_cleanup(struct vl_zscan *zscan)
475 {
476 assert(zscan);
477
478 cleanup_shaders(zscan);
479 cleanup_state(zscan);
480 }
481
482 bool
483 vl_zscan_init_buffer(struct vl_zscan *zscan, struct vl_zscan_buffer *buffer,
484 struct pipe_sampler_view *src, struct pipe_surface *dst)
485 {
486 struct pipe_resource res_tmpl, *res;
487 struct pipe_sampler_view sv_tmpl;
488
489 assert(zscan && buffer);
490
491 memset(buffer, 0, sizeof(struct vl_zscan_buffer));
492
493 pipe_sampler_view_reference(&buffer->src, src);
494
495 buffer->viewport.scale[0] = dst->width;
496 buffer->viewport.scale[1] = dst->height;
497 buffer->viewport.scale[2] = 1;
498 buffer->viewport.translate[0] = 0;
499 buffer->viewport.translate[1] = 0;
500 buffer->viewport.translate[2] = 0;
501
502 buffer->fb_state.width = dst->width;
503 buffer->fb_state.height = dst->height;
504 buffer->fb_state.nr_cbufs = 1;
505 pipe_surface_reference(&buffer->fb_state.cbufs[0], dst);
506
507 memset(&res_tmpl, 0, sizeof(res_tmpl));
508 res_tmpl.target = PIPE_TEXTURE_3D;
509 res_tmpl.format = PIPE_FORMAT_R8_UNORM;
510 res_tmpl.width0 = VL_BLOCK_WIDTH * zscan->blocks_per_line;
511 res_tmpl.height0 = VL_BLOCK_HEIGHT;
512 res_tmpl.depth0 = 2;
513 res_tmpl.array_size = 1;
514 res_tmpl.usage = PIPE_USAGE_IMMUTABLE;
515 res_tmpl.bind = PIPE_BIND_SAMPLER_VIEW;
516
517 res = zscan->pipe->screen->resource_create(zscan->pipe->screen, &res_tmpl);
518 if (!res)
519 return false;
520
521 memset(&sv_tmpl, 0, sizeof(sv_tmpl));
522 u_sampler_view_default_template(&sv_tmpl, res, res->format);
523 sv_tmpl.swizzle_r = sv_tmpl.swizzle_g = sv_tmpl.swizzle_b = sv_tmpl.swizzle_a = TGSI_SWIZZLE_X;
524 buffer->quant = zscan->pipe->create_sampler_view(zscan->pipe, res, &sv_tmpl);
525 pipe_resource_reference(&res, NULL);
526 if (!buffer->quant)
527 return false;
528
529 return true;
530 }
531
532 void
533 vl_zscan_cleanup_buffer(struct vl_zscan_buffer *buffer)
534 {
535 assert(buffer);
536
537 pipe_sampler_view_reference(&buffer->src, NULL);
538 pipe_sampler_view_reference(&buffer->layout, NULL);
539 pipe_sampler_view_reference(&buffer->quant, NULL);
540 pipe_surface_reference(&buffer->fb_state.cbufs[0], NULL);
541 }
542
543 void
544 vl_zscan_set_layout(struct vl_zscan_buffer *buffer, struct pipe_sampler_view *layout)
545 {
546 assert(buffer);
547 assert(layout);
548
549 pipe_sampler_view_reference(&buffer->layout, layout);
550 }
551
552 void
553 vl_zscan_upload_quant(struct vl_zscan *zscan, struct vl_zscan_buffer *buffer,
554 const uint8_t matrix[64], bool intra)
555 {
556 struct pipe_context *pipe;
557 struct pipe_transfer *buf_transfer;
558 unsigned x, y, i, pitch;
559 uint8_t *data;
560
561 struct pipe_box rect =
562 {
563 0, 0, intra ? 1 : 0,
564 VL_BLOCK_WIDTH,
565 VL_BLOCK_HEIGHT,
566 1
567 };
568
569 assert(buffer);
570 assert(matrix);
571
572 pipe = zscan->pipe;
573
574 rect.width *= zscan->blocks_per_line;
575
576 data = pipe->transfer_map(pipe, buffer->quant->texture,
577 0, PIPE_TRANSFER_WRITE |
578 PIPE_TRANSFER_DISCARD_RANGE,
579 &rect, &buf_transfer);
580 if (!data)
581 return;
582
583 pitch = buf_transfer->stride;
584
585 for (i = 0; i < zscan->blocks_per_line; ++i)
586 for (y = 0; y < VL_BLOCK_HEIGHT; ++y)
587 for (x = 0; x < VL_BLOCK_WIDTH; ++x)
588 data[i * VL_BLOCK_WIDTH + y * pitch + x] = matrix[x + y * VL_BLOCK_WIDTH];
589
590 pipe->transfer_unmap(pipe, buf_transfer);
591 }
592
593 void
594 vl_zscan_render(struct vl_zscan *zscan, struct vl_zscan_buffer *buffer, unsigned num_instances)
595 {
596 assert(buffer);
597
598 zscan->pipe->bind_rasterizer_state(zscan->pipe, zscan->rs_state);
599 zscan->pipe->bind_blend_state(zscan->pipe, zscan->blend);
600 zscan->pipe->bind_sampler_states(zscan->pipe, PIPE_SHADER_FRAGMENT,
601 0, 3, zscan->samplers);
602 zscan->pipe->set_framebuffer_state(zscan->pipe, &buffer->fb_state);
603 zscan->pipe->set_viewport_states(zscan->pipe, 0, 1, &buffer->viewport);
604 zscan->pipe->set_sampler_views(zscan->pipe, PIPE_SHADER_FRAGMENT,
605 0, 3, &buffer->src);
606 zscan->pipe->bind_vs_state(zscan->pipe, zscan->vs);
607 zscan->pipe->bind_fs_state(zscan->pipe, zscan->fs);
608 util_draw_arrays_instanced(zscan->pipe, PIPE_PRIM_QUADS, 0, 4, 0, num_instances);
609 }