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