revert between 56095 -> 55830 in arch
[AROS.git] / workbench / libs / mesa / src / gallium / state_trackers / vega / renderer.c
blob5715073e2d961314551c982b1ca19f841bf44b50
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"
31 #include "paint.h" /* for paint_is_opaque */
33 #include "pipe/p_context.h"
34 #include "pipe/p_state.h"
35 #include "util/u_inlines.h"
36 #include "pipe/p_screen.h"
37 #include "pipe/p_shader_tokens.h"
39 #include "util/u_draw_quad.h"
40 #include "util/u_simple_shaders.h"
41 #include "util/u_memory.h"
42 #include "util/u_sampler.h"
43 #include "util/u_surface.h"
44 #include "util/u_math.h"
45 #include "util/u_format.h"
47 #include "cso_cache/cso_context.h"
48 #include "tgsi/tgsi_ureg.h"
50 typedef enum {
51 RENDERER_STATE_INIT,
52 RENDERER_STATE_COPY,
53 RENDERER_STATE_DRAWTEX,
54 RENDERER_STATE_SCISSOR,
55 RENDERER_STATE_CLEAR,
56 RENDERER_STATE_FILTER,
57 RENDERER_STATE_POLYGON_STENCIL,
58 RENDERER_STATE_POLYGON_FILL,
59 NUM_RENDERER_STATES
60 } RendererState;
62 typedef enum {
63 RENDERER_VS_PLAIN,
64 RENDERER_VS_COLOR,
65 RENDERER_VS_TEXTURE,
66 NUM_RENDERER_VS
67 } RendererVs;
69 typedef enum {
70 RENDERER_FS_COLOR,
71 RENDERER_FS_TEXTURE,
72 RENDERER_FS_SCISSOR,
73 RENDERER_FS_WHITE,
74 NUM_RENDERER_FS
75 } RendererFs;
77 struct renderer {
78 struct pipe_context *pipe;
79 struct cso_context *cso;
81 VGbitfield dirty;
82 struct {
83 struct pipe_rasterizer_state rasterizer;
84 struct pipe_depth_stencil_alpha_state dsa;
85 struct pipe_framebuffer_state fb;
86 } g3d;
87 struct matrix projection;
89 struct matrix mvp;
90 struct pipe_resource *vs_cbuf;
92 struct pipe_resource *fs_cbuf;
93 VGfloat fs_cbuf_data[32];
94 VGint fs_cbuf_len;
96 struct pipe_vertex_element velems[2];
97 VGfloat vertices[4][2][4];
99 void *cached_vs[NUM_RENDERER_VS];
100 void *cached_fs[NUM_RENDERER_FS];
102 RendererState state;
104 /* state data */
105 union {
106 struct {
107 VGint tex_width;
108 VGint tex_height;
109 } copy;
111 struct {
112 VGint tex_width;
113 VGint tex_height;
114 } drawtex;
116 struct {
117 VGboolean restore_dsa;
118 } scissor;
120 struct {
121 VGboolean use_sampler;
122 VGint tex_width, tex_height;
123 } filter;
125 struct {
126 struct pipe_depth_stencil_alpha_state dsa;
127 VGboolean manual_two_sides;
128 VGboolean restore_dsa;
129 } polygon_stencil;
130 } u;
134 * Return VG_TRUE if the renderer can use the resource as the asked bindings.
136 static VGboolean renderer_can_support(struct renderer *renderer,
137 struct pipe_resource *res,
138 unsigned bindings)
140 struct pipe_screen *screen = renderer->pipe->screen;
142 return screen->is_format_supported(screen,
143 res->format, res->target, 0, bindings);
147 * Set the model-view-projection matrix used by vertex shaders.
149 static void renderer_set_mvp(struct renderer *renderer,
150 const struct matrix *mvp)
152 struct matrix *cur = &renderer->mvp;
153 struct pipe_resource *cbuf;
154 VGfloat consts[3][4];
155 VGint i;
157 /* projection only */
158 if (!mvp)
159 mvp = &renderer->projection;
161 /* re-upload only if necessary */
162 if (memcmp(cur, mvp, sizeof(*mvp)) == 0)
163 return;
165 /* 3x3 matrix to 3 constant vectors (no Z) */
166 for (i = 0; i < 3; i++) {
167 consts[i][0] = mvp->m[i + 0];
168 consts[i][1] = mvp->m[i + 3];
169 consts[i][2] = 0.0f;
170 consts[i][3] = mvp->m[i + 6];
173 cbuf = renderer->vs_cbuf;
174 pipe_resource_reference(&cbuf, NULL);
175 cbuf = pipe_buffer_create(renderer->pipe->screen,
176 PIPE_BIND_CONSTANT_BUFFER,
177 PIPE_USAGE_STATIC,
178 sizeof(consts));
179 if (cbuf) {
180 pipe_buffer_write(renderer->pipe, cbuf,
181 0, sizeof(consts), consts);
183 renderer->pipe->set_constant_buffer(renderer->pipe,
184 PIPE_SHADER_VERTEX, 0, cbuf);
186 memcpy(cur, mvp, sizeof(*mvp));
187 renderer->vs_cbuf = cbuf;
191 * Create a simple vertex shader that passes through position and the given
192 * attribute.
194 static void *create_passthrough_vs(struct pipe_context *pipe, int semantic_name)
196 struct ureg_program *ureg;
197 struct ureg_src src[2], constants[3];
198 struct ureg_dst dst[2], tmp;
199 int i;
201 ureg = ureg_create(TGSI_PROCESSOR_VERTEX);
202 if (!ureg)
203 return NULL;
205 /* position is in user coordinates */
206 src[0] = ureg_DECL_vs_input(ureg, 0);
207 dst[0] = ureg_DECL_output(ureg, TGSI_SEMANTIC_POSITION, 0);
208 tmp = ureg_DECL_temporary(ureg);
209 for (i = 0; i < Elements(constants); i++)
210 constants[i] = ureg_DECL_constant(ureg, i);
212 /* transform to clipped coordinates */
213 ureg_DP4(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_X), src[0], constants[0]);
214 ureg_DP4(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_Y), src[0], constants[1]);
215 ureg_MOV(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_Z), src[0]);
216 ureg_DP4(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_W), src[0], constants[2]);
217 ureg_MOV(ureg, dst[0], ureg_src(tmp));
219 if (semantic_name >= 0) {
220 src[1] = ureg_DECL_vs_input(ureg, 1);
221 dst[1] = ureg_DECL_output(ureg, semantic_name, 0);
222 ureg_MOV(ureg, dst[1], src[1]);
225 ureg_END(ureg);
227 return ureg_create_shader_and_destroy(ureg, pipe);
231 * Set renderer vertex shader.
233 * This function modifies vertex_shader state.
235 static void renderer_set_vs(struct renderer *r, RendererVs id)
237 /* create as needed */
238 if (!r->cached_vs[id]) {
239 int semantic_name = -1;
241 switch (id) {
242 case RENDERER_VS_PLAIN:
243 break;
244 case RENDERER_VS_COLOR:
245 semantic_name = TGSI_SEMANTIC_COLOR;
246 break;
247 case RENDERER_VS_TEXTURE:
248 semantic_name = TGSI_SEMANTIC_GENERIC;
249 break;
250 default:
251 assert(!"Unknown renderer vs id");
252 break;
255 r->cached_vs[id] = create_passthrough_vs(r->pipe, semantic_name);
258 cso_set_vertex_shader_handle(r->cso, r->cached_vs[id]);
262 * Create a simple fragment shader that sets the depth to 0.0f.
264 static void *create_scissor_fs(struct pipe_context *pipe)
266 struct ureg_program *ureg;
267 struct ureg_dst out;
268 struct ureg_src imm;
270 ureg = ureg_create(TGSI_PROCESSOR_FRAGMENT);
271 out = ureg_DECL_output(ureg, TGSI_SEMANTIC_POSITION, 0);
272 imm = ureg_imm4f(ureg, 0.0f, 0.0f, 0.0f, 0.0f);
274 ureg_MOV(ureg, ureg_writemask(out, TGSI_WRITEMASK_Z), imm);
275 ureg_END(ureg);
277 return ureg_create_shader_and_destroy(ureg, pipe);
281 * Create a simple fragment shader that sets the color to white.
283 static void *create_white_fs(struct pipe_context *pipe)
285 struct ureg_program *ureg;
286 struct ureg_dst out;
287 struct ureg_src imm;
289 ureg = ureg_create(TGSI_PROCESSOR_FRAGMENT);
290 out = ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 0);
291 imm = ureg_imm4f(ureg, 1.0f, 1.0f, 1.0f, 1.0f);
293 ureg_MOV(ureg, out, imm);
294 ureg_END(ureg);
296 return ureg_create_shader_and_destroy(ureg, pipe);
300 * Set renderer fragment shader.
302 * This function modifies fragment_shader state.
304 static void renderer_set_fs(struct renderer *r, RendererFs id)
306 /* create as needed */
307 if (!r->cached_fs[id]) {
308 void *fs = NULL;
310 switch (id) {
311 case RENDERER_FS_COLOR:
312 fs = util_make_fragment_passthrough_shader(r->pipe);
313 break;
314 case RENDERER_FS_TEXTURE:
315 fs = util_make_fragment_tex_shader(r->pipe,
316 TGSI_TEXTURE_2D, TGSI_INTERPOLATE_LINEAR);
317 break;
318 case RENDERER_FS_SCISSOR:
319 fs = create_scissor_fs(r->pipe);
320 break;
321 case RENDERER_FS_WHITE:
322 fs = create_white_fs(r->pipe);
323 break;
324 default:
325 assert(!"Unknown renderer fs id");
326 break;
329 r->cached_fs[id] = fs;
332 cso_set_fragment_shader_handle(r->cso, r->cached_fs[id]);
335 typedef enum {
336 VEGA_Y0_TOP,
337 VEGA_Y0_BOTTOM
338 } VegaOrientation;
340 static void vg_set_viewport(struct renderer *r,
341 VegaOrientation orientation)
343 const struct pipe_framebuffer_state *fb = &r->g3d.fb;
344 struct pipe_viewport_state viewport;
345 VGfloat y_scale = (orientation == VEGA_Y0_BOTTOM) ? -2.f : 2.f;
347 viewport.scale[0] = fb->width / 2.f;
348 viewport.scale[1] = fb->height / y_scale;
349 viewport.scale[2] = 1.0;
350 viewport.scale[3] = 1.0;
351 viewport.translate[0] = fb->width / 2.f;
352 viewport.translate[1] = fb->height / 2.f;
353 viewport.translate[2] = 0.0;
354 viewport.translate[3] = 0.0;
356 cso_set_viewport(r->cso, &viewport);
360 * Set renderer target.
362 * This function modifies framebuffer and viewport states.
364 static void renderer_set_target(struct renderer *r,
365 struct pipe_surface *cbuf,
366 struct pipe_surface *zsbuf,
367 VGboolean y0_top)
369 struct pipe_framebuffer_state fb;
371 memset(&fb, 0, sizeof(fb));
372 fb.width = cbuf->width;
373 fb.height = cbuf->height;
374 fb.cbufs[0] = cbuf;
375 fb.nr_cbufs = 1;
376 fb.zsbuf = zsbuf;
377 cso_set_framebuffer(r->cso, &fb);
379 vg_set_viewport(r, (y0_top) ? VEGA_Y0_TOP : VEGA_Y0_BOTTOM);
383 * Set renderer blend state. Blending is disabled.
385 * This function modifies blend state.
387 static void renderer_set_blend(struct renderer *r,
388 VGbitfield channel_mask)
390 struct pipe_blend_state blend;
392 memset(&blend, 0, sizeof(blend));
394 blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE;
395 blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
396 blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
397 blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
399 if (channel_mask & VG_RED)
400 blend.rt[0].colormask |= PIPE_MASK_R;
401 if (channel_mask & VG_GREEN)
402 blend.rt[0].colormask |= PIPE_MASK_G;
403 if (channel_mask & VG_BLUE)
404 blend.rt[0].colormask |= PIPE_MASK_B;
405 if (channel_mask & VG_ALPHA)
406 blend.rt[0].colormask |= PIPE_MASK_A;
408 cso_set_blend(r->cso, &blend);
412 * Set renderer sampler and view states.
414 * This function modifies samplers and fragment_sampler_views states.
416 static void renderer_set_samplers(struct renderer *r,
417 uint num_views,
418 struct pipe_sampler_view **views)
420 struct pipe_sampler_state sampler;
421 unsigned tex_filter = PIPE_TEX_FILTER_NEAREST;
422 unsigned tex_wrap = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
423 uint i;
425 memset(&sampler, 0, sizeof(sampler));
427 sampler.min_img_filter = tex_filter;
428 sampler.mag_img_filter = tex_filter;
429 sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
431 sampler.wrap_s = tex_wrap;
432 sampler.wrap_t = tex_wrap;
433 sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
435 sampler.normalized_coords = 1;
437 /* set samplers */
438 for (i = 0; i < num_views; i++)
439 cso_single_sampler(r->cso, i, &sampler);
440 cso_single_sampler_done(r->cso);
442 /* set views */
443 cso_set_fragment_sampler_views(r->cso, num_views, views);
447 * Set custom renderer fragment shader, and optionally set samplers and views
448 * and upload the fragment constant buffer.
450 * This function modifies fragment_shader, samplers and fragment_sampler_views
451 * states.
453 static void renderer_set_custom_fs(struct renderer *renderer,
454 void *fs,
455 const struct pipe_sampler_state **samplers,
456 struct pipe_sampler_view **views,
457 VGint num_samplers,
458 const void *const_buffer,
459 VGint const_buffer_len)
461 cso_set_fragment_shader_handle(renderer->cso, fs);
463 /* set samplers and views */
464 if (num_samplers) {
465 cso_set_samplers(renderer->cso, num_samplers, samplers);
466 cso_set_fragment_sampler_views(renderer->cso, num_samplers, views);
469 /* upload fs constant buffer */
470 if (const_buffer_len) {
471 struct pipe_resource *cbuf = renderer->fs_cbuf;
473 if (!cbuf || renderer->fs_cbuf_len != const_buffer_len ||
474 memcmp(renderer->fs_cbuf_data, const_buffer, const_buffer_len)) {
475 pipe_resource_reference(&cbuf, NULL);
477 cbuf = pipe_buffer_create(renderer->pipe->screen,
478 PIPE_BIND_CONSTANT_BUFFER, PIPE_USAGE_STATIC,
479 const_buffer_len);
480 pipe_buffer_write(renderer->pipe, cbuf, 0,
481 const_buffer_len, const_buffer);
482 renderer->pipe->set_constant_buffer(renderer->pipe,
483 PIPE_SHADER_FRAGMENT, 0, cbuf);
485 renderer->fs_cbuf = cbuf;
486 if (const_buffer_len <= sizeof(renderer->fs_cbuf_data)) {
487 memcpy(renderer->fs_cbuf_data, const_buffer, const_buffer_len);
488 renderer->fs_cbuf_len = const_buffer_len;
490 else {
491 renderer->fs_cbuf_len = 0;
498 * Setup renderer quad position.
500 static void renderer_quad_pos(struct renderer *r,
501 VGfloat x0, VGfloat y0,
502 VGfloat x1, VGfloat y1,
503 VGboolean scissor)
505 VGfloat z;
507 /* the depth test is used for scissoring */
508 z = (scissor) ? 0.0f : 1.0f;
510 /* positions */
511 r->vertices[0][0][0] = x0;
512 r->vertices[0][0][1] = y0;
513 r->vertices[0][0][2] = z;
515 r->vertices[1][0][0] = x1;
516 r->vertices[1][0][1] = y0;
517 r->vertices[1][0][2] = z;
519 r->vertices[2][0][0] = x1;
520 r->vertices[2][0][1] = y1;
521 r->vertices[2][0][2] = z;
523 r->vertices[3][0][0] = x0;
524 r->vertices[3][0][1] = y1;
525 r->vertices[3][0][2] = z;
529 * Setup renderer quad texture coordinates.
531 static void renderer_quad_texcoord(struct renderer *r,
532 VGfloat x0, VGfloat y0,
533 VGfloat x1, VGfloat y1,
534 VGint tex_width, VGint tex_height)
536 VGfloat s0, t0, s1, t1, r0, q0;
537 VGint i;
539 s0 = x0 / tex_width;
540 s1 = x1 / tex_width;
541 t0 = y0 / tex_height;
542 t1 = y1 / tex_height;
543 r0 = 0.0f;
544 q0 = 1.0f;
546 /* texcoords */
547 r->vertices[0][1][0] = s0;
548 r->vertices[0][1][1] = t0;
550 r->vertices[1][1][0] = s1;
551 r->vertices[1][1][1] = t0;
553 r->vertices[2][1][0] = s1;
554 r->vertices[2][1][1] = t1;
556 r->vertices[3][1][0] = s0;
557 r->vertices[3][1][1] = t1;
559 for (i = 0; i < 4; i++) {
560 r->vertices[i][1][2] = r0;
561 r->vertices[i][1][3] = q0;
566 * Draw renderer quad.
568 static void renderer_quad_draw(struct renderer *r)
570 struct pipe_resource *buf;
572 buf = pipe_user_buffer_create(r->pipe->screen,
573 r->vertices,
574 sizeof(r->vertices),
575 PIPE_BIND_VERTEX_BUFFER);
576 if (buf) {
577 util_draw_vertex_buffer(r->pipe, r->cso, buf, 0,
578 PIPE_PRIM_TRIANGLE_FAN,
579 Elements(r->vertices), /* verts */
580 Elements(r->vertices[0])); /* attribs/vert */
582 pipe_resource_reference(&buf, NULL);
587 * Prepare the renderer for copying.
589 VGboolean renderer_copy_begin(struct renderer *renderer,
590 struct pipe_surface *dst,
591 VGboolean y0_top,
592 struct pipe_sampler_view *src)
594 assert(renderer->state == RENDERER_STATE_INIT);
596 /* sanity check */
597 if (!renderer_can_support(renderer,
598 dst->texture, PIPE_BIND_RENDER_TARGET) ||
599 !renderer_can_support(renderer,
600 src->texture, PIPE_BIND_SAMPLER_VIEW))
601 return VG_FALSE;
603 cso_save_framebuffer(renderer->cso);
604 cso_save_viewport(renderer->cso);
605 cso_save_blend(renderer->cso);
606 cso_save_samplers(renderer->cso);
607 cso_save_fragment_sampler_views(renderer->cso);
608 cso_save_fragment_shader(renderer->cso);
609 cso_save_vertex_shader(renderer->cso);
611 renderer_set_target(renderer, dst, NULL, y0_top);
613 renderer_set_blend(renderer, ~0);
614 renderer_set_samplers(renderer, 1, &src);
616 renderer_set_fs(renderer, RENDERER_FS_TEXTURE);
617 renderer_set_vs(renderer, RENDERER_VS_TEXTURE);
619 renderer_set_mvp(renderer, NULL);
621 /* remember the texture size */
622 renderer->u.copy.tex_width = src->texture->width0;
623 renderer->u.copy.tex_height = src->texture->height0;
624 renderer->state = RENDERER_STATE_COPY;
626 return VG_TRUE;
630 * Draw into the destination rectangle given by (x, y, w, h). The texture is
631 * sampled from within the rectangle given by (sx, sy, sw, sh).
633 * The coordinates are in surface coordinates.
635 void renderer_copy(struct renderer *renderer,
636 VGint x, VGint y, VGint w, VGint h,
637 VGint sx, VGint sy, VGint sw, VGint sh)
639 assert(renderer->state == RENDERER_STATE_COPY);
641 /* there is no depth buffer for scissoring anyway */
642 renderer_quad_pos(renderer, x, y, x + w, y + h, VG_FALSE);
643 renderer_quad_texcoord(renderer, sx, sy, sx + sw, sy + sh,
644 renderer->u.copy.tex_width,
645 renderer->u.copy.tex_height);
647 renderer_quad_draw(renderer);
651 * End copying and restore the states.
653 void renderer_copy_end(struct renderer *renderer)
655 assert(renderer->state == RENDERER_STATE_COPY);
657 cso_restore_framebuffer(renderer->cso);
658 cso_restore_viewport(renderer->cso);
659 cso_restore_blend(renderer->cso);
660 cso_restore_samplers(renderer->cso);
661 cso_restore_fragment_sampler_views(renderer->cso);
662 cso_restore_fragment_shader(renderer->cso);
663 cso_restore_vertex_shader(renderer->cso);
665 renderer->state = RENDERER_STATE_INIT;
669 * Prepare the renderer for textured drawing.
671 VGboolean renderer_drawtex_begin(struct renderer *renderer,
672 struct pipe_sampler_view *src)
674 assert(renderer->state == RENDERER_STATE_INIT);
676 if (!renderer_can_support(renderer, src->texture, PIPE_BIND_SAMPLER_VIEW))
677 return VG_FALSE;
679 cso_save_blend(renderer->cso);
680 cso_save_samplers(renderer->cso);
681 cso_save_fragment_sampler_views(renderer->cso);
682 cso_save_fragment_shader(renderer->cso);
683 cso_save_vertex_shader(renderer->cso);
685 renderer_set_blend(renderer, ~0);
687 renderer_set_samplers(renderer, 1, &src);
689 renderer_set_fs(renderer, RENDERER_FS_TEXTURE);
690 renderer_set_vs(renderer, RENDERER_VS_TEXTURE);
692 renderer_set_mvp(renderer, NULL);
694 /* remember the texture size */
695 renderer->u.drawtex.tex_width = src->texture->width0;
696 renderer->u.drawtex.tex_height = src->texture->height0;
697 renderer->state = RENDERER_STATE_DRAWTEX;
699 return VG_TRUE;
703 * Draw into the destination rectangle given by (x, y, w, h). The texture is
704 * sampled from within the rectangle given by (sx, sy, sw, sh).
706 * The coordinates are in surface coordinates.
708 void renderer_drawtex(struct renderer *renderer,
709 VGint x, VGint y, VGint w, VGint h,
710 VGint sx, VGint sy, VGint sw, VGint sh)
712 assert(renderer->state == RENDERER_STATE_DRAWTEX);
714 /* with scissoring */
715 renderer_quad_pos(renderer, x, y, x + w, y + h, VG_TRUE);
716 renderer_quad_texcoord(renderer, sx, sy, sx + sw, sy + sh,
717 renderer->u.drawtex.tex_width,
718 renderer->u.drawtex.tex_height);
720 renderer_quad_draw(renderer);
724 * End textured drawing and restore the states.
726 void renderer_drawtex_end(struct renderer *renderer)
728 assert(renderer->state == RENDERER_STATE_DRAWTEX);
730 cso_restore_blend(renderer->cso);
731 cso_restore_samplers(renderer->cso);
732 cso_restore_fragment_sampler_views(renderer->cso);
733 cso_restore_fragment_shader(renderer->cso);
734 cso_restore_vertex_shader(renderer->cso);
736 renderer->state = RENDERER_STATE_INIT;
740 * Prepare the renderer for scissor update. This will reset the depth buffer
741 * to 1.0f.
743 VGboolean renderer_scissor_begin(struct renderer *renderer,
744 VGboolean restore_dsa)
746 struct pipe_depth_stencil_alpha_state dsa;
748 assert(renderer->state == RENDERER_STATE_INIT);
750 if (restore_dsa)
751 cso_save_depth_stencil_alpha(renderer->cso);
752 cso_save_blend(renderer->cso);
753 cso_save_fragment_shader(renderer->cso);
755 /* enable depth writes */
756 memset(&dsa, 0, sizeof(dsa));
757 dsa.depth.enabled = 1;
758 dsa.depth.writemask = 1;
759 dsa.depth.func = PIPE_FUNC_ALWAYS;
760 cso_set_depth_stencil_alpha(renderer->cso, &dsa);
762 /* disable color writes */
763 renderer_set_blend(renderer, 0);
764 renderer_set_fs(renderer, RENDERER_FS_SCISSOR);
766 renderer_set_mvp(renderer, NULL);
768 renderer->u.scissor.restore_dsa = restore_dsa;
769 renderer->state = RENDERER_STATE_SCISSOR;
771 /* clear the depth buffer to 1.0f */
772 renderer->pipe->clear(renderer->pipe,
773 PIPE_CLEAR_DEPTHSTENCIL, NULL, 1.0f, 0);
775 return VG_TRUE;
779 * Add a scissor rectangle. Depth values inside the rectangle will be set to
780 * 0.0f.
782 void renderer_scissor(struct renderer *renderer,
783 VGint x, VGint y, VGint width, VGint height)
785 assert(renderer->state == RENDERER_STATE_SCISSOR);
787 renderer_quad_pos(renderer, x, y, x + width, y + height, VG_FALSE);
788 renderer_quad_draw(renderer);
792 * End scissor update and restore the states.
794 void renderer_scissor_end(struct renderer *renderer)
796 assert(renderer->state == RENDERER_STATE_SCISSOR);
798 if (renderer->u.scissor.restore_dsa)
799 cso_restore_depth_stencil_alpha(renderer->cso);
800 cso_restore_blend(renderer->cso);
801 cso_restore_fragment_shader(renderer->cso);
803 renderer->state = RENDERER_STATE_INIT;
807 * Prepare the renderer for clearing.
809 VGboolean renderer_clear_begin(struct renderer *renderer)
811 assert(renderer->state == RENDERER_STATE_INIT);
813 cso_save_blend(renderer->cso);
814 cso_save_fragment_shader(renderer->cso);
815 cso_save_vertex_shader(renderer->cso);
817 renderer_set_blend(renderer, ~0);
818 renderer_set_fs(renderer, RENDERER_FS_COLOR);
819 renderer_set_vs(renderer, RENDERER_VS_COLOR);
821 renderer_set_mvp(renderer, NULL);
823 renderer->state = RENDERER_STATE_CLEAR;
825 return VG_TRUE;
829 * Clear the framebuffer with the specified region and color.
831 * The coordinates are in surface coordinates.
833 void renderer_clear(struct renderer *renderer,
834 VGint x, VGint y, VGint width, VGint height,
835 const VGfloat color[4])
837 VGuint i;
839 assert(renderer->state == RENDERER_STATE_CLEAR);
841 renderer_quad_pos(renderer, x, y, x + width, y + height, VG_TRUE);
842 for (i = 0; i < 4; i++)
843 memcpy(renderer->vertices[i][1], color, sizeof(VGfloat) * 4);
845 renderer_quad_draw(renderer);
849 * End clearing and retore the states.
851 void renderer_clear_end(struct renderer *renderer)
853 assert(renderer->state == RENDERER_STATE_CLEAR);
855 cso_restore_blend(renderer->cso);
856 cso_restore_fragment_shader(renderer->cso);
857 cso_restore_vertex_shader(renderer->cso);
859 renderer->state = RENDERER_STATE_INIT;
863 * Prepare the renderer for image filtering.
865 VGboolean renderer_filter_begin(struct renderer *renderer,
866 struct pipe_resource *dst,
867 VGboolean y0_top,
868 VGbitfield channel_mask,
869 const struct pipe_sampler_state **samplers,
870 struct pipe_sampler_view **views,
871 VGint num_samplers,
872 void *fs,
873 const void *const_buffer,
874 VGint const_buffer_len)
876 struct pipe_surface *surf, surf_tmpl;
878 assert(renderer->state == RENDERER_STATE_INIT);
880 if (!fs)
881 return VG_FALSE;
882 if (!renderer_can_support(renderer, dst, PIPE_BIND_RENDER_TARGET))
883 return VG_FALSE;
885 u_surface_default_template(&surf_tmpl, dst,
886 PIPE_BIND_RENDER_TARGET);
887 surf = renderer->pipe->create_surface(renderer->pipe, dst, &surf_tmpl);
888 if (!surf)
889 return VG_FALSE;
891 cso_save_framebuffer(renderer->cso);
892 cso_save_viewport(renderer->cso);
893 cso_save_blend(renderer->cso);
895 /* set the image as the target */
896 renderer_set_target(renderer, surf, NULL, y0_top);
897 pipe_surface_reference(&surf, NULL);
899 renderer_set_blend(renderer, channel_mask);
901 if (num_samplers) {
902 struct pipe_resource *tex;
904 cso_save_samplers(renderer->cso);
905 cso_save_fragment_sampler_views(renderer->cso);
906 cso_save_fragment_shader(renderer->cso);
907 cso_save_vertex_shader(renderer->cso);
909 renderer_set_custom_fs(renderer, fs,
910 samplers, views, num_samplers,
911 const_buffer, const_buffer_len);
912 renderer_set_vs(renderer, RENDERER_VS_TEXTURE);
914 tex = views[0]->texture;
915 renderer->u.filter.tex_width = tex->width0;
916 renderer->u.filter.tex_height = tex->height0;
917 renderer->u.filter.use_sampler = VG_TRUE;
919 else {
920 cso_save_fragment_shader(renderer->cso);
922 renderer_set_custom_fs(renderer, fs, NULL, NULL, 0,
923 const_buffer, const_buffer_len);
925 renderer->u.filter.use_sampler = VG_FALSE;
928 renderer_set_mvp(renderer, NULL);
930 renderer->state = RENDERER_STATE_FILTER;
932 return VG_TRUE;
936 * Draw into a rectangle of the destination with the specified region of the
937 * texture(s).
939 * The coordinates are in surface coordinates.
941 void renderer_filter(struct renderer *renderer,
942 VGint x, VGint y, VGint w, VGint h,
943 VGint sx, VGint sy, VGint sw, VGint sh)
945 assert(renderer->state == RENDERER_STATE_FILTER);
947 renderer_quad_pos(renderer, x, y, x + w, y + h, VG_FALSE);
948 if (renderer->u.filter.use_sampler) {
949 renderer_quad_texcoord(renderer, sx, sy, sx + sw, sy + sh,
950 renderer->u.filter.tex_width,
951 renderer->u.filter.tex_height);
954 renderer_quad_draw(renderer);
958 * End image filtering and restore the states.
960 void renderer_filter_end(struct renderer *renderer)
962 assert(renderer->state == RENDERER_STATE_FILTER);
964 if (renderer->u.filter.use_sampler) {
965 cso_restore_samplers(renderer->cso);
966 cso_restore_fragment_sampler_views(renderer->cso);
967 cso_restore_vertex_shader(renderer->cso);
970 cso_restore_framebuffer(renderer->cso);
971 cso_restore_viewport(renderer->cso);
972 cso_restore_blend(renderer->cso);
973 cso_restore_fragment_shader(renderer->cso);
975 renderer->state = RENDERER_STATE_INIT;
979 * Prepare the renderer for polygon silhouette rendering.
981 VGboolean renderer_polygon_stencil_begin(struct renderer *renderer,
982 struct pipe_vertex_element *velem,
983 VGFillRule rule,
984 VGboolean restore_dsa)
986 struct pipe_depth_stencil_alpha_state *dsa;
987 VGboolean manual_two_sides;
989 assert(renderer->state == RENDERER_STATE_INIT);
991 cso_save_vertex_elements(renderer->cso);
992 cso_save_blend(renderer->cso);
993 cso_save_depth_stencil_alpha(renderer->cso);
995 cso_set_vertex_elements(renderer->cso, 1, velem);
997 /* disable color writes */
998 renderer_set_blend(renderer, 0);
1000 manual_two_sides = VG_FALSE;
1001 dsa = &renderer->u.polygon_stencil.dsa;
1002 memset(dsa, 0, sizeof(*dsa));
1003 if (rule == VG_EVEN_ODD) {
1004 dsa->stencil[0].enabled = 1;
1005 dsa->stencil[0].writemask = 1;
1006 dsa->stencil[0].fail_op = PIPE_STENCIL_OP_KEEP;
1007 dsa->stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP;
1008 dsa->stencil[0].zpass_op = PIPE_STENCIL_OP_INVERT;
1009 dsa->stencil[0].func = PIPE_FUNC_ALWAYS;
1010 dsa->stencil[0].valuemask = ~0;
1012 else {
1013 assert(rule == VG_NON_ZERO);
1015 /* front face */
1016 dsa->stencil[0].enabled = 1;
1017 dsa->stencil[0].writemask = ~0;
1018 dsa->stencil[0].fail_op = PIPE_STENCIL_OP_KEEP;
1019 dsa->stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP;
1020 dsa->stencil[0].zpass_op = PIPE_STENCIL_OP_INCR_WRAP;
1021 dsa->stencil[0].func = PIPE_FUNC_ALWAYS;
1022 dsa->stencil[0].valuemask = ~0;
1024 if (renderer->pipe->screen->get_param(renderer->pipe->screen,
1025 PIPE_CAP_TWO_SIDED_STENCIL)) {
1026 /* back face */
1027 dsa->stencil[1] = dsa->stencil[0];
1028 dsa->stencil[1].zpass_op = PIPE_STENCIL_OP_DECR_WRAP;
1030 else {
1031 manual_two_sides = VG_TRUE;
1034 cso_set_depth_stencil_alpha(renderer->cso, dsa);
1036 if (manual_two_sides)
1037 cso_save_rasterizer(renderer->cso);
1039 renderer->u.polygon_stencil.manual_two_sides = manual_two_sides;
1040 renderer->u.polygon_stencil.restore_dsa = restore_dsa;
1041 renderer->state = RENDERER_STATE_POLYGON_STENCIL;
1043 return VG_TRUE;
1047 * Render a polygon silhouette to stencil buffer.
1049 void renderer_polygon_stencil(struct renderer *renderer,
1050 struct pipe_vertex_buffer *vbuf,
1051 VGuint mode, VGuint start, VGuint count)
1053 assert(renderer->state == RENDERER_STATE_POLYGON_STENCIL);
1055 cso_set_vertex_buffers(renderer->cso, 1, vbuf);
1057 if (!renderer->u.polygon_stencil.manual_two_sides) {
1058 util_draw_arrays(renderer->pipe, mode, start, count);
1060 else {
1061 struct pipe_rasterizer_state raster;
1062 struct pipe_depth_stencil_alpha_state dsa;
1064 raster = renderer->g3d.rasterizer;
1065 dsa = renderer->u.polygon_stencil.dsa;
1067 /* front */
1068 raster.cull_face = PIPE_FACE_BACK;
1069 dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_INCR_WRAP;
1071 cso_set_rasterizer(renderer->cso, &raster);
1072 cso_set_depth_stencil_alpha(renderer->cso, &dsa);
1073 util_draw_arrays(renderer->pipe, mode, start, count);
1075 /* back */
1076 raster.cull_face = PIPE_FACE_FRONT;
1077 dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_DECR_WRAP;
1079 cso_set_rasterizer(renderer->cso, &raster);
1080 cso_set_depth_stencil_alpha(renderer->cso, &dsa);
1081 util_draw_arrays(renderer->pipe, mode, start, count);
1086 * End polygon silhouette rendering.
1088 void renderer_polygon_stencil_end(struct renderer *renderer)
1090 assert(renderer->state == RENDERER_STATE_POLYGON_STENCIL);
1092 if (renderer->u.polygon_stencil.manual_two_sides)
1093 cso_restore_rasterizer(renderer->cso);
1095 cso_restore_vertex_elements(renderer->cso);
1097 /* restore color writes */
1098 cso_restore_blend(renderer->cso);
1100 if (renderer->u.polygon_stencil.restore_dsa)
1101 cso_restore_depth_stencil_alpha(renderer->cso);
1103 renderer->state = RENDERER_STATE_INIT;
1107 * Prepare the renderer for polygon filling.
1109 VGboolean renderer_polygon_fill_begin(struct renderer *renderer,
1110 VGboolean save_dsa)
1112 struct pipe_depth_stencil_alpha_state dsa;
1114 assert(renderer->state == RENDERER_STATE_INIT);
1116 if (save_dsa)
1117 cso_save_depth_stencil_alpha(renderer->cso);
1119 /* setup stencil ops */
1120 memset(&dsa, 0, sizeof(dsa));
1121 dsa.stencil[0].enabled = 1;
1122 dsa.stencil[0].func = PIPE_FUNC_NOTEQUAL;
1123 dsa.stencil[0].fail_op = PIPE_STENCIL_OP_REPLACE;
1124 dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_REPLACE;
1125 dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_REPLACE;
1126 dsa.stencil[0].valuemask = ~0;
1127 dsa.stencil[0].writemask = ~0;
1128 dsa.depth = renderer->g3d.dsa.depth;
1129 cso_set_depth_stencil_alpha(renderer->cso, &dsa);
1131 renderer->state = RENDERER_STATE_POLYGON_FILL;
1133 return VG_TRUE;
1137 * Fill a polygon.
1139 void renderer_polygon_fill(struct renderer *renderer,
1140 VGfloat min_x, VGfloat min_y,
1141 VGfloat max_x, VGfloat max_y)
1143 assert(renderer->state == RENDERER_STATE_POLYGON_FILL);
1145 renderer_quad_pos(renderer, min_x, min_y, max_x, max_y, VG_TRUE);
1146 renderer_quad_draw(renderer);
1150 * End polygon filling.
1152 void renderer_polygon_fill_end(struct renderer *renderer)
1154 assert(renderer->state == RENDERER_STATE_POLYGON_FILL);
1156 cso_restore_depth_stencil_alpha(renderer->cso);
1158 renderer->state = RENDERER_STATE_INIT;
1161 struct renderer * renderer_create(struct vg_context *owner)
1163 struct renderer *renderer;
1164 struct pipe_rasterizer_state *raster;
1165 struct pipe_stencil_ref sr;
1166 VGint i;
1168 renderer = CALLOC_STRUCT(renderer);
1169 if (!renderer)
1170 return NULL;
1172 renderer->pipe = owner->pipe;
1173 renderer->cso = owner->cso_context;
1175 /* init vertex data that doesn't change */
1176 for (i = 0; i < 4; i++)
1177 renderer->vertices[i][0][3] = 1.0f; /* w */
1179 for (i = 0; i < 2; i++) {
1180 renderer->velems[i].src_offset = i * 4 * sizeof(float);
1181 renderer->velems[i].instance_divisor = 0;
1182 renderer->velems[i].vertex_buffer_index = 0;
1183 renderer->velems[i].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
1185 cso_set_vertex_elements(renderer->cso, 2, renderer->velems);
1187 /* GL rasterization rules */
1188 raster = &renderer->g3d.rasterizer;
1189 memset(raster, 0, sizeof(*raster));
1190 raster->gl_rasterization_rules = 1;
1191 cso_set_rasterizer(renderer->cso, raster);
1193 /* fixed at 0 */
1194 memset(&sr, 0, sizeof(sr));
1195 cso_set_stencil_ref(renderer->cso, &sr);
1197 renderer_set_vs(renderer, RENDERER_VS_PLAIN);
1199 renderer->state = RENDERER_STATE_INIT;
1201 return renderer;
1204 void renderer_destroy(struct renderer *ctx)
1206 int i;
1208 for (i = 0; i < NUM_RENDERER_VS; i++) {
1209 if (ctx->cached_vs[i])
1210 cso_delete_vertex_shader(ctx->cso, ctx->cached_vs[i]);
1212 for (i = 0; i < NUM_RENDERER_FS; i++) {
1213 if (ctx->cached_fs[i])
1214 cso_delete_fragment_shader(ctx->cso, ctx->cached_fs[i]);
1217 pipe_resource_reference(&ctx->vs_cbuf, NULL);
1218 pipe_resource_reference(&ctx->fs_cbuf, NULL);
1220 FREE(ctx);
1223 static void update_clip_state(struct renderer *renderer,
1224 const struct vg_state *state)
1226 struct pipe_depth_stencil_alpha_state *dsa = &renderer->g3d.dsa;
1228 memset(dsa, 0, sizeof(struct pipe_depth_stencil_alpha_state));
1230 if (state->scissoring) {
1231 struct pipe_framebuffer_state *fb = &renderer->g3d.fb;
1232 int i;
1234 renderer_scissor_begin(renderer, VG_FALSE);
1236 for (i = 0; i < state->scissor_rects_num; ++i) {
1237 const float x = state->scissor_rects[i * 4 + 0].f;
1238 const float y = state->scissor_rects[i * 4 + 1].f;
1239 const float width = state->scissor_rects[i * 4 + 2].f;
1240 const float height = state->scissor_rects[i * 4 + 3].f;
1241 VGint x0, y0, x1, y1, iw, ih;
1243 x0 = (VGint) x;
1244 y0 = (VGint) y;
1245 if (x0 < 0)
1246 x0 = 0;
1247 if (y0 < 0)
1248 y0 = 0;
1250 /* note that x1 and y1 are exclusive */
1251 x1 = (VGint) ceilf(x + width);
1252 y1 = (VGint) ceilf(y + height);
1253 if (x1 > fb->width)
1254 x1 = fb->width;
1255 if (y1 > fb->height)
1256 y1 = fb->height;
1258 iw = x1 - x0;
1259 ih = y1 - y0;
1260 if (iw > 0 && ih> 0 )
1261 renderer_scissor(renderer, x0, y0, iw, ih);
1264 renderer_scissor_end(renderer);
1266 dsa->depth.enabled = 1; /* glEnable(GL_DEPTH_TEST); */
1267 dsa->depth.writemask = 0;/*glDepthMask(FALSE);*/
1268 dsa->depth.func = PIPE_FUNC_GEQUAL;
1272 static void renderer_validate_blend(struct renderer *renderer,
1273 const struct vg_state *state,
1274 enum pipe_format fb_format)
1276 struct pipe_blend_state blend;
1278 memset(&blend, 0, sizeof(blend));
1279 blend.rt[0].colormask = PIPE_MASK_RGBA;
1280 blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE;
1281 blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
1282 blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
1283 blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
1285 /* TODO alpha masking happens after blending? */
1287 switch (state->blend_mode) {
1288 case VG_BLEND_SRC:
1289 blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE;
1290 blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
1291 blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
1292 blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
1293 break;
1294 case VG_BLEND_SRC_OVER:
1295 if (paint_is_opaque(state->fill_paint) &&
1296 paint_is_opaque(state->stroke_paint)) {
1297 /* no blending */
1299 else if (!util_format_has_alpha(fb_format)) {
1300 blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_SRC_ALPHA;
1301 blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
1302 blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_INV_SRC_ALPHA;
1303 blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_INV_SRC_ALPHA;
1304 blend.rt[0].blend_enable = 1;
1306 break;
1307 case VG_BLEND_SRC_IN:
1308 blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE;
1309 blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_DST_ALPHA;
1310 blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
1311 blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
1312 blend.rt[0].blend_enable = 1;
1313 break;
1314 case VG_BLEND_DST_IN:
1315 blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ZERO;
1316 blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ZERO;
1317 blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ONE;
1318 blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_SRC_ALPHA;
1319 blend.rt[0].blend_enable = 1;
1320 break;
1321 case VG_BLEND_DST_OVER:
1322 case VG_BLEND_MULTIPLY:
1323 case VG_BLEND_SCREEN:
1324 case VG_BLEND_DARKEN:
1325 case VG_BLEND_LIGHTEN:
1326 case VG_BLEND_ADDITIVE:
1327 /* need a shader */
1328 break;
1329 default:
1330 assert(!"not implemented blend mode");
1331 break;
1334 cso_set_blend(renderer->cso, &blend);
1338 * Propogate OpenVG state changes to the renderer. Only framebuffer, blending
1339 * and scissoring states are relevant here.
1341 void renderer_validate(struct renderer *renderer,
1342 VGbitfield dirty,
1343 const struct st_framebuffer *stfb,
1344 const struct vg_state *state)
1346 assert(renderer->state == RENDERER_STATE_INIT);
1348 dirty |= renderer->dirty;
1349 renderer->dirty = 0;
1351 if (dirty & FRAMEBUFFER_DIRTY) {
1352 struct pipe_framebuffer_state *fb = &renderer->g3d.fb;
1353 struct matrix *proj = &renderer->projection;
1355 memset(fb, 0, sizeof(struct pipe_framebuffer_state));
1356 fb->width = stfb->width;
1357 fb->height = stfb->height;
1358 fb->nr_cbufs = 1;
1359 fb->cbufs[0] = stfb->strb->surface;
1360 fb->zsbuf = stfb->dsrb->surface;
1362 cso_set_framebuffer(renderer->cso, fb);
1363 vg_set_viewport(renderer, VEGA_Y0_BOTTOM);
1365 matrix_load_identity(proj);
1366 matrix_translate(proj, -1.0f, -1.0f);
1367 matrix_scale(proj, 2.0f / fb->width, 2.0f / fb->height);
1369 /* we also got a new depth buffer */
1370 if (dirty & DEPTH_STENCIL_DIRTY) {
1371 renderer->pipe->clear(renderer->pipe,
1372 PIPE_CLEAR_DEPTHSTENCIL, NULL, 0.0, 0);
1376 /* must be last because it renders to the depth buffer*/
1377 if (dirty & DEPTH_STENCIL_DIRTY) {
1378 update_clip_state(renderer, state);
1379 cso_set_depth_stencil_alpha(renderer->cso, &renderer->g3d.dsa);
1382 if (dirty & BLEND_DIRTY)
1383 renderer_validate_blend(renderer, state, stfb->strb->format);
1387 * Prepare the renderer for OpenVG pipeline.
1389 void renderer_validate_for_shader(struct renderer *renderer,
1390 const struct pipe_sampler_state **samplers,
1391 struct pipe_sampler_view **views,
1392 VGint num_samplers,
1393 const struct matrix *modelview,
1394 void *fs,
1395 const void *const_buffer,
1396 VGint const_buffer_len)
1398 struct matrix mvp = renderer->projection;
1400 /* will be used in POLYGON_STENCIL and POLYGON_FILL */
1401 matrix_mult(&mvp, modelview);
1402 renderer_set_mvp(renderer, &mvp);
1404 renderer_set_custom_fs(renderer, fs,
1405 samplers, views, num_samplers,
1406 const_buffer, const_buffer_len);
1409 void renderer_validate_for_mask_rendering(struct renderer *renderer,
1410 struct pipe_surface *dst,
1411 const struct matrix *modelview)
1413 struct matrix mvp = renderer->projection;
1415 /* will be used in POLYGON_STENCIL and POLYGON_FILL */
1416 matrix_mult(&mvp, modelview);
1417 renderer_set_mvp(renderer, &mvp);
1419 renderer_set_target(renderer, dst, renderer->g3d.fb.zsbuf, VG_FALSE);
1420 renderer_set_blend(renderer, ~0);
1421 renderer_set_fs(renderer, RENDERER_FS_WHITE);
1423 /* set internal dirty flags (hacky!) */
1424 renderer->dirty = FRAMEBUFFER_DIRTY | BLEND_DIRTY;
1427 void renderer_copy_surface(struct renderer *ctx,
1428 struct pipe_surface *src,
1429 int srcX0, int srcY0,
1430 int srcX1, int srcY1,
1431 struct pipe_surface *dst,
1432 int dstX0, int dstY0,
1433 int dstX1, int dstY1,
1434 float z, unsigned filter)
1436 struct pipe_context *pipe = ctx->pipe;
1437 struct pipe_screen *screen = pipe->screen;
1438 struct pipe_sampler_view view_templ;
1439 struct pipe_sampler_view *view;
1440 struct pipe_box src_box;
1441 struct pipe_resource texTemp, *tex;
1442 const struct pipe_framebuffer_state *fb = &ctx->g3d.fb;
1443 const int srcW = abs(srcX1 - srcX0);
1444 const int srcH = abs(srcY1 - srcY0);
1445 const int srcLeft = MIN2(srcX0, srcX1);
1446 const int srcTop = MIN2(srcY0, srcY1);
1448 assert(filter == PIPE_TEX_MIPFILTER_NEAREST ||
1449 filter == PIPE_TEX_MIPFILTER_LINEAR);
1451 if (srcLeft != srcX0) {
1452 /* left-right flip */
1453 int tmp = dstX0;
1454 dstX0 = dstX1;
1455 dstX1 = tmp;
1458 if (srcTop != srcY0) {
1459 /* up-down flip */
1460 int tmp = dstY0;
1461 dstY0 = dstY1;
1462 dstY1 = tmp;
1465 assert(screen->is_format_supported(screen, src->format, PIPE_TEXTURE_2D,
1466 0, PIPE_BIND_SAMPLER_VIEW));
1467 assert(screen->is_format_supported(screen, dst->format, PIPE_TEXTURE_2D,
1468 0, PIPE_BIND_SAMPLER_VIEW));
1469 assert(screen->is_format_supported(screen, dst->format, PIPE_TEXTURE_2D,
1470 0, PIPE_BIND_RENDER_TARGET));
1473 * XXX for now we're always creating a temporary texture.
1474 * Strictly speaking that's not always needed.
1477 /* create temp texture */
1478 memset(&texTemp, 0, sizeof(texTemp));
1479 texTemp.target = PIPE_TEXTURE_2D;
1480 texTemp.format = src->format;
1481 texTemp.last_level = 0;
1482 texTemp.width0 = srcW;
1483 texTemp.height0 = srcH;
1484 texTemp.depth0 = 1;
1485 texTemp.array_size = 1;
1486 texTemp.bind = PIPE_BIND_SAMPLER_VIEW;
1488 tex = screen->resource_create(screen, &texTemp);
1489 if (!tex)
1490 return;
1492 u_sampler_view_default_template(&view_templ, tex, tex->format);
1493 view = pipe->create_sampler_view(pipe, tex, &view_templ);
1495 if (!view)
1496 return;
1498 u_box_2d_zslice(srcLeft, srcTop, src->u.tex.first_layer, srcW, srcH, &src_box);
1500 pipe->resource_copy_region(pipe,
1501 tex, 0, 0, 0, 0, /* dest */
1502 src->texture, 0, &src_box);
1504 assert(floatsEqual(z, 0.0f));
1506 /* draw */
1507 if (fb->cbufs[0] == dst) {
1508 /* transform back to surface coordinates */
1509 dstY0 = dst->height - dstY0;
1510 dstY1 = dst->height - dstY1;
1512 if (renderer_drawtex_begin(ctx, view)) {
1513 renderer_drawtex(ctx,
1514 dstX0, dstY0, dstX1 - dstX0, dstY1 - dstY0,
1515 0, 0, view->texture->width0, view->texture->height0);
1516 renderer_drawtex_end(ctx);
1519 else {
1520 if (renderer_copy_begin(ctx, dst, VG_TRUE, view)) {
1521 renderer_copy(ctx,
1522 dstX0, dstY0, dstX1 - dstX0, dstY1 - dstY0,
1523 0, 0, view->texture->width0, view->texture->height0);
1524 renderer_copy_end(ctx);
1529 void renderer_texture_quad(struct renderer *r,
1530 struct pipe_resource *tex,
1531 VGfloat x1offset, VGfloat y1offset,
1532 VGfloat x2offset, VGfloat y2offset,
1533 VGfloat x1, VGfloat y1,
1534 VGfloat x2, VGfloat y2,
1535 VGfloat x3, VGfloat y3,
1536 VGfloat x4, VGfloat y4)
1538 const VGfloat z = 0.0f;
1540 assert(r->state == RENDERER_STATE_INIT);
1541 assert(tex->width0 != 0);
1542 assert(tex->height0 != 0);
1544 cso_save_vertex_shader(r->cso);
1546 renderer_set_vs(r, RENDERER_VS_TEXTURE);
1548 /* manually set up positions */
1549 r->vertices[0][0][0] = x1;
1550 r->vertices[0][0][1] = y1;
1551 r->vertices[0][0][2] = z;
1553 r->vertices[1][0][0] = x2;
1554 r->vertices[1][0][1] = y2;
1555 r->vertices[1][0][2] = z;
1557 r->vertices[2][0][0] = x3;
1558 r->vertices[2][0][1] = y3;
1559 r->vertices[2][0][2] = z;
1561 r->vertices[3][0][0] = x4;
1562 r->vertices[3][0][1] = y4;
1563 r->vertices[3][0][2] = z;
1565 /* texcoords */
1566 renderer_quad_texcoord(r, x1offset, y1offset,
1567 x2offset, y2offset, tex->width0, tex->height0);
1569 renderer_quad_draw(r);
1571 cso_restore_vertex_shader(r->cso);