diff options
author | Reinhard Tartler <siretart@tauware.de> | 2011-10-10 17:43:39 +0200 |
---|---|---|
committer | Reinhard Tartler <siretart@tauware.de> | 2011-10-10 17:43:39 +0200 |
commit | f4092abdf94af6a99aff944d6264bc1284e8bdd4 (patch) | |
tree | 2ac1c9cc16ceb93edb2c4382c088dac5aeafdf0f /nx-X11/extras/Mesa/src/mesa/drivers/dri/mga/mgaioctl.c | |
parent | a840692edc9c6d19cd7c057f68e39c7d95eb767d (diff) | |
download | nx-libs-f4092abdf94af6a99aff944d6264bc1284e8bdd4.tar.gz nx-libs-f4092abdf94af6a99aff944d6264bc1284e8bdd4.tar.bz2 nx-libs-f4092abdf94af6a99aff944d6264bc1284e8bdd4.zip |
Imported nx-X11-3.1.0-1.tar.gznx-X11/3.1.0-1
Summary: Imported nx-X11-3.1.0-1.tar.gz
Keywords:
Imported nx-X11-3.1.0-1.tar.gz
into Git repository
Diffstat (limited to 'nx-X11/extras/Mesa/src/mesa/drivers/dri/mga/mgaioctl.c')
-rw-r--r-- | nx-X11/extras/Mesa/src/mesa/drivers/dri/mga/mgaioctl.c | 743 |
1 files changed, 743 insertions, 0 deletions
diff --git a/nx-X11/extras/Mesa/src/mesa/drivers/dri/mga/mgaioctl.c b/nx-X11/extras/Mesa/src/mesa/drivers/dri/mga/mgaioctl.c new file mode 100644 index 000000000..df253d159 --- /dev/null +++ b/nx-X11/extras/Mesa/src/mesa/drivers/dri/mga/mgaioctl.c @@ -0,0 +1,743 @@ +/* + * Copyright 2000-2001 VA Linux Systems, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * \file mgaioctl.c + * MGA IOCTL related wrapper functions. + * + * \author Keith Whitwell <keith@tungstengraphics.com> + * \author Gareth Hughes <gareth@valinux.com> + */ + +#include <errno.h> +#include "mtypes.h" +#include "macros.h" +#include "dd.h" +#include "swrast/swrast.h" + +#include "mm.h" +#include "drm.h" +#include "mga_drm.h" +#include "mgacontext.h" +#include "mgadd.h" +#include "mgastate.h" +#include "mgatex.h" +#include "mgavb.h" +#include "mgaioctl.h" +#include "mgatris.h" + +#include "vblank.h" + + +int +mgaSetFence( mgaContextPtr mmesa, uint32_t * fence ) +{ + int ret = ENOSYS; + + if ( mmesa->driScreen->drmMinor >= 2 ) { + ret = drmCommandWriteRead( mmesa->driScreen->fd, DRM_MGA_SET_FENCE, + fence, sizeof( uint32_t )); + if (ret) { + fprintf(stderr, "drmMgaSetFence: %d\n", ret); + exit(1); + } + } + + return ret; +} + + +int +mgaWaitFence( mgaContextPtr mmesa, uint32_t fence, uint32_t * curr_fence ) +{ + int ret = ENOSYS; + + if ( mmesa->driScreen->drmMinor >= 2 ) { + uint32_t temp = fence; + + ret = drmCommandWriteRead( mmesa->driScreen->fd, + DRM_MGA_WAIT_FENCE, + & temp, sizeof( uint32_t )); + if (ret) { + fprintf(stderr, "drmMgaSetFence: %d\n", ret); + exit(1); + } + + if ( curr_fence ) { + *curr_fence = temp; + } + } + + return ret; +} + + +static void mga_iload_dma_ioctl(mgaContextPtr mmesa, + unsigned long dest, + int length) +{ + drmBufPtr buf = mmesa->iload_buffer; + drm_mga_iload_t iload; + int ret, i; + + if (MGA_DEBUG&DEBUG_VERBOSE_IOCTL) + fprintf(stderr, "DRM_IOCTL_MGA_ILOAD idx %d dst %x length %d\n", + buf->idx, (int) dest, length); + + if ( (length & MGA_ILOAD_MASK) != 0 ) { + UNLOCK_HARDWARE( mmesa ); + fprintf( stderr, "%s: Invalid ILOAD datasize (%d), must be " + "multiple of %u.\n", __FUNCTION__, length, MGA_ILOAD_ALIGN ); + exit( 1 ); + } + + iload.idx = buf->idx; + iload.dstorg = dest; + iload.length = length; + + i = 0; + do { + ret = drmCommandWrite( mmesa->driFd, DRM_MGA_ILOAD, + &iload, sizeof(iload) ); + } while ( ret == -EBUSY && i++ < DRM_MGA_IDLE_RETRY ); + + if ( ret < 0 ) { + printf("send iload retcode = %d\n", ret); + exit(1); + } + + mmesa->iload_buffer = 0; + + if (MGA_DEBUG&DEBUG_VERBOSE_IOCTL) + fprintf(stderr, "finished iload dma put\n"); + +} + +drmBufPtr mga_get_buffer_ioctl( mgaContextPtr mmesa ) +{ + int idx = 0; + int size = 0; + drmDMAReq dma; + int retcode; + drmBufPtr buf; + + if (MGA_DEBUG&DEBUG_VERBOSE_IOCTL) + fprintf(stderr, "Getting dma buffer\n"); + + dma.context = mmesa->hHWContext; + dma.send_count = 0; + dma.send_list = NULL; + dma.send_sizes = NULL; + dma.flags = 0; + dma.request_count = 1; + dma.request_size = MGA_BUFFER_SIZE; + dma.request_list = &idx; + dma.request_sizes = &size; + dma.granted_count = 0; + + + if (MGA_DEBUG&DEBUG_VERBOSE_IOCTL) + fprintf(stderr, "drmDMA (get) ctx %d count %d size 0x%x\n", + dma.context, dma.request_count, + dma.request_size); + + while (1) { + retcode = drmDMA(mmesa->driFd, &dma); + + if (MGA_DEBUG&DEBUG_VERBOSE_IOCTL) + fprintf(stderr, "retcode %d sz %d idx %d count %d\n", + retcode, + dma.request_sizes[0], + dma.request_list[0], + dma.granted_count); + + if (retcode == 0 && + dma.request_sizes[0] && + dma.granted_count) + break; + + if (MGA_DEBUG&DEBUG_VERBOSE_IOCTL) + fprintf(stderr, "\n\nflush"); + + UPDATE_LOCK( mmesa, DRM_LOCK_FLUSH | DRM_LOCK_QUIESCENT ); + } + + buf = &(mmesa->mgaScreen->bufs->list[idx]); + buf->used = 0; + + if (MGA_DEBUG&DEBUG_VERBOSE_IOCTL) + fprintf(stderr, + "drmDMA (get) returns size[0] 0x%x idx[0] %d\n" + "dma_buffer now: buf idx: %d size: %d used: %d addr %p\n", + dma.request_sizes[0], dma.request_list[0], + buf->idx, buf->total, + buf->used, buf->address); + + if (MGA_DEBUG&DEBUG_VERBOSE_IOCTL) + fprintf(stderr, "finished getbuffer\n"); + + return buf; +} + + + + +static void +mgaClear( GLcontext *ctx, GLbitfield mask, GLboolean all, + GLint cx, GLint cy, GLint cw, GLint ch ) +{ + mgaContextPtr mmesa = MGA_CONTEXT(ctx); + __DRIdrawablePrivate *dPriv = mmesa->driDrawable; + GLuint flags = 0; + GLuint clear_color = mmesa->ClearColor; + GLuint clear_depth = 0; + GLuint color_mask = 0; + GLuint depth_mask = 0; + int ret; + int i; + static int nrclears; + drm_mga_clear_t clear; + + FLUSH_BATCH( mmesa ); + + if ( mask & BUFFER_BIT_FRONT_LEFT ) { + flags |= MGA_FRONT; + color_mask = mmesa->setup.plnwt; + mask &= ~BUFFER_BIT_FRONT_LEFT; + } + + if ( mask & BUFFER_BIT_BACK_LEFT ) { + flags |= MGA_BACK; + color_mask = mmesa->setup.plnwt; + mask &= ~BUFFER_BIT_BACK_LEFT; + } + + if ( (mask & BUFFER_BIT_DEPTH) && ctx->Depth.Mask ) { + flags |= MGA_DEPTH; + clear_depth = (mmesa->ClearDepth & mmesa->depth_clear_mask); + depth_mask |= mmesa->depth_clear_mask; + mask &= ~BUFFER_BIT_DEPTH; + } + + if ( (mask & BUFFER_BIT_STENCIL) && mmesa->hw_stencil ) { + flags |= MGA_DEPTH; + clear_depth |= (ctx->Stencil.Clear & mmesa->stencil_clear_mask); + depth_mask |= mmesa->stencil_clear_mask; + mask &= ~BUFFER_BIT_STENCIL; + } + + if ( flags ) { + LOCK_HARDWARE( mmesa ); + + if ( mmesa->dirty_cliprects ) + mgaUpdateRects( mmesa, (MGA_FRONT | MGA_BACK) ); + + /* flip top to bottom */ + cy = dPriv->h-cy-ch; + cx += mmesa->drawX; + cy += mmesa->drawY; + + if ( MGA_DEBUG & DEBUG_VERBOSE_IOCTL ) + fprintf( stderr, "Clear, bufs %x nbox %d\n", + (int)flags, (int)mmesa->numClipRects ); + + for (i = 0 ; i < mmesa->numClipRects ; ) + { + int nr = MIN2(i + MGA_NR_SAREA_CLIPRECTS, mmesa->numClipRects); + drm_clip_rect_t *box = mmesa->pClipRects; + drm_clip_rect_t *b = mmesa->sarea->boxes; + int n = 0; + + if (!all) { + for ( ; i < nr ; i++) { + GLint x = box[i].x1; + GLint y = box[i].y1; + GLint w = box[i].x2 - x; + GLint h = box[i].y2 - y; + + if (x < cx) w -= cx - x, x = cx; + if (y < cy) h -= cy - y, y = cy; + if (x + w > cx + cw) w = cx + cw - x; + if (y + h > cy + ch) h = cy + ch - y; + if (w <= 0) continue; + if (h <= 0) continue; + + b->x1 = x; + b->y1 = y; + b->x2 = x + w; + b->y2 = y + h; + b++; + n++; + } + } else { + for ( ; i < nr ; i++) { + *b++ = box[i]; + n++; + } + } + + + if ( MGA_DEBUG & DEBUG_VERBOSE_IOCTL ) + fprintf( stderr, + "DRM_IOCTL_MGA_CLEAR flag 0x%x color %x depth %x nbox %d\n", + flags, clear_color, clear_depth, mmesa->sarea->nbox ); + + mmesa->sarea->nbox = n; + + clear.flags = flags; + clear.clear_color = clear_color; + clear.clear_depth = clear_depth; + clear.color_mask = color_mask; + clear.depth_mask = depth_mask; + ret = drmCommandWrite( mmesa->driFd, DRM_MGA_CLEAR, + &clear, sizeof(clear)); + if ( ret ) { + fprintf( stderr, "send clear retcode = %d\n", ret ); + exit( 1 ); + } + if ( MGA_DEBUG & DEBUG_VERBOSE_IOCTL ) + fprintf( stderr, "finished clear %d\n", ++nrclears ); + } + + UNLOCK_HARDWARE( mmesa ); + mmesa->dirty |= MGA_UPLOAD_CLIPRECTS|MGA_UPLOAD_CONTEXT; + } + + if (mask) + _swrast_Clear( ctx, mask, all, cx, cy, cw, ch ); +} + + +/** + * Wait for the previous frame of rendering has completed. + * + * \param mmesa Hardware context pointer. + * + * \bug + * The loop in this function should have some sort of a timeout mechanism. + * + * \warning + * This routine used to assume that the hardware lock was held on entry. It + * now assumes that the lock is \b not held on entry. + */ + +static void mgaWaitForFrameCompletion( mgaContextPtr mmesa ) +{ + if ( mgaWaitFence( mmesa, mmesa->last_frame_fence, NULL ) == ENOSYS ) { + unsigned wait = 0; + GLuint last_frame; + GLuint last_wrap; + + + LOCK_HARDWARE( mmesa ); + last_frame = mmesa->sarea->last_frame.head; + last_wrap = mmesa->sarea->last_frame.wrap; + + /* The DMA routines in the kernel track a couple values in the SAREA + * that we use here. The number of times that the primary DMA buffer + * has "wrapped" around is tracked in last_wrap. In addition, the + * wrap count and the buffer position at the end of the last frame are + * stored in last_frame.wrap and last_frame.head. + * + * By comparing the wrap counts and the current DMA pointer value + * (read directly from the hardware) to last_frame.head, we can + * determine when the graphics processor has processed all of the + * commands for the last frame. + * + * In this case "last frame" means the frame of the *previous* swap- + * buffers call. This is done to prevent queuing a second buffer swap + * before the previous swap is executed. + */ + while ( 1 ) { + if ( last_wrap < mmesa->sarea->last_wrap || + ( last_wrap == mmesa->sarea->last_wrap && + last_frame <= (MGA_READ( MGAREG_PRIMADDRESS ) - + mmesa->primary_offset) ) ) { + break; + } + if ( 0 ) { + wait++; + fprintf( stderr, " last: head=0x%06x wrap=%d\n", + last_frame, last_wrap ); + fprintf( stderr, " head: head=0x%06lx wrap=%d\n", + (long)(MGA_READ( MGAREG_PRIMADDRESS ) - mmesa->primary_offset), + mmesa->sarea->last_wrap ); + } + UPDATE_LOCK( mmesa, DRM_LOCK_FLUSH ); + + UNLOCK_HARDWARE( mmesa ); + DO_USLEEP( 1 ); + LOCK_HARDWARE( mmesa ); + } + if ( wait ) + fprintf( stderr, "\n" ); + + UNLOCK_HARDWARE( mmesa ); + } +} + + +/* + * Copy the back buffer to the front buffer. + */ +void mgaCopyBuffer( const __DRIdrawablePrivate *dPriv ) +{ + mgaContextPtr mmesa; + drm_clip_rect_t *pbox; + GLint nbox; + GLint ret; + GLint i; + GLboolean missed_target; + + + assert(dPriv); + assert(dPriv->driContextPriv); + assert(dPriv->driContextPriv->driverPrivate); + + mmesa = (mgaContextPtr) dPriv->driContextPriv->driverPrivate; + + FLUSH_BATCH( mmesa ); + + mgaWaitForFrameCompletion( mmesa ); + driWaitForVBlank( dPriv, & mmesa->vbl_seq, mmesa->vblank_flags, + & missed_target ); + if ( missed_target ) { + mmesa->swap_missed_count++; + (void) (*dri_interface->getUST)( & mmesa->swap_missed_ust ); + } + LOCK_HARDWARE( mmesa ); + + /* Use the frontbuffer cliprects + */ + if (mmesa->dirty_cliprects & MGA_FRONT) + mgaUpdateRects( mmesa, MGA_FRONT ); + + + pbox = dPriv->pClipRects; + nbox = dPriv->numClipRects; + + for (i = 0 ; i < nbox ; ) + { + int nr = MIN2(i + MGA_NR_SAREA_CLIPRECTS, dPriv->numClipRects); + drm_clip_rect_t *b = mmesa->sarea->boxes; + + mmesa->sarea->nbox = nr - i; + + for ( ; i < nr ; i++) + *b++ = pbox[i]; + + if (0) + fprintf(stderr, "DRM_IOCTL_MGA_SWAP\n"); + + ret = drmCommandNone( mmesa->driFd, DRM_MGA_SWAP ); + if ( ret ) { + printf("send swap retcode = %d\n", ret); + exit(1); + } + } + + (void) mgaSetFence( mmesa, & mmesa->last_frame_fence ); + UNLOCK_HARDWARE( mmesa ); + + mmesa->dirty |= MGA_UPLOAD_CLIPRECTS; + mmesa->swap_count++; + (void) (*dri_interface->getUST)( & mmesa->swap_ust ); +} + + +/** + * Implement the hardware-specific portion of \c glFinish. + * + * Flushes all pending commands to the hardware and wait for them to finish. + * + * \param ctx Context where the \c glFinish command was issued. + * + * \sa glFinish, mgaFlush, mgaFlushDMA + */ +static void mgaFinish( GLcontext *ctx ) +{ + mgaContextPtr mmesa = MGA_CONTEXT(ctx); + uint32_t fence; + + + LOCK_HARDWARE( mmesa ); + if ( mmesa->vertex_dma_buffer != NULL ) { + mgaFlushVerticesLocked( mmesa ); + } + + if ( mgaSetFence( mmesa, & fence ) == 0 ) { + UNLOCK_HARDWARE( mmesa ); + (void) mgaWaitFence( mmesa, fence, NULL ); + } + else { + if (MGA_DEBUG&DEBUG_VERBOSE_IOCTL) { + fprintf(stderr, "mgaRegetLockQuiescent\n"); + } + + UPDATE_LOCK( mmesa, DRM_LOCK_QUIESCENT | DRM_LOCK_FLUSH ); + UNLOCK_HARDWARE( mmesa ); + } +} + + +/** + * Flush all commands upto at least a certain point to the hardware. + * + * \note + * The term "wait" in the name of this function is misleading. It doesn't + * actually wait for anything. It just makes sure that the commands have + * been flushed to the hardware. + * + * \warning + * As the name implies, this function assumes that the hardware lock is + * held on entry. + */ +void mgaWaitAgeLocked( mgaContextPtr mmesa, int age ) +{ + if (GET_DISPATCH_AGE(mmesa) < age) { + UPDATE_LOCK( mmesa, DRM_LOCK_FLUSH ); + } +} + + +static GLboolean intersect_rect( drm_clip_rect_t *out, + const drm_clip_rect_t *a, + const drm_clip_rect_t *b ) +{ + *out = *a; + if (b->x1 > out->x1) out->x1 = b->x1; + if (b->y1 > out->y1) out->y1 = b->y1; + if (b->x2 < out->x2) out->x2 = b->x2; + if (b->y2 < out->y2) out->y2 = b->y2; + + return ((out->x1 < out->x2) && (out->y1 < out->y2)); +} + + + + +static void age_mmesa( mgaContextPtr mmesa, int age ) +{ + if (mmesa->CurrentTexObj[0]) mmesa->CurrentTexObj[0]->age = age; + if (mmesa->CurrentTexObj[1]) mmesa->CurrentTexObj[1]->age = age; +} + + +void mgaFlushVerticesLocked( mgaContextPtr mmesa ) +{ + drm_clip_rect_t *pbox = mmesa->pClipRects; + int nbox = mmesa->numClipRects; + drmBufPtr buffer = mmesa->vertex_dma_buffer; + drm_mga_vertex_t vertex; + int i; + + mmesa->vertex_dma_buffer = 0; + + if (!buffer) + return; + + if (mmesa->dirty_cliprects & mmesa->draw_buffer) + mgaUpdateRects( mmesa, mmesa->draw_buffer ); + + if (mmesa->dirty & ~MGA_UPLOAD_CLIPRECTS) + mgaEmitHwStateLocked( mmesa ); + + /* FIXME: Workaround bug in kernel module. + */ + mmesa->sarea->dirty |= MGA_UPLOAD_CONTEXT; + + if (!nbox) + buffer->used = 0; + + if (nbox >= MGA_NR_SAREA_CLIPRECTS) + mmesa->dirty |= MGA_UPLOAD_CLIPRECTS; + +#if 0 + if (!buffer->used || !(mmesa->dirty & MGA_UPLOAD_CLIPRECTS)) + { + if (nbox == 1) + mmesa->sarea->nbox = 0; + else + mmesa->sarea->nbox = nbox; + + if (MGA_DEBUG&DEBUG_VERBOSE_IOCTL) + fprintf(stderr, "Firing vertex -- case a nbox %d\n", nbox); + + vertex.idx = buffer->idx; + vertex.used = buffer->used; + vertex.discard = 1; + drmCommandWrite( mmesa->driFd, DRM_MGA_VERTEX, + &vertex, sizeof(drmMGAVertex) ); + + age_mmesa(mmesa, mmesa->sarea->last_enqueue); + } + else +#endif + { + for (i = 0 ; i < nbox ; ) + { + int nr = MIN2(i + MGA_NR_SAREA_CLIPRECTS, nbox); + drm_clip_rect_t *b = mmesa->sarea->boxes; + int discard = 0; + + if (mmesa->scissor) { + mmesa->sarea->nbox = 0; + + for ( ; i < nr ; i++) { + *b = pbox[i]; + if (intersect_rect(b, b, &mmesa->scissor_rect)) { + mmesa->sarea->nbox++; + b++; + } + } + + /* Culled? + */ + if (!mmesa->sarea->nbox) { + if (nr < nbox) continue; + buffer->used = 0; + } + } else { + mmesa->sarea->nbox = nr - i; + for ( ; i < nr ; i++) + *b++ = pbox[i]; + } + + /* Finished with the buffer? + */ + if (nr == nbox) + discard = 1; + + mmesa->sarea->dirty |= MGA_UPLOAD_CLIPRECTS; + + vertex.idx = buffer->idx; + vertex.used = buffer->used; + vertex.discard = discard; + drmCommandWrite( mmesa->driFd, DRM_MGA_VERTEX, + &vertex, sizeof(vertex) ); + + age_mmesa(mmesa, mmesa->sarea->last_enqueue); + } + } + + mmesa->dirty &= ~MGA_UPLOAD_CLIPRECTS; +} + +void mgaFlushVertices( mgaContextPtr mmesa ) +{ + LOCK_HARDWARE( mmesa ); + mgaFlushVerticesLocked( mmesa ); + UNLOCK_HARDWARE( mmesa ); +} + + +void mgaFireILoadLocked( mgaContextPtr mmesa, + GLuint offset, GLuint length ) +{ + if (!mmesa->iload_buffer) { + fprintf(stderr, "mgaFireILoad: no buffer\n"); + return; + } + + if (MGA_DEBUG&DEBUG_VERBOSE_IOCTL) + fprintf(stderr, "mgaFireILoad idx %d ofs 0x%x length %d\n", + mmesa->iload_buffer->idx, (int)offset, (int)length ); + + mga_iload_dma_ioctl( mmesa, offset, length ); +} + +void mgaGetILoadBufferLocked( mgaContextPtr mmesa ) +{ + if (MGA_DEBUG&DEBUG_VERBOSE_IOCTL) + fprintf(stderr, "mgaGetIloadBuffer (buffer now %p)\n", + (void *) mmesa->iload_buffer); + + mmesa->iload_buffer = mga_get_buffer_ioctl( mmesa ); +} + + +/** + * Implement the hardware-specific portion of \c glFlush. + * + * \param ctx Context to be flushed. + * + * \sa glFlush, mgaFinish, mgaFlushDMA + */ +static void mgaFlush( GLcontext *ctx ) +{ + mgaContextPtr mmesa = MGA_CONTEXT( ctx ); + + + LOCK_HARDWARE( mmesa ); + if ( mmesa->vertex_dma_buffer != NULL ) { + mgaFlushVerticesLocked( mmesa ); + } + + UPDATE_LOCK( mmesa, DRM_LOCK_FLUSH ); + UNLOCK_HARDWARE( mmesa ); +} + + +int mgaFlushDMA( int fd, drmLockFlags flags ) +{ + drm_lock_t lock; + int ret, i = 0; + + memset( &lock, 0, sizeof(lock) ); + + lock.flags = flags & (DRM_LOCK_QUIESCENT | DRM_LOCK_FLUSH + | DRM_LOCK_FLUSH_ALL); + + do { + ret = drmCommandWrite( fd, DRM_MGA_FLUSH, &lock, sizeof(lock) ); + } while ( ret && errno == EBUSY && i++ < DRM_MGA_IDLE_RETRY ); + + if ( ret == 0 ) + return 0; + if ( errno != EBUSY ) + return -errno; + + if ( lock.flags & DRM_LOCK_QUIESCENT ) { + /* Only keep trying if we need quiescence. + */ + lock.flags &= ~(DRM_LOCK_FLUSH | DRM_LOCK_FLUSH_ALL); + + do { + ret = drmCommandWrite( fd, DRM_MGA_FLUSH, &lock, sizeof(lock) ); + } while ( ret && errno == EBUSY && i++ < DRM_MGA_IDLE_RETRY ); + } + + if ( ret == 0 ) { + return 0; + } else { + return -errno; + } +} + +void mgaInitIoctlFuncs( struct dd_function_table *functions ) +{ + functions->Clear = mgaClear; + functions->Flush = mgaFlush; + functions->Finish = mgaFinish; +} |