dri/nouveau: Pipeline glTexSubImage texture transfers.
authorFrancisco Jerez <currojerez@riseup.net>
Fri, 29 Oct 2010 16:16:08 +0000 (18:16 +0200)
committerFrancisco Jerez <currojerez@riseup.net>
Sun, 31 Oct 2010 01:02:33 +0000 (02:02 +0100)
src/mesa/drivers/dri/nouveau/nouveau_texture.c
src/mesa/drivers/dri/nouveau/nouveau_texture.h

index 9254a9e7bec2d56c0d0d2b6d9bb0bb5007c11fcc..060c2c5bcc0a0ac88654a152e2cb06f5341cd1c2 100644 (file)
@@ -79,26 +79,65 @@ nouveau_teximage_free(struct gl_context *ctx, struct gl_texture_image *ti)
 }
 
 static void
-nouveau_teximage_map(struct gl_context *ctx, struct gl_texture_image *ti)
+nouveau_teximage_map(struct gl_context *ctx, struct gl_texture_image *ti,
+                    int access, int x, int y, int w, int h)
 {
-       struct nouveau_surface *s = &to_nouveau_teximage(ti)->surface;
-       int ret;
+       struct nouveau_teximage *nti = to_nouveau_teximage(ti);
+       struct nouveau_surface *s = &nti->surface;
+       struct nouveau_surface *st = &nti->transfer.surface;
 
        if (s->bo) {
-               ret = nouveau_bo_map(s->bo, NOUVEAU_BO_RDWR);
-               assert(!ret);
-
-               ti->Data = s->bo->map;
+               if (!(access & GL_MAP_READ_BIT) &&
+                   nouveau_bo_pending(s->bo)) {
+                       /*
+                        * Heuristic: use a bounce buffer to pipeline
+                        * teximage transfers.
+                        */
+                       st->layout = LINEAR;
+                       st->format = s->format;
+                       st->cpp = s->cpp;
+                       st->width = w;
+                       st->height = h;
+                       st->pitch = s->pitch;
+                       nti->transfer.x = x;
+                       nti->transfer.y = y;
+
+                       ti->Data = nouveau_get_scratch(ctx, st->pitch * h,
+                                                      &st->bo, &st->offset);
+
+               } else {
+                       int ret, flags = 0;
+
+                       if (access & GL_MAP_READ_BIT)
+                               flags |= NOUVEAU_BO_RD;
+                       if (access & GL_MAP_WRITE_BIT)
+                               flags |= NOUVEAU_BO_WR;
+
+                       ret = nouveau_bo_map(s->bo, flags);
+                       assert(!ret);
+
+                       ti->Data = s->bo->map + y * s->pitch + x * s->cpp;
+               }
        }
 }
 
 static void
 nouveau_teximage_unmap(struct gl_context *ctx, struct gl_texture_image *ti)
 {
-       struct nouveau_surface *s = &to_nouveau_teximage(ti)->surface;
+       struct nouveau_teximage *nti = to_nouveau_teximage(ti);
+       struct nouveau_surface *s = &nti->surface;
+       struct nouveau_surface *st = &nti->transfer.surface;
 
-       if (s->bo)
+       if (st->bo) {
+               context_drv(ctx)->surface_copy(ctx, s, st, nti->transfer.x,
+                                              nti->transfer.y, 0, 0,
+                                              st->width, st->height);
+               nouveau_surface_ref(NULL, st);
+
+       } else if (s->bo) {
                nouveau_bo_unmap(s->bo);
+       }
+
        ti->Data = NULL;
 }
 
@@ -361,7 +400,8 @@ nouveau_teximage(struct gl_context *ctx, GLint dims, GLenum target, GLint level,
                                             "glTexImage");
        if (pixels) {
                /* Store the pixel data. */
-               nouveau_teximage_map(ctx, ti);
+               nouveau_teximage_map(ctx, ti, GL_MAP_WRITE_BIT,
+                                    0, 0, width, height);
 
                ret = _mesa_texstore(ctx, dims, ti->_BaseFormat,
                                     ti->TexFormat, ti->Data,
@@ -448,13 +488,13 @@ nouveau_texsubimage(struct gl_context *ctx, GLint dims, GLenum target, GLint lev
                                             format, type, pixels, packing,
                                             "glTexSubImage");
        if (pixels) {
-               nouveau_teximage_map(ctx, ti);
+               nouveau_teximage_map(ctx, ti, GL_MAP_WRITE_BIT,
+                                    xoffset, yoffset, width, height);
 
                ret = _mesa_texstore(ctx, 3, ti->_BaseFormat, ti->TexFormat,
-                                    ti->Data, xoffset, yoffset, zoffset,
-                                    s->pitch, ti->ImageOffsets,
-                                    width, height, depth, format, type,
-                                    pixels, packing);
+                                    ti->Data, 0, 0, 0, s->pitch,
+                                    ti->ImageOffsets, width, height, depth,
+                                    format, type, pixels, packing);
                assert(ret);
 
                nouveau_teximage_unmap(ctx, ti);
@@ -513,7 +553,8 @@ nouveau_get_teximage(struct gl_context *ctx, GLenum target, GLint level,
                     struct gl_texture_object *t,
                     struct gl_texture_image *ti)
 {
-       nouveau_teximage_map(ctx, ti);
+       nouveau_teximage_map(ctx, ti, GL_MAP_READ_BIT,
+                            0, 0, ti->Width, ti->Height);
        _mesa_get_teximage(ctx, target, level, format, type, pixels,
                           t, ti);
        nouveau_teximage_unmap(ctx, ti);
@@ -584,8 +625,11 @@ nouveau_texture_map(struct gl_context *ctx, struct gl_texture_object *t)
        int i;
 
        for (i = t->BaseLevel; i < t->_MaxLevel; i++) {
-               if (t->Image[0][i])
-                       nouveau_teximage_map(ctx, t->Image[0][i]);
+               struct gl_texture_image *ti = t->Image[0][i];
+
+               if (ti)
+                       nouveau_teximage_map(ctx, ti, GL_MAP_READ_BIT,
+                                            0, 0, ti->Width, ti->Height);
        }
 }
 
@@ -635,7 +679,8 @@ nouveau_generate_mipmap(struct gl_context *ctx, GLenum target,
        if (_mesa_meta_check_generate_mipmap_fallback(ctx, target, t)) {
                struct gl_texture_image *base = t->Image[0][t->BaseLevel];
 
-               nouveau_teximage_map(ctx, base);
+               nouveau_teximage_map(ctx, base, GL_MAP_READ_BIT,
+                                    0, 0, base->Width, base->Height);
                _mesa_generate_mipmap(ctx, target, t);
                nouveau_teximage_unmap(ctx, base);
 
index fc170215f3535961dff181db1f42c9712ce2290e..56e61c7337bf1d436237c992624e3dbe5445b160 100644 (file)
 struct nouveau_teximage {
        struct gl_texture_image base;
        struct nouveau_surface surface;
+       struct {
+               struct nouveau_surface surface;
+               int x, y;
+       } transfer;
 };
 #define to_nouveau_teximage(x) ((struct nouveau_teximage *)(x))