936bf2e4e03ff3582d3eb81356cbb69c18cb8f69
[mesa.git] / src / gallium / state_trackers / vega / renderer.c
1 /**************************************************************************
2 *
3 * Copyright 2009 VMware, Inc. All Rights Reserved.
4 * Copyright 2010 LunarG, Inc. All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27
28 #include "renderer.h"
29
30 #include "vg_context.h"
31 #include "paint.h" /* for paint_is_opaque */
32
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"
38
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"
46
47 #include "cso_cache/cso_context.h"
48 #include "tgsi/tgsi_ureg.h"
49
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;
61
62 typedef enum {
63 RENDERER_VS_PLAIN,
64 RENDERER_VS_COLOR,
65 RENDERER_VS_TEXTURE,
66 NUM_RENDERER_VS
67 } RendererVs;
68
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;
76
77 struct renderer {
78 struct pipe_context *pipe;
79 struct cso_context *cso;
80
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;
88
89 struct matrix mvp;
90 struct pipe_resource *vs_cbuf;
91
92 struct pipe_resource *fs_cbuf;
93 VGfloat fs_cbuf_data[32];
94 VGint fs_cbuf_len;
95
96 struct pipe_vertex_element velems[2];
97 VGfloat vertices[4][2][4];
98
99 void *cached_vs[NUM_RENDERER_VS];
100 void *cached_fs[NUM_RENDERER_FS];
101
102 RendererState state;
103
104 /* state data */
105 union {
106 struct {
107 VGint tex_width;
108 VGint tex_height;
109 } copy;
110
111 struct {
112 VGint tex_width;
113 VGint tex_height;
114 } drawtex;
115
116 struct {
117 VGboolean restore_dsa;
118 } scissor;
119
120 struct {
121 VGboolean use_sampler;
122 VGint tex_width, tex_height;
123 } filter;
124
125 struct {
126 struct pipe_depth_stencil_alpha_state dsa;
127 VGboolean manual_two_sides;
128 VGboolean restore_dsa;
129 } polygon_stencil;
130 } u;
131 };
132
133 /**
134 * Return VG_TRUE if the renderer can use the resource as the asked bindings.
135 */
136 static VGboolean renderer_can_support(struct renderer *renderer,
137 struct pipe_resource *res,
138 unsigned bindings)
139 {
140 struct pipe_screen *screen = renderer->pipe->screen;
141
142 return screen->is_format_supported(screen,
143 res->format, res->target, 0, bindings, 0);
144 }
145
146 /**
147 * Set the model-view-projection matrix used by vertex shaders.
148 */
149 static void renderer_set_mvp(struct renderer *renderer,
150 const struct matrix *mvp)
151 {
152 struct matrix *cur = &renderer->mvp;
153 struct pipe_resource *cbuf;
154 VGfloat consts[3][4];
155 VGint i;
156
157 /* projection only */
158 if (!mvp)
159 mvp = &renderer->projection;
160
161 /* re-upload only if necessary */
162 if (memcmp(cur, mvp, sizeof(*mvp)) == 0)
163 return;
164
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];
171 }
172
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 sizeof(consts));
178 if (cbuf) {
179 pipe_buffer_write(renderer->pipe, cbuf,
180 0, sizeof(consts), consts);
181 }
182 renderer->pipe->set_constant_buffer(renderer->pipe,
183 PIPE_SHADER_VERTEX, 0, cbuf);
184
185 memcpy(cur, mvp, sizeof(*mvp));
186 renderer->vs_cbuf = cbuf;
187 }
188
189 /**
190 * Create a simple vertex shader that passes through position and the given
191 * attribute.
192 */
193 static void *create_passthrough_vs(struct pipe_context *pipe, int semantic_name)
194 {
195 struct ureg_program *ureg;
196 struct ureg_src src[2], constants[3];
197 struct ureg_dst dst[2], tmp;
198 int i;
199
200 ureg = ureg_create(TGSI_PROCESSOR_VERTEX);
201 if (!ureg)
202 return NULL;
203
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);
210
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));
217
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]);
222 }
223
224 ureg_END(ureg);
225
226 return ureg_create_shader_and_destroy(ureg, pipe);
227 }
228
229 /**
230 * Set renderer vertex shader.
231 *
232 * This function modifies vertex_shader state.
233 */
234 static void renderer_set_vs(struct renderer *r, RendererVs id)
235 {
236 /* create as needed */
237 if (!r->cached_vs[id]) {
238 int semantic_name = -1;
239
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;
252 }
253
254 r->cached_vs[id] = create_passthrough_vs(r->pipe, semantic_name);
255 }
256
257 cso_set_vertex_shader_handle(r->cso, r->cached_vs[id]);
258 }
259
260 /**
261 * Create a simple fragment shader that sets the depth to 0.0f.
262 */
263 static void *create_scissor_fs(struct pipe_context *pipe)
264 {
265 struct ureg_program *ureg;
266 struct ureg_dst out;
267 struct ureg_src imm;
268
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);
272
273 ureg_MOV(ureg, ureg_writemask(out, TGSI_WRITEMASK_Z), imm);
274 ureg_END(ureg);
275
276 return ureg_create_shader_and_destroy(ureg, pipe);
277 }
278
279 /**
280 * Create a simple fragment shader that sets the color to white.
281 */
282 static void *create_white_fs(struct pipe_context *pipe)
283 {
284 struct ureg_program *ureg;
285 struct ureg_dst out;
286 struct ureg_src imm;
287
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);
291
292 ureg_MOV(ureg, out, imm);
293 ureg_END(ureg);
294
295 return ureg_create_shader_and_destroy(ureg, pipe);
296 }
297
298 /**
299 * Set renderer fragment shader.
300 *
301 * This function modifies fragment_shader state.
302 */
303 static void renderer_set_fs(struct renderer *r, RendererFs id)
304 {
305 /* create as needed */
306 if (!r->cached_fs[id]) {
307 void *fs = NULL;
308
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;
326 }
327
328 r->cached_fs[id] = fs;
329 }
330
331 cso_set_fragment_shader_handle(r->cso, r->cached_fs[id]);
332 }
333
334 typedef enum {
335 VEGA_Y0_TOP,
336 VEGA_Y0_BOTTOM
337 } VegaOrientation;
338
339 static void vg_set_viewport(struct renderer *r,
340 VegaOrientation orientation)
341 {
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;
345
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;
354
355 cso_set_viewport(r->cso, &viewport);
356 }
357
358 /**
359 * Set renderer target.
360 *
361 * This function modifies framebuffer and viewport states.
362 */
363 static void renderer_set_target(struct renderer *r,
364 struct pipe_surface *cbuf,
365 struct pipe_surface *zsbuf,
366 VGboolean y0_top)
367 {
368 struct pipe_framebuffer_state fb;
369
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);
377
378 vg_set_viewport(r, (y0_top) ? VEGA_Y0_TOP : VEGA_Y0_BOTTOM);
379 }
380
381 /**
382 * Set renderer blend state. Blending is disabled.
383 *
384 * This function modifies blend state.
385 */
386 static void renderer_set_blend(struct renderer *r,
387 VGbitfield channel_mask)
388 {
389 struct pipe_blend_state blend;
390
391 memset(&blend, 0, sizeof(blend));
392
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;
397
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;
406
407 cso_set_blend(r->cso, &blend);
408 }
409
410 /**
411 * Set renderer sampler and view states.
412 *
413 * This function modifies samplers and fragment_sampler_views states.
414 */
415 static void renderer_set_samplers(struct renderer *r,
416 uint num_views,
417 struct pipe_sampler_view **views)
418 {
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;
423
424 memset(&sampler, 0, sizeof(sampler));
425
426 sampler.min_img_filter = tex_filter;
427 sampler.mag_img_filter = tex_filter;
428 sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
429
430 sampler.wrap_s = tex_wrap;
431 sampler.wrap_t = tex_wrap;
432 sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
433
434 sampler.normalized_coords = 1;
435
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);
440
441 /* set views */
442 cso_set_fragment_sampler_views(r->cso, num_views, views);
443 }
444
445 /**
446 * Set custom renderer fragment shader, and optionally set samplers and views
447 * and upload the fragment constant buffer.
448 *
449 * This function modifies fragment_shader, samplers and fragment_sampler_views
450 * states.
451 */
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)
459 {
460 cso_set_fragment_shader_handle(renderer->cso, fs);
461
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);
466 }
467
468 /* upload fs constant buffer */
469 if (const_buffer_len) {
470 struct pipe_resource *cbuf = renderer->fs_cbuf;
471
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);
475
476 cbuf = pipe_buffer_create(renderer->pipe->screen,
477 PIPE_BIND_CONSTANT_BUFFER, const_buffer_len);
478 pipe_buffer_write(renderer->pipe, cbuf, 0,
479 const_buffer_len, const_buffer);
480 renderer->pipe->set_constant_buffer(renderer->pipe,
481 PIPE_SHADER_FRAGMENT, 0, cbuf);
482
483 renderer->fs_cbuf = cbuf;
484 if (const_buffer_len <= sizeof(renderer->fs_cbuf_data)) {
485 memcpy(renderer->fs_cbuf_data, const_buffer, const_buffer_len);
486 renderer->fs_cbuf_len = const_buffer_len;
487 }
488 else {
489 renderer->fs_cbuf_len = 0;
490 }
491 }
492 }
493 }
494
495 /**
496 * Setup renderer quad position.
497 */
498 static void renderer_quad_pos(struct renderer *r,
499 VGfloat x0, VGfloat y0,
500 VGfloat x1, VGfloat y1,
501 VGboolean scissor)
502 {
503 VGfloat z;
504
505 /* the depth test is used for scissoring */
506 z = (scissor) ? 0.0f : 1.0f;
507
508 /* positions */
509 r->vertices[0][0][0] = x0;
510 r->vertices[0][0][1] = y0;
511 r->vertices[0][0][2] = z;
512
513 r->vertices[1][0][0] = x1;
514 r->vertices[1][0][1] = y0;
515 r->vertices[1][0][2] = z;
516
517 r->vertices[2][0][0] = x1;
518 r->vertices[2][0][1] = y1;
519 r->vertices[2][0][2] = z;
520
521 r->vertices[3][0][0] = x0;
522 r->vertices[3][0][1] = y1;
523 r->vertices[3][0][2] = z;
524 }
525
526 /**
527 * Setup renderer quad texture coordinates.
528 */
529 static void renderer_quad_texcoord(struct renderer *r,
530 VGfloat x0, VGfloat y0,
531 VGfloat x1, VGfloat y1,
532 VGint tex_width, VGint tex_height)
533 {
534 VGfloat s0, t0, s1, t1, r0, q0;
535 VGint i;
536
537 s0 = x0 / tex_width;
538 s1 = x1 / tex_width;
539 t0 = y0 / tex_height;
540 t1 = y1 / tex_height;
541 r0 = 0.0f;
542 q0 = 1.0f;
543
544 /* texcoords */
545 r->vertices[0][1][0] = s0;
546 r->vertices[0][1][1] = t0;
547
548 r->vertices[1][1][0] = s1;
549 r->vertices[1][1][1] = t0;
550
551 r->vertices[2][1][0] = s1;
552 r->vertices[2][1][1] = t1;
553
554 r->vertices[3][1][0] = s0;
555 r->vertices[3][1][1] = t1;
556
557 for (i = 0; i < 4; i++) {
558 r->vertices[i][1][2] = r0;
559 r->vertices[i][1][3] = q0;
560 }
561 }
562
563 /**
564 * Draw renderer quad.
565 */
566 static void renderer_quad_draw(struct renderer *r)
567 {
568 struct pipe_resource *buf;
569
570 buf = pipe_user_buffer_create(r->pipe->screen,
571 r->vertices,
572 sizeof(r->vertices),
573 PIPE_BIND_VERTEX_BUFFER);
574 if (buf) {
575 util_draw_vertex_buffer(r->pipe, buf, 0,
576 PIPE_PRIM_TRIANGLE_FAN,
577 Elements(r->vertices), /* verts */
578 Elements(r->vertices[0])); /* attribs/vert */
579
580 pipe_resource_reference(&buf, NULL);
581 }
582 }
583
584 /**
585 * Prepare the renderer for copying.
586 */
587 VGboolean renderer_copy_begin(struct renderer *renderer,
588 struct pipe_surface *dst,
589 VGboolean y0_top,
590 struct pipe_sampler_view *src)
591 {
592 assert(renderer->state == RENDERER_STATE_INIT);
593
594 /* sanity check */
595 if (!renderer_can_support(renderer,
596 dst->texture, PIPE_BIND_RENDER_TARGET) ||
597 !renderer_can_support(renderer,
598 src->texture, PIPE_BIND_SAMPLER_VIEW))
599 return VG_FALSE;
600
601 cso_save_framebuffer(renderer->cso);
602 cso_save_viewport(renderer->cso);
603 cso_save_blend(renderer->cso);
604 cso_save_samplers(renderer->cso);
605 cso_save_fragment_sampler_views(renderer->cso);
606 cso_save_fragment_shader(renderer->cso);
607 cso_save_vertex_shader(renderer->cso);
608
609 renderer_set_target(renderer, dst, NULL, y0_top);
610
611 renderer_set_blend(renderer, ~0);
612 renderer_set_samplers(renderer, 1, &src);
613
614 renderer_set_fs(renderer, RENDERER_FS_TEXTURE);
615 renderer_set_vs(renderer, RENDERER_VS_TEXTURE);
616
617 renderer_set_mvp(renderer, NULL);
618
619 /* remember the texture size */
620 renderer->u.copy.tex_width = src->texture->width0;
621 renderer->u.copy.tex_height = src->texture->height0;
622 renderer->state = RENDERER_STATE_COPY;
623
624 return VG_TRUE;
625 }
626
627 /**
628 * Draw into the destination rectangle given by (x, y, w, h). The texture is
629 * sampled from within the rectangle given by (sx, sy, sw, sh).
630 *
631 * The coordinates are in surface coordinates.
632 */
633 void renderer_copy(struct renderer *renderer,
634 VGint x, VGint y, VGint w, VGint h,
635 VGint sx, VGint sy, VGint sw, VGint sh)
636 {
637 assert(renderer->state == RENDERER_STATE_COPY);
638
639 /* there is no depth buffer for scissoring anyway */
640 renderer_quad_pos(renderer, x, y, x + w, y + h, VG_FALSE);
641 renderer_quad_texcoord(renderer, sx, sy, sx + sw, sy + sh,
642 renderer->u.copy.tex_width,
643 renderer->u.copy.tex_height);
644
645 renderer_quad_draw(renderer);
646 }
647
648 /**
649 * End copying and restore the states.
650 */
651 void renderer_copy_end(struct renderer *renderer)
652 {
653 assert(renderer->state == RENDERER_STATE_COPY);
654
655 cso_restore_framebuffer(renderer->cso);
656 cso_restore_viewport(renderer->cso);
657 cso_restore_blend(renderer->cso);
658 cso_restore_samplers(renderer->cso);
659 cso_restore_fragment_sampler_views(renderer->cso);
660 cso_restore_fragment_shader(renderer->cso);
661 cso_restore_vertex_shader(renderer->cso);
662
663 renderer->state = RENDERER_STATE_INIT;
664 }
665
666 /**
667 * Prepare the renderer for textured drawing.
668 */
669 VGboolean renderer_drawtex_begin(struct renderer *renderer,
670 struct pipe_sampler_view *src)
671 {
672 assert(renderer->state == RENDERER_STATE_INIT);
673
674 if (!renderer_can_support(renderer, src->texture, PIPE_BIND_SAMPLER_VIEW))
675 return VG_FALSE;
676
677 cso_save_blend(renderer->cso);
678 cso_save_samplers(renderer->cso);
679 cso_save_fragment_sampler_views(renderer->cso);
680 cso_save_fragment_shader(renderer->cso);
681 cso_save_vertex_shader(renderer->cso);
682
683 renderer_set_blend(renderer, ~0);
684
685 renderer_set_samplers(renderer, 1, &src);
686
687 renderer_set_fs(renderer, RENDERER_FS_TEXTURE);
688 renderer_set_vs(renderer, RENDERER_VS_TEXTURE);
689
690 renderer_set_mvp(renderer, NULL);
691
692 /* remember the texture size */
693 renderer->u.drawtex.tex_width = src->texture->width0;
694 renderer->u.drawtex.tex_height = src->texture->height0;
695 renderer->state = RENDERER_STATE_DRAWTEX;
696
697 return VG_TRUE;
698 }
699
700 /**
701 * Draw into the destination rectangle given by (x, y, w, h). The texture is
702 * sampled from within the rectangle given by (sx, sy, sw, sh).
703 *
704 * The coordinates are in surface coordinates.
705 */
706 void renderer_drawtex(struct renderer *renderer,
707 VGint x, VGint y, VGint w, VGint h,
708 VGint sx, VGint sy, VGint sw, VGint sh)
709 {
710 assert(renderer->state == RENDERER_STATE_DRAWTEX);
711
712 /* with scissoring */
713 renderer_quad_pos(renderer, x, y, x + w, y + h, VG_TRUE);
714 renderer_quad_texcoord(renderer, sx, sy, sx + sw, sy + sh,
715 renderer->u.drawtex.tex_width,
716 renderer->u.drawtex.tex_height);
717
718 renderer_quad_draw(renderer);
719 }
720
721 /**
722 * End textured drawing and restore the states.
723 */
724 void renderer_drawtex_end(struct renderer *renderer)
725 {
726 assert(renderer->state == RENDERER_STATE_DRAWTEX);
727
728 cso_restore_blend(renderer->cso);
729 cso_restore_samplers(renderer->cso);
730 cso_restore_fragment_sampler_views(renderer->cso);
731 cso_restore_fragment_shader(renderer->cso);
732 cso_restore_vertex_shader(renderer->cso);
733
734 renderer->state = RENDERER_STATE_INIT;
735 }
736
737 /**
738 * Prepare the renderer for scissor update. This will reset the depth buffer
739 * to 1.0f.
740 */
741 VGboolean renderer_scissor_begin(struct renderer *renderer,
742 VGboolean restore_dsa)
743 {
744 struct pipe_depth_stencil_alpha_state dsa;
745
746 assert(renderer->state == RENDERER_STATE_INIT);
747
748 if (restore_dsa)
749 cso_save_depth_stencil_alpha(renderer->cso);
750 cso_save_blend(renderer->cso);
751 cso_save_fragment_shader(renderer->cso);
752
753 /* enable depth writes */
754 memset(&dsa, 0, sizeof(dsa));
755 dsa.depth.enabled = 1;
756 dsa.depth.writemask = 1;
757 dsa.depth.func = PIPE_FUNC_ALWAYS;
758 cso_set_depth_stencil_alpha(renderer->cso, &dsa);
759
760 /* disable color writes */
761 renderer_set_blend(renderer, 0);
762 renderer_set_fs(renderer, RENDERER_FS_SCISSOR);
763
764 renderer_set_mvp(renderer, NULL);
765
766 renderer->u.scissor.restore_dsa = restore_dsa;
767 renderer->state = RENDERER_STATE_SCISSOR;
768
769 /* clear the depth buffer to 1.0f */
770 renderer->pipe->clear(renderer->pipe,
771 PIPE_CLEAR_DEPTHSTENCIL, NULL, 1.0f, 0);
772
773 return VG_TRUE;
774 }
775
776 /**
777 * Add a scissor rectangle. Depth values inside the rectangle will be set to
778 * 0.0f.
779 */
780 void renderer_scissor(struct renderer *renderer,
781 VGint x, VGint y, VGint width, VGint height)
782 {
783 assert(renderer->state == RENDERER_STATE_SCISSOR);
784
785 renderer_quad_pos(renderer, x, y, x + width, y + height, VG_FALSE);
786 renderer_quad_draw(renderer);
787 }
788
789 /**
790 * End scissor update and restore the states.
791 */
792 void renderer_scissor_end(struct renderer *renderer)
793 {
794 assert(renderer->state == RENDERER_STATE_SCISSOR);
795
796 if (renderer->u.scissor.restore_dsa)
797 cso_restore_depth_stencil_alpha(renderer->cso);
798 cso_restore_blend(renderer->cso);
799 cso_restore_fragment_shader(renderer->cso);
800
801 renderer->state = RENDERER_STATE_INIT;
802 }
803
804 /**
805 * Prepare the renderer for clearing.
806 */
807 VGboolean renderer_clear_begin(struct renderer *renderer)
808 {
809 assert(renderer->state == RENDERER_STATE_INIT);
810
811 cso_save_blend(renderer->cso);
812 cso_save_fragment_shader(renderer->cso);
813 cso_save_vertex_shader(renderer->cso);
814
815 renderer_set_blend(renderer, ~0);
816 renderer_set_fs(renderer, RENDERER_FS_COLOR);
817 renderer_set_vs(renderer, RENDERER_VS_COLOR);
818
819 renderer_set_mvp(renderer, NULL);
820
821 renderer->state = RENDERER_STATE_CLEAR;
822
823 return VG_TRUE;
824 }
825
826 /**
827 * Clear the framebuffer with the specified region and color.
828 *
829 * The coordinates are in surface coordinates.
830 */
831 void renderer_clear(struct renderer *renderer,
832 VGint x, VGint y, VGint width, VGint height,
833 const VGfloat color[4])
834 {
835 VGuint i;
836
837 assert(renderer->state == RENDERER_STATE_CLEAR);
838
839 renderer_quad_pos(renderer, x, y, x + width, y + height, VG_TRUE);
840 for (i = 0; i < 4; i++)
841 memcpy(renderer->vertices[i][1], color, sizeof(VGfloat) * 4);
842
843 renderer_quad_draw(renderer);
844 }
845
846 /**
847 * End clearing and retore the states.
848 */
849 void renderer_clear_end(struct renderer *renderer)
850 {
851 assert(renderer->state == RENDERER_STATE_CLEAR);
852
853 cso_restore_blend(renderer->cso);
854 cso_restore_fragment_shader(renderer->cso);
855 cso_restore_vertex_shader(renderer->cso);
856
857 renderer->state = RENDERER_STATE_INIT;
858 }
859
860 /**
861 * Prepare the renderer for image filtering.
862 */
863 VGboolean renderer_filter_begin(struct renderer *renderer,
864 struct pipe_resource *dst,
865 VGboolean y0_top,
866 VGbitfield channel_mask,
867 const struct pipe_sampler_state **samplers,
868 struct pipe_sampler_view **views,
869 VGint num_samplers,
870 void *fs,
871 const void *const_buffer,
872 VGint const_buffer_len)
873 {
874 struct pipe_surface *surf, surf_tmpl;
875
876 assert(renderer->state == RENDERER_STATE_INIT);
877
878 if (!fs)
879 return VG_FALSE;
880 if (!renderer_can_support(renderer, dst, PIPE_BIND_RENDER_TARGET))
881 return VG_FALSE;
882
883 u_surface_default_template(&surf_tmpl, dst,
884 PIPE_BIND_RENDER_TARGET);
885 surf = renderer->pipe->create_surface(renderer->pipe, dst, &surf_tmpl);
886 if (!surf)
887 return VG_FALSE;
888
889 cso_save_framebuffer(renderer->cso);
890 cso_save_viewport(renderer->cso);
891 cso_save_blend(renderer->cso);
892
893 /* set the image as the target */
894 renderer_set_target(renderer, surf, NULL, y0_top);
895 pipe_surface_reference(&surf, NULL);
896
897 renderer_set_blend(renderer, channel_mask);
898
899 if (num_samplers) {
900 struct pipe_resource *tex;
901
902 cso_save_samplers(renderer->cso);
903 cso_save_fragment_sampler_views(renderer->cso);
904 cso_save_fragment_shader(renderer->cso);
905 cso_save_vertex_shader(renderer->cso);
906
907 renderer_set_custom_fs(renderer, fs,
908 samplers, views, num_samplers,
909 const_buffer, const_buffer_len);
910 renderer_set_vs(renderer, RENDERER_VS_TEXTURE);
911
912 tex = views[0]->texture;
913 renderer->u.filter.tex_width = tex->width0;
914 renderer->u.filter.tex_height = tex->height0;
915 renderer->u.filter.use_sampler = VG_TRUE;
916 }
917 else {
918 cso_save_fragment_shader(renderer->cso);
919
920 renderer_set_custom_fs(renderer, fs, NULL, NULL, 0,
921 const_buffer, const_buffer_len);
922
923 renderer->u.filter.use_sampler = VG_FALSE;
924 }
925
926 renderer_set_mvp(renderer, NULL);
927
928 renderer->state = RENDERER_STATE_FILTER;
929
930 return VG_TRUE;
931 }
932
933 /**
934 * Draw into a rectangle of the destination with the specified region of the
935 * texture(s).
936 *
937 * The coordinates are in surface coordinates.
938 */
939 void renderer_filter(struct renderer *renderer,
940 VGint x, VGint y, VGint w, VGint h,
941 VGint sx, VGint sy, VGint sw, VGint sh)
942 {
943 assert(renderer->state == RENDERER_STATE_FILTER);
944
945 renderer_quad_pos(renderer, x, y, x + w, y + h, VG_FALSE);
946 if (renderer->u.filter.use_sampler) {
947 renderer_quad_texcoord(renderer, sx, sy, sx + sw, sy + sh,
948 renderer->u.filter.tex_width,
949 renderer->u.filter.tex_height);
950 }
951
952 renderer_quad_draw(renderer);
953 }
954
955 /**
956 * End image filtering and restore the states.
957 */
958 void renderer_filter_end(struct renderer *renderer)
959 {
960 assert(renderer->state == RENDERER_STATE_FILTER);
961
962 if (renderer->u.filter.use_sampler) {
963 cso_restore_samplers(renderer->cso);
964 cso_restore_fragment_sampler_views(renderer->cso);
965 cso_restore_vertex_shader(renderer->cso);
966 }
967
968 cso_restore_framebuffer(renderer->cso);
969 cso_restore_viewport(renderer->cso);
970 cso_restore_blend(renderer->cso);
971 cso_restore_fragment_shader(renderer->cso);
972
973 renderer->state = RENDERER_STATE_INIT;
974 }
975
976 /**
977 * Prepare the renderer for polygon silhouette rendering.
978 */
979 VGboolean renderer_polygon_stencil_begin(struct renderer *renderer,
980 struct pipe_vertex_element *velem,
981 VGFillRule rule,
982 VGboolean restore_dsa)
983 {
984 struct pipe_depth_stencil_alpha_state *dsa;
985 VGboolean manual_two_sides;
986
987 assert(renderer->state == RENDERER_STATE_INIT);
988
989 cso_save_vertex_elements(renderer->cso);
990 cso_save_blend(renderer->cso);
991 cso_save_depth_stencil_alpha(renderer->cso);
992
993 cso_set_vertex_elements(renderer->cso, 1, velem);
994
995 /* disable color writes */
996 renderer_set_blend(renderer, 0);
997
998 manual_two_sides = VG_FALSE;
999 dsa = &renderer->u.polygon_stencil.dsa;
1000 memset(dsa, 0, sizeof(*dsa));
1001 if (rule == VG_EVEN_ODD) {
1002 dsa->stencil[0].enabled = 1;
1003 dsa->stencil[0].writemask = 1;
1004 dsa->stencil[0].fail_op = PIPE_STENCIL_OP_KEEP;
1005 dsa->stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP;
1006 dsa->stencil[0].zpass_op = PIPE_STENCIL_OP_INVERT;
1007 dsa->stencil[0].func = PIPE_FUNC_ALWAYS;
1008 dsa->stencil[0].valuemask = ~0;
1009 }
1010 else {
1011 assert(rule == VG_NON_ZERO);
1012
1013 /* front face */
1014 dsa->stencil[0].enabled = 1;
1015 dsa->stencil[0].writemask = ~0;
1016 dsa->stencil[0].fail_op = PIPE_STENCIL_OP_KEEP;
1017 dsa->stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP;
1018 dsa->stencil[0].zpass_op = PIPE_STENCIL_OP_INCR_WRAP;
1019 dsa->stencil[0].func = PIPE_FUNC_ALWAYS;
1020 dsa->stencil[0].valuemask = ~0;
1021
1022 if (renderer->pipe->screen->get_param(renderer->pipe->screen,
1023 PIPE_CAP_TWO_SIDED_STENCIL)) {
1024 /* back face */
1025 dsa->stencil[1] = dsa->stencil[0];
1026 dsa->stencil[1].zpass_op = PIPE_STENCIL_OP_DECR_WRAP;
1027 }
1028 else {
1029 manual_two_sides = VG_TRUE;
1030 }
1031 }
1032 cso_set_depth_stencil_alpha(renderer->cso, dsa);
1033
1034 if (manual_two_sides)
1035 cso_save_rasterizer(renderer->cso);
1036
1037 renderer->u.polygon_stencil.manual_two_sides = manual_two_sides;
1038 renderer->u.polygon_stencil.restore_dsa = restore_dsa;
1039 renderer->state = RENDERER_STATE_POLYGON_STENCIL;
1040
1041 return VG_TRUE;
1042 }
1043
1044 /**
1045 * Render a polygon silhouette to stencil buffer.
1046 */
1047 void renderer_polygon_stencil(struct renderer *renderer,
1048 struct pipe_vertex_buffer *vbuf,
1049 VGuint mode, VGuint start, VGuint count)
1050 {
1051 assert(renderer->state == RENDERER_STATE_POLYGON_STENCIL);
1052
1053 renderer->pipe->set_vertex_buffers(renderer->pipe, 1, vbuf);
1054
1055 if (!renderer->u.polygon_stencil.manual_two_sides) {
1056 util_draw_arrays(renderer->pipe, mode, start, count);
1057 }
1058 else {
1059 struct pipe_rasterizer_state raster;
1060 struct pipe_depth_stencil_alpha_state dsa;
1061
1062 raster = renderer->g3d.rasterizer;
1063 dsa = renderer->u.polygon_stencil.dsa;
1064
1065 /* front */
1066 raster.cull_face = PIPE_FACE_BACK;
1067 dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_INCR_WRAP;
1068
1069 cso_set_rasterizer(renderer->cso, &raster);
1070 cso_set_depth_stencil_alpha(renderer->cso, &dsa);
1071 util_draw_arrays(renderer->pipe, mode, start, count);
1072
1073 /* back */
1074 raster.cull_face = PIPE_FACE_FRONT;
1075 dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_DECR_WRAP;
1076
1077 cso_set_rasterizer(renderer->cso, &raster);
1078 cso_set_depth_stencil_alpha(renderer->cso, &dsa);
1079 util_draw_arrays(renderer->pipe, mode, start, count);
1080 }
1081 }
1082
1083 /**
1084 * End polygon silhouette rendering.
1085 */
1086 void renderer_polygon_stencil_end(struct renderer *renderer)
1087 {
1088 assert(renderer->state == RENDERER_STATE_POLYGON_STENCIL);
1089
1090 if (renderer->u.polygon_stencil.manual_two_sides)
1091 cso_restore_rasterizer(renderer->cso);
1092
1093 cso_restore_vertex_elements(renderer->cso);
1094
1095 /* restore color writes */
1096 cso_restore_blend(renderer->cso);
1097
1098 if (renderer->u.polygon_stencil.restore_dsa)
1099 cso_restore_depth_stencil_alpha(renderer->cso);
1100
1101 renderer->state = RENDERER_STATE_INIT;
1102 }
1103
1104 /**
1105 * Prepare the renderer for polygon filling.
1106 */
1107 VGboolean renderer_polygon_fill_begin(struct renderer *renderer,
1108 VGboolean save_dsa)
1109 {
1110 struct pipe_depth_stencil_alpha_state dsa;
1111
1112 assert(renderer->state == RENDERER_STATE_INIT);
1113
1114 if (save_dsa)
1115 cso_save_depth_stencil_alpha(renderer->cso);
1116
1117 /* setup stencil ops */
1118 memset(&dsa, 0, sizeof(dsa));
1119 dsa.stencil[0].enabled = 1;
1120 dsa.stencil[0].func = PIPE_FUNC_NOTEQUAL;
1121 dsa.stencil[0].fail_op = PIPE_STENCIL_OP_REPLACE;
1122 dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_REPLACE;
1123 dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_REPLACE;
1124 dsa.stencil[0].valuemask = ~0;
1125 dsa.stencil[0].writemask = ~0;
1126 dsa.depth = renderer->g3d.dsa.depth;
1127 cso_set_depth_stencil_alpha(renderer->cso, &dsa);
1128
1129 renderer->state = RENDERER_STATE_POLYGON_FILL;
1130
1131 return VG_TRUE;
1132 }
1133
1134 /**
1135 * Fill a polygon.
1136 */
1137 void renderer_polygon_fill(struct renderer *renderer,
1138 VGfloat min_x, VGfloat min_y,
1139 VGfloat max_x, VGfloat max_y)
1140 {
1141 assert(renderer->state == RENDERER_STATE_POLYGON_FILL);
1142
1143 renderer_quad_pos(renderer, min_x, min_y, max_x, max_y, VG_TRUE);
1144 renderer_quad_draw(renderer);
1145 }
1146
1147 /**
1148 * End polygon filling.
1149 */
1150 void renderer_polygon_fill_end(struct renderer *renderer)
1151 {
1152 assert(renderer->state == RENDERER_STATE_POLYGON_FILL);
1153
1154 cso_restore_depth_stencil_alpha(renderer->cso);
1155
1156 renderer->state = RENDERER_STATE_INIT;
1157 }
1158
1159 struct renderer * renderer_create(struct vg_context *owner)
1160 {
1161 struct renderer *renderer;
1162 struct pipe_rasterizer_state *raster;
1163 struct pipe_stencil_ref sr;
1164 VGint i;
1165
1166 renderer = CALLOC_STRUCT(renderer);
1167 if (!renderer)
1168 return NULL;
1169
1170 renderer->pipe = owner->pipe;
1171 renderer->cso = owner->cso_context;
1172
1173 /* init vertex data that doesn't change */
1174 for (i = 0; i < 4; i++)
1175 renderer->vertices[i][0][3] = 1.0f; /* w */
1176
1177 for (i = 0; i < 2; i++) {
1178 renderer->velems[i].src_offset = i * 4 * sizeof(float);
1179 renderer->velems[i].instance_divisor = 0;
1180 renderer->velems[i].vertex_buffer_index = 0;
1181 renderer->velems[i].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
1182 }
1183 cso_set_vertex_elements(renderer->cso, 2, renderer->velems);
1184
1185 /* GL rasterization rules */
1186 raster = &renderer->g3d.rasterizer;
1187 memset(raster, 0, sizeof(*raster));
1188 raster->gl_rasterization_rules = 1;
1189 cso_set_rasterizer(renderer->cso, raster);
1190
1191 /* fixed at 0 */
1192 memset(&sr, 0, sizeof(sr));
1193 cso_set_stencil_ref(renderer->cso, &sr);
1194
1195 renderer_set_vs(renderer, RENDERER_VS_PLAIN);
1196
1197 renderer->state = RENDERER_STATE_INIT;
1198
1199 return renderer;
1200 }
1201
1202 void renderer_destroy(struct renderer *ctx)
1203 {
1204 int i;
1205
1206 for (i = 0; i < NUM_RENDERER_VS; i++) {
1207 if (ctx->cached_vs[i])
1208 cso_delete_vertex_shader(ctx->cso, ctx->cached_vs[i]);
1209 }
1210 for (i = 0; i < NUM_RENDERER_FS; i++) {
1211 if (ctx->cached_fs[i])
1212 cso_delete_fragment_shader(ctx->cso, ctx->cached_fs[i]);
1213 }
1214
1215 pipe_resource_reference(&ctx->vs_cbuf, NULL);
1216 pipe_resource_reference(&ctx->fs_cbuf, NULL);
1217
1218 FREE(ctx);
1219 }
1220
1221 static void update_clip_state(struct renderer *renderer,
1222 const struct vg_state *state)
1223 {
1224 struct pipe_depth_stencil_alpha_state *dsa = &renderer->g3d.dsa;
1225
1226 memset(dsa, 0, sizeof(struct pipe_depth_stencil_alpha_state));
1227
1228 if (state->scissoring) {
1229 struct pipe_framebuffer_state *fb = &renderer->g3d.fb;
1230 int i;
1231
1232 renderer_scissor_begin(renderer, VG_FALSE);
1233
1234 for (i = 0; i < state->scissor_rects_num; ++i) {
1235 const float x = state->scissor_rects[i * 4 + 0].f;
1236 const float y = state->scissor_rects[i * 4 + 1].f;
1237 const float width = state->scissor_rects[i * 4 + 2].f;
1238 const float height = state->scissor_rects[i * 4 + 3].f;
1239 VGint x0, y0, x1, y1, iw, ih;
1240
1241 x0 = (VGint) x;
1242 y0 = (VGint) y;
1243 if (x0 < 0)
1244 x0 = 0;
1245 if (y0 < 0)
1246 y0 = 0;
1247
1248 /* note that x1 and y1 are exclusive */
1249 x1 = (VGint) ceilf(x + width);
1250 y1 = (VGint) ceilf(y + height);
1251 if (x1 > fb->width)
1252 x1 = fb->width;
1253 if (y1 > fb->height)
1254 y1 = fb->height;
1255
1256 iw = x1 - x0;
1257 ih = y1 - y0;
1258 if (iw > 0 && ih> 0 )
1259 renderer_scissor(renderer, x0, y0, iw, ih);
1260 }
1261
1262 renderer_scissor_end(renderer);
1263
1264 dsa->depth.enabled = 1; /* glEnable(GL_DEPTH_TEST); */
1265 dsa->depth.writemask = 0;/*glDepthMask(FALSE);*/
1266 dsa->depth.func = PIPE_FUNC_GEQUAL;
1267 }
1268 }
1269
1270 static void renderer_validate_blend(struct renderer *renderer,
1271 const struct vg_state *state,
1272 enum pipe_format fb_format)
1273 {
1274 struct pipe_blend_state blend;
1275
1276 memset(&blend, 0, sizeof(blend));
1277 blend.rt[0].colormask = PIPE_MASK_RGBA;
1278 blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE;
1279 blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
1280 blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
1281 blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
1282
1283 /* TODO alpha masking happens after blending? */
1284
1285 switch (state->blend_mode) {
1286 case VG_BLEND_SRC:
1287 blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE;
1288 blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
1289 blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
1290 blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
1291 break;
1292 case VG_BLEND_SRC_OVER:
1293 if (paint_is_opaque(state->fill_paint) &&
1294 paint_is_opaque(state->stroke_paint)) {
1295 /* no blending */
1296 }
1297 else if (!util_format_has_alpha(fb_format)) {
1298 blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_SRC_ALPHA;
1299 blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
1300 blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_INV_SRC_ALPHA;
1301 blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_INV_SRC_ALPHA;
1302 blend.rt[0].blend_enable = 1;
1303 }
1304 break;
1305 case VG_BLEND_SRC_IN:
1306 blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE;
1307 blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_DST_ALPHA;
1308 blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
1309 blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
1310 blend.rt[0].blend_enable = 1;
1311 break;
1312 case VG_BLEND_DST_IN:
1313 blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ZERO;
1314 blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ZERO;
1315 blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ONE;
1316 blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_SRC_ALPHA;
1317 blend.rt[0].blend_enable = 1;
1318 break;
1319 case VG_BLEND_DST_OVER:
1320 case VG_BLEND_MULTIPLY:
1321 case VG_BLEND_SCREEN:
1322 case VG_BLEND_DARKEN:
1323 case VG_BLEND_LIGHTEN:
1324 case VG_BLEND_ADDITIVE:
1325 /* need a shader */
1326 break;
1327 default:
1328 assert(!"not implemented blend mode");
1329 break;
1330 }
1331
1332 cso_set_blend(renderer->cso, &blend);
1333 }
1334
1335 /**
1336 * Propogate OpenVG state changes to the renderer. Only framebuffer, blending
1337 * and scissoring states are relevant here.
1338 */
1339 void renderer_validate(struct renderer *renderer,
1340 VGbitfield dirty,
1341 const struct st_framebuffer *stfb,
1342 const struct vg_state *state)
1343 {
1344 assert(renderer->state == RENDERER_STATE_INIT);
1345
1346 dirty |= renderer->dirty;
1347 renderer->dirty = 0;
1348
1349 if (dirty & FRAMEBUFFER_DIRTY) {
1350 struct pipe_framebuffer_state *fb = &renderer->g3d.fb;
1351 struct matrix *proj = &renderer->projection;
1352
1353 memset(fb, 0, sizeof(struct pipe_framebuffer_state));
1354 fb->width = stfb->width;
1355 fb->height = stfb->height;
1356 fb->nr_cbufs = 1;
1357 fb->cbufs[0] = stfb->strb->surface;
1358 fb->zsbuf = stfb->dsrb->surface;
1359
1360 cso_set_framebuffer(renderer->cso, fb);
1361 vg_set_viewport(renderer, VEGA_Y0_BOTTOM);
1362
1363 matrix_load_identity(proj);
1364 matrix_translate(proj, -1.0f, -1.0f);
1365 matrix_scale(proj, 2.0f / fb->width, 2.0f / fb->height);
1366
1367 /* we also got a new depth buffer */
1368 if (dirty & DEPTH_STENCIL_DIRTY) {
1369 renderer->pipe->clear(renderer->pipe,
1370 PIPE_CLEAR_DEPTHSTENCIL, NULL, 0.0, 0);
1371 }
1372 }
1373
1374 /* must be last because it renders to the depth buffer*/
1375 if (dirty & DEPTH_STENCIL_DIRTY) {
1376 update_clip_state(renderer, state);
1377 cso_set_depth_stencil_alpha(renderer->cso, &renderer->g3d.dsa);
1378 }
1379
1380 if (dirty & BLEND_DIRTY)
1381 renderer_validate_blend(renderer, state, stfb->strb->format);
1382 }
1383
1384 /**
1385 * Prepare the renderer for OpenVG pipeline.
1386 */
1387 void renderer_validate_for_shader(struct renderer *renderer,
1388 const struct pipe_sampler_state **samplers,
1389 struct pipe_sampler_view **views,
1390 VGint num_samplers,
1391 const struct matrix *modelview,
1392 void *fs,
1393 const void *const_buffer,
1394 VGint const_buffer_len)
1395 {
1396 struct matrix mvp = renderer->projection;
1397
1398 /* will be used in POLYGON_STENCIL and POLYGON_FILL */
1399 matrix_mult(&mvp, modelview);
1400 renderer_set_mvp(renderer, &mvp);
1401
1402 renderer_set_custom_fs(renderer, fs,
1403 samplers, views, num_samplers,
1404 const_buffer, const_buffer_len);
1405 }
1406
1407 void renderer_validate_for_mask_rendering(struct renderer *renderer,
1408 struct pipe_surface *dst,
1409 const struct matrix *modelview)
1410 {
1411 struct matrix mvp = renderer->projection;
1412
1413 /* will be used in POLYGON_STENCIL and POLYGON_FILL */
1414 matrix_mult(&mvp, modelview);
1415 renderer_set_mvp(renderer, &mvp);
1416
1417 renderer_set_target(renderer, dst, renderer->g3d.fb.zsbuf, VG_FALSE);
1418 renderer_set_blend(renderer, ~0);
1419 renderer_set_fs(renderer, RENDERER_FS_WHITE);
1420
1421 /* set internal dirty flags (hacky!) */
1422 renderer->dirty = FRAMEBUFFER_DIRTY | BLEND_DIRTY;
1423 }
1424
1425 void renderer_copy_surface(struct renderer *ctx,
1426 struct pipe_surface *src,
1427 int srcX0, int srcY0,
1428 int srcX1, int srcY1,
1429 struct pipe_surface *dst,
1430 int dstX0, int dstY0,
1431 int dstX1, int dstY1,
1432 float z, unsigned filter)
1433 {
1434 struct pipe_context *pipe = ctx->pipe;
1435 struct pipe_screen *screen = pipe->screen;
1436 struct pipe_sampler_view view_templ;
1437 struct pipe_sampler_view *view;
1438 struct pipe_box src_box;
1439 struct pipe_resource texTemp, *tex;
1440 const struct pipe_framebuffer_state *fb = &ctx->g3d.fb;
1441 const int srcW = abs(srcX1 - srcX0);
1442 const int srcH = abs(srcY1 - srcY0);
1443 const int srcLeft = MIN2(srcX0, srcX1);
1444 const int srcTop = MIN2(srcY0, srcY1);
1445
1446 assert(filter == PIPE_TEX_MIPFILTER_NEAREST ||
1447 filter == PIPE_TEX_MIPFILTER_LINEAR);
1448
1449 if (srcLeft != srcX0) {
1450 /* left-right flip */
1451 int tmp = dstX0;
1452 dstX0 = dstX1;
1453 dstX1 = tmp;
1454 }
1455
1456 if (srcTop != srcY0) {
1457 /* up-down flip */
1458 int tmp = dstY0;
1459 dstY0 = dstY1;
1460 dstY1 = tmp;
1461 }
1462
1463 assert(screen->is_format_supported(screen, src->format, PIPE_TEXTURE_2D,
1464 0, PIPE_BIND_SAMPLER_VIEW, 0));
1465 assert(screen->is_format_supported(screen, dst->format, PIPE_TEXTURE_2D,
1466 0, PIPE_BIND_SAMPLER_VIEW, 0));
1467 assert(screen->is_format_supported(screen, dst->format, PIPE_TEXTURE_2D,
1468 0, PIPE_BIND_RENDER_TARGET, 0));
1469
1470 /*
1471 * XXX for now we're always creating a temporary texture.
1472 * Strictly speaking that's not always needed.
1473 */
1474
1475 /* create temp texture */
1476 memset(&texTemp, 0, sizeof(texTemp));
1477 texTemp.target = PIPE_TEXTURE_2D;
1478 texTemp.format = src->format;
1479 texTemp.last_level = 0;
1480 texTemp.width0 = srcW;
1481 texTemp.height0 = srcH;
1482 texTemp.depth0 = 1;
1483 texTemp.array_size = 1;
1484 texTemp.bind = PIPE_BIND_SAMPLER_VIEW;
1485
1486 tex = screen->resource_create(screen, &texTemp);
1487 if (!tex)
1488 return;
1489
1490 u_sampler_view_default_template(&view_templ, tex, tex->format);
1491 view = pipe->create_sampler_view(pipe, tex, &view_templ);
1492
1493 if (!view)
1494 return;
1495
1496 u_box_2d_zslice(srcLeft, srcTop, src->u.tex.first_layer, srcW, srcH, &src_box);
1497
1498 pipe->resource_copy_region(pipe,
1499 tex, 0, 0, 0, 0, /* dest */
1500 src->texture, 0, &src_box);
1501
1502 assert(floatsEqual(z, 0.0f));
1503
1504 /* draw */
1505 if (fb->cbufs[0] == dst) {
1506 /* transform back to surface coordinates */
1507 dstY0 = dst->height - dstY0;
1508 dstY1 = dst->height - dstY1;
1509
1510 if (renderer_drawtex_begin(ctx, view)) {
1511 renderer_drawtex(ctx,
1512 dstX0, dstY0, dstX1 - dstX0, dstY1 - dstY0,
1513 0, 0, view->texture->width0, view->texture->height0);
1514 renderer_drawtex_end(ctx);
1515 }
1516 }
1517 else {
1518 if (renderer_copy_begin(ctx, dst, VG_TRUE, view)) {
1519 renderer_copy(ctx,
1520 dstX0, dstY0, dstX1 - dstX0, dstY1 - dstY0,
1521 0, 0, view->texture->width0, view->texture->height0);
1522 renderer_copy_end(ctx);
1523 }
1524 }
1525 }
1526
1527 void renderer_texture_quad(struct renderer *r,
1528 struct pipe_resource *tex,
1529 VGfloat x1offset, VGfloat y1offset,
1530 VGfloat x2offset, VGfloat y2offset,
1531 VGfloat x1, VGfloat y1,
1532 VGfloat x2, VGfloat y2,
1533 VGfloat x3, VGfloat y3,
1534 VGfloat x4, VGfloat y4)
1535 {
1536 const VGfloat z = 0.0f;
1537
1538 assert(r->state == RENDERER_STATE_INIT);
1539 assert(tex->width0 != 0);
1540 assert(tex->height0 != 0);
1541
1542 cso_save_vertex_shader(r->cso);
1543
1544 renderer_set_vs(r, RENDERER_VS_TEXTURE);
1545
1546 /* manually set up positions */
1547 r->vertices[0][0][0] = x1;
1548 r->vertices[0][0][1] = y1;
1549 r->vertices[0][0][2] = z;
1550
1551 r->vertices[1][0][0] = x2;
1552 r->vertices[1][0][1] = y2;
1553 r->vertices[1][0][2] = z;
1554
1555 r->vertices[2][0][0] = x3;
1556 r->vertices[2][0][1] = y3;
1557 r->vertices[2][0][2] = z;
1558
1559 r->vertices[3][0][0] = x4;
1560 r->vertices[3][0][1] = y4;
1561 r->vertices[3][0][2] = z;
1562
1563 /* texcoords */
1564 renderer_quad_texcoord(r, x1offset, y1offset,
1565 x2offset, y2offset, tex->width0, tex->height0);
1566
1567 renderer_quad_draw(r);
1568
1569 cso_restore_vertex_shader(r->cso);
1570 }