1
/**************************************************************************
3
* Copyright 2006 VMware, Inc.
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 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.
26
**************************************************************************/
29
* Keith Whitwell <keithw@vmware.com>
30
* Michel Dänzer <daenzer@vmware.com>
33
#include "pipe/p_defines.h"
34
#include "util/u_inlines.h"
36
#include "util/format/u_format.h"
37
#include "util/u_math.h"
38
#include "util/u_memory.h"
39
#include "util/u_transfer.h"
40
#include "util/u_surface.h"
42
#include "sp_context.h"
44
#include "sp_texture.h"
45
#include "sp_screen.h"
47
#include "frontend/sw_winsys.h"
51
* Conventional allocation path for non-display textures:
52
* Use a simple, maximally packed layout.
55
softpipe_resource_layout(struct pipe_screen *screen,
56
struct softpipe_resource *spr,
59
struct pipe_resource *pt = &spr->base;
61
unsigned width = pt->width0;
62
unsigned height = pt->height0;
63
unsigned depth = pt->depth0;
64
uint64_t buffer_size = 0;
66
for (level = 0; level <= pt->last_level; level++) {
67
unsigned slices, nblocksy;
69
nblocksy = util_format_get_nblocksy(pt->format, height);
71
if (pt->target == PIPE_TEXTURE_CUBE)
72
assert(pt->array_size == 6);
74
if (pt->target == PIPE_TEXTURE_3D)
77
slices = pt->array_size;
79
spr->stride[level] = util_format_get_stride(pt->format, width);
81
spr->level_offset[level] = buffer_size;
83
/* if row_stride * height > SP_MAX_TEXTURE_SIZE */
84
if ((uint64_t)spr->stride[level] * nblocksy > SP_MAX_TEXTURE_SIZE) {
89
spr->img_stride[level] = spr->stride[level] * nblocksy;
91
buffer_size += (uint64_t) spr->img_stride[level] * slices;
93
width = u_minify(width, 1);
94
height = u_minify(height, 1);
95
depth = u_minify(depth, 1);
98
if (buffer_size > SP_MAX_TEXTURE_SIZE)
102
spr->data = align_malloc(buffer_size, 64);
103
return spr->data != NULL;
112
* Check the size of the texture specified by 'res'.
113
* \return TRUE if OK, FALSE if too large.
116
softpipe_can_create_resource(struct pipe_screen *screen,
117
const struct pipe_resource *res)
119
struct softpipe_resource spr;
120
memset(&spr, 0, sizeof(spr));
122
return softpipe_resource_layout(screen, &spr, FALSE);
127
* Texture layout for simple color buffers.
130
softpipe_displaytarget_layout(struct pipe_screen *screen,
131
struct softpipe_resource *spr,
132
const void *map_front_private)
134
struct sw_winsys *winsys = softpipe_screen(screen)->winsys;
136
/* Round up the surface size to a multiple of the tile size?
138
spr->dt = winsys->displaytarget_create(winsys,
147
return spr->dt != NULL;
152
* Create new pipe_resource given the template information.
154
static struct pipe_resource *
155
softpipe_resource_create_front(struct pipe_screen *screen,
156
const struct pipe_resource *templat,
157
const void *map_front_private)
159
struct softpipe_resource *spr = CALLOC_STRUCT(softpipe_resource);
163
assert(templat->format != PIPE_FORMAT_NONE);
165
spr->base = *templat;
166
pipe_reference_init(&spr->base.reference, 1);
167
spr->base.screen = screen;
169
spr->pot = (util_is_power_of_two_or_zero(templat->width0) &&
170
util_is_power_of_two_or_zero(templat->height0) &&
171
util_is_power_of_two_or_zero(templat->depth0));
173
if (spr->base.bind & (PIPE_BIND_DISPLAY_TARGET |
176
if (!softpipe_displaytarget_layout(screen, spr, map_front_private))
180
if (!softpipe_resource_layout(screen, spr, TRUE))
191
static struct pipe_resource *
192
softpipe_resource_create(struct pipe_screen *screen,
193
const struct pipe_resource *templat)
195
return softpipe_resource_create_front(screen, templat, NULL);
199
softpipe_resource_destroy(struct pipe_screen *pscreen,
200
struct pipe_resource *pt)
202
struct softpipe_screen *screen = softpipe_screen(pscreen);
203
struct softpipe_resource *spr = softpipe_resource(pt);
207
struct sw_winsys *winsys = screen->winsys;
208
winsys->displaytarget_destroy(winsys, spr->dt);
210
else if (!spr->userBuffer) {
211
/* regular texture */
212
align_free(spr->data);
219
static struct pipe_resource *
220
softpipe_resource_from_handle(struct pipe_screen *screen,
221
const struct pipe_resource *templat,
222
struct winsys_handle *whandle,
225
struct sw_winsys *winsys = softpipe_screen(screen)->winsys;
226
struct softpipe_resource *spr = CALLOC_STRUCT(softpipe_resource);
230
spr->base = *templat;
231
pipe_reference_init(&spr->base.reference, 1);
232
spr->base.screen = screen;
234
spr->pot = (util_is_power_of_two_or_zero(templat->width0) &&
235
util_is_power_of_two_or_zero(templat->height0) &&
236
util_is_power_of_two_or_zero(templat->depth0));
238
spr->dt = winsys->displaytarget_from_handle(winsys,
254
softpipe_resource_get_handle(struct pipe_screen *screen,
255
struct pipe_context *ctx,
256
struct pipe_resource *pt,
257
struct winsys_handle *whandle,
260
struct sw_winsys *winsys = softpipe_screen(screen)->winsys;
261
struct softpipe_resource *spr = softpipe_resource(pt);
267
return winsys->displaytarget_get_handle(winsys, spr->dt, whandle);
272
* Helper function to compute offset (in bytes) for a particular
273
* texture level/face/slice from the start of the buffer.
276
softpipe_get_tex_image_offset(const struct softpipe_resource *spr,
277
unsigned level, unsigned layer)
279
unsigned offset = spr->level_offset[level];
281
offset += layer * spr->img_stride[level];
288
* Get a pipe_surface "view" into a texture resource.
290
static struct pipe_surface *
291
softpipe_create_surface(struct pipe_context *pipe,
292
struct pipe_resource *pt,
293
const struct pipe_surface *surf_tmpl)
295
struct pipe_surface *ps;
297
ps = CALLOC_STRUCT(pipe_surface);
299
pipe_reference_init(&ps->reference, 1);
300
pipe_resource_reference(&ps->texture, pt);
302
ps->format = surf_tmpl->format;
303
if (pt->target != PIPE_BUFFER) {
304
assert(surf_tmpl->u.tex.level <= pt->last_level);
305
ps->width = u_minify(pt->width0, surf_tmpl->u.tex.level);
306
ps->height = u_minify(pt->height0, surf_tmpl->u.tex.level);
307
ps->u.tex.level = surf_tmpl->u.tex.level;
308
ps->u.tex.first_layer = surf_tmpl->u.tex.first_layer;
309
ps->u.tex.last_layer = surf_tmpl->u.tex.last_layer;
310
if (ps->u.tex.first_layer != ps->u.tex.last_layer) {
311
debug_printf("creating surface with multiple layers, rendering to first layer only\n");
315
/* setting width as number of elements should get us correct renderbuffer width */
316
ps->width = surf_tmpl->u.buf.last_element - surf_tmpl->u.buf.first_element + 1;
317
ps->height = pt->height0;
318
ps->u.buf.first_element = surf_tmpl->u.buf.first_element;
319
ps->u.buf.last_element = surf_tmpl->u.buf.last_element;
320
assert(ps->u.buf.first_element <= ps->u.buf.last_element);
321
assert(ps->u.buf.last_element < ps->width);
329
* Free a pipe_surface which was created with softpipe_create_surface().
332
softpipe_surface_destroy(struct pipe_context *pipe,
333
struct pipe_surface *surf)
335
/* Effectively do the texture_update work here - if texture images
336
* needed post-processing to put them into hardware layout, this is
337
* where it would happen. For softpipe, nothing to do.
339
assert(surf->texture);
340
pipe_resource_reference(&surf->texture, NULL);
346
* Geta pipe_transfer object which is used for moving data in/out of
348
* \param pipe rendering context
349
* \param resource the resource to transfer in/out of
350
* \param level which mipmap level
351
* \param usage bitmask of PIPE_MAP_x flags
352
* \param box the 1D/2D/3D region of interest
355
softpipe_transfer_map(struct pipe_context *pipe,
356
struct pipe_resource *resource,
359
const struct pipe_box *box,
360
struct pipe_transfer **transfer)
362
struct sw_winsys *winsys = softpipe_screen(pipe->screen)->winsys;
363
struct softpipe_resource *spr = softpipe_resource(resource);
364
struct softpipe_transfer *spt;
365
struct pipe_transfer *pt;
366
enum pipe_format format = resource->format;
370
assert(level <= resource->last_level);
372
/* make sure the requested region is in the image bounds */
373
assert(box->x + box->width <= (int) u_minify(resource->width0, level));
374
if (resource->target == PIPE_TEXTURE_1D_ARRAY) {
375
assert(box->y + box->height <= (int) resource->array_size);
378
assert(box->y + box->height <= (int) u_minify(resource->height0, level));
379
if (resource->target == PIPE_TEXTURE_2D_ARRAY) {
380
assert(box->z + box->depth <= (int) resource->array_size);
382
else if (resource->target == PIPE_TEXTURE_CUBE) {
385
else if (resource->target == PIPE_TEXTURE_CUBE_ARRAY) {
386
assert(box->z <= (int) resource->array_size);
389
assert(box->z + box->depth <= (int) u_minify(resource->depth0, level));
394
* Transfers, like other pipe operations, must happen in order, so flush the
395
* context if necessary.
397
if (!(usage & PIPE_MAP_UNSYNCHRONIZED)) {
398
boolean read_only = !(usage & PIPE_MAP_WRITE);
399
boolean do_not_block = !!(usage & PIPE_MAP_DONTBLOCK);
400
if (!softpipe_flush_resource(pipe, resource,
401
level, box->depth > 1 ? -1 : box->z,
404
TRUE, /* cpu_access */
407
* It would have blocked, but state tracker requested no to.
409
assert(do_not_block);
414
spt = CALLOC_STRUCT(softpipe_transfer);
420
pipe_resource_reference(&pt->resource, resource);
424
pt->stride = spr->stride[level];
425
pt->layer_stride = spr->img_stride[level];
427
spt->offset = softpipe_get_tex_image_offset(spr, level, box->z);
430
box->y / util_format_get_blockheight(format) * spt->base.stride +
431
box->x / util_format_get_blockwidth(format) * util_format_get_blocksize(format);
433
/* resources backed by display target treated specially:
436
map = winsys->displaytarget_map(winsys, spr->dt, usage);
443
pipe_resource_reference(&pt->resource, NULL);
449
return map + spt->offset;
454
* Unmap memory mapping for given pipe_transfer object.
457
softpipe_transfer_unmap(struct pipe_context *pipe,
458
struct pipe_transfer *transfer)
460
struct softpipe_resource *spr;
462
assert(transfer->resource);
463
spr = softpipe_resource(transfer->resource);
467
struct sw_winsys *winsys = softpipe_screen(pipe->screen)->winsys;
468
winsys->displaytarget_unmap(winsys, spr->dt);
471
if (transfer->usage & PIPE_MAP_WRITE) {
472
/* Mark the texture as dirty to expire the tile caches. */
476
pipe_resource_reference(&transfer->resource, NULL);
481
* Create buffer which wraps user-space data.
483
struct pipe_resource *
484
softpipe_user_buffer_create(struct pipe_screen *screen,
489
struct softpipe_resource *spr;
491
spr = CALLOC_STRUCT(softpipe_resource);
495
pipe_reference_init(&spr->base.reference, 1);
496
spr->base.screen = screen;
497
spr->base.format = PIPE_FORMAT_R8_UNORM; /* ?? */
498
spr->base.bind = bind_flags;
499
spr->base.usage = PIPE_USAGE_IMMUTABLE;
501
spr->base.width0 = bytes;
502
spr->base.height0 = 1;
503
spr->base.depth0 = 1;
504
spr->base.array_size = 1;
505
spr->userBuffer = TRUE;
513
softpipe_init_texture_funcs(struct pipe_context *pipe)
515
pipe->buffer_map = softpipe_transfer_map;
516
pipe->buffer_unmap = softpipe_transfer_unmap;
517
pipe->texture_map = softpipe_transfer_map;
518
pipe->texture_unmap = softpipe_transfer_unmap;
520
pipe->transfer_flush_region = u_default_transfer_flush_region;
521
pipe->buffer_subdata = u_default_buffer_subdata;
522
pipe->texture_subdata = u_default_texture_subdata;
524
pipe->create_surface = softpipe_create_surface;
525
pipe->surface_destroy = softpipe_surface_destroy;
526
pipe->clear_texture = util_clear_texture;
531
softpipe_init_screen_texture_funcs(struct pipe_screen *screen)
533
screen->resource_create = softpipe_resource_create;
534
screen->resource_create_front = softpipe_resource_create_front;
535
screen->resource_destroy = softpipe_resource_destroy;
536
screen->resource_from_handle = softpipe_resource_from_handle;
537
screen->resource_get_handle = softpipe_resource_get_handle;
538
screen->can_create_resource = softpipe_can_create_resource;