u_blit.c

Go to the documentation of this file.
00001 /**************************************************************************
00002  *
00003  * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
00004  * All Rights Reserved.
00005  *
00006  * Permission is hereby granted, free of charge, to any person obtaining a
00007  * copy of this software and associated documentation files (the
00008  * "Software"), to deal in the Software without restriction, including
00009  * without limitation the rights to use, copy, modify, merge, publish,
00010  * distribute, sub license, and/or sell copies of the Software, and to
00011  * permit persons to whom the Software is furnished to do so, subject to
00012  * the following conditions:
00013  *
00014  * The above copyright notice and this permission notice (including the
00015  * next paragraph) shall be included in all copies or substantial portions
00016  * of the Software.
00017  *
00018  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
00019  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00020  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
00021  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
00022  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
00023  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
00024  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00025  *
00026  **************************************************************************/
00027 
00036 #include "pipe/p_context.h"
00037 #include "pipe/p_debug.h"
00038 #include "pipe/p_defines.h"
00039 #include "pipe/p_inlines.h"
00040 #include "pipe/p_winsys.h"
00041 #include "pipe/p_shader_tokens.h"
00042 
00043 #include "util/u_blit.h"
00044 #include "util/u_draw_quad.h"
00045 #include "util/u_math.h"
00046 #include "util/u_memory.h"
00047 #include "util/u_simple_shaders.h"
00048 
00049 #include "cso_cache/cso_context.h"
00050 
00051 
00052 struct blit_state
00053 {
00054    struct pipe_context *pipe;
00055    struct cso_context *cso;
00056 
00057    struct pipe_blend_state blend;
00058    struct pipe_depth_stencil_alpha_state depthstencil;
00059    struct pipe_rasterizer_state rasterizer;
00060    struct pipe_sampler_state sampler;
00061    struct pipe_viewport_state viewport;
00062 
00063    struct pipe_shader_state vert_shader;
00064    struct pipe_shader_state frag_shader;
00065    void *vs;
00066    void *fs;
00067 
00068    struct pipe_buffer *vbuf;  
00069    unsigned vbuf_slot;
00070 
00071    float vertices[4][2][4];   
00072 };
00073 
00074 
00079 struct blit_state *
00080 util_create_blit(struct pipe_context *pipe, struct cso_context *cso)
00081 {
00082    struct blit_state *ctx;
00083    uint i;
00084 
00085    ctx = CALLOC_STRUCT(blit_state);
00086    if (!ctx)
00087       return NULL;
00088 
00089    ctx->pipe = pipe;
00090    ctx->cso = cso;
00091 
00092    /* disabled blending/masking */
00093    memset(&ctx->blend, 0, sizeof(ctx->blend));
00094    ctx->blend.rgb_src_factor = PIPE_BLENDFACTOR_ONE;
00095    ctx->blend.alpha_src_factor = PIPE_BLENDFACTOR_ONE;
00096    ctx->blend.rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
00097    ctx->blend.alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
00098    ctx->blend.colormask = PIPE_MASK_RGBA;
00099 
00100    /* no-op depth/stencil/alpha */
00101    memset(&ctx->depthstencil, 0, sizeof(ctx->depthstencil));
00102 
00103    /* rasterizer */
00104    memset(&ctx->rasterizer, 0, sizeof(ctx->rasterizer));
00105    ctx->rasterizer.front_winding = PIPE_WINDING_CW;
00106    ctx->rasterizer.cull_mode = PIPE_WINDING_NONE;
00107    ctx->rasterizer.bypass_clipping = 1;
00108    /*ctx->rasterizer.bypass_vs = 1;*/
00109    ctx->rasterizer.gl_rasterization_rules = 1;
00110 
00111    /* samplers */
00112    memset(&ctx->sampler, 0, sizeof(ctx->sampler));
00113    ctx->sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
00114    ctx->sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
00115    ctx->sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
00116    ctx->sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
00117    ctx->sampler.min_img_filter = 0; /* set later */
00118    ctx->sampler.mag_img_filter = 0; /* set later */
00119    ctx->sampler.normalized_coords = 1;
00120 
00121    /* viewport (identity, we setup vertices in wincoords) */
00122    ctx->viewport.scale[0] = 1.0;
00123    ctx->viewport.scale[1] = 1.0;
00124    ctx->viewport.scale[2] = 1.0;
00125    ctx->viewport.scale[3] = 1.0;
00126    ctx->viewport.translate[0] = 0.0;
00127    ctx->viewport.translate[1] = 0.0;
00128    ctx->viewport.translate[2] = 0.0;
00129    ctx->viewport.translate[3] = 0.0;
00130 
00131    /* vertex shader */
00132    {
00133       const uint semantic_names[] = { TGSI_SEMANTIC_POSITION,
00134                                       TGSI_SEMANTIC_GENERIC };
00135       const uint semantic_indexes[] = { 0, 0 };
00136       ctx->vs = util_make_vertex_passthrough_shader(pipe, 2, semantic_names,
00137                                                     semantic_indexes,
00138                                                     &ctx->vert_shader);
00139    }
00140 
00141    /* fragment shader */
00142    ctx->fs = util_make_fragment_tex_shader(pipe, &ctx->frag_shader);
00143    ctx->vbuf = NULL;
00144 
00145    /* init vertex data that doesn't change */
00146    for (i = 0; i < 4; i++) {
00147       ctx->vertices[i][0][3] = 1.0f; /* w */
00148       ctx->vertices[i][1][2] = 0.0f; /* r */
00149       ctx->vertices[i][1][3] = 1.0f; /* q */
00150    }
00151 
00152    return ctx;
00153 }
00154 
00155 
00159 void
00160 util_destroy_blit(struct blit_state *ctx)
00161 {
00162    struct pipe_context *pipe = ctx->pipe;
00163 
00164    pipe->delete_vs_state(pipe, ctx->vs);
00165    pipe->delete_fs_state(pipe, ctx->fs);
00166 
00167    FREE((void*) ctx->vert_shader.tokens);
00168    FREE((void*) ctx->frag_shader.tokens);
00169 
00170    pipe_buffer_reference(pipe->screen, &ctx->vbuf, NULL);
00171 
00172    FREE(ctx);
00173 }
00174 
00175 
00176 static unsigned get_next_slot( struct blit_state *ctx )
00177 {
00178    const unsigned max_slots = 4096 / sizeof ctx->vertices;
00179 
00180    if (ctx->vbuf_slot >= max_slots) 
00181       util_blit_flush( ctx );
00182 
00183    if (!ctx->vbuf) {
00184       ctx->vbuf = pipe_buffer_create(ctx->pipe->screen,
00185                                      32,
00186                                      PIPE_BUFFER_USAGE_VERTEX,
00187                                      max_slots * sizeof ctx->vertices);
00188    }
00189    
00190    return ctx->vbuf_slot++ * sizeof ctx->vertices;
00191 }
00192                                
00193 
00194 
00199 static unsigned
00200 setup_vertex_data(struct blit_state *ctx,
00201                   float x0, float y0, float x1, float y1, float z)
00202 {
00203    void *buf;
00204    unsigned offset;
00205 
00206    ctx->vertices[0][0][0] = x0;
00207    ctx->vertices[0][0][1] = y0;
00208    ctx->vertices[0][0][2] = z;
00209    ctx->vertices[0][1][0] = 0.0f; /*s*/
00210    ctx->vertices[0][1][1] = 0.0f; /*t*/
00211 
00212    ctx->vertices[1][0][0] = x1;
00213    ctx->vertices[1][0][1] = y0;
00214    ctx->vertices[1][0][2] = z;
00215    ctx->vertices[1][1][0] = 1.0f; /*s*/
00216    ctx->vertices[1][1][1] = 0.0f; /*t*/
00217 
00218    ctx->vertices[2][0][0] = x1;
00219    ctx->vertices[2][0][1] = y1;
00220    ctx->vertices[2][0][2] = z;
00221    ctx->vertices[2][1][0] = 1.0f;
00222    ctx->vertices[2][1][1] = 1.0f;
00223 
00224    ctx->vertices[3][0][0] = x0;
00225    ctx->vertices[3][0][1] = y1;
00226    ctx->vertices[3][0][2] = z;
00227    ctx->vertices[3][1][0] = 0.0f;
00228    ctx->vertices[3][1][1] = 1.0f;
00229 
00230    offset = get_next_slot( ctx );
00231 
00232    buf = pipe_buffer_map(ctx->pipe->screen, ctx->vbuf,
00233                          PIPE_BUFFER_USAGE_CPU_WRITE);
00234 
00235    memcpy((char *)buf + offset, ctx->vertices, sizeof(ctx->vertices));
00236 
00237    pipe_buffer_unmap(ctx->pipe->screen, ctx->vbuf);
00238 
00239    return offset;
00240 }
00241 
00242 
00247 static unsigned
00248 setup_vertex_data_tex(struct blit_state *ctx,
00249                       float x0, float y0, float x1, float y1,
00250                       float s0, float t0, float s1, float t1,
00251                       float z)
00252 {
00253    void *buf;
00254    unsigned offset;
00255 
00256    ctx->vertices[0][0][0] = x0;
00257    ctx->vertices[0][0][1] = y0;
00258    ctx->vertices[0][0][2] = z;
00259    ctx->vertices[0][1][0] = s0; /*s*/
00260    ctx->vertices[0][1][1] = t0; /*t*/
00261 
00262    ctx->vertices[1][0][0] = x1;
00263    ctx->vertices[1][0][1] = y0;
00264    ctx->vertices[1][0][2] = z;
00265    ctx->vertices[1][1][0] = s1; /*s*/
00266    ctx->vertices[1][1][1] = t0; /*t*/
00267 
00268    ctx->vertices[2][0][0] = x1;
00269    ctx->vertices[2][0][1] = y1;
00270    ctx->vertices[2][0][2] = z;
00271    ctx->vertices[2][1][0] = s1;
00272    ctx->vertices[2][1][1] = t1;
00273 
00274    ctx->vertices[3][0][0] = x0;
00275    ctx->vertices[3][0][1] = y1;
00276    ctx->vertices[3][0][2] = z;
00277    ctx->vertices[3][1][0] = s0;
00278    ctx->vertices[3][1][1] = t1;
00279 
00280    offset = get_next_slot( ctx );
00281 
00282    buf = pipe_buffer_map(ctx->pipe->screen, ctx->vbuf,
00283                          PIPE_BUFFER_USAGE_CPU_WRITE);
00284 
00285    memcpy((char *)buf + offset, ctx->vertices, sizeof(ctx->vertices));
00286 
00287    pipe_buffer_unmap(ctx->pipe->screen, ctx->vbuf);
00288 
00289    return offset;
00290 }
00296 void
00297 util_blit_pixels(struct blit_state *ctx,
00298                  struct pipe_surface *src,
00299                  int srcX0, int srcY0,
00300                  int srcX1, int srcY1,
00301                  struct pipe_surface *dst,
00302                  int dstX0, int dstY0,
00303                  int dstX1, int dstY1,
00304                  float z, uint filter)
00305 {
00306    struct pipe_context *pipe = ctx->pipe;
00307    struct pipe_screen *screen = pipe->screen;
00308    struct pipe_texture texTemp, *tex;
00309    struct pipe_surface *texSurf;
00310    struct pipe_framebuffer_state fb;
00311    const int srcW = abs(srcX1 - srcX0);
00312    const int srcH = abs(srcY1 - srcY0);
00313    const int srcLeft = MIN2(srcX0, srcX1);
00314    const int srcTop = MIN2(srcY0, srcY1);
00315    unsigned offset;
00316 
00317    assert(filter == PIPE_TEX_MIPFILTER_NEAREST ||
00318           filter == PIPE_TEX_MIPFILTER_LINEAR);
00319 
00320    if (srcLeft != srcX0) {
00321       /* left-right flip */
00322       int tmp = dstX0;
00323       dstX0 = dstX1;
00324       dstX1 = tmp;
00325    }
00326 
00327    if (srcTop != srcY0) {
00328       /* up-down flip */
00329       int tmp = dstY0;
00330       dstY0 = dstY1;
00331       dstY1 = tmp;
00332    }
00333 
00334    assert(screen->is_format_supported(screen, src->format, PIPE_TEXTURE_2D,
00335                                       PIPE_TEXTURE_USAGE_SAMPLER, 0));
00336    assert(screen->is_format_supported(screen, dst->format, PIPE_TEXTURE_2D,
00337                                       PIPE_TEXTURE_USAGE_SAMPLER, 0));
00338 
00339    if(dst->format == src->format && (dstX1 - dstX0) == srcW && (dstY1 - dstY0) == srcH) {
00340       /* FIXME: this will most surely fail for overlapping rectangles */
00341       pipe->surface_copy(pipe, FALSE,
00342                          dst, dstX0, dstY0,   /* dest */
00343                          src, srcX0, srcY0, /* src */
00344                          srcW, srcH);     /* size */
00345       return;
00346    }
00347    
00348    assert(screen->is_format_supported(screen, dst->format, PIPE_TEXTURE_2D,
00349                                       PIPE_TEXTURE_USAGE_RENDER_TARGET, 0));
00350 
00351    /*
00352     * XXX for now we're always creating a temporary texture.
00353     * Strictly speaking that's not always needed.
00354     */
00355 
00356    /* create temp texture */
00357    memset(&texTemp, 0, sizeof(texTemp));
00358    texTemp.target = PIPE_TEXTURE_2D;
00359    texTemp.format = src->format;
00360    texTemp.last_level = 0;
00361    texTemp.width[0] = srcW;
00362    texTemp.height[0] = srcH;
00363    texTemp.depth[0] = 1;
00364    texTemp.compressed = 0;
00365    pf_get_block(src->format, &texTemp.block);
00366 
00367    tex = screen->texture_create(screen, &texTemp);
00368    if (!tex)
00369       return;
00370 
00371    texSurf = screen->get_tex_surface(screen, tex, 0, 0, 0, 
00372                                      PIPE_BUFFER_USAGE_GPU_WRITE);
00373 
00374    /* load temp texture */
00375    pipe->surface_copy(pipe, FALSE,
00376                       texSurf, 0, 0,   /* dest */
00377                       src, srcLeft, srcTop, /* src */
00378                       srcW, srcH);     /* size */
00379 
00380    /* free the surface, update the texture if necessary.
00381     */
00382    screen->tex_surface_release(screen, &texSurf);
00383 
00384    /* save state (restored below) */
00385    cso_save_blend(ctx->cso);
00386    cso_save_depth_stencil_alpha(ctx->cso);
00387    cso_save_rasterizer(ctx->cso);
00388    cso_save_samplers(ctx->cso);
00389    cso_save_sampler_textures(ctx->cso);
00390    cso_save_framebuffer(ctx->cso);
00391    cso_save_fragment_shader(ctx->cso);
00392    cso_save_vertex_shader(ctx->cso);
00393    cso_save_viewport(ctx->cso);
00394 
00395    /* set misc state we care about */
00396    cso_set_blend(ctx->cso, &ctx->blend);
00397    cso_set_depth_stencil_alpha(ctx->cso, &ctx->depthstencil);
00398    cso_set_rasterizer(ctx->cso, &ctx->rasterizer);
00399    cso_set_viewport(ctx->cso, &ctx->viewport);
00400 
00401    /* sampler */
00402    ctx->sampler.min_img_filter = filter;
00403    ctx->sampler.mag_img_filter = filter;
00404    cso_single_sampler(ctx->cso, 0, &ctx->sampler);
00405    cso_single_sampler_done(ctx->cso);
00406 
00407    /* texture */
00408    cso_set_sampler_textures(ctx->cso, 1, &tex);
00409 
00410    /* shaders */
00411    cso_set_fragment_shader_handle(ctx->cso, ctx->fs);
00412    cso_set_vertex_shader_handle(ctx->cso, ctx->vs);
00413 
00414    /* drawing dest */
00415    memset(&fb, 0, sizeof(fb));
00416    fb.width = dst->width;
00417    fb.height = dst->height;
00418    fb.num_cbufs = 1;
00419    fb.cbufs[0] = dst;
00420    cso_set_framebuffer(ctx->cso, &fb);
00421 
00422    /* draw quad */
00423    offset = setup_vertex_data(ctx,
00424                               (float) dstX0, (float) dstY0, 
00425                               (float) dstX1, (float) dstY1, z);
00426 
00427    util_draw_vertex_buffer(ctx->pipe, ctx->vbuf, offset,
00428                            PIPE_PRIM_TRIANGLE_FAN,
00429                            4,  /* verts */
00430                            2); /* attribs/vert */
00431 
00432    /* restore state we changed */
00433    cso_restore_blend(ctx->cso);
00434    cso_restore_depth_stencil_alpha(ctx->cso);
00435    cso_restore_rasterizer(ctx->cso);
00436    cso_restore_samplers(ctx->cso);
00437    cso_restore_sampler_textures(ctx->cso);
00438    cso_restore_framebuffer(ctx->cso);
00439    cso_restore_fragment_shader(ctx->cso);
00440    cso_restore_vertex_shader(ctx->cso);
00441    cso_restore_viewport(ctx->cso);
00442 
00443    screen->texture_release(screen, &tex);
00444 }
00445 
00446 
00447 /* Release vertex buffer at end of frame to avoid synchronous
00448  * rendering.
00449  */
00450 void util_blit_flush( struct blit_state *ctx )
00451 {
00452    pipe_buffer_reference(ctx->pipe->screen, &ctx->vbuf, NULL);
00453    ctx->vbuf_slot = 0;
00454 } 
00455 
00456 
00457 
00465 void
00466 util_blit_pixels_tex(struct blit_state *ctx,
00467                  struct pipe_texture *tex,
00468                  int srcX0, int srcY0,
00469                  int srcX1, int srcY1,
00470                  struct pipe_surface *dst,
00471                  int dstX0, int dstY0,
00472                  int dstX1, int dstY1,
00473                  float z, uint filter)
00474 {
00475    struct pipe_context *pipe = ctx->pipe;
00476    struct pipe_screen *screen = pipe->screen;
00477    struct pipe_framebuffer_state fb;
00478    float s0, t0, s1, t1;
00479    unsigned offset;
00480 
00481    assert(filter == PIPE_TEX_MIPFILTER_NEAREST ||
00482           filter == PIPE_TEX_MIPFILTER_LINEAR);
00483 
00484    assert(tex->width[0] != 0);
00485    assert(tex->height[0] != 0);
00486 
00487    s0 = srcX0 / (float)tex->width[0];
00488    s1 = srcX1 / (float)tex->width[0];
00489    t0 = srcY0 / (float)tex->height[0];
00490    t1 = srcY1 / (float)tex->height[0];
00491 
00492    assert(screen->is_format_supported(screen, dst->format, PIPE_TEXTURE_2D,
00493                                       PIPE_TEXTURE_USAGE_RENDER_TARGET, 0));
00494 
00495    /* save state (restored below) */
00496    cso_save_blend(ctx->cso);
00497    cso_save_depth_stencil_alpha(ctx->cso);
00498    cso_save_rasterizer(ctx->cso);
00499    cso_save_samplers(ctx->cso);
00500    cso_save_sampler_textures(ctx->cso);
00501    cso_save_framebuffer(ctx->cso);
00502    cso_save_fragment_shader(ctx->cso);
00503    cso_save_vertex_shader(ctx->cso);
00504    cso_save_viewport(ctx->cso);
00505 
00506    /* set misc state we care about */
00507    cso_set_blend(ctx->cso, &ctx->blend);
00508    cso_set_depth_stencil_alpha(ctx->cso, &ctx->depthstencil);
00509    cso_set_rasterizer(ctx->cso, &ctx->rasterizer);
00510    cso_set_viewport(ctx->cso, &ctx->viewport);
00511 
00512    /* sampler */
00513    ctx->sampler.min_img_filter = filter;
00514    ctx->sampler.mag_img_filter = filter;
00515    cso_single_sampler(ctx->cso, 0, &ctx->sampler);
00516    cso_single_sampler_done(ctx->cso);
00517 
00518    /* texture */
00519    cso_set_sampler_textures(ctx->cso, 1, &tex);
00520 
00521    /* shaders */
00522    cso_set_fragment_shader_handle(ctx->cso, ctx->fs);
00523    cso_set_vertex_shader_handle(ctx->cso, ctx->vs);
00524 
00525    /* drawing dest */
00526    memset(&fb, 0, sizeof(fb));
00527    fb.width = dst->width;
00528    fb.height = dst->height;
00529    fb.num_cbufs = 1;
00530    fb.cbufs[0] = dst;
00531    cso_set_framebuffer(ctx->cso, &fb);
00532 
00533    /* draw quad */
00534    offset = setup_vertex_data_tex(ctx,
00535                                   (float) dstX0, (float) dstY0,
00536                                   (float) dstX1, (float) dstY1,
00537                                   s0, t0, s1, t1,
00538                                   z);
00539 
00540    util_draw_vertex_buffer(ctx->pipe, 
00541                            ctx->vbuf, offset,
00542                            PIPE_PRIM_TRIANGLE_FAN,
00543                            4,  /* verts */
00544                            2); /* attribs/vert */
00545 
00546    /* restore state we changed */
00547    cso_restore_blend(ctx->cso);
00548    cso_restore_depth_stencil_alpha(ctx->cso);
00549    cso_restore_rasterizer(ctx->cso);
00550    cso_restore_samplers(ctx->cso);
00551    cso_restore_sampler_textures(ctx->cso);
00552    cso_restore_framebuffer(ctx->cso);
00553    cso_restore_fragment_shader(ctx->cso);
00554    cso_restore_vertex_shader(ctx->cso);
00555    cso_restore_viewport(ctx->cso);
00556 }

Generated on Tue Sep 29 06:25:15 2009 for Gallium3D by  doxygen 1.5.4