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