1 /**************************************************************************
3 * Copyright 2009 VMware, Inc. All Rights Reserved.
4 * Copyright 2010 LunarG, Inc. All Rights Reserved.
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:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
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.
26 **************************************************************************/
30 #include "vg_context.h"
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"
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"
46 #include "cso_cache/cso_context.h"
47 #include "tgsi/tgsi_ureg.h"
52 RENDERER_STATE_DRAWTEX,
53 RENDERER_STATE_SCISSOR,
55 RENDERER_STATE_FILTER,
56 RENDERER_STATE_POLYGON_STENCIL,
57 RENDERER_STATE_POLYGON_FILL,
77 struct pipe_context *pipe;
78 struct cso_context *cso;
82 struct pipe_rasterizer_state rasterizer;
83 struct pipe_depth_stencil_alpha_state dsa;
84 struct pipe_framebuffer_state fb;
86 struct matrix projection;
89 struct pipe_resource *vs_cbuf;
91 struct pipe_resource *fs_cbuf;
92 VGfloat fs_cbuf_data[32];
95 struct pipe_vertex_element velems[2];
96 VGfloat vertices[4][2][4];
98 void *cached_vs[NUM_RENDERER_VS];
99 void *cached_fs[NUM_RENDERER_FS];
116 VGboolean restore_dsa;
120 VGboolean use_sampler;
121 VGint tex_width, tex_height;
125 struct pipe_depth_stencil_alpha_state dsa;
126 VGboolean manual_two_sides;
127 VGboolean restore_dsa;
133 * Return VG_TRUE if the renderer can use the resource as the asked bindings.
135 static VGboolean renderer_can_support(struct renderer *renderer,
136 struct pipe_resource *res,
139 struct pipe_screen *screen = renderer->pipe->screen;
141 return screen->is_format_supported(screen,
142 res->format, res->target, 0, bindings);
146 * Set the model-view-projection matrix used by vertex shaders.
148 static void renderer_set_mvp(struct renderer *renderer,
149 const struct matrix *mvp)
151 struct matrix *cur = &renderer->mvp;
152 struct pipe_resource *cbuf;
153 VGfloat consts[3][4];
156 /* projection only */
158 mvp = &renderer->projection;
160 /* re-upload only if necessary */
161 if (memcmp(cur, mvp, sizeof(*mvp)) == 0)
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];
169 consts[i][3] = mvp->m[i + 6];
172 cbuf = renderer->vs_cbuf;
173 pipe_resource_reference(&cbuf, NULL);
174 cbuf = pipe_buffer_create(renderer->pipe->screen,
175 PIPE_BIND_CONSTANT_BUFFER,
179 pipe_buffer_write(renderer->pipe, cbuf,
180 0, sizeof(consts), consts);
182 renderer->pipe->set_constant_buffer(renderer->pipe,
183 PIPE_SHADER_VERTEX, 0, cbuf);
185 memcpy(cur, mvp, sizeof(*mvp));
186 renderer->vs_cbuf = cbuf;
190 * Create a simple vertex shader that passes through position and the given
193 static void *create_passthrough_vs(struct pipe_context *pipe, int semantic_name)
195 struct ureg_program *ureg;
196 struct ureg_src src[2], constants[3];
197 struct ureg_dst dst[2], tmp;
200 ureg = ureg_create(TGSI_PROCESSOR_VERTEX);
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);
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));
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]);
226 return ureg_create_shader_and_destroy(ureg, pipe);
230 * Set renderer vertex shader.
232 * This function modifies vertex_shader state.
234 static void renderer_set_vs(struct renderer *r, RendererVs id)
236 /* create as needed */
237 if (!r->cached_vs[id]) {
238 int semantic_name = -1;
241 case RENDERER_VS_PLAIN:
243 case RENDERER_VS_COLOR:
244 semantic_name = TGSI_SEMANTIC_COLOR;
246 case RENDERER_VS_TEXTURE:
247 semantic_name = TGSI_SEMANTIC_GENERIC;
250 assert(!"Unknown renderer vs id");
254 r->cached_vs[id] = create_passthrough_vs(r->pipe, semantic_name);
257 cso_set_vertex_shader_handle(r->cso, r->cached_vs[id]);
261 * Create a simple fragment shader that sets the depth to 0.0f.
263 static void *create_scissor_fs(struct pipe_context *pipe)
265 struct ureg_program *ureg;
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);
273 ureg_MOV(ureg, ureg_writemask(out, TGSI_WRITEMASK_Z), imm);
276 return ureg_create_shader_and_destroy(ureg, pipe);
280 * Create a simple fragment shader that sets the color to white.
282 static void *create_white_fs(struct pipe_context *pipe)
284 struct ureg_program *ureg;
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);
292 ureg_MOV(ureg, out, imm);
295 return ureg_create_shader_and_destroy(ureg, pipe);
299 * Set renderer fragment shader.
301 * This function modifies fragment_shader state.
303 static void renderer_set_fs(struct renderer *r, RendererFs id)
305 /* create as needed */
306 if (!r->cached_fs[id]) {
310 case RENDERER_FS_COLOR:
311 fs = util_make_fragment_passthrough_shader(r->pipe);
313 case RENDERER_FS_TEXTURE:
314 fs = util_make_fragment_tex_shader(r->pipe,
315 TGSI_TEXTURE_2D, TGSI_INTERPOLATE_LINEAR);
317 case RENDERER_FS_SCISSOR:
318 fs = create_scissor_fs(r->pipe);
320 case RENDERER_FS_WHITE:
321 fs = create_white_fs(r->pipe);
324 assert(!"Unknown renderer fs id");
328 r->cached_fs[id] = fs;
331 cso_set_fragment_shader_handle(r->cso, r->cached_fs[id]);
339 static void vg_set_viewport(struct renderer *r,
340 VegaOrientation orientation)
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;
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;
355 cso_set_viewport(r->cso, &viewport);
359 * Set renderer target.
361 * This function modifies framebuffer and viewport states.
363 static void renderer_set_target(struct renderer *r,
364 struct pipe_surface *cbuf,
365 struct pipe_surface *zsbuf,
368 struct pipe_framebuffer_state fb;
370 memset(&fb, 0, sizeof(fb));
371 fb.width = cbuf->width;
372 fb.height = cbuf->height;
376 cso_set_framebuffer(r->cso, &fb);
378 vg_set_viewport(r, (y0_top) ? VEGA_Y0_TOP : VEGA_Y0_BOTTOM);
382 * Set renderer blend state. Blending is disabled.
384 * This function modifies blend state.
386 static void renderer_set_blend(struct renderer *r,
387 VGbitfield channel_mask)
389 struct pipe_blend_state blend;
391 memset(&blend, 0, sizeof(blend));
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;
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;
407 cso_set_blend(r->cso, &blend);
411 * Set renderer sampler and view states.
413 * This function modifies samplers and fragment_sampler_views states.
415 static void renderer_set_samplers(struct renderer *r,
417 struct pipe_sampler_view **views)
419 struct pipe_sampler_state sampler;
420 unsigned tex_filter = PIPE_TEX_FILTER_NEAREST;
421 unsigned tex_wrap = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
424 memset(&sampler, 0, sizeof(sampler));
426 sampler.min_img_filter = tex_filter;
427 sampler.mag_img_filter = tex_filter;
428 sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
430 sampler.wrap_s = tex_wrap;
431 sampler.wrap_t = tex_wrap;
432 sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
434 sampler.normalized_coords = 1;
437 for (i = 0; i < num_views; i++)
438 cso_single_sampler(r->cso, i, &sampler);
439 cso_single_sampler_done(r->cso);
442 cso_set_fragment_sampler_views(r->cso, num_views, views);
446 * Set custom renderer fragment shader, and optionally set samplers and views
447 * and upload the fragment constant buffer.
449 * This function modifies fragment_shader, samplers and fragment_sampler_views
452 static void renderer_set_custom_fs(struct renderer *renderer,
454 const struct pipe_sampler_state **samplers,
455 struct pipe_sampler_view **views,
457 const void *const_buffer,
458 VGint const_buffer_len)
460 cso_set_fragment_shader_handle(renderer->cso, fs);
462 /* set samplers and views */
464 cso_set_samplers(renderer->cso, num_samplers, samplers);
465 cso_set_fragment_sampler_views(renderer->cso, num_samplers, views);
468 /* upload fs constant buffer */
469 if (const_buffer_len) {
470 struct pipe_resource *cbuf = renderer->fs_cbuf;
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);
476 cbuf = pipe_buffer_create(renderer->pipe->screen,
477 PIPE_BIND_CONSTANT_BUFFER, PIPE_USAGE_STATIC,
479 pipe_buffer_write(renderer->pipe, cbuf, 0,
480 const_buffer_len, const_buffer);
481 renderer->pipe->set_constant_buffer(renderer->pipe,
482 PIPE_SHADER_FRAGMENT, 0, cbuf);
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;
490 renderer->fs_cbuf_len = 0;
497 * Setup renderer quad position.
499 static void renderer_quad_pos(struct renderer *r,
500 VGfloat x0, VGfloat y0,
501 VGfloat x1, VGfloat y1,
506 /* the depth test is used for scissoring */
507 z = (scissor) ? 0.0f : 1.0f;
510 r->vertices[0][0][0] = x0;
511 r->vertices[0][0][1] = y0;
512 r->vertices[0][0][2] = z;
514 r->vertices[1][0][0] = x1;
515 r->vertices[1][0][1] = y0;
516 r->vertices[1][0][2] = z;
518 r->vertices[2][0][0] = x1;
519 r->vertices[2][0][1] = y1;
520 r->vertices[2][0][2] = z;
522 r->vertices[3][0][0] = x0;
523 r->vertices[3][0][1] = y1;
524 r->vertices[3][0][2] = z;
528 * Setup renderer quad texture coordinates.
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)
535 VGfloat s0, t0, s1, t1, r0, q0;
540 t0 = y0 / tex_height;
541 t1 = y1 / tex_height;
546 r->vertices[0][1][0] = s0;
547 r->vertices[0][1][1] = t0;
549 r->vertices[1][1][0] = s1;
550 r->vertices[1][1][1] = t0;
552 r->vertices[2][1][0] = s1;
553 r->vertices[2][1][1] = t1;
555 r->vertices[3][1][0] = s0;
556 r->vertices[3][1][1] = t1;
558 for (i = 0; i < 4; i++) {
559 r->vertices[i][1][2] = r0;
560 r->vertices[i][1][3] = q0;
565 * Draw renderer quad.
567 static void renderer_quad_draw(struct renderer *r)
569 struct pipe_resource *buf;
571 buf = pipe_user_buffer_create(r->pipe->screen,
574 PIPE_BIND_VERTEX_BUFFER);
576 util_draw_vertex_buffer(r->pipe, r->cso, buf, 0,
577 PIPE_PRIM_TRIANGLE_FAN,
578 Elements(r->vertices), /* verts */
579 Elements(r->vertices[0])); /* attribs/vert */
581 pipe_resource_reference(&buf, NULL);
586 * Prepare the renderer for copying.
588 VGboolean renderer_copy_begin(struct renderer *renderer,
589 struct pipe_surface *dst,
591 struct pipe_sampler_view *src)
593 assert(renderer->state == RENDERER_STATE_INIT);
596 if (!renderer_can_support(renderer,
597 dst->texture, PIPE_BIND_RENDER_TARGET) ||
598 !renderer_can_support(renderer,
599 src->texture, PIPE_BIND_SAMPLER_VIEW))
602 cso_save_framebuffer(renderer->cso);
603 cso_save_viewport(renderer->cso);
604 cso_save_blend(renderer->cso);
605 cso_save_samplers(renderer->cso);
606 cso_save_fragment_sampler_views(renderer->cso);
607 cso_save_fragment_shader(renderer->cso);
608 cso_save_vertex_shader(renderer->cso);
610 renderer_set_target(renderer, dst, NULL, y0_top);
612 renderer_set_blend(renderer, ~0);
613 renderer_set_samplers(renderer, 1, &src);
615 renderer_set_fs(renderer, RENDERER_FS_TEXTURE);
616 renderer_set_vs(renderer, RENDERER_VS_TEXTURE);
618 renderer_set_mvp(renderer, NULL);
620 /* remember the texture size */
621 renderer->u.copy.tex_width = src->texture->width0;
622 renderer->u.copy.tex_height = src->texture->height0;
623 renderer->state = RENDERER_STATE_COPY;
629 * Draw into the destination rectangle given by (x, y, w, h). The texture is
630 * sampled from within the rectangle given by (sx, sy, sw, sh).
632 * The coordinates are in surface coordinates.
634 void renderer_copy(struct renderer *renderer,
635 VGint x, VGint y, VGint w, VGint h,
636 VGint sx, VGint sy, VGint sw, VGint sh)
638 assert(renderer->state == RENDERER_STATE_COPY);
640 /* there is no depth buffer for scissoring anyway */
641 renderer_quad_pos(renderer, x, y, x + w, y + h, VG_FALSE);
642 renderer_quad_texcoord(renderer, sx, sy, sx + sw, sy + sh,
643 renderer->u.copy.tex_width,
644 renderer->u.copy.tex_height);
646 renderer_quad_draw(renderer);
650 * End copying and restore the states.
652 void renderer_copy_end(struct renderer *renderer)
654 assert(renderer->state == RENDERER_STATE_COPY);
656 cso_restore_framebuffer(renderer->cso);
657 cso_restore_viewport(renderer->cso);
658 cso_restore_blend(renderer->cso);
659 cso_restore_samplers(renderer->cso);
660 cso_restore_fragment_sampler_views(renderer->cso);
661 cso_restore_fragment_shader(renderer->cso);
662 cso_restore_vertex_shader(renderer->cso);
664 renderer->state = RENDERER_STATE_INIT;
668 * Prepare the renderer for textured drawing.
670 VGboolean renderer_drawtex_begin(struct renderer *renderer,
671 struct pipe_sampler_view *src)
673 assert(renderer->state == RENDERER_STATE_INIT);
675 if (!renderer_can_support(renderer, src->texture, PIPE_BIND_SAMPLER_VIEW))
678 cso_save_blend(renderer->cso);
679 cso_save_samplers(renderer->cso);
680 cso_save_fragment_sampler_views(renderer->cso);
681 cso_save_fragment_shader(renderer->cso);
682 cso_save_vertex_shader(renderer->cso);
684 renderer_set_blend(renderer, ~0);
686 renderer_set_samplers(renderer, 1, &src);
688 renderer_set_fs(renderer, RENDERER_FS_TEXTURE);
689 renderer_set_vs(renderer, RENDERER_VS_TEXTURE);
691 renderer_set_mvp(renderer, NULL);
693 /* remember the texture size */
694 renderer->u.drawtex.tex_width = src->texture->width0;
695 renderer->u.drawtex.tex_height = src->texture->height0;
696 renderer->state = RENDERER_STATE_DRAWTEX;
702 * Draw into the destination rectangle given by (x, y, w, h). The texture is
703 * sampled from within the rectangle given by (sx, sy, sw, sh).
705 * The coordinates are in surface coordinates.
707 void renderer_drawtex(struct renderer *renderer,
708 VGint x, VGint y, VGint w, VGint h,
709 VGint sx, VGint sy, VGint sw, VGint sh)
711 assert(renderer->state == RENDERER_STATE_DRAWTEX);
713 /* with scissoring */
714 renderer_quad_pos(renderer, x, y, x + w, y + h, VG_TRUE);
715 renderer_quad_texcoord(renderer, sx, sy, sx + sw, sy + sh,
716 renderer->u.drawtex.tex_width,
717 renderer->u.drawtex.tex_height);
719 renderer_quad_draw(renderer);
723 * End textured drawing and restore the states.
725 void renderer_drawtex_end(struct renderer *renderer)
727 assert(renderer->state == RENDERER_STATE_DRAWTEX);
729 cso_restore_blend(renderer->cso);
730 cso_restore_samplers(renderer->cso);
731 cso_restore_fragment_sampler_views(renderer->cso);
732 cso_restore_fragment_shader(renderer->cso);
733 cso_restore_vertex_shader(renderer->cso);
735 renderer->state = RENDERER_STATE_INIT;
739 * Prepare the renderer for scissor update. This will reset the depth buffer
742 VGboolean renderer_scissor_begin(struct renderer *renderer,
743 VGboolean restore_dsa)
745 struct pipe_depth_stencil_alpha_state dsa;
747 assert(renderer->state == RENDERER_STATE_INIT);
750 cso_save_depth_stencil_alpha(renderer->cso);
751 cso_save_blend(renderer->cso);
752 cso_save_fragment_shader(renderer->cso);
754 /* enable depth writes */
755 memset(&dsa, 0, sizeof(dsa));
756 dsa.depth.enabled = 1;
757 dsa.depth.writemask = 1;
758 dsa.depth.func = PIPE_FUNC_ALWAYS;
759 cso_set_depth_stencil_alpha(renderer->cso, &dsa);
761 /* disable color writes */
762 renderer_set_blend(renderer, 0);
763 renderer_set_fs(renderer, RENDERER_FS_SCISSOR);
765 renderer_set_mvp(renderer, NULL);
767 renderer->u.scissor.restore_dsa = restore_dsa;
768 renderer->state = RENDERER_STATE_SCISSOR;
770 /* clear the depth buffer to 1.0f */
771 renderer->pipe->clear(renderer->pipe,
772 PIPE_CLEAR_DEPTHSTENCIL, NULL, 1.0f, 0);
778 * Add a scissor rectangle. Depth values inside the rectangle will be set to
781 void renderer_scissor(struct renderer *renderer,
782 VGint x, VGint y, VGint width, VGint height)
784 assert(renderer->state == RENDERER_STATE_SCISSOR);
786 renderer_quad_pos(renderer, x, y, x + width, y + height, VG_FALSE);
787 renderer_quad_draw(renderer);
791 * End scissor update and restore the states.
793 void renderer_scissor_end(struct renderer *renderer)
795 assert(renderer->state == RENDERER_STATE_SCISSOR);
797 if (renderer->u.scissor.restore_dsa)
798 cso_restore_depth_stencil_alpha(renderer->cso);
799 cso_restore_blend(renderer->cso);
800 cso_restore_fragment_shader(renderer->cso);
802 renderer->state = RENDERER_STATE_INIT;
806 * Prepare the renderer for clearing.
808 VGboolean renderer_clear_begin(struct renderer *renderer)
810 assert(renderer->state == RENDERER_STATE_INIT);
812 cso_save_blend(renderer->cso);
813 cso_save_fragment_shader(renderer->cso);
814 cso_save_vertex_shader(renderer->cso);
816 renderer_set_blend(renderer, ~0);
817 renderer_set_fs(renderer, RENDERER_FS_COLOR);
818 renderer_set_vs(renderer, RENDERER_VS_COLOR);
820 renderer_set_mvp(renderer, NULL);
822 renderer->state = RENDERER_STATE_CLEAR;
828 * Clear the framebuffer with the specified region and color.
830 * The coordinates are in surface coordinates.
832 void renderer_clear(struct renderer *renderer,
833 VGint x, VGint y, VGint width, VGint height,
834 const VGfloat color[4])
838 assert(renderer->state == RENDERER_STATE_CLEAR);
840 renderer_quad_pos(renderer, x, y, x + width, y + height, VG_TRUE);
841 for (i = 0; i < 4; i++)
842 memcpy(renderer->vertices[i][1], color, sizeof(VGfloat) * 4);
844 renderer_quad_draw(renderer);
848 * End clearing and retore the states.
850 void renderer_clear_end(struct renderer *renderer)
852 assert(renderer->state == RENDERER_STATE_CLEAR);
854 cso_restore_blend(renderer->cso);
855 cso_restore_fragment_shader(renderer->cso);
856 cso_restore_vertex_shader(renderer->cso);
858 renderer->state = RENDERER_STATE_INIT;
862 * Prepare the renderer for image filtering.
864 VGboolean renderer_filter_begin(struct renderer *renderer,
865 struct pipe_resource *dst,
867 VGbitfield channel_mask,
868 const struct pipe_sampler_state **samplers,
869 struct pipe_sampler_view **views,
872 const void *const_buffer,
873 VGint const_buffer_len)
875 struct pipe_surface *surf, surf_tmpl;
877 assert(renderer->state == RENDERER_STATE_INIT);
881 if (!renderer_can_support(renderer, dst, PIPE_BIND_RENDER_TARGET))
884 u_surface_default_template(&surf_tmpl, dst,
885 PIPE_BIND_RENDER_TARGET);
886 surf = renderer->pipe->create_surface(renderer->pipe, dst, &surf_tmpl);
890 cso_save_framebuffer(renderer->cso);
891 cso_save_viewport(renderer->cso);
892 cso_save_blend(renderer->cso);
894 /* set the image as the target */
895 renderer_set_target(renderer, surf, NULL, y0_top);
896 pipe_surface_reference(&surf, NULL);
898 renderer_set_blend(renderer, channel_mask);
901 struct pipe_resource *tex;
903 cso_save_samplers(renderer->cso);
904 cso_save_fragment_sampler_views(renderer->cso);
905 cso_save_fragment_shader(renderer->cso);
906 cso_save_vertex_shader(renderer->cso);
908 renderer_set_custom_fs(renderer, fs,
909 samplers, views, num_samplers,
910 const_buffer, const_buffer_len);
911 renderer_set_vs(renderer, RENDERER_VS_TEXTURE);
913 tex = views[0]->texture;
914 renderer->u.filter.tex_width = tex->width0;
915 renderer->u.filter.tex_height = tex->height0;
916 renderer->u.filter.use_sampler = VG_TRUE;
919 cso_save_fragment_shader(renderer->cso);
921 renderer_set_custom_fs(renderer, fs, NULL, NULL, 0,
922 const_buffer, const_buffer_len);
924 renderer->u.filter.use_sampler = VG_FALSE;
927 renderer_set_mvp(renderer, NULL);
929 renderer->state = RENDERER_STATE_FILTER;
935 * Draw into a rectangle of the destination with the specified region of the
938 * The coordinates are in surface coordinates.
940 void renderer_filter(struct renderer *renderer,
941 VGint x, VGint y, VGint w, VGint h,
942 VGint sx, VGint sy, VGint sw, VGint sh)
944 assert(renderer->state == RENDERER_STATE_FILTER);
946 renderer_quad_pos(renderer, x, y, x + w, y + h, VG_FALSE);
947 if (renderer->u.filter.use_sampler) {
948 renderer_quad_texcoord(renderer, sx, sy, sx + sw, sy + sh,
949 renderer->u.filter.tex_width,
950 renderer->u.filter.tex_height);
953 renderer_quad_draw(renderer);
957 * End image filtering and restore the states.
959 void renderer_filter_end(struct renderer *renderer)
961 assert(renderer->state == RENDERER_STATE_FILTER);
963 if (renderer->u.filter.use_sampler) {
964 cso_restore_samplers(renderer->cso);
965 cso_restore_fragment_sampler_views(renderer->cso);
966 cso_restore_vertex_shader(renderer->cso);
969 cso_restore_framebuffer(renderer->cso);
970 cso_restore_viewport(renderer->cso);
971 cso_restore_blend(renderer->cso);
972 cso_restore_fragment_shader(renderer->cso);
974 renderer->state = RENDERER_STATE_INIT;
978 * Prepare the renderer for polygon silhouette rendering.
980 VGboolean renderer_polygon_stencil_begin(struct renderer *renderer,
981 struct pipe_vertex_element *velem,
983 VGboolean restore_dsa)
985 struct pipe_depth_stencil_alpha_state *dsa;
986 VGboolean manual_two_sides;
988 assert(renderer->state == RENDERER_STATE_INIT);
990 cso_save_vertex_elements(renderer->cso);
991 cso_save_blend(renderer->cso);
992 cso_save_depth_stencil_alpha(renderer->cso);
994 cso_set_vertex_elements(renderer->cso, 1, velem);
996 /* disable color writes */
997 renderer_set_blend(renderer, 0);
999 manual_two_sides = VG_FALSE;
1000 dsa = &renderer->u.polygon_stencil.dsa;
1001 memset(dsa, 0, sizeof(*dsa));
1002 if (rule == VG_EVEN_ODD) {
1003 dsa->stencil[0].enabled = 1;
1004 dsa->stencil[0].writemask = 1;
1005 dsa->stencil[0].fail_op = PIPE_STENCIL_OP_KEEP;
1006 dsa->stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP;
1007 dsa->stencil[0].zpass_op = PIPE_STENCIL_OP_INVERT;
1008 dsa->stencil[0].func = PIPE_FUNC_ALWAYS;
1009 dsa->stencil[0].valuemask = ~0;
1012 assert(rule == VG_NON_ZERO);
1015 dsa->stencil[0].enabled = 1;
1016 dsa->stencil[0].writemask = ~0;
1017 dsa->stencil[0].fail_op = PIPE_STENCIL_OP_KEEP;
1018 dsa->stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP;
1019 dsa->stencil[0].zpass_op = PIPE_STENCIL_OP_INCR_WRAP;
1020 dsa->stencil[0].func = PIPE_FUNC_ALWAYS;
1021 dsa->stencil[0].valuemask = ~0;
1023 if (renderer->pipe->screen->get_param(renderer->pipe->screen,
1024 PIPE_CAP_TWO_SIDED_STENCIL)) {
1026 dsa->stencil[1] = dsa->stencil[0];
1027 dsa->stencil[1].zpass_op = PIPE_STENCIL_OP_DECR_WRAP;
1030 manual_two_sides = VG_TRUE;
1033 cso_set_depth_stencil_alpha(renderer->cso, dsa);
1035 if (manual_two_sides)
1036 cso_save_rasterizer(renderer->cso);
1038 renderer->u.polygon_stencil.manual_two_sides = manual_two_sides;
1039 renderer->u.polygon_stencil.restore_dsa = restore_dsa;
1040 renderer->state = RENDERER_STATE_POLYGON_STENCIL;
1046 * Render a polygon silhouette to stencil buffer.
1048 void renderer_polygon_stencil(struct renderer *renderer,
1049 struct pipe_vertex_buffer *vbuf,
1050 VGuint mode, VGuint start, VGuint count)
1052 assert(renderer->state == RENDERER_STATE_POLYGON_STENCIL);
1054 cso_set_vertex_buffers(renderer->cso, 1, vbuf);
1056 if (!renderer->u.polygon_stencil.manual_two_sides) {
1057 util_draw_arrays(renderer->pipe, mode, start, count);
1060 struct pipe_rasterizer_state raster;
1061 struct pipe_depth_stencil_alpha_state dsa;
1063 raster = renderer->g3d.rasterizer;
1064 dsa = renderer->u.polygon_stencil.dsa;
1067 raster.cull_face = PIPE_FACE_BACK;
1068 dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_INCR_WRAP;
1070 cso_set_rasterizer(renderer->cso, &raster);
1071 cso_set_depth_stencil_alpha(renderer->cso, &dsa);
1072 util_draw_arrays(renderer->pipe, mode, start, count);
1075 raster.cull_face = PIPE_FACE_FRONT;
1076 dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_DECR_WRAP;
1078 cso_set_rasterizer(renderer->cso, &raster);
1079 cso_set_depth_stencil_alpha(renderer->cso, &dsa);
1080 util_draw_arrays(renderer->pipe, mode, start, count);
1085 * End polygon silhouette rendering.
1087 void renderer_polygon_stencil_end(struct renderer *renderer)
1089 assert(renderer->state == RENDERER_STATE_POLYGON_STENCIL);
1091 if (renderer->u.polygon_stencil.manual_two_sides)
1092 cso_restore_rasterizer(renderer->cso);
1094 cso_restore_vertex_elements(renderer->cso);
1096 /* restore color writes */
1097 cso_restore_blend(renderer->cso);
1099 if (renderer->u.polygon_stencil.restore_dsa)
1100 cso_restore_depth_stencil_alpha(renderer->cso);
1102 renderer->state = RENDERER_STATE_INIT;
1106 * Prepare the renderer for polygon filling.
1108 VGboolean renderer_polygon_fill_begin(struct renderer *renderer,
1111 struct pipe_depth_stencil_alpha_state dsa;
1113 assert(renderer->state == RENDERER_STATE_INIT);
1116 cso_save_depth_stencil_alpha(renderer->cso);
1118 /* setup stencil ops */
1119 memset(&dsa, 0, sizeof(dsa));
1120 dsa.stencil[0].enabled = 1;
1121 dsa.stencil[0].func = PIPE_FUNC_NOTEQUAL;
1122 dsa.stencil[0].fail_op = PIPE_STENCIL_OP_REPLACE;
1123 dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_REPLACE;
1124 dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_REPLACE;
1125 dsa.stencil[0].valuemask = ~0;
1126 dsa.stencil[0].writemask = ~0;
1127 dsa.depth = renderer->g3d.dsa.depth;
1128 cso_set_depth_stencil_alpha(renderer->cso, &dsa);
1130 renderer->state = RENDERER_STATE_POLYGON_FILL;
1138 void renderer_polygon_fill(struct renderer *renderer,
1139 VGfloat min_x, VGfloat min_y,
1140 VGfloat max_x, VGfloat max_y)
1142 assert(renderer->state == RENDERER_STATE_POLYGON_FILL);
1144 renderer_quad_pos(renderer, min_x, min_y, max_x, max_y, VG_TRUE);
1145 renderer_quad_draw(renderer);
1149 * End polygon filling.
1151 void renderer_polygon_fill_end(struct renderer *renderer)
1153 assert(renderer->state == RENDERER_STATE_POLYGON_FILL);
1155 cso_restore_depth_stencil_alpha(renderer->cso);
1157 renderer->state = RENDERER_STATE_INIT;
1160 struct renderer * renderer_create(struct vg_context *owner)
1162 struct renderer *renderer;
1163 struct pipe_rasterizer_state *raster;
1164 struct pipe_stencil_ref sr;
1167 renderer = CALLOC_STRUCT(renderer);
1171 renderer->pipe = owner->pipe;
1172 renderer->cso = owner->cso_context;
1174 /* init vertex data that doesn't change */
1175 for (i = 0; i < 4; i++)
1176 renderer->vertices[i][0][3] = 1.0f; /* w */
1178 for (i = 0; i < 2; i++) {
1179 renderer->velems[i].src_offset = i * 4 * sizeof(float);
1180 renderer->velems[i].instance_divisor = 0;
1181 renderer->velems[i].vertex_buffer_index = 0;
1182 renderer->velems[i].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
1184 cso_set_vertex_elements(renderer->cso, 2, renderer->velems);
1186 /* GL rasterization rules */
1187 raster = &renderer->g3d.rasterizer;
1188 memset(raster, 0, sizeof(*raster));
1189 raster->gl_rasterization_rules = 1;
1190 raster->depth_clip = 1;
1191 cso_set_rasterizer(renderer->cso, raster);
1194 memset(&sr, 0, sizeof(sr));
1195 cso_set_stencil_ref(renderer->cso, &sr);
1197 renderer_set_vs(renderer, RENDERER_VS_PLAIN);
1199 renderer->state = RENDERER_STATE_INIT;
1204 void renderer_destroy(struct renderer *ctx)
1208 for (i = 0; i < NUM_RENDERER_VS; i++) {
1209 if (ctx->cached_vs[i])
1210 cso_delete_vertex_shader(ctx->cso, ctx->cached_vs[i]);
1212 for (i = 0; i < NUM_RENDERER_FS; i++) {
1213 if (ctx->cached_fs[i])
1214 cso_delete_fragment_shader(ctx->cso, ctx->cached_fs[i]);
1217 pipe_resource_reference(&ctx->vs_cbuf, NULL);
1218 pipe_resource_reference(&ctx->fs_cbuf, NULL);
1223 static void update_clip_state(struct renderer *renderer,
1224 const struct vg_state *state)
1226 struct pipe_depth_stencil_alpha_state *dsa = &renderer->g3d.dsa;
1228 memset(dsa, 0, sizeof(struct pipe_depth_stencil_alpha_state));
1230 if (state->scissoring) {
1231 struct pipe_framebuffer_state *fb = &renderer->g3d.fb;
1234 renderer_scissor_begin(renderer, VG_FALSE);
1236 for (i = 0; i < state->scissor_rects_num; ++i) {
1237 const float x = state->scissor_rects[i * 4 + 0].f;
1238 const float y = state->scissor_rects[i * 4 + 1].f;
1239 const float width = state->scissor_rects[i * 4 + 2].f;
1240 const float height = state->scissor_rects[i * 4 + 3].f;
1241 VGint x0, y0, x1, y1, iw, ih;
1250 /* note that x1 and y1 are exclusive */
1251 x1 = (VGint) ceilf(x + width);
1252 y1 = (VGint) ceilf(y + height);
1255 if (y1 > fb->height)
1260 if (iw > 0 && ih> 0 )
1261 renderer_scissor(renderer, x0, y0, iw, ih);
1264 renderer_scissor_end(renderer);
1266 dsa->depth.enabled = 1; /* glEnable(GL_DEPTH_TEST); */
1267 dsa->depth.writemask = 0;/*glDepthMask(FALSE);*/
1268 dsa->depth.func = PIPE_FUNC_GEQUAL;
1272 static void renderer_validate_blend(struct renderer *renderer,
1273 const struct vg_state *state,
1274 enum pipe_format fb_format)
1276 struct pipe_blend_state blend;
1278 memset(&blend, 0, sizeof(blend));
1279 blend.rt[0].colormask = PIPE_MASK_RGBA;
1280 blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE;
1281 blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
1282 blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
1283 blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
1285 /* TODO alpha masking happens after blending? */
1287 switch (state->blend_mode) {
1289 blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE;
1290 blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
1291 blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
1292 blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
1294 case VG_BLEND_SRC_OVER:
1295 /* use the blend state only when there is no alpha channel */
1296 if (!util_format_has_alpha(fb_format)) {
1297 blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_SRC_ALPHA;
1298 blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
1299 blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_INV_SRC_ALPHA;
1300 blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_INV_SRC_ALPHA;
1301 blend.rt[0].blend_enable = 1;
1304 case VG_BLEND_SRC_IN:
1305 blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE;
1306 blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_DST_ALPHA;
1307 blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
1308 blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
1309 blend.rt[0].blend_enable = 1;
1311 case VG_BLEND_DST_IN:
1312 blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ZERO;
1313 blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ZERO;
1314 blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ONE;
1315 blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_SRC_ALPHA;
1316 blend.rt[0].blend_enable = 1;
1318 case VG_BLEND_DST_OVER:
1319 case VG_BLEND_MULTIPLY:
1320 case VG_BLEND_SCREEN:
1321 case VG_BLEND_DARKEN:
1322 case VG_BLEND_LIGHTEN:
1323 case VG_BLEND_ADDITIVE:
1327 assert(!"not implemented blend mode");
1331 cso_set_blend(renderer->cso, &blend);
1335 * Propogate OpenVG state changes to the renderer. Only framebuffer, blending
1336 * and scissoring states are relevant here.
1338 void renderer_validate(struct renderer *renderer,
1340 const struct st_framebuffer *stfb,
1341 const struct vg_state *state)
1343 assert(renderer->state == RENDERER_STATE_INIT);
1345 dirty |= renderer->dirty;
1346 renderer->dirty = 0;
1348 if (dirty & FRAMEBUFFER_DIRTY) {
1349 struct pipe_framebuffer_state *fb = &renderer->g3d.fb;
1350 struct matrix *proj = &renderer->projection;
1352 memset(fb, 0, sizeof(struct pipe_framebuffer_state));
1353 fb->width = stfb->width;
1354 fb->height = stfb->height;
1356 fb->cbufs[0] = stfb->strb->surface;
1357 fb->zsbuf = stfb->dsrb->surface;
1359 cso_set_framebuffer(renderer->cso, fb);
1360 vg_set_viewport(renderer, VEGA_Y0_BOTTOM);
1362 matrix_load_identity(proj);
1363 matrix_translate(proj, -1.0f, -1.0f);
1364 matrix_scale(proj, 2.0f / fb->width, 2.0f / fb->height);
1366 /* we also got a new depth buffer */
1367 if (dirty & DEPTH_STENCIL_DIRTY) {
1368 renderer->pipe->clear(renderer->pipe,
1369 PIPE_CLEAR_DEPTHSTENCIL, NULL, 0.0, 0);
1373 /* must be last because it renders to the depth buffer*/
1374 if (dirty & DEPTH_STENCIL_DIRTY) {
1375 update_clip_state(renderer, state);
1376 cso_set_depth_stencil_alpha(renderer->cso, &renderer->g3d.dsa);
1379 if (dirty & BLEND_DIRTY)
1380 renderer_validate_blend(renderer, state, stfb->strb->format);
1384 * Prepare the renderer for OpenVG pipeline.
1386 void renderer_validate_for_shader(struct renderer *renderer,
1387 const struct pipe_sampler_state **samplers,
1388 struct pipe_sampler_view **views,
1390 const struct matrix *modelview,
1392 const void *const_buffer,
1393 VGint const_buffer_len)
1395 struct matrix mvp = renderer->projection;
1397 /* will be used in POLYGON_STENCIL and POLYGON_FILL */
1398 matrix_mult(&mvp, modelview);
1399 renderer_set_mvp(renderer, &mvp);
1401 renderer_set_custom_fs(renderer, fs,
1402 samplers, views, num_samplers,
1403 const_buffer, const_buffer_len);
1406 void renderer_validate_for_mask_rendering(struct renderer *renderer,
1407 struct pipe_surface *dst,
1408 const struct matrix *modelview)
1410 struct matrix mvp = renderer->projection;
1412 /* will be used in POLYGON_STENCIL and POLYGON_FILL */
1413 matrix_mult(&mvp, modelview);
1414 renderer_set_mvp(renderer, &mvp);
1416 renderer_set_target(renderer, dst, renderer->g3d.fb.zsbuf, VG_FALSE);
1417 renderer_set_blend(renderer, ~0);
1418 renderer_set_fs(renderer, RENDERER_FS_WHITE);
1420 /* set internal dirty flags (hacky!) */
1421 renderer->dirty = FRAMEBUFFER_DIRTY | BLEND_DIRTY;
1424 void renderer_copy_surface(struct renderer *ctx,
1425 struct pipe_surface *src,
1426 int srcX0, int srcY0,
1427 int srcX1, int srcY1,
1428 struct pipe_surface *dst,
1429 int dstX0, int dstY0,
1430 int dstX1, int dstY1,
1431 float z, unsigned filter)
1433 struct pipe_context *pipe = ctx->pipe;
1434 struct pipe_screen *screen = pipe->screen;
1435 struct pipe_sampler_view view_templ;
1436 struct pipe_sampler_view *view;
1437 struct pipe_box src_box;
1438 struct pipe_resource texTemp, *tex;
1439 const struct pipe_framebuffer_state *fb = &ctx->g3d.fb;
1440 const int srcW = abs(srcX1 - srcX0);
1441 const int srcH = abs(srcY1 - srcY0);
1442 const int srcLeft = MIN2(srcX0, srcX1);
1443 const int srcTop = MIN2(srcY0, srcY1);
1445 assert(filter == PIPE_TEX_MIPFILTER_NEAREST ||
1446 filter == PIPE_TEX_MIPFILTER_LINEAR);
1448 if (srcLeft != srcX0) {
1449 /* left-right flip */
1455 if (srcTop != srcY0) {
1462 assert(screen->is_format_supported(screen, src->format, PIPE_TEXTURE_2D,
1463 0, PIPE_BIND_SAMPLER_VIEW));
1464 assert(screen->is_format_supported(screen, dst->format, PIPE_TEXTURE_2D,
1465 0, PIPE_BIND_SAMPLER_VIEW));
1466 assert(screen->is_format_supported(screen, dst->format, PIPE_TEXTURE_2D,
1467 0, PIPE_BIND_RENDER_TARGET));
1470 * XXX for now we're always creating a temporary texture.
1471 * Strictly speaking that's not always needed.
1474 /* create temp texture */
1475 memset(&texTemp, 0, sizeof(texTemp));
1476 texTemp.target = PIPE_TEXTURE_2D;
1477 texTemp.format = src->format;
1478 texTemp.last_level = 0;
1479 texTemp.width0 = srcW;
1480 texTemp.height0 = srcH;
1482 texTemp.array_size = 1;
1483 texTemp.bind = PIPE_BIND_SAMPLER_VIEW;
1485 tex = screen->resource_create(screen, &texTemp);
1489 u_sampler_view_default_template(&view_templ, tex, tex->format);
1490 view = pipe->create_sampler_view(pipe, tex, &view_templ);
1495 u_box_2d_zslice(srcLeft, srcTop, src->u.tex.first_layer, srcW, srcH, &src_box);
1497 pipe->resource_copy_region(pipe,
1498 tex, 0, 0, 0, 0, /* dest */
1499 src->texture, 0, &src_box);
1501 assert(floatsEqual(z, 0.0f));
1504 if (fb->cbufs[0] == dst) {
1505 /* transform back to surface coordinates */
1506 dstY0 = dst->height - dstY0;
1507 dstY1 = dst->height - dstY1;
1509 if (renderer_drawtex_begin(ctx, view)) {
1510 renderer_drawtex(ctx,
1511 dstX0, dstY0, dstX1 - dstX0, dstY1 - dstY0,
1512 0, 0, view->texture->width0, view->texture->height0);
1513 renderer_drawtex_end(ctx);
1517 if (renderer_copy_begin(ctx, dst, VG_TRUE, view)) {
1519 dstX0, dstY0, dstX1 - dstX0, dstY1 - dstY0,
1520 0, 0, view->texture->width0, view->texture->height0);
1521 renderer_copy_end(ctx);
1526 void renderer_texture_quad(struct renderer *r,
1527 struct pipe_resource *tex,
1528 VGfloat x1offset, VGfloat y1offset,
1529 VGfloat x2offset, VGfloat y2offset,
1530 VGfloat x1, VGfloat y1,
1531 VGfloat x2, VGfloat y2,
1532 VGfloat x3, VGfloat y3,
1533 VGfloat x4, VGfloat y4)
1535 const VGfloat z = 0.0f;
1537 assert(r->state == RENDERER_STATE_INIT);
1538 assert(tex->width0 != 0);
1539 assert(tex->height0 != 0);
1541 cso_save_vertex_shader(r->cso);
1543 renderer_set_vs(r, RENDERER_VS_TEXTURE);
1545 /* manually set up positions */
1546 r->vertices[0][0][0] = x1;
1547 r->vertices[0][0][1] = y1;
1548 r->vertices[0][0][2] = z;
1550 r->vertices[1][0][0] = x2;
1551 r->vertices[1][0][1] = y2;
1552 r->vertices[1][0][2] = z;
1554 r->vertices[2][0][0] = x3;
1555 r->vertices[2][0][1] = y3;
1556 r->vertices[2][0][2] = z;
1558 r->vertices[3][0][0] = x4;
1559 r->vertices[3][0][1] = y4;
1560 r->vertices[3][0][2] = z;
1563 renderer_quad_texcoord(r, x1offset, y1offset,
1564 x2offset, y2offset, tex->width0, tex->height0);
1566 renderer_quad_draw(r);
1568 cso_restore_vertex_shader(r->cso);