Home | History | Annotate | Download | only in i915
      1 /**************************************************************************
      2  *
      3  * Copyright 2003 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 "i915_surface.h"
     29 #include "i915_resource.h"
     30 #include "i915_state.h"
     31 #include "i915_blit.h"
     32 #include "i915_reg.h"
     33 #include "i915_screen.h"
     34 #include "pipe/p_defines.h"
     35 #include "util/u_inlines.h"
     36 #include "util/u_math.h"
     37 #include "util/u_format.h"
     38 #include "util/u_memory.h"
     39 #include "util/u_pack_color.h"
     40 #include "util/u_surface.h"
     41 
     42 /*
     43  * surface functions using the render engine
     44  */
     45 
     46 static void
     47 i915_surface_copy_render(struct pipe_context *pipe,
     48                          struct pipe_resource *dst, unsigned dst_level,
     49                          unsigned dstx, unsigned dsty, unsigned dstz,
     50                          struct pipe_resource *src, unsigned src_level,
     51                          const struct pipe_box *src_box)
     52 {
     53    struct i915_context *i915 = i915_context(pipe);
     54 
     55    /* Fallback for buffers. */
     56    if (dst->target == PIPE_BUFFER && src->target == PIPE_BUFFER) {
     57       util_resource_copy_region(pipe, dst, dst_level, dstx, dsty, dstz,
     58                                 src, src_level, src_box);
     59       return;
     60    }
     61 
     62    if (!util_blitter_is_copy_supported(i915->blitter, dst, src,
     63                                        PIPE_MASK_RGBAZS)) {
     64       util_resource_copy_region(pipe, dst, dst_level, dstx, dsty, dstz,
     65                                 src, src_level, src_box);
     66       return;
     67    }
     68 
     69    util_blitter_save_blend(i915->blitter, (void *)i915->blend);
     70    util_blitter_save_depth_stencil_alpha(i915->blitter, (void *)i915->depth_stencil);
     71    util_blitter_save_stencil_ref(i915->blitter, &i915->stencil_ref);
     72    util_blitter_save_rasterizer(i915->blitter, (void *)i915->rasterizer);
     73    util_blitter_save_fragment_shader(i915->blitter, i915->saved_fs);
     74    util_blitter_save_vertex_shader(i915->blitter, i915->saved_vs);
     75    util_blitter_save_viewport(i915->blitter, &i915->viewport);
     76    util_blitter_save_vertex_elements(i915->blitter, i915->saved_velems);
     77    util_blitter_save_vertex_buffers(i915->blitter, i915->saved_nr_vertex_buffers,
     78                                     i915->saved_vertex_buffers);
     79 
     80    util_blitter_save_framebuffer(i915->blitter, &i915->framebuffer);
     81 
     82    util_blitter_save_fragment_sampler_states(i915->blitter,
     83                                              i915->saved_nr_samplers,
     84                                              i915->saved_samplers);
     85    util_blitter_save_fragment_sampler_views(i915->blitter,
     86                                             i915->saved_nr_sampler_views,
     87                                             i915->saved_sampler_views);
     88 
     89    util_blitter_copy_texture(i915->blitter, dst, dst_level, ~0, dstx, dsty, dstz,
     90                             src, src_level, 0, src_box);
     91 }
     92 
     93 static void
     94 i915_clear_render_target_render(struct pipe_context *pipe,
     95                                 struct pipe_surface *dst,
     96                                 const union pipe_color_union *color,
     97                                 unsigned dstx, unsigned dsty,
     98                                 unsigned width, unsigned height)
     99 {
    100    struct i915_context *i915 = i915_context(pipe);
    101    struct pipe_framebuffer_state fb_state;
    102 
    103    util_blitter_save_framebuffer(i915->blitter, &i915->framebuffer);
    104 
    105    fb_state.width = dst->width;
    106    fb_state.height = dst->height;
    107    fb_state.nr_cbufs = 1;
    108    fb_state.cbufs[0] = dst;
    109    fb_state.zsbuf = NULL;
    110    pipe->set_framebuffer_state(pipe, &fb_state);
    111 
    112    if (i915->dirty)
    113       i915_update_derived(i915);
    114 
    115    i915_clear_emit(pipe, PIPE_CLEAR_COLOR, color, 0.0, 0x0,
    116                    dstx, dsty, width, height);
    117 
    118    pipe->set_framebuffer_state(pipe, &i915->blitter->saved_fb_state);
    119    util_unreference_framebuffer_state(&i915->blitter->saved_fb_state);
    120    i915->blitter->saved_fb_state.nr_cbufs = ~0;
    121 }
    122 
    123 static void
    124 i915_clear_depth_stencil_render(struct pipe_context *pipe,
    125                                 struct pipe_surface *dst,
    126                                 unsigned clear_flags,
    127                                 double depth,
    128                                 unsigned stencil,
    129                                 unsigned dstx, unsigned dsty,
    130                                 unsigned width, unsigned height)
    131 {
    132    struct i915_context *i915 = i915_context(pipe);
    133    struct pipe_framebuffer_state fb_state;
    134 
    135    util_blitter_save_framebuffer(i915->blitter, &i915->framebuffer);
    136 
    137    fb_state.width = dst->width;
    138    fb_state.height = dst->height;
    139    fb_state.nr_cbufs = 0;
    140    fb_state.zsbuf = dst;
    141    pipe->set_framebuffer_state(pipe, &fb_state);
    142 
    143    if (i915->dirty)
    144       i915_update_derived(i915);
    145 
    146    i915_clear_emit(pipe, clear_flags & PIPE_CLEAR_DEPTHSTENCIL,
    147                    NULL, depth, stencil,
    148                    dstx, dsty, width, height);
    149 
    150    pipe->set_framebuffer_state(pipe, &i915->blitter->saved_fb_state);
    151    util_unreference_framebuffer_state(&i915->blitter->saved_fb_state);
    152    i915->blitter->saved_fb_state.nr_cbufs = ~0;
    153 }
    154 
    155 /*
    156  * surface functions using the blitter
    157  */
    158 
    159 /* Assumes all values are within bounds -- no checking at this level -
    160  * do it higher up if required.
    161  */
    162 static void
    163 i915_surface_copy_blitter(struct pipe_context *pipe,
    164                           struct pipe_resource *dst, unsigned dst_level,
    165                           unsigned dstx, unsigned dsty, unsigned dstz,
    166                           struct pipe_resource *src, unsigned src_level,
    167                           const struct pipe_box *src_box)
    168 {
    169    struct i915_texture *dst_tex = i915_texture(dst);
    170    struct i915_texture *src_tex = i915_texture(src);
    171    struct pipe_resource *dpt = &dst_tex->b.b;
    172    struct pipe_resource *spt = &src_tex->b.b;
    173    unsigned dst_offset, src_offset;  /* in bytes */
    174 
    175    /* Fallback for buffers. */
    176    if (dst->target == PIPE_BUFFER && src->target == PIPE_BUFFER) {
    177       util_resource_copy_region(pipe, dst, dst_level, dstx, dsty, dstz,
    178                                 src, src_level, src_box);
    179       return;
    180    }
    181 
    182    /* XXX cannot copy 3d regions at this time */
    183    assert(src_box->depth == 1);
    184    if (dst->target != PIPE_TEXTURE_CUBE &&
    185        dst->target != PIPE_TEXTURE_3D)
    186       assert(dstz == 0);
    187    dst_offset = i915_texture_offset(dst_tex, dst_level, dstz);
    188 
    189    if (src->target != PIPE_TEXTURE_CUBE &&
    190        src->target != PIPE_TEXTURE_3D)
    191       assert(src_box->z == 0);
    192    src_offset = i915_texture_offset(src_tex, src_level, src_box->z);
    193 
    194    assert( util_format_get_blocksize(dpt->format) == util_format_get_blocksize(spt->format) );
    195    assert( util_format_get_blockwidth(dpt->format) == util_format_get_blockwidth(spt->format) );
    196    assert( util_format_get_blockheight(dpt->format) == util_format_get_blockheight(spt->format) );
    197    assert( util_format_get_blockwidth(dpt->format) == 1 );
    198    assert( util_format_get_blockheight(dpt->format) == 1 );
    199 
    200    i915_copy_blit( i915_context(pipe),
    201                    util_format_get_blocksize(dpt->format),
    202                    (unsigned short) src_tex->stride, src_tex->buffer, src_offset,
    203                    (unsigned short) dst_tex->stride, dst_tex->buffer, dst_offset,
    204                    (short) src_box->x, (short) src_box->y, (short) dstx, (short) dsty,
    205                    (short) src_box->width, (short) src_box->height );
    206 }
    207 
    208 static void
    209 i915_clear_render_target_blitter(struct pipe_context *pipe,
    210                                  struct pipe_surface *dst,
    211                                  const union pipe_color_union *color,
    212                                  unsigned dstx, unsigned dsty,
    213                                  unsigned width, unsigned height)
    214 {
    215    struct i915_texture *tex = i915_texture(dst->texture);
    216    struct pipe_resource *pt = &tex->b.b;
    217    union util_color uc;
    218    unsigned offset = i915_texture_offset(tex, dst->u.tex.level, dst->u.tex.first_layer);
    219 
    220    assert(util_format_get_blockwidth(pt->format) == 1);
    221    assert(util_format_get_blockheight(pt->format) == 1);
    222 
    223    util_pack_color(color->f, dst->format, &uc);
    224    i915_fill_blit( i915_context(pipe),
    225                    util_format_get_blocksize(pt->format),
    226                    XY_COLOR_BLT_WRITE_ALPHA | XY_COLOR_BLT_WRITE_RGB,
    227                    (unsigned short) tex->stride,
    228                    tex->buffer, offset,
    229                    (short) dstx, (short) dsty,
    230                    (short) width, (short) height,
    231                    uc.ui );
    232 }
    233 
    234 static void
    235 i915_clear_depth_stencil_blitter(struct pipe_context *pipe,
    236                                  struct pipe_surface *dst,
    237                                  unsigned clear_flags,
    238                                  double depth,
    239                                  unsigned stencil,
    240                                  unsigned dstx, unsigned dsty,
    241                                  unsigned width, unsigned height)
    242 {
    243    struct i915_texture *tex = i915_texture(dst->texture);
    244    struct pipe_resource *pt = &tex->b.b;
    245    unsigned packedds;
    246    unsigned mask = 0;
    247    unsigned offset = i915_texture_offset(tex, dst->u.tex.level, dst->u.tex.first_layer);
    248 
    249    assert(util_format_get_blockwidth(pt->format) == 1);
    250    assert(util_format_get_blockheight(pt->format) == 1);
    251 
    252    packedds = util_pack_z_stencil(dst->format, depth, stencil);
    253 
    254    if (clear_flags & PIPE_CLEAR_DEPTH)
    255       mask |= XY_COLOR_BLT_WRITE_RGB;
    256    /* XXX presumably this does read-modify-write
    257       (otherwise this won't work anyway). Hence will only want to
    258       do it if really have stencil and it isn't cleared */
    259    if ((clear_flags & PIPE_CLEAR_STENCIL) ||
    260        (dst->format != PIPE_FORMAT_Z24_UNORM_S8_UINT))
    261       mask |= XY_COLOR_BLT_WRITE_ALPHA;
    262 
    263    i915_fill_blit( i915_context(pipe),
    264                    util_format_get_blocksize(pt->format),
    265                    mask,
    266                    (unsigned short) tex->stride,
    267                    tex->buffer, offset,
    268                    (short) dstx, (short) dsty,
    269                    (short) width, (short) height,
    270                    packedds );
    271 }
    272 
    273 /*
    274  * Screen surface functions
    275  */
    276 
    277 
    278 static struct pipe_surface *
    279 i915_create_surface(struct pipe_context *ctx,
    280                     struct pipe_resource *pt,
    281                     const struct pipe_surface *surf_tmpl)
    282 {
    283    struct pipe_surface *ps;
    284 
    285    assert(surf_tmpl->u.tex.first_layer == surf_tmpl->u.tex.last_layer);
    286    if (pt->target != PIPE_TEXTURE_CUBE &&
    287        pt->target != PIPE_TEXTURE_3D)
    288       assert(surf_tmpl->u.tex.first_layer == 0);
    289 
    290    ps = CALLOC_STRUCT(pipe_surface);
    291    if (ps) {
    292       /* could subclass pipe_surface and store offset as it used to do */
    293       pipe_reference_init(&ps->reference, 1);
    294       pipe_resource_reference(&ps->texture, pt);
    295       ps->format = surf_tmpl->format;
    296       ps->width = u_minify(pt->width0, surf_tmpl->u.tex.level);
    297       ps->height = u_minify(pt->height0, surf_tmpl->u.tex.level);
    298       ps->u.tex.level = surf_tmpl->u.tex.level;
    299       ps->u.tex.first_layer = surf_tmpl->u.tex.first_layer;
    300       ps->u.tex.last_layer = surf_tmpl->u.tex.last_layer;
    301       ps->usage = surf_tmpl->usage;
    302       ps->context = ctx;
    303    }
    304    return ps;
    305 }
    306 
    307 static void
    308 i915_surface_destroy(struct pipe_context *ctx,
    309                      struct pipe_surface *surf)
    310 {
    311    pipe_resource_reference(&surf->texture, NULL);
    312    FREE(surf);
    313 }
    314 
    315 
    316 void
    317 i915_init_surface_functions(struct i915_context *i915)
    318 {
    319    if (i915_screen(i915->base.screen)->debug.use_blitter) {
    320       i915->base.resource_copy_region = i915_surface_copy_blitter;
    321       i915->base.clear_render_target = i915_clear_render_target_blitter;
    322       i915->base.clear_depth_stencil = i915_clear_depth_stencil_blitter;
    323    } else {
    324       i915->base.resource_copy_region = i915_surface_copy_render;
    325       i915->base.clear_render_target = i915_clear_render_target_render;
    326       i915->base.clear_depth_stencil = i915_clear_depth_stencil_render;
    327    }
    328    i915->base.create_surface = i915_create_surface;
    329    i915->base.surface_destroy = i915_surface_destroy;
    330 }
    331