New driver for i915 as well as older i830/i845/i865 chipsets.

This commit is contained in:
Keith Whitwell
2004-06-10 12:48:07 +00:00
parent d7f76c7c88
commit 41b58954e1
43 changed files with 17911 additions and 0 deletions
+58
View File
@@ -0,0 +1,58 @@
TOP = ../../../../..
include $(TOP)/configs/current
LIBNAME = i915_dri.so
COMMON_SOURCES = \
../../common/driverfuncs.c \
../common/mm.c \
../common/utils.c \
../common/texmem.c \
../common/vblank.c \
../common/xmlconfig.c \
../common/dri_util.c \
../common/glcontextmodes.c
DRIVER_SOURCES = \
i915_context.c \
i915_debug.c \
i915_fragprog.c \
i915_metaops.c \
i915_program.c \
i915_state.c \
i915_tex.c \
i915_texprog.c \
i915_texstate.c \
i915_vtbl.c \
i830_context.c \
i830_metaops.c \
i830_state.c \
i830_texblend.c \
i830_tex.c \
i830_texstate.c \
i830_vtbl.c \
intel_batchbuffer.c \
intel_context.c \
intel_ioctl.c \
intel_pixel.c \
intel_render.c \
intel_screen.c \
intel_span.c \
intel_state.c \
intel_tex.c \
intel_tris.c
C_SOURCES = \
$(COMMON_SOURCES) \
$(MINIGLX_SOURCES) \
$(DRIVER_SOURCES)
ASM_SOURCES =
include ../Makefile.template
symlinks:
+143
View File
@@ -0,0 +1,143 @@
/**************************************************************************
*
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
**************************************************************************/
#include "i830_context.h"
#include "imports.h"
#include "texmem.h"
#include "intel_tex.h"
#include "tnl/tnl.h"
#include "tnl/t_vertex.h"
#include "tnl/t_context.h"
/***************************************
* Mesa's Driver Functions
***************************************/
/* This is the extension list explicitly enabled by the client and
* excludes functionality available in Mesa and also excludes legacy
* extensions. It is recognized that in an open source driver, those
* extensions will probably be re-enabled.
*/
static const GLubyte *i830GetString( GLcontext *ctx, GLenum name )
{
if (name == GL_EXTENSIONS)
return
"GL_ARB_multitexture "
"GL_ARB_texture_border_clamp "
"GL_ARB_texture_compression "
"GL_ARB_texture_env_add "
"GL_ARB_texture_env_combine "
"GL_ARB_texture_env_dot3 "
"GL_ARB_texture_mirrored_repeat "
"GL_ARB_transpose_matrix "
"GL_ARB_vertex_buffer_object "
"GL_ARB_vertex_program "
"GL_ARB_window_pos "
"GL_EXT_abgr "
"GL_EXT_bgra "
"GL_EXT_blend_color "
"GL_EXT_blend_func_separate "
"GL_EXT_blend_minmax "
"GL_EXT_blend_subtract "
"GL_EXT_clip_volume_hint "
"GL_EXT_compiled_vertex_array "
"GL_EXT_draw_range_elements "
"GL_EXT_fog_coord "
"GL_EXT_multi_draw_arrays "
"GL_EXT_packed_pixels "
"GL_EXT_rescale_normal "
"GL_EXT_secondary_color "
"GL_EXT_separate_specular_color "
"GL_EXT_stencil_wrap "
"GL_EXT_texture_env_add "
"GL_EXT_texture_env_combine "
"GL_EXT_texture_filter_anisotropic "
"GL_IBM_texture_mirrored_repeat "
"GL_MESA_ycbcr_texture "
"GL_MESA_window_pos "
"GL_NV_texgen_reflection "
"GL_SGIS_generate_mipmap ";
return intelGetString( ctx, name );
}
static void i830InitDriverFunctions( struct dd_function_table *functions )
{
intelInitDriverFunctions( functions );
i830InitStateFuncs( functions );
i830InitTextureFuncs( functions );
functions->GetString = i830GetString;
}
GLboolean i830CreateContext( const __GLcontextModes *mesaVis,
__DRIcontextPrivate *driContextPriv,
void *sharedContextPrivate)
{
struct dd_function_table functions;
i830ContextPtr i830 = (i830ContextPtr) CALLOC_STRUCT(i830_context);
intelContextPtr intel = &i830->intel;
GLcontext *ctx = &intel->ctx;
if (!i830) return GL_FALSE;
i830InitVtbl( i830 );
i830InitDriverFunctions( &functions );
if (!intelInitContext( intel, mesaVis, driContextPriv,
sharedContextPrivate, &functions )) {
FREE(i830);
return GL_FALSE;
}
intel->ctx.Const.MaxTextureUnits = I830_TEX_UNITS;
intel->ctx.Const.MaxTextureImageUnits = I830_TEX_UNITS;
intel->ctx.Const.MaxTextureCoordUnits = I830_TEX_UNITS;
intel->nr_heaps = 1;
intel->texture_heaps[0] =
driCreateTextureHeap( 0, intel,
intel->intelScreen->textureSize,
12,
I830_NR_TEX_REGIONS,
intel->sarea->texList,
& intel->sarea->texAge,
& intel->swapped,
sizeof( struct i830_texture_object ),
(destroy_texture_object_t *)intelDestroyTexObj );
/* FIXME: driCalculateMaxTextureLevels assumes that mipmaps are tightly
* FIXME: packed, but they're not in Intel graphics hardware.
*/
intel->ctx.Const.MaxTextureUnits = 1;
driCalculateMaxTextureLevels( intel->texture_heaps,
intel->nr_heaps,
&intel->ctx.Const,
4,
11, /* max 2D texture size is 2048x2048 */
8, /* max 3D texture size is 256^3 */
0, /* max CUBE. not supported */
0, /* max RECT. supported, but not enabled */
12,
GL_FALSE );
intel->ctx.Const.MaxTextureUnits = I830_TEX_UNITS;
_tnl_init_vertices( ctx, ctx->Const.MaxArrayLockSize + 12,
18 * sizeof(GLfloat) );
intel->verts = TNL_CONTEXT(ctx)->clipspace.vertex_buf;
i830InitState( i830 );
_tnl_allow_vertex_fog( ctx, 1 );
_tnl_allow_pixel_fog( ctx, 0 );
return GL_TRUE;
}
+197
View File
@@ -0,0 +1,197 @@
/**************************************************************************
*
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
**************************************************************************/
#ifndef I830CONTEXT_INC
#define I830CONTEXT_INC
#include "intel_context.h"
#define I830_FALLBACK_TEXTURE 0x1000
#define I830_FALLBACK_COLORMASK 0x2000
#define I830_FALLBACK_STENCIL 0x4000
#define I830_FALLBACK_STIPPLE 0x8000
#define I830_FALLBACK_LOGICOP 0x10000
#define I830_UPLOAD_CTX 0x1
#define I830_UPLOAD_BUFFERS 0x2
#define I830_UPLOAD_STIPPLE 0x4
#define I830_UPLOAD_TEX(i) (0x10<<(i))
#define I830_UPLOAD_TEXBLEND(i) (0x100<<(i))
#define I830_UPLOAD_TEX_ALL (0x0f0)
#define I830_UPLOAD_TEXBLEND_ALL (0xf00)
/* State structure offsets - these will probably disappear.
*/
#define I830_DESTREG_CBUFADDR0 0
#define I830_DESTREG_CBUFADDR1 1
#define I830_DESTREG_CBUFADDR2 2
#define I830_DESTREG_DBUFADDR0 3
#define I830_DESTREG_DBUFADDR1 4
#define I830_DESTREG_DBUFADDR2 5
#define I830_DESTREG_DV0 6
#define I830_DESTREG_DV1 7
#define I830_DESTREG_SENABLE 8
#define I830_DESTREG_SR0 9
#define I830_DESTREG_SR1 10
#define I830_DESTREG_SR2 11
#define I830_DEST_SETUP_SIZE 12
#define I830_CTXREG_STATE1 0
#define I830_CTXREG_STATE2 1
#define I830_CTXREG_STATE3 2
#define I830_CTXREG_STATE4 3
#define I830_CTXREG_STATE5 4
#define I830_CTXREG_IALPHAB 5
#define I830_CTXREG_STENCILTST 6
#define I830_CTXREG_ENABLES_1 7
#define I830_CTXREG_ENABLES_2 8
#define I830_CTXREG_AA 9
#define I830_CTXREG_FOGCOLOR 10
#define I830_CTXREG_BLENDCOLOR0 11
#define I830_CTXREG_BLENDCOLOR1 12
#define I830_CTXREG_VF 13
#define I830_CTXREG_VF2 14
#define I830_CTXREG_MCSB0 15
#define I830_CTXREG_MCSB1 16
#define I830_CTX_SETUP_SIZE 17
#define I830_STPREG_ST0 0
#define I830_STPREG_ST1 1
#define I830_STP_SETUP_SIZE 2
#define I830_TEXREG_TM0LI 0 /* load immediate 2 texture map n */
#define I830_TEXREG_TM0S0 1
#define I830_TEXREG_TM0S1 2
#define I830_TEXREG_TM0S2 3
#define I830_TEXREG_TM0S3 4
#define I830_TEXREG_TM0S4 5
#define I830_TEXREG_MCS 6 /* _3DSTATE_MAP_COORD_SETS */
#define I830_TEX_SETUP_SIZE 7
#define I830_TEXBLEND_SIZE 12 /* (4 args + op) * 2 + COLOR_FACTOR */
struct i830_texture_object
{
struct intel_texture_object intel;
GLuint Setup[I830_TEX_SETUP_SIZE];
};
#define I830_TEX_UNITS 4
struct i830_hw_state {
GLuint Ctx[I830_CTX_SETUP_SIZE];
GLuint Buffer[I830_DEST_SETUP_SIZE];
GLuint Stipple[I830_STP_SETUP_SIZE];
GLuint Tex[I830_TEX_UNITS][I830_TEX_SETUP_SIZE];
GLuint TexBlend[I830_TEX_UNITS][I830_TEXBLEND_SIZE];
GLuint TexBlendWordsUsed[I830_TEX_UNITS];
GLuint emitted; /* I810_UPLOAD_* */
GLuint active;
};
struct i830_context
{
struct intel_context intel;
GLuint last_index;
struct i830_hw_state meta, initial, state, *current;
};
typedef struct i830_context *i830ContextPtr;
typedef struct i830_texture_object *i830TextureObjectPtr;
#define I830_CONTEXT(ctx) ((i830ContextPtr)(ctx))
#define I830_STATECHANGE(i830, flag) \
do { \
INTEL_FIREVERTICES( &i830->intel ); \
i830->state.emitted &= ~flag; \
} while (0)
#define I830_ACTIVESTATE(i830, flag, mode) \
do { \
INTEL_FIREVERTICES( &i830->intel ); \
if (mode) \
i830->state.active |= flag; \
else \
i830->state.active &= ~flag; \
} while (0)
/* i830_vtbl.c
*/
extern void
i830InitVtbl( i830ContextPtr i830 );
/* i830_context.c
*/
extern GLboolean
i830CreateContext( const __GLcontextModes *mesaVis,
__DRIcontextPrivate *driContextPriv,
void *sharedContextPrivate);
/* i830_tex.c, i830_texstate.c
*/
extern void
i830UpdateTextureState( intelContextPtr intel );
extern void
i830InitTextureFuncs( struct dd_function_table *functions );
extern intelTextureObjectPtr
i830AllocTexObj( struct gl_texture_object *tObj );
/* i830_texblend.c
*/
extern GLuint
i830SetBlend_GL1_2(i830ContextPtr i830, int unit,
GLenum envMode, GLenum format,
GLuint texel_op,
GLuint *state,
const GLfloat *envcolor );
extern void
i830EmitTextureBlend( i830ContextPtr i830 );
/* i830_state.c
*/
extern void
i830InitStateFuncs( struct dd_function_table *functions );
extern void
i830EmitState( i830ContextPtr i830 );
extern void
i830InitState( i830ContextPtr i830 );
/* i830_metaops.c
*/
extern GLboolean
i830TryTextureReadPixels( GLcontext *ctx,
GLint x, GLint y, GLsizei width, GLsizei height,
GLenum format, GLenum type,
const struct gl_pixelstore_attrib *pack,
GLvoid *pixels );
extern GLboolean
i830TryTextureDrawPixels( GLcontext *ctx,
GLint x, GLint y, GLsizei width, GLsizei height,
GLenum format, GLenum type,
const struct gl_pixelstore_attrib *unpack,
const GLvoid *pixels );
extern void
i830ClearWithTris( intelContextPtr intel, GLbitfield mask,
GLboolean all, GLint cx, GLint cy, GLint cw, GLint ch);
#endif
+699
View File
@@ -0,0 +1,699 @@
/**************************************************************************
*
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
**************************************************************************/
#include "glheader.h"
#include "enums.h"
#include "mtypes.h"
#include "macros.h"
#include "utils.h"
#include "intel_screen.h"
#include "intel_batchbuffer.h"
#include "intel_ioctl.h"
#include "i830_context.h"
#include "i830_reg.h"
/* A large amount of state doesn't need to be uploaded.
*/
#define ACTIVE (I830_UPLOAD_TEXBLEND(0) | \
I830_UPLOAD_STIPPLE | \
I830_UPLOAD_CTX | \
I830_UPLOAD_BUFFERS | \
I830_UPLOAD_TEX(0))
#define SET_STATE( i830, STATE ) \
do { \
i830->current->emitted &= ~ACTIVE; \
i830->current = &i830->STATE; \
i830->current->emitted &= ~ACTIVE; \
} while (0)
/* Operations where the 3D engine is decoupled temporarily from the
* current GL state and used for other purposes than simply rendering
* incoming triangles.
*/
static void set_initial_state( i830ContextPtr i830 )
{
memcpy(&i830->meta, &i830->initial, sizeof(i830->meta) );
i830->meta.active = ACTIVE;
i830->meta.emitted = 0;
}
static void set_no_depth_stencil_write( i830ContextPtr i830 )
{
/* ctx->Driver.Enable( ctx, GL_STENCIL_TEST, GL_FALSE )
*/
i830->meta.Ctx[I830_CTXREG_ENABLES_1] &= ~ENABLE_STENCIL_TEST;
i830->meta.Ctx[I830_CTXREG_ENABLES_2] &= ~ENABLE_STENCIL_WRITE;
i830->meta.Ctx[I830_CTXREG_ENABLES_1] |= DISABLE_STENCIL_TEST;
i830->meta.Ctx[I830_CTXREG_ENABLES_2] |= DISABLE_STENCIL_WRITE;
/* ctx->Driver.Enable( ctx, GL_DEPTH_TEST, GL_FALSE )
*/
i830->meta.Ctx[I830_CTXREG_ENABLES_1] &= ~ENABLE_DIS_DEPTH_TEST_MASK;
i830->meta.Ctx[I830_CTXREG_ENABLES_2] &= ~ENABLE_DIS_DEPTH_WRITE_MASK;
i830->meta.Ctx[I830_CTXREG_ENABLES_1] |= DISABLE_DEPTH_TEST;
i830->meta.Ctx[I830_CTXREG_ENABLES_2] |= DISABLE_DEPTH_WRITE;
i830->meta.emitted &= ~I830_UPLOAD_CTX;
}
/* Set stencil unit to replace always with the reference value.
*/
static void set_stencil_replace( i830ContextPtr i830,
GLuint s_mask,
GLuint s_clear)
{
/* ctx->Driver.Enable( ctx, GL_STENCIL_TEST, GL_TRUE )
*/
i830->meta.Ctx[I830_CTXREG_ENABLES_1] |= ENABLE_STENCIL_TEST;
i830->meta.Ctx[I830_CTXREG_ENABLES_2] |= ENABLE_STENCIL_WRITE;
/* ctx->Driver.Enable( ctx, GL_DEPTH_TEST, GL_FALSE )
*/
i830->meta.Ctx[I830_CTXREG_ENABLES_1] &= ~ENABLE_DIS_DEPTH_TEST_MASK;
i830->meta.Ctx[I830_CTXREG_ENABLES_2] &= ~ENABLE_DIS_DEPTH_WRITE_MASK;
i830->meta.Ctx[I830_CTXREG_ENABLES_1] |= DISABLE_DEPTH_TEST;
i830->meta.Ctx[I830_CTXREG_ENABLES_2] |= DISABLE_DEPTH_WRITE;
/* ctx->Driver.StencilMask( ctx, s_mask )
*/
i830->meta.Ctx[I830_CTXREG_STATE4] &= ~MODE4_ENABLE_STENCIL_WRITE_MASK;
i830->meta.Ctx[I830_CTXREG_STATE4] |= (ENABLE_STENCIL_WRITE_MASK |
STENCIL_WRITE_MASK((s_mask&0xff)));
/* ctx->Driver.StencilOp( ctx, GL_REPLACE, GL_REPLACE, GL_REPLACE )
*/
i830->meta.Ctx[I830_CTXREG_STENCILTST] &= ~(STENCIL_OPS_MASK);
i830->meta.Ctx[I830_CTXREG_STENCILTST] |=
(ENABLE_STENCIL_PARMS |
STENCIL_FAIL_OP(STENCILOP_REPLACE) |
STENCIL_PASS_DEPTH_FAIL_OP(STENCILOP_REPLACE) |
STENCIL_PASS_DEPTH_PASS_OP(STENCILOP_REPLACE));
/* ctx->Driver.StencilFunc( ctx, GL_ALWAYS, s_clear, ~0 )
*/
i830->meta.Ctx[I830_CTXREG_STATE4] &= ~MODE4_ENABLE_STENCIL_TEST_MASK;
i830->meta.Ctx[I830_CTXREG_STATE4] |= (ENABLE_STENCIL_TEST_MASK |
STENCIL_TEST_MASK(0xff));
i830->meta.Ctx[I830_CTXREG_STENCILTST] &= ~(STENCIL_REF_VALUE_MASK |
ENABLE_STENCIL_TEST_FUNC_MASK);
i830->meta.Ctx[I830_CTXREG_STENCILTST] |=
(ENABLE_STENCIL_REF_VALUE |
ENABLE_STENCIL_TEST_FUNC |
STENCIL_REF_VALUE((s_clear&0xff)) |
STENCIL_TEST_FUNC(COMPAREFUNC_ALWAYS));
i830->meta.emitted &= ~I830_UPLOAD_CTX;
}
static void set_color_mask( i830ContextPtr i830, GLboolean state )
{
const GLuint mask = ((1 << WRITEMASK_RED_SHIFT) |
(1 << WRITEMASK_GREEN_SHIFT) |
(1 << WRITEMASK_BLUE_SHIFT) |
(1 << WRITEMASK_ALPHA_SHIFT));
if (state) {
i830->meta.Ctx[I830_CTXREG_ENABLES_2] &= ~mask;
i830->meta.Ctx[I830_CTXREG_ENABLES_2] |=
(i830->state.Ctx[I830_CTXREG_ENABLES_2] & mask);
}
else
i830->meta.Ctx[I830_CTXREG_ENABLES_2] |= mask;
i830->meta.emitted &= ~I830_UPLOAD_CTX;
}
/* Installs a one-stage passthrough texture blend pipeline. Is there
* more that can be done to turn off texturing?
*/
static void set_no_texture( i830ContextPtr i830 )
{
i830->meta.TexBlendWordsUsed[0] =
i830SetBlend_GL1_2( i830, 0, GL_NONE, 0,
TEXBLENDARG_TEXEL0,
i830->meta.TexBlend[0], 0 );
i830->meta.TexBlend[0][0] |= TEXOP_LAST_STAGE;
i830->meta.emitted &= ~I830_UPLOAD_TEXBLEND(0);
}
/* Set up a single element blend stage for 'replace' texturing with no
* funny ops.
*/
static void enable_texture_blend_replace( i830ContextPtr i830,
GLenum format )
{
i830->meta.TexBlendWordsUsed[0] =
i830SetBlend_GL1_2( i830, 0, GL_REPLACE, format,
TEXBLENDARG_TEXEL0,
i830->meta.TexBlend[0], 0 );
i830->meta.TexBlend[0][0] |= TEXOP_LAST_STAGE;
i830->meta.emitted &= ~I830_UPLOAD_TEXBLEND(0);
/* fprintf(stderr, "%s: TexBlendWordsUsed[0]: %d\n", */
/* __FUNCTION__, i830->meta.TexBlendWordsUsed[0]); */
}
/* Set up an arbitary piece of memory as a rectangular texture
* (including the front or back buffer).
*/
static void set_tex_rect_source( i830ContextPtr i830,
GLuint offset,
GLuint width,
GLuint height,
GLuint pitch,
GLuint textureFormat )
{
GLint numLevels = 1;
GLuint *setup = i830->meta.Tex[0];
pitch *= i830->intel.intelScreen->cpp;
/* fprintf(stderr, "%s: offset: %x w: %d h: %d pitch %d format %x\n", */
/* __FUNCTION__, offset, width, height, pitch, textureFormat ); */
setup[I830_TEXREG_TM0LI] = (_3DSTATE_LOAD_STATE_IMMEDIATE_2 |
(LOAD_TEXTURE_MAP0 << 0) | 4);
setup[I830_TEXREG_TM0S0] = (TM0S0_USE_FENCE | offset);
setup[I830_TEXREG_TM0S1] = (((height - 1) << TM0S1_HEIGHT_SHIFT) |
((width - 1) << TM0S1_WIDTH_SHIFT) |
textureFormat);
setup[I830_TEXREG_TM0S2] = ((((pitch / 4) - 1) << TM0S2_PITCH_SHIFT));
setup[I830_TEXREG_TM0S3] &= ~TM0S3_MAX_MIP_MASK;
setup[I830_TEXREG_TM0S3] &= ~TM0S3_MIN_MIP_MASK;
setup[I830_TEXREG_TM0S3] |= ((numLevels - 1)*4) << TM0S3_MIN_MIP_SHIFT;
setup[I830_TEXREG_MCS] = (_3DSTATE_MAP_COORD_SET_CMD |
MAP_UNIT(0) |
ENABLE_TEXCOORD_PARAMS |
TEXCOORDS_ARE_IN_TEXELUNITS |
TEXCOORDTYPE_CARTESIAN |
ENABLE_ADDR_V_CNTL |
TEXCOORD_ADDR_V_MODE(TEXCOORDMODE_WRAP) |
ENABLE_ADDR_U_CNTL |
TEXCOORD_ADDR_U_MODE(TEXCOORDMODE_WRAP));
i830->meta.emitted &= ~I830_UPLOAD_TEX(0);
}
/* Select between front and back draw buffers.
*/
static void set_draw_offset( i830ContextPtr i830,
GLuint offset )
{
i830->meta.Buffer[I830_DESTREG_CBUFADDR2] = offset;
i830->meta.emitted &= ~I830_UPLOAD_BUFFERS;
}
/* Setup an arbitary draw format, useful for targeting
* texture or agp memory.
*/
static void set_draw_format( i830ContextPtr i830,
GLuint format,
GLuint depth_format)
{
i830->meta.Buffer[I830_DESTREG_DV1] = (DSTORG_HORT_BIAS(0x8) | /* .5 */
DSTORG_VERT_BIAS(0x8) | /* .5 */
format |
DEPTH_IS_Z |
depth_format);
}
static void set_vertex_format( i830ContextPtr i830 )
{
i830->meta.Ctx[I830_CTXREG_VF] = (_3DSTATE_VFT0_CMD |
VFT0_TEX_COUNT(1) |
VFT0_DIFFUSE |
VFT0_SPEC |
VFT0_XYZW);
i830->meta.Ctx[I830_CTXREG_VF2] = (_3DSTATE_VFT1_CMD |
VFT1_TEX0_FMT(TEXCOORDFMT_2D) |
VFT1_TEX1_FMT(TEXCOORDFMT_2D) |
VFT1_TEX2_FMT(TEXCOORDFMT_2D) |
VFT1_TEX3_FMT(TEXCOORDFMT_2D));
i830->meta.emitted &= ~I830_UPLOAD_CTX;
}
static void draw_quad(i830ContextPtr i830,
GLfloat x0, GLfloat x1,
GLfloat y0, GLfloat y1,
GLubyte red, GLubyte green,
GLubyte blue, GLubyte alpha,
GLfloat s0, GLfloat s1,
GLfloat t0, GLfloat t1 )
{
GLuint vertex_size = 8;
GLuint *vb = intelEmitInlinePrimitiveLocked( &i830->intel,
PRIM3D_TRIFAN,
4*vertex_size,
vertex_size );
intelVertex tmp;
int i;
/* fprintf(stderr, "%s: %f,%f-%f,%f 0x%x%x%x%x %f,%f-%f,%f\n", */
/* __FUNCTION__, */
/* x0,y0,x1,y1,red,green,blue,alpha,s0,t0,s1,t1); */
/* initial vertex, left bottom */
tmp.v.x = x0;
tmp.v.y = y0;
tmp.v.z = 1.0;
tmp.v.w = 1.0;
tmp.v.color.red = red;
tmp.v.color.green = green;
tmp.v.color.blue = blue;
tmp.v.color.alpha = alpha;
tmp.v.specular.red = 0;
tmp.v.specular.green = 0;
tmp.v.specular.blue = 0;
tmp.v.specular.alpha = 0;
tmp.v.u0 = s0;
tmp.v.v0 = t0;
for (i = 0 ; i < 8 ; i++)
vb[i] = tmp.ui[i];
/* right bottom */
vb += 8;
tmp.v.x = x1;
tmp.v.u0 = s1;
for (i = 0 ; i < 8 ; i++)
vb[i] = tmp.ui[i];
/* right top */
vb += 8;
tmp.v.y = y1;
tmp.v.v0 = t1;
for (i = 0 ; i < 8 ; i++)
vb[i] = tmp.ui[i];
/* left top */
vb += 8;
tmp.v.x = x0;
tmp.v.u0 = s0;
for (i = 0 ; i < 8 ; i++)
vb[i] = tmp.ui[i];
/* fprintf(stderr, "%s: DV1: %x\n", */
/* __FUNCTION__, i830->meta.Buffer[I830_DESTREG_DV1]); */
}
void
i830ClearWithTris(intelContextPtr intel, GLbitfield mask,
GLboolean all,
GLint cx, GLint cy, GLint cw, GLint ch)
{
i830ContextPtr i830 = I830_CONTEXT( intel );
__DRIdrawablePrivate *dPriv = intel->driDrawable;
intelScreenPrivate *screen = intel->intelScreen;
int x0, y0, x1, y1;
SET_STATE( i830, meta );
set_initial_state( i830 );
set_no_texture( i830 );
set_vertex_format( i830 );
LOCK_HARDWARE(intel);
if(!all) {
x0 = cx;
y0 = cy;
x1 = x0 + cw;
y1 = y0 + ch;
} else {
x0 = 0;
y0 = 0;
x1 = x0 + dPriv->w;
y1 = y0 + dPriv->h;
}
/* Don't do any clipping to screen - these are window coordinates.
* The active cliprects will be applied as for any other geometry.
*/
if(mask & DD_FRONT_LEFT_BIT) {
set_no_depth_stencil_write( i830 );
set_color_mask( i830, GL_TRUE );
set_draw_offset( i830, screen->frontOffset );
draw_quad(i830, x0, x1, y0, y1,
intel->clear_red, intel->clear_green,
intel->clear_blue, intel->clear_alpha,
0, 0, 0, 0);
}
if(mask & DD_BACK_LEFT_BIT) {
set_no_depth_stencil_write( i830 );
set_color_mask( i830, GL_TRUE );
set_draw_offset( i830, screen->backOffset );
draw_quad(i830, x0, x1, y0, y1,
intel->clear_red, intel->clear_green,
intel->clear_blue, intel->clear_alpha,
0, 0, 0, 0);
}
if(mask & DD_STENCIL_BIT) {
set_stencil_replace( i830,
intel->ctx.Stencil.WriteMask[0],
intel->ctx.Stencil.Clear);
set_color_mask( i830, GL_FALSE );
set_draw_offset( i830, screen->frontOffset );
draw_quad( i830, x0, x1, y0, y1, 0, 0, 0, 0, 0, 0, 0, 0 );
}
UNLOCK_HARDWARE(intel);
SET_STATE( i830, state );
}
GLboolean
i830TryTextureReadPixels( GLcontext *ctx,
GLint x, GLint y, GLsizei width, GLsizei height,
GLenum format, GLenum type,
const struct gl_pixelstore_attrib *pack,
GLvoid *pixels )
{
i830ContextPtr i830 = I830_CONTEXT(ctx);
intelContextPtr intel = INTEL_CONTEXT(ctx);
intelScreenPrivate *screen = i830->intel.intelScreen;
GLint pitch = pack->RowLength ? pack->RowLength : width;
__DRIdrawablePrivate *dPriv = i830->intel.driDrawable;
int textureFormat;
GLenum glTextureFormat;
int src_offset = i830->meta.Buffer[I830_DESTREG_CBUFADDR2];
int destOffset = intelAgpOffsetFromVirtual( &i830->intel, pixels);
int destFormat, depthFormat, destPitch;
drm_clip_rect_t tmp;
if (INTEL_DEBUG & DEBUG_PIXEL)
fprintf(stderr, "%s\n", __FUNCTION__);
if ( ctx->_ImageTransferState ||
pack->SwapBytes ||
pack->LsbFirst ||
!pack->Invert) {
fprintf(stderr, "%s: check_color failed\n", __FUNCTION__);
return GL_FALSE;
}
switch (screen->fbFormat) {
case DV_PF_565:
textureFormat = MAPSURF_16BIT | MT_16BIT_RGB565;
glTextureFormat = GL_RGB;
break;
case DV_PF_555:
textureFormat = MAPSURF_16BIT | MT_16BIT_ARGB1555;
glTextureFormat = GL_RGBA;
break;
case DV_PF_8888:
textureFormat = MAPSURF_32BIT | MT_32BIT_ARGB8888;
glTextureFormat = GL_RGBA;
break;
default:
fprintf(stderr, "%s: textureFormat failed %x\n", __FUNCTION__,
screen->fbFormat);
return GL_FALSE;
}
switch (type) {
case GL_UNSIGNED_SHORT_5_6_5:
if (format != GL_RGB) return GL_FALSE;
destFormat = COLR_BUF_RGB565;
depthFormat = DEPTH_FRMT_16_FIXED;
destPitch = pitch * 2;
break;
case GL_UNSIGNED_INT_8_8_8_8_REV:
if (format != GL_BGRA) return GL_FALSE;
destFormat = COLR_BUF_ARGB8888;
depthFormat = DEPTH_FRMT_24_FIXED_8_OTHER;
destPitch = pitch * 4;
break;
default:
fprintf(stderr, "%s: destFormat failed %s\n", __FUNCTION__,
_mesa_lookup_enum_by_nr(type));
return GL_FALSE;
}
destFormat |= (0x02<<24);
/* fprintf(stderr, "type: %s destFormat: %x\n", */
/* _mesa_lookup_enum_by_nr(type), */
/* destFormat); */
intelFlush( ctx );
SET_STATE( i830, meta );
set_initial_state( i830 );
set_no_depth_stencil_write( i830 );
LOCK_HARDWARE( intel );
{
intelWaitForIdle( intel ); /* required by GL */
if (!driClipRectToFramebuffer(ctx->ReadBuffer, &x, &y, &width, &height)) {
UNLOCK_HARDWARE( intel );
SET_STATE(i830, state);
fprintf(stderr, "%s: cliprect failed\n", __FUNCTION__);
return GL_TRUE;
}
#if 0
/* FIXME -- Just emit the correct state
*/
if (i830SetParam(i830->driFd, I830_SETPARAM_CBUFFER_PITCH,
destPitch) != 0) {
UNLOCK_HARDWARE( intel );
SET_STATE(i830, state);
fprintf(stderr, "%s: setparam failed\n", __FUNCTION__);
return GL_FALSE;
}
#endif
y = dPriv->h - y - height;
x += dPriv->x;
y += dPriv->y;
/* Set the frontbuffer up as a large rectangular texture.
*/
set_tex_rect_source( i830,
src_offset,
screen->width,
screen->height,
screen->frontPitch,
textureFormat );
enable_texture_blend_replace( i830, glTextureFormat );
/* Set the 3d engine to draw into the agp memory
*/
set_draw_offset( i830, destOffset );
set_draw_format( i830, destFormat, depthFormat );
/* Draw a single quad, no cliprects:
*/
i830->intel.numClipRects = 1;
i830->intel.pClipRects = &tmp;
i830->intel.pClipRects[0].x1 = 0;
i830->intel.pClipRects[0].y1 = 0;
i830->intel.pClipRects[0].x2 = width;
i830->intel.pClipRects[0].y2 = height;
draw_quad( i830,
0, width, 0, height,
0, 255, 0, 0,
x, x+width, y, y+height );
intelWindowMoved( intel );
}
UNLOCK_HARDWARE( intel );
intelFinish( ctx ); /* required by GL */
SET_STATE( i830, state );
return GL_TRUE;
}
GLboolean
i830TryTextureDrawPixels( GLcontext *ctx,
GLint x, GLint y, GLsizei width, GLsizei height,
GLenum format, GLenum type,
const struct gl_pixelstore_attrib *unpack,
const GLvoid *pixels )
{
intelContextPtr intel = INTEL_CONTEXT(ctx);
i830ContextPtr i830 = I830_CONTEXT(ctx);
GLint pitch = unpack->RowLength ? unpack->RowLength : width;
__DRIdrawablePrivate *dPriv = intel->driDrawable;
int textureFormat;
GLenum glTextureFormat;
int dst_offset = i830->meta.Buffer[I830_DESTREG_CBUFADDR2];
int src_offset = intelAgpOffsetFromVirtual( intel, pixels );
if (INTEL_DEBUG & DEBUG_PIXEL)
fprintf(stderr, "%s\n", __FUNCTION__);
/* Todo -- upload images that aren't in agp space, then texture
* from them.
*/
if ( !intelIsAgpMemory( intel, pixels, pitch*height ) ) {
fprintf(stderr, "%s: intelIsAgpMemory failed\n", __FUNCTION__);
return GL_FALSE;
}
/* Todo -- don't want to clobber all the drawing state like we do
* for readpixels -- most of this state can be handled just fine.
*/
if ( ctx->_ImageTransferState ||
unpack->SwapBytes ||
unpack->LsbFirst ||
ctx->Color.AlphaEnabled ||
ctx->Depth.Test ||
ctx->Fog.Enabled ||
ctx->Scissor.Enabled ||
ctx->Stencil.Enabled ||
!ctx->Color.ColorMask[0] ||
!ctx->Color.ColorMask[1] ||
!ctx->Color.ColorMask[2] ||
!ctx->Color.ColorMask[3] ||
ctx->Color.ColorLogicOpEnabled ||
ctx->Texture._EnabledUnits ||
ctx->Depth.OcclusionTest) {
fprintf(stderr, "%s: other tests failed\n", __FUNCTION__);
return GL_FALSE;
}
/* Todo -- remove these restrictions:
*/
if (ctx->Pixel.ZoomX != 1.0F ||
ctx->Pixel.ZoomY != -1.0F)
return GL_FALSE;
switch (type) {
case GL_UNSIGNED_SHORT_1_5_5_5_REV:
if (format != GL_BGRA) return GL_FALSE;
textureFormat = MAPSURF_16BIT | MT_16BIT_ARGB1555;
glTextureFormat = GL_RGBA;
break;
case GL_UNSIGNED_SHORT_5_6_5:
if (format != GL_RGB) return GL_FALSE;
textureFormat = MAPSURF_16BIT | MT_16BIT_RGB565;
glTextureFormat = GL_RGB;
break;
case GL_UNSIGNED_SHORT_8_8_MESA:
if (format != GL_YCBCR_MESA) return GL_FALSE;
textureFormat = (MAPSURF_422 | MT_422_YCRCB_SWAPY
/* | TM0S1_COLORSPACE_CONVERSION */
);
glTextureFormat = GL_YCBCR_MESA;
break;
case GL_UNSIGNED_SHORT_8_8_REV_MESA:
if (format != GL_YCBCR_MESA) return GL_FALSE;
textureFormat = (MAPSURF_422 | MT_422_YCRCB_NORMAL
/* | TM0S1_COLORSPACE_CONVERSION */
);
glTextureFormat = GL_YCBCR_MESA;
break;
case GL_UNSIGNED_INT_8_8_8_8_REV:
if (format != GL_BGRA) return GL_FALSE;
textureFormat = MAPSURF_32BIT | MT_32BIT_ARGB8888;
glTextureFormat = GL_RGBA;
break;
default:
fprintf(stderr, "%s: destFormat failed\n", __FUNCTION__);
return GL_FALSE;
}
intelFlush( ctx );
SET_STATE( i830, meta );
LOCK_HARDWARE( intel );
{
intelWaitForIdle( intel ); /* required by GL */
y -= height; /* cope with pixel zoom */
if (!driClipRectToFramebuffer(ctx->ReadBuffer, &x, &y, &width, &height)) {
UNLOCK_HARDWARE( intel );
SET_STATE(i830, state);
fprintf(stderr, "%s: cliprect failed\n", __FUNCTION__);
return GL_TRUE;
}
y = dPriv->h - y - height;
set_initial_state( i830 );
/* Set the pixel image up as a rectangular texture.
*/
set_tex_rect_source( i830,
src_offset,
width,
height,
pitch, /* XXXX!!!! -- /2 sometimes */
textureFormat );
enable_texture_blend_replace( i830, glTextureFormat );
/* Draw to the current draw buffer:
*/
set_draw_offset( i830, dst_offset );
/* Draw a quad, use regular cliprects
*/
/* fprintf(stderr, "x: %d y: %d width %d height %d\n", x, y, width, height); */
draw_quad( i830,
x, x+width, y, y+height,
0, 255, 0, 0,
0, width, 0, height );
intelWindowMoved( intel );
}
UNLOCK_HARDWARE( intel );
intelFinish( ctx ); /* required by GL */
SET_STATE(i830, state);
return GL_TRUE;
}
+665
View File
@@ -0,0 +1,665 @@
/**************************************************************************
*
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
**************************************************************************/
#ifndef _I830_REG_H_
#define _I830_REG_H_
#include "intel_reg.h"
#define I830_SET_FIELD( var, mask, value ) (var &= ~(mask), var |= value)
#define _3DSTATE_AA_CMD (CMD_3D | (0x06<<24))
#define AA_LINE_ECAAR_WIDTH_ENABLE (1<<16)
#define AA_LINE_ECAAR_WIDTH_0_5 0
#define AA_LINE_ECAAR_WIDTH_1_0 (1<<14)
#define AA_LINE_ECAAR_WIDTH_2_0 (2<<14)
#define AA_LINE_ECAAR_WIDTH_4_0 (3<<14)
#define AA_LINE_REGION_WIDTH_ENABLE (1<<8)
#define AA_LINE_REGION_WIDTH_0_5 0
#define AA_LINE_REGION_WIDTH_1_0 (1<<6)
#define AA_LINE_REGION_WIDTH_2_0 (2<<6)
#define AA_LINE_REGION_WIDTH_4_0 (3<<6)
#define AA_LINE_ENABLE ((1<<1) | 1)
#define AA_LINE_DISABLE (1<<1)
#define _3DSTATE_BUF_INFO_CMD (CMD_3D | (0x1d<<24) | (0x8e<<16) | 1)
/* Dword 1 */
#define BUF_3D_ID_COLOR_BACK (0x3<<24)
#define BUF_3D_ID_DEPTH (0x7<<24)
#define BUF_3D_USE_FENCE (1<<23)
#define BUF_3D_TILED_SURFACE (1<<22)
#define BUF_3D_TILE_WALK_X 0
#define BUF_3D_TILE_WALK_Y (1<<21)
#define BUF_3D_PITCH(x) (((x)/4)<<2)
/* Dword 2 */
#define BUF_3D_ADDR(x) ((x) & ~0x3)
#define _3DSTATE_COLOR_FACTOR_CMD (CMD_3D | (0x1d<<24) | (0x1<<16))
#define _3DSTATE_COLOR_FACTOR_N_CMD(stage) (CMD_3D | (0x1d<<24) | \
((0x90+(stage))<<16))
#define _3DSTATE_CONST_BLEND_COLOR_CMD (CMD_3D | (0x1d<<24) | (0x88<<16))
#define _3DSTATE_DFLT_DIFFUSE_CMD (CMD_3D | (0x1d<<24) | (0x99<<16))
#define _3DSTATE_DFLT_SPEC_CMD (CMD_3D | (0x1d<<24) | (0x9a<<16))
#define _3DSTATE_DFLT_Z_CMD (CMD_3D | (0x1d<<24) | (0x98<<16))
#define _3DSTATE_DST_BUF_VARS_CMD (CMD_3D | (0x1d<<24) | (0x85<<16))
/* Dword 1 */
#define DSTORG_HORT_BIAS(x) ((x)<<20)
#define DSTORG_VERT_BIAS(x) ((x)<<16)
#define COLOR_4_2_2_CHNL_WRT_ALL 0
#define COLOR_4_2_2_CHNL_WRT_Y (1<<12)
#define COLOR_4_2_2_CHNL_WRT_CR (2<<12)
#define COLOR_4_2_2_CHNL_WRT_CB (3<<12)
#define COLOR_4_2_2_CHNL_WRT_CRCB (4<<12)
#define COLR_BUF_8BIT 0
#define COLR_BUF_RGB555 (1<<8)
#define COLR_BUF_RGB565 (2<<8)
#define COLR_BUF_ARGB8888 (3<<8)
#define DEPTH_IS_Z 0
#define DEPTH_IS_W (1<<6)
#define DEPTH_FRMT_16_FIXED 0
#define DEPTH_FRMT_16_FLOAT (1<<2)
#define DEPTH_FRMT_24_FIXED_8_OTHER (2<<2)
#define DEPTH_FRMT_24_FLOAT_8_OTHER (3<<2)
#define VERT_LINE_STRIDE_1 (1<<1)
#define VERT_LINE_STRIDE_0 0
#define VERT_LINE_STRIDE_OFS_1 1
#define VERT_LINE_STRIDE_OFS_0 0
#define _3DSTATE_DRAW_RECT_CMD (CMD_3D|(0x1d<<24)|(0x80<<16)|3)
/* Dword 1 */
#define DRAW_RECT_DIS_DEPTH_OFS (1<<30)
#define DRAW_DITHER_OFS_X(x) ((x)<<26)
#define DRAW_DITHER_OFS_Y(x) ((x)<<24)
/* Dword 2 */
#define DRAW_YMIN(x) ((x)<<16)
#define DRAW_XMIN(x) (x)
/* Dword 3 */
#define DRAW_YMAX(x) ((x)<<16)
#define DRAW_XMAX(x) (x)
/* Dword 4 */
#define DRAW_YORG(x) ((x)<<16)
#define DRAW_XORG(x) (x)
#define _3DSTATE_ENABLES_1_CMD (CMD_3D|(0x3<<24))
#define ENABLE_LOGIC_OP_MASK ((1<<23)|(1<<22))
#define ENABLE_LOGIC_OP ((1<<23)|(1<<22))
#define DISABLE_LOGIC_OP (1<<23)
#define ENABLE_STENCIL_TEST ((1<<21)|(1<<20))
#define DISABLE_STENCIL_TEST (1<<21)
#define ENABLE_DEPTH_BIAS ((1<<11)|(1<<10))
#define DISABLE_DEPTH_BIAS (1<<11)
#define ENABLE_SPEC_ADD_MASK ((1<<9)|(1<<8))
#define ENABLE_SPEC_ADD ((1<<9)|(1<<8))
#define DISABLE_SPEC_ADD (1<<9)
#define ENABLE_DIS_FOG_MASK ((1<<7)|(1<<6))
#define ENABLE_FOG ((1<<7)|(1<<6))
#define DISABLE_FOG (1<<7)
#define ENABLE_DIS_ALPHA_TEST_MASK ((1<<5)|(1<<4))
#define ENABLE_ALPHA_TEST ((1<<5)|(1<<4))
#define DISABLE_ALPHA_TEST (1<<5)
#define ENABLE_DIS_CBLEND_MASK ((1<<3)|(1<<2))
#define ENABLE_COLOR_BLEND ((1<<3)|(1<<2))
#define DISABLE_COLOR_BLEND (1<<3)
#define ENABLE_DIS_DEPTH_TEST_MASK ((1<<1)|1)
#define ENABLE_DEPTH_TEST ((1<<1)|1)
#define DISABLE_DEPTH_TEST (1<<1)
/* _3DSTATE_ENABLES_2, p138 */
#define _3DSTATE_ENABLES_2_CMD (CMD_3D|(0x4<<24))
#define ENABLE_STENCIL_WRITE ((1<<21)|(1<<20))
#define DISABLE_STENCIL_WRITE (1<<21)
#define ENABLE_TEX_CACHE ((1<<17)|(1<<16))
#define DISABLE_TEX_CACHE (1<<17)
#define ENABLE_DITHER ((1<<9)|(1<<8))
#define DISABLE_DITHER (1<<9)
#define ENABLE_COLOR_MASK (1<<10)
#define WRITEMASK_ALPHA (1<<7)
#define WRITEMASK_ALPHA_SHIFT 7
#define WRITEMASK_RED (1<<6)
#define WRITEMASK_RED_SHIFT 6
#define WRITEMASK_GREEN (1<<5)
#define WRITEMASK_GREEN_SHIFT 5
#define WRITEMASK_BLUE (1<<4)
#define WRITEMASK_BLUE_SHIFT 4
#define WRITEMASK_MASK ((1<<4)|(1<<5)|(1<<6)|(1<<7))
#define ENABLE_COLOR_WRITE ((1<<3)|(1<<2))
#define DISABLE_COLOR_WRITE (1<<3)
#define ENABLE_DIS_DEPTH_WRITE_MASK 0x3
#define ENABLE_DEPTH_WRITE ((1<<1)|1)
#define DISABLE_DEPTH_WRITE (1<<1)
/* _3DSTATE_FOG_COLOR, p139 */
#define _3DSTATE_FOG_COLOR_CMD (CMD_3D|(0x15<<24))
#define FOG_COLOR_RED(x) ((x)<<16)
#define FOG_COLOR_GREEN(x) ((x)<<8)
#define FOG_COLOR_BLUE(x) (x)
/* _3DSTATE_FOG_MODE, p140 */
#define _3DSTATE_FOG_MODE_CMD (CMD_3D|(0x1d<<24)|(0x89<<16)|2)
/* Dword 1 */
#define FOGFUNC_ENABLE (1<<31)
#define FOGFUNC_VERTEX 0
#define FOGFUNC_PIXEL_EXP (1<<28)
#define FOGFUNC_PIXEL_EXP2 (2<<28)
#define FOGFUNC_PIXEL_LINEAR (3<<28)
#define FOGSRC_INDEX_Z (1<<27)
#define FOGSRC_INDEX_W ((1<<27)|(1<<25))
#define FOG_LINEAR_CONST (1<<24)
#define FOG_CONST_1(x) ((x)<<4)
#define ENABLE_FOG_DENSITY (1<<23)
/* Dword 2 */
#define FOG_CONST_2(x) (x)
/* Dword 3 */
#define FOG_DENSITY(x) (x)
/* _3DSTATE_INDEPENDENT_ALPHA_BLEND, p142 */
#define _3DSTATE_INDPT_ALPHA_BLEND_CMD (CMD_3D|(0x0b<<24))
#define ENABLE_INDPT_ALPHA_BLEND ((1<<23)|(1<<22))
#define DISABLE_INDPT_ALPHA_BLEND (1<<23)
#define ALPHA_BLENDFUNC_MASK 0x3f0000
#define ENABLE_ALPHA_BLENDFUNC (1<<21)
#define ABLENDFUNC_ADD 0
#define ABLENDFUNC_SUB (1<<16)
#define ABLENDFUNC_RVSE_SUB (2<<16)
#define ABLENDFUNC_MIN (3<<16)
#define ABLENDFUNC_MAX (4<<16)
#define SRC_DST_ABLEND_MASK 0xfff
#define ENABLE_SRC_ABLEND_FACTOR (1<<11)
#define SRC_ABLEND_FACT(x) ((x)<<6)
#define ENABLE_DST_ABLEND_FACTOR (1<<5)
#define DST_ABLEND_FACT(x) (x)
#define BLENDFACT_ZERO 0x01
#define BLENDFACT_ONE 0x02
#define BLENDFACT_SRC_COLR 0x03
#define BLENDFACT_INV_SRC_COLR 0x04
#define BLENDFACT_SRC_ALPHA 0x05
#define BLENDFACT_INV_SRC_ALPHA 0x06
#define BLENDFACT_DST_ALPHA 0x07
#define BLENDFACT_INV_DST_ALPHA 0x08
#define BLENDFACT_DST_COLR 0x09
#define BLENDFACT_INV_DST_COLR 0x0a
#define BLENDFACT_SRC_ALPHA_SATURATE 0x0b
#define BLENDFACT_CONST_COLOR 0x0c
#define BLENDFACT_INV_CONST_COLOR 0x0d
#define BLENDFACT_CONST_ALPHA 0x0e
#define BLENDFACT_INV_CONST_ALPHA 0x0f
/* _3DSTATE_MAP_BLEND_ARG, p152 */
#define _3DSTATE_MAP_BLEND_ARG_CMD(stage) (CMD_3D|(0x0e<<24)|((stage)<<20))
#define TEXPIPE_COLOR 0
#define TEXPIPE_ALPHA (1<<18)
#define TEXPIPE_KILL (2<<18)
#define TEXBLEND_ARG0 0
#define TEXBLEND_ARG1 (1<<15)
#define TEXBLEND_ARG2 (2<<15)
#define TEXBLEND_ARG3 (3<<15)
#define TEXBLENDARG_MODIFY_PARMS (1<<6)
#define TEXBLENDARG_REPLICATE_ALPHA (1<<5)
#define TEXBLENDARG_INV_ARG (1<<4)
#define TEXBLENDARG_ONE 0
#define TEXBLENDARG_FACTOR 0x01
#define TEXBLENDARG_ACCUM 0x02
#define TEXBLENDARG_DIFFUSE 0x03
#define TEXBLENDARG_SPEC 0x04
#define TEXBLENDARG_CURRENT 0x05
#define TEXBLENDARG_TEXEL0 0x06
#define TEXBLENDARG_TEXEL1 0x07
#define TEXBLENDARG_TEXEL2 0x08
#define TEXBLENDARG_TEXEL3 0x09
#define TEXBLENDARG_FACTOR_N 0x0e
/* _3DSTATE_MAP_BLEND_OP, p155 */
#define _3DSTATE_MAP_BLEND_OP_CMD(stage) (CMD_3D|(0x0d<<24)|((stage)<<20))
#if 0
# define TEXPIPE_COLOR 0
# define TEXPIPE_ALPHA (1<<18)
# define TEXPIPE_KILL (2<<18)
#endif
#define ENABLE_TEXOUTPUT_WRT_SEL (1<<17)
#define TEXOP_OUTPUT_CURRENT 0
#define TEXOP_OUTPUT_ACCUM (1<<15)
#define ENABLE_TEX_CNTRL_STAGE ((1<<12)|(1<<11))
#define DISABLE_TEX_CNTRL_STAGE (1<<12)
#define TEXOP_SCALE_SHIFT 9
#define TEXOP_SCALE_1X (0 << TEXOP_SCALE_SHIFT)
#define TEXOP_SCALE_2X (1 << TEXOP_SCALE_SHIFT)
#define TEXOP_SCALE_4X (2 << TEXOP_SCALE_SHIFT)
#define TEXOP_MODIFY_PARMS (1<<8)
#define TEXOP_LAST_STAGE (1<<7)
#define TEXBLENDOP_KILLPIXEL 0x02
#define TEXBLENDOP_ARG1 0x01
#define TEXBLENDOP_ARG2 0x02
#define TEXBLENDOP_MODULATE 0x03
#define TEXBLENDOP_ADD 0x06
#define TEXBLENDOP_ADDSIGNED 0x07
#define TEXBLENDOP_BLEND 0x08
#define TEXBLENDOP_BLEND_AND_ADD 0x09
#define TEXBLENDOP_SUBTRACT 0x0a
#define TEXBLENDOP_DOT3 0x0b
#define TEXBLENDOP_DOT4 0x0c
#define TEXBLENDOP_MODULATE_AND_ADD 0x0d
#define TEXBLENDOP_MODULATE_2X_AND_ADD 0x0e
#define TEXBLENDOP_MODULATE_4X_AND_ADD 0x0f
/* _3DSTATE_MAP_BUMP_TABLE, p160 TODO */
/* _3DSTATE_MAP_COLOR_CHROMA_KEY, p161 TODO */
#define _3DSTATE_MAP_COORD_TRANSFORM ((3<<29)|(0x1d<<24)|(0x8c<<16))
#define DISABLE_TEX_TRANSFORM (1<<28)
#define TEXTURE_SET(x) (x<<29)
#define _3DSTATE_VERTEX_TRANSFORM ((3<<29)|(0x1d<<24)|(0x8b<<16))
#define DISABLE_VIEWPORT_TRANSFORM (1<<31)
#define DISABLE_PERSPECTIVE_DIVIDE (1<<29)
/* _3DSTATE_MAP_COORD_SET_BINDINGS, p162 */
#define _3DSTATE_MAP_COORD_SETBIND_CMD (CMD_3D|(0x1d<<24)|(0x02<<16))
#define TEXBIND_MASK3 ((1<<15)|(1<<14)|(1<<13)|(1<<12))
#define TEXBIND_MASK2 ((1<<11)|(1<<10)|(1<<9)|(1<<8))
#define TEXBIND_MASK1 ((1<<7)|(1<<6)|(1<<5)|(1<<4))
#define TEXBIND_MASK0 ((1<<3)|(1<<2)|(1<<1)|1)
#define TEXBIND_SET3(x) ((x)<<12)
#define TEXBIND_SET2(x) ((x)<<8)
#define TEXBIND_SET1(x) ((x)<<4)
#define TEXBIND_SET0(x) (x)
#define TEXCOORDSRC_KEEP 0
#define TEXCOORDSRC_DEFAULT 0x01
#define TEXCOORDSRC_VTXSET_0 0x08
#define TEXCOORDSRC_VTXSET_1 0x09
#define TEXCOORDSRC_VTXSET_2 0x0a
#define TEXCOORDSRC_VTXSET_3 0x0b
#define TEXCOORDSRC_VTXSET_4 0x0c
#define TEXCOORDSRC_VTXSET_5 0x0d
#define TEXCOORDSRC_VTXSET_6 0x0e
#define TEXCOORDSRC_VTXSET_7 0x0f
#define MAP_UNIT(unit) ((unit)<<16)
#define MAP_UNIT_MASK (0x7<<16)
/* _3DSTATE_MAP_COORD_SETS, p164 */
#define _3DSTATE_MAP_COORD_SET_CMD (CMD_3D|(0x1c<<24)|(0x01<<19))
#define ENABLE_TEXCOORD_PARAMS (1<<15)
#define TEXCOORDS_ARE_NORMAL (1<<14)
#define TEXCOORDS_ARE_IN_TEXELUNITS 0
#define TEXCOORDTYPE_CARTESIAN 0
#define TEXCOORDTYPE_HOMOGENEOUS (1<<11)
#define TEXCOORDTYPE_VECTOR (2<<11)
#define TEXCOORDTYPE_MASK (0x7<<11)
#define ENABLE_ADDR_V_CNTL (1<<7)
#define ENABLE_ADDR_U_CNTL (1<<3)
#define TEXCOORD_ADDR_V_MODE(x) ((x)<<4)
#define TEXCOORD_ADDR_U_MODE(x) (x)
#define TEXCOORDMODE_WRAP 0
#define TEXCOORDMODE_MIRROR 1
#define TEXCOORDMODE_CLAMP 2
#define TEXCOORDMODE_WRAP_SHORTEST 3
#define TEXCOORDMODE_CLAMP_BORDER 4
#define TEXCOORD_ADDR_V_MASK 0x70
#define TEXCOORD_ADDR_U_MASK 0x7
/* _3DSTATE_MAP_CUBE, p168 TODO */
#define _3DSTATE_MAP_CUBE (CMD_3D|(0x1c<<24)|(0x0a<<19))
#define CUBE_NEGX_ENABLE (1<<5)
#define CUBE_POSX_ENABLE (1<<4)
#define CUBE_NEGY_ENABLE (1<<3)
#define CUBE_POSY_ENABLE (1<<2)
#define CUBE_NEGZ_ENABLE (1<<1)
#define CUBE_POSZ_ENABLE (1<<0)
/* _3DSTATE_MODES_1, p190 */
#define _3DSTATE_MODES_1_CMD (CMD_3D|(0x08<<24))
#define BLENDFUNC_MASK 0x3f0000
#define ENABLE_COLR_BLND_FUNC (1<<21)
#define BLENDFUNC_ADD 0
#define BLENDFUNC_SUB (1<<16)
#define BLENDFUNC_RVRSE_SUB (2<<16)
#define BLENDFUNC_MIN (3<<16)
#define BLENDFUNC_MAX (4<<16)
#define SRC_DST_BLND_MASK 0xfff
#define ENABLE_SRC_BLND_FACTOR (1<<11)
#define ENABLE_DST_BLND_FACTOR (1<<5)
#define SRC_BLND_FACT(x) ((x)<<6)
#define DST_BLND_FACT(x) (x)
/* Use the blendfact defines for BLND_FACTOR macros */
#if 0
#define BLENDFACT_ZERO 0x01
#define BLENDFACT_ONE 0x02
#define BLENDFACT_SRC_COLR 0x03
#define BLENDFACT_INV_SRC_COLR 0x04
#define BLENDFACT_SRC_ALPHA 0x05
#define BLENDFACT_INV_SRC_ALPHA 0x06
#define BLENDFACT_DST_ALPHA 0x07
#define BLENDFACT_INV_DST_ALPHA 0x08
#define BLENDFACT_CONST_ALPHA 0x0e
#define BLENDFACT_INV_CONST_ALPHA 0x0f
#endif
/* _3DSTATE_MODES_2, p192 */
#define _3DSTATE_MODES_2_CMD (CMD_3D|(0x0f<<24))
#define ENABLE_GLOBAL_DEPTH_BIAS (1<<22)
#define GLOBAL_DEPTH_BIAS(x) ((x)<<14)
#define ENABLE_ALPHA_TEST_FUNC (1<<13)
#define ENABLE_ALPHA_REF_VALUE (1<<8)
#define ALPHA_TEST_FUNC(x) ((x)<<9)
#define ALPHA_REF_VALUE(x) (x)
#define ALPHA_TEST_REF_MASK 0x3fff
#define COMPAREFUNC_ALWAYS 0
#define COMPAREFUNC_NEVER 0x1
#define COMPAREFUNC_LESS 0x2
#define COMPAREFUNC_EQUAL 0x3
#define COMPAREFUNC_LEQUAL 0x4
#define COMPAREFUNC_GREATER 0x5
#define COMPAREFUNC_NOTEQUAL 0x6
#define COMPAREFUNC_GEQUAL 0x7
/* _3DSTATE_MODES_3, p193 */
#define _3DSTATE_MODES_3_CMD (CMD_3D|(0x02<<24))
#define DEPTH_TEST_FUNC_MASK 0x1f0000
#define ENABLE_DEPTH_TEST_FUNC (1<<20)
/* Uses COMPAREFUNC */
#define DEPTH_TEST_FUNC(x) ((x)<<16)
#define ENABLE_ALPHA_SHADE_MODE (1<<11)
#define ENABLE_FOG_SHADE_MODE (1<<9)
#define ENABLE_SPEC_SHADE_MODE (1<<7)
#define ENABLE_COLOR_SHADE_MODE (1<<5)
#define ALPHA_SHADE_MODE(x) ((x)<<10)
#define FOG_SHADE_MODE(x) ((x)<<8)
#define SPEC_SHADE_MODE(x) ((x)<<6)
#define COLOR_SHADE_MODE(x) ((x)<<4)
#define CULLMODE_MASK 0xf
#define ENABLE_CULL_MODE (1<<3)
#define CULLMODE_BOTH 0
#define CULLMODE_NONE 1
#define CULLMODE_CW 2
#define CULLMODE_CCW 3
#define SHADE_MODE_LINEAR 0
#define SHADE_MODE_FLAT 0x1
/* _3DSTATE_MODES_4, p195 */
#define _3DSTATE_MODES_4_CMD (CMD_3D|(0x16<<24))
#define ENABLE_LOGIC_OP_FUNC (1<<23)
#define LOGIC_OP_FUNC(x) ((x)<<18)
#define LOGICOP_MASK ((1<<18)|(1<<19)|(1<<20)|(1<<21))
#define LOGICOP_CLEAR 0
#define LOGICOP_NOR 0x1
#define LOGICOP_AND_INV 0x2
#define LOGICOP_COPY_INV 0x3
#define LOGICOP_AND_RVRSE 0x4
#define LOGICOP_INV 0x5
#define LOGICOP_XOR 0x6
#define LOGICOP_NAND 0x7
#define LOGICOP_AND 0x8
#define LOGICOP_EQUIV 0x9
#define LOGICOP_NOOP 0xa
#define LOGICOP_OR_INV 0xb
#define LOGICOP_COPY 0xc
#define LOGICOP_OR_RVRSE 0xd
#define LOGICOP_OR 0xe
#define LOGICOP_SET 0xf
#define MODE4_ENABLE_STENCIL_TEST_MASK ((1<<17)|(0xff00))
#define ENABLE_STENCIL_TEST_MASK (1<<17)
#define STENCIL_TEST_MASK(x) ((x)<<8)
#define MODE4_ENABLE_STENCIL_WRITE_MASK ((1<<16)|(0x00ff))
#define ENABLE_STENCIL_WRITE_MASK (1<<16)
#define STENCIL_WRITE_MASK(x) (x)
/* _3DSTATE_MODES_5, p196 */
#define _3DSTATE_MODES_5_CMD (CMD_3D|(0x0c<<24))
#define ENABLE_SPRITE_POINT_TEX (1<<23)
#define SPRITE_POINT_TEX_ON (1<<22)
#define SPRITE_POINT_TEX_OFF 0
#define FLUSH_RENDER_CACHE (1<<18)
#define FLUSH_TEXTURE_CACHE (1<<16)
#define FIXED_LINE_WIDTH_MASK 0xfc00
#define ENABLE_FIXED_LINE_WIDTH (1<<15)
#define FIXED_LINE_WIDTH(x) ((x)<<10)
#define FIXED_POINT_WIDTH_MASK 0x3ff
#define ENABLE_FIXED_POINT_WIDTH (1<<9)
#define FIXED_POINT_WIDTH(x) (x)
/* _3DSTATE_RASTERIZATION_RULES, p198 */
#define _3DSTATE_RASTER_RULES_CMD (CMD_3D|(0x07<<24))
#define ENABLE_POINT_RASTER_RULE (1<<15)
#define OGL_POINT_RASTER_RULE (1<<13)
#define ENABLE_LINE_STRIP_PROVOKE_VRTX (1<<8)
#define ENABLE_TRI_FAN_PROVOKE_VRTX (1<<5)
#define ENABLE_TRI_STRIP_PROVOKE_VRTX (1<<2)
#define LINE_STRIP_PROVOKE_VRTX(x) ((x)<<6)
#define TRI_FAN_PROVOKE_VRTX(x) ((x)<<3)
#define TRI_STRIP_PROVOKE_VRTX(x) (x)
/* _3DSTATE_SCISSOR_ENABLE, p200 */
#define _3DSTATE_SCISSOR_ENABLE_CMD (CMD_3D|(0x1c<<24)|(0x10<<19))
#define ENABLE_SCISSOR_RECT ((1<<1) | 1)
#define DISABLE_SCISSOR_RECT (1<<1)
/* _3DSTATE_SCISSOR_RECTANGLE_0, p201 */
#define _3DSTATE_SCISSOR_RECT_0_CMD (CMD_3D|(0x1d<<24)|(0x81<<16)|1)
/* Dword 1 */
#define SCISSOR_RECT_0_YMIN(x) ((x)<<16)
#define SCISSOR_RECT_0_XMIN(x) (x)
/* Dword 2 */
#define SCISSOR_RECT_0_YMAX(x) ((x)<<16)
#define SCISSOR_RECT_0_XMAX(x) (x)
/* _3DSTATE_STENCIL_TEST, p202 */
#define _3DSTATE_STENCIL_TEST_CMD (CMD_3D|(0x09<<24))
#define ENABLE_STENCIL_PARMS (1<<23)
#define STENCIL_OPS_MASK (0xffc000)
#define STENCIL_FAIL_OP(x) ((x)<<20)
#define STENCIL_PASS_DEPTH_FAIL_OP(x) ((x)<<17)
#define STENCIL_PASS_DEPTH_PASS_OP(x) ((x)<<14)
#define STENCILOP_KEEP 0
#define STENCILOP_ZERO 0x1
#define STENCILOP_REPLACE 0x2
#define STENCILOP_INCRSAT 0x3
#define STENCILOP_DECRSAT 0x4
#define STENCILOP_INCR 0x5
#define STENCILOP_DECR 0x6
#define STENCILOP_INVERT 0x7
#define ENABLE_STENCIL_TEST_FUNC_MASK ((1<<13)|(1<<12)|(1<<11)|(1<<10)|(1<<9))
#define ENABLE_STENCIL_TEST_FUNC (1<<13)
/* Uses COMPAREFUNC */
#define STENCIL_TEST_FUNC(x) ((x)<<9)
#define STENCIL_REF_VALUE_MASK ((1<<8)|0xff)
#define ENABLE_STENCIL_REF_VALUE (1<<8)
#define STENCIL_REF_VALUE(x) (x)
/* _3DSTATE_VERTEX_FORMAT, p204 */
#define _3DSTATE_VFT0_CMD (CMD_3D|(0x05<<24))
#define VFT0_POINT_WIDTH (1<<12)
#define VFT0_TEX_COUNT_MASK (7<<8)
#define VFT0_TEX_COUNT_SHIFT 8
#define VFT0_TEX_COUNT(x) ((x)<<8)
#define VFT0_SPEC (1<<7)
#define VFT0_DIFFUSE (1<<6)
#define VFT0_DEPTH_OFFSET (1<<5)
#define VFT0_XYZ (1<<1)
#define VFT0_XYZW (2<<1)
#define VFT0_XY (3<<1)
#define VFT0_XYW (4<<1)
#define VFT0_XYZW_MASK (7<<1)
/* _3DSTATE_VERTEX_FORMAT_2, p206 */
#define _3DSTATE_VFT1_CMD (CMD_3D|(0x0a<<24))
#define VFT1_TEX7_FMT(x) ((x)<<14)
#define VFT1_TEX6_FMT(x) ((x)<<12)
#define VFT1_TEX5_FMT(x) ((x)<<10)
#define VFT1_TEX4_FMT(x) ((x)<<8)
#define VFT1_TEX3_FMT(x) ((x)<<6)
#define VFT1_TEX2_FMT(x) ((x)<<4)
#define VFT1_TEX1_FMT(x) ((x)<<2)
#define VFT1_TEX0_FMT(x) (x)
#define VFT1_TEX0_MASK 3
#define VFT1_TEX1_SHIFT 2
#define TEXCOORDFMT_2D 0
#define TEXCOORDFMT_3D 1
#define TEXCOORDFMT_4D 2
#define TEXCOORDFMT_1D 3
/*New stuff picked up along the way */
#define MLC_LOD_BIAS_MASK ((1<<7)-1)
/* _3DSTATE_VERTEX_TRANSFORM, p207 */
#define _3DSTATE_VERTEX_TRANS_CMD (CMD_3D|(0x1d<<24)|(0x8b<<16)|0)
#define _3DSTATE_VERTEX_TRANS_MTX_CMD (CMD_3D|(0x1d<<24)|(0x8b<<16)|6)
/* Dword 1 */
#define ENABLE_VIEWPORT_TRANSFORM ((1<<31)|(1<<30))
#define DISABLE_VIEWPORT_TRANSFORM (1<<31)
#define ENABLE_PERSP_DIVIDE ((1<<29)|(1<<28))
#define DISABLE_PERSP_DIVIDE (1<<29)
#define VRTX_TRANS_LOAD_MATRICES 0x7421
#define VRTX_TRANS_NO_LOAD_MATRICES 0x0000
/* Dword 2 -> 7 are matrix elements */
/* _3DSTATE_W_STATE, p209 */
#define _3DSTATE_W_STATE_CMD (CMD_3D|(0x1d<<24)|(0x8d<<16)|1)
/* Dword 1 */
#define MAGIC_W_STATE_DWORD1 0x00000008
/* Dword 2 */
#define WFAR_VALUE(x) (x)
/* Stipple command, carried over from the i810, apparently:
*/
#define _3DSTATE_STIPPLE ((0x3<<29)|(0x1d<<24)|(0x83<<16))
#define ST1_ENABLE (1<<16)
#define ST1_MASK (0xffff)
#define _3DSTATE_LOAD_STATE_IMMEDIATE_2 ((0x3<<29)|(0x1d<<24)|(0x03<<16))
#define LOAD_TEXTURE_MAP0 (1<<11)
#define LOAD_GLOBAL_COLOR_FACTOR (1<<6)
#define TM0S0_ADDRESS_MASK 0xfffffffc
#define TM0S0_USE_FENCE (1<<1)
#define TM0S1_HEIGHT_SHIFT 21
#define TM0S1_WIDTH_SHIFT 10
#define TM0S1_PALETTE_SELECT (1<<9)
#define TM0S1_MAPSURF_FORMAT_MASK (0x7 << 6)
#define TM0S1_MAPSURF_FORMAT_SHIFT 6
#define MAPSURF_8BIT_INDEXED (0<<6)
#define MAPSURF_8BIT (1<<6)
#define MAPSURF_16BIT (2<<6)
#define MAPSURF_32BIT (3<<6)
#define MAPSURF_411 (4<<6)
#define MAPSURF_422 (5<<6)
#define MAPSURF_COMPRESSED (6<<6)
#define MAPSURF_4BIT_INDEXED (7<<6)
#define TM0S1_MT_FORMAT_MASK (0x7 << 3)
#define TM0S1_MT_FORMAT_SHIFT 3
#define MT_4BIT_IDX_ARGB8888 (7<<3) /* SURFACE_4BIT_INDEXED */
#define MT_8BIT_IDX_RGB565 (0<<3) /* SURFACE_8BIT_INDEXED */
#define MT_8BIT_IDX_ARGB1555 (1<<3)
#define MT_8BIT_IDX_ARGB4444 (2<<3)
#define MT_8BIT_IDX_AY88 (3<<3)
#define MT_8BIT_IDX_ABGR8888 (4<<3)
#define MT_8BIT_IDX_BUMP_88DVDU (5<<3)
#define MT_8BIT_IDX_BUMP_655LDVDU (6<<3)
#define MT_8BIT_IDX_ARGB8888 (7<<3)
#define MT_8BIT_I8 (0<<3) /* SURFACE_8BIT */
#define MT_8BIT_L8 (1<<3)
#define MT_16BIT_RGB565 (0<<3) /* SURFACE_16BIT */
#define MT_16BIT_ARGB1555 (1<<3)
#define MT_16BIT_ARGB4444 (2<<3)
#define MT_16BIT_AY88 (3<<3)
#define MT_16BIT_DIB_ARGB1555_8888 (4<<3)
#define MT_16BIT_BUMP_88DVDU (5<<3)
#define MT_16BIT_BUMP_655LDVDU (6<<3)
#define MT_16BIT_DIB_RGB565_8888 (7<<3)
#define MT_32BIT_ARGB8888 (0<<3) /* SURFACE_32BIT */
#define MT_32BIT_ABGR8888 (1<<3)
#define MT_32BIT_BUMP_XLDVDU_8888 (6<<3)
#define MT_32BIT_DIB_8888 (7<<3)
#define MT_411_YUV411 (0<<3) /* SURFACE_411 */
#define MT_422_YCRCB_SWAPY (0<<3) /* SURFACE_422 */
#define MT_422_YCRCB_NORMAL (1<<3)
#define MT_422_YCRCB_SWAPUV (2<<3)
#define MT_422_YCRCB_SWAPUVY (3<<3)
#define MT_COMPRESS_DXT1 (0<<3) /* SURFACE_COMPRESSED */
#define MT_COMPRESS_DXT2_3 (1<<3)
#define MT_COMPRESS_DXT4_5 (2<<3)
#define MT_COMPRESS_FXT1 (3<<3)
#define TM0S1_COLORSPACE_CONVERSION (1 << 2)
#define TM0S1_TILED_SURFACE (1 << 1)
#define TM0S1_TILE_WALK (1 << 0)
#define TM0S2_PITCH_SHIFT 21
#define TM0S2_CUBE_FACE_ENA_SHIFT 15
#define TM0S2_MAP_FORMAT (1<<14)
#define TM0S2_VERTICAL_LINE_STRIDE (1<<13)
#define TM0S2_VERITCAL_LINE_STRIDE_OFF (1<<12)
#define TM0S2_OUTPUT_CHAN_SHIFT 10
#define TM0S2_OUTPUT_CHAN_MASK (3<<10)
#define TM0S3_MIP_FILTER_MASK (0x3<<30)
#define TM0S3_MIP_FILTER_SHIFT 30
#define MIPFILTER_NONE 0
#define MIPFILTER_NEAREST 1
#define MIPFILTER_LINEAR 3
#define TM0S3_MAG_FILTER_MASK (0x3<<28)
#define TM0S3_MAG_FILTER_SHIFT 28
#define TM0S3_MIN_FILTER_MASK (0x3<<26)
#define TM0S3_MIN_FILTER_SHIFT 26
#define FILTER_NEAREST 0
#define FILTER_LINEAR 1
#define FILTER_ANISOTROPIC 2
#define TM0S3_LOD_BIAS_SHIFT 17
#define TM0S3_LOD_BIAS_MASK (0x1ff<<17)
#define TM0S3_MAX_MIP_SHIFT 9
#define TM0S3_MAX_MIP_MASK (0xff<<9)
#define TM0S3_MIN_MIP_SHIFT 3
#define TM0S3_MIN_MIP_MASK (0x3f<<3)
#define TM0S3_KILL_PIXEL (1<<2)
#define TM0S3_KEYED_FILTER (1<<1)
#define TM0S3_CHROMA_KEY (1<<0)
/* _3DSTATE_MAP_TEXEL_STREAM, p188 */
#define _3DSTATE_MAP_TEX_STREAM_CMD (CMD_3D|(0x1c<<24)|(0x05<<19))
#define DISABLE_TEX_STREAM_BUMP (1<<12)
#define ENABLE_TEX_STREAM_BUMP ((1<<12)|(1<<11))
#define TEX_MODIFY_UNIT_0 0
#define TEX_MODIFY_UNIT_1 (1<<8)
#define ENABLE_TEX_STREAM_COORD_SET (1<<7)
#define TEX_STREAM_COORD_SET(x) ((x)<<4)
#define ENABLE_TEX_STREAM_MAP_IDX (1<<3)
#define TEX_STREAM_MAP_IDX(x) (x)
#define MI_FLUSH ((0<<29)|(4<<23))
#define FLUSH_MAP_CACHE (1<<0)
#endif
File diff suppressed because it is too large Load Diff
+325
View File
@@ -0,0 +1,325 @@
/**************************************************************************
*
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
**************************************************************************/
#include "glheader.h"
#include "mtypes.h"
#include "imports.h"
#include "simple_list.h"
#include "enums.h"
#include "image.h"
#include "texstore.h"
#include "texformat.h"
#include "texmem.h"
#include "swrast/swrast.h"
#include "mm.h"
#include "intel_ioctl.h"
#include "i830_context.h"
#include "i830_reg.h"
/**
* Set the texture wrap modes.
*
* The i830M (and related graphics cores) do not support GL_CLAMP. The Intel
* drivers for "other operating systems" implement GL_CLAMP as
* GL_CLAMP_TO_EDGE, so the same is done here.
*
* \param t Texture object whose wrap modes are to be set
* \param swrap Wrap mode for the \a s texture coordinate
* \param twrap Wrap mode for the \a t texture coordinate
*/
static void i830SetTexWrapping(i830TextureObjectPtr tex,
GLenum swrap,
GLenum twrap)
{
tex->Setup[I830_TEXREG_MCS] &= ~(TEXCOORD_ADDR_U_MASK|TEXCOORD_ADDR_V_MASK);
switch( swrap ) {
case GL_REPEAT:
tex->Setup[I830_TEXREG_MCS] |= TEXCOORD_ADDR_U_MODE(TEXCOORDMODE_WRAP);
break;
case GL_CLAMP:
case GL_CLAMP_TO_EDGE:
tex->Setup[I830_TEXREG_MCS] |= TEXCOORD_ADDR_U_MODE(TEXCOORDMODE_CLAMP);
break;
case GL_CLAMP_TO_BORDER:
tex->Setup[I830_TEXREG_MCS] |=
TEXCOORD_ADDR_U_MODE(TEXCOORDMODE_CLAMP_BORDER);
break;
case GL_MIRRORED_REPEAT:
tex->Setup[I830_TEXREG_MCS] |=
TEXCOORD_ADDR_U_MODE(TEXCOORDMODE_MIRROR);
break;
default:
break;
}
switch( twrap ) {
case GL_REPEAT:
tex->Setup[I830_TEXREG_MCS] |= TEXCOORD_ADDR_V_MODE(TEXCOORDMODE_WRAP);
break;
case GL_CLAMP:
case GL_CLAMP_TO_EDGE:
tex->Setup[I830_TEXREG_MCS] |= TEXCOORD_ADDR_V_MODE(TEXCOORDMODE_CLAMP);
break;
case GL_CLAMP_TO_BORDER:
tex->Setup[I830_TEXREG_MCS] |=
TEXCOORD_ADDR_V_MODE(TEXCOORDMODE_CLAMP_BORDER);
break;
case GL_MIRRORED_REPEAT:
tex->Setup[I830_TEXREG_MCS] |=
TEXCOORD_ADDR_V_MODE(TEXCOORDMODE_MIRROR);
break;
default:
break;
}
}
/**
* Set the texture magnification and minification modes.
*
* \param t Texture whose filter modes are to be set
* \param minf Texture minification mode
* \param magf Texture magnification mode
* \param bias LOD bias for this texture unit.
*/
static void i830SetTexFilter( i830TextureObjectPtr t, GLenum minf, GLenum magf,
GLfloat maxanisotropy )
{
int minFilt = 0, mipFilt = 0, magFilt = 0;
if(INTEL_DEBUG&DEBUG_DRI)
fprintf(stderr, "%s\n", __FUNCTION__);
if ( maxanisotropy > 1.0 ) {
minFilt = FILTER_ANISOTROPIC;
magFilt = FILTER_ANISOTROPIC;
}
else {
switch (minf) {
case GL_NEAREST:
minFilt = FILTER_NEAREST;
mipFilt = MIPFILTER_NONE;
break;
case GL_LINEAR:
minFilt = FILTER_LINEAR;
mipFilt = MIPFILTER_NONE;
break;
case GL_NEAREST_MIPMAP_NEAREST:
minFilt = FILTER_NEAREST;
mipFilt = MIPFILTER_NEAREST;
break;
case GL_LINEAR_MIPMAP_NEAREST:
minFilt = FILTER_LINEAR;
mipFilt = MIPFILTER_NEAREST;
break;
case GL_NEAREST_MIPMAP_LINEAR:
minFilt = FILTER_NEAREST;
mipFilt = MIPFILTER_LINEAR;
break;
case GL_LINEAR_MIPMAP_LINEAR:
minFilt = FILTER_LINEAR;
mipFilt = MIPFILTER_LINEAR;
break;
default:
break;
}
switch (magf) {
case GL_NEAREST:
magFilt = FILTER_NEAREST;
break;
case GL_LINEAR:
magFilt = FILTER_LINEAR;
break;
default:
break;
}
}
t->Setup[I830_TEXREG_TM0S3] &= ~TM0S3_MIN_FILTER_MASK;
t->Setup[I830_TEXREG_TM0S3] &= ~TM0S3_MIP_FILTER_MASK;
t->Setup[I830_TEXREG_TM0S3] &= ~TM0S3_MAG_FILTER_MASK;
t->Setup[I830_TEXREG_TM0S3] |= ((minFilt << TM0S3_MIN_FILTER_SHIFT) |
(mipFilt << TM0S3_MIP_FILTER_SHIFT) |
(magFilt << TM0S3_MAG_FILTER_SHIFT));
}
static void i830SetTexBorderColor(i830TextureObjectPtr t, GLubyte color[4])
{
if(INTEL_DEBUG&DEBUG_DRI)
fprintf(stderr, "%s\n", __FUNCTION__);
t->Setup[I830_TEXREG_TM0S4] =
INTEL_PACKCOLOR8888(color[0],color[1],color[2],color[3]);
}
/**
* Allocate space for and load the mesa images into the texture memory block.
* This will happen before drawing with a new texture, or drawing with a
* texture after it was swapped out or teximaged again.
*/
intelTextureObjectPtr i830AllocTexObj( struct gl_texture_object *texObj )
{
i830TextureObjectPtr t = CALLOC_STRUCT( i830_texture_object );
if ( !t )
return NULL;
texObj->DriverData = t;
t->intel.base.tObj = texObj;
t->intel.dirty = I830_UPLOAD_TEX_ALL;
make_empty_list( &t->intel.base );
t->Setup[I830_TEXREG_TM0LI] = 0; /* not used */
t->Setup[I830_TEXREG_TM0S0] = 0;
t->Setup[I830_TEXREG_TM0S1] = 0;
t->Setup[I830_TEXREG_TM0S2] = 0;
t->Setup[I830_TEXREG_TM0S3] = 0;
t->Setup[I830_TEXREG_MCS] = (_3DSTATE_MAP_COORD_SET_CMD |
MAP_UNIT(0) |
ENABLE_TEXCOORD_PARAMS |
TEXCOORDS_ARE_NORMAL |
TEXCOORDTYPE_CARTESIAN |
ENABLE_ADDR_V_CNTL |
TEXCOORD_ADDR_V_MODE(TEXCOORDMODE_WRAP) |
ENABLE_ADDR_U_CNTL |
TEXCOORD_ADDR_U_MODE(TEXCOORDMODE_WRAP));
i830SetTexWrapping( t, texObj->WrapS, texObj->WrapT );
i830SetTexFilter( t, texObj->MinFilter, texObj->MagFilter,
texObj->MaxAnisotropy );
i830SetTexBorderColor( t, texObj->_BorderChan );
return &t->intel;
}
static void i830TexParameter( GLcontext *ctx, GLenum target,
struct gl_texture_object *tObj,
GLenum pname, const GLfloat *params )
{
i830TextureObjectPtr t = (i830TextureObjectPtr) tObj->DriverData;
if (!t)
return;
switch (pname) {
case GL_TEXTURE_MIN_FILTER:
case GL_TEXTURE_MAG_FILTER:
case GL_TEXTURE_MAX_ANISOTROPY_EXT:
i830SetTexFilter( t, tObj->MinFilter, tObj->MagFilter,
tObj->MaxAnisotropy);
break;
case GL_TEXTURE_WRAP_S:
case GL_TEXTURE_WRAP_T:
i830SetTexWrapping( t, tObj->WrapS, tObj->WrapT );
break;
case GL_TEXTURE_BORDER_COLOR:
i830SetTexBorderColor( t, tObj->_BorderChan );
break;
case GL_TEXTURE_BASE_LEVEL:
case GL_TEXTURE_MAX_LEVEL:
case GL_TEXTURE_MIN_LOD:
case GL_TEXTURE_MAX_LOD:
/* The i830 and its successors can do a lot of this without
* reloading the textures. A project for someone?
*/
intelFlush( ctx );
driSwapOutTextureObject( (driTextureObject *) t );
break;
default:
return;
}
t->intel.dirty = I830_UPLOAD_TEX_ALL;
}
static void i830TexEnv( GLcontext *ctx, GLenum target,
GLenum pname, const GLfloat *param )
{
i830ContextPtr i830 = I830_CONTEXT( ctx );
GLuint unit = ctx->Texture.CurrentUnit;
switch (pname) {
case GL_TEXTURE_ENV_COLOR:
#if 0
{
GLubyte r, g, b, a;
GLuint col;
UNCLAMPED_FLOAT_TO_UBYTE(r, param[RCOMP]);
UNCLAMPED_FLOAT_TO_UBYTE(g, param[GCOMP]);
UNCLAMPED_FLOAT_TO_UBYTE(b, param[BCOMP]);
UNCLAMPED_FLOAT_TO_UBYTE(a, param[ACOMP]);
col = ((a << 24) | (r << 16) | (g << 8) | b);
if (col != i830->state.TexEnv[unit][I830_TEXENVREG_COL1]) {
I830_STATECHANGE(i830, I830_UPLOAD_TEXENV);
i830->state.TexEnv[unit][I830_TEXENVREG_COL1] = col;
}
break;
}
#endif
case GL_TEXTURE_ENV_MODE:
case GL_COMBINE_RGB:
case GL_COMBINE_ALPHA:
case GL_SOURCE0_RGB:
case GL_SOURCE1_RGB:
case GL_SOURCE2_RGB:
case GL_SOURCE0_ALPHA:
case GL_SOURCE1_ALPHA:
case GL_SOURCE2_ALPHA:
case GL_OPERAND0_RGB:
case GL_OPERAND1_RGB:
case GL_OPERAND2_RGB:
case GL_OPERAND0_ALPHA:
case GL_OPERAND1_ALPHA:
case GL_OPERAND2_ALPHA:
case GL_RGB_SCALE:
case GL_ALPHA_SCALE:
break;
case GL_TEXTURE_LOD_BIAS: {
int b = (int) ((*param) * 16.0);
if (b > 63) b = 63;
if (b < -64) b = -64;
I830_STATECHANGE(i830, I830_UPLOAD_TEX(unit));
i830->state.Tex[unit][I830_TEXREG_TM0S3] &= ~TM0S3_LOD_BIAS_MASK;
i830->state.Tex[unit][I830_TEXREG_TM0S3] |=
((b << TM0S3_LOD_BIAS_SHIFT) & TM0S3_LOD_BIAS_MASK);
break;
}
default:
break;
}
}
void i830InitTextureFuncs( struct dd_function_table *functions )
{
functions->TexEnv = i830TexEnv;
functions->TexParameter = i830TexParameter;
}
File diff suppressed because it is too large Load Diff
+333
View File
@@ -0,0 +1,333 @@
/**************************************************************************
*
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
**************************************************************************/
#include "glheader.h"
#include "macros.h"
#include "mtypes.h"
#include "simple_list.h"
#include "enums.h"
#include "texformat.h"
#include "texstore.h"
#include "mm.h"
#include "intel_screen.h"
#include "intel_ioctl.h"
#include "intel_tex.h"
#include "i830_context.h"
#include "i830_reg.h"
#define I830_TEX_UNIT_ENABLED(unit) (1<<unit)
static GLboolean i830SetTexImages( i830ContextPtr i830,
struct gl_texture_object *tObj )
{
GLuint total_height, pitch, i, textureFormat;
i830TextureObjectPtr t = (i830TextureObjectPtr) tObj->DriverData;
const struct gl_texture_image *baseImage = tObj->Image[0][tObj->BaseLevel];
GLint firstLevel, lastLevel, numLevels;
switch( baseImage->TexFormat->MesaFormat ) {
case MESA_FORMAT_L8:
t->intel.texelBytes = 1;
textureFormat = MAPSURF_8BIT | MT_8BIT_L8;
break;
case MESA_FORMAT_I8:
t->intel.texelBytes = 1;
textureFormat = MAPSURF_8BIT | MT_8BIT_I8;
break;
case MESA_FORMAT_A8:
t->intel.texelBytes = 1;
textureFormat = MAPSURF_8BIT | MT_8BIT_I8; /* Kludge -- check with conform, glean */
break;
case MESA_FORMAT_AL88:
t->intel.texelBytes = 2;
textureFormat = MAPSURF_16BIT | MT_16BIT_AY88;
break;
case MESA_FORMAT_RGB565:
t->intel.texelBytes = 2;
textureFormat = MAPSURF_16BIT | MT_16BIT_RGB565;
break;
case MESA_FORMAT_ARGB1555:
t->intel.texelBytes = 2;
textureFormat = MAPSURF_16BIT | MT_16BIT_ARGB1555;
break;
case MESA_FORMAT_ARGB4444:
t->intel.texelBytes = 2;
textureFormat = MAPSURF_16BIT | MT_16BIT_ARGB4444;
break;
case MESA_FORMAT_ARGB8888:
t->intel.texelBytes = 4;
textureFormat = MAPSURF_32BIT | MT_32BIT_ARGB8888;
break;
case MESA_FORMAT_YCBCR_REV:
t->intel.texelBytes = 2;
textureFormat = (MAPSURF_422 | MT_422_YCRCB_NORMAL |
TM0S1_COLORSPACE_CONVERSION);
break;
case MESA_FORMAT_YCBCR:
t->intel.texelBytes = 2;
textureFormat = (MAPSURF_422 | MT_422_YCRCB_SWAPY | /* ??? */
TM0S1_COLORSPACE_CONVERSION);
break;
default:
fprintf(stderr, "%s: bad image format\n", __FUNCTION__);
abort();
}
/* Compute which mipmap levels we really want to send to the hardware.
* This depends on the base image size, GL_TEXTURE_MIN_LOD,
* GL_TEXTURE_MAX_LOD, GL_TEXTURE_BASE_LEVEL, and GL_TEXTURE_MAX_LEVEL.
* Yes, this looks overly complicated, but it's all needed.
*/
driCalculateTextureFirstLastLevel( (driTextureObject *) t );
/* Figure out the amount of memory required to hold all the mipmap
* levels. Choose the smallest pitch to accomodate the largest
* mipmap:
*/
firstLevel = t->intel.base.firstLevel;
lastLevel = t->intel.base.lastLevel;
numLevels = lastLevel - firstLevel + 1;
/* Pitch would be subject to additional rules if texture memory were
* tiled. Currently it isn't.
*/
if (0) {
pitch = 128;
while (pitch < tObj->Image[0][firstLevel]->Width * t->intel.texelBytes)
pitch *= 2;
}
else {
pitch = tObj->Image[0][firstLevel]->Width * t->intel.texelBytes;
pitch = (pitch + 3) & ~3;
}
/* All images must be loaded at this pitch. Count the number of
* lines required:
*/
for ( total_height = i = 0 ; i < numLevels ; i++ ) {
t->intel.image[0][i].image = tObj->Image[0][firstLevel + i];
if (!t->intel.image[0][i].image)
break;
t->intel.image[0][i].offset = total_height * pitch;
t->intel.image[0][i].internalFormat = baseImage->Format;
total_height += MAX2(2, t->intel.image[0][i].image->Height);
}
t->intel.Pitch = pitch;
t->intel.base.totalSize = total_height*pitch;
t->intel.max_level = i-1;
t->Setup[I830_TEXREG_TM0S1] =
(((tObj->Image[0][firstLevel]->Height - 1) << TM0S1_HEIGHT_SHIFT) |
((tObj->Image[0][firstLevel]->Width - 1) << TM0S1_WIDTH_SHIFT) |
textureFormat);
t->Setup[I830_TEXREG_TM0S2] =
(((pitch / 4) - 1) << TM0S2_PITCH_SHIFT);
t->Setup[I830_TEXREG_TM0S3] &= ~TM0S3_MAX_MIP_MASK;
t->Setup[I830_TEXREG_TM0S3] &= ~TM0S3_MIN_MIP_MASK;
t->Setup[I830_TEXREG_TM0S3] |= ((numLevels - 1)*4) << TM0S3_MIN_MIP_SHIFT;
t->intel.dirty = I830_UPLOAD_TEX_ALL;
return intelUploadTexImages( &i830->intel, &t->intel, 0 );
}
static void i830_import_tex_unit( i830ContextPtr i830,
i830TextureObjectPtr t,
GLuint unit )
{
if(INTEL_DEBUG&DEBUG_TEXTURE)
fprintf(stderr, "%s unit(%d)\n", __FUNCTION__, unit);
if (i830->intel.CurrentTexObj[unit])
i830->intel.CurrentTexObj[unit]->base.bound &= ~(1U << unit);
i830->intel.CurrentTexObj[unit] = (intelTextureObjectPtr)t;
t->intel.base.bound |= (1 << unit);
I830_STATECHANGE( i830, I830_UPLOAD_TEX(unit) );
i830->state.Tex[unit][I830_TEXREG_TM0LI] = (_3DSTATE_LOAD_STATE_IMMEDIATE_2 |
(LOAD_TEXTURE_MAP0 << unit) | 4);
i830->state.Tex[unit][I830_TEXREG_TM0S0] = (TM0S0_USE_FENCE |
t->intel.TextureOffset);
i830->state.Tex[unit][I830_TEXREG_TM0S1] = t->Setup[I830_TEXREG_TM0S1];
i830->state.Tex[unit][I830_TEXREG_TM0S2] = t->Setup[I830_TEXREG_TM0S2];
i830->state.Tex[unit][I830_TEXREG_TM0S3] &= TM0S3_LOD_BIAS_MASK;
i830->state.Tex[unit][I830_TEXREG_TM0S3] |= (t->Setup[I830_TEXREG_TM0S3] &
~TM0S3_LOD_BIAS_MASK);
i830->state.Tex[unit][I830_TEXREG_TM0S4] = t->Setup[I830_TEXREG_TM0S4];
i830->state.Tex[unit][I830_TEXREG_MCS] = (t->Setup[I830_TEXREG_MCS] &
~MAP_UNIT_MASK);
i830->state.Tex[unit][I830_TEXREG_MCS] |= MAP_UNIT(unit);
t->intel.dirty &= ~I830_UPLOAD_TEX(unit);
}
static GLboolean enable_tex_common( GLcontext *ctx, GLuint unit )
{
i830ContextPtr i830 = I830_CONTEXT(ctx);
struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
struct gl_texture_object *tObj = texUnit->_Current;
i830TextureObjectPtr t = (i830TextureObjectPtr)tObj->DriverData;
if (0) fprintf(stderr, "%s\n", __FUNCTION__);
/* Fallback if there's a texture border */
if ( tObj->Image[0][tObj->BaseLevel]->Border > 0 ) {
fprintf(stderr, "Texture border\n");
return GL_FALSE;
}
/* Upload teximages (not pipelined)
*/
if (t->intel.base.dirty_images[0]) {
if (!i830SetTexImages( i830, tObj )) {
return GL_FALSE;
}
}
/* Update state if this is a different texture object to last
* time.
*/
if (i830->intel.CurrentTexObj[unit] != &t->intel ||
(t->intel.dirty & I830_UPLOAD_TEX(unit))) {
i830_import_tex_unit( i830, t, unit);
}
I830_ACTIVESTATE(i830, I830_UPLOAD_TEX(unit), GL_TRUE);
return GL_TRUE;
}
static GLboolean enable_tex_rect( GLcontext *ctx, GLuint unit )
{
i830ContextPtr i830 = I830_CONTEXT(ctx);
GLuint mcs = i830->state.Tex[unit][I830_TEXREG_MCS];
mcs &= ~TEXCOORDS_ARE_NORMAL;
mcs |= TEXCOORDS_ARE_IN_TEXELUNITS;
if (mcs != i830->state.Tex[unit][I830_TEXREG_MCS]) {
I830_STATECHANGE(i830, I830_UPLOAD_TEX(unit));
i830->state.Tex[unit][I830_TEXREG_MCS] = mcs;
}
return GL_TRUE;
}
static GLboolean enable_tex_2d( GLcontext *ctx, GLuint unit )
{
i830ContextPtr i830 = I830_CONTEXT(ctx);
GLuint mcs = i830->state.Tex[unit][I830_TEXREG_MCS];
mcs &= ~TEXCOORDS_ARE_IN_TEXELUNITS;
mcs |= TEXCOORDS_ARE_NORMAL;
if (mcs != i830->state.Tex[unit][I830_TEXREG_MCS]) {
I830_STATECHANGE(i830, I830_UPLOAD_TEX(unit));
i830->state.Tex[unit][I830_TEXREG_MCS] = mcs;
}
return GL_TRUE;
}
static GLboolean disable_tex( GLcontext *ctx, GLuint unit )
{
i830ContextPtr i830 = I830_CONTEXT(ctx);
/* This is happening too often. I need to conditionally send diffuse
* state to the card. Perhaps a diffuse dirty flag of some kind.
* Will need to change this logic if more than 2 texture units are
* used. We need to only do this up to the last unit enabled, or unit
* one if nothing is enabled.
*/
if ( i830->intel.CurrentTexObj[unit] != NULL ) {
/* The old texture is no longer bound to this texture unit.
* Mark it as such.
*/
i830->intel.CurrentTexObj[unit]->base.bound &= ~(1U << 0);
i830->intel.CurrentTexObj[unit] = NULL;
}
return GL_TRUE;
}
static GLboolean i830UpdateTexUnit( GLcontext *ctx, GLuint unit )
{
struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
if (texUnit->_ReallyEnabled &&
INTEL_CONTEXT(ctx)->intelScreen->textureSize < 2048 * 1024)
return GL_FALSE;
if (texUnit->_ReallyEnabled == TEXTURE_1D_BIT ||
texUnit->_ReallyEnabled == TEXTURE_2D_BIT) {
return (enable_tex_common( ctx, unit ) &&
enable_tex_2d( ctx, unit ));
}
else if (texUnit->_ReallyEnabled == TEXTURE_RECT_BIT) {
return (enable_tex_common( ctx, unit ) &&
enable_tex_rect( ctx, unit ));
}
else if (texUnit->_ReallyEnabled) {
return GL_FALSE;
}
else {
return disable_tex( ctx, unit );
}
}
void i830UpdateTextureState( intelContextPtr intel )
{
i830ContextPtr i830 = I830_CONTEXT(intel);
GLcontext *ctx = &intel->ctx;
GLboolean ok;
if (0) fprintf(stderr, "%s\n", __FUNCTION__);
I830_ACTIVESTATE(i830, I830_UPLOAD_TEX_ALL, GL_FALSE);
ok = (i830UpdateTexUnit( ctx, 0 ) &&
i830UpdateTexUnit( ctx, 1 ) &&
i830UpdateTexUnit( ctx, 2 ) &&
i830UpdateTexUnit( ctx, 3 ));
FALLBACK( intel, I830_FALLBACK_TEXTURE, !ok );
if (ok)
i830EmitTextureBlend( i830 );
}
+426
View File
@@ -0,0 +1,426 @@
/**************************************************************************
*
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
**************************************************************************/
#include "i830_context.h"
#include "i830_reg.h"
#include "intel_batchbuffer.h"
#include "tnl/t_context.h"
#include "tnl/t_vertex.h"
static GLboolean i830_check_vertex_size( intelContextPtr intel,
GLuint expected );
#define SZ_TO_HW(sz) ((sz-2)&0x3)
#define EMIT_SZ(sz) (EMIT_1F + (sz) - 1)
#define EMIT_ATTR( ATTR, STYLE, V0 ) \
do { \
intel->vertex_attrs[intel->vertex_attr_count].attrib = (ATTR); \
intel->vertex_attrs[intel->vertex_attr_count].format = (STYLE); \
intel->vertex_attr_count++; \
v0 |= V0; \
} while (0)
#define EMIT_PAD( N ) \
do { \
intel->vertex_attrs[intel->vertex_attr_count].attrib = 0; \
intel->vertex_attrs[intel->vertex_attr_count].format = EMIT_PAD; \
intel->vertex_attrs[intel->vertex_attr_count].offset = (N); \
intel->vertex_attr_count++; \
} while (0)
#define VRTX_TEX_SET_FMT(n, x) ((x)<<((n)*2))
#define TEXBIND_SET(n, x) ((x)<<((n)*4))
static void i830_render_start( intelContextPtr intel )
{
GLcontext *ctx = &intel->ctx;
i830ContextPtr i830 = I830_CONTEXT(intel);
TNLcontext *tnl = TNL_CONTEXT(ctx);
struct vertex_buffer *VB = &tnl->vb;
GLuint index = tnl->render_inputs;
GLuint v0 = _3DSTATE_VFT0_CMD;
GLuint v2 = _3DSTATE_VFT1_CMD;
GLuint mcsb1 = 0;
/* Important:
*/
VB->AttribPtr[VERT_ATTRIB_POS] = VB->NdcPtr;
intel->vertex_attr_count = 0;
/* EMIT_ATTR's must be in order as they tell t_vertex.c how to
* build up a hardware vertex.
*/
if (index & _TNL_BITS_TEX_ANY) {
EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_4F_VIEWPORT, VFT0_XYZW );
intel->coloroffset = 4;
}
else {
EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_3F_VIEWPORT, VFT0_XYZ );
intel->coloroffset = 3;
}
EMIT_ATTR( _TNL_ATTRIB_COLOR0, EMIT_4UB_4F_RGBA, VFT0_DIFFUSE );
intel->specoffset = 0;
if (index & (_TNL_BIT_COLOR1|_TNL_BIT_FOG)) {
if (index & _TNL_BIT_COLOR1) {
intel->specoffset = intel->coloroffset + 1;
EMIT_ATTR( _TNL_ATTRIB_COLOR1, EMIT_3UB_3F_RGB, VFT0_SPEC );
}
else
EMIT_PAD( 3 );
if (index & _TNL_BIT_FOG)
EMIT_ATTR( _TNL_ATTRIB_FOG, EMIT_1UB_1F, VFT0_SPEC );
else
EMIT_PAD( 1 );
}
if (index & _TNL_BITS_TEX_ANY) {
int i, count = 0;
for (i = 0; i < I830_TEX_UNITS; i++) {
if (index & _TNL_BIT_TEX(i)) {
GLuint sz = VB->TexCoordPtr[i]->size;
GLuint emit;
GLuint mcs = (i830->state.Tex[i][I830_TEXREG_MCS] &
~TEXCOORDTYPE_MASK);
switch (sz) {
case 1:
case 2:
case 3: /* XXX: fix for CUBE/VOLUME textures */
emit = EMIT_2F;
sz = 2;
mcs |= TEXCOORDTYPE_CARTESIAN;
break;
case 4:
emit = EMIT_3F_XYW;
sz = 3;
mcs |= TEXCOORDTYPE_HOMOGENEOUS;
break;
default:
continue;
};
EMIT_ATTR( _TNL_ATTRIB_TEX0+i, emit, 0 );
v2 |= VRTX_TEX_SET_FMT(count, SZ_TO_HW(sz));
mcsb1 |= (count+8)<<(i*4);
if (mcs != i830->state.Tex[i][I830_TEXREG_MCS]) {
I830_STATECHANGE(i830, I830_UPLOAD_TEX(i));
i830->state.Tex[i][I830_TEXREG_MCS] = mcs;
}
count++;
}
}
v0 |= VFT0_TEX_COUNT(count);
}
/* Only need to change the vertex emit code if there has been a
* statechange to a new hardware vertex format:
*/
if (v0 != i830->state.Ctx[I830_CTXREG_VF] ||
v2 != i830->state.Ctx[I830_CTXREG_VF2] ||
mcsb1 != i830->state.Ctx[I830_CTXREG_MCSB1] ||
index != i830->last_index) {
I830_STATECHANGE( i830, I830_UPLOAD_CTX );
/* Must do this *after* statechange, so as not to affect
* buffered vertices reliant on the old state:
*/
intel->vertex_size =
_tnl_install_attrs( ctx,
intel->vertex_attrs,
intel->vertex_attr_count,
intel->ViewportMatrix.m, 0 );
intel->vertex_size >>= 2;
i830->state.Ctx[I830_CTXREG_VF] = v0;
i830->state.Ctx[I830_CTXREG_VF2] = v2;
i830->state.Ctx[I830_CTXREG_MCSB1] = mcsb1;
i830->last_index = index;
assert(i830_check_vertex_size( intel, intel->vertex_size ));
}
}
static void i830_reduced_primitive_state( intelContextPtr intel,
GLenum rprim )
{
i830ContextPtr i830 = I830_CONTEXT(intel);
GLuint st1 = i830->state.Stipple[I830_STPREG_ST1];
st1 &= ~ST1_ENABLE;
switch (rprim) {
case GL_TRIANGLES:
if (intel->ctx.Polygon.StippleFlag &&
intel->hw_stipple)
st1 |= ST1_ENABLE;
break;
case GL_LINES:
case GL_POINTS:
default:
break;
}
i830->intel.reduced_primitive = rprim;
if (st1 != i830->state.Stipple[I830_STPREG_ST1]) {
I830_STATECHANGE(i830, I830_UPLOAD_STIPPLE);
i830->state.Stipple[I830_STPREG_ST1] = st1;
}
}
/* Pull apart the vertex format registers and figure out how large a
* vertex is supposed to be.
*/
static GLboolean i830_check_vertex_size( intelContextPtr intel,
GLuint expected )
{
i830ContextPtr i830 = I830_CONTEXT(intel);
int vft0 = i830->current->Ctx[I830_CTXREG_VF];
int vft1 = i830->current->Ctx[I830_CTXREG_VF2];
int nrtex = (vft0 & VFT0_TEX_COUNT_MASK) >> VFT0_TEX_COUNT_SHIFT;
int i, sz = 0;
switch (vft0 & VFT0_XYZW_MASK) {
case VFT0_XY: sz = 2; break;
case VFT0_XYZ: sz = 3; break;
case VFT0_XYW: sz = 3; break;
case VFT0_XYZW: sz = 4; break;
default:
fprintf(stderr, "no xyzw specified\n");
return 0;
}
if (vft0 & VFT0_SPEC) sz++;
if (vft0 & VFT0_DIFFUSE) sz++;
if (vft0 & VFT0_DEPTH_OFFSET) sz++;
if (vft0 & VFT0_POINT_WIDTH) sz++;
for (i = 0 ; i < nrtex ; i++) {
switch (vft1 & VFT1_TEX0_MASK) {
case TEXCOORDFMT_2D: sz += 2; break;
case TEXCOORDFMT_3D: sz += 3; break;
case TEXCOORDFMT_4D: sz += 4; break;
case TEXCOORDFMT_1D: sz += 1; break;
}
vft1 >>= VFT1_TEX1_SHIFT;
}
if (sz != expected)
fprintf(stderr, "vertex size mismatch %d/%d\n", sz, expected);
return sz == expected;
}
static void i830_emit_invarient_state( intelContextPtr intel )
{
BATCH_LOCALS;
BEGIN_BATCH( 200 );
OUT_BATCH(_3DSTATE_MAP_CUBE | MAP_UNIT(0));
OUT_BATCH(_3DSTATE_MAP_CUBE | MAP_UNIT(1));
OUT_BATCH(_3DSTATE_MAP_CUBE | MAP_UNIT(2));
OUT_BATCH(_3DSTATE_MAP_CUBE | MAP_UNIT(3));
OUT_BATCH(_3DSTATE_DFLT_DIFFUSE_CMD);
OUT_BATCH(0);
OUT_BATCH(_3DSTATE_DFLT_SPEC_CMD);
OUT_BATCH(0);
OUT_BATCH(_3DSTATE_DFLT_Z_CMD);
OUT_BATCH(0);
OUT_BATCH(_3DSTATE_FOG_MODE_CMD);
OUT_BATCH(FOGFUNC_ENABLE |
FOG_LINEAR_CONST |
FOGSRC_INDEX_Z |
ENABLE_FOG_DENSITY);
OUT_BATCH(0);
OUT_BATCH(0);
OUT_BATCH(_3DSTATE_MAP_TEX_STREAM_CMD |
MAP_UNIT(0) |
DISABLE_TEX_STREAM_BUMP |
ENABLE_TEX_STREAM_COORD_SET |
TEX_STREAM_COORD_SET(0) |
ENABLE_TEX_STREAM_MAP_IDX | TEX_STREAM_MAP_IDX(0));
OUT_BATCH(_3DSTATE_MAP_TEX_STREAM_CMD |
MAP_UNIT(1) |
DISABLE_TEX_STREAM_BUMP |
ENABLE_TEX_STREAM_COORD_SET |
TEX_STREAM_COORD_SET(1) |
ENABLE_TEX_STREAM_MAP_IDX | TEX_STREAM_MAP_IDX(1));
OUT_BATCH(_3DSTATE_MAP_TEX_STREAM_CMD |
MAP_UNIT(2) |
DISABLE_TEX_STREAM_BUMP |
ENABLE_TEX_STREAM_COORD_SET |
TEX_STREAM_COORD_SET(2) |
ENABLE_TEX_STREAM_MAP_IDX | TEX_STREAM_MAP_IDX(2));
OUT_BATCH(_3DSTATE_MAP_TEX_STREAM_CMD |
MAP_UNIT(3) |
DISABLE_TEX_STREAM_BUMP |
ENABLE_TEX_STREAM_COORD_SET |
TEX_STREAM_COORD_SET(3) |
ENABLE_TEX_STREAM_MAP_IDX | TEX_STREAM_MAP_IDX(3));
OUT_BATCH(_3DSTATE_MAP_COORD_TRANSFORM);
OUT_BATCH(DISABLE_TEX_TRANSFORM | TEXTURE_SET(0));
OUT_BATCH(_3DSTATE_MAP_COORD_TRANSFORM);
OUT_BATCH(DISABLE_TEX_TRANSFORM | TEXTURE_SET(1));
OUT_BATCH(_3DSTATE_MAP_COORD_TRANSFORM);
OUT_BATCH(DISABLE_TEX_TRANSFORM | TEXTURE_SET(2));
OUT_BATCH(_3DSTATE_MAP_COORD_TRANSFORM);
OUT_BATCH(DISABLE_TEX_TRANSFORM | TEXTURE_SET(3));
OUT_BATCH(_3DSTATE_RASTER_RULES_CMD |
ENABLE_POINT_RASTER_RULE |
OGL_POINT_RASTER_RULE |
ENABLE_LINE_STRIP_PROVOKE_VRTX |
ENABLE_TRI_FAN_PROVOKE_VRTX |
ENABLE_TRI_STRIP_PROVOKE_VRTX |
LINE_STRIP_PROVOKE_VRTX(1) |
TRI_FAN_PROVOKE_VRTX(2) |
TRI_STRIP_PROVOKE_VRTX(2));
OUT_BATCH(_3DSTATE_SCISSOR_ENABLE_CMD |
DISABLE_SCISSOR_RECT);
OUT_BATCH(_3DSTATE_SCISSOR_RECT_0_CMD);
OUT_BATCH(0);
OUT_BATCH(0);
OUT_BATCH(_3DSTATE_VERTEX_TRANSFORM);
OUT_BATCH(DISABLE_VIEWPORT_TRANSFORM | DISABLE_PERSPECTIVE_DIVIDE);
OUT_BATCH(_3DSTATE_W_STATE_CMD);
OUT_BATCH(MAGIC_W_STATE_DWORD1);
OUT_BATCH(0x3f800000 /* 1.0 in IEEE float */ );
OUT_BATCH(_3DSTATE_COLOR_FACTOR_CMD);
OUT_BATCH(0x80808080); /* .5 required in alpha for GL_DOT3_RGBA_EXT */
ADVANCE_BATCH();
}
#define emit( intel, state, size ) \
do { \
int k; \
BEGIN_BATCH( size / sizeof(GLuint)); \
for (k = 0 ; k < size / sizeof(GLuint) ; k++) \
OUT_BATCH(state[k]); \
ADVANCE_BATCH(); \
} while (0);
/* Push the state into the sarea and/or texture memory.
*/
static void i830_emit_state( intelContextPtr intel )
{
i830ContextPtr i830 = I830_CONTEXT(intel);
struct i830_hw_state *state = i830->current;
BATCH_LOCALS;
int i;
GLuint dirty = state->active & ~state->emitted;
if (dirty & I830_UPLOAD_CTX) {
if (VERBOSE) fprintf(stderr, "I830_UPLOAD_CTX:\n");
emit( i830, state->Ctx, sizeof(state->Ctx) );
}
if (dirty & I830_UPLOAD_BUFFERS) {
if (VERBOSE) fprintf(stderr, "I830_UPLOAD_BUFFERS:\n");
emit( i830, state->Buffer, sizeof(state->Buffer) );
}
if (dirty & I830_UPLOAD_STIPPLE) {
if (VERBOSE) fprintf(stderr, "I830_UPLOAD_STIPPLE:\n");
emit( i830, state->Stipple, sizeof(state->Stipple) );
}
for (i = 0; i < I830_TEX_UNITS; i++) {
if ((dirty & I830_UPLOAD_TEX(i))) {
if (VERBOSE) fprintf(stderr, "I830_UPLOAD_TEX(%d):\n", i);
emit( i830, state->Tex[i], sizeof(state->Tex[i]));
}
if (dirty & I830_UPLOAD_TEXBLEND(i)) {
if (VERBOSE) fprintf(stderr, "I830_UPLOAD_TEXBLEND(%d):\n", i);
emit( i830, state->TexBlend[i],
state->TexBlendWordsUsed[i] * 4 );
}
}
state->emitted |= dirty;
}
static void i830_destroy_context( intelContextPtr intel )
{
_tnl_free_vertices(&intel->ctx);
}
static void i830_set_draw_offset( intelContextPtr intel, int offset )
{
i830ContextPtr i830 = I830_CONTEXT(intel);
I830_STATECHANGE( i830, I830_UPLOAD_BUFFERS );
i830->state.Buffer[I830_DESTREG_CBUFADDR2] = offset;
}
/* This isn't really handled at the moment.
*/
static void i830_lost_hardware( intelContextPtr intel )
{
I830_CONTEXT(intel)->state.emitted = 0;
}
static void i830_emit_flush( intelContextPtr intel )
{
BATCH_LOCALS;
BEGIN_BATCH(2);
OUT_BATCH( MI_FLUSH | FLUSH_MAP_CACHE );
OUT_BATCH( 0 );
ADVANCE_BATCH();
}
void i830InitVtbl( i830ContextPtr i830 )
{
i830->intel.vtbl.alloc_tex_obj = i830AllocTexObj;
i830->intel.vtbl.check_vertex_size = i830_check_vertex_size;
i830->intel.vtbl.clear_with_tris = i830ClearWithTris;
i830->intel.vtbl.destroy = i830_destroy_context;
i830->intel.vtbl.emit_invarient_state = i830_emit_invarient_state;
i830->intel.vtbl.emit_state = i830_emit_state;
i830->intel.vtbl.lost_hardware = i830_lost_hardware;
i830->intel.vtbl.reduced_primitive_state = i830_reduced_primitive_state;
i830->intel.vtbl.set_draw_offset = i830_set_draw_offset;
i830->intel.vtbl.update_texture_state = i830UpdateTextureState;
i830->intel.vtbl.emit_flush = i830_emit_flush;
i830->intel.vtbl.render_start = i830_render_start;
}
+211
View File
@@ -0,0 +1,211 @@
/**************************************************************************
*
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
**************************************************************************/
#include "i915_context.h"
#include "imports.h"
#include "intel_tex.h"
#include "intel_tris.h"
#include "tnl/t_context.h"
#include "tnl/t_pipeline.h"
#include "tnl/t_vertex.h"
#include "swrast/swrast.h"
#include "swrast_setup/swrast_setup.h"
#include "tnl/tnl.h"
#include "array_cache/acache.h"
#include "utils.h"
#include "i915_reg.h"
/***************************************
* Mesa's Driver Functions
***************************************/
static const char * const card_extensions[] =
{
"GL_ARB_fragment_program",
"GL_ARB_texture_cube_map",
"GL_EXT_blend_equation_separate",
"GL_ATI_blend_equation_separate",
"GL_ARB_point_parameters",
NULL
};
/* Override intel default.
*/
static void i915InvalidateState( GLcontext *ctx, GLuint new_state )
{
_swrast_InvalidateState( ctx, new_state );
_swsetup_InvalidateState( ctx, new_state );
_ac_InvalidateState( ctx, new_state );
_tnl_InvalidateState( ctx, new_state );
_tnl_invalidate_vertex_state( ctx, new_state );
INTEL_CONTEXT(ctx)->NewGLState |= new_state;
/* Todo: gather state values under which tracked parameters become
* invalidated, add callbacks for things like
* ProgramLocalParameters, etc.
*/
{
struct i915_fragment_program *p =
(struct i915_fragment_program *)ctx->FragmentProgram.Current;
if (p->nr_params)
p->params_uptodate = 0;
}
}
/* This is the extension list explicitly enabled by the client and
* excludes functionality available in Mesa and also excludes legacy
* extensions. It is recognized that in an open source driver, those
* extensions will probably be re-enabled.
*/
static const GLubyte *i915GetString( GLcontext *ctx, GLenum name )
{
if (name == GL_EXTENSIONS)
return
"GL_ARB_fragment_program "
"GL_ARB_multitexture "
"GL_ARB_point_parameters "
"GL_ARB_texture_border_clamp "
"GL_ARB_texture_compression "
"GL_ARB_texture_cube_map "
"GL_ARB_texture_env_add "
"GL_ARB_texture_env_combine "
"GL_ARB_texture_env_dot3 "
"GL_ARB_texture_mirrored_repeat "
"GL_ARB_transpose_matrix "
"GL_ARB_vertex_buffer_object "
"GL_ARB_vertex_program "
"GL_ARB_window_pos "
"GL_EXT_abgr "
"GL_EXT_bgra "
"GL_EXT_blend_color "
"GL_EXT_blend_func_separate "
"GL_EXT_blend_minmax "
"GL_EXT_blend_subtract "
"GL_EXT_clip_volume_hint "
"GL_EXT_compiled_vertex_array "
"GL_EXT_draw_range_elements "
"GL_EXT_fog_coord "
"GL_EXT_multi_draw_arrays "
"GL_EXT_packed_pixels "
"GL_EXT_rescale_normal "
"GL_EXT_secondary_color "
"GL_EXT_separate_specular_color "
"GL_EXT_stencil_wrap "
"GL_EXT_texture3D "
"GL_EXT_texture_env_add "
"GL_EXT_texture_env_combine "
"GL_EXT_texture_filter_anisotropic "
"GL_IBM_texture_mirrored_repeat "
"GL_MESA_ycbcr_texture "
"GL_MESA_window_pos "
"GL_NV_texgen_reflection "
"GL_SGIS_generate_mipmap";
return intelGetString( ctx, name );
}
static void i915InitDriverFunctions( struct dd_function_table *functions )
{
intelInitDriverFunctions( functions );
i915InitStateFunctions( functions );
i915InitTextureFuncs( functions );
i915InitFragProgFuncs( functions );
functions->UpdateState = i915InvalidateState;
functions->GetString = i915GetString;
}
GLboolean i915CreateContext( const __GLcontextModes *mesaVis,
__DRIcontextPrivate *driContextPriv,
void *sharedContextPrivate)
{
struct dd_function_table functions;
i915ContextPtr i915 = (i915ContextPtr) CALLOC_STRUCT(i915_context);
intelContextPtr intel = &i915->intel;
GLcontext *ctx = &intel->ctx;
if (!i915) return GL_FALSE;
i915InitVtbl( i915 );
i915InitDriverFunctions( &functions );
if (!intelInitContext( intel, mesaVis, driContextPriv,
sharedContextPrivate, &functions )) {
FREE(i915);
return GL_FALSE;
}
ctx->Const.MaxTextureUnits = I915_TEX_UNITS;
ctx->Const.MaxTextureImageUnits = I915_TEX_UNITS;
ctx->Const.MaxTextureCoordUnits = I915_TEX_UNITS;
intel->nr_heaps = 1;
intel->texture_heaps[0] =
driCreateTextureHeap( 0, intel,
intel->intelScreen->textureSize,
12,
I830_NR_TEX_REGIONS,
intel->sarea->texList,
& intel->sarea->texAge,
& intel->swapped,
sizeof( struct i915_texture_object ),
(destroy_texture_object_t *)intelDestroyTexObj );
/* FIXME: driCalculateMaxTextureLevels assumes that mipmaps are tightly
* FIXME: packed, but they're not in Intel graphics hardware.
*/
ctx->Const.MaxTextureUnits = 1;
driCalculateMaxTextureLevels( intel->texture_heaps,
intel->nr_heaps,
&intel->ctx.Const,
4,
11, /* max 2D texture size is 2048x2048 */
8, /* 3D texture */
11, /* cube texture. */
0, /* max RECT. supported, but not enabled */
12,
GL_FALSE );
ctx->Const.MaxTextureUnits = I915_TEX_UNITS;
/* GL_ARB_fragment_program limits - don't think Mesa actually
* validates programs against these, and in any case one ARB
* instruction can translate to more than one HW instruction, so
* we'll still have to check and fallback each time.
*/
ctx->Const.MaxFragmentProgramTemps = I915_MAX_TEMPORARY;
ctx->Const.MaxFragmentProgramAttribs = 11; /* 8 tex, 2 color, fog */
ctx->Const.MaxFragmentProgramLocalParams = I915_MAX_CONSTANT;
ctx->Const.MaxFragmentProgramEnvParams = I915_MAX_CONSTANT;
ctx->Const.MaxFragmentProgramAluInstructions = I915_MAX_ALU_INSN;
ctx->Const.MaxFragmentProgramTexInstructions = I915_MAX_TEX_INSN;
ctx->Const.MaxFragmentProgramInstructions = (I915_MAX_ALU_INSN +
I915_MAX_TEX_INSN);
ctx->Const.MaxFragmentProgramTexIndirections = I915_MAX_TEX_INDIRECT;
ctx->Const.MaxFragmentProgramAddressRegs = 0; /* I don't think we have one */
driInitExtensions( ctx, card_extensions, GL_FALSE );
_tnl_init_vertices( ctx, ctx->Const.MaxArrayLockSize + 12,
36 * sizeof(GLfloat) );
intel->verts = TNL_CONTEXT(ctx)->clipspace.vertex_buf;
i915InitState( i915 );
return GL_TRUE;
}
+330
View File
@@ -0,0 +1,330 @@
/**************************************************************************
*
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
**************************************************************************/
#ifndef I915CONTEXT_INC
#define I915CONTEXT_INC
#include "intel_context.h"
#define I915_FALLBACK_TEXTURE 0x1000
#define I915_FALLBACK_COLORMASK 0x2000
#define I915_FALLBACK_STENCIL 0x4000
#define I915_FALLBACK_STIPPLE 0x8000
#define I915_FALLBACK_PROGRAM 0x10000
#define I915_FALLBACK_LOGICOP 0x20000
#define I915_UPLOAD_CTX 0x1
#define I915_UPLOAD_BUFFERS 0x2
#define I915_UPLOAD_STIPPLE 0x4
#define I915_UPLOAD_PROGRAM 0x8
#define I915_UPLOAD_CONSTANTS 0x10
#define I915_UPLOAD_FOG 0x20
#define I915_UPLOAD_TEX(i) (0x00010000<<(i))
#define I915_UPLOAD_TEX_ALL (0x00ff0000)
#define I915_UPLOAD_TEX_0_SHIFT 16
/* State structure offsets - these will probably disappear.
*/
#define I915_DESTREG_CBUFADDR0 0
#define I915_DESTREG_CBUFADDR1 1
#define I915_DESTREG_CBUFADDR2 2
#define I915_DESTREG_DBUFADDR0 3
#define I915_DESTREG_DBUFADDR1 4
#define I915_DESTREG_DBUFADDR2 5
#define I915_DESTREG_DV0 6
#define I915_DESTREG_DV1 7
#define I915_DESTREG_SENABLE 8
#define I915_DESTREG_SR0 9
#define I915_DESTREG_SR1 10
#define I915_DESTREG_SR2 11
#define I915_DEST_SETUP_SIZE 12
#define I915_CTXREG_STATE4 0
#define I915_CTXREG_LI 1
#define I915_CTXREG_LIS2 2
#define I915_CTXREG_LIS4 3
#define I915_CTXREG_LIS5 4
#define I915_CTXREG_LIS6 5
#define I915_CTXREG_IAB 6
#define I915_CTXREG_BLENDCOLOR0 7
#define I915_CTXREG_BLENDCOLOR1 8
#define I915_CTX_SETUP_SIZE 9
#define I915_FOGREG_COLOR 0
#define I915_FOGREG_MODE0 1
#define I915_FOGREG_MODE1 2
#define I915_FOGREG_MODE2 3
#define I915_FOGREG_MODE3 4
#define I915_FOG_SETUP_SIZE 5
#define I915_STPREG_ST0 0
#define I915_STPREG_ST1 1
#define I915_STP_SETUP_SIZE 2
#define I915_TEXREG_MS2 0
#define I915_TEXREG_MS3 1
#define I915_TEXREG_MS4 2
#define I915_TEXREG_SS2 3
#define I915_TEXREG_SS3 4
#define I915_TEXREG_SS4 5
#define I915_TEX_SETUP_SIZE 6
#define I915_MAX_CONSTANT 32
#define I915_CONSTANT_SIZE (2+(4*I915_MAX_CONSTANT))
#define I915_PROGRAM_SIZE 192
/* Hardware version of a parsed fragment program. "Derived" from the
* mesa fragment_program struct.
*/
struct i915_fragment_program {
struct fragment_program FragProg;
GLboolean translated;
GLboolean params_uptodate;
GLboolean on_hardware;
GLboolean error; /* If program is malformed for any reason. */
GLuint nr_tex_indirect;
GLuint nr_tex_insn;
GLuint nr_alu_insn;
GLuint nr_decl_insn;
/* TODO: split between the stored representation of a program and
* the state used to build that representation.
*/
GLcontext *ctx;
GLuint declarations[I915_PROGRAM_SIZE];
GLuint program[I915_PROGRAM_SIZE];
GLfloat constant[I915_MAX_CONSTANT][4];
GLuint constant_flags[I915_MAX_CONSTANT];
GLuint nr_constants;
GLuint *csr; /* Cursor, points into program.
*/
GLuint *decl; /* Cursor, points into declarations.
*/
GLuint decl_s; /* flags for which s regs need to be decl'd */
GLuint decl_t; /* flags for which t regs need to be decl'd */
GLuint temp_flag; /* Tracks temporary regs which are in
* use.
*/
GLuint utemp_flag; /* Tracks TYPE_U temporary regs which are in
* use.
*/
/* Helpers for i915_fragprog.c:
*/
GLuint wpos_tex;
GLboolean depth_written;
struct {
GLuint reg; /* Hardware constant idx */
const GLfloat *values; /* Pointer to tracked values */
} param[I915_MAX_CONSTANT];
GLuint nr_params;
/* Helpers for i915_texprog.c:
*/
GLuint src_texture; /* Reg containing sampled texture color,
* else UREG_BAD.
*/
GLuint src_previous; /* Reg containing color from previous
* stage. May need to be decl'd.
*/
GLuint last_tex_stage; /* Number of last enabled texture unit */
struct vertex_buffer *VB;
};
struct i915_texture_object
{
struct intel_texture_object intel;
GLenum lastTarget;
GLboolean refs_border_color;
GLuint Setup[I915_TEX_SETUP_SIZE];
};
#define I915_TEX_UNITS 8
struct i915_hw_state {
GLuint Ctx[I915_CTX_SETUP_SIZE];
GLuint Buffer[I915_DEST_SETUP_SIZE];
GLuint Stipple[I915_STP_SETUP_SIZE];
GLuint Fog[I915_FOG_SETUP_SIZE];
GLuint Tex[I915_TEX_UNITS][I915_TEX_SETUP_SIZE];
GLuint Constant[I915_CONSTANT_SIZE];
GLuint ConstantSize;
GLuint Program[I915_PROGRAM_SIZE];
GLuint ProgramSize;
GLuint active; /* I915_UPLOAD_* */
GLuint emitted; /* I915_UPLOAD_* */
};
#define I915_FOG_PIXEL 2
#define I915_FOG_VERTEX 1
#define I915_FOG_NONE 0
struct i915_context
{
struct intel_context intel;
GLuint last_ReallyEnabled;
GLuint vertex_fog;
struct i915_fragment_program tex_program;
struct i915_fragment_program *current_program;
struct i915_hw_state meta, initial, state, *current;
};
typedef struct i915_context *i915ContextPtr;
typedef struct i915_texture_object *i915TextureObjectPtr;
#define I915_CONTEXT(ctx) ((i915ContextPtr)(ctx))
#define I915_STATECHANGE(i915, flag) \
do { \
if (0) fprintf(stderr, "I915_STATECHANGE %x in %s\n", flag, __FUNCTION__); \
INTEL_FIREVERTICES( &(i915)->intel ); \
(i915)->state.emitted &= ~(flag); \
} while (0)
#define I915_ACTIVESTATE(i915, flag, mode) \
do { \
if (0) fprintf(stderr, "I915_ACTIVESTATE %x %d in %s\n", \
flag, mode, __FUNCTION__); \
INTEL_FIREVERTICES( &(i915)->intel ); \
if (mode) \
(i915)->state.active |= (flag); \
else \
(i915)->state.active &= ~(flag); \
} while (0)
/*======================================================================
* i915_vtbl.c
*/
extern void i915InitVtbl( i915ContextPtr i915 );
#define SZ_TO_HW(sz) ((sz-2)&0x3)
#define EMIT_SZ(sz) (EMIT_1F + (sz) - 1)
#define EMIT_ATTR( ATTR, STYLE, S4, SZ ) \
do { \
intel->vertex_attrs[intel->vertex_attr_count].attrib = (ATTR); \
intel->vertex_attrs[intel->vertex_attr_count].format = (STYLE); \
s4 |= S4; \
intel->vertex_attr_count++; \
offset += (SZ); \
} while (0)
#define EMIT_PAD( N ) \
do { \
intel->vertex_attrs[intel->vertex_attr_count].attrib = 0; \
intel->vertex_attrs[intel->vertex_attr_count].format = EMIT_PAD; \
intel->vertex_attrs[intel->vertex_attr_count].offset = (N); \
intel->vertex_attr_count++; \
offset += (N); \
} while (0)
/*======================================================================
* i915_context.c
*/
extern GLboolean i915CreateContext( const __GLcontextModes *mesaVis,
__DRIcontextPrivate *driContextPriv,
void *sharedContextPrivate);
/*======================================================================
* i915_texprog.c
*/
extern void i915ValidateTextureProgram( i915ContextPtr i915 );
/*======================================================================
* i915_debug.c
*/
extern void i915_disassemble_program( const GLuint *program, GLuint sz );
extern void i915_print_ureg( const char *msg, GLuint ureg );
/*======================================================================
* i915_state.c
*/
extern void i915InitStateFunctions( struct dd_function_table *functions );
extern void i915InitState( i915ContextPtr i915 );
/*======================================================================
* i915_tex.c
*/
extern void i915UpdateTextureState( intelContextPtr intel );
extern void i915InitTextureFuncs( struct dd_function_table *functions );
extern intelTextureObjectPtr i915AllocTexObj( struct gl_texture_object *texObj );
/*======================================================================
* i915_metaops.c
*/
extern GLboolean
i915TryTextureReadPixels( GLcontext *ctx,
GLint x, GLint y, GLsizei width, GLsizei height,
GLenum format, GLenum type,
const struct gl_pixelstore_attrib *pack,
GLvoid *pixels );
extern GLboolean
i915TryTextureDrawPixels( GLcontext *ctx,
GLint x, GLint y, GLsizei width, GLsizei height,
GLenum format, GLenum type,
const struct gl_pixelstore_attrib *unpack,
const GLvoid *pixels );
extern void
i915ClearWithTris( intelContextPtr intel, GLbitfield mask,
GLboolean all, GLint cx, GLint cy, GLint cw, GLint ch);
/*======================================================================
* i915_fragprog.c
*/
extern void i915ValidateFragmentProgram( i915ContextPtr i915 );
extern void i915InitFragProgFuncs( struct dd_function_table *functions );
#endif
+272
View File
@@ -0,0 +1,272 @@
#include "i915_reg.h"
#include "i915_context.h"
#include <stdio.h>
static const char *opcodes[0x20] = {
"NOP",
"ADD",
"MOV",
"MUL",
"MAD",
"DP2ADD",
"DP3",
"DP4",
"FRC",
"RCP",
"RSQ",
"EXP",
"LOG",
"CMP",
"MIN",
"MAX",
"FLR",
"MOD",
"TRC",
"SGE",
"SLT",
"TEXLD",
"TEXLDP",
"TEXLDB",
"TEXKILL",
"DCL",
"0x1a",
"0x1b",
"0x1c",
"0x1d",
"0x1e",
"0x1f",
};
static const int args[0x20] = {
0, /* 0 nop */
2, /* 1 add */
1, /* 2 mov */
2, /* 3 m ul */
3, /* 4 mad */
3, /* 5 dp2add */
2, /* 6 dp3 */
2, /* 7 dp4 */
1, /* 8 frc */
1, /* 9 rcp */
1, /* a rsq */
1, /* b exp */
1, /* c log */
3, /* d cmp */
2, /* e min */
2, /* f max */
1, /* 10 flr */
1, /* 11 mod */
1, /* 12 trc */
2, /* 13 sge */
2, /* 14 slt */
1,
1,
1,
1,
0,
0,
0,
0,
0,
0,
0,
};
static const char *regname[0x8] = {
"R",
"T",
"CONST",
"S",
"OC",
"OD",
"U",
"UNKNOWN",
};
static void print_reg_type_nr( GLuint type, GLuint nr )
{
switch (type) {
case REG_TYPE_T:
switch (nr) {
case T_DIFFUSE: fprintf(stderr, "T_DIFFUSE"); return;
case T_SPECULAR: fprintf(stderr, "T_SPECULAR"); return;
case T_FOG_W: fprintf(stderr, "T_FOG_W"); return;
default: fprintf(stderr, "T_TEX%d", nr); return;
}
case REG_TYPE_OC:
if (nr == 0) {
fprintf(stderr, "oC");
return;
}
break;
case REG_TYPE_OD:
if (nr == 0) {
fprintf(stderr, "oD");
return;
}
break;
default:
break;
}
fprintf(stderr, "%s[%d]", regname[type], nr);
}
#define REG_SWIZZLE_MASK 0x7777
#define REG_NEGATE_MASK 0x8888
#define REG_SWIZZLE_XYZW ((SRC_X << A2_SRC2_CHANNEL_X_SHIFT) | \
(SRC_Y << A2_SRC2_CHANNEL_Y_SHIFT) | \
(SRC_Z << A2_SRC2_CHANNEL_Z_SHIFT) | \
(SRC_W << A2_SRC2_CHANNEL_W_SHIFT))
static void print_reg_neg_swizzle( GLuint reg )
{
int i;
if ((reg & REG_SWIZZLE_MASK) == REG_SWIZZLE_XYZW &&
(reg & REG_NEGATE_MASK) == 0)
return;
fprintf(stderr, ".");
for (i = 3 ; i >= 0; i--) {
if (reg & (1<<((i*4)+3)))
fprintf(stderr, "-");
switch ((reg>>(i*4)) & 0x7) {
case 0: fprintf(stderr, "x"); break;
case 1: fprintf(stderr, "y"); break;
case 2: fprintf(stderr, "z"); break;
case 3: fprintf(stderr, "w"); break;
case 4: fprintf(stderr, "0"); break;
case 5: fprintf(stderr, "1"); break;
default: fprintf(stderr, "?"); break;
}
}
}
static void print_src_reg( GLuint dword )
{
GLuint nr = (dword >> A2_SRC2_NR_SHIFT) & REG_NR_MASK;
GLuint type = (dword >> A2_SRC2_TYPE_SHIFT) & REG_TYPE_MASK;
print_reg_type_nr( type, nr );
print_reg_neg_swizzle( dword );
}
void i915_print_ureg( const char *msg, GLuint ureg )
{
fprintf(stderr, "%s: ", msg);
print_src_reg( ureg >> 8 );
fprintf(stderr, "\n");
}
static void print_dest_reg( GLuint dword )
{
GLuint nr = (dword >> A0_DEST_NR_SHIFT) & REG_NR_MASK;
GLuint type = (dword >> A0_DEST_TYPE_SHIFT) & REG_TYPE_MASK;
print_reg_type_nr( type, nr );
if ((dword & A0_DEST_CHANNEL_ALL) == A0_DEST_CHANNEL_ALL)
return;
fprintf(stderr, ".");
if (dword & A0_DEST_CHANNEL_X) fprintf(stderr, "x");
if (dword & A0_DEST_CHANNEL_Y) fprintf(stderr, "y");
if (dword & A0_DEST_CHANNEL_Z) fprintf(stderr, "z");
if (dword & A0_DEST_CHANNEL_W) fprintf(stderr, "w");
}
#define GET_SRC0_REG(r0, r1) ((r0<<14)|(r1>>A1_SRC0_CHANNEL_W_SHIFT))
#define GET_SRC1_REG(r0, r1) ((r0<<8)|(r1>>A2_SRC1_CHANNEL_W_SHIFT))
#define GET_SRC2_REG(r) (r)
static void print_arith_op( GLuint opcode, const GLuint *program )
{
if (opcode != A0_NOP) {
print_dest_reg(program[0]);
if (program[0] & A0_DEST_SATURATE)
fprintf(stderr, " = SATURATE ");
else
fprintf(stderr, " = ");
}
fprintf(stderr, "%s ", opcodes[opcode]);
print_src_reg(GET_SRC0_REG(program[0], program[1]));
if (args[opcode] == 1) {
fprintf(stderr, "\n");
return;
}
fprintf(stderr, ", ");
print_src_reg(GET_SRC1_REG(program[1], program[2]));
if (args[opcode] == 2) {
fprintf(stderr, "\n");
return;
}
fprintf(stderr, ", ");
print_src_reg(GET_SRC2_REG(program[2]));
fprintf(stderr, "\n");
return;
}
static void print_tex_op( GLuint opcode, const GLuint *program )
{
print_dest_reg(program[0] | A0_DEST_CHANNEL_ALL);
fprintf(stderr, " = ");
fprintf(stderr, "%s ", opcodes[opcode]);
fprintf(stderr, "S[%d],",
program[0] & T0_SAMPLER_NR_MASK);
print_reg_type_nr( (program[1]>>T1_ADDRESS_REG_TYPE_SHIFT) & REG_TYPE_MASK,
(program[1]>>T1_ADDRESS_REG_NR_SHIFT) & REG_NR_MASK );
fprintf(stderr, "\n");
}
static void print_dcl_op( GLuint opcode, const GLuint *program )
{
fprintf(stderr, "%s ", opcodes[opcode]);
print_dest_reg(program[0] | A0_DEST_CHANNEL_ALL);
fprintf(stderr, "\n");
}
void i915_disassemble_program( const GLuint *program, GLuint sz )
{
GLuint size = program[0] & 0x1ff;
GLint i;
fprintf(stderr, "BEGIN\n");
if (size+2 != sz) {
fprintf(stderr, "%s: program size mismatch %d/%d\n", __FUNCTION__,
size+2, sz);
exit(1);
}
program ++;
for (i = 1 ; i < sz ; i+=3, program+=3) {
GLuint opcode = program[0] & (0x1f<<24);
if (opcode >= A0_NOP && opcode <= A0_SLT)
print_arith_op(opcode >> 24, program);
else if (opcode >= T0_TEXLD && opcode <= T0_TEXKILL)
print_tex_op(opcode >> 24, program);
else if (opcode == D0_DCL)
print_dcl_op(opcode >> 24, program);
else
fprintf(stderr, "Unknown opcode 0x%x\n", opcode);
}
fprintf(stderr, "END\n\n");
}
File diff suppressed because it is too large Load Diff
+494
View File
@@ -0,0 +1,494 @@
/**************************************************************************
*
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
**************************************************************************/
#include "glheader.h"
#include "enums.h"
#include "mtypes.h"
#include "macros.h"
#include "utils.h"
#include "intel_screen.h"
#include "intel_batchbuffer.h"
#include "intel_ioctl.h"
#include "i915_context.h"
#include "i915_reg.h"
/* A large amount of state doesn't need to be uploaded.
*/
#define ACTIVE (I915_UPLOAD_PROGRAM | \
I915_UPLOAD_STIPPLE | \
I915_UPLOAD_CTX | \
I915_UPLOAD_BUFFERS | \
I915_UPLOAD_TEX(0))
#define SET_STATE( i915, STATE ) \
do { \
i915->current->emitted &= ~ACTIVE; \
i915->current = &i915->STATE; \
i915->current->emitted &= ~ACTIVE; \
} while (0)
/* Operations where the 3D engine is decoupled temporarily from the
* current GL state and used for other purposes than simply rendering
* incoming triangles.
*/
static void set_initial_state( i915ContextPtr i915 )
{
memcpy(&i915->meta, &i915->initial, sizeof(i915->meta) );
i915->meta.active = ACTIVE;
i915->meta.emitted = 0;
}
static void set_no_depth_stencil_write( i915ContextPtr i915 )
{
/* ctx->Driver.Enable( ctx, GL_STENCIL_TEST, GL_FALSE )
*/
i915->meta.Ctx[I915_CTXREG_LIS5] &= ~(S5_STENCIL_TEST_ENABLE |
S5_STENCIL_WRITE_ENABLE);
/* ctx->Driver.Enable( ctx, GL_DEPTH_TEST, GL_FALSE )
*/
i915->meta.Ctx[I915_CTXREG_LIS6] &= ~(S6_DEPTH_TEST_ENABLE |
S6_DEPTH_WRITE_ENABLE);
i915->meta.emitted &= ~I915_UPLOAD_CTX;
}
/* Set stencil unit to replace always with the reference value.
*/
static void set_stencil_replace( i915ContextPtr i915,
GLuint s_mask,
GLuint s_clear)
{
GLuint op = STENCILOP_REPLACE;
GLuint func = COMPAREFUNC_ALWAYS;
/* ctx->Driver.Enable( ctx, GL_STENCIL_TEST, GL_TRUE )
*/
i915->meta.Ctx[I915_CTXREG_LIS5] |= (S5_STENCIL_TEST_ENABLE |
S5_STENCIL_WRITE_ENABLE);
/* ctx->Driver.Enable( ctx, GL_DEPTH_TEST, GL_FALSE )
*/
i915->meta.Ctx[I915_CTXREG_LIS6] &= ~(S6_DEPTH_TEST_ENABLE |
S6_DEPTH_WRITE_ENABLE);
/* ctx->Driver.StencilMask( ctx, s_mask )
*/
i915->meta.Ctx[I915_CTXREG_STATE4] &= ~MODE4_ENABLE_STENCIL_WRITE_MASK;
i915->meta.Ctx[I915_CTXREG_STATE4] |= (ENABLE_STENCIL_WRITE_MASK |
STENCIL_WRITE_MASK(s_mask));
/* ctx->Driver.StencilOp( ctx, GL_REPLACE, GL_REPLACE, GL_REPLACE )
*/
i915->meta.Ctx[I915_CTXREG_LIS5] &= ~(S5_STENCIL_FAIL_MASK |
S5_STENCIL_PASS_Z_FAIL_MASK |
S5_STENCIL_PASS_Z_PASS_MASK);
i915->meta.Ctx[I915_CTXREG_LIS5] |= ((op << S5_STENCIL_FAIL_SHIFT) |
(op << S5_STENCIL_PASS_Z_FAIL_SHIFT) |
(op << S5_STENCIL_PASS_Z_PASS_SHIFT));
/* ctx->Driver.StencilFunc( ctx, GL_ALWAYS, s_ref, ~0 )
*/
i915->meta.Ctx[I915_CTXREG_STATE4] &= ~MODE4_ENABLE_STENCIL_TEST_MASK;
i915->meta.Ctx[I915_CTXREG_STATE4] |= (ENABLE_STENCIL_TEST_MASK |
STENCIL_TEST_MASK(0xff));
i915->meta.Ctx[I915_CTXREG_LIS5] &= ~(S5_STENCIL_REF_MASK |
S5_STENCIL_TEST_FUNC_MASK);
i915->meta.Ctx[I915_CTXREG_LIS5] |= ((s_clear << S5_STENCIL_REF_SHIFT) |
(func << S5_STENCIL_TEST_FUNC_SHIFT));
i915->meta.emitted &= ~I915_UPLOAD_CTX;
}
static void set_color_mask( i915ContextPtr i915, GLboolean state )
{
const GLuint mask = (S5_WRITEDISABLE_RED |
S5_WRITEDISABLE_GREEN |
S5_WRITEDISABLE_BLUE |
S5_WRITEDISABLE_ALPHA);
/* Copy colormask state from "regular" hw context.
*/
if (state) {
i915->meta.Ctx[I915_CTXREG_LIS5] &= ~mask;
i915->meta.Ctx[I915_CTXREG_LIS5] |=
(i915->state.Ctx[I915_CTXREG_LIS5] & mask);
}
else
i915->meta.Ctx[I915_CTXREG_LIS5] |= mask;
i915->meta.emitted &= ~I915_UPLOAD_CTX;
}
#define REG( type, nr ) (((type)<<5)|(nr))
#define REG_R(x) REG(REG_TYPE_R, x)
#define REG_T(x) REG(REG_TYPE_T, x)
#define REG_CONST(x) REG(REG_TYPE_CONST, x)
#define REG_S(x) REG(REG_TYPE_S, x)
#define REG_OC REG(REG_TYPE_OC, 0)
#define REG_OD REG(REG_TYPE_OD, 0)
#define REG_U(x) REG(REG_TYPE_U, x)
#define REG_T_DIFFUSE REG(REG_TYPE_T, T_DIFFUSE)
#define REG_T_SPECULAR REG(REG_TYPE_T, T_SPECULAR)
#define REG_T_FOG_W REG(REG_TYPE_T, T_FOG_W)
#define REG_T_TEX(x) REG(REG_TYPE_T, x)
#define A0_DEST_REG( reg ) ( (reg) << A0_DEST_NR_SHIFT )
#define A0_SRC0_REG( reg ) ( (reg) << A0_SRC0_NR_SHIFT )
#define A1_SRC1_REG( reg ) ( (reg) << A1_SRC1_NR_SHIFT )
#define A1_SRC2_REG( reg ) ( (reg) << A1_SRC2_NR_SHIFT )
#define A2_SRC2_REG( reg ) ( (reg) << A2_SRC2_NR_SHIFT )
#define D0_DECL_REG( reg ) ( (reg) << D0_NR_SHIFT )
#define T0_DEST_REG( reg ) ( (reg) << T0_DEST_NR_SHIFT )
#define T0_SAMPLER( unit ) ((unit)<<T0_SAMPLER_NR_SHIFT)
#define T1_ADDRESS_REG( type, nr ) (((type)<<T1_ADDRESS_REG_TYPE_SHIFT)| \
((nr)<<T1_ADDRESS_REG_NR_SHIFT))
#define A1_SRC0_XYZW ((SRC_X << A1_SRC0_CHANNEL_X_SHIFT) | \
(SRC_Y << A1_SRC0_CHANNEL_Y_SHIFT) | \
(SRC_Z << A1_SRC0_CHANNEL_Z_SHIFT) | \
(SRC_W << A1_SRC0_CHANNEL_W_SHIFT))
#define A1_SRC1_XY ((SRC_X << A1_SRC1_CHANNEL_X_SHIFT) | \
(SRC_Y << A1_SRC1_CHANNEL_Y_SHIFT))
#define A2_SRC1_ZW ((SRC_Z << A2_SRC1_CHANNEL_Z_SHIFT) | \
(SRC_W << A2_SRC1_CHANNEL_W_SHIFT))
#define A2_SRC2_XYZW ((SRC_X << A2_SRC2_CHANNEL_X_SHIFT) | \
(SRC_Y << A2_SRC2_CHANNEL_Y_SHIFT) | \
(SRC_Z << A2_SRC2_CHANNEL_Z_SHIFT) | \
(SRC_W << A2_SRC2_CHANNEL_W_SHIFT))
static void set_no_texture( i915ContextPtr i915 )
{
static const GLuint prog[] = {
_3DSTATE_PIXEL_SHADER_PROGRAM,
/* Declare incoming diffuse color:
*/
(D0_DCL |
D0_DECL_REG( REG_T_DIFFUSE ) |
D0_CHANNEL_ALL),
D1_MBZ,
D2_MBZ,
/* output-color = mov(t_diffuse)
*/
(A0_MOV |
A0_DEST_REG( REG_OC ) |
A0_DEST_CHANNEL_ALL |
A0_SRC0_REG( REG_T_DIFFUSE )),
(A1_SRC0_XYZW),
0,
};
memcpy( i915->meta.Program, prog, sizeof(prog) );
i915->meta.ProgramSize = sizeof(prog) / sizeof(*prog);
i915->meta.Program[0] |= i915->meta.ProgramSize - 2;
i915->meta.emitted &= ~I915_UPLOAD_PROGRAM;
}
static void enable_texture_blend_replace( i915ContextPtr i915 )
{
static const GLuint prog[] = {
_3DSTATE_PIXEL_SHADER_PROGRAM,
/* Declare the sampler:
*/
(D0_DCL |
D0_DECL_REG( REG_S(0) ) |
D0_SAMPLE_TYPE_2D |
D0_CHANNEL_NONE),
D1_MBZ,
D2_MBZ,
/* Declare the interpolated texture coordinate:
*/
(D0_DCL |
D0_DECL_REG( REG_T_TEX(0) ) |
D0_CHANNEL_ALL),
D1_MBZ,
D2_MBZ,
/* output-color = texld(sample0, texcoord0)
*/
(T0_TEXLD |
T0_DEST_REG( REG_OC ) |
T0_SAMPLER( 0 )),
T1_ADDRESS_REG(REG_TYPE_T, 0),
T2_MBZ
};
memcpy( i915->meta.Program, prog, sizeof(prog) );
i915->meta.ProgramSize = sizeof(prog) / sizeof(*prog);
i915->meta.Program[0] |= i915->meta.ProgramSize - 2;
i915->meta.emitted &= ~I915_UPLOAD_PROGRAM;
}
/* Set up an arbitary piece of memory as a rectangular texture
* (including the front or back buffer).
*/
static void set_tex_rect_source( i915ContextPtr i915,
GLuint offset,
GLuint width,
GLuint height,
GLuint pitch,
GLuint textureFormat )
{
GLuint unit = 0;
GLint numLevels = 1;
GLuint *state = i915->meta.Tex[0];
pitch *= i915->intel.intelScreen->cpp;
/* fprintf(stderr, "%s: offset: %x w: %d h: %d pitch %d format %x\n", */
/* __FUNCTION__, offset, width, height, pitch, textureFormat ); */
state[I915_TEXREG_MS2] = offset;
state[I915_TEXREG_MS3] = (((height - 1) << MS3_HEIGHT_SHIFT) |
((width - 1) << MS3_WIDTH_SHIFT) |
textureFormat |
MS3_USE_FENCE_REGS);
state[I915_TEXREG_MS4] = ((((pitch / 4) - 1) << MS4_PITCH_SHIFT) |
MS4_CUBE_FACE_ENA_MASK |
((((numLevels-1) * 4)) << MS4_MAX_LOD_SHIFT));
state[I915_TEXREG_SS2] = ((FILTER_NEAREST << SS2_MIN_FILTER_SHIFT) |
(MIPFILTER_NONE << SS2_MIP_FILTER_SHIFT) |
(FILTER_NEAREST << SS2_MAG_FILTER_SHIFT));
state[I915_TEXREG_SS3] = ((TEXCOORDMODE_WRAP << SS3_TCX_ADDR_MODE_SHIFT) |
(TEXCOORDMODE_WRAP << SS3_TCY_ADDR_MODE_SHIFT) |
(TEXCOORDMODE_WRAP << SS3_TCZ_ADDR_MODE_SHIFT) |
(unit<<SS3_TEXTUREMAP_INDEX_SHIFT));
state[I915_TEXREG_SS4] = 0;
i915->meta.emitted &= ~I915_UPLOAD_TEX(0);
}
/* Select between front and back draw buffers.
*/
static void set_draw_offset( i915ContextPtr i915,
GLuint offset )
{
i915->meta.Buffer[I915_DESTREG_CBUFADDR2] = offset;
i915->meta.emitted &= ~I915_UPLOAD_BUFFERS;
}
/* Setup an arbitary draw format, useful for targeting texture or agp
* memory.
*/
static void set_draw_format( i915ContextPtr i915,
GLuint format,
GLuint depth_format)
{
i915->meta.Buffer[I915_DESTREG_DV1] = (DSTORG_HORT_BIAS(0x8) | /* .5 */
DSTORG_VERT_BIAS(0x8) | /* .5 */
format |
LOD_PRECLAMP_OGL |
TEX_DEFAULT_COLOR_OGL |
depth_format);
i915->meta.emitted &= ~I915_UPLOAD_BUFFERS;
/* fprintf(stderr, "%s: DV1: %x\n", */
/* __FUNCTION__, i915->meta.Buffer[I915_DESTREG_DV1]); */
}
static void set_vertex_format( i915ContextPtr i915 )
{
i915->meta.Ctx[I915_CTXREG_LIS2] =
(S2_TEXCOORD_FMT(0, TEXCOORDFMT_2D) |
S2_TEXCOORD_FMT(1, TEXCOORDFMT_NOT_PRESENT) |
S2_TEXCOORD_FMT(2, TEXCOORDFMT_NOT_PRESENT) |
S2_TEXCOORD_FMT(3, TEXCOORDFMT_NOT_PRESENT) |
S2_TEXCOORD_FMT(4, TEXCOORDFMT_NOT_PRESENT) |
S2_TEXCOORD_FMT(5, TEXCOORDFMT_NOT_PRESENT) |
S2_TEXCOORD_FMT(6, TEXCOORDFMT_NOT_PRESENT) |
S2_TEXCOORD_FMT(7, TEXCOORDFMT_NOT_PRESENT));
i915->meta.Ctx[I915_CTXREG_LIS4] &= ~S4_VFMT_MASK;
i915->meta.Ctx[I915_CTXREG_LIS4] |=
(S4_VFMT_COLOR |
S4_VFMT_SPEC_FOG |
S4_VFMT_XYZW);
i915->meta.emitted &= ~I915_UPLOAD_CTX;
}
static void draw_quad(i915ContextPtr i915,
GLfloat x0, GLfloat x1,
GLfloat y0, GLfloat y1,
GLubyte red, GLubyte green,
GLubyte blue, GLubyte alpha,
GLfloat s0, GLfloat s1,
GLfloat t0, GLfloat t1 )
{
GLuint vertex_size = 8;
GLuint *vb = intelEmitInlinePrimitiveLocked( &i915->intel,
PRIM3D_TRIFAN,
4 * vertex_size,
vertex_size );
intelVertex tmp;
int i;
if (0)
fprintf(stderr, "%s: %f,%f-%f,%f 0x%x%x%x%x %f,%f-%f,%f\n",
__FUNCTION__,
x0,y0,x1,y1,red,green,blue,alpha,s0,t0,s1,t1);
/* initial vertex, left bottom */
tmp.v.x = x0;
tmp.v.y = y0;
tmp.v.z = 1.0;
tmp.v.w = 1.0;
tmp.v.color.red = red;
tmp.v.color.green = green;
tmp.v.color.blue = blue;
tmp.v.color.alpha = alpha;
tmp.v.specular.red = 0;
tmp.v.specular.green = 0;
tmp.v.specular.blue = 0;
tmp.v.specular.alpha = 0;
tmp.v.u0 = s0;
tmp.v.v0 = t0;
for (i = 0 ; i < vertex_size ; i++)
vb[i] = tmp.ui[i];
/* right bottom */
vb += vertex_size;
tmp.v.x = x1;
tmp.v.u0 = s1;
for (i = 0 ; i < vertex_size ; i++)
vb[i] = tmp.ui[i];
/* right top */
vb += vertex_size;
tmp.v.y = y1;
tmp.v.v0 = t1;
for (i = 0 ; i < vertex_size ; i++)
vb[i] = tmp.ui[i];
/* left top */
vb += vertex_size;
tmp.v.x = x0;
tmp.v.u0 = s0;
for (i = 0 ; i < vertex_size ; i++)
vb[i] = tmp.ui[i];
}
void
i915ClearWithTris(intelContextPtr intel, GLbitfield mask,
GLboolean all,
GLint cx, GLint cy, GLint cw, GLint ch)
{
i915ContextPtr i915 = I915_CONTEXT( intel );
__DRIdrawablePrivate *dPriv = intel->driDrawable;
intelScreenPrivate *screen = intel->intelScreen;
int x0, y0, x1, y1;
SET_STATE( i915, meta );
set_initial_state( i915 );
set_no_texture( i915 );
set_vertex_format( i915 );
LOCK_HARDWARE(intel);
if(!all) {
x0 = cx;
y0 = cy;
x1 = x0 + cw;
y1 = y0 + ch;
} else {
x0 = 0;
y0 = 0;
x1 = x0 + dPriv->w;
y1 = y0 + dPriv->h;
}
/* Don't do any clipping to screen - these are window coordinates.
* The active cliprects will be applied as for any other geometry.
*/
if (mask & DD_FRONT_LEFT_BIT) {
set_no_depth_stencil_write( i915 );
set_color_mask( i915, GL_TRUE );
set_draw_offset( i915, screen->frontOffset );
draw_quad(i915, x0, x1, y0, y1,
intel->clear_red, intel->clear_green,
intel->clear_blue, intel->clear_alpha,
0, 0, 0, 0);
}
if(mask & DD_BACK_LEFT_BIT) {
set_no_depth_stencil_write( i915 );
set_color_mask( i915, GL_TRUE );
set_draw_offset( i915, screen->backOffset );
draw_quad(i915, x0, x1, y0, y1,
intel->clear_red, intel->clear_green,
intel->clear_blue, intel->clear_alpha,
0, 0, 0, 0);
}
if(mask & DD_STENCIL_BIT) {
set_stencil_replace( i915,
intel->ctx.Stencil.WriteMask[0],
intel->ctx.Stencil.Clear);
set_color_mask( i915, GL_FALSE );
set_draw_offset( i915, screen->frontOffset ); /* could be either? */
draw_quad( i915, x0, x1, y0, y1, 0, 0, 0, 0, 0, 0, 0, 0 );
}
UNLOCK_HARDWARE(intel);
SET_STATE( i915, state );
}
+446
View File
@@ -0,0 +1,446 @@
/**************************************************************************
*
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
**************************************************************************/
#include <strings.h>
#include "glheader.h"
#include "macros.h"
#include "enums.h"
#include "tnl/t_context.h"
#include "intel_batchbuffer.h"
#include "i915_reg.h"
#include "i915_context.h"
#include "i915_program.h"
#define A0_DEST( reg ) (((reg)&UREG_TYPE_NR_MASK)>>UREG_A0_DEST_SHIFT_LEFT)
#define D0_DEST( reg ) (((reg)&UREG_TYPE_NR_MASK)>>UREG_A0_DEST_SHIFT_LEFT)
#define T0_DEST( reg ) (((reg)&UREG_TYPE_NR_MASK)>>UREG_A0_DEST_SHIFT_LEFT)
#define A0_SRC0( reg ) (((reg)&UREG_MASK)>>UREG_A0_SRC0_SHIFT_LEFT)
#define A1_SRC0( reg ) (((reg)&UREG_MASK)<<UREG_A1_SRC0_SHIFT_RIGHT)
#define A1_SRC1( reg ) (((reg)&UREG_MASK)>>UREG_A1_SRC1_SHIFT_LEFT)
#define A2_SRC1( reg ) (((reg)&UREG_MASK)<<UREG_A2_SRC1_SHIFT_RIGHT)
#define A2_SRC2( reg ) (((reg)&UREG_MASK)>>UREG_A2_SRC2_SHIFT_LEFT)
/* These are special, and don't have swizzle/negate bits.
*/
#define T0_SAMPLER( reg ) (GET_UREG_NR(reg)<<T0_SAMPLER_NR_SHIFT)
#define T1_ADDRESS_REG( reg ) ((GET_UREG_NR(reg)<<T1_ADDRESS_REG_NR_SHIFT) | \
(GET_UREG_TYPE(reg)<<T1_ADDRESS_REG_TYPE_SHIFT))
/* Macros for translating UREG's into the various register fields used
* by the I915 programmable unit.
*/
#define UREG_A0_DEST_SHIFT_LEFT (UREG_TYPE_SHIFT - A0_DEST_TYPE_SHIFT)
#define UREG_A0_SRC0_SHIFT_LEFT (UREG_TYPE_SHIFT - A0_SRC0_TYPE_SHIFT)
#define UREG_A1_SRC0_SHIFT_RIGHT (A1_SRC0_CHANNEL_W_SHIFT - UREG_CHANNEL_W_SHIFT)
#define UREG_A1_SRC1_SHIFT_LEFT (UREG_TYPE_SHIFT - A1_SRC1_TYPE_SHIFT)
#define UREG_A2_SRC1_SHIFT_RIGHT (A2_SRC1_CHANNEL_W_SHIFT - UREG_CHANNEL_W_SHIFT)
#define UREG_A2_SRC2_SHIFT_LEFT (UREG_TYPE_SHIFT - A2_SRC2_TYPE_SHIFT)
#define UREG_MASK 0xffffff00
#define UREG_TYPE_NR_MASK ((REG_TYPE_MASK << UREG_TYPE_SHIFT) | \
(REG_NR_MASK << UREG_NR_SHIFT))
#define I915_CONSTFLAG_PARAM 0x1f
GLuint i915_get_temp( struct i915_fragment_program *p )
{
int bit = ffs( ~p->temp_flag );
if (!bit) {
fprintf(stderr, "%s: out of temporaries\n", __FILE__);
exit(1);
}
p->temp_flag |= 1<<(bit-1);
return UREG(REG_TYPE_R, (bit-1));
}
GLuint i915_get_utemp( struct i915_fragment_program *p )
{
int bit = ffs( ~p->utemp_flag );
if (!bit) {
fprintf(stderr, "%s: out of temporaries\n", __FILE__);
exit(1);
}
p->utemp_flag |= 1<<(bit-1);
return UREG(REG_TYPE_U, (bit-1));
}
void i915_release_utemps( struct i915_fragment_program *p )
{
p->utemp_flag = ~0x7;
}
GLuint i915_emit_decl( struct i915_fragment_program *p,
GLuint type, GLuint nr, GLuint d0_flags )
{
GLuint reg = UREG(type, nr);
if (type == REG_TYPE_T) {
if (p->decl_t & (1<<nr))
return reg;
p->decl_t |= (1<<nr);
}
else if (type == REG_TYPE_S) {
if (p->decl_s & (1<<nr))
return reg;
p->decl_s |= (1<<nr);
}
else
return reg;
*(p->decl++) = (D0_DCL | D0_DEST( reg ) | d0_flags);
*(p->decl++) = D1_MBZ;
*(p->decl++) = D2_MBZ;
p->nr_decl_insn++;
return reg;
}
GLuint i915_emit_arith( struct i915_fragment_program *p,
GLuint op,
GLuint dest,
GLuint mask,
GLuint saturate,
GLuint src0,
GLuint src1,
GLuint src2 )
{
GLuint c[3];
GLuint nr_const = 0;
assert(GET_UREG_TYPE(dest) != REG_TYPE_CONST);
assert(dest = UREG(GET_UREG_TYPE(dest), GET_UREG_NR(dest)));
if (GET_UREG_TYPE(src0) == REG_TYPE_CONST) c[nr_const++] = 0;
if (GET_UREG_TYPE(src1) == REG_TYPE_CONST) c[nr_const++] = 1;
if (GET_UREG_TYPE(src2) == REG_TYPE_CONST) c[nr_const++] = 2;
/* Recursively call this function to MOV additional const values
* into temporary registers. Use utemp registers for this -
* currently shouldn't be possible to run out, but keep an eye on
* this.
*/
if (nr_const > 1) {
GLuint s[3], first, i, old_utemp_flag;
s[0] = src0;
s[1] = src1;
s[2] = src2;
old_utemp_flag = p->utemp_flag;
first = GET_UREG_NR(s[c[0]]);
for (i = 1 ; i < nr_const ; i++) {
if (GET_UREG_NR(s[c[i]]) != first) {
GLuint tmp = i915_get_utemp(p);
i915_emit_arith( p, A0_MOV, tmp, A0_DEST_CHANNEL_ALL, 0,
s[c[i]], 0, 0 );
s[c[i]] = tmp;
}
}
src0 = s[0];
src1 = s[1];
src2 = s[2];
p->utemp_flag = old_utemp_flag; /* restore */
}
*(p->csr++) = (op |
A0_DEST( dest ) |
mask |
saturate |
A0_SRC0( src0 ));
*(p->csr++) = (A1_SRC0( src0 ) |
A1_SRC1( src1 ));
*(p->csr++) = (A2_SRC1( src1 ) |
A2_SRC2( src2 ));
p->nr_alu_insn++;
return dest;
}
GLuint i915_emit_texld( struct i915_fragment_program *p,
GLuint dest,
GLuint destmask,
GLuint sampler,
GLuint coord,
GLuint op )
{
assert(GET_UREG_TYPE(dest) != REG_TYPE_CONST);
assert(dest = UREG(GET_UREG_TYPE(dest), GET_UREG_NR(dest)));
if (GET_UREG_TYPE(coord) != REG_TYPE_T) {
p->nr_tex_indirect++;
}
*(p->csr++) = (op |
T0_DEST( dest ) |
destmask |
T0_SAMPLER( sampler ));
*(p->csr++) = T1_ADDRESS_REG( coord );
*(p->csr++) = T2_MBZ;
p->nr_tex_insn++;
return dest;
}
GLuint i915_emit_const1f( struct i915_fragment_program *p, GLfloat c0 )
{
GLint reg, idx;
if (c0 == 0.0) return swizzle(UREG(REG_TYPE_R, 0), ZERO, ZERO, ZERO, ZERO);
if (c0 == 1.0) return swizzle(UREG(REG_TYPE_R, 0), ONE, ONE, ONE, ONE );
for (reg = 0; reg < I915_MAX_CONSTANT; reg++) {
if (p->constant_flags[reg] == I915_CONSTFLAG_PARAM)
continue;
for (idx = 0; idx < 4; idx++) {
if (!(p->constant_flags[reg] & (1<<idx)) ||
p->constant[reg][idx] == c0) {
p->constant[reg][idx] = c0;
p->constant_flags[reg] |= 1<<idx;
if (reg+1 > p->nr_constants) p->nr_constants = reg+1;
return swizzle(UREG(REG_TYPE_CONST, reg),idx,ZERO,ZERO,ONE);
}
}
}
fprintf(stderr, "%s: out of constants\n", __FUNCTION__);
p->error = 1;
return 0;
}
GLuint i915_emit_const2f( struct i915_fragment_program *p,
GLfloat c0, GLfloat c1 )
{
GLint reg, idx;
if (c0 == 0.0) return swizzle(i915_emit_const1f(p, c1), ZERO, X, Z, W);
if (c0 == 1.0) return swizzle(i915_emit_const1f(p, c1), ONE, X, Z, W);
if (c1 == 0.0) return swizzle(i915_emit_const1f(p, c0), X, ZERO, Z, W);
if (c1 == 1.0) return swizzle(i915_emit_const1f(p, c0), X, ONE, Z, W);
for (reg = 0; reg < I915_MAX_CONSTANT; reg++) {
if (p->constant_flags[reg] == 0xf ||
p->constant_flags[reg] == I915_CONSTFLAG_PARAM)
continue;
for (idx = 0; idx < 3; idx++) {
if (!(p->constant_flags[reg] & (3<<idx))) {
p->constant[reg][idx] = c0;
p->constant[reg][idx+1] = c1;
p->constant_flags[reg] |= 3<<idx;
if (reg+1 > p->nr_constants) p->nr_constants = reg+1;
return swizzle(UREG(REG_TYPE_CONST, reg),idx,idx+1,ZERO,ONE);
}
}
}
fprintf(stderr, "%s: out of constants\n", __FUNCTION__);
p->error = 1;
return 0;
}
GLuint i915_emit_const4f( struct i915_fragment_program *p,
GLfloat c0, GLfloat c1, GLfloat c2, GLfloat c3 )
{
GLint reg;
for (reg = 0; reg < I915_MAX_CONSTANT; reg++) {
if (p->constant_flags[reg] == 0xf &&
p->constant[reg][0] == c0 &&
p->constant[reg][1] == c1 &&
p->constant[reg][2] == c2 &&
p->constant[reg][3] == c3) {
return UREG(REG_TYPE_CONST, reg);
}
else if (p->constant_flags[reg] == 0) {
p->constant[reg][0] = c0;
p->constant[reg][1] = c1;
p->constant[reg][2] = c2;
p->constant[reg][3] = c3;
p->constant_flags[reg] = 0xf;
if (reg+1 > p->nr_constants) p->nr_constants = reg+1;
return UREG(REG_TYPE_CONST, reg);
}
}
fprintf(stderr, "%s: out of constants\n", __FUNCTION__);
p->error = 1;
return 0;
}
GLuint i915_emit_const4fv( struct i915_fragment_program *p, const GLfloat *c )
{
return i915_emit_const4f( p, c[0], c[1], c[2], c[3] );
}
GLuint i915_emit_param4fv( struct i915_fragment_program *p,
const GLfloat *values )
{
GLint reg, i;
for (i = 0; i < p->nr_params; i++) {
if (p->param[i].values == values)
return UREG(REG_TYPE_CONST, p->param[i].reg);
}
for (reg = 0; reg < I915_MAX_CONSTANT; reg++) {
if (p->constant_flags[reg] == 0) {
p->constant_flags[reg] = I915_CONSTFLAG_PARAM;
i = p->nr_params++;
p->param[i].values = values;
p->param[i].reg = reg;
p->params_uptodate = 0;
if (reg+1 > p->nr_constants) p->nr_constants = reg+1;
return UREG(REG_TYPE_CONST, reg);
}
}
fprintf(stderr, "%s: out of constants\n", __FUNCTION__);
p->error = 1;
return 0;
}
void i915_program_error( struct i915_fragment_program *p, const GLubyte *msg )
{
fprintf(stderr, "%s\n", msg);
p->error = 1;
}
void i915_init_program( i915ContextPtr i915, struct i915_fragment_program *p )
{
GLcontext *ctx = &i915->intel.ctx;
TNLcontext *tnl = TNL_CONTEXT( ctx );
p->translated = 0;
p->params_uptodate = 0;
p->on_hardware = 0;
p->error = 0;
p->nr_tex_indirect = 1; /* correct? */
p->nr_tex_insn = 0;
p->nr_alu_insn = 0;
p->nr_decl_insn = 0;
p->ctx = ctx;
memset( p->constant_flags, 0, sizeof(p->constant_flags) );
p->nr_constants = 0;
p->csr = p->program;
p->decl = p->declarations;
p->decl_s = 0;
p->decl_t = 0;
p->temp_flag = 0xffff000;
p->utemp_flag = ~0x7;
p->wpos_tex = 0;
p->depth_written = 0;
p->nr_params = 0;
p->src_texture = UREG_BAD;
p->src_previous = UREG(REG_TYPE_T, T_DIFFUSE);
p->last_tex_stage = 0;
p->VB = &tnl->vb;
*(p->decl++) = _3DSTATE_PIXEL_SHADER_PROGRAM;
}
void i915_fini_program( struct i915_fragment_program *p )
{
GLuint program_size = p->csr - p->program;
GLuint decl_size = p->decl - p->declarations;
if (p->nr_tex_indirect > I915_MAX_TEX_INDIRECT)
i915_program_error(p, "Exceeded max nr indirect texture lookups");
if (p->nr_tex_insn > I915_MAX_TEX_INSN)
i915_program_error(p, "Exceeded max TEX instructions");
if (p->nr_alu_insn > I915_MAX_ALU_INSN)
i915_program_error(p, "Exceeded max ALU instructions");
if (p->nr_decl_insn > I915_MAX_DECL_INSN)
i915_program_error(p, "Exceeded max DECL instructions");
p->declarations[0] |= program_size + decl_size - 2;
}
void i915_upload_program( i915ContextPtr i915, struct i915_fragment_program *p )
{
GLuint program_size = p->csr - p->program;
GLuint decl_size = p->decl - p->declarations;
FALLBACK( &i915->intel, I915_FALLBACK_PROGRAM, p->error );
/* Could just go straight to the batchbuffer from here:
*/
if (i915->state.ProgramSize != (program_size + decl_size) ||
memcmp(i915->state.Program + decl_size, p->program,
program_size*sizeof(int)) != 0) {
I915_STATECHANGE( i915, I915_UPLOAD_PROGRAM );
memcpy(i915->state.Program, p->declarations, decl_size*sizeof(int));
memcpy(i915->state.Program + decl_size, p->program,
program_size*sizeof(int));
i915->state.ProgramSize = decl_size + program_size;
}
/* Always seemed to get a failure if I used memcmp() to
* shortcircuit this state upload. Needs further investigation?
*/
if (p->nr_constants) {
GLuint nr = p->nr_constants;
I915_ACTIVESTATE( i915, I915_UPLOAD_CONSTANTS, 1 );
I915_STATECHANGE( i915, I915_UPLOAD_CONSTANTS );
i915->state.Constant[0] = _3DSTATE_PIXEL_SHADER_CONSTANTS | ((nr) * 4);
i915->state.Constant[1] = (1<<(nr-1)) | ((1<<(nr-1))-1);
memcpy(&i915->state.Constant[2], p->constant, 4*sizeof(int)*(nr));
i915->state.ConstantSize = 2 + (nr) * 4;
if (0) {
GLuint i;
for (i = 0; i < nr; i++) {
fprintf(stderr, "const[%d]: %f %f %f %f\n", i,
p->constant[i][0],
p->constant[i][1],
p->constant[i][2],
p->constant[i][3]);
}
}
}
else {
I915_ACTIVESTATE( i915, I915_UPLOAD_CONSTANTS, 0 );
}
p->on_hardware = 1;
}
+143
View File
@@ -0,0 +1,143 @@
/**************************************************************************
*
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
**************************************************************************/
#ifndef I915_PROGRAM_H
#define I915_PROGRAM_H
#include "i915_context.h"
#include "i915_reg.h"
/* Having zero and one in here makes the definition of swizzle a lot
* easier.
*/
#define UREG_TYPE_SHIFT 29
#define UREG_NR_SHIFT 24
#define UREG_CHANNEL_X_NEGATE_SHIFT 23
#define UREG_CHANNEL_X_SHIFT 20
#define UREG_CHANNEL_Y_NEGATE_SHIFT 19
#define UREG_CHANNEL_Y_SHIFT 16
#define UREG_CHANNEL_Z_NEGATE_SHIFT 15
#define UREG_CHANNEL_Z_SHIFT 12
#define UREG_CHANNEL_W_NEGATE_SHIFT 11
#define UREG_CHANNEL_W_SHIFT 8
#define UREG_CHANNEL_ZERO_NEGATE_MBZ 5
#define UREG_CHANNEL_ZERO_SHIFT 4
#define UREG_CHANNEL_ONE_NEGATE_MBZ 1
#define UREG_CHANNEL_ONE_SHIFT 0
#define UREG_BAD 0xffffffff /* not a valid ureg */
#define X SRC_X
#define Y SRC_Y
#define Z SRC_Z
#define W SRC_W
#define ZERO SRC_ZERO
#define ONE SRC_ONE
/* Construct a ureg:
*/
#define UREG( type, nr ) (((type)<< UREG_TYPE_SHIFT) | \
((nr) << UREG_NR_SHIFT) | \
(X << UREG_CHANNEL_X_SHIFT) | \
(Y << UREG_CHANNEL_Y_SHIFT) | \
(Z << UREG_CHANNEL_Z_SHIFT) | \
(W << UREG_CHANNEL_W_SHIFT) | \
(ZERO << UREG_CHANNEL_ZERO_SHIFT) | \
(ONE << UREG_CHANNEL_ONE_SHIFT))
#define GET_CHANNEL_SRC( reg, channel ) ((reg<<(channel*4)) & (0xf<<20))
#define CHANNEL_SRC( src, channel ) (src>>(channel*4))
#define GET_UREG_TYPE(reg) (((reg)>>UREG_TYPE_SHIFT)&REG_TYPE_MASK)
#define GET_UREG_NR(reg) (((reg)>>UREG_NR_SHIFT)&REG_NR_MASK)
#define UREG_XYZW_CHANNEL_MASK 0x00ffff00
/* One neat thing about the UREG representation:
*/
static __inline int swizzle( int reg, int x, int y, int z, int w )
{
return ((reg & ~UREG_XYZW_CHANNEL_MASK) |
CHANNEL_SRC( GET_CHANNEL_SRC( reg, x ), 0 ) |
CHANNEL_SRC( GET_CHANNEL_SRC( reg, y ), 1 ) |
CHANNEL_SRC( GET_CHANNEL_SRC( reg, z ), 2 ) |
CHANNEL_SRC( GET_CHANNEL_SRC( reg, w ), 3 ));
}
/* Another neat thing about the UREG representation:
*/
static __inline int negate( int reg, int x, int y, int z, int w )
{
return reg ^ (((x&1)<<UREG_CHANNEL_X_NEGATE_SHIFT)|
((y&1)<<UREG_CHANNEL_Y_NEGATE_SHIFT)|
((z&1)<<UREG_CHANNEL_Z_NEGATE_SHIFT)|
((w&1)<<UREG_CHANNEL_W_NEGATE_SHIFT));
}
extern GLuint i915_get_temp( struct i915_fragment_program *p );
extern GLuint i915_get_utemp( struct i915_fragment_program *p );
extern void i915_release_utemps( struct i915_fragment_program *p );
extern GLuint i915_emit_texld( struct i915_fragment_program *p,
GLuint dest,
GLuint destmask,
GLuint sampler,
GLuint coord,
GLuint op );
extern GLuint i915_emit_arith( struct i915_fragment_program *p,
GLuint op,
GLuint dest,
GLuint mask,
GLuint saturate,
GLuint src0,
GLuint src1,
GLuint src2 );
extern GLuint i915_emit_decl( struct i915_fragment_program *p,
GLuint type, GLuint nr, GLuint d0_flags );
extern GLuint i915_emit_const1f( struct i915_fragment_program *p,
GLfloat c0 );
extern GLuint i915_emit_const2f( struct i915_fragment_program *p,
GLfloat c0, GLfloat c1 );
extern GLuint i915_emit_const4fv( struct i915_fragment_program *p,
const GLfloat *c );
extern GLuint i915_emit_const4f( struct i915_fragment_program *p,
GLfloat c0, GLfloat c1,
GLfloat c2, GLfloat c3 );
extern GLuint i915_emit_param4fv( struct i915_fragment_program *p,
const GLfloat *values );
extern void i915_program_error( struct i915_fragment_program *p,
const GLubyte *msg );
extern void i915_init_program( i915ContextPtr i915,
struct i915_fragment_program *p );
extern void i915_upload_program( i915ContextPtr i915,
struct i915_fragment_program *p );
extern void i915_fini_program( struct i915_fragment_program *p );
#endif
+859
View File
@@ -0,0 +1,859 @@
/**************************************************************************
*
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
**************************************************************************/
#ifndef _I915_REG_H_
#define _I915_REG_H_
#include "intel_reg.h"
#define I915_SET_FIELD( var, mask, value ) (var &= ~(mask), var |= value)
#define CMD_3D (0x3<<29)
#define PRIM3D_INLINE (CMD_3D | (0x1f<<24))
#define PRIM3D_TRILIST (0x0<<18)
#define PRIM3D_TRISTRIP (0x1<<18)
#define PRIM3D_TRISTRIP_RVRSE (0x2<<18)
#define PRIM3D_TRIFAN (0x3<<18)
#define PRIM3D_POLY (0x4<<18)
#define PRIM3D_LINELIST (0x5<<18)
#define PRIM3D_LINESTRIP (0x6<<18)
#define PRIM3D_RECTLIST (0x7<<18)
#define PRIM3D_POINTLIST (0x8<<18)
#define PRIM3D_DIB (0x9<<18)
#define PRIM3D_CLEAR_RECT (0xa<<18)
#define PRIM3D_ZONE_INIT (0xd<<18)
#define PRIM3D_MASK (0x1f<<18)
/* p137 */
#define _3DSTATE_AA_CMD (CMD_3D | (0x06<<24))
#define AA_LINE_ECAAR_WIDTH_ENABLE (1<<16)
#define AA_LINE_ECAAR_WIDTH_0_5 0
#define AA_LINE_ECAAR_WIDTH_1_0 (1<<14)
#define AA_LINE_ECAAR_WIDTH_2_0 (2<<14)
#define AA_LINE_ECAAR_WIDTH_4_0 (3<<14)
#define AA_LINE_REGION_WIDTH_ENABLE (1<<8)
#define AA_LINE_REGION_WIDTH_0_5 0
#define AA_LINE_REGION_WIDTH_1_0 (1<<6)
#define AA_LINE_REGION_WIDTH_2_0 (2<<6)
#define AA_LINE_REGION_WIDTH_4_0 (3<<6)
/* 3DSTATE_BACKFACE_STENCIL_OPS, p138*/
#define _3DSTATE_BACKFACE_STENCIL_OPS (CMD_3D | (0x8<<24))
#define BFO_ENABLE_STENCIL_REF (1<<23)
#define BFO_STENCIL_REF_SHIFT 15
#define BFO_STENCIL_REF_MASK (0xff<<15)
#define BFO_ENABLE_STENCIL_FUNCS (1<<14)
#define BFO_STENCIL_TEST_SHIFT 11
#define BFO_STENCIL_TEST_MASK (0x7<<11)
#define BFO_STENCIL_FAIL_SHIFT 8
#define BFO_STENCIL_FAIL_MASK (0x7<<8)
#define BFO_STENCIL_PASS_Z_FAIL_SHIFT 5
#define BFO_STENCIL_PASS_Z_FAIL_MASK (0x7<<5)
#define BFO_STENCIL_PASS_Z_PASS_SHIFT 2
#define BFO_STENCIL_PASS_Z_PASS_MASK (0x7<<2)
#define BFO_ENABLE_STENCIL_TWO_SIDE (1<<1)
#define BFO_STENCIL_TWO_SIDE (1<<0)
/* 3DSTATE_BACKFACE_STENCIL_MASKS, p140 */
#define _3DSTATE_BACKFACE_STENCIL_MASKS (CMD_3D | (0x9<<24))
#define BFM_ENABLE_STENCIL_TEST_MASK (1<<17)
#define BFM_ENABLE_STENCIL_WRITE_MASK (1<<16)
#define BFM_STENCIL_TEST_MASK_SHIFT 8
#define BFM_STENCIL_TEST_MASK_MASK (0xff<<8)
#define BFM_STENCIL_WRITE_MASK_SHIFT 0
#define BFM_STENCIL_WRITE_MASK_MASK (0xff<<0)
/* 3DSTATE_BIN_CONTROL p141 */
/* p143 */
#define _3DSTATE_BUF_INFO_CMD (CMD_3D | (0x1d<<24) | (0x8e<<16) | 1)
/* Dword 1 */
#define BUF_3D_ID_COLOR_BACK (0x3<<24)
#define BUF_3D_ID_DEPTH (0x7<<24)
#define BUF_3D_USE_FENCE (1<<23)
#define BUF_3D_TILED_SURFACE (1<<22)
#define BUF_3D_TILE_WALK_X 0
#define BUF_3D_TILE_WALK_Y (1<<21)
#define BUF_3D_PITCH(x) (((x)/4)<<2)
/* Dword 2 */
#define BUF_3D_ADDR(x) ((x) & ~0x3)
/* 3DSTATE_CHROMA_KEY */
/* 3DSTATE_CLEAR_PARAMETERS, p150 */
/* 3DSTATE_CONSTANT_BLEND_COLOR, p153 */
#define _3DSTATE_CONST_BLEND_COLOR_CMD (CMD_3D | (0x1d<<24) | (0x88<<16))
/* 3DSTATE_COORD_SET_BINDINGS, p154 */
#define _3DSTATE_COORD_SET_BINDINGS (CMD_3D | (0x16<<24))
#define CSB_TCB(iunit, eunit) ((eunit)<<(iunit*3))
/* p156 */
#define _3DSTATE_DFLT_DIFFUSE_CMD (CMD_3D | (0x1d<<24) | (0x99<<16))
/* p157 */
#define _3DSTATE_DFLT_SPEC_CMD (CMD_3D | (0x1d<<24) | (0x9a<<16))
/* p158 */
#define _3DSTATE_DFLT_Z_CMD (CMD_3D | (0x1d<<24) | (0x98<<16))
/* 3DSTATE_DEPTH_OFFSET_SCALE, p159 */
#define _3DSTATE_DEPTH_OFFSET_SCALE (CMD_3D | (0x1d<<24) | (0x97<<16))
/* scale in dword 1 */
/* 3DSTATE_DEPTH_SUBRECT_DISABLE, p160 */
#define _3DSTATE_DEPTH_SUBRECT_DISABLE (CMD_3D | (0x1c<<24) | (0x11<19) | 0x2)
/* p161 */
#define _3DSTATE_DST_BUF_VARS_CMD (CMD_3D | (0x1d<<24) | (0x85<<16))
/* Dword 1 */
#define TEX_DEFAULT_COLOR_OGL (0<<30)
#define TEX_DEFAULT_COLOR_D3D (1<<30)
#define ZR_EARLY_DEPTH (1<<29)
#define LOD_PRECLAMP_OGL (1<<28)
#define LOD_PRECLAMP_D3D (0<<28)
#define DITHER_FULL_ALWAYS (0<<26)
#define DITHER_FULL_ON_FB_BLEND (1<<26)
#define DITHER_CLAMPED_ALWAYS (2<<26)
#define LINEAR_GAMMA_BLEND_32BPP (1<<25)
#define DEBUG_DISABLE_ENH_DITHER (1<<24)
#define DSTORG_HORT_BIAS(x) ((x)<<20)
#define DSTORG_VERT_BIAS(x) ((x)<<16)
#define COLOR_4_2_2_CHNL_WRT_ALL 0
#define COLOR_4_2_2_CHNL_WRT_Y (1<<12)
#define COLOR_4_2_2_CHNL_WRT_CR (2<<12)
#define COLOR_4_2_2_CHNL_WRT_CB (3<<12)
#define COLOR_4_2_2_CHNL_WRT_CRCB (4<<12)
#define COLR_BUF_8BIT 0
#define COLR_BUF_RGB555 (1<<8)
#define COLR_BUF_RGB565 (2<<8)
#define COLR_BUF_ARGB8888 (3<<8)
#define DEPTH_FRMT_16_FIXED 0
#define DEPTH_FRMT_16_FLOAT (1<<2)
#define DEPTH_FRMT_24_FIXED_8_OTHER (2<<2)
#define VERT_LINE_STRIDE_1 (1<<1)
#define VERT_LINE_STRIDE_0 (0<<1)
#define VERT_LINE_STRIDE_OFS_1 1
#define VERT_LINE_STRIDE_OFS_0 0
/* p166 */
#define _3DSTATE_DRAW_RECT_CMD (CMD_3D|(0x1d<<24)|(0x80<<16)|3)
/* Dword 1 */
#define DRAW_RECT_DIS_DEPTH_OFS (1<<30)
#define DRAW_DITHER_OFS_X(x) ((x)<<26)
#define DRAW_DITHER_OFS_Y(x) ((x)<<24)
/* Dword 2 */
#define DRAW_YMIN(x) ((x)<<16)
#define DRAW_XMIN(x) (x)
/* Dword 3 */
#define DRAW_YMAX(x) ((x)<<16)
#define DRAW_XMAX(x) (x)
/* Dword 4 */
#define DRAW_YORG(x) ((x)<<16)
#define DRAW_XORG(x) (x)
/* 3DSTATE_FILTER_COEFFICIENTS_4X4, p170 */
/* 3DSTATE_FILTER_COEFFICIENTS_6X5, p172 */
/* _3DSTATE_FOG_COLOR, p173 */
#define _3DSTATE_FOG_COLOR_CMD (CMD_3D|(0x15<<24))
#define FOG_COLOR_RED(x) ((x)<<16)
#define FOG_COLOR_GREEN(x) ((x)<<8)
#define FOG_COLOR_BLUE(x) (x)
/* _3DSTATE_FOG_MODE, p174 */
#define _3DSTATE_FOG_MODE_CMD (CMD_3D|(0x1d<<24)|(0x89<<16)|2)
/* Dword 1 */
#define FMC1_FOGFUNC_MODIFY_ENABLE (1<<31)
#define FMC1_FOGFUNC_VERTEX (0<<28)
#define FMC1_FOGFUNC_PIXEL_EXP (1<<28)
#define FMC1_FOGFUNC_PIXEL_EXP2 (2<<28)
#define FMC1_FOGFUNC_PIXEL_LINEAR (3<<28)
#define FMC1_FOGFUNC_MASK (3<<28)
#define FMC1_FOGINDEX_MODIFY_ENABLE (1<<27)
#define FMC1_FOGINDEX_Z (0<<25)
#define FMC1_FOGINDEX_W (1<<25)
#define FMC1_C1_C2_MODIFY_ENABLE (1<<24)
#define FMC1_DENSITY_MODIFY_ENABLE (1<<23)
#define FMC1_C1_ONE (1<<13)
#define FMC1_C1_MASK (0xffff<<4)
/* Dword 2 */
#define FMC2_C2_ONE (1<<16)
/* Dword 3 */
#define FMC3_D_ONE (1<<16)
/* _3DSTATE_INDEPENDENT_ALPHA_BLEND, p177 */
#define _3DSTATE_INDEPENDENT_ALPHA_BLEND_CMD (CMD_3D|(0x0b<<24))
#define IAB_MODIFY_ENABLE (1<<23)
#define IAB_ENABLE (1<<22)
#define IAB_MODIFY_FUNC (1<<21)
#define IAB_FUNC_SHIFT 16
#define IAB_MODIFY_SRC_FACTOR (1<<11)
#define IAB_SRC_FACTOR_SHIFT 6
#define IAB_SRC_FACTOR_MASK (BLENDFACT_MASK<<6)
#define IAB_MODIFY_DST_FACTOR (1<<5)
#define IAB_DST_FACTOR_SHIFT 0
#define IAB_DST_FACTOR_MASK (BLENDFACT_MASK<<0)
#define BLENDFACT_ZERO 0x01
#define BLENDFACT_ONE 0x02
#define BLENDFACT_SRC_COLR 0x03
#define BLENDFACT_INV_SRC_COLR 0x04
#define BLENDFACT_SRC_ALPHA 0x05
#define BLENDFACT_INV_SRC_ALPHA 0x06
#define BLENDFACT_DST_ALPHA 0x07
#define BLENDFACT_INV_DST_ALPHA 0x08
#define BLENDFACT_DST_COLR 0x09
#define BLENDFACT_INV_DST_COLR 0x0a
#define BLENDFACT_SRC_ALPHA_SATURATE 0x0b
#define BLENDFACT_CONST_COLOR 0x0c
#define BLENDFACT_INV_CONST_COLOR 0x0d
#define BLENDFACT_CONST_ALPHA 0x0e
#define BLENDFACT_INV_CONST_ALPHA 0x0f
#define BLENDFACT_MASK 0x0f
#define BLENDFUNC_ADD 0x0
#define BLENDFUNC_SUBTRACT 0x1
#define BLENDFUNC_REVERSE_SUBTRACT 0x2
#define BLENDFUNC_MIN 0x3
#define BLENDFUNC_MAX 0x4
#define BLENDFUNC_MASK 0x7
/* 3DSTATE_LOAD_INDIRECT, p180 */
#define _3DSTATE_LOAD_INDIRECT (CMD_3D|(0x1d<<24)|(0x7<<16))
#define LI0_STATE_STATIC_INDIRECT (0x01<<8)
#define LI0_STATE_DYNAMIC_INDIRECT (0x02<<8)
#define LI0_STATE_SAMPLER (0x04<<8)
#define LI0_STATE_MAP (0x08<<8)
#define LI0_STATE_PROGRAM (0x10<<8)
#define LI0_STATE_CONSTANTS (0x20<<8)
#define SIS0_BUFFER_ADDRESS(x) ((x)&~0x3)
#define SIS0_FORCE_LOAD (1<<1)
#define SIS0_BUFFER_VALID (1<<0)
#define SIS1_BUFFER_LENGTH(x) ((x)&0xff)
#define DIS0_BUFFER_ADDRESS(x) ((x)&~0x3)
#define DIS0_BUFFER_RESET (1<<1)
#define DIS0_BUFFER_VALID (1<<0)
#define SSB0_BUFFER_ADDRESS(x) ((x)&~0x3)
#define SSB0_FORCE_LOAD (1<<1)
#define SSB0_BUFFER_VALID (1<<0)
#define SSB1_BUFFER_LENGTH(x) ((x)&0xff)
#define MSB0_BUFFER_ADDRESS(x) ((x)&~0x3)
#define MSB0_FORCE_LOAD (1<<1)
#define MSB0_BUFFER_VALID (1<<0)
#define MSB1_BUFFER_LENGTH(x) ((x)&0xff)
#define PSP0_BUFFER_ADDRESS(x) ((x)&~0x3)
#define PSP0_FORCE_LOAD (1<<1)
#define PSP0_BUFFER_VALID (1<<0)
#define PSP1_BUFFER_LENGTH(x) ((x)&0xff)
#define PSC0_BUFFER_ADDRESS(x) ((x)&~0x3)
#define PSC0_FORCE_LOAD (1<<1)
#define PSC0_BUFFER_VALID (1<<0)
#define PSC1_BUFFER_LENGTH(x) ((x)&0xff)
/* _3DSTATE_RASTERIZATION_RULES */
#define _3DSTATE_RASTER_RULES_CMD (CMD_3D|(0x07<<24))
#define ENABLE_POINT_RASTER_RULE (1<<15)
#define OGL_POINT_RASTER_RULE (1<<13)
#define ENABLE_TEXKILL_3D_4D (1<<10)
#define TEXKILL_3D (0<<9)
#define TEXKILL_4D (1<<9)
#define ENABLE_LINE_STRIP_PROVOKE_VRTX (1<<8)
#define ENABLE_TRI_FAN_PROVOKE_VRTX (1<<5)
#define LINE_STRIP_PROVOKE_VRTX(x) ((x)<<6)
#define TRI_FAN_PROVOKE_VRTX(x) ((x)<<3)
/* _3DSTATE_SCISSOR_ENABLE, p256 */
#define _3DSTATE_SCISSOR_ENABLE_CMD (CMD_3D|(0x1c<<24)|(0x10<<19))
#define ENABLE_SCISSOR_RECT ((1<<1) | 1)
#define DISABLE_SCISSOR_RECT (1<<1)
/* _3DSTATE_SCISSOR_RECTANGLE_0, p257 */
#define _3DSTATE_SCISSOR_RECT_0_CMD (CMD_3D|(0x1d<<24)|(0x81<<16)|1)
/* Dword 1 */
#define SCISSOR_RECT_0_YMIN(x) ((x)<<16)
#define SCISSOR_RECT_0_XMIN(x) (x)
/* Dword 2 */
#define SCISSOR_RECT_0_YMAX(x) ((x)<<16)
#define SCISSOR_RECT_0_XMAX(x) (x)
/* p189 */
#define _3DSTATE_LOAD_STATE_IMMEDIATE_1 ((0x3<<29)|(0x1d<<24)|(0x04<<16))
#define I1_LOAD_S(n) (1<<(4+n))
#define S0_VB_OFFSET_MASK 0xffffffc
#define S0_AUTO_CACHE_INV_DISABLE (1<<0)
#define S1_VERTEX_WIDTH_SHIFT 24
#define S1_VERTEX_WIDTH_MASK (0x3f<<24)
#define S1_VERTEX_PITCH_SHIFT 16
#define S1_VERTEX_PITCH_MASK (0x3f<<16)
#define TEXCOORDFMT_2D 0x0
#define TEXCOORDFMT_3D 0x1
#define TEXCOORDFMT_4D 0x2
#define TEXCOORDFMT_1D 0x3
#define TEXCOORDFMT_2D_16 0x4
#define TEXCOORDFMT_4D_16 0x5
#define TEXCOORDFMT_NOT_PRESENT 0xf
#define S2_TEXCOORD_FMT0_MASK 0xf
#define S2_TEXCOORD_FMT1_SHIFT 4
#define S2_TEXCOORD_FMT(unit, type) ((type)<<(unit*4))
#define S2_TEXCOORD_NONE (~0)
/* S3 not interesting */
#define S4_POINT_WIDTH_SHIFT 23
#define S4_POINT_WIDTH_MASK (0x1ff<<23)
#define S4_LINE_WIDTH_SHIFT 19
#define S4_LINE_WIDTH_ONE (0x2<<19)
#define S4_LINE_WIDTH_MASK (0xf<<19)
#define S4_FLATSHADE_ALPHA (1<<18)
#define S4_FLATSHADE_FOG (1<<17)
#define S4_FLATSHADE_SPECULAR (1<<16)
#define S4_FLATSHADE_COLOR (1<<15)
#define S4_CULLMODE_BOTH (0<<13)
#define S4_CULLMODE_NONE (1<<13)
#define S4_CULLMODE_CW (2<<13)
#define S4_CULLMODE_CCW (3<<13)
#define S4_CULLMODE_MASK (3<<13)
#define S4_VFMT_POINT_WIDTH (1<<12)
#define S4_VFMT_SPEC_FOG (1<<11)
#define S4_VFMT_COLOR (1<<10)
#define S4_VFMT_DEPTH_OFFSET (1<<9)
#define S4_VFMT_XYZ (1<<6)
#define S4_VFMT_XYZW (2<<6)
#define S4_VFMT_XY (3<<6)
#define S4_VFMT_XYW (4<<6)
#define S4_VFMT_XYZW_MASK (7<<6)
#define S4_FORCE_DEFAULT_DIFFUSE (1<<5)
#define S4_FORCE_DEFAULT_SPECULAR (1<<4)
#define S4_LOCAL_DEPTH_OFFSET_ENABLE (1<<3)
#define S4_VFMT_FOG_PARAM (1<<2)
#define S4_SPRITE_POINT_ENABLE (1<<1)
#define S4_LINE_ANTIALIAS_ENABLE (1<<0)
#define S4_VFMT_MASK (S4_VFMT_POINT_WIDTH | \
S4_VFMT_SPEC_FOG | \
S4_VFMT_COLOR | \
S4_VFMT_DEPTH_OFFSET | \
S4_VFMT_XYZW_MASK | \
S4_VFMT_FOG_PARAM)
#define COMPAREFUNC_ALWAYS 0
#define COMPAREFUNC_NEVER 0x1
#define COMPAREFUNC_LESS 0x2
#define COMPAREFUNC_EQUAL 0x3
#define COMPAREFUNC_LEQUAL 0x4
#define COMPAREFUNC_GREATER 0x5
#define COMPAREFUNC_NOTEQUAL 0x6
#define COMPAREFUNC_GEQUAL 0x7
#define STENCILOP_KEEP 0
#define STENCILOP_ZERO 0x1
#define STENCILOP_REPLACE 0x2
#define STENCILOP_INCRSAT 0x3
#define STENCILOP_DECRSAT 0x4
#define STENCILOP_INCR 0x5
#define STENCILOP_DECR 0x6
#define STENCILOP_INVERT 0x7
#define S5_WRITEDISABLE_ALPHA (1<<31)
#define S5_WRITEDISABLE_RED (1<<30)
#define S5_WRITEDISABLE_GREEN (1<<29)
#define S5_WRITEDISABLE_BLUE (1<<28)
#define S5_WRITEDISABLE_MASK (0xf<<28)
#define S5_FORCE_DEFAULT_POINT_SIZE (1<<27)
#define S5_LAST_PIXEL_ENABLE (1<<26)
#define S5_GLOBAL_DEPTH_OFFSET_ENABLE (1<<25)
#define S5_FOG_ENABLE (1<<24)
#define S5_STENCIL_REF_SHIFT 16
#define S5_STENCIL_REF_MASK (0xff<<16)
#define S5_STENCIL_TEST_FUNC_SHIFT 13
#define S5_STENCIL_TEST_FUNC_MASK (0x7<<13)
#define S5_STENCIL_FAIL_SHIFT 10
#define S5_STENCIL_FAIL_MASK (0x7<<10)
#define S5_STENCIL_PASS_Z_FAIL_SHIFT 7
#define S5_STENCIL_PASS_Z_FAIL_MASK (0x7<<7)
#define S5_STENCIL_PASS_Z_PASS_SHIFT 4
#define S5_STENCIL_PASS_Z_PASS_MASK (0x7<<4)
#define S5_STENCIL_WRITE_ENABLE (1<<3)
#define S5_STENCIL_TEST_ENABLE (1<<2)
#define S5_COLOR_DITHER_ENABLE (1<<1)
#define S5_LOGICOP_ENABLE (1<<0)
#define S6_ALPHA_TEST_ENABLE (1<<31)
#define S6_ALPHA_TEST_FUNC_SHIFT 28
#define S6_ALPHA_TEST_FUNC_MASK (0x7<<28)
#define S6_ALPHA_REF_SHIFT 20
#define S6_ALPHA_REF_MASK (0xff<<20)
#define S6_DEPTH_TEST_ENABLE (1<<19)
#define S6_DEPTH_TEST_FUNC_SHIFT 16
#define S6_DEPTH_TEST_FUNC_MASK (0x7<<16)
#define S6_CBUF_BLEND_ENABLE (1<<15)
#define S6_CBUF_BLEND_FUNC_SHIFT 12
#define S6_CBUF_BLEND_FUNC_MASK (0x7<<12)
#define S6_CBUF_SRC_BLEND_FACT_SHIFT 8
#define S6_CBUF_SRC_BLEND_FACT_MASK (0xf<<8)
#define S6_CBUF_DST_BLEND_FACT_SHIFT 4
#define S6_CBUF_DST_BLEND_FACT_MASK (0xf<<4)
#define S6_DEPTH_WRITE_ENABLE (1<<3)
#define S6_COLOR_WRITE_ENABLE (1<<2)
#define S6_TRISTRIP_PV_SHIFT 0
#define S6_TRISTRIP_PV_MASK (0x3<<0)
#define S7_DEPTH_OFFSET_CONST_MASK ~0
/* 3DSTATE_MAP_DEINTERLACER_PARAMETERS */
/* 3DSTATE_MAP_PALETTE_LOAD_32, p206 */
/* _3DSTATE_MODES_4, p218 */
#define _3DSTATE_MODES_4_CMD (CMD_3D|(0x0d<<24))
#define ENABLE_LOGIC_OP_FUNC (1<<23)
#define LOGIC_OP_FUNC(x) ((x)<<18)
#define LOGICOP_MASK ((1<<18)|(1<<19)|(1<<20)|(1<<21))
#define LOGICOP_CLEAR 0
#define LOGICOP_NOR 0x1
#define LOGICOP_AND_INV 0x2
#define LOGICOP_COPY_INV 0x3
#define LOGICOP_AND_RVRSE 0x4
#define LOGICOP_INV 0x5
#define LOGICOP_XOR 0x6
#define LOGICOP_NAND 0x7
#define LOGICOP_AND 0x8
#define LOGICOP_EQUIV 0x9
#define LOGICOP_NOOP 0xa
#define LOGICOP_OR_INV 0xb
#define LOGICOP_COPY 0xc
#define LOGICOP_OR_RVRSE 0xd
#define LOGICOP_OR 0xe
#define LOGICOP_SET 0xf
#define MODE4_ENABLE_STENCIL_TEST_MASK ((1<<17)|(0xff00))
#define ENABLE_STENCIL_TEST_MASK (1<<17)
#define STENCIL_TEST_MASK(x) ((x)<<8)
#define MODE4_ENABLE_STENCIL_WRITE_MASK ((1<<16)|(0x00ff))
#define ENABLE_STENCIL_WRITE_MASK (1<<16)
#define STENCIL_WRITE_MASK(x) (x)
/* _3DSTATE_MODES_5, p220 */
#define _3DSTATE_MODES_5_CMD (CMD_3D|(0x0c<<24))
#define PIPELINE_FLUSH_RENDER_CACHE (1<<18)
#define PIPELINE_FLUSH_TEXTURE_CACHE (1<<16)
/* p221 */
#define _3DSTATE_PIXEL_SHADER_CONSTANTS (CMD_3D|(0x1d<<24)|(0x6<<16))
#define PS1_REG(n) (1<<(n))
#define PS2_CONST_X(n) (n)
#define PS3_CONST_Y(n) (n)
#define PS4_CONST_Z(n) (n)
#define PS5_CONST_W(n) (n)
/* p222 */
#define I915_MAX_TEX_INDIRECT 4
#define I915_MAX_TEX_INSN 32
#define I915_MAX_ALU_INSN 64
#define I915_MAX_DECL_INSN 27
#define I915_MAX_TEMPORARY 16
/* Each instruction is 3 dwords long, though most don't require all
* this space. Maximum of 123 instructions. Smaller maxes per insn
* type.
*/
#define _3DSTATE_PIXEL_SHADER_PROGRAM (CMD_3D|(0x1d<<24)|(0x5<<16))
#define REG_TYPE_R 0 /* temporary regs, no need to
* dcl, must be written before
* read -- Preserved between
* phases.
*/
#define REG_TYPE_T 1 /* Interpolated values, must be
* dcl'ed before use.
*
* 0..7: texture coord,
* 8: diffuse spec,
* 9: specular color,
* 10: fog parameter in w.
*/
#define REG_TYPE_CONST 2 /* Restriction: only one const
* can be referenced per
* instruction, though it may be
* selected for multiple inputs.
* Constants not initialized
* default to zero.
*/
#define REG_TYPE_S 3 /* sampler */
#define REG_TYPE_OC 4 /* output color (rgba) */
#define REG_TYPE_OD 5 /* output depth (w), xyz are
* temporaries. If not written,
* interpolated depth is used?
*/
#define REG_TYPE_U 6 /* unpreserved temporaries */
#define REG_TYPE_MASK 0x7
#define REG_NR_MASK 0xf
/* REG_TYPE_T:
*/
#define T_TEX0 0
#define T_TEX1 1
#define T_TEX2 2
#define T_TEX3 3
#define T_TEX4 4
#define T_TEX5 5
#define T_TEX6 6
#define T_TEX7 7
#define T_DIFFUSE 8
#define T_SPECULAR 9
#define T_FOG_W 10 /* interpolated fog is in W coord */
/* Arithmetic instructions */
/* .replicate_swizzle == selection and replication of a particular
* scalar channel, ie., .xxxx, .yyyy, .zzzz or .wwww
*/
#define A0_NOP (0x0<<24) /* no operation */
#define A0_ADD (0x1<<24) /* dst = src0 + src1 */
#define A0_MOV (0x2<<24) /* dst = src0 */
#define A0_MUL (0x3<<24) /* dst = src0 * src1 */
#define A0_MAD (0x4<<24) /* dst = src0 * src1 + src2 */
#define A0_DP2ADD (0x5<<24) /* dst.xyzw = src0.xy dot src1.xy + src2.replicate_swizzle */
#define A0_DP3 (0x6<<24) /* dst.xyzw = src0.xyz dot src1.xyz */
#define A0_DP4 (0x7<<24) /* dst.xyzw = src0.xyzw dot src1.xyzw */
#define A0_FRC (0x8<<24) /* dst = src0 - floor(src0) */
#define A0_RCP (0x9<<24) /* dst.xyzw = 1/(src0.replicate_swizzle) */
#define A0_RSQ (0xa<<24) /* dst.xyzw = 1/(sqrt(abs(src0.replicate_swizzle))) */
#define A0_EXP (0xb<<24) /* dst.xyzw = exp2(src0.replicate_swizzle) */
#define A0_LOG (0xc<<24) /* dst.xyzw = log2(abs(src0.replicate_swizzle)) */
#define A0_CMP (0xd<<24) /* dst = (src0 >= 0.0) ? src1 : src2 */
#define A0_MIN (0xe<<24) /* dst = (src0 < src1) ? src0 : src1 */
#define A0_MAX (0xf<<24) /* dst = (src0 >= src1) ? src0 : src1 */
#define A0_FLR (0x10<<24) /* dst = floor(src0) */
#define A0_MOD (0x11<<24) /* dst = src0 fmod 1.0 */
#define A0_TRC (0x12<<24) /* dst = int(src0) */
#define A0_SGE (0x13<<24) /* dst = src0 >= src1 ? 1.0 : 0.0 */
#define A0_SLT (0x14<<24) /* dst = src0 < src1 ? 1.0 : 0.0 */
#define A0_DEST_SATURATE (1<<22)
#define A0_DEST_TYPE_SHIFT 19
/* Allow: R, OC, OD, U */
#define A0_DEST_NR_SHIFT 14
/* Allow R: 0..15, OC,OD: 0..0, U: 0..2 */
#define A0_DEST_CHANNEL_X (1<<10)
#define A0_DEST_CHANNEL_Y (2<<10)
#define A0_DEST_CHANNEL_Z (4<<10)
#define A0_DEST_CHANNEL_W (8<<10)
#define A0_DEST_CHANNEL_ALL (0xf<<10)
#define A0_DEST_CHANNEL_SHIFT 10
#define A0_SRC0_TYPE_SHIFT 7
#define A0_SRC0_NR_SHIFT 2
#define A0_DEST_CHANNEL_XY (A0_DEST_CHANNEL_X|A0_DEST_CHANNEL_Y)
#define A0_DEST_CHANNEL_XYZ (A0_DEST_CHANNEL_XY|A0_DEST_CHANNEL_Z)
#define SRC_X 0
#define SRC_Y 1
#define SRC_Z 2
#define SRC_W 3
#define SRC_ZERO 4
#define SRC_ONE 5
#define A1_SRC0_CHANNEL_X_NEGATE (1<<31)
#define A1_SRC0_CHANNEL_X_SHIFT 28
#define A1_SRC0_CHANNEL_Y_NEGATE (1<<27)
#define A1_SRC0_CHANNEL_Y_SHIFT 24
#define A1_SRC0_CHANNEL_Z_NEGATE (1<<23)
#define A1_SRC0_CHANNEL_Z_SHIFT 20
#define A1_SRC0_CHANNEL_W_NEGATE (1<<19)
#define A1_SRC0_CHANNEL_W_SHIFT 16
#define A1_SRC1_TYPE_SHIFT 13
#define A1_SRC1_NR_SHIFT 8
#define A1_SRC1_CHANNEL_X_NEGATE (1<<7)
#define A1_SRC1_CHANNEL_X_SHIFT 4
#define A1_SRC1_CHANNEL_Y_NEGATE (1<<3)
#define A1_SRC1_CHANNEL_Y_SHIFT 0
#define A2_SRC1_CHANNEL_Z_NEGATE (1<<31)
#define A2_SRC1_CHANNEL_Z_SHIFT 28
#define A2_SRC1_CHANNEL_W_NEGATE (1<<27)
#define A2_SRC1_CHANNEL_W_SHIFT 24
#define A2_SRC2_TYPE_SHIFT 21
#define A2_SRC2_NR_SHIFT 16
#define A2_SRC2_CHANNEL_X_NEGATE (1<<15)
#define A2_SRC2_CHANNEL_X_SHIFT 12
#define A2_SRC2_CHANNEL_Y_NEGATE (1<<11)
#define A2_SRC2_CHANNEL_Y_SHIFT 8
#define A2_SRC2_CHANNEL_Z_NEGATE (1<<7)
#define A2_SRC2_CHANNEL_Z_SHIFT 4
#define A2_SRC2_CHANNEL_W_NEGATE (1<<3)
#define A2_SRC2_CHANNEL_W_SHIFT 0
/* Texture instructions */
#define T0_TEXLD (0x15<<24) /* Sample texture using predeclared
* sampler and address, and output
* filtered texel data to destination
* register */
#define T0_TEXLDP (0x16<<24) /* Same as texld but performs a
* perspective divide of the texture
* coordinate .xyz values by .w before
* sampling. */
#define T0_TEXLDB (0x17<<24) /* Same as texld but biases the
* computed LOD by w. Only S4.6 two's
* comp is used. This implies that a
* float to fixed conversion is
* done. */
#define T0_TEXKILL (0x18<<24) /* Does not perform a sampling
* operation. Simply kills the pixel
* if any channel of the address
* register is < 0.0. */
#define T0_DEST_TYPE_SHIFT 19
/* Allow: R, OC, OD, U */
/* Note: U (unpreserved) regs do not retain their values between
* phases (cannot be used for feedback)
*
* Note: oC and OD registers can only be used as the destination of a
* texture instruction once per phase (this is an implementation
* restriction).
*/
#define T0_DEST_NR_SHIFT 14
/* Allow R: 0..15, OC,OD: 0..0, U: 0..2 */
#define T0_SAMPLER_NR_SHIFT 0 /* This field ignored for TEXKILL */
#define T0_SAMPLER_NR_MASK (0xf<<0)
#define T1_ADDRESS_REG_TYPE_SHIFT 24 /* Reg to use as texture coord */
/* Allow R, T, OC, OD -- R, OC, OD are 'dependent' reads, new program phase */
#define T1_ADDRESS_REG_NR_SHIFT 17
#define T2_MBZ 0
/* Declaration instructions */
#define D0_DCL (0x19<<24) /* Declare a t (interpolated attrib)
* register or an s (sampler)
* register. */
#define D0_SAMPLE_TYPE_SHIFT 22
#define D0_SAMPLE_TYPE_2D (0x0<<22)
#define D0_SAMPLE_TYPE_CUBE (0x1<<22)
#define D0_SAMPLE_TYPE_VOLUME (0x2<<22)
#define D0_SAMPLE_TYPE_MASK (0x3<<22)
#define D0_TYPE_SHIFT 19
/* Allow: T, S */
#define D0_NR_SHIFT 14
/* Allow T: 0..10, S: 0..15 */
#define D0_CHANNEL_X (1<<10)
#define D0_CHANNEL_Y (2<<10)
#define D0_CHANNEL_Z (4<<10)
#define D0_CHANNEL_W (8<<10)
#define D0_CHANNEL_ALL (0xf<<10)
#define D0_CHANNEL_NONE (0<<10)
#define D0_CHANNEL_XY (D0_CHANNEL_X|D0_CHANNEL_Y)
#define D0_CHANNEL_XYZ (D0_CHANNEL_XY|D0_CHANNEL_Z)
/* I915 Errata: Do not allow (xz), (xw), (xzw) combinations for diffuse
* or specular declarations.
*
* For T dcls, only allow: (x), (xy), (xyz), (w), (xyzw)
*
* Must be zero for S (sampler) dcls
*/
#define D1_MBZ 0
#define D2_MBZ 0
/* p207 */
#define _3DSTATE_MAP_STATE (CMD_3D|(0x1d<<24)|(0x0<<16))
#define MS1_MAPMASK_SHIFT 0
#define MS1_MAPMASK_MASK (0x8fff<<0)
#define MS2_UNTRUSTED_SURFACE (1<<31)
#define MS2_ADDRESS_MASK 0xfffffffc
#define MS2_VERTICAL_LINE_STRIDE (1<<1)
#define MS2_VERTICAL_OFFSET (1<<1)
#define MS3_HEIGHT_SHIFT 21
#define MS3_WIDTH_SHIFT 10
#define MS3_PALETTE_SELECT (1<<9)
#define MS3_MAPSURF_FORMAT_SHIFT 7
#define MS3_MAPSURF_FORMAT_MASK (0x7<<7)
#define MAPSURF_8BIT (1<<7)
#define MAPSURF_16BIT (2<<7)
#define MAPSURF_32BIT (3<<7)
#define MAPSURF_422 (5<<7)
#define MAPSURF_COMPRESSED (6<<7)
#define MAPSURF_4BIT_INDEXED (7<<7)
#define MS3_MT_FORMAT_MASK (0x7 << 3)
#define MS3_MT_FORMAT_SHIFT 3
#define MT_4BIT_IDX_ARGB8888 (7<<3) /* SURFACE_4BIT_INDEXED */
#define MT_8BIT_I8 (0<<3) /* SURFACE_8BIT */
#define MT_8BIT_L8 (1<<3)
#define MT_8BIT_A8 (4<<3)
#define MT_8BIT_MONO8 (5<<3)
#define MT_16BIT_RGB565 (0<<3) /* SURFACE_16BIT */
#define MT_16BIT_ARGB1555 (1<<3)
#define MT_16BIT_ARGB4444 (2<<3)
#define MT_16BIT_AY88 (3<<3)
#define MT_16BIT_88DVDU (5<<3)
#define MT_16BIT_BUMP_655LDVDU (6<<3)
#define MT_16BIT_I16 (7<<3)
#define MT_16BIT_L16 (8<<3)
#define MT_16BIT_A16 (9<<3)
#define MT_32BIT_ARGB8888 (0<<3) /* SURFACE_32BIT */
#define MT_32BIT_ABGR8888 (1<<3)
#define MT_32BIT_XRGB8888 (2<<3)
#define MT_32BIT_XBGR8888 (3<<3)
#define MT_32BIT_QWVU8888 (4<<3)
#define MT_32BIT_AXVU8888 (5<<3)
#define MT_32BIT_LXVU8888 (6<<3)
#define MT_32BIT_XLVU8888 (7<<3)
#define MT_32BIT_ARGB2101010 (8<<3)
#define MT_32BIT_ABGR2101010 (9<<3)
#define MT_422_YCRCB_SWAPY (0<<3) /* SURFACE_422 */
#define MT_422_YCRCB_NORMAL (1<<3)
#define MT_422_YCRCB_SWAPUV (2<<3)
#define MT_422_YCRCB_SWAPUVY (3<<3)
#define MT_COMPRESS_DXT1 (0<<3) /* SURFACE_COMPRESSED */
#define MT_COMPRESS_DXT2_3 (1<<3)
#define MT_COMPRESS_DXT4_5 (2<<3)
#define MT_COMPRESS_FXT1 (3<<3)
#define MT_COMPRESS_DXT1_RGB (4<<3)
#define MS3_USE_FENCE_REGS (1<<2)
#define MS3_TILED_SURFACE (1<<1)
#define MS3_TILE_WALK (1<<0)
#define MS4_PITCH_SHIFT 21
#define MS4_CUBE_FACE_ENA_NEGX (1<<20)
#define MS4_CUBE_FACE_ENA_POSX (1<<19)
#define MS4_CUBE_FACE_ENA_NEGY (1<<18)
#define MS4_CUBE_FACE_ENA_POSY (1<<17)
#define MS4_CUBE_FACE_ENA_NEGZ (1<<16)
#define MS4_CUBE_FACE_ENA_POSZ (1<<15)
#define MS4_CUBE_FACE_ENA_MASK (0x3f<<15)
#define MS4_MAX_LOD_SHIFT 9
#define MS4_MAX_LOD_MASK (0x3f<<9)
#define MS4_VOLUME_DEPTH_SHIFT 0
#define MS4_VOLUME_DEPTH_MASK (0xff<<0)
/* p244 */
#define _3DSTATE_SAMPLER_STATE (CMD_3D|(0x1d<<24)|(0x1<<16))
#define SS1_MAPMASK_SHIFT 0
#define SS1_MAPMASK_MASK (0x8fff<<0)
#define SS2_REVERSE_GAMMA_ENABLE (1<<31)
#define SS2_PACKED_TO_PLANAR_ENABLE (1<<30)
#define SS2_COLORSPACE_CONVERSION (1<<29)
#define SS2_CHROMAKEY_SHIFT 27
#define SS2_BASE_MIP_LEVEL_SHIFT 22
#define SS2_BASE_MIP_LEVEL_MASK (0x1f<<22)
#define SS2_MIP_FILTER_SHIFT 20
#define SS2_MIP_FILTER_MASK (0x3<<20)
#define MIPFILTER_NONE 0
#define MIPFILTER_NEAREST 1
#define MIPFILTER_LINEAR 3
#define SS2_MAG_FILTER_SHIFT 17
#define SS2_MAG_FILTER_MASK (0x7<<17)
#define FILTER_NEAREST 0
#define FILTER_LINEAR 1
#define FILTER_ANISOTROPIC 2
#define FILTER_4X4_1 3
#define FILTER_4X4_2 4
#define FILTER_4X4_FLAT 5
#define FILTER_6X5_MONO 6 /* XXX - check */
#define SS2_MIN_FILTER_SHIFT 14
#define SS2_MIN_FILTER_MASK (0x7<<14)
#define SS2_LOD_BIAS_SHIFT 5
#define SS2_LOD_BIAS_ONE (0x10<<5)
#define SS2_LOD_BIAS_MASK (0x1ff<<5)
#define SS2_SHADOW_ENABLE (1<<4)
#define SS2_MAX_ANISO_MASK (1<<3)
#define SS2_MAX_ANISO_2 (0<<3)
#define SS2_MAX_ANISO_4 (1<<3)
#define SS2_SHADOW_FUNC_SHIFT 0
#define SS2_SHADOW_FUNC_MASK (0x7<<0)
#define SHADOWOP_ALWAYS 0
#define SHADOWOP_NEVER 1
#define SHADOWOP_LESS 2
#define SHADOWOP_EQUAL 3
#define SHADOWOP_LEQUAL 4
#define SHADOWOP_GREATER 5
#define SHADOWOP_NOTEQUAL 6
#define SHADOWOP_GEQUAL 7
#define SS3_MIN_LOD_SHIFT 24
#define SS3_MIN_LOD_ONE (0x10<<24)
#define SS3_MIN_LOD_MASK (0xff<<24)
#define SS3_KILL_PIXEL_ENABLE (1<<17)
#define SS3_TCX_ADDR_MODE_SHIFT 12
#define SS3_TCX_ADDR_MODE_MASK (0x7<<12)
#define TEXCOORDMODE_WRAP 0
#define TEXCOORDMODE_MIRROR 1
#define TEXCOORDMODE_CLAMP_EDGE 2
#define TEXCOORDMODE_CUBE 3
#define TEXCOORDMODE_CLAMP_BORDER 4
#define TEXCOORDMODE_MIRROR_ONCE 5
#define SS3_TCY_ADDR_MODE_SHIFT 9
#define SS3_TCY_ADDR_MODE_MASK (0x7<<9)
#define SS3_TCZ_ADDR_MODE_SHIFT 6
#define SS3_TCZ_ADDR_MODE_MASK (0x7<<6)
#define SS3_NORMALIZED_COORDS (1<<5)
#define SS3_TEXTUREMAP_INDEX_SHIFT 1
#define SS3_TEXTUREMAP_INDEX_MASK (0xf<<1)
#define SS3_DEINTERLACER_ENABLE (1<<0)
#define SS4_BORDER_COLOR_MASK (~0)
/* 3DSTATE_SPAN_STIPPLE, p258
*/
#define _3DSTATE_STIPPLE ((0x3<<29)|(0x1d<<24)|(0x83<<16))
#define ST1_ENABLE (1<<16)
#define ST1_MASK (0xffff)
#define MI_FLUSH ((0<<29)|(4<<23))
#define FLUSH_MAP_CACHE (1<<0)
#define FLUSH_RENDER_CACHE (1<<1)
#endif
File diff suppressed because it is too large Load Diff
+155
View File
@@ -0,0 +1,155 @@
/**************************************************************************
*
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
**************************************************************************/
#include "glheader.h"
#include "mtypes.h"
#include "imports.h"
#include "simple_list.h"
#include "enums.h"
#include "image.h"
#include "texstore.h"
#include "texformat.h"
#include "texmem.h"
#include "swrast/swrast.h"
#include "mm.h"
#include "intel_ioctl.h"
#include "i915_context.h"
#include "i915_reg.h"
/**
* Allocate space for and load the mesa images into the texture memory block.
* This will happen before drawing with a new texture, or drawing with a
* texture after it was swapped out or teximaged again.
*/
intelTextureObjectPtr i915AllocTexObj( struct gl_texture_object *texObj )
{
i915TextureObjectPtr t = CALLOC_STRUCT( i915_texture_object );
if ( !t )
return NULL;
texObj->DriverData = t;
t->intel.base.tObj = texObj;
t->intel.dirty = I915_UPLOAD_TEX_ALL;
make_empty_list( &t->intel.base );
return &t->intel;
}
static void i915TexParameter( GLcontext *ctx, GLenum target,
struct gl_texture_object *tObj,
GLenum pname, const GLfloat *params )
{
i915TextureObjectPtr t = (i915TextureObjectPtr) tObj->DriverData;
switch (pname) {
case GL_TEXTURE_MIN_FILTER:
case GL_TEXTURE_MAG_FILTER:
case GL_TEXTURE_MAX_ANISOTROPY_EXT:
case GL_TEXTURE_WRAP_S:
case GL_TEXTURE_WRAP_T:
case GL_TEXTURE_WRAP_R:
case GL_TEXTURE_BORDER_COLOR:
t->intel.dirty = I915_UPLOAD_TEX_ALL;
break;
case GL_TEXTURE_BASE_LEVEL:
case GL_TEXTURE_MAX_LEVEL:
case GL_TEXTURE_MIN_LOD:
case GL_TEXTURE_MAX_LOD:
/* The i915 and its successors can do a lot of this without
* reloading the textures. A project for someone?
*/
intelFlush( ctx );
driSwapOutTextureObject( (driTextureObject *) t );
t->intel.dirty = I915_UPLOAD_TEX_ALL;
break;
default:
return;
}
}
static void i915TexEnv( GLcontext *ctx, GLenum target,
GLenum pname, const GLfloat *param )
{
i915ContextPtr i915 = I915_CONTEXT( ctx );
GLuint unit = ctx->Texture.CurrentUnit;
switch (pname) {
case GL_TEXTURE_ENV_COLOR: /* Should be a tracked param */
case GL_TEXTURE_ENV_MODE:
case GL_COMBINE_RGB:
case GL_COMBINE_ALPHA:
case GL_SOURCE0_RGB:
case GL_SOURCE1_RGB:
case GL_SOURCE2_RGB:
case GL_SOURCE0_ALPHA:
case GL_SOURCE1_ALPHA:
case GL_SOURCE2_ALPHA:
case GL_OPERAND0_RGB:
case GL_OPERAND1_RGB:
case GL_OPERAND2_RGB:
case GL_OPERAND0_ALPHA:
case GL_OPERAND1_ALPHA:
case GL_OPERAND2_ALPHA:
case GL_RGB_SCALE:
case GL_ALPHA_SCALE:
i915->tex_program.translated = 0;
break;
case GL_TEXTURE_LOD_BIAS: {
int b = (int) ((*param) * 16.0);
if (b > 255) b = 255;
if (b < -256) b = -256;
I915_STATECHANGE(i915, I915_UPLOAD_TEX(unit));
i915->state.Tex[unit][I915_TEXREG_SS2] &= ~SS2_LOD_BIAS_MASK;
i915->state.Tex[unit][I915_TEXREG_SS2] |=
((b << SS2_LOD_BIAS_SHIFT) & SS2_LOD_BIAS_MASK);
break;
}
default:
break;
}
}
static void i915BindTexture( GLcontext *ctx, GLenum target,
struct gl_texture_object *texObj )
{
i915TextureObjectPtr tex = (i915TextureObjectPtr)texObj->DriverData;
if (tex->lastTarget != texObj->Target) {
tex->intel.dirty = I915_UPLOAD_TEX_ALL;
tex->lastTarget = texObj->Target;
}
/* Need this if image format changes between bound textures.
* Could try and shortcircuit by checking for differences in
* state between incoming and outgoing textures:
*/
I915_CONTEXT(ctx)->tex_program.translated = 0;
}
void i915InitTextureFuncs( struct dd_function_table *functions )
{
functions->BindTexture = i915BindTexture;
functions->TexEnv = i915TexEnv;
functions->TexParameter = i915TexParameter;
}
+635
View File
@@ -0,0 +1,635 @@
/**************************************************************************
*
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
**************************************************************************/
#include <strings.h>
#include "glheader.h"
#include "macros.h"
#include "enums.h"
#include "tnl/t_context.h"
#include "intel_batchbuffer.h"
#include "i915_reg.h"
#include "i915_context.h"
#include "i915_program.h"
static GLuint translate_tex_src_bit( struct i915_fragment_program *p,
GLubyte bit )
{
switch (bit) {
case TEXTURE_1D_BIT: return D0_SAMPLE_TYPE_2D;
case TEXTURE_2D_BIT: return D0_SAMPLE_TYPE_2D;
case TEXTURE_RECT_BIT: return D0_SAMPLE_TYPE_2D;
case TEXTURE_3D_BIT: return D0_SAMPLE_TYPE_VOLUME;
case TEXTURE_CUBE_BIT: return D0_SAMPLE_TYPE_CUBE;
default: i915_program_error(p, "TexSrcBit"); return 0;
}
}
static GLuint get_source( struct i915_fragment_program *p,
GLenum src, GLuint unit )
{
switch (src) {
case GL_TEXTURE:
if (p->src_texture == UREG_BAD) {
/* TODO: Use D0_CHANNEL_XY where possible.
*/
GLuint dim = translate_tex_src_bit( p, p->ctx->Texture.Unit[unit]._ReallyEnabled);
GLuint sampler = i915_emit_decl(p, REG_TYPE_S, unit, dim);
GLuint texcoord = i915_emit_decl(p, REG_TYPE_T, unit, D0_CHANNEL_ALL);
GLuint tmp = i915_get_temp( p );
GLuint op = T0_TEXLD;
if (p->VB->TexCoordPtr[unit]->size == 4)
op = T0_TEXLDP;
p->src_texture = i915_emit_texld( p, tmp, A0_DEST_CHANNEL_ALL,
sampler, texcoord, op );
}
return p->src_texture;
case GL_CONSTANT:
return i915_emit_const4fv( p, p->ctx->Texture.Unit[unit].EnvColor );
case GL_PRIMARY_COLOR:
return i915_emit_decl(p, REG_TYPE_T, T_DIFFUSE, D0_CHANNEL_ALL);
case GL_PREVIOUS:
default:
i915_emit_decl(p,
GET_UREG_TYPE(p->src_previous),
GET_UREG_NR(p->src_previous), D0_CHANNEL_ALL);
return p->src_previous;
}
}
static GLuint emit_combine_source( struct i915_fragment_program *p,
GLuint mask,
GLuint unit,
GLenum source,
GLenum operand )
{
GLuint arg, src;
src = get_source(p, source, unit);
switch (operand) {
case GL_ONE_MINUS_SRC_COLOR:
/* Get unused tmp,
* Emit tmp = 1.0 + arg.-x-y-z-w
*/
arg = i915_get_temp( p );
return i915_emit_arith( p, A0_ADD, arg, mask, 0,
swizzle(src, ONE, ONE, ONE, ONE ),
negate(src, 1,1,1,1), 0);
case GL_SRC_ALPHA:
if (mask == A0_DEST_CHANNEL_W)
return src;
else
return swizzle( src, W, W, W, W );
case GL_ONE_MINUS_SRC_ALPHA:
/* Get unused tmp,
* Emit tmp = 1.0 + arg.-w-w-w-w
*/
arg = i915_get_temp( p );
return i915_emit_arith( p, A0_ADD, arg, mask, 0,
swizzle(src, ONE, ONE, ONE, ONE ),
negate( swizzle(src,W,W,W,W), 1,1,1,1), 0);
case GL_SRC_COLOR:
default:
return src;
}
}
static int nr_args( GLenum mode )
{
switch (mode) {
case GL_REPLACE: return 1;
case GL_MODULATE: return 2;
case GL_ADD: return 2;
case GL_ADD_SIGNED: return 2;
case GL_INTERPOLATE: return 3;
case GL_SUBTRACT: return 2;
case GL_DOT3_RGB_EXT: return 2;
case GL_DOT3_RGBA_EXT: return 2;
case GL_DOT3_RGB: return 2;
case GL_DOT3_RGBA: return 2;
default: return 0;
}
}
static GLboolean args_match( struct gl_texture_unit *texUnit )
{
int i, nr = nr_args(texUnit->Combine.ModeRGB);
for (i = 0 ; i < nr ; i++) {
if (texUnit->Combine.SourceA[i] != texUnit->Combine.SourceRGB[i])
return GL_FALSE;
switch(texUnit->Combine.OperandA[i]) {
case GL_SRC_ALPHA:
switch(texUnit->Combine.OperandRGB[i]) {
case GL_SRC_COLOR:
case GL_SRC_ALPHA:
break;
default:
return GL_FALSE;
}
break;
case GL_ONE_MINUS_SRC_ALPHA:
switch(texUnit->Combine.OperandRGB[i]) {
case GL_ONE_MINUS_SRC_COLOR:
case GL_ONE_MINUS_SRC_ALPHA:
break;
default:
return GL_FALSE;
}
break;
default:
return GL_FALSE; /* impossible */
}
}
return GL_TRUE;
}
static GLuint emit_combine( struct i915_fragment_program *p,
GLuint dest,
GLuint mask,
GLuint saturate,
GLuint unit,
GLenum mode,
const GLenum *source,
const GLenum *operand)
{
int tmp, src[3], nr = nr_args(mode);
int i;
for (i = 0; i < nr; i++)
src[i] = emit_combine_source( p, mask, unit, source[i], operand[i] );
switch (mode) {
case GL_REPLACE:
if (mask == A0_DEST_CHANNEL_ALL && !saturate)
return src[0];
else
return i915_emit_arith( p, A0_MOV, dest, mask, saturate, src[0], 0, 0 );
case GL_MODULATE:
return i915_emit_arith( p, A0_MUL, dest, mask, saturate,
src[0], src[1], 0 );
case GL_ADD:
return i915_emit_arith( p, A0_ADD, dest, mask, saturate,
src[0], src[1], 0 );
case GL_ADD_SIGNED:
/* tmp = arg0 + arg1
* result = tmp + -.5
*/
tmp = i915_emit_const1f(p, .5);
tmp = negate(swizzle(tmp,X,X,X,X),1,1,1,1);
i915_emit_arith( p, A0_ADD, dest, mask, 0, src[0], src[1], 0 );
i915_emit_arith( p, A0_ADD, dest, mask, saturate, dest, tmp, 0 );
return dest;
case GL_INTERPOLATE: /* TWO INSTRUCTIONS */
/* Arg0 * (Arg2) + Arg1 * (1-Arg2)
*
* Arg0*Arg2 + Arg1 - Arg1Arg2
*
* tmp = Arg0*Arg2 + Arg1,
* result = (-Arg1)Arg2 + tmp
*/
tmp = i915_get_temp( p );
i915_emit_arith( p, A0_MAD, tmp, mask, 0, src[0], src[2], src[1] );
i915_emit_arith( p, A0_MAD, dest, mask, saturate,
negate(src[1], 1,1,1,1), src[2], tmp );
return dest;
case GL_SUBTRACT:
/* negate src[1] */
return i915_emit_arith( p, A0_ADD, dest, mask, saturate, src[0],
negate(src[1],1,1,1,1), 0 );
case GL_DOT3_RGBA:
case GL_DOT3_RGBA_EXT:
case GL_DOT3_RGB_EXT:
case GL_DOT3_RGB: {
GLuint tmp0 = i915_get_temp( p );
GLuint tmp1 = i915_get_temp( p );
GLuint neg1 = negate(swizzle(i915_emit_const1f(p, 1),X,X,X,X), 1,1,1,1);
GLuint two = swizzle(i915_emit_const1f(p, 2),X,X,X,X);
i915_emit_arith( p, A0_MAD, tmp0, A0_DEST_CHANNEL_ALL, 0,
two, src[0], neg1);
if (src[0] == src[1])
tmp1 = tmp0;
else
i915_emit_arith( p, A0_MAD, tmp1, A0_DEST_CHANNEL_ALL, 0,
two, src[1], neg1);
i915_emit_arith( p, A0_DP3, dest, mask, saturate, tmp0, tmp1, 0);
return dest;
}
default:
return src[0];
}
}
static GLuint get_dest( struct i915_fragment_program *p, int unit )
{
if (p->ctx->_TriangleCaps & DD_SEPARATE_SPECULAR)
return i915_get_temp( p );
else if (unit != p->last_tex_stage)
return i915_get_temp( p );
else
return UREG(REG_TYPE_OC, 0);
}
static GLuint emit_texenv( struct i915_fragment_program *p, int unit )
{
struct gl_texture_unit *texUnit = &p->ctx->Texture.Unit[unit];
GLenum envMode = texUnit->EnvMode;
struct gl_texture_object *tObj = texUnit->_Current;
GLenum format = tObj->Image[0][tObj->BaseLevel]->Format;
GLuint saturate = unit < p->last_tex_stage ? A0_DEST_SATURATE : 0;
switch(envMode) {
case GL_BLEND: {
const int cf = get_source(p, GL_PREVIOUS, unit);
const int cc = get_source(p, GL_CONSTANT, unit);
const int cs = get_source(p, GL_TEXTURE, unit);
const int out = get_dest(p, unit);
if (format == GL_INTENSITY) {
/* cv = cf(1 - cs) + cc.cs
* cv = cf - cf.cs + cc.cs
*/
/* u[2] = MAD( -cf * cs + cf )
* cv = MAD( cc * cs + u[2] )
*/
i915_emit_arith( p, A0_MAD, out, A0_DEST_CHANNEL_ALL, 0,
negate(cf,1,1,1,1), cs, cf );
i915_emit_arith( p, A0_MAD, out, A0_DEST_CHANNEL_ALL, saturate,
cc, cs, out );
return out;
} else {
/* cv = cf(1 - cs) + cc.cs
* cv = cf - cf.cs + cc.cs
* av = af.as
*/
/* u[2] = MAD( cf.-x-y-zw * cs.xyzw + cf.xyz0 )
* oC = MAD( cc.xyz0 * cs.xyz0 + u[2].xyzw )
*/
i915_emit_arith( p, A0_MAD, out, A0_DEST_CHANNEL_ALL, 0,
negate(cf,1,1,1,0),
cs,
swizzle(cf,X,Y,Z,ZERO) );
i915_emit_arith( p, A0_MAD, out, A0_DEST_CHANNEL_ALL, saturate,
swizzle(cc,X,Y,Z,ZERO),
swizzle(cs,X,Y,Z,ZERO),
out );
return out;
}
}
case GL_DECAL: {
if (format == GL_RGB ||
format == GL_RGBA) {
int cf = get_source( p, GL_PREVIOUS, unit );
int cs = get_source( p, GL_TEXTURE, unit );
int out = get_dest(p, unit);
/* cv = cf(1-as) + cs.as
* cv = cf.(-as) + cf + cs.as
* av = af
*/
/* u[2] = mad( cf.xyzw * cs.-w-w-w1 + cf.xyz0 )
* oc = mad( cs.xyz0 * cs.www0 + u[2].xyzw )
*/
i915_emit_arith( p, A0_MAD, out, A0_DEST_CHANNEL_ALL, 0,
cf,
negate(swizzle(cs,W,W,W,ONE),1,1,1,0),
swizzle(cf,X,Y,Z,ZERO) );
i915_emit_arith( p, A0_MAD, out, A0_DEST_CHANNEL_ALL, saturate,
swizzle(cs,X,Y,Z,ZERO),
swizzle(cs,W,W,W,ZERO),
out );
return out;
}
else {
return get_source( p, GL_PREVIOUS, unit );
}
}
case GL_REPLACE: {
const int cs = get_source( p, GL_TEXTURE, unit ); /* saturated */
switch (format) {
case GL_ALPHA: {
const int cf = get_source( p, GL_PREVIOUS, unit ); /* saturated */
i915_emit_arith( p, A0_MOV, cs, A0_DEST_CHANNEL_XYZ, 0, cf, 0, 0 );
return cs;
}
case GL_RGB:
case GL_LUMINANCE: {
const int cf = get_source( p, GL_PREVIOUS, unit ); /* saturated */
i915_emit_arith( p, A0_MOV, cs, A0_DEST_CHANNEL_W, 0, cf, 0, 0 );
return cs;
}
default:
return cs;
}
}
case GL_MODULATE: {
const int cf = get_source( p, GL_PREVIOUS, unit );
const int cs = get_source( p, GL_TEXTURE, unit );
const int out = get_dest(p, unit);
switch (format) {
case GL_ALPHA:
i915_emit_arith( p, A0_MUL, out, A0_DEST_CHANNEL_ALL, saturate,
swizzle(cs, ONE, ONE, ONE, W), cf, 0 );
break;
default:
i915_emit_arith( p, A0_MUL, out, A0_DEST_CHANNEL_ALL, saturate,
cs, cf, 0 );
break;
}
return out;
}
case GL_ADD: {
int cf = get_source( p, GL_PREVIOUS, unit );
int cs = get_source( p, GL_TEXTURE, unit );
const int out = get_dest( p, unit );
if (format == GL_INTENSITY) {
/* output-color.rgba = add( incoming, u[1] )
*/
i915_emit_arith( p, A0_ADD, out, A0_DEST_CHANNEL_ALL, saturate,
cs, cf, 0 );
return out;
}
else {
/* cv.xyz = cf.xyz + cs.xyz
* cv.w = cf.w * cs.w
*
* cv.xyzw = MAD( cf.111w * cs.xyzw + cf.xyz0 )
*/
i915_emit_arith( p, A0_MAD, out, A0_DEST_CHANNEL_ALL, saturate,
swizzle(cf,ONE,ONE,ONE,W),
cs,
swizzle(cf,X,Y,Z,ZERO) );
return out;
}
break;
}
case GL_COMBINE: {
GLuint rgb_shift, alpha_shift, out, shift;
GLuint dest = get_dest(p, unit);
/* The EXT version of the DOT3 extension does not support the
* scale factor, but the ARB version (and the version in OpenGL
* 1.3) does.
*/
switch (texUnit->Combine.ModeRGB) {
case GL_DOT3_RGB_EXT:
alpha_shift = texUnit->Combine.ScaleShiftA;
rgb_shift = 0;
break;
case GL_DOT3_RGBA_EXT:
alpha_shift = 0;
rgb_shift = 0;
break;
default:
rgb_shift = texUnit->Combine.ScaleShiftRGB;
alpha_shift = texUnit->Combine.ScaleShiftA;
break;
}
/* Emit the RGB and A combine ops
*/
if (texUnit->Combine.ModeRGB == texUnit->Combine.ModeA &&
args_match( texUnit )) {
out = emit_combine( p, dest, A0_DEST_CHANNEL_ALL, saturate,
unit,
texUnit->Combine.ModeRGB,
texUnit->Combine.SourceRGB,
texUnit->Combine.OperandRGB );
}
else if (texUnit->Combine.ModeRGB == GL_DOT3_RGBA_EXT ||
texUnit->Combine.ModeRGB == GL_DOT3_RGBA) {
out = emit_combine( p, dest, A0_DEST_CHANNEL_ALL, saturate,
unit,
texUnit->Combine.ModeRGB,
texUnit->Combine.SourceRGB,
texUnit->Combine.OperandRGB );
}
else {
/* Need to do something to stop from re-emitting identical
* argument calculations here:
*/
out = emit_combine( p, dest, A0_DEST_CHANNEL_XYZ, saturate,
unit,
texUnit->Combine.ModeRGB,
texUnit->Combine.SourceRGB,
texUnit->Combine.OperandRGB );
out = emit_combine( p, dest, A0_DEST_CHANNEL_W, saturate,
unit,
texUnit->Combine.ModeA,
texUnit->Combine.SourceA,
texUnit->Combine.OperandA );
}
/* Deal with the final shift:
*/
if (alpha_shift || rgb_shift) {
if (rgb_shift == alpha_shift) {
shift = i915_emit_const1f(p, 1<<rgb_shift);
shift = swizzle(shift,X,X,X,X);
}
else {
shift = i915_emit_const2f(p, 1<<rgb_shift, 1<<alpha_shift);
shift = swizzle(shift,X,X,X,Y);
}
return i915_emit_arith( p, A0_MUL, dest, A0_DEST_CHANNEL_ALL,
saturate, out, shift, 0 );
}
return out;
}
default:
return get_source(p, GL_PREVIOUS, 0);
}
}
static void emit_program_fini( struct i915_fragment_program *p )
{
int cf = get_source( p, GL_PREVIOUS, 0 );
int out = UREG( REG_TYPE_OC, 0 );
if (p->ctx->_TriangleCaps & DD_SEPARATE_SPECULAR) {
/* Emit specular add.
*/
GLuint s = i915_emit_decl(p, REG_TYPE_T, T_SPECULAR, D0_CHANNEL_ALL);
i915_emit_arith( p, A0_ADD, out, A0_DEST_CHANNEL_ALL, 0, cf,
swizzle(s, X,Y,Z,ZERO), 0 );
}
else if (cf != out) {
/* Will wind up in here if no texture enabled or a couple of
* other scenarios (GL_REPLACE for instance).
*/
i915_emit_arith( p, A0_MOV, out, A0_DEST_CHANNEL_ALL, 0, cf, 0, 0 );
}
}
static void i915EmitTextureProgram( i915ContextPtr i915 )
{
GLcontext *ctx = &i915->intel.ctx;
struct i915_fragment_program *p = &i915->tex_program;
GLuint unit;
if (0) fprintf(stderr, "%s\n", __FUNCTION__);
i915_init_program( i915, p );
if (ctx->Texture._EnabledUnits) {
for (unit = 0 ; unit < ctx->Const.MaxTextureUnits ; unit++)
if (ctx->Texture.Unit[unit]._ReallyEnabled) {
p->last_tex_stage = unit;
}
for (unit = 0 ; unit < ctx->Const.MaxTextureUnits; unit++)
if (ctx->Texture.Unit[unit]._ReallyEnabled) {
p->src_previous = emit_texenv( p, unit );
p->src_texture = UREG_BAD;
p->temp_flag = 0xffff000;
p->temp_flag |= 1 << GET_UREG_NR(p->src_previous);
}
}
emit_program_fini( p );
i915_fini_program( p );
i915_upload_program( i915, p );
p->translated = 1;
}
void i915ValidateTextureProgram( i915ContextPtr i915 )
{
intelContextPtr intel = &i915->intel;
GLcontext *ctx = &intel->ctx;
TNLcontext *tnl = TNL_CONTEXT(ctx);
struct vertex_buffer *VB = &tnl->vb;
GLuint index = tnl->render_inputs;
int i, offset;
GLuint s4 = i915->state.Ctx[I915_CTXREG_LIS4] & ~S4_VFMT_MASK;
GLuint s2 = S2_TEXCOORD_NONE;
/* Important:
*/
VB->AttribPtr[VERT_ATTRIB_POS] = VB->NdcPtr;
intel->vertex_attr_count = 0;
intel->coloroffset = 0;
intel->specoffset = 0;
offset = 0;
if (i915->vertex_fog == I915_FOG_PIXEL) {
EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_4F_VIEWPORT, S4_VFMT_XYZW, 16 );
index &= ~_TNL_BIT_FOG;
}
else if (index & _TNL_BITS_TEX_ANY) {
EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_4F_VIEWPORT, S4_VFMT_XYZW, 16 );
}
else {
EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_3F_VIEWPORT, S4_VFMT_XYZ, 12 );
}
/* How undefined is undefined? */
if (index & _TNL_BIT_POINTSIZE) {
EMIT_ATTR( _TNL_ATTRIB_POINTSIZE, EMIT_1F, S4_VFMT_POINT_WIDTH, 4 );
}
intel->coloroffset = offset / 4;
EMIT_ATTR( _TNL_ATTRIB_COLOR0, EMIT_4UB_4F_RGBA, S4_VFMT_COLOR, 4 );
if (index & (_TNL_BIT_COLOR1|_TNL_BIT_FOG)) {
if (index & _TNL_BIT_COLOR1) {
intel->specoffset = offset / 4;
EMIT_ATTR( _TNL_ATTRIB_COLOR1, EMIT_3UB_3F_RGB, S4_VFMT_SPEC_FOG, 3 );
} else
EMIT_PAD( 3 );
if (index & _TNL_BIT_FOG)
EMIT_ATTR( _TNL_ATTRIB_FOG, EMIT_1UB_1F, S4_VFMT_SPEC_FOG, 1 );
else
EMIT_PAD( 1 );
}
if (index & _TNL_BITS_TEX_ANY) {
for (i = 0; i < 8; i++) {
if (index & _TNL_BIT_TEX(i)) {
int sz = VB->TexCoordPtr[i]->size;
s2 &= ~S2_TEXCOORD_FMT(i, S2_TEXCOORD_FMT0_MASK);
s2 |= S2_TEXCOORD_FMT(i, SZ_TO_HW(sz));
EMIT_ATTR( _TNL_ATTRIB_TEX0+i, EMIT_SZ(sz), 0, sz * 4 );
}
}
}
/* Only need to change the vertex emit code if there has been a
* statechange to a new hardware vertex format:
*/
if (s2 != i915->state.Ctx[I915_CTXREG_LIS2] ||
s4 != i915->state.Ctx[I915_CTXREG_LIS4]) {
I915_STATECHANGE( i915, I915_UPLOAD_CTX );
i915->tex_program.translated = 0;
/* Must do this *after* statechange, so as not to affect
* buffered vertices reliant on the old state:
*/
intel->vertex_size = _tnl_install_attrs( ctx,
intel->vertex_attrs,
intel->vertex_attr_count,
intel->ViewportMatrix.m, 0 );
intel->vertex_size >>= 2;
i915->state.Ctx[I915_CTXREG_LIS2] = s2;
i915->state.Ctx[I915_CTXREG_LIS4] = s4;
assert(intel->vtbl.check_vertex_size( intel, intel->vertex_size ));
}
if (!i915->tex_program.translated ||
i915->last_ReallyEnabled != ctx->Texture._EnabledUnits) {
i915EmitTextureProgram( i915 );
i915->last_ReallyEnabled = ctx->Texture._EnabledUnits;
}
}
+625
View File
@@ -0,0 +1,625 @@
/**************************************************************************
*
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
**************************************************************************/
#include "glheader.h"
#include "macros.h"
#include "mtypes.h"
#include "simple_list.h"
#include "enums.h"
#include "texformat.h"
#include "texstore.h"
#include "mm.h"
#include "intel_screen.h"
#include "intel_ioctl.h"
#include "intel_tex.h"
#include "i915_context.h"
#include "i915_reg.h"
static GLint initial_offsets[6][2] = { {0,0},
{0,2},
{1,0},
{1,2},
{1,1},
{1,3} };
static GLint step_offsets[6][2] = { {0,2},
{0,2},
{-1,2},
{-1,2},
{-1,1},
{-1,1} };
#define I915_TEX_UNIT_ENABLED(unit) (1<<unit)
static void i915SetTexImages( i915ContextPtr i915,
struct gl_texture_object *tObj )
{
GLuint total_height, pitch, i, textureFormat;
i915TextureObjectPtr t = (i915TextureObjectPtr) tObj->DriverData;
const struct gl_texture_image *baseImage = tObj->Image[0][tObj->BaseLevel];
GLint firstLevel, lastLevel, numLevels;
GLint ss2 = 0;
switch( baseImage->TexFormat->MesaFormat ) {
case MESA_FORMAT_L8:
t->intel.texelBytes = 1;
textureFormat = MAPSURF_8BIT | MT_8BIT_L8;
break;
case MESA_FORMAT_I8:
t->intel.texelBytes = 1;
textureFormat = MAPSURF_8BIT | MT_8BIT_I8;
break;
case MESA_FORMAT_A8:
t->intel.texelBytes = 1;
textureFormat = MAPSURF_8BIT | MT_8BIT_A8;
break;
case MESA_FORMAT_AL88:
t->intel.texelBytes = 2;
textureFormat = MAPSURF_16BIT | MT_16BIT_AY88;
break;
case MESA_FORMAT_RGB565:
t->intel.texelBytes = 2;
textureFormat = MAPSURF_16BIT | MT_16BIT_RGB565;
break;
case MESA_FORMAT_ARGB1555:
t->intel.texelBytes = 2;
textureFormat = MAPSURF_16BIT | MT_16BIT_ARGB1555;
break;
case MESA_FORMAT_ARGB4444:
t->intel.texelBytes = 2;
textureFormat = MAPSURF_16BIT | MT_16BIT_ARGB4444;
break;
case MESA_FORMAT_ARGB8888:
t->intel.texelBytes = 4;
textureFormat = MAPSURF_32BIT | MT_32BIT_ARGB8888;
break;
case MESA_FORMAT_YCBCR_REV:
t->intel.texelBytes = 2;
textureFormat = (MAPSURF_422 | MT_422_YCRCB_NORMAL);
ss2 |= SS2_COLORSPACE_CONVERSION;
break;
case MESA_FORMAT_YCBCR:
t->intel.texelBytes = 2;
textureFormat = (MAPSURF_422 | MT_422_YCRCB_SWAPY);
ss2 |= SS2_COLORSPACE_CONVERSION;
break;
default:
fprintf(stderr, "%s: bad image format\n", __FUNCTION__);
abort();
}
/* Compute which mipmap levels we really want to send to the hardware.
*/
driCalculateTextureFirstLastLevel( (driTextureObject *) t );
/* Figure out the amount of memory required to hold all the mipmap
* levels. Choose the smallest pitch to accomodate the largest
* mipmap:
*/
firstLevel = t->intel.base.firstLevel;
lastLevel = t->intel.base.lastLevel;
numLevels = lastLevel - firstLevel + 1;
/* All images must be loaded at this pitch. Count the number of
* lines required:
*/
switch (tObj->Target) {
case GL_TEXTURE_CUBE_MAP: {
const GLuint dim = tObj->Image[0][firstLevel]->Width;
GLuint face;
pitch = dim * t->intel.texelBytes;
pitch *= 2; /* double pitch for cube layouts */
pitch = (pitch + 3) & ~3;
total_height = dim * 4;
for ( face = 0 ; face < 6 ; face++) {
GLuint x = initial_offsets[face][0] * dim;
GLuint y = initial_offsets[face][1] * dim;
GLuint d = dim;
t->intel.base.dirty_images[face] = ~0;
assert(tObj->Image[face][firstLevel]->Width == dim);
assert(tObj->Image[face][firstLevel]->Height == dim);
for (i = 0; i < numLevels; i++) {
t->intel.image[face][i].image = tObj->Image[face][firstLevel + i];
if (!t->intel.image[face][i].image) {
fprintf(stderr, "no image %d %d\n", face, i);
break; /* can't happen */
}
t->intel.image[face][i].offset =
y * pitch + x * t->intel.texelBytes;
t->intel.image[face][i].internalFormat = baseImage->Format;
d >>= 1;
x += step_offsets[face][0] * d;
y += step_offsets[face][1] * d;
}
}
break;
}
case GL_TEXTURE_3D: {
GLuint virtual_height;
GLuint tmp_numLevels = numLevels;
pitch = tObj->Image[0][firstLevel]->Width * t->intel.texelBytes;
pitch = (pitch + 3) & ~3;
t->intel.base.dirty_images[0] = ~0;
/* Calculate the size of a single slice. Hardware demands a
* minimum of 8 mipmaps, some of which might ultimately not be
* used:
*/
if (tmp_numLevels < 9)
tmp_numLevels = 9;
virtual_height = tObj->Image[0][firstLevel]->Height;
for ( total_height = i = 0 ; i < tmp_numLevels ; i++ ) {
t->intel.image[0][i].image = tObj->Image[0][firstLevel + i];
if (t->intel.image[0][i].image) {
t->intel.image[0][i].offset = total_height * pitch;
t->intel.image[0][i].internalFormat = baseImage->Format;
}
total_height += MAX2(2, virtual_height);
virtual_height >>= 1;
}
t->intel.depth_pitch = total_height * pitch;
/* Multiply slice size by texture depth for total size. It's
* remarkable how wasteful of memory all the i8x0 texture
* layouts are.
*/
total_height *= t->intel.image[0][0].image->Depth;
break;
}
default:
pitch = tObj->Image[0][firstLevel]->Width * t->intel.texelBytes;
pitch = (pitch + 3) & ~3;
t->intel.base.dirty_images[0] = ~0;
for ( total_height = i = 0 ; i < numLevels ; i++ ) {
t->intel.image[0][i].image = tObj->Image[0][firstLevel + i];
if (!t->intel.image[0][i].image)
break;
t->intel.image[0][i].offset = total_height * pitch;
t->intel.image[0][i].internalFormat = baseImage->Format;
total_height += MAX2(2, t->intel.image[0][i].image->Height);
}
break;
}
t->intel.Pitch = pitch;
t->intel.base.totalSize = total_height*pitch;
t->intel.max_level = numLevels-1;
t->Setup[I915_TEXREG_MS3] =
(((tObj->Image[0][firstLevel]->Height - 1) << MS3_HEIGHT_SHIFT) |
((tObj->Image[0][firstLevel]->Width - 1) << MS3_WIDTH_SHIFT) |
textureFormat |
MS3_USE_FENCE_REGS);
t->Setup[I915_TEXREG_MS4] =
((((pitch / 4) - 1) << MS4_PITCH_SHIFT) |
MS4_CUBE_FACE_ENA_MASK |
(((t->intel.max_level * 4)) << MS4_MAX_LOD_SHIFT) |
((tObj->Image[0][firstLevel]->Depth - 1) << MS4_VOLUME_DEPTH_SHIFT));
t->Setup[I915_TEXREG_SS2] &= ~SS2_COLORSPACE_CONVERSION;
t->Setup[I915_TEXREG_SS2] |= ss2;
t->intel.dirty = I915_UPLOAD_TEX_ALL;
}
/* The i915 (and related graphics cores) do not support GL_CLAMP. The
* Intel drivers for "other operating systems" implement GL_CLAMP as
* GL_CLAMP_TO_EDGE, so the same is done here.
*/
static GLuint translate_wrap_mode( GLenum wrap )
{
switch( wrap ) {
case GL_REPEAT: return TEXCOORDMODE_WRAP;
case GL_CLAMP: return TEXCOORDMODE_CLAMP_EDGE; /* not quite correct */
case GL_CLAMP_TO_EDGE: return TEXCOORDMODE_CLAMP_EDGE;
case GL_CLAMP_TO_BORDER: return TEXCOORDMODE_CLAMP_BORDER;
case GL_MIRRORED_REPEAT: return TEXCOORDMODE_MIRROR;
default: return TEXCOORDMODE_WRAP;
}
}
/**
*/
static void i915ImportTexObjState( struct gl_texture_object *texObj )
{
i915TextureObjectPtr t = (i915TextureObjectPtr)texObj->DriverData;
int minFilt = 0, mipFilt = 0, magFilt = 0;
if(INTEL_DEBUG&DEBUG_DRI)
fprintf(stderr, "%s\n", __FUNCTION__);
switch (texObj->MinFilter) {
case GL_NEAREST:
minFilt = FILTER_NEAREST;
mipFilt = MIPFILTER_NONE;
break;
case GL_LINEAR:
minFilt = FILTER_LINEAR;
mipFilt = MIPFILTER_NONE;
break;
case GL_NEAREST_MIPMAP_NEAREST:
minFilt = FILTER_NEAREST;
mipFilt = MIPFILTER_NEAREST;
break;
case GL_LINEAR_MIPMAP_NEAREST:
minFilt = FILTER_LINEAR;
mipFilt = MIPFILTER_NEAREST;
break;
case GL_NEAREST_MIPMAP_LINEAR:
minFilt = FILTER_NEAREST;
mipFilt = MIPFILTER_LINEAR;
break;
case GL_LINEAR_MIPMAP_LINEAR:
minFilt = FILTER_LINEAR;
mipFilt = MIPFILTER_LINEAR;
break;
default:
break;
}
if ( texObj->MaxAnisotropy > 1.0 ) {
minFilt = FILTER_ANISOTROPIC;
magFilt = FILTER_ANISOTROPIC;
}
else {
switch (texObj->MagFilter) {
case GL_NEAREST:
magFilt = FILTER_NEAREST;
break;
case GL_LINEAR:
magFilt = FILTER_LINEAR;
break;
default:
break;
}
}
t->Setup[I915_TEXREG_SS2] &= ~SS2_MIN_FILTER_MASK;
t->Setup[I915_TEXREG_SS2] &= ~SS2_MIP_FILTER_MASK;
t->Setup[I915_TEXREG_SS2] &= ~SS2_MAG_FILTER_MASK;
t->Setup[I915_TEXREG_SS2] |= ((minFilt << SS2_MIN_FILTER_SHIFT) |
(mipFilt << SS2_MIP_FILTER_SHIFT) |
(magFilt << SS2_MAG_FILTER_SHIFT));
{
GLuint ss3 = t->Setup[I915_TEXREG_SS3] & ~(SS3_TCX_ADDR_MODE_MASK |
SS3_TCY_ADDR_MODE_MASK |
SS3_TCZ_ADDR_MODE_MASK);
GLenum ws = texObj->WrapS;
GLenum wt = texObj->WrapT;
GLenum wr = texObj->WrapR;
t->refs_border_color = 0;
if (texObj->Target == GL_TEXTURE_3D &&
(texObj->MinFilter != GL_NEAREST ||
texObj->MagFilter != GL_NEAREST)) {
/* Try to mimic GL_CLAMP functionality a little better -
* switch to CLAMP_TO_BORDER whenever a non-NEAREST filter is
* in use. Only do this for 3D textures at the moment --
* doing it universally would fix the conform texbc.c
* failure, though.
*/
if (ws == GL_CLAMP) ws = GL_CLAMP_TO_BORDER;
if (wt == GL_CLAMP) wt = GL_CLAMP_TO_BORDER;
if (wr == GL_CLAMP) wr = GL_CLAMP_TO_BORDER;
/* 3D textures don't seem to respect the border color.
* Fallback if there's ever a danger that they might refer to
* it.
*/
if (ws == GL_CLAMP_TO_BORDER) t->refs_border_color = 1;
if (wt == GL_CLAMP_TO_BORDER) t->refs_border_color = 1;
if (wr == GL_CLAMP_TO_BORDER) t->refs_border_color = 1;
}
ss3 |= translate_wrap_mode(ws) << SS3_TCX_ADDR_MODE_SHIFT;
ss3 |= translate_wrap_mode(wt) << SS3_TCY_ADDR_MODE_SHIFT;
ss3 |= translate_wrap_mode(wr) << SS3_TCZ_ADDR_MODE_SHIFT;
if (ss3 != t->Setup[I915_TEXREG_SS3]) {
t->intel.dirty = I915_UPLOAD_TEX_ALL;
t->Setup[I915_TEXREG_SS3] = ss3;
}
}
{
const GLubyte *color = texObj->_BorderChan;
t->Setup[I915_TEXREG_SS4] = INTEL_PACKCOLOR8888(color[0],color[1],
color[2],color[3]);
}
}
static void i915_import_tex_unit( i915ContextPtr i915,
i915TextureObjectPtr t,
GLuint unit )
{
GLuint state[I915_TEX_SETUP_SIZE];
if(INTEL_DEBUG&DEBUG_TEXTURE)
fprintf(stderr, "%s unit(%d)\n", __FUNCTION__, unit);
if (i915->intel.CurrentTexObj[unit])
i915->intel.CurrentTexObj[unit]->base.bound &= ~(1U << unit);
i915->intel.CurrentTexObj[unit] = (intelTextureObjectPtr)t;
t->intel.base.bound |= (1 << unit);
if (t->intel.dirty & I915_UPLOAD_TEX(unit)) {
i915ImportTexObjState( t->intel.base.tObj );
t->intel.dirty &= ~I915_UPLOAD_TEX(unit);
}
state[I915_TEXREG_MS2] = t->intel.TextureOffset;
state[I915_TEXREG_MS3] = t->Setup[I915_TEXREG_MS3];
state[I915_TEXREG_MS4] = t->Setup[I915_TEXREG_MS4];
state[I915_TEXREG_SS2] = (i915->state.Tex[unit][I915_TEXREG_SS2] &
SS2_LOD_BIAS_MASK);
state[I915_TEXREG_SS2] |= (t->Setup[I915_TEXREG_SS2] & ~SS2_LOD_BIAS_MASK);
state[I915_TEXREG_SS3] = (i915->state.Tex[unit][I915_TEXREG_SS3] &
SS3_NORMALIZED_COORDS);
state[I915_TEXREG_SS3] |= (t->Setup[I915_TEXREG_SS3] &
~(SS3_NORMALIZED_COORDS|
SS3_TEXTUREMAP_INDEX_MASK));
state[I915_TEXREG_SS3] |= (unit<<SS3_TEXTUREMAP_INDEX_SHIFT);
state[I915_TEXREG_SS4] = t->Setup[I915_TEXREG_SS4];
if (memcmp(state, i915->state.Tex[unit], sizeof(state)) != 0) {
I915_STATECHANGE( i915, I915_UPLOAD_TEX(unit) );
memcpy(i915->state.Tex[unit], state, sizeof(state));
}
}
static GLboolean enable_tex_common( GLcontext *ctx, GLuint unit )
{
i915ContextPtr i915 = I915_CONTEXT(ctx);
struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
struct gl_texture_object *tObj = texUnit->_Current;
i915TextureObjectPtr t = (i915TextureObjectPtr)tObj->DriverData;
if (0) fprintf(stderr, "%s %d\n", __FUNCTION__, unit);
if (!(i915->state.active & I915_UPLOAD_TEX(unit))) {
I915_ACTIVESTATE(i915, I915_UPLOAD_TEX(unit), GL_TRUE);
}
/* Fallback if there's a texture border */
if ( tObj->Image[0][tObj->BaseLevel]->Border > 0 ) {
return GL_FALSE;
}
/* Update state if this is a different texture object to last
* time.
*/
if (i915->intel.CurrentTexObj[unit] != &t->intel ||
(t->intel.dirty & I915_UPLOAD_TEX(unit))) {
i915_import_tex_unit( i915, t, unit);
i915->tex_program.translated = 0;
}
return GL_TRUE;
}
static GLboolean enable_tex_rect( GLcontext *ctx, GLuint unit )
{
i915ContextPtr i915 = I915_CONTEXT(ctx);
struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
struct gl_texture_object *tObj = texUnit->_Current;
i915TextureObjectPtr t = (i915TextureObjectPtr)tObj->DriverData;
GLuint ss3 = i915->state.Tex[unit][I915_TEXREG_SS3];
ss3 &= ~SS3_NORMALIZED_COORDS;
if (ss3 != i915->state.Tex[unit][I915_TEXREG_SS3]) {
I915_STATECHANGE(i915, I915_UPLOAD_TEX(unit));
i915->state.Tex[unit][I915_TEXREG_SS3] = ss3;
}
/* Upload teximages (not pipelined)
*/
if (t->intel.base.dirty_images[0]) {
i915SetTexImages( i915, tObj );
if (!intelUploadTexImages( &i915->intel, &t->intel, 0 )) {
return GL_FALSE;
}
}
return GL_TRUE;
}
static GLboolean enable_tex_2d( GLcontext *ctx, GLuint unit )
{
i915ContextPtr i915 = I915_CONTEXT(ctx);
struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
struct gl_texture_object *tObj = texUnit->_Current;
i915TextureObjectPtr t = (i915TextureObjectPtr)tObj->DriverData;
GLuint ss3 = i915->state.Tex[unit][I915_TEXREG_SS3];
ss3 |= SS3_NORMALIZED_COORDS;
if (ss3 != i915->state.Tex[unit][I915_TEXREG_SS3]) {
I915_STATECHANGE(i915, I915_UPLOAD_TEX(unit));
i915->state.Tex[unit][I915_TEXREG_SS3] = ss3;
}
/* Upload teximages (not pipelined)
*/
if (t->intel.base.dirty_images[0]) {
i915SetTexImages( i915, tObj );
if (!intelUploadTexImages( &i915->intel, &t->intel, 0 )) {
return GL_FALSE;
}
}
return GL_TRUE;
}
static GLboolean enable_tex_cube( GLcontext *ctx, GLuint unit )
{
i915ContextPtr i915 = I915_CONTEXT(ctx);
struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
struct gl_texture_object *tObj = texUnit->_Current;
i915TextureObjectPtr t = (i915TextureObjectPtr)tObj->DriverData;
GLuint ss3 = i915->state.Tex[unit][I915_TEXREG_SS3];
GLuint face;
ss3 |= SS3_NORMALIZED_COORDS;
if (ss3 != i915->state.Tex[unit][I915_TEXREG_SS3]) {
I915_STATECHANGE(i915, I915_UPLOAD_TEX(unit));
i915->state.Tex[unit][I915_TEXREG_SS3] = ss3;
}
/* Upload teximages (not pipelined)
*/
if ( t->intel.base.dirty_images[0] || t->intel.base.dirty_images[1] ||
t->intel.base.dirty_images[2] || t->intel.base.dirty_images[3] ||
t->intel.base.dirty_images[4] || t->intel.base.dirty_images[5] ) {
i915SetTexImages( i915, tObj );
}
/* upload (per face) */
for (face = 0; face < 6; face++) {
if (t->intel.base.dirty_images[face]) {
if (!intelUploadTexImages( &i915->intel, &t->intel, face )) {
return GL_FALSE;
}
}
}
return GL_TRUE;
}
static GLboolean enable_tex_3d( GLcontext *ctx, GLuint unit )
{
struct gl_texture_object *tObj = ctx->Texture.Unit[unit]._Current;
i915TextureObjectPtr t = (i915TextureObjectPtr)tObj->DriverData;
/* 3D textures on I915 seem to get bogus border colors, hence this
* fallback:
*/
if (t->refs_border_color)
return GL_FALSE;
return GL_TRUE;
}
static GLboolean disable_tex( GLcontext *ctx, GLuint unit )
{
i915ContextPtr i915 = I915_CONTEXT(ctx);
if (i915->state.active & I915_UPLOAD_TEX(unit)) {
I915_ACTIVESTATE(i915, I915_UPLOAD_TEX(unit), GL_FALSE);
}
/* The old texture is no longer bound to this texture unit.
* Mark it as such.
*/
if ( i915->intel.CurrentTexObj[unit] != NULL ) {
i915->intel.CurrentTexObj[unit]->base.bound &= ~(1U << 0);
i915->intel.CurrentTexObj[unit] = NULL;
}
return GL_TRUE;
}
static GLboolean i915UpdateTexUnit( GLcontext *ctx, GLuint unit )
{
struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
if (texUnit->_ReallyEnabled &&
INTEL_CONTEXT(ctx)->intelScreen->textureSize < 2048 * 1024)
return GL_FALSE;
switch (texUnit->_ReallyEnabled) {
case TEXTURE_1D_BIT:
case TEXTURE_2D_BIT:
return (enable_tex_2d( ctx, unit ) &&
enable_tex_common( ctx, unit ));
case TEXTURE_RECT_BIT:
return (enable_tex_rect( ctx, unit ) &&
enable_tex_common( ctx, unit ));
case TEXTURE_CUBE_BIT:
return (enable_tex_cube( ctx, unit ) &&
enable_tex_common( ctx, unit ));
case TEXTURE_3D_BIT:
return (enable_tex_2d( ctx, unit ) &&
enable_tex_common( ctx, unit ) &&
enable_tex_3d( ctx, unit));
case 0:
return disable_tex( ctx, unit );
default:
return GL_FALSE;
}
}
void i915UpdateTextureState( intelContextPtr intel )
{
GLcontext *ctx = &intel->ctx;
GLboolean ok = GL_TRUE;
GLuint i;
for (i = 0 ; i < I915_TEX_UNITS && ok ; i++) {
ok = i915UpdateTexUnit( ctx, i );
}
FALLBACK( intel, I915_FALLBACK_TEXTURE, !ok );
}
+332
View File
@@ -0,0 +1,332 @@
/**************************************************************************
*
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
**************************************************************************/
#include "glheader.h"
#include "mtypes.h"
#include "imports.h"
#include "macros.h"
#include "colormac.h"
#include "tnl/t_context.h"
#include "tnl/t_vertex.h"
#include "intel_batchbuffer.h"
#include "i915_reg.h"
#include "i915_context.h"
static void i915_render_start( intelContextPtr intel )
{
GLcontext *ctx = &intel->ctx;
i915ContextPtr i915 = I915_CONTEXT(intel);
if (ctx->FragmentProgram.Enabled && ctx->FragmentProgram.Current)
i915ValidateFragmentProgram( i915 );
else
i915ValidateTextureProgram( i915 );
}
static void i915_reduced_primitive_state( intelContextPtr intel,
GLenum rprim )
{
i915ContextPtr i915 = I915_CONTEXT(intel);
GLuint st1 = i915->state.Stipple[I915_STPREG_ST1];
st1 &= ~ST1_ENABLE;
switch (rprim) {
case GL_TRIANGLES:
if (intel->ctx.Polygon.StippleFlag &&
intel->hw_stipple)
st1 |= ST1_ENABLE;
break;
case GL_LINES:
case GL_POINTS:
default:
break;
}
i915->intel.reduced_primitive = rprim;
if (st1 != i915->state.Stipple[I915_STPREG_ST1]) {
I915_STATECHANGE(i915, I915_UPLOAD_STIPPLE);
i915->state.Stipple[I915_STPREG_ST1] = st1;
}
}
/* Pull apart the vertex format registers and figure out how large a
* vertex is supposed to be.
*/
static GLboolean i915_check_vertex_size( intelContextPtr intel,
GLuint expected )
{
i915ContextPtr i915 = I915_CONTEXT(intel);
int lis2 = i915->current->Ctx[I915_CTXREG_LIS2];
int lis4 = i915->current->Ctx[I915_CTXREG_LIS4];
int i, sz = 0;
switch (lis4 & S4_VFMT_XYZW_MASK) {
case S4_VFMT_XY: sz = 2; break;
case S4_VFMT_XYZ: sz = 3; break;
case S4_VFMT_XYW: sz = 3; break;
case S4_VFMT_XYZW: sz = 4; break;
default:
fprintf(stderr, "no xyzw specified\n");
return 0;
}
if (lis4 & S4_VFMT_SPEC_FOG) sz++;
if (lis4 & S4_VFMT_COLOR) sz++;
if (lis4 & S4_VFMT_DEPTH_OFFSET) sz++;
if (lis4 & S4_VFMT_POINT_WIDTH) sz++;
for (i = 0 ; i < 8 ; i++) {
switch (lis2 & S2_TEXCOORD_FMT0_MASK) {
case TEXCOORDFMT_2D: sz += 2; break;
case TEXCOORDFMT_3D: sz += 3; break;
case TEXCOORDFMT_4D: sz += 4; break;
case TEXCOORDFMT_1D: sz += 1; break;
case TEXCOORDFMT_2D_16: sz += 1; break;
case TEXCOORDFMT_4D_16: sz += 2; break;
case TEXCOORDFMT_NOT_PRESENT: break;
default:
fprintf(stderr, "bad texcoord fmt %d\n", i);
return GL_FALSE;
}
lis2 >>= S2_TEXCOORD_FMT1_SHIFT;
}
if (sz != expected)
fprintf(stderr, "vertex size mismatch %d/%d\n", sz, expected);
return sz == expected;
}
static void i915_emit_invarient_state( intelContextPtr intel )
{
BATCH_LOCALS;
BEGIN_BATCH( 200 );
OUT_BATCH(_3DSTATE_AA_CMD |
AA_LINE_ECAAR_WIDTH_ENABLE |
AA_LINE_ECAAR_WIDTH_1_0 |
AA_LINE_REGION_WIDTH_ENABLE |
AA_LINE_REGION_WIDTH_1_0);
OUT_BATCH(_3DSTATE_DFLT_DIFFUSE_CMD);
OUT_BATCH(0);
OUT_BATCH(_3DSTATE_DFLT_SPEC_CMD);
OUT_BATCH(0);
OUT_BATCH(_3DSTATE_DFLT_Z_CMD);
OUT_BATCH(0);
/* Don't support texture crossbar yet */
OUT_BATCH(_3DSTATE_COORD_SET_BINDINGS |
CSB_TCB(0, 0) |
CSB_TCB(1, 1) |
CSB_TCB(2, 2) |
CSB_TCB(3, 3) |
CSB_TCB(4, 4) |
CSB_TCB(5, 5) |
CSB_TCB(6, 6) |
CSB_TCB(7, 7));
OUT_BATCH(_3DSTATE_RASTER_RULES_CMD |
ENABLE_POINT_RASTER_RULE |
OGL_POINT_RASTER_RULE |
ENABLE_LINE_STRIP_PROVOKE_VRTX |
ENABLE_TRI_FAN_PROVOKE_VRTX |
LINE_STRIP_PROVOKE_VRTX(1) |
TRI_FAN_PROVOKE_VRTX(2) |
ENABLE_TEXKILL_3D_4D |
TEXKILL_4D);
/* Need to initialize this to zero.
*/
OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 |
I1_LOAD_S(3) |
(1));
OUT_BATCH(0);
/* XXX: Use this */
OUT_BATCH(_3DSTATE_SCISSOR_ENABLE_CMD |
DISABLE_SCISSOR_RECT);
OUT_BATCH(_3DSTATE_SCISSOR_RECT_0_CMD);
OUT_BATCH(0);
OUT_BATCH(0);
OUT_BATCH(_3DSTATE_DEPTH_SUBRECT_DISABLE);
OUT_BATCH(_3DSTATE_LOAD_INDIRECT | 0); /* disable indirect state */
OUT_BATCH(0);
/* Don't support twosided stencil yet */
OUT_BATCH(_3DSTATE_BACKFACE_STENCIL_OPS |
BFO_ENABLE_STENCIL_TWO_SIDE |
0 );
ADVANCE_BATCH();
}
#define emit( intel, state, size ) \
do { \
int k; \
BEGIN_BATCH( (size) / sizeof(GLuint)); \
for (k = 0 ; k < (size) / sizeof(GLuint) ; k++) \
OUT_BATCH((state)[k]); \
ADVANCE_BATCH(); \
} while (0);
/* Push the state into the sarea and/or texture memory.
*/
static void i915_emit_state( intelContextPtr intel )
{
i915ContextPtr i915 = I915_CONTEXT(intel);
struct i915_hw_state *state = i915->current;
BATCH_LOCALS;
int i;
GLuint dirty;
/* More to workaround the multitex hang - if one texture unit state
* is modified, emit all texture units.
*/
dirty = state->active & ~state->emitted;
if (dirty & I915_UPLOAD_TEX_ALL)
state->emitted &= ~I915_UPLOAD_TEX_ALL;
dirty = state->active & ~state->emitted;
if (VERBOSE)
fprintf(stderr, "%s dirty: %x\n", __FUNCTION__, dirty);
if (dirty & I915_UPLOAD_CTX) {
if (VERBOSE) fprintf(stderr, "I915_UPLOAD_CTX:\n");
emit( i915, state->Ctx, sizeof(state->Ctx) );
}
if (dirty & I915_UPLOAD_BUFFERS) {
if (VERBOSE) fprintf(stderr, "I915_UPLOAD_BUFFERS:\n");
emit( i915, state->Buffer, sizeof(state->Buffer) );
}
if (dirty & I915_UPLOAD_STIPPLE) {
if (VERBOSE) fprintf(stderr, "I915_UPLOAD_STIPPLE:\n");
emit( i915, state->Stipple, sizeof(state->Stipple) );
}
if (dirty & I915_UPLOAD_FOG) {
if (VERBOSE) fprintf(stderr, "I915_UPLOAD_FOG:\n");
emit( i915, state->Fog, sizeof(state->Fog) );
}
/* Combine all the dirty texture state into a single command to
* avoid lockups on I915 hardware.
*/
if (dirty & I915_UPLOAD_TEX_ALL) {
int nr = 0;
for (i = 0; i < I915_TEX_UNITS; i++)
if (dirty & I915_UPLOAD_TEX(i))
nr++;
BEGIN_BATCH(2+nr*3);
OUT_BATCH(_3DSTATE_MAP_STATE | (3*nr));
OUT_BATCH((dirty & I915_UPLOAD_TEX_ALL) >> I915_UPLOAD_TEX_0_SHIFT);
for (i = 0 ; i < I915_TEX_UNITS ; i++)
if (dirty & I915_UPLOAD_TEX(i)) {
OUT_BATCH(state->Tex[i][I915_TEXREG_MS2]);
OUT_BATCH(state->Tex[i][I915_TEXREG_MS3]);
OUT_BATCH(state->Tex[i][I915_TEXREG_MS4]);
}
ADVANCE_BATCH();
BEGIN_BATCH(2+nr*3);
OUT_BATCH(_3DSTATE_SAMPLER_STATE | (3*nr));
OUT_BATCH((dirty & I915_UPLOAD_TEX_ALL) >> I915_UPLOAD_TEX_0_SHIFT);
for (i = 0 ; i < I915_TEX_UNITS ; i++)
if (dirty & I915_UPLOAD_TEX(i)) {
OUT_BATCH(state->Tex[i][I915_TEXREG_SS2]);
OUT_BATCH(state->Tex[i][I915_TEXREG_SS3]);
OUT_BATCH(state->Tex[i][I915_TEXREG_SS4]);
}
ADVANCE_BATCH();
}
if (dirty & I915_UPLOAD_CONSTANTS) {
if (VERBOSE) fprintf(stderr, "I915_UPLOAD_CONSTANTS:\n");
emit( i915, state->Constant, state->ConstantSize * sizeof(GLuint) );
}
if (dirty & I915_UPLOAD_PROGRAM) {
if (VERBOSE) fprintf(stderr, "I915_UPLOAD_PROGRAM:\n");
assert((state->Program[0] & 0x1ff)+2 == state->ProgramSize);
emit( i915, state->Program, state->ProgramSize * sizeof(GLuint) );
if (VERBOSE)
i915_disassemble_program( state->Program, state->ProgramSize );
}
state->emitted |= dirty;
}
static void i915_destroy_context( intelContextPtr intel )
{
_tnl_free_vertices(&intel->ctx);
}
static void i915_set_draw_offset( intelContextPtr intel, int offset )
{
i915ContextPtr i915 = I915_CONTEXT(intel);
I915_STATECHANGE( i915, I915_UPLOAD_BUFFERS );
i915->state.Buffer[I915_DESTREG_CBUFADDR2] = offset;
}
static void i915_lost_hardware( intelContextPtr intel )
{
I915_CONTEXT(intel)->state.emitted = 0;
}
static void i915_emit_flush( intelContextPtr intel )
{
BATCH_LOCALS;
BEGIN_BATCH(2);
OUT_BATCH( MI_FLUSH | FLUSH_MAP_CACHE | FLUSH_RENDER_CACHE );
OUT_BATCH( 0 );
ADVANCE_BATCH();
}
void i915InitVtbl( i915ContextPtr i915 )
{
i915->intel.vtbl.alloc_tex_obj = i915AllocTexObj;
i915->intel.vtbl.check_vertex_size = i915_check_vertex_size;
i915->intel.vtbl.clear_with_tris = i915ClearWithTris;
i915->intel.vtbl.destroy = i915_destroy_context;
i915->intel.vtbl.emit_invarient_state = i915_emit_invarient_state;
i915->intel.vtbl.emit_state = i915_emit_state;
i915->intel.vtbl.lost_hardware = i915_lost_hardware;
i915->intel.vtbl.reduced_primitive_state = i915_reduced_primitive_state;
i915->intel.vtbl.render_start = i915_render_start;
i915->intel.vtbl.set_draw_offset = i915_set_draw_offset;
i915->intel.vtbl.update_texture_state = i915UpdateTextureState;
i915->intel.vtbl.emit_flush = i915_emit_flush;
}
@@ -0,0 +1,668 @@
/**************************************************************************
*
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
**************************************************************************/
#include <stdio.h>
#include <errno.h>
#include "mtypes.h"
#include "context.h"
#include "enums.h"
#include "intel_reg.h"
#include "intel_batchbuffer.h"
#include "intel_context.h"
/* ================================================================
* Performance monitoring functions
*/
static void intel_fill_box( intelContextPtr intel,
GLshort x, GLshort y,
GLshort w, GLshort h,
GLubyte r, GLubyte g, GLubyte b )
{
intelEmitFillBlitLocked( intel,
intel->intelScreen->cpp,
intel->intelScreen->backPitch,
intel->intelScreen->frontOffset,
x, y, w, h,
INTEL_PACKCOLOR(intel->intelScreen->fbFormat,
r,g,b,0xff));
}
static void intel_draw_performance_boxes( intelContextPtr intel )
{
/* Purple box for page flipping
*/
if ( intel->perf_boxes & I830_BOX_FLIP )
intel_fill_box( intel, 4, 4, 8, 8, 255, 0, 255 );
/* Red box if we have to wait for idle at any point
*/
if ( intel->perf_boxes & I830_BOX_WAIT )
intel_fill_box( intel, 16, 4, 8, 8, 255, 0, 0 );
/* Blue box: lost context?
*/
if ( intel->perf_boxes & I830_BOX_LOST_CONTEXT )
intel_fill_box( intel, 28, 4, 8, 8, 0, 0, 255 );
/* Yellow box for texture swaps
*/
if ( intel->perf_boxes & I830_BOX_TEXTURE_LOAD )
intel_fill_box( intel, 40, 4, 8, 8, 255, 255, 0 );
/* Green box if hardware never idles (as far as we can tell)
*/
if ( !(intel->perf_boxes & I830_BOX_RING_EMPTY) )
intel_fill_box( intel, 64, 4, 8, 8, 0, 255, 0 );
/* Draw bars indicating number of buffers allocated
* (not a great measure, easily confused)
*/
#if 0
if (intel->dma_used) {
int bar = intel->dma_used / 10240;
if (bar > 100) bar = 100;
if (bar < 1) bar = 1;
intel_fill_box( intel, 4, 16, bar, 4, 196, 128, 128 );
intel->dma_used = 0;
}
#endif
intel->perf_boxes = 0;
}
static int bad_prim_vertex_nr( int primitive, int nr )
{
switch (primitive & PRIM3D_MASK) {
case PRIM3D_POINTLIST:
return nr < 1;
case PRIM3D_LINELIST:
return (nr & 1) || nr == 0;
case PRIM3D_LINESTRIP:
return nr < 2;
case PRIM3D_TRILIST:
case PRIM3D_RECTLIST:
return nr % 3 || nr == 0;
case PRIM3D_POLY:
case PRIM3D_TRIFAN:
case PRIM3D_TRISTRIP:
case PRIM3D_TRISTRIP_RVRSE:
return nr < 3;
default:
return 1;
}
}
static void intel_flush_inline_primitive( GLcontext *ctx )
{
intelContextPtr intel = INTEL_CONTEXT( ctx );
GLuint used = intel->batch.ptr - intel->prim.start_ptr;
GLuint vertcount;
assert(intel->prim.primitive != ~0);
if (1) {
/* Check vertex size against the vertex we're specifying to
* hardware. If it's wrong, ditch the primitive.
*/
if (!intel->vtbl.check_vertex_size( intel, intel->vertex_size ))
goto do_discard;
vertcount = (used - 4)/ (intel->vertex_size * 4);
if (!vertcount)
goto do_discard;
if (vertcount * intel->vertex_size * 4 != used - 4) {
fprintf(stderr, "vertex size confusion %d %d\n", used,
intel->vertex_size * vertcount * 4);
goto do_discard;
}
if (bad_prim_vertex_nr( intel->prim.primitive, vertcount )) {
fprintf(stderr, "bad_prim_vertex_nr %x %d\n", intel->prim.primitive,
vertcount);
goto do_discard;
}
}
if (used < 8)
goto do_discard;
*(int *)intel->prim.start_ptr = (_3DPRIMITIVE |
intel->prim.primitive |
(used/4-2));
goto finished;
do_discard:
intel->batch.ptr -= used;
intel->batch.space += used;
assert(intel->batch.space >= 0);
finished:
intel->prim.primitive = ~0;
intel->prim.start_ptr = 0;
intel->prim.flush = 0;
}
/* Emit a primitive referencing vertices in a vertex buffer.
*/
void intelStartInlinePrimitive( intelContextPtr intel, GLuint prim )
{
BATCH_LOCALS;
if (0)
fprintf(stderr, "%s %x\n", __FUNCTION__, prim);
/* Finish any in-progress primitive:
*/
INTEL_FIREVERTICES( intel );
/* Emit outstanding state:
*/
intel->vtbl.emit_state( intel );
/* Make sure there is some space in this buffer:
*/
if (intel->vertex_size * 10 * sizeof(GLuint) >= intel->batch.space)
intelFlushBatch(intel, GL_TRUE);
#if 1
if (((int)intel->batch.ptr) & 0x4) {
BEGIN_BATCH(1);
OUT_BATCH(0);
ADVANCE_BATCH();
}
#endif
/* Emit a slot which will be filled with the inline primitive
* command later.
*/
BEGIN_BATCH(2);
OUT_BATCH( 0 );
intel->prim.start_ptr = batch_ptr;
intel->prim.primitive = prim;
intel->prim.flush = intel_flush_inline_primitive;
OUT_BATCH( 0 );
ADVANCE_BATCH();
}
void intelRestartInlinePrimitive( intelContextPtr intel )
{
GLuint prim = intel->prim.primitive;
intel_flush_inline_primitive( &intel->ctx );
if (1) intelFlushBatch(intel, GL_TRUE); /* GL_TRUE - is critical */
intelStartInlinePrimitive( intel, prim );
}
void intelWrapInlinePrimitive( intelContextPtr intel )
{
GLuint prim = intel->prim.primitive;
if (0)
fprintf(stderr, "%s\n", __FUNCTION__);
intel_flush_inline_primitive( &intel->ctx );
intelFlushBatch(intel, GL_TRUE);
intelStartInlinePrimitive( intel, prim );
}
/* Emit a primitive with space for inline vertices.
*/
GLuint *intelEmitInlinePrimitiveLocked(intelContextPtr intel,
int primitive,
int dwords,
int vertex_size )
{
GLuint *tmp = 0;
BATCH_LOCALS;
if (0)
fprintf(stderr, "%s 0x%x %d\n", __FUNCTION__, primitive, dwords);
/* Emit outstanding state:
*/
intel->vtbl.emit_state( intel );
if (1) {
int used = dwords * 4;
int vertcount;
/* Check vertex size against the vertex we're specifying to
* hardware. If it's wrong, ditch the primitive.
*/
if (!intel->vtbl.check_vertex_size( intel, vertex_size ))
goto do_discard;
vertcount = dwords / vertex_size;
if (dwords % vertex_size) {
fprintf(stderr, "did not request a whole number of vertices\n");
goto do_discard;
}
if (bad_prim_vertex_nr( primitive, vertcount )) {
fprintf(stderr, "bad_prim_vertex_nr %x %d\n", primitive, vertcount);
goto do_discard;
}
if (used < 8)
goto do_discard;
}
/* Emit 3D_PRIMITIVE commands:
*/
BEGIN_BATCH(1 + dwords);
OUT_BATCH( _3DPRIMITIVE |
primitive |
(dwords-1) );
tmp = (GLuint *)batch_ptr;
batch_ptr += dwords * 4;
ADVANCE_BATCH();
do_discard:
return tmp;
}
/*
* Copy the back buffer to the front buffer.
*/
void intelCopyBuffer( const __DRIdrawablePrivate *dPriv )
{
intelContextPtr intel;
if (0)
fprintf(stderr, "%s\n", __FUNCTION__);
assert(dPriv);
assert(dPriv->driContextPriv);
assert(dPriv->driContextPriv->driverPrivate);
intel = (intelContextPtr) dPriv->driContextPriv->driverPrivate;
intelFlush( &intel->ctx );
LOCK_HARDWARE( intel );
{
intelScreenPrivate *intelScreen = intel->intelScreen;
__DRIdrawablePrivate *dPriv = intel->driDrawable;
int nbox = dPriv->numClipRects;
drm_clip_rect_t *pbox = dPriv->pClipRects;
int pitch = intelScreen->frontPitch;
int cpp = intelScreen->cpp;
int i;
GLuint CMD, BR13;
BATCH_LOCALS;
switch(cpp) {
case 2:
BR13 = (pitch * cpp) | (0xCC << 16) | (1<<24);
CMD = XY_SRC_COPY_BLT_CMD;
break;
case 4:
BR13 = (pitch * cpp) | (0xCC << 16) | (1<<24) | (1<<25);
CMD = (XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA |
XY_SRC_COPY_BLT_WRITE_RGB);
break;
default:
BR13 = (pitch * cpp) | (0xCC << 16) | (1<<24);
CMD = XY_SRC_COPY_BLT_CMD;
break;
}
if (0)
intel_draw_performance_boxes( intel );
for (i = 0 ; i < nbox; i++, pbox++)
{
if (pbox->x1 > pbox->x2 ||
pbox->y1 > pbox->y2 ||
pbox->x2 > intelScreen->width ||
pbox->y2 > intelScreen->height)
continue;
BEGIN_BATCH( 8);
OUT_BATCH( CMD );
OUT_BATCH( BR13 );
OUT_BATCH( (pbox->y1 << 16) | pbox->x1 );
OUT_BATCH( (pbox->y2 << 16) | pbox->x2 );
if (intel->sarea->pf_current_page == 0)
OUT_BATCH( intelScreen->frontOffset );
else
OUT_BATCH( intelScreen->backOffset );
OUT_BATCH( (pbox->y1 << 16) | pbox->x1 );
OUT_BATCH( BR13 & 0xffff );
if (intel->sarea->pf_current_page == 0)
OUT_BATCH( intelScreen->backOffset );
else
OUT_BATCH( intelScreen->frontOffset );
ADVANCE_BATCH();
}
}
intelFlushBatchLocked( intel, GL_TRUE, GL_TRUE, GL_TRUE );
UNLOCK_HARDWARE( intel );
}
void intelEmitFillBlitLocked( intelContextPtr intel,
GLuint cpp,
GLshort dst_pitch,
GLuint dst_offset,
GLshort x, GLshort y,
GLshort w, GLshort h,
GLuint color )
{
GLuint BR13, CMD;
BATCH_LOCALS;
dst_pitch *= cpp;
switch(cpp) {
case 1:
case 2:
case 3:
BR13 = dst_pitch | (0xF0 << 16) | (1<<24);
CMD = XY_COLOR_BLT_CMD;
break;
case 4:
BR13 = dst_pitch | (0xF0 << 16) | (1<<24) | (1<<25);
CMD = (XY_COLOR_BLT_CMD | XY_COLOR_BLT_WRITE_ALPHA |
XY_COLOR_BLT_WRITE_RGB);
break;
default:
return;
}
BEGIN_BATCH( 6);
OUT_BATCH( CMD );
OUT_BATCH( BR13 );
OUT_BATCH( (y << 16) | x );
OUT_BATCH( ((y+h) << 16) | (x+w) );
OUT_BATCH( dst_offset );
OUT_BATCH( color );
ADVANCE_BATCH();
}
/* Copy BitBlt
*/
void intelEmitCopyBlitLocked( intelContextPtr intel,
GLuint cpp,
GLshort src_pitch,
GLuint src_offset,
GLshort dst_pitch,
GLuint dst_offset,
GLshort src_x, GLshort src_y,
GLshort dst_x, GLshort dst_y,
GLshort w, GLshort h )
{
GLuint CMD, BR13;
int dst_y2 = dst_y + h;
int dst_x2 = dst_x + w;
BATCH_LOCALS;
src_pitch *= cpp;
dst_pitch *= cpp;
switch(cpp) {
case 1:
case 2:
case 3:
BR13 = dst_pitch | (0xCC << 16) | (1<<24);
CMD = XY_SRC_COPY_BLT_CMD;
break;
case 4:
BR13 = dst_pitch | (0xCC << 16) | (1<<24) | (1<<25);
CMD = (XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA |
XY_SRC_COPY_BLT_WRITE_RGB);
break;
default:
return;
}
if (dst_y2 < dst_y ||
dst_x2 < dst_x) {
return;
}
BEGIN_BATCH( 12);
OUT_BATCH( CMD );
OUT_BATCH( BR13 );
OUT_BATCH( (dst_y << 16) | dst_x );
OUT_BATCH( (dst_y2 << 16) | dst_x2 );
OUT_BATCH( dst_offset );
OUT_BATCH( (src_y << 16) | src_x );
OUT_BATCH( src_pitch );
OUT_BATCH( src_offset );
ADVANCE_BATCH();
}
void intelClearWithBlit(GLcontext *ctx, GLbitfield flags, GLboolean all,
GLint cx1, GLint cy1, GLint cw, GLint ch)
{
intelContextPtr intel = INTEL_CONTEXT( ctx );
intelScreenPrivate *intelScreen = intel->intelScreen;
GLuint clear_depth, clear_color;
GLint cx, cy;
GLint pitch = intelScreen->frontPitch;
GLint cpp = intelScreen->cpp;
GLint i;
GLuint BR13, CMD, D_CMD;
BATCH_LOCALS;
clear_color = intel->ClearColor;
clear_depth = 0;
if (flags & DD_DEPTH_BIT) {
clear_depth = (GLuint)(ctx->Depth.Clear * intel->ClearDepth);
}
if (flags & DD_STENCIL_BIT) {
clear_depth |= (ctx->Stencil.Clear & 0xff) << 24;
}
switch(cpp) {
case 2:
BR13 = (0xF0 << 16) | (pitch * cpp) | (1<<24);
D_CMD = CMD = XY_COLOR_BLT_CMD;
break;
case 4:
BR13 = (0xF0 << 16) | (pitch * cpp) | (1<<24) | (1<<25);
CMD = (XY_COLOR_BLT_CMD |
XY_COLOR_BLT_WRITE_ALPHA |
XY_COLOR_BLT_WRITE_RGB);
D_CMD = XY_COLOR_BLT_CMD;
if (flags & DD_DEPTH_BIT) D_CMD |= XY_COLOR_BLT_WRITE_RGB;
if (flags & DD_STENCIL_BIT) D_CMD |= XY_COLOR_BLT_WRITE_ALPHA;
break;
default:
BR13 = (0xF0 << 16) | (pitch * cpp) | (1<<24);
D_CMD = CMD = XY_COLOR_BLT_CMD;
break;
}
intelFlush( &intel->ctx );
LOCK_HARDWARE( intel );
{
/* flip top to bottom */
cy = intel->driDrawable->h-cy1-ch;
cx = cx1 + intel->drawX;
cy += intel->drawY;
/* adjust for page flipping */
if ( intel->sarea->pf_current_page == 1 ) {
GLuint tmp = flags;
flags &= ~(DD_FRONT_LEFT_BIT | DD_BACK_LEFT_BIT);
if ( tmp & DD_FRONT_LEFT_BIT ) flags |= DD_BACK_LEFT_BIT;
if ( tmp & DD_BACK_LEFT_BIT ) flags |= DD_FRONT_LEFT_BIT;
}
for (i = 0 ; i < intel->numClipRects ; i++)
{
drm_clip_rect_t *box = &intel->pClipRects[i];
drm_clip_rect_t b;
if (!all) {
GLint x = box[i].x1;
GLint y = box[i].y1;
GLint w = box[i].x2 - x;
GLint h = box[i].y2 - y;
if (x < cx) w -= cx - x, x = cx;
if (y < cy) h -= cy - y, y = cy;
if (x + w > cx + cw) w = cx + cw - x;
if (y + h > cy + ch) h = cy + ch - y;
if (w <= 0) continue;
if (h <= 0) continue;
b.x1 = x;
b.y1 = y;
b.x2 = x + w;
b.y2 = y + h;
} else {
b = *box;
}
if (b.x1 > b.x2 ||
b.y1 > b.y2 ||
b.x2 > intelScreen->width ||
b.y2 > intelScreen->height)
continue;
if ( flags & DD_FRONT_LEFT_BIT ) {
BEGIN_BATCH( 6);
OUT_BATCH( CMD );
OUT_BATCH( BR13 );
OUT_BATCH( (b.y1 << 16) | b.x1 );
OUT_BATCH( (b.y2 << 16) | b.x2 );
OUT_BATCH( intelScreen->frontOffset );
OUT_BATCH( clear_color );
ADVANCE_BATCH();
}
if ( flags & DD_BACK_LEFT_BIT ) {
BEGIN_BATCH( 6);
OUT_BATCH( CMD );
OUT_BATCH( BR13 );
OUT_BATCH( (b.y1 << 16) | b.x1 );
OUT_BATCH( (b.y2 << 16) | b.x2 );
OUT_BATCH( intelScreen->backOffset );
OUT_BATCH( clear_color );
ADVANCE_BATCH();
}
if ( flags & (DD_STENCIL_BIT | DD_DEPTH_BIT) ) {
BEGIN_BATCH( 6);
OUT_BATCH( D_CMD );
OUT_BATCH( BR13 );
OUT_BATCH( (b.y1 << 16) | b.x1 );
OUT_BATCH( (b.y2 << 16) | b.x2 );
OUT_BATCH( intelScreen->depthOffset );
OUT_BATCH( clear_depth );
ADVANCE_BATCH();
}
}
}
intelFlushBatchLocked( intel, GL_TRUE, GL_FALSE, GL_TRUE );
UNLOCK_HARDWARE( intel );
}
void intelDestroyBatchBuffer( GLcontext *ctx )
{
intelContextPtr intel = INTEL_CONTEXT(ctx);
if (intel->alloc.ptr) {
intelFreeAGP( intel, intel->alloc.ptr );
intel->alloc.ptr = 0;
}
}
void intelInitBatchBuffer( GLcontext *ctx )
{
intelContextPtr intel = INTEL_CONTEXT(ctx);
if (!intel->intelScreen->allow_batchbuffer || getenv("INTEL_NO_BATCH")) {
intel->alloc.size = 8 * 1024;
intel->alloc.ptr = malloc( intel->alloc.size );
intel->alloc.offset = 0;
}
else {
switch (intel->intelScreen->deviceID) {
case PCI_CHIP_I865_G:
/* HW bug? Seems to crash if batchbuffer crosses 4k boundary.
*/
intel->alloc.size = 8 * 1024;
break;
default:
/* This is the smallest amount of memory the kernel deals with.
* We'd ideally like to make this smaller.
*/
intel->alloc.size = 1 << intel->intelScreen->logTextureGranularity;
break;
}
intel->alloc.ptr = intelAllocateAGP( intel, intel->alloc.size );
if (intel->alloc.ptr)
intel->alloc.offset =
intelAgpOffsetFromVirtual( intel, intel->alloc.ptr );
}
if (!intel->alloc.ptr) {
FALLBACK(intel, INTEL_FALLBACK_NO_BATCHBUFFER, 1);
}
else {
intel->prim.flush = 0;
intel->vtbl.emit_invarient_state( intel );
/* Make sure this gets to the hardware, even if we have no cliprects:
*/
LOCK_HARDWARE( intel );
intelFlushBatchLocked( intel, GL_TRUE, GL_FALSE, GL_TRUE );
UNLOCK_HARDWARE( intel );
}
}
@@ -0,0 +1,103 @@
/**************************************************************************
*
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
**************************************************************************/
#ifndef INTEL_BATCHBUFFER_H
#define INTEL_BATCHBUFFER_H
#include "intel_context.h"
#include "intel_ioctl.h"
#define BATCH_LOCALS GLubyte *batch_ptr;
/* #define VERBOSE 0 */
#ifndef VERBOSE
extern int VERBOSE;
#endif
#define BEGIN_BATCH(n) \
do { \
if (VERBOSE) fprintf(stderr, \
"BEGIN_BATCH(%d) in %s, %d dwords free\n", \
(n), __FUNCTION__, intel->batch.space/4); \
if (intel->batch.space < (n)*4) \
intelFlushBatch(intel, GL_TRUE); \
batch_ptr = intel->batch.ptr; \
} while (0)
#define OUT_BATCH(n) \
do { \
*(GLuint *)batch_ptr = (n); \
if (VERBOSE) fprintf(stderr, " -- %08x at %s/%d\n", (n), __FILE__, __LINE__); \
batch_ptr += 4; \
} while (0)
#define ADVANCE_BATCH() \
do { \
if (VERBOSE) fprintf(stderr, "ADVANCE_BATCH()\n"); \
intel->batch.space -= (batch_ptr - intel->batch.ptr); \
intel->batch.ptr = batch_ptr; \
assert(intel->batch.space >= 0); \
} while(0)
extern void intelInitBatchBuffer( GLcontext *ctx );
extern void intelDestroyBatchBuffer( GLcontext *ctx );
extern void intelStartInlinePrimitive( intelContextPtr intel, GLuint prim );
extern void intelWrapInlinePrimitive( intelContextPtr intel );
extern void intelRestartInlinePrimitive( intelContextPtr intel );
extern GLuint *intelEmitInlinePrimitiveLocked(intelContextPtr intel,
int primitive, int dwords,
int vertex_size);
extern void intelCopyBuffer( const __DRIdrawablePrivate *dpriv );
extern void intelClearWithBlit(GLcontext *ctx, GLbitfield mask, GLboolean all,
GLint cx1, GLint cy1, GLint cw, GLint ch);
extern void intelEmitCopyBlitLocked( intelContextPtr intel,
GLuint cpp,
GLshort src_pitch,
GLuint src_offset,
GLshort dst_pitch,
GLuint dst_offset,
GLshort srcx, GLshort srcy,
GLshort dstx, GLshort dsty,
GLshort w, GLshort h );
extern void intelEmitFillBlitLocked( intelContextPtr intel,
GLuint cpp,
GLshort dst_pitch,
GLuint dst_offset,
GLshort x, GLshort y,
GLshort w, GLshort h,
GLuint color );
static __inline GLuint *intelExtendInlinePrimitive( intelContextPtr intel,
GLuint dwords )
{
GLuint sz = dwords * sizeof(GLuint);
GLuint *ptr;
if (intel->batch.space < sz) {
intelWrapInlinePrimitive( intel );
/* assert(intel->batch.space >= sz); */
}
/* assert(intel->prim.primitive != ~0); */
ptr = (GLuint *)intel->batch.ptr;
intel->batch.ptr += sz;
intel->batch.space -= sz;
return ptr;
}
#endif
+666
View File
@@ -0,0 +1,666 @@
/**************************************************************************
*
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
**************************************************************************/
#include "glheader.h"
#include "context.h"
#include "matrix.h"
#include "simple_list.h"
#include "extensions.h"
#include "imports.h"
#include "swrast/swrast.h"
#include "swrast_setup/swrast_setup.h"
#include "tnl/tnl.h"
#include "array_cache/acache.h"
#include "tnl/t_pipeline.h"
#include "tnl/t_vertex.h"
#include "drivers/common/driverfuncs.h"
#include "intel_screen.h"
#include "i830_dri.h"
#include "i830_common.h"
#include "intel_tex.h"
#include "intel_span.h"
#include "intel_tris.h"
#include "intel_ioctl.h"
#include "intel_batchbuffer.h"
#include "utils.h"
#ifndef INTEL_DEBUG
int INTEL_DEBUG = (0);
#endif
#ifndef VERBOSE
int VERBOSE = 0;
#endif
#if DEBUG_LOCKING
char *prevLockFile;
int prevLockLine;
#endif
const char __driConfigOptions[] = { 0 };
const GLuint __driNConfigOptions = 0;
/***************************************
* Mesa's Driver Functions
***************************************/
#define DRIVER_DATE "20040528"
const GLubyte *intelGetString( GLcontext *ctx, GLenum name )
{
const char * chipset;
static char buffer[128];
switch (name) {
case GL_VENDOR:
return (GLubyte *)"Tungsten Graphics, Inc";
break;
case GL_RENDERER:
switch (INTEL_CONTEXT(ctx)->intelScreen->deviceID) {
case PCI_CHIP_845_G:
chipset = "Intel(R) 845G"; break;
case PCI_CHIP_I830_M:
chipset = "Intel(R) 830M"; break;
case PCI_CHIP_I855_GM:
chipset = "Intel(R) 852GM/855GM"; break;
case PCI_CHIP_I865_G:
chipset = "Intel(R) 865G"; break;
case PCI_CHIP_I915_G:
chipset = "Intel(R) 915G"; break;
default:
chipset = "Unknown Intel Chipset"; break;
}
(void) driGetRendererString( buffer, chipset, DRIVER_DATE, 0 );
return (GLubyte *) buffer;
default:
return NULL;
}
}
static void intelBufferSize(GLframebuffer *buffer,
GLuint *width, GLuint *height)
{
GET_CURRENT_CONTEXT(ctx);
intelContextPtr intel = INTEL_CONTEXT(ctx);
/* Need to lock to make sure the driDrawable is uptodate. This
* information is used to resize Mesa's software buffers, so it has
* to be correct.
*/
LOCK_HARDWARE(intel);
*width = intel->driDrawable->w;
*height = intel->driDrawable->h;
UNLOCK_HARDWARE(intel);
}
/* Extension strings exported by the intel driver.
*
* NOTE: See implementation of glGetString in each hw_context.c file:
* This set of extensions is overridden and many are not actually
* exported to the driver. They are however enabled internally as
* Mesa requires this when calculating things like GL version number.
*/
static const char * const card_extensions[] =
{
"GL_APPLE_client_storage",
"GL_ARB_multisample",
"GL_ARB_multitexture",
"GL_ARB_texture_border_clamp",
"GL_ARB_texture_compression",
"GL_ARB_texture_env_add",
"GL_ARB_texture_env_combine",
"GL_ARB_texture_env_dot3",
"GL_ARB_texture_mirrored_repeat",
"GL_ARB_vertex_program",
"GL_EXT_blend_color",
"GL_EXT_blend_func_separate",
"GL_EXT_blend_minmax",
"GL_EXT_blend_subtract",
"GL_EXT_fog_coord",
"GL_EXT_secondary_color",
"GL_EXT_stencil_wrap",
"GL_EXT_texture_edge_clamp",
"GL_EXT_texture_env_add",
"GL_EXT_texture_env_combine",
"GL_EXT_texture_env_dot3",
"GL_EXT_texture_filter_anisotropic",
"GL_EXT_texture_lod_bias",
"GL_IBM_texture_mirrored_repeat",
"GL_INGR_blend_func_separate",
"GL_MESA_pack_invert",
"GL_MESA_ycbcr_texture",
"GL_NV_texture_rectangle",
"GL_NV_vertex_program",
/* New in final:
*/
"GL_ARB_vertex_buffer_object",
"GL_ARB_window_pos",
"GL_EXT_multi_draw_arrays",
"GL_EXT_abgr",
"GL_EXT_bgra",
"GL_SGIS_generate_mipmap",
"GL_SGIS_texture_border_clamp",
"GL_SGIS_texture_edge_clamp",
NULL
};
extern const struct tnl_pipeline_stage _intel_render_stage;
static const struct tnl_pipeline_stage *intel_pipeline[] = {
&_tnl_vertex_transform_stage,
&_tnl_normal_transform_stage,
&_tnl_lighting_stage,
&_tnl_fog_coordinate_stage,
&_tnl_texgen_stage,
&_tnl_texture_transform_stage,
&_tnl_point_attenuation_stage,
&_tnl_vertex_program_stage,
#if 1
&_intel_render_stage, /* ADD: unclipped rastersetup-to-dma */
#endif
&_tnl_render_stage,
0,
};
static const struct dri_debug_control debug_control[] =
{
{ "fall", DEBUG_FALLBACKS },
{ "tex", DEBUG_TEXTURE },
{ "ioctl", DEBUG_IOCTL },
{ "prim", DEBUG_PRIMS },
{ "vert", DEBUG_VERTS },
{ "state", DEBUG_STATE },
{ "verb", DEBUG_VERBOSE },
{ "dri", DEBUG_DRI },
{ "dma", DEBUG_DMA },
{ "san", DEBUG_SANITY },
{ "sync", DEBUG_SYNC },
{ "sleep", DEBUG_SLEEP },
{ "pix", DEBUG_PIXEL },
{ NULL, 0 }
};
static void intelInvalidateState( GLcontext *ctx, GLuint new_state )
{
_swrast_InvalidateState( ctx, new_state );
_swsetup_InvalidateState( ctx, new_state );
_ac_InvalidateState( ctx, new_state );
_tnl_InvalidateState( ctx, new_state );
_tnl_invalidate_vertex_state( ctx, new_state );
INTEL_CONTEXT(ctx)->NewGLState |= new_state;
}
void intelInitDriverFunctions( struct dd_function_table *functions )
{
_mesa_init_driver_functions( functions );
functions->Flush = intelFlush;
functions->Clear = intelClear;
functions->Finish = intelFinish;
functions->GetBufferSize = intelBufferSize;
functions->ResizeBuffers = _swrast_alloc_buffers;
functions->GetString = intelGetString;
functions->UpdateState = intelInvalidateState;
functions->CopyColorTable = _swrast_CopyColorTable;
functions->CopyColorSubTable = _swrast_CopyColorSubTable;
functions->CopyConvolutionFilter1D = _swrast_CopyConvolutionFilter1D;
functions->CopyConvolutionFilter2D = _swrast_CopyConvolutionFilter2D;
intelInitTextureFuncs( functions );
intelInitPixelFuncs( functions );
intelInitStateFuncs( functions );
}
GLboolean intelInitContext( intelContextPtr intel,
const __GLcontextModes *mesaVis,
__DRIcontextPrivate *driContextPriv,
void *sharedContextPrivate,
struct dd_function_table *functions )
{
GLcontext *ctx = &intel->ctx;
GLcontext *shareCtx = (GLcontext *) sharedContextPrivate;
__DRIscreenPrivate *sPriv = driContextPriv->driScreenPriv;
intelScreenPrivate *intelScreen = (intelScreenPrivate *)sPriv->private;
drmI830Sarea *saPriv = (drmI830Sarea *)
(((GLubyte *)sPriv->pSAREA)+intelScreen->sarea_priv_offset);
if (!_mesa_initialize_context(&intel->ctx,
mesaVis, shareCtx,
functions,
(void*) intel))
return GL_FALSE;
driContextPriv->driverPrivate = intel;
intel->intelScreen = intelScreen;
intel->driScreen = sPriv;
intel->sarea = saPriv;
(void) memset( intel->texture_heaps, 0, sizeof( intel->texture_heaps ) );
make_empty_list( & intel->swapped );
ctx->Const.MaxTextureMaxAnisotropy = 2.0;
ctx->Const.MinLineWidth = 1.0;
ctx->Const.MinLineWidthAA = 1.0;
ctx->Const.MaxLineWidth = 3.0;
ctx->Const.MaxLineWidthAA = 3.0;
ctx->Const.LineWidthGranularity = 1.0;
ctx->Const.MinPointSize = 1.0;
ctx->Const.MinPointSizeAA = 1.0;
ctx->Const.MaxPointSize = 255.0;
ctx->Const.MaxPointSizeAA = 3.0;
ctx->Const.PointSizeGranularity = 1.0;
/* Initialize the software rasterizer and helper modules. */
_swrast_CreateContext( ctx );
_ac_CreateContext( ctx );
_tnl_CreateContext( ctx );
_swsetup_CreateContext( ctx );
/* Install the customized pipeline: */
_tnl_destroy_pipeline( ctx );
_tnl_install_pipeline( ctx, intel_pipeline );
/* Configure swrast to match hardware characteristics: */
_swrast_allow_pixel_fog( ctx, GL_FALSE );
_swrast_allow_vertex_fog( ctx, GL_TRUE );
/* Dri stuff */
intel->hHWContext = driContextPriv->hHWContext;
intel->driFd = sPriv->fd;
intel->driHwLock = (drmLock *) &sPriv->pSAREA->lock;
intel->hw_stencil = mesaVis->stencilBits && mesaVis->depthBits == 24;
intel->hw_stipple = 1;
switch(mesaVis->depthBits) {
case 0: /* what to do in this case? */
case 16:
intel->depth_scale = 1.0/0xffff;
intel->polygon_offset_scale = 1.0/0xffff;
intel->depth_clear_mask = ~0;
intel->ClearDepth = 0xffff;
break;
case 24:
intel->depth_scale = 1.0/0xffffff;
intel->polygon_offset_scale = 2.0/0xffffff; /* req'd to pass glean */
intel->depth_clear_mask = 0x00ffffff;
intel->stencil_clear_mask = 0xff000000;
intel->ClearDepth = 0x00ffffff;
break;
default:
assert(0);
break;
}
/* Initialize swrast, tnl driver tables: */
intelInitSpanFuncs( ctx );
intelInitTriFuncs( ctx );
intel->RenderIndex = ~0;
intel->do_irqs = (intel->intelScreen->irq_active &&
!getenv("INTEL_NO_IRQS"));
_math_matrix_ctr (&intel->ViewportMatrix);
driInitExtensions( ctx, card_extensions, GL_TRUE );
/* driInitTextureObjects( ctx, & intel->swapped, */
/* DRI_TEXMGR_DO_TEXTURE_1D | */
/* DRI_TEXMGR_DO_TEXTURE_2D | */
/* DRI_TEXMGR_DO_TEXTURE_RECT ); */
intel->prim.flush = intelInitBatchBuffer;
intel->prim.primitive = ~0;
#if DO_DEBUG
INTEL_DEBUG = driParseDebugString( getenv( "INTEL_DEBUG" ),
debug_control );
INTEL_DEBUG |= driParseDebugString( getenv( "INTEL_DEBUG" ),
debug_control );
#endif
#ifndef VERBOSE
if (getenv("INTEL_VERBOSE"))
VERBOSE=1;
#endif
if (getenv("INTEL_NO_RAST") ||
getenv("INTEL_NO_RAST")) {
fprintf(stderr, "disabling 3D rasterization\n");
FALLBACK(intel, INTEL_FALLBACK_USER, 1);
}
return GL_TRUE;
}
void intelDestroyContext(__DRIcontextPrivate *driContextPriv)
{
intelContextPtr intel = (intelContextPtr) driContextPriv->driverPrivate;
assert(intel); /* should never be null */
if (intel) {
GLboolean release_texture_heaps;
intel->vtbl.destroy( intel );
release_texture_heaps = (intel->ctx.Shared->RefCount == 1);
_swsetup_DestroyContext (&intel->ctx);
_tnl_DestroyContext (&intel->ctx);
_ac_DestroyContext (&intel->ctx);
_swrast_DestroyContext (&intel->ctx);
intel->Fallback = 0; /* don't call _swrast_Flush later */
intelDestroyBatchBuffer(&intel->ctx);
if ( release_texture_heaps ) {
/* This share group is about to go away, free our private
* texture object data.
*/
int i;
for ( i = 0 ; i < intel->nr_heaps ; i++ ) {
driDestroyTextureHeap( intel->texture_heaps[ i ] );
intel->texture_heaps[ i ] = NULL;
}
assert( is_empty_list( & intel->swapped ) );
}
/* free the Mesa context */
_mesa_destroy_context(&intel->ctx);
}
}
void intelSetFrontClipRects( intelContextPtr intel )
{
__DRIdrawablePrivate *dPriv = intel->driDrawable;
if (!dPriv) return;
intel->numClipRects = dPriv->numClipRects;
intel->pClipRects = dPriv->pClipRects;
intel->drawX = dPriv->x;
intel->drawY = dPriv->y;
}
void intelSetBackClipRects( intelContextPtr intel )
{
__DRIdrawablePrivate *dPriv = intel->driDrawable;
if (!dPriv) return;
if (intel->sarea->pf_enabled == 0 && dPriv->numBackClipRects == 0) {
intel->numClipRects = dPriv->numClipRects;
intel->pClipRects = dPriv->pClipRects;
intel->drawX = dPriv->x;
intel->drawY = dPriv->y;
} else {
intel->numClipRects = dPriv->numBackClipRects;
intel->pClipRects = dPriv->pBackClipRects;
intel->drawX = dPriv->backX;
intel->drawY = dPriv->backY;
if (dPriv->numBackClipRects == 1 &&
dPriv->x == dPriv->backX &&
dPriv->y == dPriv->backY) {
/* Repeat the calculation of the back cliprect dimensions here
* as early versions of dri.a in the Xserver are incorrect. Try
* very hard not to restrict future versions of dri.a which
* might eg. allocate truly private back buffers.
*/
int x1, y1;
int x2, y2;
x1 = dPriv->x;
y1 = dPriv->y;
x2 = dPriv->x + dPriv->w;
y2 = dPriv->y + dPriv->h;
if (x1 < 0) x1 = 0;
if (y1 < 0) y1 = 0;
if (x2 > intel->intelScreen->width) x2 = intel->intelScreen->width;
if (y2 > intel->intelScreen->height) y2 = intel->intelScreen->height;
if (x1 == dPriv->pBackClipRects[0].x1 &&
y1 == dPriv->pBackClipRects[0].y1) {
dPriv->pBackClipRects[0].x2 = x2;
dPriv->pBackClipRects[0].y2 = y2;
}
}
}
}
void intelWindowMoved( intelContextPtr intel )
{
switch (intel->ctx.Color._DrawDestMask) {
case DD_FRONT_LEFT_BIT:
intelSetFrontClipRects( intel );
break;
case DD_BACK_LEFT_BIT:
intelSetBackClipRects( intel );
break;
default:
/* glDrawBuffer(GL_NONE or GL_FRONT_AND_BACK): software fallback */
intelSetFrontClipRects( intel );
}
}
GLboolean intelUnbindContext(__DRIcontextPrivate *driContextPriv)
{
return GL_TRUE;
}
GLboolean intelMakeCurrent(__DRIcontextPrivate *driContextPriv,
__DRIdrawablePrivate *driDrawPriv,
__DRIdrawablePrivate *driReadPriv)
{
if (driContextPriv) {
intelContextPtr intel = (intelContextPtr) driContextPriv->driverPrivate;
if ( intel->driDrawable != driDrawPriv ) {
/* Shouldn't the readbuffer be stored also? */
intel->driDrawable = driDrawPriv;
intelWindowMoved( intel );
}
_mesa_make_current2(&intel->ctx,
(GLframebuffer *) driDrawPriv->driverPrivate,
(GLframebuffer *) driReadPriv->driverPrivate);
if (!intel->ctx.Viewport.Width)
_mesa_set_viewport(&intel->ctx, 0, 0, driDrawPriv->w, driDrawPriv->h);
} else {
_mesa_make_current(0,0);
}
return GL_TRUE;
}
void intelGetLock( intelContextPtr intel, GLuint flags )
{
__DRIdrawablePrivate *dPriv = intel->driDrawable;
__DRIscreenPrivate *sPriv = intel->driScreen;
drmI830Sarea * sarea = intel->sarea;
int me = intel->hHWContext;
unsigned i;
drmGetLock(intel->driFd, intel->hHWContext, flags);
/* If the window moved, may need to set a new cliprect now.
*
* NOTE: This releases and regains the hw lock, so all state
* checking must be done *after* this call:
*/
if (dPriv)
DRI_VALIDATE_DRAWABLE_INFO(sPriv, dPriv);
/* If we lost context, need to dump all registers to hardware.
* Note that we don't care about 2d contexts, even if they perform
* accelerated commands, so the DRI locking in the X server is even
* more broken than usual.
*/
if (sarea->ctxOwner != me) {
intel->perf_boxes |= I830_BOX_LOST_CONTEXT;
sarea->ctxOwner = me;
}
/* Shared texture managment - if another client has played with
* texture space, figure out which if any of our textures have been
* ejected, and update our global LRU.
*/
for ( i = 0 ; i < intel->nr_heaps ; i++ ) {
DRI_AGE_TEXTURES( intel->texture_heaps[ i ] );
}
if (dPriv && intel->lastStamp != dPriv->lastStamp) {
intelWindowMoved( intel );
intel->lastStamp = dPriv->lastStamp;
}
}
void intelSwapBuffers( __DRIdrawablePrivate *dPriv )
{
if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) {
intelContextPtr intel;
GLcontext *ctx;
intel = (intelContextPtr) dPriv->driContextPriv->driverPrivate;
ctx = &intel->ctx;
if (ctx->Visual.doubleBufferMode) {
_mesa_notifySwapBuffers( ctx ); /* flush pending rendering comands */
if ( 0 /*intel->doPageFlip*/ ) { /* doPageFlip is never set !!! */
intelPageFlip( dPriv );
} else {
intelCopyBuffer( dPriv );
}
}
} else {
/* XXX this shouldn't be an error but we can't handle it for now */
fprintf(stderr, "%s: drawable has no context!\n", __FUNCTION__);
}
}
void intelInitState( GLcontext *ctx )
{
/* Mesa should do this for us:
*/
ctx->Driver.AlphaFunc( ctx,
ctx->Color.AlphaFunc,
ctx->Color.AlphaRef);
ctx->Driver.BlendColor( ctx,
ctx->Color.BlendColor );
ctx->Driver.BlendEquationSeparate( ctx,
ctx->Color.BlendEquationRGB,
ctx->Color.BlendEquationA);
ctx->Driver.BlendFuncSeparate( ctx,
ctx->Color.BlendSrcRGB,
ctx->Color.BlendDstRGB,
ctx->Color.BlendSrcA,
ctx->Color.BlendDstA);
ctx->Driver.ColorMask( ctx,
ctx->Color.ColorMask[RCOMP],
ctx->Color.ColorMask[GCOMP],
ctx->Color.ColorMask[BCOMP],
ctx->Color.ColorMask[ACOMP]);
ctx->Driver.CullFace( ctx, ctx->Polygon.CullFaceMode );
ctx->Driver.DepthFunc( ctx, ctx->Depth.Func );
ctx->Driver.DepthMask( ctx, ctx->Depth.Mask );
ctx->Driver.Enable( ctx, GL_ALPHA_TEST, ctx->Color.AlphaEnabled );
ctx->Driver.Enable( ctx, GL_BLEND, ctx->Color.BlendEnabled );
ctx->Driver.Enable( ctx, GL_COLOR_LOGIC_OP, ctx->Color.ColorLogicOpEnabled );
ctx->Driver.Enable( ctx, GL_COLOR_SUM, ctx->Fog.ColorSumEnabled );
ctx->Driver.Enable( ctx, GL_CULL_FACE, ctx->Polygon.CullFlag );
ctx->Driver.Enable( ctx, GL_DEPTH_TEST, ctx->Depth.Test );
ctx->Driver.Enable( ctx, GL_DITHER, ctx->Color.DitherFlag );
ctx->Driver.Enable( ctx, GL_FOG, ctx->Fog.Enabled );
ctx->Driver.Enable( ctx, GL_LIGHTING, ctx->Light.Enabled );
ctx->Driver.Enable( ctx, GL_LINE_SMOOTH, ctx->Line.SmoothFlag );
ctx->Driver.Enable( ctx, GL_POLYGON_STIPPLE, ctx->Polygon.StippleFlag );
ctx->Driver.Enable( ctx, GL_SCISSOR_TEST, ctx->Scissor.Enabled );
ctx->Driver.Enable( ctx, GL_STENCIL_TEST, ctx->Stencil.Enabled );
ctx->Driver.Enable( ctx, GL_TEXTURE_1D, GL_FALSE );
ctx->Driver.Enable( ctx, GL_TEXTURE_2D, GL_FALSE );
ctx->Driver.Enable( ctx, GL_TEXTURE_RECTANGLE_NV, GL_FALSE );
ctx->Driver.Enable( ctx, GL_TEXTURE_3D, GL_FALSE );
ctx->Driver.Enable( ctx, GL_TEXTURE_CUBE_MAP, GL_FALSE );
ctx->Driver.Fogfv( ctx, GL_FOG_COLOR, ctx->Fog.Color );
ctx->Driver.Fogfv( ctx, GL_FOG_MODE, 0 );
ctx->Driver.Fogfv( ctx, GL_FOG_DENSITY, &ctx->Fog.Density );
ctx->Driver.Fogfv( ctx, GL_FOG_START, &ctx->Fog.Start );
ctx->Driver.Fogfv( ctx, GL_FOG_END, &ctx->Fog.End );
ctx->Driver.FrontFace( ctx, ctx->Polygon.FrontFace );
{
GLfloat f = (GLfloat)ctx->Light.Model.ColorControl;
ctx->Driver.LightModelfv( ctx, GL_LIGHT_MODEL_COLOR_CONTROL, &f );
}
ctx->Driver.LineWidth( ctx, ctx->Line.Width );
ctx->Driver.LogicOpcode( ctx, ctx->Color.LogicOp );
ctx->Driver.PointSize( ctx, ctx->Point.Size );
ctx->Driver.PolygonStipple( ctx, (const GLubyte *)ctx->PolygonStipple );
ctx->Driver.Scissor( ctx, ctx->Scissor.X, ctx->Scissor.Y,
ctx->Scissor.Width, ctx->Scissor.Height );
ctx->Driver.ShadeModel( ctx, ctx->Light.ShadeModel );
ctx->Driver.StencilFunc( ctx,
ctx->Stencil.Function[0],
ctx->Stencil.Ref[0],
ctx->Stencil.ValueMask[0] );
ctx->Driver.StencilMask( ctx, ctx->Stencil.WriteMask[0] );
ctx->Driver.StencilOp( ctx,
ctx->Stencil.FailFunc[0],
ctx->Stencil.ZFailFunc[0],
ctx->Stencil.ZPassFunc[0]);
ctx->Driver.DrawBuffer( ctx, ctx->Color.DrawBuffer );
}
+431
View File
@@ -0,0 +1,431 @@
/**************************************************************************
*
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
**************************************************************************/
#ifndef INTELCONTEXT_INC
#define INTELCONTEXT_INC
#include "mtypes.h"
#include "drm.h"
#include "mm.h"
#include "texmem.h"
#include "intel_screen.h"
#include "i830_common.h"
#include "tnl/t_vertex.h"
#define TAG(x) intel##x
#include "tnl_dd/t_dd_vertex.h"
#undef TAG
#define DV_PF_555 (1<<8)
#define DV_PF_565 (2<<8)
#define DV_PF_8888 (3<<8)
#define INTEL_CONTEXT(ctx) ((intelContextPtr)(ctx))
typedef struct intel_context intelContext;
typedef struct intel_context *intelContextPtr;
typedef struct intel_texture_object *intelTextureObjectPtr;
typedef void (*intel_tri_func)(intelContextPtr, intelVertex *, intelVertex *,
intelVertex *);
typedef void (*intel_line_func)(intelContextPtr, intelVertex *, intelVertex *);
typedef void (*intel_point_func)(intelContextPtr, intelVertex *);
#define INTEL_FALLBACK_DRAW_BUFFER 0x1
#define INTEL_FALLBACK_READ_BUFFER 0x2
#define INTEL_FALLBACK_USER 0x4
#define INTEL_FALLBACK_NO_BATCHBUFFER 0x8
#define INTEL_FALLBACK_NO_TEXMEM 0x10
#define INTEL_FALLBACK_RENDERMODE 0x20
extern void intelFallback( intelContextPtr intel, GLuint bit, GLboolean mode );
#define FALLBACK( intel, bit, mode ) intelFallback( intel, bit, mode )
#define INTEL_TEX_MAXLEVELS 10
struct intel_texture_object
{
driTextureObject base; /* the parent class */
GLuint texelBytes;
GLuint age;
GLuint Pitch;
GLuint Height;
GLuint TextureOffset;
GLubyte *BufAddr;
GLuint min_level;
GLuint max_level;
GLuint depth_pitch;
struct {
const struct gl_texture_image *image;
GLuint offset; /* into BufAddr */
GLuint height;
GLuint internalFormat;
} image[6][INTEL_TEX_MAXLEVELS];
GLuint dirty;
GLuint firstLevel,lastLevel;
};
struct intel_context
{
GLcontext ctx; /* the parent class */
struct {
void (*destroy)( intelContextPtr intel );
void (*emit_state)( intelContextPtr intel );
void (*emit_invarient_state)( intelContextPtr intel );
void (*lost_hardware)( intelContextPtr intel );
void (*update_texture_state)( intelContextPtr intel );
void (*render_start)( intelContextPtr intel );
void (*set_draw_offset)( intelContextPtr intel, int offset );
void (*emit_flush)( intelContextPtr intel );
void (*reduced_primitive_state)( intelContextPtr intel, GLenum rprim );
GLboolean (*check_vertex_size)( intelContextPtr intel, GLuint expected );
void (*clear_with_tris)( intelContextPtr intel, GLbitfield mask,
GLboolean all,
GLint cx, GLint cy, GLint cw, GLint ch);
intelTextureObjectPtr (*alloc_tex_obj)( struct gl_texture_object *tObj );
} vtbl;
GLint refcount;
GLuint Fallback;
GLuint NewGLState;
struct {
GLuint start_offset;
GLint size;
GLint space;
GLubyte *ptr;
} batch;
struct {
void *ptr;
GLint size;
GLuint offset;
GLuint active_buf;
GLuint irq_emitted;
} alloc;
struct {
GLuint primitive;
GLubyte *start_ptr;
void (*flush)( GLcontext * );
} prim;
GLboolean locked;
GLubyte clear_red;
GLubyte clear_green;
GLubyte clear_blue;
GLubyte clear_alpha;
GLuint ClearColor;
GLuint ClearDepth;
GLuint coloroffset;
GLuint specoffset;
/* Support for duplicating XYZW as WPOS parameter (crutch for I915).
*/
GLuint wpos_offset;
GLuint wpos_size;
struct tnl_attr_map vertex_attrs[VERT_ATTRIB_MAX];
GLuint vertex_attr_count;
GLfloat depth_scale;
GLfloat polygon_offset_scale; /* dependent on depth_scale, bpp */
GLuint depth_clear_mask;
GLuint stencil_clear_mask;
GLboolean hw_stencil;
GLboolean hw_stipple;
/* Texture object bookkeeping
*/
GLuint nr_heaps;
driTexHeap * texture_heaps[1];
driTextureObject swapped;
GLuint lastStamp;
struct intel_texture_object *CurrentTexObj[MAX_TEXTURE_UNITS];
/* State for intelvb.c and inteltris.c.
*/
GLuint RenderIndex;
GLmatrix ViewportMatrix;
GLenum render_primitive;
GLenum reduced_primitive;
GLuint vertex_size;
char *verts; /* points to tnl->clipspace.vertex_buf */
/* Fallback rasterization functions
*/
intel_point_func draw_point;
intel_line_func draw_line;
intel_tri_func draw_tri;
/* These refer to the current draw (front vs. back) buffer:
*/
char *drawMap; /* draw buffer address in virtual mem */
char *readMap;
GLuint drawOffset; /* agp offset of drawbuffer */
int drawX; /* origin of drawable in draw buffer */
int drawY;
GLuint numClipRects; /* cliprects for that buffer */
drm_clip_rect_t *pClipRects;
int dirtyAge;
int perf_boxes;
int do_irqs;
GLboolean scissor;
drm_clip_rect_t draw_rect;
drm_clip_rect_t scissor_rect;
drm_context_t hHWContext;
drmLock *driHwLock;
int driFd;
__DRIdrawablePrivate *driDrawable;
__DRIscreenPrivate *driScreen;
intelScreenPrivate *intelScreen;
drmI830Sarea *sarea;
};
#define DEBUG_LOCKING 1
#if DEBUG_LOCKING
extern char *prevLockFile;
extern int prevLockLine;
#define DEBUG_LOCK() \
do { \
prevLockFile = (__FILE__); \
prevLockLine = (__LINE__); \
} while (0)
#define DEBUG_RESET() \
do { \
prevLockFile = 0; \
prevLockLine = 0; \
} while (0)
/* Slightly less broken way of detecting recursive locking in a
* threaded environment. The right way to do this would be to make
* prevLockFile, prevLockLine thread-local.
*
* This technique instead checks to see if the same context is
* requesting the lock twice -- this will not catch application
* breakages where the same context is active in two different threads
* at once, but it will catch driver breakages (recursive locking) in
* threaded apps.
*/
#define DEBUG_CHECK_LOCK() \
do { \
if ( *((volatile int *)intel->driHwLock) == \
(DRM_LOCK_HELD | intel->hHWContext) ) { \
fprintf( stderr, \
"LOCK SET!\n\tPrevious %s:%d\n\tCurrent: %s:%d\n", \
prevLockFile, prevLockLine, __FILE__, __LINE__ ); \
abort(); \
} \
} while (0)
#else
#define DEBUG_LOCK()
#define DEBUG_RESET()
#define DEBUG_CHECK_LOCK()
#endif
/* Lock the hardware and validate our state.
*/
#define LOCK_HARDWARE( intel ) \
do { \
char __ret=0; \
DEBUG_CHECK_LOCK(); \
assert(!(intel)->locked); \
DRM_CAS((intel)->driHwLock, (intel)->hHWContext, \
(DRM_LOCK_HELD|(intel)->hHWContext), __ret); \
if (__ret) \
intelGetLock( (intel), 0 ); \
DEBUG_LOCK(); \
(intel)->locked = 1; \
}while (0)
/* Unlock the hardware using the global current context
*/
#define UNLOCK_HARDWARE(intel) \
do { \
intel->locked = 0; \
if (0) { \
intel->perf_boxes |= intel->sarea->perf_boxes; \
intel->sarea->perf_boxes = 0; \
} \
DRM_UNLOCK((intel)->driFd, (intel)->driHwLock, (intel)->hHWContext); \
DEBUG_RESET(); \
} while (0)
#define SUBPIXEL_X 0.125
#define SUBPIXEL_Y 0.125
#define INTEL_FIREVERTICES(intel) \
do { \
if ((intel)->prim.flush) \
(intel)->prim.flush(&(intel)->ctx); \
} while (0)
/* ================================================================
* Color packing:
*/
#define INTEL_PACKCOLOR4444(r,g,b,a) \
((((a) & 0xf0) << 8) | (((r) & 0xf0) << 4) | ((g) & 0xf0) | ((b) >> 4))
#define INTEL_PACKCOLOR1555(r,g,b,a) \
((((r) & 0xf8) << 7) | (((g) & 0xf8) << 2) | (((b) & 0xf8) >> 3) | \
((a) ? 0x8000 : 0))
#define INTEL_PACKCOLOR565(r,g,b) \
((((r) & 0xf8) << 8) | (((g) & 0xfc) << 3) | (((b) & 0xf8) >> 3))
#define INTEL_PACKCOLOR8888(r,g,b,a) \
((a<<24) | (r<<16) | (g<<8) | b)
#define INTEL_PACKCOLOR(format, r, g, b, a) \
(format == DV_PF_555 ? INTEL_PACKCOLOR1555(r,g,b,a) : \
(format == DV_PF_565 ? INTEL_PACKCOLOR565(r,g,b) : \
(format == DV_PF_8888 ? INTEL_PACKCOLOR8888(r,g,b,a) : \
0)))
/* ================================================================
* From linux kernel i386 header files, copes with odd sizes better
* than COPY_DWORDS would:
*/
static __inline__ void * __memcpy(void * to, const void * from, size_t n)
{
int d0, d1, d2;
__asm__ __volatile__(
"rep ; movsl\n\t"
"testb $2,%b4\n\t"
"je 1f\n\t"
"movsw\n"
"1:\ttestb $1,%b4\n\t"
"je 2f\n\t"
"movsb\n"
"2:"
: "=&c" (d0), "=&D" (d1), "=&S" (d2)
:"0" (n/4), "q" (n),"1" ((long) to),"2" ((long) from)
: "memory");
return (to);
}
/* ================================================================
* Debugging:
*/
#define DO_DEBUG 1
#if DO_DEBUG
extern int INTEL_DEBUG;
#else
#define INTEL_DEBUG 0
#endif
#define DEBUG_TEXTURE 0x1
#define DEBUG_STATE 0x2
#define DEBUG_IOCTL 0x4
#define DEBUG_PRIMS 0x8
#define DEBUG_VERTS 0x10
#define DEBUG_FALLBACKS 0x20
#define DEBUG_VERBOSE 0x40
#define DEBUG_DRI 0x80
#define DEBUG_DMA 0x100
#define DEBUG_SANITY 0x200
#define DEBUG_SYNC 0x400
#define DEBUG_SLEEP 0x800
#define DEBUG_PIXEL 0x1000
#define PCI_CHIP_845_G 0x2562
#define PCI_CHIP_I830_M 0x3577
#define PCI_CHIP_I855_GM 0x3582
#define PCI_CHIP_I865_G 0x2572
#define PCI_CHIP_I915_G 0x2582
/* ================================================================
* intel_context.c:
*/
extern void intelInitDriverFunctions( struct dd_function_table *functions );
extern GLboolean intelInitContext( intelContextPtr intel,
const __GLcontextModes *mesaVis,
__DRIcontextPrivate *driContextPriv,
void *sharedContextPrivate,
struct dd_function_table *functions );
extern void intelGetLock(intelContextPtr intel, GLuint flags);
extern void intelSetBackClipRects(intelContextPtr intel);
extern void intelSetFrontClipRects(intelContextPtr intel);
extern void intelWindowMoved( intelContextPtr intel );
extern void intelInitState( GLcontext *ctx );
extern const GLubyte *intelGetString( GLcontext *ctx, GLenum name );
/* ================================================================
* intel_state.c:
*/
extern void intelInitStateFuncs( struct dd_function_table *functions );
/* ================================================================
* intel_ioctl.c:
*/
extern void intel_dump_batchbuffer( long offset,
int *ptr,
int count );
/* ================================================================
* intel_pixel.c:
*/
extern void intelInitPixelFuncs( struct dd_function_table *functions );
#endif
+585
View File
@@ -0,0 +1,585 @@
/**************************************************************************
*
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
**************************************************************************/
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include "mtypes.h"
#include "context.h"
#include "swrast/swrast.h"
#include "intel_context.h"
#include "intel_ioctl.h"
#include "intel_batchbuffer.h"
#include "drm.h"
static int intelEmitIrqLocked( intelContextPtr intel )
{
drmI830IrqEmit ie;
int ret, seq;
assert(((*(int *)intel->driHwLock) & ~DRM_LOCK_CONT) ==
(DRM_LOCK_HELD|intel->hHWContext));
ie.irq_seq = &seq;
ret = drmCommandWriteRead( intel->driFd, DRM_I830_IRQ_EMIT,
&ie, sizeof(ie) );
if ( ret ) {
fprintf( stderr, "%s: drmI830IrqEmit: %d\n", __FUNCTION__, ret );
exit(1);
}
if (0)
fprintf(stderr, "%s --> %d\n", __FUNCTION__, seq );
return seq;
}
static void intelWaitIrq( intelContextPtr intel, int seq )
{
drmI830IrqWait iw;
int ret;
if (0)
fprintf(stderr, "%s %d\n", __FUNCTION__, seq );
iw.irq_seq = seq;
do {
ret = drmCommandWrite( intel->driFd, DRM_I830_IRQ_WAIT, &iw, sizeof(iw) );
} while (ret == -EAGAIN || ret == -EINTR);
if ( ret ) {
fprintf( stderr, "%s: drmI830IrqWait: %d\n", __FUNCTION__, ret );
if (0)
intel_dump_batchbuffer( intel->alloc.offset,
intel->alloc.ptr,
intel->alloc.size );
exit(1);
}
}
static void age_intel( intelContextPtr intel, int age )
{
GLuint i;
for (i = 0 ; i < MAX_TEXTURE_UNITS ; i++)
if (intel->CurrentTexObj[i])
intel->CurrentTexObj[i]->age = age;
}
void intel_dump_batchbuffer( long offset,
int *ptr,
int count )
{
int i;
fprintf(stderr, "\n\n\nSTART BATCH (%d dwords):\n", count);
for (i = 0; i < count/4; i += 4)
fprintf(stderr, "\t0x%x: 0x%08x 0x%08x 0x%08x 0x%08x\n",
offset + i*4, ptr[i], ptr[i+1], ptr[i+2], ptr[i+3]);
fprintf(stderr, "END BATCH\n\n\n");
}
void intelRefillBatchLocked( intelContextPtr intel, GLboolean allow_unlock )
{
GLuint last_irq = intel->alloc.irq_emitted;
GLuint half = intel->alloc.size / 2;
GLuint buf = (intel->alloc.active_buf ^= 1);
intel->alloc.irq_emitted = intelEmitIrqLocked( intel );
if (last_irq) {
if (allow_unlock) UNLOCK_HARDWARE( intel );
intelWaitIrq( intel, last_irq );
if (allow_unlock) LOCK_HARDWARE( intel );
}
if (0)
fprintf(stderr, "%s: now using half %d\n", __FUNCTION__, buf);
intel->batch.start_offset = intel->alloc.offset + buf * half;
intel->batch.ptr = (char *)intel->alloc.ptr + buf * half;
intel->batch.size = half - 8;
intel->batch.space = half - 8;
assert(intel->batch.space >= 0);
}
#define MI_BATCH_BUFFER_END (0xA<<23)
void intelFlushBatchLocked( intelContextPtr intel,
GLboolean ignore_cliprects,
GLboolean refill,
GLboolean allow_unlock)
{
drmI830BatchBuffer batch;
assert(intel->locked);
if (0)
fprintf(stderr, "%s used %d of %d offset %x..%x refill %d\n",
__FUNCTION__,
(intel->batch.size - intel->batch.space),
intel->batch.size,
intel->batch.start_offset,
intel->batch.start_offset +
(intel->batch.size - intel->batch.space),
refill);
/* Throw away non-effective packets. Won't work once we have
* hardware contexts which would preserve statechanges beyond a
* single buffer.
*/
if (intel->numClipRects == 0 && !ignore_cliprects) {
intel->batch.space = intel->batch.size;
/* Without this yeild, an application with no cliprects can hog
* the hardware. Without unlocking, the effect is much worse -
* effectively a lock-out of other contexts.
*/
if (allow_unlock) {
UNLOCK_HARDWARE( intel );
sched_yield();
LOCK_HARDWARE( intel );
}
/* Note that any state thought to have been emitted actually
* hasn't:
*/
intel->vtbl.lost_hardware( intel );
}
if (intel->batch.space != intel->batch.size) {
batch.start = intel->batch.start_offset;
batch.used = intel->batch.size - intel->batch.space;
batch.cliprects = intel->pClipRects;
batch.num_cliprects = ignore_cliprects ? 0 : intel->numClipRects;
batch.DR1 = 0;
batch.DR4 = ((((GLuint)intel->drawX) & 0xffff) |
(((GLuint)intel->drawY) << 16));
if (intel->alloc.offset) {
if ((batch.used & 0x4) == 0) {
((int *)intel->batch.ptr)[0] = 0;
((int *)intel->batch.ptr)[1] = MI_BATCH_BUFFER_END;
batch.used += 0x8;
intel->batch.ptr += 0x8;
}
else {
((int *)intel->batch.ptr)[0] = MI_BATCH_BUFFER_END;
batch.used += 0x4;
intel->batch.ptr += 0x4;
}
}
if (0)
intel_dump_batchbuffer( batch.start,
(int *)(intel->batch.ptr - batch.used),
batch.used );
if (0)
fprintf(stderr, "%s: 0x%x..0x%x DR4: %x cliprects: %d\n",
__FUNCTION__,
batch.start,
batch.start + batch.used,
batch.DR4, batch.num_cliprects);
intel->batch.start_offset += batch.used;
intel->batch.size -= batch.used;
if (intel->batch.size < 8) {
refill = GL_TRUE;
intel->batch.space = intel->batch.size = 0;
}
else {
intel->batch.size -= 8;
intel->batch.space = intel->batch.size;
}
assert(intel->batch.space >= 0);
assert(batch.start >= intel->alloc.offset);
assert(batch.start < intel->alloc.offset + intel->alloc.size);
assert(batch.start + batch.used > intel->alloc.offset);
assert(batch.start + batch.used <=
intel->alloc.offset + intel->alloc.size);
if (intel->alloc.offset) {
if (drmCommandWrite (intel->driFd, DRM_I830_BATCHBUFFER, &batch,
sizeof(batch))) {
fprintf(stderr, "DRM_I830_BATCHBUFFER: %d\n", -errno);
UNLOCK_HARDWARE(intel);
exit(1);
}
} else {
drmI830CmdBuffer cmd;
cmd.buf = intel->alloc.ptr + batch.start;
cmd.sz = batch.used;
cmd.DR1 = batch.DR1;
cmd.DR4 = batch.DR4;
cmd.num_cliprects = batch.num_cliprects;
cmd.cliprects = batch.cliprects;
if (drmCommandWrite (intel->driFd, DRM_I830_CMDBUFFER, &cmd,
sizeof(cmd))) {
fprintf(stderr, "DRM_I830_CMDBUFFER: %d\n", -errno);
UNLOCK_HARDWARE(intel);
exit(1);
}
}
age_intel(intel, intel->sarea->last_enqueue);
/* FIXME: use hardware contexts to avoid 'losing' hardware after
* each buffer flush.
*/
intel->vtbl.lost_hardware( intel );
}
if (refill)
intelRefillBatchLocked( intel, allow_unlock );
}
void intelFlushBatch( intelContextPtr intel, GLboolean refill )
{
if (intel->locked) {
intelFlushBatchLocked( intel, GL_FALSE, refill, GL_FALSE );
}
else {
LOCK_HARDWARE(intel);
intelFlushBatchLocked( intel, GL_FALSE, refill, GL_TRUE );
UNLOCK_HARDWARE(intel);
}
}
void intelWaitForIdle( intelContextPtr intel )
{
if (0)
fprintf(stderr, "%s\n", __FUNCTION__);
intel->vtbl.emit_flush( intel );
intelFlushBatch( intel, GL_TRUE );
/* Use an irq to wait for dma idle -- Need to track lost contexts
* to shortcircuit consecutive calls to this function:
*/
intelWaitIrq( intel, intel->alloc.irq_emitted );
intel->alloc.irq_emitted = 0;
}
void intelFlush( GLcontext *ctx )
{
intelContextPtr intel = INTEL_CONTEXT( ctx );
if (intel->Fallback)
_swrast_flush( ctx );
INTEL_FIREVERTICES( intel );
if (intel->batch.size != intel->batch.space)
intelFlushBatch( intel, GL_FALSE );
}
void intelFinish( GLcontext *ctx )
{
intelContextPtr intel = INTEL_CONTEXT( ctx );
intelFlush( ctx );
intelWaitForIdle( intel );
}
void intelClear(GLcontext *ctx, GLbitfield mask, GLboolean all,
GLint cx, GLint cy, GLint cw, GLint ch)
{
intelContextPtr intel = INTEL_CONTEXT( ctx );
const GLuint colorMask = *((GLuint *) &ctx->Color.ColorMask);
GLbitfield tri_mask = 0;
GLbitfield blit_mask = 0;
GLbitfield swrast_mask = 0;
if (0)
fprintf(stderr, "%s\n", __FUNCTION__);
/* Take care of cliprects, which are handled differently for
* clears, etc.
*/
intelFlush( &intel->ctx );
if (mask & DD_FRONT_LEFT_BIT) {
if (colorMask == ~0) {
blit_mask |= DD_FRONT_LEFT_BIT;
}
else {
tri_mask |= DD_FRONT_LEFT_BIT;
}
}
if (mask & DD_BACK_LEFT_BIT) {
if (colorMask == ~0) {
blit_mask |= DD_BACK_LEFT_BIT;
}
else {
tri_mask |= DD_BACK_LEFT_BIT;
}
}
if (mask & DD_DEPTH_BIT) {
blit_mask |= DD_DEPTH_BIT;
}
if (mask & DD_STENCIL_BIT) {
if (!intel->hw_stencil) {
swrast_mask |= DD_STENCIL_BIT;
}
else if (ctx->Stencil.WriteMask[0] != 0xff) {
tri_mask |= DD_STENCIL_BIT;
}
else {
blit_mask |= DD_STENCIL_BIT;
}
}
swrast_mask |= (mask & DD_ACCUM_BIT);
if (blit_mask)
intelClearWithBlit( ctx, blit_mask, all, cx, cy, cw, ch );
if (tri_mask)
intel->vtbl.clear_with_tris( intel, tri_mask, all, cx, cy, cw, ch);
if (swrast_mask)
_swrast_Clear( ctx, swrast_mask, all, cx, cy, cw, ch );
}
void *intelAllocateAGP( intelContextPtr intel, GLsizei size )
{
int region_offset;
drmI830MemAlloc alloc;
int ret;
if (0)
fprintf(stderr, "%s: %d bytes\n", __FUNCTION__, size);
alloc.region = I830_MEM_REGION_AGP;
alloc.alignment = 0;
alloc.size = size;
alloc.region_offset = &region_offset;
LOCK_HARDWARE(intel);
/* Make sure the global heap is initialized
*/
if (intel->texture_heaps[0])
driAgeTextures( intel->texture_heaps[0] );
ret = drmCommandWriteRead( intel->driFd,
DRM_I830_ALLOC,
&alloc, sizeof(alloc));
if (ret) {
fprintf(stderr, "%s: DRM_I830_ALLOC ret %d\n", __FUNCTION__, ret);
UNLOCK_HARDWARE(intel);
return NULL;
}
if (0)
fprintf(stderr, "%s: allocated %d bytes\n", __FUNCTION__, size);
/* Need to propogate this information (agp memory in use) to our
* local texture lru. The kernel has already updated the global
* lru. An alternative would have been to allocate memory the
* usual way and then notify the kernel to pin the allocation.
*/
if (intel->texture_heaps[0])
driAgeTextures( intel->texture_heaps[0] );
UNLOCK_HARDWARE(intel);
return (void *)((char *)intel->intelScreen->tex.map + region_offset);
}
void intelFreeAGP( intelContextPtr intel, void *pointer )
{
int region_offset;
drmI830MemFree memfree;
int ret;
region_offset = (char *)pointer - (char *)intel->intelScreen->tex.map;
if (region_offset < 0 ||
region_offset > intel->intelScreen->tex.size) {
fprintf(stderr, "offset %d outside range 0..%d\n", region_offset,
intel->intelScreen->tex.size);
return;
}
memfree.region = I830_MEM_REGION_AGP;
memfree.region_offset = region_offset;
ret = drmCommandWrite( intel->driFd,
DRM_I830_FREE,
&memfree, sizeof(memfree));
if (ret)
fprintf(stderr, "%s: DRM_I830_FREE ret %d\n", __FUNCTION__, ret);
}
/* This version of AllocateMemoryMESA allocates only agp memory, and
* only does so after the point at which the driver has been
* initialized.
*
* Theoretically a valid context isn't required. However, in this
* implementation, it is, as I'm using the hardware lock to protect
* the kernel data structures, and the current context to get the
* device fd.
*/
void *intelAllocateMemoryMESA(__DRInativeDisplay *dpy, int scrn,
GLsizei size, GLfloat readfreq,
GLfloat writefreq, GLfloat priority)
{
GET_CURRENT_CONTEXT(ctx);
if (INTEL_DEBUG & DEBUG_IOCTL)
fprintf(stderr, "%s sz %d %f/%f/%f\n", __FUNCTION__, size, readfreq,
writefreq, priority);
if (getenv("INTEL_NO_ALLOC"))
return NULL;
if (!ctx || INTEL_CONTEXT(ctx) == 0)
return NULL;
return intelAllocateAGP( INTEL_CONTEXT(ctx), size );
}
/* Called via glXFreeMemoryMESA() */
void intelFreeMemoryMESA(__DRInativeDisplay *dpy, int scrn, GLvoid *pointer)
{
GET_CURRENT_CONTEXT(ctx);
if (INTEL_DEBUG & DEBUG_IOCTL)
fprintf(stderr, "%s %p\n", __FUNCTION__, pointer);
if (!ctx || INTEL_CONTEXT(ctx) == 0) {
fprintf(stderr, "%s: no context\n", __FUNCTION__);
return;
}
intelFreeAGP( INTEL_CONTEXT(ctx), pointer );
}
/* Called via glXGetMemoryOffsetMESA()
*
* Returns offset of pointer from the start of agp aperture.
*/
GLuint intelGetMemoryOffsetMESA(__DRInativeDisplay *dpy, int scrn,
const GLvoid *pointer)
{
GET_CURRENT_CONTEXT(ctx);
intelContextPtr intel;
if (!ctx || !(intel = INTEL_CONTEXT(ctx)) ) {
fprintf(stderr, "%s: no context\n", __FUNCTION__);
return ~0;
}
if (!intelIsAgpMemory( intel, pointer, 0 ))
return ~0;
return intelAgpOffsetFromVirtual( intel, pointer );
}
GLboolean intelIsAgpMemory( intelContextPtr intel, const GLvoid *pointer,
GLint size )
{
int offset = (char *)pointer - (char *)intel->intelScreen->tex.map;
int valid = (size >= 0 &&
offset >= 0 &&
offset + size < intel->intelScreen->tex.size);
if (INTEL_DEBUG & DEBUG_IOCTL)
fprintf(stderr, "intelIsAgpMemory( %p ) : %d\n", pointer, valid );
return valid;
}
GLuint intelAgpOffsetFromVirtual( intelContextPtr intel, const GLvoid *pointer )
{
int offset = (char *)pointer - (char *)intel->intelScreen->tex.map;
if (offset < 0 || offset > intel->intelScreen->tex.size)
return ~0;
else
return intel->intelScreen->textureOffset + offset;
}
/* Flip the front & back buffes
*/
void intelPageFlip( const __DRIdrawablePrivate *dPriv )
{
#if 0
intelContextPtr intel;
int tmp, ret;
if (INTEL_DEBUG & DEBUG_IOCTL)
fprintf(stderr, "%s\n", __FUNCTION__);
assert(dPriv);
assert(dPriv->driContextPriv);
assert(dPriv->driContextPriv->driverPrivate);
intel = (intelContextPtr) dPriv->driContextPriv->driverPrivate;
intelFlush( &intel->ctx );
LOCK_HARDWARE( intel );
if (dPriv->pClipRects) {
*(drm_clip_rect_t *)intel->sarea->boxes = dPriv->pClipRects[0];
intel->sarea->nbox = 1;
}
ret = drmCommandNone(intel->driFd, DRM_I830_FLIP);
if (ret) {
fprintf(stderr, "%s: %d\n", __FUNCTION__, ret);
UNLOCK_HARDWARE( intel );
exit(1);
}
tmp = intel->sarea->last_enqueue;
intelRefillBatchLocked( intel );
UNLOCK_HARDWARE( intel );
intelSetDrawBuffer( &intel->ctx, intel->ctx.Color.DriverDrawBuffer );
#endif
}
+46
View File
@@ -0,0 +1,46 @@
/**************************************************************************
*
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
**************************************************************************/
#ifndef INTEL_IOCTL_H
#define INTEL_IOCTL_H
#include "intel_context.h"
extern void intelWaitAgeLocked( intelContextPtr intel, int age, GLboolean unlock );
extern void intelClear(GLcontext *ctx, GLbitfield mask, GLboolean all,
GLint cx, GLint cy, GLint cw, GLint ch);
extern void intelPageFlip( const __DRIdrawablePrivate *dpriv );
extern void intelWaitForIdle( intelContextPtr intel );
extern void intelFlushBatch( intelContextPtr intel, GLboolean refill );
extern void intelFlushBatchLocked( intelContextPtr intel,
GLboolean ignore_cliprects,
GLboolean refill,
GLboolean allow_unlock);
extern void intelRefillBatchLocked( intelContextPtr intel, GLboolean allow_unlock );
extern void intelFinish( GLcontext *ctx );
extern void intelFlush( GLcontext *ctx );
extern void *intelAllocateAGP( intelContextPtr intel, GLsizei size );
extern void intelFreeAGP( intelContextPtr intel, void *pointer );
extern void *intelAllocateMemoryMESA( __DRInativeDisplay *dpy, int scrn,
GLsizei size, GLfloat readfreq,
GLfloat writefreq, GLfloat priority );
extern void intelFreeMemoryMESA( __DRInativeDisplay *dpy, int scrn,
GLvoid *pointer );
extern GLuint intelGetMemoryOffsetMESA( __DRInativeDisplay *dpy, int scrn, const GLvoid *pointer );
extern GLboolean intelIsAgpMemory( intelContextPtr intel, const GLvoid *pointer,
GLint size );
extern GLuint intelAgpOffsetFromVirtual( intelContextPtr intel, const GLvoid *p );
#endif
+469
View File
@@ -0,0 +1,469 @@
/**************************************************************************
*
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
**************************************************************************/
#include "glheader.h"
#include "enums.h"
#include "mtypes.h"
#include "macros.h"
#include "swrast/swrast.h"
#include "intel_screen.h"
#include "intel_context.h"
#include "intel_ioctl.h"
#include "intel_batchbuffer.h"
static GLboolean
check_color( const GLcontext *ctx, GLenum type, GLenum format,
const struct gl_pixelstore_attrib *packing,
const void *pixels, GLint sz, GLint pitch )
{
intelContextPtr intel = INTEL_CONTEXT(ctx);
GLuint cpp = intel->intelScreen->cpp;
if (INTEL_DEBUG & DEBUG_PIXEL)
fprintf(stderr, "%s\n", __FUNCTION__);
if ( (pitch & 63) ||
ctx->_ImageTransferState ||
packing->SwapBytes ||
packing->LsbFirst) {
if (INTEL_DEBUG & DEBUG_PIXEL)
fprintf(stderr, "%s: failed 1\n", __FUNCTION__);
return GL_FALSE;
}
if ( type == GL_UNSIGNED_INT_8_8_8_8_REV &&
cpp == 4 &&
format == GL_BGRA ) {
if (INTEL_DEBUG & DEBUG_PIXEL)
fprintf(stderr, "%s: passed 2\n", __FUNCTION__);
return GL_TRUE;
}
if (INTEL_DEBUG & DEBUG_PIXEL)
fprintf(stderr, "%s: failed\n", __FUNCTION__);
return GL_FALSE;
}
static GLboolean
check_color_per_fragment_ops( const GLcontext *ctx )
{
int result;
result = (!( ctx->Color.AlphaEnabled ||
ctx->Depth.Test ||
ctx->Fog.Enabled ||
ctx->Scissor.Enabled ||
ctx->Stencil.Enabled ||
!ctx->Color.ColorMask[0] ||
!ctx->Color.ColorMask[1] ||
!ctx->Color.ColorMask[2] ||
!ctx->Color.ColorMask[3] ||
ctx->Color.ColorLogicOpEnabled ||
ctx->Texture._EnabledUnits ||
ctx->Depth.OcclusionTest
) &&
ctx->Current.RasterPosValid);
return result;
}
static GLboolean
clip_pixelrect( const GLcontext *ctx,
const GLframebuffer *buffer,
GLint *x, GLint *y,
GLsizei *width, GLsizei *height,
GLint *size )
{
intelContextPtr intel = INTEL_CONTEXT(ctx);
/* left clipping */
if (*x < buffer->_Xmin) {
*width -= (buffer->_Xmin - *x);
*x = buffer->_Xmin;
}
/* right clipping */
if (*x + *width > buffer->_Xmax)
*width -= (*x + *width - buffer->_Xmax - 1);
if (*width <= 0)
return GL_FALSE;
/* bottom clipping */
if (*y < buffer->_Ymin) {
*height -= (buffer->_Ymin - *y);
*y = buffer->_Ymin;
}
/* top clipping */
if (*y + *height > buffer->_Ymax)
*height -= (*y + *height - buffer->_Ymax - 1);
if (*height <= 0)
return GL_FALSE;
*size = ((*y + *height - 1) * intel->intelScreen->frontPitch +
(*x + *width - 1) * intel->intelScreen->cpp);
return GL_TRUE;
}
static GLboolean
intelTryReadPixels( GLcontext *ctx,
GLint x, GLint y, GLsizei width, GLsizei height,
GLenum format, GLenum type,
const struct gl_pixelstore_attrib *pack,
GLvoid *pixels )
{
intelContextPtr intel = INTEL_CONTEXT(ctx);
GLint size;
GLint pitch = pack->RowLength ? pack->RowLength : width;
if (INTEL_DEBUG & DEBUG_PIXEL)
fprintf(stderr, "%s\n", __FUNCTION__);
/* Only accelerate reading to agp buffers.
*/
if ( !intelIsAgpMemory(intel, pixels,
pitch * height * intel->intelScreen->cpp ) ) {
if (INTEL_DEBUG & DEBUG_PIXEL)
fprintf(stderr, "%s: dest not agp\n", __FUNCTION__);
return GL_FALSE;
}
/* Need GL_PACK_INVERT_MESA to cope with upsidedown results from
* blitter:
*/
if (!pack->Invert) {
if (INTEL_DEBUG & DEBUG_PIXEL)
fprintf(stderr, "%s: MESA_PACK_INVERT not set\n", __FUNCTION__);
return GL_FALSE;
}
if (!check_color(ctx, type, format, pack, pixels, size, pitch))
return GL_FALSE;
switch ( intel->intelScreen->cpp ) {
case 4:
break;
default:
return GL_FALSE;
}
/* Although the blits go on the command buffer, need to do this and
* fire with lock held to guarentee cliprects and drawOffset are
* correct.
*
* This is an unusual situation however, as the code which flushes
* a full command buffer expects to be called unlocked. As a
* workaround, immediately flush the buffer on aquiring the lock.
*/
intelFlush( &intel->ctx );
LOCK_HARDWARE( intel );
{
__DRIdrawablePrivate *dPriv = intel->driDrawable;
int nbox = dPriv->numClipRects;
int src_offset = intel->drawOffset;
int src_pitch = intel->intelScreen->frontPitch;
int dst_offset = intelAgpOffsetFromVirtual( intel, pixels);
drm_clip_rect_t *box = dPriv->pClipRects;
int i;
if (!clip_pixelrect(ctx, ctx->ReadBuffer, &x, &y, &width, &height,
&size)) {
UNLOCK_HARDWARE( intel );
if (INTEL_DEBUG & DEBUG_PIXEL)
fprintf(stderr, "%s totally clipped -- nothing to do\n",
__FUNCTION__);
return GL_TRUE;
}
y = dPriv->h - y - height;
x += dPriv->x;
y += dPriv->y;
if (INTEL_DEBUG & DEBUG_PIXEL)
fprintf(stderr, "readpixel blit src_pitch %d dst_pitch %d\n",
src_pitch, pitch);
for (i = 0 ; i < nbox ; i++)
{
GLint bx = box[i].x1;
GLint by = box[i].y1;
GLint bw = box[i].x2 - bx;
GLint bh = box[i].y2 - by;
if (bx < x) bw -= x - bx, bx = x;
if (by < y) bh -= y - by, by = y;
if (bx + bw > x + width) bw = x + width - bx;
if (by + bh > y + height) bh = y + height - by;
if (bw <= 0) continue;
if (bh <= 0) continue;
intelEmitCopyBlitLocked( intel,
intel->intelScreen->cpp,
src_pitch, src_offset,
pitch, dst_offset,
bx, by,
bx - x, by - y,
bw, bh );
}
}
UNLOCK_HARDWARE( intel );
intelFinish( &intel->ctx );
return GL_TRUE;
}
static void
intelReadPixels( GLcontext *ctx,
GLint x, GLint y, GLsizei width, GLsizei height,
GLenum format, GLenum type,
const struct gl_pixelstore_attrib *pack,
GLvoid *pixels )
{
if (INTEL_DEBUG & DEBUG_PIXEL)
fprintf(stderr, "%s\n", __FUNCTION__);
if (!intelTryReadPixels( ctx, x, y, width, height, format, type, pack,
pixels))
_swrast_ReadPixels( ctx, x, y, width, height, format, type, pack,
pixels);
}
static void do_draw_pix( GLcontext *ctx,
GLint x, GLint y, GLsizei width, GLsizei height,
GLint pitch,
const void *pixels,
GLuint dest )
{
intelContextPtr intel = INTEL_CONTEXT(ctx);
__DRIdrawablePrivate *dPriv = intel->driDrawable;
drm_clip_rect_t *box = dPriv->pClipRects;
int nbox = dPriv->numClipRects;
int i;
int size;
int src_offset = intelAgpOffsetFromVirtual( intel, pixels);
int src_pitch = pitch;
if (INTEL_DEBUG & DEBUG_PIXEL)
fprintf(stderr, "%s\n", __FUNCTION__);
intelFlush( &intel->ctx );
LOCK_HARDWARE( intel );
{
y -= height; /* cope with pixel zoom */
if (!clip_pixelrect(ctx, ctx->DrawBuffer,
&x, &y, &width, &height,
&size)) {
UNLOCK_HARDWARE( intel );
return;
}
y = dPriv->h - y - height; /* convert from gl to hardware coords */
x += dPriv->x;
y += dPriv->y;
for (i = 0 ; i < nbox ; i++ )
{
GLint bx = box[i].x1;
GLint by = box[i].y1;
GLint bw = box[i].x2 - bx;
GLint bh = box[i].y2 - by;
if (bx < x) bw -= x - bx, bx = x;
if (by < y) bh -= y - by, by = y;
if (bx + bw > x + width) bw = x + width - bx;
if (by + bh > y + height) bh = y + height - by;
if (bw <= 0) continue;
if (bh <= 0) continue;
intelEmitCopyBlitLocked( intel,
intel->intelScreen->cpp,
src_pitch, src_offset,
intel->intelScreen->frontPitch,
intel->drawOffset,
bx - x, by - y,
bx, by,
bw, bh );
}
}
UNLOCK_HARDWARE( intel );
intelFinish( &intel->ctx );
}
static GLboolean
intelTryDrawPixels( GLcontext *ctx,
GLint x, GLint y, GLsizei width, GLsizei height,
GLenum format, GLenum type,
const struct gl_pixelstore_attrib *unpack,
const GLvoid *pixels )
{
intelContextPtr intel = INTEL_CONTEXT(ctx);
GLint pitch = unpack->RowLength ? unpack->RowLength : width;
GLuint dest;
GLuint cpp = intel->intelScreen->cpp;
GLint size = width * pitch * cpp;
if (INTEL_DEBUG & DEBUG_PIXEL)
fprintf(stderr, "%s\n", __FUNCTION__);
switch (format) {
case GL_RGB:
case GL_RGBA:
case GL_BGRA:
dest = intel->drawOffset;
/* Planemask doesn't have full support in blits.
*/
if (!ctx->Color.ColorMask[RCOMP] ||
!ctx->Color.ColorMask[GCOMP] ||
!ctx->Color.ColorMask[BCOMP] ||
!ctx->Color.ColorMask[ACOMP]) {
if (INTEL_DEBUG & DEBUG_PIXEL)
fprintf(stderr, "%s: planemask\n", __FUNCTION__);
return GL_FALSE;
}
/* Can't do conversions on agp reads/draws.
*/
if ( !intelIsAgpMemory( intel, pixels, size ) ) {
if (INTEL_DEBUG & DEBUG_PIXEL)
fprintf(stderr, "%s: not agp memory\n", __FUNCTION__);
return GL_FALSE;
}
if (!check_color(ctx, type, format, unpack, pixels, size, pitch)) {
return GL_FALSE;
}
if (!check_color_per_fragment_ops(ctx)) {
return GL_FALSE;
}
if (ctx->Pixel.ZoomX != 1.0F ||
ctx->Pixel.ZoomY != -1.0F)
return GL_FALSE;
break;
default:
return GL_FALSE;
}
if ( intelIsAgpMemory(intel, pixels, size) )
{
do_draw_pix( ctx, x, y, width, height, pitch, pixels,
dest );
return GL_TRUE;
}
else if (0)
{
/* Pixels is in regular memory -- get dma buffers and perform
* upload through them. No point doing this for regular uploads
* but once we remove some of the restrictions above (colormask,
* pixelformat conversion, zoom?, etc), this could be a win.
*/
}
else
return GL_FALSE;
}
static void
intelDrawPixels( GLcontext *ctx,
GLint x, GLint y, GLsizei width, GLsizei height,
GLenum format, GLenum type,
const struct gl_pixelstore_attrib *unpack,
const GLvoid *pixels )
{
if (INTEL_DEBUG & DEBUG_PIXEL)
fprintf(stderr, "%s\n", __FUNCTION__);
if (!intelTryDrawPixels( ctx, x, y, width, height, format, type,
unpack, pixels ))
_swrast_DrawPixels( ctx, x, y, width, height, format, type,
unpack, pixels );
}
/**
* Implement glCopyPixels for the front color buffer (or back buffer Pixmap)
* for the color buffer. Don't support zooming, pixel transfer, etc.
* We do support copying from one window to another, ala glXMakeCurrentRead.
*/
static void
intelCopyPixels( GLcontext *ctx,
GLint srcx, GLint srcy, GLsizei width, GLsizei height,
GLint destx, GLint desty, GLenum type )
{
#if 0
const XMesaContext xmesa = XMESA_CONTEXT(ctx);
const SWcontext *swrast = SWRAST_CONTEXT( ctx );
XMesaDisplay *dpy = xmesa->xm_visual->display;
const XMesaDrawable drawBuffer = xmesa->xm_draw_buffer->buffer;
const XMesaDrawable readBuffer = xmesa->xm_read_buffer->buffer;
const XMesaGC gc = xmesa->xm_draw_buffer->gc;
ASSERT(dpy);
ASSERT(gc);
if (drawBuffer && /* buffer != 0 means it's a Window or Pixmap */
readBuffer &&
type == GL_COLOR &&
(swrast->_RasterMask & ~CLIP_BIT) == 0 && /* no blend, z-test, etc */
ctx->_ImageTransferState == 0 && /* no color tables, scale/bias, etc */
ctx->Pixel.ZoomX == 1.0 && /* no zooming */
ctx->Pixel.ZoomY == 1.0) {
/* Note: we don't do any special clipping work here. We could,
* but X will do it for us.
*/
srcy = FLIP(xmesa->xm_read_buffer, srcy) - height + 1;
desty = FLIP(xmesa->xm_draw_buffer, desty) - height + 1;
XCopyArea(dpy, readBuffer, drawBuffer, gc,
srcx, srcy, width, height, destx, desty);
}
#else
_swrast_CopyPixels(ctx, srcx, srcy, width, height, destx, desty, type );
#endif
}
void intelInitPixelFuncs( struct dd_function_table *functions )
{
/* Pixel path fallbacks.
*/
functions->Accum = _swrast_Accum;
functions->Bitmap = _swrast_Bitmap;
functions->CopyPixels = intelCopyPixels;
if (!getenv("INTEL_NO_BLITS")) {
functions->ReadPixels = intelReadPixels;
functions->DrawPixels = intelDrawPixels;
}
else {
functions->ReadPixels = _swrast_ReadPixels;
functions->DrawPixels = _swrast_DrawPixels;
}
}
+64
View File
@@ -0,0 +1,64 @@
/**************************************************************************
*
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
**************************************************************************/
#ifndef _INTEL_REG_H_
#define _INTEL_REG_H_
#define CMD_3D (0x3<<29)
#define _3DPRIMITIVE ((0x3<<29)|(0x1f<<24))
#define PRIM_INDIRECT (1<<23)
#define PRIM_INLINE (0<<23)
#define PRIM_INDIRECT_SEQUENTIAL (0<<17)
#define PRIM_INDIRECT_ELTS (1<<17)
#define PRIM3D_TRILIST (0x0<<18)
#define PRIM3D_TRISTRIP (0x1<<18)
#define PRIM3D_TRISTRIP_RVRSE (0x2<<18)
#define PRIM3D_TRIFAN (0x3<<18)
#define PRIM3D_POLY (0x4<<18)
#define PRIM3D_LINELIST (0x5<<18)
#define PRIM3D_LINESTRIP (0x6<<18)
#define PRIM3D_RECTLIST (0x7<<18)
#define PRIM3D_POINTLIST (0x8<<18)
#define PRIM3D_DIB (0x9<<18)
#define PRIM3D_MASK (0x1f<<18)
#define I915PACKCOLOR4444(r,g,b,a) \
((((a) & 0xf0) << 8) | (((r) & 0xf0) << 4) | ((g) & 0xf0) | ((b) >> 4))
#define I915PACKCOLOR1555(r,g,b,a) \
((((r) & 0xf8) << 7) | (((g) & 0xf8) << 2) | (((b) & 0xf8) >> 3) | \
((a) ? 0x8000 : 0))
#define I915PACKCOLOR565(r,g,b) \
((((r) & 0xf8) << 8) | (((g) & 0xfc) << 3) | (((b) & 0xf8) >> 3))
#define I915PACKCOLOR8888(r,g,b,a) \
((a<<24) | (r<<16) | (g<<8) | b)
#define BR00_BITBLT_CLIENT 0x40000000
#define BR00_OP_COLOR_BLT 0x10000000
#define BR00_OP_SRC_COPY_BLT 0x10C00000
#define BR13_SOLID_PATTERN 0x80000000
#define XY_COLOR_BLT_CMD ((2<<29)|(0x50<<22)|0x4)
#define XY_COLOR_BLT_WRITE_ALPHA (1<<21)
#define XY_COLOR_BLT_WRITE_RGB (1<<20)
#define XY_SRC_COPY_BLT_CMD ((2<<29)|(0x53<<22)|6)
#define XY_SRC_COPY_BLT_WRITE_ALPHA (1<<21)
#define XY_SRC_COPY_BLT_WRITE_RGB (1<<20)
#endif
+239
View File
@@ -0,0 +1,239 @@
/**************************************************************************
*
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
**************************************************************************/
/*
* Render unclipped vertex buffers by emitting vertices directly to
* dma buffers. Use strip/fan hardware acceleration where possible.
*
*/
#include "glheader.h"
#include "context.h"
#include "macros.h"
#include "imports.h"
#include "mtypes.h"
#include "enums.h"
#include "tnl/t_context.h"
#include "tnl/t_vertex.h"
#include "intel_screen.h"
#include "intel_context.h"
#include "intel_tris.h"
#include "intel_batchbuffer.h"
#include "intel_reg.h"
/*
* Render unclipped vertex buffers by emitting vertices directly to
* dma buffers. Use strip/fan hardware primitives where possible.
* Try to simulate missing primitives with indexed vertices.
*/
#define HAVE_POINTS 0 /* Has it, but can't use because subpixel has to
* be adjusted for points on the INTEL/I845G
*/
#define HAVE_LINES 1
#define HAVE_LINE_STRIPS 1
#define HAVE_TRIANGLES 1
#define HAVE_TRI_STRIPS 1
#define HAVE_TRI_STRIP_1 0 /* has it, template can't use it yet */
#define HAVE_TRI_FANS 1
#define HAVE_POLYGONS 1
#define HAVE_QUADS 0
#define HAVE_QUAD_STRIPS 0
#define HAVE_ELTS 0
static GLuint hw_prim[GL_POLYGON+1] = {
0,
PRIM3D_LINELIST,
PRIM3D_LINESTRIP,
PRIM3D_LINESTRIP,
PRIM3D_TRILIST,
PRIM3D_TRISTRIP,
PRIM3D_TRIFAN,
0,
0,
PRIM3D_POLY
};
static const GLenum reduced_prim[GL_POLYGON+1] = {
GL_POINTS,
GL_LINES,
GL_LINES,
GL_LINES,
GL_TRIANGLES,
GL_TRIANGLES,
GL_TRIANGLES,
GL_TRIANGLES,
GL_TRIANGLES,
GL_TRIANGLES
};
static const int scale_prim[GL_POLYGON+1] = {
0, /* fallback case */
1,
2,
2,
1,
3,
3,
0, /* fallback case */
0, /* fallback case */
3
};
static void intelDmaPrimitive( intelContextPtr intel, GLenum prim )
{
if (0) fprintf(stderr, "%s %s\n", __FUNCTION__, _mesa_lookup_enum_by_nr(prim));
INTEL_FIREVERTICES(intel);
intel->vtbl.reduced_primitive_state( intel, reduced_prim[prim] );
intelStartInlinePrimitive( intel, hw_prim[prim] );
}
#define LOCAL_VARS intelContextPtr intel = INTEL_CONTEXT(ctx)
#define INIT( prim ) \
do { \
intelDmaPrimitive( intel, prim ); \
} while (0)
#define FLUSH() INTEL_FIREVERTICES( intel )
#define GET_SUBSEQUENT_VB_MAX_VERTS() \
(((intel->alloc.size / 2) - 1500) / (intel->vertex_size*4))
#define GET_CURRENT_VB_MAX_VERTS() GET_SUBSEQUENT_VB_MAX_VERTS()
#define ALLOC_VERTS( nr ) \
intelExtendInlinePrimitive( intel, (nr) * intel->vertex_size )
#define EMIT_VERTS( ctx, j, nr, buf ) \
_tnl_emit_vertices_to_buffer(ctx, j, (j)+(nr), buf )
#define TAG(x) intel_##x
#include "tnl_dd/t_dd_dmatmp.h"
/**********************************************************************/
/* Render pipeline stage */
/**********************************************************************/
/* Heuristic to choose between the two render paths:
*/
static GLboolean choose_render( intelContextPtr intel,
struct vertex_buffer *VB )
{
int vertsz = intel->vertex_size;
int cost_render = 0;
int cost_fallback = 0;
int nr_prims = 0;
int nr_rprims = 0;
int nr_rverts = 0;
int rprim = intel->reduced_primitive;
int i = 0;
for (i = 0 ; i < VB->PrimitiveCount ; i++) {
GLuint prim = VB->Primitive[i].mode;
GLuint length = VB->Primitive[i].count;
if (!length)
continue;
nr_prims++;
nr_rverts += length * scale_prim[prim & PRIM_MODE_MASK];
if (reduced_prim[prim & PRIM_MODE_MASK] != rprim) {
nr_rprims++;
rprim = reduced_prim[prim & PRIM_MODE_MASK];
}
}
/* One point for each generated primitive:
*/
cost_render = nr_prims;
cost_fallback = nr_rprims;
/* One point for every 1024 dwords (4k) of dma:
*/
cost_render += (vertsz * i) / 1024;
cost_fallback += (vertsz * nr_rverts) / 1024;
if (0)
fprintf(stderr, "cost render: %d fallback: %d\n",
cost_render, cost_fallback);
if (cost_render > cost_fallback)
return GL_FALSE;
return GL_TRUE;
}
static GLboolean intel_run_render( GLcontext *ctx,
struct tnl_pipeline_stage *stage )
{
intelContextPtr intel = INTEL_CONTEXT(ctx);
TNLcontext *tnl = TNL_CONTEXT(ctx);
struct vertex_buffer *VB = &tnl->vb;
GLuint i;
/* Don't handle clipping or indexed vertices.
*/
if (intel->RenderIndex != 0 ||
!intel_validate_render( ctx, VB ) ||
!choose_render( intel, VB )) {
return GL_TRUE;
}
tnl->clipspace.new_inputs |= VERT_BIT_POS;
tnl->Driver.Render.Start( ctx );
for (i = 0 ; i < VB->PrimitiveCount ; i++)
{
GLuint prim = VB->Primitive[i].mode;
GLuint start = VB->Primitive[i].start;
GLuint length = VB->Primitive[i].count;
if (!length)
continue;
intel_render_tab_verts[prim & PRIM_MODE_MASK]( ctx, start, start + length,
prim );
}
tnl->Driver.Render.Finish( ctx );
return GL_FALSE; /* finished the pipe */
}
static void intel_check_render( GLcontext *ctx,
struct tnl_pipeline_stage *stage )
{
stage->inputs = TNL_CONTEXT(ctx)->render_inputs;
}
static void dtr( struct tnl_pipeline_stage *stage )
{
(void)stage;
}
const struct tnl_pipeline_stage _intel_render_stage =
{
"intel render",
(_DD_NEW_SEPARATE_SPECULAR |
_NEW_TEXTURE|
_NEW_FOG|
_NEW_RENDERMODE), /* re-check (new inputs) */
0, /* re-run (always runs) */
GL_TRUE, /* active */
0, 0, /* inputs (set in check_render), outputs */
0, 0, /* changed_inputs, private */
dtr, /* destructor */
intel_check_render, /* check - initially set to alloc data */
intel_run_render /* run */
};
+543
View File
@@ -0,0 +1,543 @@
/**************************************************************************
*
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
**************************************************************************/
#include "glheader.h"
#include "context.h"
#include "matrix.h"
#include "simple_list.h"
#include "utils.h"
#include "intel_screen.h"
#include "intel_tex.h"
#include "intel_span.h"
#include "intel_tris.h"
#include "intel_ioctl.h"
#include "i830_dri.h"
#ifdef USE_NEW_INTERFACE
static PFNGLXCREATECONTEXTMODES create_context_modes = NULL;
#endif /*USE_NEW_INTERFACE*/
static void intelPrintDRIInfo(intelScreenPrivate *intelScreen,
__DRIscreenPrivate *sPriv,
I830DRIPtr gDRIPriv)
{
fprintf(stderr, "Front size : 0x%x\n", sPriv->fbSize);
fprintf(stderr, "Front offset : 0x%x\n", intelScreen->frontOffset);
fprintf(stderr, "Back size : 0x%x\n", intelScreen->back.size);
fprintf(stderr, "Back offset : 0x%x\n", intelScreen->backOffset);
fprintf(stderr, "Depth size : 0x%x\n", intelScreen->depth.size);
fprintf(stderr, "Depth offset : 0x%x\n", intelScreen->depthOffset);
fprintf(stderr, "Texture size : 0x%x\n", intelScreen->textureSize);
fprintf(stderr, "Texture offset : 0x%x\n", intelScreen->textureOffset);
fprintf(stderr, "Memory : 0x%x\n", gDRIPriv->mem);
}
static GLboolean intelInitDriver(__DRIscreenPrivate *sPriv)
{
intelScreenPrivate *intelScreen;
I830DRIPtr gDRIPriv = (I830DRIPtr)sPriv->pDevPriv;
/* Allocate the private area */
intelScreen = (intelScreenPrivate *)MALLOC(sizeof(intelScreenPrivate));
if (!intelScreen) {
fprintf(stderr,"\nERROR! Allocating private area failed\n");
return GL_FALSE;
}
intelScreen->driScrnPriv = sPriv;
sPriv->private = (void *)intelScreen;
intelScreen->deviceID = gDRIPriv->deviceID;
intelScreen->width = gDRIPriv->width;
intelScreen->height = gDRIPriv->height;
intelScreen->mem = gDRIPriv->mem;
intelScreen->cpp = gDRIPriv->cpp;
intelScreen->frontPitch = gDRIPriv->fbStride;
intelScreen->frontOffset = gDRIPriv->fbOffset;
switch (gDRIPriv->bitsPerPixel) {
case 15: intelScreen->fbFormat = DV_PF_555; break;
case 16: intelScreen->fbFormat = DV_PF_565; break;
case 32: intelScreen->fbFormat = DV_PF_8888; break;
}
intelScreen->backOffset = gDRIPriv->backOffset;
intelScreen->backPitch = gDRIPriv->backPitch;
intelScreen->depthOffset = gDRIPriv->depthOffset;
intelScreen->depthPitch = gDRIPriv->depthPitch;
intelScreen->textureOffset = gDRIPriv->textureOffset;
intelScreen->textureSize = gDRIPriv->textureSize;
intelScreen->logTextureGranularity = gDRIPriv->logTextureGranularity;
intelScreen->back.handle = gDRIPriv->backbuffer;
intelScreen->back.size = gDRIPriv->backbufferSize;
if (drmMap(sPriv->fd,
intelScreen->back.handle,
intelScreen->back.size,
(drmAddress *)&intelScreen->back.map) != 0) {
fprintf(stderr, "\nERROR: line %d, Function %s, File %s\n",
__LINE__, __FUNCTION__, __FILE__);
FREE(intelScreen);
sPriv->private = NULL;
return GL_FALSE;
}
intelScreen->depth.handle = gDRIPriv->depthbuffer;
intelScreen->depth.size = gDRIPriv->depthbufferSize;
if (drmMap(sPriv->fd,
intelScreen->depth.handle,
intelScreen->depth.size,
(drmAddress *)&intelScreen->depth.map) != 0) {
fprintf(stderr, "\nERROR: line %d, Function %s, File %s\n",
__LINE__, __FUNCTION__, __FILE__);
FREE(intelScreen);
drmUnmap(intelScreen->back.map, intelScreen->back.size);
sPriv->private = NULL;
return GL_FALSE;
}
intelScreen->tex.handle = gDRIPriv->textures;
intelScreen->tex.size = gDRIPriv->textureSize;
if (drmMap(sPriv->fd,
intelScreen->tex.handle,
intelScreen->tex.size,
(drmAddress *)&intelScreen->tex.map) != 0) {
fprintf(stderr, "\nERROR: line %d, Function %s, File %s\n",
__LINE__, __FUNCTION__, __FILE__);
FREE(intelScreen);
drmUnmap(intelScreen->back.map, intelScreen->back.size);
drmUnmap(intelScreen->depth.map, intelScreen->depth.size);
sPriv->private = NULL;
return GL_FALSE;
}
intelScreen->sarea_priv_offset = gDRIPriv->sarea_priv_offset;
if (0) intelPrintDRIInfo(intelScreen, sPriv, gDRIPriv);
intelScreen->drmMinor = sPriv->drmMinor;
{
int ret;
drmI830GetParam gp;
gp.param = I830_PARAM_IRQ_ACTIVE;
gp.value = &intelScreen->irq_active;
ret = drmCommandWriteRead( sPriv->fd, DRM_I830_GETPARAM,
&gp, sizeof(gp));
if (ret) {
fprintf(stderr, "drmI830GetParam: %d\n", ret);
return GL_FALSE;
}
}
{
int ret;
drmI830GetParam gp;
gp.param = I830_PARAM_ALLOW_BATCHBUFFER;
gp.value = &intelScreen->allow_batchbuffer;
ret = drmCommandWriteRead( sPriv->fd, DRM_I830_GETPARAM,
&gp, sizeof(gp));
if (ret) {
fprintf(stderr, "drmI830GetParam: (%d) %d\n", gp.param, ret);
return GL_FALSE;
}
}
#ifndef _SOLO
if ( driCompareGLXAPIVersion( 20030813 ) >= 0 ) {
PFNGLXSCRENABLEEXTENSIONPROC glx_enable_extension =
(PFNGLXSCRENABLEEXTENSIONPROC) glXGetProcAddress( (const GLubyte *) "__glXScrEnableExtension" );
void * const psc = sPriv->psc->screenConfigs;
if (glx_enable_extension != NULL) {
(*glx_enable_extension)( psc, "GLX_SGI_make_current_read" );
if ( driCompareGLXAPIVersion( 20030915 ) >= 0 ) {
(*glx_enable_extension)( psc, "GLX_SGIX_fbconfig" );
(*glx_enable_extension)( psc, "GLX_OML_swap_method" );
}
if ( driCompareGLXAPIVersion( 20030818 ) >= 0 ) {
sPriv->psc->allocateMemory = (void *) intelAllocateMemoryMESA;
sPriv->psc->freeMemory = (void *) intelFreeMemoryMESA;
sPriv->psc->memoryOffset = (void *) intelGetMemoryOffsetMESA;
(*glx_enable_extension)( psc, "GLX_MESA_allocate_memory" );
}
}
}
#endif
return GL_TRUE;
}
static void intelDestroyScreen(__DRIscreenPrivate *sPriv)
{
intelScreenPrivate *intelScreen = (intelScreenPrivate *)sPriv->private;
/* Need to unmap all the bufs and maps here:
*/
drmUnmap(intelScreen->back.map, intelScreen->back.size);
drmUnmap(intelScreen->depth.map, intelScreen->depth.size);
drmUnmap(intelScreen->tex.map, intelScreen->tex.size);
FREE(intelScreen);
sPriv->private = NULL;
}
static GLboolean intelCreateBuffer( __DRIscreenPrivate *driScrnPriv,
__DRIdrawablePrivate *driDrawPriv,
const __GLcontextModes *mesaVis,
GLboolean isPixmap )
{
if (isPixmap) {
return GL_FALSE; /* not implemented */
} else {
GLboolean swStencil = (mesaVis->stencilBits > 0 &&
mesaVis->depthBits != 24);
driDrawPriv->driverPrivate = (void *)
_mesa_create_framebuffer(mesaVis,
GL_FALSE, /* software depth buffer? */
swStencil,
mesaVis->accumRedBits > 0,
GL_FALSE /* s/w alpha planes */);
return (driDrawPriv->driverPrivate != NULL);
}
}
static void intelDestroyBuffer(__DRIdrawablePrivate *driDrawPriv)
{
_mesa_destroy_framebuffer((GLframebuffer *) (driDrawPriv->driverPrivate));
}
/* There are probably better ways to do this, such as an
* init-designated function to register chipids and createcontext
* functions.
*/
extern GLboolean i830CreateContext( const __GLcontextModes *mesaVis,
__DRIcontextPrivate *driContextPriv,
void *sharedContextPrivate);
extern GLboolean i915CreateContext( const __GLcontextModes *mesaVis,
__DRIcontextPrivate *driContextPriv,
void *sharedContextPrivate);
static GLboolean intelCreateContext( const __GLcontextModes *mesaVis,
__DRIcontextPrivate *driContextPriv,
void *sharedContextPrivate)
{
__DRIscreenPrivate *sPriv = driContextPriv->driScreenPriv;
intelScreenPrivate *intelScreen = (intelScreenPrivate *)sPriv->private;
switch (intelScreen->deviceID) {
case PCI_CHIP_845_G:
case PCI_CHIP_I830_M:
case PCI_CHIP_I855_GM:
case PCI_CHIP_I865_G:
return i830CreateContext( mesaVis, driContextPriv,
sharedContextPrivate );
case PCI_CHIP_I915_G:
return i915CreateContext( mesaVis, driContextPriv,
sharedContextPrivate );
default:
fprintf(stderr, "Unrecognized deviceID %x\n", intelScreen->deviceID);
return GL_FALSE;
}
}
static const struct __DriverAPIRec intelAPI = {
.InitDriver = intelInitDriver,
.DestroyScreen = intelDestroyScreen,
.CreateContext = intelCreateContext,
.DestroyContext = intelDestroyContext,
.CreateBuffer = intelCreateBuffer,
.DestroyBuffer = intelDestroyBuffer,
.SwapBuffers = intelSwapBuffers,
.MakeCurrent = intelMakeCurrent,
.UnbindContext = intelUnbindContext,
.GetSwapInfo = NULL,
.GetMSC = NULL,
.WaitForMSC = NULL,
.WaitForSBC = NULL,
.SwapBuffersMSC = NULL
};
/*
* This is the bootstrap function for the driver.
* The __driCreateScreen name is the symbol that libGL.so fetches.
* Return: pointer to a __DRIscreenPrivate.
*/
#if !defined(DRI_NEW_INTERFACE_ONLY)
#ifndef _SOLO
void *__driCreateScreen(Display *dpy, int scrn, __DRIscreen *psc,
int numConfigs, __GLXvisualConfig *config)
{
__DRIscreenPrivate *psp;
psp = __driUtilCreateScreen(dpy, scrn, psc, numConfigs, config, &intelAPI);
return (void *) psp;
}
#else
void *__driCreateScreen(struct DRIDriverRec *driver,
struct DRIDriverContextRec *driverContext)
{
__DRIscreenPrivate *psp;
psp = __driUtilCreateScreen(driver, driverContext, &i830API);
return (void *) psp;
}
#endif
#endif /* !defined(DRI_NEW_INTERFACE_ONLY) */
/* This function is called by libGL.so as soon as libGL.so is loaded.
* This is where we'd register new extension functions with the dispatcher.
*
* Note: Most of these are probably already registered - just doing
* this for the benefit of old libGL.so's out there.
*/
#include "glapioffsets.h"
void __driRegisterExtensions( void )
{
int i;
static struct { const char *name; int offset; } funcs[] = {
{ "glSecondaryColor3bEXT", _gloffset_SecondaryColor3bEXT },
{ "glSecondaryColor3dEXT", _gloffset_SecondaryColor3dEXT },
{ "glSecondaryColor3fEXT", _gloffset_SecondaryColor3fEXT },
{ "glSecondaryColor3iEXT", _gloffset_SecondaryColor3iEXT },
{ "glSecondaryColor3sEXT", _gloffset_SecondaryColor3sEXT },
{ "glSecondaryColor3ubEXT", _gloffset_SecondaryColor3ubEXT },
{ "glSecondaryColor3uiEXT", _gloffset_SecondaryColor3uiEXT },
{ "glSecondaryColor3usEXT", _gloffset_SecondaryColor3usEXT },
{ "glSecondaryColor3bvEXT", _gloffset_SecondaryColor3bvEXT },
{ "glSecondaryColor3dvEXT", _gloffset_SecondaryColor3dvEXT },
{ "glSecondaryColor3fvEXT", _gloffset_SecondaryColor3fvEXT },
{ "glSecondaryColor3ivEXT", _gloffset_SecondaryColor3ivEXT },
{ "glSecondaryColor3svEXT", _gloffset_SecondaryColor3svEXT },
{ "glSecondaryColor3ubvEXT", _gloffset_SecondaryColor3ubvEXT },
{ "glSecondaryColor3uivEXT", _gloffset_SecondaryColor3uivEXT },
{ "glSecondaryColor3usvEXT", _gloffset_SecondaryColor3usvEXT },
{ "glSecondaryColorPointerEXT", _gloffset_SecondaryColorPointerEXT }
};
for (i = 0 ; i < sizeof(funcs) / sizeof(*funcs) ; i++ )
_glapi_add_entrypoint( funcs[i].name, funcs[i].offset );
}
#ifdef USE_NEW_INTERFACE
static __GLcontextModes * fill_in_modes( __GLcontextModes * modes,
unsigned pixel_bits,
unsigned depth_bits,
unsigned stencil_bits,
const GLenum * db_modes,
unsigned num_db_modes,
int visType )
{
static const uint8_t bits[2][4] = {
{ 5, 6, 5, 0 },
{ 8, 8, 8, 8 }
};
static const uint32_t masks[2][4] = {
{ 0x0000F800, 0x000007E0, 0x0000001F, 0x00000000 },
{ 0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000 }
};
unsigned i;
unsigned j;
const unsigned index = ((pixel_bits + 15) / 16) - 1;
for ( i = 0 ; i < num_db_modes ; i++ ) {
for ( j = 0 ; j < 2 ; j++ ) {
modes->redBits = bits[index][0];
modes->greenBits = bits[index][1];
modes->blueBits = bits[index][2];
modes->alphaBits = bits[index][3];
modes->redMask = masks[index][0];
modes->greenMask = masks[index][1];
modes->blueMask = masks[index][2];
modes->alphaMask = masks[index][3];
modes->rgbBits = modes->redBits + modes->greenBits
+ modes->blueBits + modes->alphaBits;
modes->accumRedBits = 16 * j;
modes->accumGreenBits = 16 * j;
modes->accumBlueBits = 16 * j;
modes->accumAlphaBits = (masks[index][3] != 0) ? 16 * j : 0;
modes->visualRating = (j == 0) ? GLX_NONE : GLX_SLOW_CONFIG;
modes->stencilBits = stencil_bits;
modes->depthBits = depth_bits;
modes->visualType = visType;
modes->renderType = GLX_RGBA_BIT;
modes->drawableType = GLX_WINDOW_BIT;
modes->rgbMode = GL_TRUE;
if ( db_modes[i] == GLX_NONE ) {
modes->doubleBufferMode = GL_FALSE;
}
else {
modes->doubleBufferMode = GL_TRUE;
modes->swapMethod = db_modes[i];
}
modes = modes->next;
}
}
return modes;
}
#endif /* USE_NEW_INTERFACE */
#ifdef USE_NEW_INTERFACE
static __GLcontextModes *
intelFillInModes( unsigned pixel_bits, unsigned depth_bits,
unsigned stencil_bits, GLboolean have_back_buffer )
{
__GLcontextModes * modes;
__GLcontextModes * m;
unsigned num_modes;
unsigned depth_buffer_factor;
unsigned back_buffer_factor;
unsigned i;
/* GLX_SWAP_COPY_OML is only supported because the MGA driver doesn't
* support pageflipping at all.
*/
static const GLenum back_buffer_modes[] = {
GLX_NONE, GLX_SWAP_UNDEFINED_OML, GLX_SWAP_COPY_OML
};
int depth_buffer_modes[2][2];
depth_buffer_modes[0][0] = depth_bits;
depth_buffer_modes[1][0] = depth_bits;
/* Just like with the accumulation buffer, always provide some modes
* with a stencil buffer. It will be a sw fallback, but some apps won't
* care about that.
*/
depth_buffer_modes[0][1] = 0;
depth_buffer_modes[1][1] = (stencil_bits == 0) ? 8 : stencil_bits;
depth_buffer_factor = ((depth_bits != 0) || (stencil_bits != 0)) ? 2 : 1;
back_buffer_factor = (have_back_buffer) ? 3 : 1;
num_modes = depth_buffer_factor * back_buffer_factor * 4;
modes = (*create_context_modes)( num_modes, sizeof( __GLcontextModes ) );
m = modes;
for ( i = 0 ; i < depth_buffer_factor ; i++ ) {
m = fill_in_modes( m, pixel_bits,
depth_buffer_modes[i][0], depth_buffer_modes[i][1],
back_buffer_modes, back_buffer_factor,
GLX_TRUE_COLOR );
}
/* There's no direct color modes on intel? */
#if 0
for ( i = 0 ; i < depth_buffer_factor ; i++ ) {
m = fill_in_modes( m, pixel_bits,
depth_buffer_modes[i][0], depth_buffer_modes[i][1],
back_buffer_modes, back_buffer_factor,
GLX_DIRECT_COLOR );
}
#endif
/* Mark the visual as slow if there are "fake" stencil bits.
*/
for ( m = modes ; m != NULL ; m = m->next ) {
if ( (m->stencilBits != 0) && (m->stencilBits != stencil_bits) ) {
m->visualRating = GLX_SLOW_CONFIG;
}
}
return modes;
}
#endif /* USE_NEW_INTERFACE */
/**
* This is the bootstrap function for the driver. libGL supplies all of the
* requisite information about the system, and the driver initializes itself.
* This routine also fills in the linked list pointed to by \c driver_modes
* with the \c __GLcontextModes that the driver can support for windows or
* pbuffers.
*
* \return A pointer to a \c __DRIscreenPrivate on success, or \c NULL on
* failure.
*/
#ifdef USE_NEW_INTERFACE
void * __driCreateNewScreen( __DRInativeDisplay *dpy, int scrn, __DRIscreen *psc,
const __GLcontextModes * modes,
const __DRIversion * ddx_version,
const __DRIversion * dri_version,
const __DRIversion * drm_version,
const __DRIframebuffer * frame_buffer,
drmAddress pSAREA, int fd,
int internal_api_version,
__GLcontextModes ** driver_modes )
{
__DRIscreenPrivate *psp;
static const __DRIversion ddx_expected = { 1, 0, 0 };
static const __DRIversion dri_expected = { 4, 0, 0 };
static const __DRIversion drm_expected = { 1, 1, 0 };
if ( ! driCheckDriDdxDrmVersions2( "i915",
dri_version, & dri_expected,
ddx_version, & ddx_expected,
drm_version, & drm_expected ) ) {
return NULL;
}
psp = __driUtilCreateNewScreen(dpy, scrn, psc, NULL,
ddx_version, dri_version, drm_version,
frame_buffer, pSAREA, fd,
internal_api_version, &intelAPI);
if ( psp != NULL ) {
create_context_modes = (PFNGLXCREATECONTEXTMODES)
glXGetProcAddress( (const GLubyte *) "__glXCreateContextModes" );
if ( create_context_modes != NULL ) {
I830DRIPtr dri_priv = (I830DRIPtr) psp->pDevPriv;
*driver_modes = intelFillInModes( dri_priv->cpp * 8,
(dri_priv->cpp == 2) ? 16 : 24,
(dri_priv->cpp == 2) ? 0 : 8,
(dri_priv->backOffset != dri_priv->depthOffset) );
}
}
return (void *) psp;
}
#endif /* USE_NEW_INTERFACE */
+76
View File
@@ -0,0 +1,76 @@
/**************************************************************************
*
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
**************************************************************************/
#ifndef _INTEL_INIT_H_
#define _INTEL_INIT_H_
#include <sys/time.h>
#include "dri_util.h"
typedef struct {
drm_handle_t handle;
drmSize size;
char *map;
} intelRegion;
typedef struct
{
intelRegion front;
intelRegion back;
intelRegion depth;
intelRegion tex;
int deviceID;
int width;
int height;
int mem;
int cpp; /* for front and back buffers */
int bitsPerPixel;
int fbFormat;
int frontOffset;
int frontPitch;
int backOffset;
int backPitch;
int depthOffset;
int depthPitch;
int textureOffset;
int textureSize;
int logTextureGranularity;
__DRIscreenPrivate *driScrnPriv;
unsigned int sarea_priv_offset;
int drmMinor;
int irq_active;
int allow_batchbuffer;
} intelScreenPrivate;
extern void
intelDestroyContext(__DRIcontextPrivate *driContextPriv);
extern GLboolean
intelUnbindContext(__DRIcontextPrivate *driContextPriv);
extern GLboolean
intelMakeCurrent(__DRIcontextPrivate *driContextPriv,
__DRIdrawablePrivate *driDrawPriv,
__DRIdrawablePrivate *driReadPriv);
extern void
intelSwapBuffers( __DRIdrawablePrivate *dPriv);
#endif
+323
View File
@@ -0,0 +1,323 @@
/**************************************************************************
*
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
**************************************************************************/
#include "glheader.h"
#include "macros.h"
#include "mtypes.h"
#include "colormac.h"
#include "intel_screen.h"
#include "intel_span.h"
#include "intel_ioctl.h"
#include "swrast/swrast.h"
#define DBG 0
#define LOCAL_VARS \
intelContextPtr intel = INTEL_CONTEXT(ctx); \
__DRIdrawablePrivate *dPriv = intel->driDrawable; \
intelScreenPrivate *intelScreen = intel->intelScreen; \
GLuint pitch = intelScreen->backPitch * intelScreen->cpp; \
GLuint height = dPriv->h; \
char *buf = (char *)(intel->drawMap + \
dPriv->x * intelScreen->cpp + \
dPriv->y * pitch); \
char *read_buf = (char *)(intel->readMap + \
dPriv->x * intelScreen->cpp + \
dPriv->y * pitch); \
GLushort p; \
(void) read_buf; (void) buf; (void) p
#define LOCAL_DEPTH_VARS \
intelContextPtr intel = INTEL_CONTEXT(ctx); \
__DRIdrawablePrivate *dPriv = intel->driDrawable; \
intelScreenPrivate *intelScreen = intel->intelScreen; \
GLuint pitch = intelScreen->backPitch * intelScreen->cpp; \
GLuint height = dPriv->h; \
char *buf = (char *)(intelScreen->depth.map + \
dPriv->x * intelScreen->cpp + \
dPriv->y * pitch)
#define LOCAL_STENCIL_VARS LOCAL_DEPTH_VARS
#define INIT_MONO_PIXEL(p,color)\
p = PACK_COLOR_565(color[0],color[1],color[2])
#define CLIPPIXEL(_x,_y) (_x >= minx && _x < maxx && \
_y >= miny && _y < maxy)
#define CLIPSPAN( _x, _y, _n, _x1, _n1, _i ) \
if ( _y < miny || _y >= maxy ) { \
_n1 = 0, _x1 = x; \
} else { \
_n1 = _n; \
_x1 = _x; \
if ( _x1 < minx ) _i += (minx-_x1), n1 -= (minx-_x1), _x1 = minx; \
if ( _x1 + _n1 >= maxx ) n1 -= (_x1 + n1 - maxx); \
}
#define Y_FLIP(_y) (height - _y - 1)
#define HW_LOCK()
#define HW_CLIPLOOP() \
do { \
__DRIdrawablePrivate *dPriv = intel->driDrawable; \
int _nc = dPriv->numClipRects; \
while (_nc--) { \
int minx = dPriv->pClipRects[_nc].x1 - dPriv->x; \
int miny = dPriv->pClipRects[_nc].y1 - dPriv->y; \
int maxx = dPriv->pClipRects[_nc].x2 - dPriv->x; \
int maxy = dPriv->pClipRects[_nc].y2 - dPriv->y;
#define HW_ENDCLIPLOOP() \
} \
} while (0)
#define HW_UNLOCK()
/* 16 bit, 565 rgb color spanline and pixel functions
*/
#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 *)(read_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] = 255; \
} while(0)
#define TAG(x) intel##x##_565
#include "spantmp.h"
/* 15 bit, 555 rgb color spanline and pixel functions
*/
#define WRITE_RGBA( _x, _y, r, g, b, a ) \
*(GLushort *)(buf + _x*2 + _y*pitch) = (((r & 0xf8) << 7) | \
((g & 0xf8) << 3) | \
((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 *)(read_buf + _x*2 + _y*pitch); \
rgba[0] = (p >> 7) & 0xf8; \
rgba[1] = (p >> 3) & 0xf8; \
rgba[2] = (p << 3) & 0xf8; \
rgba[3] = 255; \
} while(0)
#define TAG(x) intel##x##_555
#include "spantmp.h"
/* 16 bit depthbuffer functions.
*/
#define WRITE_DEPTH( _x, _y, d ) \
*(GLushort *)(buf + _x*2 + _y*pitch) = d;
#define READ_DEPTH( d, _x, _y ) \
d = *(GLushort *)(buf + _x*2 + _y*pitch);
#define TAG(x) intel##x##_16
#include "depthtmp.h"
#undef LOCAL_VARS
#define LOCAL_VARS \
intelContextPtr intel = INTEL_CONTEXT(ctx); \
__DRIdrawablePrivate *dPriv = intel->driDrawable; \
intelScreenPrivate *intelScreen = intel->intelScreen; \
GLuint pitch = intelScreen->backPitch * intelScreen->cpp; \
GLuint height = dPriv->h; \
char *buf = (char *)(intel->drawMap + \
dPriv->x * intelScreen->cpp + \
dPriv->y * pitch); \
char *read_buf = (char *)(intel->readMap + \
dPriv->x * intelScreen->cpp + \
dPriv->y * pitch); \
GLuint p; \
(void) read_buf; (void) buf; (void) p
#undef INIT_MONO_PIXEL
#define INIT_MONO_PIXEL(p,color)\
p = PACK_COLOR_888(color[0],color[1],color[2])
/* 32 bit, 8888 argb color spanline and pixel functions
*/
#define WRITE_RGBA(_x, _y, r, g, b, a) \
*(GLuint *)(buf + _x*4 + _y*pitch) = ((r << 16) | \
(g << 8) | \
(b << 0) | \
(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 *)(read_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) intel##x##_8888
#include "spantmp.h"
/* 24/8 bit interleaved depth/stencil functions
*/
#define WRITE_DEPTH( _x, _y, d ) { \
GLuint tmp = *(GLuint *)(buf + (_x)*4 + (_y)*pitch); \
tmp &= 0xff000000; \
tmp |= (d) & 0xffffff; \
*(GLuint *)(buf + (_x)*4 + (_y)*pitch) = tmp; \
}
#define READ_DEPTH( d, _x, _y ) \
d = *(GLuint *)(buf + (_x)*4 + (_y)*pitch) & 0xffffff;
#define TAG(x) intel##x##_24_8
#include "depthtmp.h"
#define WRITE_STENCIL( _x, _y, d ) { \
GLuint tmp = *(GLuint *)(buf + (_x)*4 + (_y)*pitch); \
tmp &= 0xffffff; \
tmp |= ((d)<<24); \
*(GLuint *)(buf + (_x)*4 + (_y)*pitch) = tmp; \
}
#define READ_STENCIL( d, _x, _y ) \
d = *(GLuint *)(buf + (_x)*4 + (_y)*pitch) >> 24;
#define TAG(x) intel##x##_24_8
#include "stenciltmp.h"
/*
* This function is called to specify which buffer to read and write
* for software rasterization (swrast) fallbacks. This doesn't necessarily
* correspond to glDrawBuffer() or glReadBuffer() calls.
*/
static void intelSetBuffer(GLcontext *ctx, GLframebuffer *colorBuffer,
GLuint bufferBit)
{
intelContextPtr intel = INTEL_CONTEXT(ctx);
if (bufferBit == DD_FRONT_LEFT_BIT) {
intel->drawMap = (char *)intel->driScreen->pFB;
intel->readMap = (char *)intel->driScreen->pFB;
} else if (bufferBit == DD_BACK_LEFT_BIT) {
intel->drawMap = intel->intelScreen->back.map;
intel->readMap = intel->intelScreen->back.map;
} else {
ASSERT(0);
}
}
/* Move locking out to get reasonable span performance.
*/
void intelSpanRenderStart( GLcontext *ctx )
{
intelContextPtr intel = INTEL_CONTEXT(ctx);
intelFlush(&intel->ctx);
LOCK_HARDWARE(intel);
intelWaitForIdle(intel);
}
void intelSpanRenderFinish( GLcontext *ctx )
{
intelContextPtr intel = INTEL_CONTEXT( ctx );
_swrast_flush( ctx );
UNLOCK_HARDWARE( intel );
}
void intelInitSpanFuncs( GLcontext *ctx )
{
intelContextPtr intel = INTEL_CONTEXT(ctx);
intelScreenPrivate *intelScreen = intel->intelScreen;
struct swrast_device_driver *swdd = _swrast_GetDeviceDriverReference(ctx);
swdd->SetBuffer = intelSetBuffer;
switch (intelScreen->fbFormat) {
case DV_PF_555:
swdd->WriteRGBASpan = intelWriteRGBASpan_555;
swdd->WriteRGBSpan = intelWriteRGBSpan_555;
swdd->WriteMonoRGBASpan = intelWriteMonoRGBASpan_555;
swdd->WriteRGBAPixels = intelWriteRGBAPixels_555;
swdd->WriteMonoRGBAPixels = intelWriteMonoRGBAPixels_555;
swdd->ReadRGBASpan = intelReadRGBASpan_555;
swdd->ReadRGBAPixels = intelReadRGBAPixels_555;
swdd->ReadDepthSpan = intelReadDepthSpan_16;
swdd->WriteDepthSpan = intelWriteDepthSpan_16;
swdd->ReadDepthPixels = intelReadDepthPixels_16;
swdd->WriteDepthPixels = intelWriteDepthPixels_16;
break;
case DV_PF_565:
swdd->WriteRGBASpan = intelWriteRGBASpan_565;
swdd->WriteRGBSpan = intelWriteRGBSpan_565;
swdd->WriteMonoRGBASpan = intelWriteMonoRGBASpan_565;
swdd->WriteRGBAPixels = intelWriteRGBAPixels_565;
swdd->WriteMonoRGBAPixels = intelWriteMonoRGBAPixels_565;
swdd->ReadRGBASpan = intelReadRGBASpan_565;
swdd->ReadRGBAPixels = intelReadRGBAPixels_565;
swdd->ReadDepthSpan = intelReadDepthSpan_16;
swdd->WriteDepthSpan = intelWriteDepthSpan_16;
swdd->ReadDepthPixels = intelReadDepthPixels_16;
swdd->WriteDepthPixels = intelWriteDepthPixels_16;
break;
case DV_PF_8888:
swdd->WriteRGBASpan = intelWriteRGBASpan_8888;
swdd->WriteRGBSpan = intelWriteRGBSpan_8888;
swdd->WriteMonoRGBASpan = intelWriteMonoRGBASpan_8888;
swdd->WriteRGBAPixels = intelWriteRGBAPixels_8888;
swdd->WriteMonoRGBAPixels = intelWriteMonoRGBAPixels_8888;
swdd->ReadRGBASpan = intelReadRGBASpan_8888;
swdd->ReadRGBAPixels = intelReadRGBAPixels_8888;
swdd->ReadDepthSpan = intelReadDepthSpan_24_8;
swdd->WriteDepthSpan = intelWriteDepthSpan_24_8;
swdd->ReadDepthPixels = intelReadDepthPixels_24_8;
swdd->WriteDepthPixels = intelWriteDepthPixels_24_8;
swdd->WriteStencilSpan = intelWriteStencilSpan_24_8;
swdd->ReadStencilSpan = intelReadStencilSpan_24_8;
swdd->WriteStencilPixels = intelWriteStencilPixels_24_8;
swdd->ReadStencilPixels = intelReadStencilPixels_24_8;
break;
}
swdd->SpanRenderStart = intelSpanRenderStart;
swdd->SpanRenderFinish = intelSpanRenderFinish;
}
+16
View File
@@ -0,0 +1,16 @@
/**************************************************************************
*
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
**************************************************************************/
#ifndef _INTEL_SPAN_H
#define _INTEL_SPAN_H
extern void intelInitSpanFuncs( GLcontext *ctx );
extern void intelSpanRenderFinish( GLcontext *ctx );
extern void intelSpanRenderStart( GLcontext *ctx );
#endif
+135
View File
@@ -0,0 +1,135 @@
/**************************************************************************
*
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
**************************************************************************/
#include "glheader.h"
#include "context.h"
#include "macros.h"
#include "enums.h"
#include "dd.h"
#include "intel_screen.h"
#include "intel_context.h"
#include "swrast/swrast.h"
static void intelDrawBuffer(GLcontext *ctx, GLenum mode )
{
intelContextPtr intel = INTEL_CONTEXT(ctx);
intelScreenPrivate *screen = intel->intelScreen;
int front = 0;
switch ( ctx->Color._DrawDestMask ) {
case DD_FRONT_LEFT_BIT:
front = 1;
FALLBACK( intel, INTEL_FALLBACK_DRAW_BUFFER, GL_FALSE );
break;
case DD_BACK_LEFT_BIT:
front = 0;
FALLBACK( intel, INTEL_FALLBACK_DRAW_BUFFER, GL_FALSE );
break;
default:
FALLBACK( intel, INTEL_FALLBACK_DRAW_BUFFER, GL_TRUE );
return;
}
/* We want to update the s/w rast state too so that r200SetBuffer()
* gets called.
*/
_swrast_DrawBuffer(ctx, mode);
if ( intel->sarea->pf_current_page == 1 )
front ^= 1;
intelSetFrontClipRects( intel );
if (front) {
intel->drawOffset = screen->frontOffset;
intel->drawMap = (char *)intel->driScreen->pFB;
intel->readMap = (char *)intel->driScreen->pFB;
} else {
intel->drawOffset = screen->backOffset;
intel->drawMap = screen->back.map;
intel->readMap = screen->back.map;
}
intel->vtbl.set_draw_offset( intel, intel->drawOffset );
}
static void intelReadBuffer( GLcontext *ctx, GLenum mode )
{
/* nothing, until we implement h/w glRead/CopyPixels or CopyTexImage */
}
static void intelClearColor(GLcontext *ctx, const GLfloat color[4])
{
intelContextPtr intel = INTEL_CONTEXT(ctx);
intelScreenPrivate *screen = intel->intelScreen;
CLAMPED_FLOAT_TO_UBYTE(intel->clear_red, color[0]);
CLAMPED_FLOAT_TO_UBYTE(intel->clear_green, color[1]);
CLAMPED_FLOAT_TO_UBYTE(intel->clear_blue, color[2]);
CLAMPED_FLOAT_TO_UBYTE(intel->clear_alpha, color[3]);
intel->ClearColor = INTEL_PACKCOLOR(screen->fbFormat,
intel->clear_red,
intel->clear_green,
intel->clear_blue,
intel->clear_alpha);
}
static void intelCalcViewport( GLcontext *ctx )
{
intelContextPtr intel = INTEL_CONTEXT(ctx);
const GLfloat *v = ctx->Viewport._WindowMap.m;
GLfloat *m = intel->ViewportMatrix.m;
/* See also intel_translate_vertex. SUBPIXEL adjustments can be done
* via state vars, too.
*/
m[MAT_SX] = v[MAT_SX];
m[MAT_TX] = v[MAT_TX] + SUBPIXEL_X;
m[MAT_SY] = - v[MAT_SY];
m[MAT_TY] = - v[MAT_TY] + intel->driDrawable->h + SUBPIXEL_Y;
m[MAT_SZ] = v[MAT_SZ] * intel->depth_scale;
m[MAT_TZ] = v[MAT_TZ] * intel->depth_scale;
}
static void intelViewport( GLcontext *ctx,
GLint x, GLint y,
GLsizei width, GLsizei height )
{
intelCalcViewport( ctx );
}
static void intelDepthRange( GLcontext *ctx,
GLclampd nearval, GLclampd farval )
{
intelCalcViewport( ctx );
}
/* Fallback to swrast for select and feedback.
*/
static void intelRenderMode( GLcontext *ctx, GLenum mode )
{
intelContextPtr intel = INTEL_CONTEXT(ctx);
FALLBACK( intel, INTEL_FALLBACK_RENDERMODE, (mode != GL_RENDER) );
}
void intelInitStateFuncs( struct dd_function_table *functions )
{
functions->DrawBuffer = intelDrawBuffer;
functions->ReadBuffer = intelReadBuffer;
functions->RenderMode = intelRenderMode;
functions->Viewport = intelViewport;
functions->DepthRange = intelDepthRange;
functions->ClearColor = intelClearColor;
}
+665
View File
@@ -0,0 +1,665 @@
/**************************************************************************
*
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
**************************************************************************/
#include "glheader.h"
#include "mtypes.h"
#include "imports.h"
#include "simple_list.h"
#include "enums.h"
#include "image.h"
#include "texstore.h"
#include "texformat.h"
#include "teximage.h"
#include "texmem.h"
#include "texobj.h"
#include "swrast/swrast.h"
#include "mm.h"
#include "intel_screen.h"
#include "intel_batchbuffer.h"
#include "intel_context.h"
#include "intel_tex.h"
#include "intel_ioctl.h"
static GLboolean
intelValidateClientStorage( intelContextPtr intel, GLenum target,
GLint internalFormat,
GLint srcWidth, GLint srcHeight,
GLenum format, GLenum type, const void *pixels,
const struct gl_pixelstore_attrib *packing,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage)
{
GLcontext *ctx = &intel->ctx;
int texelBytes;
if (0)
fprintf(stderr, "intformat %s format %s type %s\n",
_mesa_lookup_enum_by_nr( internalFormat ),
_mesa_lookup_enum_by_nr( format ),
_mesa_lookup_enum_by_nr( type ));
if (!ctx->Unpack.ClientStorage)
return 0;
if (ctx->_ImageTransferState ||
texImage->IsCompressed ||
texObj->GenerateMipmap)
return 0;
/* This list is incomplete
*/
switch ( internalFormat ) {
case GL_RGBA:
if ( format == GL_BGRA && type == GL_UNSIGNED_INT_8_8_8_8_REV ) {
texImage->TexFormat = &_mesa_texformat_argb8888;
texelBytes = 4;
}
else
return 0;
break;
case GL_RGB:
if ( format == GL_RGB && type == GL_UNSIGNED_SHORT_5_6_5 ) {
texImage->TexFormat = &_mesa_texformat_rgb565;
texelBytes = 2;
}
else
return 0;
break;
case GL_YCBCR_MESA:
if ( format == GL_YCBCR_MESA &&
type == GL_UNSIGNED_SHORT_8_8_REV_APPLE ) {
texImage->TexFormat = &_mesa_texformat_ycbcr_rev;
texelBytes = 2;
}
else if ( format == GL_YCBCR_MESA &&
(type == GL_UNSIGNED_SHORT_8_8_APPLE ||
type == GL_UNSIGNED_BYTE)) {
texImage->TexFormat = &_mesa_texformat_ycbcr;
texelBytes = 2;
}
else
return 0;
break;
default:
return 0;
}
/* Could deal with these packing issues, but currently don't:
*/
if (packing->SkipPixels ||
packing->SkipRows ||
packing->SwapBytes ||
packing->LsbFirst) {
return 0;
}
{
GLint srcRowStride = _mesa_image_row_stride(packing, srcWidth,
format, type);
if (0)
fprintf(stderr, "%s: srcRowStride %d/%x\n",
__FUNCTION__, srcRowStride, srcRowStride);
/* Could check this later in upload, pitch restrictions could be
* relaxed, but would need to store the image pitch somewhere,
* as packing details might change before image is uploaded:
*/
if (!intelIsAgpMemory( intel, pixels, srcHeight * srcRowStride ) ||
(srcRowStride & 63))
return 0;
/* Have validated that _mesa_transfer_teximage would be a straight
* memcpy at this point. NOTE: future calls to TexSubImage will
* overwrite the client data. This is explicitly mentioned in the
* extension spec.
*/
texImage->Data = (void *)pixels;
texImage->IsClientData = GL_TRUE;
texImage->RowStride = srcRowStride / texelBytes;
return 1;
}
}
static void intelTexImage1D( GLcontext *ctx, GLenum target, GLint level,
GLint internalFormat,
GLint width, GLint border,
GLenum format, GLenum type, const GLvoid *pixels,
const struct gl_pixelstore_attrib *packing,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage )
{
driTextureObject * t = (driTextureObject *) texObj->DriverData;
assert(t);
intelFlush( ctx );
driSwapOutTextureObject( t );
texImage->IsClientData = GL_FALSE;
_mesa_store_teximage1d( ctx, target, level, internalFormat,
width, border, format, type,
pixels, packing, texObj, texImage );
t->dirty_images[0] |= (1 << level);
}
static void intelTexSubImage1D( GLcontext *ctx,
GLenum target,
GLint level,
GLint xoffset,
GLsizei width,
GLenum format, GLenum type,
const GLvoid *pixels,
const struct gl_pixelstore_attrib *packing,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage )
{
driTextureObject * t = (driTextureObject *) texObj->DriverData;
assert(t);
intelFlush( ctx );
driSwapOutTextureObject( t );
_mesa_store_texsubimage1d(ctx, target, level, xoffset, width,
format, type, pixels, packing, texObj,
texImage);
}
/* Handles 2D, CUBE, RECT:
*/
static void intelTexImage2D( GLcontext *ctx, GLenum target, GLint level,
GLint internalFormat,
GLint width, GLint height, GLint border,
GLenum format, GLenum type, const GLvoid *pixels,
const struct gl_pixelstore_attrib *packing,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage )
{
driTextureObject * t = (driTextureObject *) texObj->DriverData;
GLuint face;
/* which cube face or ordinary 2D image */
switch (target) {
case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
face = (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X;
ASSERT(face < 6);
break;
default:
face = 0;
}
assert(t);
intelFlush( ctx );
driSwapOutTextureObject( t );
texImage->IsClientData = GL_FALSE;
if (intelValidateClientStorage( INTEL_CONTEXT(ctx), target,
internalFormat,
width, height,
format, type, pixels,
packing, texObj, texImage)) {
if (INTEL_DEBUG & DEBUG_TEXTURE)
fprintf(stderr, "%s: Using client storage\n", __FUNCTION__);
}
else {
_mesa_store_teximage2d( ctx, target, level, internalFormat,
width, height, border, format, type,
pixels, packing, texObj, texImage );
t->dirty_images[face] |= (1 << level);
}
}
static void intelTexSubImage2D( GLcontext *ctx,
GLenum target,
GLint level,
GLint xoffset, GLint yoffset,
GLsizei width, GLsizei height,
GLenum format, GLenum type,
const GLvoid *pixels,
const struct gl_pixelstore_attrib *packing,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage )
{
driTextureObject * t = (driTextureObject *) texObj->DriverData;
GLuint face;
/* which cube face or ordinary 2D image */
switch (target) {
case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
face = (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X;
ASSERT(face < 6);
break;
default:
face = 0;
}
if (texImage->IsClientData &&
(char *)pixels == (char *)texImage->Data +
((xoffset + yoffset * texImage->RowStride) *
texImage->TexFormat->TexelBytes)) {
/* Notification only - no upload required */
}
else {
assert( t ); /* this _should_ be true */
intelFlush( ctx );
driSwapOutTextureObject( t );
_mesa_store_texsubimage2d(ctx, target, level, xoffset, yoffset, width,
height, format, type, pixels, packing, texObj,
texImage);
t->dirty_images[face] |= (1 << level);
}
}
static void intelTexImage3D( GLcontext *ctx, GLenum target, GLint level,
GLint internalFormat,
GLint width, GLint height, GLint depth,
GLint border,
GLenum format, GLenum type, const GLvoid *pixels,
const struct gl_pixelstore_attrib *packing,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage )
{
driTextureObject * t = (driTextureObject *) texObj->DriverData;
assert(t);
driSwapOutTextureObject( t );
texImage->IsClientData = GL_FALSE;
_mesa_store_teximage3d(ctx, target, level, internalFormat,
width, height, depth, border,
format, type, pixels,
&ctx->Unpack, texObj, texImage);
t->dirty_images[0] |= (1 << level);
}
static void
intelTexSubImage3D( GLcontext *ctx, GLenum target, GLint level,
GLint xoffset, GLint yoffset, GLint zoffset,
GLsizei width, GLsizei height, GLsizei depth,
GLenum format, GLenum type,
const GLvoid *pixels,
const struct gl_pixelstore_attrib *packing,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage )
{
driTextureObject * t = (driTextureObject *) texObj->DriverData;
assert( t ); /* this _should_ be true */
driSwapOutTextureObject( t );
_mesa_store_texsubimage3d(ctx, target, level, xoffset, yoffset, zoffset,
width, height, depth,
format, type, pixels, packing, texObj, texImage);
t->dirty_images[0] |= (1 << level);
}
static void intelDeleteTexture( GLcontext *ctx, struct gl_texture_object *tObj )
{
driTextureObject * t = (driTextureObject *) tObj->DriverData;
if ( t != NULL ) {
intelFlush( ctx );
driDestroyTextureObject( t );
}
/* Free mipmap images and the texture object itself */
_mesa_delete_texture_object(ctx, tObj);
}
static const struct gl_texture_format *
intelChooseTextureFormat( GLcontext *ctx, GLint internalFormat,
GLenum format, GLenum type )
{
intelContextPtr intel = INTEL_CONTEXT( ctx );
const GLboolean do32bpt = ( intel->intelScreen->cpp == 4 &&
intel->intelScreen->textureSize > 4*1024*1024);
switch ( internalFormat ) {
case 4:
case GL_RGBA:
case GL_COMPRESSED_RGBA:
if ( format == GL_BGRA ) {
if ( type == GL_UNSIGNED_INT_8_8_8_8_REV ) {
return &_mesa_texformat_argb8888;
}
else if ( type == GL_UNSIGNED_SHORT_4_4_4_4_REV ) {
return &_mesa_texformat_argb4444;
}
else if ( type == GL_UNSIGNED_SHORT_1_5_5_5_REV ) {
return &_mesa_texformat_argb1555;
}
}
return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_argb4444;
case 3:
case GL_RGB:
case GL_COMPRESSED_RGB:
if ( format == GL_RGB && type == GL_UNSIGNED_SHORT_5_6_5 ) {
return &_mesa_texformat_rgb565;
}
return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_rgb565;
case GL_RGBA8:
case GL_RGB10_A2:
case GL_RGBA12:
case GL_RGBA16:
return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_argb4444;
case GL_RGBA4:
case GL_RGBA2:
return &_mesa_texformat_argb4444;
case GL_RGB5_A1:
return &_mesa_texformat_argb1555;
case GL_RGB8:
case GL_RGB10:
case GL_RGB12:
case GL_RGB16:
return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_rgb565;
case GL_RGB5:
case GL_RGB4:
case GL_R3_G3_B2:
return &_mesa_texformat_rgb565;
case GL_ALPHA:
case GL_ALPHA4:
case GL_ALPHA8:
case GL_ALPHA12:
case GL_ALPHA16:
case GL_COMPRESSED_ALPHA:
/* if (1 || intel->intelScreen->deviceID == PCI_CHIP_I915_G) */
return &_mesa_texformat_a8;
/* else */
/* return &_mesa_texformat_al88; */
case 1:
case GL_LUMINANCE:
case GL_LUMINANCE4:
case GL_LUMINANCE8:
case GL_LUMINANCE12:
case GL_LUMINANCE16:
case GL_COMPRESSED_LUMINANCE:
return &_mesa_texformat_l8;
case 2:
case GL_LUMINANCE_ALPHA:
case GL_LUMINANCE4_ALPHA4:
case GL_LUMINANCE6_ALPHA2:
case GL_LUMINANCE8_ALPHA8:
case GL_LUMINANCE12_ALPHA4:
case GL_LUMINANCE12_ALPHA12:
case GL_LUMINANCE16_ALPHA16:
case GL_COMPRESSED_LUMINANCE_ALPHA:
return &_mesa_texformat_al88;
case GL_INTENSITY:
case GL_INTENSITY4:
case GL_INTENSITY8:
case GL_INTENSITY12:
case GL_INTENSITY16:
case GL_COMPRESSED_INTENSITY:
return &_mesa_texformat_i8;
case GL_YCBCR_MESA:
if (type == GL_UNSIGNED_SHORT_8_8_MESA ||
type == GL_UNSIGNED_BYTE)
return &_mesa_texformat_ycbcr;
else
return &_mesa_texformat_ycbcr_rev;
default:
fprintf(stderr, "unexpected texture format in %s\n", __FUNCTION__);
return NULL;
}
return NULL; /* never get here */
}
void intelDestroyTexObj(intelContextPtr intel, intelTextureObjectPtr t)
{
unsigned i;
if ( intel == NULL )
return;
if ( t->age > intel->dirtyAge )
intel->dirtyAge = t->age;
for ( i = 0 ; i < MAX_TEXTURE_UNITS ; i++ ) {
if ( t == intel->CurrentTexObj[ i ] )
intel->CurrentTexObj[ i ] = NULL;
}
}
/* Upload an image from mesa's internal copy. Image may be 1D, 2D or
* 3D. Cubemaps are expanded elsewhere.
*/
static void intelUploadTexImage( intelContextPtr intel,
intelTextureObjectPtr t,
const struct gl_texture_image *image,
const GLuint offset )
{
if (!image || !image->Data)
return;
if (image->Depth == 1 && image->IsClientData) {
if (INTEL_DEBUG & DEBUG_TEXTURE)
fprintf(stderr, "Blit uploading\n");
/* Do it with a blit.
*/
intelEmitCopyBlitLocked( intel,
image->TexFormat->TexelBytes,
image->RowStride, /* ? */
intelGetMemoryOffsetMESA( NULL, 0, image->Data ),
t->Pitch / image->TexFormat->TexelBytes,
intelGetMemoryOffsetMESA( NULL, 0, t->BufAddr + offset ),
0, 0,
0, 0,
image->Width,
image->Height);
}
else {
GLuint row_len = image->Width * image->TexFormat->TexelBytes;
GLubyte *dst = (GLubyte *)(t->BufAddr + offset);
GLubyte *src = (GLubyte *)image->Data;
GLuint d, j;
if (INTEL_DEBUG & DEBUG_TEXTURE)
fprintf(stderr,
"Upload image %dx%dx%d offset %xm row_len %x "
"pitch %x depth_pitch %x\n",
image->Width, image->Height, image->Depth, offset,
row_len, t->Pitch, t->depth_pitch);
if (row_len == t->Pitch) {
for (d = 0; d < image->Depth; d++) {
memcpy( dst, src, t->Pitch * image->Height );
dst += t->depth_pitch;
src += row_len * image->Height;
}
}
else {
for (d = 0 ; d < image->Depth ; d++) {
for (j = 0 ; j < image->Height ; j++) {
__memcpy(dst, src, row_len );
src += row_len;
dst += t->Pitch;
}
dst += t->depth_pitch - (t->Pitch * image->Height);
}
}
}
}
int intelUploadTexImages( intelContextPtr intel,
intelTextureObjectPtr t,
GLuint face)
{
const int numLevels = t->base.lastLevel - t->base.firstLevel + 1;
const struct gl_texture_image *firstImage = t->image[face][t->base.firstLevel].image;
int pitch = firstImage->RowStride * firstImage->TexFormat->TexelBytes;
/* Can we texture out of the existing client data? */
if ( numLevels == 1 &&
firstImage->IsClientData &&
(pitch & 3) == 0) {
if (INTEL_DEBUG & DEBUG_TEXTURE)
fprintf(stderr, "AGP texturing from client memory\n");
t->TextureOffset = intelAgpOffsetFromVirtual( intel, firstImage->Data );
t->BufAddr = 0;
t->dirty = ~0;
return GL_TRUE;
}
else {
if (INTEL_DEBUG & DEBUG_TEXTURE)
fprintf(stderr, "Uploading client data to agp\n");
INTEL_FIREVERTICES( intel );
LOCK_HARDWARE( intel );
if ( t->base.memBlock == NULL ) {
int heap;
heap = driAllocateTexture( intel->texture_heaps, intel->nr_heaps,
(driTextureObject *) t );
if ( heap == -1 ) {
UNLOCK_HARDWARE( intel );
return GL_FALSE;
}
/* Set the base offset of the texture image */
t->BufAddr = intel->intelScreen->tex.map + t->base.memBlock->ofs;
t->TextureOffset = intel->intelScreen->textureOffset + t->base.memBlock->ofs;
t->dirty = ~0;
}
/* Let the world know we've used this memory recently.
*/
driUpdateTextureLRU( (driTextureObject *) t );
/* Upload any images that are new */
if (t->base.dirty_images[face]) {
int i;
intelWaitForIdle( intel );
for (i = 0 ; i < numLevels ; i++) {
int level = i + t->base.firstLevel;
if (t->base.dirty_images[face] & (1<<level)) {
const struct gl_texture_image *image = t->image[face][i].image;
GLuint offset = t->image[face][i].offset;
if (INTEL_DEBUG & DEBUG_TEXTURE)
fprintf(stderr, "upload level %d, offset %x\n",
level, offset);
intelUploadTexImage( intel, t, image, offset );
}
}
t->base.dirty_images[face] = 0;
intel->perf_boxes |= I830_BOX_TEXTURE_LOAD;
}
UNLOCK_HARDWARE( intel );
return GL_TRUE;
}
}
/**
* Allocate a new texture object.
* Called via ctx->Driver.NewTextureObject.
* Note: this function will be called during context creation to
* allocate the default texture objects.
* Note: we could use containment here to 'derive' the driver-specific
* texture object from the core mesa gl_texture_object. Not done at this time.
*/
static struct gl_texture_object *
intelNewTextureObject( GLcontext *ctx, GLuint name, GLenum target )
{
struct gl_texture_object *obj = _mesa_new_texture_object(ctx, name, target);
INTEL_CONTEXT(ctx)->vtbl.alloc_tex_obj( obj );
return obj;
}
void intelInitTextureFuncs( struct dd_function_table *functions )
{
functions->NewTextureObject = intelNewTextureObject;
functions->ChooseTextureFormat = intelChooseTextureFormat;
functions->TexImage1D = intelTexImage1D;
functions->TexImage2D = intelTexImage2D;
functions->TexImage3D = intelTexImage3D;
functions->TexSubImage1D = intelTexSubImage1D;
functions->TexSubImage2D = intelTexSubImage2D;
functions->TexSubImage3D = intelTexSubImage3D;
functions->CopyTexImage1D = _swrast_copy_teximage1d;
functions->CopyTexImage2D = _swrast_copy_teximage2d;
functions->CopyTexSubImage1D = _swrast_copy_texsubimage1d;
functions->CopyTexSubImage2D = _swrast_copy_texsubimage2d;
functions->CopyTexSubImage3D = _swrast_copy_texsubimage3d;
functions->DeleteTexture = intelDeleteTexture;
functions->UpdateTexturePalette = NULL;
functions->IsTextureResident = driIsTextureResident;
functions->TestProxyTexImage = _mesa_test_proxy_teximage;
functions->DeleteTexture = intelDeleteTexture;
}
+22
View File
@@ -0,0 +1,22 @@
/**************************************************************************
*
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
**************************************************************************/
#ifndef INTELTEX_INC
#define INTELTEX_INC
#include "mtypes.h"
#include "intel_context.h"
#include "texmem.h"
void intelInitTextureFuncs( struct dd_function_table *functions );
void intelDestroyTexObj( intelContextPtr intel, intelTextureObjectPtr t );
int intelUploadTexImages( intelContextPtr intel, intelTextureObjectPtr t,
GLuint face );
#endif
+900
View File
@@ -0,0 +1,900 @@
/**************************************************************************
*
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
**************************************************************************/
#include "glheader.h"
#include "context.h"
#include "macros.h"
#include "enums.h"
#include "dd.h"
#include "swrast/swrast.h"
#include "swrast_setup/swrast_setup.h"
#include "tnl/t_context.h"
#include "tnl/t_pipeline.h"
#include "tnl/t_vertex.h"
#include "intel_screen.h"
#include "intel_tris.h"
#include "intel_batchbuffer.h"
#include "intel_reg.h"
#include "intel_span.h"
static void intelRenderPrimitive( GLcontext *ctx, GLenum prim );
static void intelRasterPrimitive( GLcontext *ctx, GLenum rprim, GLuint hwprim );
/***********************************************************************
* Emit primitives as inline vertices *
***********************************************************************/
#if 1
#define COPY_DWORDS( j, vb, vertsize, v ) \
do { \
int __tmp; \
__asm__ __volatile__( "rep ; movsl" \
: "=%c" (j), "=D" (vb), "=S" (__tmp) \
: "0" (vertsize), \
"D" ((long)vb), \
"S" ((long)v) ); \
} while (0)
#else
#define COPY_DWORDS( j, vb, vertsize, v ) \
do { \
if (1) fprintf(stderr, "\n"); \
for ( j = 0 ; j < vertsize ; j++ ) { \
if (1) fprintf(stderr, " -- v(%d): %x/%f\n",j, \
((GLuint *)v)[j], \
((GLfloat *)v)[j]); \
vb[j] = ((GLuint *)v)[j]; \
} \
vb += vertsize; \
} while (0)
#endif
static void __inline__ intel_draw_quad( intelContextPtr intel,
intelVertexPtr v0,
intelVertexPtr v1,
intelVertexPtr v2,
intelVertexPtr v3 )
{
GLuint vertsize = intel->vertex_size;
GLuint *vb = intelExtendInlinePrimitive( intel, 6 * vertsize );
int j;
COPY_DWORDS( j, vb, vertsize, v0 );
COPY_DWORDS( j, vb, vertsize, v1 );
COPY_DWORDS( j, vb, vertsize, v3 );
COPY_DWORDS( j, vb, vertsize, v1 );
COPY_DWORDS( j, vb, vertsize, v2 );
COPY_DWORDS( j, vb, vertsize, v3 );
}
static void __inline__ intel_draw_triangle( intelContextPtr intel,
intelVertexPtr v0,
intelVertexPtr v1,
intelVertexPtr v2 )
{
GLuint vertsize = intel->vertex_size;
GLuint *vb = intelExtendInlinePrimitive( intel, 3 * vertsize );
int j;
COPY_DWORDS( j, vb, vertsize, v0 );
COPY_DWORDS( j, vb, vertsize, v1 );
COPY_DWORDS( j, vb, vertsize, v2 );
}
static __inline__ void intel_draw_line( intelContextPtr intel,
intelVertexPtr v0,
intelVertexPtr v1 )
{
GLuint vertsize = intel->vertex_size;
GLuint *vb = intelExtendInlinePrimitive( intel, 2 * vertsize );
int j;
COPY_DWORDS( j, vb, vertsize, v0 );
COPY_DWORDS( j, vb, vertsize, v1 );
}
static __inline__ void intel_draw_point( intelContextPtr intel,
intelVertexPtr v0 )
{
GLuint vertsize = intel->vertex_size;
GLuint *vb = intelExtendInlinePrimitive( intel, vertsize );
int j;
/* Adjust for sub pixel position -- still required for conform. */
*(float *)&vb[0] = v0->v.x - 0.125;
*(float *)&vb[1] = v0->v.y - 0.125;
for (j = 2 ; j < vertsize ; j++)
vb[j] = v0->ui[j];
}
/***********************************************************************
* Fixup for ARB_point_parameters *
***********************************************************************/
static void intel_atten_point( intelContextPtr intel, intelVertexPtr v0 )
{
GLcontext *ctx = &intel->ctx;
GLfloat psz[4], col[4], restore_psz, restore_alpha;
_tnl_get_attr( ctx, v0, _TNL_ATTRIB_POINTSIZE, psz );
_tnl_get_attr( ctx, v0, _TNL_ATTRIB_COLOR0, col );
restore_psz = psz[0];
restore_alpha = col[3];
if (psz[0] >= ctx->Point.Threshold) {
psz[0] = MIN2(psz[0], ctx->Point.MaxSize);
}
else {
GLfloat dsize = psz[0] / ctx->Point.Threshold;
psz[0] = MAX2(ctx->Point.Threshold, ctx->Point.MinSize);
col[3] *= dsize * dsize;
}
if (psz[0] < 1.0)
psz[0] = 1.0;
if (restore_psz != psz[0] || restore_alpha != col[3]) {
_tnl_set_attr( ctx, v0, _TNL_ATTRIB_POINTSIZE, psz);
_tnl_set_attr( ctx, v0, _TNL_ATTRIB_COLOR0, col);
intel_draw_point( intel, v0 );
psz[0] = restore_psz;
col[3] = restore_alpha;
_tnl_set_attr( ctx, v0, _TNL_ATTRIB_POINTSIZE, psz);
_tnl_set_attr( ctx, v0, _TNL_ATTRIB_COLOR0, col);
}
else
intel_draw_point( intel, v0 );
}
/***********************************************************************
* Fixup for I915 WPOS texture coordinate *
***********************************************************************/
static void intel_wpos_triangle( intelContextPtr intel,
intelVertexPtr v0,
intelVertexPtr v1,
intelVertexPtr v2 )
{
GLuint offset = intel->wpos_offset;
GLuint size = intel->wpos_size;
__memcpy( ((char *)v0) + offset, v0, size );
__memcpy( ((char *)v1) + offset, v1, size );
__memcpy( ((char *)v2) + offset, v2, size );
intel_draw_triangle( intel, v0, v1, v2 );
}
static void intel_wpos_line( intelContextPtr intel,
intelVertexPtr v0,
intelVertexPtr v1 )
{
GLuint offset = intel->wpos_offset;
GLuint size = intel->wpos_size;
__memcpy( ((char *)v0) + offset, v0, size );
__memcpy( ((char *)v1) + offset, v1, size );
intel_draw_line( intel, v0, v1 );
}
static void intel_wpos_point( intelContextPtr intel,
intelVertexPtr v0 )
{
GLuint offset = intel->wpos_offset;
GLuint size = intel->wpos_size;
__memcpy( ((char *)v0) + offset, v0, size );
intel_draw_point( intel, v0 );
}
/***********************************************************************
* Macros for t_dd_tritmp.h to draw basic primitives *
***********************************************************************/
#define TRI( a, b, c ) \
do { \
if (DO_FALLBACK) \
intel->draw_tri( intel, a, b, c ); \
else \
intel_draw_triangle( intel, a, b, c ); \
} while (0)
#define QUAD( a, b, c, d ) \
do { \
if (DO_FALLBACK) { \
intel->draw_tri( intel, a, b, d ); \
intel->draw_tri( intel, b, c, d ); \
} else \
intel_draw_quad( intel, a, b, c, d ); \
} while (0)
#define LINE( v0, v1 ) \
do { \
if (DO_FALLBACK) \
intel->draw_line( intel, v0, v1 ); \
else \
intel_draw_line( intel, v0, v1 ); \
} while (0)
#define POINT( v0 ) \
do { \
if (DO_FALLBACK) \
intel->draw_point( intel, v0 ); \
else \
intel_draw_point( intel, v0 ); \
} while (0)
/***********************************************************************
* Build render functions from dd templates *
***********************************************************************/
#define INTEL_OFFSET_BIT 0x01
#define INTEL_TWOSIDE_BIT 0x02
#define INTEL_UNFILLED_BIT 0x04
#define INTEL_FALLBACK_BIT 0x08
#define INTEL_MAX_TRIFUNC 0x10
static struct {
points_func points;
line_func line;
triangle_func triangle;
quad_func quad;
} rast_tab[INTEL_MAX_TRIFUNC];
#define DO_FALLBACK (IND & INTEL_FALLBACK_BIT)
#define DO_OFFSET (IND & INTEL_OFFSET_BIT)
#define DO_UNFILLED (IND & INTEL_UNFILLED_BIT)
#define DO_TWOSIDE (IND & INTEL_TWOSIDE_BIT)
#define DO_FLAT 0
#define DO_TRI 1
#define DO_QUAD 1
#define DO_LINE 1
#define DO_POINTS 1
#define DO_FULL_QUAD 1
#define HAVE_RGBA 1
#define HAVE_SPEC 1
#define HAVE_BACK_COLORS 0
#define HAVE_HW_FLATSHADE 1
#define VERTEX intelVertex
#define TAB rast_tab
/* Only used to pull back colors into vertices (ie, we know color is
* floating point).
*/
#define INTEL_COLOR( dst, src ) \
do { \
UNCLAMPED_FLOAT_TO_UBYTE((dst)[0], (src)[2]); \
UNCLAMPED_FLOAT_TO_UBYTE((dst)[1], (src)[1]); \
UNCLAMPED_FLOAT_TO_UBYTE((dst)[2], (src)[0]); \
UNCLAMPED_FLOAT_TO_UBYTE((dst)[3], (src)[3]); \
} while (0)
#define INTEL_SPEC( dst, src ) \
do { \
UNCLAMPED_FLOAT_TO_UBYTE((dst)[0], (src)[2]); \
UNCLAMPED_FLOAT_TO_UBYTE((dst)[1], (src)[1]); \
UNCLAMPED_FLOAT_TO_UBYTE((dst)[2], (src)[0]); \
} while (0)
#define DEPTH_SCALE intel->polygon_offset_scale
#define UNFILLED_TRI unfilled_tri
#define UNFILLED_QUAD unfilled_quad
#define VERT_X(_v) _v->v.x
#define VERT_Y(_v) _v->v.y
#define VERT_Z(_v) _v->v.z
#define AREA_IS_CCW( a ) (a > 0)
#define GET_VERTEX(e) (intel->verts + (e * intel->vertex_size * sizeof(GLuint)))
#define VERT_SET_RGBA( v, c ) if (coloroffset) INTEL_COLOR( v->ub4[coloroffset], c )
#define VERT_COPY_RGBA( v0, v1 ) if (coloroffset) v0->ui[coloroffset] = v1->ui[coloroffset]
#define VERT_SAVE_RGBA( idx ) if (coloroffset) color[idx] = v[idx]->ui[coloroffset]
#define VERT_RESTORE_RGBA( idx ) if (coloroffset) v[idx]->ui[coloroffset] = color[idx]
#define VERT_SET_SPEC( v, c ) if (specoffset) INTEL_SPEC( v->ub4[specoffset], c )
#define VERT_COPY_SPEC( v0, v1 ) if (specoffset) COPY_3V(v0->ub4[specoffset], v1->ub4[specoffset])
#define VERT_SAVE_SPEC( idx ) if (specoffset) spec[idx] = v[idx]->ui[specoffset]
#define VERT_RESTORE_SPEC( idx ) if (specoffset) v[idx]->ui[specoffset] = spec[idx]
#define LOCAL_VARS(n) \
intelContextPtr intel = INTEL_CONTEXT(ctx); \
GLuint color[n], spec[n]; \
GLuint coloroffset = intel->coloroffset; \
GLboolean specoffset = intel->specoffset; \
(void) color; (void) spec; (void) coloroffset; (void) specoffset;
/***********************************************************************
* Helpers for rendering unfilled primitives *
***********************************************************************/
static const GLuint hw_prim[GL_POLYGON+1] = {
PRIM3D_POINTLIST,
PRIM3D_LINELIST,
PRIM3D_LINELIST,
PRIM3D_LINELIST,
PRIM3D_TRILIST,
PRIM3D_TRILIST,
PRIM3D_TRILIST,
PRIM3D_TRILIST,
PRIM3D_TRILIST,
PRIM3D_TRILIST
};
#define RASTERIZE(x) intelRasterPrimitive( ctx, x, hw_prim[x] )
#define RENDER_PRIMITIVE intel->render_primitive
#define TAG(x) x
#define IND INTEL_FALLBACK_BIT
#include "tnl_dd/t_dd_unfilled.h"
#undef IND
/***********************************************************************
* Generate GL render functions *
***********************************************************************/
#define IND (0)
#define TAG(x) x
#include "tnl_dd/t_dd_tritmp.h"
#define IND (INTEL_OFFSET_BIT)
#define TAG(x) x##_offset
#include "tnl_dd/t_dd_tritmp.h"
#define IND (INTEL_TWOSIDE_BIT)
#define TAG(x) x##_twoside
#include "tnl_dd/t_dd_tritmp.h"
#define IND (INTEL_TWOSIDE_BIT|INTEL_OFFSET_BIT)
#define TAG(x) x##_twoside_offset
#include "tnl_dd/t_dd_tritmp.h"
#define IND (INTEL_UNFILLED_BIT)
#define TAG(x) x##_unfilled
#include "tnl_dd/t_dd_tritmp.h"
#define IND (INTEL_OFFSET_BIT|INTEL_UNFILLED_BIT)
#define TAG(x) x##_offset_unfilled
#include "tnl_dd/t_dd_tritmp.h"
#define IND (INTEL_TWOSIDE_BIT|INTEL_UNFILLED_BIT)
#define TAG(x) x##_twoside_unfilled
#include "tnl_dd/t_dd_tritmp.h"
#define IND (INTEL_TWOSIDE_BIT|INTEL_OFFSET_BIT|INTEL_UNFILLED_BIT)
#define TAG(x) x##_twoside_offset_unfilled
#include "tnl_dd/t_dd_tritmp.h"
#define IND (INTEL_FALLBACK_BIT)
#define TAG(x) x##_fallback
#include "tnl_dd/t_dd_tritmp.h"
#define IND (INTEL_OFFSET_BIT|INTEL_FALLBACK_BIT)
#define TAG(x) x##_offset_fallback
#include "tnl_dd/t_dd_tritmp.h"
#define IND (INTEL_TWOSIDE_BIT|INTEL_FALLBACK_BIT)
#define TAG(x) x##_twoside_fallback
#include "tnl_dd/t_dd_tritmp.h"
#define IND (INTEL_TWOSIDE_BIT|INTEL_OFFSET_BIT|INTEL_FALLBACK_BIT)
#define TAG(x) x##_twoside_offset_fallback
#include "tnl_dd/t_dd_tritmp.h"
#define IND (INTEL_UNFILLED_BIT|INTEL_FALLBACK_BIT)
#define TAG(x) x##_unfilled_fallback
#include "tnl_dd/t_dd_tritmp.h"
#define IND (INTEL_OFFSET_BIT|INTEL_UNFILLED_BIT|INTEL_FALLBACK_BIT)
#define TAG(x) x##_offset_unfilled_fallback
#include "tnl_dd/t_dd_tritmp.h"
#define IND (INTEL_TWOSIDE_BIT|INTEL_UNFILLED_BIT|INTEL_FALLBACK_BIT)
#define TAG(x) x##_twoside_unfilled_fallback
#include "tnl_dd/t_dd_tritmp.h"
#define IND (INTEL_TWOSIDE_BIT|INTEL_OFFSET_BIT|INTEL_UNFILLED_BIT| \
INTEL_FALLBACK_BIT)
#define TAG(x) x##_twoside_offset_unfilled_fallback
#include "tnl_dd/t_dd_tritmp.h"
static void init_rast_tab( void )
{
init();
init_offset();
init_twoside();
init_twoside_offset();
init_unfilled();
init_offset_unfilled();
init_twoside_unfilled();
init_twoside_offset_unfilled();
init_fallback();
init_offset_fallback();
init_twoside_fallback();
init_twoside_offset_fallback();
init_unfilled_fallback();
init_offset_unfilled_fallback();
init_twoside_unfilled_fallback();
init_twoside_offset_unfilled_fallback();
}
/***********************************************************************
* Rasterization fallback helpers *
***********************************************************************/
/* This code is hit only when a mix of accelerated and unaccelerated
* primitives are being drawn, and only for the unaccelerated
* primitives.
*/
static void
intel_fallback_tri( intelContextPtr intel,
intelVertex *v0,
intelVertex *v1,
intelVertex *v2 )
{
GLcontext *ctx = &intel->ctx;
SWvertex v[3];
if (0)
fprintf(stderr, "\n%s\n", __FUNCTION__);
_swsetup_Translate( ctx, v0, &v[0] );
_swsetup_Translate( ctx, v1, &v[1] );
_swsetup_Translate( ctx, v2, &v[2] );
intelSpanRenderStart( ctx );
_swrast_Triangle( ctx, &v[0], &v[1], &v[2] );
intelSpanRenderFinish( ctx );
}
static void
intel_fallback_line( intelContextPtr intel,
intelVertex *v0,
intelVertex *v1 )
{
GLcontext *ctx = &intel->ctx;
SWvertex v[2];
if (0)
fprintf(stderr, "\n%s\n", __FUNCTION__);
_swsetup_Translate( ctx, v0, &v[0] );
_swsetup_Translate( ctx, v1, &v[1] );
intelSpanRenderStart( ctx );
_swrast_Line( ctx, &v[0], &v[1] );
intelSpanRenderFinish( ctx );
}
static void
intel_fallback_point( intelContextPtr intel,
intelVertex *v0 )
{
GLcontext *ctx = &intel->ctx;
SWvertex v[1];
if (0)
fprintf(stderr, "\n%s\n", __FUNCTION__);
_swsetup_Translate( ctx, v0, &v[0] );
intelSpanRenderStart( ctx );
_swrast_Point( ctx, &v[0] );
intelSpanRenderFinish( ctx );
}
/**********************************************************************/
/* Render unclipped begin/end objects */
/**********************************************************************/
#define IND 0
#define V(x) (intelVertex *)(vertptr + ((x)*vertsize*sizeof(GLuint)))
#define RENDER_POINTS( start, count ) \
for ( ; start < count ; start++) POINT( V(ELT(start)) );
#define RENDER_LINE( v0, v1 ) LINE( V(v0), V(v1) )
#define RENDER_TRI( v0, v1, v2 ) TRI( V(v0), V(v1), V(v2) )
#define RENDER_QUAD( v0, v1, v2, v3 ) QUAD( V(v0), V(v1), V(v2), V(v3) )
#define INIT(x) intelRenderPrimitive( ctx, x )
#undef LOCAL_VARS
#define LOCAL_VARS \
intelContextPtr intel = INTEL_CONTEXT(ctx); \
GLubyte *vertptr = (GLubyte *)intel->verts; \
const GLuint vertsize = intel->vertex_size; \
const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts; \
(void) elt;
#define RESET_STIPPLE
#define RESET_OCCLUSION
#define PRESERVE_VB_DEFS
#define ELT(x) x
#define TAG(x) intel_##x##_verts
#include "tnl/t_vb_rendertmp.h"
#undef ELT
#undef TAG
#define TAG(x) intel_##x##_elts
#define ELT(x) elt[x]
#include "tnl/t_vb_rendertmp.h"
/**********************************************************************/
/* Render clipped primitives */
/**********************************************************************/
static void intelRenderClippedPoly( GLcontext *ctx, const GLuint *elts,
GLuint n )
{
intelContextPtr intel = INTEL_CONTEXT(ctx);
TNLcontext *tnl = TNL_CONTEXT(ctx);
struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
GLuint prim = intel->render_primitive;
/* Render the new vertices as an unclipped polygon.
*/
{
GLuint *tmp = VB->Elts;
VB->Elts = (GLuint *)elts;
tnl->Driver.Render.PrimTabElts[GL_POLYGON]( ctx, 0, n,
PRIM_BEGIN|PRIM_END );
VB->Elts = tmp;
}
/* Restore the render primitive
*/
if (prim != GL_POLYGON)
tnl->Driver.Render.PrimitiveNotify( ctx, prim );
}
static void intelRenderClippedLine( GLcontext *ctx, GLuint ii, GLuint jj )
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
tnl->Driver.Render.Line( ctx, ii, jj );
}
static void intelFastRenderClippedPoly( GLcontext *ctx, const GLuint *elts,
GLuint n )
{
intelContextPtr intel = INTEL_CONTEXT( ctx );
const GLuint vertsize = intel->vertex_size;
GLuint *vb = intelExtendInlinePrimitive( intel, (n-2) * 3 * vertsize );
GLubyte *vertptr = (GLubyte *)intel->verts;
const GLuint *start = (const GLuint *)V(elts[0]);
int i,j;
for (i = 2 ; i < n ; i++) {
COPY_DWORDS( j, vb, vertsize, V(elts[i-1]) );
COPY_DWORDS( j, vb, vertsize, V(elts[i]) );
COPY_DWORDS( j, vb, vertsize, start );
}
}
/**********************************************************************/
/* Choose render functions */
/**********************************************************************/
#define POINT_FALLBACK (0)
#define LINE_FALLBACK (DD_LINE_STIPPLE)
#define TRI_FALLBACK (0)
#define ANY_FALLBACK_FLAGS (POINT_FALLBACK|LINE_FALLBACK|TRI_FALLBACK|\
DD_TRI_STIPPLE|DD_POINT_ATTEN)
#define ANY_RASTER_FLAGS (DD_TRI_LIGHT_TWOSIDE|DD_TRI_OFFSET|DD_TRI_UNFILLED)
void intelChooseRenderState(GLcontext *ctx)
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
intelContextPtr intel = INTEL_CONTEXT(ctx);
GLuint flags = ctx->_TriangleCaps;
struct fragment_program *program = ctx->FragmentProgram.Current;
GLboolean have_wpos = (program && (program->InputsRead & FRAG_BIT_WPOS));
GLuint index = 0;
if (INTEL_DEBUG & DEBUG_STATE)
fprintf(stderr,"\n%s\n",__FUNCTION__);
if ((flags & (ANY_FALLBACK_FLAGS|ANY_RASTER_FLAGS)) || have_wpos) {
if (flags & ANY_RASTER_FLAGS) {
if (flags & DD_TRI_LIGHT_TWOSIDE) index |= INTEL_TWOSIDE_BIT;
if (flags & DD_TRI_OFFSET) index |= INTEL_OFFSET_BIT;
if (flags & DD_TRI_UNFILLED) index |= INTEL_UNFILLED_BIT;
}
if (have_wpos) {
intel->draw_point = intel_wpos_point;
intel->draw_line = intel_wpos_line;
intel->draw_tri = intel_wpos_triangle;
/* Make sure these get called:
*/
index |= INTEL_FALLBACK_BIT;
}
else {
intel->draw_point = intel_draw_point;
intel->draw_line = intel_draw_line;
intel->draw_tri = intel_draw_triangle;
}
/* Hook in fallbacks for specific primitives.
*/
if (flags & ANY_FALLBACK_FLAGS)
{
if (flags & POINT_FALLBACK)
intel->draw_point = intel_fallback_point;
if (flags & LINE_FALLBACK)
intel->draw_line = intel_fallback_line;
if (flags & TRI_FALLBACK)
intel->draw_tri = intel_fallback_tri;
if ((flags & DD_TRI_STIPPLE) && !intel->hw_stipple)
intel->draw_tri = intel_fallback_tri;
if (flags & DD_POINT_ATTEN)
intel->draw_point = intel_atten_point;
index |= INTEL_FALLBACK_BIT;
}
}
if (intel->RenderIndex != index) {
intel->RenderIndex = index;
tnl->Driver.Render.Points = rast_tab[index].points;
tnl->Driver.Render.Line = rast_tab[index].line;
tnl->Driver.Render.Triangle = rast_tab[index].triangle;
tnl->Driver.Render.Quad = rast_tab[index].quad;
if (index == 0) {
tnl->Driver.Render.PrimTabVerts = intel_render_tab_verts;
tnl->Driver.Render.PrimTabElts = intel_render_tab_elts;
tnl->Driver.Render.ClippedLine = line; /* from tritmp.h */
tnl->Driver.Render.ClippedPolygon = intelFastRenderClippedPoly;
} else {
tnl->Driver.Render.PrimTabVerts = _tnl_render_tab_verts;
tnl->Driver.Render.PrimTabElts = _tnl_render_tab_elts;
tnl->Driver.Render.ClippedLine = intelRenderClippedLine;
tnl->Driver.Render.ClippedPolygon = intelRenderClippedPoly;
}
}
}
static const GLenum reduced_prim[GL_POLYGON+1] = {
GL_POINTS,
GL_LINES,
GL_LINES,
GL_LINES,
GL_TRIANGLES,
GL_TRIANGLES,
GL_TRIANGLES,
GL_TRIANGLES,
GL_TRIANGLES,
GL_TRIANGLES
};
/**********************************************************************/
/* High level hooks for t_vb_render.c */
/**********************************************************************/
static void intelRunPipeline( GLcontext *ctx )
{
intelContextPtr intel = INTEL_CONTEXT(ctx);
if (intel->NewGLState) {
if (intel->NewGLState & _NEW_TEXTURE) {
intel->vtbl.update_texture_state( intel );
}
if (!intel->Fallback) {
if (intel->NewGLState & _INTEL_NEW_RENDERSTATE)
intelChooseRenderState( ctx );
}
intel->NewGLState = 0;
}
_tnl_run_pipeline( ctx );
}
static void intelRenderStart( GLcontext *ctx )
{
INTEL_CONTEXT(ctx)->vtbl.render_start( INTEL_CONTEXT(ctx) );
}
static void intelRenderFinish( GLcontext *ctx )
{
if (INTEL_CONTEXT(ctx)->RenderIndex & INTEL_FALLBACK_BIT)
_swrast_flush( ctx );
}
/* System to flush dma and emit state changes based on the rasterized
* primitive.
*/
static void intelRasterPrimitive( GLcontext *ctx, GLenum rprim, GLuint hwprim )
{
intelContextPtr intel = INTEL_CONTEXT(ctx);
if (0)
fprintf(stderr, "%s %s %x\n", __FUNCTION__,
_mesa_lookup_enum_by_nr(rprim), hwprim);
intel->vtbl.reduced_primitive_state( intel, rprim );
/* Start a new primitive. Arrange to have it flushed later on.
*/
if (hwprim != intel->prim.primitive)
intelStartInlinePrimitive( intel, hwprim );
}
/*
*/
static void intelRenderPrimitive( GLcontext *ctx, GLenum prim )
{
intelContextPtr intel = INTEL_CONTEXT(ctx);
if (0)
fprintf(stderr, "%s %s\n", __FUNCTION__, _mesa_lookup_enum_by_nr(prim));
/* Let some clipping routines know which primitive they're dealing
* with.
*/
intel->render_primitive = prim;
/* Shortcircuit this when called from t_dd_rendertmp.h for unfilled
* triangles. The rasterized primitive will always be reset by
* lower level functions in that case, potentially pingponging the
* state:
*/
if (reduced_prim[prim] == GL_TRIANGLES &&
(ctx->_TriangleCaps & DD_TRI_UNFILLED))
return;
/* Set some primitive-dependent state and Start? a new primitive.
*/
intelRasterPrimitive( ctx, reduced_prim[prim], hw_prim[prim] );
}
/**********************************************************************/
/* Transition to/from hardware rasterization. */
/**********************************************************************/
static char *fallbackStrings[] = {
"Texture",
"Draw buffer",
"Read buffer",
"Color mask",
"Render mode",
"Stencil",
"Stipple",
"User disable"
};
static char *getFallbackString(GLuint bit)
{
int i = 0;
while (bit > 1) {
i++;
bit >>= 1;
}
return fallbackStrings[i];
}
void intelFallback( intelContextPtr intel, GLuint bit, GLboolean mode )
{
GLcontext *ctx = &intel->ctx;
TNLcontext *tnl = TNL_CONTEXT(ctx);
GLuint oldfallback = intel->Fallback;
if (mode) {
intel->Fallback |= bit;
if (oldfallback == 0) {
intelFlush(ctx);
if (INTEL_DEBUG & DEBUG_FALLBACKS)
fprintf(stderr, "ENTER FALLBACK %x: %s\n",
bit, getFallbackString( bit ));
_swsetup_Wakeup( ctx );
intel->RenderIndex = ~0;
}
}
else {
intel->Fallback &= ~bit;
if (oldfallback == bit) {
_swrast_flush( ctx );
if (INTEL_DEBUG & DEBUG_FALLBACKS)
fprintf(stderr, "LEAVE FALLBACK %s\n", getFallbackString( bit ));
tnl->Driver.Render.Start = intelRenderStart;
tnl->Driver.Render.PrimitiveNotify = intelRenderPrimitive;
tnl->Driver.Render.Finish = intelRenderFinish;
tnl->Driver.Render.BuildVertices = _tnl_build_vertices;
tnl->Driver.Render.CopyPV = _tnl_copy_pv;
tnl->Driver.Render.Interp = _tnl_interp;
_tnl_invalidate_vertex_state( ctx, ~0 );
_tnl_invalidate_vertices( ctx, ~0 );
_tnl_install_attrs( ctx,
intel->vertex_attrs,
intel->vertex_attr_count,
intel->ViewportMatrix.m, 0 );
intel->NewGLState |= _INTEL_NEW_RENDERSTATE;
}
}
}
/**********************************************************************/
/* Initialization. */
/**********************************************************************/
void intelInitTriFuncs( GLcontext *ctx )
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
static int firsttime = 1;
if (firsttime) {
init_rast_tab();
firsttime = 0;
}
tnl->Driver.RunPipeline = intelRunPipeline;
tnl->Driver.Render.Start = intelRenderStart;
tnl->Driver.Render.Finish = intelRenderFinish;
tnl->Driver.Render.PrimitiveNotify = intelRenderPrimitive;
tnl->Driver.Render.ResetLineStipple = _swrast_ResetLineStipple;
tnl->Driver.Render.BuildVertices = _tnl_build_vertices;
tnl->Driver.Render.CopyPV = _tnl_copy_pv;
tnl->Driver.Render.Interp = _tnl_interp;
}
+26
View File
@@ -0,0 +1,26 @@
/**************************************************************************
*
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
**************************************************************************/
#ifndef INTELTRIS_INC
#define INTELTRIS_INC
#include "mtypes.h"
#define _INTEL_NEW_RENDERSTATE (_DD_NEW_LINE_STIPPLE | \
_DD_NEW_TRI_UNFILLED | \
_DD_NEW_TRI_LIGHT_TWOSIDE | \
_DD_NEW_TRI_OFFSET | \
_DD_NEW_TRI_STIPPLE | \
_NEW_PROGRAM | \
_NEW_POLYGONSTIPPLE)
extern void intelInitTriFuncs( GLcontext *ctx );
extern void intelPrintRenderState( const char *msg, GLuint state );
extern void intelChooseRenderState( GLcontext *ctx );
#endif
@@ -0,0 +1,169 @@
/**************************************************************************
Copyright 2001 VA Linux Systems Inc., Fremont, California.
Copyright 2002 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, VA LINUX SYSTEMS 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: xc/programs/Xserver/hw/xfree86/drivers/i810/i830_common.h,v 1.1 2002/09/11 00:29:32 dawes Exp $ */
#ifndef _I830_COMMON_H_
#define _I830_COMMON_H_
#define I830_NR_TEX_REGIONS 255 /* maximum due to use of chars for next/prev */
#define I830_LOG_MIN_TEX_REGION_SIZE 14
/* Driver specific DRM command indices
* NOTE: these are not OS specific, but they are driver specific
*/
#define DRM_I830_INIT 0x00
#define DRM_I830_FLUSH 0x01
#define DRM_I830_FLIP 0x02
#define DRM_I830_BATCHBUFFER 0x03
#define DRM_I830_IRQ_EMIT 0x04
#define DRM_I830_IRQ_WAIT 0x05
#define DRM_I830_GETPARAM 0x06
#define DRM_I830_SETPARAM 0x07
#define DRM_I830_ALLOC 0x08
#define DRM_I830_FREE 0x09
#define DRM_I830_INIT_HEAP 0x0a
#define DRM_I830_CMDBUFFER 0x0b
typedef struct {
enum {
I830_INIT_DMA = 0x01,
I830_CLEANUP_DMA = 0x02,
I830_RESUME_DMA = 0x03
} func;
unsigned int mmio_offset;
int sarea_priv_offset;
unsigned int ring_start;
unsigned int ring_end;
unsigned int ring_size;
unsigned int front_offset;
unsigned int back_offset;
unsigned int depth_offset;
unsigned int w;
unsigned int h;
unsigned int pitch;
unsigned int pitch_bits;
unsigned int back_pitch;
unsigned int depth_pitch;
unsigned int cpp;
unsigned int chipset;
} drmI830Init;
typedef struct {
drmTextureRegion texList[I830_NR_TEX_REGIONS+1];
int last_upload; /* last time texture was uploaded */
int last_enqueue; /* last time a buffer was enqueued */
int last_dispatch; /* age of the most recently dispatched buffer */
int ctxOwner; /* last context to upload state */
int texAge;
int pf_enabled; /* is pageflipping allowed? */
int pf_active;
int pf_current_page; /* which buffer is being displayed? */
int perf_boxes; /* performance boxes to be displayed */
} drmI830Sarea;
/* Flags for perf_boxes
*/
#define I830_BOX_RING_EMPTY 0x1 /* populated by kernel */
#define I830_BOX_FLIP 0x2 /* populated by kernel */
#define I830_BOX_WAIT 0x4 /* populated by kernel & client */
#define I830_BOX_TEXTURE_LOAD 0x8 /* populated by kernel */
#define I830_BOX_LOST_CONTEXT 0x10 /* populated by client */
typedef struct {
int start; /* agp offset */
int used; /* nr bytes in use */
int DR1; /* hw flags for GFX_OP_DRAWRECT_INFO */
int DR4; /* window origin for GFX_OP_DRAWRECT_INFO*/
int num_cliprects; /* mulitpass with multiple cliprects? */
drm_clip_rect_t *cliprects; /* pointer to userspace cliprects */
} drmI830BatchBuffer;
typedef struct {
char *buf; /* agp offset */
int sz; /* nr bytes in use */
int DR1; /* hw flags for GFX_OP_DRAWRECT_INFO */
int DR4; /* window origin for GFX_OP_DRAWRECT_INFO*/
int num_cliprects; /* mulitpass with multiple cliprects? */
drm_clip_rect_t *cliprects; /* pointer to userspace cliprects */
} drmI830CmdBuffer;
typedef struct {
int *irq_seq;
} drmI830IrqEmit;
typedef struct {
int irq_seq;
} drmI830IrqWait;
typedef struct {
int param;
int *value;
} drmI830GetParam;
#define I830_PARAM_IRQ_ACTIVE 1
#define I830_PARAM_ALLOW_BATCHBUFFER 2
typedef struct {
int param;
int value;
} drmI830SetParam;
#define I830_SETPARAM_USE_MI_BATCHBUFFER_START 1
#define I830_SETPARAM_TEX_LRU_LOG_GRANULARITY 2
#define I830_SETPARAM_ALLOW_BATCHBUFFER 3
/* A memory manager for regions of shared memory:
*/
#define I830_MEM_REGION_AGP 1
typedef struct {
int region;
int alignment;
int size;
int *region_offset; /* offset from start of fb or agp */
} drmI830MemAlloc;
typedef struct {
int region;
int region_offset;
} drmI830MemFree;
typedef struct {
int region;
int size;
int start;
} drmI830MemInitHeap;
#endif /* _I830_DRM_H_ */
@@ -0,0 +1,70 @@
/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/i810/i830_dri.h,v 1.4 2002/10/30 12:52:18 alanh Exp $ */
#ifndef _I830_DRI_H
#define _I830_DRI_H
#include "xf86drm.h"
#include "i830_common.h"
#define I830_MAX_DRAWABLES 256
#define I830_MAJOR_VERSION 1
#define I830_MINOR_VERSION 3
#define I830_PATCHLEVEL 0
#define I830_REG_SIZE 0x80000
/* Note: This structure has changed slightly from what is expected by
* the i830_drv.o driver. Maybe that should be reverted.
*/
typedef struct _I830DRIRec {
drm_handle_t regs;
drmSize regsSize;
drmAddress regsMap;
drmSize backbufferSize;
drm_handle_t backbuffer;
drmSize depthbufferSize;
drm_handle_t depthbuffer;
drm_handle_t textures;
int textureSize;
drm_handle_t agp_buffers;
drmSize agp_buf_size;
int deviceID;
int width;
int height;
int mem;
int cpp;
int bitsPerPixel;
int fbOffset;
int fbStride;
int backOffset;
int backPitch;
int depthOffset;
int depthPitch;
int logTextureGranularity;
int textureOffset;
int irq;
int sarea_priv_offset;
} I830DRIRec, *I830DRIPtr;
typedef struct {
/* Nothing here yet */
int dummy;
} I830ConfigPrivRec, *I830ConfigPrivPtr;
typedef struct {
/* Nothing here yet */
int dummy;
} I830DRIContextRec, *I830DRIContextPtr;
#endif