1 /**************************************************************************
2 *
3 * Copyright 2007 VMware, Inc.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27
28 #ifndef U_INLINES_H
29 #define U_INLINES_H
30
31 #include "pipe/p_defines.h"
32 #include "pipe/p_shader_tokens.h"
33 #include "pipe/p_state.h"
34 #include "util/u_debug.h"
35 #include "util/u_debug_describe.h"
36 #include "util/u_debug_refcnt.h"
37 #include "util/u_atomic.h"
38 #include "util/u_math.h"
39
40
41 #ifdef __cplusplus
42 extern "C" {
43 #endif
44
45
46 /*
47 * Reference counting helper functions.
48 */
49
50
51 static inline void
pipe_reference_init(struct pipe_reference * reference,unsigned count)52 pipe_reference_init(struct pipe_reference *reference, unsigned count)
53 {
54 p_atomic_set(&reference->count, count);
55 }
56
57 static inline boolean
pipe_is_referenced(struct pipe_reference * reference)58 pipe_is_referenced(struct pipe_reference *reference)
59 {
60 return p_atomic_read(&reference->count) != 0;
61 }
62
63 /**
64 * Update reference counting.
65 * The old thing pointed to, if any, will be unreferenced.
66 * Both 'ptr' and 'reference' may be NULL.
67 * \return TRUE if the object's refcount hits zero and should be destroyed.
68 */
69 static inline boolean
pipe_reference_described(struct pipe_reference * ptr,struct pipe_reference * reference,debug_reference_descriptor get_desc)70 pipe_reference_described(struct pipe_reference *ptr,
71 struct pipe_reference *reference,
72 debug_reference_descriptor get_desc)
73 {
74 boolean destroy = FALSE;
75
76 if(ptr != reference) {
77 /* bump the reference.count first */
78 if (reference) {
79 assert(pipe_is_referenced(reference));
80 p_atomic_inc(&reference->count);
81 debug_reference(reference, get_desc, 1);
82 }
83
84 if (ptr) {
85 assert(pipe_is_referenced(ptr));
86 if (p_atomic_dec_zero(&ptr->count)) {
87 destroy = TRUE;
88 }
89 debug_reference(ptr, get_desc, -1);
90 }
91 }
92
93 return destroy;
94 }
95
96 static inline boolean
pipe_reference(struct pipe_reference * ptr,struct pipe_reference * reference)97 pipe_reference(struct pipe_reference *ptr, struct pipe_reference *reference)
98 {
99 return pipe_reference_described(ptr, reference,
100 (debug_reference_descriptor)debug_describe_reference);
101 }
102
103 /* Return true if the surfaces are equal. */
104 static inline boolean
pipe_surface_equal(struct pipe_surface * s1,struct pipe_surface * s2)105 pipe_surface_equal(struct pipe_surface *s1, struct pipe_surface *s2)
106 {
107 return s1->texture == s2->texture &&
108 s1->format == s2->format &&
109 (s1->texture->target != PIPE_BUFFER ||
110 (s1->u.buf.first_element == s2->u.buf.first_element &&
111 s1->u.buf.last_element == s2->u.buf.last_element)) &&
112 (s1->texture->target == PIPE_BUFFER ||
113 (s1->u.tex.level == s2->u.tex.level &&
114 s1->u.tex.first_layer == s2->u.tex.first_layer &&
115 s1->u.tex.last_layer == s2->u.tex.last_layer));
116 }
117
118 /**
119 * Get the polygon offset enable/disable flag for the given polygon fill mode.
120 * \param fill_mode one of PIPE_POLYGON_MODE_POINT/LINE/FILL
121 */
122 static inline boolean
util_get_offset(const struct pipe_rasterizer_state * templ,unsigned fill_mode)123 util_get_offset(const struct pipe_rasterizer_state *templ,
124 unsigned fill_mode)
125 {
126 switch(fill_mode) {
127 case PIPE_POLYGON_MODE_POINT:
128 return templ->offset_point;
129 case PIPE_POLYGON_MODE_LINE:
130 return templ->offset_line;
131 case PIPE_POLYGON_MODE_FILL:
132 return templ->offset_tri;
133 default:
134 assert(0);
135 return FALSE;
136 }
137 }
138
139 static inline float
util_get_min_point_size(const struct pipe_rasterizer_state * state)140 util_get_min_point_size(const struct pipe_rasterizer_state *state)
141 {
142 /* The point size should be clamped to this value at the rasterizer stage.
143 */
144 return !state->point_quad_rasterization &&
145 !state->point_smooth &&
146 !state->multisample ? 1.0f : 0.0f;
147 }
148
149 static inline void
util_query_clear_result(union pipe_query_result * result,unsigned type)150 util_query_clear_result(union pipe_query_result *result, unsigned type)
151 {
152 switch (type) {
153 case PIPE_QUERY_OCCLUSION_PREDICATE:
154 case PIPE_QUERY_SO_OVERFLOW_PREDICATE:
155 case PIPE_QUERY_GPU_FINISHED:
156 result->b = FALSE;
157 break;
158 case PIPE_QUERY_OCCLUSION_COUNTER:
159 case PIPE_QUERY_TIMESTAMP:
160 case PIPE_QUERY_TIME_ELAPSED:
161 case PIPE_QUERY_PRIMITIVES_GENERATED:
162 case PIPE_QUERY_PRIMITIVES_EMITTED:
163 result->u64 = 0;
164 break;
165 case PIPE_QUERY_SO_STATISTICS:
166 memset(&result->so_statistics, 0, sizeof(result->so_statistics));
167 break;
168 case PIPE_QUERY_TIMESTAMP_DISJOINT:
169 memset(&result->timestamp_disjoint, 0, sizeof(result->timestamp_disjoint));
170 break;
171 case PIPE_QUERY_PIPELINE_STATISTICS:
172 memset(&result->pipeline_statistics, 0, sizeof(result->pipeline_statistics));
173 break;
174 default:
175 memset(result, 0, sizeof(*result));
176 }
177 }
178
179 /** Convert PIPE_TEXTURE_x to TGSI_TEXTURE_x */
180 static inline unsigned
util_pipe_tex_to_tgsi_tex(enum pipe_texture_target pipe_tex_target,unsigned nr_samples)181 util_pipe_tex_to_tgsi_tex(enum pipe_texture_target pipe_tex_target,
182 unsigned nr_samples)
183 {
184 switch (pipe_tex_target) {
185 case PIPE_TEXTURE_1D:
186 assert(nr_samples <= 1);
187 return TGSI_TEXTURE_1D;
188
189 case PIPE_TEXTURE_2D:
190 return nr_samples > 1 ? TGSI_TEXTURE_2D_MSAA : TGSI_TEXTURE_2D;
191
192 case PIPE_TEXTURE_RECT:
193 assert(nr_samples <= 1);
194 return TGSI_TEXTURE_RECT;
195
196 case PIPE_TEXTURE_3D:
197 assert(nr_samples <= 1);
198 return TGSI_TEXTURE_3D;
199
200 case PIPE_TEXTURE_CUBE:
201 assert(nr_samples <= 1);
202 return TGSI_TEXTURE_CUBE;
203
204 case PIPE_TEXTURE_1D_ARRAY:
205 assert(nr_samples <= 1);
206 return TGSI_TEXTURE_1D_ARRAY;
207
208 case PIPE_TEXTURE_2D_ARRAY:
209 return nr_samples > 1 ? TGSI_TEXTURE_2D_ARRAY_MSAA :
210 TGSI_TEXTURE_2D_ARRAY;
211
212 case PIPE_TEXTURE_CUBE_ARRAY:
213 return TGSI_TEXTURE_CUBE_ARRAY;
214
215 default:
216 assert(0 && "unexpected texture target");
217 return TGSI_TEXTURE_UNKNOWN;
218 }
219 }
220
221
222 static inline unsigned
util_max_layer(const struct pipe_resource * r,unsigned level)223 util_max_layer(const struct pipe_resource *r, unsigned level)
224 {
225 switch (r->target) {
226 case PIPE_TEXTURE_CUBE:
227 return 6 - 1;
228 case PIPE_TEXTURE_3D:
229 return u_minify(r->depth0, level) - 1;
230 case PIPE_TEXTURE_1D_ARRAY:
231 case PIPE_TEXTURE_2D_ARRAY:
232 case PIPE_TEXTURE_CUBE_ARRAY:
233 return r->array_size - 1;
234 default:
235 return 0;
236 }
237 }
238
239 #ifdef __cplusplus
240 }
241 #endif
242
243 #endif /* U_INLINES_H */
244