gallium: Add PIPE_CAP_BLEND_EQUATION_ADVANCED
[mesa.git] / src / gallium / drivers / virgl / virgl_tgsi.c
index 4a2271f24f4f4da5f0872300eb4c435c3ec0e609..9ec552ad6fb1acf977a47af3f68571ab61c6434f 100644 (file)
    so add a transform stage to remove things we don't want to send unless
    the receiver supports it.
 */
+
 #include "tgsi/tgsi_transform.h"
+#include "tgsi/tgsi_info.h"
 #include "virgl_context.h"
+#include "virgl_screen.h"
+
 struct virgl_transform_context {
    struct tgsi_transform_context base;
+   bool cull_enabled;
+   bool has_precise;
+   bool fake_fp64;
 };
 
+static void
+virgl_tgsi_transform_declaration(struct tgsi_transform_context *ctx,
+                                 struct tgsi_full_declaration *decl)
+{
+   switch (decl->Declaration.File) {
+   case TGSI_FILE_CONSTANT:
+      if (decl->Declaration.Dimension) {
+         if (decl->Dim.Index2D == 0)
+            decl->Declaration.Dimension = 0;
+      }
+      break;
+   default:
+      break;
+   }
+   ctx->emit_declaration(ctx, decl);
+
+}
+
 /* for now just strip out the new properties the remote doesn't understand
    yet */
 static void
 virgl_tgsi_transform_property(struct tgsi_transform_context *ctx,
                               struct tgsi_full_property *prop)
 {
+   struct virgl_transform_context *vtctx = (struct virgl_transform_context *)ctx;
    switch (prop->Property.PropertyName) {
    case TGSI_PROPERTY_NUM_CLIPDIST_ENABLED:
    case TGSI_PROPERTY_NUM_CULLDIST_ENABLED:
+      if (vtctx->cull_enabled)
+        ctx->emit_property(ctx, prop);
+      break;
    case TGSI_PROPERTY_NEXT_SHADER:
       break;
    default:
@@ -48,9 +77,33 @@ virgl_tgsi_transform_property(struct tgsi_transform_context *ctx,
    }
 }
 
-struct tgsi_token *virgl_tgsi_transform(const struct tgsi_token *tokens_in)
+static void
+virgl_tgsi_transform_instruction(struct tgsi_transform_context *ctx,
+                                struct tgsi_full_instruction *inst)
 {
+   struct virgl_transform_context *vtctx = (struct virgl_transform_context *)ctx;
+   if (vtctx->fake_fp64 &&
+       (tgsi_opcode_infer_src_type(inst->Instruction.Opcode, 0) == TGSI_TYPE_DOUBLE ||
+        tgsi_opcode_infer_dst_type(inst->Instruction.Opcode, 0) == TGSI_TYPE_DOUBLE)) {
+      debug_printf("VIRGL: ARB_gpu_shader_fp64 is exposed but not supported.");
+      return;
+   }
+
+   if (!vtctx->has_precise && inst->Instruction.Precise)
+      inst->Instruction.Precise = 0;
 
+   for (unsigned i = 0; i < inst->Instruction.NumSrcRegs; i++) {
+      if (inst->Src[i].Register.File == TGSI_FILE_CONSTANT &&
+          inst->Src[i].Register.Dimension &&
+          inst->Src[i].Dimension.Index == 0)
+         inst->Src[i].Register.Dimension = 0;
+   }
+   ctx->emit_instruction(ctx, inst);
+}
+
+struct tgsi_token *virgl_tgsi_transform(struct virgl_context *vctx, const struct tgsi_token *tokens_in)
+{
+   struct virgl_screen *vscreen = (struct virgl_screen *)vctx->base.screen;
    struct virgl_transform_context transform;
    const uint newLen = tgsi_num_tokens(tokens_in);
    struct tgsi_token *new_tokens;
@@ -60,7 +113,13 @@ struct tgsi_token *virgl_tgsi_transform(const struct tgsi_token *tokens_in)
       return NULL;
 
    memset(&transform, 0, sizeof(transform));
+   transform.base.transform_declaration = virgl_tgsi_transform_declaration;
    transform.base.transform_property = virgl_tgsi_transform_property;
+   transform.base.transform_instruction = virgl_tgsi_transform_instruction;
+   transform.cull_enabled = vscreen->caps.caps.v1.bset.has_cull;
+   transform.has_precise = vscreen->caps.caps.v2.capability_bits & VIRGL_CAP_TGSI_PRECISE;
+   transform.fake_fp64 =
+      vscreen->caps.caps.v2.capability_bits & VIRGL_CAP_FAKE_FP64;
    tgsi_transform_shader(tokens_in, new_tokens, newLen, &transform.base);
 
    return new_tokens;