1 /**************************************************************************
3 * Copyright 2009 VMware, Inc. All Rights Reserved.
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sub license, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
13 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial portions
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
20 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
21 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 **************************************************************************/
29 #include "vg_context.h"
31 #include "pipe/p_context.h"
32 #include "pipe/p_state.h"
33 #include "util/u_inlines.h"
34 #include "pipe/p_screen.h"
35 #include "pipe/p_shader_tokens.h"
37 #include "util/u_draw_quad.h"
38 #include "util/u_format.h"
39 #include "util/u_simple_shaders.h"
40 #include "util/u_memory.h"
41 #include "util/u_rect.h"
42 #include "util/u_sampler.h"
44 #include "cso_cache/cso_context.h"
47 struct pipe_context *pipe;
48 struct vg_context *owner;
50 struct cso_context *cso;
54 VGfloat vertices[4][2][4];
57 static void setup_shaders(struct renderer *ctx)
59 struct pipe_context *pipe = ctx->pipe;
61 ctx->fs = util_make_fragment_tex_shader(pipe, TGSI_TEXTURE_2D);
64 static struct pipe_resource *
65 setup_vertex_data(struct renderer *ctx,
66 float x0, float y0, float x1, float y1, float z)
68 ctx->vertices[0][0][0] = x0;
69 ctx->vertices[0][0][1] = y0;
70 ctx->vertices[0][0][2] = z;
71 ctx->vertices[0][1][0] = 0.0f; /*s*/
72 ctx->vertices[0][1][1] = 0.0f; /*t*/
74 ctx->vertices[1][0][0] = x1;
75 ctx->vertices[1][0][1] = y0;
76 ctx->vertices[1][0][2] = z;
77 ctx->vertices[1][1][0] = 1.0f; /*s*/
78 ctx->vertices[1][1][1] = 0.0f; /*t*/
80 ctx->vertices[2][0][0] = x1;
81 ctx->vertices[2][0][1] = y1;
82 ctx->vertices[2][0][2] = z;
83 ctx->vertices[2][1][0] = 1.0f;
84 ctx->vertices[2][1][1] = 1.0f;
86 ctx->vertices[3][0][0] = x0;
87 ctx->vertices[3][0][1] = y1;
88 ctx->vertices[3][0][2] = z;
89 ctx->vertices[3][1][0] = 0.0f;
90 ctx->vertices[3][1][1] = 1.0f;
92 return pipe_user_buffer_create( ctx->pipe->screen,
94 sizeof(ctx->vertices),
95 PIPE_BIND_VERTEX_BUFFER);
98 static struct pipe_resource *
99 setup_vertex_data_tex(struct renderer *ctx,
100 float x0, float y0, float x1, float y1,
101 float s0, float t0, float s1, float t1,
104 ctx->vertices[0][0][0] = x0;
105 ctx->vertices[0][0][1] = y0;
106 ctx->vertices[0][0][2] = z;
107 ctx->vertices[0][1][0] = s0; /*s*/
108 ctx->vertices[0][1][1] = t0; /*t*/
110 ctx->vertices[1][0][0] = x1;
111 ctx->vertices[1][0][1] = y0;
112 ctx->vertices[1][0][2] = z;
113 ctx->vertices[1][1][0] = s1; /*s*/
114 ctx->vertices[1][1][1] = t0; /*t*/
116 ctx->vertices[2][0][0] = x1;
117 ctx->vertices[2][0][1] = y1;
118 ctx->vertices[2][0][2] = z;
119 ctx->vertices[2][1][0] = s1;
120 ctx->vertices[2][1][1] = t1;
122 ctx->vertices[3][0][0] = x0;
123 ctx->vertices[3][0][1] = y1;
124 ctx->vertices[3][0][2] = z;
125 ctx->vertices[3][1][0] = s0;
126 ctx->vertices[3][1][1] = t1;
128 return pipe_user_buffer_create( ctx->pipe->screen,
130 sizeof(ctx->vertices),
131 PIPE_BIND_VERTEX_BUFFER);
135 static struct pipe_resource *
136 setup_vertex_data_qtex(struct renderer *ctx,
137 float x0, float y0, float x1, float y1,
138 float x2, float y2, float x3, float y3,
139 float s0, float t0, float s1, float t1,
142 ctx->vertices[0][0][0] = x0;
143 ctx->vertices[0][0][1] = y0;
144 ctx->vertices[0][0][2] = z;
145 ctx->vertices[0][1][0] = s0; /*s*/
146 ctx->vertices[0][1][1] = t0; /*t*/
148 ctx->vertices[1][0][0] = x1;
149 ctx->vertices[1][0][1] = y1;
150 ctx->vertices[1][0][2] = z;
151 ctx->vertices[1][1][0] = s1; /*s*/
152 ctx->vertices[1][1][1] = t0; /*t*/
154 ctx->vertices[2][0][0] = x2;
155 ctx->vertices[2][0][1] = y2;
156 ctx->vertices[2][0][2] = z;
157 ctx->vertices[2][1][0] = s1;
158 ctx->vertices[2][1][1] = t1;
160 ctx->vertices[3][0][0] = x3;
161 ctx->vertices[3][0][1] = y3;
162 ctx->vertices[3][0][2] = z;
163 ctx->vertices[3][1][0] = s0;
164 ctx->vertices[3][1][1] = t1;
166 return pipe_user_buffer_create( ctx->pipe->screen,
168 sizeof(ctx->vertices),
169 PIPE_BIND_VERTEX_BUFFER);
172 struct renderer * renderer_create(struct vg_context *owner)
175 struct renderer *renderer = CALLOC_STRUCT(renderer);
180 renderer->owner = owner;
181 renderer->pipe = owner->pipe;
182 renderer->cso = owner->cso_context;
184 setup_shaders(renderer);
186 /* init vertex data that doesn't change */
187 for (i = 0; i < 4; i++) {
188 renderer->vertices[i][0][3] = 1.0f; /* w */
189 renderer->vertices[i][1][2] = 0.0f; /* r */
190 renderer->vertices[i][1][3] = 1.0f; /* q */
196 void renderer_destroy(struct renderer *ctx)
200 cso_delete_fragment_shader(ctx->cso, ctx->fs);
207 void renderer_draw_quad(struct renderer *r,
208 VGfloat x1, VGfloat y1,
209 VGfloat x2, VGfloat y2,
212 struct pipe_resource *buf;
214 buf = setup_vertex_data(r, x1, y1, x2, y2, depth);
217 cso_set_vertex_elements(r->cso, 2, r->owner->velems);
218 util_draw_vertex_buffer(r->pipe, buf, 0,
219 PIPE_PRIM_TRIANGLE_FAN,
221 2); /* attribs/vert */
223 pipe_resource_reference( &buf,
228 void renderer_draw_texture(struct renderer *r,
229 struct pipe_resource *tex,
230 VGfloat x1offset, VGfloat y1offset,
231 VGfloat x2offset, VGfloat y2offset,
232 VGfloat x1, VGfloat y1,
233 VGfloat x2, VGfloat y2)
235 struct pipe_context *pipe = r->pipe;
236 struct pipe_resource *buf;
237 VGfloat s0, t0, s1, t1;
239 assert(tex->width0 != 0);
240 assert(tex->height0 != 0);
242 s0 = x1offset / tex->width0;
243 s1 = x2offset / tex->width0;
244 t0 = y1offset / tex->height0;
245 t1 = y2offset / tex->height0;
247 cso_save_vertex_shader(r->cso);
249 cso_set_vertex_shader_handle(r->cso, vg_texture_vs(r->owner));
252 buf = setup_vertex_data_tex(r, x1, y1, x2, y2,
253 s0, t0, s1, t1, 0.0f);
256 cso_set_vertex_elements(r->cso, 2, r->owner->velems);
257 util_draw_vertex_buffer(pipe, buf, 0,
258 PIPE_PRIM_TRIANGLE_FAN,
260 2); /* attribs/vert */
262 pipe_resource_reference( &buf,
266 cso_restore_vertex_shader(r->cso);
269 void renderer_copy_texture(struct renderer *ctx,
270 struct pipe_sampler_view *src,
271 VGfloat sx1, VGfloat sy1,
272 VGfloat sx2, VGfloat sy2,
273 struct pipe_resource *dst,
274 VGfloat dx1, VGfloat dy1,
275 VGfloat dx2, VGfloat dy2)
277 struct pipe_context *pipe = ctx->pipe;
278 struct pipe_screen *screen = pipe->screen;
279 struct pipe_resource *tex = src->texture;
280 struct pipe_resource *buf;
281 struct pipe_surface *dst_surf = screen->get_tex_surface(
282 screen, dst, 0, 0, 0,
283 PIPE_BIND_RENDER_TARGET);
284 struct pipe_framebuffer_state fb;
285 float s0, t0, s1, t1;
287 assert(tex->width0 != 0);
288 assert(tex->height0 != 0);
289 assert(dst->width0 != 0);
290 assert(dst->height0 != 0);
293 debug_printf("copy texture [%f, %f, %f, %f], [%f, %f, %f, %f]\n",
294 sx1, sy1, sx2, sy2, dx1, dy1, dx2, dy2);
298 s0 = sx1 / tex->width0;
299 s1 = sx2 / tex->width0;
300 t0 = sy1 / tex->height0;
301 t1 = sy2 / tex->height0;
309 assert(screen->is_format_supported(screen, dst_surf->format, PIPE_TEXTURE_2D,
310 PIPE_BIND_RENDER_TARGET, 0));
312 /* save state (restored below) */
313 cso_save_blend(ctx->cso);
314 cso_save_samplers(ctx->cso);
315 cso_save_fragment_sampler_views(ctx->cso);
316 cso_save_framebuffer(ctx->cso);
317 cso_save_fragment_shader(ctx->cso);
318 cso_save_vertex_shader(ctx->cso);
320 cso_save_viewport(ctx->cso);
323 /* set misc state we care about */
325 struct pipe_blend_state blend;
326 memset(&blend, 0, sizeof(blend));
327 blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE;
328 blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
329 blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
330 blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
331 blend.rt[0].colormask = PIPE_MASK_RGBA;
332 cso_set_blend(ctx->cso, &blend);
337 struct pipe_sampler_state sampler;
338 memset(&sampler, 0, sizeof(sampler));
339 sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
340 sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
341 sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
342 sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
343 sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST;
344 sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
345 sampler.normalized_coords = 1;
346 cso_single_sampler(ctx->cso, 0, &sampler);
347 cso_single_sampler_done(ctx->cso);
350 vg_set_viewport(ctx->owner, VEGA_Y0_TOP);
353 cso_set_fragment_sampler_views(ctx->cso, 1, &src);
356 cso_set_vertex_shader_handle(ctx->cso, vg_texture_vs(ctx->owner));
357 cso_set_fragment_shader_handle(ctx->cso, ctx->fs);
360 memset(&fb, 0, sizeof(fb));
361 fb.width = dst_surf->width;
362 fb.height = dst_surf->height;
364 fb.cbufs[0] = dst_surf;
367 for (i = 1; i < PIPE_MAX_COLOR_BUFS; ++i)
370 cso_set_framebuffer(ctx->cso, &fb);
373 buf = setup_vertex_data_tex(ctx,
380 cso_set_vertex_elements(ctx->cso, 2, ctx->owner->velems);
381 util_draw_vertex_buffer(ctx->pipe, buf, 0,
382 PIPE_PRIM_TRIANGLE_FAN,
384 2); /* attribs/vert */
386 pipe_resource_reference( &buf,
390 /* restore state we changed */
391 cso_restore_blend(ctx->cso);
392 cso_restore_samplers(ctx->cso);
393 cso_restore_fragment_sampler_views(ctx->cso);
394 cso_restore_framebuffer(ctx->cso);
395 cso_restore_vertex_shader(ctx->cso);
396 cso_restore_fragment_shader(ctx->cso);
397 cso_restore_viewport(ctx->cso);
399 pipe_surface_reference(&dst_surf, NULL);
402 void renderer_copy_surface(struct renderer *ctx,
403 struct pipe_surface *src,
404 int srcX0, int srcY0,
405 int srcX1, int srcY1,
406 struct pipe_surface *dst,
407 int dstX0, int dstY0,
408 int dstX1, int dstY1,
409 float z, unsigned filter)
411 struct pipe_context *pipe = ctx->pipe;
412 struct pipe_screen *screen = pipe->screen;
413 struct pipe_resource *buf;
414 struct pipe_sampler_view view_templ;
415 struct pipe_sampler_view *view;
416 struct pipe_resource texTemp, *tex;
417 struct pipe_surface *texSurf;
418 struct pipe_framebuffer_state fb;
419 struct st_framebuffer *stfb = ctx->owner->draw_buffer;
420 const int srcW = abs(srcX1 - srcX0);
421 const int srcH = abs(srcY1 - srcY0);
422 const int srcLeft = MIN2(srcX0, srcX1);
423 const int srcTop = MIN2(srcY0, srcY1);
425 assert(filter == PIPE_TEX_MIPFILTER_NEAREST ||
426 filter == PIPE_TEX_MIPFILTER_LINEAR);
428 if (srcLeft != srcX0) {
429 /* left-right flip */
435 if (srcTop != srcY0) {
442 assert(screen->is_format_supported(screen, src->format, PIPE_TEXTURE_2D,
443 PIPE_BIND_SAMPLER_VIEW, 0));
444 assert(screen->is_format_supported(screen, dst->format, PIPE_TEXTURE_2D,
445 PIPE_BIND_SAMPLER_VIEW, 0));
446 assert(screen->is_format_supported(screen, dst->format, PIPE_TEXTURE_2D,
447 PIPE_BIND_RENDER_TARGET, 0));
450 * XXX for now we're always creating a temporary texture.
451 * Strictly speaking that's not always needed.
454 /* create temp texture */
455 memset(&texTemp, 0, sizeof(texTemp));
456 texTemp.target = PIPE_TEXTURE_2D;
457 texTemp.format = src->format;
458 texTemp.last_level = 0;
459 texTemp.width0 = srcW;
460 texTemp.height0 = srcH;
463 tex = screen->resource_create(screen, &texTemp);
467 u_sampler_view_default_template(&view_templ, tex, tex->format);
468 view = pipe->create_sampler_view(pipe, tex, &view_templ);
473 texSurf = screen->get_tex_surface(screen, tex, 0, 0, 0,
474 PIPE_BIND_RENDER_TARGET);
476 /* load temp texture */
477 if (pipe->surface_copy) {
478 pipe->surface_copy(pipe,
479 texSurf, 0, 0, /* dest */
480 src, srcLeft, srcTop, /* src */
481 srcW, srcH); /* size */
483 util_surface_copy(pipe, FALSE,
484 texSurf, 0, 0, /* dest */
485 src, srcLeft, srcTop, /* src */
486 srcW, srcH); /* size */
489 /* free the surface, update the texture if necessary.*/
490 screen->tex_surface_destroy(texSurf);
492 /* save state (restored below) */
493 cso_save_blend(ctx->cso);
494 cso_save_samplers(ctx->cso);
495 cso_save_fragment_sampler_views(ctx->cso);
496 cso_save_framebuffer(ctx->cso);
497 cso_save_fragment_shader(ctx->cso);
498 cso_save_vertex_shader(ctx->cso);
499 cso_save_viewport(ctx->cso);
501 /* set misc state we care about */
503 struct pipe_blend_state blend;
504 memset(&blend, 0, sizeof(blend));
505 blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE;
506 blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
507 blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
508 blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
509 blend.rt[0].colormask = PIPE_MASK_RGBA;
510 cso_set_blend(ctx->cso, &blend);
513 vg_set_viewport(ctx->owner, VEGA_Y0_TOP);
517 struct pipe_sampler_state sampler;
518 memset(&sampler, 0, sizeof(sampler));
519 sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
520 sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
521 sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
522 sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
523 sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST;
524 sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
525 sampler.normalized_coords = 1;
526 cso_single_sampler(ctx->cso, 0, &sampler);
527 cso_single_sampler_done(ctx->cso);
531 cso_set_fragment_sampler_views(ctx->cso, 1, &view);
534 cso_set_fragment_shader_handle(ctx->cso, ctx->fs);
535 cso_set_vertex_shader_handle(ctx->cso, vg_texture_vs(ctx->owner));
538 if (stfb->strb->surface != dst) {
539 memset(&fb, 0, sizeof(fb));
540 fb.width = dst->width;
541 fb.height = dst->height;
544 fb.zsbuf = stfb->dsrb->surface;
545 cso_set_framebuffer(ctx->cso, &fb);
549 buf = setup_vertex_data(ctx,
550 (float) dstX0, (float) dstY0,
551 (float) dstX1, (float) dstY1, z);
554 cso_set_vertex_elements(ctx->cso, 2, ctx->owner->velems);
555 util_draw_vertex_buffer(ctx->pipe, buf, 0,
556 PIPE_PRIM_TRIANGLE_FAN,
558 2); /* attribs/vert */
560 pipe_resource_reference( &buf,
565 /* restore state we changed */
566 cso_restore_blend(ctx->cso);
567 cso_restore_samplers(ctx->cso);
568 cso_restore_fragment_sampler_views(ctx->cso);
569 cso_restore_framebuffer(ctx->cso);
570 cso_restore_fragment_shader(ctx->cso);
571 cso_restore_vertex_shader(ctx->cso);
572 cso_restore_viewport(ctx->cso);
574 pipe_resource_reference(&tex, NULL);
575 pipe_sampler_view_reference(&view, NULL);
578 void renderer_texture_quad(struct renderer *r,
579 struct pipe_resource *tex,
580 VGfloat x1offset, VGfloat y1offset,
581 VGfloat x2offset, VGfloat y2offset,
582 VGfloat x1, VGfloat y1,
583 VGfloat x2, VGfloat y2,
584 VGfloat x3, VGfloat y3,
585 VGfloat x4, VGfloat y4)
587 struct pipe_context *pipe = r->pipe;
588 struct pipe_resource *buf;
589 VGfloat s0, t0, s1, t1;
591 assert(tex->width0 != 0);
592 assert(tex->height0 != 0);
594 s0 = x1offset / tex->width0;
595 s1 = x2offset / tex->width0;
596 t0 = y1offset / tex->height0;
597 t1 = y2offset / tex->height0;
599 cso_save_vertex_shader(r->cso);
601 cso_set_vertex_shader_handle(r->cso, vg_texture_vs(r->owner));
604 buf = setup_vertex_data_qtex(r, x1, y1, x2, y2, x3, y3, x4, y4,
605 s0, t0, s1, t1, 0.0f);
608 cso_set_vertex_elements(r->cso, 2, r->owner->velems);
609 util_draw_vertex_buffer(pipe, buf, 0,
610 PIPE_PRIM_TRIANGLE_FAN,
612 2); /* attribs/vert */
614 pipe_resource_reference(&buf,
618 cso_restore_vertex_shader(r->cso);