📄 mgaioctl.c
字号:
/* * 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"static intmgaSetFence( mgaContextPtr mmesa, uint32_t * fence ){ int ret = ENOSYS; if ( mmesa->driScreen->drm_version.minor >= 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;}static intmgaWaitFence( mgaContextPtr mmesa, uint32_t fence, uint32_t * curr_fence ){ int ret = ENOSYS; if ( mmesa->driScreen->drm_version.minor >= 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 voidmgaClear( GLcontext *ctx, GLbitfield mask ){ 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; GLint cx, cy, cw, ch; 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 ); /* compute region after locking: */ cx = ctx->DrawBuffer->_Xmin; cy = ctx->DrawBuffer->_Ymin; cw = ctx->DrawBuffer->_Xmax - cx; ch = ctx->DrawBuffer->_Ymax - cy; 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 (cw != dPriv->w || ch != dPriv->h) { /* clear subregion */ 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 { /* clear whole window */ 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 );}/** * 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-
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -