From: Marek Olšák <marek.ol...@amd.com>

Notes:
- make sure the default size is large enough to handle all state trackers
- pipe wrappers don't receive transfer calls from stream_uploader, because
  pipe_context::stream_uploader points directly to the underlying driver's
  stream_uploader (to keep it simple for now)

v2: add error handling to nv50, nvc0, noop
v3: set const_uploader

Reviewed-by: Nicolai Hähnle <nicolai.haeh...@amd.com> (v2)
Tested-by: Edmondo Tommasina <edmondo.tommas...@gmail.com> (v1)
---
 src/gallium/drivers/ddebug/dd_context.c           |  2 ++
 src/gallium/drivers/etnaviv/etnaviv_context.c     |  8 ++++++++
 src/gallium/drivers/freedreno/freedreno_context.c |  9 +++++++++
 src/gallium/drivers/i915/i915_context.c           |  6 ++++++
 src/gallium/drivers/llvmpipe/lp_context.c         |  9 +++++++++
 src/gallium/drivers/noop/noop_pipe.c              | 13 +++++++++++++
 src/gallium/drivers/nouveau/nv30/nv30_context.c   | 11 +++++++++++
 src/gallium/drivers/nouveau/nv50/nv50_context.c   | 11 +++++++++++
 src/gallium/drivers/nouveau/nvc0/nvc0_context.c   | 10 ++++++++++
 src/gallium/drivers/r300/r300_context.c           |  4 +++-
 src/gallium/drivers/radeon/r600_pipe_common.c     |  2 ++
 src/gallium/drivers/rbug/rbug_context.c           |  2 ++
 src/gallium/drivers/softpipe/sp_context.c         |  8 ++++++++
 src/gallium/drivers/svga/svga_context.c           | 18 ++++++++++++++++++
 src/gallium/drivers/swr/swr_context.cpp           |  9 +++++++++
 src/gallium/drivers/trace/tr_context.c            |  2 ++
 src/gallium/drivers/vc4/vc4_context.c             | 11 ++++++-----
 src/gallium/drivers/virgl/virgl_context.c         |  2 ++
 18 files changed, 131 insertions(+), 6 deletions(-)

diff --git a/src/gallium/drivers/ddebug/dd_context.c 
b/src/gallium/drivers/ddebug/dd_context.c
index 0b1dfbb..ba47b73 100644
--- a/src/gallium/drivers/ddebug/dd_context.c
+++ b/src/gallium/drivers/ddebug/dd_context.c
@@ -756,20 +756,22 @@ dd_context_create(struct dd_screen *dscreen, struct 
pipe_context *pipe)
    if (!pipe)
       return NULL;
 
    dctx = CALLOC_STRUCT(dd_context);
    if (!dctx)
       goto fail;
 
    dctx->pipe = pipe;
    dctx->base.priv = pipe->priv; /* expose wrapped priv data */
    dctx->base.screen = &dscreen->base;
+   dctx->base.stream_uploader = pipe->stream_uploader;
+   dctx->base.const_uploader = pipe->const_uploader;
 
    dctx->base.destroy = dd_context_destroy;
 
    CTX_INIT(render_condition);
    CTX_INIT(create_query);
    CTX_INIT(create_batch_query);
    CTX_INIT(destroy_query);
    CTX_INIT(begin_query);
    CTX_INIT(end_query);
    CTX_INIT(get_query_result);
diff --git a/src/gallium/drivers/etnaviv/etnaviv_context.c 
b/src/gallium/drivers/etnaviv/etnaviv_context.c
index d767cd1..c69283e 100644
--- a/src/gallium/drivers/etnaviv/etnaviv_context.c
+++ b/src/gallium/drivers/etnaviv/etnaviv_context.c
@@ -42,34 +42,38 @@
 #include "etnaviv_texture.h"
 #include "etnaviv_transfer.h"
 #include "etnaviv_translate.h"
 #include "etnaviv_zsa.h"
 
 #include "pipe/p_context.h"
 #include "pipe/p_state.h"
 #include "util/u_blitter.h"
 #include "util/u_memory.h"
 #include "util/u_prim.h"
+#include "util/u_upload_mgr.h"
 
 #include "hw/common.xml.h"
 
 static void
 etna_context_destroy(struct pipe_context *pctx)
 {
    struct etna_context *ctx = etna_context(pctx);
 
    if (ctx->primconvert)
       util_primconvert_destroy(ctx->primconvert);
 
    if (ctx->blitter)
       util_blitter_destroy(ctx->blitter);
 
+   if (pctx->stream_uploader)
+      u_upload_destroy(pctx->stream_uploader);
+
    if (ctx->stream)
       etna_cmd_stream_del(ctx->stream);
 
    slab_destroy_child(&ctx->transfer_pool);
 
    FREE(pctx);
 }
 
 /* Update render state where needed based on draw operation */
 static void
@@ -257,20 +261,24 @@ etna_context_create(struct pipe_screen *pscreen, void 
*priv, unsigned flags)
       return NULL;
 
    screen = etna_screen(pscreen);
    ctx->stream = etna_cmd_stream_new(screen->pipe, 0x2000, 
&etna_cmd_stream_reset_notify, ctx);
    if (ctx->stream == NULL)
       goto fail;
 
    pctx = &ctx->base;
    pctx->priv = ctx;
    pctx->screen = pscreen;
+   pctx->stream_uploader = u_upload_create_default(pctx);
+   if (!pctx->stream_uploader)
+      goto fail;
+   pctx->const_uploader = pctx->stream_uploader;
 
    /* context ctxate setup */
    ctx->specs = screen->specs;
    ctx->screen = screen;
    /* need some sane default in case state tracker doesn't set some state: */
    ctx->sample_mask = 0xffff;
 
    list_inithead(&ctx->used_resources);
 
    /*  Set sensible defaults for state */
diff --git a/src/gallium/drivers/freedreno/freedreno_context.c 
b/src/gallium/drivers/freedreno/freedreno_context.c
index 348cc60..4d8c425 100644
--- a/src/gallium/drivers/freedreno/freedreno_context.c
+++ b/src/gallium/drivers/freedreno/freedreno_context.c
@@ -30,20 +30,21 @@
 #include "freedreno_draw.h"
 #include "freedreno_fence.h"
 #include "freedreno_program.h"
 #include "freedreno_resource.h"
 #include "freedreno_texture.h"
 #include "freedreno_state.h"
 #include "freedreno_gmem.h"
 #include "freedreno_query.h"
 #include "freedreno_query_hw.h"
 #include "freedreno_util.h"
+#include "util/u_upload_mgr.h"
 
 static void
 fd_context_flush(struct pipe_context *pctx, struct pipe_fence_handle **fence,
                unsigned flags)
 {
        struct fd_context *ctx = fd_context(pctx);
 
        if (flags & PIPE_FLUSH_FENCE_FD)
                ctx->batch->needs_out_fence_fd = true;
 
@@ -118,20 +119,23 @@ fd_context_destroy(struct pipe_context *pctx)
        fd_bc_invalidate_context(ctx);
 
        fd_fence_ref(pctx->screen, &ctx->last_fence, NULL);
 
        fd_prog_fini(pctx);
        fd_hw_query_fini(pctx);
 
        if (ctx->blitter)
                util_blitter_destroy(ctx->blitter);
 
+       if (pctx->stream_uploader)
+               u_upload_destroy(pctx->stream_uploader);
+
        if (ctx->clear_rs_state)
                pctx->delete_rasterizer_state(pctx, ctx->clear_rs_state);
 
        if (ctx->primconvert)
                util_primconvert_destroy(ctx->primconvert);
 
        slab_destroy_child(&ctx->transfer_pool);
 
        for (i = 0; i < ARRAY_SIZE(ctx->pipe); i++) {
                struct fd_vsc_pipe *pipe = &ctx->pipe[i];
@@ -262,20 +266,25 @@ fd_context_init(struct fd_context *ctx, struct 
pipe_screen *pscreen,
 
        pctx = &ctx->base;
        pctx->screen = pscreen;
        pctx->priv = priv;
        pctx->flush = fd_context_flush;
        pctx->emit_string_marker = fd_emit_string_marker;
        pctx->set_debug_callback = fd_set_debug_callback;
        pctx->create_fence_fd = fd_create_fence_fd;
        pctx->fence_server_sync = fd_fence_server_sync;
 
+       pctx->stream_uploader = u_upload_create_default(pctx);
+       if (!pctx->stream_uploader)
+               goto fail;
+       pctx->const_uploader = pctx->stream_uploader;
+
        /* TODO what about compute?  Ideally it creates it's own independent
         * batches per compute job (since it isn't using tiling, so no point
         * in getting involved with the re-ordering madness)..
         */
        if (!screen->reorder) {
                ctx->batch = fd_bc_alloc_batch(&screen->batch_cache, ctx);
        }
 
        slab_create_child(&ctx->transfer_pool, &screen->transfer_pool);
 
diff --git a/src/gallium/drivers/i915/i915_context.c 
b/src/gallium/drivers/i915/i915_context.c
index f3324db..6664cfc 100644
--- a/src/gallium/drivers/i915/i915_context.c
+++ b/src/gallium/drivers/i915/i915_context.c
@@ -30,20 +30,21 @@
 #include "i915_screen.h"
 #include "i915_surface.h"
 #include "i915_query.h"
 #include "i915_batch.h"
 #include "i915_resource.h"
 
 #include "draw/draw_context.h"
 #include "pipe/p_defines.h"
 #include "util/u_inlines.h"
 #include "util/u_memory.h"
+#include "util/u_upload_mgr.h"
 #include "pipe/p_screen.h"
 
 
 DEBUG_GET_ONCE_BOOL_OPTION(i915_no_vbuf, "I915_NO_VBUF", FALSE)
 
 
 /*
  * Draw functions
  */
 
@@ -130,20 +131,23 @@ i915_draw_vbo(struct pipe_context *pipe, const struct 
pipe_draw_info *info)
 static void i915_destroy(struct pipe_context *pipe)
 {
    struct i915_context *i915 = i915_context(pipe);
    int i;
 
    if (i915->blitter)
       util_blitter_destroy(i915->blitter);
 
    draw_destroy(i915->draw);
 
+   if (i915->base.stream_uploader)
+      u_upload_destroy(i915->base.stream_uploader);
+
    if(i915->batch)
       i915->iws->batchbuffer_destroy(i915->batch);
 
    /* unbind framebuffer */
    for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) {
       pipe_surface_reference(&i915->framebuffer.cbufs[i], NULL);
    }
    pipe_surface_reference(&i915->framebuffer.zsbuf, NULL);
 
    /* unbind constant buffers */
@@ -159,20 +163,22 @@ i915_create_context(struct pipe_screen *screen, void 
*priv, unsigned flags)
 {
    struct i915_context *i915;
 
    i915 = CALLOC_STRUCT(i915_context);
    if (!i915)
       return NULL;
 
    i915->iws = i915_screen(screen)->iws;
    i915->base.screen = screen;
    i915->base.priv = priv;
+   i915->base.stream_uploader = u_upload_create_default(&i915->base);
+   i915->base.const_uploader = i915->base.stream_uploader;
 
    i915->base.destroy = i915_destroy;
 
    if (i915_screen(screen)->debug.use_blitter)
       i915->base.clear = i915_clear_blitter;
    else
       i915->base.clear = i915_clear_render;
 
    i915->base.draw_vbo = i915_draw_vbo;
 
diff --git a/src/gallium/drivers/llvmpipe/lp_context.c 
b/src/gallium/drivers/llvmpipe/lp_context.c
index 84912c6..9a1a7b9 100644
--- a/src/gallium/drivers/llvmpipe/lp_context.c
+++ b/src/gallium/drivers/llvmpipe/lp_context.c
@@ -30,20 +30,21 @@
  *    Keith Whitwell <kei...@vmware.com>
  */
 
 #include "draw/draw_context.h"
 #include "draw/draw_vbuf.h"
 #include "pipe/p_defines.h"
 #include "util/u_inlines.h"
 #include "util/u_math.h"
 #include "util/u_memory.h"
 #include "util/simple_list.h"
+#include "util/u_upload_mgr.h"
 #include "lp_clear.h"
 #include "lp_context.h"
 #include "lp_flush.h"
 #include "lp_perf.h"
 #include "lp_state.h"
 #include "lp_surface.h"
 #include "lp_query.h"
 #include "lp_setup.h"
 
 /* This is only safe if there's just one concurrent context */
@@ -55,20 +56,23 @@ static void llvmpipe_destroy( struct pipe_context *pipe )
 {
    struct llvmpipe_context *llvmpipe = llvmpipe_context( pipe );
    uint i, j;
 
    lp_print_counters();
 
    if (llvmpipe->blitter) {
       util_blitter_destroy(llvmpipe->blitter);
    }
 
+   if (llvmpipe->pipe.stream_uploader)
+      u_upload_destroy(llvmpipe->pipe.stream_uploader);
+
    /* This will also destroy llvmpipe->setup:
     */
    if (llvmpipe->draw)
       draw_destroy( llvmpipe->draw );
 
    for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) {
       pipe_surface_reference(&llvmpipe->framebuffer.cbufs[i], NULL);
    }
 
    pipe_surface_reference(&llvmpipe->framebuffer.zsbuf, NULL);
@@ -188,20 +192,25 @@ llvmpipe_create_context(struct pipe_screen *screen, void 
*priv,
    if (!llvmpipe->draw)
       goto fail;
 
    /* FIXME: devise alternative to draw_texture_samplers */
 
    llvmpipe->setup = lp_setup_create( &llvmpipe->pipe,
                                       llvmpipe->draw );
    if (!llvmpipe->setup)
       goto fail;
 
+   llvmpipe->pipe.stream_uploader = u_upload_create_default(&llvmpipe->pipe);
+   if (!llvmpipe->pipe.stream_uploader)
+      goto fail;
+   llvmpipe->pipe.const_uploader = llvmpipe->pipe.stream_uploader;
+
    llvmpipe->blitter = util_blitter_create(&llvmpipe->pipe);
    if (!llvmpipe->blitter) {
       goto fail;
    }
 
    /* must be done before installing Draw stages */
    util_blitter_cache_all_shaders(llvmpipe->blitter);
 
    /* plug in AA line/point stages */
    draw_install_aaline_stage(llvmpipe->draw, &llvmpipe->pipe);
diff --git a/src/gallium/drivers/noop/noop_pipe.c 
b/src/gallium/drivers/noop/noop_pipe.c
index 3013019..db2375e 100644
--- a/src/gallium/drivers/noop/noop_pipe.c
+++ b/src/gallium/drivers/noop/noop_pipe.c
@@ -22,20 +22,21 @@
  */
 #include <stdio.h>
 #include <errno.h>
 #include "pipe/p_defines.h"
 #include "pipe/p_state.h"
 #include "pipe/p_context.h"
 #include "pipe/p_screen.h"
 #include "util/u_memory.h"
 #include "util/u_inlines.h"
 #include "util/u_format.h"
+#include "util/u_upload_mgr.h"
 #include "noop_public.h"
 
 DEBUG_GET_ONCE_BOOL_OPTION(noop, "GALLIUM_NOOP", FALSE)
 
 void noop_init_state_functions(struct pipe_context *ctx);
 
 struct noop_pipe_screen {
    struct pipe_screen  pscreen;
    struct pipe_screen  *oscreen;
 };
@@ -282,20 +283,23 @@ noop_flush_resource(struct pipe_context *ctx,
 static void noop_flush(struct pipe_context *ctx,
                        struct pipe_fence_handle **fence,
                        unsigned flags)
 {
    if (fence)
       *fence = NULL;
 }
 
 static void noop_destroy_context(struct pipe_context *ctx)
 {
+   if (ctx->stream_uploader)
+      u_upload_destroy(ctx->stream_uploader);
+
    FREE(ctx);
 }
 
 static boolean noop_generate_mipmap(struct pipe_context *ctx,
                                     struct pipe_resource *resource,
                                     enum pipe_format format,
                                     unsigned base_level,
                                     unsigned last_level,
                                     unsigned first_layer,
                                     unsigned last_layer)
@@ -303,22 +307,31 @@ static boolean noop_generate_mipmap(struct pipe_context 
*ctx,
    return true;
 }
 
 static struct pipe_context *noop_create_context(struct pipe_screen *screen,
                                                 void *priv, unsigned flags)
 {
    struct pipe_context *ctx = CALLOC_STRUCT(pipe_context);
 
    if (!ctx)
       return NULL;
+
    ctx->screen = screen;
    ctx->priv = priv;
+
+   ctx->stream_uploader = u_upload_create_default(ctx);
+   if (!ctx->stream_uploader) {
+      FREE(ctx);
+      return NULL;
+   }
+   ctx->const_uploader = ctx->stream_uploader;
+
    ctx->destroy = noop_destroy_context;
    ctx->flush = noop_flush;
    ctx->clear = noop_clear;
    ctx->clear_render_target = noop_clear_render_target;
    ctx->clear_depth_stencil = noop_clear_depth_stencil;
    ctx->resource_copy_region = noop_resource_copy_region;
    ctx->generate_mipmap = noop_generate_mipmap;
    ctx->blit = noop_blit;
    ctx->flush_resource = noop_flush_resource;
    ctx->create_query = noop_create_query;
diff --git a/src/gallium/drivers/nouveau/nv30/nv30_context.c 
b/src/gallium/drivers/nouveau/nv30/nv30_context.c
index 3ed0889..716d2bb 100644
--- a/src/gallium/drivers/nouveau/nv30/nv30_context.c
+++ b/src/gallium/drivers/nouveau/nv30/nv30_context.c
@@ -17,20 +17,21 @@
  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  * OTHER DEALINGS IN THE SOFTWARE.
  *
  * Authors: Ben Skeggs
  *
  */
 
 #include "draw/draw_context.h"
+#include "util/u_upload_mgr.h"
 
 #include "nv_object.xml.h"
 #include "nv30/nv30-40_3d.xml.h"
 
 #include "nouveau_fence.h"
 #include "nv30/nv30_context.h"
 #include "nv30/nv30_transfer.h"
 #include "nv30/nv30_state.h"
 
 static void
@@ -158,20 +159,23 @@ static void
 nv30_context_destroy(struct pipe_context *pipe)
 {
    struct nv30_context *nv30 = nv30_context(pipe);
 
    if (nv30->blitter)
       util_blitter_destroy(nv30->blitter);
 
    if (nv30->draw)
       draw_destroy(nv30->draw);
 
+   if (nv30->base.pipe.stream_uploader)
+      u_upload_destroy(nv30->base.pipe.stream_uploader);
+
    if (nv30->blit_vp)
       nouveau_heap_free(&nv30->blit_vp);
 
    if (nv30->blit_fp)
       pipe_resource_reference(&nv30->blit_fp, NULL);
 
    if (nv30->screen->base.pushbuf->user_priv == &nv30->bufctx)
       nv30->screen->base.pushbuf->user_priv = NULL;
 
    nouveau_bufctx_del(&nv30->bufctx);
@@ -198,20 +202,27 @@ nv30_context_create(struct pipe_screen *pscreen, void 
*priv, unsigned ctxflags)
    struct pipe_context *pipe;
    int ret;
 
    if (!nv30)
       return NULL;
 
    nv30->screen = screen;
    nv30->base.screen = &screen->base;
    nv30->base.copy_data = nv30_transfer_copy_data;
 
+   nv30->base.pipe.stream_uploader = u_upload_create_default(&nv30->base.pipe);
+   if (!nv30->base.pipe.stream_uploader) {
+      nv30_context_destroy(pipe);
+      return NULL;
+   }
+   nv30->base.pipe.const_uploader = nv30->base.pipe.stream_uploader;
+
    pipe = &nv30->base.pipe;
    pipe->screen = pscreen;
    pipe->priv = priv;
    pipe->destroy = nv30_context_destroy;
    pipe->flush = nv30_context_flush;
 
    /*XXX: *cough* per-context client */
    nv30->base.client = screen->base.client;
 
    /*XXX: *cough* per-context pushbufs */
diff --git a/src/gallium/drivers/nouveau/nv50/nv50_context.c 
b/src/gallium/drivers/nouveau/nv50/nv50_context.c
index ece7da9..bf768bc 100644
--- a/src/gallium/drivers/nouveau/nv50/nv50_context.c
+++ b/src/gallium/drivers/nouveau/nv50/nv50_context.c
@@ -15,20 +15,21 @@
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  * OTHER DEALINGS IN THE SOFTWARE.
  */
 
 #include "pipe/p_defines.h"
 #include "util/u_framebuffer.h"
+#include "util/u_upload_mgr.h"
 
 #include "nv50/nv50_context.h"
 #include "nv50/nv50_screen.h"
 #include "nv50/nv50_resource.h"
 
 static void
 nv50_flush(struct pipe_context *pipe,
            struct pipe_fence_handle **fence,
            unsigned flags)
 {
@@ -169,20 +170,24 @@ nv50_context_unreference_resources(struct nv50_context 
*nv50)
 static void
 nv50_destroy(struct pipe_context *pipe)
 {
    struct nv50_context *nv50 = nv50_context(pipe);
 
    if (nv50->screen->cur_ctx == nv50) {
       nv50->screen->cur_ctx = NULL;
       /* Save off the state in case another context gets created */
       nv50->screen->save_state = nv50->state;
    }
+
+   if (nv50->base.pipe.stream_uploader)
+      u_upload_destroy(nv50->base.pipe.stream_uploader);
+
    nouveau_pushbuf_bufctx(nv50->base.pushbuf, NULL);
    nouveau_pushbuf_kick(nv50->base.pushbuf, nv50->base.pushbuf->channel);
 
    nv50_context_unreference_resources(nv50);
 
    FREE(nv50->blit);
 
    nouveau_context_destroy(&nv50->base);
 }
 
@@ -308,20 +313,24 @@ nv50_create(struct pipe_screen *pscreen, void *priv, 
unsigned ctxflags)
       goto out_err;
 
    nv50->base.screen    = &screen->base;
    nv50->base.copy_data = nv50_m2mf_copy_linear;
    nv50->base.push_data = nv50_sifc_linear_u8;
    nv50->base.push_cb   = nv50_cb_push;
 
    nv50->screen = screen;
    pipe->screen = pscreen;
    pipe->priv = priv;
+   pipe->stream_uploader = u_upload_create_default(pipe);
+   if (!pipe->stream_uploader)
+      goto out_err;
+   pipe->const_uploader = pipe->stream_uploader;
 
    pipe->destroy = nv50_destroy;
 
    pipe->draw_vbo = nv50_draw_vbo;
    pipe->clear = nv50_clear;
    pipe->launch_grid = nv50_launch_grid;
 
    pipe->flush = nv50_flush;
    pipe->texture_barrier = nv50_texture_barrier;
    pipe->memory_barrier = nv50_memory_barrier;
@@ -380,20 +389,22 @@ nv50_create(struct pipe_screen *pscreen, void *priv, 
unsigned ctxflags)
    if (screen->compute)
       BCTX_REFN_bo(nv50->bufctx_cp, CP_SCREEN, flags, screen->fence.bo);
 
    nv50->base.scratch.bo_size = 2 << 20;
 
    util_dynarray_init(&nv50->global_residents);
 
    return pipe;
 
 out_err:
+   if (pipe->stream_uploader)
+      u_upload_destroy(pipe->stream_uploader);
    if (nv50->bufctx_3d)
       nouveau_bufctx_del(&nv50->bufctx_3d);
    if (nv50->bufctx_cp)
       nouveau_bufctx_del(&nv50->bufctx_cp);
    if (nv50->bufctx)
       nouveau_bufctx_del(&nv50->bufctx);
    FREE(nv50->blit);
    FREE(nv50);
    return NULL;
 }
diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_context.c 
b/src/gallium/drivers/nouveau/nvc0/nvc0_context.c
index 8f2b974..d0f4da3 100644
--- a/src/gallium/drivers/nouveau/nvc0/nvc0_context.c
+++ b/src/gallium/drivers/nouveau/nvc0/nvc0_context.c
@@ -15,20 +15,21 @@
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  * OTHER DEALINGS IN THE SOFTWARE.
  */
 
 #include "pipe/p_defines.h"
 #include "util/u_framebuffer.h"
+#include "util/u_upload_mgr.h"
 
 #include "nvc0/nvc0_context.h"
 #include "nvc0/nvc0_screen.h"
 #include "nvc0/nvc0_resource.h"
 
 static void
 nvc0_flush(struct pipe_context *pipe,
            struct pipe_fence_handle **fence,
            unsigned flags)
 {
@@ -192,20 +193,23 @@ static void
 nvc0_destroy(struct pipe_context *pipe)
 {
    struct nvc0_context *nvc0 = nvc0_context(pipe);
 
    if (nvc0->screen->cur_ctx == nvc0) {
       nvc0->screen->cur_ctx = NULL;
       nvc0->screen->save_state = nvc0->state;
       nvc0->screen->save_state.tfb = NULL;
    }
 
+   if (nvc0->base.pipe.stream_uploader)
+      u_upload_destroy(nvc0->base.pipe.stream_uploader);
+
    /* Unset bufctx, we don't want to revalidate any resources after the flush.
     * Other contexts will always set their bufctx again on action calls.
     */
    nouveau_pushbuf_bufctx(nvc0->base.pushbuf, NULL);
    nouveau_pushbuf_kick(nvc0->base.pushbuf, nvc0->base.pushbuf->channel);
 
    nvc0_context_unreference_resources(nvc0);
    nvc0_blitctx_destroy(nvc0);
 
    nouveau_context_destroy(&nvc0->base);
@@ -379,20 +383,24 @@ nvc0_create(struct pipe_screen *pscreen, void *priv, 
unsigned ctxflags)
       ret = nouveau_bufctx_new(screen->base.client, NVC0_BIND_CP_COUNT,
                                &nvc0->bufctx_cp);
    if (ret)
       goto out_err;
 
    nvc0->screen = screen;
    nvc0->base.screen = &screen->base;
 
    pipe->screen = pscreen;
    pipe->priv = priv;
+   pipe->stream_uploader = u_upload_create_default(pipe);
+   if (!pipe->stream_uploader)
+      goto out_err;
+   pipe->const_uploader = pipe->stream_uploader;
 
    pipe->destroy = nvc0_destroy;
 
    pipe->draw_vbo = nvc0_draw_vbo;
    pipe->clear = nvc0_clear;
    pipe->launch_grid = (nvc0->screen->base.class_3d >= NVE4_3D_CLASS) ?
       nve4_launch_grid : nvc0_launch_grid;
 
    pipe->flush = nvc0_flush;
    pipe->texture_barrier = nvc0_texture_barrier;
@@ -465,20 +473,22 @@ nvc0_create(struct pipe_screen *pscreen, void *priv, 
unsigned ctxflags)
    nvc0->base.scratch.bo_size = 2 << 20;
 
    memset(nvc0->tex_handles, ~0, sizeof(nvc0->tex_handles));
 
    util_dynarray_init(&nvc0->global_residents);
 
    return pipe;
 
 out_err:
    if (nvc0) {
+      if (pipe->stream_uploader)
+         u_upload_destroy(pipe->stream_uploader);
       if (nvc0->bufctx_3d)
          nouveau_bufctx_del(&nvc0->bufctx_3d);
       if (nvc0->bufctx_cp)
          nouveau_bufctx_del(&nvc0->bufctx_cp);
       if (nvc0->bufctx)
          nouveau_bufctx_del(&nvc0->bufctx);
       FREE(nvc0->blit);
       FREE(nvc0);
    }
    return NULL;
diff --git a/src/gallium/drivers/r300/r300_context.c 
b/src/gallium/drivers/r300/r300_context.c
index b914cdb..02af5d7 100644
--- a/src/gallium/drivers/r300/r300_context.c
+++ b/src/gallium/drivers/r300/r300_context.c
@@ -417,22 +417,24 @@ struct pipe_context* r300_create_context(struct 
pipe_screen* screen,
     r300_init_flush_functions(r300);
     r300_init_query_functions(r300);
     r300_init_state_functions(r300);
     r300_init_resource_functions(r300);
     r300_init_render_functions(r300);
     r300_init_states(&r300->context);
 
     r300->context.create_video_codec = vl_create_decoder;
     r300->context.create_video_buffer = vl_video_buffer_create;
 
-    r300->uploader = u_upload_create(&r300->context, 256 * 1024,
+    r300->uploader = u_upload_create(&r300->context, 1024 * 1024,
                                      PIPE_BIND_CUSTOM, PIPE_USAGE_STREAM);
+    r300->context.stream_uploader = r300->uploader;
+    r300->context.const_uploader = r300->uploader;
 
     r300->blitter = util_blitter_create(&r300->context);
     if (r300->blitter == NULL)
         goto fail;
     r300->blitter->draw_rectangle = r300_blitter_draw_rectangle;
 
     /* The KIL opcode needs the first texture unit to be enabled
      * on r3xx-r4xx. In order to calm down the CS checker, we bind this
      * dummy texture there. */
     if (!r300->screen->caps.is_r500) {
diff --git a/src/gallium/drivers/radeon/r600_pipe_common.c 
b/src/gallium/drivers/radeon/r600_pipe_common.c
index 95a6a48..732f5c3 100644
--- a/src/gallium/drivers/radeon/r600_pipe_common.c
+++ b/src/gallium/drivers/radeon/r600_pipe_common.c
@@ -599,20 +599,22 @@ bool r600_common_context_init(struct r600_common_context 
*rctx,
                u_suballocator_create(&rctx->b, rscreen->info.gart_page_size,
                                      0, PIPE_USAGE_DEFAULT, true);
        if (!rctx->allocator_zeroed_memory)
                return false;
 
        rctx->uploader = u_upload_create(&rctx->b, 1024 * 1024,
                                        PIPE_BIND_INDEX_BUFFER |
                                        PIPE_BIND_CONSTANT_BUFFER, 
PIPE_USAGE_STREAM);
        if (!rctx->uploader)
                return false;
+       rctx->b.stream_uploader = rctx->uploader;
+       rctx->b.const_uploader = rctx->uploader;
 
        rctx->ctx = rctx->ws->ctx_create(rctx->ws);
        if (!rctx->ctx)
                return false;
 
        if (rscreen->info.has_sdma && !(rscreen->debug_flags & 
DBG_NO_ASYNC_DMA)) {
                rctx->dma.cs = rctx->ws->cs_create(rctx->ctx, RING_DMA,
                                                   r600_flush_dma_ring,
                                                   rctx);
                rctx->dma.flush = r600_flush_dma_ring;
diff --git a/src/gallium/drivers/rbug/rbug_context.c 
b/src/gallium/drivers/rbug/rbug_context.c
index b08acfa..1dd0f6d 100644
--- a/src/gallium/drivers/rbug/rbug_context.c
+++ b/src/gallium/drivers/rbug/rbug_context.c
@@ -1205,20 +1205,22 @@ rbug_context_create(struct pipe_screen *_screen, struct 
pipe_context *pipe)
 
    pipe_mutex_init(rb_pipe->draw_mutex);
    pipe_condvar_init(rb_pipe->draw_cond);
    pipe_mutex_init(rb_pipe->call_mutex);
    pipe_mutex_init(rb_pipe->list_mutex);
    make_empty_list(&rb_pipe->shaders);
 
    rb_pipe->base.screen = _screen;
    rb_pipe->base.priv = pipe->priv; /* expose wrapped data */
    rb_pipe->base.draw = NULL;
+   rb_pipe->base.stream_uploader = pipe->stream_uploader;
+   rb_pipe->base.const_uploader = pipe->const_uploader;
 
    rb_pipe->base.destroy = rbug_destroy;
    rb_pipe->base.draw_vbo = rbug_draw_vbo;
    rb_pipe->base.create_query = rbug_create_query;
    rb_pipe->base.destroy_query = rbug_destroy_query;
    rb_pipe->base.begin_query = rbug_begin_query;
    rb_pipe->base.end_query = rbug_end_query;
    rb_pipe->base.get_query_result = rbug_get_query_result;
    rb_pipe->base.set_active_query_state = rbug_set_active_query_state;
    rb_pipe->base.create_blend_state = rbug_create_blend_state;
diff --git a/src/gallium/drivers/softpipe/sp_context.c 
b/src/gallium/drivers/softpipe/sp_context.c
index 323f74f..0597301 100644
--- a/src/gallium/drivers/softpipe/sp_context.c
+++ b/src/gallium/drivers/softpipe/sp_context.c
@@ -30,20 +30,21 @@
  *    Keith Whitwell <kei...@vmware.com>
  */
 
 #include "draw/draw_context.h"
 #include "draw/draw_vbuf.h"
 #include "pipe/p_defines.h"
 #include "util/u_math.h"
 #include "util/u_memory.h"
 #include "util/u_pstipple.h"
 #include "util/u_inlines.h"
+#include "util/u_upload_mgr.h"
 #include "tgsi/tgsi_exec.h"
 #include "sp_buffer.h"
 #include "sp_clear.h"
 #include "sp_context.h"
 #include "sp_flush.h"
 #include "sp_prim_vbuf.h"
 #include "sp_state.h"
 #include "sp_surface.h"
 #include "sp_tile_cache.h"
 #include "sp_tex_tile_cache.h"
@@ -79,20 +80,23 @@ softpipe_destroy( struct pipe_context *pipe )
 
    if (softpipe->quad.depth_test)
       softpipe->quad.depth_test->destroy( softpipe->quad.depth_test );
 
    if (softpipe->quad.blend)
       softpipe->quad.blend->destroy( softpipe->quad.blend );
 
    if (softpipe->quad.pstipple)
       softpipe->quad.pstipple->destroy( softpipe->quad.pstipple );
 
+   if (softpipe->pipe.stream_uploader)
+      u_upload_destroy(softpipe->pipe.stream_uploader);
+
    for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) {
       sp_destroy_tile_cache(softpipe->cbuf_cache[i]);
       pipe_surface_reference(&softpipe->framebuffer.cbufs[i], NULL);
    }
 
    sp_destroy_tile_cache(softpipe->zsbuf_cache);
    pipe_surface_reference(&softpipe->framebuffer.zsbuf, NULL);
 
    for (sh = 0; sh < ARRAY_SIZE(softpipe->tex_cache); sh++) {
       for (i = 0; i < ARRAY_SIZE(softpipe->tex_cache[0]); i++) {
@@ -260,20 +264,24 @@ softpipe_create_context(struct pipe_screen *screen,
    }
 
    softpipe->fs_machine = tgsi_exec_machine_create(PIPE_SHADER_FRAGMENT);
 
    /* setup quad rendering stages */
    softpipe->quad.shade = sp_quad_shade_stage(softpipe);
    softpipe->quad.depth_test = sp_quad_depth_test_stage(softpipe);
    softpipe->quad.blend = sp_quad_blend_stage(softpipe);
    softpipe->quad.pstipple = sp_quad_polygon_stipple_stage(softpipe);
 
+   softpipe->pipe.stream_uploader = u_upload_create_default(&softpipe->pipe);
+   if (!softpipe->pipe.stream_uploader)
+      goto fail;
+   softpipe->pipe.const_uploader = softpipe->pipe.stream_uploader;
 
    /*
     * Create drawing context and plug our rendering stage into it.
     */
    if (sp_screen->use_llvm)
       softpipe->draw = draw_create(&softpipe->pipe);
    else
       softpipe->draw = draw_create_no_llvm(&softpipe->pipe);
    if (!softpipe->draw) 
       goto fail;
diff --git a/src/gallium/drivers/svga/svga_context.c 
b/src/gallium/drivers/svga/svga_context.c
index d3f1801..ec86073 100644
--- a/src/gallium/drivers/svga/svga_context.c
+++ b/src/gallium/drivers/svga/svga_context.c
@@ -96,20 +96,22 @@ svga_destroy(struct pipe_context *pipe)
    util_bitmask_destroy(svga->ds_object_id_bm);
    util_bitmask_destroy(svga->input_element_object_id_bm);
    util_bitmask_destroy(svga->rast_object_id_bm);
    util_bitmask_destroy(svga->sampler_object_id_bm);
    util_bitmask_destroy(svga->sampler_view_id_bm);
    util_bitmask_destroy(svga->shader_id_bm);
    util_bitmask_destroy(svga->surface_view_id_bm);
    util_bitmask_destroy(svga->stream_output_id_bm);
    util_bitmask_destroy(svga->query_id_bm);
    u_upload_destroy(svga->const0_upload);
+   u_upload_destroy(svga->pipe.stream_uploader);
+   u_upload_destroy(svga->pipe.const_uploader);
    svga_texture_transfer_map_upload_destroy(svga);
 
    /* free user's constant buffers */
    for (shader = 0; shader < PIPE_SHADER_TYPES; ++shader) {
       for (i = 0; i < ARRAY_SIZE(svga->curr.constbufs[shader]); ++i) {
          pipe_resource_reference(&svga->curr.constbufs[shader][i].buffer, 
NULL);
       }
    }
 
    FREE(svga);
@@ -125,20 +127,32 @@ svga_context_create(struct pipe_screen *screen, void 
*priv, unsigned flags)
 
    svga = CALLOC_STRUCT(svga_context);
    if (!svga)
       goto cleanup;
 
    LIST_INITHEAD(&svga->dirty_buffers);
 
    svga->pipe.screen = screen;
    svga->pipe.priv = priv;
    svga->pipe.destroy = svga_destroy;
+   svga->pipe.stream_uploader = u_upload_create(&svga->pipe, 1024 * 1024,
+                                                PIPE_BIND_VERTEX_BUFFER |
+                                                PIPE_BIND_INDEX_BUFFER,
+                                                PIPE_USAGE_STREAM);
+   if (!svga->pipe.stream_uploader)
+      goto cleanup;
+
+   svga->pipe.const_uploader = u_upload_create(&svga->pipe, 128 * 1024,
+                                               PIPE_BIND_CONSTANT_BUFFER,
+                                               PIPE_USAGE_STREAM);
+   if (!svga->pipe.const_uploader)
+      goto cleanup;
 
    svga->swc = svgascreen->sws->context_create(svgascreen->sws);
    if (!svga->swc)
       goto cleanup;
 
    svga_init_resource_functions(svga);
    svga_init_blend_functions(svga);
    svga_init_blit_functions(svga);
    svga_init_depth_stencil_functions(svga);
    svga_init_draw_functions(svga);
@@ -276,20 +290,24 @@ svga_context_create(struct pipe_screen *screen, void 
*priv, unsigned flags)
    svga->dirty = ~0;
    svga->pred.query_id = SVGA3D_INVALID_ID;
 
    return &svga->pipe;
 
 cleanup:
    svga_destroy_swtnl(svga);
 
    if (svga->const0_upload)
       u_upload_destroy(svga->const0_upload);
+   if (svga->pipe.const_uploader)
+      u_upload_destroy(svga->pipe.const_uploader);
+   if (svga->pipe.stream_uploader)
+      u_upload_destroy(svga->pipe.stream_uploader);
    svga_texture_transfer_map_upload_destroy(svga);
    if (svga->hwtnl)
       svga_hwtnl_destroy(svga->hwtnl);
    if (svga->swc)
       svga->swc->destroy(svga->swc);
    util_bitmask_destroy(svga->blend_object_id_bm);
    util_bitmask_destroy(svga->ds_object_id_bm);
    util_bitmask_destroy(svga->input_element_object_id_bm);
    util_bitmask_destroy(svga->rast_object_id_bm);
    util_bitmask_destroy(svga->sampler_object_id_bm);
diff --git a/src/gallium/drivers/swr/swr_context.cpp 
b/src/gallium/drivers/swr/swr_context.cpp
index 8933085..2e37bac 100644
--- a/src/gallium/drivers/swr/swr_context.cpp
+++ b/src/gallium/drivers/swr/swr_context.cpp
@@ -26,20 +26,21 @@
 #include "swr_screen.h"
 #include "swr_resource.h"
 #include "swr_scratch.h"
 #include "swr_query.h"
 #include "swr_fence.h"
 
 #include "util/u_memory.h"
 #include "util/u_inlines.h"
 #include "util/u_format.h"
 #include "util/u_atomic.h"
+#include "util/u_upload_mgr.h"
 
 extern "C" {
 #include "util/u_transfer.h"
 #include "util/u_surface.h"
 }
 
 #include "api.h"
 #include "backend.h"
 
 static struct pipe_surface *
@@ -362,20 +363,23 @@ swr_destroy(struct pipe_context *pipe)
    pipe_surface_reference(&ctx->framebuffer.zsbuf, NULL);
 
    for (unsigned i = 0; i < ARRAY_SIZE(ctx->sampler_views[0]); i++) {
       
pipe_sampler_view_reference(&ctx->sampler_views[PIPE_SHADER_FRAGMENT][i], NULL);
    }
 
    for (unsigned i = 0; i < ARRAY_SIZE(ctx->sampler_views[0]); i++) {
       pipe_sampler_view_reference(&ctx->sampler_views[PIPE_SHADER_VERTEX][i], 
NULL);
    }
 
+   if (ctx->pipe.stream_uploader)
+      u_upload_destroy(ctx->pipe.stream_uploader);
+
    /* Idle core after destroying buffer resources, but before deleting
     * context.  Destroying resources has potentially called StoreTiles.*/
    SwrWaitForIdle(ctx->swrContext);
 
    if (ctx->swrContext)
       SwrDestroyContext(ctx->swrContext);
 
    delete ctx->blendJIT;
 
    swr_destroy_scratch_buffers(ctx);
@@ -486,20 +490,25 @@ swr_create_context(struct pipe_screen *p_screen, void 
*priv, unsigned flags)
    ctx->pipe.texture_subdata = u_default_texture_subdata;
 
    ctx->pipe.resource_copy_region = swr_resource_copy;
    ctx->pipe.render_condition = swr_render_condition;
 
    swr_state_init(&ctx->pipe);
    swr_clear_init(&ctx->pipe);
    swr_draw_init(&ctx->pipe);
    swr_query_init(&ctx->pipe);
 
+   ctx->pipe.stream_uploader = u_upload_create_default(&ctx->pipe);
+   if (!ctx->pipe.stream_uploader)
+      goto fail;
+   ctx->pipe.const_uploader = ctx->pipe.stream_uploader;
+
    ctx->pipe.blit = swr_blit;
    ctx->blitter = util_blitter_create(&ctx->pipe);
    if (!ctx->blitter)
       goto fail;
 
    swr_init_scratch_buffers(ctx);
 
    return &ctx->pipe;
 
 fail:
diff --git a/src/gallium/drivers/trace/tr_context.c 
b/src/gallium/drivers/trace/tr_context.c
index de03e29..f5939b1 100644
--- a/src/gallium/drivers/trace/tr_context.c
+++ b/src/gallium/drivers/trace/tr_context.c
@@ -1844,20 +1844,22 @@ trace_context_create(struct trace_screen *tr_scr,
 
    if (!trace_enabled())
       goto error1;
 
    tr_ctx = CALLOC_STRUCT(trace_context);
    if (!tr_ctx)
       goto error1;
 
    tr_ctx->base.priv = pipe->priv; /* expose wrapped priv data */
    tr_ctx->base.screen = &tr_scr->base;
+   tr_ctx->base.stream_uploader = pipe->stream_uploader;
+   tr_ctx->base.const_uploader = pipe->const_uploader;
 
    tr_ctx->base.destroy = trace_context_destroy;
 
 #define TR_CTX_INIT(_member) \
    tr_ctx->base . _member = pipe -> _member ? trace_context_ ## _member : NULL
 
    TR_CTX_INIT(draw_vbo);
    TR_CTX_INIT(render_condition);
    TR_CTX_INIT(create_query);
    TR_CTX_INIT(destroy_query);
diff --git a/src/gallium/drivers/vc4/vc4_context.c 
b/src/gallium/drivers/vc4/vc4_context.c
index 974df8a..401c160 100644
--- a/src/gallium/drivers/vc4/vc4_context.c
+++ b/src/gallium/drivers/vc4/vc4_context.c
@@ -137,33 +137,34 @@ vc4_context_create(struct pipe_screen *pscreen, void 
*priv, unsigned flags)
         vc4_state_init(pctx);
         vc4_program_init(pctx);
         vc4_query_init(pctx);
         vc4_resource_context_init(pctx);
 
         vc4_job_init(vc4);
 
         vc4->fd = screen->fd;
 
         slab_create_child(&vc4->transfer_pool, &screen->transfer_pool);
-        vc4->blitter = util_blitter_create(pctx);
+
+       vc4->uploader = u_upload_create_default(&vc4->base);
+       vc4->base.stream_uploader = vc4->uploader;
+       vc4->base.const_uploader = vc4->uploader;
+
+       vc4->blitter = util_blitter_create(pctx);
         if (!vc4->blitter)
                 goto fail;
 
         vc4->primconvert = util_primconvert_create(pctx,
                                                    (1 << PIPE_PRIM_QUADS) - 1);
         if (!vc4->primconvert)
                 goto fail;
 
-        vc4->uploader = u_upload_create(pctx, 16 * 1024,
-                                        PIPE_BIND_INDEX_BUFFER,
-                                        PIPE_USAGE_STREAM);
-
         vc4_debug |= saved_shaderdb_flag;
 
         vc4->sample_mask = (1 << VC4_MAX_SAMPLES) - 1;
 
         return &vc4->base;
 
 fail:
         pctx->destroy(pctx);
         return NULL;
 }
diff --git a/src/gallium/drivers/virgl/virgl_context.c 
b/src/gallium/drivers/virgl/virgl_context.c
index bda9515..2ee89d7 100644
--- a/src/gallium/drivers/virgl/virgl_context.c
+++ b/src/gallium/drivers/virgl/virgl_context.c
@@ -943,19 +943,21 @@ struct pipe_context *virgl_context_create(struct 
pipe_screen *pscreen,
    virgl_init_so_functions(vctx);
 
    list_inithead(&vctx->to_flush_bufs);
    slab_create_child(&vctx->texture_transfer_pool, &rs->texture_transfer_pool);
 
    vctx->primconvert = util_primconvert_create(&vctx->base, 
rs->caps.caps.v1.prim_mask);
    vctx->uploader = u_upload_create(&vctx->base, 1024 * 1024,
                                      PIPE_BIND_INDEX_BUFFER, 
PIPE_USAGE_STREAM);
    if (!vctx->uploader)
            goto fail;
+   vctx->base.stream_uploader = vctx->uploader;
+   vctx->base.const_uploader = vctx->uploader;
 
    vctx->hw_sub_ctx_id = rs->sub_ctx_id++;
    virgl_encoder_create_sub_ctx(vctx, vctx->hw_sub_ctx_id);
 
    virgl_encoder_set_sub_ctx(vctx, vctx->hw_sub_ctx_id);
    return &vctx->base;
 fail:
    return NULL;
 }
-- 
2.7.4

_______________________________________________
mesa-dev mailing list
mesa-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/mesa-dev

Reply via email to