Home | History | Annotate | Download | only in i915
      1 /**************************************************************************
      2  *
      3  * Copyright 2007 VMware, Inc.
      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 VMWARE 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 /* Authors:
     29  *    Brian Paul
     30  */
     31 
     32 
     33 #include "util/u_format.h"
     34 #include "util/u_pack_color.h"
     35 #include "i915_context.h"
     36 #include "i915_screen.h"
     37 #include "i915_reg.h"
     38 #include "i915_batch.h"
     39 #include "i915_resource.h"
     40 #include "i915_state.h"
     41 
     42 void
     43 i915_clear_emit(struct pipe_context *pipe, unsigned buffers,
     44                 const union pipe_color_union *color,
     45                 double depth, unsigned stencil,
     46                 unsigned destx, unsigned desty, unsigned width, unsigned height)
     47 {
     48    struct i915_context *i915 = i915_context(pipe);
     49    uint32_t clear_params, clear_color, clear_depth, clear_stencil,
     50             clear_color8888, packed_z_stencil;
     51    union util_color u_color;
     52    float f_depth = depth;
     53    struct i915_texture *cbuf_tex, *depth_tex;
     54    int depth_clear_bbp, color_clear_bbp;
     55 
     56    cbuf_tex = depth_tex = NULL;
     57    clear_params = 0;
     58    depth_clear_bbp = color_clear_bbp = 0;
     59 
     60    if (buffers & PIPE_CLEAR_COLOR) {
     61       struct pipe_surface *cbuf = i915->framebuffer.cbufs[0];
     62 
     63       clear_params |= CLEARPARAM_WRITE_COLOR;
     64       cbuf_tex = i915_texture(cbuf->texture);
     65 
     66       util_pack_color(color->f, cbuf->format, &u_color);
     67       if (util_format_get_blocksize(cbuf_tex->b.b.format) == 4) {
     68          clear_color = u_color.ui[0];
     69          color_clear_bbp = 32;
     70       } else {
     71          clear_color = (u_color.ui[0] & 0xffff) | (u_color.ui[0] << 16);
     72          color_clear_bbp = 16;
     73       }
     74 
     75       /* correctly swizzle clear value */
     76       if (i915->current.target_fixup_format)
     77          util_pack_color(color->f, cbuf->format, &u_color);
     78       else
     79          util_pack_color(color->f, PIPE_FORMAT_B8G8R8A8_UNORM, &u_color);
     80       clear_color8888 = u_color.ui[0];
     81    } else
     82       clear_color = clear_color8888 = 0;
     83 
     84    clear_depth = clear_stencil = 0;
     85    if (buffers & PIPE_CLEAR_DEPTH) {
     86       struct pipe_surface *zbuf = i915->framebuffer.zsbuf;
     87 
     88       clear_params |= CLEARPARAM_WRITE_DEPTH;
     89       depth_tex = i915_texture(zbuf->texture);
     90       packed_z_stencil = util_pack_z_stencil(depth_tex->b.b.format, depth, stencil);
     91 
     92       if (util_format_get_blocksize(depth_tex->b.b.format) == 4) {
     93          /* Avoid read-modify-write if there's no stencil. */
     94          if (buffers & PIPE_CLEAR_STENCIL
     95                || depth_tex->b.b.format != PIPE_FORMAT_Z24_UNORM_S8_UINT) {
     96             clear_params |= CLEARPARAM_WRITE_STENCIL;
     97             clear_stencil = packed_z_stencil >> 24;
     98          }
     99 
    100          clear_depth = packed_z_stencil & 0xffffff;
    101          depth_clear_bbp = 32;
    102       } else {
    103          clear_depth = (packed_z_stencil & 0xffff) | (packed_z_stencil << 16);
    104          depth_clear_bbp = 16;
    105       }
    106    } else if (buffers & PIPE_CLEAR_STENCIL) {
    107       struct pipe_surface *zbuf = i915->framebuffer.zsbuf;
    108 
    109       clear_params |= CLEARPARAM_WRITE_STENCIL;
    110       depth_tex = i915_texture(zbuf->texture);
    111       assert(depth_tex->b.b.format == PIPE_FORMAT_Z24_UNORM_S8_UINT);
    112 
    113       packed_z_stencil = util_pack_z_stencil(depth_tex->b.b.format, depth, stencil);
    114       depth_clear_bbp = 32;
    115       clear_stencil = packed_z_stencil >> 24;
    116    }
    117 
    118    /* hw can't fastclear both depth and color if their bbp mismatch. */
    119    if (color_clear_bbp && depth_clear_bbp
    120          && color_clear_bbp != depth_clear_bbp) {
    121       if (i915->hardware_dirty)
    122          i915_emit_hardware_state(i915);
    123 
    124       if (!BEGIN_BATCH(1 + 2*(7 + 7))) {
    125          FLUSH_BATCH(NULL, I915_FLUSH_ASYNC);
    126 
    127          i915_emit_hardware_state(i915);
    128          i915->vbo_flushed = 1;
    129 
    130          assert(BEGIN_BATCH(1 + 2*(7 + 7)));
    131       }
    132 
    133       OUT_BATCH(_3DSTATE_SCISSOR_ENABLE_CMD | DISABLE_SCISSOR_RECT);
    134 
    135       OUT_BATCH(_3DSTATE_CLEAR_PARAMETERS);
    136       OUT_BATCH(CLEARPARAM_WRITE_COLOR | CLEARPARAM_CLEAR_RECT);
    137       /* Used for zone init prim */
    138       OUT_BATCH(clear_color);
    139       OUT_BATCH(clear_depth);
    140       /* Used for clear rect prim */
    141       OUT_BATCH(clear_color8888);
    142       OUT_BATCH_F(f_depth);
    143       OUT_BATCH(clear_stencil);
    144 
    145       OUT_BATCH(_3DPRIMITIVE | PRIM3D_CLEAR_RECT | 5);
    146       OUT_BATCH_F(destx + width);
    147       OUT_BATCH_F(desty + height);
    148       OUT_BATCH_F(destx);
    149       OUT_BATCH_F(desty + height);
    150       OUT_BATCH_F(destx);
    151       OUT_BATCH_F(desty);
    152 
    153       OUT_BATCH(_3DSTATE_CLEAR_PARAMETERS);
    154       OUT_BATCH((clear_params & ~CLEARPARAM_WRITE_COLOR) |
    155                 CLEARPARAM_CLEAR_RECT);
    156       /* Used for zone init prim */
    157       OUT_BATCH(clear_color);
    158       OUT_BATCH(clear_depth);
    159       /* Used for clear rect prim */
    160       OUT_BATCH(clear_color8888);
    161       OUT_BATCH_F(f_depth);
    162       OUT_BATCH(clear_stencil);
    163 
    164       OUT_BATCH(_3DPRIMITIVE | PRIM3D_CLEAR_RECT | 5);
    165       OUT_BATCH_F(destx + width);
    166       OUT_BATCH_F(desty + height);
    167       OUT_BATCH_F(destx);
    168       OUT_BATCH_F(desty + height);
    169       OUT_BATCH_F(destx);
    170       OUT_BATCH_F(desty);
    171    } else {
    172       if (i915->hardware_dirty)
    173          i915_emit_hardware_state(i915);
    174 
    175       if (!BEGIN_BATCH(1 + 7 + 7)) {
    176          FLUSH_BATCH(NULL, I915_FLUSH_ASYNC);
    177 
    178          i915_emit_hardware_state(i915);
    179          i915->vbo_flushed = 1;
    180 
    181          assert(BEGIN_BATCH(1 + 7 + 7));
    182       }
    183 
    184       OUT_BATCH(_3DSTATE_SCISSOR_ENABLE_CMD | DISABLE_SCISSOR_RECT);
    185 
    186       OUT_BATCH(_3DSTATE_CLEAR_PARAMETERS);
    187       OUT_BATCH(clear_params | CLEARPARAM_CLEAR_RECT);
    188       /* Used for zone init prim */
    189       OUT_BATCH(clear_color);
    190       OUT_BATCH(clear_depth);
    191       /* Used for clear rect prim */
    192       OUT_BATCH(clear_color8888);
    193       OUT_BATCH_F(f_depth);
    194       OUT_BATCH(clear_stencil);
    195 
    196       OUT_BATCH(_3DPRIMITIVE | PRIM3D_CLEAR_RECT | 5);
    197       OUT_BATCH_F(destx + width);
    198       OUT_BATCH_F(desty + height);
    199       OUT_BATCH_F(destx);
    200       OUT_BATCH_F(desty + height);
    201       OUT_BATCH_F(destx);
    202       OUT_BATCH_F(desty);
    203    }
    204 
    205    /* Flush after clear, its expected to be a costly operation.
    206     * This is not required, just a heuristic, but without the flush we'd need to
    207     * clobber the SCISSOR_ENABLE dynamic state. */
    208    FLUSH_BATCH(NULL, I915_FLUSH_ASYNC);
    209 
    210    i915->last_fired_vertices = i915->fired_vertices;
    211    i915->fired_vertices = 0;
    212 }
    213 
    214 /**
    215  * Clear the given buffers to the specified values.
    216  * No masking, no scissor (clear entire buffer).
    217  */
    218 void
    219 i915_clear_blitter(struct pipe_context *pipe, unsigned buffers,
    220                    const union pipe_color_union *color,
    221                    double depth, unsigned stencil)
    222 {
    223    struct pipe_framebuffer_state *framebuffer =
    224       &i915_context(pipe)->framebuffer;
    225    unsigned i;
    226 
    227    for (i = 0; i < framebuffer->nr_cbufs; i++) {
    228       if (buffers & (PIPE_CLEAR_COLOR0 << i)) {
    229          struct pipe_surface *ps = framebuffer->cbufs[i];
    230 
    231          if (ps) {
    232             pipe->clear_render_target(pipe, ps, color, 0, 0, ps->width,
    233                                       ps->height, true);
    234          }
    235       }
    236    }
    237 
    238    if (buffers & PIPE_CLEAR_DEPTHSTENCIL) {
    239       struct pipe_surface *ps = framebuffer->zsbuf;
    240       pipe->clear_depth_stencil(pipe, ps, buffers & PIPE_CLEAR_DEPTHSTENCIL,
    241                                 depth, stencil,
    242                                 0, 0, ps->width, ps->height, true);
    243    }
    244 }
    245 
    246 void
    247 i915_clear_render(struct pipe_context *pipe, unsigned buffers,
    248                   const union pipe_color_union *color,
    249                   double depth, unsigned stencil)
    250 {
    251    struct i915_context *i915 = i915_context(pipe);
    252 
    253    if (i915->dirty)
    254       i915_update_derived(i915);
    255 
    256    i915_clear_emit(pipe, buffers, color, depth, stencil,
    257                    0, 0, i915->framebuffer.width, i915->framebuffer.height);
    258 }
    259