Introduce write_fence2

Bug: 193809913
Change-Id: I116e2cca3fce84a5203da8c9914bc8ee679bac83
diff --git a/stream-servers/virglrenderer.h b/stream-servers/virglrenderer.h
index a2d2ebf..4dcc66c 100644
--- a/stream-servers/virglrenderer.h
+++ b/stream-servers/virglrenderer.h
@@ -47,11 +47,13 @@
 struct virgl_renderer_callbacks {
    int version;
    void (*write_fence)(void *cookie, uint32_t fence);
+   void (*write_fence2)(void *cookie, uint32_t fence, uint32_t ctx_id, uint32_t fence_ctx_idx);
 
    /* interact with GL implementation */
    virgl_renderer_gl_context (*create_gl_context)(void *cookie, int scanout_idx, struct virgl_renderer_gl_ctx_param *param);
    void (*destroy_gl_context)(void *cookie, virgl_renderer_gl_context ctx);
    int (*make_current)(void *cookie, int scanout_idx, virgl_renderer_gl_context ctx);
+
 };
 
 /* virtio-gpu compatible interface */
diff --git a/stream-servers/virtio-gpu-gfxstream-renderer.cpp b/stream-servers/virtio-gpu-gfxstream-renderer.cpp
index ea81df7..6a2dcf7 100644
--- a/stream-servers/virtio-gpu-gfxstream-renderer.cpp
+++ b/stream-servers/virtio-gpu-gfxstream-renderer.cpp
@@ -917,6 +917,44 @@
         return 0;
     }
 
+    int contextCreateFence(uint32_t fence_id, uint32_t ctx_id, uint32_t fence_ctx_idx) {
+        AutoLock lock(mLock);
+        fprintf(stderr, "%s: fence id %u ctx id %u fence_ctx_idx %u\n", __func__, fence_id, ctx_id, fence_ctx_idx);
+        VGPLOG("fenceid: %u cmdtype: %u", fence_id, ctx_id);
+        if (mUseAsyncFenceCb) {
+            fprintf(stderr, "%s: create fence using async fence cb\n", __func__);
+            if (0 == ctx_id) {
+                fprintf(stderr, "%s: is 0 ctx id, signal right away as everything's serialized to this point\n", __func__);
+                mVirglRendererCallbacks.write_fence(mCookie, fence_id);
+            } else {
+                // Check what fencing type was needed.
+                AutoLock lock(mCtxPendingFencesLock);
+                {
+                    if (mCtxNeededFencingTypes.find(ctx_id) == mCtxNeededFencingTypes.end()) {
+                        fprintf(stderr, "%s: init new fencing type for ctx %u as sync signaled\n", __func__, ctx_id);
+                        mCtxNeededFencingTypes[ctx_id] = CtxFencingType::SyncSignal;
+                    } else {
+                        fprintf(stderr, "%s: this ctx had signal type of 0x%x\n", __func__,
+                                (uint32_t)(mCtxNeededFencingTypes[ctx_id]));
+                    }
+                }
+
+                fprintf(stderr, "%s: is Not 0 ctx id (%u), do not signal right away if async signal on top.. the client fence id was %d\n", __func__, ctx_id, fence_id);
+                enqueueFenceLocked(ctx_id, fence_id, mCtxNeededFencingTypes[ctx_id]);
+
+                // Regardless of what fencing type was needed, set it back to sync signal after enqueue.
+                mCtxNeededFencingTypes[ctx_id] = CtxFencingType::SyncSignal;
+
+                // Process any sync-signaled fences.
+                signalOutstandingSyncSignaledFencesLocked(ctx_id);
+            }
+        } else {
+            fprintf(stderr, "%s: create fence without async fence cb\n", __func__);
+            mFenceDeque.push_back(fence_id);
+        }
+        return 0;
+    }
+
     void poll() {
         VGPLOG("start");
         AutoLock lock(mLock);
@@ -1608,7 +1646,7 @@
 
             if (pendingState.type == CtxFencingType::AsyncSignal) {
                 VGPLOG("This was an async signal, write fence, erase it and continue");
-                mVirglRendererCallbacks.write_fence(mCookie, fence_value);
+                mVirglRendererCallbacks.write_fence2(mCookie, fence_value, ctx_id, 0 /* ring idx */);
                 it = pendingFencesThisCtx.erase(it);
             } else {
                 VGPLOG("This was Not an async signal, quit and process them in subsequent call to signalOutstandingSyncSignaledFences");
@@ -1641,7 +1679,7 @@
 
             if (pendingState.type == CtxFencingType::SyncSignal) {
                 VGPLOG("This was a sync signal, write fence, erase it and continue")
-                mVirglRendererCallbacks.write_fence(mCookie, fence_value);
+                mVirglRendererCallbacks.write_fence2(mCookie, fence_value, ctx_id, 0 /* ring_idx */);
                 it = pendingFencesThisCtx.erase(it);
             } else {
                 if (CtxFencingType::AsyncSignal != pendingState.type) {
@@ -1861,6 +1899,12 @@
     return sRenderer()->resourceUnmap(res_handle);
 }
 
+VG_EXPORT int stream_renderer_context_create_fence(
+    uint32_t fence_id, uint32_t ctx_id, uint32_t fence_ctx_idx) {
+    sRenderer()->contextCreateFence(fence_id, ctx_id, fence_ctx_idx);
+    return 0;
+}
+
 
 #define VIRGLRENDERER_API_PIPE_STRUCT_DEF(api) pipe_##api,
 
diff --git a/stream-servers/virtio-gpu-gfxstream-renderer.h b/stream-servers/virtio-gpu-gfxstream-renderer.h
index 9dd7344..de5f1da 100644
--- a/stream-servers/virtio-gpu-gfxstream-renderer.h
+++ b/stream-servers/virtio-gpu-gfxstream-renderer.h
@@ -91,6 +91,8 @@
 VG_EXPORT uint32_t stream_renderer_resource_get_hv_slot(uint32_t res_handle);
 VG_EXPORT int stream_renderer_resource_map(uint32_t res_handle, void** hvaOut, uint64_t* sizeOut);
 VG_EXPORT int stream_renderer_resource_unmap(uint32_t res_handle);
+VG_EXPORT int stream_renderer_context_create_fence(
+    uint32_t fence_id, uint32_t ctx_id, uint32_t fence_ctx_idx);
 
 #else