1 /**************************************************************************
3 * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
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:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
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 TUNGSTEN GRAPHICS 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.
26 **************************************************************************/
29 * Keith Whitwell <keith@tungstengraphics.com>
30 * Michel Dänzer <michel@tungstengraphics.com>
33 #include "pipe/p_defines.h"
34 #include "util/u_inlines.h"
36 #include "util/u_format.h"
37 #include "util/u_math.h"
38 #include "util/u_memory.h"
39 #include "util/u_transfer.h"
41 #include "sp_context.h"
43 #include "sp_texture.h"
44 #include "sp_screen.h"
46 #include "state_tracker/sw_winsys.h"
50 * Conventional allocation path for non-display textures:
51 * Use a simple, maximally packed layout.
54 softpipe_resource_layout(struct pipe_screen
*screen
,
55 struct softpipe_resource
*spr
)
57 struct pipe_resource
*pt
= &spr
->base
;
59 unsigned width
= pt
->width0
;
60 unsigned height
= pt
->height0
;
61 unsigned depth
= pt
->depth0
;
62 unsigned buffer_size
= 0;
64 for (level
= 0; level
<= pt
->last_level
; level
++) {
65 spr
->stride
[level
] = util_format_get_stride(pt
->format
, width
);
67 spr
->level_offset
[level
] = buffer_size
;
69 buffer_size
+= (util_format_get_nblocksy(pt
->format
, height
) *
70 ((pt
->target
== PIPE_TEXTURE_CUBE
) ? 6 : depth
) *
73 width
= u_minify(width
, 1);
74 height
= u_minify(height
, 1);
75 depth
= u_minify(depth
, 1);
78 spr
->data
= align_malloc(buffer_size
, 16);
80 return spr
->data
!= NULL
;
85 * Texture layout for simple color buffers.
88 softpipe_displaytarget_layout(struct pipe_screen
*screen
,
89 struct softpipe_resource
*spr
)
91 struct sw_winsys
*winsys
= softpipe_screen(screen
)->winsys
;
93 /* Round up the surface size to a multiple of the tile size?
95 spr
->dt
= winsys
->displaytarget_create(winsys
,
103 return spr
->dt
!= NULL
;
108 * Create new pipe_resource given the template information.
110 static struct pipe_resource
*
111 softpipe_resource_create(struct pipe_screen
*screen
,
112 const struct pipe_resource
*templat
)
114 struct softpipe_resource
*spr
= CALLOC_STRUCT(softpipe_resource
);
118 assert(templat
->format
!= PIPE_FORMAT_NONE
);
120 spr
->base
= *templat
;
121 pipe_reference_init(&spr
->base
.reference
, 1);
122 spr
->base
.screen
= screen
;
124 spr
->pot
= (util_is_power_of_two(templat
->width0
) &&
125 util_is_power_of_two(templat
->height0
) &&
126 util_is_power_of_two(templat
->depth0
));
128 if (spr
->base
.bind
& (PIPE_BIND_DISPLAY_TARGET
|
131 if (!softpipe_displaytarget_layout(screen
, spr
))
135 if (!softpipe_resource_layout(screen
, spr
))
148 softpipe_resource_destroy(struct pipe_screen
*pscreen
,
149 struct pipe_resource
*pt
)
151 struct softpipe_screen
*screen
= softpipe_screen(pscreen
);
152 struct softpipe_resource
*spr
= softpipe_resource(pt
);
156 struct sw_winsys
*winsys
= screen
->winsys
;
157 winsys
->displaytarget_destroy(winsys
, spr
->dt
);
159 else if (!spr
->userBuffer
) {
160 /* regular texture */
161 align_free(spr
->data
);
168 static struct pipe_resource
*
169 softpipe_resource_from_handle(struct pipe_screen
*screen
,
170 const struct pipe_resource
*templat
,
171 struct winsys_handle
*whandle
)
173 struct sw_winsys
*winsys
= softpipe_screen(screen
)->winsys
;
174 struct softpipe_resource
*spr
= CALLOC_STRUCT(softpipe_resource
);
178 spr
->base
= *templat
;
179 pipe_reference_init(&spr
->base
.reference
, 1);
180 spr
->base
.screen
= screen
;
182 spr
->pot
= (util_is_power_of_two(templat
->width0
) &&
183 util_is_power_of_two(templat
->height0
) &&
184 util_is_power_of_two(templat
->depth0
));
186 spr
->dt
= winsys
->displaytarget_from_handle(winsys
,
202 softpipe_resource_get_handle(struct pipe_screen
*screen
,
203 struct pipe_resource
*pt
,
204 struct winsys_handle
*whandle
)
206 struct sw_winsys
*winsys
= softpipe_screen(screen
)->winsys
;
207 struct softpipe_resource
*spr
= softpipe_resource(pt
);
213 return winsys
->displaytarget_get_handle(winsys
, spr
->dt
, whandle
);
218 * Helper function to compute offset (in bytes) for a particular
219 * texture level/face/slice from the start of the buffer.
222 sp_get_tex_image_offset(const struct softpipe_resource
*spr
,
223 unsigned level
, unsigned face
, unsigned zslice
)
225 const unsigned hgt
= u_minify(spr
->base
.height0
, level
);
226 const unsigned nblocksy
= util_format_get_nblocksy(spr
->base
.format
, hgt
);
227 unsigned offset
= spr
->level_offset
[level
];
229 if (spr
->base
.target
== PIPE_TEXTURE_CUBE
) {
231 offset
+= face
* nblocksy
* spr
->stride
[level
];
233 else if (spr
->base
.target
== PIPE_TEXTURE_3D
) {
235 offset
+= zslice
* nblocksy
* spr
->stride
[level
];
247 * Get a pipe_surface "view" into a texture resource.
249 static struct pipe_surface
*
250 softpipe_get_tex_surface(struct pipe_screen
*screen
,
251 struct pipe_resource
*pt
,
252 unsigned face
, unsigned level
, unsigned zslice
,
255 struct softpipe_resource
*spr
= softpipe_resource(pt
);
256 struct pipe_surface
*ps
;
258 assert(level
<= pt
->last_level
);
260 ps
= CALLOC_STRUCT(pipe_surface
);
262 pipe_reference_init(&ps
->reference
, 1);
263 pipe_resource_reference(&ps
->texture
, pt
);
264 ps
->format
= pt
->format
;
265 ps
->width
= u_minify(pt
->width0
, level
);
266 ps
->height
= u_minify(pt
->height0
, level
);
267 ps
->offset
= sp_get_tex_image_offset(spr
, level
, face
, zslice
);
279 * Free a pipe_surface which was created with softpipe_get_tex_surface().
282 softpipe_tex_surface_destroy(struct pipe_surface
*surf
)
284 /* Effectively do the texture_update work here - if texture images
285 * needed post-processing to put them into hardware layout, this is
286 * where it would happen. For softpipe, nothing to do.
288 assert(surf
->texture
);
289 pipe_resource_reference(&surf
->texture
, NULL
);
295 * Geta pipe_transfer object which is used for moving data in/out of
297 * \param pipe rendering context
298 * \param resource the resource to transfer in/out of
299 * \param sr indicates cube face or 3D texture slice
300 * \param usage bitmask of PIPE_TRANSFER_x flags
301 * \param box the 1D/2D/3D region of interest
303 static struct pipe_transfer
*
304 softpipe_get_transfer(struct pipe_context
*pipe
,
305 struct pipe_resource
*resource
,
306 struct pipe_subresource sr
,
308 const struct pipe_box
*box
)
310 struct softpipe_resource
*spr
= softpipe_resource(resource
);
311 struct softpipe_transfer
*spt
;
314 assert(sr
.level
<= resource
->last_level
);
316 /* make sure the requested region is in the image bounds */
317 assert(box
->x
+ box
->width
<= u_minify(resource
->width0
, sr
.level
));
318 assert(box
->y
+ box
->height
<= u_minify(resource
->height0
, sr
.level
));
319 assert(box
->z
+ box
->depth
<= u_minify(resource
->depth0
, sr
.level
));
322 * Transfers, like other pipe operations, must happen in order, so flush the
323 * context if necessary.
325 if (!(usage
& PIPE_TRANSFER_UNSYNCHRONIZED
)) {
326 boolean read_only
= !(usage
& PIPE_TRANSFER_WRITE
);
327 boolean do_not_block
= !!(usage
& PIPE_TRANSFER_DONTBLOCK
);
328 if (!softpipe_flush_resource(pipe
, resource
,
332 TRUE
, /* cpu_access */
335 * It would have blocked, but state tracker requested no to.
337 assert(do_not_block
);
342 spt
= CALLOC_STRUCT(softpipe_transfer
);
344 struct pipe_transfer
*pt
= &spt
->base
;
345 enum pipe_format format
= resource
->format
;
346 const unsigned hgt
= u_minify(spr
->base
.height0
, sr
.level
);
347 const unsigned nblocksy
= util_format_get_nblocksy(format
, hgt
);
349 pipe_resource_reference(&pt
->resource
, resource
);
353 pt
->stride
= spr
->stride
[sr
.level
];
354 pt
->slice_stride
= pt
->stride
* nblocksy
;
356 spt
->offset
= sp_get_tex_image_offset(spr
, sr
.level
, sr
.face
, box
->z
);
359 box
->y
/ util_format_get_blockheight(format
) * spt
->base
.stride
+
360 box
->x
/ util_format_get_blockwidth(format
) * util_format_get_blocksize(format
);
369 * Free a pipe_transfer object which was created with
370 * softpipe_get_transfer().
373 softpipe_transfer_destroy(struct pipe_context
*pipe
,
374 struct pipe_transfer
*transfer
)
376 pipe_resource_reference(&transfer
->resource
, NULL
);
382 * Create memory mapping for given pipe_transfer object.
385 softpipe_transfer_map(struct pipe_context
*pipe
,
386 struct pipe_transfer
*transfer
)
388 struct softpipe_transfer
*spt
= softpipe_transfer(transfer
);
389 struct softpipe_resource
*spr
= softpipe_resource(transfer
->resource
);
390 struct sw_winsys
*winsys
= softpipe_screen(pipe
->screen
)->winsys
;
393 /* resources backed by display target treated specially:
396 map
= winsys
->displaytarget_map(winsys
, spr
->dt
, transfer
->usage
);
405 return map
+ spt
->offset
;
410 * Unmap memory mapping for given pipe_transfer object.
413 softpipe_transfer_unmap(struct pipe_context
*pipe
,
414 struct pipe_transfer
*transfer
)
416 struct softpipe_resource
*spr
;
418 assert(transfer
->resource
);
419 spr
= softpipe_resource(transfer
->resource
);
423 struct sw_winsys
*winsys
= softpipe_screen(pipe
->screen
)->winsys
;
424 winsys
->displaytarget_unmap(winsys
, spr
->dt
);
427 if (transfer
->usage
& PIPE_TRANSFER_WRITE
) {
428 /* Mark the texture as dirty to expire the tile caches. */
434 * Create buffer which wraps user-space data.
436 static struct pipe_resource
*
437 softpipe_user_buffer_create(struct pipe_screen
*screen
,
442 struct softpipe_resource
*spr
;
444 spr
= CALLOC_STRUCT(softpipe_resource
);
448 pipe_reference_init(&spr
->base
.reference
, 1);
449 spr
->base
.screen
= screen
;
450 spr
->base
.format
= PIPE_FORMAT_R8_UNORM
; /* ?? */
451 spr
->base
.bind
= bind_flags
;
452 spr
->base
.usage
= PIPE_USAGE_IMMUTABLE
;
454 spr
->base
.width0
= bytes
;
455 spr
->base
.height0
= 1;
456 spr
->base
.depth0
= 1;
457 spr
->userBuffer
= TRUE
;
465 softpipe_init_texture_funcs(struct pipe_context
*pipe
)
467 pipe
->get_transfer
= softpipe_get_transfer
;
468 pipe
->transfer_destroy
= softpipe_transfer_destroy
;
469 pipe
->transfer_map
= softpipe_transfer_map
;
470 pipe
->transfer_unmap
= softpipe_transfer_unmap
;
472 pipe
->transfer_flush_region
= u_default_transfer_flush_region
;
473 pipe
->transfer_inline_write
= u_default_transfer_inline_write
;
478 softpipe_init_screen_texture_funcs(struct pipe_screen
*screen
)
480 screen
->resource_create
= softpipe_resource_create
;
481 screen
->resource_destroy
= softpipe_resource_destroy
;
482 screen
->resource_from_handle
= softpipe_resource_from_handle
;
483 screen
->resource_get_handle
= softpipe_resource_get_handle
;
484 screen
->user_buffer_create
= softpipe_user_buffer_create
;
486 screen
->get_tex_surface
= softpipe_get_tex_surface
;
487 screen
->tex_surface_destroy
= softpipe_tex_surface_destroy
;