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