📄 tdfx_span.c
字号:
*/#define TILE_WIDTH_IN_BYTES 128#define TILE_WIDTH_IN_ZOXELS(bpz) (TILE_WIDTH_IN_BYTES/(bpz))#define TILE_HEIGHT_IN_LINES 32typedef struct{ void *lfbPtr; void *lfbWrapPtr; FxU32 LFBStrideInElts; GLint firstWrappedX;}LFBParameters;/* * We need information about the back buffer. Note that * this function *cannot be called* while the aux buffer * is locked, or the caller will hang. * * Only Glide knows the LFB address of the back and depth * offsets. The upper levels of Mesa know the depth offset, * but that is not in LFB space, it is tiled memory space, * and is not useable for us. */static voidGetBackBufferInfo(tdfxContextPtr fxMesa, GrLfbInfo_t * backBufferInfo){ READ_FB_SPAN_LOCK(fxMesa, *backBufferInfo, GR_BUFFER_BACKBUFFER); READ_FB_SPAN_UNLOCK(fxMesa, GR_BUFFER_BACKBUFFER);}static voidGetFbParams(tdfxContextPtr fxMesa, GrLfbInfo_t * info, GrLfbInfo_t * backBufferInfo, LFBParameters * ReadParamsp, FxU32 elementSize){ FxU32 physicalStrideInBytes, bufferOffset; FxU32 strideInBytes = info->strideInBytes; char *lfbPtr = (char *) (info->lfbPtr); /* For arithmetic, use char * */ /* * These two come directly from the info structure. */ ReadParamsp->lfbPtr = (void *) lfbPtr; ReadParamsp->LFBStrideInElts = strideInBytes / elementSize; /* * Now, calculate the value of firstWrappedX. * * The physical stride is the screen width in bytes rounded up to * the next highest multiple of 128 bytes. Note that this fails * when TILE_WIDTH_IN_BYTES is not a power of two. * * The buffer Offset is the distance between the beginning of * the LFB space, which is the beginning of the back buffer, * and the buffer we are gathering information about. * We want to make this routine usable for operations on the * back buffer, though we don't actually use it on the back * buffer. Note, then, that if bufferOffset == 0, the firstWrappedX * is in the forbidden zone, and is therefore never reached. * * Note that if * physicalStrideInBytes * < bufferOffset&(info->strideInBytes-1) * the buffer begins in the forbidden zone. We assert for this. */ bufferOffset = (FxU32)(lfbPtr - (char *) backBufferInfo->lfbPtr); physicalStrideInBytes = (fxMesa->screen_width * elementSize + TILE_WIDTH_IN_BYTES - 1) & ~(TILE_WIDTH_IN_BYTES - 1); assert(physicalStrideInBytes > (bufferOffset & (strideInBytes - 1))); ReadParamsp->firstWrappedX = (physicalStrideInBytes - (bufferOffset & (strideInBytes - 1))) / elementSize; /* * This is the address of the next physical line. */ ReadParamsp->lfbWrapPtr = (void *) ((char *) backBufferInfo->lfbPtr + (bufferOffset & ~(strideInBytes - 1)) + (TILE_HEIGHT_IN_LINES) * strideInBytes);}/* * These macros fetch data from the frame buffer. The type is * the type of data we want to fetch. It should match the type * whose size was used with GetFbParams to fill in the structure * in *ReadParamsp. We have a macro to read the ordinary * part, a second macro to read the wrapped part, and one which * will do either. When we are reading a span, we will know * when the ordinary part ends, so there's no need to test for * it. However, when reading and writing pixels, we don't * necessarily know. I suppose it's a matter of taste whether * it's better in the macro or in the call. * * Recall that x and y are screen coordinates. */#define GET_ORDINARY_FB_DATA(ReadParamsp, type, x, y) \ (((type *)((ReadParamsp)->lfbPtr)) \ [(y) * ((ReadParamsp)->LFBStrideInElts) \ + (x)])#define GET_WRAPPED_FB_DATA(ReadParamsp, type, x, y) \ (((type *)((ReadParamsp)->lfbWrapPtr)) \ [((y)) * ((ReadParamsp)->LFBStrideInElts) \ + ((x) - (ReadParamsp)->firstWrappedX)])#define GET_FB_DATA(ReadParamsp, type, x, y) \ (((x) < (ReadParamsp)->firstWrappedX) \ ? GET_ORDINARY_FB_DATA(ReadParamsp, type, x, y) \ : GET_WRAPPED_FB_DATA(ReadParamsp, type, x, y))#define PUT_ORDINARY_FB_DATA(ReadParamsp, type, x, y, value) \ (GET_ORDINARY_FB_DATA(ReadParamsp, type, x, y) = (type)(value))#define PUT_WRAPPED_FB_DATA(ReadParamsp, type, x, y, value) \ (GET_WRAPPED_FB_DATA(ReadParamsp, type, x, y) = (type)(value))#define PUT_FB_DATA(ReadParamsp, type, x, y, value) \ do { \ if ((x) < (ReadParamsp)->firstWrappedX) \ PUT_ORDINARY_FB_DATA(ReadParamsp, type, x, y, value); \ else \ PUT_WRAPPED_FB_DATA(ReadParamsp, type, x, y, value); \ } while (0)static voidtdfxDDWriteDepthSpan(GLcontext * ctx, struct gl_renderbuffer *rb, GLuint n, GLint x, GLint y, const void *values, const GLubyte mask[]){ const GLuint *depth = (const GLuint *) values; tdfxContextPtr fxMesa = (tdfxContextPtr) ctx->DriverCtx; GLint bottom = fxMesa->y_offset + fxMesa->height - 1; GLuint depth_size = fxMesa->glCtx->Visual.depthBits; GLuint stencil_size = fxMesa->glCtx->Visual.stencilBits; GrLfbInfo_t info; GLubyte visMask[MAX_WIDTH]; if (MESA_VERBOSE & VERBOSE_DRIVER) { fprintf(stderr, "tdfxmesa: tdfxDDWriteDepthSpan(...)\n"); } assert((depth_size == 16) || (depth_size == 24) || (depth_size == 32)); /* * Convert x and y to screen coordinates. */ x += fxMesa->x_offset; y = bottom - y; if (mask) { GLint i; GLushort d16; GrLfbInfo_t backBufferInfo; switch (depth_size) { case 16: GetBackBufferInfo(fxMesa, &backBufferInfo); /* * Note that the _LOCK macro adds a curly brace, * and the UNLOCK macro removes it. */ WRITE_FB_SPAN_LOCK(fxMesa, info, GR_BUFFER_AUXBUFFER, GR_LFBWRITEMODE_ANY); generate_vismask(fxMesa, x, y, n, visMask); { LFBParameters ReadParams; int wrappedPartStart; GetFbParams(fxMesa, &info, &backBufferInfo, &ReadParams, sizeof(GLushort)); if (ReadParams.firstWrappedX <= x) { wrappedPartStart = 0; } else if (n <= (ReadParams.firstWrappedX - x)) { wrappedPartStart = n; } else { wrappedPartStart = (ReadParams.firstWrappedX - x); } for (i = 0; i < wrappedPartStart; i++) { if (mask[i] && visMask[i]) { d16 = depth[i]; PUT_ORDINARY_FB_DATA(&ReadParams, GLushort, x + i, y, d16); } } for (; i < n; i++) { if (mask[i] && visMask[i]) { d16 = depth[i]; PUT_WRAPPED_FB_DATA(&ReadParams, GLushort, x + i, y, d16); } } } WRITE_FB_SPAN_UNLOCK(fxMesa, GR_BUFFER_AUXBUFFER); break; case 24: case 32: GetBackBufferInfo(fxMesa, &backBufferInfo); /* * Note that the _LOCK macro adds a curly brace, * and the UNLOCK macro removes it. */ WRITE_FB_SPAN_LOCK(fxMesa, info, GR_BUFFER_AUXBUFFER, GR_LFBWRITEMODE_ANY); generate_vismask(fxMesa, x, y, n, visMask); { LFBParameters ReadParams; int wrappedPartStart; GetFbParams(fxMesa, &info, &backBufferInfo, &ReadParams, sizeof(GLuint)); if (ReadParams.firstWrappedX <= x) { wrappedPartStart = 0; } else if (n <= (ReadParams.firstWrappedX - x)) { wrappedPartStart = n; } else { wrappedPartStart = (ReadParams.firstWrappedX - x); } for (i = 0; i < wrappedPartStart; i++) { GLuint d32; if (mask[i] && visMask[i]) { if (stencil_size > 0) { d32 = GET_ORDINARY_FB_DATA(&ReadParams, GLuint, x + i, y); d32 = (d32 & 0xFF000000) | (depth[i] & 0x00FFFFFF); } else { d32 = depth[i]; } PUT_ORDINARY_FB_DATA(&ReadParams, GLuint, x + i, y, d32); } } for (; i < n; i++) { GLuint d32; if (mask[i] && visMask[i]) { if (stencil_size > 0) { d32 = GET_WRAPPED_FB_DATA(&ReadParams, GLuint, x + i, y); d32 = (d32 & 0xFF000000) | (depth[i] & 0x00FFFFFF); } else { d32 = depth[i]; } PUT_WRAPPED_FB_DATA(&ReadParams, GLuint, x + i, y, d32); } } } WRITE_FB_SPAN_UNLOCK(fxMesa, GR_BUFFER_AUXBUFFER); break; } } else { GLint i; GLuint d32; GLushort d16; GrLfbInfo_t backBufferInfo; switch (depth_size) { case 16: GetBackBufferInfo(fxMesa, &backBufferInfo); /* * Note that the _LOCK macro adds a curly brace, * and the UNLOCK macro removes it. */ WRITE_FB_SPAN_LOCK(fxMesa, info, GR_BUFFER_AUXBUFFER, GR_LFBWRITEMODE_ANY); generate_vismask(fxMesa, x, y, n, visMask); { LFBParameters ReadParams; GLuint wrappedPartStart; GetFbParams(fxMesa, &info, &backBufferInfo, &ReadParams, sizeof(GLushort)); if (ReadParams.firstWrappedX <= x) { wrappedPartStart = 0; } else if (n <= (ReadParams.firstWrappedX - x)) { wrappedPartStart = n; } else { wrappedPartStart = (ReadParams.firstWrappedX - x); } for (i = 0; i < wrappedPartStart; i++) { if (visMask[i]) { d16 = depth[i]; PUT_ORDINARY_FB_DATA(&ReadParams, GLushort, x + i, y, d16); } } for (; i < n; i++) { if (visMask[i]) { d16 = depth[i]; PUT_WRAPPED_FB_DATA(&ReadParams, GLushort, x + i, y, d16); } } } WRITE_FB_SPAN_UNLOCK(fxMesa, GR_BUFFER_AUXBUFFER); break; case 24: case 32: GetBackBufferInfo(fxMesa, &backBufferInfo); /* * Note that the _LOCK macro adds a curly brace, * and the UNLOCK macro removes it. */ WRITE_FB_SPAN_LOCK(fxMesa, info, GR_BUFFER_AUXBUFFER, GR_LFBWRITEMODE_ANY); generate_vismask(fxMesa, x, y, n, visMask); { LFBParameters ReadParams; GLuint wrappedPartStart; GetFbParams(fxMesa, &info, &backBufferInfo, &ReadParams, sizeof(GLuint)); if (ReadParams.firstWrappedX <= x) { wrappedPartStart = 0; } else if (n <= (ReadParams.firstWrappedX - x)) { wrappedPartStart = n; } else { wrappedPartStart = (ReadParams.firstWrappedX - x); } for (i = 0; i < wrappedPartStart; i++) { if (visMask[i]) { if (stencil_size > 0) { d32 = GET_ORDINARY_FB_DATA(&ReadParams, GLuint, x + i, y); d32 = (d32 & 0xFF000000) | (depth[i] & 0x00FFFFFF); } else { d32 = depth[i]; } PUT_ORDINARY_FB_DATA(&ReadParams, GLuint, x + i, y, d32); } } for (; i < n; i++) { if (visMask[i]) { if (stencil_size > 0) { d32 = GET_WRAPPED_FB_DATA(&ReadParams, GLuint, x + i, y); d32 = (d32 & 0xFF000000) | (depth[i] & 0x00FFFFFF); } else { d32 = depth[i]; } PUT_WRAPPED_FB_DATA(&ReadParams, GLuint, x + i, y, d32); } } } WRITE_FB_SPAN_UNLOCK(fxMesa, GR_BUFFER_AUXBUFFER); break; } }}static voidtdfxDDWriteMonoDepthSpan(GLcontext * ctx, struct gl_renderbuffer *rb, GLuint n, GLint x, GLint y, const void *value, const GLubyte mask[]){ GLuint depthVal = *((GLuint *) value); GLuint depths[MAX_WIDTH]; GLuint i; for (i = 0; i < n; i++) depths[i] = depthVal; tdfxDDWriteDepthSpan(ctx, rb, n, x, y, depths, mask);}static voidtdfxDDReadDepthSpan(GLcontext * ctx, struct gl_renderbuffer *rb, GLuint n, GLint x, GLint y, void *values){ GLuint *depth = (GLuint *) values; tdfxContextPtr fxMesa = (tdfxContextPtr) ctx->DriverCtx; GLint bottom = fxMesa->height + fxMesa->y_offset - 1; GLuint i; GLuint depth_size = fxMesa->glCtx->Visual.depthBits; GrLfbInfo_t info; if (MESA_VERBOSE & VERBOSE_DRIVER) { fprintf(stderr, "tdfxmesa: tdfxDDReadDepthSpan(...)\n"); } /* * Convert to screen coordinates. */ x += fxMesa->x_offset; y = bottom - y; switch (depth_size) { case 16: { LFBParameters ReadParams; GrLfbInfo_t backBufferInfo; int wrappedPartStart; GetBackBufferInfo(fxMesa, &backBufferInfo); /* * Note that the _LOCK macro adds a curly brace, * and the UNLOCK macro removes it. */ READ_FB_SPAN_LOCK(fxMesa, info, GR_BUFFER_AUXBUFFER); GetFbParams(fxMesa, &info, &backBufferInfo, &ReadParams, sizeof(GLushort)); if (ReadParams.firstWrappedX <= x) { wrappedPartStart = 0; } else if (n <= (ReadParams.firstWrappedX - x)) { wrappedPartStart = n; } else { wrappedPartStart = (ReadParams.firstWrappedX - x); } /* * Read the line. */ for (i = 0; i < wrappedPartStart; i++) { depth[i] = GET_ORDINARY_FB_DATA(&ReadParams, GLushort, x + i, y); } for (; i < n; i++) { depth[i] = GET_WRAPPED_FB_DATA(&ReadParams, GLushort, x + i, y); } READ_FB_SPAN_UNLOCK(fxMesa, GR_BUFFER_AUXBUFFER); break; } case 24: case 32: { LFBParameters ReadParams; GrLfbInfo_t backBufferInfo; int wrappedPartStart; GLuint stencil_size = fxMesa->glCtx->Visual.stencilBits; GetBackBufferInfo(fxMesa, &backBufferInfo); /* * Note that the _LOCK macro adds a curly brace, * and the UNLOCK macro removes it. */ READ_FB_SPAN_LOCK(fxMesa, info, GR_BUFFER_AUXBUFFER); GetFbParams(fxMesa, &info, &backBufferInfo, &ReadParams, sizeof(GLuint)); if (ReadParams.firstWrappedX <= x) { wrappedPartStart = 0; } else if (n <= (ReadParams.firstWrappedX - x)) { wrappedPartStart = n; } else { wrappedPartStart = (ReadParams.firstWrappedX - x); } /* * Read the line. */ for (i = 0; i < wrappedPartStart; i++) { const GLuint mask = (stencil_size > 0) ? 0x00FFFFFF : 0xFFFFFFFF; depth[i] = GET_ORDINARY_FB_DATA(&ReadParams, GLuint, x + i, y); depth[i] &= mask; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -