swr/rast: add SwrGetInterface() function to return api
[mesa.git] / src / gallium / drivers / swr / swr_context.cpp
index 6f46d666ac59909f1bb790e9c8599b545b8363bb..aa5cca8e653e2c36df95f4ccde28d513661df9ab 100644 (file)
@@ -267,20 +267,104 @@ swr_resource_copy(struct pipe_context *pipe,
 }
 
 
+/* XXX: This resolve is incomplete and suboptimal. It will be removed once the
+ * pipelined resolve blit works. */
+void
+swr_do_msaa_resolve(struct pipe_resource *src_resource,
+                    struct pipe_resource *dst_resource)
+{
+   /* This is a pretty dumb inline resolve.  It only supports 8-bit formats
+    * (ex RGBA8/BGRA8) - which are most common display formats anyway.
+    */
+
+   /* quick check for 8-bit and number of components */
+   uint8_t bits_per_component =
+      util_format_get_component_bits(src_resource->format,
+            UTIL_FORMAT_COLORSPACE_RGB, 0);
+
+   /* Unsupported resolve format */
+   assert(src_resource->format == dst_resource->format);
+   assert(bits_per_component == 8);
+   if ((src_resource->format != dst_resource->format) ||
+       (bits_per_component != 8)) {
+      return;
+   }
+
+   uint8_t src_num_comps = util_format_get_nr_components(src_resource->format);
+
+   SWR_SURFACE_STATE *src_surface = &swr_resource(src_resource)->swr;
+   SWR_SURFACE_STATE *dst_surface = &swr_resource(dst_resource)->swr;
+
+   uint32_t *src, *dst, offset;
+   uint32_t num_samples = src_surface->numSamples;
+   float recip_num_samples = 1.0f / num_samples;
+   for (uint32_t y = 0; y < src_surface->height; y++) {
+      for (uint32_t x = 0; x < src_surface->width; x++) {
+         float r = 0.0f;
+         float g = 0.0f;
+         float b = 0.0f;
+         float a = 0.0f;
+         for (uint32_t sampleNum = 0;  sampleNum < num_samples; sampleNum++) {
+            offset = ComputeSurfaceOffset<false>(x, y, 0, 0, sampleNum, 0, src_surface);
+            src = (uint32_t *) src_surface->pBaseAddress + offset/src_num_comps;
+            const uint32_t sample = *src;
+            r += (float)((sample >> 24) & 0xff) / 255.0f * recip_num_samples;
+            g += (float)((sample >> 16) & 0xff) / 255.0f * recip_num_samples;
+            b += (float)((sample >>  8) & 0xff) / 255.0f * recip_num_samples;
+            a += (float)((sample      ) & 0xff) / 255.0f * recip_num_samples;
+         }
+         uint32_t result = 0;
+         result  = ((uint8_t)(r * 255.0f) & 0xff) << 24;
+         result |= ((uint8_t)(g * 255.0f) & 0xff) << 16;
+         result |= ((uint8_t)(b * 255.0f) & 0xff) <<  8;
+         result |= ((uint8_t)(a * 255.0f) & 0xff);
+         offset = ComputeSurfaceOffset<false>(x, y, 0, 0, 0, 0, src_surface);
+         dst = (uint32_t *) dst_surface->pBaseAddress + offset/src_num_comps;
+         *dst = result;
+      }
+   }
+}
+
+
 static void
 swr_blit(struct pipe_context *pipe, const struct pipe_blit_info *blit_info)
 {
    struct swr_context *ctx = swr_context(pipe);
+   /* Make a copy of the const blit_info, so we can modify it */
    struct pipe_blit_info info = *blit_info;
 
-   if (blit_info->render_condition_enable && !swr_check_render_cond(pipe))
+   if (info.render_condition_enable && !swr_check_render_cond(pipe))
       return;
 
    if (info.src.resource->nr_samples > 1 && info.dst.resource->nr_samples <= 1
        && !util_format_is_depth_or_stencil(info.src.resource->format)
        && !util_format_is_pure_integer(info.src.resource->format)) {
-      debug_printf("swr: color resolve unimplemented\n");
-      return;
+      debug_printf("swr_blit: color resolve : %d -> %d\n",
+            info.src.resource->nr_samples, info.dst.resource->nr_samples);
+
+      /* Because the resolve is being done inline (not pipelined),
+       * resources need to be stored out of hottiles and the pipeline empty.
+       *
+       * Resources are marked unused following fence finish because all
+       * pipeline operations are complete.  Validation of the blit will mark
+       * them are read/write again.
+       */
+      swr_store_dirty_resource(pipe, info.src.resource, SWR_TILE_RESOLVED);
+      swr_store_dirty_resource(pipe, info.dst.resource, SWR_TILE_RESOLVED);
+      swr_fence_finish(pipe->screen, NULL, swr_screen(pipe->screen)->flush_fence, 0);
+      swr_resource_unused(info.src.resource);
+      swr_resource_unused(info.dst.resource);
+
+      struct pipe_resource *src_resource = info.src.resource;
+      struct pipe_resource *resolve_target =
+         swr_resource(src_resource)->resolve_target;
+
+      /* Inline resolve samples into resolve target resource, then continue
+       * the blit. */
+      swr_do_msaa_resolve(src_resource, resolve_target);
+
+      /* The resolve target becomes the new source for the blit.  */
+      info.src.resource = resolve_target;
    }
 
    if (util_try_blit_via_copy_region(pipe, &info)) {