Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Copyright © 2012 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.  *    Jordan Justen <jordan.l.justen@intel.com>
  25.  *
  26.  */
  27.  
  28. #include "main/imports.h"
  29. #include "main/bufferobj.h"
  30. #include "main/varray.h"
  31.  
  32. #include "brw_context.h"
  33. #include "brw_defines.h"
  34. #include "brw_draw.h"
  35.  
  36. #include "intel_batchbuffer.h"
  37.  
  38. /**
  39.  * Check if the hardware's cut index support can handle the primitive
  40.  * restart index value (pre-Haswell only).
  41.  */
  42. static bool
  43. can_cut_index_handle_restart_index(struct gl_context *ctx,
  44.                                    const struct _mesa_index_buffer *ib)
  45. {
  46.    /* The FixedIndex variant means 0xFF, 0xFFFF, or 0xFFFFFFFF based on
  47.     * the index buffer type, which corresponds exactly to the hardware.
  48.     */
  49.    if (ctx->Array.PrimitiveRestartFixedIndex)
  50.       return true;
  51.  
  52.    bool cut_index_will_work;
  53.  
  54.    switch (ib->type) {
  55.    case GL_UNSIGNED_BYTE:
  56.       cut_index_will_work = ctx->Array.RestartIndex == 0xff;
  57.       break;
  58.    case GL_UNSIGNED_SHORT:
  59.       cut_index_will_work = ctx->Array.RestartIndex == 0xffff;
  60.       break;
  61.    case GL_UNSIGNED_INT:
  62.       cut_index_will_work = ctx->Array.RestartIndex == 0xffffffff;
  63.       break;
  64.    default:
  65.       unreachable("not reached");
  66.    }
  67.  
  68.    return cut_index_will_work;
  69. }
  70.  
  71. /**
  72.  * Check if the hardware's cut index support can handle the primitive
  73.  * restart case.
  74.  */
  75. static bool
  76. can_cut_index_handle_prims(struct gl_context *ctx,
  77.                            const struct _mesa_prim *prim,
  78.                            GLuint nr_prims,
  79.                            const struct _mesa_index_buffer *ib)
  80. {
  81.    struct brw_context *brw = brw_context(ctx);
  82.  
  83.    /* Otherwise Haswell can do it all. */
  84.    if (brw->gen >= 8 || brw->is_haswell)
  85.       return true;
  86.  
  87.    if (!can_cut_index_handle_restart_index(ctx, ib)) {
  88.       /* The primitive restart index can't be handled, so take
  89.        * the software path
  90.        */
  91.       return false;
  92.    }
  93.  
  94.    for (int i = 0; i < nr_prims; i++) {
  95.       switch (prim[i].mode) {
  96.       case GL_POINTS:
  97.       case GL_LINES:
  98.       case GL_LINE_STRIP:
  99.       case GL_TRIANGLES:
  100.       case GL_TRIANGLE_STRIP:
  101.       case GL_LINES_ADJACENCY:
  102.       case GL_LINE_STRIP_ADJACENCY:
  103.       case GL_TRIANGLES_ADJACENCY:
  104.       case GL_TRIANGLE_STRIP_ADJACENCY:
  105.          /* Cut index supports these primitive types */
  106.          break;
  107.       default:
  108.          /* Cut index does not support these primitive types */
  109.       //case GL_LINE_LOOP:
  110.       //case GL_TRIANGLE_FAN:
  111.       //case GL_QUADS:
  112.       //case GL_QUAD_STRIP:
  113.       //case GL_POLYGON:
  114.          return false;
  115.       }
  116.    }
  117.  
  118.    return true;
  119. }
  120.  
  121. /**
  122.  * Check if primitive restart is enabled, and if so, handle it properly.
  123.  *
  124.  * In some cases the support will be handled in software. When available
  125.  * hardware will handle primitive restart.
  126.  */
  127. GLboolean
  128. brw_handle_primitive_restart(struct gl_context *ctx,
  129.                              const struct _mesa_prim *prims,
  130.                              GLuint nr_prims,
  131.                              const struct _mesa_index_buffer *ib,
  132.                              struct gl_buffer_object *indirect)
  133. {
  134.    struct brw_context *brw = brw_context(ctx);
  135.  
  136.    /* We only need to handle cases where there is an index buffer. */
  137.    if (ib == NULL) {
  138.       return GL_FALSE;
  139.    }
  140.  
  141.    /* If we have set the in_progress flag, then we are in the middle
  142.     * of handling the primitive restart draw.
  143.     */
  144.    if (brw->prim_restart.in_progress) {
  145.       return GL_FALSE;
  146.    }
  147.  
  148.    /* If PrimitiveRestart is not enabled, then we aren't concerned about
  149.     * handling this draw.
  150.     */
  151.    if (!(ctx->Array._PrimitiveRestart)) {
  152.       return GL_FALSE;
  153.    }
  154.  
  155.    /* Signal that we are in the process of handling the
  156.     * primitive restart draw
  157.     */
  158.    brw->prim_restart.in_progress = true;
  159.  
  160.    if (can_cut_index_handle_prims(ctx, prims, nr_prims, ib)) {
  161.       /* Cut index should work for primitive restart, so use it
  162.        */
  163.       brw->prim_restart.enable_cut_index = true;
  164.       brw_draw_prims(ctx, prims, nr_prims, ib, GL_FALSE, -1, -1, NULL, indirect);
  165.       brw->prim_restart.enable_cut_index = false;
  166.    } else {
  167.       /* Not all the primitive draw modes are supported by the cut index,
  168.        * so take the software path
  169.        */
  170.       vbo_sw_primitive_restart(ctx, prims, nr_prims, ib, indirect);
  171.    }
  172.  
  173.    brw->prim_restart.in_progress = false;
  174.  
  175.    /* The primitive restart draw was completed, so return true. */
  176.    return GL_TRUE;
  177. }
  178.  
  179. static void
  180. haswell_upload_cut_index(struct brw_context *brw)
  181. {
  182.    struct gl_context *ctx = &brw->ctx;
  183.  
  184.    /* Don't trigger on Ivybridge */
  185.    if (brw->gen < 8 && !brw->is_haswell)
  186.       return;
  187.  
  188.    const unsigned cut_index_setting =
  189.       ctx->Array._PrimitiveRestart ? HSW_CUT_INDEX_ENABLE : 0;
  190.  
  191.    /* BRW_NEW_INDEX_BUFFER */
  192.    unsigned cut_index;
  193.    if (brw->ib.ib) {
  194.       cut_index = _mesa_primitive_restart_index(ctx, brw->ib.type);
  195.    } else {
  196.       /* There's no index buffer, but primitive restart may still apply
  197.        * to glDrawArrays and such.  FIXED_INDEX mode only applies to drawing
  198.        * operations that use an index buffer, so we can ignore it and use
  199.        * the GL restart index directly.
  200.        */
  201.       cut_index = ctx->Array.RestartIndex;
  202.    }
  203.  
  204.    BEGIN_BATCH(2);
  205.    OUT_BATCH(_3DSTATE_VF << 16 | cut_index_setting | (2 - 2));
  206.    OUT_BATCH(cut_index);
  207.    ADVANCE_BATCH();
  208. }
  209.  
  210. const struct brw_tracked_state haswell_cut_index = {
  211.    .dirty = {
  212.       .mesa  = _NEW_TRANSFORM,
  213.       .brw   = BRW_NEW_INDEX_BUFFER,
  214.    },
  215.    .emit = haswell_upload_cut_index,
  216. };
  217.