⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mach64_ioctl.c

📁 Mesa is an open-source implementation of the OpenGL specification - a system for rendering interacti
💻 C
📖 第 1 页 / 共 2 页
字号:
/* $XFree86$ */ /* -*- mode: c; c-basic-offset: 3 -*- *//* * Copyright 2000 Gareth Hughes * 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 * the rights to use, copy, modify, merge, publish, distribute, sublicense, * 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 NONINFRINGEMENT.  IN NO EVENT SHALL * GARETH HUGHES 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. *//* * Authors: *	Gareth Hughes <gareth@valinux.com> *	Leif Delgass <ldelgass@retinalburn.net> *	Jos�Fonseca <j_r_fonseca@yahoo.co.uk> */#include <errno.h>#include "mach64_context.h"#include "mach64_state.h"#include "mach64_ioctl.h"#include "mach64_tex.h"#include "imports.h"#include "macros.h"#include "swrast/swrast.h"#include "vblank.h"#define MACH64_TIMEOUT        10 /* the DRM already has a timeout, so keep this small *//* ============================================================= * Hardware vertex buffer handling *//* Get a new VB from the pool of vertex buffers in AGP space. */drmBufPtr mach64GetBufferLocked( mach64ContextPtr mmesa ){   int fd = mmesa->mach64Screen->driScreen->fd;   int index = 0;   int size = 0;   drmDMAReq dma;   drmBufPtr buf = NULL;   int to = 0;   int ret;   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 = MACH64_BUFFER_SIZE;   dma.request_list = &index;   dma.request_sizes = &size;   dma.granted_count = 0;   while ( !buf && ( to++ < MACH64_TIMEOUT ) ) {      ret = drmDMA( fd, &dma );      if ( ret == 0 ) {	 buf = &mmesa->mach64Screen->buffers->list[index];	 buf->used = 0;#if ENABLE_PERF_BOXES	 /* Bump the performance counter */	 mmesa->c_vertexBuffers++;#endif	 return buf;      }   }   if ( !buf ) {      drmCommandNone( fd, DRM_MACH64_RESET );      UNLOCK_HARDWARE( mmesa );      fprintf( stderr, "Error: Could not get new VB... exiting\n" );      exit( -1 );   }   return buf;}void mach64FlushVerticesLocked( mach64ContextPtr mmesa ){   drm_clip_rect_t *pbox = mmesa->pClipRects;   int nbox = mmesa->numClipRects;   void *buffer = mmesa->vert_buf;   int count = mmesa->vert_used;   int prim = mmesa->hw_primitive;   int fd = mmesa->driScreen->fd;   drm_mach64_vertex_t vertex;   int i;   mmesa->num_verts = 0;   mmesa->vert_used = 0;   if ( !count )      return;   if ( mmesa->dirty & ~MACH64_UPLOAD_CLIPRECTS )      mach64EmitHwStateLocked( mmesa );   if ( !nbox )      count = 0;   if ( nbox > MACH64_NR_SAREA_CLIPRECTS )      mmesa->dirty |= MACH64_UPLOAD_CLIPRECTS;   if ( !count || !(mmesa->dirty & MACH64_UPLOAD_CLIPRECTS) ) {      int to = 0;      int ret;      /* FIXME: Is this really necessary */      if ( nbox == 1 )	 mmesa->sarea->nbox = 0;      else	 mmesa->sarea->nbox = nbox;      vertex.prim = prim;      vertex.buf = buffer;      vertex.used = count;      vertex.discard = 1;      do {	 ret = drmCommandWrite( fd, DRM_MACH64_VERTEX,				&vertex, sizeof(drm_mach64_vertex_t) );      } while ( ( ret == -EAGAIN ) && ( to++ < MACH64_TIMEOUT ) );      if ( ret ) {	 UNLOCK_HARDWARE( mmesa );	 fprintf( stderr, "Error flushing vertex buffer: return = %d\n", ret );	 exit( -1 );      }   } else {      for ( i = 0 ; i < nbox ; ) {	 int nr = MIN2( i + MACH64_NR_SAREA_CLIPRECTS, nbox );	 drm_clip_rect_t *b = mmesa->sarea->boxes;	 int discard = 0;	 int to = 0;	 int ret;	 mmesa->sarea->nbox = nr - i;	 for ( ; i < nr ; i++ ) {	    *b++ = pbox[i];	 }	 /* Finished with the buffer?	  */	 if ( nr == nbox ) {	    discard = 1;	 }	 mmesa->sarea->dirty |= MACH64_UPLOAD_CLIPRECTS;	 	 vertex.prim = prim;	 vertex.buf = buffer;	 vertex.used = count;	 vertex.discard = discard;	 do {	    ret = drmCommandWrite( fd, DRM_MACH64_VERTEX,				   &vertex, sizeof(drm_mach64_vertex_t) );	 } while ( ( ret == -EAGAIN ) && ( to++ < MACH64_TIMEOUT ) );	 if ( ret ) {	    UNLOCK_HARDWARE( mmesa );	    fprintf( stderr, "Error flushing vertex buffer: return = %d\n", ret );	    exit( -1 );	 }      }   }   mmesa->dirty &= ~MACH64_UPLOAD_CLIPRECTS;}/* ================================================================ * Texture uploads */void mach64FireBlitLocked( mach64ContextPtr mmesa, void *buffer,			   GLint offset, GLint pitch, GLint format,			   GLint x, GLint y, GLint width, GLint height ){   drm_mach64_blit_t blit;   int to = 0;   int ret;   blit.buf = buffer;   blit.offset = offset;   blit.pitch = pitch;   blit.format = format;   blit.x = x;   blit.y = y;   blit.width = width;   blit.height = height;   do {      ret = drmCommandWrite( mmesa->driFd, DRM_MACH64_BLIT, 			     &blit, sizeof(drm_mach64_blit_t) );   } while ( ( ret == -EAGAIN ) && ( to++ < MACH64_TIMEOUT ) );   if ( ret ) {      UNLOCK_HARDWARE( mmesa );      fprintf( stderr, "DRM_MACH64_BLIT: return = %d\n", ret );      exit( -1 );   }}/* ================================================================ * SwapBuffers with client-side throttling */static void delay( void ) {/* Prevent an optimizing compiler from removing a spin loop */}/* Throttle the frame rate -- only allow MACH64_MAX_QUEUED_FRAMES * pending swap buffers requests at a time. * * GH: We probably don't want a timeout here, as we can wait as * long as we want for a frame to complete.  If it never does, then * the card has locked. */static int mach64WaitForFrameCompletion( mach64ContextPtr mmesa ){   int fd = mmesa->driFd;   int i;   int wait = 0;   int frames;   while ( 1 ) {      drm_mach64_getparam_t gp;      int ret;      if ( mmesa->sarea->frames_queued < MACH64_MAX_QUEUED_FRAMES ) {	 break;      }      if (MACH64_DEBUG & DEBUG_NOWAIT) {	 return 1;      }      gp.param = MACH64_PARAM_FRAMES_QUEUED;      gp.value = &frames; /* also copied into sarea->frames_queued by DRM */      ret = drmCommandWriteRead( fd, DRM_MACH64_GETPARAM, &gp, sizeof(gp) );      if ( ret ) {	 UNLOCK_HARDWARE( mmesa );	 fprintf( stderr, "DRM_MACH64_GETPARAM: return = %d\n", ret );	 exit( -1 );      }      /* Spin in place a bit so we aren't hammering the register */      wait++;      for ( i = 0 ; i < 1024 ; i++ ) {	 delay();      }   }   return wait;}/* Copy the back color buffer to the front color buffer. */void mach64CopyBuffer( __DRIdrawablePrivate *dPriv ){   mach64ContextPtr mmesa;   GLint nbox, i, ret;   drm_clip_rect_t *pbox;   GLboolean missed_target;   assert(dPriv);   assert(dPriv->driContextPriv);   assert(dPriv->driContextPriv->driverPrivate);   mmesa = (mach64ContextPtr) dPriv->driContextPriv->driverPrivate;   if ( MACH64_DEBUG & DEBUG_VERBOSE_API ) {      fprintf( stderr, "\n********************************\n" );      fprintf( stderr, "\n%s( %p )\n\n",	       __FUNCTION__, mmesa->glCtx );      fflush( stderr );   }   /* Flush any outstanding vertex buffers */   FLUSH_BATCH( mmesa );   LOCK_HARDWARE( mmesa );   /* Throttle the frame rate -- only allow one pending swap buffers    * request at a time.    */   if ( !mach64WaitForFrameCompletion( mmesa ) ) {      mmesa->hardwareWentIdle = 1;   } else {      mmesa->hardwareWentIdle = 0;   }#if ENABLE_PERF_BOXES   if ( mmesa->boxes ) {      mach64PerformanceBoxesLocked( mmesa );   }#endif   UNLOCK_HARDWARE( mmesa );   driWaitForVBlank( dPriv, &missed_target );   LOCK_HARDWARE( mmesa );   /* use front buffer cliprects */   nbox = dPriv->numClipRects;   pbox = dPriv->pClipRects;   for ( i = 0 ; i < nbox ; ) {      GLint nr = MIN2( i + MACH64_NR_SAREA_CLIPRECTS , nbox );      drm_clip_rect_t *b = mmesa->sarea->boxes;      GLint n = 0;      for ( ; i < nr ; i++ ) {	 *b++ = pbox[i];	 n++;      }      mmesa->sarea->nbox = n;      ret = drmCommandNone( mmesa->driFd, DRM_MACH64_SWAP );      if ( ret ) {	 UNLOCK_HARDWARE( mmesa );	 fprintf( stderr, "DRM_MACH64_SWAP: return = %d\n", ret );	 exit( -1 );      }   }   if ( MACH64_DEBUG & DEBUG_ALWAYS_SYNC ) {      mach64WaitForIdleLocked( mmesa );   }   UNLOCK_HARDWARE( mmesa );   mmesa->dirty |= (MACH64_UPLOAD_CONTEXT |		    MACH64_UPLOAD_MISC |		    MACH64_UPLOAD_CLIPRECTS);#if ENABLE_PERF_BOXES   /* Log the performance counters if necessary */   mach64PerformanceCounters( mmesa );#endif}#if ENABLE_PERF_BOXES/* ================================================================ * Performance monitoring */void mach64PerformanceCounters( mach64ContextPtr mmesa ){   if (MACH64_DEBUG & DEBUG_VERBOSE_COUNT) {      /* report performance counters */      fprintf( stderr, "mach64CopyBuffer: vertexBuffers:%i drawWaits:%i clears:%i\n",	       mmesa->c_vertexBuffers, mmesa->c_drawWaits, mmesa->c_clears );   }   mmesa->c_vertexBuffers = 0;   mmesa->c_drawWaits = 0;   mmesa->c_clears = 0;   if ( mmesa->c_textureSwaps || mmesa->c_textureBytes || mmesa->c_agpTextureBytes ) {      if (MACH64_DEBUG & DEBUG_VERBOSE_COUNT) {	 fprintf( stderr, "    textureSwaps:%i  textureBytes:%i agpTextureBytes:%i\n",		  mmesa->c_textureSwaps, mmesa->c_textureBytes, mmesa->c_agpTextureBytes );      }      mmesa->c_textureSwaps = 0;      mmesa->c_textureBytes = 0;      mmesa->c_agpTextureBytes = 0;   }   mmesa->c_texsrc_agp = 0;   mmesa->c_texsrc_card = 0;   if (MACH64_DEBUG & DEBUG_VERBOSE_COUNT)      fprintf( stderr, "---------------------------------------------------------\n" );}void mach64PerformanceBoxesLocked( mach64ContextPtr mmesa ){   GLint ret;   drm_mach64_clear_t clear;   GLint x, y, w, h;   GLuint color;   GLint nbox;   GLint x1, y1, x2, y2;   drm_clip_rect_t *b = mmesa->sarea->boxes;   /* save cliprects */   nbox = mmesa->sarea->nbox;   x1 = b[0].x1;   y1 = b[0].y1;   x2 = b[0].x2;   y2 = b[0].y2;    /* setup a single cliprect and call the clear ioctl for each box */   mmesa->sarea->nbox = 1;   w = h = 8;   x = mmesa->drawX;   y = mmesa->drawY;   b[0].x1 = x;   b[0].x2 = x + w;   b[0].y1 = y;   b[0].y2 = y + h;   clear.flags = MACH64_BACK;   clear.clear_depth = 0;   /* Red box if DDFinish was called to wait for rendering to complete */   if ( mmesa->c_drawWaits ) {      color = mach64PackColor( mmesa->mach64Screen->cpp, 255, 0, 0, 0 );            clear.x = x;      clear.y = y;      clear.w = w;      clear.h = h;      clear.clear_color = color;      ret = drmCommandWrite( mmesa->driFd, DRM_MACH64_CLEAR,			     &clear, sizeof(drm_mach64_clear_t) );      if (ret < 0) {	 UNLOCK_HARDWARE( mmesa );	 fprintf( stderr, "DRM_MACH64_CLEAR: return = %d\n", ret );	 exit( -1 );      }   }   x += w;   b[0].x1 = x;   b[0].x2 = x + w;   /* draw a green box if we had to wait for previous frame(s) to complete */   if ( !mmesa->hardwareWentIdle ) {      color = mach64PackColor( mmesa->mach64Screen->cpp, 0, 255, 0, 0 );            clear.x = x;      clear.y = y;      clear.w = w;      clear.h = h;      clear.clear_color = color;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -