freedreno/a6xx: fix hang with large render target
[mesa.git] / src / gallium / drivers / svga / svga_pipe_blit.c
index 57df5f4c48915401f1b72d16f708981ffc30727e..a756509ce76246af440e41d89250f8f3f1255bc1 100644 (file)
@@ -32,7 +32,7 @@
 #include "svga_surface.h"
 
 //#include "util/u_blit_sw.h"
-#include "util/u_format.h"
+#include "util/format/u_format.h"
 #include "util/u_surface.h"
 
 #define FILE_DEBUG_FLAG DEBUG_BLIT
@@ -69,7 +69,6 @@ build_blit_info(struct pipe_resource *dst_tex,
             src_box->depth, &blit->dst.box);
 }
 
-
 /**
  * Copy when src texture and dst texture are same with IntraSurfaceCopy
  * command.
@@ -81,10 +80,15 @@ intra_surface_copy(struct svga_context *svga, struct pipe_resource *tex,
                     unsigned dst_x, unsigned dst_y, unsigned dst_z,
                     unsigned width, unsigned height, unsigned depth)
 {
-   enum pipe_error ret;
    SVGA3dCopyBox box;
    struct svga_texture *stex;
 
+   /*
+    * Makes sure we have flushed all buffered draw operations and also
+    * synchronizes all surfaces with any emulated surface views.
+    */
+   svga_surfaces_flush(svga);
+
    stex = svga_texture(tex);
 
    box.x = dst_x;
@@ -97,15 +101,8 @@ intra_surface_copy(struct svga_context *svga, struct pipe_resource *tex,
    box.srcy = src_y;
    box.srcz = src_z;
 
-   ret = SVGA3D_vgpu10_IntraSurfaceCopy(svga->swc,
-                                 stex->handle, level, layer_face,  &box);
-   if (ret != PIPE_OK) {
-      svga_context_flush(svga, NULL);
-   ret = SVGA3D_vgpu10_IntraSurfaceCopy(svga->swc,
-                                 stex->handle, level, layer_face, &box);
-      assert(ret == PIPE_OK);
-   }
-
+   SVGA_RETRY(svga, SVGA3D_vgpu10_IntraSurfaceCopy(svga->swc, stex->handle,
+                                                   level, layer_face,  &box));
    /* Mark the texture subresource as rendered-to. */
    svga_set_texture_rendered_to(stex, layer_face, level);
 }
@@ -234,7 +231,8 @@ is_blending_enabled(struct svga_context *svga,
    if (svga->curr.blend) {
       if (svga->curr.blend->independent_blend_enable) {
          for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) {
-            if (svga->curr.framebuffer.cbufs[i]->texture == blit->dst.resource) {
+            struct pipe_surface *cbuf = svga->curr.framebuffer.cbufs[i];
+            if (cbuf && (cbuf->texture == blit->dst.resource)) {
                if (svga->curr.blend->rt[i].blend_enable) {
                   blend_enable = true;
                }
@@ -250,7 +248,6 @@ is_blending_enabled(struct svga_context *svga,
    return blend_enable;
 }
 
-
 /**
  * If GL_FRAMEBUFFER_SRGB is enabled, then output colorspace is
  * expected to be sRGB if blending is not enabled.
@@ -338,13 +335,15 @@ can_blit_via_svga_copy_region(struct svga_context *svga,
    return check_blending_and_srgb_cond(svga, blit_info);
 }
 
-
+/**
+ * Check whether we can blit using the intra_surface_copy command.
+ */
 static bool
 can_blit_via_intra_surface_copy(struct svga_context *svga,
                                 const struct pipe_blit_info *blit_info)
 {
-   struct svga_texture *dtex, *stex;
    struct svga_winsys_screen *sws = svga_screen(svga->pipe.screen)->sws;
+   struct svga_texture *dtex, *stex;
 
    if (!svga_have_vgpu10(svga))
       return false;
@@ -356,10 +355,7 @@ can_blit_via_intra_surface_copy(struct svga_context *svga,
    if (!sws->have_intra_surface_copy)
       return false;
 
-   stex = svga_texture(blit_info->src.resource);
-   dtex = svga_texture(blit_info->dst.resource);
-
-   if (stex->handle != dtex->handle)
+   if (svga->render_condition && blit_info->render_condition_enable)
       return false;
 
    if (blit_info->src.level != blit_info->dst.level)
@@ -370,30 +366,15 @@ can_blit_via_intra_surface_copy(struct svga_context *svga,
          return false;
    }
 
-   /* check that the blit src/dst regions are same size, no flipping, etc. */
-   if (blit_info->src.box.width != blit_info->dst.box.width ||
-       blit_info->src.box.height != blit_info->dst.box.height)
-      return false;
-
-   /* For depth+stencil formats, copy with mask != PIPE_MASK_ZS is not
-    * supported
-    */
-   if (util_format_is_depth_and_stencil(blit_info->src.format) &&
-      blit_info->mask != (PIPE_MASK_ZS))
-     return false;
-
-   if (blit_info->alpha_blend ||
-       (svga->render_condition && blit_info->render_condition_enable) ||
-       blit_info->scissor_enable)
-      return false;
+   stex = svga_texture(blit_info->src.resource);
+   dtex = svga_texture(blit_info->dst.resource);
 
-   return !(is_blending_enabled(svga, blit_info) &&
-           util_format_is_srgb(blit_info->src.resource->format));
+   return (stex->handle == dtex->handle);
 }
 
 
 /**
- * The state tracker implements some resource copies with blits (for
+ * the gallium frontend implements some resource copies with blits (for
  * GL_ARB_copy_image).  This function checks if we should really do the blit
  * with a VGPU10 CopyRegion command or software fallback (for incompatible
  * src/dst formats).
@@ -584,7 +565,7 @@ try_blit(struct svga_context *svga, const struct pipe_blit_info *blit_info)
    struct pipe_blit_info blit = *blit_info;
 
    SVGA_STATS_TIME_PUSH(sws, SVGA_STATS_TIME_BLITBLITTER);
-   
+
    /**
     * Avoid using util_blitter_blit() for these depth formats on non-vgpu10
     * devices because these depth formats only support comparison mode
@@ -641,11 +622,13 @@ try_blit(struct svga_context *svga, const struct pipe_blit_info *blit_info)
    util_blitter_save_vertex_elements(svga->blitter, (void*)svga->curr.velems);
    util_blitter_save_vertex_shader(svga->blitter, svga->curr.vs);
    util_blitter_save_geometry_shader(svga->blitter, svga->curr.user_gs);
+   util_blitter_save_tessctrl_shader(svga->blitter, svga->curr.tcs);
+   util_blitter_save_tesseval_shader(svga->blitter, svga->curr.tes);
    util_blitter_save_so_targets(svga->blitter, svga->num_so_targets,
                      (struct pipe_stream_output_target**)svga->so_targets);
    util_blitter_save_rasterizer(svga->blitter, (void*)svga->curr.rast);
-   util_blitter_save_viewport(svga->blitter, &svga->curr.viewport);
-   util_blitter_save_scissor(svga->blitter, &svga->curr.scissor);
+   util_blitter_save_viewport(svga->blitter, &svga->curr.viewport[0]);
+   util_blitter_save_scissor(svga->blitter, &svga->curr.scissor[0]);
    util_blitter_save_fragment_shader(svga->blitter, svga->curr.fs);
    util_blitter_save_blend(svga->blitter, (void*)svga->curr.blend);
    util_blitter_save_depth_stencil_alpha(svga->blitter,
@@ -846,7 +829,6 @@ svga_resource_copy_region(struct pipe_context *pipe,
    if (dst_tex->target == PIPE_BUFFER && src_tex->target == PIPE_BUFFER) {
       /* can't copy within the same buffer, unfortunately */
       if (svga_have_vgpu10(svga) && src_tex != dst_tex) {
-         enum pipe_error ret;
          struct svga_winsys_surface *src_surf;
          struct svga_winsys_surface *dst_surf;
          struct svga_buffer *dbuffer = svga_buffer(dst_tex);
@@ -855,15 +837,9 @@ svga_resource_copy_region(struct pipe_context *pipe,
          src_surf = svga_buffer_handle(svga, src_tex, sbuffer->bind_flags);
          dst_surf = svga_buffer_handle(svga, dst_tex, dbuffer->bind_flags);
 
-         ret = SVGA3D_vgpu10_BufferCopy(svga->swc, src_surf, dst_surf,
-                                        src_box->x, dstx, src_box->width);
-         if (ret != PIPE_OK) {
-            svga_context_flush(svga, NULL);
-            ret = SVGA3D_vgpu10_BufferCopy(svga->swc, src_surf, dst_surf,
-                                           src_box->x, dstx, src_box->width);
-            assert(ret == PIPE_OK);
-         }
-
+         SVGA_RETRY(svga, SVGA3D_vgpu10_BufferCopy(svga->swc, src_surf,
+                                                   dst_surf, src_box->x, dstx,
+                                                   src_box->width));
          dbuffer->dirty = TRUE;
       }
       else {