Merge branch 'master' into pipe-video
[mesa.git] / src / gallium / state_trackers / vega / renderer.c
1 /**************************************************************************
2 *
3 * Copyright 2009 VMware, Inc. All Rights Reserved.
4 *
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:
12 *
13 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial portions
15 * of the Software.
16 *
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.
24 *
25 **************************************************************************/
26
27 #include "renderer.h"
28
29 #include "vg_context.h"
30
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"
36
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"
43 #include "util/u_surface.h"
44
45 #include "cso_cache/cso_context.h"
46
47 struct renderer {
48 struct pipe_context *pipe;
49 struct vg_context *owner;
50
51 struct cso_context *cso;
52
53 void *fs;
54
55 VGfloat vertices[4][2][4];
56 };
57
58 static void setup_shaders(struct renderer *ctx)
59 {
60 struct pipe_context *pipe = ctx->pipe;
61 /* fragment shader */
62 ctx->fs = util_make_fragment_tex_shader(pipe, TGSI_TEXTURE_2D,
63 TGSI_INTERPOLATE_LINEAR);
64 }
65
66 static struct pipe_resource *
67 setup_vertex_data(struct renderer *ctx,
68 float x0, float y0, float x1, float y1, float z)
69 {
70 ctx->vertices[0][0][0] = x0;
71 ctx->vertices[0][0][1] = y0;
72 ctx->vertices[0][0][2] = z;
73 ctx->vertices[0][1][0] = 0.0f; /*s*/
74 ctx->vertices[0][1][1] = 0.0f; /*t*/
75
76 ctx->vertices[1][0][0] = x1;
77 ctx->vertices[1][0][1] = y0;
78 ctx->vertices[1][0][2] = z;
79 ctx->vertices[1][1][0] = 1.0f; /*s*/
80 ctx->vertices[1][1][1] = 0.0f; /*t*/
81
82 ctx->vertices[2][0][0] = x1;
83 ctx->vertices[2][0][1] = y1;
84 ctx->vertices[2][0][2] = z;
85 ctx->vertices[2][1][0] = 1.0f;
86 ctx->vertices[2][1][1] = 1.0f;
87
88 ctx->vertices[3][0][0] = x0;
89 ctx->vertices[3][0][1] = y1;
90 ctx->vertices[3][0][2] = z;
91 ctx->vertices[3][1][0] = 0.0f;
92 ctx->vertices[3][1][1] = 1.0f;
93
94 return pipe_user_buffer_create( ctx->pipe->screen,
95 ctx->vertices,
96 sizeof(ctx->vertices),
97 PIPE_BIND_VERTEX_BUFFER);
98 }
99
100 static struct pipe_resource *
101 setup_vertex_data_tex(struct renderer *ctx,
102 float x0, float y0, float x1, float y1,
103 float s0, float t0, float s1, float t1,
104 float z)
105 {
106 ctx->vertices[0][0][0] = x0;
107 ctx->vertices[0][0][1] = y0;
108 ctx->vertices[0][0][2] = z;
109 ctx->vertices[0][1][0] = s0; /*s*/
110 ctx->vertices[0][1][1] = t0; /*t*/
111
112 ctx->vertices[1][0][0] = x1;
113 ctx->vertices[1][0][1] = y0;
114 ctx->vertices[1][0][2] = z;
115 ctx->vertices[1][1][0] = s1; /*s*/
116 ctx->vertices[1][1][1] = t0; /*t*/
117
118 ctx->vertices[2][0][0] = x1;
119 ctx->vertices[2][0][1] = y1;
120 ctx->vertices[2][0][2] = z;
121 ctx->vertices[2][1][0] = s1;
122 ctx->vertices[2][1][1] = t1;
123
124 ctx->vertices[3][0][0] = x0;
125 ctx->vertices[3][0][1] = y1;
126 ctx->vertices[3][0][2] = z;
127 ctx->vertices[3][1][0] = s0;
128 ctx->vertices[3][1][1] = t1;
129
130 return pipe_user_buffer_create( ctx->pipe->screen,
131 ctx->vertices,
132 sizeof(ctx->vertices),
133 PIPE_BIND_VERTEX_BUFFER);
134 }
135
136
137 static struct pipe_resource *
138 setup_vertex_data_qtex(struct renderer *ctx,
139 float x0, float y0, float x1, float y1,
140 float x2, float y2, float x3, float y3,
141 float s0, float t0, float s1, float t1,
142 float z)
143 {
144 ctx->vertices[0][0][0] = x0;
145 ctx->vertices[0][0][1] = y0;
146 ctx->vertices[0][0][2] = z;
147 ctx->vertices[0][1][0] = s0; /*s*/
148 ctx->vertices[0][1][1] = t0; /*t*/
149
150 ctx->vertices[1][0][0] = x1;
151 ctx->vertices[1][0][1] = y1;
152 ctx->vertices[1][0][2] = z;
153 ctx->vertices[1][1][0] = s1; /*s*/
154 ctx->vertices[1][1][1] = t0; /*t*/
155
156 ctx->vertices[2][0][0] = x2;
157 ctx->vertices[2][0][1] = y2;
158 ctx->vertices[2][0][2] = z;
159 ctx->vertices[2][1][0] = s1;
160 ctx->vertices[2][1][1] = t1;
161
162 ctx->vertices[3][0][0] = x3;
163 ctx->vertices[3][0][1] = y3;
164 ctx->vertices[3][0][2] = z;
165 ctx->vertices[3][1][0] = s0;
166 ctx->vertices[3][1][1] = t1;
167
168 return pipe_user_buffer_create( ctx->pipe->screen,
169 ctx->vertices,
170 sizeof(ctx->vertices),
171 PIPE_BIND_VERTEX_BUFFER);
172 }
173
174 struct renderer * renderer_create(struct vg_context *owner)
175 {
176 VGint i;
177 struct renderer *renderer = CALLOC_STRUCT(renderer);
178
179 if (!renderer)
180 return NULL;
181
182 renderer->owner = owner;
183 renderer->pipe = owner->pipe;
184 renderer->cso = owner->cso_context;
185
186 setup_shaders(renderer);
187
188 /* init vertex data that doesn't change */
189 for (i = 0; i < 4; i++) {
190 renderer->vertices[i][0][3] = 1.0f; /* w */
191 renderer->vertices[i][1][2] = 0.0f; /* r */
192 renderer->vertices[i][1][3] = 1.0f; /* q */
193 }
194
195 return renderer;
196 }
197
198 void renderer_destroy(struct renderer *ctx)
199 {
200 #if 0
201 if (ctx->fs) {
202 cso_delete_fragment_shader(ctx->cso, ctx->fs);
203 ctx->fs = NULL;
204 }
205 #endif
206 FREE(ctx);
207 }
208
209 void renderer_draw_quad(struct renderer *r,
210 VGfloat x1, VGfloat y1,
211 VGfloat x2, VGfloat y2,
212 VGfloat depth)
213 {
214 struct pipe_resource *buf;
215
216 buf = setup_vertex_data(r, x1, y1, x2, y2, depth);
217
218 if (buf) {
219 cso_set_vertex_elements(r->cso, 2, r->owner->velems);
220 util_draw_vertex_buffer(r->pipe, buf, 0,
221 PIPE_PRIM_TRIANGLE_FAN,
222 4, /* verts */
223 2); /* attribs/vert */
224
225 pipe_resource_reference( &buf,
226 NULL );
227 }
228 }
229
230 void renderer_draw_texture(struct renderer *r,
231 struct pipe_resource *tex,
232 VGfloat x1offset, VGfloat y1offset,
233 VGfloat x2offset, VGfloat y2offset,
234 VGfloat x1, VGfloat y1,
235 VGfloat x2, VGfloat y2)
236 {
237 struct pipe_context *pipe = r->pipe;
238 struct pipe_resource *buf;
239 VGfloat s0, t0, s1, t1;
240
241 assert(tex->width0 != 0);
242 assert(tex->height0 != 0);
243
244 s0 = x1offset / tex->width0;
245 s1 = x2offset / tex->width0;
246 t0 = y1offset / tex->height0;
247 t1 = y2offset / tex->height0;
248
249 cso_save_vertex_shader(r->cso);
250 /* shaders */
251 cso_set_vertex_shader_handle(r->cso, vg_texture_vs(r->owner));
252
253 /* draw quad */
254 buf = setup_vertex_data_tex(r, x1, y1, x2, y2,
255 s0, t0, s1, t1, 0.0f);
256
257 if (buf) {
258 cso_set_vertex_elements(r->cso, 2, r->owner->velems);
259 util_draw_vertex_buffer(pipe, buf, 0,
260 PIPE_PRIM_TRIANGLE_FAN,
261 4, /* verts */
262 2); /* attribs/vert */
263
264 pipe_resource_reference( &buf,
265 NULL );
266 }
267
268 cso_restore_vertex_shader(r->cso);
269 }
270
271 void renderer_copy_texture(struct renderer *ctx,
272 struct pipe_sampler_view *src,
273 VGfloat sx1, VGfloat sy1,
274 VGfloat sx2, VGfloat sy2,
275 struct pipe_resource *dst,
276 VGfloat dx1, VGfloat dy1,
277 VGfloat dx2, VGfloat dy2)
278 {
279 struct pipe_context *pipe = ctx->pipe;
280 struct pipe_screen *screen = pipe->screen;
281 struct pipe_resource *tex = src->texture;
282 struct pipe_resource *buf;
283 struct pipe_surface *dst_surf = screen->get_tex_surface(
284 screen, dst, 0, 0, 0,
285 PIPE_BIND_RENDER_TARGET);
286 struct pipe_framebuffer_state fb;
287 float s0, t0, s1, t1;
288
289 assert(tex->width0 != 0);
290 assert(tex->height0 != 0);
291 assert(dst->width0 != 0);
292 assert(dst->height0 != 0);
293
294 #if 0
295 debug_printf("copy texture [%f, %f, %f, %f], [%f, %f, %f, %f]\n",
296 sx1, sy1, sx2, sy2, dx1, dy1, dx2, dy2);
297 #endif
298
299 #if 1
300 s0 = sx1 / tex->width0;
301 s1 = sx2 / tex->width0;
302 t0 = sy1 / tex->height0;
303 t1 = sy2 / tex->height0;
304 #else
305 s0 = 0;
306 s1 = 1;
307 t0 = 0;
308 t1 = 1;
309 #endif
310
311 assert(screen->is_format_supported(screen, dst_surf->format, PIPE_TEXTURE_2D,
312 0, PIPE_BIND_RENDER_TARGET, 0));
313
314 /* save state (restored below) */
315 cso_save_blend(ctx->cso);
316 cso_save_samplers(ctx->cso);
317 cso_save_fragment_sampler_views(ctx->cso);
318 cso_save_framebuffer(ctx->cso);
319 cso_save_fragment_shader(ctx->cso);
320 cso_save_vertex_shader(ctx->cso);
321
322 cso_save_viewport(ctx->cso);
323
324
325 /* set misc state we care about */
326 {
327 struct pipe_blend_state blend;
328 memset(&blend, 0, sizeof(blend));
329 blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE;
330 blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
331 blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
332 blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
333 blend.rt[0].colormask = PIPE_MASK_RGBA;
334 cso_set_blend(ctx->cso, &blend);
335 }
336
337 /* sampler */
338 {
339 struct pipe_sampler_state sampler;
340 memset(&sampler, 0, sizeof(sampler));
341 sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
342 sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
343 sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
344 sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
345 sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST;
346 sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
347 sampler.normalized_coords = 1;
348 cso_single_sampler(ctx->cso, 0, &sampler);
349 cso_single_sampler_done(ctx->cso);
350 }
351
352 vg_set_viewport(ctx->owner, VEGA_Y0_TOP);
353
354 /* texture */
355 cso_set_fragment_sampler_views(ctx->cso, 1, &src);
356
357 /* shaders */
358 cso_set_vertex_shader_handle(ctx->cso, vg_texture_vs(ctx->owner));
359 cso_set_fragment_shader_handle(ctx->cso, ctx->fs);
360
361 /* drawing dest */
362 memset(&fb, 0, sizeof(fb));
363 fb.width = dst_surf->width;
364 fb.height = dst_surf->height;
365 fb.nr_cbufs = 1;
366 fb.cbufs[0] = dst_surf;
367 {
368 VGint i;
369 for (i = 1; i < PIPE_MAX_COLOR_BUFS; ++i)
370 fb.cbufs[i] = 0;
371 }
372 cso_set_framebuffer(ctx->cso, &fb);
373
374 /* draw quad */
375 buf = setup_vertex_data_tex(ctx,
376 dx1, dy1,
377 dx2, dy2,
378 s0, t0, s1, t1,
379 0.0f);
380
381 if (buf) {
382 cso_set_vertex_elements(ctx->cso, 2, ctx->owner->velems);
383 util_draw_vertex_buffer(ctx->pipe, buf, 0,
384 PIPE_PRIM_TRIANGLE_FAN,
385 4, /* verts */
386 2); /* attribs/vert */
387
388 pipe_resource_reference( &buf,
389 NULL );
390 }
391
392 /* restore state we changed */
393 cso_restore_blend(ctx->cso);
394 cso_restore_samplers(ctx->cso);
395 cso_restore_fragment_sampler_views(ctx->cso);
396 cso_restore_framebuffer(ctx->cso);
397 cso_restore_vertex_shader(ctx->cso);
398 cso_restore_fragment_shader(ctx->cso);
399 cso_restore_viewport(ctx->cso);
400
401 pipe_surface_reference(&dst_surf, NULL);
402 }
403
404 void renderer_copy_surface(struct renderer *ctx,
405 struct pipe_surface *src,
406 int srcX0, int srcY0,
407 int srcX1, int srcY1,
408 struct pipe_surface *dst,
409 int dstX0, int dstY0,
410 int dstX1, int dstY1,
411 float z, unsigned filter)
412 {
413 struct pipe_context *pipe = ctx->pipe;
414 struct pipe_screen *screen = pipe->screen;
415 struct pipe_resource *buf;
416 struct pipe_sampler_view view_templ;
417 struct pipe_sampler_view *view;
418 struct pipe_resource texTemp, *tex;
419 struct pipe_subresource subsrc, subdst;
420 struct pipe_framebuffer_state fb;
421 struct st_framebuffer *stfb = ctx->owner->draw_buffer;
422 const int srcW = abs(srcX1 - srcX0);
423 const int srcH = abs(srcY1 - srcY0);
424 const int srcLeft = MIN2(srcX0, srcX1);
425 const int srcTop = MIN2(srcY0, srcY1);
426
427 assert(filter == PIPE_TEX_MIPFILTER_NEAREST ||
428 filter == PIPE_TEX_MIPFILTER_LINEAR);
429
430 if (srcLeft != srcX0) {
431 /* left-right flip */
432 int tmp = dstX0;
433 dstX0 = dstX1;
434 dstX1 = tmp;
435 }
436
437 if (srcTop != srcY0) {
438 /* up-down flip */
439 int tmp = dstY0;
440 dstY0 = dstY1;
441 dstY1 = tmp;
442 }
443
444 assert(screen->is_format_supported(screen, src->format, PIPE_TEXTURE_2D,
445 0, PIPE_BIND_SAMPLER_VIEW, 0));
446 assert(screen->is_format_supported(screen, dst->format, PIPE_TEXTURE_2D,
447 0, PIPE_BIND_SAMPLER_VIEW, 0));
448 assert(screen->is_format_supported(screen, dst->format, PIPE_TEXTURE_2D,
449 0, PIPE_BIND_RENDER_TARGET, 0));
450
451 /*
452 * XXX for now we're always creating a temporary texture.
453 * Strictly speaking that's not always needed.
454 */
455
456 /* create temp texture */
457 memset(&texTemp, 0, sizeof(texTemp));
458 texTemp.target = PIPE_TEXTURE_2D;
459 texTemp.format = src->format;
460 texTemp.last_level = 0;
461 texTemp.width0 = srcW;
462 texTemp.height0 = srcH;
463 texTemp.depth0 = 1;
464 texTemp.bind = PIPE_BIND_SAMPLER_VIEW;
465
466 tex = screen->resource_create(screen, &texTemp);
467 if (!tex)
468 return;
469
470 u_sampler_view_default_template(&view_templ, tex, tex->format);
471 view = pipe->create_sampler_view(pipe, tex, &view_templ);
472
473 if (!view)
474 return;
475
476 subdst.face = 0;
477 subdst.level = 0;
478 subsrc.face = src->face;
479 subsrc.level = src->level;
480
481 pipe->resource_copy_region(pipe,
482 tex, subdst, 0, 0, 0, /* dest */
483 src->texture, subsrc, srcLeft, srcTop, src->zslice, /* src */
484 srcW, srcH); /* size */
485
486 /* save state (restored below) */
487 cso_save_blend(ctx->cso);
488 cso_save_samplers(ctx->cso);
489 cso_save_fragment_sampler_views(ctx->cso);
490 cso_save_framebuffer(ctx->cso);
491 cso_save_fragment_shader(ctx->cso);
492 cso_save_vertex_shader(ctx->cso);
493 cso_save_viewport(ctx->cso);
494
495 /* set misc state we care about */
496 {
497 struct pipe_blend_state blend;
498 memset(&blend, 0, sizeof(blend));
499 blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE;
500 blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
501 blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
502 blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
503 blend.rt[0].colormask = PIPE_MASK_RGBA;
504 cso_set_blend(ctx->cso, &blend);
505 }
506
507 vg_set_viewport(ctx->owner, VEGA_Y0_TOP);
508
509 /* sampler */
510 {
511 struct pipe_sampler_state sampler;
512 memset(&sampler, 0, sizeof(sampler));
513 sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
514 sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
515 sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
516 sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
517 sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST;
518 sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
519 sampler.normalized_coords = 1;
520 cso_single_sampler(ctx->cso, 0, &sampler);
521 cso_single_sampler_done(ctx->cso);
522 }
523
524 /* texture */
525 cso_set_fragment_sampler_views(ctx->cso, 1, &view);
526
527 /* shaders */
528 cso_set_fragment_shader_handle(ctx->cso, ctx->fs);
529 cso_set_vertex_shader_handle(ctx->cso, vg_texture_vs(ctx->owner));
530
531 /* drawing dest */
532 if (stfb->strb->surface != dst) {
533 memset(&fb, 0, sizeof(fb));
534 fb.width = dst->width;
535 fb.height = dst->height;
536 fb.nr_cbufs = 1;
537 fb.cbufs[0] = dst;
538 fb.zsbuf = stfb->dsrb->surface;
539 cso_set_framebuffer(ctx->cso, &fb);
540 }
541
542 /* draw quad */
543 buf = setup_vertex_data(ctx,
544 (float) dstX0, (float) dstY0,
545 (float) dstX1, (float) dstY1, z);
546
547 if (buf) {
548 cso_set_vertex_elements(ctx->cso, 2, ctx->owner->velems);
549 util_draw_vertex_buffer(ctx->pipe, buf, 0,
550 PIPE_PRIM_TRIANGLE_FAN,
551 4, /* verts */
552 2); /* attribs/vert */
553
554 pipe_resource_reference( &buf,
555 NULL );
556 }
557
558
559 /* restore state we changed */
560 cso_restore_blend(ctx->cso);
561 cso_restore_samplers(ctx->cso);
562 cso_restore_fragment_sampler_views(ctx->cso);
563 cso_restore_framebuffer(ctx->cso);
564 cso_restore_fragment_shader(ctx->cso);
565 cso_restore_vertex_shader(ctx->cso);
566 cso_restore_viewport(ctx->cso);
567
568 pipe_resource_reference(&tex, NULL);
569 pipe_sampler_view_reference(&view, NULL);
570 }
571
572 void renderer_texture_quad(struct renderer *r,
573 struct pipe_resource *tex,
574 VGfloat x1offset, VGfloat y1offset,
575 VGfloat x2offset, VGfloat y2offset,
576 VGfloat x1, VGfloat y1,
577 VGfloat x2, VGfloat y2,
578 VGfloat x3, VGfloat y3,
579 VGfloat x4, VGfloat y4)
580 {
581 struct pipe_context *pipe = r->pipe;
582 struct pipe_resource *buf;
583 VGfloat s0, t0, s1, t1;
584
585 assert(tex->width0 != 0);
586 assert(tex->height0 != 0);
587
588 s0 = x1offset / tex->width0;
589 s1 = x2offset / tex->width0;
590 t0 = y1offset / tex->height0;
591 t1 = y2offset / tex->height0;
592
593 cso_save_vertex_shader(r->cso);
594 /* shaders */
595 cso_set_vertex_shader_handle(r->cso, vg_texture_vs(r->owner));
596
597 /* draw quad */
598 buf = setup_vertex_data_qtex(r, x1, y1, x2, y2, x3, y3, x4, y4,
599 s0, t0, s1, t1, 0.0f);
600
601 if (buf) {
602 cso_set_vertex_elements(r->cso, 2, r->owner->velems);
603 util_draw_vertex_buffer(pipe, buf, 0,
604 PIPE_PRIM_TRIANGLE_FAN,
605 4, /* verts */
606 2); /* attribs/vert */
607
608 pipe_resource_reference(&buf,
609 NULL);
610 }
611
612 cso_restore_vertex_shader(r->cso);
613 }