1df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen/*
2df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen * Copyright © 2012 Intel Corporation
3df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen *
4df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen * Permission is hereby granted, free of charge, to any person obtaining a
5df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen * copy of this software and associated documentation files (the "Software"),
6df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen * to deal in the Software without restriction, including without limitation
7df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen * and/or sell copies of the Software, and to permit persons to whom the
9df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen * Software is furnished to do so, subject to the following conditions:
10df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen *
11df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen * The above copyright notice and this permission notice (including the next
12df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen * paragraph) shall be included in all copies or substantial portions of the
13df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen * Software.
14df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen *
15df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen * IN THE SOFTWARE.
22df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen *
23df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen * Authors:
24df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen *    Jordan Justen <jordan.l.justen@intel.com>
25df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen *
26df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen */
27df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen
28df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen#include "main/imports.h"
29df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen#include "main/bufferobj.h"
30df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen
31df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen#include "brw_context.h"
32b922999a404322a1034c4f96c21acae860483bb0Kenneth Graunke#include "brw_defines.h"
33df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen#include "brw_draw.h"
34df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen
35b922999a404322a1034c4f96c21acae860483bb0Kenneth Graunke#include "intel_batchbuffer.h"
36b922999a404322a1034c4f96c21acae860483bb0Kenneth Graunke
37df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen/**
38dc501452534e6e004acf3206a581232971c00cd0Jordan Justen * Check if the hardware's cut index support can handle the primitive
39dc501452534e6e004acf3206a581232971c00cd0Jordan Justen * restart index value.
40dc501452534e6e004acf3206a581232971c00cd0Jordan Justen */
41dc501452534e6e004acf3206a581232971c00cd0Jordan Justenstatic bool
42dc501452534e6e004acf3206a581232971c00cd0Jordan Justencan_cut_index_handle_restart_index(struct gl_context *ctx,
43dc501452534e6e004acf3206a581232971c00cd0Jordan Justen                                   const struct _mesa_index_buffer *ib)
44dc501452534e6e004acf3206a581232971c00cd0Jordan Justen{
45b922999a404322a1034c4f96c21acae860483bb0Kenneth Graunke   struct intel_context *intel = intel_context(ctx);
46b922999a404322a1034c4f96c21acae860483bb0Kenneth Graunke
47b922999a404322a1034c4f96c21acae860483bb0Kenneth Graunke   /* Haswell supports an arbitrary cut index. */
48b922999a404322a1034c4f96c21acae860483bb0Kenneth Graunke   if (intel->is_haswell)
49b922999a404322a1034c4f96c21acae860483bb0Kenneth Graunke      return true;
50b922999a404322a1034c4f96c21acae860483bb0Kenneth Graunke
51dc501452534e6e004acf3206a581232971c00cd0Jordan Justen   bool cut_index_will_work;
52dc501452534e6e004acf3206a581232971c00cd0Jordan Justen
53dc501452534e6e004acf3206a581232971c00cd0Jordan Justen   switch (ib->type) {
54dc501452534e6e004acf3206a581232971c00cd0Jordan Justen   case GL_UNSIGNED_BYTE:
55dc501452534e6e004acf3206a581232971c00cd0Jordan Justen      cut_index_will_work = (ctx->Array.RestartIndex & 0xff) == 0xff;
56dc501452534e6e004acf3206a581232971c00cd0Jordan Justen      break;
57dc501452534e6e004acf3206a581232971c00cd0Jordan Justen   case GL_UNSIGNED_SHORT:
58dc501452534e6e004acf3206a581232971c00cd0Jordan Justen      cut_index_will_work = (ctx->Array.RestartIndex & 0xffff) == 0xffff;
59dc501452534e6e004acf3206a581232971c00cd0Jordan Justen      break;
60dc501452534e6e004acf3206a581232971c00cd0Jordan Justen   case GL_UNSIGNED_INT:
61dc501452534e6e004acf3206a581232971c00cd0Jordan Justen      cut_index_will_work = ctx->Array.RestartIndex == 0xffffffff;
62dc501452534e6e004acf3206a581232971c00cd0Jordan Justen      break;
63dc501452534e6e004acf3206a581232971c00cd0Jordan Justen   default:
64dc501452534e6e004acf3206a581232971c00cd0Jordan Justen      cut_index_will_work = false;
65dc501452534e6e004acf3206a581232971c00cd0Jordan Justen      assert(0);
66dc501452534e6e004acf3206a581232971c00cd0Jordan Justen   }
67dc501452534e6e004acf3206a581232971c00cd0Jordan Justen
68dc501452534e6e004acf3206a581232971c00cd0Jordan Justen   return cut_index_will_work;
69dc501452534e6e004acf3206a581232971c00cd0Jordan Justen}
70dc501452534e6e004acf3206a581232971c00cd0Jordan Justen
71dc501452534e6e004acf3206a581232971c00cd0Jordan Justen/**
72dc501452534e6e004acf3206a581232971c00cd0Jordan Justen * Check if the hardware's cut index support can handle the primitive
73dc501452534e6e004acf3206a581232971c00cd0Jordan Justen * restart case.
74dc501452534e6e004acf3206a581232971c00cd0Jordan Justen */
75dc501452534e6e004acf3206a581232971c00cd0Jordan Justenstatic bool
76dc501452534e6e004acf3206a581232971c00cd0Jordan Justencan_cut_index_handle_prims(struct gl_context *ctx,
77dc501452534e6e004acf3206a581232971c00cd0Jordan Justen                           const struct _mesa_prim *prim,
78dc501452534e6e004acf3206a581232971c00cd0Jordan Justen                           GLuint nr_prims,
79dc501452534e6e004acf3206a581232971c00cd0Jordan Justen                           const struct _mesa_index_buffer *ib)
80dc501452534e6e004acf3206a581232971c00cd0Jordan Justen{
818aa78c104a6fa9497cba558b54c41f6f2292bd74Jordan Justen   struct brw_context *brw = brw_context(ctx);
828aa78c104a6fa9497cba558b54c41f6f2292bd74Jordan Justen
838aa78c104a6fa9497cba558b54c41f6f2292bd74Jordan Justen   if (brw->sol.counting_primitives_generated ||
848aa78c104a6fa9497cba558b54c41f6f2292bd74Jordan Justen       brw->sol.counting_primitives_written) {
858aa78c104a6fa9497cba558b54c41f6f2292bd74Jordan Justen      /* Counting primitives generated in hardware is not currently
868aa78c104a6fa9497cba558b54c41f6f2292bd74Jordan Justen       * supported, so take the software path. We need to investigate
878aa78c104a6fa9497cba558b54c41f6f2292bd74Jordan Justen       * the *_PRIMITIVES_COUNT registers to allow this to be handled
888aa78c104a6fa9497cba558b54c41f6f2292bd74Jordan Justen       * entirely in hardware.
898aa78c104a6fa9497cba558b54c41f6f2292bd74Jordan Justen       */
908aa78c104a6fa9497cba558b54c41f6f2292bd74Jordan Justen      return false;
918aa78c104a6fa9497cba558b54c41f6f2292bd74Jordan Justen   }
928aa78c104a6fa9497cba558b54c41f6f2292bd74Jordan Justen
93dc501452534e6e004acf3206a581232971c00cd0Jordan Justen   if (!can_cut_index_handle_restart_index(ctx, ib)) {
94dc501452534e6e004acf3206a581232971c00cd0Jordan Justen      /* The primitive restart index can't be handled, so take
95dc501452534e6e004acf3206a581232971c00cd0Jordan Justen       * the software path
96dc501452534e6e004acf3206a581232971c00cd0Jordan Justen       */
97dc501452534e6e004acf3206a581232971c00cd0Jordan Justen      return false;
98dc501452534e6e004acf3206a581232971c00cd0Jordan Justen   }
99dc501452534e6e004acf3206a581232971c00cd0Jordan Justen
100dc501452534e6e004acf3206a581232971c00cd0Jordan Justen   for ( ; nr_prims > 0; nr_prims--) {
101dc501452534e6e004acf3206a581232971c00cd0Jordan Justen      switch(prim->mode) {
102dc501452534e6e004acf3206a581232971c00cd0Jordan Justen      case GL_POINTS:
103dc501452534e6e004acf3206a581232971c00cd0Jordan Justen      case GL_LINES:
104dc501452534e6e004acf3206a581232971c00cd0Jordan Justen      case GL_LINE_STRIP:
105dc501452534e6e004acf3206a581232971c00cd0Jordan Justen      case GL_TRIANGLES:
106dc501452534e6e004acf3206a581232971c00cd0Jordan Justen      case GL_TRIANGLE_STRIP:
107dc501452534e6e004acf3206a581232971c00cd0Jordan Justen         /* Cut index supports these primitive types */
108dc501452534e6e004acf3206a581232971c00cd0Jordan Justen         break;
109dc501452534e6e004acf3206a581232971c00cd0Jordan Justen      default:
110dc501452534e6e004acf3206a581232971c00cd0Jordan Justen         /* Cut index does not support these primitive types */
111dc501452534e6e004acf3206a581232971c00cd0Jordan Justen      //case GL_LINE_LOOP:
112dc501452534e6e004acf3206a581232971c00cd0Jordan Justen      //case GL_TRIANGLE_FAN:
113dc501452534e6e004acf3206a581232971c00cd0Jordan Justen      //case GL_QUADS:
114dc501452534e6e004acf3206a581232971c00cd0Jordan Justen      //case GL_QUAD_STRIP:
115dc501452534e6e004acf3206a581232971c00cd0Jordan Justen      //case GL_POLYGON:
116dc501452534e6e004acf3206a581232971c00cd0Jordan Justen         return false;
117dc501452534e6e004acf3206a581232971c00cd0Jordan Justen      }
118dc501452534e6e004acf3206a581232971c00cd0Jordan Justen   }
119dc501452534e6e004acf3206a581232971c00cd0Jordan Justen
120dc501452534e6e004acf3206a581232971c00cd0Jordan Justen   return true;
121dc501452534e6e004acf3206a581232971c00cd0Jordan Justen}
122dc501452534e6e004acf3206a581232971c00cd0Jordan Justen
123dc501452534e6e004acf3206a581232971c00cd0Jordan Justen/**
124df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen * Check if primitive restart is enabled, and if so, handle it properly.
125df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen *
126df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen * In some cases the support will be handled in software. When available
127df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen * hardware will handle primitive restart.
128df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen */
129df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan JustenGLboolean
130df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justenbrw_handle_primitive_restart(struct gl_context *ctx,
131df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen                             const struct _mesa_prim *prim,
132df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen                             GLuint nr_prims,
133df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen                             const struct _mesa_index_buffer *ib)
134df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen{
135df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen   struct brw_context *brw = brw_context(ctx);
136df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen
137df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen   /* We only need to handle cases where there is an index buffer. */
138df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen   if (ib == NULL) {
139df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen      return GL_FALSE;
140df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen   }
141df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen
142df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen   /* If the driver has requested software handling of primitive restarts,
143df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen    * then the VBO module has already taken care of things, and we can
144df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen    * just draw as normal.
145df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen    */
146df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen   if (ctx->Const.PrimitiveRestartInSoftware) {
147df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen      return GL_FALSE;
148df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen   }
149df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen
150df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen   /* If we have set the in_progress flag, then we are in the middle
151df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen    * of handling the primitive restart draw.
152df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen    */
153df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen   if (brw->prim_restart.in_progress) {
154df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen      return GL_FALSE;
155df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen   }
156df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen
157df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen   /* If PrimitiveRestart is not enabled, then we aren't concerned about
158df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen    * handling this draw.
159df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen    */
160df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen   if (!(ctx->Array.PrimitiveRestart)) {
161df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen      return GL_FALSE;
162df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen   }
163df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen
164df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen   /* Signal that we are in the process of handling the
165df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen    * primitive restart draw
166df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen    */
167df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen   brw->prim_restart.in_progress = true;
168df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen
169dc501452534e6e004acf3206a581232971c00cd0Jordan Justen   if (can_cut_index_handle_prims(ctx, prim, nr_prims, ib)) {
170dc501452534e6e004acf3206a581232971c00cd0Jordan Justen      /* Cut index should work for primitive restart, so use it
171dc501452534e6e004acf3206a581232971c00cd0Jordan Justen       */
172dc501452534e6e004acf3206a581232971c00cd0Jordan Justen      brw->prim_restart.enable_cut_index = true;
173dc501452534e6e004acf3206a581232971c00cd0Jordan Justen      brw_draw_prims(ctx, prim, nr_prims, ib, GL_FALSE, -1, -1, NULL);
174dc501452534e6e004acf3206a581232971c00cd0Jordan Justen      brw->prim_restart.enable_cut_index = false;
175dc501452534e6e004acf3206a581232971c00cd0Jordan Justen   } else {
176dc501452534e6e004acf3206a581232971c00cd0Jordan Justen      /* Not all the primitive draw modes are supported by the cut index,
177dc501452534e6e004acf3206a581232971c00cd0Jordan Justen       * so take the software path
178dc501452534e6e004acf3206a581232971c00cd0Jordan Justen       */
179dc501452534e6e004acf3206a581232971c00cd0Jordan Justen      vbo_sw_primitive_restart(ctx, prim, nr_prims, ib);
180dc501452534e6e004acf3206a581232971c00cd0Jordan Justen   }
181df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen
182df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen   brw->prim_restart.in_progress = false;
183df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen
184df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen   /* The primitive restart draw was completed, so return true. */
185df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen   return GL_TRUE;
186df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen}
187df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen
188b922999a404322a1034c4f96c21acae860483bb0Kenneth Graunkestatic void
189b922999a404322a1034c4f96c21acae860483bb0Kenneth Graunkehaswell_upload_cut_index(struct brw_context *brw)
190b922999a404322a1034c4f96c21acae860483bb0Kenneth Graunke{
191b922999a404322a1034c4f96c21acae860483bb0Kenneth Graunke   struct intel_context *intel = &brw->intel;
192b922999a404322a1034c4f96c21acae860483bb0Kenneth Graunke   struct gl_context *ctx = &intel->ctx;
193b922999a404322a1034c4f96c21acae860483bb0Kenneth Graunke
194b922999a404322a1034c4f96c21acae860483bb0Kenneth Graunke   /* Don't trigger on Ivybridge */
195b922999a404322a1034c4f96c21acae860483bb0Kenneth Graunke   if (!intel->is_haswell)
196b922999a404322a1034c4f96c21acae860483bb0Kenneth Graunke      return;
197b922999a404322a1034c4f96c21acae860483bb0Kenneth Graunke
198b922999a404322a1034c4f96c21acae860483bb0Kenneth Graunke   const unsigned cut_index_setting =
199b922999a404322a1034c4f96c21acae860483bb0Kenneth Graunke      ctx->Array.PrimitiveRestart ? HSW_CUT_INDEX_ENABLE : 0;
200b922999a404322a1034c4f96c21acae860483bb0Kenneth Graunke
201b922999a404322a1034c4f96c21acae860483bb0Kenneth Graunke   BEGIN_BATCH(2);
202b922999a404322a1034c4f96c21acae860483bb0Kenneth Graunke   OUT_BATCH(_3DSTATE_VF << 16 | cut_index_setting | (2 - 2));
203b922999a404322a1034c4f96c21acae860483bb0Kenneth Graunke   OUT_BATCH(ctx->Array.RestartIndex);
204b922999a404322a1034c4f96c21acae860483bb0Kenneth Graunke   ADVANCE_BATCH();
205b922999a404322a1034c4f96c21acae860483bb0Kenneth Graunke}
206b922999a404322a1034c4f96c21acae860483bb0Kenneth Graunke
207b922999a404322a1034c4f96c21acae860483bb0Kenneth Graunkeconst struct brw_tracked_state haswell_cut_index = {
208b922999a404322a1034c4f96c21acae860483bb0Kenneth Graunke   .dirty = {
209b922999a404322a1034c4f96c21acae860483bb0Kenneth Graunke      .mesa  = _NEW_TRANSFORM,
210b922999a404322a1034c4f96c21acae860483bb0Kenneth Graunke      .brw   = 0,
211b922999a404322a1034c4f96c21acae860483bb0Kenneth Graunke      .cache = 0,
212b922999a404322a1034c4f96c21acae860483bb0Kenneth Graunke   },
213b922999a404322a1034c4f96c21acae860483bb0Kenneth Graunke   .emit = haswell_upload_cut_index,
214b922999a404322a1034c4f96c21acae860483bb0Kenneth Graunke};
215