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