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

📄 tdfx_span.c

📁 Mesa is an open-source implementation of the OpenGL specification - a system for rendering interacti
💻 C
📖 第 1 页 / 共 3 页
字号:
/* -*- mode: c; c-basic-offset: 3 -*- * * Copyright 2000 VA Linux Systems Inc., Fremont, California. * * 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 * VA LINUX SYSTEMS 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. *//* $XFree86: xc/lib/GL/mesa/src/drv/tdfx/tdfx_span.c,v 1.7 2002/10/30 12:52:00 alanh Exp $ *//* * Original rewrite: *	Gareth Hughes <gareth@valinux.com>, 29 Sep - 1 Oct 2000 * * Authors: *	Gareth Hughes <gareth@valinux.com> *	Brian Paul <brianp@valinux.com> *	Keith Whitwell <keith@tungstengraphics.com> * */#include "tdfx_context.h"#include "tdfx_lock.h"#include "tdfx_span.h"#include "tdfx_render.h"#include "swrast/swrast.h"#define DBG 0#define LOCAL_VARS							\   driRenderbuffer *drb = (driRenderbuffer *) rb;			\   __DRIdrawablePrivate *const dPriv = drb->dPriv;			\   GLuint pitch = drb->backBuffer ? info.strideInBytes			\     : (drb->pitch * drb->cpp);						\   const GLuint bottom = dPriv->h - 1;					\   char *buf = (char *)((char *)info.lfbPtr +				\			 (dPriv->x * drb->cpp) +			\			 (dPriv->y * pitch));				\   GLuint p;								\   (void) buf; (void) p;#define Y_FLIP(_y)		(bottom - _y)#define HW_WRITE_LOCK()							\   tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);				\   GrLfbInfo_t info;							\   FLUSH_BATCH( fxMesa );						\   UNLOCK_HARDWARE( fxMesa );						\   LOCK_HARDWARE( fxMesa );						\   info.size = sizeof(GrLfbInfo_t);					\   if (fxMesa->Glide.grLfbLock(GR_LFB_WRITE_ONLY, fxMesa->DrawBuffer,	\			       LFB_MODE, GR_ORIGIN_UPPER_LEFT, FXFALSE,	\			       &info)) {#define HW_WRITE_UNLOCK()						\      fxMesa->Glide.grLfbUnlock( GR_LFB_WRITE_ONLY, fxMesa->DrawBuffer );\   }#define HW_READ_LOCK()							\   tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);				\   GrLfbInfo_t info;							\   FLUSH_BATCH( fxMesa );						\   UNLOCK_HARDWARE( fxMesa );						\   LOCK_HARDWARE( fxMesa );						\   info.size = sizeof(GrLfbInfo_t);					\   if ( fxMesa->Glide.grLfbLock( GR_LFB_READ_ONLY, fxMesa->ReadBuffer,	\                   LFB_MODE, GR_ORIGIN_UPPER_LEFT, FXFALSE, &info ) )	\   {#define HW_READ_UNLOCK()						\      fxMesa->Glide.grLfbUnlock( GR_LFB_READ_ONLY, fxMesa->ReadBuffer );\   }#define HW_WRITE_CLIPLOOP()						\      do {								\         int _nc = fxMesa->numClipRects;				\         while (_nc--) {						\            int minx = fxMesa->pClipRects[_nc].x1 - fxMesa->x_offset;	\	    int miny = fxMesa->pClipRects[_nc].y1 - fxMesa->y_offset;	\	    int maxx = fxMesa->pClipRects[_nc].x2 - fxMesa->x_offset;	\	    int maxy = fxMesa->pClipRects[_nc].y2 - fxMesa->y_offset;#define HW_READ_CLIPLOOP()						\      do {								\         const __DRIdrawablePrivate *dPriv = fxMesa->driDrawable;	\         drm_clip_rect_t *rect = dPriv->pClipRects;			\         int _nc = dPriv->numClipRects;					\         while (_nc--) {						\            const int minx = rect->x1 - fxMesa->x_offset;		\            const int miny = rect->y1 - fxMesa->y_offset;		\            const int maxx = rect->x2 - fxMesa->x_offset;		\            const int maxy = rect->y2 - fxMesa->y_offset;		\            rect++;#define HW_ENDCLIPLOOP()						\	 }								\      } while (0)#define LFB_MODE	GR_LFBWRITEMODE_565/* 16 bit, RGB565 color spanline and pixel functions */			\#undef INIT_MONO_PIXEL#define INIT_MONO_PIXEL(p, color) \  p = TDFXPACKCOLOR565( color[0], color[1], color[2] )#define WRITE_RGBA( _x, _y, r, g, b, a )				\   *(GLushort *)(buf + _x*2 + _y*pitch) = ((((int)r & 0xf8) << 8) |	\					   (((int)g & 0xfc) << 3) |	\					   (((int)b & 0xf8) >> 3))#define WRITE_PIXEL( _x, _y, p )					\    *(GLushort *)(buf + _x*2 + _y*pitch) = p#define READ_RGBA( rgba, _x, _y )					\    do {								\	GLushort p = *(GLushort *)(buf + _x*2 + _y*pitch);		\	rgba[0] = (((p >> 11) & 0x1f) * 255) / 31;			\	rgba[1] = (((p >>  5) & 0x3f) * 255) / 63;			\	rgba[2] = (((p >>  0) & 0x1f) * 255) / 31;			\	rgba[3] = 0xff;							\    } while (0)#define TAG(x) tdfx##x##_RGB565#define BYTESPERPIXEL 2#include "spantmp.h"#undef BYTESPERPIXEL/* 16 bit, BGR565 color spanline and pixel functions */			\#if 0#define WRITE_RGBA( _x, _y, r, g, b, a )				\   *(GLushort *)(buf + _x*2 + _y*pitch) = ((((int)b & 0xf8) << 8) |	\					   (((int)g & 0xfc) << 3) |	\					   (((int)r & 0xf8) >> 3))#define WRITE_PIXEL( _x, _y, p )					\    *(GLushort *)(buf + _x*2 + _y*pitch) = p#define READ_RGBA( rgba, _x, _y )					\    do {								\	GLushort p = *(GLushort *)(buf + _x*2 + _y*pitch);		\	rgba[0] = (p << 3) & 0xf8;					\	rgba[1] = (p >> 3) & 0xfc;					\	rgba[2] = (p >> 8) & 0xf8;					\	rgba[3] = 0xff;							\    } while (0)#define TAG(x) tdfx##x##_BGR565#define BYTESPERPIXEL 2#include "spantmp.h"#undef BYTESPERPIXEL#endif#undef LFB_MODE#define LFB_MODE	GR_LFBWRITEMODE_888/* 24 bit, RGB888 color spanline and pixel functions */#undef INIT_MONO_PIXEL#define INIT_MONO_PIXEL(p, color) \  p = TDFXPACKCOLOR888( color[0], color[1], color[2] )#define WRITE_RGBA( _x, _y, r, g, b, a )				\   *(GLuint *)(buf + _x*3 + _y*pitch) = ((b << 0) |			\					 (g << 8) |			\					 (r << 16))#define WRITE_PIXEL( _x, _y, p )					\   *(GLuint *)(buf + _x*3 + _y*pitch) = p#define READ_RGBA( rgba, _x, _y )					\do {									\   GLuint p = *(GLuint *)(buf + _x*3 + _y*pitch);			\   rgba[0] = (p >> 16) & 0xff;						\   rgba[1] = (p >> 8)  & 0xff;						\   rgba[2] = (p >> 0)  & 0xff;						\   rgba[3] = 0xff;							\} while (0)#define TAG(x) tdfx##x##_RGB888#define BYTESPERPIXEL 4#include "spantmp.h"#undef BYTESPERPIXEL#undef LFB_MODE#define LFB_MODE	GR_LFBWRITEMODE_8888/* 32 bit, ARGB8888 color spanline and pixel functions */#undef INIT_MONO_PIXEL#define INIT_MONO_PIXEL(p, color) \  p = TDFXPACKCOLOR8888( color[0], color[1], color[2], color[3] )#define WRITE_RGBA( _x, _y, r, g, b, a )				\   *(GLuint *)(buf + _x*4 + _y*pitch) = ((b <<  0) |			\					 (g <<  8) |			\					 (r << 16) |			\					 (a << 24) )#define WRITE_PIXEL( _x, _y, p )					\   *(GLuint *)(buf + _x*4 + _y*pitch) = p#define READ_RGBA( rgba, _x, _y )					\do {									\   GLuint p = *(GLuint *)(buf + _x*4 + _y*pitch);			\   rgba[0] = (p >> 16) & 0xff;						\   rgba[1] = (p >>  8) & 0xff;						\   rgba[2] = (p >>  0) & 0xff;						\   rgba[3] = (p >> 24) & 0xff;						\} while (0)#define TAG(x) tdfx##x##_ARGB8888#define BYTESPERPIXEL 4#include "spantmp.h"#undef BYTESPERPIXEL/* ================================================================ * Old span functions below... *//* * Examine the cliprects to generate an array of flags to indicate * which pixels in a span are visible.  Note: (x,y) is a screen * coordinate. */static voidgenerate_vismask(const tdfxContextPtr fxMesa, GLint x, GLint y, GLint n,                 GLubyte vismask[]){   GLboolean initialized = GL_FALSE;   GLint i, j;   /* Ensure we clear the visual mask */   MEMSET(vismask, 0, n);   /* turn on flags for all visible pixels */   for (i = 0; i < fxMesa->numClipRects; i++) {      const drm_clip_rect_t *rect = &fxMesa->pClipRects[i];      if (y >= rect->y1 && y < rect->y2) {	 if (x >= rect->x1 && x + n <= rect->x2) {	    /* common case, whole span inside cliprect */	    MEMSET(vismask, 1, n);	    return;	 }	 if (x < rect->x2 && x + n >= rect->x1) {	    /* some of the span is inside the rect */	    GLint start, end;	    if (!initialized) {	       MEMSET(vismask, 0, n);	       initialized = GL_TRUE;	    }	    if (x < rect->x1)	       start = rect->x1 - x;	    else	       start = 0;	    if (x + n > rect->x2)	       end = rect->x2 - x;	    else	       end = n;	    assert(start >= 0);	    assert(end <= n);	    for (j = start; j < end; j++)	       vismask[j] = 1;	 }      }   }}/* * Examine cliprects and determine if the given screen pixel is visible. */static GLbooleanvisible_pixel(const tdfxContextPtr fxMesa, int scrX, int scrY){   int i;   for (i = 0; i < fxMesa->numClipRects; i++) {      const drm_clip_rect_t *rect = &fxMesa->pClipRects[i];      if (scrX >= rect->x1 &&	  scrX < rect->x2 &&	  scrY >= rect->y1 && scrY < rect->y2) return GL_TRUE;   }   return GL_FALSE;}/* * Depth buffer read/write functions. *//* * To read the frame buffer, we need to lock and unlock it.  The * four macros {READ,WRITE}_FB_SPAN_{LOCK,UNLOCK} * do this for us. * * Note that the lock must be matched with an unlock.  These * macros include a spare curly brace, so they must * be syntactically matched. * * Note, also, that you can't lock a buffer twice with different * modes.  That is to say, you can't lock a buffer in both read * and write modes.  The strideInBytes and LFB pointer will be * the same with read and write locks, so you can use either. * o The HW has different state for reads and writes, so *   locking it twice may give screwy results. * o The DRM won't let you lock twice.  It hangs.  This is probably *   because of the LOCK_HARDWARE IN THE *_FB_SPAN_LOCK macros, *   and could be eliminated with nonlocking lock routines.  But *   what's the point after all. */#define READ_FB_SPAN_LOCK(fxMesa, info, target_buffer)              \  UNLOCK_HARDWARE(fxMesa);                                          \  LOCK_HARDWARE(fxMesa);                                            \  (info).size=sizeof(info);                                         \  if (fxMesa->Glide.grLfbLock(GR_LFB_READ_ONLY,                     \                target_buffer,                                      \                GR_LFBWRITEMODE_ANY,                                \                GR_ORIGIN_UPPER_LEFT,                               \                FXFALSE,                                            \                &(info))) {#define READ_FB_SPAN_UNLOCK(fxMesa, target_buffer)                  \    fxMesa->Glide.grLfbUnlock(GR_LFB_READ_ONLY, target_buffer);     \  } else {                                                          \    fprintf(stderr, "tdfxDriver: Can't get %s (%d) read lock\n",    \            (target_buffer == GR_BUFFER_BACKBUFFER)                 \                ? "back buffer"                                     \            : ((target_buffer == GR_BUFFER_AUXBUFFER)               \                ? "depth buffer"                                    \               : "unknown buffer"),                                 \            target_buffer);                                         \  }#define WRITE_FB_SPAN_LOCK(fxMesa, info, target_buffer, write_mode) \  UNLOCK_HARDWARE(fxMesa);                                          \  LOCK_HARDWARE(fxMesa);                                            \  info.size=sizeof(info);                                           \  if (fxMesa->Glide.grLfbLock(GR_LFB_WRITE_ONLY,                    \                target_buffer,                                      \                write_mode,                                         \                GR_ORIGIN_UPPER_LEFT,                               \                FXFALSE,                                            \                &info)) {#define WRITE_FB_SPAN_UNLOCK(fxMesa, target_buffer)                 \    fxMesa->Glide.grLfbUnlock(GR_LFB_WRITE_ONLY, target_buffer);    \  } else {                                                          \    fprintf(stderr, "tdfxDriver: Can't get %s (%d) write lock\n",   \            (target_buffer == GR_BUFFER_BACKBUFFER)                 \                ? "back buffer"                                     \            : ((target_buffer == GR_BUFFER_AUXBUFFER)               \                ? "depth buffer"                                    \               : "unknown buffer"),                                 \            target_buffer);                                         \  }/* * Because the Linear Frame Buffer is not necessarily aligned * with the depth buffer, we have to do some fiddling * around to get the right addresses. * * Perhaps a picture is in order.  The Linear Frame Buffer * looks like this: * *   |<----------------------info.strideInBytes------------->| *   |<-----physicalStrideInBytes------->| *   +-----------------------------------+xxxxxxxxxxxxxxxxxxx+ *   |                                   |                   | *   |          Legal Memory             |  Forbidden Zone   | *   |                                   |                   | *   +-----------------------------------+xxxxxxxxxxxxxxxxxxx+ * * You can only reliably read and write legal locations.  Reads * and writes from the Forbidden Zone will return undefined values, * and may cause segmentation faults. * * Now, the depth buffer may not end up in a location such each * scan line is an LFB line.  For example, the depth buffer may * look like this: * *    wrapped               ordinary. *   +-----------------------------------+xxxxxxxxxxxxxxxxxxx+ *   |0000000000000000000000             |                   | back *   |1111111111111111111111             |                   | buffer *   |2222222222222222222222             |                   | *   |4096b align. padxx00000000000000000|  Forbidden Zone   | depth *   |0000              11111111111111111|                   | buffer *   |1111              22222222222222222|                   | *   |2222                               |                   | *   +-----------------------------------+xxxxxxxxxxxxxxxxxxx+ * where each number is the scan line number.  We know it will * be aligned on 128 byte boundaries, at least.  Aligning this * on a scanline boundary causes the back and depth buffers to * thrash in the SST1 cache.  (Note that the back buffer is always * allocated at the beginning of LFB memory, and so it is always * properly aligned with the LFB stride.) * * We call the beginning of the line (which is the rightmost * part of the depth line in the picture above) the *ordinary* part * of the scanline, and the end of the line (which is the * leftmost part, one line below) the *wrapped* part of the scanline. * a.) We need to know what x value to subtract from the screen *     x coordinate to index into the wrapped part. * b.) We also need to figure out if we need to read from the ordinary *     part scan line, or from the wrapped part of the scan line. * * [ad a] * The first wrapped x coordinate is that coordinate such that *           depthBufferOffset&(info.strideInBytes) + x*elmentSize  {*} *                            > physicalStrideInBytes *     where depthBufferOffset is the LFB distance in bytes *     from the back buffer to the depth buffer.  The expression *           depthBufferOffset&(info.strideInBytes) *     is then the offset (in bytes) from the beginining of (any) *     depth buffer line to first element in the line. * Simplifying inequation {*} above we see that x is the smallest * value such that *         x*elementSize > physicalStrideInBytes                      {**} *                            - depthBufferOffset&(info.strideInBytes) * Now, we know that both the summands on the right are multiples of * 128, and elementSize <= 4, so if equality holds in {**}, x would * be a multiple of 32.  Thus we can set x to *         xwrapped = (physicalStrideInBytes *                      - depthBufferOffset&(info.strideInBytes))/elementSize *                      + 1 * * [ad b] * Question b is now simple.  We read from the wrapped scan line if * x is greater than xwrapped.

⌨️ 快捷键说明

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