1 /**********************************************************
2 * Copyright 2008-2009 VMware, Inc. All rights reserved.
4 * Permission is hereby granted, free of charge, to any person
5 * obtaining a copy of this software and associated documentation
6 * files (the "Software"), to deal in the Software without
7 * restriction, including without limitation the rights to use, copy,
8 * modify, merge, publish, distribute, sublicense, and/or sell copies
9 * of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 **********************************************************/
28 #include "pipe/p_state.h"
29 #include "pipe/p_defines.h"
30 #include "util/u_inlines.h"
31 #include "os/os_thread.h"
32 #include "util/u_math.h"
33 #include "util/u_memory.h"
35 #include "svga_context.h"
36 #include "svga_screen.h"
37 #include "svga_resource_buffer.h"
38 #include "svga_resource_buffer_upload.h"
39 #include "svga_winsys.h"
40 #include "svga_debug.h"
44 * Vertex and index buffers need hardware backing. Constant buffers
45 * do not. No other types of buffers currently supported.
48 svga_buffer_needs_hw_storage(unsigned usage
)
50 return usage
& (PIPE_BIND_VERTEX_BUFFER
| PIPE_BIND_INDEX_BUFFER
);
55 svga_buffer_is_referenced( struct pipe_context
*pipe
,
56 struct pipe_resource
*buf
,
57 unsigned level
, int layer
)
59 struct svga_screen
*ss
= svga_screen(pipe
->screen
);
60 struct svga_buffer
*sbuf
= svga_buffer(buf
);
64 * The screen may cache buffer writes, but when we map, we map out
65 * of those cached writes, so we don't need to set a
66 * PIPE_REFERENCED_FOR_WRITE flag for cached buffers.
69 if (!sbuf
->handle
|| ss
->sws
->surface_is_flushed(ss
->sws
, sbuf
->handle
))
70 return PIPE_UNREFERENCED
;
73 * sws->surface_is_flushed() does not distinguish between read references
74 * and write references. So assume a reference is both,
75 * however, we make an exception for index- and vertex buffers, to avoid
76 * a flush in st_bufferobj_get_subdata, during display list replay.
79 if (sbuf
->b
.b
.bind
& (PIPE_BIND_VERTEX_BUFFER
| PIPE_BIND_INDEX_BUFFER
))
80 return PIPE_REFERENCED_FOR_READ
;
82 return PIPE_REFERENCED_FOR_READ
| PIPE_REFERENCED_FOR_WRITE
;
91 svga_buffer_map_range( struct pipe_screen
*screen
,
92 struct pipe_resource
*buf
,
97 struct svga_screen
*ss
= svga_screen(screen
);
98 struct svga_winsys_screen
*sws
= ss
->sws
;
99 struct svga_buffer
*sbuf
= svga_buffer( buf
);
102 if (!sbuf
->swbuf
&& !sbuf
->hwbuf
) {
103 if (svga_buffer_create_hw_storage(ss
, sbuf
) != PIPE_OK
) {
105 * We can't create a hardware buffer big enough, so create a malloc
109 debug_printf("%s: failed to allocate %u KB of DMA, "
110 "splitting DMA transfers\n",
112 (sbuf
->b
.b
.width0
+ 1023)/1024);
115 sbuf
->swbuf
= align_malloc(sbuf
->b
.b
.width0
, 16);
120 /* User/malloc buffer */
123 else if (sbuf
->hwbuf
) {
124 map
= sws
->buffer_map(sws
, sbuf
->hwbuf
, usage
);
133 if (usage
& PIPE_TRANSFER_WRITE
) {
134 assert(sbuf
->map
.count
<= 1);
135 sbuf
->map
.writing
= TRUE
;
136 if (usage
& PIPE_TRANSFER_FLUSH_EXPLICIT
)
137 sbuf
->map
.flush_explicit
= TRUE
;
147 svga_buffer_flush_mapped_range( struct pipe_screen
*screen
,
148 struct pipe_resource
*buf
,
149 unsigned offset
, unsigned length
)
151 struct svga_buffer
*sbuf
= svga_buffer( buf
);
152 struct svga_screen
*ss
= svga_screen(screen
);
154 pipe_mutex_lock(ss
->swc_mutex
);
155 assert(sbuf
->map
.writing
);
156 if(sbuf
->map
.writing
) {
157 assert(sbuf
->map
.flush_explicit
);
158 svga_buffer_add_range(sbuf
, offset
, offset
+ length
);
160 pipe_mutex_unlock(ss
->swc_mutex
);
164 svga_buffer_unmap( struct pipe_screen
*screen
,
165 struct pipe_resource
*buf
)
167 struct svga_screen
*ss
= svga_screen(screen
);
168 struct svga_winsys_screen
*sws
= ss
->sws
;
169 struct svga_buffer
*sbuf
= svga_buffer( buf
);
171 pipe_mutex_lock(ss
->swc_mutex
);
173 assert(sbuf
->map
.count
);
178 sws
->buffer_unmap(sws
, sbuf
->hwbuf
);
180 if(sbuf
->map
.writing
) {
181 if(!sbuf
->map
.flush_explicit
) {
182 /* No mapped range was flushed -- flush the whole buffer */
183 SVGA_DBG(DEBUG_DMA
, "flushing the whole buffer\n");
185 svga_buffer_add_range(sbuf
, 0, sbuf
->b
.b
.width0
);
188 sbuf
->map
.writing
= FALSE
;
189 sbuf
->map
.flush_explicit
= FALSE
;
192 pipe_mutex_unlock(ss
->swc_mutex
);
198 svga_buffer_destroy( struct pipe_screen
*screen
,
199 struct pipe_resource
*buf
)
201 struct svga_screen
*ss
= svga_screen(screen
);
202 struct svga_buffer
*sbuf
= svga_buffer( buf
);
204 assert(!p_atomic_read(&buf
->reference
.count
));
206 assert(!sbuf
->dma
.pending
);
209 svga_buffer_destroy_host_surface(ss
, sbuf
);
211 if(sbuf
->uploaded
.buffer
)
212 pipe_resource_reference(&sbuf
->uploaded
.buffer
, NULL
);
215 svga_buffer_destroy_hw_storage(ss
, sbuf
);
217 if(sbuf
->swbuf
&& !sbuf
->user
)
218 align_free(sbuf
->swbuf
);
224 /* Keep the original code more or less intact, implement transfers in
225 * terms of the old functions.
228 svga_buffer_transfer_map( struct pipe_context
*pipe
,
229 struct pipe_transfer
*transfer
)
231 uint8_t *map
= svga_buffer_map_range( pipe
->screen
,
239 /* map_buffer() returned a pointer to the beginning of the buffer,
240 * but transfers are expected to return a pointer to just the
241 * region specified in the box.
243 return map
+ transfer
->box
.x
;
248 static void svga_buffer_transfer_flush_region( struct pipe_context
*pipe
,
249 struct pipe_transfer
*transfer
,
250 const struct pipe_box
*box
)
252 assert(box
->x
+ box
->width
<= transfer
->box
.width
);
254 svga_buffer_flush_mapped_range(pipe
->screen
,
256 transfer
->box
.x
+ box
->x
,
260 static void svga_buffer_transfer_unmap( struct pipe_context
*pipe
,
261 struct pipe_transfer
*transfer
)
263 svga_buffer_unmap(pipe
->screen
,
273 struct u_resource_vtbl svga_buffer_vtbl
=
275 u_default_resource_get_handle
, /* get_handle */
276 svga_buffer_destroy
, /* resource_destroy */
277 svga_buffer_is_referenced
, /* is_resource_referenced */
278 u_default_get_transfer
, /* get_transfer */
279 u_default_transfer_destroy
, /* transfer_destroy */
280 svga_buffer_transfer_map
, /* transfer_map */
281 svga_buffer_transfer_flush_region
, /* transfer_flush_region */
282 svga_buffer_transfer_unmap
, /* transfer_unmap */
283 u_default_transfer_inline_write
/* transfer_inline_write */
288 struct pipe_resource
*
289 svga_buffer_create(struct pipe_screen
*screen
,
290 const struct pipe_resource
*template)
292 struct svga_screen
*ss
= svga_screen(screen
);
293 struct svga_buffer
*sbuf
;
295 sbuf
= CALLOC_STRUCT(svga_buffer
);
299 sbuf
->b
.b
= *template;
300 sbuf
->b
.vtbl
= &svga_buffer_vtbl
;
301 pipe_reference_init(&sbuf
->b
.b
.reference
, 1);
302 sbuf
->b
.b
.screen
= screen
;
304 if(svga_buffer_needs_hw_storage(template->bind
)) {
305 if(svga_buffer_create_host_surface(ss
, sbuf
) != PIPE_OK
)
309 sbuf
->swbuf
= align_malloc(template->width0
, 64);
314 debug_reference(&sbuf
->b
.b
.reference
,
315 (debug_reference_descriptor
)debug_describe_resource
, 0);
325 struct pipe_resource
*
326 svga_user_buffer_create(struct pipe_screen
*screen
,
331 struct svga_buffer
*sbuf
;
333 sbuf
= CALLOC_STRUCT(svga_buffer
);
337 pipe_reference_init(&sbuf
->b
.b
.reference
, 1);
338 sbuf
->b
.vtbl
= &svga_buffer_vtbl
;
339 sbuf
->b
.b
.screen
= screen
;
340 sbuf
->b
.b
.format
= PIPE_FORMAT_R8_UNORM
; /* ?? */
341 sbuf
->b
.b
.usage
= PIPE_USAGE_IMMUTABLE
;
342 sbuf
->b
.b
.bind
= bind
;
343 sbuf
->b
.b
.width0
= bytes
;
344 sbuf
->b
.b
.height0
= 1;
345 sbuf
->b
.b
.depth0
= 1;
346 sbuf
->b
.b
.array_size
= 1;
351 debug_reference(&sbuf
->b
.b
.reference
,
352 (debug_reference_descriptor
)debug_describe_resource
, 0);