• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 *
create_vert_shader(struct vl_zscan * zscan)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 *
create_frag_shader(struct vl_zscan * zscan)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
init_shaders(struct vl_zscan * zscan)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
cleanup_shaders(struct vl_zscan * zscan)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
init_state(struct vl_zscan * zscan)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
cleanup_state(struct vl_zscan * zscan)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 *
vl_zscan_layout(struct pipe_context * pipe,const int layout[64],unsigned blocks_per_line)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
vl_zscan_init(struct vl_zscan * zscan,struct pipe_context * pipe,unsigned buffer_width,unsigned buffer_height,unsigned blocks_per_line,unsigned blocks_total,unsigned num_channels)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
vl_zscan_cleanup(struct vl_zscan * zscan)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
vl_zscan_init_buffer(struct vl_zscan * zscan,struct vl_zscan_buffer * buffer,struct pipe_sampler_view * src,struct pipe_surface * dst)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
vl_zscan_cleanup_buffer(struct vl_zscan_buffer * buffer)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
vl_zscan_set_layout(struct vl_zscan_buffer * buffer,struct pipe_sampler_view * layout)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
vl_zscan_upload_quant(struct vl_zscan * zscan,struct vl_zscan_buffer * buffer,const uint8_t matrix[64],bool intra)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
vl_zscan_render(struct vl_zscan * zscan,struct vl_zscan_buffer * buffer,unsigned num_instances)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 }
610