Merge branch 'mesa_7_7_branch'
[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 "pipe/p_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 util_draw_vertex_buffer(r->pipe, buf, 0,
214 PIPE_PRIM_TRIANGLE_FAN,
215 4, /* verts */
216 2); /* attribs/vert */
217
218 pipe_buffer_reference( &buf,
219 NULL );
220 }
221 }
222
223 void renderer_draw_texture(struct renderer *r,
224 struct pipe_texture *tex,
225 VGfloat x1offset, VGfloat y1offset,
226 VGfloat x2offset, VGfloat y2offset,
227 VGfloat x1, VGfloat y1,
228 VGfloat x2, VGfloat y2)
229 {
230 struct pipe_context *pipe = r->pipe;
231 struct pipe_buffer *buf;
232 VGfloat s0, t0, s1, t1;
233
234 assert(tex->width0 != 0);
235 assert(tex->height0 != 0);
236
237 s0 = x1offset / tex->width0;
238 s1 = x2offset / tex->width0;
239 t0 = y1offset / tex->height0;
240 t1 = y2offset / tex->height0;
241
242 cso_save_vertex_shader(r->cso);
243 /* shaders */
244 cso_set_vertex_shader_handle(r->cso, vg_texture_vs(r->owner));
245
246 /* draw quad */
247 buf = setup_vertex_data_tex(r, x1, y1, x2, y2,
248 s0, t0, s1, t1, 0.0f);
249
250 if (buf) {
251 util_draw_vertex_buffer(pipe, buf, 0,
252 PIPE_PRIM_TRIANGLE_FAN,
253 4, /* verts */
254 2); /* attribs/vert */
255
256 pipe_buffer_reference( &buf,
257 NULL );
258 }
259
260 cso_restore_vertex_shader(r->cso);
261 }
262
263 void renderer_copy_texture(struct renderer *ctx,
264 struct pipe_texture *src,
265 VGfloat sx1, VGfloat sy1,
266 VGfloat sx2, VGfloat sy2,
267 struct pipe_texture *dst,
268 VGfloat dx1, VGfloat dy1,
269 VGfloat dx2, VGfloat dy2)
270 {
271 struct pipe_context *pipe = ctx->pipe;
272 struct pipe_screen *screen = pipe->screen;
273 struct pipe_buffer *buf;
274 struct pipe_surface *dst_surf = screen->get_tex_surface(
275 screen, dst, 0, 0, 0,
276 PIPE_BUFFER_USAGE_GPU_WRITE);
277 struct pipe_framebuffer_state fb;
278 float s0, t0, s1, t1;
279
280 assert(src->width0 != 0);
281 assert(src->height0 != 0);
282 assert(dst->width0 != 0);
283 assert(dst->height0 != 0);
284
285 #if 0
286 debug_printf("copy texture [%f, %f, %f, %f], [%f, %f, %f, %f]\n",
287 sx1, sy1, sx2, sy2, dx1, dy1, dx2, dy2);
288 #endif
289
290 #if 1
291 s0 = sx1 / src->width0;
292 s1 = sx2 / src->width0;
293 t0 = sy1 / src->height0;
294 t1 = sy2 / src->height0;
295 #else
296 s0 = 0;
297 s1 = 1;
298 t0 = 0;
299 t1 = 1;
300 #endif
301
302 assert(screen->is_format_supported(screen, dst_surf->format, PIPE_TEXTURE_2D,
303 PIPE_TEXTURE_USAGE_RENDER_TARGET, 0));
304
305 /* save state (restored below) */
306 cso_save_blend(ctx->cso);
307 cso_save_samplers(ctx->cso);
308 cso_save_sampler_textures(ctx->cso);
309 cso_save_framebuffer(ctx->cso);
310 cso_save_fragment_shader(ctx->cso);
311 cso_save_vertex_shader(ctx->cso);
312
313 cso_save_viewport(ctx->cso);
314
315
316 /* set misc state we care about */
317 {
318 struct pipe_blend_state blend;
319 memset(&blend, 0, sizeof(blend));
320 blend.rgb_src_factor = PIPE_BLENDFACTOR_ONE;
321 blend.alpha_src_factor = PIPE_BLENDFACTOR_ONE;
322 blend.rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
323 blend.alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
324 blend.colormask = PIPE_MASK_RGBA;
325 cso_set_blend(ctx->cso, &blend);
326 }
327
328 /* sampler */
329 {
330 struct pipe_sampler_state sampler;
331 memset(&sampler, 0, sizeof(sampler));
332 sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
333 sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
334 sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
335 sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
336 sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST;
337 sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
338 sampler.normalized_coords = 1;
339 cso_single_sampler(ctx->cso, 0, &sampler);
340 cso_single_sampler_done(ctx->cso);
341 }
342
343 vg_set_viewport(ctx->owner, VEGA_Y0_TOP);
344
345 /* texture */
346 cso_set_sampler_textures(ctx->cso, 1, &src);
347
348 /* shaders */
349 cso_set_vertex_shader_handle(ctx->cso, vg_texture_vs(ctx->owner));
350 cso_set_fragment_shader_handle(ctx->cso, ctx->fs);
351
352 /* drawing dest */
353 memset(&fb, 0, sizeof(fb));
354 fb.width = dst_surf->width;
355 fb.height = dst_surf->height;
356 fb.nr_cbufs = 1;
357 fb.cbufs[0] = dst_surf;
358 {
359 VGint i;
360 for (i = 1; i < PIPE_MAX_COLOR_BUFS; ++i)
361 fb.cbufs[i] = 0;
362 }
363 cso_set_framebuffer(ctx->cso, &fb);
364
365 /* draw quad */
366 buf = setup_vertex_data_tex(ctx,
367 dx1, dy1,
368 dx2, dy2,
369 s0, t0, s1, t1,
370 0.0f);
371
372 if (buf) {
373 util_draw_vertex_buffer(ctx->pipe, buf, 0,
374 PIPE_PRIM_TRIANGLE_FAN,
375 4, /* verts */
376 2); /* attribs/vert */
377
378 pipe_buffer_reference( &buf,
379 NULL );
380 }
381
382 /* restore state we changed */
383 cso_restore_blend(ctx->cso);
384 cso_restore_samplers(ctx->cso);
385 cso_restore_sampler_textures(ctx->cso);
386 cso_restore_framebuffer(ctx->cso);
387 cso_restore_vertex_shader(ctx->cso);
388 cso_restore_fragment_shader(ctx->cso);
389 cso_restore_viewport(ctx->cso);
390
391 pipe_surface_reference(&dst_surf, NULL);
392 }
393
394 void renderer_copy_surface(struct renderer *ctx,
395 struct pipe_surface *src,
396 int srcX0, int srcY0,
397 int srcX1, int srcY1,
398 struct pipe_surface *dst,
399 int dstX0, int dstY0,
400 int dstX1, int dstY1,
401 float z, unsigned filter)
402 {
403 struct pipe_context *pipe = ctx->pipe;
404 struct pipe_screen *screen = pipe->screen;
405 struct pipe_buffer *buf;
406 struct pipe_texture texTemp, *tex;
407 struct pipe_surface *texSurf;
408 struct pipe_framebuffer_state fb;
409 struct st_framebuffer *stfb = ctx->owner->draw_buffer;
410 const int srcW = abs(srcX1 - srcX0);
411 const int srcH = abs(srcY1 - srcY0);
412 const int srcLeft = MIN2(srcX0, srcX1);
413 const int srcTop = MIN2(srcY0, srcY1);
414
415 assert(filter == PIPE_TEX_MIPFILTER_NEAREST ||
416 filter == PIPE_TEX_MIPFILTER_LINEAR);
417
418 if (srcLeft != srcX0) {
419 /* left-right flip */
420 int tmp = dstX0;
421 dstX0 = dstX1;
422 dstX1 = tmp;
423 }
424
425 if (srcTop != srcY0) {
426 /* up-down flip */
427 int tmp = dstY0;
428 dstY0 = dstY1;
429 dstY1 = tmp;
430 }
431
432 assert(screen->is_format_supported(screen, src->format, PIPE_TEXTURE_2D,
433 PIPE_TEXTURE_USAGE_SAMPLER, 0));
434 assert(screen->is_format_supported(screen, dst->format, PIPE_TEXTURE_2D,
435 PIPE_TEXTURE_USAGE_SAMPLER, 0));
436 assert(screen->is_format_supported(screen, dst->format, PIPE_TEXTURE_2D,
437 PIPE_TEXTURE_USAGE_RENDER_TARGET, 0));
438
439 /*
440 * XXX for now we're always creating a temporary texture.
441 * Strictly speaking that's not always needed.
442 */
443
444 /* create temp texture */
445 memset(&texTemp, 0, sizeof(texTemp));
446 texTemp.target = PIPE_TEXTURE_2D;
447 texTemp.format = src->format;
448 texTemp.last_level = 0;
449 texTemp.width0 = srcW;
450 texTemp.height0 = srcH;
451 texTemp.depth0 = 1;
452
453 tex = screen->texture_create(screen, &texTemp);
454 if (!tex)
455 return;
456
457 texSurf = screen->get_tex_surface(screen, tex, 0, 0, 0,
458 PIPE_BUFFER_USAGE_GPU_WRITE);
459
460 /* load temp texture */
461 if (pipe->surface_copy) {
462 pipe->surface_copy(pipe,
463 texSurf, 0, 0, /* dest */
464 src, srcLeft, srcTop, /* src */
465 srcW, srcH); /* size */
466 } else {
467 util_surface_copy(pipe, FALSE,
468 texSurf, 0, 0, /* dest */
469 src, srcLeft, srcTop, /* src */
470 srcW, srcH); /* size */
471 }
472
473 /* free the surface, update the texture if necessary.*/
474 screen->tex_surface_destroy(texSurf);
475
476 /* save state (restored below) */
477 cso_save_blend(ctx->cso);
478 cso_save_samplers(ctx->cso);
479 cso_save_sampler_textures(ctx->cso);
480 cso_save_framebuffer(ctx->cso);
481 cso_save_fragment_shader(ctx->cso);
482 cso_save_vertex_shader(ctx->cso);
483 cso_save_viewport(ctx->cso);
484
485 /* set misc state we care about */
486 {
487 struct pipe_blend_state blend;
488 memset(&blend, 0, sizeof(blend));
489 blend.rgb_src_factor = PIPE_BLENDFACTOR_ONE;
490 blend.alpha_src_factor = PIPE_BLENDFACTOR_ONE;
491 blend.rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
492 blend.alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
493 blend.colormask = PIPE_MASK_RGBA;
494 cso_set_blend(ctx->cso, &blend);
495 }
496
497 vg_set_viewport(ctx->owner, VEGA_Y0_TOP);
498
499 /* sampler */
500 {
501 struct pipe_sampler_state sampler;
502 memset(&sampler, 0, sizeof(sampler));
503 sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
504 sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
505 sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
506 sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
507 sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST;
508 sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
509 sampler.normalized_coords = 1;
510 cso_single_sampler(ctx->cso, 0, &sampler);
511 cso_single_sampler_done(ctx->cso);
512 }
513
514 /* texture */
515 cso_set_sampler_textures(ctx->cso, 1, &tex);
516
517 /* shaders */
518 cso_set_fragment_shader_handle(ctx->cso, ctx->fs);
519 cso_set_vertex_shader_handle(ctx->cso, vg_texture_vs(ctx->owner));
520
521 /* drawing dest */
522 if (stfb->strb->surface != dst) {
523 memset(&fb, 0, sizeof(fb));
524 fb.width = dst->width;
525 fb.height = dst->height;
526 fb.nr_cbufs = 1;
527 fb.cbufs[0] = dst;
528 fb.zsbuf = stfb->dsrb->surface;
529 cso_set_framebuffer(ctx->cso, &fb);
530 }
531
532 /* draw quad */
533 buf = setup_vertex_data(ctx,
534 (float) dstX0, (float) dstY0,
535 (float) dstX1, (float) dstY1, z);
536
537 if (buf) {
538 util_draw_vertex_buffer(ctx->pipe, buf, 0,
539 PIPE_PRIM_TRIANGLE_FAN,
540 4, /* verts */
541 2); /* attribs/vert */
542
543 pipe_buffer_reference( &buf,
544 NULL );
545 }
546
547
548 /* restore state we changed */
549 cso_restore_blend(ctx->cso);
550 cso_restore_samplers(ctx->cso);
551 cso_restore_sampler_textures(ctx->cso);
552 cso_restore_framebuffer(ctx->cso);
553 cso_restore_fragment_shader(ctx->cso);
554 cso_restore_vertex_shader(ctx->cso);
555 cso_restore_viewport(ctx->cso);
556
557 pipe_texture_reference(&tex, NULL);
558 }
559
560 void renderer_texture_quad(struct renderer *r,
561 struct pipe_texture *tex,
562 VGfloat x1offset, VGfloat y1offset,
563 VGfloat x2offset, VGfloat y2offset,
564 VGfloat x1, VGfloat y1,
565 VGfloat x2, VGfloat y2,
566 VGfloat x3, VGfloat y3,
567 VGfloat x4, VGfloat y4)
568 {
569 struct pipe_context *pipe = r->pipe;
570 struct pipe_buffer *buf;
571 VGfloat s0, t0, s1, t1;
572
573 assert(tex->width0 != 0);
574 assert(tex->height0 != 0);
575
576 s0 = x1offset / tex->width0;
577 s1 = x2offset / tex->width0;
578 t0 = y1offset / tex->height0;
579 t1 = y2offset / tex->height0;
580
581 cso_save_vertex_shader(r->cso);
582 /* shaders */
583 cso_set_vertex_shader_handle(r->cso, vg_texture_vs(r->owner));
584
585 /* draw quad */
586 buf = setup_vertex_data_qtex(r, x1, y1, x2, y2, x3, y3, x4, y4,
587 s0, t0, s1, t1, 0.0f);
588
589 if (buf) {
590 util_draw_vertex_buffer(pipe, buf, 0,
591 PIPE_PRIM_TRIANGLE_FAN,
592 4, /* verts */
593 2); /* attribs/vert */
594
595 pipe_buffer_reference(&buf,
596 NULL);
597 }
598
599 cso_restore_vertex_shader(r->cso);
600 }