📄 mgaioctl.c
字号:
* 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( __DRIdrawablePrivate *dPriv ){ mgaContextPtr mmesa; drm_clip_rect_t *pbox; GLint nbox; GLint ret; GLint i; GLboolean missed_target; __DRIscreenPrivate *psp = dPriv->driScreenPriv; assert(dPriv); assert(dPriv->driContextPriv); assert(dPriv->driContextPriv->driverPrivate); mmesa = (mgaContextPtr) dPriv->driContextPriv->driverPrivate; FLUSH_BATCH( mmesa ); mgaWaitForFrameCompletion( mmesa ); driWaitForVBlank( dPriv, & missed_target ); if ( missed_target ) { mmesa->swap_missed_count++; (void) (*psp->systemTime->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) (*psp->systemTime->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;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -