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