Remove all the radeon_subset files. They were completely unused. Keith

Whitwell says, "[T]he radeon subset code can probably be archived now."
This "fixes" bug #1623.
This commit is contained in:
Ian Romanick 2005-04-08 23:54:20 +00:00
parent a657c1aee8
commit db382c5b1d
6 changed files with 0 additions and 3522 deletions

View File

@ -1,75 +0,0 @@
/**
* \file radeon_subset.h
* \brief Radeon subset driver declarations.
*
* \author Keith Whitwell <keith@tungstengraphics.com>
*/
/*
* Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
* Tungsten Grahpics Inc., Austin, Texas.
*
* 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
* ATI, TUNGSTEN GRAHPICS AND/OR THEIR 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.
*/
/* $XFree86$ */
#ifndef __RADEON_SUBSET_H__
#define __RADEON_SUBSET_H__
extern void radeonPointsBitmap( GLsizei width, GLsizei height,
GLfloat xorig, GLfloat yorig,
GLfloat xmove, GLfloat ymove,
const GLubyte *bitmap );
extern void radeonReadPixels( GLint x, GLint y,
GLsizei width, GLsizei height,
GLenum format, GLenum type,
GLvoid *pixels );
extern void radeon_select_Install( GLcontext *ctx );
extern void radeonInitSelect( GLcontext *ctx );
extern void radeonVtxfmtDestroy( GLcontext *ctx );
extern void radeonVtxfmtMakeCurrent( GLcontext *ctx );
extern void radeonVtxfmtUnbindContext( GLcontext *ctx );
extern void radeonVtxfmtInit( GLcontext *ctx );
extern void radeonTclFallback( GLcontext *ctx, GLuint bit, GLboolean mode );
extern void radeonVtxfmtInvalidate( GLcontext *ctx );
extern void radeonSubsetVtxEnableTCL( radeonContextPtr rmesa, GLboolean flag );
extern void radeonUpdateTextureState( GLcontext *ctx );
extern void radeonInitTextureFuncs( GLcontext *ctx );
extern void radeonAgeTextures( radeonContextPtr rmesa, int heap );
extern void radeonDestroyTexObj( radeonContextPtr rmesa, radeonTexObjPtr t );
#endif

View File

@ -1,197 +0,0 @@
/**
* \file radeon_subset_bitmap.c
* \brief Bitmap drawing.
*
* \author Keith Whitwell <keith@tungstengraphics.com>
*/
/*
* Copyright 2003 ATI Technologies Inc., Ontario, Canada, and
* Tungsten Graphics Inc., Cedar Park, Texas.
*
* 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
* ATI, TUNGSTEN GRAPHICS AND/OR THEIR 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.
*
*/
/* $XFree86$ */
#include "glheader.h"
#include "mtypes.h"
#include "colormac.h"
#include "context.h"
#include "enums.h"
#include "imports.h"
#include "image.h"
/*#include "mmath.h"*/
#include "macros.h"
#include "state.h"
#include "radeon_context.h"
#include "radeon_ioctl.h"
#include "radeon_state.h"
#include "radeon_subset.h"
/**
* \brief Cope with depth operations by drawing individual pixels as points
*
* \param xorig x coordinate of the bitmap corner.
* \param yorig y coordinate of the bitmap corner.
* \param xmove increment to the final x coordinate.
* \param ymove increment to the final y coordinate.
* \param width bitmap width.
* \param height bitmap height.
* \param bitmap bitmap pointer.
*
* Clips the bitmap coordinates and adjusts for windows coordinates. Draws the
* bitmap with glPoints(), turning off TCL and hardware viewport transformation
* to emit raw pixel coordinates. Finally fires any outstanding vertices and
* restores TCL, viewport, texture and color states.
*/
void
radeonPointsBitmap( GLsizei width, GLsizei height,
GLfloat xorig, GLfloat yorig,
GLfloat xmove, GLfloat ymove,
const GLubyte *bitmap )
{
GET_CURRENT_CONTEXT(ctx);
GLsizei bmwidth = width, bmheight = height;
GLint px, py;
radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
GLfloat saved_color[4], saved_tex0[2];
GLint row, col;
GLuint orig_se_cntl;
GLuint w, h;
const struct gl_pixelstore_attrib *unpack = &ctx->Unpack;
ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
if (width < 0 || height < 0) {
_mesa_error( ctx, GL_INVALID_VALUE, "glBitmap(width or height < 0)" );
return;
}
if (!ctx->Current.RasterPosValid)
return;
if (ctx->NewState)
_mesa_update_state(ctx);
if (ctx->_RotateMode) {
width = bmheight; height = bmwidth;
px = IFLOOR(ctx->Current.RasterPos[0] + yorig);
py = IFLOOR(ctx->Current.RasterPos[1] + xorig);
ctx->Current.RasterPos[0] += ymove;
ctx->Current.RasterPos[1] += xmove;
}
else {
px = IFLOOR(ctx->Current.RasterPos[0] - xorig);
py = IFLOOR(ctx->Current.RasterPos[1] - yorig);
ctx->Current.RasterPos[0] += xmove;
ctx->Current.RasterPos[1] += ymove;
}
/* Turn off tcl and the hw viewport transformation so that we can
* emit raw pixel coordinates:
*/
radeonSubsetVtxEnableTCL( rmesa, GL_FALSE );
RADEON_STATECHANGE( rmesa, set );
orig_se_cntl = rmesa->hw.set.cmd[SET_SE_CNTL];
rmesa->hw.set.cmd[SET_SE_CNTL] &= ~(RADEON_VPORT_XY_XFORM_ENABLE |
RADEON_VPORT_Z_XFORM_ENABLE);
/* Adjust for window coordinates, flip y values:
*/
h = rmesa->dri.drawable->h + rmesa->dri.drawable->y - 1;
w = rmesa->dri.drawable->w;
px += rmesa->dri.drawable->x;
/* Save current color, texcoord to restore later:
*/
COPY_4V( saved_color, ctx->Current.Attrib[VERT_ATTRIB_COLOR0] );
COPY_2V( saved_tex0, ctx->Current.Attrib[VERT_ATTRIB_TEX0] );
/* Just use the GL entrypoints to talk to radeon_subset_vtx.c:
*/
glBegin( GL_POINTS );
glColor4fv( ctx->Current.RasterColor );
glTexCoord2fv( ctx->Current.RasterTexCoords[0] );
if (ctx->_RotateMode) {
for (col=0; col<width; col++) {
const GLubyte *src = (const GLubyte *)
_mesa_image_address2d(unpack, bitmap, height, width,
GL_COLOR_INDEX, GL_BITMAP, col, 0 );
/* Msb first */
GLubyte mask = 128U >> (unpack->SkipPixels & 0x7);
for (row=0; row<height; row++) {
if (*src & mask) {
glVertex2f( px-col, h - (py + row) );
}
src += mask & 1;
mask = ((mask << 7) & 0xff) | (mask >> 1);
}
/* get ready for next row */
if (mask != 128)
src++;
}
}
else {
for (row=0; row<height; row++) {
const GLubyte *src = (const GLubyte *)
_mesa_image_address2d(unpack, bitmap, width, height,
GL_COLOR_INDEX, GL_BITMAP, row, 0 );
/* Msb first */
GLubyte mask = 128U >> (unpack->SkipPixels & 0x7);
for (col=0; col<width; col++) {
if (*src & mask) {
glVertex2f( px+col, h - (py + row) );
}
src += mask & 1;
mask = ((mask << 7) & 0xff) | (mask >> 1);
}
/* get ready for next row */
if (mask != 128)
src++;
}
}
glEnd();
glColor4fv( saved_color );
glTexCoord2fv( saved_tex0 );
/* Fire outstanding vertices, restore state
*/
RADEON_STATECHANGE( rmesa, set );
rmesa->hw.set.cmd[SET_SE_CNTL] = orig_se_cntl;
radeonSubsetVtxEnableTCL( rmesa, GL_TRUE );
}

View File

@ -1,246 +0,0 @@
/**
* \file radeon_subset_readpix.c
* \brief Pixel reading.
*
* \author Keith Whitwell <keith@tungstengraphics.com>
* \author Brian Paul <brian@tungstengraphics.com>
*/
/*
* Copyright 2003 ATI Technologies Inc., Ontario, Canada, and
* Tungsten Graphics Inc., Cedar Park, Texas.
*
* 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
* ATI, TUNGSTEN GRAPHICS AND/OR THEIR 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.
*/
/* $XFree86$ */
#include "glheader.h"
#include "mtypes.h"
#include "colormac.h"
#include "context.h"
#include "enums.h"
#include "imports.h"
/*#include "mmath.h" */
#include "macros.h"
#include "state.h"
#include "radeon_context.h"
#include "radeon_ioctl.h"
#include "radeon_state.h"
#include "radeon_subset.h"
/**
* \brief Read pixel in RGBA format on a Radeon 16bpp frame buffer.
*
* \param rgba destination pointer.
* \param ptr pointer to the pixel in the frame buffer.
*/
#define READ_RGBA_16( rgba, ptr ) \
do { \
GLushort p = *(GLushort *)ptr; \
rgba[0] = ((p >> 8) & 0xf8) * 255 / 0xf8; \
rgba[1] = ((p >> 3) & 0xfc) * 255 / 0xfc; \
rgba[2] = ((p << 3) & 0xf8) * 255 / 0xf8; \
rgba[3] = 0xff; \
} while (0)
/**
* \brief Read pixel in RGBA format on a Radeon 32bpp frame buffer.
*
* \param rgba destination pointer.
* \param ptr pointer to the pixel in the frame buffer.
*/
#define READ_RGBA_32( rgba, ptr ) \
do { \
GLuint p = *(GLuint *)ptr; \
rgba[0] = (p >> 16) & 0xff; \
rgba[1] = (p >> 8) & 0xff; \
rgba[2] = (p >> 0) & 0xff; \
rgba[3] = (p >> 24) & 0xff; \
} while (0)
/**
* \brief Read a span in RGBA format.
*
* \param ctx GL context.
* \param n number of pixels in the span.
* \param x x position of the span start.
* \param y y position of the span.
* \param rgba destination buffer.
*
* Calculates the pointer to the span start in the frame buffer and uses either
* #READ_RGBA_16 or #READ_RGBA_32 macros to copy the values.
*/
static void ReadRGBASpan( const GLcontext *ctx,
GLuint n, GLint x, GLint y,
GLubyte rgba[][4])
{
radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
radeonScreenPtr radeonScreen = rmesa->radeonScreen;
__DRIdrawablePrivate *dPriv = rmesa->dri.drawable;
GLuint cpp = radeonScreen->cpp;
GLuint pitch = radeonScreen->frontPitch * cpp;
GLint i;
if (ctx->_RotateMode) {
char *ptr = (char *)(rmesa->dri.screen->pFB +
rmesa->state.pixel.readOffset +
((dPriv->x + (dPriv->w - y - 1)) * cpp) +
((dPriv->y + (dPriv->h - x - 1)) * pitch));
if (cpp == 4)
for (i = 0; i < n; i++, ptr -= pitch)
READ_RGBA_32( rgba[i], ptr );
else
for (i = 0; i < n; i++, ptr -= pitch)
READ_RGBA_16( rgba[i], ptr );
}
else {
char *ptr = (char *)(rmesa->dri.screen->pFB +
rmesa->state.pixel.readOffset +
((dPriv->x + x) * cpp) +
((dPriv->y + (dPriv->h - y - 1)) * pitch));
if (cpp == 4)
for (i = 0; i < n; i++, ptr += cpp)
READ_RGBA_32( rgba[i], ptr );
else
for (i = 0; i < n; i++, ptr += cpp)
READ_RGBA_16( rgba[i], ptr );
}
}
/**
* \brief Optimized glReadPixels().
*
* To be used with particular pixel formats GL_UNSIGNED_BYTE and GL_RGBA, when pixel
* scaling, biasing and mapping are disabled.
*
* \param x x start position of the reading rectangle.
* \param y y start position of the reading rectangle.
* \param width width of the reading rectangle.
* \param height height of the reading rectangle.
* \param format pixel format. Must be GL_RGBA.
* \param type pixel type. Must be GL_UNSIGNED_BYTE.
* \param pixels pixel data.
*
* After asserting the above conditions, compensates for clipping and calls
* ReadRGBASpan() to read each row.
*/
void radeonReadPixels( GLint x, GLint y,
GLsizei width, GLsizei height,
GLenum format, GLenum type,
GLvoid *pixels )
{
GET_CURRENT_CONTEXT(ctx);
GLint srcX = x;
GLint srcY = y;
GLint readWidth = width; /* actual width read */
GLint readHeight = height; /* actual height read */
const struct gl_pixelstore_attrib *packing = &ctx->Pack;
GLint skipRows = packing->SkipRows;
GLint skipPixels = packing->SkipPixels;
GLint rowLength;
ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
{
GLint tmp, tmps;
tmp = x; x = y; y = tmp;
tmps = width; width = height; height = tmps;
}
if (width < 0 || height < 0) {
_mesa_error( ctx, GL_INVALID_VALUE,
"glReadPixels(width=%d height=%d)", width, height );
return;
}
if (!pixels) {
_mesa_error( ctx, GL_INVALID_VALUE, "glReadPixels(pixels)" );
return;
}
if (ctx->NewState)
_mesa_update_state(ctx);
/* can't do scale, bias, mapping, etc */
assert(!ctx->_ImageTransferState);
/* can't do fancy pixel packing */
assert (packing->Alignment == 1 &&
!packing->SwapBytes &&
!packing->LsbFirst);
if (packing->RowLength > 0)
rowLength = packing->RowLength;
else
rowLength = width;
/* horizontal clipping */
if (srcX < 0) {
skipPixels -= srcX;
readWidth += srcX;
srcX = 0;
}
if (srcX + readWidth > (GLint) ctx->ReadBuffer->Width)
readWidth -= (srcX + readWidth - (GLint) ctx->ReadBuffer->Width);
if (readWidth <= 0)
return;
/* vertical clipping */
if (srcY < 0) {
skipRows -= srcY;
readHeight += srcY;
srcY = 0;
}
if (srcY + readHeight > (GLint) ctx->ReadBuffer->Height)
readHeight -= (srcY + readHeight - (GLint) ctx->ReadBuffer->Height);
if (readHeight <= 0)
return;
/*
* Ready to read!
* The window region at (destX, destY) of size (readWidth, readHeight)
* will be read back.
* We'll write pixel data to buffer pointed to by "pixels" but we'll
* skip "skipRows" rows and skip "skipPixels" pixels/row.
*/
if (format == GL_RGBA && type == GL_UNSIGNED_BYTE) {
GLchan *dest = (GLchan *) pixels
+ (skipRows * rowLength + skipPixels) * 4;
GLint row;
for (row=0; row<readHeight; row++) {
ReadRGBASpan(ctx, readWidth, srcX, srcY, (GLchan (*)[4]) dest);
dest += rowLength * 4;
srcY++;
}
}
else {
/* can't do this format/type combination */
assert(0);
}
}

View File

@ -1,998 +0,0 @@
/**
* \file radeon_subset_select.c
* \brief Selection.
*/
/*
* Mesa 3-D graphics library
* Version: 4.1
*
* Copyright (C) 1999-2002 Brian Paul 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 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
* BRIAN PAUL 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.
*/
/* $Id: radeon_subset_select.c,v 1.2 2003/08/22 20:11:45 brianp Exp $ */
#include "glheader.h"
#include "imports.h"
#include "context.h"
/*#include "mmath.h"*/
#include "mtypes.h"
#include "enums.h"
#include "glapi.h"
#include "feedback.h"
#include "radeon_context.h"
#include "radeon_subset.h"
/**
* \brief Vertex.
*/
typedef struct {
struct { GLfloat x, y, z, w; } pos; /**< \brief position */
struct { GLfloat x, y, z, w; } eyePos; /**< \brief position, eye coordinates */
struct { GLfloat x, y, z, w; } clipPos; /**< \brief clipped coordinates */
struct { GLfloat x, y, z, w; } winPos; /**< \brief position, windows coordinates */
struct { GLfloat s, t; } texCoord; /**< \brief texture coordinates */
struct { GLfloat r, g, b, a; } color; /**< \brief color */
} vertex;
/**
* \brief Vertex buffer.
*/
static struct select_vb_t {
GLuint vCount; /**< \brief vertex count */
vertex vBuffer[4]; /**< \brief vertex buffer */
GLboolean lineReset;
GLboolean partialLineLoop; /**< \brief whether we are in a middle of a line loop */
} vb;
/**********************************************************************/
/** \name Vertex Transformation and Clipping */
/**********************************************************************/
/*@{*/
/**
* \brief Transform a point (column vector) by a matrix: Q = M * P.
*
* \param Q destination point.
* \param P source point.
* \param M transformation matrix.
*/
#define TRANSFORM_POINT( Q, M, P ) \
Q.x = M[0] * P.x + M[4] * P.y + M[8] * P.z + M[12] * P.w; \
Q.y = M[1] * P.x + M[5] * P.y + M[9] * P.z + M[13] * P.w; \
Q.z = M[2] * P.x + M[6] * P.y + M[10] * P.z + M[14] * P.w; \
Q.w = M[3] * P.x + M[7] * P.y + M[11] * P.z + M[15] * P.w;
/**
* \brief Clip coord to window coord mapping.
*
* \param Q destination point.
* \param P source point.
* \param VP view port.
*/
#define MAP_POINT( Q, P, VP ) \
Q.x = (GLfloat) (((P.x / P.w) + 1.0) * VP.Width / 2.0 + VP.X); \
Q.y = (GLfloat) (((P.y / P.w) + 1.0) * VP.Height / 2.0 + VP.Y); \
Q.z = (GLfloat) (((P.z / P.w) + 1.0) * (VP.Far - VP.Near) / 2.0 + VP.Near);\
Q.w = (GLfloat) P.w;
/**
* \brief Linear interpolation: (1 - T) * A + T * B.
*
* \param T interpolation factor.
* \param A first value.
* \param B second value.
* \result interpolated value.
*/
#define INTERPOLATE(T, A, B) ((A) + ((B) - (A)) * (T))
/**
* \brief Interpolate vertex position, color, texcoords, etc.
*
* \param t interpolation factor.
* \param v0 first vertex.
* \param v1 second vertex.
* \param vOut output vertex.
*
* Uses the #INTERPOLATE macro for all the interpolation of all elements.
*/
static void
interpolate_vertex(GLfloat t, const vertex *v0, const vertex *v1,
vertex *vOut)
{
vOut->eyePos.x = INTERPOLATE(t, v0->eyePos.x, v1->eyePos.x);
vOut->eyePos.y = INTERPOLATE(t, v0->eyePos.y, v1->eyePos.y);
vOut->eyePos.z = INTERPOLATE(t, v0->eyePos.z, v1->eyePos.z);
vOut->eyePos.w = INTERPOLATE(t, v0->eyePos.w, v1->eyePos.w);
vOut->clipPos.x = INTERPOLATE(t, v0->clipPos.x, v1->clipPos.x);
vOut->clipPos.y = INTERPOLATE(t, v0->clipPos.y, v1->clipPos.y);
vOut->clipPos.z = INTERPOLATE(t, v0->clipPos.z, v1->clipPos.z);
vOut->clipPos.w = INTERPOLATE(t, v0->clipPos.w, v1->clipPos.w);
vOut->color.r = INTERPOLATE(t, v0->color.r, v1->color.r);
vOut->color.g = INTERPOLATE(t, v0->color.g, v1->color.g);
vOut->color.b = INTERPOLATE(t, v0->color.b, v1->color.b);
vOut->color.a = INTERPOLATE(t, v0->color.a, v1->color.a);
vOut->texCoord.s = INTERPOLATE(t, v0->texCoord.s, v1->texCoord.s);
vOut->texCoord.t = INTERPOLATE(t, v0->texCoord.t, v1->texCoord.t);
}
/*
* Clip bit codes
*/
#define CLIP_LEFT 1
#define CLIP_RIGHT 2
#define CLIP_BOTTOM 4
#define CLIP_TOP 8
#define CLIP_NEAR 16
#define CLIP_FAR 32
/**
* \brief Apply view volume clip testing to a point.
*
* \param v point to test.
* \return zero if visible, or the clip code mask, i.e., binary OR of a
* combination of the #CLIP_LEFT, #CLIP_RIGHT, #CLIP_BOTTOM, #CLIP_TOP, #CLIP_NEAR,
* #CLIP_FAR clip bit codes.
*/
static GLuint
clip_point(const vertex *v)
{
GLuint mask = 0;
if (v->clipPos.x > v->clipPos.w) mask |= CLIP_RIGHT;
if (v->clipPos.x < -v->clipPos.w) mask |= CLIP_LEFT;
if (v->clipPos.y > v->clipPos.w) mask |= CLIP_TOP;
if (v->clipPos.y < -v->clipPos.w) mask |= CLIP_BOTTOM;
if (v->clipPos.z > v->clipPos.w) mask |= CLIP_FAR;
if (v->clipPos.z < -v->clipPos.w) mask |= CLIP_NEAR;
return mask;
}
/**
* \def GENERAL_CLIP
* \brief Clipping utility macro.
*
* We use 6 instances of this code in each of the clip_line() and
* clip_polygon() to clip against the 6 planes. For each plane, we define the
* #OUTSIDE and #COMPUTE_INTERSECTION macros appropriately.
*/
/**
* \brief Apply clipping to a line segment.
*
* \param v0in input start vertex
* \param v1in input end vertesx
* \param v0new output start vertex
* \param v1new output end vertex
*
* \return GL_TRUE if the line segment is visible, or GL_FALSE if it is totally
* clipped.
*
* \sa #GENERAL_CLIP.
*/
static GLboolean
clip_line(const vertex *v0in, const vertex *v1in,
vertex *v0new, vertex *v1new)
{
vertex v0, v1, vNew;
GLfloat dx, dy, dz, dw, t;
GLuint code0, code1;
code0 = clip_point(v0in);
code1 = clip_point(v1in);
if (code0 & code1)
return GL_FALSE; /* totally clipped */
*v0new = *v0in;
*v1new = *v1in;
if (code0 == 0 && code1 == 0)
return GL_TRUE; /* no clipping needed */
v0 = *v0in;
v1 = *v1in;
#define GENERAL_CLIP \
if (OUTSIDE(v0)) { \
if (OUTSIDE(v1)) { \
/* both verts are outside ==> return 0 */ \
return 0; \
} \
else { \
/* v0 is outside, v1 is inside ==> clip */ \
COMPUTE_INTERSECTION( v1, v0, vNew ) \
interpolate_vertex(t, &v1, &v0, &vNew); \
v0 = vNew; \
} \
} \
else { \
if (OUTSIDE(v1)) { \
/* v0 is inside, v1 is outside ==> clip */ \
COMPUTE_INTERSECTION( v0, v1, vNew ) \
interpolate_vertex(t, &v0, &v1, &vNew); \
v1 = vNew; \
} \
/* else both verts are inside ==> do nothing */ \
}
/* Clip against +X side */
#define OUTSIDE(V) (V.clipPos.x > V.clipPos.w)
#define COMPUTE_INTERSECTION( IN, OUT, NEW ) \
dx = OUT.clipPos.x - IN.clipPos.x; \
dw = OUT.clipPos.w - IN.clipPos.w; \
t = (IN.clipPos.x - IN.clipPos.w) / (dw-dx);
GENERAL_CLIP
#undef OUTSIDE
#undef COMPUTE_INTERSECTION
/* Clip against -X side */
#define OUTSIDE(V) (V.clipPos.x < -(V.clipPos.w))
#define COMPUTE_INTERSECTION( IN, OUT, NEW ) \
dx = OUT.clipPos.x - IN.clipPos.x; \
dw = OUT.clipPos.w - IN.clipPos.w; \
t = -(IN.clipPos.x + IN.clipPos.w) / (dw+dx);
GENERAL_CLIP
#undef OUTSIDE
#undef COMPUTE_INTERSECTION
/* Clip against +Y side */
#define OUTSIDE(V) (V.clipPos.y > V.clipPos.w)
#define COMPUTE_INTERSECTION( IN, OUT, NEW ) \
dy = OUT.clipPos.y - IN.clipPos.y; \
dw = OUT.clipPos.w - IN.clipPos.w; \
t = (IN.clipPos.y - IN.clipPos.w) / (dw-dy);
GENERAL_CLIP
#undef OUTSIDE
#undef COMPUTE_INTERSECTION
/* Clip against -Y side */
#define OUTSIDE(V) (V.clipPos.y < -(V.clipPos.w))
#define COMPUTE_INTERSECTION( IN, OUT, NEW ) \
dy = OUT.clipPos.y - IN.clipPos.y; \
dw = OUT.clipPos.w - IN.clipPos.w; \
t = -(IN.clipPos.y + IN.clipPos.w) / (dw+dy);
GENERAL_CLIP
#undef OUTSIDE
#undef COMPUTE_INTERSECTION
/* Clip against +Z side */
#define OUTSIDE(V) (V.clipPos.z > V.clipPos.w)
#define COMPUTE_INTERSECTION( IN, OUT, NEW ) \
dz = OUT.clipPos.z - IN.clipPos.z; \
dw = OUT.clipPos.w - IN.clipPos.w; \
t = (IN.clipPos.z - IN.clipPos.w) / (dw-dz);
GENERAL_CLIP
#undef OUTSIDE
#undef COMPUTE_INTERSECTION
/* Clip against -Z side */
#define OUTSIDE(V) (V.clipPos.z < -(V.clipPos.w))
#define COMPUTE_INTERSECTION( IN, OUT, NEW ) \
dz = OUT.clipPos.z - IN.clipPos.z; \
dw = OUT.clipPos.w - IN.clipPos.w; \
t = -(IN.clipPos.z + IN.clipPos.w) / (dw+dz);
GENERAL_CLIP
#undef OUTSIDE
#undef COMPUTE_INTERSECTION
#undef GENERAL_CLIP
*v0new = v0;
*v1new = v1;
return GL_TRUE;
}
/**
* \brief Apply clipping to a polygon.
*
* \param vIn array of input vertices.
* \param inCount number of input vertices
* \param vOut array of output vertices.
*
* \return number of vertices in \p vOut.
*
* \sa #GENERAL_CLIP.
*/
static GLuint
clip_polygon(const vertex *vIn, unsigned int inCount, vertex *vOut)
{
vertex inlist[20], outlist[20];
GLfloat dx, dy, dz, dw, t;
GLuint incount, outcount, previ, curri, result;
const vertex *currVert, *prevVert;
vertex *newVert;
#define GENERAL_CLIP(INCOUNT, INLIST, OUTCOUNT, OUTLIST) \
if (INCOUNT < 3) \
return GL_FALSE; \
previ = INCOUNT - 1; /* let previous = last vertex */ \
prevVert = INLIST + previ; \
OUTCOUNT = 0; \
for (curri = 0; curri < INCOUNT; curri++) { \
currVert = INLIST + curri; \
if (INSIDE(currVert)) { \
if (INSIDE(prevVert)) { \
/* both verts are inside ==> copy current to outlist */ \
OUTLIST[OUTCOUNT] = *currVert; \
OUTCOUNT++; \
} \
else { \
newVert = OUTLIST + OUTCOUNT; \
/* current is inside and previous is outside ==> clip */ \
COMPUTE_INTERSECTION( currVert, prevVert, newVert ) \
OUTCOUNT++; \
/* Output current */ \
OUTLIST[OUTCOUNT] = *currVert; \
OUTCOUNT++; \
} \
} \
else { \
if (INSIDE(prevVert)) { \
newVert = OUTLIST + OUTCOUNT; \
/* current is outside and previous is inside ==> clip */ \
COMPUTE_INTERSECTION( prevVert, currVert, newVert ); \
OUTLIST[OUTCOUNT] = *newVert; \
OUTCOUNT++; \
} \
/* else both verts are outside ==> do nothing */ \
} \
/* let previous = current */ \
previ = curri; \
prevVert = currVert; \
}
/*
* Clip against +X
*/
#define INSIDE(V) (V->clipPos.x <= V->clipPos.w)
#define COMPUTE_INTERSECTION( IN, OUT, NEW ) \
dx = OUT->clipPos.x - IN->clipPos.x; \
dw = OUT->clipPos.w - IN->clipPos.w; \
t = (IN->clipPos.x - IN->clipPos.w) / (dw - dx); \
interpolate_vertex(t, IN, OUT, NEW );
GENERAL_CLIP(inCount, vIn, outcount, outlist)
#undef INSIDE
#undef COMPUTE_INTERSECTION
/*
* Clip against -X
*/
#define INSIDE(V) (V->clipPos.x >= -V->clipPos.w)
#define COMPUTE_INTERSECTION( IN, OUT, NEW ) \
dx = OUT->clipPos.x - IN->clipPos.x; \
dw = OUT->clipPos.w - IN->clipPos.w; \
t = -(IN->clipPos.x + IN->clipPos.w) / (dw + dx); \
interpolate_vertex(t, IN, OUT, NEW );
GENERAL_CLIP(outcount, outlist, incount, inlist)
#undef INSIDE
#undef COMPUTE_INTERSECTION
/*
* Clip against +Y
*/
#define INSIDE(V) (V->clipPos.y <= V->clipPos.w)
#define COMPUTE_INTERSECTION( IN, OUT, NEW ) \
dy = OUT->clipPos.y - IN->clipPos.y; \
dw = OUT->clipPos.w - IN->clipPos.w; \
t = (IN->clipPos.y - IN->clipPos.w) / (dw - dy); \
interpolate_vertex(t, IN, OUT, NEW );
GENERAL_CLIP(incount, inlist, outcount, outlist)
#undef INSIDE
#undef COMPUTE_INTERSECTION
/*
* Clip against -Y
*/
#define INSIDE(V) (V->clipPos.y >= -V->clipPos.w)
#define COMPUTE_INTERSECTION( IN, OUT, NEW ) \
dy = OUT->clipPos.y - IN->clipPos.y; \
dw = OUT->clipPos.w - IN->clipPos.w; \
t = -(IN->clipPos.y + IN->clipPos.w) / (dw + dy); \
interpolate_vertex(t, IN, OUT, NEW );
GENERAL_CLIP(outcount, outlist, incount, inlist)
#undef INSIDE
#undef COMPUTE_INTERSECTION
/*
* Clip against +Z
*/
#define INSIDE(V) (V->clipPos.z <= V->clipPos.w)
#define COMPUTE_INTERSECTION( IN, OUT, NEW ) \
dz = OUT->clipPos.z - IN->clipPos.z; \
dw = OUT->clipPos.w - IN->clipPos.w; \
t = (IN->clipPos.z - IN->clipPos.w) / (dw - dz); \
interpolate_vertex(t, IN, OUT, NEW );
GENERAL_CLIP(incount, inlist, outcount, outlist)
#undef INSIDE
#undef COMPUTE_INTERSECTION
/*
* Clip against -Z
*/
#define INSIDE(V) (V->clipPos.z >= -V->clipPos.w)
#define COMPUTE_INTERSECTION( IN, OUT, NEW ) \
dz = OUT->clipPos.z - IN->clipPos.z; \
dw = OUT->clipPos.w - IN->clipPos.w; \
t = -(IN->clipPos.z + IN->clipPos.w) / (dw + dz); \
interpolate_vertex(t, IN, OUT, NEW );
GENERAL_CLIP(outcount, outlist, result, vOut)
#undef INSIDE
#undef COMPUTE_INTERSECTION
#undef GENERAL_CLIP
return result;
}
/*@}*/
/**********************************************************************/
/** \name Selection */
/**********************************************************************/
/*@{*/
/**
* \brief Select point.
*
* \param v vertex.
*
* If the clipped point is visible then maps the vertex into window coordinates
* and calls _mesa_update_hitflag().
*/
static void
select_point(const vertex *v)
{
GET_CURRENT_CONTEXT(ctx);
if (clip_point(v) == 0)
{
vertex c = *v;
MAP_POINT(c.winPos, c.clipPos, ctx->Viewport);
_mesa_update_hitflag(ctx, c.winPos.z);
}
}
/**
* \brief Select line.
*
* \param v0 first vertex.
* \param v1 second vertex.
*
* If the clipped line is visible then maps the vertices into window coordinates
* and calls _mesa_update_hitflag().
*/
static void
select_line(const vertex *v0, const vertex *v1)
{
GET_CURRENT_CONTEXT(ctx);
vertex c0, c1;
if (clip_line(v0, v1, &c0, &c1))
{
MAP_POINT(c0.winPos, c0.clipPos, ctx->Viewport);
MAP_POINT(c1.winPos, c1.clipPos, ctx->Viewport);
_mesa_update_hitflag(ctx, c0.winPos.z);
_mesa_update_hitflag(ctx, c1.winPos.z);
}
}
/**
* \brief Select line.
*
* \param v0 first vertex.
* \param v1 second vertex.
* \param v2 third vertex.
*
* If the clipped polygon is visible then maps the vertices into window
* coordinates and calls _mesa_update_hitflag().
*/
static void
select_triangle(const vertex *v0,
const vertex *v1,
const vertex *v2)
{
GET_CURRENT_CONTEXT(ctx);
vertex vlist[3], vclipped[8];
GLuint i, n;
vlist[0] = *v0;
vlist[1] = *v1;
vlist[2] = *v2;
n = clip_polygon(vlist, 3, vclipped);
for (i = 0; i < n; i++) {
MAP_POINT(vclipped[i].winPos, vclipped[i].clipPos, ctx->Viewport);
_mesa_update_hitflag(ctx, vclipped[i].winPos.z);
}
}
/**
* \brief Set current vertex coordinates.
*
* \param x x vertex coordinate.
* \param y y vertex coordinate.
* \param z z vertex coordinate.
* \param w homogeneous coordinate.
*
* Stores the vertex and current attributes in ::vb, transforms it into eye space and then clip space.
*
* If a sufficient number of vertices is stored calls one of select_point(),
* select_line() or select_triangle(), according to the current primitive.
*/
static void
radeon_select_Vertex4f(GLfloat x, GLfloat y, GLfloat z, GLfloat w)
{
GET_CURRENT_CONTEXT(ctx);
struct gl_polygon_attrib *p = &(ctx->Polygon);
vertex *v = vb.vBuffer + vb.vCount;
/* store the vertex */
v->pos.x = x;
v->pos.y = y;
v->pos.z = z;
v->pos.w = w;
v->color.r = ctx->Current.Attrib[VERT_ATTRIB_COLOR0][0];
v->color.g = ctx->Current.Attrib[VERT_ATTRIB_COLOR0][1];
v->color.b = ctx->Current.Attrib[VERT_ATTRIB_COLOR0][2];
v->color.a = ctx->Current.Attrib[VERT_ATTRIB_COLOR0][3];
v->texCoord.s = ctx->Current.Attrib[VERT_ATTRIB_TEX0][0];
v->texCoord.t = ctx->Current.Attrib[VERT_ATTRIB_TEX0][1];
/* transform to eye space, then clip space */
TRANSFORM_POINT(v->eyePos, ctx->ModelviewMatrixStack.Top->m, v->pos);
TRANSFORM_POINT(v->clipPos, ctx->ProjectionMatrixStack.Top->m, v->eyePos);
switch (ctx->Driver.CurrentExecPrimitive) {
case GL_POINTS:
assert(vb.vCount == 0);
select_point(v);
break;
case GL_LINES:
if (vb.vCount == 0)
{
vb.vCount = 1;
}
else
{
assert(vb.vCount == 1);
select_line(vb.vBuffer + 0, vb.vBuffer + 1);
vb.vCount = 0;
}
break;
case GL_LINE_STRIP:
if (vb.vCount == 0)
{
vb.vCount = 1;
}
else
{
assert(vb.vCount == 1);
select_line(vb.vBuffer + 0, vb.vBuffer + 1);
vb.vBuffer[0] = vb.vBuffer[1];
/* leave vb.vCount at 1 */
}
break;
case GL_LINE_LOOP:
if (vb.vCount == 0)
{
vb.vCount = 1;
vb.partialLineLoop = GL_FALSE;
}
else if (vb.vCount == 1)
{
select_line(vb.vBuffer + 0, vb.vBuffer + 1);
vb.partialLineLoop = GL_TRUE;
vb.vCount = 2;
}
else
{
assert(vb.vCount == 2);
vb.partialLineLoop = GL_FALSE;
select_line(vb.vBuffer + 1, vb.vBuffer + 2);
vb.vBuffer[1] = vb.vBuffer[2];
/* leave vb.vCount at 2 */
}
break;
case GL_TRIANGLES:
if (vb.vCount == 0 || vb.vCount == 1)
{
vb.vCount++;
}
else
{
assert(vb.vCount == 2);
select_triangle(vb.vBuffer + 0, vb.vBuffer + 1, vb.vBuffer + 2);
vb.vCount = 0;
}
break;
case GL_TRIANGLE_STRIP:
if (vb.vCount == 0 || vb.vCount == 1)
{
vb.vCount++;
}
else if (vb.vCount == 2)
{
select_triangle(vb.vBuffer + 0, vb.vBuffer + 1, vb.vBuffer + 2);
vb.vCount = 3;
}
else
{
assert(vb.vCount == 3);
select_triangle(vb.vBuffer + 1, vb.vBuffer + 3, vb.vBuffer + 2);
vb.vBuffer[0] = vb.vBuffer[2];
vb.vBuffer[1] = vb.vBuffer[3];
vb.vCount = 2;
}
break;
case GL_TRIANGLE_FAN:
if (vb.vCount == 0 || vb.vCount == 1)
{
vb.vCount++;
}
else
{
assert(vb.vCount == 2);
select_triangle(vb.vBuffer + 0, vb.vBuffer + 1, vb.vBuffer + 2);
vb.vBuffer[1] = vb.vBuffer[2];
/* leave vb.vCount = 2 */
}
break;
case GL_QUADS:
if (vb.vCount < 3)
{
vb.vCount++;
}
else
{
assert(vb.vCount == 3);
select_triangle(vb.vBuffer + 0, vb.vBuffer + 1, vb.vBuffer + 2);
select_triangle(vb.vBuffer + 0, vb.vBuffer + 2, vb.vBuffer + 3);
vb.vCount = 0;
}
break;
case GL_QUAD_STRIP:
if (vb.vCount < 3)
{
vb.vCount++;
}
else
{
assert(vb.vCount == 3);
select_triangle(vb.vBuffer + 0, vb.vBuffer + 1, vb.vBuffer + 2);
select_triangle(vb.vBuffer + 1, vb.vBuffer + 3, vb.vBuffer + 2);
vb.vBuffer[0] = vb.vBuffer[2];
vb.vBuffer[1] = vb.vBuffer[3];
vb.vCount = 2;
}
break;
case GL_POLYGON:
switch (p->FrontMode) {
case GL_POINT:
assert(vb.vCount == 0);
select_point(v);
break;
case GL_LINE:
if (vb.vCount == 0)
{
vb.vCount = 1;
vb.partialLineLoop = GL_FALSE;
}
else if (vb.vCount == 1)
{
select_line(vb.vBuffer + 0, vb.vBuffer + 1);
vb.partialLineLoop = GL_TRUE;
vb.vCount = 2;
}
else
{
assert(vb.vCount == 2);
vb.partialLineLoop = GL_FALSE;
select_line(vb.vBuffer + 1, vb.vBuffer + 2);
vb.vBuffer[1] = vb.vBuffer[2];
/* leave vb.vCount at 2 */
}
break;
case GL_FILL:
/* draw as a tri-fan */
if (vb.vCount == 0 || vb.vCount == 1)
{
vb.vCount++;
}
else
{
assert(vb.vCount == 2);
select_triangle(vb.vBuffer + 0, vb.vBuffer + 1, vb.vBuffer + 2);
vb.vBuffer[1] = vb.vBuffer[2];
/* leave vb.vCount = 2 */
}
break;
default:
; /* impossible */
}
break;
default:
; /* outside begin/end -- no action required */
}
}
/**
* \brief Calls radeon_select_Vertex4f().
*/
static void radeon_select_Vertex2f(GLfloat x, GLfloat y)
{
radeon_select_Vertex4f(x, y, 0.0, 1.0);
}
/**
* \brief Calls radeon_select_Vertex4f().
*/
static void radeon_select_Vertex2fv(const GLfloat * v)
{
radeon_select_Vertex4f(v[0], v[1], 0.0, 1.0);
}
/**
* \brief Calls radeon_select_Vertex4f().
*/
static void radeon_select_Vertex3f(GLfloat x, GLfloat y, GLfloat z)
{
radeon_select_Vertex4f(x, y, z, 1.0);
}
/**
* \brief Calls radeon_select_Vertex4f().
*/
static void radeon_select_Vertex3fv(const GLfloat * v)
{
radeon_select_Vertex4f(v[0], v[1], v[2], 1.0);
}
/**
* \brief Set current vertex color.
*
* \param r red color component.
* \param g gree color component.
* \param b blue color component.
* \param a alpha color component.
*
* Updates the GL context's current vertex color.
*/
static void radeon_select_Color4f( GLfloat r, GLfloat g,
GLfloat b, GLfloat a )
{
GET_CURRENT_CONTEXT(ctx);
GLfloat *dest = ctx->Current.Attrib[VERT_ATTRIB_COLOR0];
dest[0] = r;
dest[1] = g;
dest[2] = b;
dest[3] = a;
}
/**
* \brief Calls radeon_select_Color4f().
*/
static void radeon_select_Color4fv( const GLfloat *v )
{
radeon_select_Color4f( v[0], v[1], v[2], v[3] );
}
/**
* \brief Calls radeon_select_Color4f().
*/
static void radeon_select_Color3f( GLfloat r, GLfloat g, GLfloat b )
{
radeon_select_Color4f( r, g, b, 1.0 );
}
/**
* \brief Calls radeon_select_Color4f().
*/
static void radeon_select_Color3fv( const GLfloat *v )
{
radeon_select_Color4f( v[0], v[1], v[2], 1.0 );
}
/**
* \brief Set current vertex texture coordinates.
*
* \param s texture coordinate.
* \param t texture coordinate.
*
* Updates the GL context's current vertex texture coordinates.
*/
static __inline__ void radeon_select_TexCoord2f( GLfloat s, GLfloat t )
{
GET_CURRENT_CONTEXT(ctx);
GLfloat *dest = ctx->Current.Attrib[VERT_ATTRIB_TEX0];
dest[0] = s;
dest[1] = t;
}
/**
* \brief Calls radeon_select_TexCoord2f().
*/
static void radeon_select_TexCoord2fv( const GLfloat *v )
{
radeon_select_TexCoord2f( v[0], v[1] );
}
/**
* \brief Process glBegin().
*
* \param mode primitive.
*/
static void radeon_select_Begin(GLenum mode)
{
GET_CURRENT_CONTEXT(ctx);
if (mode > GL_POLYGON) {
_mesa_error( ctx, GL_INVALID_ENUM, "glBegin" );
return;
}
if (ctx->Driver.CurrentExecPrimitive != GL_POLYGON+1) {
_mesa_error( ctx, GL_INVALID_OPERATION, "glBegin" );
return;
}
ctx->Driver.CurrentExecPrimitive = mode;
vb.vCount = 0;
vb.lineReset = GL_TRUE;
vb.partialLineLoop = GL_FALSE;
}
/**
* \brief Process glEnd().
*/
static void radeon_select_End(void)
{
GET_CURRENT_CONTEXT(ctx);
if ( (ctx->Driver.CurrentExecPrimitive == GL_LINE_LOOP ||
(ctx->Driver.CurrentExecPrimitive == GL_POLYGON &&
ctx->Polygon.FrontMode == GL_LINE))
&& vb.vCount == 2 )
{
/* draw the last line segment */
if (vb.partialLineLoop)
select_line(vb.vBuffer + 1, vb.vBuffer + 0);
else
select_line(vb.vBuffer + 2, vb.vBuffer + 0);
}
ctx->Driver.CurrentExecPrimitive = GL_POLYGON+1;
}
/**
* \brief Flush vertices.
*
* \param ctx GL context.
* \param flags not used.
*
* Nothing much to do here, besides marking the vertices as flushed, as we
* don't buffer anything.
*/
static void radeonSelectFlushVertices( GLcontext *ctx, GLuint flags )
{
ctx->Driver.NeedFlush = 0;
}
/**
* \brief Install the select callbacks.
*
* \param ctx GL context.
*
* Installs the glBegin()/glEnd() associated select callbacks into the glapi
* table.
*/
void radeon_select_Install( GLcontext *ctx )
{
struct _glapi_table *exec = ctx->Exec;
exec->Color3f = radeon_select_Color3f;
exec->Color3fv = radeon_select_Color3fv;
exec->Color4f = radeon_select_Color4f;
exec->Color4fv = radeon_select_Color4fv;
exec->TexCoord2f = radeon_select_TexCoord2f;
exec->TexCoord2fv = radeon_select_TexCoord2fv;
exec->Vertex2f = radeon_select_Vertex2f;
exec->Vertex2fv = radeon_select_Vertex2fv;
exec->Vertex3f = radeon_select_Vertex3f;
exec->Vertex3fv = radeon_select_Vertex3fv;
exec->Begin = radeon_select_Begin;
exec->End = radeon_select_End;
ctx->Driver.FlushVertices = radeonSelectFlushVertices;
}
/*@}*/
/**
* \brief Set rasterization mode.
*
* \param ctx GL context.
* \param mode rasterization mode. Supports GL_RENDER or
*
* If mode is GL_RENDER, calls either radeonVtxfmtInit() or
* radeon_noop_Install depending on whether the application has focus
* (i.e., a fullscreen-cliprect) or not. If mode is GL_SELECT, calls
* radeon_select_Install().
*/
static void radeonRenderMode( GLcontext *ctx, GLenum mode )
{
switch (mode) {
case GL_RENDER:
radeonVtxfmtInit( ctx );
break;
case GL_SELECT:
radeon_select_Install( ctx );
break;
default:
break;
}
}
/**
* \brief Setup the GL context driver callbacks.
*
* \param ctx GL context.
*
* \sa Called by radeonCreateContext().
*/
void radeonInitSelect( GLcontext *ctx )
{
ctx->Driver.RenderMode = radeonRenderMode;
}

File diff suppressed because it is too large Load Diff

View File

@ -1,989 +0,0 @@
/**
* \file radeon_subset_vtx.c
* \brief Vertex buffering.
*
* \author Keith Whitwell <keith@tungstengraphics.com>
*/
/*
* Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
* Tungsten Graphics Inc., Cedar Park, Texas.
*
* 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
* ATI, TUNGSTEN GRAPHICS AND/OR THEIR 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.
*
*/
/* $XFree86$ */
#include "glheader.h"
#include "imports.h"
#include "api_noop.h"
#include "context.h"
/*#include "mmath.h" */
#include "mtypes.h"
#include "enums.h"
#include "glapi.h"
#include "colormac.h"
#include "state.h"
#include "radeon_context.h"
#include "radeon_state.h"
#include "radeon_ioctl.h"
#include "radeon_subset.h"
/**
* \brief Union for vertex data.
*/
union vertex_dword {
float f; /**< \brief floating point value */
int i; /**< \brief integer point value */
};
/**
* \brief Maximum number of dwords per vertex.
*
* Defined as 10 to hold: \code xyzw rgba st \endcode
*/
#define MAX_VERTEX_DWORDS 10
/**
* \brief Global vertex buffer data.
*/
static struct vb_t {
/**
* \brief Notification mechanism.
*
* These are treated as a stack to allow us to do things like build quads in
* temporary storage and then emit them as triangles.
*/
struct {
GLint vertspace; /**< \brief free vertices count */
GLint initial_vertspace; /**< \brief total vertices count */
GLint *dmaptr; /**< \brief */
void (*notify)( void ); /**< \brief notification callback */
} stack[2];
/**
* \brief Storage for current vertex.
*/
union vertex_dword vertex[MAX_VERTEX_DWORDS];
/**
* \brief Temporary storage for quads, etc.
*/
union vertex_dword vertex_store[MAX_VERTEX_DWORDS * 4];
/**
* \name Color/texture
*
* Pointers to either vertex or ctx->Current.Attrib, depending on whether
* color/texture participates in the current vertex.
*/
/*@{*/
GLfloat *floatcolorptr; /**< \brief color */
GLfloat *texcoordptr; /**< \brief texture */
/*@}*/
/**
* \brief Pointer to the GL context.
*/
GLcontext *context;
/**
* \brief Active primitive.
*
* \note May differ from ctx->Driver.CurrentExecPrimitive.
*/
/*@{*/
GLenum prim; /**< \brief primitive */
GLuint vertex_format; /**< \brief vertex format */
GLint vertex_size; /**< \brief vertex size */
GLboolean recheck; /**< \brief set if it's needed to validate this information */
/*@}*/
} vb;
static void radeonFlushVertices( GLcontext *, GLuint );
/**
* \brief Primitive information table.
*/
static struct prims_t {
int start, /**< \brief vertex count for the starting primitive */
incr, /**< \brief vertex increment for a further primitive */
hwprim; /**< \brief hardware primitive */
} prims[10] = {
{ 1, 1, RADEON_CP_VC_CNTL_PRIM_TYPE_POINT },
{ 2, 2, RADEON_CP_VC_CNTL_PRIM_TYPE_LINE },
{ 2, 1, RADEON_CP_VC_CNTL_PRIM_TYPE_LINE_STRIP },
{ 2, 1, RADEON_CP_VC_CNTL_PRIM_TYPE_LINE_STRIP },
{ 3, 3, RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_LIST },
{ 3, 1, RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_STRIP },
{ 3, 1, RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_FAN },
{ 4, 4, RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_LIST },
{ 4, 2, RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_STRIP },
{ 3, 1, RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_FAN },
};
/**
* \brief Finish the primitive in the vertex buffer.
*
* \param rmesa Radeon context.
*
* Truncates any redundant vertices off the end of the buffer, emit the
* remaining vertices and advances the current DMA region.
*/
static void finish_prim( radeonContextPtr rmesa )
{
GLuint prim_end = vb.stack[0].initial_vertspace - vb.stack[0].vertspace;
/* Too few vertices? (eg: 2 vertices for a triangles prim?)
*/
if (prim_end < prims[vb.prim].start)
return;
/* Drop redundant vertices off end of primitive. (eg: 5 vertices
* for triangles prim?)
*/
prim_end -= (prim_end - prims[vb.prim].start) % prims[vb.prim].incr;
radeonEmitVertexAOS( rmesa, vb.vertex_size, GET_START(&rmesa->dma.current) );
radeonEmitVbufPrim( rmesa, vb.vertex_format,
prims[vb.prim].hwprim | rmesa->tcl.tcl_flag,
prim_end );
rmesa->dma.current.ptr =
rmesa->dma.current.start += prim_end * vb.vertex_size * 4;
}
/**
* \brief Copy a vertex from the current DMA region
*
* \param rmesa Radeon context.
* \param n vertex index relative to the current DMA region.
* \param dst destination pointer.
*
* Used internally by copy_dma_verts().
*/
static void copy_vertex( radeonContextPtr rmesa, GLuint n, GLfloat *dst )
{
GLuint i;
GLfloat *src = (GLfloat *)(rmesa->dma.current.address +
rmesa->dma.current.ptr +
n * vb.vertex_size * 4);
for (i = 0 ; i < vb.vertex_size; i++)
dst[i] = src[i];
}
/**
* \brief Copy last vertices from the current DMA buffer to resume in a new buffer.
*
* \param rmesa Radeon context.
* \param tmp destination buffer.
*
* Takes from the current DMA buffer the last vertices necessary to resume in a
* new buffer, according to the current primitive. Uses internally
* copy_vertex() for the vertex copying.
*
*/
static GLuint copy_dma_verts( radeonContextPtr rmesa,
GLfloat (*tmp)[MAX_VERTEX_DWORDS] )
{
GLuint ovf, i;
GLuint nr = vb.stack[0].initial_vertspace - vb.stack[0].vertspace;
switch( vb.prim )
{
case GL_POINTS:
return 0;
case GL_LINES:
ovf = nr&1;
for (i = 0 ; i < ovf ; i++)
copy_vertex( rmesa, nr-ovf+i, tmp[i] );
return i;
case GL_LINE_STRIP:
if (nr == 0)
return 0;
copy_vertex( rmesa, nr-1, tmp[0] );
return 1;
case GL_LINE_LOOP:
case GL_TRIANGLE_FAN:
case GL_POLYGON:
if (nr == 0)
return 0;
else if (nr == 1) {
copy_vertex( rmesa, 0, tmp[0] );
return 1;
} else {
copy_vertex( rmesa, 0, tmp[0] );
copy_vertex( rmesa, nr-1, tmp[1] );
return 2;
}
case GL_TRIANGLES:
ovf = nr % 3;
for (i = 0 ; i < ovf ; i++)
copy_vertex( rmesa, nr-ovf+i, tmp[i] );
return i;
case GL_QUADS:
ovf = nr % 4;
for (i = 0 ; i < ovf ; i++)
copy_vertex( rmesa, nr-ovf+i, tmp[i] );
return i;
case GL_TRIANGLE_STRIP:
case GL_QUAD_STRIP:
ovf = MIN2(nr, 2);
for (i = 0 ; i < ovf ; i++)
copy_vertex( rmesa, nr-ovf+i, tmp[i] );
return i;
default:
return 0;
}
}
static void notify_wrap_buffer( void );
/**
* \brief Resets the vertex buffer notification mechanism.
*
* Fills in vb_t::stack with the values from the current DMA region in
* radeon_dma::current and sets the notification callback to
* notify_wrap_buffer().
*/
static void reset_notify( void )
{
radeonContextPtr rmesa = RADEON_CONTEXT( vb.context );
vb.stack[0].dmaptr = (int *)(rmesa->dma.current.address +
rmesa->dma.current.ptr);
vb.stack[0].vertspace = ((rmesa->dma.current.end - rmesa->dma.current.ptr) /
(vb.vertex_size * 4));
vb.stack[0].vertspace &= ~1; /* even numbers only -- avoid tristrip parity */
vb.stack[0].initial_vertspace = vb.stack[0].vertspace;
vb.stack[0].notify = notify_wrap_buffer;
}
/**
* \brief Full buffer notification callback.
*
* Makes a copy of the necessary vertices of the current buffer via
* copy_dma_verts(), gets and resets new buffer via radeon and re-emits the
* saved vertices.
*/
static void notify_wrap_buffer( void )
{
GLcontext *ctx = vb.context;
radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
GLfloat tmp[3][MAX_VERTEX_DWORDS];
GLuint i, nrverts = 0;
/* Copy vertices out of dma:
*/
nrverts = copy_dma_verts( rmesa, tmp );
finish_prim( rmesa );
/* Get new buffer
*/
radeonRefillCurrentDmaRegion( rmesa );
/* Reset vertspace[0], dmaptr
*/
reset_notify();
/* Reemit saved vertices
*/
for (i = 0 ; i < nrverts; i++) {
memcpy( vb.stack[0].dmaptr, tmp[i], vb.vertex_size * 4 );
vb.stack[0].dmaptr += vb.vertex_size;
vb.stack[0].vertspace--;
}
}
static void notify_noop( void )
{
vb.stack[0].dmaptr = (int *)vb.vertex;
vb.stack[0].notify = notify_noop;
vb.stack[0].vertspace = 1;
}
/**
* \brief Pop the notification mechanism stack.
*
* Simply copy the second stack array element into the first.
*
* \sa vb_t::stack and push_notify().
*/
static void pop_notify( void )
{
vb.stack[0] = vb.stack[1];
}
/**
* \brief Push the notification mechanism stack.
*
* \param notify new notify callback for the stack head.
* \param space space available for vertices in \p store.
* \param store buffer where to store the vertices.
*
* Copy the second stack array element into the first and makes the stack head
* use the given resources.
*
* \sa vb_t::stack and pop_notify().
*/
static void push_notify( void (*notify)( void ), int space,
union vertex_dword *store )
{
vb.stack[1] = vb.stack[0];
vb.stack[0].notify = notify;
vb.stack[0].initial_vertspace = space;
vb.stack[0].vertspace = space;
vb.stack[0].dmaptr = (int *)store;
}
/**
* \brief Emit a stored vertex (in vb_t::vertex_store) to DMA.
*
* \param v vertex index.
*
* Adds the vertex into the current vertex buffer and calls the notification
* callback vb_t::notify().
*/
static void emit_vertex( int v )
{
int i, *tmp = (int *)vb.vertex_store + v * vb.vertex_size;
for (i = 0 ; i < vb.vertex_size ; i++)
*vb.stack[0].dmaptr++ = *tmp++;
if (--vb.stack[0].vertspace == 0)
vb.stack[0].notify();
}
/**
* \brief Emit a quad (in vb_t::vertex_store) to DMA as two triangles.
*
* \param v0 first vertex index.
* \param v1 second vertex index.
* \param v2 third vertex index.
* \param v3 fourth vertex index.
*
* Calls emit_vertex() to emit the triangles' vertices.
*/
static void emit_quad( int v0, int v1, int v2, int v3 )
{
emit_vertex( v0 ); emit_vertex( v1 ); emit_vertex( v3 );
emit_vertex( v1 ); emit_vertex( v2 ); emit_vertex( v3 );
}
/**
* \brief Every fourth vertex in a quad primitive, this is called to emit it.
*
* Pops the notification stack, calls emit_quad() and pushes the notification
* stack again, with itself and the vb_t::vertex_store to process another four
* vertices.
*/
static void notify_quad( void )
{
pop_notify();
emit_quad( 0, 1, 2, 3 );
push_notify( notify_quad, 4, vb.vertex_store );
}
static void notify_qstrip1( void );
/**
* \brief After the 4th vertex, emit either a quad or a flipped quad each two
* vertices.
*
* Pops the notification stack, calls emit_quad() with the flipped vertices and
* pushes the notification stack again, with notify_qstrip1() and the
* vb_t::vertex_store to process another two vertices.
*
* \sa notify_qstrip1().
*/
static void notify_qstrip0( void )
{
pop_notify();
emit_quad( 0, 1, 3, 2 );
push_notify( notify_qstrip1, 2, vb.vertex_store );
}
/**
* \brief After the 4th vertex, emit either a quad or a flipped quad each two
* vertices.
*
* Pops the notification stack, calls emit_quad() with the straight vertices
* and pushes the notification stack again, with notify_qstrip0() and the
* vb_t::vertex_store to process another two vertices.
*
* \sa notify_qstrip0().
*/
static void notify_qstrip1( void )
{
pop_notify();
emit_quad( 2, 3, 1, 0 );
push_notify( notify_qstrip0, 2, vb.vertex_store + 2*vb.vertex_size );
}
/**
* \brief Emit the saved vertex (but hang on to it for later).
*
* Continue processing this primitive as a linestrip.
*
* Pops the notification stack and calls emit_quad with the first vertex.
*/
static void notify_lineloop0( void )
{
pop_notify();
emit_vertex(0);
}
/**
* \brief Invalidate the current vertex format.
*
* \param ctx GL context.
*
* Sets the vb_t::recheck flag.
*/
void radeonVtxfmtInvalidate( GLcontext *ctx )
{
vb.recheck = GL_TRUE;
}
/**
* \brief Validate the vertex format from the context.
*
* \param ctx GL context.
*
* Signals a new primitive and determines the appropriate vertex format and
* size. Points vb_t::floatcolorptr and vb_t::texcoordptr to the current vertex
* and sets them to the current color and texture attributes.
*
* Clears the vb_t::recheck flag on exit.
*/
static void radeonVtxfmtValidate( GLcontext *ctx )
{
radeonContextPtr rmesa = RADEON_CONTEXT( ctx );
GLuint ind = (RADEON_CP_VC_FRMT_Z |
RADEON_CP_VC_FRMT_FPCOLOR |
RADEON_CP_VC_FRMT_FPALPHA);
if (ctx->Driver.NeedFlush)
ctx->Driver.FlushVertices( ctx, ctx->Driver.NeedFlush );
if (ctx->Texture.Unit[0]._ReallyEnabled)
ind |= RADEON_CP_VC_FRMT_ST0;
RADEON_NEWPRIM(rmesa);
vb.vertex_format = ind;
vb.vertex_size = 3;
/* Would prefer to use ubyte floats in the vertex:
*/
vb.floatcolorptr = &vb.vertex[vb.vertex_size].f;
vb.vertex_size += 4;
vb.floatcolorptr[0] = ctx->Current.Attrib[VERT_ATTRIB_COLOR0][0];
vb.floatcolorptr[1] = ctx->Current.Attrib[VERT_ATTRIB_COLOR0][1];
vb.floatcolorptr[2] = ctx->Current.Attrib[VERT_ATTRIB_COLOR0][2];
vb.floatcolorptr[3] = ctx->Current.Attrib[VERT_ATTRIB_COLOR0][3];
if (ind & RADEON_CP_VC_FRMT_ST0) {
vb.texcoordptr = &vb.vertex[vb.vertex_size].f;
vb.vertex_size += 2;
vb.texcoordptr[0] = ctx->Current.Attrib[VERT_ATTRIB_TEX0][0];
vb.texcoordptr[1] = ctx->Current.Attrib[VERT_ATTRIB_TEX0][1];
}
else
vb.texcoordptr = ctx->Current.Attrib[VERT_ATTRIB_TEX0];
vb.recheck = GL_FALSE;
ctx->Driver.NeedFlush = FLUSH_UPDATE_CURRENT;
}
#define RESET_STIPPLE() do { \
RADEON_STATECHANGE( rmesa, lin ); \
radeonEmitState( rmesa ); \
} while (0)
#define AUTO_STIPPLE( mode ) do { \
RADEON_STATECHANGE( rmesa, lin ); \
if (mode) \
rmesa->hw.lin.cmd[LIN_RE_LINE_PATTERN] |= \
RADEON_LINE_PATTERN_AUTO_RESET; \
else \
rmesa->hw.lin.cmd[LIN_RE_LINE_PATTERN] &= \
~RADEON_LINE_PATTERN_AUTO_RESET; \
radeonEmitState( rmesa ); \
} while (0)
/**
* \brief Process glBegin().
*
* \param mode primitive.
*/
static void radeon_Begin( GLenum mode )
{
GLcontext *ctx = vb.context;
radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
GLuint se_cntl;
if (mode > GL_POLYGON) {
_mesa_error( ctx, GL_INVALID_ENUM, "glBegin" );
return;
}
if (ctx->Driver.CurrentExecPrimitive != GL_POLYGON+1) {
_mesa_error( ctx, GL_INVALID_OPERATION, "glBegin" );
return;
}
if (ctx->NewState)
_mesa_update_state( ctx );
if (rmesa->NewGLState)
radeonValidateState( ctx );
if (vb.recheck)
radeonVtxfmtValidate( ctx );
/* Do we need to grab a new DMA region for the vertices?
*/
if (rmesa->dma.current.ptr + 12*vb.vertex_size*4 > rmesa->dma.current.end) {
RADEON_NEWPRIM( rmesa );
radeonRefillCurrentDmaRegion( rmesa );
}
reset_notify();
vb.prim = ctx->Driver.CurrentExecPrimitive = mode;
se_cntl = rmesa->hw.set.cmd[SET_SE_CNTL] | RADEON_FLAT_SHADE_VTX_LAST;
if (ctx->Line.StippleFlag &&
(mode == GL_LINES ||
mode == GL_LINE_LOOP ||
mode == GL_LINE_STRIP))
RESET_STIPPLE();
switch( mode ) {
case GL_LINES:
if (ctx->Line.StippleFlag)
AUTO_STIPPLE( GL_TRUE );
break;
case GL_LINE_LOOP:
vb.prim = GL_LINE_STRIP;
push_notify( notify_lineloop0, 1, vb.vertex_store );
break;
case GL_QUADS:
vb.prim = GL_TRIANGLES;
push_notify( notify_quad, 4, vb.vertex_store );
break;
case GL_QUAD_STRIP:
if (ctx->_TriangleCaps & DD_FLATSHADE) {
vb.prim = GL_TRIANGLES;
push_notify( notify_qstrip0, 4, vb.vertex_store );
}
break;
case GL_POLYGON:
if (ctx->_TriangleCaps & DD_FLATSHADE)
se_cntl &= ~RADEON_FLAT_SHADE_VTX_LAST;
break;
default:
break;
}
if (se_cntl != rmesa->hw.set.cmd[SET_SE_CNTL]) {
RADEON_STATECHANGE( rmesa, set );
rmesa->hw.set.cmd[SET_SE_CNTL] = se_cntl;
}
}
/**
* \brief Process glEnd().
*
*/
static void radeon_End( void )
{
GLcontext *ctx = vb.context;
radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
if (ctx->Driver.CurrentExecPrimitive == GL_POLYGON+1) {
_mesa_error( ctx, GL_INVALID_OPERATION, "glEnd" );
return;
}
/* Need to finish a line loop?
*/
if (ctx->Driver.CurrentExecPrimitive == GL_LINE_LOOP)
emit_vertex( 0 );
/* Need to pop off quads/quadstrip/etc notification?
*/
if (vb.stack[0].notify != notify_wrap_buffer)
pop_notify();
finish_prim( rmesa );
if (ctx->Driver.CurrentExecPrimitive == GL_LINES && ctx->Line.StippleFlag)
AUTO_STIPPLE( GL_FALSE );
ctx->Driver.CurrentExecPrimitive = GL_POLYGON+1;
notify_noop();
}
/**
* \brief Flush vertices.
*
* \param ctx GL context.
* \param flags flags.
*
* If FLUSH_UPDATE_CURRENT is et in \p flags then the current vertex attributes
* in the GL context is updated from vb_t::floatcolorptr and vb_t::texcoordptr.
*/
static void radeonFlushVertices( GLcontext *ctx, GLuint flags )
{
if (flags & FLUSH_UPDATE_CURRENT) {
ctx->Current.Attrib[VERT_ATTRIB_COLOR0][0] = vb.floatcolorptr[0];
ctx->Current.Attrib[VERT_ATTRIB_COLOR0][1] = vb.floatcolorptr[1];
ctx->Current.Attrib[VERT_ATTRIB_COLOR0][2] = vb.floatcolorptr[2];
ctx->Current.Attrib[VERT_ATTRIB_COLOR0][3] = vb.floatcolorptr[3];
if (vb.vertex_format & RADEON_CP_VC_FRMT_ST0) {
ctx->Current.Attrib[VERT_ATTRIB_TEX0][0] = vb.texcoordptr[0];
ctx->Current.Attrib[VERT_ATTRIB_TEX0][1] = vb.texcoordptr[1];
ctx->Current.Attrib[VERT_ATTRIB_TEX0][2] = 0.0F;
ctx->Current.Attrib[VERT_ATTRIB_TEX0][3] = 1.0F;
}
}
ctx->Driver.NeedFlush &= ~FLUSH_STORED_VERTICES;
}
/**
* \brief Set current vertex coordinates.
*
* \param x x vertex coordinate.
* \param y y vertex coordinate.
* \param z z vertex coordinate.
*
* Set the current vertex coordinates. If run out of space in this buffer call
* the notification callback.
*/
static __inline__ void radeon_Vertex3f( GLfloat x, GLfloat y, GLfloat z )
{
int i;
*vb.stack[0].dmaptr++ = *(int *)&x;
*vb.stack[0].dmaptr++ = *(int *)&y;
*vb.stack[0].dmaptr++ = *(int *)&z;
for (i = 3; i < vb.vertex_size; i++)
*vb.stack[0].dmaptr++ = vb.vertex[i].i;
if (--vb.stack[0].vertspace == 0)
vb.stack[0].notify();
}
/**
* \brief Set current vertex color.
*
* \param r red color component.
* \param g gree color component.
* \param b blue color component.
* \param a alpha color component.
*
* Sets the current vertex color via vb_t::floatcolorptr.
*/
static __inline__ void radeon_Color4f( GLfloat r, GLfloat g,
GLfloat b, GLfloat a )
{
GLfloat *dest = vb.floatcolorptr;
dest[0] = r;
dest[1] = g;
dest[2] = b;
dest[3] = a;
}
/**
* \brief Set current vertex texture coordinates.
*
* \param s texture coordinate.
* \param t texture coordinate.
*
* Sets the current vertex color via vb_t::texcoordptr.
*/
static __inline__ void radeon_TexCoord2f( GLfloat s, GLfloat t )
{
GLfloat *dest = vb.texcoordptr;
dest[0] = s;
dest[1] = t;
}
/**
* Calls radeon_Vertex3f(), which is expanded inline by the compiler to be
* efficient.
*/
static void radeon_Vertex3fv( const GLfloat *v )
{
radeon_Vertex3f( v[0], v[1], v[2] );
}
/**
* Calls radeon_Vertex3f(), which is expanded inline by the compiler to be
* efficient.
*/
static void radeon_Vertex2f( GLfloat x, GLfloat y )
{
radeon_Vertex3f( x, y, 0 );
}
/**
* Calls radeon_Vertex3f(), which is expanded inline by the compiler to be
* efficient.
*/
static void radeon_Vertex2fv( const GLfloat *v )
{
radeon_Vertex3f( v[0], v[1], 0 );
}
/**
* Calls radeon_Vertex3f(), which is expanded inline by the compiler to be
* efficient.
*/
static void radeon_Color4fv( const GLfloat *v )
{
radeon_Color4f( v[0], v[1], v[2], v[3] );
}
/**
* Calls radeon_Color4f(), which is expanded inline by the compiler to be
* efficient.
*/
static void radeon_Color3f( GLfloat r, GLfloat g, GLfloat b )
{
radeon_Color4f( r, g, b, 1.0 );
}
/**
* Calls radeon_Color4f(), which is expanded inline by the compiler to be
* efficient.
*/
static void radeon_Color3fv( const GLfloat *v )
{
radeon_Color4f( v[0], v[1], v[2], 1.0 );
}
/**
* Calls radeon_TexCoord2f(), which is expanded inline by the compiler to be
* efficient.
*/
static void radeon_TexCoord2fv( const GLfloat *v )
{
radeon_TexCoord2f( v[0], v[1] );
}
/**
* No-op.
*/
void radeonVtxfmtUnbindContext( GLcontext *ctx )
{
}
/**
* No-op.
*/
void radeonVtxfmtMakeCurrent( GLcontext *ctx )
{
}
/**
* No-op.
*/
void radeonVtxfmtDestroy( GLcontext *ctx )
{
}
/**
* \brief Software rendering fallback.
*
* \param ctx GL context.
* \param bit fallback bitmask.
* \param mode enable or disable.
*
* Does nothing except display a warning message if \p mode is set.
*/
void radeonFallback( GLcontext *ctx, GLuint bit, GLboolean mode )
{
if (mode)
fprintf(stderr, "Warning: hit nonexistant fallback path!\n");
}
/**
* \brief Software TCL fallback.
*
* \param ctx GL context.
* \param bit fallback bitmask.
* \param mode enable or disable.
*
* Does nothing except display a warning message if \p mode is set.
*/
void radeonTclFallback( GLcontext *ctx, GLuint bit, GLboolean mode )
{
if (mode)
fprintf(stderr, "Warning: hit nonexistant fallback path!\n");
}
/**
* \brief Called by radeonPointsBitmap() to disable TCL.
*
* \param rmesa Radeon context.
* \param flag whether to enable or disable TCL.
*
* Updates radeon_tcl_info::tcl_flag.
*/
void radeonSubsetVtxEnableTCL( radeonContextPtr rmesa, GLboolean flag )
{
rmesa->tcl.tcl_flag = flag ? RADEON_CP_VC_CNTL_TCL_ENABLE : 0;
}
/**********************************************************************/
/** \name Noop mode for operation without focus */
/**********************************************************************/
/*@{*/
/**
* \brief Process glBegin().
*
* \param mode primitive.
*/
static void radeon_noop_Begin(GLenum mode)
{
GET_CURRENT_CONTEXT(ctx);
if (mode > GL_POLYGON) {
_mesa_error( ctx, GL_INVALID_ENUM, "glBegin" );
return;
}
if (ctx->Driver.CurrentExecPrimitive != GL_POLYGON+1) {
_mesa_error( ctx, GL_INVALID_OPERATION, "glBegin" );
return;
}
ctx->Driver.CurrentExecPrimitive = mode;
}
/**
* \brief Process glEnd().
*/
static void radeon_noop_End(void)
{
GET_CURRENT_CONTEXT(ctx);
ctx->Driver.CurrentExecPrimitive = GL_POLYGON+1;
}
/**
* \brief Install the noop callbacks.
*
* \param ctx GL context.
*
* Installs the noop callbacks into the glapi table. These functions
* will not attempt to emit any DMA vertices, but will keep internal
* GL state updated. Borrows heavily from the select code.
*/
static void radeon_noop_Install( GLcontext *ctx )
{
ctx->Exec->Begin = radeon_noop_Begin;
ctx->Exec->End = radeon_noop_End;
vb.texcoordptr = ctx->Current.Attrib[VERT_ATTRIB_TEX0];
vb.floatcolorptr = ctx->Current.Attrib[VERT_ATTRIB_COLOR0];
notify_noop();
}
/**
* \brief Setup the GL context callbacks.
*
* \param ctx GL context.
*
* Setups the GL context callbacks and links _glapi_table entries related to
* the glBegin()/glEnd() pairs to the functions in this module.
*
* Called by radeonCreateContext() and radeonRenderMode().
*/
void radeonVtxfmtInit( GLcontext *ctx )
{
radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
struct _glapi_table *exec = ctx->Exec;
exec->Color3f = radeon_Color3f;
exec->Color3fv = radeon_Color3fv;
exec->Color4f = radeon_Color4f;
exec->Color4fv = radeon_Color4fv;
exec->TexCoord2f = radeon_TexCoord2f;
exec->TexCoord2fv = radeon_TexCoord2fv;
exec->Vertex2f = radeon_Vertex2f;
exec->Vertex2fv = radeon_Vertex2fv;
exec->Vertex3f = radeon_Vertex3f;
exec->Vertex3fv = radeon_Vertex3fv;
exec->Begin = radeon_Begin;
exec->End = radeon_End;
vb.context = ctx;
ctx->Driver.FlushVertices = radeonFlushVertices;
ctx->Driver.CurrentExecPrimitive = GL_POLYGON+1;
if (rmesa->radeonScreen->buffers) {
radeonVtxfmtValidate( ctx );
notify_noop();
}
else
radeon_noop_Install( ctx );
}
/*@}*/