Merge remote branch 'origin/7.8'
[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
44 #include "cso_cache/cso_context.h"
45
46 struct renderer {
47 struct pipe_context *pipe;
48 struct vg_context *owner;
49
50 struct cso_context *cso;
51
52 void *fs;
53
54 VGfloat vertices[4][2][4];
55 };
56
57 static void setup_shaders(struct renderer *ctx)
58 {
59 struct pipe_context *pipe = ctx->pipe;
60 /* fragment shader */
61 ctx->fs = util_make_fragment_tex_shader(pipe, TGSI_TEXTURE_2D);
62 }
63
64 static struct pipe_resource *
65 setup_vertex_data(struct renderer *ctx,
66 float x0, float y0, float x1, float y1, float z)
67 {
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*/
73
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*/
79
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;
85
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;
91
92 return pipe_user_buffer_create( ctx->pipe->screen,
93 ctx->vertices,
94 sizeof(ctx->vertices),
95 PIPE_BIND_VERTEX_BUFFER);
96 }
97
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,
102 float z)
103 {
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*/
109
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*/
115
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;
121
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;
127
128 return pipe_user_buffer_create( ctx->pipe->screen,
129 ctx->vertices,
130 sizeof(ctx->vertices),
131 PIPE_BIND_VERTEX_BUFFER);
132 }
133
134
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,
140 float z)
141 {
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*/
147
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*/
153
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;
159
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;
165
166 return pipe_user_buffer_create( ctx->pipe->screen,
167 ctx->vertices,
168 sizeof(ctx->vertices),
169 PIPE_BIND_VERTEX_BUFFER);
170 }
171
172 struct renderer * renderer_create(struct vg_context *owner)
173 {
174 VGint i;
175 struct renderer *renderer = CALLOC_STRUCT(renderer);
176
177 if (!renderer)
178 return NULL;
179
180 renderer->owner = owner;
181 renderer->pipe = owner->pipe;
182 renderer->cso = owner->cso_context;
183
184 setup_shaders(renderer);
185
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 */
191 }
192
193 return renderer;
194 }
195
196 void renderer_destroy(struct renderer *ctx)
197 {
198 #if 0
199 if (ctx->fs) {
200 cso_delete_fragment_shader(ctx->cso, ctx->fs);
201 ctx->fs = NULL;
202 }
203 #endif
204 free(ctx);
205 }
206
207 void renderer_draw_quad(struct renderer *r,
208 VGfloat x1, VGfloat y1,
209 VGfloat x2, VGfloat y2,
210 VGfloat depth)
211 {
212 struct pipe_resource *buf;
213
214 buf = setup_vertex_data(r, x1, y1, x2, y2, depth);
215
216 if (buf) {
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,
220 4, /* verts */
221 2); /* attribs/vert */
222
223 pipe_resource_reference( &buf,
224 NULL );
225 }
226 }
227
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)
234 {
235 struct pipe_context *pipe = r->pipe;
236 struct pipe_resource *buf;
237 VGfloat s0, t0, s1, t1;
238
239 assert(tex->width0 != 0);
240 assert(tex->height0 != 0);
241
242 s0 = x1offset / tex->width0;
243 s1 = x2offset / tex->width0;
244 t0 = y1offset / tex->height0;
245 t1 = y2offset / tex->height0;
246
247 cso_save_vertex_shader(r->cso);
248 /* shaders */
249 cso_set_vertex_shader_handle(r->cso, vg_texture_vs(r->owner));
250
251 /* draw quad */
252 buf = setup_vertex_data_tex(r, x1, y1, x2, y2,
253 s0, t0, s1, t1, 0.0f);
254
255 if (buf) {
256 cso_set_vertex_elements(r->cso, 2, r->owner->velems);
257 util_draw_vertex_buffer(pipe, buf, 0,
258 PIPE_PRIM_TRIANGLE_FAN,
259 4, /* verts */
260 2); /* attribs/vert */
261
262 pipe_resource_reference( &buf,
263 NULL );
264 }
265
266 cso_restore_vertex_shader(r->cso);
267 }
268
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)
276 {
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;
286
287 assert(tex->width0 != 0);
288 assert(tex->height0 != 0);
289 assert(dst->width0 != 0);
290 assert(dst->height0 != 0);
291
292 #if 0
293 debug_printf("copy texture [%f, %f, %f, %f], [%f, %f, %f, %f]\n",
294 sx1, sy1, sx2, sy2, dx1, dy1, dx2, dy2);
295 #endif
296
297 #if 1
298 s0 = sx1 / tex->width0;
299 s1 = sx2 / tex->width0;
300 t0 = sy1 / tex->height0;
301 t1 = sy2 / tex->height0;
302 #else
303 s0 = 0;
304 s1 = 1;
305 t0 = 0;
306 t1 = 1;
307 #endif
308
309 assert(screen->is_format_supported(screen, dst_surf->format, PIPE_TEXTURE_2D,
310 PIPE_BIND_RENDER_TARGET, 0));
311
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);
319
320 cso_save_viewport(ctx->cso);
321
322
323 /* set misc state we care about */
324 {
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);
333 }
334
335 /* sampler */
336 {
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);
348 }
349
350 vg_set_viewport(ctx->owner, VEGA_Y0_TOP);
351
352 /* texture */
353 cso_set_fragment_sampler_views(ctx->cso, 1, &src);
354
355 /* shaders */
356 cso_set_vertex_shader_handle(ctx->cso, vg_texture_vs(ctx->owner));
357 cso_set_fragment_shader_handle(ctx->cso, ctx->fs);
358
359 /* drawing dest */
360 memset(&fb, 0, sizeof(fb));
361 fb.width = dst_surf->width;
362 fb.height = dst_surf->height;
363 fb.nr_cbufs = 1;
364 fb.cbufs[0] = dst_surf;
365 {
366 VGint i;
367 for (i = 1; i < PIPE_MAX_COLOR_BUFS; ++i)
368 fb.cbufs[i] = 0;
369 }
370 cso_set_framebuffer(ctx->cso, &fb);
371
372 /* draw quad */
373 buf = setup_vertex_data_tex(ctx,
374 dx1, dy1,
375 dx2, dy2,
376 s0, t0, s1, t1,
377 0.0f);
378
379 if (buf) {
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,
383 4, /* verts */
384 2); /* attribs/vert */
385
386 pipe_resource_reference( &buf,
387 NULL );
388 }
389
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);
398
399 pipe_surface_reference(&dst_surf, NULL);
400 }
401
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)
410 {
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);
424
425 assert(filter == PIPE_TEX_MIPFILTER_NEAREST ||
426 filter == PIPE_TEX_MIPFILTER_LINEAR);
427
428 if (srcLeft != srcX0) {
429 /* left-right flip */
430 int tmp = dstX0;
431 dstX0 = dstX1;
432 dstX1 = tmp;
433 }
434
435 if (srcTop != srcY0) {
436 /* up-down flip */
437 int tmp = dstY0;
438 dstY0 = dstY1;
439 dstY1 = tmp;
440 }
441
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));
448
449 /*
450 * XXX for now we're always creating a temporary texture.
451 * Strictly speaking that's not always needed.
452 */
453
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;
461 texTemp.depth0 = 1;
462
463 tex = screen->resource_create(screen, &texTemp);
464 if (!tex)
465 return;
466
467 u_sampler_view_default_template(&view_templ, tex, tex->format);
468 view = pipe->create_sampler_view(pipe, tex, &view_templ);
469
470 if (!view)
471 return;
472
473 texSurf = screen->get_tex_surface(screen, tex, 0, 0, 0,
474 PIPE_BIND_RENDER_TARGET);
475
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 */
482 } else {
483 util_surface_copy(pipe, FALSE,
484 texSurf, 0, 0, /* dest */
485 src, srcLeft, srcTop, /* src */
486 srcW, srcH); /* size */
487 }
488
489 /* free the surface, update the texture if necessary.*/
490 screen->tex_surface_destroy(texSurf);
491
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);
500
501 /* set misc state we care about */
502 {
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);
511 }
512
513 vg_set_viewport(ctx->owner, VEGA_Y0_TOP);
514
515 /* sampler */
516 {
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);
528 }
529
530 /* texture */
531 cso_set_fragment_sampler_views(ctx->cso, 1, &view);
532
533 /* shaders */
534 cso_set_fragment_shader_handle(ctx->cso, ctx->fs);
535 cso_set_vertex_shader_handle(ctx->cso, vg_texture_vs(ctx->owner));
536
537 /* drawing dest */
538 if (stfb->strb->surface != dst) {
539 memset(&fb, 0, sizeof(fb));
540 fb.width = dst->width;
541 fb.height = dst->height;
542 fb.nr_cbufs = 1;
543 fb.cbufs[0] = dst;
544 fb.zsbuf = stfb->dsrb->surface;
545 cso_set_framebuffer(ctx->cso, &fb);
546 }
547
548 /* draw quad */
549 buf = setup_vertex_data(ctx,
550 (float) dstX0, (float) dstY0,
551 (float) dstX1, (float) dstY1, z);
552
553 if (buf) {
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,
557 4, /* verts */
558 2); /* attribs/vert */
559
560 pipe_resource_reference( &buf,
561 NULL );
562 }
563
564
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);
573
574 pipe_resource_reference(&tex, NULL);
575 pipe_sampler_view_reference(&view, NULL);
576 }
577
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)
586 {
587 struct pipe_context *pipe = r->pipe;
588 struct pipe_resource *buf;
589 VGfloat s0, t0, s1, t1;
590
591 assert(tex->width0 != 0);
592 assert(tex->height0 != 0);
593
594 s0 = x1offset / tex->width0;
595 s1 = x2offset / tex->width0;
596 t0 = y1offset / tex->height0;
597 t1 = y2offset / tex->height0;
598
599 cso_save_vertex_shader(r->cso);
600 /* shaders */
601 cso_set_vertex_shader_handle(r->cso, vg_texture_vs(r->owner));
602
603 /* draw quad */
604 buf = setup_vertex_data_qtex(r, x1, y1, x2, y2, x3, y3, x4, y4,
605 s0, t0, s1, t1, 0.0f);
606
607 if (buf) {
608 cso_set_vertex_elements(r->cso, 2, r->owner->velems);
609 util_draw_vertex_buffer(pipe, buf, 0,
610 PIPE_PRIM_TRIANGLE_FAN,
611 4, /* verts */
612 2); /* attribs/vert */
613
614 pipe_resource_reference(&buf,
615 NULL);
616 }
617
618 cso_restore_vertex_shader(r->cso);
619 }