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
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, PIPE_SHADER_FRAGMENT, i, &sampler);
439
cso_single_sampler_done(r->cso, PIPE_SHADER_FRAGMENT);
442
cso_set_sampler_views(r->cso, PIPE_SHADER_FRAGMENT, 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, PIPE_SHADER_FRAGMENT, num_samplers, samplers);
465
cso_set_sampler_views(renderer->cso, PIPE_SHADER_FRAGMENT, 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
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
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 */
575
* Prepare the renderer for copying.
577
VGboolean renderer_copy_begin(struct renderer *renderer,
578
struct pipe_surface *dst,
580
struct pipe_sampler_view *src)
582
assert(renderer->state == RENDERER_STATE_INIT);
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))
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);
599
renderer_set_target(renderer, dst, NULL, y0_top);
601
renderer_set_blend(renderer, ~0);
602
renderer_set_samplers(renderer, 1, &src);
604
renderer_set_fs(renderer, RENDERER_FS_TEXTURE);
605
renderer_set_vs(renderer, RENDERER_VS_TEXTURE);
607
renderer_set_mvp(renderer, NULL);
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;
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).
621
* The coordinates are in surface coordinates.
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)
627
assert(renderer->state == RENDERER_STATE_COPY);
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);
635
renderer_quad_draw(renderer);
639
* End copying and restore the states.
641
void renderer_copy_end(struct renderer *renderer)
643
assert(renderer->state == RENDERER_STATE_COPY);
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);
653
renderer->state = RENDERER_STATE_INIT;
657
* Prepare the renderer for textured drawing.
659
VGboolean renderer_drawtex_begin(struct renderer *renderer,
660
struct pipe_sampler_view *src)
662
assert(renderer->state == RENDERER_STATE_INIT);
664
if (!renderer_can_support(renderer, src->texture, PIPE_BIND_SAMPLER_VIEW))
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);
673
renderer_set_blend(renderer, ~0);
675
renderer_set_samplers(renderer, 1, &src);
677
renderer_set_fs(renderer, RENDERER_FS_TEXTURE);
678
renderer_set_vs(renderer, RENDERER_VS_TEXTURE);
680
renderer_set_mvp(renderer, NULL);
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;
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).
694
* The coordinates are in surface coordinates.
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)
700
assert(renderer->state == RENDERER_STATE_DRAWTEX);
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);
708
renderer_quad_draw(renderer);
712
* End textured drawing and restore the states.
714
void renderer_drawtex_end(struct renderer *renderer)
716
assert(renderer->state == RENDERER_STATE_DRAWTEX);
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);
724
renderer->state = RENDERER_STATE_INIT;
728
* Prepare the renderer for scissor update. This will reset the depth buffer
731
VGboolean renderer_scissor_begin(struct renderer *renderer,
732
VGboolean restore_dsa)
734
struct pipe_depth_stencil_alpha_state dsa;
736
assert(renderer->state == RENDERER_STATE_INIT);
739
cso_save_depth_stencil_alpha(renderer->cso);
740
cso_save_blend(renderer->cso);
741
cso_save_fragment_shader(renderer->cso);
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);
750
/* disable color writes */
751
renderer_set_blend(renderer, 0);
752
renderer_set_fs(renderer, RENDERER_FS_SCISSOR);
754
renderer_set_mvp(renderer, NULL);
756
renderer->u.scissor.restore_dsa = restore_dsa;
757
renderer->state = RENDERER_STATE_SCISSOR;
759
/* clear the depth buffer to 1.0f */
760
renderer->pipe->clear(renderer->pipe,
761
PIPE_CLEAR_DEPTHSTENCIL, NULL, 1.0f, 0);
767
* Add a scissor rectangle. Depth values inside the rectangle will be set to
770
void renderer_scissor(struct renderer *renderer,
771
VGint x, VGint y, VGint width, VGint height)
773
assert(renderer->state == RENDERER_STATE_SCISSOR);
775
renderer_quad_pos(renderer, x, y, x + width, y + height, VG_FALSE);
776
renderer_quad_draw(renderer);
780
* End scissor update and restore the states.
782
void renderer_scissor_end(struct renderer *renderer)
784
assert(renderer->state == RENDERER_STATE_SCISSOR);
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);
791
renderer->state = RENDERER_STATE_INIT;
795
* Prepare the renderer for clearing.
797
VGboolean renderer_clear_begin(struct renderer *renderer)
799
assert(renderer->state == RENDERER_STATE_INIT);
801
cso_save_blend(renderer->cso);
802
cso_save_fragment_shader(renderer->cso);
803
cso_save_vertex_shader(renderer->cso);
805
renderer_set_blend(renderer, ~0);
806
renderer_set_fs(renderer, RENDERER_FS_COLOR);
807
renderer_set_vs(renderer, RENDERER_VS_COLOR);
809
renderer_set_mvp(renderer, NULL);
811
renderer->state = RENDERER_STATE_CLEAR;
817
* Clear the framebuffer with the specified region and color.
819
* The coordinates are in surface coordinates.
821
void renderer_clear(struct renderer *renderer,
822
VGint x, VGint y, VGint width, VGint height,
823
const VGfloat color[4])
827
assert(renderer->state == RENDERER_STATE_CLEAR);
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);
833
renderer_quad_draw(renderer);
837
* End clearing and retore the states.
839
void renderer_clear_end(struct renderer *renderer)
841
assert(renderer->state == RENDERER_STATE_CLEAR);
843
cso_restore_blend(renderer->cso);
844
cso_restore_fragment_shader(renderer->cso);
845
cso_restore_vertex_shader(renderer->cso);
847
renderer->state = RENDERER_STATE_INIT;
851
* Prepare the renderer for image filtering.
853
VGboolean renderer_filter_begin(struct renderer *renderer,
854
struct pipe_resource *dst,
856
VGbitfield channel_mask,
857
const struct pipe_sampler_state **samplers,
858
struct pipe_sampler_view **views,
861
const void *const_buffer,
862
VGint const_buffer_len)
864
struct pipe_surface *surf, surf_tmpl;
866
assert(renderer->state == RENDERER_STATE_INIT);
870
if (!renderer_can_support(renderer, dst, PIPE_BIND_RENDER_TARGET))
873
u_surface_default_template(&surf_tmpl, dst,
874
PIPE_BIND_RENDER_TARGET);
875
surf = renderer->pipe->create_surface(renderer->pipe, dst, &surf_tmpl);
879
cso_save_framebuffer(renderer->cso);
880
cso_save_viewport(renderer->cso);
881
cso_save_blend(renderer->cso);
883
/* set the image as the target */
884
renderer_set_target(renderer, surf, NULL, y0_top);
885
pipe_surface_reference(&surf, NULL);
887
renderer_set_blend(renderer, channel_mask);
890
struct pipe_resource *tex;
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);
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);
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;
908
cso_save_fragment_shader(renderer->cso);
910
renderer_set_custom_fs(renderer, fs, NULL, NULL, 0,
911
const_buffer, const_buffer_len);
913
renderer->u.filter.use_sampler = VG_FALSE;
916
renderer_set_mvp(renderer, NULL);
918
renderer->state = RENDERER_STATE_FILTER;
924
* Draw into a rectangle of the destination with the specified region of the
927
* The coordinates are in surface coordinates.
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)
933
assert(renderer->state == RENDERER_STATE_FILTER);
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);
942
renderer_quad_draw(renderer);
946
* End image filtering and restore the states.
948
void renderer_filter_end(struct renderer *renderer)
950
assert(renderer->state == RENDERER_STATE_FILTER);
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);
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);
963
renderer->state = RENDERER_STATE_INIT;
967
* Prepare the renderer for polygon silhouette rendering.
969
VGboolean renderer_polygon_stencil_begin(struct renderer *renderer,
970
struct pipe_vertex_element *velem,
972
VGboolean restore_dsa)
974
struct pipe_depth_stencil_alpha_state *dsa;
975
VGboolean manual_two_sides;
977
assert(renderer->state == RENDERER_STATE_INIT);
979
cso_save_vertex_elements(renderer->cso);
980
cso_save_blend(renderer->cso);
981
cso_save_depth_stencil_alpha(renderer->cso);
983
cso_set_vertex_elements(renderer->cso, 1, velem);
985
/* disable color writes */
986
renderer_set_blend(renderer, 0);
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;
1001
assert(rule == VG_NON_ZERO);
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;
1012
if (renderer->pipe->screen->get_param(renderer->pipe->screen,
1013
PIPE_CAP_TWO_SIDED_STENCIL)) {
1015
dsa->stencil[1] = dsa->stencil[0];
1016
dsa->stencil[1].zpass_op = PIPE_STENCIL_OP_DECR_WRAP;
1019
manual_two_sides = VG_TRUE;
1022
cso_set_depth_stencil_alpha(renderer->cso, dsa);
1024
if (manual_two_sides)
1025
cso_save_rasterizer(renderer->cso);
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;
1035
* Render a polygon silhouette to stencil buffer.
1037
void renderer_polygon_stencil(struct renderer *renderer,
1038
struct pipe_vertex_buffer *vbuf,
1039
VGuint mode, VGuint start, VGuint count)
1041
assert(renderer->state == RENDERER_STATE_POLYGON_STENCIL);
1043
cso_set_vertex_buffers(renderer->cso, 1, vbuf);
1045
if (!renderer->u.polygon_stencil.manual_two_sides) {
1046
cso_draw_arrays(renderer->cso, mode, start, count);
1049
struct pipe_rasterizer_state raster;
1050
struct pipe_depth_stencil_alpha_state dsa;
1052
raster = renderer->g3d.rasterizer;
1053
dsa = renderer->u.polygon_stencil.dsa;
1056
raster.cull_face = PIPE_FACE_BACK;
1057
dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_INCR_WRAP;
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);
1064
raster.cull_face = PIPE_FACE_FRONT;
1065
dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_DECR_WRAP;
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);
1074
* End polygon silhouette rendering.
1076
void renderer_polygon_stencil_end(struct renderer *renderer)
1078
assert(renderer->state == RENDERER_STATE_POLYGON_STENCIL);
1080
if (renderer->u.polygon_stencil.manual_two_sides)
1081
cso_restore_rasterizer(renderer->cso);
1083
cso_restore_vertex_elements(renderer->cso);
1085
/* restore color writes */
1086
cso_restore_blend(renderer->cso);
1088
if (renderer->u.polygon_stencil.restore_dsa)
1089
cso_restore_depth_stencil_alpha(renderer->cso);
1091
renderer->state = RENDERER_STATE_INIT;
1095
* Prepare the renderer for polygon filling.
1097
VGboolean renderer_polygon_fill_begin(struct renderer *renderer,
1100
struct pipe_depth_stencil_alpha_state dsa;
1102
assert(renderer->state == RENDERER_STATE_INIT);
1105
cso_save_depth_stencil_alpha(renderer->cso);
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);
1119
renderer->state = RENDERER_STATE_POLYGON_FILL;
1127
void renderer_polygon_fill(struct renderer *renderer,
1128
VGfloat min_x, VGfloat min_y,
1129
VGfloat max_x, VGfloat max_y)
1131
assert(renderer->state == RENDERER_STATE_POLYGON_FILL);
1133
renderer_quad_pos(renderer, min_x, min_y, max_x, max_y, VG_TRUE);
1134
renderer_quad_draw(renderer);
1138
* End polygon filling.
1140
void renderer_polygon_fill_end(struct renderer *renderer)
1142
assert(renderer->state == RENDERER_STATE_POLYGON_FILL);
1144
cso_restore_depth_stencil_alpha(renderer->cso);
1146
renderer->state = RENDERER_STATE_INIT;
1149
struct renderer * renderer_create(struct vg_context *owner)
1151
struct renderer *renderer;
1152
struct pipe_rasterizer_state *raster;
1153
struct pipe_stencil_ref sr;
1156
renderer = CALLOC_STRUCT(renderer);
1160
renderer->pipe = owner->pipe;
1161
renderer->cso = owner->cso_context;
1163
/* init vertex data that doesn't change */
1164
for (i = 0; i < 4; i++)
1165
renderer->vertices[i][0][3] = 1.0f; /* w */
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;
1173
cso_set_vertex_elements(renderer->cso, 2, renderer->velems);
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);
1183
memset(&sr, 0, sizeof(sr));
1184
cso_set_stencil_ref(renderer->cso, &sr);
1186
renderer_set_vs(renderer, RENDERER_VS_PLAIN);
1188
renderer->state = RENDERER_STATE_INIT;
1193
void renderer_destroy(struct renderer *ctx)
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]);
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]);
1206
pipe_resource_reference(&ctx->vs_cbuf, NULL);
1207
pipe_resource_reference(&ctx->fs_cbuf, NULL);
1212
static void update_clip_state(struct renderer *renderer,
1213
const struct vg_state *state)
1215
struct pipe_depth_stencil_alpha_state *dsa = &renderer->g3d.dsa;
1217
memset(dsa, 0, sizeof(struct pipe_depth_stencil_alpha_state));
1219
if (state->scissoring) {
1220
struct pipe_framebuffer_state *fb = &renderer->g3d.fb;
1223
renderer_scissor_begin(renderer, VG_FALSE);
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;
1239
/* note that x1 and y1 are exclusive */
1240
x1 = (VGint) ceilf(x + width);
1241
y1 = (VGint) ceilf(y + height);
1244
if (y1 > fb->height)
1249
if (iw > 0 && ih> 0 )
1250
renderer_scissor(renderer, x0, y0, iw, ih);
1253
renderer_scissor_end(renderer);
1255
dsa->depth.enabled = 1; /* glEnable(GL_DEPTH_TEST); */
1256
dsa->depth.writemask = 0;/*glDepthMask(FALSE);*/
1257
dsa->depth.func = PIPE_FUNC_GEQUAL;
1261
static void renderer_validate_blend(struct renderer *renderer,
1262
const struct vg_state *state,
1263
enum pipe_format fb_format)
1265
struct pipe_blend_state blend;
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;
1274
/* TODO alpha masking happens after blending? */
1276
switch (state->blend_mode) {
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;
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;
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;
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;
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:
1316
assert(!"not implemented blend mode");
1320
cso_set_blend(renderer->cso, &blend);
1324
* Propogate OpenVG state changes to the renderer. Only framebuffer, blending
1325
* and scissoring states are relevant here.
1327
void renderer_validate(struct renderer *renderer,
1329
const struct st_framebuffer *stfb,
1330
const struct vg_state *state)
1332
assert(renderer->state == RENDERER_STATE_INIT);
1334
dirty |= renderer->dirty;
1335
renderer->dirty = 0;
1337
if (dirty & FRAMEBUFFER_DIRTY) {
1338
struct pipe_framebuffer_state *fb = &renderer->g3d.fb;
1339
struct matrix *proj = &renderer->projection;
1341
memset(fb, 0, sizeof(struct pipe_framebuffer_state));
1342
fb->width = stfb->width;
1343
fb->height = stfb->height;
1345
fb->cbufs[0] = stfb->strb->surface;
1346
fb->zsbuf = stfb->dsrb->surface;
1348
cso_set_framebuffer(renderer->cso, fb);
1349
vg_set_viewport(renderer, VEGA_Y0_BOTTOM);
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);
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);
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);
1368
if (dirty & BLEND_DIRTY)
1369
renderer_validate_blend(renderer, state, stfb->strb->format);
1373
* Prepare the renderer for OpenVG pipeline.
1375
void renderer_validate_for_shader(struct renderer *renderer,
1376
const struct pipe_sampler_state **samplers,
1377
struct pipe_sampler_view **views,
1379
const struct matrix *modelview,
1381
const void *const_buffer,
1382
VGint const_buffer_len)
1384
struct matrix mvp = renderer->projection;
1386
/* will be used in POLYGON_STENCIL and POLYGON_FILL */
1387
matrix_mult(&mvp, modelview);
1388
renderer_set_mvp(renderer, &mvp);
1390
renderer_set_custom_fs(renderer, fs,
1391
samplers, views, num_samplers,
1392
const_buffer, const_buffer_len);
1395
void renderer_validate_for_mask_rendering(struct renderer *renderer,
1396
struct pipe_surface *dst,
1397
const struct matrix *modelview)
1399
struct matrix mvp = renderer->projection;
1401
/* will be used in POLYGON_STENCIL and POLYGON_FILL */
1402
matrix_mult(&mvp, modelview);
1403
renderer_set_mvp(renderer, &mvp);
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);
1409
/* set internal dirty flags (hacky!) */
1410
renderer->dirty = FRAMEBUFFER_DIRTY | BLEND_DIRTY;
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)
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);
1434
assert(filter == PIPE_TEX_MIPFILTER_NEAREST ||
1435
filter == PIPE_TEX_MIPFILTER_LINEAR);
1437
if (srcLeft != srcX0) {
1438
/* left-right flip */
1444
if (srcTop != srcY0) {
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));
1459
* XXX for now we're always creating a temporary texture.
1460
* Strictly speaking that's not always needed.
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;
1471
texTemp.array_size = 1;
1472
texTemp.bind = PIPE_BIND_SAMPLER_VIEW;
1474
tex = screen->resource_create(screen, &texTemp);
1478
u_sampler_view_default_template(&view_templ, tex, tex->format);
1479
view = pipe->create_sampler_view(pipe, tex, &view_templ);
1484
u_box_2d_zslice(srcLeft, srcTop, src->u.tex.first_layer, srcW, srcH, &src_box);
1486
pipe->resource_copy_region(pipe,
1487
tex, 0, 0, 0, 0, /* dest */
1488
src->texture, 0, &src_box);
1490
assert(floatsEqual(z, 0.0f));
1493
if (fb->cbufs[0] == dst) {
1494
/* transform back to surface coordinates */
1495
dstY0 = dst->height - dstY0;
1496
dstY1 = dst->height - dstY1;
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);
1506
if (renderer_copy_begin(ctx, dst, VG_TRUE, view)) {
1508
dstX0, dstY0, dstX1 - dstX0, dstY1 - dstY0,
1509
0, 0, view->texture->width0, view->texture->height0);
1510
renderer_copy_end(ctx);
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)
1524
const VGfloat z = 0.0f;
1526
assert(r->state == RENDERER_STATE_INIT);
1527
assert(tex->width0 != 0);
1528
assert(tex->height0 != 0);
1530
cso_save_vertex_shader(r->cso);
1532
renderer_set_vs(r, RENDERER_VS_TEXTURE);
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;
1539
r->vertices[1][0][0] = x2;
1540
r->vertices[1][0][1] = y2;
1541
r->vertices[1][0][2] = z;
1543
r->vertices[2][0][0] = x3;
1544
r->vertices[2][0][1] = y3;
1545
r->vertices[2][0][2] = z;
1547
r->vertices[3][0][0] = x4;
1548
r->vertices[3][0][1] = y4;
1549
r->vertices[3][0][2] = z;
1552
renderer_quad_texcoord(r, x1offset, y1offset,
1553
x2offset, y2offset, tex->width0, tex->height0);
1555
renderer_quad_draw(r);
1557
cso_restore_vertex_shader(r->cso);