for (i = 0; i < num_targets; i++) {
struct svga_stream_output_target *sot
= svga_stream_output_target(targets[i]);
- struct svga_buffer *sbuf = svga_buffer(sot->base.buffer);
unsigned size;
- assert(sbuf->key.flags & SVGA3D_SURFACE_BIND_STREAM_OUTPUT);
- (void) sbuf;
-
svga->so_surfaces[i] = svga_buffer_handle(svga, sot->base.buffer,
PIPE_BIND_STREAM_OUTPUT);
+
+ assert(svga_buffer(sot->base.buffer)->key.flags
+ & SVGA3D_SURFACE_BIND_STREAM_OUTPUT);
+
svga->so_targets[i] = &sot->base;
soBindings[i].offset = sot->base.buffer_offset;
if (svga_buffer_needs_hw_storage(bind_flags)) {
- /* If the buffer will be used for vertex/index/stream data, set all
- * the flags so that the buffer will be accepted for all those uses.
+ /* If the buffer will be used for vertex/index/stream data, set
+ * the vertex/index bind flags as well so that the buffer will be
+ * accepted for those uses.
* Note that the PIPE_BIND_ flags we get from the state tracker are
* just a hint about how the buffer may be used. And OpenGL buffer
* object may be used for many different things.
+ * Also note that we do not unconditionally set the streamout
+ * bind flag since streamout buffer is an output buffer and
+ * might have performance implication.
*/
if (!(template->bind & PIPE_BIND_CONSTANT_BUFFER)) {
- /* Not a constant buffer. The buffer may be used for vertex data,
- * indexes or stream-out.
+ /* Not a constant buffer. The buffer may be used for vertex data
+ * or indexes.
*/
bind_flags |= (PIPE_BIND_VERTEX_BUFFER |
PIPE_BIND_INDEX_BUFFER);
- if (ss->sws->have_vgpu10)
- bind_flags |= PIPE_BIND_STREAM_OUTPUT;
}
if (svga_buffer_create_host_surface(ss, sbuf, bind_flags) != PIPE_OK)
}
+/**
+ * Recreates a host surface with the new bind flags.
+ */
+enum pipe_error
+svga_buffer_recreate_host_surface(struct svga_context *svga,
+ struct svga_buffer *sbuf,
+ unsigned bind_flags)
+{
+ struct svga_screen *ss = svga_screen(sbuf->b.b.screen);
+ struct svga_winsys_surface *old_handle;
+ struct svga_host_surface_cache_key old_key;
+ enum pipe_error ret = PIPE_OK;
+
+ assert(sbuf->bind_flags != bind_flags);
+
+ /* Flush any pending upload first */
+ svga_buffer_upload_flush(svga, sbuf);
+
+ /* Save the old resource handle and key */
+ old_handle = sbuf->handle;
+ old_key = sbuf->key;
+ sbuf->handle = NULL;
+
+ /* Create a new resource with the required bind_flags */
+ ret = svga_buffer_create_host_surface(ss, sbuf, bind_flags);
+ if (ret == PIPE_OK) {
+ /* Copy the surface data */
+ assert(sbuf->handle);
+ ret = SVGA3D_vgpu10_BufferCopy(svga->swc, old_handle, sbuf->handle,
+ 0, 0, sbuf->b.b.width0);
+ if (ret != PIPE_OK) {
+ svga_context_flush(svga, NULL);
+ ret = SVGA3D_vgpu10_BufferCopy(svga->swc, old_handle, sbuf->handle,
+ 0, 0, sbuf->b.b.width0);
+ assert(ret == PIPE_OK);
+ }
+ }
+
+ /* Set the new bind flags for this buffer resource */
+ sbuf->bind_flags = bind_flags;
+
+ /* Destroy the old resource handle */
+ svga_screen_surface_destroy(ss, &old_key, &old_handle);
+
+ return ret;
+}
+
void
svga_buffer_destroy_host_surface(struct svga_screen *ss,
struct svga_buffer *sbuf)
assert(!sbuf->user);
- if (!sbuf->handle) {
+ if (sbuf->handle) {
+ if ((sbuf->bind_flags & tobind_flags) != tobind_flags) {
+ /* If the allocated resource's bind flags do not include the
+ * requested bind flags, create a new resource to include the
+ * new bind flags, and do a BufferCopy from the old resource to
+ * the new one.
+ */
+ assert(svga_have_vgpu10(svga));
+ ret = svga_buffer_recreate_host_surface(svga, sbuf,
+ sbuf->bind_flags|tobind_flags);
+ if (ret != PIPE_OK)
+ return NULL;
+ }
+ } else {
/* This call will set sbuf->handle */
if (svga_have_gb_objects(svga)) {
ret = svga_buffer_update_hw(svga, sbuf, sbuf->bind_flags);