Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Copyright © 2009 Intel Corporation
  3.  *
  4.  * Permission is hereby granted, free of charge, to any person obtaining a
  5.  * copy of this software and associated documentation files (the "Software"),
  6.  * to deal in the Software without restriction, including without limitation
  7.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  8.  * and/or sell copies of the Software, and to permit persons to whom the
  9.  * Software is furnished to do so, subject to the following conditions:
  10.  *
  11.  * The above copyright notice and this permission notice (including the next
  12.  * paragraph) shall be included in all copies or substantial portions of the
  13.  * Software.
  14.  *
  15.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16.  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  18.  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19.  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  20.  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  21.  * IN THE SOFTWARE.
  22.  *
  23.  * Authors:
  24.  *    Eric Anholt <eric@anholt.net>
  25.  *
  26.  */
  27.  
  28. #include "brw_context.h"
  29. #include "brw_state.h"
  30. #include "brw_defines.h"
  31. #include "brw_util.h"
  32. #include "intel_batchbuffer.h"
  33. #include "main/fbobject.h"
  34.  
  35. static void
  36. upload_clip_state(struct brw_context *brw)
  37. {
  38.    struct gl_context *ctx = &brw->ctx;
  39.    /* BRW_NEW_META_IN_PROGRESS */
  40.    uint32_t dw1 = brw->meta_in_progress ? 0 : GEN6_CLIP_STATISTICS_ENABLE;
  41.    uint32_t dw2 = 0;
  42.  
  43.    /* _NEW_BUFFERS */
  44.    struct gl_framebuffer *fb = ctx->DrawBuffer;
  45.  
  46.    /* BRW_NEW_FS_PROG_DATA */
  47.    if (brw->wm.prog_data->barycentric_interp_modes &
  48.        BRW_WM_NONPERSPECTIVE_BARYCENTRIC_BITS) {
  49.       dw2 |= GEN6_CLIP_NON_PERSPECTIVE_BARYCENTRIC_ENABLE;
  50.    }
  51.  
  52.    if (brw->gen >= 7)
  53.       dw1 |= GEN7_CLIP_EARLY_CULL;
  54.  
  55.    if (brw->gen == 7) {
  56.       /* _NEW_POLYGON */
  57.       if (ctx->Polygon._FrontBit == _mesa_is_user_fbo(fb))
  58.          dw1 |= GEN7_CLIP_WINDING_CCW;
  59.  
  60.       if (ctx->Polygon.CullFlag) {
  61.          switch (ctx->Polygon.CullFaceMode) {
  62.          case GL_FRONT:
  63.             dw1 |= GEN7_CLIP_CULLMODE_FRONT;
  64.             break;
  65.          case GL_BACK:
  66.             dw1 |= GEN7_CLIP_CULLMODE_BACK;
  67.             break;
  68.          case GL_FRONT_AND_BACK:
  69.             dw1 |= GEN7_CLIP_CULLMODE_BOTH;
  70.             break;
  71.          default:
  72.             unreachable("Should not get here: invalid CullFlag");
  73.          }
  74.       } else {
  75.          dw1 |= GEN7_CLIP_CULLMODE_NONE;
  76.       }
  77.    }
  78.  
  79.    if (brw->gen < 8 && !ctx->Transform.DepthClamp)
  80.       dw2 |= GEN6_CLIP_Z_TEST;
  81.  
  82.    /* _NEW_LIGHT */
  83.    if (ctx->Light.ProvokingVertex == GL_FIRST_VERTEX_CONVENTION) {
  84.       dw2 |=
  85.          (0 << GEN6_CLIP_TRI_PROVOKE_SHIFT) |
  86.          (1 << GEN6_CLIP_TRIFAN_PROVOKE_SHIFT) |
  87.          (0 << GEN6_CLIP_LINE_PROVOKE_SHIFT);
  88.    } else {
  89.       dw2 |=
  90.          (2 << GEN6_CLIP_TRI_PROVOKE_SHIFT) |
  91.          (2 << GEN6_CLIP_TRIFAN_PROVOKE_SHIFT) |
  92.          (1 << GEN6_CLIP_LINE_PROVOKE_SHIFT);
  93.    }
  94.  
  95.    /* _NEW_TRANSFORM */
  96.    dw2 |= (ctx->Transform.ClipPlanesEnabled <<
  97.            GEN6_USER_CLIP_CLIP_DISTANCES_SHIFT);
  98.    if (ctx->Transform.ClipDepthMode == GL_ZERO_TO_ONE)
  99.       dw2 |= GEN6_CLIP_API_D3D;
  100.    else
  101.       dw2 |= GEN6_CLIP_API_OGL;
  102.  
  103.    dw2 |= GEN6_CLIP_GB_TEST;
  104.  
  105.    /* We need to disable guardband clipping if the guardband (which we always
  106.     * program to the maximum screen-space bounding box of 8K x 8K) will be
  107.     * smaller than the viewport.
  108.     *
  109.     * Closely examining the clip determination formulas in the documentation
  110.     * reveals that objects will be discarded entirely if they're outside the
  111.     * (small) guardband, even if they're within the (large) viewport:
  112.     *
  113.     *     TR = TR_GB || TR_VPXY || TR_VPZ || TR_UC || TR_NEGW
  114.     *     TA   = !TR && TA_GB && TA_VPZ && TA_NEGW
  115.     *     MC = !(TA || TR)
  116.     *
  117.     * (TA is "Trivial Accept", TR is "Trivial Reject", MC is "Must Clip".)
  118.     *
  119.     * Disabling guardband clipping removes the TR_GB condition, which means
  120.     * they'll be considered MC ("Must Clip") unless they're rejected for
  121.     * some other reason.
  122.     *
  123.     * Note that there is no TA_VPXY condition.  If there were, objects entirely
  124.     * inside a 16384x16384 viewport would be trivially accepted, breaking the
  125.     * "objects must have a screenspace bounding box not exceeding 8K in the X
  126.     * or Y direction" restriction.  Instead, they're clipped.
  127.     */
  128.    for (unsigned i = 0; i < ctx->Const.MaxViewports; i++) {
  129.       if (ctx->ViewportArray[i].Width > 8192 ||
  130.           ctx->ViewportArray[i].Height > 8192) {
  131.          dw2 &= ~GEN6_CLIP_GB_TEST;
  132.          break;
  133.       }
  134.    }
  135.  
  136.    /* If the viewport dimensions are smaller than the drawable dimensions,
  137.     * we have to disable guardband clipping prior to Gen8.  We always program
  138.     * the guardband to a fixed size, which is almost always larger than the
  139.     * viewport.  Any geometry which intersects the viewport but lies within
  140.     * the guardband would bypass the 3D clipping stage, so it wouldn't be
  141.     * clipped to the viewport.  Rendering would happen beyond the viewport,
  142.     * but still inside the drawable.
  143.     *
  144.     * Gen8+ introduces a viewport extents test which restricts rendering to
  145.     * the viewport, so we can ignore this restriction.
  146.     */
  147.    if (brw->gen < 8) {
  148.       for (unsigned i = 0; i < ctx->Const.MaxViewports; i++) {
  149.          if (ctx->ViewportArray[i].X != 0 ||
  150.              ctx->ViewportArray[i].Y != 0 ||
  151.              ctx->ViewportArray[i].Width != (float) fb->Width ||
  152.              ctx->ViewportArray[i].Height != (float) fb->Height) {
  153.             dw2 &= ~GEN6_CLIP_GB_TEST;
  154.             break;
  155.          }
  156.       }
  157.    }
  158.  
  159.    /* BRW_NEW_RASTERIZER_DISCARD */
  160.    if (ctx->RasterDiscard) {
  161.       dw2 |= GEN6_CLIP_MODE_REJECT_ALL;
  162.       perf_debug("Rasterizer discard is currently implemented via the clipper; "
  163.                  "%s be faster.\n", brw->gen >= 7 ? "using the SOL unit may" :
  164.                  "having the GS not write primitives would likely");
  165.    }
  166.  
  167.    uint32_t enable;
  168.    if (brw->primitive == _3DPRIM_RECTLIST)
  169.       enable = 0;
  170.    else
  171.       enable = GEN6_CLIP_ENABLE;
  172.  
  173.    BEGIN_BATCH(4);
  174.    OUT_BATCH(_3DSTATE_CLIP << 16 | (4 - 2));
  175.    OUT_BATCH(dw1);
  176.    OUT_BATCH(enable |
  177.              GEN6_CLIP_MODE_NORMAL |
  178.              GEN6_CLIP_XY_TEST |
  179.              dw2);
  180.    OUT_BATCH(U_FIXED(0.125, 3) << GEN6_CLIP_MIN_POINT_WIDTH_SHIFT |
  181.              U_FIXED(255.875, 3) << GEN6_CLIP_MAX_POINT_WIDTH_SHIFT |
  182.              (fb->MaxNumLayers > 0 ? 0 : GEN6_CLIP_FORCE_ZERO_RTAINDEX) |
  183.              ((ctx->Const.MaxViewports - 1) & GEN6_CLIP_MAX_VP_INDEX_MASK));
  184.    ADVANCE_BATCH();
  185. }
  186.  
  187. const struct brw_tracked_state gen6_clip_state = {
  188.    .dirty = {
  189.       .mesa  = _NEW_BUFFERS |
  190.                _NEW_LIGHT |
  191.                _NEW_TRANSFORM,
  192.       .brw   = BRW_NEW_CONTEXT |
  193.                BRW_NEW_FS_PROG_DATA |
  194.                BRW_NEW_META_IN_PROGRESS |
  195.                BRW_NEW_RASTERIZER_DISCARD,
  196.    },
  197.    .emit = upload_clip_state,
  198. };
  199.  
  200. const struct brw_tracked_state gen7_clip_state = {
  201.    .dirty = {
  202.       .mesa  = _NEW_BUFFERS |
  203.                _NEW_LIGHT |
  204.                _NEW_POLYGON |
  205.                _NEW_TRANSFORM,
  206.       .brw   = BRW_NEW_CONTEXT |
  207.                BRW_NEW_FS_PROG_DATA |
  208.                BRW_NEW_META_IN_PROGRESS |
  209.                BRW_NEW_RASTERIZER_DISCARD,
  210.    },
  211.    .emit = upload_clip_state,
  212. };
  213.