15a0915870c7e994d20334042b7647db749e79224Ben Skeggs/*
25a0915870c7e994d20334042b7647db749e79224Ben Skeggs * Copyright 2010 Christoph Bumiller
35a0915870c7e994d20334042b7647db749e79224Ben Skeggs *
45a0915870c7e994d20334042b7647db749e79224Ben Skeggs * Permission is hereby granted, free of charge, to any person obtaining a
55a0915870c7e994d20334042b7647db749e79224Ben Skeggs * copy of this software and associated documentation files (the "Software"),
65a0915870c7e994d20334042b7647db749e79224Ben Skeggs * to deal in the Software without restriction, including without limitation
75a0915870c7e994d20334042b7647db749e79224Ben Skeggs * the rights to use, copy, modify, merge, publish, distribute, sublicense,
85a0915870c7e994d20334042b7647db749e79224Ben Skeggs * and/or sell copies of the Software, and to permit persons to whom the
95a0915870c7e994d20334042b7647db749e79224Ben Skeggs * Software is furnished to do so, subject to the following conditions:
105a0915870c7e994d20334042b7647db749e79224Ben Skeggs *
115a0915870c7e994d20334042b7647db749e79224Ben Skeggs * The above copyright notice and this permission notice shall be included in
125a0915870c7e994d20334042b7647db749e79224Ben Skeggs * all copies or substantial portions of the Software.
135a0915870c7e994d20334042b7647db749e79224Ben Skeggs *
145a0915870c7e994d20334042b7647db749e79224Ben Skeggs * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
155a0915870c7e994d20334042b7647db749e79224Ben Skeggs * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
165a0915870c7e994d20334042b7647db749e79224Ben Skeggs * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
175a0915870c7e994d20334042b7647db749e79224Ben Skeggs * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
185a0915870c7e994d20334042b7647db749e79224Ben Skeggs * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
195a0915870c7e994d20334042b7647db749e79224Ben Skeggs * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
205a0915870c7e994d20334042b7647db749e79224Ben Skeggs * SOFTWARE.
215a0915870c7e994d20334042b7647db749e79224Ben Skeggs */
225a0915870c7e994d20334042b7647db749e79224Ben Skeggs
235a0915870c7e994d20334042b7647db749e79224Ben Skeggs#include "util/u_double_list.h"
245a0915870c7e994d20334042b7647db749e79224Ben Skeggs
255a0915870c7e994d20334042b7647db749e79224Ben Skeggs#include "nouveau_screen.h"
266d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller#include "nouveau_winsys.h"
275a0915870c7e994d20334042b7647db749e79224Ben Skeggs#include "nouveau_fence.h"
285a0915870c7e994d20334042b7647db749e79224Ben Skeggs
295a0915870c7e994d20334042b7647db749e79224Ben Skeggs#ifdef PIPE_OS_UNIX
305a0915870c7e994d20334042b7647db749e79224Ben Skeggs#include <sched.h>
315a0915870c7e994d20334042b7647db749e79224Ben Skeggs#endif
325a0915870c7e994d20334042b7647db749e79224Ben Skeggs
335a0915870c7e994d20334042b7647db749e79224Ben Skeggsboolean
345a0915870c7e994d20334042b7647db749e79224Ben Skeggsnouveau_fence_new(struct nouveau_screen *screen, struct nouveau_fence **fence,
355a0915870c7e994d20334042b7647db749e79224Ben Skeggs                  boolean emit)
365a0915870c7e994d20334042b7647db749e79224Ben Skeggs{
375a0915870c7e994d20334042b7647db749e79224Ben Skeggs   *fence = CALLOC_STRUCT(nouveau_fence);
385a0915870c7e994d20334042b7647db749e79224Ben Skeggs   if (!*fence)
395a0915870c7e994d20334042b7647db749e79224Ben Skeggs      return FALSE;
405a0915870c7e994d20334042b7647db749e79224Ben Skeggs
415a0915870c7e994d20334042b7647db749e79224Ben Skeggs   (*fence)->screen = screen;
425a0915870c7e994d20334042b7647db749e79224Ben Skeggs   (*fence)->ref = 1;
435a0915870c7e994d20334042b7647db749e79224Ben Skeggs   LIST_INITHEAD(&(*fence)->work);
445a0915870c7e994d20334042b7647db749e79224Ben Skeggs
455a0915870c7e994d20334042b7647db749e79224Ben Skeggs   if (emit)
465a0915870c7e994d20334042b7647db749e79224Ben Skeggs      nouveau_fence_emit(*fence);
475a0915870c7e994d20334042b7647db749e79224Ben Skeggs
485a0915870c7e994d20334042b7647db749e79224Ben Skeggs   return TRUE;
495a0915870c7e994d20334042b7647db749e79224Ben Skeggs}
505a0915870c7e994d20334042b7647db749e79224Ben Skeggs
515a0915870c7e994d20334042b7647db749e79224Ben Skeggsstatic void
525a0915870c7e994d20334042b7647db749e79224Ben Skeggsnouveau_fence_trigger_work(struct nouveau_fence *fence)
535a0915870c7e994d20334042b7647db749e79224Ben Skeggs{
545a0915870c7e994d20334042b7647db749e79224Ben Skeggs   struct nouveau_fence_work *work, *tmp;
555a0915870c7e994d20334042b7647db749e79224Ben Skeggs
565a0915870c7e994d20334042b7647db749e79224Ben Skeggs   LIST_FOR_EACH_ENTRY_SAFE(work, tmp, &fence->work, list) {
575a0915870c7e994d20334042b7647db749e79224Ben Skeggs      work->func(work->data);
585a0915870c7e994d20334042b7647db749e79224Ben Skeggs      LIST_DEL(&work->list);
595a0915870c7e994d20334042b7647db749e79224Ben Skeggs      FREE(work);
605a0915870c7e994d20334042b7647db749e79224Ben Skeggs   }
615a0915870c7e994d20334042b7647db749e79224Ben Skeggs}
625a0915870c7e994d20334042b7647db749e79224Ben Skeggs
635a0915870c7e994d20334042b7647db749e79224Ben Skeggsboolean
645a0915870c7e994d20334042b7647db749e79224Ben Skeggsnouveau_fence_work(struct nouveau_fence *fence,
655a0915870c7e994d20334042b7647db749e79224Ben Skeggs                   void (*func)(void *), void *data)
665a0915870c7e994d20334042b7647db749e79224Ben Skeggs{
675a0915870c7e994d20334042b7647db749e79224Ben Skeggs   struct nouveau_fence_work *work;
685a0915870c7e994d20334042b7647db749e79224Ben Skeggs
695a0915870c7e994d20334042b7647db749e79224Ben Skeggs   if (!fence || fence->state == NOUVEAU_FENCE_STATE_SIGNALLED) {
705a0915870c7e994d20334042b7647db749e79224Ben Skeggs      func(data);
715a0915870c7e994d20334042b7647db749e79224Ben Skeggs      return TRUE;
725a0915870c7e994d20334042b7647db749e79224Ben Skeggs   }
735a0915870c7e994d20334042b7647db749e79224Ben Skeggs
745a0915870c7e994d20334042b7647db749e79224Ben Skeggs   work = CALLOC_STRUCT(nouveau_fence_work);
755a0915870c7e994d20334042b7647db749e79224Ben Skeggs   if (!work)
765a0915870c7e994d20334042b7647db749e79224Ben Skeggs      return FALSE;
775a0915870c7e994d20334042b7647db749e79224Ben Skeggs   work->func = func;
785a0915870c7e994d20334042b7647db749e79224Ben Skeggs   work->data = data;
795a0915870c7e994d20334042b7647db749e79224Ben Skeggs   LIST_ADD(&work->list, &fence->work);
805a0915870c7e994d20334042b7647db749e79224Ben Skeggs   return TRUE;
815a0915870c7e994d20334042b7647db749e79224Ben Skeggs}
825a0915870c7e994d20334042b7647db749e79224Ben Skeggs
835a0915870c7e994d20334042b7647db749e79224Ben Skeggsvoid
845a0915870c7e994d20334042b7647db749e79224Ben Skeggsnouveau_fence_emit(struct nouveau_fence *fence)
855a0915870c7e994d20334042b7647db749e79224Ben Skeggs{
865a0915870c7e994d20334042b7647db749e79224Ben Skeggs   struct nouveau_screen *screen = fence->screen;
875a0915870c7e994d20334042b7647db749e79224Ben Skeggs
885a0915870c7e994d20334042b7647db749e79224Ben Skeggs   assert(fence->state == NOUVEAU_FENCE_STATE_AVAILABLE);
895a0915870c7e994d20334042b7647db749e79224Ben Skeggs
904388817a678431146744a030bc7c0b8c01da9f72Christoph Bumiller   /* set this now, so that if fence.emit triggers a flush we don't recurse */
919849f366cbfd781ebeca725058029b70c96836f9Marcin Slusarz   fence->state = NOUVEAU_FENCE_STATE_EMITTING;
924388817a678431146744a030bc7c0b8c01da9f72Christoph Bumiller
935a0915870c7e994d20334042b7647db749e79224Ben Skeggs   ++fence->ref;
945a0915870c7e994d20334042b7647db749e79224Ben Skeggs
955a0915870c7e994d20334042b7647db749e79224Ben Skeggs   if (screen->fence.tail)
965a0915870c7e994d20334042b7647db749e79224Ben Skeggs      screen->fence.tail->next = fence;
975a0915870c7e994d20334042b7647db749e79224Ben Skeggs   else
985a0915870c7e994d20334042b7647db749e79224Ben Skeggs      screen->fence.head = fence;
995a0915870c7e994d20334042b7647db749e79224Ben Skeggs
1005a0915870c7e994d20334042b7647db749e79224Ben Skeggs   screen->fence.tail = fence;
10165b8eea0644fdb7e9150d0e98c06d7f8ba6d5302Marcin Slusarz
1029849f366cbfd781ebeca725058029b70c96836f9Marcin Slusarz   screen->fence.emit(&screen->base, &fence->sequence);
1039849f366cbfd781ebeca725058029b70c96836f9Marcin Slusarz
1049849f366cbfd781ebeca725058029b70c96836f9Marcin Slusarz   assert(fence->state == NOUVEAU_FENCE_STATE_EMITTING);
1059849f366cbfd781ebeca725058029b70c96836f9Marcin Slusarz   fence->state = NOUVEAU_FENCE_STATE_EMITTED;
1065a0915870c7e994d20334042b7647db749e79224Ben Skeggs}
1075a0915870c7e994d20334042b7647db749e79224Ben Skeggs
1085a0915870c7e994d20334042b7647db749e79224Ben Skeggsvoid
1095a0915870c7e994d20334042b7647db749e79224Ben Skeggsnouveau_fence_del(struct nouveau_fence *fence)
1105a0915870c7e994d20334042b7647db749e79224Ben Skeggs{
1115a0915870c7e994d20334042b7647db749e79224Ben Skeggs   struct nouveau_fence *it;
1125a0915870c7e994d20334042b7647db749e79224Ben Skeggs   struct nouveau_screen *screen = fence->screen;
1135a0915870c7e994d20334042b7647db749e79224Ben Skeggs
1145a0915870c7e994d20334042b7647db749e79224Ben Skeggs   if (fence->state == NOUVEAU_FENCE_STATE_EMITTED ||
1155a0915870c7e994d20334042b7647db749e79224Ben Skeggs       fence->state == NOUVEAU_FENCE_STATE_FLUSHED) {
1165a0915870c7e994d20334042b7647db749e79224Ben Skeggs      if (fence == screen->fence.head) {
1175a0915870c7e994d20334042b7647db749e79224Ben Skeggs         screen->fence.head = fence->next;
1185a0915870c7e994d20334042b7647db749e79224Ben Skeggs         if (!screen->fence.head)
1195a0915870c7e994d20334042b7647db749e79224Ben Skeggs            screen->fence.tail = NULL;
1205a0915870c7e994d20334042b7647db749e79224Ben Skeggs      } else {
1215a0915870c7e994d20334042b7647db749e79224Ben Skeggs         for (it = screen->fence.head; it && it->next != fence; it = it->next);
1225a0915870c7e994d20334042b7647db749e79224Ben Skeggs         it->next = fence->next;
1235a0915870c7e994d20334042b7647db749e79224Ben Skeggs         if (screen->fence.tail == fence)
1245a0915870c7e994d20334042b7647db749e79224Ben Skeggs            screen->fence.tail = it;
1255a0915870c7e994d20334042b7647db749e79224Ben Skeggs      }
1265a0915870c7e994d20334042b7647db749e79224Ben Skeggs   }
1275a0915870c7e994d20334042b7647db749e79224Ben Skeggs
1285a0915870c7e994d20334042b7647db749e79224Ben Skeggs   if (!LIST_IS_EMPTY(&fence->work)) {
1295a0915870c7e994d20334042b7647db749e79224Ben Skeggs      debug_printf("WARNING: deleting fence with work still pending !\n");
1305a0915870c7e994d20334042b7647db749e79224Ben Skeggs      nouveau_fence_trigger_work(fence);
1315a0915870c7e994d20334042b7647db749e79224Ben Skeggs   }
1325a0915870c7e994d20334042b7647db749e79224Ben Skeggs
1335a0915870c7e994d20334042b7647db749e79224Ben Skeggs   FREE(fence);
1345a0915870c7e994d20334042b7647db749e79224Ben Skeggs}
1355a0915870c7e994d20334042b7647db749e79224Ben Skeggs
1365a0915870c7e994d20334042b7647db749e79224Ben Skeggsvoid
1375a0915870c7e994d20334042b7647db749e79224Ben Skeggsnouveau_fence_update(struct nouveau_screen *screen, boolean flushed)
1385a0915870c7e994d20334042b7647db749e79224Ben Skeggs{
1395a0915870c7e994d20334042b7647db749e79224Ben Skeggs   struct nouveau_fence *fence;
1405a0915870c7e994d20334042b7647db749e79224Ben Skeggs   struct nouveau_fence *next = NULL;
1415a0915870c7e994d20334042b7647db749e79224Ben Skeggs   u32 sequence = screen->fence.update(&screen->base);
1425a0915870c7e994d20334042b7647db749e79224Ben Skeggs
1435a0915870c7e994d20334042b7647db749e79224Ben Skeggs   if (screen->fence.sequence_ack == sequence)
1445a0915870c7e994d20334042b7647db749e79224Ben Skeggs      return;
1455a0915870c7e994d20334042b7647db749e79224Ben Skeggs   screen->fence.sequence_ack = sequence;
1465a0915870c7e994d20334042b7647db749e79224Ben Skeggs
1475a0915870c7e994d20334042b7647db749e79224Ben Skeggs   for (fence = screen->fence.head; fence; fence = next) {
1485a0915870c7e994d20334042b7647db749e79224Ben Skeggs      next = fence->next;
1495a0915870c7e994d20334042b7647db749e79224Ben Skeggs      sequence = fence->sequence;
1505a0915870c7e994d20334042b7647db749e79224Ben Skeggs
1515a0915870c7e994d20334042b7647db749e79224Ben Skeggs      fence->state = NOUVEAU_FENCE_STATE_SIGNALLED;
1525a0915870c7e994d20334042b7647db749e79224Ben Skeggs
1535a0915870c7e994d20334042b7647db749e79224Ben Skeggs      nouveau_fence_trigger_work(fence);
1545a0915870c7e994d20334042b7647db749e79224Ben Skeggs      nouveau_fence_ref(NULL, &fence);
1555a0915870c7e994d20334042b7647db749e79224Ben Skeggs
1565a0915870c7e994d20334042b7647db749e79224Ben Skeggs      if (sequence == screen->fence.sequence_ack)
1575a0915870c7e994d20334042b7647db749e79224Ben Skeggs         break;
1585a0915870c7e994d20334042b7647db749e79224Ben Skeggs   }
1595a0915870c7e994d20334042b7647db749e79224Ben Skeggs   screen->fence.head = next;
1605a0915870c7e994d20334042b7647db749e79224Ben Skeggs   if (!next)
1615a0915870c7e994d20334042b7647db749e79224Ben Skeggs      screen->fence.tail = NULL;
1625a0915870c7e994d20334042b7647db749e79224Ben Skeggs
1635a0915870c7e994d20334042b7647db749e79224Ben Skeggs   if (flushed) {
1645a0915870c7e994d20334042b7647db749e79224Ben Skeggs      for (fence = next; fence; fence = fence->next)
1659849f366cbfd781ebeca725058029b70c96836f9Marcin Slusarz         if (fence->state == NOUVEAU_FENCE_STATE_EMITTED)
1669849f366cbfd781ebeca725058029b70c96836f9Marcin Slusarz            fence->state = NOUVEAU_FENCE_STATE_FLUSHED;
1675a0915870c7e994d20334042b7647db749e79224Ben Skeggs   }
1685a0915870c7e994d20334042b7647db749e79224Ben Skeggs}
1695a0915870c7e994d20334042b7647db749e79224Ben Skeggs
1705a0915870c7e994d20334042b7647db749e79224Ben Skeggs#define NOUVEAU_FENCE_MAX_SPINS (1 << 31)
1715a0915870c7e994d20334042b7647db749e79224Ben Skeggs
1725a0915870c7e994d20334042b7647db749e79224Ben Skeggsboolean
1735a0915870c7e994d20334042b7647db749e79224Ben Skeggsnouveau_fence_signalled(struct nouveau_fence *fence)
1745a0915870c7e994d20334042b7647db749e79224Ben Skeggs{
1755a0915870c7e994d20334042b7647db749e79224Ben Skeggs   struct nouveau_screen *screen = fence->screen;
1765a0915870c7e994d20334042b7647db749e79224Ben Skeggs
1775a0915870c7e994d20334042b7647db749e79224Ben Skeggs   if (fence->state >= NOUVEAU_FENCE_STATE_EMITTED)
1785a0915870c7e994d20334042b7647db749e79224Ben Skeggs      nouveau_fence_update(screen, FALSE);
1795a0915870c7e994d20334042b7647db749e79224Ben Skeggs
1805a0915870c7e994d20334042b7647db749e79224Ben Skeggs   return fence->state == NOUVEAU_FENCE_STATE_SIGNALLED;
1815a0915870c7e994d20334042b7647db749e79224Ben Skeggs}
1825a0915870c7e994d20334042b7647db749e79224Ben Skeggs
1835a0915870c7e994d20334042b7647db749e79224Ben Skeggsboolean
1845a0915870c7e994d20334042b7647db749e79224Ben Skeggsnouveau_fence_wait(struct nouveau_fence *fence)
1855a0915870c7e994d20334042b7647db749e79224Ben Skeggs{
1865a0915870c7e994d20334042b7647db749e79224Ben Skeggs   struct nouveau_screen *screen = fence->screen;
1875a0915870c7e994d20334042b7647db749e79224Ben Skeggs   uint32_t spins = 0;
1885a0915870c7e994d20334042b7647db749e79224Ben Skeggs
1899849f366cbfd781ebeca725058029b70c96836f9Marcin Slusarz   /* wtf, someone is waiting on a fence in flush_notify handler? */
1909849f366cbfd781ebeca725058029b70c96836f9Marcin Slusarz   assert(fence->state != NOUVEAU_FENCE_STATE_EMITTING);
1919849f366cbfd781ebeca725058029b70c96836f9Marcin Slusarz
1925a0915870c7e994d20334042b7647db749e79224Ben Skeggs   if (fence->state < NOUVEAU_FENCE_STATE_EMITTED) {
1935a0915870c7e994d20334042b7647db749e79224Ben Skeggs      nouveau_fence_emit(fence);
1945a0915870c7e994d20334042b7647db749e79224Ben Skeggs
1955a0915870c7e994d20334042b7647db749e79224Ben Skeggs      if (fence == screen->fence.current)
1965a0915870c7e994d20334042b7647db749e79224Ben Skeggs         nouveau_fence_new(screen, &screen->fence.current, FALSE);
1975a0915870c7e994d20334042b7647db749e79224Ben Skeggs   }
1985a0915870c7e994d20334042b7647db749e79224Ben Skeggs   if (fence->state < NOUVEAU_FENCE_STATE_FLUSHED)
1996d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller      nouveau_pushbuf_kick(screen->pushbuf, screen->pushbuf->channel);
2005a0915870c7e994d20334042b7647db749e79224Ben Skeggs
2015a0915870c7e994d20334042b7647db749e79224Ben Skeggs   do {
2025a0915870c7e994d20334042b7647db749e79224Ben Skeggs      nouveau_fence_update(screen, FALSE);
2035a0915870c7e994d20334042b7647db749e79224Ben Skeggs
2045a0915870c7e994d20334042b7647db749e79224Ben Skeggs      if (fence->state == NOUVEAU_FENCE_STATE_SIGNALLED)
2055a0915870c7e994d20334042b7647db749e79224Ben Skeggs         return TRUE;
2065a0915870c7e994d20334042b7647db749e79224Ben Skeggs      spins++;
2075a0915870c7e994d20334042b7647db749e79224Ben Skeggs#ifdef PIPE_OS_UNIX
2085a0915870c7e994d20334042b7647db749e79224Ben Skeggs      if (!(spins % 8)) /* donate a few cycles */
2095a0915870c7e994d20334042b7647db749e79224Ben Skeggs         sched_yield();
2105a0915870c7e994d20334042b7647db749e79224Ben Skeggs#endif
2115a0915870c7e994d20334042b7647db749e79224Ben Skeggs   } while (spins < NOUVEAU_FENCE_MAX_SPINS);
2125a0915870c7e994d20334042b7647db749e79224Ben Skeggs
2135a0915870c7e994d20334042b7647db749e79224Ben Skeggs   debug_printf("Wait on fence %u (ack = %u, next = %u) timed out !\n",
2145a0915870c7e994d20334042b7647db749e79224Ben Skeggs                fence->sequence,
2155a0915870c7e994d20334042b7647db749e79224Ben Skeggs                screen->fence.sequence_ack, screen->fence.sequence);
2165a0915870c7e994d20334042b7647db749e79224Ben Skeggs
2175a0915870c7e994d20334042b7647db749e79224Ben Skeggs   return FALSE;
2185a0915870c7e994d20334042b7647db749e79224Ben Skeggs}
2195a0915870c7e994d20334042b7647db749e79224Ben Skeggs
2205a0915870c7e994d20334042b7647db749e79224Ben Skeggsvoid
2215a0915870c7e994d20334042b7647db749e79224Ben Skeggsnouveau_fence_next(struct nouveau_screen *screen)
2225a0915870c7e994d20334042b7647db749e79224Ben Skeggs{
2239849f366cbfd781ebeca725058029b70c96836f9Marcin Slusarz   if (screen->fence.current->state < NOUVEAU_FENCE_STATE_EMITTING)
2244388817a678431146744a030bc7c0b8c01da9f72Christoph Bumiller      nouveau_fence_emit(screen->fence.current);
2254388817a678431146744a030bc7c0b8c01da9f72Christoph Bumiller
22696054375b1ea98d7827f0d4b567168fa2baeb38eMarcin Slusarz   nouveau_fence_ref(NULL, &screen->fence.current);
22796054375b1ea98d7827f0d4b567168fa2baeb38eMarcin Slusarz
2285a0915870c7e994d20334042b7647db749e79224Ben Skeggs   nouveau_fence_new(screen, &screen->fence.current, FALSE);
2295a0915870c7e994d20334042b7647db749e79224Ben Skeggs}
230