1/*
2 * Copyright 2010 Marek Olšák <maraeo@gmail.com>
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 * on the rights to use, copy, modify, merge, publish, distribute, sub
8 * license, and/or sell copies of the Software, and to permit persons to whom
9 * the 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 NON-INFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
19 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
20 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
21 * USE OR OTHER DEALINGS IN THE SOFTWARE. */
22
23#include "pipe/p_context.h"
24#include "util/u_index_modify.h"
25#include "util/u_inlines.h"
26
27/* Ubyte indices. */
28
29void util_shorten_ubyte_elts_to_userptr(struct pipe_context *context,
30					struct pipe_index_buffer *ib,
31					int index_bias,
32					unsigned start,
33					unsigned count,
34					void *out)
35{
36    struct pipe_transfer *src_transfer = NULL;
37    const unsigned char *in_map;
38    unsigned short *out_map = out;
39    unsigned i;
40
41    if (ib->user_buffer) {
42       in_map = ib->user_buffer;
43    } else {
44       in_map = pipe_buffer_map(context, ib->buffer,
45                                PIPE_TRANSFER_READ |
46                                PIPE_TRANSFER_UNSYNCHRONIZED,
47                                &src_transfer);
48    }
49    in_map += start;
50
51    for (i = 0; i < count; i++) {
52        *out_map = (unsigned short)(*in_map + index_bias);
53        in_map++;
54        out_map++;
55    }
56
57    if (src_transfer)
58       pipe_buffer_unmap(context, src_transfer);
59}
60
61void util_shorten_ubyte_elts(struct pipe_context *context,
62			     struct pipe_index_buffer *ib,
63			     struct pipe_resource **out_buf,
64			     int index_bias,
65			     unsigned start,
66			     unsigned count)
67{
68    struct pipe_resource* new_elts;
69    unsigned short *out_map;
70    struct pipe_transfer *dst_transfer;
71
72    new_elts = pipe_buffer_create(context->screen,
73                                  PIPE_BIND_INDEX_BUFFER,
74                                  PIPE_USAGE_STATIC,
75                                  2 * count);
76
77    out_map = pipe_buffer_map(context, new_elts, PIPE_TRANSFER_WRITE,
78                              &dst_transfer);
79    util_shorten_ubyte_elts_to_userptr(context, ib, index_bias,
80                                       start, count, out_map);
81    pipe_buffer_unmap(context, dst_transfer);
82
83    pipe_resource_reference(out_buf, NULL);
84    *out_buf = new_elts;
85}
86
87
88/* Ushort indices. */
89
90void util_rebuild_ushort_elts_to_userptr(struct pipe_context *context,
91					 struct pipe_index_buffer *ib,
92					 int index_bias,
93					 unsigned start, unsigned count,
94					 void *out)
95{
96    struct pipe_transfer *in_transfer = NULL;
97    const unsigned short *in_map;
98    unsigned short *out_map = out;
99    unsigned i;
100
101    if (ib->user_buffer) {
102       in_map = ib->user_buffer;
103    } else {
104       in_map = pipe_buffer_map(context, ib->buffer,
105                                PIPE_TRANSFER_READ |
106                                PIPE_TRANSFER_UNSYNCHRONIZED,
107                                &in_transfer);
108    }
109    in_map += start;
110
111    for (i = 0; i < count; i++) {
112        *out_map = (unsigned short)(*in_map + index_bias);
113        in_map++;
114        out_map++;
115    }
116
117    if (in_transfer)
118       pipe_buffer_unmap(context, in_transfer);
119}
120
121void util_rebuild_ushort_elts(struct pipe_context *context,
122			      struct pipe_index_buffer *ib,
123			      struct pipe_resource **out_buf,
124			      int index_bias,
125			      unsigned start, unsigned count)
126{
127    struct pipe_transfer *out_transfer = NULL;
128    struct pipe_resource *new_elts;
129    unsigned short *out_map;
130
131    new_elts = pipe_buffer_create(context->screen,
132                                  PIPE_BIND_INDEX_BUFFER,
133                                  PIPE_USAGE_STATIC,
134                                  2 * count);
135
136    out_map = pipe_buffer_map(context, new_elts,
137                              PIPE_TRANSFER_WRITE, &out_transfer);
138    util_rebuild_ushort_elts_to_userptr(context, ib, index_bias,
139                                        start, count, out_map);
140    pipe_buffer_unmap(context, out_transfer);
141
142    pipe_resource_reference(out_buf, NULL);
143    *out_buf = new_elts;
144}
145
146
147/* Uint indices. */
148
149void util_rebuild_uint_elts_to_userptr(struct pipe_context *context,
150				       struct pipe_index_buffer *ib,
151				       int index_bias,
152				       unsigned start, unsigned count,
153				       void *out)
154{
155    struct pipe_transfer *in_transfer = NULL;
156    const unsigned int *in_map;
157    unsigned int *out_map = out;
158    unsigned i;
159
160    if (ib->user_buffer) {
161       in_map = ib->user_buffer;
162    } else {
163       in_map = pipe_buffer_map(context, ib->buffer,
164                                PIPE_TRANSFER_READ |
165                                PIPE_TRANSFER_UNSYNCHRONIZED,
166                                &in_transfer);
167    }
168    in_map += start;
169
170    for (i = 0; i < count; i++) {
171        *out_map = (unsigned int)(*in_map + index_bias);
172        in_map++;
173        out_map++;
174    }
175
176    if (in_transfer)
177       pipe_buffer_unmap(context, in_transfer);
178}
179
180void util_rebuild_uint_elts(struct pipe_context *context,
181			    struct pipe_index_buffer *ib,
182			    struct pipe_resource **out_buf,
183			    int index_bias,
184			    unsigned start, unsigned count)
185{
186    struct pipe_transfer *out_transfer = NULL;
187    struct pipe_resource *new_elts;
188    unsigned int *out_map;
189
190    new_elts = pipe_buffer_create(context->screen,
191                                  PIPE_BIND_INDEX_BUFFER,
192                                  PIPE_USAGE_STATIC,
193                                  2 * count);
194
195    out_map = pipe_buffer_map(context, new_elts,
196                              PIPE_TRANSFER_WRITE, &out_transfer);
197    util_rebuild_uint_elts_to_userptr(context, ib, index_bias,
198                                      start, count, out_map);
199    pipe_buffer_unmap(context, out_transfer);
200
201    pipe_resource_reference(out_buf, NULL);
202    *out_buf = new_elts;
203}
204