Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
5564 | serge | 1 | /* |
2 | * Copyright (C) 2013 Rob Clark |
||
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 FROM, |
||
20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
||
21 | * SOFTWARE. |
||
22 | * |
||
23 | * Authors: |
||
24 | * Rob Clark |
||
25 | */ |
||
26 | |||
27 | /** |
||
28 | * This module converts provides a more convenient front-end to u_indices, |
||
29 | * etc, utils to convert primitive types supported not supported by the |
||
30 | * hardware. It handles binding new index buffer state, and restoring |
||
31 | * previous state after. To use, put something like this at the front of |
||
32 | * drivers pipe->draw_vbo(): |
||
33 | * |
||
34 | * // emulate unsupported primitives: |
||
35 | * if (info->mode needs emulating) { |
||
36 | * util_primconvert_save_index_buffer(ctx->primconvert, &ctx->indexbuf); |
||
37 | * util_primconvert_save_rasterizer_state(ctx->primconvert, ctx->rasterizer); |
||
38 | * util_primconvert_draw_vbo(ctx->primconvert, info); |
||
39 | * return; |
||
40 | * } |
||
41 | * |
||
42 | */ |
||
43 | |||
44 | #include "pipe/p_state.h" |
||
45 | #include "util/u_draw.h" |
||
46 | #include "util/u_inlines.h" |
||
47 | #include "util/u_memory.h" |
||
48 | #include "util/u_upload_mgr.h" |
||
49 | |||
50 | #include "indices/u_indices.h" |
||
51 | #include "indices/u_primconvert.h" |
||
52 | |||
53 | struct primconvert_context |
||
54 | { |
||
55 | struct pipe_context *pipe; |
||
56 | struct pipe_index_buffer saved_ib; |
||
57 | uint32_t primtypes_mask; |
||
58 | unsigned api_pv; |
||
59 | struct u_upload_mgr *upload; |
||
60 | }; |
||
61 | |||
62 | |||
63 | struct primconvert_context * |
||
64 | util_primconvert_create(struct pipe_context *pipe, uint32_t primtypes_mask) |
||
65 | { |
||
66 | struct primconvert_context *pc = CALLOC_STRUCT(primconvert_context); |
||
67 | if (!pc) |
||
68 | return NULL; |
||
69 | pc->pipe = pipe; |
||
70 | pc->primtypes_mask = primtypes_mask; |
||
71 | return pc; |
||
72 | } |
||
73 | |||
74 | void |
||
75 | util_primconvert_destroy(struct primconvert_context *pc) |
||
76 | { |
||
77 | if (pc->upload) |
||
78 | u_upload_destroy(pc->upload); |
||
79 | util_primconvert_save_index_buffer(pc, NULL); |
||
80 | FREE(pc); |
||
81 | } |
||
82 | |||
83 | void |
||
84 | util_primconvert_save_index_buffer(struct primconvert_context *pc, |
||
85 | const struct pipe_index_buffer *ib) |
||
86 | { |
||
87 | if (ib) { |
||
88 | pipe_resource_reference(&pc->saved_ib.buffer, ib->buffer); |
||
89 | pc->saved_ib.index_size = ib->index_size; |
||
90 | pc->saved_ib.offset = ib->offset; |
||
91 | pc->saved_ib.user_buffer = ib->user_buffer; |
||
92 | } |
||
93 | else { |
||
94 | pipe_resource_reference(&pc->saved_ib.buffer, NULL); |
||
95 | } |
||
96 | } |
||
97 | |||
98 | void |
||
99 | util_primconvert_save_rasterizer_state(struct primconvert_context *pc, |
||
100 | const struct pipe_rasterizer_state |
||
101 | *rast) |
||
102 | { |
||
103 | /* if we actually translated the provoking vertex for the buffer, |
||
104 | * we would actually need to save/restore rasterizer state. As |
||
105 | * it is, we just need to make note of the pv. |
||
106 | */ |
||
107 | pc->api_pv = rast->flatshade_first ? PV_FIRST : PV_LAST; |
||
108 | } |
||
109 | |||
110 | void |
||
111 | util_primconvert_draw_vbo(struct primconvert_context *pc, |
||
112 | const struct pipe_draw_info *info) |
||
113 | { |
||
114 | struct pipe_index_buffer *ib = &pc->saved_ib; |
||
115 | struct pipe_index_buffer new_ib; |
||
116 | struct pipe_draw_info new_info; |
||
117 | struct pipe_transfer *src_transfer = NULL; |
||
118 | u_translate_func trans_func; |
||
119 | u_generate_func gen_func; |
||
120 | const void *src = NULL; |
||
121 | void *dst; |
||
122 | |||
123 | memset(&new_ib, 0, sizeof(new_ib)); |
||
124 | util_draw_init_info(&new_info); |
||
125 | new_info.indexed = true; |
||
126 | new_info.min_index = info->min_index; |
||
127 | new_info.max_index = info->max_index; |
||
128 | new_info.index_bias = info->index_bias; |
||
129 | new_info.start_instance = info->start_instance; |
||
130 | new_info.instance_count = info->instance_count; |
||
131 | new_info.primitive_restart = info->primitive_restart; |
||
132 | new_info.restart_index = info->restart_index; |
||
133 | if (info->indexed) { |
||
134 | u_index_translator(pc->primtypes_mask, |
||
135 | info->mode, pc->saved_ib.index_size, info->count, |
||
136 | pc->api_pv, pc->api_pv, |
||
137 | info->primitive_restart ? PR_ENABLE : PR_DISABLE, |
||
138 | &new_info.mode, &new_ib.index_size, &new_info.count, |
||
139 | &trans_func); |
||
140 | src = ib->user_buffer; |
||
141 | if (!src) { |
||
142 | src = pipe_buffer_map(pc->pipe, ib->buffer, |
||
143 | PIPE_TRANSFER_READ, &src_transfer); |
||
144 | } |
||
145 | src = (const uint8_t *)src + ib->offset; |
||
146 | } |
||
147 | else { |
||
148 | u_index_generator(pc->primtypes_mask, |
||
149 | info->mode, info->start, info->count, |
||
150 | pc->api_pv, pc->api_pv, |
||
151 | &new_info.mode, &new_ib.index_size, &new_info.count, |
||
152 | &gen_func); |
||
153 | } |
||
154 | |||
155 | if (!pc->upload) { |
||
156 | pc->upload = u_upload_create(pc->pipe, 4096, 4, PIPE_BIND_INDEX_BUFFER); |
||
157 | } |
||
158 | |||
159 | u_upload_alloc(pc->upload, 0, new_ib.index_size * new_info.count, |
||
160 | &new_ib.offset, &new_ib.buffer, &dst); |
||
161 | |||
162 | if (info->indexed) { |
||
163 | trans_func(src, info->start, info->count, new_info.count, info->restart_index, dst); |
||
164 | } |
||
165 | else { |
||
166 | gen_func(info->start, new_info.count, dst); |
||
167 | } |
||
168 | |||
169 | if (src_transfer) |
||
170 | pipe_buffer_unmap(pc->pipe, src_transfer); |
||
171 | |||
172 | u_upload_unmap(pc->upload); |
||
173 | |||
174 | /* bind new index buffer: */ |
||
175 | pc->pipe->set_index_buffer(pc->pipe, &new_ib); |
||
176 | |||
177 | /* to the translated draw: */ |
||
178 | pc->pipe->draw_vbo(pc->pipe, &new_info); |
||
179 | |||
180 | /* and then restore saved ib: */ |
||
181 | pc->pipe->set_index_buffer(pc->pipe, ib); |
||
182 | |||
183 | pipe_resource_reference(&new_ib.buffer, NULL); |
||
184 | } |