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 
util_shorten_ubyte_elts_to_userptr(struct pipe_context * context,struct pipe_index_buffer * ib,int index_bias,unsigned start,unsigned count,void * out)29 void 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 
util_shorten_ubyte_elts(struct pipe_context * context,struct pipe_index_buffer * ib,struct pipe_resource ** out_buf,int index_bias,unsigned start,unsigned count)61 void 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 
util_rebuild_ushort_elts_to_userptr(struct pipe_context * context,struct pipe_index_buffer * ib,int index_bias,unsigned start,unsigned count,void * out)90 void 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 
util_rebuild_ushort_elts(struct pipe_context * context,struct pipe_index_buffer * ib,struct pipe_resource ** out_buf,int index_bias,unsigned start,unsigned count)121 void 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 
util_rebuild_uint_elts_to_userptr(struct pipe_context * context,struct pipe_index_buffer * ib,int index_bias,unsigned start,unsigned count,void * out)149 void 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 
util_rebuild_uint_elts(struct pipe_context * context,struct pipe_index_buffer * ib,struct pipe_resource ** out_buf,int index_bias,unsigned start,unsigned count)180 void 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