1 /*
2 * Copyright (c) 2008-2024 Broadcom. All Rights Reserved.
3 * The term “Broadcom” refers to Broadcom Inc.
4 * and/or its subsidiaries.
5 * SPDX-License-Identifier: MIT
6 */
7
8 #ifndef SVGA_TEXTURE_H
9 #define SVGA_TEXTURE_H
10
11
12 #include "util/compiler.h"
13 #include "pipe/p_state.h"
14 #include "util/u_inlines.h"
15 #include "util/u_memory.h"
16 #include "util/u_transfer.h"
17 #include "svga_screen_cache.h"
18 #include "svga_context.h"
19
20 struct pipe_context;
21 struct pipe_screen;
22 struct svga_context;
23 struct svga_winsys_surface;
24 enum SVGA3dSurfaceFormat;
25
26
27 #define SVGA_MAX_TEXTURE_LEVELS 16
28
29 struct svga_texture
30 {
31 struct pipe_resource b;
32
33 uint16_t *defined;
34
35 struct svga_sampler_view *cached_view;
36
37 unsigned view_age[SVGA_MAX_TEXTURE_LEVELS];
38 unsigned age;
39
40 bool views_modified;
41
42 /**
43 * Creation key for the host surface handle.
44 *
45 * This structure describes all the host surface characteristics so that it
46 * can be looked up in cache, since creating a host surface is often a slow
47 * operation.
48 */
49 struct svga_host_surface_cache_key key;
50
51 /**
52 * Handle for the host side surface.
53 *
54 * This handle is owned by this texture. Views should hold on to a reference
55 * to this texture and never destroy this handle directly.
56 */
57 struct svga_winsys_surface *handle;
58
59 /**
60 * Whether the host side surface is imported and not created by this
61 * driver.
62 */
63 bool imported;
64
65 /**
66 * Whether texture upload buffer can be used on this texture
67 */
68 bool can_use_upload;
69
70 /**
71 * Whether texture is modified. Set if any of the dirty bits is set.
72 */
73 bool modified;
74
75 unsigned size; /**< Approximate size in bytes */
76
77 /** array indexed by cube face or 3D/array slice, one bit per mipmap level */
78 uint16_t *rendered_to;
79
80 /** array indexed by cube face or 3D/array slice, one bit per mipmap level.
81 * Set if the level is marked as dirty.
82 */
83 uint16_t *dirty;
84
85 enum svga_surface_state surface_state;
86
87 /**
88 * A cached backing host side surface to be used if this texture is being
89 * used for rendering and sampling at the same time.
90 * Currently we only cache one handle. If needed, we can extend this to
91 * support multiple handles.
92 */
93 struct svga_host_surface_cache_key backed_key;
94 struct svga_winsys_surface *backed_handle;
95 unsigned backed_age;
96 };
97
98
99
100 /* Note this is only used for texture (not buffer) transfers:
101 */
102 struct svga_transfer
103 {
104 struct pipe_transfer base;
105
106 unsigned slice; /**< array slice or cube face */
107 SVGA3dBox box; /* The adjusted box with slice index removed from z */
108
109 struct svga_winsys_buffer *hwbuf;
110
111 /* Height of the hardware buffer in pixel blocks */
112 unsigned hw_nblocksy;
113
114 /* Temporary malloc buffer when we can't allocate a hardware buffer
115 * big enough */
116 void *swbuf;
117
118 /* True if guest backed surface is supported and we can directly map
119 * to the surface for this transfer.
120 */
121 bool use_direct_map;
122
123 struct {
124 struct pipe_resource *buf; /* points to the upload buffer if this
125 * transfer is done via the upload buffer
126 * instead of directly mapping to the
127 * resource's surface.
128 */
129 void *map;
130 unsigned offset;
131 SVGA3dBox box;
132 unsigned nlayers;
133 } upload;
134 };
135
136
137 static inline struct svga_texture *
svga_texture(struct pipe_resource * resource)138 svga_texture(struct pipe_resource *resource)
139 {
140 struct svga_texture *tex = (struct svga_texture *)resource;
141 assert(tex == NULL || tex->b.target != PIPE_BUFFER);
142 return tex;
143 }
144
145
146 static inline struct svga_transfer *
svga_transfer(struct pipe_transfer * transfer)147 svga_transfer(struct pipe_transfer *transfer)
148 {
149 assert(transfer);
150 return (struct svga_transfer *)transfer;
151 }
152
153
154 /**
155 * Increment the age of a view into a texture
156 * This is used to track updates to textures when we draw into
157 * them via a surface.
158 */
159 static inline void
svga_age_texture_view(struct svga_texture * tex,unsigned level)160 svga_age_texture_view(struct svga_texture *tex, unsigned level)
161 {
162 assert(level < ARRAY_SIZE(tex->view_age));
163 tex->view_age[level] = ++(tex->age);
164 }
165
166
167 /** For debugging, check that face and level are legal */
168 static inline void
check_face_level(const struct svga_texture * tex,unsigned face,unsigned level)169 check_face_level(const struct svga_texture *tex,
170 unsigned face, unsigned level)
171 {
172 if (tex->b.target == PIPE_TEXTURE_CUBE) {
173 assert(face < 6);
174 }
175 else if (tex->b.target == PIPE_TEXTURE_3D) {
176 assert(face < tex->b.depth0);
177 }
178 else {
179 assert(face < tex->b.array_size);
180 }
181
182 assert(level < 8 * sizeof(tex->rendered_to[0]));
183 }
184
185
186 /**
187 * Mark the given texture face/level as being defined.
188 */
189 static inline void
svga_define_texture_level(struct svga_texture * tex,unsigned face,unsigned level)190 svga_define_texture_level(struct svga_texture *tex,
191 unsigned face,unsigned level)
192 {
193 check_face_level(tex, face, level);
194 tex->defined[face] |= 1 << level;
195 }
196
197
198 static inline bool
svga_is_texture_level_defined(const struct svga_texture * tex,unsigned face,unsigned level)199 svga_is_texture_level_defined(const struct svga_texture *tex,
200 unsigned face, unsigned level)
201 {
202 check_face_level(tex, face, level);
203 return (tex->defined[face] & (1 << level)) != 0;
204 }
205
206
207 static inline void
svga_set_texture_rendered_to(struct svga_texture * tex)208 svga_set_texture_rendered_to(struct svga_texture *tex)
209 {
210 tex->surface_state = SVGA_SURFACE_STATE_RENDERED;
211 }
212
213
214 static inline void
svga_clear_texture_rendered_to(struct svga_texture * tex)215 svga_clear_texture_rendered_to(struct svga_texture *tex)
216 {
217 tex->surface_state = SVGA_SURFACE_STATE_UPDATED;
218 }
219
220 static inline bool
svga_was_texture_rendered_to(const struct svga_texture * tex)221 svga_was_texture_rendered_to(const struct svga_texture *tex)
222 {
223 return (tex->surface_state == SVGA_SURFACE_STATE_RENDERED);
224 }
225
226 static inline void
svga_set_texture_dirty(struct svga_texture * tex,unsigned face,unsigned level)227 svga_set_texture_dirty(struct svga_texture *tex,
228 unsigned face, unsigned level)
229 {
230 check_face_level(tex, face, level);
231 tex->dirty[face] |= 1 << level;
232 tex->modified = true;
233 }
234
235 static inline void
svga_clear_texture_dirty(struct svga_texture * tex)236 svga_clear_texture_dirty(struct svga_texture *tex)
237 {
238 unsigned i;
239 for (i = 0; i < tex->b.depth0 * tex->b.array_size; i++) {
240 tex->dirty[i] = 0;
241 }
242 tex->modified = false;
243 }
244
245 static inline bool
svga_is_texture_level_dirty(const struct svga_texture * tex,unsigned face,unsigned level)246 svga_is_texture_level_dirty(const struct svga_texture *tex,
247 unsigned face, unsigned level)
248 {
249 check_face_level(tex, face, level);
250 return !!(tex->dirty[face] & (1 << level));
251 }
252
253 static inline bool
svga_is_texture_dirty(const struct svga_texture * tex)254 svga_is_texture_dirty(const struct svga_texture *tex)
255 {
256 return tex->modified;
257 }
258
259 struct pipe_resource *
260 svga_texture_create(struct pipe_screen *screen,
261 const struct pipe_resource *template);
262
263 bool
264 svga_resource_get_handle(struct pipe_screen *screen,
265 struct pipe_context *context,
266 struct pipe_resource *texture,
267 struct winsys_handle *whandle,
268 unsigned usage);
269
270 struct pipe_resource *
271 svga_texture_from_handle(struct pipe_screen * screen,
272 const struct pipe_resource *template,
273 struct winsys_handle *whandle);
274
275 bool
276 svga_texture_generate_mipmap(struct pipe_context *pipe,
277 struct pipe_resource *pt,
278 enum pipe_format format,
279 unsigned base_level,
280 unsigned last_level,
281 unsigned first_layer,
282 unsigned last_layer);
283
284 bool
285 svga_texture_transfer_map_upload_create(struct svga_context *svga);
286
287 void
288 svga_texture_transfer_map_upload_destroy(struct svga_context *svga);
289
290 bool
291 svga_texture_transfer_map_can_upload(const struct svga_screen *svgascreen,
292 const struct pipe_resource *pt);
293
294 void *
295 svga_texture_transfer_map_upload(struct svga_context *svga,
296 struct svga_transfer *st);
297
298 void
299 svga_texture_transfer_unmap_upload(struct svga_context *svga,
300 struct svga_transfer *st);
301
302 bool
303 svga_texture_device_format_has_alpha(struct pipe_resource *texture);
304
305 void *
306 svga_texture_transfer_map(struct pipe_context *pipe,
307 struct pipe_resource *texture,
308 unsigned level,
309 unsigned usage,
310 const struct pipe_box *box,
311 struct pipe_transfer **ptransfer);
312
313 void
314 svga_texture_transfer_unmap(struct pipe_context *pipe,
315 struct pipe_transfer *transfer);
316
317 #endif /* SVGA_TEXTURE_H */
318