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