ws_dri_bufmgr.c

Go to the documentation of this file.
00001 /**************************************************************************
00002  *
00003  * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND., USA
00004  * All Rights Reserved.
00005  *
00006  * Permission is hereby granted, free of charge, to any person obtaining a
00007  * copy of this software and associated documentation files (the
00008  * "Software"), to deal in the Software without restriction, including
00009  * without limitation the rights to use, copy, modify, merge, publish,
00010  * distribute, sub license, and/or sell copies of the Software, and to
00011  * permit persons to whom the Software is furnished to do so, subject to
00012  * the following conditions:
00013  *
00014  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00015  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00016  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
00017  * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
00018  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
00019  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
00020  * USE OR OTHER DEALINGS IN THE SOFTWARE.
00021  *
00022  * The above copyright notice and this permission notice (including the
00023  * next paragraph) shall be included in all copies or substantial portions
00024  * of the Software.
00025  *
00026  *
00027  **************************************************************************/
00028 /*
00029  * Authors: Thomas Hellström <thomas-at-tungstengraphics-dot-com>
00030  *          Keith Whitwell <keithw-at-tungstengraphics-dot-com>
00031  */
00032 
00033 #include <xf86drm.h>
00034 #include <stdlib.h>
00035 #include <stdio.h>
00036 #include "pipe/p_thread.h"
00037 #include "errno.h"
00038 #include "ws_dri_bufmgr.h"
00039 #include "string.h"
00040 #include "pipe/p_debug.h"
00041 #include "ws_dri_bufpool.h"
00042 #include "ws_dri_fencemgr.h"
00043 
00044 
00045 /*
00046  * This lock is here to protect drmBO structs changing underneath us during a
00047  * validate list call, since validatelist cannot take individiual locks for
00048  * each drmBO. Validatelist takes this lock in write mode. Any access to an
00049  * individual drmBO should take this lock in read mode, since in that case, the
00050  * driBufferObject mutex will protect the access. Locking order is
00051  * driBufferObject mutex - > this rw lock.
00052  */
00053 
00054 pipe_static_mutex(bmMutex);
00055 pipe_static_condvar(bmCond);
00056 
00057 static int kernelReaders = 0;
00058 static int num_buffers = 0;
00059 static int num_user_buffers = 0;
00060 
00061 static drmBO *drmBOListBuf(void *iterator)
00062 {
00063     drmBONode *node;
00064     drmMMListHead *l = (drmMMListHead *) iterator;
00065     node = DRMLISTENTRY(drmBONode, l, head);
00066     return node->buf;
00067 }
00068 
00069 static void *drmBOListIterator(drmBOList *list)
00070 {
00071     void *ret = list->list.next;
00072 
00073     if (ret == &list->list)
00074         return NULL;
00075     return ret;
00076 }
00077 
00078 static void *drmBOListNext(drmBOList *list, void *iterator)
00079 {
00080     void *ret;
00081 
00082     drmMMListHead *l = (drmMMListHead *) iterator;
00083     ret = l->next;
00084     if (ret == &list->list)
00085         return NULL;
00086     return ret;
00087 }
00088 
00089 static drmBONode *drmAddListItem(drmBOList *list, drmBO *item,
00090                                  uint64_t arg0,
00091                                  uint64_t arg1)
00092 {
00093     drmBONode *node;
00094     drmMMListHead *l;
00095 
00096     l = list->free.next;
00097     if (l == &list->free) {
00098         node = (drmBONode *) malloc(sizeof(*node));
00099         if (!node) {
00100             return NULL;
00101         }
00102         list->numCurrent++;
00103     }
00104     else {
00105         DRMLISTDEL(l);
00106         node = DRMLISTENTRY(drmBONode, l, head);
00107     }
00108     node->buf = item;
00109     node->arg0 = arg0;
00110     node->arg1 = arg1;
00111     DRMLISTADD(&node->head, &list->list);
00112     list->numOnList++;
00113     return node;
00114 }
00115 
00116 static int drmAddValidateItem(drmBOList *list, drmBO *buf, uint64_t flags,
00117                               uint64_t mask, int *newItem)
00118 {
00119     drmBONode *node, *cur;
00120     drmMMListHead *l;
00121 
00122     *newItem = 0;
00123     cur = NULL;
00124 
00125     for (l = list->list.next; l != &list->list; l = l->next) {
00126         node = DRMLISTENTRY(drmBONode, l, head);
00127         if (node->buf == buf) {
00128             cur = node;
00129             break;
00130         }
00131     }
00132     if (!cur) {
00133         cur = drmAddListItem(list, buf, flags, mask);
00134         if (!cur) {
00135             return -ENOMEM;
00136         }
00137         *newItem = 1;
00138         cur->arg0 = flags;
00139         cur->arg1 = mask;
00140     }
00141     else {
00142         uint64_t memFlags = cur->arg0 & flags & DRM_BO_MASK_MEM;
00143         uint64_t accFlags = (cur->arg0 | flags) & ~DRM_BO_MASK_MEM;
00144 
00145         if (mask & cur->arg1 & ~DRM_BO_MASK_MEM  & (cur->arg0 ^ flags)) {
00146             return -EINVAL;
00147         }
00148 
00149         cur->arg1 |= mask;
00150         cur->arg0 = (cur->arg0 & ~mask) | ((memFlags | accFlags) & mask);
00151 
00152         if (((cur->arg1 & DRM_BO_MASK_MEM) != 0) &&
00153             (cur->arg0 & DRM_BO_MASK_MEM) == 0) {
00154             return -EINVAL;
00155         }
00156     }
00157     return 0;
00158 }
00159 
00160 static void drmBOFreeList(drmBOList *list)
00161 {
00162     drmBONode *node;
00163     drmMMListHead *l;
00164 
00165     l = list->list.next;
00166     while(l != &list->list) {
00167         DRMLISTDEL(l);
00168         node = DRMLISTENTRY(drmBONode, l, head);
00169         free(node);
00170         l = list->list.next;
00171         list->numCurrent--;
00172         list->numOnList--;
00173     }
00174 
00175     l = list->free.next;
00176     while(l != &list->free) {
00177         DRMLISTDEL(l);
00178         node = DRMLISTENTRY(drmBONode, l, head);
00179         free(node);
00180         l = list->free.next;
00181         list->numCurrent--;
00182     }
00183 }
00184 
00185 static int drmAdjustListNodes(drmBOList *list)
00186 {
00187     drmBONode *node;
00188     drmMMListHead *l;
00189     int ret = 0;
00190 
00191     while(list->numCurrent < list->numTarget) {
00192         node = (drmBONode *) malloc(sizeof(*node));
00193         if (!node) {
00194             ret = -ENOMEM;
00195             break;
00196         }
00197         list->numCurrent++;
00198         DRMLISTADD(&node->head, &list->free);
00199     }
00200 
00201     while(list->numCurrent > list->numTarget) {
00202         l = list->free.next;
00203         if (l == &list->free)
00204             break;
00205         DRMLISTDEL(l);
00206         node = DRMLISTENTRY(drmBONode, l, head);
00207         free(node);
00208         list->numCurrent--;
00209     }
00210     return ret;
00211 }
00212 
00213 static int drmBOCreateList(int numTarget, drmBOList *list)
00214 {
00215     DRMINITLISTHEAD(&list->list);
00216     DRMINITLISTHEAD(&list->free);
00217     list->numTarget = numTarget;
00218     list->numCurrent = 0;
00219     list->numOnList = 0;
00220     return drmAdjustListNodes(list);
00221 }
00222 
00223 static int drmBOResetList(drmBOList *list)
00224 {
00225     drmMMListHead *l;
00226     int ret;
00227 
00228     ret = drmAdjustListNodes(list);
00229     if (ret)
00230         return ret;
00231 
00232     l = list->list.next;
00233     while (l != &list->list) {
00234         DRMLISTDEL(l);
00235         DRMLISTADD(l, &list->free);
00236         list->numOnList--;
00237         l = list->list.next;
00238     }
00239     return drmAdjustListNodes(list);
00240 }
00241 
00242 void driWriteLockKernelBO(void)
00243 {
00244     pipe_mutex_lock(bmMutex);
00245     while(kernelReaders != 0)
00246         pipe_condvar_wait(bmCond, bmMutex);
00247 }
00248 
00249 void driWriteUnlockKernelBO(void)
00250 {
00251     pipe_mutex_unlock(bmMutex);
00252 }
00253 
00254 void driReadLockKernelBO(void)
00255 {
00256     pipe_mutex_lock(bmMutex);
00257     kernelReaders++;
00258     pipe_mutex_unlock(bmMutex);
00259 }
00260 
00261 void driReadUnlockKernelBO(void)
00262 {
00263     pipe_mutex_lock(bmMutex);
00264     if (--kernelReaders == 0)
00265        pipe_condvar_broadcast(bmCond);
00266     pipe_mutex_unlock(bmMutex);
00267 }
00268 
00269 
00270 
00271 
00272 /*
00273  * TODO: Introduce fence pools in the same way as
00274  * buffer object pools.
00275  */
00276 
00277 typedef struct _DriBufferObject
00278 {
00279    DriBufferPool *pool;
00280    pipe_mutex mutex;
00281    int refCount;
00282    const char *name;
00283    uint64_t flags;
00284    unsigned hint;
00285    unsigned alignment;
00286    unsigned createdByReference;
00287    void *private;
00288    /* user-space buffer: */
00289    unsigned userBuffer;
00290    void *userData;
00291    unsigned userSize;
00292 } DriBufferObject;
00293 
00294 typedef struct _DriBufferList {
00295     drmBOList drmBuffers;  /* List of kernel buffers needing validation */
00296     drmBOList driBuffers;  /* List of user-space buffers needing validation */
00297 } DriBufferList;
00298 
00299 
00300 void
00301 bmError(int val, const char *file, const char *function, int line)
00302 {
00303    printf("Fatal video memory manager error \"%s\".\n"
00304           "Check kernel logs or set the LIBGL_DEBUG\n"
00305           "environment variable to \"verbose\" for more info.\n"
00306           "Detected in file %s, line %d, function %s.\n",
00307           strerror(-val), file, line, function);
00308 #ifndef NDEBUG
00309    abort();
00310 #else
00311    abort();
00312 #endif
00313 }
00314 
00315 extern drmBO *
00316 driBOKernel(struct _DriBufferObject *buf)
00317 {
00318    drmBO *ret;
00319 
00320    driReadLockKernelBO();
00321    pipe_mutex_lock(buf->mutex);
00322    assert(buf->private != NULL);
00323    ret = buf->pool->kernel(buf->pool, buf->private);
00324    if (!ret)
00325       BM_CKFATAL(-EINVAL);
00326    pipe_mutex_unlock(buf->mutex);
00327    driReadUnlockKernelBO();
00328 
00329    return ret;
00330 }
00331 
00332 void
00333 driBOWaitIdle(struct _DriBufferObject *buf, int lazy)
00334 {
00335 
00336   /*
00337    * This function may block. Is it sane to keep the mutex held during
00338    * that time??
00339    */
00340 
00341    pipe_mutex_lock(buf->mutex);
00342    BM_CKFATAL(buf->pool->waitIdle(buf->pool, buf->private, &buf->mutex, lazy));
00343    pipe_mutex_unlock(buf->mutex);
00344 }
00345 
00346 void *
00347 driBOMap(struct _DriBufferObject *buf, unsigned flags, unsigned hint)
00348 {
00349    void *virtual;
00350    int retval;
00351 
00352    if (buf->userBuffer) {
00353       return buf->userData;
00354    }
00355 
00356    pipe_mutex_lock(buf->mutex);
00357    assert(buf->private != NULL);
00358    retval = buf->pool->map(buf->pool, buf->private, flags, hint,
00359                            &buf->mutex, &virtual);
00360    pipe_mutex_unlock(buf->mutex);
00361 
00362    return retval == 0 ? virtual : NULL;
00363 }
00364 
00365 void
00366 driBOUnmap(struct _DriBufferObject *buf)
00367 {
00368    if (buf->userBuffer)
00369       return;
00370 
00371    assert(buf->private != NULL);
00372    pipe_mutex_lock(buf->mutex);
00373    BM_CKFATAL(buf->pool->unmap(buf->pool, buf->private));
00374    pipe_mutex_unlock(buf->mutex);
00375 }
00376 
00377 unsigned long
00378 driBOOffset(struct _DriBufferObject *buf)
00379 {
00380    unsigned long ret;
00381 
00382    assert(buf->private != NULL);
00383 
00384    pipe_mutex_lock(buf->mutex);
00385    ret = buf->pool->offset(buf->pool, buf->private);
00386    pipe_mutex_unlock(buf->mutex);
00387    return ret;
00388 }
00389 
00390 unsigned long
00391 driBOPoolOffset(struct _DriBufferObject *buf)
00392 {
00393    unsigned long ret;
00394 
00395    assert(buf->private != NULL);
00396 
00397    pipe_mutex_lock(buf->mutex);
00398    ret = buf->pool->poolOffset(buf->pool, buf->private);
00399    pipe_mutex_unlock(buf->mutex);
00400    return ret;
00401 }
00402 
00403 uint64_t
00404 driBOFlags(struct _DriBufferObject *buf)
00405 {
00406    uint64_t ret;
00407 
00408    assert(buf->private != NULL);
00409 
00410    driReadLockKernelBO();
00411    pipe_mutex_lock(buf->mutex);
00412    ret = buf->pool->flags(buf->pool, buf->private);
00413    pipe_mutex_unlock(buf->mutex);
00414    driReadUnlockKernelBO();
00415    return ret;
00416 }
00417 
00418 struct _DriBufferObject *
00419 driBOReference(struct _DriBufferObject *buf)
00420 {
00421    pipe_mutex_lock(buf->mutex);
00422    if (++buf->refCount == 1) {
00423       pipe_mutex_unlock(buf->mutex);
00424       BM_CKFATAL(-EINVAL);
00425    }
00426    pipe_mutex_unlock(buf->mutex);
00427    return buf;
00428 }
00429 
00430 void
00431 driBOUnReference(struct _DriBufferObject *buf)
00432 {
00433    int tmp;
00434 
00435    if (!buf)
00436       return;
00437 
00438    pipe_mutex_lock(buf->mutex);
00439    tmp = --buf->refCount;
00440    if (!tmp) {
00441       pipe_mutex_unlock(buf->mutex);
00442       if (buf->private) {
00443          if (buf->createdByReference)
00444             buf->pool->unreference(buf->pool, buf->private);
00445          else
00446             buf->pool->destroy(buf->pool, buf->private);
00447       }
00448       if (buf->userBuffer)
00449          num_user_buffers--;
00450       else
00451          num_buffers--;
00452       free(buf);
00453    } else
00454      pipe_mutex_unlock(buf->mutex);
00455 
00456 }
00457 
00458 
00459 int
00460 driBOData(struct _DriBufferObject *buf,
00461           unsigned size, const void *data,
00462           DriBufferPool *newPool,
00463           uint64_t flags)
00464 {
00465    void *virtual = NULL;
00466    int newBuffer;
00467    int retval = 0;
00468    struct _DriBufferPool *pool;
00469 
00470    assert(!buf->userBuffer); /* XXX just do a memcpy? */
00471 
00472    pipe_mutex_lock(buf->mutex);
00473    pool = buf->pool;
00474 
00475    if (pool == NULL && newPool != NULL) {
00476        buf->pool = newPool;
00477        pool = newPool;
00478    }
00479    if (newPool == NULL)
00480        newPool = pool;
00481 
00482    if (!pool->create) {
00483       assert((size_t)"driBOData called on invalid buffer\n" & 0);
00484       BM_CKFATAL(-EINVAL);
00485    }
00486 
00487    newBuffer = (!buf->private || pool != newPool ||
00488                 pool->size(pool, buf->private) < size);
00489 
00490    if (!flags)
00491        flags = buf->flags;
00492 
00493    if (newBuffer) {
00494 
00495        if (buf->createdByReference) {
00496           assert((size_t)"driBOData requiring resizing called on shared buffer.\n" & 0);
00497           BM_CKFATAL(-EINVAL);
00498        }
00499 
00500        if (buf->private)
00501            buf->pool->destroy(buf->pool, buf->private);
00502 
00503        pool = newPool;
00504        buf->pool = newPool;
00505        buf->private = pool->create(pool, size, flags, DRM_BO_HINT_DONT_FENCE,
00506                                   buf->alignment);
00507       if (!buf->private)
00508           retval = -ENOMEM;
00509 
00510       if (retval == 0)
00511           retval = pool->map(pool, buf->private,
00512                              DRM_BO_FLAG_WRITE,
00513                              DRM_BO_HINT_DONT_BLOCK, &buf->mutex, &virtual);
00514    } else if (pool->map(pool, buf->private, DRM_BO_FLAG_WRITE,
00515                         DRM_BO_HINT_DONT_BLOCK, &buf->mutex, &virtual)) {
00516        /*
00517         * Buffer is busy. need to create a new one.
00518         */
00519 
00520        void *newBuf;
00521 
00522        newBuf = pool->create(pool, size, flags, DRM_BO_HINT_DONT_FENCE,
00523                              buf->alignment);
00524        if (newBuf) {
00525            buf->pool->destroy(buf->pool, buf->private);
00526            buf->private = newBuf;
00527        }
00528 
00529        retval = pool->map(pool, buf->private,
00530                           DRM_BO_FLAG_WRITE, 0, &buf->mutex, &virtual);
00531    } else {
00532        uint64_t flag_diff = flags ^ buf->flags;
00533 
00534        /*
00535         * We might need to change buffer flags.
00536         */
00537 
00538        if (flag_diff){
00539            assert(pool->setStatus != NULL);
00540            BM_CKFATAL(pool->unmap(pool, buf->private));
00541            BM_CKFATAL(pool->setStatus(pool, buf->private, flag_diff,
00542                                       buf->flags));
00543            if (!data)
00544              goto out;
00545 
00546            retval = pool->map(pool, buf->private,
00547                               DRM_BO_FLAG_WRITE, 0, &buf->mutex, &virtual);
00548        }
00549    }
00550 
00551    if (retval == 0) {
00552       if (data)
00553          memcpy(virtual, data, size);
00554 
00555       BM_CKFATAL(pool->unmap(pool, buf->private));
00556    }
00557 
00558  out:
00559    pipe_mutex_unlock(buf->mutex);
00560 
00561    return retval;
00562 }
00563 
00564 void
00565 driBOSubData(struct _DriBufferObject *buf,
00566              unsigned long offset, unsigned long size, const void *data)
00567 {
00568    void *virtual;
00569 
00570    assert(!buf->userBuffer); /* XXX just do a memcpy? */
00571 
00572    pipe_mutex_lock(buf->mutex);
00573    if (size && data) {
00574       BM_CKFATAL(buf->pool->map(buf->pool, buf->private,
00575                                 DRM_BO_FLAG_WRITE, 0, &buf->mutex,
00576                                 &virtual));
00577       memcpy((unsigned char *) virtual + offset, data, size);
00578       BM_CKFATAL(buf->pool->unmap(buf->pool, buf->private));
00579    }
00580    pipe_mutex_unlock(buf->mutex);
00581 }
00582 
00583 void
00584 driBOGetSubData(struct _DriBufferObject *buf,
00585                 unsigned long offset, unsigned long size, void *data)
00586 {
00587    void *virtual;
00588 
00589    assert(!buf->userBuffer); /* XXX just do a memcpy? */
00590 
00591    pipe_mutex_lock(buf->mutex);
00592    if (size && data) {
00593       BM_CKFATAL(buf->pool->map(buf->pool, buf->private,
00594                                 DRM_BO_FLAG_READ, 0, &buf->mutex, &virtual));
00595       memcpy(data, (unsigned char *) virtual + offset, size);
00596       BM_CKFATAL(buf->pool->unmap(buf->pool, buf->private));
00597    }
00598    pipe_mutex_unlock(buf->mutex);
00599 }
00600 
00601 void
00602 driBOSetReferenced(struct _DriBufferObject *buf,
00603                    unsigned long handle)
00604 {
00605    pipe_mutex_lock(buf->mutex);
00606    if (buf->private != NULL) {
00607       assert((size_t)"Invalid buffer for setReferenced\n" & 0);
00608       BM_CKFATAL(-EINVAL);
00609 
00610    }
00611    if (buf->pool->reference == NULL) {
00612       assert((size_t)"Invalid buffer pool for setReferenced\n" & 0);
00613       BM_CKFATAL(-EINVAL);
00614    }
00615    buf->private = buf->pool->reference(buf->pool, handle);
00616    if (!buf->private) {
00617       assert((size_t)"Invalid buffer pool for setStatic\n" & 0);
00618       BM_CKFATAL(-ENOMEM);
00619    }
00620    buf->createdByReference = TRUE;
00621    buf->flags = buf->pool->kernel(buf->pool, buf->private)->flags;
00622    pipe_mutex_unlock(buf->mutex);
00623 }
00624 
00625 int
00626 driGenBuffers(struct _DriBufferPool *pool,
00627               const char *name,
00628               unsigned n,
00629               struct _DriBufferObject *buffers[],
00630               unsigned alignment, uint64_t flags, unsigned hint)
00631 {
00632    struct _DriBufferObject *buf;
00633    int i;
00634 
00635    flags = (flags) ? flags : DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_MEM_VRAM |
00636       DRM_BO_FLAG_MEM_LOCAL | DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE;
00637 
00638    ++num_buffers;
00639 
00640    assert(pool);
00641 
00642    for (i = 0; i < n; ++i) {
00643       buf = (struct _DriBufferObject *) calloc(1, sizeof(*buf));
00644       if (!buf)
00645          return -ENOMEM;
00646 
00647       pipe_mutex_init(buf->mutex);
00648       pipe_mutex_lock(buf->mutex);
00649       buf->refCount = 1;
00650       buf->flags = flags;
00651       buf->hint = hint;
00652       buf->name = name;
00653       buf->alignment = alignment;
00654       buf->pool = pool;
00655       buf->createdByReference = 0;
00656       pipe_mutex_unlock(buf->mutex);
00657       buffers[i] = buf;
00658    }
00659    return 0;
00660 }
00661 
00662 void
00663 driGenUserBuffer(struct _DriBufferPool *pool,
00664                  const char *name,
00665                  struct _DriBufferObject **buffers,
00666                  void *ptr, unsigned bytes)
00667 {
00668    const unsigned alignment = 1, flags = 0, hint = 0;
00669 
00670    --num_buffers; /* JB: is inced in GenBuffes */
00671    driGenBuffers(pool, name, 1, buffers, alignment, flags, hint);
00672    ++num_user_buffers;
00673 
00674    (*buffers)->userBuffer = 1;
00675    (*buffers)->userData = ptr;
00676    (*buffers)->userSize = bytes;
00677 }
00678 
00679 void
00680 driDeleteBuffers(unsigned n, struct _DriBufferObject *buffers[])
00681 {
00682    int i;
00683 
00684    for (i = 0; i < n; ++i) {
00685       driBOUnReference(buffers[i]);
00686    }
00687 }
00688 
00689 
00690 void
00691 driInitBufMgr(int fd)
00692 {
00693    ;
00694 }
00695 
00696 /*
00697  * Note that lists are per-context and don't need mutex protection.
00698  */
00699 
00700 struct _DriBufferList *
00701 driBOCreateList(int target)
00702 {
00703     struct _DriBufferList *list = calloc(sizeof(*list), 1);
00704 
00705     BM_CKFATAL(drmBOCreateList(target, &list->drmBuffers));
00706     BM_CKFATAL(drmBOCreateList(target, &list->driBuffers));
00707     return list;
00708 }
00709 
00710 int
00711 driBOResetList(struct _DriBufferList * list)
00712 {
00713     int ret;
00714     ret = drmBOResetList(&list->drmBuffers);
00715     if (ret)
00716         return ret;
00717     ret = drmBOResetList(&list->driBuffers);
00718     return ret;
00719 }
00720 
00721 void
00722 driBOFreeList(struct _DriBufferList * list)
00723 {
00724    drmBOFreeList(&list->drmBuffers);
00725    drmBOFreeList(&list->driBuffers);
00726    free(list);
00727 }
00728 
00729 
00730 /*
00731  * Copied from libdrm, because it is needed by driAddValidateItem.
00732  */
00733 
00734 static drmBONode *
00735 driAddListItem(drmBOList * list, drmBO * item,
00736                uint64_t arg0, uint64_t arg1)
00737 {
00738     drmBONode *node;
00739     drmMMListHead *l;
00740 
00741     l = list->free.next;
00742     if (l == &list->free) {
00743         node = (drmBONode *) malloc(sizeof(*node));
00744         if (!node) {
00745             return NULL;
00746         }
00747         list->numCurrent++;
00748     } else {
00749         DRMLISTDEL(l);
00750         node = DRMLISTENTRY(drmBONode, l, head);
00751     }
00752     memset(&node->bo_arg, 0, sizeof(node->bo_arg));
00753     node->buf = item;
00754     node->arg0 = arg0;
00755     node->arg1 = arg1;
00756     DRMLISTADDTAIL(&node->head, &list->list);
00757     list->numOnList++;
00758     return node;
00759 }
00760 
00761 /*
00762  * Slightly modified version compared to the libdrm version.
00763  * This one returns the list index of the buffer put on the list.
00764  */
00765 
00766 static int
00767 driAddValidateItem(drmBOList * list, drmBO * buf, uint64_t flags,
00768                    uint64_t mask, int *itemLoc,
00769                    struct _drmBONode **pnode)
00770 {
00771     drmBONode *node, *cur;
00772     drmMMListHead *l;
00773     int count = 0;
00774 
00775     cur = NULL;
00776 
00777     for (l = list->list.next; l != &list->list; l = l->next) {
00778         node = DRMLISTENTRY(drmBONode, l, head);
00779         if (node->buf == buf) {
00780             cur = node;
00781             break;
00782         }
00783         count++;
00784     }
00785     if (!cur) {
00786         cur = driAddListItem(list, buf, flags, mask);
00787         if (!cur)
00788             return -ENOMEM;
00789 
00790         cur->arg0 = flags;
00791         cur->arg1 = mask;
00792     } else {
00793         uint64_t memFlags = cur->arg0 & flags & DRM_BO_MASK_MEM;
00794         uint64_t accFlags = (cur->arg0 | flags) & ~DRM_BO_MASK_MEM;
00795 
00796         if (mask & cur->arg1 & ~DRM_BO_MASK_MEM  & (cur->arg0 ^ flags)) {
00797             return -EINVAL;
00798         }
00799 
00800         cur->arg1 |= mask;
00801         cur->arg0 = (cur->arg0 & ~mask) | ((memFlags | accFlags) & mask);
00802 
00803         if (((cur->arg1 & DRM_BO_MASK_MEM) != 0) &&
00804             (cur->arg0 & DRM_BO_MASK_MEM) == 0) {
00805             return -EINVAL;
00806         }
00807     }
00808     *itemLoc = count;
00809     *pnode = cur;
00810     return 0;
00811 }
00812 
00813 
00814 void
00815 driBOAddListItem(struct _DriBufferList * list, struct _DriBufferObject *buf,
00816                  uint64_t flags, uint64_t mask, int *itemLoc,
00817                  struct _drmBONode **node)
00818 {
00819    int newItem;
00820 
00821    pipe_mutex_lock(buf->mutex);
00822    BM_CKFATAL(driAddValidateItem(&list->drmBuffers,
00823                                  buf->pool->kernel(buf->pool, buf->private),
00824                                  flags, mask, itemLoc, node));
00825    BM_CKFATAL(drmAddValidateItem(&list->driBuffers, (drmBO *) buf,
00826                                  flags, mask, &newItem));
00827    if (newItem)
00828      buf->refCount++;
00829 
00830    pipe_mutex_unlock(buf->mutex);
00831 }
00832 
00833 drmBOList *driGetdrmBOList(struct _DriBufferList *list)
00834 {
00835         driWriteLockKernelBO();
00836         return &list->drmBuffers;
00837 }
00838 
00839 void driPutdrmBOList(struct _DriBufferList *list)
00840 {
00841         driWriteUnlockKernelBO();
00842 }
00843 
00844 
00845 void
00846 driBOFence(struct _DriBufferObject *buf, struct _DriFenceObject *fence)
00847 {
00848    pipe_mutex_lock(buf->mutex);
00849    if (buf->pool->fence)
00850        BM_CKFATAL(buf->pool->fence(buf->pool, buf->private, fence));
00851    pipe_mutex_unlock(buf->mutex);
00852 
00853 }
00854 
00855 void
00856 driBOUnrefUserList(struct _DriBufferList *list)
00857 {
00858     struct _DriBufferObject *buf;
00859     void *curBuf;
00860 
00861     curBuf = drmBOListIterator(&list->driBuffers);
00862     while (curBuf) {
00863         buf = (struct _DriBufferObject *)drmBOListBuf(curBuf);
00864         driBOUnReference(buf);
00865         curBuf = drmBOListNext(&list->driBuffers, curBuf);
00866     }
00867 }
00868 
00869 struct _DriFenceObject *
00870 driBOFenceUserList(struct _DriFenceMgr *mgr,
00871                    struct _DriBufferList *list, const char *name,
00872                    drmFence *kFence)
00873 {
00874     struct _DriFenceObject *fence;
00875     struct _DriBufferObject *buf;
00876     void *curBuf;
00877 
00878     fence = driFenceCreate(mgr, kFence->fence_class, kFence->type,
00879                            kFence, sizeof(*kFence));
00880     curBuf = drmBOListIterator(&list->driBuffers);
00881 
00882    /*
00883     * User-space fencing callbacks.
00884     */
00885 
00886    while (curBuf) {
00887         buf = (struct _DriBufferObject *) drmBOListBuf(curBuf);
00888         driBOFence(buf, fence);
00889         driBOUnReference(buf);
00890         curBuf = drmBOListNext(&list->driBuffers, curBuf);
00891    }
00892 
00893    driBOResetList(list);
00894    return fence;
00895 }
00896 
00897 void
00898 driBOValidateUserList(struct _DriBufferList * list)
00899 {
00900     void *curBuf;
00901     struct _DriBufferObject *buf;
00902 
00903     curBuf = drmBOListIterator(&list->driBuffers);
00904 
00905     /*
00906      * User-space validation callbacks.
00907      */
00908 
00909     while (curBuf) {
00910         buf = (struct _DriBufferObject *) drmBOListBuf(curBuf);
00911         pipe_mutex_lock(buf->mutex);
00912         if (buf->pool->validate)
00913             BM_CKFATAL(buf->pool->validate(buf->pool, buf->private, &buf->mutex));
00914         pipe_mutex_unlock(buf->mutex);
00915         curBuf = drmBOListNext(&list->driBuffers, curBuf);
00916     }
00917 }
00918 
00919 
00920 void
00921 driPoolTakeDown(struct _DriBufferPool *pool)
00922 {
00923    pool->takeDown(pool);
00924 
00925 }
00926 
00927 unsigned long
00928 driBOSize(struct _DriBufferObject *buf)
00929 {
00930   unsigned long size;
00931 
00932    pipe_mutex_lock(buf->mutex);
00933    size = buf->pool->size(buf->pool, buf->private);
00934    pipe_mutex_unlock(buf->mutex);
00935 
00936   return size;
00937 
00938 }
00939 
00940 drmBOList *driBOGetDRMBuffers(struct _DriBufferList *list)
00941 {
00942     return &list->drmBuffers;
00943 }
00944 
00945 drmBOList *driBOGetDRIBuffers(struct _DriBufferList *list)
00946 {
00947     return &list->driBuffers;
00948 }
00949 

Generated on Tue Sep 29 06:25:17 2009 for Gallium3D by  doxygen 1.5.4