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