[magma] Support for querying engines

Just hardcoded for now, this should eventually query the MSD.
Also add stub support for load balancing so even though we only
support one video engine, we handle the change in command buffer
submit semantics.

Bug:110484

Change-Id: If80f565fbc28d102e5d99ae6fa0fdfb53695a423
Reviewed-on: https://fuchsia-review.googlesource.com/c/third_party/github.com/intel/media-driver/+/731822
Reviewed-by: John Bauman <jbauman@google.com>
diff --git a/media_driver/linux/common/os/magma/mos_bufmgr_magma.cpp b/media_driver/linux/common/os/magma/mos_bufmgr_magma.cpp
index 2b703e0..dfae40e 100644
--- a/media_driver/linux/common/os/magma/mos_bufmgr_magma.cpp
+++ b/media_driver/linux/common/os/magma/mos_bufmgr_magma.cpp
@@ -40,7 +40,7 @@
 
 #define LOG_VERBOSE(msg, ...) do { \
     if (false) {\
-        fprintf(stderr, "%s:%d " msg "\n", __FILE__, __LINE__, ##__VA_ARGS__); \
+        fprintf(stderr, "mos_bufmgr_magma:%d " msg "\n", __LINE__, ##__VA_ARGS__); \
         fflush(stderr); \
     } \
 } while (0)
@@ -196,6 +196,28 @@
     return true;
 }
 
+class MagmaContext : public mos_linux_context {
+public:
+    MagmaContext(struct mos_bufmgr* bufmgr, uint32_t context_id) {
+        this->ctx_id = context_id;
+        this->bufmgr = bufmgr;
+        this->pOsContext = nullptr;
+        this->vm = nullptr;
+    }
+
+    // Should only be called once.
+    void set_target_engines(std::vector<uint32_t>&& engines) {
+        assert(!engines.empty());
+        assert(target_engines_.empty());
+        target_engines_ = std::move(engines);
+    }
+
+    const std::vector<uint32_t>& target_engines() { return target_engines_; }
+
+private:
+    std::vector<uint32_t> target_engines_;
+};
+
 static void bufmgr_destroy(struct mos_bufmgr* mos_bufmgr)
 {
     LOG_VERBOSE("bufmgr_destroy");
@@ -567,20 +589,23 @@
     }
     assert(context_id);
 
-    auto context = new mos_linux_context;
-
-    context->ctx_id = context_id;
-    context->bufmgr = bufmgr;
-    context->pOsContext = NULL;
-    context->vm = NULL;
+    auto context = new MagmaContext(mos_bufmgr, context_id);
 
     LOG_VERBOSE("mos_gem_context_create context_id %u", context_id);
 
     return context;
 }
 
-void mos_gem_context_destroy(struct mos_linux_context *context)
+struct mos_linux_context* mos_gem_context_create_ext(struct mos_bufmgr *bufmgr, __u32 flags)
 {
+    assert(flags == 0);
+    return mos_gem_context_create(bufmgr);
+}
+
+void mos_gem_context_destroy(struct mos_linux_context *mos_context)
+{
+    auto context = static_cast<MagmaContext*>(mos_context);
+
     LOG_VERBOSE("mos_gem_context_destroy context_id %u", context->ctx_id);
 
     auto bufmgr = static_cast<MagmaBufMgr*>(context->bufmgr);
@@ -590,6 +615,43 @@
     delete context;
 }
 
+int mos_set_context_param_load_balance(struct mos_linux_context *mos_context,
+    struct i915_engine_class_instance *ci, unsigned int count)
+{
+    LOG_VERBOSE("mos_set_context_param_load_balance: context_id %u count %u [%u]",
+        mos_context->ctx_id, count, count == 0 ? 0 : ci->engine_class);
+
+    // May be called with count 0 in the case mos_query_engines sets engine count to 0.
+    if (count == 0)
+        return 0;
+
+    std::vector<uint32_t> target_engines;
+
+    for (uint32_t i = 0; i < count; i++) {
+        if (ci->engine_class != I915_ENGINE_CLASS_RENDER &&
+            ci->engine_class != I915_ENGINE_CLASS_VIDEO) {
+            LOG_VERBOSE("Unhandled engine class: %u", ci->engine_class);
+            return -1;
+        }
+        if (ci->engine_instance != 0) {
+            LOG_VERBOSE("Unhandled engine instance: %u", ci->engine_instance);
+            return -1;
+        }
+        target_engines.push_back(ci->engine_class);
+    }
+
+    // Magma doesn't support load balancing so just check that we're only targetting a single
+    // video engine; however, enabling this on Linux uses I915_CONTEXT_PARAM_ENGINES which changes
+    // the meaning of the exec ring to an array index (see mos_gem_bo_context_exec2).
+    assert(target_engines.size() == 1);
+
+    auto context = static_cast<MagmaContext*>(mos_context);
+
+    context->set_target_engines(std::move(target_engines));
+
+    return 0;
+}
+
 int mos_bufmgr_gem_get_devid(struct mos_bufmgr *mos_bufmgr)
 {
     auto bufmgr = static_cast<MagmaBufMgr*>(mos_bufmgr);
@@ -605,18 +667,59 @@
     return true;
 }
 
-int mos_gem_bo_context_exec2(struct mos_linux_bo *mos_linux_bo, int used, struct mos_linux_context *ctx,
-                           drm_clip_rect_t *cliprects, int num_cliprects, int DR4,
-                           unsigned int flags, int *fence) {
-    constexpr uint32_t kExpectedFlags = I915_EXEC_BSD|I915_EXEC_BSD_RING1|I915_EXEC_RENDER;
+static uint64_t get_magma_flags(MagmaContext* context, uint32_t exec_ring)
+{
+    uint64_t flags = 0;
 
+    if (context->target_engines().size()) {
+        if (exec_ring >= context->target_engines().size()) {
+            LOG_VERBOSE("Unexpected exec ring index: %u", exec_ring);
+            assert(false);
+        } else {
+            uint32_t engine = context->target_engines()[exec_ring];
+            switch (engine) {
+                case I915_ENGINE_CLASS_RENDER:
+                    flags |= kMagmaIntelGenCommandBufferForRender;
+                    break;
+                case I915_ENGINE_CLASS_VIDEO:
+                    flags |= kMagmaIntelGenCommandBufferForVideo;
+                    break;
+                default:
+                    LOG_VERBOSE("Unrecognized engine: %u", engine);
+                    assert(false);
+            }
+        }
+    } else switch (exec_ring) {
+        case I915_EXEC_RENDER:
+            flags |= kMagmaIntelGenCommandBufferForRender;
+            break;
+        case I915_EXEC_BSD:
+            flags |= kMagmaIntelGenCommandBufferForVideo;
+            break;
+        default:
+            LOG_VERBOSE("unexpected ring 0x%x", exec_ring);
+            assert(false);
+    }
+
+    return flags;
+}
+
+int mos_gem_bo_context_exec2(struct mos_linux_bo *mos_linux_bo, int used, struct mos_linux_context *mos_context,
+    drm_clip_rect_t *cliprects, int num_cliprects, int DR4, unsigned int flags, int *fence) {
+
+    constexpr uint32_t kAllowedFlags = I915_EXEC_BSD|I915_EXEC_BSD_RING1|I915_EXEC_RENDER;
+
+    assert((flags & ~kAllowedFlags) == 0); // only these flags
+
+    auto context = static_cast<MagmaContext*>(mos_context);
     auto bo = static_cast<MagmaBo*>(mos_linux_bo);
-    auto bufmgr = static_cast<MagmaBufMgr*>(ctx->bufmgr);
+    auto bufmgr = static_cast<MagmaBufMgr*>(context->bufmgr);
 
-    LOG_VERBOSE("mos_gem_bo_context_exec2 bo %lu used %d context_id %u num_cliprects %d DR4 %d flags 0x%x kExpectedFlags 0x%x",
-        bo->id(), used, ctx->ctx_id, num_cliprects, DR4, flags, kExpectedFlags);
+    uint64_t magma_flags = get_magma_flags(context, flags & I915_EXEC_RING_MASK);
 
-    assert((flags & ~kExpectedFlags) == 0); // only these flags
+    LOG_VERBOSE("mos_gem_bo_context_exec2 bo %lu used %d context_id %u num_cliprects %d DR4 %d "
+        "flags 0x%x kAllowedFlags 0x%x magma_flags 0x%lx",
+        bo->id(), used, context->ctx_id, num_cliprects, DR4, flags, kAllowedFlags, magma_flags);
 
     // TODO(fxbug.78281)
     uint64_t* semaphore_ids = nullptr;
@@ -627,18 +730,6 @@
         .resource_index = 0,
         .start_offset = 0
     };
-    int magma_flags = 0;
-    switch (flags & I915_EXEC_RING_MASK) {
-        case I915_EXEC_RENDER:
-            magma_flags = 0;
-            break;
-        case I915_EXEC_BSD:
-            magma_flags = kMagmaIntelGenCommandBufferForVideo;
-            break;
-        default:
-            LOG_VERBOSE("unexpected ring 0x%x", flags & I915_EXEC_RING_MASK);
-            assert(false);
-    }
 
     magma_command_descriptor descriptor = {
         .resource_count = resources.size(),
@@ -660,7 +751,7 @@
 
 
     magma_status_t status = magma_execute_command(bo->magma_bufmgr()->connection(),
-        ctx->ctx_id, &descriptor);
+        context->ctx_id, &descriptor);
 
     if (status != MAGMA_STATUS_OK) {
         LOG_VERBOSE("magma_execute_command failed: %d", status);
@@ -740,3 +831,42 @@
 {
     return bufmgr_bo_unmap(bo);
 }
+
+int mos_query_engines_count(struct mos_bufmgr *bufmgr, unsigned int *nengine)
+{
+    // TODO(fxbug.dev/110484) - query the MSD for set of available engines
+    *nengine = 2;
+    return 0;
+}
+
+int mos_query_engines(struct mos_bufmgr *bufmgr,
+                      __u16 engine_class,
+                      __u64 caps,
+                      unsigned int *nengine,
+                      struct i915_engine_class_instance *ci)
+{
+    unsigned int max = *nengine;
+
+    LOG_VERBOSE("mos_query_engines: class %u max %u", engine_class, max);
+
+    *nengine = 0;
+
+    // TODO(fxbug.dev/110484) - query the MSD for set of available engines
+    switch (engine_class) {
+        case I915_ENGINE_CLASS_RENDER:
+        case I915_ENGINE_CLASS_VIDEO:
+            if (*nengine >= max) {
+                LOG_VERBOSE("Can't report engines max %u", max);
+                return -1;
+            }
+            ci[*nengine].engine_class = engine_class;
+            ci[*nengine].engine_instance = 0;
+            *nengine += 1;
+            break;
+        default:
+            LOG_VERBOSE("mos_query_engines: class %u not supported", engine_class);
+            break;
+    }
+
+    return 0;
+}
diff --git a/media_driver/linux/common/os/magma/mos_bufmgr_stub.c b/media_driver/linux/common/os/magma/mos_bufmgr_stub.c
index a2db382..cc8d0b1 100644
--- a/media_driver/linux/common/os/magma/mos_bufmgr_stub.c
+++ b/media_driver/linux/common/os/magma/mos_bufmgr_stub.c
@@ -29,7 +29,7 @@
 
 #define LOG_VERBOSE(msg, ...) do { \
     if (true) \
-        fprintf(stderr, "%s:%d " msg "\n", __FILE__, __LINE__, ##__VA_ARGS__); \
+        fprintf(stderr, "mos_bufmgr_stub:%d " msg "\n", __LINE__, ##__VA_ARGS__); \
         fflush(stderr); \
 } while (0)
 
@@ -76,24 +76,6 @@
     return -1;
 }
 
-int mos_query_engines_count(struct mos_bufmgr *bufmgr,
-                      unsigned int *nengine)
-
-{
-    LOG_VERBOSE("mos_query_engines_count unimplemented");
-    return 0;
-}
-
-int mos_query_engines(struct mos_bufmgr *bufmgr,
-                      __u16 engine_class,
-                      __u64 caps,
-                      unsigned int *nengine,
-                      struct i915_engine_class_instance *ci)
-{
-    LOG_VERBOSE("mos_query_engines unimplemented");
-    return 0;
-}
-
 int mos_get_context_param(struct mos_linux_context *ctx,
                 uint32_t size,
                 uint64_t param,
@@ -112,12 +94,6 @@
     return 0;
 }
 
-struct mos_linux_context *mos_gem_context_create_ext(struct mos_bufmgr *bufmgr, __u32 flags)
-{
-    LOG_VERBOSE("mos_gem_context_create_ext unimplemented");
-    return NULL;
-}
-
 struct drm_i915_gem_vm_control* mos_gem_vm_create(struct mos_bufmgr *bufmgr)
 {
     LOG_VERBOSE("mos_gem_vm_create unimplemented");
@@ -170,14 +146,6 @@
     return 0;
 }
 
-int mos_set_context_param_load_balance(struct mos_linux_context *ctx,
-                     struct i915_engine_class_instance *ci,
-                     unsigned int count)
-{
-    LOG_VERBOSE("mos_set_context_param_load_balance unimplemented");
-    return 0;
-}
-
 int mos_set_context_param_bond(struct mos_linux_context *ctx,
                         struct i915_engine_class_instance master_ci,
                         struct i915_engine_class_instance *bond_ci,