add1eec00385b11473aebace171a08f6e638488d
[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
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"
37
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"
45
46 #include "cso_cache/cso_context.h"
47 #include "tgsi/tgsi_ureg.h"
48
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;
60
61 typedef enum {
62 RENDERER_VS_PLAIN,
63 RENDERER_VS_COLOR,
64 RENDERER_VS_TEXTURE,
65 NUM_RENDERER_VS
66 } RendererVs;
67
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;
75
76 struct renderer {
77 struct pipe_context *pipe;
78 struct cso_context *cso;
79
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;
87
88 struct matrix mvp;
89 struct pipe_resource *vs_cbuf;
90
91 struct pipe_resource *fs_cbuf;
92 VGfloat fs_cbuf_data[32];
93 VGint fs_cbuf_len;
94
95 struct pipe_vertex_element velems[2];
96 VGfloat vertices[4][2][4];
97
98 void *cached_vs[NUM_RENDERER_VS];
99 void *cached_fs[NUM_RENDERER_FS];
100
101 RendererState state;
102
103 /* state data */
104 union {
105 struct {
106 VGint tex_width;
107 VGint tex_height;
108 } copy;
109
110 struct {
111 VGint tex_width;
112 VGint tex_height;
113 } drawtex;
114
115 struct {
116 VGboolean restore_dsa;
117 } scissor;
118
119 struct {
120 VGboolean use_sampler;
121 VGint tex_width, tex_height;
122 } filter;
123
124 struct {
125 struct pipe_depth_stencil_alpha_state dsa;
126 VGboolean manual_two_sides;
127 VGboolean restore_dsa;
128 } polygon_stencil;
129 } u;
130 };
131
132 /**
133 * Return VG_TRUE if the renderer can use the resource as the asked bindings.
134 */
135 static VGboolean renderer_can_support(struct renderer *renderer,
136 struct pipe_resource *res,
137 unsigned bindings)
138 {
139 struct pipe_screen *screen = renderer->pipe->screen;
140
141 return screen->is_format_supported(screen,
142 res->format, res->target, 0, bindings);
143 }
144
145 /**
146 * Set the model-view-projection matrix used by vertex shaders.
147 */
148 static void renderer_set_mvp(struct renderer *renderer,
149 const struct matrix *mvp)
150 {
151 struct matrix *cur = &renderer->mvp;
152 struct pipe_resource *cbuf;
153 VGfloat consts[3][4];
154 VGint i;
155
156 /* projection only */
157 if (!mvp)
158 mvp = &renderer->projection;
159
160 /* re-upload only if necessary */
161 if (memcmp(cur, mvp, sizeof(*mvp)) == 0)
162 return;
163
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];
170 }
171
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);
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, 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);
483
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;
488 }
489 else {
490 renderer->fs_cbuf_len = 0;
491 }
492 }
493 }
494 }
495
496 /**
497 * Setup renderer quad position.
498 */
499 static void renderer_quad_pos(struct renderer *r,
500 VGfloat x0, VGfloat y0,
501 VGfloat x1, VGfloat y1,
502 VGboolean scissor)
503 {
504 VGfloat z;
505
506 /* the depth test is used for scissoring */
507 z = (scissor) ? 0.0f : 1.0f;
508
509 /* positions */
510 r->vertices[0][0][0] = x0;
511 r->vertices[0][0][1] = y0;
512 r->vertices[0][0][2] = z;
513
514 r->vertices[1][0][0] = x1;
515 r->vertices[1][0][1] = y0;
516 r->vertices[1][0][2] = z;
517
518 r->vertices[2][0][0] = x1;
519 r->vertices[2][0][1] = y1;
520 r->vertices[2][0][2] = z;
521
522 r->vertices[3][0][0] = x0;
523 r->vertices[3][0][1] = y1;
524 r->vertices[3][0][2] = z;
525 }
526
527 /**
528 * Setup renderer quad texture coordinates.
529 */
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)
534 {
535 VGfloat s0, t0, s1, t1, r0, q0;
536 VGint i;
537
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;
544
545 /* texcoords */
546 r->vertices[0][1][0] = s0;
547 r->vertices[0][1][1] = t0;
548
549 r->vertices[1][1][0] = s1;
550 r->vertices[1][1][1] = t0;
551
552 r->vertices[2][1][0] = s1;
553 r->vertices[2][1][1] = t1;
554
555 r->vertices[3][1][0] = s0;
556 r->vertices[3][1][1] = t1;
557
558 for (i = 0; i < 4; i++) {
559 r->vertices[i][1][2] = r0;
560 r->vertices[i][1][3] = q0;
561 }
562 }
563
564 /**
565 * Draw renderer quad.
566 */
567 static void renderer_quad_draw(struct renderer *r)
568 {
569 struct pipe_resource *buf;
570
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 */
580
581 pipe_resource_reference(&buf, NULL);
582 }
583 }
584
585 /**
586 * Prepare the renderer for copying.
587 */
588 VGboolean renderer_copy_begin(struct renderer *renderer,
589 struct pipe_surface *dst,
590 VGboolean y0_top,
591 struct pipe_sampler_view *src)
592 {
593 assert(renderer->state == RENDERER_STATE_INIT);
594
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;
601
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);
609
610 renderer_set_target(renderer, dst, NULL, y0_top);
611
612 renderer_set_blend(renderer, ~0);
613 renderer_set_samplers(renderer, 1, &src);
614
615 renderer_set_fs(renderer, RENDERER_FS_TEXTURE);
616 renderer_set_vs(renderer, RENDERER_VS_TEXTURE);
617
618 renderer_set_mvp(renderer, NULL);
619
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;
624
625 return VG_TRUE;
626 }
627
628 /**
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).
631 *
632 * The coordinates are in surface coordinates.
633 */
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)
637 {
638 assert(renderer->state == RENDERER_STATE_COPY);
639
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);
645
646 renderer_quad_draw(renderer);
647 }
648
649 /**
650 * End copying and restore the states.
651 */
652 void renderer_copy_end(struct renderer *renderer)
653 {
654 assert(renderer->state == RENDERER_STATE_COPY);
655
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);
663
664 renderer->state = RENDERER_STATE_INIT;
665 }
666
667 /**
668 * Prepare the renderer for textured drawing.
669 */
670 VGboolean renderer_drawtex_begin(struct renderer *renderer,
671 struct pipe_sampler_view *src)
672 {
673 assert(renderer->state == RENDERER_STATE_INIT);
674
675 if (!renderer_can_support(renderer, src->texture, PIPE_BIND_SAMPLER_VIEW))
676 return VG_FALSE;
677
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);
683
684 renderer_set_blend(renderer, ~0);
685
686 renderer_set_samplers(renderer, 1, &src);
687
688 renderer_set_fs(renderer, RENDERER_FS_TEXTURE);
689 renderer_set_vs(renderer, RENDERER_VS_TEXTURE);
690
691 renderer_set_mvp(renderer, NULL);
692
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;
697
698 return VG_TRUE;
699 }
700
701 /**
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).
704 *
705 * The coordinates are in surface coordinates.
706 */
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)
710 {
711 assert(renderer->state == RENDERER_STATE_DRAWTEX);
712
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);
718
719 renderer_quad_draw(renderer);
720 }
721
722 /**
723 * End textured drawing and restore the states.
724 */
725 void renderer_drawtex_end(struct renderer *renderer)
726 {
727 assert(renderer->state == RENDERER_STATE_DRAWTEX);
728
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);
734
735 renderer->state = RENDERER_STATE_INIT;
736 }
737
738 /**
739 * Prepare the renderer for scissor update. This will reset the depth buffer
740 * to 1.0f.
741 */
742 VGboolean renderer_scissor_begin(struct renderer *renderer,
743 VGboolean restore_dsa)
744 {
745 struct pipe_depth_stencil_alpha_state dsa;
746
747 assert(renderer->state == RENDERER_STATE_INIT);
748
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);
753
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);
760
761 /* disable color writes */
762 renderer_set_blend(renderer, 0);
763 renderer_set_fs(renderer, RENDERER_FS_SCISSOR);
764
765 renderer_set_mvp(renderer, NULL);
766
767 renderer->u.scissor.restore_dsa = restore_dsa;
768 renderer->state = RENDERER_STATE_SCISSOR;
769
770 /* clear the depth buffer to 1.0f */
771 renderer->pipe->clear(renderer->pipe,
772 PIPE_CLEAR_DEPTHSTENCIL, NULL, 1.0f, 0);
773
774 return VG_TRUE;
775 }
776
777 /**
778 * Add a scissor rectangle. Depth values inside the rectangle will be set to
779 * 0.0f.
780 */
781 void renderer_scissor(struct renderer *renderer,
782 VGint x, VGint y, VGint width, VGint height)
783 {
784 assert(renderer->state == RENDERER_STATE_SCISSOR);
785
786 renderer_quad_pos(renderer, x, y, x + width, y + height, VG_FALSE);
787 renderer_quad_draw(renderer);
788 }
789
790 /**
791 * End scissor update and restore the states.
792 */
793 void renderer_scissor_end(struct renderer *renderer)
794 {
795 assert(renderer->state == RENDERER_STATE_SCISSOR);
796
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);
801
802 renderer->state = RENDERER_STATE_INIT;
803 }
804
805 /**
806 * Prepare the renderer for clearing.
807 */
808 VGboolean renderer_clear_begin(struct renderer *renderer)
809 {
810 assert(renderer->state == RENDERER_STATE_INIT);
811
812 cso_save_blend(renderer->cso);
813 cso_save_fragment_shader(renderer->cso);
814 cso_save_vertex_shader(renderer->cso);
815
816 renderer_set_blend(renderer, ~0);
817 renderer_set_fs(renderer, RENDERER_FS_COLOR);
818 renderer_set_vs(renderer, RENDERER_VS_COLOR);
819
820 renderer_set_mvp(renderer, NULL);
821
822 renderer->state = RENDERER_STATE_CLEAR;
823
824 return VG_TRUE;
825 }
826
827 /**
828 * Clear the framebuffer with the specified region and color.
829 *
830 * The coordinates are in surface coordinates.
831 */
832 void renderer_clear(struct renderer *renderer,
833 VGint x, VGint y, VGint width, VGint height,
834 const VGfloat color[4])
835 {
836 VGuint i;
837
838 assert(renderer->state == RENDERER_STATE_CLEAR);
839
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);
843
844 renderer_quad_draw(renderer);
845 }
846
847 /**
848 * End clearing and retore the states.
849 */
850 void renderer_clear_end(struct renderer *renderer)
851 {
852 assert(renderer->state == RENDERER_STATE_CLEAR);
853
854 cso_restore_blend(renderer->cso);
855 cso_restore_fragment_shader(renderer->cso);
856 cso_restore_vertex_shader(renderer->cso);
857
858 renderer->state = RENDERER_STATE_INIT;
859 }
860
861 /**
862 * Prepare the renderer for image filtering.
863 */
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)
874 {
875 struct pipe_surface *surf, surf_tmpl;
876
877 assert(renderer->state == RENDERER_STATE_INIT);
878
879 if (!fs)
880 return VG_FALSE;
881 if (!renderer_can_support(renderer, dst, PIPE_BIND_RENDER_TARGET))
882 return VG_FALSE;
883
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;
889
890 cso_save_framebuffer(renderer->cso);
891 cso_save_viewport(renderer->cso);
892 cso_save_blend(renderer->cso);
893
894 /* set the image as the target */
895 renderer_set_target(renderer, surf, NULL, y0_top);
896 pipe_surface_reference(&surf, NULL);
897
898 renderer_set_blend(renderer, channel_mask);
899
900 if (num_samplers) {
901 struct pipe_resource *tex;
902
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);
907
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);
912
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;
917 }
918 else {
919 cso_save_fragment_shader(renderer->cso);
920
921 renderer_set_custom_fs(renderer, fs, NULL, NULL, 0,
922 const_buffer, const_buffer_len);
923
924 renderer->u.filter.use_sampler = VG_FALSE;
925 }
926
927 renderer_set_mvp(renderer, NULL);
928
929 renderer->state = RENDERER_STATE_FILTER;
930
931 return VG_TRUE;
932 }
933
934 /**
935 * Draw into a rectangle of the destination with the specified region of the
936 * texture(s).
937 *
938 * The coordinates are in surface coordinates.
939 */
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)
943 {
944 assert(renderer->state == RENDERER_STATE_FILTER);
945
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);
951 }
952
953 renderer_quad_draw(renderer);
954 }
955
956 /**
957 * End image filtering and restore the states.
958 */
959 void renderer_filter_end(struct renderer *renderer)
960 {
961 assert(renderer->state == RENDERER_STATE_FILTER);
962
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);
967 }
968
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);
973
974 renderer->state = RENDERER_STATE_INIT;
975 }
976
977 /**
978 * Prepare the renderer for polygon silhouette rendering.
979 */
980 VGboolean renderer_polygon_stencil_begin(struct renderer *renderer,
981 struct pipe_vertex_element *velem,
982 VGFillRule rule,
983 VGboolean restore_dsa)
984 {
985 struct pipe_depth_stencil_alpha_state *dsa;
986 VGboolean manual_two_sides;
987
988 assert(renderer->state == RENDERER_STATE_INIT);
989
990 cso_save_vertex_elements(renderer->cso);
991 cso_save_blend(renderer->cso);
992 cso_save_depth_stencil_alpha(renderer->cso);
993
994 cso_set_vertex_elements(renderer->cso, 1, velem);
995
996 /* disable color writes */
997 renderer_set_blend(renderer, 0);
998
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;
1010 }
1011 else {
1012 assert(rule == VG_NON_ZERO);
1013
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;
1022
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;
1028 }
1029 else {
1030 manual_two_sides = VG_TRUE;
1031 }
1032 }
1033 cso_set_depth_stencil_alpha(renderer->cso, dsa);
1034
1035 if (manual_two_sides)
1036 cso_save_rasterizer(renderer->cso);
1037
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;
1041
1042 return VG_TRUE;
1043 }
1044
1045 /**
1046 * Render a polygon silhouette to stencil buffer.
1047 */
1048 void renderer_polygon_stencil(struct renderer *renderer,
1049 struct pipe_vertex_buffer *vbuf,
1050 VGuint mode, VGuint start, VGuint count)
1051 {
1052 assert(renderer->state == RENDERER_STATE_POLYGON_STENCIL);
1053
1054 cso_set_vertex_buffers(renderer->cso, 1, vbuf);
1055
1056 if (!renderer->u.polygon_stencil.manual_two_sides) {
1057 util_draw_arrays(renderer->pipe, mode, start, count);
1058 }
1059 else {
1060 struct pipe_rasterizer_state raster;
1061 struct pipe_depth_stencil_alpha_state dsa;
1062
1063 raster = renderer->g3d.rasterizer;
1064 dsa = renderer->u.polygon_stencil.dsa;
1065
1066 /* front */
1067 raster.cull_face = PIPE_FACE_BACK;
1068 dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_INCR_WRAP;
1069
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);
1073
1074 /* back */
1075 raster.cull_face = PIPE_FACE_FRONT;
1076 dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_DECR_WRAP;
1077
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);
1081 }
1082 }
1083
1084 /**
1085 * End polygon silhouette rendering.
1086 */
1087 void renderer_polygon_stencil_end(struct renderer *renderer)
1088 {
1089 assert(renderer->state == RENDERER_STATE_POLYGON_STENCIL);
1090
1091 if (renderer->u.polygon_stencil.manual_two_sides)
1092 cso_restore_rasterizer(renderer->cso);
1093
1094 cso_restore_vertex_elements(renderer->cso);
1095
1096 /* restore color writes */
1097 cso_restore_blend(renderer->cso);
1098
1099 if (renderer->u.polygon_stencil.restore_dsa)
1100 cso_restore_depth_stencil_alpha(renderer->cso);
1101
1102 renderer->state = RENDERER_STATE_INIT;
1103 }
1104
1105 /**
1106 * Prepare the renderer for polygon filling.
1107 */
1108 VGboolean renderer_polygon_fill_begin(struct renderer *renderer,
1109 VGboolean save_dsa)
1110 {
1111 struct pipe_depth_stencil_alpha_state dsa;
1112
1113 assert(renderer->state == RENDERER_STATE_INIT);
1114
1115 if (save_dsa)
1116 cso_save_depth_stencil_alpha(renderer->cso);
1117
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);
1129
1130 renderer->state = RENDERER_STATE_POLYGON_FILL;
1131
1132 return VG_TRUE;
1133 }
1134
1135 /**
1136 * Fill a polygon.
1137 */
1138 void renderer_polygon_fill(struct renderer *renderer,
1139 VGfloat min_x, VGfloat min_y,
1140 VGfloat max_x, VGfloat max_y)
1141 {
1142 assert(renderer->state == RENDERER_STATE_POLYGON_FILL);
1143
1144 renderer_quad_pos(renderer, min_x, min_y, max_x, max_y, VG_TRUE);
1145 renderer_quad_draw(renderer);
1146 }
1147
1148 /**
1149 * End polygon filling.
1150 */
1151 void renderer_polygon_fill_end(struct renderer *renderer)
1152 {
1153 assert(renderer->state == RENDERER_STATE_POLYGON_FILL);
1154
1155 cso_restore_depth_stencil_alpha(renderer->cso);
1156
1157 renderer->state = RENDERER_STATE_INIT;
1158 }
1159
1160 struct renderer * renderer_create(struct vg_context *owner)
1161 {
1162 struct renderer *renderer;
1163 struct pipe_rasterizer_state *raster;
1164 struct pipe_stencil_ref sr;
1165 VGint i;
1166
1167 renderer = CALLOC_STRUCT(renderer);
1168 if (!renderer)
1169 return NULL;
1170
1171 renderer->pipe = owner->pipe;
1172 renderer->cso = owner->cso_context;
1173
1174 /* init vertex data that doesn't change */
1175 for (i = 0; i < 4; i++)
1176 renderer->vertices[i][0][3] = 1.0f; /* w */
1177
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;
1183 }
1184 cso_set_vertex_elements(renderer->cso, 2, renderer->velems);
1185
1186 /* GL rasterization rules */
1187 raster = &renderer->g3d.rasterizer;
1188 memset(raster, 0, sizeof(*raster));
1189 raster->gl_rasterization_rules = 1;
1190 raster->depth_clip = 1;
1191 cso_set_rasterizer(renderer->cso, raster);
1192
1193 /* fixed at 0 */
1194 memset(&sr, 0, sizeof(sr));
1195 cso_set_stencil_ref(renderer->cso, &sr);
1196
1197 renderer_set_vs(renderer, RENDERER_VS_PLAIN);
1198
1199 renderer->state = RENDERER_STATE_INIT;
1200
1201 return renderer;
1202 }
1203
1204 void renderer_destroy(struct renderer *ctx)
1205 {
1206 int i;
1207
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]);
1211 }
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]);
1215 }
1216
1217 pipe_resource_reference(&ctx->vs_cbuf, NULL);
1218 pipe_resource_reference(&ctx->fs_cbuf, NULL);
1219
1220 FREE(ctx);
1221 }
1222
1223 static void update_clip_state(struct renderer *renderer,
1224 const struct vg_state *state)
1225 {
1226 struct pipe_depth_stencil_alpha_state *dsa = &renderer->g3d.dsa;
1227
1228 memset(dsa, 0, sizeof(struct pipe_depth_stencil_alpha_state));
1229
1230 if (state->scissoring) {
1231 struct pipe_framebuffer_state *fb = &renderer->g3d.fb;
1232 int i;
1233
1234 renderer_scissor_begin(renderer, VG_FALSE);
1235
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;
1242
1243 x0 = (VGint) x;
1244 y0 = (VGint) y;
1245 if (x0 < 0)
1246 x0 = 0;
1247 if (y0 < 0)
1248 y0 = 0;
1249
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;
1257
1258 iw = x1 - x0;
1259 ih = y1 - y0;
1260 if (iw > 0 && ih> 0 )
1261 renderer_scissor(renderer, x0, y0, iw, ih);
1262 }
1263
1264 renderer_scissor_end(renderer);
1265
1266 dsa->depth.enabled = 1; /* glEnable(GL_DEPTH_TEST); */
1267 dsa->depth.writemask = 0;/*glDepthMask(FALSE);*/
1268 dsa->depth.func = PIPE_FUNC_GEQUAL;
1269 }
1270 }
1271
1272 static void renderer_validate_blend(struct renderer *renderer,
1273 const struct vg_state *state,
1274 enum pipe_format fb_format)
1275 {
1276 struct pipe_blend_state blend;
1277
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;
1284
1285 /* TODO alpha masking happens after blending? */
1286
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 /* use the blend state only when there is no alpha channel */
1296 if (!util_format_has_alpha(fb_format)) {
1297 blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_SRC_ALPHA;
1298 blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
1299 blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_INV_SRC_ALPHA;
1300 blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_INV_SRC_ALPHA;
1301 blend.rt[0].blend_enable = 1;
1302 }
1303 break;
1304 case VG_BLEND_SRC_IN:
1305 blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE;
1306 blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_DST_ALPHA;
1307 blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
1308 blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
1309 blend.rt[0].blend_enable = 1;
1310 break;
1311 case VG_BLEND_DST_IN:
1312 blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ZERO;
1313 blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ZERO;
1314 blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ONE;
1315 blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_SRC_ALPHA;
1316 blend.rt[0].blend_enable = 1;
1317 break;
1318 case VG_BLEND_DST_OVER:
1319 case VG_BLEND_MULTIPLY:
1320 case VG_BLEND_SCREEN:
1321 case VG_BLEND_DARKEN:
1322 case VG_BLEND_LIGHTEN:
1323 case VG_BLEND_ADDITIVE:
1324 /* need a shader */
1325 break;
1326 default:
1327 assert(!"not implemented blend mode");
1328 break;
1329 }
1330
1331 cso_set_blend(renderer->cso, &blend);
1332 }
1333
1334 /**
1335 * Propogate OpenVG state changes to the renderer. Only framebuffer, blending
1336 * and scissoring states are relevant here.
1337 */
1338 void renderer_validate(struct renderer *renderer,
1339 VGbitfield dirty,
1340 const struct st_framebuffer *stfb,
1341 const struct vg_state *state)
1342 {
1343 assert(renderer->state == RENDERER_STATE_INIT);
1344
1345 dirty |= renderer->dirty;
1346 renderer->dirty = 0;
1347
1348 if (dirty & FRAMEBUFFER_DIRTY) {
1349 struct pipe_framebuffer_state *fb = &renderer->g3d.fb;
1350 struct matrix *proj = &renderer->projection;
1351
1352 memset(fb, 0, sizeof(struct pipe_framebuffer_state));
1353 fb->width = stfb->width;
1354 fb->height = stfb->height;
1355 fb->nr_cbufs = 1;
1356 fb->cbufs[0] = stfb->strb->surface;
1357 fb->zsbuf = stfb->dsrb->surface;
1358
1359 cso_set_framebuffer(renderer->cso, fb);
1360 vg_set_viewport(renderer, VEGA_Y0_BOTTOM);
1361
1362 matrix_load_identity(proj);
1363 matrix_translate(proj, -1.0f, -1.0f);
1364 matrix_scale(proj, 2.0f / fb->width, 2.0f / fb->height);
1365
1366 /* we also got a new depth buffer */
1367 if (dirty & DEPTH_STENCIL_DIRTY) {
1368 renderer->pipe->clear(renderer->pipe,
1369 PIPE_CLEAR_DEPTHSTENCIL, NULL, 0.0, 0);
1370 }
1371 }
1372
1373 /* must be last because it renders to the depth buffer*/
1374 if (dirty & DEPTH_STENCIL_DIRTY) {
1375 update_clip_state(renderer, state);
1376 cso_set_depth_stencil_alpha(renderer->cso, &renderer->g3d.dsa);
1377 }
1378
1379 if (dirty & BLEND_DIRTY)
1380 renderer_validate_blend(renderer, state, stfb->strb->format);
1381 }
1382
1383 /**
1384 * Prepare the renderer for OpenVG pipeline.
1385 */
1386 void renderer_validate_for_shader(struct renderer *renderer,
1387 const struct pipe_sampler_state **samplers,
1388 struct pipe_sampler_view **views,
1389 VGint num_samplers,
1390 const struct matrix *modelview,
1391 void *fs,
1392 const void *const_buffer,
1393 VGint const_buffer_len)
1394 {
1395 struct matrix mvp = renderer->projection;
1396
1397 /* will be used in POLYGON_STENCIL and POLYGON_FILL */
1398 matrix_mult(&mvp, modelview);
1399 renderer_set_mvp(renderer, &mvp);
1400
1401 renderer_set_custom_fs(renderer, fs,
1402 samplers, views, num_samplers,
1403 const_buffer, const_buffer_len);
1404 }
1405
1406 void renderer_validate_for_mask_rendering(struct renderer *renderer,
1407 struct pipe_surface *dst,
1408 const struct matrix *modelview)
1409 {
1410 struct matrix mvp = renderer->projection;
1411
1412 /* will be used in POLYGON_STENCIL and POLYGON_FILL */
1413 matrix_mult(&mvp, modelview);
1414 renderer_set_mvp(renderer, &mvp);
1415
1416 renderer_set_target(renderer, dst, renderer->g3d.fb.zsbuf, VG_FALSE);
1417 renderer_set_blend(renderer, ~0);
1418 renderer_set_fs(renderer, RENDERER_FS_WHITE);
1419
1420 /* set internal dirty flags (hacky!) */
1421 renderer->dirty = FRAMEBUFFER_DIRTY | BLEND_DIRTY;
1422 }
1423
1424 void renderer_copy_surface(struct renderer *ctx,
1425 struct pipe_surface *src,
1426 int srcX0, int srcY0,
1427 int srcX1, int srcY1,
1428 struct pipe_surface *dst,
1429 int dstX0, int dstY0,
1430 int dstX1, int dstY1,
1431 float z, unsigned filter)
1432 {
1433 struct pipe_context *pipe = ctx->pipe;
1434 struct pipe_screen *screen = pipe->screen;
1435 struct pipe_sampler_view view_templ;
1436 struct pipe_sampler_view *view;
1437 struct pipe_box src_box;
1438 struct pipe_resource texTemp, *tex;
1439 const struct pipe_framebuffer_state *fb = &ctx->g3d.fb;
1440 const int srcW = abs(srcX1 - srcX0);
1441 const int srcH = abs(srcY1 - srcY0);
1442 const int srcLeft = MIN2(srcX0, srcX1);
1443 const int srcTop = MIN2(srcY0, srcY1);
1444
1445 assert(filter == PIPE_TEX_MIPFILTER_NEAREST ||
1446 filter == PIPE_TEX_MIPFILTER_LINEAR);
1447
1448 if (srcLeft != srcX0) {
1449 /* left-right flip */
1450 int tmp = dstX0;
1451 dstX0 = dstX1;
1452 dstX1 = tmp;
1453 }
1454
1455 if (srcTop != srcY0) {
1456 /* up-down flip */
1457 int tmp = dstY0;
1458 dstY0 = dstY1;
1459 dstY1 = tmp;
1460 }
1461
1462 assert(screen->is_format_supported(screen, src->format, PIPE_TEXTURE_2D,
1463 0, PIPE_BIND_SAMPLER_VIEW));
1464 assert(screen->is_format_supported(screen, dst->format, PIPE_TEXTURE_2D,
1465 0, PIPE_BIND_SAMPLER_VIEW));
1466 assert(screen->is_format_supported(screen, dst->format, PIPE_TEXTURE_2D,
1467 0, PIPE_BIND_RENDER_TARGET));
1468
1469 /*
1470 * XXX for now we're always creating a temporary texture.
1471 * Strictly speaking that's not always needed.
1472 */
1473
1474 /* create temp texture */
1475 memset(&texTemp, 0, sizeof(texTemp));
1476 texTemp.target = PIPE_TEXTURE_2D;
1477 texTemp.format = src->format;
1478 texTemp.last_level = 0;
1479 texTemp.width0 = srcW;
1480 texTemp.height0 = srcH;
1481 texTemp.depth0 = 1;
1482 texTemp.array_size = 1;
1483 texTemp.bind = PIPE_BIND_SAMPLER_VIEW;
1484
1485 tex = screen->resource_create(screen, &texTemp);
1486 if (!tex)
1487 return;
1488
1489 u_sampler_view_default_template(&view_templ, tex, tex->format);
1490 view = pipe->create_sampler_view(pipe, tex, &view_templ);
1491
1492 if (!view)
1493 return;
1494
1495 u_box_2d_zslice(srcLeft, srcTop, src->u.tex.first_layer, srcW, srcH, &src_box);
1496
1497 pipe->resource_copy_region(pipe,
1498 tex, 0, 0, 0, 0, /* dest */
1499 src->texture, 0, &src_box);
1500
1501 assert(floatsEqual(z, 0.0f));
1502
1503 /* draw */
1504 if (fb->cbufs[0] == dst) {
1505 /* transform back to surface coordinates */
1506 dstY0 = dst->height - dstY0;
1507 dstY1 = dst->height - dstY1;
1508
1509 if (renderer_drawtex_begin(ctx, view)) {
1510 renderer_drawtex(ctx,
1511 dstX0, dstY0, dstX1 - dstX0, dstY1 - dstY0,
1512 0, 0, view->texture->width0, view->texture->height0);
1513 renderer_drawtex_end(ctx);
1514 }
1515 }
1516 else {
1517 if (renderer_copy_begin(ctx, dst, VG_TRUE, view)) {
1518 renderer_copy(ctx,
1519 dstX0, dstY0, dstX1 - dstX0, dstY1 - dstY0,
1520 0, 0, view->texture->width0, view->texture->height0);
1521 renderer_copy_end(ctx);
1522 }
1523 }
1524 }
1525
1526 void renderer_texture_quad(struct renderer *r,
1527 struct pipe_resource *tex,
1528 VGfloat x1offset, VGfloat y1offset,
1529 VGfloat x2offset, VGfloat y2offset,
1530 VGfloat x1, VGfloat y1,
1531 VGfloat x2, VGfloat y2,
1532 VGfloat x3, VGfloat y3,
1533 VGfloat x4, VGfloat y4)
1534 {
1535 const VGfloat z = 0.0f;
1536
1537 assert(r->state == RENDERER_STATE_INIT);
1538 assert(tex->width0 != 0);
1539 assert(tex->height0 != 0);
1540
1541 cso_save_vertex_shader(r->cso);
1542
1543 renderer_set_vs(r, RENDERER_VS_TEXTURE);
1544
1545 /* manually set up positions */
1546 r->vertices[0][0][0] = x1;
1547 r->vertices[0][0][1] = y1;
1548 r->vertices[0][0][2] = z;
1549
1550 r->vertices[1][0][0] = x2;
1551 r->vertices[1][0][1] = y2;
1552 r->vertices[1][0][2] = z;
1553
1554 r->vertices[2][0][0] = x3;
1555 r->vertices[2][0][1] = y3;
1556 r->vertices[2][0][2] = z;
1557
1558 r->vertices[3][0][0] = x4;
1559 r->vertices[3][0][1] = y4;
1560 r->vertices[3][0][2] = z;
1561
1562 /* texcoords */
1563 renderer_quad_texcoord(r, x1offset, y1offset,
1564 x2offset, y2offset, tex->width0, tex->height0);
1565
1566 renderer_quad_draw(r);
1567
1568 cso_restore_vertex_shader(r->cso);
1569 }