intel: Support glCopyTexImage() from XRGB8888 to ARGB8888.
authorEric Anholt <eric@anholt.net>
Wed, 15 Dec 2010 20:10:03 +0000 (12:10 -0800)
committerEric Anholt <eric@anholt.net>
Thu, 16 Dec 2010 18:48:19 +0000 (10:48 -0800)
The only mismatch between the two is that we have to clear the
destination's alpha to 1.0.  Fixes WOW performance on my Ironlake,
from a few frames a second to almost playable.

src/mesa/drivers/dri/intel/intel_blit.c
src/mesa/drivers/dri/intel/intel_blit.h
src/mesa/drivers/dri/intel/intel_tex_copy.c

index ede88de82f1fa4d68c3d26260449999c684bb6d5..a2822b11d9626d6cde2b8d54dbd74803350aa738 100644 (file)
@@ -38,6 +38,8 @@
 #include "intel_reg.h"
 #include "intel_regions.h"
 #include "intel_batchbuffer.h"
+#include "intel_tex.h"
+#include "intel_mipmap_tree.h"
 
 #define FILE_DEBUG_FLAG DEBUG_BLIT
 
@@ -500,3 +502,81 @@ intel_emit_linear_blit(struct intel_context *intel,
       assert(ok);
    }
 }
+
+/**
+ * Used to initialize the alpha value of an ARGB8888 teximage after
+ * loading it from an XRGB8888 source.
+ *
+ * This is very common with glCopyTexImage2D().
+ */
+void
+intel_set_teximage_alpha_to_one(struct gl_context *ctx,
+                               struct intel_texture_image *intel_image)
+{
+   struct intel_context *intel = intel_context(ctx);
+   unsigned int image_x, image_y;
+   uint32_t x1, y1, x2, y2;
+   uint32_t BR13, CMD;
+   int pitch, cpp;
+   drm_intel_bo *aper_array[2];
+   struct intel_region *region = intel_image->mt->region;
+   BATCH_LOCALS;
+
+   assert(intel_image->base.TexFormat == MESA_FORMAT_ARGB8888);
+
+   /* get dest x/y in destination texture */
+   intel_miptree_get_image_offset(intel_image->mt,
+                                 intel_image->level,
+                                 intel_image->face,
+                                 0,
+                                 &image_x, &image_y);
+
+   x1 = image_x;
+   y1 = image_y;
+   x2 = image_x + intel_image->base.Width;
+   y2 = image_y + intel_image->base.Height;
+
+   pitch = region->pitch;
+   cpp = region->cpp;
+
+   DBG("%s dst:buf(%p)/%d %d,%d sz:%dx%d\n",
+       __FUNCTION__,
+       intel_image->mt->region->buffer, (pitch * region->cpp),
+       x1, y1, x2 - x1, y2 - y1);
+
+   BR13 = br13_for_cpp(region->cpp) | 0xf0 << 16;
+   CMD = XY_COLOR_BLT_CMD;
+   CMD |= XY_BLT_WRITE_ALPHA;
+
+   assert(region->tiling != I915_TILING_Y);
+
+#ifndef I915
+   if (region->tiling != I915_TILING_NONE) {
+      CMD |= XY_DST_TILED;
+      pitch /= 4;
+   }
+#endif
+   BR13 |= (pitch * region->cpp);
+
+   /* do space check before going any further */
+   aper_array[0] = intel->batch->buf;
+   aper_array[1] = region->buffer;
+
+   if (drm_intel_bufmgr_check_aperture_space(aper_array,
+                                            ARRAY_SIZE(aper_array)) != 0) {
+      intel_batchbuffer_flush(intel->batch);
+   }
+
+   BEGIN_BATCH_BLT(6);
+   OUT_BATCH(CMD);
+   OUT_BATCH(BR13);
+   OUT_BATCH((y1 << 16) | x1);
+   OUT_BATCH((y2 << 16) | x2);
+   OUT_RELOC_FENCED(region->buffer,
+                   I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER,
+                   0);
+   OUT_BATCH(0xffffffff); /* white, but only alpha gets written */
+   ADVANCE_BATCH();
+
+   intel_batchbuffer_emit_mi_flush(intel->batch);
+}
index 01631465735323d9fc08f76f59084d11f1f10b7f..ff69e4f8f8f4ed99b6f086f7c6759d3a6ed0fbc2 100644 (file)
@@ -69,5 +69,7 @@ void intel_emit_linear_blit(struct intel_context *intel,
                            drm_intel_bo *src_bo,
                            unsigned int src_offset,
                            unsigned int size);
+void intel_set_teximage_alpha_to_one(struct gl_context *ctx,
+                                    struct intel_texture_image *intel_image);
 
 #endif
index c4a3364ceba1d05052da1dbdd16195adabe1dd27..c6bc3d962ab54a3a9e7187cf9a655a2f85a76b54 100644 (file)
@@ -78,18 +78,25 @@ do_copy_texsubimage(struct intel_context *intel,
 {
    struct gl_context *ctx = &intel->ctx;
    struct intel_renderbuffer *irb;
+   bool copy_supported_with_alpha_override = false;
 
    intel_prepare_render(intel);
 
    irb = get_teximage_readbuffer(intel, internalFormat);
-   if (!intelImage->mt || !irb) {
+   if (!intelImage->mt || !irb || !irb->region) {
       if (unlikely(INTEL_DEBUG & DEBUG_FALLBACKS))
         fprintf(stderr, "%s fail %p %p (0x%08x)\n",
                 __FUNCTION__, intelImage->mt, irb, internalFormat);
       return GL_FALSE;
    }
 
-   if (intelImage->base.TexFormat != irb->Base.Format) {
+   if (irb->Base.Format == MESA_FORMAT_XRGB8888 &&
+       intelImage->base.TexFormat == MESA_FORMAT_ARGB8888) {
+      copy_supported_with_alpha_override = true;
+   }
+
+   if (intelImage->base.TexFormat != irb->Base.Format &&
+       !copy_supported_with_alpha_override) {
       if (unlikely(INTEL_DEBUG & DEBUG_FALLBACKS))
         fprintf(stderr, "%s mismatched formats %s, %s\n",
                 __FUNCTION__,
@@ -145,6 +152,9 @@ do_copy_texsubimage(struct intel_context *intel,
       }
    }
 
+   if (copy_supported_with_alpha_override)
+      intel_set_teximage_alpha_to_one(ctx, intelImage);
+
    return GL_TRUE;
 }