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