r600g: add support for subsampled rgb formats
[mesa.git] / src / gallium / drivers / r600 / r600_texture.c
index 54d7c91b5c91c2eb95a17ee08f454f49da5cd55f..ce66117ed47eaf5bf4ce5acaac8769ae4bbccdb7 100644 (file)
  *      Jerome Glisse
  *      Corbin Simpson
  */
+#include "r600_formats.h"
+#include "r600d.h"
+
 #include <errno.h>
-#include "pipe/p_screen.h"
-#include "util/u_format.h"
 #include "util/u_format_s3tc.h"
-#include "util/u_math.h"
-#include "util/u_inlines.h"
 #include "util/u_memory.h"
-#include "pipebuffer/pb_buffer.h"
-#include "r600_pipe.h"
-#include "r600_resource.h"
-#include "r600d.h"
-#include "r600_formats.h"
 
 /* Copy from a full GPU texture to a transfer's staging one. */
 static void r600_copy_to_staging_texture(struct pipe_context *ctx, struct r600_transfer *rtransfer)
@@ -43,7 +37,7 @@ static void r600_copy_to_staging_texture(struct pipe_context *ctx, struct r600_t
        struct pipe_transfer *transfer = (struct pipe_transfer*)rtransfer;
        struct pipe_resource *texture = transfer->resource;
 
-       ctx->resource_copy_region(ctx, rtransfer->staging_texture,
+       ctx->resource_copy_region(ctx, &rtransfer->staging->b.b.b,
                                0, 0, 0, 0, texture, transfer->level,
                                &transfer->box);
 }
@@ -63,7 +57,7 @@ static void r600_copy_from_staging_texture(struct pipe_context *ctx, struct r600
        sbox.depth = 1;
        ctx->resource_copy_region(ctx, texture, transfer->level,
                                  transfer->box.x, transfer->box.y, transfer->box.z,
-                                 rtransfer->staging_texture,
+                                 &rtransfer->staging->b.b.b,
                                  0, &sbox);
 }
 
@@ -444,14 +438,7 @@ static boolean permit_hardware_blit(struct pipe_screen *screen,
                                 PIPE_BIND_SAMPLER_VIEW))
                return FALSE;
 
-       switch (res->usage) {
-       case PIPE_USAGE_STREAM:
-       case PIPE_USAGE_STAGING:
-               return FALSE;
-
-       default:
-               return TRUE;
-       }
+       return TRUE;
 }
 
 static boolean r600_texture_get_handle(struct pipe_screen* screen,
@@ -489,9 +476,9 @@ static const struct u_resource_vtbl r600_texture_vtbl =
        r600_texture_get_transfer,      /* get_transfer */
        r600_texture_transfer_destroy,  /* transfer_destroy */
        r600_texture_transfer_map,      /* transfer_map */
-       u_default_transfer_flush_region,/* transfer_flush_region */
+       NULL,                           /* transfer_flush_region */
        r600_texture_transfer_unmap,    /* transfer_unmap */
-       u_default_transfer_inline_write /* transfer_inline_write */
+       NULL                            /* transfer_inline_write */
 };
 
 static struct r600_resource_texture *
@@ -630,12 +617,13 @@ struct pipe_resource *r600_texture_create(struct pipe_screen *screen,
        unsigned array_mode = 0;
        int r;
 
-       if (!(templ->flags & R600_RESOURCE_FLAG_TRANSFER) &&
-           !(templ->bind & PIPE_BIND_SCANOUT)) {
-               if (rscreen->use_surface_alloc) {
-                       if (permit_hardware_blit(screen, templ)) {
-                               array_mode = V_038000_ARRAY_2D_TILED_THIN1;
-                       }
+       if (!(templ->flags & R600_RESOURCE_FLAG_TRANSFER)) {
+               if (rscreen->use_surface_alloc &&
+                   !(templ->bind & PIPE_BIND_SCANOUT) &&
+                   templ->usage != PIPE_USAGE_STAGING &&
+                   templ->usage != PIPE_USAGE_STREAM &&
+                   permit_hardware_blit(screen, templ)) {
+                       array_mode = V_038000_ARRAY_2D_TILED_THIN1;
                } else if (util_format_is_compressed(templ->format)) {
                        array_mode = V_038000_ARRAY_1D_TILED_THIN1;
                }
@@ -664,8 +652,6 @@ static struct pipe_surface *r600_create_surface(struct pipe_context *pipe,
        assert(surf_tmpl->u.tex.first_layer == surf_tmpl->u.tex.last_layer);
        if (surface == NULL)
                return NULL;
-       /* XXX no offset */
-/*     offset = r600_texture_get_offset(rtex, level, surf_tmpl->u.tex.first_layer);*/
        pipe_reference_init(&surface->base.reference, 1);
        pipe_resource_reference(&surface->base.texture, texture);
        surface->base.context = pipe;
@@ -790,10 +776,6 @@ struct pipe_transfer* r600_texture_get_transfer(struct pipe_context *ctx,
        int r;
        boolean use_staging_texture = FALSE;
 
-       if (usage & PIPE_TRANSFER_MAP_PERMANENTLY) {
-          return NULL;
-       }
-
        /* We cannot map a tiled texture directly because the data is
         * in a different order, therefore we do detiling using a blit.
         *
@@ -809,7 +791,7 @@ struct pipe_transfer* r600_texture_get_transfer(struct pipe_context *ctx,
 
        /* Use a staging texture for uploads if the underlying BO is busy. */
        if (!(usage & PIPE_TRANSFER_READ) &&
-           (rctx->ws->cs_is_buffer_referenced(rctx->cs, rtex->resource.cs_buf) ||
+           (rctx->ws->cs_is_buffer_referenced(rctx->cs, rtex->resource.cs_buf, RADEON_USAGE_READWRITE) ||
             rctx->ws->buffer_is_busy(rtex->resource.buf, RADEON_USAGE_READWRITE)))
                use_staging_texture = TRUE;
 
@@ -865,8 +847,8 @@ struct pipe_transfer* r600_texture_get_transfer(struct pipe_context *ctx,
                        resource.bind |= PIPE_BIND_SAMPLER_VIEW;
                }
                /* Create the temporary texture. */
-               trans->staging_texture = ctx->screen->resource_create(ctx->screen, &resource);
-               if (trans->staging_texture == NULL) {
+               trans->staging = (struct r600_resource*)ctx->screen->resource_create(ctx->screen, &resource);
+               if (trans->staging == NULL) {
                        R600_ERR("failed to create temporary texture to hold untiled copy\n");
                        pipe_resource_reference(&trans->transfer.resource, NULL);
                        FREE(trans);
@@ -874,7 +856,7 @@ struct pipe_transfer* r600_texture_get_transfer(struct pipe_context *ctx,
                }
 
                trans->transfer.stride =
-                       ((struct r600_resource_texture *)trans->staging_texture)->pitch_in_bytes[0];
+                       ((struct r600_resource_texture *)trans->staging)->pitch_in_bytes[0];
                if (usage & PIPE_TRANSFER_READ) {
                        r600_copy_to_staging_texture(ctx, trans);
                        /* Always referenced in the blit. */
@@ -895,11 +877,11 @@ void r600_texture_transfer_destroy(struct pipe_context *ctx,
        struct pipe_resource *texture = transfer->resource;
        struct r600_resource_texture *rtex = (struct r600_resource_texture*)texture;
 
-       if (rtransfer->staging_texture) {
+       if (rtransfer->staging) {
                if (transfer->usage & PIPE_TRANSFER_WRITE) {
                        r600_copy_from_staging_texture(ctx, rtransfer);
                }
-               pipe_resource_reference(&rtransfer->staging_texture, NULL);
+               pipe_resource_reference((struct pipe_resource**)&rtransfer->staging, NULL);
        }
 
        if (rtex->is_depth && !rtex->is_flushing_texture) {
@@ -921,8 +903,8 @@ void* r600_texture_transfer_map(struct pipe_context *ctx,
        unsigned offset = 0;
        char *map;
 
-       if (rtransfer->staging_texture) {
-               buf = ((struct r600_resource *)rtransfer->staging_texture)->buf;
+       if (rtransfer->staging) {
+               buf = ((struct r600_resource *)rtransfer->staging)->buf;
        } else {
                struct r600_resource_texture *rtex = (struct r600_resource_texture*)transfer->resource;
 
@@ -950,8 +932,8 @@ void r600_texture_transfer_unmap(struct pipe_context *ctx,
        struct r600_context *rctx = (struct r600_context*)ctx;
        struct pb_buffer *buf;
 
-       if (rtransfer->staging_texture) {
-               buf = ((struct r600_resource *)rtransfer->staging_texture)->buf;
+       if (rtransfer->staging) {
+               buf = ((struct r600_resource *)rtransfer->staging)->buf;
        } else {
                struct r600_resource_texture *rtex = (struct r600_resource_texture*)transfer->resource;
 
@@ -1079,7 +1061,7 @@ uint32_t r600_translate_texformat(struct pipe_screen *screen,
                default:
                        break;
                }
-               goto out_unknown; /* TODO */
+               goto out_unknown; /* XXX */
 
        case UTIL_FORMAT_COLORSPACE_SRGB:
                word4 |= S_038010_FORCE_DEGAMMA(1);
@@ -1153,6 +1135,21 @@ uint32_t r600_translate_texformat(struct pipe_screen *screen,
                }
        }
 
+       if (desc->layout == UTIL_FORMAT_LAYOUT_SUBSAMPLED) {
+               switch (format) {
+               case PIPE_FORMAT_R8G8_B8G8_UNORM:
+               case PIPE_FORMAT_G8R8_B8R8_UNORM:
+                       result = FMT_GB_GR;
+                       goto out_word4;
+               case PIPE_FORMAT_G8R8_G8B8_UNORM:
+               case PIPE_FORMAT_R8G8_R8B8_UNORM:
+                       result = FMT_BG_RG;
+                       goto out_word4;
+               default:
+                       goto out_unknown;
+               }
+       }
+
        if (format == PIPE_FORMAT_R9G9B9E5_FLOAT) {
                result = FMT_5_9_9_9_SHAREDEXP;
                goto out_word4;
@@ -1168,7 +1165,7 @@ uint32_t r600_translate_texformat(struct pipe_screen *screen,
                }
        }
 
-       /* R8G8Bx_SNORM - TODO CxV8U8 */
+       /* R8G8Bx_SNORM - XXX CxV8U8 */
 
        /* See whether the components are of the same size. */
        for (i = 1; i < desc->nr_channels; i++) {