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