1f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**************************************************************************
2f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
3f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Copyright 2011 VMware, Inc.
4f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * All Rights Reserved.
5f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
6f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Permission is hereby granted, free of charge, to any person obtaining a
7f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * copy of this software and associated documentation files (the
8f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * "Software"), to deal in the Software without restriction, including
9f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * without limitation the rights to use, copy, modify, merge, publish,
10f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * distribute, sub license, and/or sell copies of the Software, and to
11f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * permit persons to whom the Software is furnished to do so, subject to
12f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * the following conditions:
13f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
14f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * The above copyright notice and this permission notice (including the
15f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * next paragraph) shall be included in all copies or substantial portions
16f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * of the Software.
17f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
18f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
22f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
26f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org **************************************************************************/
27f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
28f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
29f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "util/u_debug.h"
30f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "util/u_math.h"
31f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "util/u_format.h"
32f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "util/u_draw.h"
33f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
34f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
35f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
36f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Returns the largest legal index value plus one for the current set
37f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * of bound vertex buffers.  Regardless of any other consideration,
38f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * all vertex lookups need to be clamped to 0..max_index-1 to prevent
39f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * an out-of-bound access.
40f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
41f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Note that if zero is returned it means that one or more buffers is
42f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * too small to contain any valid vertex data.
43f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
44f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgunsigned
45f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgutil_draw_max_index(
46f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      const struct pipe_vertex_buffer *vertex_buffers,
47f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      const struct pipe_vertex_element *vertex_elements,
48f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      unsigned nr_vertex_elements,
49f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      const struct pipe_draw_info *info)
50f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
51f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   unsigned max_index;
52f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   unsigned i;
53f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
54f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   max_index = ~0U - 1;
55f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   for (i = 0; i < nr_vertex_elements; i++) {
56f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      const struct pipe_vertex_element *element =
57f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         &vertex_elements[i];
58f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      const struct pipe_vertex_buffer *buffer =
59f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         &vertex_buffers[element->vertex_buffer_index];
60f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      unsigned buffer_size;
61f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      const struct util_format_description *format_desc;
62f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      unsigned format_size;
63f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
64f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (!buffer->buffer) {
65f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         continue;
66f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
67f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
68f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      assert(buffer->buffer->height0 == 1);
69f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      assert(buffer->buffer->depth0 == 1);
70f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      buffer_size = buffer->buffer->width0;
71f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
72f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      format_desc = util_format_description(element->src_format);
73f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      assert(format_desc->block.width == 1);
74f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      assert(format_desc->block.height == 1);
75f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      assert(format_desc->block.bits % 8 == 0);
76f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      format_size = format_desc->block.bits/8;
77f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
78f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (buffer->buffer_offset >= buffer_size) {
79f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         /* buffer is too small */
80f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         return 0;
81f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
82f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
83f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      buffer_size -= buffer->buffer_offset;
84f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
85f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (element->src_offset >= buffer_size) {
86f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         /* buffer is too small */
87f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         return 0;
88f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
89f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
90f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      buffer_size -= element->src_offset;
91f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
92f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (format_size > buffer_size) {
93f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         /* buffer is too small */
94f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         return 0;
95f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
96f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
97f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      buffer_size -= format_size;
98f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
99f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (buffer->stride != 0) {
100f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         unsigned buffer_max_index;
101f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
102f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         buffer_max_index = buffer_size / buffer->stride;
103f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
104f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         if (element->instance_divisor == 0) {
105f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            /* Per-vertex data */
106f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            max_index = MIN2(max_index, buffer_max_index);
107f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         }
108f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         else {
109f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            /* Per-instance data. Simply make sure the state tracker didn't
110f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org             * request more instances than those that fit in the buffer */
111f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            assert((info->start_instance + info->instance_count)/element->instance_divisor
112f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                   <= (buffer_max_index + 1));
113f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         }
114f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
115f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
116f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
117f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return max_index + 1;
118f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
119