ilo: add support for PIPE_FORMAT_ETC1_RGB8
authorChia-I Wu <olvaffe@gmail.com>
Thu, 9 May 2013 07:14:11 +0000 (15:14 +0800)
committerChia-I Wu <olvaffe@gmail.com>
Thu, 9 May 2013 08:05:48 +0000 (16:05 +0800)
It is decompressed to and stored as PIPE_FORMAT_R8G8B8X8_UNORM on-the-fly.

src/gallium/drivers/ilo/ilo_format.h
src/gallium/drivers/ilo/ilo_resource.c

index 556b21887c32181e5de4db9b19be0c965c4157f6..c01edd9b73cf00421d622738a7d11ad733c3e84a 100644 (file)
@@ -70,6 +70,9 @@ ilo_translate_format(enum pipe_format format, unsigned bind)
        * values.  But we assume in many places that the depth values are
        * returned as I values (util_make_fragment_tex_shader_writedepth() is
        * one such example).  We have to live with that at least for now.
+       *
+       * For ETC1 format, the texture data will be decompressed before being
+       * written to the bo.  See transfer_unmap_sys_convert().
        */
       switch (format) {
       case PIPE_FORMAT_Z16_UNORM:
@@ -81,6 +84,8 @@ ilo_translate_format(enum pipe_format format, unsigned bind)
          return BRW_SURFACEFORMAT_I24X8_UNORM;
       case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT:
          return BRW_SURFACEFORMAT_I32X32_FLOAT;
+      case PIPE_FORMAT_ETC1_RGB8:
+         return BRW_SURFACEFORMAT_R8G8B8X8_UNORM;
       default:
          return ilo_translate_color_format(format);
       }
index 082d9170fd0ff5f5b5f0c9361359e022c26bfcb3..c401d9f5f2b3ecfb811f4b0b217a7b2969304f1d 100644 (file)
@@ -27,6 +27,7 @@
 
 #include "util/u_surface.h"
 #include "util/u_transfer.h"
+#include "util/u_format_etc.h"
 
 #include "ilo_cp.h"
 #include "ilo_context.h"
@@ -265,6 +266,35 @@ ilo_transfer_inline_write(struct pipe_context *pipe,
    res->bo->pwrite(res->bo, offset, size, data);
 }
 
+static void
+transfer_unmap_sys_convert(enum pipe_format dst_fmt,
+                           const struct pipe_transfer *dst_xfer,
+                           void *dst,
+                           enum pipe_format src_fmt,
+                           const struct pipe_transfer *src_xfer,
+                           const void *src)
+{
+   int i;
+
+   switch (src_fmt) {
+   case PIPE_FORMAT_ETC1_RGB8:
+      assert(dst_fmt == PIPE_FORMAT_R8G8B8X8_UNORM);
+
+      for (i = 0; i < dst_xfer->box.depth; i++) {
+         util_format_etc1_rgb8_unpack_rgba_8unorm(dst,
+               dst_xfer->stride, src, src_xfer->stride,
+               dst_xfer->box.width, dst_xfer->box.height);
+
+         dst += dst_xfer->layer_stride;
+         src += src_xfer->layer_stride;
+      }
+      break;
+   default:
+      assert(!"unable to convert the staging data");
+      break;
+   }
+}
+
 static void
 transfer_unmap_sys(struct ilo_context *ilo,
                    struct ilo_resource *res,
@@ -286,10 +316,16 @@ transfer_unmap_sys(struct ilo_context *ilo,
       return;
    }
 
-   util_copy_box(dst, res->bo_format,
-         dst_xfer->stride, dst_xfer->layer_stride, 0, 0, 0,
-         dst_xfer->box.width, dst_xfer->box.height, dst_xfer->box.depth,
-         src, xfer->base.stride, xfer->base.layer_stride, 0, 0, 0);
+   if (likely(res->bo_format != res->base.format)) {
+      transfer_unmap_sys_convert(res->bo_format, dst_xfer, dst,
+            res->base.format, &xfer->base, src);
+   }
+   else {
+      util_copy_box(dst, res->bo_format,
+            dst_xfer->stride, dst_xfer->layer_stride, 0, 0, 0,
+            dst_xfer->box.width, dst_xfer->box.height, dst_xfer->box.depth,
+            src, xfer->base.stride, xfer->base.layer_stride, 0, 0, 0);
+   }
 
    ilo->base.transfer_unmap(&ilo->base, dst_xfer);
    FREE(xfer->staging_sys);
@@ -406,6 +442,14 @@ transfer_map_choose_method(struct ilo_context *ilo,
 {
    bool will_be_busy, will_stall;
 
+   /* need to convert on-the-fly */
+   if (res->bo_format != res->base.format &&
+       !(xfer->base.usage & PIPE_TRANSFER_MAP_DIRECTLY)) {
+      xfer->method = ILO_TRANSFER_MAP_STAGING_SYS;
+
+      return true;
+   }
+
    xfer->method = ILO_TRANSFER_MAP_DIRECT;
 
    /* unsynchronized map does not stall */
@@ -1220,7 +1264,14 @@ init_texture(struct ilo_resource *res)
 {
    struct layout_tex_info info;
 
-   res->bo_format = res->base.format;
+   switch (res->base.format) {
+   case PIPE_FORMAT_ETC1_RGB8:
+      res->bo_format = PIPE_FORMAT_R8G8B8X8_UNORM;
+      break;
+   default:
+      res->bo_format = res->base.format;
+      break;
+   }
 
    /* determine tiling first as it may affect the layout */
    res->tiling = get_tex_tiling(res);