1 /**************************************************************************
3 * Copyright 2009 Younes Manton.
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:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
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 TUNGSTEN GRAPHICS 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.
26 **************************************************************************/
28 #include "vl_mpeg12_mc_renderer.h"
29 #include "vl_vertex_buffers.h"
30 #include "vl_defines.h"
31 #include "util/u_draw.h"
33 #include <pipe/p_context.h>
34 #include <util/u_inlines.h>
35 #include <util/u_format.h>
36 #include <util/u_math.h>
37 #include <util/u_memory.h>
38 #include <util/u_keymap.h>
39 #include <util/u_sampler.h>
40 #include <util/u_draw.h>
41 #include <tgsi/tgsi_ureg.h>
56 create_vert_shader(struct vl_mpeg12_mc_renderer
*r
)
58 struct ureg_program
*shader
;
59 struct ureg_src block_scale
, mv_scale
;
60 struct ureg_src vrect
, vpos
, eb
, flags
, vmv
[2][2];
61 struct ureg_dst t_vpos
, t_vtex
, t_vmv
;
62 struct ureg_dst o_vpos
, o_line
, o_vtex
[2], o_vmv
[2][2];
65 shader
= ureg_create(TGSI_PROCESSOR_VERTEX
);
69 t_vpos
= ureg_DECL_temporary(shader
);
70 t_vtex
= ureg_DECL_temporary(shader
);
71 t_vmv
= ureg_DECL_temporary(shader
);
73 vrect
= ureg_DECL_vs_input(shader
, VS_I_RECT
);
74 vpos
= ureg_DECL_vs_input(shader
, VS_I_VPOS
);
75 eb
= ureg_DECL_vs_input(shader
, VS_I_EB
);
76 flags
= ureg_DECL_vs_input(shader
, VS_I_FLAGS
);
77 vmv
[0][0] = ureg_DECL_vs_input(shader
, VS_I_MV0_TOP
);
78 vmv
[0][1] = ureg_DECL_vs_input(shader
, VS_I_MV0_BOTTOM
);
79 vmv
[1][0] = ureg_DECL_vs_input(shader
, VS_I_MV1_TOP
);
80 vmv
[1][1] = ureg_DECL_vs_input(shader
, VS_I_MV1_BOTTOM
);
82 o_vpos
= ureg_DECL_output(shader
, TGSI_SEMANTIC_POSITION
, VS_O_VPOS
);
83 o_line
= ureg_DECL_output(shader
, TGSI_SEMANTIC_GENERIC
, VS_O_LINE
);
84 o_vtex
[0] = ureg_DECL_output(shader
, TGSI_SEMANTIC_GENERIC
, VS_O_TEX_TOP
);
85 o_vtex
[1] = ureg_DECL_output(shader
, TGSI_SEMANTIC_GENERIC
, VS_O_TEX_BOTTOM
);
86 o_vmv
[0][0] = ureg_DECL_output(shader
, TGSI_SEMANTIC_GENERIC
, VS_O_MV0_TOP
);
87 o_vmv
[0][1] = ureg_DECL_output(shader
, TGSI_SEMANTIC_GENERIC
, VS_O_MV0_BOTTOM
);
88 o_vmv
[1][0] = ureg_DECL_output(shader
, TGSI_SEMANTIC_GENERIC
, VS_O_MV1_TOP
);
89 o_vmv
[1][1] = ureg_DECL_output(shader
, TGSI_SEMANTIC_GENERIC
, VS_O_MV1_BOTTOM
);
92 * block_scale = (MACROBLOCK_WIDTH, MACROBLOCK_HEIGHT) / (dst.width, dst.height)
93 * mv_scale = 0.5 / (dst.width, dst.height);
95 * t_vpos = (vpos + vrect) * block_scale
99 * o_eb[0..1] = vrect.x ? eb[0..1][1] : eb[0..1][0]
101 * o_frame_pred = frame_pred
102 * o_info.x = not_intra
103 * o_info.y = ref_weight / 2
105 * // Apply motion vectors
106 * o_vmv[0..3] = t_vpos + vmv[0..3] * mv_scale
108 * o_line.xy = vrect * 8
109 * o_line.z = interlaced
111 * if(eb[0][0].w) { //interlaced
113 * t_vtex.y = vrect.y * 0.5
116 * o_vtex[0].xy = t_vtex * block_scale
119 * o_vtex[1].xy = t_vtex * block_scale
121 * o_vtex[0..1].xy = t_vpos
123 * o_vtex[2].xy = t_vpos
126 block_scale
= ureg_imm2f(shader
,
127 (float)MACROBLOCK_WIDTH
/ r
->buffer_width
,
128 (float)MACROBLOCK_HEIGHT
/ r
->buffer_height
);
130 mv_scale
= ureg_imm2f(shader
,
131 0.5f
/ r
->buffer_width
,
132 0.5f
/ r
->buffer_height
);
134 ureg_ADD(shader
, ureg_writemask(t_vpos
, TGSI_WRITEMASK_XY
), vpos
, vrect
);
135 ureg_MUL(shader
, ureg_writemask(t_vpos
, TGSI_WRITEMASK_XY
), ureg_src(t_vpos
), block_scale
);
136 ureg_MOV(shader
, ureg_writemask(o_vpos
, TGSI_WRITEMASK_XY
), ureg_src(t_vpos
));
137 ureg_MOV(shader
, ureg_writemask(o_vpos
, TGSI_WRITEMASK_ZW
), vpos
);
139 for (i
= 0; i
< 2; ++i
)
140 for (j
= 0; j
< 2; ++j
) {
141 ureg_MAD(shader
, ureg_writemask(o_vmv
[i
][j
], TGSI_WRITEMASK_XY
), mv_scale
, vmv
[i
][j
], ureg_src(t_vpos
));
142 ureg_MOV(shader
, ureg_writemask(o_vmv
[i
][j
], TGSI_WRITEMASK_Z
), ureg_scalar(flags
, TGSI_SWIZZLE_Z
+ i
));
145 ureg_MOV(shader
, ureg_writemask(o_vtex
[0], TGSI_WRITEMASK_XY
), ureg_src(t_vpos
));
146 ureg_CMP(shader
, ureg_writemask(o_vtex
[0], TGSI_WRITEMASK_Z
),
147 ureg_negate(ureg_scalar(vrect
, TGSI_SWIZZLE_X
)),
148 ureg_scalar(eb
, TGSI_SWIZZLE_Y
),
149 ureg_scalar(eb
, TGSI_SWIZZLE_X
));
151 ureg_MOV(shader
, ureg_writemask(o_vtex
[1], TGSI_WRITEMASK_XY
), ureg_src(t_vpos
));
152 ureg_CMP(shader
, ureg_writemask(o_vtex
[1], TGSI_WRITEMASK_Z
),
153 ureg_negate(ureg_scalar(vrect
, TGSI_SWIZZLE_X
)),
154 ureg_scalar(eb
, TGSI_SWIZZLE_W
),
155 ureg_scalar(eb
, TGSI_SWIZZLE_Z
));
157 ureg_MOV(shader
, ureg_writemask(o_line
, TGSI_WRITEMASK_X
), ureg_scalar(vrect
, TGSI_SWIZZLE_Y
));
158 ureg_MUL(shader
, ureg_writemask(o_line
, TGSI_WRITEMASK_Y
),
159 vrect
, ureg_imm1f(shader
, MACROBLOCK_HEIGHT
/ 2));
160 ureg_MOV(shader
, ureg_writemask(o_line
, TGSI_WRITEMASK_Z
),
161 ureg_scalar(flags
, TGSI_SWIZZLE_Y
));
163 ureg_IF(shader
, ureg_scalar(flags
, TGSI_SWIZZLE_X
), &label
);
165 ureg_MOV(shader
, ureg_writemask(t_vtex
, TGSI_WRITEMASK_X
), vrect
);
166 ureg_MUL(shader
, ureg_writemask(t_vtex
, TGSI_WRITEMASK_Y
), vrect
, ureg_imm1f(shader
, 0.5f
));
167 ureg_ADD(shader
, ureg_writemask(t_vtex
, TGSI_WRITEMASK_XY
), vpos
, ureg_src(t_vtex
));
168 ureg_MUL(shader
, ureg_writemask(o_vtex
[0], TGSI_WRITEMASK_XY
), ureg_src(t_vtex
), block_scale
);
169 ureg_ADD(shader
, ureg_writemask(t_vtex
, TGSI_WRITEMASK_Y
), ureg_src(t_vtex
), ureg_imm1f(shader
, 0.5f
));
170 ureg_MUL(shader
, ureg_writemask(o_vtex
[1], TGSI_WRITEMASK_XY
), ureg_src(t_vtex
), block_scale
);
172 ureg_MUL(shader
, ureg_writemask(o_line
, TGSI_WRITEMASK_X
),
173 ureg_scalar(vrect
, TGSI_SWIZZLE_Y
),
174 ureg_imm1f(shader
, MACROBLOCK_HEIGHT
/ 2));
176 ureg_fixup_label(shader
, label
, ureg_get_instruction_number(shader
));
179 ureg_release_temporary(shader
, t_vtex
);
180 ureg_release_temporary(shader
, t_vpos
);
181 ureg_release_temporary(shader
, t_vmv
);
185 return ureg_create_shader_and_destroy(shader
, r
->pipe
);
188 static struct ureg_dst
189 calc_field(struct ureg_program
*shader
)
192 struct ureg_src line
;
194 tmp
= ureg_DECL_temporary(shader
);
196 line
= ureg_DECL_fs_input(shader
, TGSI_SEMANTIC_GENERIC
, VS_O_LINE
, TGSI_INTERPOLATE_LINEAR
);
199 * line.x going from 0 to 1 if not interlaced
200 * line.x going from 0 to 8 in steps of 0.5 if interlaced
201 * line.y going from 0 to 8 in steps of 0.5
202 * line.z is flag for intra frames
204 * tmp.xy = fraction(line)
205 * tmp.xy = tmp.xy >= 0.5 ? 1 : 0
207 ureg_FRC(shader
, ureg_writemask(tmp
, TGSI_WRITEMASK_XY
), line
);
208 ureg_SGE(shader
, ureg_writemask(tmp
, TGSI_WRITEMASK_XY
), ureg_src(tmp
), ureg_imm1f(shader
, 0.5f
));
209 ureg_MOV(shader
, ureg_writemask(tmp
, TGSI_WRITEMASK_Z
), line
);
214 static struct ureg_dst
215 fetch_ycbcr(struct vl_mpeg12_mc_renderer
*r
, struct ureg_program
*shader
, struct ureg_dst field
, float scale
)
217 struct ureg_src tc
[2], sampler
;
218 struct ureg_dst texel
, t_tc
;
221 texel
= ureg_DECL_temporary(shader
);
222 t_tc
= ureg_DECL_temporary(shader
);
224 tc
[0] = ureg_DECL_fs_input(shader
, TGSI_SEMANTIC_GENERIC
, VS_O_TEX_TOP
, TGSI_INTERPOLATE_LINEAR
);
225 tc
[1] = ureg_DECL_fs_input(shader
, TGSI_SEMANTIC_GENERIC
, VS_O_TEX_BOTTOM
, TGSI_INTERPOLATE_LINEAR
);
227 sampler
= ureg_DECL_sampler(shader
, 0);
230 * texel.y = tex(field.y ? tc[1] : tc[0], sampler[0])
231 * texel.cb = tex(tc[2], sampler[1])
232 * texel.cr = tex(tc[2], sampler[2])
235 ureg_CMP(shader
, ureg_writemask(t_tc
, TGSI_WRITEMASK_XYZ
),
236 ureg_negate(ureg_scalar(ureg_src(field
), TGSI_SWIZZLE_X
)),
239 ureg_SLT(shader
, ureg_writemask(t_tc
, TGSI_WRITEMASK_Z
), ureg_src(t_tc
), ureg_imm1f(shader
, 0.5f
));
241 ureg_MOV(shader
, ureg_writemask(texel
, TGSI_WRITEMASK_XYZ
), ureg_imm1f(shader
, 0.0f
));
242 ureg_IF(shader
, ureg_scalar(ureg_src(t_tc
), TGSI_SWIZZLE_Z
), &label
);
244 ureg_TEX(shader
, texel
, TGSI_TEXTURE_3D
, ureg_src(t_tc
), sampler
);
246 ureg_fixup_label(shader
, label
, ureg_get_instruction_number(shader
));
250 ureg_MUL(shader
, texel
, ureg_src(texel
), ureg_imm1f(shader
, scale
));
252 ureg_release_temporary(shader
, t_tc
);
257 static struct ureg_dst
258 fetch_ref(struct ureg_program
*shader
, struct ureg_dst field
)
260 struct ureg_src tc
[2][2], sampler
[2];
261 struct ureg_dst ref
[2], result
;
262 unsigned i
, intra_label
;
264 tc
[0][0] = ureg_DECL_fs_input(shader
, TGSI_SEMANTIC_GENERIC
, VS_O_MV0_TOP
, TGSI_INTERPOLATE_LINEAR
);
265 tc
[0][1] = ureg_DECL_fs_input(shader
, TGSI_SEMANTIC_GENERIC
, VS_O_MV0_BOTTOM
, TGSI_INTERPOLATE_LINEAR
);
266 tc
[1][0] = ureg_DECL_fs_input(shader
, TGSI_SEMANTIC_GENERIC
, VS_O_MV1_TOP
, TGSI_INTERPOLATE_LINEAR
);
267 tc
[1][1] = ureg_DECL_fs_input(shader
, TGSI_SEMANTIC_GENERIC
, VS_O_MV1_BOTTOM
, TGSI_INTERPOLATE_LINEAR
);
269 for (i
= 0; i
< 2; ++i
) {
270 sampler
[i
] = ureg_DECL_sampler(shader
, i
+ 1);
271 ref
[i
] = ureg_DECL_temporary(shader
);
274 result
= ureg_DECL_temporary(shader
);
276 ureg_MOV(shader
, result
, ureg_imm1f(shader
, 0.5f
));
278 ureg_IF(shader
, ureg_scalar(ureg_src(field
), TGSI_SWIZZLE_Z
), &intra_label
);
281 * ref[0..1] = tex(tc[0..1], sampler[0..1])
283 * ref[0..1] = tex(tc[2..3], sampler[0..1])
284 * result = LRP(info.y, ref[0..1])
286 ureg_CMP(shader
, ureg_writemask(ref
[0], TGSI_WRITEMASK_XY
),
287 ureg_negate(ureg_scalar(ureg_src(field
), TGSI_SWIZZLE_Y
)),
289 ureg_CMP(shader
, ureg_writemask(ref
[1], TGSI_WRITEMASK_XY
),
290 ureg_negate(ureg_scalar(ureg_src(field
), TGSI_SWIZZLE_Y
)),
293 ureg_TEX(shader
, ref
[0], TGSI_TEXTURE_2D
, ureg_src(ref
[0]), sampler
[0]);
294 ureg_TEX(shader
, ref
[1], TGSI_TEXTURE_2D
, ureg_src(ref
[1]), sampler
[1]);
296 ureg_LRP(shader
, ref
[0],
297 ureg_scalar(tc
[0][0], TGSI_SWIZZLE_Z
),
298 ureg_src(ref
[0]), ureg_imm1f(shader
, 0.0f
));
300 ureg_LRP(shader
, ref
[1],
301 ureg_scalar(tc
[1][0], TGSI_SWIZZLE_Z
),
302 ureg_src(ref
[1]), ureg_imm1f(shader
, 0.0f
));
304 ureg_ADD(shader
, result
, ureg_src(ref
[0]), ureg_src(ref
[1]));
306 ureg_fixup_label(shader
, intra_label
, ureg_get_instruction_number(shader
));
309 for (i
= 0; i
< 2; ++i
)
310 ureg_release_temporary(shader
, ref
[i
]);
316 create_frag_shader(struct vl_mpeg12_mc_renderer
*r
, float scale
)
318 struct ureg_program
*shader
;
319 struct ureg_dst result
;
320 struct ureg_dst field
, texel
;
321 struct ureg_dst fragment
;
323 shader
= ureg_create(TGSI_PROCESSOR_FRAGMENT
);
327 fragment
= ureg_DECL_output(shader
, TGSI_SEMANTIC_COLOR
, 0);
329 field
= calc_field(shader
);
330 texel
= fetch_ycbcr(r
, shader
, field
, scale
);
332 result
= fetch_ref(shader
, field
);
334 ureg_ADD(shader
, fragment
, ureg_src(texel
), ureg_src(result
));
336 ureg_release_temporary(shader
, field
);
337 ureg_release_temporary(shader
, texel
);
338 ureg_release_temporary(shader
, result
);
341 return ureg_create_shader_and_destroy(shader
, r
->pipe
);
345 init_pipe_state(struct vl_mpeg12_mc_renderer
*r
)
347 struct pipe_sampler_state sampler
;
348 struct pipe_rasterizer_state rs_state
;
354 r
->viewport
.scale
[2] = 1;
355 r
->viewport
.scale
[3] = 1;
356 r
->viewport
.translate
[0] = 0;
357 r
->viewport
.translate
[1] = 0;
358 r
->viewport
.translate
[2] = 0;
359 r
->viewport
.translate
[3] = 0;
361 r
->fb_state
.nr_cbufs
= 1;
362 r
->fb_state
.zsbuf
= NULL
;
365 filters
[0] = PIPE_TEX_FILTER_NEAREST
;
367 /* Fwd, bkwd ref filters */
368 filters
[1] = PIPE_TEX_FILTER_LINEAR
;
369 filters
[2] = PIPE_TEX_FILTER_LINEAR
;
371 for (i
= 0; i
< 3; ++i
) {
372 memset(&sampler
, 0, sizeof(sampler
));
373 sampler
.wrap_s
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
374 sampler
.wrap_t
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
375 sampler
.wrap_r
= PIPE_TEX_WRAP_CLAMP_TO_BORDER
;
376 sampler
.min_img_filter
= filters
[i
];
377 sampler
.min_mip_filter
= PIPE_TEX_MIPFILTER_NONE
;
378 sampler
.mag_img_filter
= filters
[i
];
379 sampler
.compare_mode
= PIPE_TEX_COMPARE_NONE
;
380 sampler
.compare_func
= PIPE_FUNC_ALWAYS
;
381 sampler
.normalized_coords
= 1;
382 /*sampler.shadow_ambient = ; */
383 /*sampler.lod_bias = ; */
385 /*sampler.max_lod = ; */
386 sampler
.border_color
[0] = 0.0f
;
387 sampler
.border_color
[1] = 0.0f
;
388 sampler
.border_color
[2] = 0.0f
;
389 sampler
.border_color
[3] = 0.0f
;
390 /*sampler.max_anisotropy = ; */
391 r
->samplers
.all
[i
] = r
->pipe
->create_sampler_state(r
->pipe
, &sampler
);
392 if (!r
->samplers
.all
[i
])
396 memset(&rs_state
, 0, sizeof(rs_state
));
397 /*rs_state.sprite_coord_enable */
398 rs_state
.sprite_coord_mode
= PIPE_SPRITE_COORD_UPPER_LEFT
;
399 rs_state
.point_quad_rasterization
= true;
400 rs_state
.point_size
= BLOCK_WIDTH
;
401 rs_state
.gl_rasterization_rules
= true;
402 r
->rs_state
= r
->pipe
->create_rasterizer_state(r
->pipe
, &rs_state
);
409 for (i
= 0; i
< 5; ++i
)
410 r
->pipe
->delete_sampler_state(r
->pipe
, r
->samplers
.all
[i
]);
416 cleanup_pipe_state(struct vl_mpeg12_mc_renderer
*r
)
422 for (i
= 0; i
< 3; ++i
)
423 r
->pipe
->delete_sampler_state(r
->pipe
, r
->samplers
.all
[i
]);
425 r
->pipe
->delete_rasterizer_state(r
->pipe
, r
->rs_state
);
429 vl_mpeg12_mc_renderer_init(struct vl_mpeg12_mc_renderer
*renderer
,
430 struct pipe_context
*pipe
,
431 unsigned buffer_width
,
432 unsigned buffer_height
,
435 struct pipe_resource tex_templ
, *tex_dummy
;
436 struct pipe_sampler_view sampler_view
;
441 memset(renderer
, 0, sizeof(struct vl_mpeg12_mc_renderer
));
443 renderer
->pipe
= pipe
;
444 renderer
->buffer_width
= buffer_width
;
445 renderer
->buffer_height
= buffer_height
;
447 if (!init_pipe_state(renderer
))
448 goto error_pipe_state
;
450 renderer
->vs
= create_vert_shader(renderer
);
452 goto error_vs_shaders
;
454 renderer
->fs
= create_frag_shader(renderer
, scale
);
456 goto error_fs_shaders
;
458 /* create a dummy sampler */
459 memset(&tex_templ
, 0, sizeof(tex_templ
));
460 tex_templ
.bind
= PIPE_BIND_SAMPLER_VIEW
;
463 tex_templ
.target
= PIPE_TEXTURE_2D
;
464 tex_templ
.format
= PIPE_FORMAT_R8_SNORM
;
465 tex_templ
.width0
= 1;
466 tex_templ
.height0
= 1;
467 tex_templ
.depth0
= 1;
468 tex_templ
.array_size
= 1;
469 tex_templ
.last_level
= 0;
470 tex_templ
.usage
= PIPE_USAGE_STATIC
;
471 tex_dummy
= pipe
->screen
->resource_create(pipe
->screen
, &tex_templ
);
475 memset(&sampler_view
, 0, sizeof(sampler_view
));
476 u_sampler_view_default_template(&sampler_view
, tex_dummy
, tex_dummy
->format
);
477 renderer
->dummy
= pipe
->create_sampler_view(pipe
, tex_dummy
, &sampler_view
);
478 pipe_resource_reference(&tex_dummy
, NULL
);
479 if (!renderer
->dummy
)
485 renderer
->pipe
->delete_fs_state(renderer
->pipe
, renderer
->fs
);
488 renderer
->pipe
->delete_vs_state(renderer
->pipe
, renderer
->vs
);
491 cleanup_pipe_state(renderer
);
498 vl_mpeg12_mc_renderer_cleanup(struct vl_mpeg12_mc_renderer
*renderer
)
502 pipe_sampler_view_reference(&renderer
->dummy
, NULL
);
504 cleanup_pipe_state(renderer
);
506 renderer
->pipe
->delete_vs_state(renderer
->pipe
, renderer
->vs
);
507 renderer
->pipe
->delete_fs_state(renderer
->pipe
, renderer
->fs
);
511 vl_mpeg12_mc_init_buffer(struct vl_mpeg12_mc_renderer
*renderer
, struct vl_mpeg12_mc_buffer
*buffer
,
512 struct pipe_sampler_view
*source
)
514 assert(renderer
&& buffer
);
517 pipe_sampler_view_reference(&buffer
->sampler_views
.individual
.source
, source
);
523 vl_mpeg12_mc_cleanup_buffer(struct vl_mpeg12_mc_buffer
*buffer
)
529 for (i
= 0; i
< 3; ++i
)
530 pipe_sampler_view_reference(&buffer
->sampler_views
.all
[i
], NULL
);
534 vl_mpeg12_mc_renderer_flush(struct vl_mpeg12_mc_renderer
*renderer
, struct vl_mpeg12_mc_buffer
*buffer
,
535 struct pipe_surface
*surface
, struct pipe_sampler_view
*ref
[2],
536 unsigned not_empty_start_instance
, unsigned not_empty_num_instances
,
537 unsigned empty_start_instance
, unsigned empty_num_instances
,
538 struct pipe_fence_handle
**fence
)
540 assert(renderer
&& buffer
);
541 assert(surface
&& ref
);
543 if (not_empty_num_instances
== 0 && empty_num_instances
== 0)
546 renderer
->viewport
.scale
[0] = surface
->width
;
547 renderer
->viewport
.scale
[1] = surface
->height
;
549 renderer
->fb_state
.width
= surface
->width
;
550 renderer
->fb_state
.height
= surface
->height
;
551 renderer
->fb_state
.cbufs
[0] = surface
;
554 renderer
->pipe
->bind_rasterizer_state(renderer
->pipe
, renderer
->rs_state
);
555 renderer
->pipe
->set_framebuffer_state(renderer
->pipe
, &renderer
->fb_state
);
556 renderer
->pipe
->set_viewport_state(renderer
->pipe
, &renderer
->viewport
);
558 /* if no reference frame provided use a dummy sampler instead */
559 pipe_sampler_view_reference(&buffer
->sampler_views
.individual
.ref
[0],
560 ref
[0] ? ref
[0] : renderer
->dummy
);
561 pipe_sampler_view_reference(&buffer
->sampler_views
.individual
.ref
[1],
562 ref
[1] ? ref
[1] : renderer
->dummy
);
564 renderer
->pipe
->set_fragment_sampler_views(renderer
->pipe
, 3, buffer
->sampler_views
.all
);
565 renderer
->pipe
->bind_fragment_sampler_states(renderer
->pipe
, 3, renderer
->samplers
.all
);
567 renderer
->pipe
->bind_vs_state(renderer
->pipe
, renderer
->vs
);
568 renderer
->pipe
->bind_fs_state(renderer
->pipe
, renderer
->fs
);
570 if (not_empty_num_instances
> 0)
571 util_draw_arrays_instanced(renderer
->pipe
, PIPE_PRIM_QUADS
, 0, 4,
572 not_empty_start_instance
, not_empty_num_instances
);
574 if (empty_num_instances
> 0)
575 util_draw_arrays_instanced(renderer
->pipe
, PIPE_PRIM_QUADS
, 0, 4,
576 empty_start_instance
, empty_num_instances
);
578 renderer
->pipe
->flush(renderer
->pipe
, fence
);