2 * GLX Hardware Device Driver for Intel i810
3 * Copyright (C) 1999 Keith Whitwell
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice shall be included
13 * in all copies or substantial portions of the Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
16 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * KEITH WHITWELL, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM,
19 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
20 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
21 * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 #include "main/glheader.h"
26 #include "main/mtypes.h"
27 #include "main/imports.h"
28 #include "main/simple_list.h"
29 #include "main/enums.h"
30 #include "main/texstore.h"
31 #include "main/teximage.h"
32 #include "main/texobj.h"
33 #include "main/colormac.h"
38 #include "i810screen.h"
41 #include "i810context.h"
43 #include "i810ioctl.h"
47 * Compute the 'S2.4' lod bias factor from the floating point OpenGL bias.
49 static GLuint i810ComputeLodBias(GLfloat bias)
51 int b = (int) (bias * 16.0) + 12;
56 return (GLuint) (b & MLC_LOD_BIAS_MASK);
60 static void i810SetTexWrapping(i810TextureObjectPtr tex,
61 GLenum swrap, GLenum twrap)
63 tex->Setup[I810_TEXREG_MCS] &= ~(MCS_U_STATE_MASK| MCS_V_STATE_MASK);
67 tex->Setup[I810_TEXREG_MCS] |= MCS_U_WRAP;
70 case GL_CLAMP_TO_EDGE:
71 tex->Setup[I810_TEXREG_MCS] |= MCS_U_CLAMP;
73 case GL_MIRRORED_REPEAT:
74 tex->Setup[I810_TEXREG_MCS] |= MCS_U_MIRROR;
77 _mesa_problem(NULL, "bad S wrap mode in %s", __FUNCTION__);
82 tex->Setup[I810_TEXREG_MCS] |= MCS_V_WRAP;
85 case GL_CLAMP_TO_EDGE:
86 tex->Setup[I810_TEXREG_MCS] |= MCS_V_CLAMP;
88 case GL_MIRRORED_REPEAT:
89 tex->Setup[I810_TEXREG_MCS] |= MCS_V_MIRROR;
92 _mesa_problem(NULL, "bad T wrap mode in %s", __FUNCTION__);
97 static void i810SetTexFilter(i810ContextPtr imesa,
98 i810TextureObjectPtr t,
99 GLenum minf, GLenum magf,
102 t->Setup[I810_TEXREG_MF] &= ~(MF_MIN_MASK|
105 t->Setup[I810_TEXREG_MLC] &= ~(MLC_LOD_BIAS_MASK);
109 t->Setup[I810_TEXREG_MF] |= MF_MIN_NEAREST | MF_MIP_NONE;
112 t->Setup[I810_TEXREG_MF] |= MF_MIN_LINEAR | MF_MIP_NONE;
114 case GL_NEAREST_MIPMAP_NEAREST:
115 t->Setup[I810_TEXREG_MF] |= MF_MIN_NEAREST | MF_MIP_NEAREST;
116 if (magf == GL_LINEAR) {
117 /*bias -= 0.5;*/ /* this doesn't work too good */
120 case GL_LINEAR_MIPMAP_NEAREST:
121 t->Setup[I810_TEXREG_MF] |= MF_MIN_LINEAR | MF_MIP_NEAREST;
123 case GL_NEAREST_MIPMAP_LINEAR:
125 t->Setup[I810_TEXREG_MF] |= MF_MIN_NEAREST | MF_MIP_LINEAR;
127 t->Setup[I810_TEXREG_MF] |= MF_MIN_NEAREST | MF_MIP_DITHER;
129 if (magf == GL_LINEAR) {
133 bias -= 0.5; /* always biasing here looks better */
135 case GL_LINEAR_MIPMAP_LINEAR:
137 t->Setup[I810_TEXREG_MF] |= MF_MIN_LINEAR | MF_MIP_LINEAR;
139 t->Setup[I810_TEXREG_MF] |= MF_MIN_LINEAR | MF_MIP_DITHER;
147 t->Setup[I810_TEXREG_MF] |= MF_MAG_NEAREST;
150 t->Setup[I810_TEXREG_MF] |= MF_MAG_LINEAR;
156 t->Setup[I810_TEXREG_MLC] |= i810ComputeLodBias(bias);
161 i810SetTexBorderColor( i810TextureObjectPtr t, const GLfloat color[4] )
168 static i810TextureObjectPtr
169 i810AllocTexObj( struct gl_context *ctx, struct gl_texture_object *texObj )
171 i810TextureObjectPtr t;
172 i810ContextPtr imesa = I810_CONTEXT(ctx);
174 t = CALLOC_STRUCT( i810_texture_object_t );
175 texObj->DriverData = t;
177 GLfloat bias = ctx->Texture.Unit[ctx->Texture.CurrentUnit].LodBias;
178 /* Initialize non-image-dependent parts of the state:
180 t->base.tObj = texObj;
181 t->Setup[I810_TEXREG_MI0] = GFX_OP_MAP_INFO;
182 t->Setup[I810_TEXREG_MI1] = MI1_MAP_0;
183 t->Setup[I810_TEXREG_MI2] = MI2_DIMENSIONS_ARE_LOG2;
184 t->Setup[I810_TEXREG_MLC] = (GFX_OP_MAP_LOD_CTL |
186 /*MLC_DITHER_WEIGHT_FULL |*/
187 MLC_DITHER_WEIGHT_12 |
188 MLC_UPDATE_LOD_BIAS |
190 t->Setup[I810_TEXREG_MCS] = (GFX_OP_MAP_COORD_SETS |
192 MCS_UPDATE_NORMALIZED |
193 MCS_NORMALIZED_COORDS |
198 t->Setup[I810_TEXREG_MF] = (GFX_OP_MAP_FILTER |
200 MF_UPDATE_ANISOTROPIC |
201 MF_UPDATE_MIP_FILTER |
202 MF_UPDATE_MAG_FILTER |
203 MF_UPDATE_MIN_FILTER);
205 make_empty_list( & t->base );
207 i810SetTexWrapping( t, texObj->Sampler.WrapS, texObj->Sampler.WrapT );
208 /*i830SetTexMaxAnisotropy( t, texObj->MaxAnisotropy );*/
209 i810SetTexFilter( imesa, t, texObj->Sampler.MinFilter, texObj->Sampler.MagFilter, bias );
210 i810SetTexBorderColor( t, texObj->Sampler.BorderColor.f );
217 static void i810TexParameter( struct gl_context *ctx, GLenum target,
218 struct gl_texture_object *tObj,
219 GLenum pname, const GLfloat *params )
221 i810ContextPtr imesa = I810_CONTEXT(ctx);
222 i810TextureObjectPtr t = (i810TextureObjectPtr) tObj->DriverData;
227 if ( target != GL_TEXTURE_2D )
230 /* Can't do the update now as we don't know whether to flush
231 * vertices or not. Setting imesa->new_state means that
232 * i810UpdateTextureState() will be called before any triangles are
233 * rendered. If a statechange has occurred, it will be detected at
234 * that point, and buffered vertices flushed.
237 case GL_TEXTURE_MIN_FILTER:
238 case GL_TEXTURE_MAG_FILTER:
240 GLfloat bias = ctx->Texture.Unit[ctx->Texture.CurrentUnit].LodBias;
241 i810SetTexFilter( imesa, t, tObj->Sampler.MinFilter, tObj->Sampler.MagFilter, bias );
245 case GL_TEXTURE_WRAP_S:
246 case GL_TEXTURE_WRAP_T:
247 i810SetTexWrapping( t, tObj->Sampler.WrapS, tObj->Sampler.WrapT );
250 case GL_TEXTURE_BORDER_COLOR:
251 i810SetTexBorderColor( t, tObj->Sampler.BorderColor.f );
254 case GL_TEXTURE_BASE_LEVEL:
255 case GL_TEXTURE_MAX_LEVEL:
256 case GL_TEXTURE_MIN_LOD:
257 case GL_TEXTURE_MAX_LOD:
258 /* This isn't the most efficient solution but there doesn't appear to
259 * be a nice alternative for Radeon. Since there's no LOD clamping,
260 * we just have to rely on loading the right subset of mipmap levels
261 * to simulate a clamped LOD.
263 I810_FIREVERTICES( I810_CONTEXT(ctx) );
264 driSwapOutTextureObject( (driTextureObject *) t );
271 if (t == imesa->CurrentTexObj[0]) {
272 I810_STATECHANGE( imesa, I810_UPLOAD_TEX0 );
275 if (t == imesa->CurrentTexObj[1]) {
276 I810_STATECHANGE( imesa, I810_UPLOAD_TEX1 );
282 * Setup hardware bits for new texture environment settings.
285 * Determine whether or not \c param can be used instead of
286 * \c texUnit->EnvColor in the \c GL_TEXTURE_ENV_COLOR case.
288 static void i810TexEnv( struct gl_context *ctx, GLenum target,
289 GLenum pname, const GLfloat *param )
291 i810ContextPtr imesa = I810_CONTEXT( ctx );
292 const GLuint unit = ctx->Texture.CurrentUnit;
293 const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
295 /* Only one env color. Need a fallback if env colors are different
296 * and texture setup references env color in both units.
299 case GL_TEXTURE_ENV_COLOR: {
303 UNCLAMPED_FLOAT_TO_RGBA_CHAN( c, texUnit->EnvColor );
304 envColor = PACK_COLOR_8888( c[3], c[0], c[1], c[2] );
306 if (imesa->Setup[I810_CTXREG_CF1] != envColor) {
307 I810_STATECHANGE(imesa, I810_UPLOAD_CTX);
308 imesa->Setup[I810_CTXREG_CF1] = envColor;
313 case GL_TEXTURE_ENV_MODE:
314 imesa->TexEnvImageFmt[unit] = 0; /* force recalc of env state */
317 case GL_TEXTURE_LOD_BIAS: {
318 if ( texUnit->_Current != NULL ) {
319 const struct gl_texture_object *tObj = texUnit->_Current;
320 i810TextureObjectPtr t = (i810TextureObjectPtr) tObj->DriverData;
322 t->Setup[I810_TEXREG_MLC] &= ~(MLC_LOD_BIAS_MASK);
323 t->Setup[I810_TEXREG_MLC] |= i810ComputeLodBias(*param);
336 static void i810TexImage1D( struct gl_context *ctx, GLenum target, GLint level,
337 GLint internalFormat,
338 GLint width, GLint border,
339 GLenum format, GLenum type,
340 const GLvoid *pixels,
341 const struct gl_pixelstore_attrib *pack,
342 struct gl_texture_object *texObj,
343 struct gl_texture_image *texImage )
345 i810TextureObjectPtr t = (i810TextureObjectPtr) texObj->DriverData;
347 i810SwapOutTexObj( imesa, t );
351 static void i810TexSubImage1D( struct gl_context *ctx,
356 GLenum format, GLenum type,
357 const GLvoid *pixels,
358 const struct gl_pixelstore_attrib *pack,
359 struct gl_texture_object *texObj,
360 struct gl_texture_image *texImage )
366 static void i810TexImage2D( struct gl_context *ctx, GLenum target, GLint level,
367 GLint internalFormat,
368 GLint width, GLint height, GLint border,
369 GLenum format, GLenum type, const GLvoid *pixels,
370 const struct gl_pixelstore_attrib *packing,
371 struct gl_texture_object *texObj,
372 struct gl_texture_image *texImage )
374 driTextureObject *t = (driTextureObject *) texObj->DriverData;
376 I810_FIREVERTICES( I810_CONTEXT(ctx) );
377 driSwapOutTextureObject( t );
380 t = (driTextureObject *) i810AllocTexObj( ctx, texObj );
382 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
386 _mesa_store_teximage2d( ctx, target, level, internalFormat,
387 width, height, border, format, type,
388 pixels, packing, texObj, texImage );
391 static void i810TexSubImage2D( struct gl_context *ctx,
394 GLint xoffset, GLint yoffset,
395 GLsizei width, GLsizei height,
396 GLenum format, GLenum type,
397 const GLvoid *pixels,
398 const struct gl_pixelstore_attrib *packing,
399 struct gl_texture_object *texObj,
400 struct gl_texture_image *texImage )
402 driTextureObject *t = (driTextureObject *)texObj->DriverData;
404 I810_FIREVERTICES( I810_CONTEXT(ctx) );
405 driSwapOutTextureObject( t );
407 _mesa_store_texsubimage2d(ctx, target, level, xoffset, yoffset, width,
408 height, format, type, pixels, packing, texObj,
413 static void i810BindTexture( struct gl_context *ctx, GLenum target,
414 struct gl_texture_object *tObj )
416 assert( (target != GL_TEXTURE_2D) || (tObj->DriverData != NULL) );
420 static void i810DeleteTexture( struct gl_context *ctx, struct gl_texture_object *tObj )
422 driTextureObject * t = (driTextureObject *) tObj->DriverData;
424 i810ContextPtr imesa = I810_CONTEXT( ctx );
426 I810_FIREVERTICES( imesa );
427 driDestroyTextureObject( t );
429 /* Free mipmap images and the texture object itself */
430 _mesa_delete_texture_object(ctx, tObj);
434 * Choose a Mesa texture format to match the requested format.
436 * The i810 only supports 5 texture modes that are useful to Mesa. That
437 * makes this routine pretty simple.
440 i810ChooseTextureFormat( struct gl_context *ctx, GLint internalFormat,
441 GLenum format, GLenum type )
443 switch ( internalFormat ) {
453 case GL_COMPRESSED_RGBA:
454 if ( ((format == GL_BGRA) && (type == GL_UNSIGNED_SHORT_1_5_5_5_REV))
455 || ((format == GL_RGBA) && (type == GL_UNSIGNED_SHORT_5_5_5_1))
456 || (internalFormat == GL_RGB5_A1) ) {
457 return MESA_FORMAT_ARGB1555;
459 return MESA_FORMAT_ARGB4444;
463 case GL_COMPRESSED_RGB:
471 return MESA_FORMAT_RGB565;
478 case GL_COMPRESSED_ALPHA:
485 case GL_COMPRESSED_LUMINANCE:
487 case GL_LUMINANCE_ALPHA:
488 case GL_LUMINANCE4_ALPHA4:
489 case GL_LUMINANCE6_ALPHA2:
490 case GL_LUMINANCE8_ALPHA8:
491 case GL_LUMINANCE12_ALPHA4:
492 case GL_LUMINANCE12_ALPHA12:
493 case GL_LUMINANCE16_ALPHA16:
494 case GL_COMPRESSED_LUMINANCE_ALPHA:
500 case GL_COMPRESSED_INTENSITY:
501 return MESA_FORMAT_AL88;
504 if (type == GL_UNSIGNED_SHORT_8_8_MESA ||
505 type == GL_UNSIGNED_BYTE)
506 return MESA_FORMAT_YCBCR;
508 return MESA_FORMAT_YCBCR_REV;
511 fprintf(stderr, "unexpected texture format in %s\n", __FUNCTION__);
512 return MESA_FORMAT_NONE;
515 return MESA_FORMAT_NONE; /* never get here */
519 * Allocate a new texture object.
520 * Called via ctx->Driver.NewTextureObject.
521 * Note: this function will be called during context creation to
522 * allocate the default texture objects.
523 * Note: we could use containment here to 'derive' the driver-specific
524 * texture object from the core mesa gl_texture_object. Not done at this time.
526 static struct gl_texture_object *
527 i810NewTextureObject( struct gl_context *ctx, GLuint name, GLenum target )
529 struct gl_texture_object *obj;
530 obj = _mesa_new_texture_object(ctx, name, target);
531 i810AllocTexObj( ctx, obj );
535 void i810InitTextureFuncs( struct dd_function_table *functions )
537 functions->ChooseTextureFormat = i810ChooseTextureFormat;
538 functions->TexImage2D = i810TexImage2D;
539 functions->TexSubImage2D = i810TexSubImage2D;
540 functions->BindTexture = i810BindTexture;
541 functions->NewTextureObject = i810NewTextureObject;
542 functions->DeleteTexture = i810DeleteTexture;
543 functions->TexParameter = i810TexParameter;
544 functions->TexEnv = i810TexEnv;
545 functions->IsTextureResident = driIsTextureResident;