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"
42 #include "sp_texture.h"
43 #include "sp_screen.h"
45 #include "state_tracker/sw_winsys.h"
49 * Conventional allocation path for non-display textures:
50 * Use a simple, maximally packed layout.
53 softpipe_resource_layout(struct pipe_screen
*screen
,
54 struct softpipe_resource
* spt
)
56 struct pipe_resource
*pt
= &spt
->base
;
58 unsigned width
= pt
->width0
;
59 unsigned height
= pt
->height0
;
60 unsigned depth
= pt
->depth0
;
61 unsigned buffer_size
= 0;
63 for (level
= 0; level
<= pt
->last_level
; level
++) {
64 spt
->stride
[level
] = util_format_get_stride(pt
->format
, width
);
66 spt
->level_offset
[level
] = buffer_size
;
68 buffer_size
+= (util_format_get_nblocksy(pt
->format
, height
) *
69 ((pt
->target
== PIPE_TEXTURE_CUBE
) ? 6 : depth
) *
72 width
= u_minify(width
, 1);
73 height
= u_minify(height
, 1);
74 depth
= u_minify(depth
, 1);
77 spt
->data
= align_malloc(buffer_size
, 16);
79 return spt
->data
!= NULL
;
84 * Texture layout for simple color buffers.
87 softpipe_displaytarget_layout(struct pipe_screen
*screen
,
88 struct softpipe_resource
* spt
)
90 struct sw_winsys
*winsys
= softpipe_screen(screen
)->winsys
;
92 /* Round up the surface size to a multiple of the tile size?
94 spt
->dt
= winsys
->displaytarget_create(winsys
,
102 return spt
->dt
!= NULL
;
107 * Create new pipe_resource given the template information.
109 static struct pipe_resource
*
110 softpipe_resource_create(struct pipe_screen
*screen
,
111 const struct pipe_resource
*template)
113 struct softpipe_resource
*spt
= CALLOC_STRUCT(softpipe_resource
);
117 assert(template->format
!= PIPE_FORMAT_NONE
);
119 spt
->base
= *template;
120 pipe_reference_init(&spt
->base
.reference
, 1);
121 spt
->base
.screen
= screen
;
123 spt
->pot
= (util_is_power_of_two(template->width0
) &&
124 util_is_power_of_two(template->height0
) &&
125 util_is_power_of_two(template->depth0
));
127 if (spt
->base
.bind
& (PIPE_BIND_DISPLAY_TARGET
|
130 if (!softpipe_displaytarget_layout(screen
, spt
))
134 if (!softpipe_resource_layout(screen
, spt
))
147 softpipe_resource_destroy(struct pipe_screen
*pscreen
,
148 struct pipe_resource
*pt
)
150 struct softpipe_screen
*screen
= softpipe_screen(pscreen
);
151 struct softpipe_resource
*spt
= softpipe_resource(pt
);
155 struct sw_winsys
*winsys
= screen
->winsys
;
156 winsys
->displaytarget_destroy(winsys
, spt
->dt
);
158 else if (!spt
->userBuffer
) {
159 /* regular texture */
160 align_free(spt
->data
);
167 static struct pipe_resource
*
168 softpipe_resource_from_handle(struct pipe_screen
*screen
,
169 const struct pipe_resource
*template,
170 struct winsys_handle
*whandle
)
172 struct sw_winsys
*winsys
= softpipe_screen(screen
)->winsys
;
173 struct softpipe_resource
*spt
= CALLOC_STRUCT(softpipe_resource
);
177 spt
->base
= *template;
178 pipe_reference_init(&spt
->base
.reference
, 1);
179 spt
->base
.screen
= screen
;
181 spt
->pot
= (util_is_power_of_two(template->width0
) &&
182 util_is_power_of_two(template->height0
) &&
183 util_is_power_of_two(template->depth0
));
185 spt
->dt
= winsys
->displaytarget_from_handle(winsys
,
201 softpipe_resource_get_handle(struct pipe_screen
*screen
,
202 struct pipe_resource
*pt
,
203 struct winsys_handle
*whandle
)
205 struct sw_winsys
*winsys
= softpipe_screen(screen
)->winsys
;
206 struct softpipe_resource
*spt
= softpipe_resource(pt
);
212 return winsys
->displaytarget_get_handle(winsys
, spt
->dt
, whandle
);
217 * Get a pipe_surface "view" into a texture.
219 static struct pipe_surface
*
220 softpipe_get_tex_surface(struct pipe_screen
*screen
,
221 struct pipe_resource
*pt
,
222 unsigned face
, unsigned level
, unsigned zslice
,
225 struct softpipe_resource
*spt
= softpipe_resource(pt
);
226 struct pipe_surface
*ps
;
228 assert(level
<= pt
->last_level
);
230 ps
= CALLOC_STRUCT(pipe_surface
);
232 pipe_reference_init(&ps
->reference
, 1);
233 pipe_resource_reference(&ps
->texture
, pt
);
234 ps
->format
= pt
->format
;
235 ps
->width
= u_minify(pt
->width0
, level
);
236 ps
->height
= u_minify(pt
->height0
, level
);
237 ps
->offset
= spt
->level_offset
[level
];
244 if (pt
->target
== PIPE_TEXTURE_CUBE
) {
245 ps
->offset
+= face
* util_format_get_nblocksy(pt
->format
, u_minify(pt
->height0
, level
)) *
248 else if (pt
->target
== PIPE_TEXTURE_3D
) {
249 ps
->offset
+= zslice
* util_format_get_nblocksy(pt
->format
, u_minify(pt
->height0
, level
)) *
262 * Free a pipe_surface which was created with softpipe_get_tex_surface().
265 softpipe_tex_surface_destroy(struct pipe_surface
*surf
)
267 /* Effectively do the texture_update work here - if texture images
268 * needed post-processing to put them into hardware layout, this is
269 * where it would happen. For softpipe, nothing to do.
271 assert(surf
->texture
);
272 pipe_resource_reference(&surf
->texture
, NULL
);
278 * Geta pipe_transfer object which is used for moving data in/out of
280 * \param face one of PIPE_TEX_FACE_x or 0
281 * \param level texture mipmap level
282 * \param zslice 2D slice of a 3D texture
283 * \param usage one of PIPE_TRANSFER_READ/WRITE/READ_WRITE
284 * \param x X position of region to read/write
285 * \param y Y position of region to read/write
286 * \param width width of region to read/write
287 * \param height height of region to read/write
289 static struct pipe_transfer
*
290 softpipe_get_transfer(struct pipe_context
*pipe
,
291 struct pipe_resource
*resource
,
292 struct pipe_subresource sr
,
294 const struct pipe_box
*box
)
296 struct softpipe_resource
*sptex
= softpipe_resource(resource
);
297 struct softpipe_transfer
*spt
;
300 assert(sr
.level
<= resource
->last_level
);
302 /* make sure the requested region is in the image bounds */
303 assert(box
->x
+ box
->width
<= u_minify(resource
->width0
, sr
.level
));
304 assert(box
->y
+ box
->height
<= u_minify(resource
->height0
, sr
.level
));
305 assert(box
->z
+ box
->depth
<= u_minify(resource
->depth0
, sr
.level
));
307 spt
= CALLOC_STRUCT(softpipe_transfer
);
309 struct pipe_transfer
*pt
= &spt
->base
;
310 enum pipe_format format
= resource
->format
;
311 int nblocksy
= util_format_get_nblocksy(resource
->format
,
312 u_minify(resource
->height0
, sr
.level
));
313 pipe_resource_reference(&pt
->resource
, resource
);
317 pt
->stride
= sptex
->stride
[sr
.level
];
319 spt
->offset
= sptex
->level_offset
[sr
.level
];
321 if (resource
->target
== PIPE_TEXTURE_CUBE
) {
322 spt
->offset
+= sr
.face
* nblocksy
* pt
->stride
;
324 else if (resource
->target
== PIPE_TEXTURE_3D
) {
325 spt
->offset
+= box
->z
* nblocksy
* pt
->stride
;
328 assert(sr
.face
== 0);
333 box
->y
/ util_format_get_blockheight(format
) * spt
->base
.stride
+
334 box
->x
/ util_format_get_blockwidth(format
) * util_format_get_blocksize(format
);
343 * Free a pipe_transfer object which was created with
344 * softpipe_get_transfer().
347 softpipe_transfer_destroy(struct pipe_context
*pipe
,
348 struct pipe_transfer
*transfer
)
350 pipe_resource_reference(&transfer
->resource
, NULL
);
356 * Create memory mapping for given pipe_transfer object.
359 softpipe_transfer_map( struct pipe_context
*pipe
,
360 struct pipe_transfer
*transfer
)
362 struct softpipe_transfer
*sp_transfer
= softpipe_transfer(transfer
);
363 struct softpipe_resource
*sp_resource
= softpipe_resource(transfer
->resource
);
364 struct sw_winsys
*winsys
= softpipe_screen(pipe
->screen
)->winsys
;
367 /* resources backed by display target treated specially:
369 if (sp_resource
->dt
) {
370 map
= winsys
->displaytarget_map(winsys
,
375 map
= sp_resource
->data
;
381 return map
+ sp_transfer
->offset
;
386 * Unmap memory mapping for given pipe_transfer object.
389 softpipe_transfer_unmap(struct pipe_context
*pipe
,
390 struct pipe_transfer
*transfer
)
392 struct softpipe_resource
*spt
;
394 assert(transfer
->resource
);
395 spt
= softpipe_resource(transfer
->resource
);
399 struct sw_winsys
*winsys
= softpipe_screen(pipe
->screen
)->winsys
;
400 winsys
->displaytarget_unmap(winsys
, spt
->dt
);
403 if (transfer
->usage
& PIPE_TRANSFER_WRITE
) {
404 /* Mark the texture as dirty to expire the tile caches. */
410 * Create buffer which wraps user-space data.
412 static struct pipe_resource
*
413 softpipe_user_buffer_create(struct pipe_screen
*screen
,
418 struct softpipe_resource
*buffer
;
420 buffer
= CALLOC_STRUCT(softpipe_resource
);
425 pipe_reference_init(&buffer
->base
.reference
, 1);
426 buffer
->base
.screen
= screen
;
427 buffer
->base
.format
= PIPE_FORMAT_R8_UNORM
; /* ?? */
428 buffer
->base
.bind
= bind_flags
;
429 buffer
->base
._usage
= PIPE_USAGE_IMMUTABLE
;
430 buffer
->base
.flags
= 0;
431 buffer
->base
.width0
= bytes
;
432 buffer
->base
.height0
= 1;
433 buffer
->base
.depth0
= 1;
434 buffer
->userBuffer
= TRUE
;
437 return &buffer
->base
;
445 softpipe_init_texture_funcs(struct pipe_context
*pipe
)
447 pipe
->get_transfer
= softpipe_get_transfer
;
448 pipe
->transfer_destroy
= softpipe_transfer_destroy
;
449 pipe
->transfer_map
= softpipe_transfer_map
;
450 pipe
->transfer_unmap
= softpipe_transfer_unmap
;
452 pipe
->transfer_flush_region
= u_default_transfer_flush_region
;
453 pipe
->transfer_inline_write
= u_default_transfer_inline_write
;
457 softpipe_init_screen_texture_funcs(struct pipe_screen
*screen
)
459 screen
->resource_create
= softpipe_resource_create
;
460 screen
->resource_destroy
= softpipe_resource_destroy
;
461 screen
->resource_from_handle
= softpipe_resource_from_handle
;
462 screen
->resource_get_handle
= softpipe_resource_get_handle
;
463 screen
->user_buffer_create
= softpipe_user_buffer_create
;
465 screen
->get_tex_surface
= softpipe_get_tex_surface
;
466 screen
->tex_surface_destroy
= softpipe_tex_surface_destroy
;