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