g3dvl: Use sobel filter for chroma interpolation
[mesa/nouveau-pmpeg.git] / src / gallium / state_trackers / vega / renderer.c
blobe4c1fd5e3a36976229f852ca7f315b0744e6194d
1 /**************************************************************************
3 * Copyright 2009 VMware, Inc. All Rights Reserved.
4 * Copyright 2010 LunarG, Inc. All Rights Reserved.
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
16 * of the Software.
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.
26 **************************************************************************/
28 #include "renderer.h"
30 #include "vg_context.h"
32 #include "pipe/p_context.h"
33 #include "pipe/p_state.h"
34 #include "util/u_inlines.h"
35 #include "pipe/p_screen.h"
36 #include "pipe/p_shader_tokens.h"
38 #include "util/u_draw_quad.h"
39 #include "util/u_simple_shaders.h"
40 #include "util/u_memory.h"
41 #include "util/u_sampler.h"
42 #include "util/u_surface.h"
43 #include "util/u_math.h"
44 #include "util/u_format.h"
46 #include "cso_cache/cso_context.h"
47 #include "tgsi/tgsi_ureg.h"
49 typedef enum {
50 RENDERER_STATE_INIT,
51 RENDERER_STATE_COPY,
52 RENDERER_STATE_DRAWTEX,
53 RENDERER_STATE_SCISSOR,
54 RENDERER_STATE_CLEAR,
55 RENDERER_STATE_FILTER,
56 RENDERER_STATE_POLYGON_STENCIL,
57 RENDERER_STATE_POLYGON_FILL,
58 NUM_RENDERER_STATES
59 } RendererState;
61 typedef enum {
62 RENDERER_VS_PLAIN,
63 RENDERER_VS_COLOR,
64 RENDERER_VS_TEXTURE,
65 NUM_RENDERER_VS
66 } RendererVs;
68 typedef enum {
69 RENDERER_FS_COLOR,
70 RENDERER_FS_TEXTURE,
71 RENDERER_FS_SCISSOR,
72 RENDERER_FS_WHITE,
73 NUM_RENDERER_FS
74 } RendererFs;
76 struct renderer {
77 struct pipe_context *pipe;
78 struct cso_context *cso;
80 VGbitfield dirty;
81 struct {
82 struct pipe_rasterizer_state rasterizer;
83 struct pipe_depth_stencil_alpha_state dsa;
84 struct pipe_framebuffer_state fb;
85 } g3d;
86 struct matrix projection;
88 struct matrix mvp;
89 struct pipe_resource *vs_cbuf;
91 struct pipe_resource *fs_cbuf;
92 VGfloat fs_cbuf_data[32];
93 VGint fs_cbuf_len;
95 struct pipe_vertex_element velems[2];
96 VGfloat vertices[4][2][4];
98 void *cached_vs[NUM_RENDERER_VS];
99 void *cached_fs[NUM_RENDERER_FS];
101 RendererState state;
103 /* state data */
104 union {
105 struct {
106 VGint tex_width;
107 VGint tex_height;
108 } copy;
110 struct {
111 VGint tex_width;
112 VGint tex_height;
113 } drawtex;
115 struct {
116 VGboolean restore_dsa;
117 } scissor;
119 struct {
120 VGboolean use_sampler;
121 VGint tex_width, tex_height;
122 } filter;
124 struct {
125 struct pipe_depth_stencil_alpha_state dsa;
126 VGboolean manual_two_sides;
127 VGboolean restore_dsa;
128 } polygon_stencil;
129 } u;
133 * Return VG_TRUE if the renderer can use the resource as the asked bindings.
135 static VGboolean renderer_can_support(struct renderer *renderer,
136 struct pipe_resource *res,
137 unsigned bindings)
139 struct pipe_screen *screen = renderer->pipe->screen;
141 return screen->is_format_supported(screen,
142 res->format, res->target, 0, bindings);
146 * Set the model-view-projection matrix used by vertex shaders.
148 static void renderer_set_mvp(struct renderer *renderer,
149 const struct matrix *mvp)
151 struct matrix *cur = &renderer->mvp;
152 struct pipe_resource *cbuf;
153 VGfloat consts[3][4];
154 VGint i;
156 /* projection only */
157 if (!mvp)
158 mvp = &renderer->projection;
160 /* re-upload only if necessary */
161 if (memcmp(cur, mvp, sizeof(*mvp)) == 0)
162 return;
164 /* 3x3 matrix to 3 constant vectors (no Z) */
165 for (i = 0; i < 3; i++) {
166 consts[i][0] = mvp->m[i + 0];
167 consts[i][1] = mvp->m[i + 3];
168 consts[i][2] = 0.0f;
169 consts[i][3] = mvp->m[i + 6];
172 cbuf = renderer->vs_cbuf;
173 pipe_resource_reference(&cbuf, NULL);
174 cbuf = pipe_buffer_create(renderer->pipe->screen,
175 PIPE_BIND_CONSTANT_BUFFER,
176 PIPE_USAGE_STATIC,
177 sizeof(consts));
178 if (cbuf) {
179 pipe_buffer_write(renderer->pipe, cbuf,
180 0, sizeof(consts), consts);
182 renderer->pipe->set_constant_buffer(renderer->pipe,
183 PIPE_SHADER_VERTEX, 0, cbuf);
185 memcpy(cur, mvp, sizeof(*mvp));
186 renderer->vs_cbuf = cbuf;
190 * Create a simple vertex shader that passes through position and the given
191 * attribute.
193 static void *create_passthrough_vs(struct pipe_context *pipe, int semantic_name)
195 struct ureg_program *ureg;
196 struct ureg_src src[2], constants[3];
197 struct ureg_dst dst[2], tmp;
198 int i;
200 ureg = ureg_create(TGSI_PROCESSOR_VERTEX);
201 if (!ureg)
202 return NULL;
204 /* position is in user coordinates */
205 src[0] = ureg_DECL_vs_input(ureg, 0);
206 dst[0] = ureg_DECL_output(ureg, TGSI_SEMANTIC_POSITION, 0);
207 tmp = ureg_DECL_temporary(ureg);
208 for (i = 0; i < Elements(constants); i++)
209 constants[i] = ureg_DECL_constant(ureg, i);
211 /* transform to clipped coordinates */
212 ureg_DP4(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_X), src[0], constants[0]);
213 ureg_DP4(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_Y), src[0], constants[1]);
214 ureg_MOV(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_Z), src[0]);
215 ureg_DP4(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_W), src[0], constants[2]);
216 ureg_MOV(ureg, dst[0], ureg_src(tmp));
218 if (semantic_name >= 0) {
219 src[1] = ureg_DECL_vs_input(ureg, 1);
220 dst[1] = ureg_DECL_output(ureg, semantic_name, 0);
221 ureg_MOV(ureg, dst[1], src[1]);
224 ureg_END(ureg);
226 return ureg_create_shader_and_destroy(ureg, pipe);
230 * Set renderer vertex shader.
232 * This function modifies vertex_shader state.
234 static void renderer_set_vs(struct renderer *r, RendererVs id)
236 /* create as needed */
237 if (!r->cached_vs[id]) {
238 int semantic_name = -1;
240 switch (id) {
241 case RENDERER_VS_PLAIN:
242 break;
243 case RENDERER_VS_COLOR:
244 semantic_name = TGSI_SEMANTIC_COLOR;
245 break;
246 case RENDERER_VS_TEXTURE:
247 semantic_name = TGSI_SEMANTIC_GENERIC;
248 break;
249 default:
250 assert(!"Unknown renderer vs id");
251 break;
254 r->cached_vs[id] = create_passthrough_vs(r->pipe, semantic_name);
257 cso_set_vertex_shader_handle(r->cso, r->cached_vs[id]);
261 * Create a simple fragment shader that sets the depth to 0.0f.
263 static void *create_scissor_fs(struct pipe_context *pipe)
265 struct ureg_program *ureg;
266 struct ureg_dst out;
267 struct ureg_src imm;
269 ureg = ureg_create(TGSI_PROCESSOR_FRAGMENT);
270 out = ureg_DECL_output(ureg, TGSI_SEMANTIC_POSITION, 0);
271 imm = ureg_imm4f(ureg, 0.0f, 0.0f, 0.0f, 0.0f);
273 ureg_MOV(ureg, ureg_writemask(out, TGSI_WRITEMASK_Z), imm);
274 ureg_END(ureg);
276 return ureg_create_shader_and_destroy(ureg, pipe);
280 * Create a simple fragment shader that sets the color to white.
282 static void *create_white_fs(struct pipe_context *pipe)
284 struct ureg_program *ureg;
285 struct ureg_dst out;
286 struct ureg_src imm;
288 ureg = ureg_create(TGSI_PROCESSOR_FRAGMENT);
289 out = ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 0);
290 imm = ureg_imm4f(ureg, 1.0f, 1.0f, 1.0f, 1.0f);
292 ureg_MOV(ureg, out, imm);
293 ureg_END(ureg);
295 return ureg_create_shader_and_destroy(ureg, pipe);
299 * Set renderer fragment shader.
301 * This function modifies fragment_shader state.
303 static void renderer_set_fs(struct renderer *r, RendererFs id)
305 /* create as needed */
306 if (!r->cached_fs[id]) {
307 void *fs = NULL;
309 switch (id) {
310 case RENDERER_FS_COLOR:
311 fs = util_make_fragment_passthrough_shader(r->pipe);
312 break;
313 case RENDERER_FS_TEXTURE:
314 fs = util_make_fragment_tex_shader(r->pipe,
315 TGSI_TEXTURE_2D, TGSI_INTERPOLATE_LINEAR);
316 break;
317 case RENDERER_FS_SCISSOR:
318 fs = create_scissor_fs(r->pipe);
319 break;
320 case RENDERER_FS_WHITE:
321 fs = create_white_fs(r->pipe);
322 break;
323 default:
324 assert(!"Unknown renderer fs id");
325 break;
328 r->cached_fs[id] = fs;
331 cso_set_fragment_shader_handle(r->cso, r->cached_fs[id]);
334 typedef enum {
335 VEGA_Y0_TOP,
336 VEGA_Y0_BOTTOM
337 } VegaOrientation;
339 static void vg_set_viewport(struct renderer *r,
340 VegaOrientation orientation)
342 const struct pipe_framebuffer_state *fb = &r->g3d.fb;
343 struct pipe_viewport_state viewport;
344 VGfloat y_scale = (orientation == VEGA_Y0_BOTTOM) ? -2.f : 2.f;
346 viewport.scale[0] = fb->width / 2.f;
347 viewport.scale[1] = fb->height / y_scale;
348 viewport.scale[2] = 1.0;
349 viewport.scale[3] = 1.0;
350 viewport.translate[0] = fb->width / 2.f;
351 viewport.translate[1] = fb->height / 2.f;
352 viewport.translate[2] = 0.0;
353 viewport.translate[3] = 0.0;
355 cso_set_viewport(r->cso, &viewport);
359 * Set renderer target.
361 * This function modifies framebuffer and viewport states.
363 static void renderer_set_target(struct renderer *r,
364 struct pipe_surface *cbuf,
365 struct pipe_surface *zsbuf,
366 VGboolean y0_top)
368 struct pipe_framebuffer_state fb;
370 memset(&fb, 0, sizeof(fb));
371 fb.width = cbuf->width;
372 fb.height = cbuf->height;
373 fb.cbufs[0] = cbuf;
374 fb.nr_cbufs = 1;
375 fb.zsbuf = zsbuf;
376 cso_set_framebuffer(r->cso, &fb);
378 vg_set_viewport(r, (y0_top) ? VEGA_Y0_TOP : VEGA_Y0_BOTTOM);
382 * Set renderer blend state. Blending is disabled.
384 * This function modifies blend state.
386 static void renderer_set_blend(struct renderer *r,
387 VGbitfield channel_mask)
389 struct pipe_blend_state blend;
391 memset(&blend, 0, sizeof(blend));
393 blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE;
394 blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
395 blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
396 blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
398 if (channel_mask & VG_RED)
399 blend.rt[0].colormask |= PIPE_MASK_R;
400 if (channel_mask & VG_GREEN)
401 blend.rt[0].colormask |= PIPE_MASK_G;
402 if (channel_mask & VG_BLUE)
403 blend.rt[0].colormask |= PIPE_MASK_B;
404 if (channel_mask & VG_ALPHA)
405 blend.rt[0].colormask |= PIPE_MASK_A;
407 cso_set_blend(r->cso, &blend);
411 * Set renderer sampler and view states.
413 * This function modifies samplers and fragment_sampler_views states.
415 static void renderer_set_samplers(struct renderer *r,
416 uint num_views,
417 struct pipe_sampler_view **views)
419 struct pipe_sampler_state sampler;
420 unsigned tex_filter = PIPE_TEX_FILTER_NEAREST;
421 unsigned tex_wrap = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
422 uint i;
424 memset(&sampler, 0, sizeof(sampler));
426 sampler.min_img_filter = tex_filter;
427 sampler.mag_img_filter = tex_filter;
428 sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
430 sampler.wrap_s = tex_wrap;
431 sampler.wrap_t = tex_wrap;
432 sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
434 sampler.normalized_coords = 1;
436 /* set samplers */
437 for (i = 0; i < num_views; i++)
438 cso_single_sampler(r->cso, i, &sampler);
439 cso_single_sampler_done(r->cso);
441 /* set views */
442 cso_set_fragment_sampler_views(r->cso, num_views, views);
446 * Set custom renderer fragment shader, and optionally set samplers and views
447 * and upload the fragment constant buffer.
449 * This function modifies fragment_shader, samplers and fragment_sampler_views
450 * states.
452 static void renderer_set_custom_fs(struct renderer *renderer,
453 void *fs,
454 const struct pipe_sampler_state **samplers,
455 struct pipe_sampler_view **views,
456 VGint num_samplers,
457 const void *const_buffer,
458 VGint const_buffer_len)
460 cso_set_fragment_shader_handle(renderer->cso, fs);
462 /* set samplers and views */
463 if (num_samplers) {
464 cso_set_samplers(renderer->cso, num_samplers, samplers);
465 cso_set_fragment_sampler_views(renderer->cso, num_samplers, views);
468 /* upload fs constant buffer */
469 if (const_buffer_len) {
470 struct pipe_resource *cbuf = renderer->fs_cbuf;
472 if (!cbuf || renderer->fs_cbuf_len != const_buffer_len ||
473 memcmp(renderer->fs_cbuf_data, const_buffer, const_buffer_len)) {
474 pipe_resource_reference(&cbuf, NULL);
476 cbuf = pipe_buffer_create(renderer->pipe->screen,
477 PIPE_BIND_CONSTANT_BUFFER, PIPE_USAGE_STATIC,
478 const_buffer_len);
479 pipe_buffer_write(renderer->pipe, cbuf, 0,
480 const_buffer_len, const_buffer);
481 renderer->pipe->set_constant_buffer(renderer->pipe,
482 PIPE_SHADER_FRAGMENT, 0, cbuf);
484 renderer->fs_cbuf = cbuf;
485 if (const_buffer_len <= sizeof(renderer->fs_cbuf_data)) {
486 memcpy(renderer->fs_cbuf_data, const_buffer, const_buffer_len);
487 renderer->fs_cbuf_len = const_buffer_len;
489 else {
490 renderer->fs_cbuf_len = 0;
497 * Setup renderer quad position.
499 static void renderer_quad_pos(struct renderer *r,
500 VGfloat x0, VGfloat y0,
501 VGfloat x1, VGfloat y1,
502 VGboolean scissor)
504 VGfloat z;
506 /* the depth test is used for scissoring */
507 z = (scissor) ? 0.0f : 1.0f;
509 /* positions */
510 r->vertices[0][0][0] = x0;
511 r->vertices[0][0][1] = y0;
512 r->vertices[0][0][2] = z;
514 r->vertices[1][0][0] = x1;
515 r->vertices[1][0][1] = y0;
516 r->vertices[1][0][2] = z;
518 r->vertices[2][0][0] = x1;
519 r->vertices[2][0][1] = y1;
520 r->vertices[2][0][2] = z;
522 r->vertices[3][0][0] = x0;
523 r->vertices[3][0][1] = y1;
524 r->vertices[3][0][2] = z;
528 * Setup renderer quad texture coordinates.
530 static void renderer_quad_texcoord(struct renderer *r,
531 VGfloat x0, VGfloat y0,
532 VGfloat x1, VGfloat y1,
533 VGint tex_width, VGint tex_height)
535 VGfloat s0, t0, s1, t1, r0, q0;
536 VGint i;
538 s0 = x0 / tex_width;
539 s1 = x1 / tex_width;
540 t0 = y0 / tex_height;
541 t1 = y1 / tex_height;
542 r0 = 0.0f;
543 q0 = 1.0f;
545 /* texcoords */
546 r->vertices[0][1][0] = s0;
547 r->vertices[0][1][1] = t0;
549 r->vertices[1][1][0] = s1;
550 r->vertices[1][1][1] = t0;
552 r->vertices[2][1][0] = s1;
553 r->vertices[2][1][1] = t1;
555 r->vertices[3][1][0] = s0;
556 r->vertices[3][1][1] = t1;
558 for (i = 0; i < 4; i++) {
559 r->vertices[i][1][2] = r0;
560 r->vertices[i][1][3] = q0;
565 * Draw renderer quad.
567 static void renderer_quad_draw(struct renderer *r)
569 struct pipe_resource *buf;
571 buf = pipe_user_buffer_create(r->pipe->screen,
572 r->vertices,
573 sizeof(r->vertices),
574 PIPE_BIND_VERTEX_BUFFER);
575 if (buf) {
576 util_draw_vertex_buffer(r->pipe, r->cso, buf, 0,
577 PIPE_PRIM_TRIANGLE_FAN,
578 Elements(r->vertices), /* verts */
579 Elements(r->vertices[0])); /* attribs/vert */
581 pipe_resource_reference(&buf, NULL);
586 * Prepare the renderer for copying.
588 VGboolean renderer_copy_begin(struct renderer *renderer,
589 struct pipe_surface *dst,
590 VGboolean y0_top,
591 struct pipe_sampler_view *src)
593 assert(renderer->state == RENDERER_STATE_INIT);
595 /* sanity check */
596 if (!renderer_can_support(renderer,
597 dst->texture, PIPE_BIND_RENDER_TARGET) ||
598 !renderer_can_support(renderer,
599 src->texture, PIPE_BIND_SAMPLER_VIEW))
600 return VG_FALSE;
602 cso_save_framebuffer(renderer->cso);
603 cso_save_viewport(renderer->cso);
604 cso_save_blend(renderer->cso);
605 cso_save_samplers(renderer->cso);
606 cso_save_fragment_sampler_views(renderer->cso);
607 cso_save_fragment_shader(renderer->cso);
608 cso_save_vertex_shader(renderer->cso);
610 renderer_set_target(renderer, dst, NULL, y0_top);
612 renderer_set_blend(renderer, ~0);
613 renderer_set_samplers(renderer, 1, &src);
615 renderer_set_fs(renderer, RENDERER_FS_TEXTURE);
616 renderer_set_vs(renderer, RENDERER_VS_TEXTURE);
618 renderer_set_mvp(renderer, NULL);
620 /* remember the texture size */
621 renderer->u.copy.tex_width = src->texture->width0;
622 renderer->u.copy.tex_height = src->texture->height0;
623 renderer->state = RENDERER_STATE_COPY;
625 return VG_TRUE;
629 * Draw into the destination rectangle given by (x, y, w, h). The texture is
630 * sampled from within the rectangle given by (sx, sy, sw, sh).
632 * The coordinates are in surface coordinates.
634 void renderer_copy(struct renderer *renderer,
635 VGint x, VGint y, VGint w, VGint h,
636 VGint sx, VGint sy, VGint sw, VGint sh)
638 assert(renderer->state == RENDERER_STATE_COPY);
640 /* there is no depth buffer for scissoring anyway */
641 renderer_quad_pos(renderer, x, y, x + w, y + h, VG_FALSE);
642 renderer_quad_texcoord(renderer, sx, sy, sx + sw, sy + sh,
643 renderer->u.copy.tex_width,
644 renderer->u.copy.tex_height);
646 renderer_quad_draw(renderer);
650 * End copying and restore the states.
652 void renderer_copy_end(struct renderer *renderer)
654 assert(renderer->state == RENDERER_STATE_COPY);
656 cso_restore_framebuffer(renderer->cso);
657 cso_restore_viewport(renderer->cso);
658 cso_restore_blend(renderer->cso);
659 cso_restore_samplers(renderer->cso);
660 cso_restore_fragment_sampler_views(renderer->cso);
661 cso_restore_fragment_shader(renderer->cso);
662 cso_restore_vertex_shader(renderer->cso);
664 renderer->state = RENDERER_STATE_INIT;
668 * Prepare the renderer for textured drawing.
670 VGboolean renderer_drawtex_begin(struct renderer *renderer,
671 struct pipe_sampler_view *src)
673 assert(renderer->state == RENDERER_STATE_INIT);
675 if (!renderer_can_support(renderer, src->texture, PIPE_BIND_SAMPLER_VIEW))
676 return VG_FALSE;
678 cso_save_blend(renderer->cso);
679 cso_save_samplers(renderer->cso);
680 cso_save_fragment_sampler_views(renderer->cso);
681 cso_save_fragment_shader(renderer->cso);
682 cso_save_vertex_shader(renderer->cso);
684 renderer_set_blend(renderer, ~0);
686 renderer_set_samplers(renderer, 1, &src);
688 renderer_set_fs(renderer, RENDERER_FS_TEXTURE);
689 renderer_set_vs(renderer, RENDERER_VS_TEXTURE);
691 renderer_set_mvp(renderer, NULL);
693 /* remember the texture size */
694 renderer->u.drawtex.tex_width = src->texture->width0;
695 renderer->u.drawtex.tex_height = src->texture->height0;
696 renderer->state = RENDERER_STATE_DRAWTEX;
698 return VG_TRUE;
702 * Draw into the destination rectangle given by (x, y, w, h). The texture is
703 * sampled from within the rectangle given by (sx, sy, sw, sh).
705 * The coordinates are in surface coordinates.
707 void renderer_drawtex(struct renderer *renderer,
708 VGint x, VGint y, VGint w, VGint h,
709 VGint sx, VGint sy, VGint sw, VGint sh)
711 assert(renderer->state == RENDERER_STATE_DRAWTEX);
713 /* with scissoring */
714 renderer_quad_pos(renderer, x, y, x + w, y + h, VG_TRUE);
715 renderer_quad_texcoord(renderer, sx, sy, sx + sw, sy + sh,
716 renderer->u.drawtex.tex_width,
717 renderer->u.drawtex.tex_height);
719 renderer_quad_draw(renderer);
723 * End textured drawing and restore the states.
725 void renderer_drawtex_end(struct renderer *renderer)
727 assert(renderer->state == RENDERER_STATE_DRAWTEX);
729 cso_restore_blend(renderer->cso);
730 cso_restore_samplers(renderer->cso);
731 cso_restore_fragment_sampler_views(renderer->cso);
732 cso_restore_fragment_shader(renderer->cso);
733 cso_restore_vertex_shader(renderer->cso);
735 renderer->state = RENDERER_STATE_INIT;
739 * Prepare the renderer for scissor update. This will reset the depth buffer
740 * to 1.0f.
742 VGboolean renderer_scissor_begin(struct renderer *renderer,
743 VGboolean restore_dsa)
745 struct pipe_depth_stencil_alpha_state dsa;
747 assert(renderer->state == RENDERER_STATE_INIT);
749 if (restore_dsa)
750 cso_save_depth_stencil_alpha(renderer->cso);
751 cso_save_blend(renderer->cso);
752 cso_save_fragment_shader(renderer->cso);
754 /* enable depth writes */
755 memset(&dsa, 0, sizeof(dsa));
756 dsa.depth.enabled = 1;
757 dsa.depth.writemask = 1;
758 dsa.depth.func = PIPE_FUNC_ALWAYS;
759 cso_set_depth_stencil_alpha(renderer->cso, &dsa);
761 /* disable color writes */
762 renderer_set_blend(renderer, 0);
763 renderer_set_fs(renderer, RENDERER_FS_SCISSOR);
765 renderer_set_mvp(renderer, NULL);
767 renderer->u.scissor.restore_dsa = restore_dsa;
768 renderer->state = RENDERER_STATE_SCISSOR;
770 /* clear the depth buffer to 1.0f */
771 renderer->pipe->clear(renderer->pipe,
772 PIPE_CLEAR_DEPTHSTENCIL, NULL, 1.0f, 0);
774 return VG_TRUE;
778 * Add a scissor rectangle. Depth values inside the rectangle will be set to
779 * 0.0f.
781 void renderer_scissor(struct renderer *renderer,
782 VGint x, VGint y, VGint width, VGint height)
784 assert(renderer->state == RENDERER_STATE_SCISSOR);
786 renderer_quad_pos(renderer, x, y, x + width, y + height, VG_FALSE);
787 renderer_quad_draw(renderer);
791 * End scissor update and restore the states.
793 void renderer_scissor_end(struct renderer *renderer)
795 assert(renderer->state == RENDERER_STATE_SCISSOR);
797 if (renderer->u.scissor.restore_dsa)
798 cso_restore_depth_stencil_alpha(renderer->cso);
799 cso_restore_blend(renderer->cso);
800 cso_restore_fragment_shader(renderer->cso);
802 renderer->state = RENDERER_STATE_INIT;
806 * Prepare the renderer for clearing.
808 VGboolean renderer_clear_begin(struct renderer *renderer)
810 assert(renderer->state == RENDERER_STATE_INIT);
812 cso_save_blend(renderer->cso);
813 cso_save_fragment_shader(renderer->cso);
814 cso_save_vertex_shader(renderer->cso);
816 renderer_set_blend(renderer, ~0);
817 renderer_set_fs(renderer, RENDERER_FS_COLOR);
818 renderer_set_vs(renderer, RENDERER_VS_COLOR);
820 renderer_set_mvp(renderer, NULL);
822 renderer->state = RENDERER_STATE_CLEAR;
824 return VG_TRUE;
828 * Clear the framebuffer with the specified region and color.
830 * The coordinates are in surface coordinates.
832 void renderer_clear(struct renderer *renderer,
833 VGint x, VGint y, VGint width, VGint height,
834 const VGfloat color[4])
836 VGuint i;
838 assert(renderer->state == RENDERER_STATE_CLEAR);
840 renderer_quad_pos(renderer, x, y, x + width, y + height, VG_TRUE);
841 for (i = 0; i < 4; i++)
842 memcpy(renderer->vertices[i][1], color, sizeof(VGfloat) * 4);
844 renderer_quad_draw(renderer);
848 * End clearing and retore the states.
850 void renderer_clear_end(struct renderer *renderer)
852 assert(renderer->state == RENDERER_STATE_CLEAR);
854 cso_restore_blend(renderer->cso);
855 cso_restore_fragment_shader(renderer->cso);
856 cso_restore_vertex_shader(renderer->cso);
858 renderer->state = RENDERER_STATE_INIT;
862 * Prepare the renderer for image filtering.
864 VGboolean renderer_filter_begin(struct renderer *renderer,
865 struct pipe_resource *dst,
866 VGboolean y0_top,
867 VGbitfield channel_mask,
868 const struct pipe_sampler_state **samplers,
869 struct pipe_sampler_view **views,
870 VGint num_samplers,
871 void *fs,
872 const void *const_buffer,
873 VGint const_buffer_len)
875 struct pipe_surface *surf, surf_tmpl;
877 assert(renderer->state == RENDERER_STATE_INIT);
879 if (!fs)
880 return VG_FALSE;
881 if (!renderer_can_support(renderer, dst, PIPE_BIND_RENDER_TARGET))
882 return VG_FALSE;
884 u_surface_default_template(&surf_tmpl, dst,
885 PIPE_BIND_RENDER_TARGET);
886 surf = renderer->pipe->create_surface(renderer->pipe, dst, &surf_tmpl);
887 if (!surf)
888 return VG_FALSE;
890 cso_save_framebuffer(renderer->cso);
891 cso_save_viewport(renderer->cso);
892 cso_save_blend(renderer->cso);
894 /* set the image as the target */
895 renderer_set_target(renderer, surf, NULL, y0_top);
896 pipe_surface_reference(&surf, NULL);
898 renderer_set_blend(renderer, channel_mask);
900 if (num_samplers) {
901 struct pipe_resource *tex;
903 cso_save_samplers(renderer->cso);
904 cso_save_fragment_sampler_views(renderer->cso);
905 cso_save_fragment_shader(renderer->cso);
906 cso_save_vertex_shader(renderer->cso);
908 renderer_set_custom_fs(renderer, fs,
909 samplers, views, num_samplers,
910 const_buffer, const_buffer_len);
911 renderer_set_vs(renderer, RENDERER_VS_TEXTURE);
913 tex = views[0]->texture;
914 renderer->u.filter.tex_width = tex->width0;
915 renderer->u.filter.tex_height = tex->height0;
916 renderer->u.filter.use_sampler = VG_TRUE;
918 else {
919 cso_save_fragment_shader(renderer->cso);
921 renderer_set_custom_fs(renderer, fs, NULL, NULL, 0,
922 const_buffer, const_buffer_len);
924 renderer->u.filter.use_sampler = VG_FALSE;
927 renderer_set_mvp(renderer, NULL);
929 renderer->state = RENDERER_STATE_FILTER;
931 return VG_TRUE;
935 * Draw into a rectangle of the destination with the specified region of the
936 * texture(s).
938 * The coordinates are in surface coordinates.
940 void renderer_filter(struct renderer *renderer,
941 VGint x, VGint y, VGint w, VGint h,
942 VGint sx, VGint sy, VGint sw, VGint sh)
944 assert(renderer->state == RENDERER_STATE_FILTER);
946 renderer_quad_pos(renderer, x, y, x + w, y + h, VG_FALSE);
947 if (renderer->u.filter.use_sampler) {
948 renderer_quad_texcoord(renderer, sx, sy, sx + sw, sy + sh,
949 renderer->u.filter.tex_width,
950 renderer->u.filter.tex_height);
953 renderer_quad_draw(renderer);
957 * End image filtering and restore the states.
959 void renderer_filter_end(struct renderer *renderer)
961 assert(renderer->state == RENDERER_STATE_FILTER);
963 if (renderer->u.filter.use_sampler) {
964 cso_restore_samplers(renderer->cso);
965 cso_restore_fragment_sampler_views(renderer->cso);
966 cso_restore_vertex_shader(renderer->cso);
969 cso_restore_framebuffer(renderer->cso);
970 cso_restore_viewport(renderer->cso);
971 cso_restore_blend(renderer->cso);
972 cso_restore_fragment_shader(renderer->cso);
974 renderer->state = RENDERER_STATE_INIT;
978 * Prepare the renderer for polygon silhouette rendering.
980 VGboolean renderer_polygon_stencil_begin(struct renderer *renderer,
981 struct pipe_vertex_element *velem,
982 VGFillRule rule,
983 VGboolean restore_dsa)
985 struct pipe_depth_stencil_alpha_state *dsa;
986 VGboolean manual_two_sides;
988 assert(renderer->state == RENDERER_STATE_INIT);
990 cso_save_vertex_elements(renderer->cso);
991 cso_save_blend(renderer->cso);
992 cso_save_depth_stencil_alpha(renderer->cso);
994 cso_set_vertex_elements(renderer->cso, 1, velem);
996 /* disable color writes */
997 renderer_set_blend(renderer, 0);
999 manual_two_sides = VG_FALSE;
1000 dsa = &renderer->u.polygon_stencil.dsa;
1001 memset(dsa, 0, sizeof(*dsa));
1002 if (rule == VG_EVEN_ODD) {
1003 dsa->stencil[0].enabled = 1;
1004 dsa->stencil[0].writemask = 1;
1005 dsa->stencil[0].fail_op = PIPE_STENCIL_OP_KEEP;
1006 dsa->stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP;
1007 dsa->stencil[0].zpass_op = PIPE_STENCIL_OP_INVERT;
1008 dsa->stencil[0].func = PIPE_FUNC_ALWAYS;
1009 dsa->stencil[0].valuemask = ~0;
1011 else {
1012 assert(rule == VG_NON_ZERO);
1014 /* front face */
1015 dsa->stencil[0].enabled = 1;
1016 dsa->stencil[0].writemask = ~0;
1017 dsa->stencil[0].fail_op = PIPE_STENCIL_OP_KEEP;
1018 dsa->stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP;
1019 dsa->stencil[0].zpass_op = PIPE_STENCIL_OP_INCR_WRAP;
1020 dsa->stencil[0].func = PIPE_FUNC_ALWAYS;
1021 dsa->stencil[0].valuemask = ~0;
1023 if (renderer->pipe->screen->get_param(renderer->pipe->screen,
1024 PIPE_CAP_TWO_SIDED_STENCIL)) {
1025 /* back face */
1026 dsa->stencil[1] = dsa->stencil[0];
1027 dsa->stencil[1].zpass_op = PIPE_STENCIL_OP_DECR_WRAP;
1029 else {
1030 manual_two_sides = VG_TRUE;
1033 cso_set_depth_stencil_alpha(renderer->cso, dsa);
1035 if (manual_two_sides)
1036 cso_save_rasterizer(renderer->cso);
1038 renderer->u.polygon_stencil.manual_two_sides = manual_two_sides;
1039 renderer->u.polygon_stencil.restore_dsa = restore_dsa;
1040 renderer->state = RENDERER_STATE_POLYGON_STENCIL;
1042 return VG_TRUE;
1046 * Render a polygon silhouette to stencil buffer.
1048 void renderer_polygon_stencil(struct renderer *renderer,
1049 struct pipe_vertex_buffer *vbuf,
1050 VGuint mode, VGuint start, VGuint count)
1052 assert(renderer->state == RENDERER_STATE_POLYGON_STENCIL);
1054 cso_set_vertex_buffers(renderer->cso, 1, vbuf);
1056 if (!renderer->u.polygon_stencil.manual_two_sides) {
1057 util_draw_arrays(renderer->pipe, mode, start, count);
1059 else {
1060 struct pipe_rasterizer_state raster;
1061 struct pipe_depth_stencil_alpha_state dsa;
1063 raster = renderer->g3d.rasterizer;
1064 dsa = renderer->u.polygon_stencil.dsa;
1066 /* front */
1067 raster.cull_face = PIPE_FACE_BACK;
1068 dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_INCR_WRAP;
1070 cso_set_rasterizer(renderer->cso, &raster);
1071 cso_set_depth_stencil_alpha(renderer->cso, &dsa);
1072 util_draw_arrays(renderer->pipe, mode, start, count);
1074 /* back */
1075 raster.cull_face = PIPE_FACE_FRONT;
1076 dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_DECR_WRAP;
1078 cso_set_rasterizer(renderer->cso, &raster);
1079 cso_set_depth_stencil_alpha(renderer->cso, &dsa);
1080 util_draw_arrays(renderer->pipe, mode, start, count);
1085 * End polygon silhouette rendering.
1087 void renderer_polygon_stencil_end(struct renderer *renderer)
1089 assert(renderer->state == RENDERER_STATE_POLYGON_STENCIL);
1091 if (renderer->u.polygon_stencil.manual_two_sides)
1092 cso_restore_rasterizer(renderer->cso);
1094 cso_restore_vertex_elements(renderer->cso);
1096 /* restore color writes */
1097 cso_restore_blend(renderer->cso);
1099 if (renderer->u.polygon_stencil.restore_dsa)
1100 cso_restore_depth_stencil_alpha(renderer->cso);
1102 renderer->state = RENDERER_STATE_INIT;
1106 * Prepare the renderer for polygon filling.
1108 VGboolean renderer_polygon_fill_begin(struct renderer *renderer,
1109 VGboolean save_dsa)
1111 struct pipe_depth_stencil_alpha_state dsa;
1113 assert(renderer->state == RENDERER_STATE_INIT);
1115 if (save_dsa)
1116 cso_save_depth_stencil_alpha(renderer->cso);
1118 /* setup stencil ops */
1119 memset(&dsa, 0, sizeof(dsa));
1120 dsa.stencil[0].enabled = 1;
1121 dsa.stencil[0].func = PIPE_FUNC_NOTEQUAL;
1122 dsa.stencil[0].fail_op = PIPE_STENCIL_OP_REPLACE;
1123 dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_REPLACE;
1124 dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_REPLACE;
1125 dsa.stencil[0].valuemask = ~0;
1126 dsa.stencil[0].writemask = ~0;
1127 dsa.depth = renderer->g3d.dsa.depth;
1128 cso_set_depth_stencil_alpha(renderer->cso, &dsa);
1130 renderer->state = RENDERER_STATE_POLYGON_FILL;
1132 return VG_TRUE;
1136 * Fill a polygon.
1138 void renderer_polygon_fill(struct renderer *renderer,
1139 VGfloat min_x, VGfloat min_y,
1140 VGfloat max_x, VGfloat max_y)
1142 assert(renderer->state == RENDERER_STATE_POLYGON_FILL);
1144 renderer_quad_pos(renderer, min_x, min_y, max_x, max_y, VG_TRUE);
1145 renderer_quad_draw(renderer);
1149 * End polygon filling.
1151 void renderer_polygon_fill_end(struct renderer *renderer)
1153 assert(renderer->state == RENDERER_STATE_POLYGON_FILL);
1155 cso_restore_depth_stencil_alpha(renderer->cso);
1157 renderer->state = RENDERER_STATE_INIT;
1160 struct renderer * renderer_create(struct vg_context *owner)
1162 struct renderer *renderer;
1163 struct pipe_rasterizer_state *raster;
1164 struct pipe_stencil_ref sr;
1165 VGint i;
1167 renderer = CALLOC_STRUCT(renderer);
1168 if (!renderer)
1169 return NULL;
1171 renderer->pipe = owner->pipe;
1172 renderer->cso = owner->cso_context;
1174 /* init vertex data that doesn't change */
1175 for (i = 0; i < 4; i++)
1176 renderer->vertices[i][0][3] = 1.0f; /* w */
1178 for (i = 0; i < 2; i++) {
1179 renderer->velems[i].src_offset = i * 4 * sizeof(float);
1180 renderer->velems[i].instance_divisor = 0;
1181 renderer->velems[i].vertex_buffer_index = 0;
1182 renderer->velems[i].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
1184 cso_set_vertex_elements(renderer->cso, 2, renderer->velems);
1186 /* GL rasterization rules */
1187 raster = &renderer->g3d.rasterizer;
1188 memset(raster, 0, sizeof(*raster));
1189 raster->gl_rasterization_rules = 1;
1190 cso_set_rasterizer(renderer->cso, raster);
1192 /* fixed at 0 */
1193 memset(&sr, 0, sizeof(sr));
1194 cso_set_stencil_ref(renderer->cso, &sr);
1196 renderer_set_vs(renderer, RENDERER_VS_PLAIN);
1198 renderer->state = RENDERER_STATE_INIT;
1200 return renderer;
1203 void renderer_destroy(struct renderer *ctx)
1205 int i;
1207 for (i = 0; i < NUM_RENDERER_VS; i++) {
1208 if (ctx->cached_vs[i])
1209 cso_delete_vertex_shader(ctx->cso, ctx->cached_vs[i]);
1211 for (i = 0; i < NUM_RENDERER_FS; i++) {
1212 if (ctx->cached_fs[i])
1213 cso_delete_fragment_shader(ctx->cso, ctx->cached_fs[i]);
1216 pipe_resource_reference(&ctx->vs_cbuf, NULL);
1217 pipe_resource_reference(&ctx->fs_cbuf, NULL);
1219 FREE(ctx);
1222 static void update_clip_state(struct renderer *renderer,
1223 const struct vg_state *state)
1225 struct pipe_depth_stencil_alpha_state *dsa = &renderer->g3d.dsa;
1227 memset(dsa, 0, sizeof(struct pipe_depth_stencil_alpha_state));
1229 if (state->scissoring) {
1230 struct pipe_framebuffer_state *fb = &renderer->g3d.fb;
1231 int i;
1233 renderer_scissor_begin(renderer, VG_FALSE);
1235 for (i = 0; i < state->scissor_rects_num; ++i) {
1236 const float x = state->scissor_rects[i * 4 + 0].f;
1237 const float y = state->scissor_rects[i * 4 + 1].f;
1238 const float width = state->scissor_rects[i * 4 + 2].f;
1239 const float height = state->scissor_rects[i * 4 + 3].f;
1240 VGint x0, y0, x1, y1, iw, ih;
1242 x0 = (VGint) x;
1243 y0 = (VGint) y;
1244 if (x0 < 0)
1245 x0 = 0;
1246 if (y0 < 0)
1247 y0 = 0;
1249 /* note that x1 and y1 are exclusive */
1250 x1 = (VGint) ceilf(x + width);
1251 y1 = (VGint) ceilf(y + height);
1252 if (x1 > fb->width)
1253 x1 = fb->width;
1254 if (y1 > fb->height)
1255 y1 = fb->height;
1257 iw = x1 - x0;
1258 ih = y1 - y0;
1259 if (iw > 0 && ih> 0 )
1260 renderer_scissor(renderer, x0, y0, iw, ih);
1263 renderer_scissor_end(renderer);
1265 dsa->depth.enabled = 1; /* glEnable(GL_DEPTH_TEST); */
1266 dsa->depth.writemask = 0;/*glDepthMask(FALSE);*/
1267 dsa->depth.func = PIPE_FUNC_GEQUAL;
1271 static void renderer_validate_blend(struct renderer *renderer,
1272 const struct vg_state *state,
1273 enum pipe_format fb_format)
1275 struct pipe_blend_state blend;
1277 memset(&blend, 0, sizeof(blend));
1278 blend.rt[0].colormask = PIPE_MASK_RGBA;
1279 blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE;
1280 blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
1281 blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
1282 blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
1284 /* TODO alpha masking happens after blending? */
1286 switch (state->blend_mode) {
1287 case VG_BLEND_SRC:
1288 blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE;
1289 blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
1290 blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
1291 blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
1292 break;
1293 case VG_BLEND_SRC_OVER:
1294 /* use the blend state only when there is no alpha channel */
1295 if (!util_format_has_alpha(fb_format)) {
1296 blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_SRC_ALPHA;
1297 blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
1298 blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_INV_SRC_ALPHA;
1299 blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_INV_SRC_ALPHA;
1300 blend.rt[0].blend_enable = 1;
1302 break;
1303 case VG_BLEND_SRC_IN:
1304 blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE;
1305 blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_DST_ALPHA;
1306 blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
1307 blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
1308 blend.rt[0].blend_enable = 1;
1309 break;
1310 case VG_BLEND_DST_IN:
1311 blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ZERO;
1312 blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ZERO;
1313 blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ONE;
1314 blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_SRC_ALPHA;
1315 blend.rt[0].blend_enable = 1;
1316 break;
1317 case VG_BLEND_DST_OVER:
1318 case VG_BLEND_MULTIPLY:
1319 case VG_BLEND_SCREEN:
1320 case VG_BLEND_DARKEN:
1321 case VG_BLEND_LIGHTEN:
1322 case VG_BLEND_ADDITIVE:
1323 /* need a shader */
1324 break;
1325 default:
1326 assert(!"not implemented blend mode");
1327 break;
1330 cso_set_blend(renderer->cso, &blend);
1334 * Propogate OpenVG state changes to the renderer. Only framebuffer, blending
1335 * and scissoring states are relevant here.
1337 void renderer_validate(struct renderer *renderer,
1338 VGbitfield dirty,
1339 const struct st_framebuffer *stfb,
1340 const struct vg_state *state)
1342 assert(renderer->state == RENDERER_STATE_INIT);
1344 dirty |= renderer->dirty;
1345 renderer->dirty = 0;
1347 if (dirty & FRAMEBUFFER_DIRTY) {
1348 struct pipe_framebuffer_state *fb = &renderer->g3d.fb;
1349 struct matrix *proj = &renderer->projection;
1351 memset(fb, 0, sizeof(struct pipe_framebuffer_state));
1352 fb->width = stfb->width;
1353 fb->height = stfb->height;
1354 fb->nr_cbufs = 1;
1355 fb->cbufs[0] = stfb->strb->surface;
1356 fb->zsbuf = stfb->dsrb->surface;
1358 cso_set_framebuffer(renderer->cso, fb);
1359 vg_set_viewport(renderer, VEGA_Y0_BOTTOM);
1361 matrix_load_identity(proj);
1362 matrix_translate(proj, -1.0f, -1.0f);
1363 matrix_scale(proj, 2.0f / fb->width, 2.0f / fb->height);
1365 /* we also got a new depth buffer */
1366 if (dirty & DEPTH_STENCIL_DIRTY) {
1367 renderer->pipe->clear(renderer->pipe,
1368 PIPE_CLEAR_DEPTHSTENCIL, NULL, 0.0, 0);
1372 /* must be last because it renders to the depth buffer*/
1373 if (dirty & DEPTH_STENCIL_DIRTY) {
1374 update_clip_state(renderer, state);
1375 cso_set_depth_stencil_alpha(renderer->cso, &renderer->g3d.dsa);
1378 if (dirty & BLEND_DIRTY)
1379 renderer_validate_blend(renderer, state, stfb->strb->format);
1383 * Prepare the renderer for OpenVG pipeline.
1385 void renderer_validate_for_shader(struct renderer *renderer,
1386 const struct pipe_sampler_state **samplers,
1387 struct pipe_sampler_view **views,
1388 VGint num_samplers,
1389 const struct matrix *modelview,
1390 void *fs,
1391 const void *const_buffer,
1392 VGint const_buffer_len)
1394 struct matrix mvp = renderer->projection;
1396 /* will be used in POLYGON_STENCIL and POLYGON_FILL */
1397 matrix_mult(&mvp, modelview);
1398 renderer_set_mvp(renderer, &mvp);
1400 renderer_set_custom_fs(renderer, fs,
1401 samplers, views, num_samplers,
1402 const_buffer, const_buffer_len);
1405 void renderer_validate_for_mask_rendering(struct renderer *renderer,
1406 struct pipe_surface *dst,
1407 const struct matrix *modelview)
1409 struct matrix mvp = renderer->projection;
1411 /* will be used in POLYGON_STENCIL and POLYGON_FILL */
1412 matrix_mult(&mvp, modelview);
1413 renderer_set_mvp(renderer, &mvp);
1415 renderer_set_target(renderer, dst, renderer->g3d.fb.zsbuf, VG_FALSE);
1416 renderer_set_blend(renderer, ~0);
1417 renderer_set_fs(renderer, RENDERER_FS_WHITE);
1419 /* set internal dirty flags (hacky!) */
1420 renderer->dirty = FRAMEBUFFER_DIRTY | BLEND_DIRTY;
1423 void renderer_copy_surface(struct renderer *ctx,
1424 struct pipe_surface *src,
1425 int srcX0, int srcY0,
1426 int srcX1, int srcY1,
1427 struct pipe_surface *dst,
1428 int dstX0, int dstY0,
1429 int dstX1, int dstY1,
1430 float z, unsigned filter)
1432 struct pipe_context *pipe = ctx->pipe;
1433 struct pipe_screen *screen = pipe->screen;
1434 struct pipe_sampler_view view_templ;
1435 struct pipe_sampler_view *view;
1436 struct pipe_box src_box;
1437 struct pipe_resource texTemp, *tex;
1438 const struct pipe_framebuffer_state *fb = &ctx->g3d.fb;
1439 const int srcW = abs(srcX1 - srcX0);
1440 const int srcH = abs(srcY1 - srcY0);
1441 const int srcLeft = MIN2(srcX0, srcX1);
1442 const int srcTop = MIN2(srcY0, srcY1);
1444 assert(filter == PIPE_TEX_MIPFILTER_NEAREST ||
1445 filter == PIPE_TEX_MIPFILTER_LINEAR);
1447 if (srcLeft != srcX0) {
1448 /* left-right flip */
1449 int tmp = dstX0;
1450 dstX0 = dstX1;
1451 dstX1 = tmp;
1454 if (srcTop != srcY0) {
1455 /* up-down flip */
1456 int tmp = dstY0;
1457 dstY0 = dstY1;
1458 dstY1 = tmp;
1461 assert(screen->is_format_supported(screen, src->format, PIPE_TEXTURE_2D,
1462 0, PIPE_BIND_SAMPLER_VIEW));
1463 assert(screen->is_format_supported(screen, dst->format, PIPE_TEXTURE_2D,
1464 0, PIPE_BIND_SAMPLER_VIEW));
1465 assert(screen->is_format_supported(screen, dst->format, PIPE_TEXTURE_2D,
1466 0, PIPE_BIND_RENDER_TARGET));
1469 * XXX for now we're always creating a temporary texture.
1470 * Strictly speaking that's not always needed.
1473 /* create temp texture */
1474 memset(&texTemp, 0, sizeof(texTemp));
1475 texTemp.target = PIPE_TEXTURE_2D;
1476 texTemp.format = src->format;
1477 texTemp.last_level = 0;
1478 texTemp.width0 = srcW;
1479 texTemp.height0 = srcH;
1480 texTemp.depth0 = 1;
1481 texTemp.array_size = 1;
1482 texTemp.bind = PIPE_BIND_SAMPLER_VIEW;
1484 tex = screen->resource_create(screen, &texTemp);
1485 if (!tex)
1486 return;
1488 u_sampler_view_default_template(&view_templ, tex, tex->format);
1489 view = pipe->create_sampler_view(pipe, tex, &view_templ);
1491 if (!view)
1492 return;
1494 u_box_2d_zslice(srcLeft, srcTop, src->u.tex.first_layer, srcW, srcH, &src_box);
1496 pipe->resource_copy_region(pipe,
1497 tex, 0, 0, 0, 0, /* dest */
1498 src->texture, 0, &src_box);
1500 assert(floatsEqual(z, 0.0f));
1502 /* draw */
1503 if (fb->cbufs[0] == dst) {
1504 /* transform back to surface coordinates */
1505 dstY0 = dst->height - dstY0;
1506 dstY1 = dst->height - dstY1;
1508 if (renderer_drawtex_begin(ctx, view)) {
1509 renderer_drawtex(ctx,
1510 dstX0, dstY0, dstX1 - dstX0, dstY1 - dstY0,
1511 0, 0, view->texture->width0, view->texture->height0);
1512 renderer_drawtex_end(ctx);
1515 else {
1516 if (renderer_copy_begin(ctx, dst, VG_TRUE, view)) {
1517 renderer_copy(ctx,
1518 dstX0, dstY0, dstX1 - dstX0, dstY1 - dstY0,
1519 0, 0, view->texture->width0, view->texture->height0);
1520 renderer_copy_end(ctx);
1525 void renderer_texture_quad(struct renderer *r,
1526 struct pipe_resource *tex,
1527 VGfloat x1offset, VGfloat y1offset,
1528 VGfloat x2offset, VGfloat y2offset,
1529 VGfloat x1, VGfloat y1,
1530 VGfloat x2, VGfloat y2,
1531 VGfloat x3, VGfloat y3,
1532 VGfloat x4, VGfloat y4)
1534 const VGfloat z = 0.0f;
1536 assert(r->state == RENDERER_STATE_INIT);
1537 assert(tex->width0 != 0);
1538 assert(tex->height0 != 0);
1540 cso_save_vertex_shader(r->cso);
1542 renderer_set_vs(r, RENDERER_VS_TEXTURE);
1544 /* manually set up positions */
1545 r->vertices[0][0][0] = x1;
1546 r->vertices[0][0][1] = y1;
1547 r->vertices[0][0][2] = z;
1549 r->vertices[1][0][0] = x2;
1550 r->vertices[1][0][1] = y2;
1551 r->vertices[1][0][2] = z;
1553 r->vertices[2][0][0] = x3;
1554 r->vertices[2][0][1] = y3;
1555 r->vertices[2][0][2] = z;
1557 r->vertices[3][0][0] = x4;
1558 r->vertices[3][0][1] = y4;
1559 r->vertices[3][0][2] = z;
1561 /* texcoords */
1562 renderer_quad_texcoord(r, x1offset, y1offset,
1563 x2offset, y2offset, tex->width0, tex->height0);
1565 renderer_quad_draw(r);
1567 cso_restore_vertex_shader(r->cso);