Home | History | Annotate | Download | only in svga
      1 /**********************************************************
      2  * Copyright 2008-2009 VMware, Inc.  All rights reserved.
      3  *
      4  * Permission is hereby granted, free of charge, to any person
      5  * obtaining a copy of this software and associated documentation
      6  * files (the "Software"), to deal in the Software without
      7  * restriction, including without limitation the rights to use, copy,
      8  * modify, merge, publish, distribute, sublicense, and/or sell copies
      9  * of the Software, and to permit persons to whom the Software is
     10  * furnished to do so, subject to the following conditions:
     11  *
     12  * The above copyright notice and this permission notice shall be
     13  * included in all copies or substantial portions of the Software.
     14  *
     15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
     16  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     17  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
     18  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
     19  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
     20  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
     21  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
     22  * SOFTWARE.
     23  *
     24  **********************************************************/
     25 
     26 #include "svga_cmd.h"
     27 #include "svga_debug.h"
     28 
     29 #include "pipe/p_defines.h"
     30 #include "util/u_pack_color.h"
     31 #include "util/u_surface.h"
     32 
     33 #include "svga_context.h"
     34 #include "svga_state.h"
     35 #include "svga_surface.h"
     36 
     37 
     38 /**
     39  * Saving blitter states before doing any blitter operation
     40  */
     41 static void
     42 begin_blit(struct svga_context *svga)
     43 {
     44    util_blitter_save_vertex_buffer_slot(svga->blitter, svga->curr.vb);
     45    util_blitter_save_vertex_elements(svga->blitter, (void*)svga->curr.velems);
     46    util_blitter_save_vertex_shader(svga->blitter, svga->curr.vs);
     47    util_blitter_save_geometry_shader(svga->blitter, svga->curr.gs);
     48    util_blitter_save_so_targets(svga->blitter, svga->num_so_targets,
     49                      (struct pipe_stream_output_target**)svga->so_targets);
     50    util_blitter_save_rasterizer(svga->blitter, (void*)svga->curr.rast);
     51    util_blitter_save_viewport(svga->blitter, &svga->curr.viewport);
     52    util_blitter_save_scissor(svga->blitter, &svga->curr.scissor);
     53    util_blitter_save_fragment_shader(svga->blitter, svga->curr.fs);
     54    util_blitter_save_blend(svga->blitter, (void*)svga->curr.blend);
     55    util_blitter_save_depth_stencil_alpha(svga->blitter,
     56                                          (void*)svga->curr.depth);
     57    util_blitter_save_stencil_ref(svga->blitter, &svga->curr.stencil_ref);
     58    util_blitter_save_sample_mask(svga->blitter, svga->curr.sample_mask);
     59 }
     60 
     61 
     62 /**
     63  * Clear the whole color buffer(s) by drawing a quad.  For VGPU10 we use
     64  * this when clearing integer render targets.  We'll also clear the
     65  * depth and/or stencil buffers if the clear_buffers mask specifies them.
     66  */
     67 static void
     68 clear_buffers_with_quad(struct svga_context *svga,
     69                         unsigned clear_buffers,
     70                         const union pipe_color_union *color,
     71                         double depth, unsigned stencil)
     72 {
     73    const struct pipe_framebuffer_state *fb = &svga->curr.framebuffer;
     74 
     75    begin_blit(svga);
     76    util_blitter_clear(svga->blitter,
     77                       fb->width, fb->height,
     78                       1, /* num_layers */
     79                       clear_buffers, color,
     80                       depth, stencil);
     81 }
     82 
     83 
     84 /**
     85  * Check if any of the color buffers are integer buffers.
     86  */
     87 static boolean
     88 is_integer_target(struct pipe_framebuffer_state *fb, unsigned buffers)
     89 {
     90    unsigned i;
     91 
     92    for (i = 0; i < fb->nr_cbufs; i++) {
     93       if ((buffers & (PIPE_CLEAR_COLOR0 << i)) &&
     94           fb->cbufs[i] &&
     95           util_format_is_pure_integer(fb->cbufs[i]->format)) {
     96          return TRUE;
     97       }
     98    }
     99    return FALSE;
    100 }
    101 
    102 
    103 /**
    104  * Check if the integer values in the clear color can be represented
    105  * by floats.  If so, we can use the VGPU10 ClearRenderTargetView command.
    106  * Otherwise, we need to clear with a quad.
    107  */
    108 static boolean
    109 ints_fit_in_floats(const union pipe_color_union *color)
    110 {
    111    const int max = 1 << 24;
    112    return (color->i[0] <= max &&
    113            color->i[1] <= max &&
    114            color->i[2] <= max &&
    115            color->i[3] <= max);
    116 }
    117 
    118 
    119 static enum pipe_error
    120 try_clear(struct svga_context *svga,
    121           unsigned buffers,
    122           const union pipe_color_union *color,
    123           double depth,
    124           unsigned stencil)
    125 {
    126    enum pipe_error ret = PIPE_OK;
    127    SVGA3dRect rect = { 0, 0, 0, 0 };
    128    boolean restore_viewport = FALSE;
    129    SVGA3dClearFlag flags = 0;
    130    struct pipe_framebuffer_state *fb = &svga->curr.framebuffer;
    131    union util_color uc = {0};
    132 
    133    ret = svga_update_state(svga, SVGA_STATE_HW_CLEAR);
    134    if (ret != PIPE_OK)
    135       return ret;
    136 
    137    if (svga->rebind.flags.rendertargets) {
    138       ret = svga_reemit_framebuffer_bindings(svga);
    139       if (ret != PIPE_OK) {
    140          return ret;
    141       }
    142    }
    143 
    144    if (buffers & PIPE_CLEAR_COLOR) {
    145       flags |= SVGA3D_CLEAR_COLOR;
    146       util_pack_color(color->f, PIPE_FORMAT_B8G8R8A8_UNORM, &uc);
    147 
    148       rect.w = fb->width;
    149       rect.h = fb->height;
    150    }
    151 
    152    if ((buffers & PIPE_CLEAR_DEPTHSTENCIL) && fb->zsbuf) {
    153       if (buffers & PIPE_CLEAR_DEPTH)
    154          flags |= SVGA3D_CLEAR_DEPTH;
    155 
    156       if (buffers & PIPE_CLEAR_STENCIL)
    157          flags |= SVGA3D_CLEAR_STENCIL;
    158 
    159       rect.w = MAX2(rect.w, fb->zsbuf->width);
    160       rect.h = MAX2(rect.h, fb->zsbuf->height);
    161    }
    162 
    163    if (!svga_have_vgpu10(svga) &&
    164        !svga_rects_equal(&rect, &svga->state.hw_clear.viewport)) {
    165       restore_viewport = TRUE;
    166       ret = SVGA3D_SetViewport(svga->swc, &rect);
    167       if (ret != PIPE_OK)
    168          return ret;
    169    }
    170 
    171    if (svga_have_vgpu10(svga)) {
    172       if (flags & SVGA3D_CLEAR_COLOR) {
    173          unsigned i;
    174 
    175          if (is_integer_target(fb, buffers) && !ints_fit_in_floats(color)) {
    176             clear_buffers_with_quad(svga, buffers, color, depth, stencil);
    177             /* We also cleared depth/stencil, so that's done */
    178             flags &= ~(SVGA3D_CLEAR_DEPTH | SVGA3D_CLEAR_STENCIL);
    179          }
    180          else {
    181             struct pipe_surface *rtv;
    182 
    183             /* Issue VGPU10 Clear commands */
    184             for (i = 0; i < fb->nr_cbufs; i++) {
    185                if ((fb->cbufs[i] == NULL) ||
    186                    !(buffers & (PIPE_CLEAR_COLOR0 << i)))
    187                   continue;
    188 
    189                rtv = svga_validate_surface_view(svga,
    190                                                 svga_surface(fb->cbufs[i]));
    191                if (!rtv)
    192                   return PIPE_ERROR_OUT_OF_MEMORY;
    193 
    194                ret = SVGA3D_vgpu10_ClearRenderTargetView(svga->swc,
    195                                                          rtv, color->f);
    196                if (ret != PIPE_OK)
    197                   return ret;
    198             }
    199          }
    200       }
    201       if (flags & (SVGA3D_CLEAR_DEPTH | SVGA3D_CLEAR_STENCIL)) {
    202          struct pipe_surface *dsv =
    203             svga_validate_surface_view(svga, svga_surface(fb->zsbuf));
    204          if (!dsv)
    205             return PIPE_ERROR_OUT_OF_MEMORY;
    206 
    207          ret = SVGA3D_vgpu10_ClearDepthStencilView(svga->swc, dsv, flags,
    208                                                    stencil, (float) depth);
    209          if (ret != PIPE_OK)
    210             return ret;
    211       }
    212    }
    213    else {
    214       ret = SVGA3D_ClearRect(svga->swc, flags, uc.ui[0], (float) depth, stencil,
    215                              rect.x, rect.y, rect.w, rect.h);
    216       if (ret != PIPE_OK)
    217          return ret;
    218    }
    219 
    220    if (restore_viewport) {
    221       ret = SVGA3D_SetViewport(svga->swc, &svga->state.hw_clear.viewport);
    222    }
    223 
    224    return ret;
    225 }
    226 
    227 /**
    228  * Clear the given surface to the specified value.
    229  * No masking, no scissor (clear entire buffer).
    230  */
    231 static void
    232 svga_clear(struct pipe_context *pipe, unsigned buffers,
    233            const union pipe_color_union *color,
    234 	   double depth, unsigned stencil)
    235 {
    236    struct svga_context *svga = svga_context( pipe );
    237    enum pipe_error ret;
    238 
    239    if (buffers & PIPE_CLEAR_COLOR) {
    240       struct svga_winsys_surface *h = NULL;
    241       if (svga->curr.framebuffer.cbufs[0]) {
    242          h = svga_surface(svga->curr.framebuffer.cbufs[0])->handle;
    243       }
    244       SVGA_DBG(DEBUG_DMA, "clear sid %p\n", h);
    245    }
    246 
    247    /* flush any queued prims (don't want them to appear after the clear!) */
    248    svga_hwtnl_flush_retry(svga);
    249 
    250    ret = try_clear( svga, buffers, color, depth, stencil );
    251 
    252    if (ret == PIPE_ERROR_OUT_OF_MEMORY) {
    253       /* Flush command buffer and retry:
    254        */
    255       svga_context_flush( svga, NULL );
    256 
    257       ret = try_clear( svga, buffers, color, depth, stencil );
    258    }
    259 
    260    /*
    261     * Mark target surfaces as dirty
    262     * TODO Mark only cleared surfaces.
    263     */
    264    svga_mark_surfaces_dirty(svga);
    265 
    266    assert (ret == PIPE_OK);
    267 }
    268 
    269 
    270 static void
    271 svga_clear_texture(struct pipe_context *pipe,
    272                    struct pipe_resource *res,
    273                    unsigned level,
    274                    const struct pipe_box *box,
    275                    const void *data)
    276 {
    277    struct svga_context *svga = svga_context(pipe);
    278    struct svga_surface *svga_surface_dst;
    279    enum pipe_error ret;
    280    struct pipe_surface tmpl;
    281    struct pipe_surface *surface;
    282 
    283    memset(&tmpl, 0, sizeof(tmpl));
    284    tmpl.format = res->format;
    285    tmpl.u.tex.first_layer = box->z;
    286    tmpl.u.tex.last_layer = box->z + box->depth - 1;
    287    tmpl.u.tex.level = level;
    288 
    289    surface = pipe->create_surface(pipe, res, &tmpl);
    290    if (surface == NULL) {
    291       debug_printf("failed to create surface\n");
    292       return;
    293    }
    294    svga_surface_dst = svga_surface(surface);
    295 
    296    union pipe_color_union color;
    297    const struct util_format_description *desc =
    298       util_format_description(surface->format);
    299 
    300    if (util_format_is_depth_or_stencil(surface->format)) {
    301       float depth;
    302       uint8_t stencil;
    303       unsigned clear_flags = 0;
    304 
    305       /* If data is NULL, then set depthValue and stencilValue to zeros */
    306       if (data == NULL) {
    307          depth = 0.0;
    308          stencil = 0;
    309       }
    310       else {
    311          desc->unpack_z_float(&depth, 0, data, 0, 1, 1);
    312          desc->unpack_s_8uint(&stencil, 0, data, 0, 1, 1);
    313       }
    314 
    315       if (util_format_has_depth(desc)) {
    316          clear_flags |= PIPE_CLEAR_DEPTH;
    317       }
    318       if (util_format_has_stencil(desc)) {
    319          clear_flags |= PIPE_CLEAR_STENCIL;
    320       }
    321 
    322       /* Setup depth stencil view */
    323       struct pipe_surface *dsv =
    324          svga_validate_surface_view(svga, svga_surface_dst);
    325 
    326       if (!dsv) {
    327          pipe_surface_reference(&surface, NULL);
    328          return;
    329       }
    330 
    331       if (box->x == 0 && box->y == 0 && box->width == surface->width &&
    332           box->height == surface->height) {
    333          /* clearing whole surface, use direct VGPU10 command */
    334 
    335 
    336          ret = SVGA3D_vgpu10_ClearDepthStencilView(svga->swc, dsv,
    337                                                    clear_flags,
    338                                                    stencil, depth);
    339          if (ret != PIPE_OK) {
    340             /* flush and try again */
    341             svga_context_flush(svga, NULL);
    342             ret = SVGA3D_vgpu10_ClearDepthStencilView(svga->swc, dsv,
    343                                                       clear_flags,
    344                                                       stencil, depth);
    345             assert(ret == PIPE_OK);
    346          }
    347       }
    348       else {
    349          /* To clear subtexture use software fallback */
    350 
    351          util_blitter_save_framebuffer(svga->blitter,
    352                                        &svga->curr.framebuffer);
    353          begin_blit(svga);
    354          util_blitter_clear_depth_stencil(svga->blitter,
    355                                           dsv, clear_flags,
    356                                           depth,stencil,
    357                                           box->x, box->y,
    358                                           box->width, box->height);
    359       }
    360    }
    361    else {
    362       /* non depth-stencil formats */
    363 
    364       if (data == NULL) {
    365          /* If data is NULL, the texture image is filled with zeros */
    366          color.f[0] = color.f[1] = color.f[2] = color.f[3] = 0;
    367       }
    368       else {
    369          if (util_format_is_pure_sint(surface->format)) {
    370             /* signed integer */
    371             desc->unpack_rgba_sint(color.i, 0, data, 0, 1, 1);
    372          }
    373          else if (util_format_is_pure_uint(surface->format)) {
    374             /* unsigned integer */
    375             desc->unpack_rgba_uint(color.ui, 0, data, 0, 1, 1);
    376          }
    377          else {
    378             /* floating point */
    379             desc->unpack_rgba_float(color.f, 0, data, 0, 1, 1);
    380          }
    381       }
    382 
    383       /* Setup render target view */
    384       struct pipe_surface *rtv =
    385          svga_validate_surface_view(svga, svga_surface_dst);
    386 
    387       if (!rtv) {
    388          pipe_surface_reference(&surface, NULL);
    389          return;
    390       }
    391 
    392       if (box->x == 0 && box->y == 0 && box->width == surface->width &&
    393           box->height == surface->height) {
    394          struct pipe_framebuffer_state *curr =  &svga->curr.framebuffer;
    395 
    396          if (is_integer_target(curr, PIPE_CLEAR_COLOR) &&
    397              !ints_fit_in_floats(&color)) {
    398             /* To clear full texture with integer format */
    399             clear_buffers_with_quad(svga, PIPE_CLEAR_COLOR, &color, 0.0, 0);
    400          }
    401          else {
    402             /* clearing whole surface using VGPU10 command */
    403             ret = SVGA3D_vgpu10_ClearRenderTargetView(svga->swc, rtv,
    404                                                       color.f);
    405             if (ret != PIPE_OK) {
    406                svga_context_flush(svga,NULL);
    407                ret = SVGA3D_vgpu10_ClearRenderTargetView(svga->swc, rtv,
    408                                                          color.f);
    409                assert(ret == PIPE_OK);
    410             }
    411          }
    412       }
    413       else {
    414          /* To clear subtexture use software fallback */
    415 
    416          /**
    417           * util_blitter_clear_render_target doesn't support PIPE_TEXTURE_3D
    418           * It tries to draw quad with depth 0 for PIPE_TEXTURE_3D so use
    419           * util_clear_render_target() for PIPE_TEXTURE_3D.
    420           */
    421          if (rtv->texture->target != PIPE_TEXTURE_3D &&
    422              pipe->screen->is_format_supported(pipe->screen, rtv->format,
    423                                                rtv->texture->target,
    424                                                rtv->texture->nr_samples,
    425                                                PIPE_BIND_RENDER_TARGET)) {
    426             /* clear with quad drawing */
    427             util_blitter_save_framebuffer(svga->blitter,
    428                                           &svga->curr.framebuffer);
    429             begin_blit(svga);
    430             util_blitter_clear_render_target(svga->blitter,
    431                                              rtv,
    432                                              &color,
    433                                              box->x, box->y,
    434                                              box->width, box->height);
    435          }
    436          else {
    437             /* clear with map/write/unmap */
    438 
    439             /* store layer values */
    440             unsigned first_layer = rtv->u.tex.first_layer;
    441             unsigned last_layer = rtv->u.tex.last_layer;
    442             unsigned box_depth = last_layer - first_layer + 1;
    443 
    444             for (unsigned i = 0; i < box_depth; i++) {
    445                rtv->u.tex.first_layer = rtv->u.tex.last_layer =
    446                   first_layer + i;
    447                util_clear_render_target(pipe, rtv, &color, box->x, box->y,
    448                                         box->width, box->height);
    449             }
    450             /* restore layer values */
    451             rtv->u.tex.first_layer = first_layer;
    452             rtv->u.tex.last_layer = last_layer;
    453          }
    454       }
    455    }
    456    pipe_surface_reference(&surface, NULL);
    457 }
    458 
    459 /**
    460  * \brief  Clear the whole render target using vgpu10 functionality
    461  *
    462  * \param svga[in]  The svga context
    463  * \param dst[in]  The surface to clear
    464  * \param color[in]  Clear color
    465  * \return PIPE_OK if all well, PIPE_ERROR_OUT_OF_MEMORY if ran out of
    466  * command submission resources.
    467  */
    468 static enum pipe_error
    469 svga_try_clear_render_target(struct svga_context *svga,
    470                              struct pipe_surface *dst,
    471                              const union pipe_color_union *color)
    472 {
    473    struct pipe_surface *rtv =
    474       svga_validate_surface_view(svga, svga_surface(dst));
    475 
    476    if (!rtv)
    477       return PIPE_ERROR_OUT_OF_MEMORY;
    478 
    479    return SVGA3D_vgpu10_ClearRenderTargetView(svga->swc, rtv, color->f);
    480  }
    481 
    482 /**
    483  * \brief  Clear part of render target using gallium blitter utilities
    484  *
    485  * \param svga[in]  The svga context
    486  * \param dst[in]  The surface to clear
    487  * \param color[in]  Clear color
    488  * \param dstx[in]  Clear region left
    489  * \param dsty[in]  Clear region top
    490  * \param width[in]  Clear region width
    491  * \param height[in]  Clear region height
    492  */
    493 static void
    494 svga_blitter_clear_render_target(struct svga_context *svga,
    495                                  struct pipe_surface *dst,
    496                                  const union pipe_color_union *color,
    497                                  unsigned dstx, unsigned dsty,
    498                                  unsigned width, unsigned height)
    499 {
    500    begin_blit(svga);
    501    util_blitter_save_framebuffer(svga->blitter, &svga->curr.framebuffer);
    502 
    503    util_blitter_clear_render_target(svga->blitter, dst, color,
    504                                     dstx, dsty, width, height);
    505 }
    506 
    507 /**
    508  * \brief Toggle conditional rendering if already enabled
    509  *
    510  * \param svga[in]  The svga context
    511  * \param render_condition_enabled[in]  Whether to ignore requests to turn
    512  * conditional rendering off
    513  * \param on[in]  Whether to turn conditional rendering on or off
    514  */
    515 static void
    516 svga_toggle_render_condition(struct svga_context *svga,
    517                              boolean render_condition_enabled,
    518                              boolean on)
    519 {
    520    SVGA3dQueryId query_id;
    521    enum pipe_error ret;
    522 
    523    if (render_condition_enabled ||
    524        svga->pred.query_id == SVGA3D_INVALID_ID) {
    525       return;
    526    }
    527 
    528    /*
    529     * If we get here, it means that the system supports
    530     * conditional rendering since svga->pred.query_id has already been
    531     * modified for this context and thus support has already been
    532     * verified.
    533     */
    534    query_id = on ? svga->pred.query_id : SVGA3D_INVALID_ID;
    535 
    536    ret = SVGA3D_vgpu10_SetPredication(svga->swc, query_id,
    537                                       (uint32) svga->pred.cond);
    538    if (ret == PIPE_ERROR_OUT_OF_MEMORY) {
    539       svga_context_flush(svga, NULL);
    540       ret = SVGA3D_vgpu10_SetPredication(svga->swc, query_id,
    541                                          (uint32) svga->pred.cond);
    542       assert(ret == PIPE_OK);
    543    }
    544 }
    545 
    546 /**
    547  * \brief Clear render target pipe callback
    548  *
    549  * \param pipe[in]  The pipe context
    550  * \param dst[in]  The surface to clear
    551  * \param color[in]  Clear color
    552  * \param dstx[in]  Clear region left
    553  * \param dsty[in]  Clear region top
    554  * \param width[in]  Clear region width
    555  * \param height[in]  Clear region height
    556  * \param render_condition_enabled[in]  Whether to use conditional rendering
    557  * to clear (if elsewhere enabled).
    558  */
    559 static void
    560 svga_clear_render_target(struct pipe_context *pipe,
    561                          struct pipe_surface *dst,
    562                          const union pipe_color_union *color,
    563                          unsigned dstx, unsigned dsty,
    564                          unsigned width, unsigned height,
    565                          bool render_condition_enabled)
    566 {
    567     struct svga_context *svga = svga_context( pipe );
    568 
    569     svga_toggle_render_condition(svga, render_condition_enabled, FALSE);
    570     if (!svga_have_vgpu10(svga) || dstx != 0 || dsty != 0 ||
    571         width != dst->width || height != dst->height) {
    572        svga_blitter_clear_render_target(svga, dst, color, dstx, dsty, width,
    573                                         height);
    574     } else {
    575        enum pipe_error ret;
    576 
    577        ret = svga_try_clear_render_target(svga, dst, color);
    578        if (ret == PIPE_ERROR_OUT_OF_MEMORY) {
    579           svga_context_flush( svga, NULL );
    580           ret = svga_try_clear_render_target(svga, dst, color);
    581        }
    582 
    583        assert (ret == PIPE_OK);
    584     }
    585     svga_toggle_render_condition(svga, render_condition_enabled, TRUE);
    586 }
    587 
    588 void svga_init_clear_functions(struct svga_context *svga)
    589 {
    590    svga->pipe.clear_render_target = svga_clear_render_target;
    591    svga->pipe.clear_texture = svga_clear_texture;
    592    svga->pipe.clear = svga_clear;
    593 }
    594