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