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 */
renderer_can_support(struct renderer * renderer,struct pipe_resource * res,unsigned bindings)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 */
renderer_set_mvp(struct renderer * renderer,const struct matrix * mvp)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 */
create_passthrough_vs(struct pipe_context * pipe,int semantic_name)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 */
renderer_set_vs(struct renderer * r,RendererVs id)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 */
create_scissor_fs(struct pipe_context * pipe)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 */
create_white_fs(struct pipe_context * pipe)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 */
renderer_set_fs(struct renderer * r,RendererFs id)303 static void renderer_set_fs(struct renderer *r, RendererFs id)
304 {
305 /* create as needed */
306 if (!r->cached_fs[id]) {
307 void *fs = NULL;
308
309 switch (id) {
310 case RENDERER_FS_COLOR:
311 fs = util_make_fragment_passthrough_shader(r->pipe);
312 break;
313 case RENDERER_FS_TEXTURE:
314 fs = util_make_fragment_tex_shader(r->pipe,
315 TGSI_TEXTURE_2D, TGSI_INTERPOLATE_LINEAR);
316 break;
317 case RENDERER_FS_SCISSOR:
318 fs = create_scissor_fs(r->pipe);
319 break;
320 case RENDERER_FS_WHITE:
321 fs = create_white_fs(r->pipe);
322 break;
323 default:
324 assert(!"Unknown renderer fs id");
325 break;
326 }
327
328 r->cached_fs[id] = fs;
329 }
330
331 cso_set_fragment_shader_handle(r->cso, r->cached_fs[id]);
332 }
333
334 typedef enum {
335 VEGA_Y0_TOP,
336 VEGA_Y0_BOTTOM
337 } VegaOrientation;
338
vg_set_viewport(struct renderer * r,VegaOrientation orientation)339 static void vg_set_viewport(struct renderer *r,
340 VegaOrientation orientation)
341 {
342 const struct pipe_framebuffer_state *fb = &r->g3d.fb;
343 struct pipe_viewport_state viewport;
344 VGfloat y_scale = (orientation == VEGA_Y0_BOTTOM) ? -2.f : 2.f;
345
346 viewport.scale[0] = fb->width / 2.f;
347 viewport.scale[1] = fb->height / y_scale;
348 viewport.scale[2] = 1.0;
349 viewport.scale[3] = 1.0;
350 viewport.translate[0] = fb->width / 2.f;
351 viewport.translate[1] = fb->height / 2.f;
352 viewport.translate[2] = 0.0;
353 viewport.translate[3] = 0.0;
354
355 cso_set_viewport(r->cso, &viewport);
356 }
357
358 /**
359 * Set renderer target.
360 *
361 * This function modifies framebuffer and viewport states.
362 */
renderer_set_target(struct renderer * r,struct pipe_surface * cbuf,struct pipe_surface * zsbuf,VGboolean y0_top)363 static void renderer_set_target(struct renderer *r,
364 struct pipe_surface *cbuf,
365 struct pipe_surface *zsbuf,
366 VGboolean y0_top)
367 {
368 struct pipe_framebuffer_state fb;
369
370 memset(&fb, 0, sizeof(fb));
371 fb.width = cbuf->width;
372 fb.height = cbuf->height;
373 fb.cbufs[0] = cbuf;
374 fb.nr_cbufs = 1;
375 fb.zsbuf = zsbuf;
376 cso_set_framebuffer(r->cso, &fb);
377
378 vg_set_viewport(r, (y0_top) ? VEGA_Y0_TOP : VEGA_Y0_BOTTOM);
379 }
380
381 /**
382 * Set renderer blend state. Blending is disabled.
383 *
384 * This function modifies blend state.
385 */
renderer_set_blend(struct renderer * r,VGbitfield channel_mask)386 static void renderer_set_blend(struct renderer *r,
387 VGbitfield channel_mask)
388 {
389 struct pipe_blend_state blend;
390
391 memset(&blend, 0, sizeof(blend));
392
393 blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE;
394 blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
395 blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
396 blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
397
398 if (channel_mask & VG_RED)
399 blend.rt[0].colormask |= PIPE_MASK_R;
400 if (channel_mask & VG_GREEN)
401 blend.rt[0].colormask |= PIPE_MASK_G;
402 if (channel_mask & VG_BLUE)
403 blend.rt[0].colormask |= PIPE_MASK_B;
404 if (channel_mask & VG_ALPHA)
405 blend.rt[0].colormask |= PIPE_MASK_A;
406
407 cso_set_blend(r->cso, &blend);
408 }
409
410 /**
411 * Set renderer sampler and view states.
412 *
413 * This function modifies samplers and fragment_sampler_views states.
414 */
renderer_set_samplers(struct renderer * r,uint num_views,struct pipe_sampler_view ** views)415 static void renderer_set_samplers(struct renderer *r,
416 uint num_views,
417 struct pipe_sampler_view **views)
418 {
419 struct pipe_sampler_state sampler;
420 unsigned tex_filter = PIPE_TEX_FILTER_NEAREST;
421 unsigned tex_wrap = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
422 uint i;
423
424 memset(&sampler, 0, sizeof(sampler));
425
426 sampler.min_img_filter = tex_filter;
427 sampler.mag_img_filter = tex_filter;
428 sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
429
430 sampler.wrap_s = tex_wrap;
431 sampler.wrap_t = tex_wrap;
432 sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
433
434 sampler.normalized_coords = 1;
435
436 /* set samplers */
437 for (i = 0; i < num_views; i++)
438 cso_single_sampler(r->cso, PIPE_SHADER_FRAGMENT, i, &sampler);
439 cso_single_sampler_done(r->cso, PIPE_SHADER_FRAGMENT);
440
441 /* set views */
442 cso_set_sampler_views(r->cso, PIPE_SHADER_FRAGMENT, num_views, views);
443 }
444
445 /**
446 * Set custom renderer fragment shader, and optionally set samplers and views
447 * and upload the fragment constant buffer.
448 *
449 * This function modifies fragment_shader, samplers and fragment_sampler_views
450 * states.
451 */
renderer_set_custom_fs(struct renderer * renderer,void * fs,const struct pipe_sampler_state ** samplers,struct pipe_sampler_view ** views,VGint num_samplers,const void * const_buffer,VGint const_buffer_len)452 static void renderer_set_custom_fs(struct renderer *renderer,
453 void *fs,
454 const struct pipe_sampler_state **samplers,
455 struct pipe_sampler_view **views,
456 VGint num_samplers,
457 const void *const_buffer,
458 VGint const_buffer_len)
459 {
460 cso_set_fragment_shader_handle(renderer->cso, fs);
461
462 /* set samplers and views */
463 if (num_samplers) {
464 cso_set_samplers(renderer->cso, PIPE_SHADER_FRAGMENT, num_samplers, samplers);
465 cso_set_sampler_views(renderer->cso, PIPE_SHADER_FRAGMENT, num_samplers, views);
466 }
467
468 /* upload fs constant buffer */
469 if (const_buffer_len) {
470 struct pipe_resource *cbuf = renderer->fs_cbuf;
471
472 if (!cbuf || renderer->fs_cbuf_len != const_buffer_len ||
473 memcmp(renderer->fs_cbuf_data, const_buffer, const_buffer_len)) {
474 pipe_resource_reference(&cbuf, NULL);
475
476 cbuf = pipe_buffer_create(renderer->pipe->screen,
477 PIPE_BIND_CONSTANT_BUFFER, PIPE_USAGE_STATIC,
478 const_buffer_len);
479 pipe_buffer_write(renderer->pipe, cbuf, 0,
480 const_buffer_len, const_buffer);
481 pipe_set_constant_buffer(renderer->pipe,
482 PIPE_SHADER_FRAGMENT, 0, cbuf);
483
484 renderer->fs_cbuf = cbuf;
485 if (const_buffer_len <= sizeof(renderer->fs_cbuf_data)) {
486 memcpy(renderer->fs_cbuf_data, const_buffer, const_buffer_len);
487 renderer->fs_cbuf_len = const_buffer_len;
488 }
489 else {
490 renderer->fs_cbuf_len = 0;
491 }
492 }
493 }
494 }
495
496 /**
497 * Setup renderer quad position.
498 */
renderer_quad_pos(struct renderer * r,VGfloat x0,VGfloat y0,VGfloat x1,VGfloat y1,VGboolean scissor)499 static void renderer_quad_pos(struct renderer *r,
500 VGfloat x0, VGfloat y0,
501 VGfloat x1, VGfloat y1,
502 VGboolean scissor)
503 {
504 VGfloat z;
505
506 /* the depth test is used for scissoring */
507 z = (scissor) ? 0.0f : 1.0f;
508
509 /* positions */
510 r->vertices[0][0][0] = x0;
511 r->vertices[0][0][1] = y0;
512 r->vertices[0][0][2] = z;
513
514 r->vertices[1][0][0] = x1;
515 r->vertices[1][0][1] = y0;
516 r->vertices[1][0][2] = z;
517
518 r->vertices[2][0][0] = x1;
519 r->vertices[2][0][1] = y1;
520 r->vertices[2][0][2] = z;
521
522 r->vertices[3][0][0] = x0;
523 r->vertices[3][0][1] = y1;
524 r->vertices[3][0][2] = z;
525 }
526
527 /**
528 * Setup renderer quad texture coordinates.
529 */
renderer_quad_texcoord(struct renderer * r,VGfloat x0,VGfloat y0,VGfloat x1,VGfloat y1,VGint tex_width,VGint tex_height)530 static void renderer_quad_texcoord(struct renderer *r,
531 VGfloat x0, VGfloat y0,
532 VGfloat x1, VGfloat y1,
533 VGint tex_width, VGint tex_height)
534 {
535 VGfloat s0, t0, s1, t1, r0, q0;
536 VGint i;
537
538 s0 = x0 / tex_width;
539 s1 = x1 / tex_width;
540 t0 = y0 / tex_height;
541 t1 = y1 / tex_height;
542 r0 = 0.0f;
543 q0 = 1.0f;
544
545 /* texcoords */
546 r->vertices[0][1][0] = s0;
547 r->vertices[0][1][1] = t0;
548
549 r->vertices[1][1][0] = s1;
550 r->vertices[1][1][1] = t0;
551
552 r->vertices[2][1][0] = s1;
553 r->vertices[2][1][1] = t1;
554
555 r->vertices[3][1][0] = s0;
556 r->vertices[3][1][1] = t1;
557
558 for (i = 0; i < 4; i++) {
559 r->vertices[i][1][2] = r0;
560 r->vertices[i][1][3] = q0;
561 }
562 }
563
564 /**
565 * Draw renderer quad.
566 */
renderer_quad_draw(struct renderer * r)567 static void renderer_quad_draw(struct renderer *r)
568 {
569 util_draw_user_vertex_buffer(r->cso, r->vertices, PIPE_PRIM_TRIANGLE_FAN,
570 Elements(r->vertices), /* verts */
571 Elements(r->vertices[0])); /* attribs/vert */
572 }
573
574 /**
575 * Prepare the renderer for copying.
576 */
renderer_copy_begin(struct renderer * renderer,struct pipe_surface * dst,VGboolean y0_top,struct pipe_sampler_view * src)577 VGboolean renderer_copy_begin(struct renderer *renderer,
578 struct pipe_surface *dst,
579 VGboolean y0_top,
580 struct pipe_sampler_view *src)
581 {
582 assert(renderer->state == RENDERER_STATE_INIT);
583
584 /* sanity check */
585 if (!renderer_can_support(renderer,
586 dst->texture, PIPE_BIND_RENDER_TARGET) ||
587 !renderer_can_support(renderer,
588 src->texture, PIPE_BIND_SAMPLER_VIEW))
589 return VG_FALSE;
590
591 cso_save_framebuffer(renderer->cso);
592 cso_save_viewport(renderer->cso);
593 cso_save_blend(renderer->cso);
594 cso_save_samplers(renderer->cso, PIPE_SHADER_FRAGMENT);
595 cso_save_sampler_views(renderer->cso, PIPE_SHADER_FRAGMENT);
596 cso_save_fragment_shader(renderer->cso);
597 cso_save_vertex_shader(renderer->cso);
598
599 renderer_set_target(renderer, dst, NULL, y0_top);
600
601 renderer_set_blend(renderer, ~0);
602 renderer_set_samplers(renderer, 1, &src);
603
604 renderer_set_fs(renderer, RENDERER_FS_TEXTURE);
605 renderer_set_vs(renderer, RENDERER_VS_TEXTURE);
606
607 renderer_set_mvp(renderer, NULL);
608
609 /* remember the texture size */
610 renderer->u.copy.tex_width = src->texture->width0;
611 renderer->u.copy.tex_height = src->texture->height0;
612 renderer->state = RENDERER_STATE_COPY;
613
614 return VG_TRUE;
615 }
616
617 /**
618 * Draw into the destination rectangle given by (x, y, w, h). The texture is
619 * sampled from within the rectangle given by (sx, sy, sw, sh).
620 *
621 * The coordinates are in surface coordinates.
622 */
renderer_copy(struct renderer * renderer,VGint x,VGint y,VGint w,VGint h,VGint sx,VGint sy,VGint sw,VGint sh)623 void renderer_copy(struct renderer *renderer,
624 VGint x, VGint y, VGint w, VGint h,
625 VGint sx, VGint sy, VGint sw, VGint sh)
626 {
627 assert(renderer->state == RENDERER_STATE_COPY);
628
629 /* there is no depth buffer for scissoring anyway */
630 renderer_quad_pos(renderer, x, y, x + w, y + h, VG_FALSE);
631 renderer_quad_texcoord(renderer, sx, sy, sx + sw, sy + sh,
632 renderer->u.copy.tex_width,
633 renderer->u.copy.tex_height);
634
635 renderer_quad_draw(renderer);
636 }
637
638 /**
639 * End copying and restore the states.
640 */
renderer_copy_end(struct renderer * renderer)641 void renderer_copy_end(struct renderer *renderer)
642 {
643 assert(renderer->state == RENDERER_STATE_COPY);
644
645 cso_restore_framebuffer(renderer->cso);
646 cso_restore_viewport(renderer->cso);
647 cso_restore_blend(renderer->cso);
648 cso_restore_samplers(renderer->cso, PIPE_SHADER_FRAGMENT);
649 cso_restore_sampler_views(renderer->cso, PIPE_SHADER_FRAGMENT);
650 cso_restore_fragment_shader(renderer->cso);
651 cso_restore_vertex_shader(renderer->cso);
652
653 renderer->state = RENDERER_STATE_INIT;
654 }
655
656 /**
657 * Prepare the renderer for textured drawing.
658 */
renderer_drawtex_begin(struct renderer * renderer,struct pipe_sampler_view * src)659 VGboolean renderer_drawtex_begin(struct renderer *renderer,
660 struct pipe_sampler_view *src)
661 {
662 assert(renderer->state == RENDERER_STATE_INIT);
663
664 if (!renderer_can_support(renderer, src->texture, PIPE_BIND_SAMPLER_VIEW))
665 return VG_FALSE;
666
667 cso_save_blend(renderer->cso);
668 cso_save_samplers(renderer->cso, PIPE_SHADER_FRAGMENT);
669 cso_save_sampler_views(renderer->cso, PIPE_SHADER_FRAGMENT);
670 cso_save_fragment_shader(renderer->cso);
671 cso_save_vertex_shader(renderer->cso);
672
673 renderer_set_blend(renderer, ~0);
674
675 renderer_set_samplers(renderer, 1, &src);
676
677 renderer_set_fs(renderer, RENDERER_FS_TEXTURE);
678 renderer_set_vs(renderer, RENDERER_VS_TEXTURE);
679
680 renderer_set_mvp(renderer, NULL);
681
682 /* remember the texture size */
683 renderer->u.drawtex.tex_width = src->texture->width0;
684 renderer->u.drawtex.tex_height = src->texture->height0;
685 renderer->state = RENDERER_STATE_DRAWTEX;
686
687 return VG_TRUE;
688 }
689
690 /**
691 * Draw into the destination rectangle given by (x, y, w, h). The texture is
692 * sampled from within the rectangle given by (sx, sy, sw, sh).
693 *
694 * The coordinates are in surface coordinates.
695 */
renderer_drawtex(struct renderer * renderer,VGint x,VGint y,VGint w,VGint h,VGint sx,VGint sy,VGint sw,VGint sh)696 void renderer_drawtex(struct renderer *renderer,
697 VGint x, VGint y, VGint w, VGint h,
698 VGint sx, VGint sy, VGint sw, VGint sh)
699 {
700 assert(renderer->state == RENDERER_STATE_DRAWTEX);
701
702 /* with scissoring */
703 renderer_quad_pos(renderer, x, y, x + w, y + h, VG_TRUE);
704 renderer_quad_texcoord(renderer, sx, sy, sx + sw, sy + sh,
705 renderer->u.drawtex.tex_width,
706 renderer->u.drawtex.tex_height);
707
708 renderer_quad_draw(renderer);
709 }
710
711 /**
712 * End textured drawing and restore the states.
713 */
renderer_drawtex_end(struct renderer * renderer)714 void renderer_drawtex_end(struct renderer *renderer)
715 {
716 assert(renderer->state == RENDERER_STATE_DRAWTEX);
717
718 cso_restore_blend(renderer->cso);
719 cso_restore_samplers(renderer->cso, PIPE_SHADER_FRAGMENT);
720 cso_restore_sampler_views(renderer->cso, PIPE_SHADER_FRAGMENT);
721 cso_restore_fragment_shader(renderer->cso);
722 cso_restore_vertex_shader(renderer->cso);
723
724 renderer->state = RENDERER_STATE_INIT;
725 }
726
727 /**
728 * Prepare the renderer for scissor update. This will reset the depth buffer
729 * to 1.0f.
730 */
renderer_scissor_begin(struct renderer * renderer,VGboolean restore_dsa)731 VGboolean renderer_scissor_begin(struct renderer *renderer,
732 VGboolean restore_dsa)
733 {
734 struct pipe_depth_stencil_alpha_state dsa;
735
736 assert(renderer->state == RENDERER_STATE_INIT);
737
738 if (restore_dsa)
739 cso_save_depth_stencil_alpha(renderer->cso);
740 cso_save_blend(renderer->cso);
741 cso_save_fragment_shader(renderer->cso);
742
743 /* enable depth writes */
744 memset(&dsa, 0, sizeof(dsa));
745 dsa.depth.enabled = 1;
746 dsa.depth.writemask = 1;
747 dsa.depth.func = PIPE_FUNC_ALWAYS;
748 cso_set_depth_stencil_alpha(renderer->cso, &dsa);
749
750 /* disable color writes */
751 renderer_set_blend(renderer, 0);
752 renderer_set_fs(renderer, RENDERER_FS_SCISSOR);
753
754 renderer_set_mvp(renderer, NULL);
755
756 renderer->u.scissor.restore_dsa = restore_dsa;
757 renderer->state = RENDERER_STATE_SCISSOR;
758
759 /* clear the depth buffer to 1.0f */
760 renderer->pipe->clear(renderer->pipe,
761 PIPE_CLEAR_DEPTHSTENCIL, NULL, 1.0f, 0);
762
763 return VG_TRUE;
764 }
765
766 /**
767 * Add a scissor rectangle. Depth values inside the rectangle will be set to
768 * 0.0f.
769 */
renderer_scissor(struct renderer * renderer,VGint x,VGint y,VGint width,VGint height)770 void renderer_scissor(struct renderer *renderer,
771 VGint x, VGint y, VGint width, VGint height)
772 {
773 assert(renderer->state == RENDERER_STATE_SCISSOR);
774
775 renderer_quad_pos(renderer, x, y, x + width, y + height, VG_FALSE);
776 renderer_quad_draw(renderer);
777 }
778
779 /**
780 * End scissor update and restore the states.
781 */
renderer_scissor_end(struct renderer * renderer)782 void renderer_scissor_end(struct renderer *renderer)
783 {
784 assert(renderer->state == RENDERER_STATE_SCISSOR);
785
786 if (renderer->u.scissor.restore_dsa)
787 cso_restore_depth_stencil_alpha(renderer->cso);
788 cso_restore_blend(renderer->cso);
789 cso_restore_fragment_shader(renderer->cso);
790
791 renderer->state = RENDERER_STATE_INIT;
792 }
793
794 /**
795 * Prepare the renderer for clearing.
796 */
renderer_clear_begin(struct renderer * renderer)797 VGboolean renderer_clear_begin(struct renderer *renderer)
798 {
799 assert(renderer->state == RENDERER_STATE_INIT);
800
801 cso_save_blend(renderer->cso);
802 cso_save_fragment_shader(renderer->cso);
803 cso_save_vertex_shader(renderer->cso);
804
805 renderer_set_blend(renderer, ~0);
806 renderer_set_fs(renderer, RENDERER_FS_COLOR);
807 renderer_set_vs(renderer, RENDERER_VS_COLOR);
808
809 renderer_set_mvp(renderer, NULL);
810
811 renderer->state = RENDERER_STATE_CLEAR;
812
813 return VG_TRUE;
814 }
815
816 /**
817 * Clear the framebuffer with the specified region and color.
818 *
819 * The coordinates are in surface coordinates.
820 */
renderer_clear(struct renderer * renderer,VGint x,VGint y,VGint width,VGint height,const VGfloat color[4])821 void renderer_clear(struct renderer *renderer,
822 VGint x, VGint y, VGint width, VGint height,
823 const VGfloat color[4])
824 {
825 VGuint i;
826
827 assert(renderer->state == RENDERER_STATE_CLEAR);
828
829 renderer_quad_pos(renderer, x, y, x + width, y + height, VG_TRUE);
830 for (i = 0; i < 4; i++)
831 memcpy(renderer->vertices[i][1], color, sizeof(VGfloat) * 4);
832
833 renderer_quad_draw(renderer);
834 }
835
836 /**
837 * End clearing and retore the states.
838 */
renderer_clear_end(struct renderer * renderer)839 void renderer_clear_end(struct renderer *renderer)
840 {
841 assert(renderer->state == RENDERER_STATE_CLEAR);
842
843 cso_restore_blend(renderer->cso);
844 cso_restore_fragment_shader(renderer->cso);
845 cso_restore_vertex_shader(renderer->cso);
846
847 renderer->state = RENDERER_STATE_INIT;
848 }
849
850 /**
851 * Prepare the renderer for image filtering.
852 */
renderer_filter_begin(struct renderer * renderer,struct pipe_resource * dst,VGboolean y0_top,VGbitfield channel_mask,const struct pipe_sampler_state ** samplers,struct pipe_sampler_view ** views,VGint num_samplers,void * fs,const void * const_buffer,VGint const_buffer_len)853 VGboolean renderer_filter_begin(struct renderer *renderer,
854 struct pipe_resource *dst,
855 VGboolean y0_top,
856 VGbitfield channel_mask,
857 const struct pipe_sampler_state **samplers,
858 struct pipe_sampler_view **views,
859 VGint num_samplers,
860 void *fs,
861 const void *const_buffer,
862 VGint const_buffer_len)
863 {
864 struct pipe_surface *surf, surf_tmpl;
865
866 assert(renderer->state == RENDERER_STATE_INIT);
867
868 if (!fs)
869 return VG_FALSE;
870 if (!renderer_can_support(renderer, dst, PIPE_BIND_RENDER_TARGET))
871 return VG_FALSE;
872
873 u_surface_default_template(&surf_tmpl, dst,
874 PIPE_BIND_RENDER_TARGET);
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 */
renderer_filter(struct renderer * renderer,VGint x,VGint y,VGint w,VGint h,VGint sx,VGint sy,VGint sw,VGint sh)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 */
renderer_filter_end(struct renderer * renderer)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 */
renderer_polygon_stencil_begin(struct renderer * renderer,struct pipe_vertex_element * velem,VGFillRule rule,VGboolean restore_dsa)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 */
renderer_polygon_stencil(struct renderer * renderer,struct pipe_vertex_buffer * vbuf,VGuint mode,VGuint start,VGuint count)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, 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 */
renderer_polygon_stencil_end(struct renderer * renderer)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 */
renderer_polygon_fill_begin(struct renderer * renderer,VGboolean save_dsa)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 */
renderer_polygon_fill(struct renderer * renderer,VGfloat min_x,VGfloat min_y,VGfloat max_x,VGfloat max_y)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 */
renderer_polygon_fill_end(struct renderer * renderer)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
renderer_create(struct vg_context * owner)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->gl_rasterization_rules = 1;
1179 raster->depth_clip = 1;
1180 cso_set_rasterizer(renderer->cso, raster);
1181
1182 /* fixed at 0 */
1183 memset(&sr, 0, sizeof(sr));
1184 cso_set_stencil_ref(renderer->cso, &sr);
1185
1186 renderer_set_vs(renderer, RENDERER_VS_PLAIN);
1187
1188 renderer->state = RENDERER_STATE_INIT;
1189
1190 return renderer;
1191 }
1192
renderer_destroy(struct renderer * ctx)1193 void renderer_destroy(struct renderer *ctx)
1194 {
1195 int i;
1196
1197 for (i = 0; i < NUM_RENDERER_VS; i++) {
1198 if (ctx->cached_vs[i])
1199 cso_delete_vertex_shader(ctx->cso, ctx->cached_vs[i]);
1200 }
1201 for (i = 0; i < NUM_RENDERER_FS; i++) {
1202 if (ctx->cached_fs[i])
1203 cso_delete_fragment_shader(ctx->cso, ctx->cached_fs[i]);
1204 }
1205
1206 pipe_resource_reference(&ctx->vs_cbuf, NULL);
1207 pipe_resource_reference(&ctx->fs_cbuf, NULL);
1208
1209 FREE(ctx);
1210 }
1211
update_clip_state(struct renderer * renderer,const struct vg_state * state)1212 static void update_clip_state(struct renderer *renderer,
1213 const struct vg_state *state)
1214 {
1215 struct pipe_depth_stencil_alpha_state *dsa = &renderer->g3d.dsa;
1216
1217 memset(dsa, 0, sizeof(struct pipe_depth_stencil_alpha_state));
1218
1219 if (state->scissoring) {
1220 struct pipe_framebuffer_state *fb = &renderer->g3d.fb;
1221 int i;
1222
1223 renderer_scissor_begin(renderer, VG_FALSE);
1224
1225 for (i = 0; i < state->scissor_rects_num; ++i) {
1226 const float x = state->scissor_rects[i * 4 + 0].f;
1227 const float y = state->scissor_rects[i * 4 + 1].f;
1228 const float width = state->scissor_rects[i * 4 + 2].f;
1229 const float height = state->scissor_rects[i * 4 + 3].f;
1230 VGint x0, y0, x1, y1, iw, ih;
1231
1232 x0 = (VGint) x;
1233 y0 = (VGint) y;
1234 if (x0 < 0)
1235 x0 = 0;
1236 if (y0 < 0)
1237 y0 = 0;
1238
1239 /* note that x1 and y1 are exclusive */
1240 x1 = (VGint) ceilf(x + width);
1241 y1 = (VGint) ceilf(y + height);
1242 if (x1 > fb->width)
1243 x1 = fb->width;
1244 if (y1 > fb->height)
1245 y1 = fb->height;
1246
1247 iw = x1 - x0;
1248 ih = y1 - y0;
1249 if (iw > 0 && ih> 0 )
1250 renderer_scissor(renderer, x0, y0, iw, ih);
1251 }
1252
1253 renderer_scissor_end(renderer);
1254
1255 dsa->depth.enabled = 1; /* glEnable(GL_DEPTH_TEST); */
1256 dsa->depth.writemask = 0;/*glDepthMask(FALSE);*/
1257 dsa->depth.func = PIPE_FUNC_GEQUAL;
1258 }
1259 }
1260
renderer_validate_blend(struct renderer * renderer,const struct vg_state * state,enum pipe_format fb_format)1261 static void renderer_validate_blend(struct renderer *renderer,
1262 const struct vg_state *state,
1263 enum pipe_format fb_format)
1264 {
1265 struct pipe_blend_state blend;
1266
1267 memset(&blend, 0, sizeof(blend));
1268 blend.rt[0].colormask = PIPE_MASK_RGBA;
1269 blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE;
1270 blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
1271 blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
1272 blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
1273
1274 /* TODO alpha masking happens after blending? */
1275
1276 switch (state->blend_mode) {
1277 case VG_BLEND_SRC:
1278 blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE;
1279 blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
1280 blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
1281 blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
1282 break;
1283 case VG_BLEND_SRC_OVER:
1284 /* use the blend state only when there is no alpha channel */
1285 if (!util_format_has_alpha(fb_format)) {
1286 blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_SRC_ALPHA;
1287 blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
1288 blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_INV_SRC_ALPHA;
1289 blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_INV_SRC_ALPHA;
1290 blend.rt[0].blend_enable = 1;
1291 }
1292 break;
1293 case VG_BLEND_SRC_IN:
1294 blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE;
1295 blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_DST_ALPHA;
1296 blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
1297 blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
1298 blend.rt[0].blend_enable = 1;
1299 break;
1300 case VG_BLEND_DST_IN:
1301 blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ZERO;
1302 blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ZERO;
1303 blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ONE;
1304 blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_SRC_ALPHA;
1305 blend.rt[0].blend_enable = 1;
1306 break;
1307 case VG_BLEND_DST_OVER:
1308 case VG_BLEND_MULTIPLY:
1309 case VG_BLEND_SCREEN:
1310 case VG_BLEND_DARKEN:
1311 case VG_BLEND_LIGHTEN:
1312 case VG_BLEND_ADDITIVE:
1313 /* need a shader */
1314 break;
1315 default:
1316 assert(!"not implemented blend mode");
1317 break;
1318 }
1319
1320 cso_set_blend(renderer->cso, &blend);
1321 }
1322
1323 /**
1324 * Propogate OpenVG state changes to the renderer. Only framebuffer, blending
1325 * and scissoring states are relevant here.
1326 */
renderer_validate(struct renderer * renderer,VGbitfield dirty,const struct st_framebuffer * stfb,const struct vg_state * state)1327 void renderer_validate(struct renderer *renderer,
1328 VGbitfield dirty,
1329 const struct st_framebuffer *stfb,
1330 const struct vg_state *state)
1331 {
1332 assert(renderer->state == RENDERER_STATE_INIT);
1333
1334 dirty |= renderer->dirty;
1335 renderer->dirty = 0;
1336
1337 if (dirty & FRAMEBUFFER_DIRTY) {
1338 struct pipe_framebuffer_state *fb = &renderer->g3d.fb;
1339 struct matrix *proj = &renderer->projection;
1340
1341 memset(fb, 0, sizeof(struct pipe_framebuffer_state));
1342 fb->width = stfb->width;
1343 fb->height = stfb->height;
1344 fb->nr_cbufs = 1;
1345 fb->cbufs[0] = stfb->strb->surface;
1346 fb->zsbuf = stfb->dsrb->surface;
1347
1348 cso_set_framebuffer(renderer->cso, fb);
1349 vg_set_viewport(renderer, VEGA_Y0_BOTTOM);
1350
1351 matrix_load_identity(proj);
1352 matrix_translate(proj, -1.0f, -1.0f);
1353 matrix_scale(proj, 2.0f / fb->width, 2.0f / fb->height);
1354
1355 /* we also got a new depth buffer */
1356 if (dirty & DEPTH_STENCIL_DIRTY) {
1357 renderer->pipe->clear(renderer->pipe,
1358 PIPE_CLEAR_DEPTHSTENCIL, NULL, 0.0, 0);
1359 }
1360 }
1361
1362 /* must be last because it renders to the depth buffer*/
1363 if (dirty & DEPTH_STENCIL_DIRTY) {
1364 update_clip_state(renderer, state);
1365 cso_set_depth_stencil_alpha(renderer->cso, &renderer->g3d.dsa);
1366 }
1367
1368 if (dirty & BLEND_DIRTY)
1369 renderer_validate_blend(renderer, state, stfb->strb->format);
1370 }
1371
1372 /**
1373 * Prepare the renderer for OpenVG pipeline.
1374 */
renderer_validate_for_shader(struct renderer * renderer,const struct pipe_sampler_state ** samplers,struct pipe_sampler_view ** views,VGint num_samplers,const struct matrix * modelview,void * fs,const void * const_buffer,VGint const_buffer_len)1375 void renderer_validate_for_shader(struct renderer *renderer,
1376 const struct pipe_sampler_state **samplers,
1377 struct pipe_sampler_view **views,
1378 VGint num_samplers,
1379 const struct matrix *modelview,
1380 void *fs,
1381 const void *const_buffer,
1382 VGint const_buffer_len)
1383 {
1384 struct matrix mvp = renderer->projection;
1385
1386 /* will be used in POLYGON_STENCIL and POLYGON_FILL */
1387 matrix_mult(&mvp, modelview);
1388 renderer_set_mvp(renderer, &mvp);
1389
1390 renderer_set_custom_fs(renderer, fs,
1391 samplers, views, num_samplers,
1392 const_buffer, const_buffer_len);
1393 }
1394
renderer_validate_for_mask_rendering(struct renderer * renderer,struct pipe_surface * dst,const struct matrix * modelview)1395 void renderer_validate_for_mask_rendering(struct renderer *renderer,
1396 struct pipe_surface *dst,
1397 const struct matrix *modelview)
1398 {
1399 struct matrix mvp = renderer->projection;
1400
1401 /* will be used in POLYGON_STENCIL and POLYGON_FILL */
1402 matrix_mult(&mvp, modelview);
1403 renderer_set_mvp(renderer, &mvp);
1404
1405 renderer_set_target(renderer, dst, renderer->g3d.fb.zsbuf, VG_FALSE);
1406 renderer_set_blend(renderer, ~0);
1407 renderer_set_fs(renderer, RENDERER_FS_WHITE);
1408
1409 /* set internal dirty flags (hacky!) */
1410 renderer->dirty = FRAMEBUFFER_DIRTY | BLEND_DIRTY;
1411 }
1412
renderer_copy_surface(struct renderer * ctx,struct pipe_surface * src,int srcX0,int srcY0,int srcX1,int srcY1,struct pipe_surface * dst,int dstX0,int dstY0,int dstX1,int dstY1,float z,unsigned filter)1413 void renderer_copy_surface(struct renderer *ctx,
1414 struct pipe_surface *src,
1415 int srcX0, int srcY0,
1416 int srcX1, int srcY1,
1417 struct pipe_surface *dst,
1418 int dstX0, int dstY0,
1419 int dstX1, int dstY1,
1420 float z, unsigned filter)
1421 {
1422 struct pipe_context *pipe = ctx->pipe;
1423 struct pipe_screen *screen = pipe->screen;
1424 struct pipe_sampler_view view_templ;
1425 struct pipe_sampler_view *view;
1426 struct pipe_box src_box;
1427 struct pipe_resource texTemp, *tex;
1428 const struct pipe_framebuffer_state *fb = &ctx->g3d.fb;
1429 const int srcW = abs(srcX1 - srcX0);
1430 const int srcH = abs(srcY1 - srcY0);
1431 const int srcLeft = MIN2(srcX0, srcX1);
1432 const int srcTop = MIN2(srcY0, srcY1);
1433
1434 assert(filter == PIPE_TEX_MIPFILTER_NEAREST ||
1435 filter == PIPE_TEX_MIPFILTER_LINEAR);
1436
1437 if (srcLeft != srcX0) {
1438 /* left-right flip */
1439 int tmp = dstX0;
1440 dstX0 = dstX1;
1441 dstX1 = tmp;
1442 }
1443
1444 if (srcTop != srcY0) {
1445 /* up-down flip */
1446 int tmp = dstY0;
1447 dstY0 = dstY1;
1448 dstY1 = tmp;
1449 }
1450
1451 assert(screen->is_format_supported(screen, src->format, PIPE_TEXTURE_2D,
1452 0, PIPE_BIND_SAMPLER_VIEW));
1453 assert(screen->is_format_supported(screen, dst->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_RENDER_TARGET));
1457
1458 /*
1459 * XXX for now we're always creating a temporary texture.
1460 * Strictly speaking that's not always needed.
1461 */
1462
1463 /* create temp texture */
1464 memset(&texTemp, 0, sizeof(texTemp));
1465 texTemp.target = PIPE_TEXTURE_2D;
1466 texTemp.format = src->format;
1467 texTemp.last_level = 0;
1468 texTemp.width0 = srcW;
1469 texTemp.height0 = srcH;
1470 texTemp.depth0 = 1;
1471 texTemp.array_size = 1;
1472 texTemp.bind = PIPE_BIND_SAMPLER_VIEW;
1473
1474 tex = screen->resource_create(screen, &texTemp);
1475 if (!tex)
1476 return;
1477
1478 u_sampler_view_default_template(&view_templ, tex, tex->format);
1479 view = pipe->create_sampler_view(pipe, tex, &view_templ);
1480
1481 if (!view)
1482 return;
1483
1484 u_box_2d_zslice(srcLeft, srcTop, src->u.tex.first_layer, srcW, srcH, &src_box);
1485
1486 pipe->resource_copy_region(pipe,
1487 tex, 0, 0, 0, 0, /* dest */
1488 src->texture, 0, &src_box);
1489
1490 assert(floatsEqual(z, 0.0f));
1491
1492 /* draw */
1493 if (fb->cbufs[0] == dst) {
1494 /* transform back to surface coordinates */
1495 dstY0 = dst->height - dstY0;
1496 dstY1 = dst->height - dstY1;
1497
1498 if (renderer_drawtex_begin(ctx, view)) {
1499 renderer_drawtex(ctx,
1500 dstX0, dstY0, dstX1 - dstX0, dstY1 - dstY0,
1501 0, 0, view->texture->width0, view->texture->height0);
1502 renderer_drawtex_end(ctx);
1503 }
1504 }
1505 else {
1506 if (renderer_copy_begin(ctx, dst, VG_TRUE, view)) {
1507 renderer_copy(ctx,
1508 dstX0, dstY0, dstX1 - dstX0, dstY1 - dstY0,
1509 0, 0, view->texture->width0, view->texture->height0);
1510 renderer_copy_end(ctx);
1511 }
1512 }
1513 }
1514
renderer_texture_quad(struct renderer * r,struct pipe_resource * tex,VGfloat x1offset,VGfloat y1offset,VGfloat x2offset,VGfloat y2offset,VGfloat x1,VGfloat y1,VGfloat x2,VGfloat y2,VGfloat x3,VGfloat y3,VGfloat x4,VGfloat y4)1515 void renderer_texture_quad(struct renderer *r,
1516 struct pipe_resource *tex,
1517 VGfloat x1offset, VGfloat y1offset,
1518 VGfloat x2offset, VGfloat y2offset,
1519 VGfloat x1, VGfloat y1,
1520 VGfloat x2, VGfloat y2,
1521 VGfloat x3, VGfloat y3,
1522 VGfloat x4, VGfloat y4)
1523 {
1524 const VGfloat z = 0.0f;
1525
1526 assert(r->state == RENDERER_STATE_INIT);
1527 assert(tex->width0 != 0);
1528 assert(tex->height0 != 0);
1529
1530 cso_save_vertex_shader(r->cso);
1531
1532 renderer_set_vs(r, RENDERER_VS_TEXTURE);
1533
1534 /* manually set up positions */
1535 r->vertices[0][0][0] = x1;
1536 r->vertices[0][0][1] = y1;
1537 r->vertices[0][0][2] = z;
1538
1539 r->vertices[1][0][0] = x2;
1540 r->vertices[1][0][1] = y2;
1541 r->vertices[1][0][2] = z;
1542
1543 r->vertices[2][0][0] = x3;
1544 r->vertices[2][0][1] = y3;
1545 r->vertices[2][0][2] = z;
1546
1547 r->vertices[3][0][0] = x4;
1548 r->vertices[3][0][1] = y4;
1549 r->vertices[3][0][2] = z;
1550
1551 /* texcoords */
1552 renderer_quad_texcoord(r, x1offset, y1offset,
1553 x2offset, y2offset, tex->width0, tex->height0);
1554
1555 renderer_quad_draw(r);
1556
1557 cso_restore_vertex_shader(r->cso);
1558 }
1559