r600g: move constant buffer creation behind winsys abstraction.
[mesa.git] / src / gallium / drivers / r600 / r600_texture.c
index 92b4f430c57ef0465d6ccaaa68469354d3c724eb..efc5f820659e628ab8549092ef21a846e870c567 100644 (file)
@@ -24,6 +24,7 @@
  *      Jerome Glisse
  *      Corbin Simpson
  */
+#include <errno.h>
 #include <pipe/p_screen.h>
 #include <util/u_format.h>
 #include <util/u_math.h>
@@ -33,6 +34,7 @@
 #include "r600_screen.h"
 #include "r600_context.h"
 #include "r600_resource.h"
+#include "r600_state_inlines.h"
 #include "r600d.h"
 
 extern struct u_resource_vtbl r600_texture_vtbl;
@@ -71,7 +73,7 @@ static unsigned long r600_texture_get_offset(struct r600_resource_texture *rtex,
        }
 }
 
-static void r600_setup_miptree(struct r600_screen *rscreen, struct r600_resource_texture *rtex)
+static void r600_setup_miptree(struct r600_resource_texture *rtex)
 {
        struct pipe_resource *ptex = &rtex->resource.base.b;
        unsigned long w, h, pitch, size, layer_size, i, offset;
@@ -91,6 +93,8 @@ static void r600_setup_miptree(struct r600_screen *rscreen, struct r600_resource
                rtex->offset[i] = offset;
                rtex->layer_size[i] = layer_size;
                rtex->pitch[i] = pitch;
+               rtex->width[i] = w;
+               rtex->height[i] = h;
                offset += size;
        }
        rtex->size = offset;
@@ -101,7 +105,7 @@ struct pipe_resource *r600_texture_create(struct pipe_screen *screen,
 {
        struct r600_resource_texture *rtex;
        struct r600_resource *resource;
-       struct r600_screen *rscreen = r600_screen(screen);
+       struct radeon *radeon = (struct radeon *)screen->winsys;
 
        rtex = CALLOC_STRUCT(r600_resource_texture);
        if (!rtex) {
@@ -112,11 +116,12 @@ struct pipe_resource *r600_texture_create(struct pipe_screen *screen,
        resource->base.vtbl = &r600_texture_vtbl;
        pipe_reference_init(&resource->base.b.reference, 1);
        resource->base.b.screen = screen;
-       r600_setup_miptree(rscreen, rtex);
+       r600_setup_miptree(rtex);
 
        /* FIXME alignment 4096 enought ? too much ? */
        resource->domain = r600_domain_from_usage(resource->base.b.bind);
-       resource->bo = radeon_bo(rscreen->rw, 0, rtex->size, 4096, NULL);
+       resource->size = rtex->size;
+       resource->bo = radeon_ws_bo(radeon, rtex->size, 4096, 0);
        if (resource->bo == NULL) {
                FREE(rtex);
                return NULL;
@@ -124,16 +129,33 @@ struct pipe_resource *r600_texture_create(struct pipe_screen *screen,
        return &resource->base.b;
 }
 
+static void r600_texture_destroy_state(struct pipe_resource *ptexture)
+{
+       struct r600_resource_texture *rtexture = (struct r600_resource_texture*)ptexture;
+
+       for (int i = 0; i < PIPE_MAX_TEXTURE_LEVELS; i++) {
+               radeon_state_fini(&rtexture->scissor[i]);
+               radeon_state_fini(&rtexture->db[i]);
+               for (int j = 0; j < 8; j++) {
+                       radeon_state_fini(&rtexture->cb[j][i]);
+               }
+       }
+}
+
 static void r600_texture_destroy(struct pipe_screen *screen,
                                 struct pipe_resource *ptex)
 {
        struct r600_resource_texture *rtex = (struct r600_resource_texture*)ptex;
        struct r600_resource *resource = &rtex->resource;
-       struct r600_screen *rscreen = r600_screen(screen);
+       struct radeon *radeon = (struct radeon *)screen->winsys;
 
        if (resource->bo) {
-               radeon_bo_decref(rscreen->rw, resource->bo);
+               radeon_ws_bo_reference(radeon, &resource->bo, NULL);
+       }
+       if (rtex->uncompressed) {
+               radeon_ws_bo_reference(radeon, &rtex->uncompressed, NULL);
        }
+       r600_texture_destroy_state(ptex);
        FREE(rtex);
 }
 
@@ -176,12 +198,7 @@ struct pipe_resource *r600_texture_from_handle(struct pipe_screen *screen,
        struct radeon *rw = (struct radeon*)screen->winsys;
        struct r600_resource_texture *rtex;
        struct r600_resource *resource;
-       struct radeon_bo *bo = NULL;
-
-       bo = radeon_bo(rw, whandle->handle, 0, 0, NULL);
-       if (bo == NULL) {
-               return NULL;
-       }
+       struct radeon_ws_bo *bo = NULL;
 
        /* Support only 2D textures without mipmaps */
        if ((templ->target != PIPE_TEXTURE_2D && templ->target != PIPE_TEXTURE_RECT) ||
@@ -192,15 +209,24 @@ struct pipe_resource *r600_texture_from_handle(struct pipe_screen *screen,
        if (rtex == NULL)
                return NULL;
 
+       bo = radeon_ws_bo_handle(rw, whandle->handle);
+       if (bo == NULL) {
+               FREE(rtex);
+               return NULL;
+       }
+
        resource = &rtex->resource;
        resource->base.b = *templ;
        resource->base.vtbl = &r600_texture_vtbl;
        pipe_reference_init(&resource->base.b.reference, 1);
        resource->base.b.screen = screen;
        resource->bo = bo;
+       rtex->depth = 0;
        rtex->pitch_override = whandle->stride;
        rtex->bpt = util_format_get_blocksize(templ->format);
        rtex->pitch[0] = whandle->stride;
+       rtex->width[0] = templ->width0;
+       rtex->height[0] = templ->height0;
        rtex->offset[0] = 0;
        rtex->size = align(rtex->pitch[0] * templ->height0, 64);
 
@@ -234,7 +260,7 @@ struct pipe_transfer* r600_texture_get_transfer(struct pipe_context *ctx,
        trans->transfer.box = *box;
        trans->transfer.stride = rtex->pitch[sr.level];
        trans->offset = r600_texture_get_offset(rtex, sr.level, box->z, sr.face);
-       if (rtex->tilled) {
+       if (rtex->tilled && !rtex->depth) {
                resource.target = PIPE_TEXTURE_2D;
                resource.format = texture->format;
                resource.width0 = box->width;
@@ -289,46 +315,63 @@ void r600_texture_transfer_destroy(struct pipe_context *ctx,
 void* r600_texture_transfer_map(struct pipe_context *ctx,
                                struct pipe_transfer* transfer)
 {
+       struct r600_screen *rscreen = r600_screen(ctx->screen);
        struct r600_transfer *rtransfer = (struct r600_transfer*)transfer;
-       struct r600_resource *resource;
+       struct radeon_ws_bo *bo;
        enum pipe_format format = transfer->resource->format;
-       struct r600_screen *rscreen = r600_screen(ctx->screen);
+       struct radeon *radeon = (struct radeon *)ctx->screen->winsys;
+       struct r600_resource_texture *rtex;
+       unsigned long offset = 0;
        char *map;
+       int r;
 
        r600_flush(ctx, 0, NULL);
        if (rtransfer->linear_texture) {
-               resource = (struct r600_resource *)rtransfer->linear_texture;
+               bo = ((struct r600_resource *)rtransfer->linear_texture)->bo;
        } else {
-               resource = (struct r600_resource *)transfer->resource;
+               rtex = (struct r600_resource_texture*)transfer->resource;
+               if (rtex->depth && rscreen->chip_class != EVERGREEN) {
+                       r = r600_texture_from_depth(ctx, rtex, transfer->sr.level);
+                       if (r) {
+                               return NULL;
+                       }
+                       r600_flush(ctx, 0, NULL);
+                       bo = rtex->uncompressed;
+               } else {
+                       bo = ((struct r600_resource *)transfer->resource)->bo;
+               }
+               offset = rtransfer->offset +
+                       transfer->box.y / util_format_get_blockheight(format) * transfer->stride +
+                       transfer->box.x / util_format_get_blockwidth(format) * util_format_get_blocksize(format);
        }
-       if (radeon_bo_map(rscreen->rw, resource->bo)) {
+       map = radeon_ws_bo_map(radeon, bo, 0, r600_context(ctx));
+       if (!map) {
                return NULL;
        }
-       radeon_bo_wait(rscreen->rw, resource->bo);
+       radeon_ws_bo_wait(radeon, bo);
 
-       map = resource->bo->data;
-       if (rtransfer->linear_texture) {
-               return map;
-       }
-
-       return map + rtransfer->offset +
-               transfer->box.y / util_format_get_blockheight(format) * transfer->stride +
-               transfer->box.x / util_format_get_blockwidth(format) * util_format_get_blocksize(format);
+       return map + offset;
 }
 
 void r600_texture_transfer_unmap(struct pipe_context *ctx,
                                 struct pipe_transfer* transfer)
 {
        struct r600_transfer *rtransfer = (struct r600_transfer*)transfer;
-       struct r600_screen *rscreen = r600_screen(ctx->screen);
-       struct r600_resource *resource;
+       struct radeon *radeon = (struct radeon *)ctx->screen->winsys;
+       struct r600_resource_texture *rtex;
+       struct radeon_ws_bo *bo;
 
        if (rtransfer->linear_texture) {
-               resource = (struct r600_resource *)rtransfer->linear_texture;
+               bo = ((struct r600_resource *)rtransfer->linear_texture)->bo;
        } else {
-               resource = (struct r600_resource *)transfer->resource;
+               rtex = (struct r600_resource_texture*)transfer->resource;
+               if (rtex->depth) {
+                       bo = rtex->uncompressed;
+               } else {
+                       bo = ((struct r600_resource *)transfer->resource)->bo;
+               }
        }
-       radeon_bo_unmap(rscreen->rw, resource->bo);
+       radeon_ws_bo_unmap(radeon, bo);
 }
 
 struct u_resource_vtbl r600_texture_vtbl =
@@ -415,6 +458,8 @@ uint32_t r600_translate_texformat(enum pipe_format format,
        };
        desc = util_format_description(format);
 
+       word4 |= r600_get_swizzle_combined(desc->swizzle, swizzle_view);
+
        /* Colorspace (return non-RGB formats directly). */
        switch (desc->colorspace) {
                /* Depth stencil formats */
@@ -452,8 +497,6 @@ uint32_t r600_translate_texformat(enum pipe_format format,
        default:
                break;
        }
-       
-       word4 |= r600_get_swizzle_combined(desc->swizzle, swizzle_view);
 
        /* S3TC formats. TODO */
        if (desc->layout == UTIL_FORMAT_LAYOUT_S3TC) {
@@ -483,7 +526,7 @@ uint32_t r600_translate_texformat(enum pipe_format format,
                        if (desc->channel[0].size == 5 &&
                            desc->channel[1].size == 6 &&
                            desc->channel[2].size == 5) {
-                               result |= V_0280A0_COLOR_5_6_5;
+                               result = V_0280A0_COLOR_5_6_5;
                                goto out_word4;
                        }
                        goto out_unknown;
@@ -492,14 +535,14 @@ uint32_t r600_translate_texformat(enum pipe_format format,
                            desc->channel[1].size == 5 &&
                            desc->channel[2].size == 5 &&
                            desc->channel[3].size == 1) {
-                               result |= V_0280A0_COLOR_1_5_5_5;
+                               result = V_0280A0_COLOR_1_5_5_5;
                                goto out_word4;
                        }
                        if (desc->channel[0].size == 10 &&
                            desc->channel[1].size == 10 &&
                            desc->channel[2].size == 10 &&
                            desc->channel[3].size == 2) {
-                               result |= V_0280A0_COLOR_10_10_10_2;
+                               result = V_0280A0_COLOR_10_10_10_2;
                                goto out_word4;
                        }
                        goto out_unknown;
@@ -520,36 +563,36 @@ uint32_t r600_translate_texformat(enum pipe_format format,
                case 4:
                        switch (desc->nr_channels) {
                        case 2:
-                               result |= V_0280A0_COLOR_4_4;
+                               result = V_0280A0_COLOR_4_4;
                                goto out_word4;
                        case 4:
-                               result |= V_0280A0_COLOR_4_4_4_4;
+                               result = V_0280A0_COLOR_4_4_4_4;
                                goto out_word4;
                        }
                        goto out_unknown;
                case 8:
                        switch (desc->nr_channels) {
                        case 1:
-                               result |= V_0280A0_COLOR_8;
+                               result = V_0280A0_COLOR_8;
                                goto out_word4;
                        case 2:
-                               result |= V_0280A0_COLOR_8_8;
+                               result = V_0280A0_COLOR_8_8;
                                goto out_word4;
                        case 4:
-                               result |= V_0280A0_COLOR_8_8_8_8;
+                               result = V_0280A0_COLOR_8_8_8_8;
                                goto out_word4;
                        }
                        goto out_unknown;
                case 16:
                        switch (desc->nr_channels) {
                        case 1:
-                               result |= V_0280A0_COLOR_16;
+                               result = V_0280A0_COLOR_16;
                                goto out_word4;
                        case 2:
-                               result |= V_0280A0_COLOR_16_16;
+                               result = V_0280A0_COLOR_16_16;
                                goto out_word4;
                        case 4:
-                               result |= V_0280A0_COLOR_16_16_16_16;
+                               result = V_0280A0_COLOR_16_16_16_16;
                                goto out_word4;
                        }
                }
@@ -560,26 +603,26 @@ uint32_t r600_translate_texformat(enum pipe_format format,
                case 16:
                        switch (desc->nr_channels) {
                        case 1:
-                               result |= V_0280A0_COLOR_16_FLOAT;
+                               result = V_0280A0_COLOR_16_FLOAT;
                                goto out_word4;
                        case 2:
-                               result |= V_0280A0_COLOR_16_16_FLOAT;
+                               result = V_0280A0_COLOR_16_16_FLOAT;
                                goto out_word4;
                        case 4:
-                               result |= V_0280A0_COLOR_16_16_16_16_FLOAT;
+                               result = V_0280A0_COLOR_16_16_16_16_FLOAT;
                                goto out_word4;
                        }
                        goto out_unknown;
                case 32:
                        switch (desc->nr_channels) {
                        case 1:
-                               result |= V_0280A0_COLOR_32_FLOAT;
+                               result = V_0280A0_COLOR_32_FLOAT;
                                goto out_word4;
                        case 2:
-                               result |= V_0280A0_COLOR_32_32_FLOAT;
+                               result = V_0280A0_COLOR_32_32_FLOAT;
                                goto out_word4;
                        case 4:
-                               result |= V_0280A0_COLOR_32_32_32_32_FLOAT;
+                               result = V_0280A0_COLOR_32_32_32_32_FLOAT;
                                goto out_word4;
                        }
                }
@@ -592,6 +635,84 @@ out_word4:
                *yuv_format_p = yuv_format;
        return result;
 out_unknown:
-       R600_ERR("Unable to handle texformat %d %s\n", format, util_format_name(format));
+//     R600_ERR("Unable to handle texformat %d %s\n", format, util_format_name(format));
        return ~0;
 }
+
+int r600_texture_from_depth(struct pipe_context *ctx, struct r600_resource_texture *rtexture, unsigned level)
+{
+       struct r600_screen *rscreen = r600_screen(ctx->screen);
+       int r;
+
+       if (!rtexture->depth) {
+               /* This shouldn't happen maybe print a warning */
+               return 0;
+       }
+       if (rtexture->uncompressed && !rtexture->dirty) {
+               /* Uncompressed bo already in good state */
+               return 0;
+       }
+
+       /* allocate uncompressed texture */
+       if (rtexture->uncompressed == NULL) {
+               rtexture->uncompressed = radeon_ws_bo(rscreen->rw, rtexture->size, 4096, 0);
+               if (rtexture->uncompressed == NULL) {
+                       return -ENOMEM;
+               }
+       }
+
+       /* render a rectangle covering whole buffer to uncompress depth */
+       r = r600_blit_uncompress_depth(ctx, rtexture, level);
+       if (r) {
+               return r;
+       }
+
+       rtexture->dirty = 0;
+       return 0;
+}
+
+
+
+int r600_texture_scissor(struct pipe_context *ctx, struct r600_resource_texture *rtexture, unsigned level)
+{
+       struct r600_screen *rscreen = r600_screen(ctx->screen);
+       struct r600_context *rctx = r600_context(ctx);
+
+       if (!rtexture->scissor[level].cpm4) {
+               rctx->vtbl->texture_state_scissor(rscreen, rtexture, level);
+       }
+       return 0;
+}
+
+int r600_texture_cb(struct pipe_context *ctx, struct r600_resource_texture *rtexture, unsigned cb, unsigned level)
+{
+       struct r600_screen *rscreen = r600_screen(ctx->screen);
+       struct r600_context *rctx = r600_context(ctx);
+
+       if (!rtexture->cb[cb][level].cpm4) {
+               rctx->vtbl->texture_state_cb(rscreen, rtexture, cb, level);
+       }
+       return 0;
+}
+
+int r600_texture_db(struct pipe_context *ctx, struct r600_resource_texture *rtexture, unsigned level)
+{
+       struct r600_screen *rscreen = r600_screen(ctx->screen);
+       struct r600_context *rctx = r600_context(ctx);
+
+       if (!rtexture->db[level].cpm4) {
+               rctx->vtbl->texture_state_db(rscreen, rtexture, level);
+       }
+       return 0;
+}
+
+int r600_texture_viewport(struct pipe_context *ctx, struct r600_resource_texture *rtexture, unsigned level)
+{
+       struct r600_screen *rscreen = r600_screen(ctx->screen);
+       struct r600_context *rctx = r600_context(ctx);
+
+       if (!rtexture->viewport[level].cpm4) {
+               rctx->vtbl->texture_state_viewport(rscreen, rtexture, level);
+       }
+       return 0;
+}