Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  1. /**************************************************************************
  2.  *
  3.  * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
  4.  * All Rights Reserved.
  5.  *
  6.  * Permission is hereby granted, free of charge, to any person obtaining a
  7.  * copy of this software and associated documentation files (the
  8.  * "Software"), to deal in the Software without restriction, including
  9.  * without limitation the rights to use, copy, modify, merge, publish,
  10.  * distribute, sub license, and/or sell copies of the Software, and to
  11.  * permit persons to whom the Software is furnished to do so, subject to
  12.  * the following conditions:
  13.  *
  14.  * The above copyright notice and this permission notice (including the
  15.  * next paragraph) shall be included in all copies or substantial portions
  16.  * of the Software.
  17.  *
  18.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  19.  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  20.  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
  21.  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
  22.  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  23.  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  24.  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  25.  *
  26.  **************************************************************************/
  27.  
  28. #include "util/u_rect.h"
  29. #include "util/u_surface.h"
  30. #include "lp_context.h"
  31. #include "lp_flush.h"
  32. #include "lp_limits.h"
  33. #include "lp_surface.h"
  34. #include "lp_texture.h"
  35. #include "lp_query.h"
  36.  
  37.  
  38. /**
  39.  * Adjust x, y, width, height to lie on tile bounds.
  40.  */
  41. static void
  42. adjust_to_tile_bounds(unsigned x, unsigned y, unsigned width, unsigned height,
  43.                       unsigned *x_tile, unsigned *y_tile,
  44.                       unsigned *w_tile, unsigned *h_tile)
  45. {
  46.    *x_tile = x & ~(TILE_SIZE - 1);
  47.    *y_tile = y & ~(TILE_SIZE - 1);
  48.    *w_tile = ((x + width + TILE_SIZE - 1) & ~(TILE_SIZE - 1)) - *x_tile;
  49.    *h_tile = ((y + height + TILE_SIZE - 1) & ~(TILE_SIZE - 1)) - *y_tile;
  50. }
  51.  
  52.  
  53.  
  54. static void
  55. lp_resource_copy(struct pipe_context *pipe,
  56.                  struct pipe_resource *dst, unsigned dst_level,
  57.                  unsigned dstx, unsigned dsty, unsigned dstz,
  58.                  struct pipe_resource *src, unsigned src_level,
  59.                  const struct pipe_box *src_box)
  60. {
  61.    struct llvmpipe_resource *src_tex = llvmpipe_resource(src);
  62.    struct llvmpipe_resource *dst_tex = llvmpipe_resource(dst);
  63.    const enum pipe_format format = src_tex->base.format;
  64.    unsigned width = src_box->width;
  65.    unsigned height = src_box->height;
  66.    unsigned depth = src_box->depth;
  67.    unsigned z;
  68.  
  69.    llvmpipe_flush_resource(pipe,
  70.                            dst, dst_level,
  71.                            FALSE, /* read_only */
  72.                            TRUE, /* cpu_access */
  73.                            FALSE, /* do_not_block */
  74.                            "blit dest");
  75.  
  76.    llvmpipe_flush_resource(pipe,
  77.                            src, src_level,
  78.                            TRUE, /* read_only */
  79.                            TRUE, /* cpu_access */
  80.                            FALSE, /* do_not_block */
  81.                            "blit src");
  82.  
  83.    /* Fallback for buffers. */
  84.    if (dst->target == PIPE_BUFFER && src->target == PIPE_BUFFER) {
  85.       util_resource_copy_region(pipe, dst, dst_level, dstx, dsty, dstz,
  86.                                 src, src_level, src_box);
  87.       return;
  88.    }
  89.  
  90.    /*
  91.    printf("surface copy from %u lvl %u to %u lvl %u: %u,%u,%u to %u,%u,%u %u x %u x %u\n",
  92.           src_tex->id, src_level, dst_tex->id, dst_level,
  93.           src_box->x, src_box->y, src_box->z, dstx, dsty, dstz,
  94.           src_box->width, src_box->height, src_box->depth);
  95.    */
  96.  
  97.    for (z = 0; z < src_box->depth; z++){
  98.  
  99.       /* set src tiles to linear layout */
  100.       {
  101.          unsigned tx, ty, tw, th;
  102.          unsigned x, y;
  103.  
  104.          adjust_to_tile_bounds(src_box->x, src_box->y, width, height,
  105.                                &tx, &ty, &tw, &th);
  106.  
  107.          for (y = 0; y < th; y += TILE_SIZE) {
  108.             for (x = 0; x < tw; x += TILE_SIZE) {
  109.                (void) llvmpipe_get_texture_tile_linear(src_tex,
  110.                                                        src_box->z + z, src_level,
  111.                                                        LP_TEX_USAGE_READ,
  112.                                                        tx + x, ty + y);
  113.             }
  114.          }
  115.       }
  116.  
  117.       /* set dst tiles to linear layout */
  118.       {
  119.          unsigned tx, ty, tw, th;
  120.          unsigned x, y;
  121.          enum lp_texture_usage usage;
  122.  
  123.          adjust_to_tile_bounds(dstx, dsty, width, height, &tx, &ty, &tw, &th);
  124.  
  125.          for (y = 0; y < th; y += TILE_SIZE) {
  126.             boolean contained_y = ty + y >= dsty &&
  127.                                   ty + y + TILE_SIZE <= dsty + height ?
  128.                                   TRUE : FALSE;
  129.  
  130.             for (x = 0; x < tw; x += TILE_SIZE) {
  131.                boolean contained_x = tx + x >= dstx &&
  132.                                      tx + x + TILE_SIZE <= dstx + width ?
  133.                                      TRUE : FALSE;
  134.  
  135.                /*
  136.                 * Set the usage mode to WRITE_ALL for the tiles which are
  137.                 * completely contained by the dest rectangle.
  138.                 */
  139.                if (contained_y && contained_x)
  140.                   usage = LP_TEX_USAGE_WRITE_ALL;
  141.                else
  142.                   usage = LP_TEX_USAGE_READ_WRITE;
  143.  
  144.                (void) llvmpipe_get_texture_tile_linear(dst_tex,
  145.                                                        dstz + z, dst_level,
  146.                                                        usage,
  147.                                                        tx + x, ty + y);
  148.             }
  149.          }
  150.       }
  151.    }
  152.  
  153.    /* copy */
  154.    {
  155.       const ubyte *src_linear_ptr
  156.          = llvmpipe_get_texture_image_address(src_tex, src_box->z,
  157.                                               src_level);
  158.       ubyte *dst_linear_ptr
  159.          = llvmpipe_get_texture_image_address(dst_tex, dstz,
  160.                                               dst_level);
  161.  
  162.       if (dst_linear_ptr && src_linear_ptr) {
  163.          util_copy_box(dst_linear_ptr, format,
  164.                        llvmpipe_resource_stride(&dst_tex->base, dst_level),
  165.                        dst_tex->img_stride[dst_level],
  166.                        dstx, dsty, 0,
  167.                        width, height, depth,
  168.                        src_linear_ptr,
  169.                        llvmpipe_resource_stride(&src_tex->base, src_level),
  170.                        src_tex->img_stride[src_level],
  171.                        src_box->x, src_box->y, 0);
  172.       }
  173.    }
  174. }
  175.  
  176.  
  177. static void lp_blit(struct pipe_context *pipe,
  178.                     const struct pipe_blit_info *blit_info)
  179. {
  180.    struct llvmpipe_context *lp = llvmpipe_context(pipe);
  181.    struct pipe_blit_info info = *blit_info;
  182.  
  183.    if (info.src.resource->nr_samples > 1 &&
  184.        info.dst.resource->nr_samples <= 1 &&
  185.        !util_format_is_depth_or_stencil(info.src.resource->format) &&
  186.        !util_format_is_pure_integer(info.src.resource->format)) {
  187.       debug_printf("llvmpipe: color resolve unimplemented\n");
  188.       return;
  189.    }
  190.  
  191.    if (util_try_blit_via_copy_region(pipe, &info)) {
  192.       return; /* done */
  193.    }
  194.  
  195.    if (info.mask & PIPE_MASK_S) {
  196.       debug_printf("llvmpipe: cannot blit stencil, skipping\n");
  197.       info.mask &= ~PIPE_MASK_S;
  198.    }
  199.  
  200.    if (!util_blitter_is_blit_supported(lp->blitter, &info)) {
  201.       debug_printf("llvmpipe: blit unsupported %s -> %s\n",
  202.                    util_format_short_name(info.src.resource->format),
  203.                    util_format_short_name(info.dst.resource->format));
  204.       return;
  205.    }
  206.  
  207.    /* XXX turn off occlusion and streamout queries */
  208.  
  209.    util_blitter_save_vertex_buffer_slot(lp->blitter, lp->vertex_buffer);
  210.    util_blitter_save_vertex_elements(lp->blitter, (void*)lp->velems);
  211.    util_blitter_save_vertex_shader(lp->blitter, (void*)lp->vs);
  212.    util_blitter_save_geometry_shader(lp->blitter, (void*)lp->gs);
  213.    util_blitter_save_so_targets(lp->blitter, lp->num_so_targets,
  214.                                 (struct pipe_stream_output_target**)lp->so_targets);
  215.    util_blitter_save_rasterizer(lp->blitter, (void*)lp->rasterizer);
  216.    util_blitter_save_viewport(lp->blitter, &lp->viewports[0]);
  217.    util_blitter_save_scissor(lp->blitter, &lp->scissors[0]);
  218.    util_blitter_save_fragment_shader(lp->blitter, lp->fs);
  219.    util_blitter_save_blend(lp->blitter, (void*)lp->blend);
  220.    util_blitter_save_depth_stencil_alpha(lp->blitter, (void*)lp->depth_stencil);
  221.    util_blitter_save_stencil_ref(lp->blitter, &lp->stencil_ref);
  222.    /*util_blitter_save_sample_mask(sp->blitter, lp->sample_mask);*/
  223.    util_blitter_save_framebuffer(lp->blitter, &lp->framebuffer);
  224.    util_blitter_save_fragment_sampler_states(lp->blitter,
  225.                      lp->num_samplers[PIPE_SHADER_FRAGMENT],
  226.                      (void**)lp->samplers[PIPE_SHADER_FRAGMENT]);
  227.    util_blitter_save_fragment_sampler_views(lp->blitter,
  228.                      lp->num_sampler_views[PIPE_SHADER_FRAGMENT],
  229.                      lp->sampler_views[PIPE_SHADER_FRAGMENT]);
  230.    util_blitter_save_render_condition(lp->blitter, lp->render_cond_query,
  231.                                       lp->render_cond_cond, lp->render_cond_mode);
  232.    util_blitter_blit(lp->blitter, &info);
  233. }
  234.  
  235.  
  236. static struct pipe_surface *
  237. llvmpipe_create_surface(struct pipe_context *pipe,
  238.                         struct pipe_resource *pt,
  239.                         const struct pipe_surface *surf_tmpl)
  240. {
  241.    struct pipe_surface *ps;
  242.  
  243.    if (!(pt->bind & (PIPE_BIND_DEPTH_STENCIL | PIPE_BIND_RENDER_TARGET)))
  244.       debug_printf("Illegal surface creation without bind flag\n");
  245.  
  246.    ps = CALLOC_STRUCT(pipe_surface);
  247.    if (ps) {
  248.       pipe_reference_init(&ps->reference, 1);
  249.       pipe_resource_reference(&ps->texture, pt);
  250.       ps->context = pipe;
  251.       ps->format = surf_tmpl->format;
  252.       if (llvmpipe_resource_is_texture(pt)) {
  253.          assert(surf_tmpl->u.tex.level <= pt->last_level);
  254.          assert(surf_tmpl->u.tex.first_layer <= surf_tmpl->u.tex.last_layer);
  255.          ps->width = u_minify(pt->width0, surf_tmpl->u.tex.level);
  256.          ps->height = u_minify(pt->height0, surf_tmpl->u.tex.level);
  257.          ps->u.tex.level = surf_tmpl->u.tex.level;
  258.          ps->u.tex.first_layer = surf_tmpl->u.tex.first_layer;
  259.          ps->u.tex.last_layer = surf_tmpl->u.tex.last_layer;
  260.       }
  261.       else {
  262.          /* setting width as number of elements should get us correct renderbuffer width */
  263.          ps->width = surf_tmpl->u.buf.last_element - surf_tmpl->u.buf.first_element + 1;
  264.          ps->height = pt->height0;
  265.          ps->u.buf.first_element = surf_tmpl->u.buf.first_element;
  266.          ps->u.buf.last_element = surf_tmpl->u.buf.last_element;
  267.          assert(ps->u.buf.first_element <= ps->u.buf.last_element);
  268.          assert(util_format_get_blocksize(surf_tmpl->format) *
  269.                 (ps->u.buf.last_element + 1) <= pt->width0);
  270.       }
  271.    }
  272.    return ps;
  273. }
  274.  
  275.  
  276. static void
  277. llvmpipe_surface_destroy(struct pipe_context *pipe,
  278.                          struct pipe_surface *surf)
  279. {
  280.    /* Effectively do the texture_update work here - if texture images
  281.     * needed post-processing to put them into hardware layout, this is
  282.     * where it would happen.  For llvmpipe, nothing to do.
  283.     */
  284.    assert(surf->texture);
  285.    pipe_resource_reference(&surf->texture, NULL);
  286.    FREE(surf);
  287. }
  288.  
  289.  
  290. static void
  291. llvmpipe_clear_render_target(struct pipe_context *pipe,
  292.                              struct pipe_surface *dst,
  293.                              const union pipe_color_union *color,
  294.                              unsigned dstx, unsigned dsty,
  295.                              unsigned width, unsigned height)
  296. {
  297.    struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
  298.  
  299.    if (!llvmpipe_check_render_cond(llvmpipe))
  300.       return;
  301.  
  302.    util_clear_render_target(pipe, dst, color,
  303.                             dstx, dsty, width, height);
  304. }
  305.  
  306.  
  307. static void
  308. llvmpipe_clear_depth_stencil(struct pipe_context *pipe,
  309.                              struct pipe_surface *dst,
  310.                              unsigned clear_flags,
  311.                              double depth,
  312.                              unsigned stencil,
  313.                              unsigned dstx, unsigned dsty,
  314.                              unsigned width, unsigned height)
  315. {
  316.    struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
  317.  
  318.    if (!llvmpipe_check_render_cond(llvmpipe))
  319.       return;
  320.  
  321.    util_clear_depth_stencil(pipe, dst, clear_flags,
  322.                             depth, stencil,
  323.                             dstx, dsty, width, height);
  324. }
  325.  
  326.  
  327. void
  328. llvmpipe_init_surface_functions(struct llvmpipe_context *lp)
  329. {
  330.    lp->pipe.clear_render_target = llvmpipe_clear_render_target;
  331.    lp->pipe.clear_depth_stencil = llvmpipe_clear_depth_stencil;
  332.    lp->pipe.create_surface = llvmpipe_create_surface;
  333.    lp->pipe.surface_destroy = llvmpipe_surface_destroy;
  334.    /* These two are not actually functions dealing with surfaces */
  335.    lp->pipe.resource_copy_region = lp_resource_copy;
  336.    lp->pipe.blit = lp_blit;
  337. }
  338.