freedreno/a3xx/compiler: refactor trans_samp()
[mesa.git] / src / gallium / drivers / freedreno / freedreno_draw.c
index 2b7c16847dc0254fddab0192bcb41506d9c83bc2..e3c8cc8e5a0c89b79ca64a06599fcffd5b2a7dcd 100644 (file)
 #include "freedreno_context.h"
 #include "freedreno_state.h"
 #include "freedreno_resource.h"
+#include "freedreno_query_hw.h"
 #include "freedreno_util.h"
 
 
-static enum pc_di_primtype
-mode2primtype(unsigned mode)
-{
-       switch (mode) {
-       case PIPE_PRIM_POINTS:         return DI_PT_POINTLIST;
-       case PIPE_PRIM_LINES:          return DI_PT_LINELIST;
-       case PIPE_PRIM_LINE_STRIP:     return DI_PT_LINESTRIP;
-       case PIPE_PRIM_TRIANGLES:      return DI_PT_TRILIST;
-       case PIPE_PRIM_TRIANGLE_STRIP: return DI_PT_TRISTRIP;
-       case PIPE_PRIM_TRIANGLE_FAN:   return DI_PT_TRIFAN;
-       case PIPE_PRIM_QUADS:          return DI_PT_QUADLIST;
-       case PIPE_PRIM_QUAD_STRIP:     return DI_PT_QUADSTRIP;
-       case PIPE_PRIM_POLYGON:        return DI_PT_POLYGON;
-       }
-       DBG("unsupported mode: (%s) %d", u_prim_name(mode), mode);
-       assert(0);
-       return DI_PT_NONE;
-}
-
 static enum pc_di_index_size
 size2indextype(unsigned index_size)
 {
@@ -73,9 +55,10 @@ size2indextype(unsigned index_size)
 
 /* this is same for a2xx/a3xx, so split into helper: */
 void
-fd_draw_emit(struct fd_context *ctx, const struct pipe_draw_info *info)
+fd_draw_emit(struct fd_context *ctx, struct fd_ringbuffer *ring,
+               enum pc_di_vis_cull_mode vismode,
+               const struct pipe_draw_info *info)
 {
-       struct fd_ringbuffer *ring = ctx->ring;
        struct pipe_index_buffer *idx = &ctx->indexbuf;
        struct fd_bo *idx_bo = NULL;
        enum pc_di_index_size idx_type = INDEX_SIZE_IGN;
@@ -88,7 +71,7 @@ fd_draw_emit(struct fd_context *ctx, const struct pipe_draw_info *info)
                idx_bo = fd_resource(idx->buffer)->bo;
                idx_type = size2indextype(idx->index_size);
                idx_size = idx->index_size * info->count;
-               idx_offset = idx->offset;
+               idx_offset = idx->offset + (info->start * idx->index_size);
                src_sel = DI_SRC_SEL_DMA;
        } else {
                idx_bo = NULL;
@@ -98,15 +81,8 @@ fd_draw_emit(struct fd_context *ctx, const struct pipe_draw_info *info)
                src_sel = DI_SRC_SEL_AUTO_INDEX;
        }
 
-       OUT_PKT3(ring, CP_DRAW_INDX, info->indexed ? 5 : 3);
-       OUT_RING(ring, 0x00000000);        /* viz query info. */
-       OUT_RING(ring, DRAW(mode2primtype(info->mode),
-                       src_sel, idx_type, IGNORE_VISIBILITY));
-       OUT_RING(ring, info->count);       /* NumIndices */
-       if (info->indexed) {
-               OUT_RELOC(ring, idx_bo, idx_offset, 0);
-               OUT_RING (ring, idx_size);
-       }
+       fd_draw(ctx, ring, ctx->primtypes[info->mode], vismode, src_sel,
+                       info->count, idx_type, idx_size, idx_offset, idx_bo);
 }
 
 static void
@@ -114,34 +90,74 @@ fd_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info)
 {
        struct fd_context *ctx = fd_context(pctx);
        struct pipe_framebuffer_state *pfb = &ctx->framebuffer;
-       unsigned buffers;
+       struct pipe_scissor_state *scissor = fd_context_get_scissor(ctx);
+       unsigned i, buffers = 0;
 
        /* if we supported transform feedback, we'd have to disable this: */
-       if (((ctx->scissor.maxx - ctx->scissor.minx) *
-                       (ctx->scissor.maxy - ctx->scissor.miny)) == 0) {
+       if (((scissor->maxx - scissor->minx) *
+                       (scissor->maxy - scissor->miny)) == 0) {
+               return;
+       }
+
+       /* emulate unsupported primitives: */
+       if (!fd_supported_prim(ctx, info->mode)) {
+               util_primconvert_save_index_buffer(ctx->primconvert, &ctx->indexbuf);
+               util_primconvert_save_rasterizer_state(ctx->primconvert, ctx->rasterizer);
+               util_primconvert_draw_vbo(ctx->primconvert, info);
                return;
        }
 
        ctx->needs_flush = true;
 
-       fd_resource(pfb->cbufs[0]->texture)->dirty = true;
+       /*
+        * Figure out the buffers/features we need:
+        */
 
-       /* figure out the buffers we need: */
-       buffers = FD_BUFFER_COLOR;
        if (fd_depth_enabled(ctx)) {
                buffers |= FD_BUFFER_DEPTH;
                fd_resource(pfb->zsbuf->texture)->dirty = true;
+               ctx->gmem_reason |= FD_GMEM_DEPTH_ENABLED;
        }
+
        if (fd_stencil_enabled(ctx)) {
                buffers |= FD_BUFFER_STENCIL;
                fd_resource(pfb->zsbuf->texture)->dirty = true;
+               ctx->gmem_reason |= FD_GMEM_STENCIL_ENABLED;
        }
 
+       if (fd_logicop_enabled(ctx))
+               ctx->gmem_reason |= FD_GMEM_LOGICOP_ENABLED;
+
+       for (i = 0; i < pfb->nr_cbufs; i++) {
+               struct pipe_resource *surf;
+
+               if (!pfb->cbufs[i])
+                       continue;
+
+               surf = pfb->cbufs[i]->texture;
+
+               fd_resource(surf)->dirty = true;
+               buffers |= FD_BUFFER_COLOR;
+
+               if (surf->nr_samples > 1)
+                       ctx->gmem_reason |= FD_GMEM_MSAA_ENABLED;
+
+               if (fd_blend_enabled(ctx, i))
+                       ctx->gmem_reason |= FD_GMEM_BLEND_ENABLED;
+       }
+
+       ctx->num_draws++;
+
+       ctx->stats.draw_calls++;
+       ctx->stats.prims_emitted +=
+               u_reduced_prims_for_vertices(info->mode, info->count);
+
        /* any buffers that haven't been cleared, we need to restore: */
        ctx->restore |= buffers & (FD_BUFFER_ALL & ~ctx->cleared);
        /* and any buffers used, need to be resolved: */
        ctx->resolve |= buffers;
 
+       fd_hw_query_set_stage(ctx, ctx->ring, FD_STAGE_DRAW);
        ctx->draw(ctx, info);
 }
 
@@ -165,16 +181,21 @@ fd_clear(struct pipe_context *pctx, unsigned buffers,
        if (buffers & PIPE_CLEAR_COLOR)
                fd_resource(pfb->cbufs[0]->texture)->dirty = true;
 
-       if (buffers & (PIPE_CLEAR_DEPTH | PIPE_CLEAR_STENCIL))
+       if (buffers & (PIPE_CLEAR_DEPTH | PIPE_CLEAR_STENCIL)) {
                fd_resource(pfb->zsbuf->texture)->dirty = true;
+               ctx->gmem_reason |= FD_GMEM_CLEARS_DEPTH_STENCIL;
+       }
 
        DBG("%x depth=%f, stencil=%u (%s/%s)", buffers, depth, stencil,
-                       util_format_name(pfb->cbufs[0]->format),
-                       pfb->zsbuf ? util_format_name(pfb->zsbuf->format) : "none");
+               util_format_short_name(pipe_surface_format(pfb->cbufs[0])),
+               util_format_short_name(pipe_surface_format(pfb->zsbuf)));
+
+       fd_hw_query_set_stage(ctx, ctx->ring, FD_STAGE_CLEAR);
 
        ctx->clear(ctx, buffers, color, depth, stencil);
 
        ctx->dirty |= FD_DIRTY_ZSA |
+                       FD_DIRTY_VIEWPORT |
                        FD_DIRTY_RASTERIZER |
                        FD_DIRTY_SAMPLE_MASK |
                        FD_DIRTY_PROG |