mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-06 07:18:17 +02:00
Checkpoint of texture manager rework for i915.
Compiles but won't do any more than that.
This commit is contained in:
parent
3bca9c47f4
commit
ff84b1f1b2
21 changed files with 1539 additions and 1847 deletions
|
|
@ -6,23 +6,24 @@ LIBNAME = i915_dri.so
|
|||
|
||||
DRIVER_SOURCES = \
|
||||
bufmgr_fake.c \
|
||||
intel_regions.c \
|
||||
intel_mipmap_tree.c \
|
||||
i915_tex_layout.c \
|
||||
intel_tex_image.c \
|
||||
intel_tex_subimage.c \
|
||||
intel_tex_validate.c \
|
||||
intel_tex_format.c \
|
||||
intel_tex.c \
|
||||
i915_tex.c \
|
||||
i915_texstate.c \
|
||||
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 \
|
||||
|
|
@ -31,9 +32,18 @@ DRIVER_SOURCES = \
|
|||
intel_screen.c \
|
||||
intel_span.c \
|
||||
intel_state.c \
|
||||
intel_tex.c \
|
||||
intel_tris.c
|
||||
|
||||
|
||||
DISABLED = \
|
||||
i830_context.c \
|
||||
i830_metaops.c \
|
||||
i830_state.c \
|
||||
i830_texblend.c \
|
||||
i830_tex.c \
|
||||
i830_texstate.c \
|
||||
i830_vtbl.c
|
||||
|
||||
C_SOURCES = \
|
||||
$(COMMON_SOURCES) \
|
||||
$(MINIGLX_SOURCES) \
|
||||
|
|
|
|||
|
|
@ -200,7 +200,7 @@ intelTextureObjectPtr i830AllocTexObj( struct gl_texture_object *texObj )
|
|||
|
||||
texObj->DriverData = t;
|
||||
t->intel.base.tObj = texObj;
|
||||
t->intel.dirty = I830_UPLOAD_TEX_ALL;
|
||||
t->intel.dirty = ~0;
|
||||
make_empty_list( &t->intel.base );
|
||||
|
||||
t->Setup[I830_TEXREG_TM0LI] = 0; /* not used */
|
||||
|
|
@ -268,7 +268,7 @@ static void i830TexParameter( GLcontext *ctx, GLenum target,
|
|||
return;
|
||||
}
|
||||
|
||||
t->intel.dirty = I830_UPLOAD_TEX_ALL;
|
||||
t->intel.dirty = ~0;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -246,7 +246,7 @@ static GLboolean i830SetTexImages( i830ContextPtr i830,
|
|||
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;
|
||||
t->intel.dirty = ~0;
|
||||
|
||||
return intelUploadTexImages( &i830->intel, &t->intel, 0 );
|
||||
}
|
||||
|
|
@ -259,11 +259,7 @@ static void i830_import_tex_unit( i830ContextPtr i830,
|
|||
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) );
|
||||
|
||||
|
|
@ -285,7 +281,7 @@ static void i830_import_tex_unit( i830ContextPtr i830,
|
|||
i830->state.Tex[unit][I830_TEXREG_CUBE] = t->Setup[I830_TEXREG_CUBE];
|
||||
i830->state.Tex[unit][I830_TEXREG_MCS] |= MAP_UNIT(unit);
|
||||
|
||||
t->intel.dirty &= ~I830_UPLOAD_TEX(unit);
|
||||
t->intel.dirty &= ~(1<<unit); /* This is broken! */
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -317,7 +313,7 @@ static GLboolean enable_tex_common( GLcontext *ctx, GLuint unit )
|
|||
* time.
|
||||
*/
|
||||
if (i830->intel.CurrentTexObj[unit] != &t->intel ||
|
||||
(t->intel.dirty & I830_UPLOAD_TEX(unit))) {
|
||||
(t->intel.dirty & (1<<unit))) {
|
||||
i830_import_tex_unit( i830, t, unit);
|
||||
}
|
||||
|
||||
|
|
@ -419,14 +415,10 @@ static GLboolean disable_tex( GLcontext *ctx, GLuint 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;
|
||||
}
|
||||
/* The old texture is no longer bound to this texture unit.
|
||||
* Mark it as such.
|
||||
*/
|
||||
i830->intel.CurrentTexObj[unit] = NULL;
|
||||
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,6 +41,8 @@
|
|||
#include "utils.h"
|
||||
#include "i915_reg.h"
|
||||
|
||||
#include "bufmgr.h"
|
||||
|
||||
/***************************************
|
||||
* Mesa's Driver Functions
|
||||
***************************************/
|
||||
|
|
@ -119,33 +121,22 @@ GLboolean i915CreateContext( const __GLcontextModes *mesaVis,
|
|||
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->tex.size,
|
||||
12,
|
||||
I830_NR_TEX_REGIONS,
|
||||
intel->sarea->texList,
|
||||
& intel->sarea->texAge,
|
||||
& intel->swapped,
|
||||
sizeof( struct i915_texture_object ),
|
||||
(destroy_texture_object_t *)intelDestroyTexObj );
|
||||
intel->bm = bm_fake_intel_Attach( intel );
|
||||
|
||||
/* FIXME: driCalculateMaxTextureLevels assumes that mipmaps are
|
||||
* tightly packed, but they're not in Intel graphics
|
||||
* hardware.
|
||||
bmInitPool(intel->bm,
|
||||
0,
|
||||
0, /* low offset */
|
||||
intel->intelScreen->tex.size, /* high offset */
|
||||
intel->intelScreen->tex.map); /* virtual base */
|
||||
|
||||
/* AGP allocation won't work:
|
||||
*/
|
||||
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. */
|
||||
11, /* rect texture */
|
||||
12,
|
||||
GL_FALSE );
|
||||
intel->intelScreen->allow_batchbuffer = GL_FALSE;
|
||||
|
||||
ctx->Const.MaxTextureLevels = 11;
|
||||
ctx->Const.Max3DTextureLevels = 8;
|
||||
ctx->Const.MaxCubeTextureLevels = 11;
|
||||
ctx->Const.MaxTextureRectSize = (1<<11);
|
||||
ctx->Const.MaxTextureUnits = I915_TEX_UNITS;
|
||||
|
||||
/* GL_ARB_fragment_program limits - don't think Mesa actually
|
||||
|
|
|
|||
|
|
@ -163,8 +163,6 @@ struct i915_fragment_program {
|
|||
GLuint nr_params;
|
||||
|
||||
|
||||
|
||||
|
||||
/* Helpers for i915_texprog.c:
|
||||
*/
|
||||
GLuint src_texture; /* Reg containing sampled texture color,
|
||||
|
|
@ -185,13 +183,6 @@ struct i915_fragment_program {
|
|||
|
||||
|
||||
|
||||
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
|
||||
|
||||
|
|
@ -220,6 +211,8 @@ struct i915_context
|
|||
|
||||
GLuint last_ReallyEnabled;
|
||||
GLuint vertex_fog;
|
||||
GLuint lodbias_ss2[MAX_TEXTURE_UNITS];
|
||||
|
||||
|
||||
struct i915_fragment_program tex_program;
|
||||
struct i915_fragment_program *current_program;
|
||||
|
|
@ -229,10 +222,6 @@ struct i915_context
|
|||
|
||||
|
||||
typedef struct i915_context *i915ContextPtr;
|
||||
typedef struct i915_texture_object *i915TextureObjectPtr;
|
||||
|
||||
#define I915_CONTEXT(ctx) ((i915ContextPtr)(ctx))
|
||||
|
||||
|
||||
|
||||
#define I915_STATECHANGE(i915, flag) \
|
||||
|
|
@ -346,6 +335,22 @@ i915ClearWithTris( intelContextPtr intel, GLbitfield mask,
|
|||
*/
|
||||
extern void i915ValidateFragmentProgram( i915ContextPtr i915 );
|
||||
extern void i915InitFragProgFuncs( struct dd_function_table *functions );
|
||||
|
||||
/*======================================================================
|
||||
* Inline conversion functions. These are better-typed than the
|
||||
* macros used previously:
|
||||
*/
|
||||
static inline struct i915_context *
|
||||
i915_context( GLcontext *ctx )
|
||||
{
|
||||
return (struct i915_context *)ctx;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#define I915_CONTEXT(ctx) i915_context(ctx)
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -447,7 +447,7 @@ i915ClearWithTris(intelContextPtr intel, GLbitfield mask,
|
|||
GLboolean all,
|
||||
GLint cx, GLint cy, GLint cw, GLint ch)
|
||||
{
|
||||
i915ContextPtr i915 = I915_CONTEXT( intel );
|
||||
i915ContextPtr i915 = i915_context( &intel->ctx );
|
||||
__DRIdrawablePrivate *dPriv = intel->driDrawable;
|
||||
intelScreenPrivate *screen = intel->intelScreen;
|
||||
int x0, y0, x1, y1;
|
||||
|
|
|
|||
|
|
@ -45,76 +45,10 @@
|
|||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 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_COMPARE_MODE:
|
||||
t->intel.dirty = I915_UPLOAD_TEX_ALL;
|
||||
break;
|
||||
case GL_TEXTURE_COMPARE_FUNC:
|
||||
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 */
|
||||
|
|
@ -139,13 +73,12 @@ static void i915TexEnv( GLcontext *ctx, GLenum target,
|
|||
break;
|
||||
|
||||
case GL_TEXTURE_LOD_BIAS: {
|
||||
int b = (int) ((*param) * 16.0);
|
||||
GLuint unit = ctx->Texture.CurrentUnit;
|
||||
GLint 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);
|
||||
i915->lodbias_ss2[unit] = ((b << SS2_LOD_BIAS_SHIFT) & SS2_LOD_BIAS_MASK);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -156,15 +89,8 @@ static void i915TexEnv( GLcontext *ctx, GLenum target,
|
|||
|
||||
|
||||
static void i915BindTexture( GLcontext *ctx, GLenum target,
|
||||
struct gl_texture_object *texObj )
|
||||
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:
|
||||
|
|
@ -178,5 +104,4 @@ void i915InitTextureFuncs( struct dd_function_table *functions )
|
|||
{
|
||||
functions->BindTexture = i915BindTexture;
|
||||
functions->TexEnv = i915TexEnv;
|
||||
functions->TexParameter = i915TexParameter;
|
||||
}
|
||||
|
|
|
|||
330
src/mesa/drivers/dri/i915/i915_tex_layout.c
Normal file
330
src/mesa/drivers/dri/i915/i915_tex_layout.c
Normal file
|
|
@ -0,0 +1,330 @@
|
|||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2006 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 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 TUNGSTEN GRAPHICS AND/OR ITS 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.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
/* Code to layout images in a mipmap tree for i915 and i945
|
||||
* respectively.
|
||||
*/
|
||||
|
||||
#include "intel_mipmap_tree.h"
|
||||
#include "macros.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} };
|
||||
|
||||
static GLuint minify( GLuint d )
|
||||
{
|
||||
return MAX2(1, d>>1);
|
||||
}
|
||||
|
||||
GLboolean i915_miptree_layout( struct intel_mipmap_tree *mt )
|
||||
{
|
||||
GLint i;
|
||||
GLint numLevels = mt->last_level - mt->first_level + 1;
|
||||
|
||||
switch (mt->target) {
|
||||
case GL_TEXTURE_CUBE_MAP: {
|
||||
const GLuint dim = mt->width0;
|
||||
GLuint face;
|
||||
|
||||
/* double pitch for cube layouts */
|
||||
mt->pitch = (dim * mt->cpp * 2 + 3) & ~3;
|
||||
mt->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;
|
||||
|
||||
for (i = 0; i < numLevels; i++) {
|
||||
mt->offset[face][i].x = x;
|
||||
mt->offset[face][i].y = y;
|
||||
mt->offset[face][i].width = d;
|
||||
mt->offset[face][i].height = d;
|
||||
mt->offset[face][i].depth = 0;
|
||||
|
||||
d >>= 1;
|
||||
assert(d > 0);
|
||||
|
||||
x += step_offsets[face][0] * d;
|
||||
y += step_offsets[face][1] * d;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case GL_TEXTURE_3D: {
|
||||
GLuint width = mt->width0;
|
||||
GLuint height = mt->height0;
|
||||
GLuint depth = mt->depth0;
|
||||
GLuint tmp_numLevels = MAX2(numLevels, 9);
|
||||
|
||||
/* Calculate the size of a single slice. Hardware demands a
|
||||
* minimum of 8 mipmaps, some of which might ultimately not be
|
||||
* used:
|
||||
*/
|
||||
mt->pitch = (mt->width0 * mt->cpp + 3) & ~3;
|
||||
mt->total_height = 0;
|
||||
|
||||
for ( i = 0 ; i < tmp_numLevels ; i++ ) {
|
||||
mt->offset[0][i].x = 0;
|
||||
mt->offset[0][i].y = mt->total_height;
|
||||
mt->offset[0][i].width = width;
|
||||
mt->offset[0][i].height = height;
|
||||
mt->offset[0][i].depth = depth;
|
||||
|
||||
mt->total_height += MAX2(2, height);
|
||||
|
||||
width = minify(width);
|
||||
height = minify(height);
|
||||
depth = minify(depth);
|
||||
}
|
||||
|
||||
|
||||
/* Multiply slice size by texture depth for total size. It's
|
||||
* remarkable how wasteful of memory the i915 texture layouts
|
||||
* are. They are largely fixed in the i945.
|
||||
*/
|
||||
mt->depth_pitch = mt->total_height * mt->pitch;
|
||||
mt->total_height *= mt->depth0;
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
GLuint width = mt->width0;
|
||||
GLuint height = mt->height0;
|
||||
|
||||
mt->pitch = (mt->width0 * mt->cpp + 3) & ~3;
|
||||
mt->total_height = 0;
|
||||
|
||||
for ( i = 0 ; i < numLevels ; i++ ) {
|
||||
mt->offset[0][i].x = 0;
|
||||
mt->offset[0][i].y = mt->total_height;
|
||||
mt->offset[0][i].height = height;
|
||||
mt->offset[0][i].width = width;
|
||||
mt->offset[0][i].depth = 0;
|
||||
|
||||
|
||||
if (mt->compressed)
|
||||
mt->total_height += MAX2(1, height/4);
|
||||
else
|
||||
mt->total_height += MAX2(2, height);
|
||||
|
||||
width = minify(width);
|
||||
height = minify(height);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
GLboolean i945_miptree_layout( struct intel_mipmap_tree *mt )
|
||||
{
|
||||
GLint numLevels = mt->last_level - mt->first_level + 1;
|
||||
GLint i;
|
||||
|
||||
switch (mt->target) {
|
||||
case GL_TEXTURE_CUBE_MAP: {
|
||||
const GLuint dim = mt->width0;
|
||||
GLuint face;
|
||||
|
||||
/* Depending on the size of the largest images, pitch can be
|
||||
* determined either by the old-style packing of cubemap faces,
|
||||
* or the final row of 4x4, 2x2 and 1x1 faces below this.
|
||||
*/
|
||||
if (dim > 32)
|
||||
mt->pitch = (dim * mt->cpp * 2 + 3) & ~3;
|
||||
else
|
||||
mt->pitch = 14 * 8 * mt->cpp;
|
||||
|
||||
mt->total_height = dim * 4 + 4;
|
||||
|
||||
|
||||
for ( face = 0 ; face < 6 ; face++) {
|
||||
GLuint x = initial_offsets[face][0] * dim;
|
||||
GLuint y = initial_offsets[face][1] * dim;
|
||||
GLuint d = dim;
|
||||
|
||||
if (dim == 4 && face >= 4) {
|
||||
y = mt->total_height - 4;
|
||||
x = (face - 4) * 8;
|
||||
}
|
||||
else if (dim < 4) {
|
||||
y = mt->total_height - 4;
|
||||
x = face * 8;
|
||||
}
|
||||
|
||||
for (i = 0; i < numLevels; i++) {
|
||||
mt->offset[face][i].x = x;
|
||||
mt->offset[face][i].y = y;
|
||||
mt->offset[face][i].width = d;
|
||||
mt->offset[face][i].height = d;
|
||||
mt->offset[face][i].depth = 0;
|
||||
|
||||
d >>= 1;
|
||||
assert(d > 0);
|
||||
|
||||
switch (d) {
|
||||
case 4:
|
||||
switch (face) {
|
||||
case FACE_POS_X:
|
||||
case FACE_NEG_X:
|
||||
x += step_offsets[face][0] * d;
|
||||
y += step_offsets[face][1] * d;
|
||||
break;
|
||||
case FACE_POS_Y:
|
||||
case FACE_NEG_Y:
|
||||
y += 12;
|
||||
x -= 8;
|
||||
break;
|
||||
case FACE_POS_Z:
|
||||
case FACE_NEG_Z:
|
||||
y = mt->total_height - 4;
|
||||
x = (face - 4) * 8;
|
||||
break;
|
||||
}
|
||||
|
||||
case 2:
|
||||
y = mt->total_height - 4;
|
||||
x = 16 + face * 8;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
x += 48;
|
||||
break;
|
||||
|
||||
default:
|
||||
x += step_offsets[face][0] * d;
|
||||
y += step_offsets[face][1] * d;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case GL_TEXTURE_3D: {
|
||||
GLuint width = mt->width0;
|
||||
GLuint height = mt->height0;
|
||||
GLuint depth = mt->depth0;
|
||||
GLuint depth_pack_pitch;
|
||||
GLuint depth_packing = 0;
|
||||
|
||||
mt->pitch = (mt->width0 * mt->cpp + 3) & ~3;
|
||||
mt->total_height = 0;
|
||||
|
||||
depth_pack_pitch = mt->pitch;
|
||||
|
||||
for ( i = 0 ; i < numLevels ; i++ ) {
|
||||
|
||||
mt->offset[0][i].x = 0;
|
||||
mt->offset[0][i].y = mt->total_height;
|
||||
mt->offset[0][i].width = width;
|
||||
mt->offset[0][i].height = height;
|
||||
mt->offset[0][i].depth = depth;
|
||||
|
||||
mt->total_height += MAX2(2, height) * MAX2((depth >> depth_packing), 1);
|
||||
|
||||
/* When alignment dominates, can't increase depth packing?
|
||||
* Or does pitch grow??? What are the alignment constraints,
|
||||
* anyway?
|
||||
*/
|
||||
if (depth_pack_pitch > 4) {
|
||||
depth_packing++;
|
||||
depth_pack_pitch <<= 2; /* KW: is this right?? */
|
||||
}
|
||||
|
||||
width = minify(width);
|
||||
height = minify(height);
|
||||
depth = minify(depth);
|
||||
|
||||
/* XXX: Not sure how 3d textures work on i945 - where did
|
||||
* t->depth_pitch get set in the old code. Did it ever work?
|
||||
* Fix up later.
|
||||
*/
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
GLuint x = 0;
|
||||
GLuint y = 0;
|
||||
GLuint width = mt->width0;
|
||||
GLuint height = mt->height0;
|
||||
|
||||
mt->pitch = (mt->width0 * mt->cpp + 3) & ~3;
|
||||
mt->total_height = 0;
|
||||
|
||||
for ( i = 0 ; i < numLevels ; i++ ) {
|
||||
mt->offset[0][i].x = x;
|
||||
mt->offset[0][i].y = y;
|
||||
mt->offset[0][i].height = height;
|
||||
mt->offset[0][i].width = width;
|
||||
mt->offset[0][i].depth = 0;
|
||||
|
||||
|
||||
/* LPT change: step right after second mipmap.
|
||||
*/
|
||||
if (i == 1)
|
||||
x += mt->pitch / (2 * mt->cpp);
|
||||
else {
|
||||
GLuint img_height;
|
||||
|
||||
if (mt->compressed)
|
||||
img_height = MAX2(1, height/4);
|
||||
else
|
||||
img_height = MAX2(2, height);
|
||||
|
||||
y += img_height;
|
||||
}
|
||||
|
||||
/* Because the images are packed better, the final offset
|
||||
* might not be the maximal one:
|
||||
*/
|
||||
mt->total_height = MAX2(mt->total_height, y);
|
||||
|
||||
width = minify(width);
|
||||
height = minify(height);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -44,7 +44,7 @@
|
|||
static void i915_render_start( intelContextPtr intel )
|
||||
{
|
||||
GLcontext *ctx = &intel->ctx;
|
||||
i915ContextPtr i915 = I915_CONTEXT(intel);
|
||||
i915ContextPtr i915 = i915_context(&intel->ctx);
|
||||
|
||||
if (ctx->FragmentProgram._Active)
|
||||
i915ValidateFragmentProgram( i915 );
|
||||
|
|
@ -56,7 +56,7 @@ static void i915_render_start( intelContextPtr intel )
|
|||
static void i915_reduced_primitive_state( intelContextPtr intel,
|
||||
GLenum rprim )
|
||||
{
|
||||
i915ContextPtr i915 = I915_CONTEXT(intel);
|
||||
i915ContextPtr i915 = i915_context(&intel->ctx);
|
||||
GLuint st1 = i915->state.Stipple[I915_STPREG_ST1];
|
||||
|
||||
st1 &= ~ST1_ENABLE;
|
||||
|
|
@ -88,7 +88,7 @@ static void i915_reduced_primitive_state( intelContextPtr intel,
|
|||
static GLboolean i915_check_vertex_size( intelContextPtr intel,
|
||||
GLuint expected )
|
||||
{
|
||||
i915ContextPtr i915 = I915_CONTEXT(intel);
|
||||
i915ContextPtr i915 = i915_context(&intel->ctx);
|
||||
int lis2 = i915->current->Ctx[I915_CTXREG_LIS2];
|
||||
int lis4 = i915->current->Ctx[I915_CTXREG_LIS4];
|
||||
int i, sz = 0;
|
||||
|
|
@ -218,7 +218,7 @@ do { \
|
|||
*/
|
||||
static void i915_emit_state( intelContextPtr intel )
|
||||
{
|
||||
i915ContextPtr i915 = I915_CONTEXT(intel);
|
||||
i915ContextPtr i915 = i915_context(&intel->ctx);
|
||||
struct i915_hw_state *state = i915->current;
|
||||
int i;
|
||||
GLuint dirty;
|
||||
|
|
@ -314,14 +314,15 @@ static void i915_destroy_context( intelContextPtr intel )
|
|||
|
||||
static void i915_set_draw_offset( intelContextPtr intel, int offset )
|
||||
{
|
||||
i915ContextPtr i915 = I915_CONTEXT(intel);
|
||||
i915ContextPtr i915 = i915_context(&intel->ctx);
|
||||
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;
|
||||
i915ContextPtr i915 = i915_context(&intel->ctx);
|
||||
i915->state.emitted = 0;
|
||||
}
|
||||
|
||||
static void i915_emit_flush( intelContextPtr intel )
|
||||
|
|
|
|||
|
|
@ -300,9 +300,6 @@ GLboolean intelInitContext( intelContextPtr intel,
|
|||
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;
|
||||
|
|
@ -438,14 +435,7 @@ void intelDestroyContext(__DRIcontextPrivate *driContextPriv)
|
|||
/* 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 ) );
|
||||
fprintf(stderr, "do somethign to free texture heaps\n");
|
||||
}
|
||||
|
||||
/* free the Mesa context */
|
||||
|
|
@ -586,7 +576,6 @@ void intelGetLock( intelContextPtr intel, GLuint flags )
|
|||
__DRIscreenPrivate *sPriv = intel->driScreen;
|
||||
drmI830Sarea * sarea = intel->sarea;
|
||||
int me = intel->hHWContext;
|
||||
unsigned i;
|
||||
|
||||
drmGetLock(intel->driFd, intel->hHWContext, flags);
|
||||
|
||||
|
|
@ -609,15 +598,6 @@ void intelGetLock( intelContextPtr intel, GLuint flags )
|
|||
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;
|
||||
|
|
|
|||
|
|
@ -47,8 +47,6 @@
|
|||
#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;
|
||||
|
|
@ -72,30 +70,34 @@ extern void intelFallback( intelContextPtr intel, GLuint bit, GLboolean mode );
|
|||
#define INTEL_TEX_MAXLEVELS 10
|
||||
|
||||
|
||||
|
||||
struct intel_texture_object
|
||||
{
|
||||
driTextureObject base; /* the parent class */
|
||||
struct gl_texture_object base; /* The "parent" object */
|
||||
|
||||
GLuint texelBytes;
|
||||
GLuint age;
|
||||
GLuint Pitch;
|
||||
GLuint Height;
|
||||
GLuint TextureOffset;
|
||||
GLubyte *BufAddr;
|
||||
/* The mipmap tree must include at least these levels once
|
||||
* validated:
|
||||
*/
|
||||
GLuint firstLevel;
|
||||
GLuint lastLevel;
|
||||
|
||||
GLuint min_level;
|
||||
GLuint max_level;
|
||||
GLuint depth_pitch;
|
||||
/* On validation any active images held in main memory or in other
|
||||
* regions will be copied to this region and the old storage freed.
|
||||
*/
|
||||
struct intel_mipmap_tree *mt;
|
||||
};
|
||||
|
||||
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_texture_image {
|
||||
struct gl_texture_image base;
|
||||
|
||||
/* These aren't stored in gl_texture_image
|
||||
*/
|
||||
GLuint level;
|
||||
GLuint face;
|
||||
|
||||
struct intel_mipmap_tree *mt;
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -179,12 +181,9 @@ struct intel_context
|
|||
GLboolean hw_stencil;
|
||||
GLboolean hw_stipple;
|
||||
|
||||
/* Texture object bookkeeping
|
||||
/* AGP memory buffer manager:
|
||||
*/
|
||||
GLuint nr_heaps;
|
||||
driTexHeap * texture_heaps[1];
|
||||
driTextureObject swapped;
|
||||
GLuint lastStamp;
|
||||
struct bufmgr *bm;
|
||||
|
||||
struct intel_texture_object *CurrentTexObj[MAX_TEXTURE_UNITS];
|
||||
|
||||
|
|
@ -212,7 +211,6 @@ struct intel_context
|
|||
GLuint numClipRects; /* cliprects for that buffer */
|
||||
drm_clip_rect_t *pClipRects;
|
||||
|
||||
int dirtyAge;
|
||||
int perf_boxes;
|
||||
int do_irqs;
|
||||
|
||||
|
|
@ -228,6 +226,8 @@ struct intel_context
|
|||
__DRIscreenPrivate *driScreen;
|
||||
intelScreenPrivate *intelScreen;
|
||||
drmI830Sarea *sarea;
|
||||
|
||||
GLuint lastStamp;
|
||||
|
||||
/**
|
||||
* Configuration cache
|
||||
|
|
@ -512,6 +512,25 @@ extern void intel_dump_batchbuffer( long offset,
|
|||
extern void intelInitPixelFuncs( struct dd_function_table *functions );
|
||||
|
||||
|
||||
/* Inline conversion functions. These are better-typed than the macros used previously:
|
||||
*/
|
||||
static inline struct intel_context *intel_context( GLcontext *ctx )
|
||||
{
|
||||
return (struct intel_context *)ctx;
|
||||
}
|
||||
|
||||
static inline struct intel_texture_object *intel_texture_object( struct gl_texture_object *obj )
|
||||
{
|
||||
return (struct intel_texture_object *)obj;
|
||||
}
|
||||
|
||||
static inline struct intel_texture_image *intel_texture_image( struct gl_texture_image *img )
|
||||
{
|
||||
return (struct intel_texture_image *)img;
|
||||
}
|
||||
|
||||
#define INTEL_CONTEXT(ctx) intel_context(ctx)
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -91,15 +91,6 @@ void intelWaitIrq( intelContextPtr intel, int seq )
|
|||
|
||||
|
||||
|
||||
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 )
|
||||
|
|
@ -263,8 +254,6 @@ void intelFlushBatchLocked( intelContextPtr intel,
|
|||
}
|
||||
|
||||
|
||||
age_intel(intel, intel->sarea->last_enqueue);
|
||||
|
||||
/* FIXME: use hardware contexts to avoid 'losing' hardware after
|
||||
* each buffer flush.
|
||||
*/
|
||||
|
|
@ -402,6 +391,11 @@ void *intelAllocateAGP( intelContextPtr intel, GLsizei size )
|
|||
drmI830MemAlloc alloc;
|
||||
int ret;
|
||||
|
||||
/* This won't work with the current state of the texture memory
|
||||
* manager:
|
||||
*/
|
||||
assert(0);
|
||||
|
||||
if (0)
|
||||
fprintf(stderr, "%s: %d bytes\n", __FUNCTION__, size);
|
||||
|
||||
|
|
@ -412,11 +406,6 @@ void *intelAllocateAGP( intelContextPtr intel, GLsizei size )
|
|||
|
||||
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,
|
||||
|
|
@ -431,13 +420,6 @@ void *intelAllocateAGP( intelContextPtr intel, GLsizei size )
|
|||
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);
|
||||
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@
|
|||
|
||||
|
||||
static GLboolean
|
||||
check_color( const GLcontext *ctx, GLenum type, GLenum format,
|
||||
check_color( GLcontext *ctx, GLenum type, GLenum format,
|
||||
const struct gl_pixelstore_attrib *packing,
|
||||
const void *pixels, GLint sz, GLint pitch )
|
||||
{
|
||||
|
|
@ -96,7 +96,7 @@ check_color_per_fragment_ops( const GLcontext *ctx )
|
|||
|
||||
|
||||
static GLboolean
|
||||
clip_pixelrect( const GLcontext *ctx,
|
||||
clip_pixelrect( GLcontext *ctx,
|
||||
const GLframebuffer *buffer,
|
||||
GLint *x, GLint *y,
|
||||
GLsizei *width, GLsizei *height,
|
||||
|
|
|
|||
|
|
@ -338,12 +338,16 @@ static GLboolean intelCreateContext( const __GLcontextModes *mesaVis,
|
|||
intelScreenPrivate *intelScreen = (intelScreenPrivate *)sPriv->private;
|
||||
|
||||
switch (intelScreen->deviceID) {
|
||||
#if 0
|
||||
/* Don't deal with i830 until texture work complete:
|
||||
*/
|
||||
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 );
|
||||
#endif
|
||||
|
||||
case PCI_CHIP_I915_G:
|
||||
case PCI_CHIP_I915_GM:
|
||||
|
|
|
|||
|
|
@ -1,830 +1,75 @@
|
|||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2003 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 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 TUNGSTEN GRAPHICS AND/OR ITS 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.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
#include "glheader.h"
|
||||
#include "mtypes.h"
|
||||
#include "imports.h"
|
||||
#include "macros.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_mipmap_tree.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)
|
||||
|
||||
static GLboolean intelIsTextureResident(GLcontext *ctx,
|
||||
struct gl_texture_object *texObj)
|
||||
{
|
||||
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 intelCompressedTexImage2D( GLcontext *ctx, GLenum target, GLint level,
|
||||
GLint internalFormat,
|
||||
GLint width, GLint height, GLint border,
|
||||
GLsizei imageSize, const GLvoid *data,
|
||||
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 );
|
||||
#if 0
|
||||
struct intel_context *intel = intel_context(ctx);
|
||||
struct intel_texture_object *intelObj = intel_texture_object(texObj);
|
||||
|
||||
driSwapOutTextureObject( t );
|
||||
texImage->IsClientData = GL_FALSE;
|
||||
|
||||
if (INTEL_DEBUG & DEBUG_TEXTURE)
|
||||
fprintf(stderr, "%s: Using normal storage\n", __FUNCTION__);
|
||||
|
||||
_mesa_store_compressed_teximage2d(ctx, target, level, internalFormat, width,
|
||||
height, border, imageSize, data, texObj, texImage);
|
||||
|
||||
t->dirty_images[face] |= (1 << level);
|
||||
}
|
||||
|
||||
|
||||
static void intelCompressedTexSubImage2D( GLcontext *ctx, GLenum target, GLint level,
|
||||
GLint xoffset, GLint yoffset,
|
||||
GLsizei width, GLsizei height,
|
||||
GLenum format,
|
||||
GLsizei imageSize, const GLvoid *data,
|
||||
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 ); /* this _should_ be true */
|
||||
intelFlush( ctx );
|
||||
driSwapOutTextureObject( t );
|
||||
|
||||
_mesa_store_compressed_texsubimage2d(ctx, target, level, xoffset, yoffset, width,
|
||||
height, format, imageSize, data, 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);
|
||||
return
|
||||
intelObj->mt &&
|
||||
intelObj->mt->region &&
|
||||
intel_is_region_resident(intel, intelObj->mt->region);
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static void intelDeleteTexture( GLcontext *ctx, struct gl_texture_object *tObj )
|
||||
static struct gl_texture_image *intelNewTextureImage( GLcontext *ctx )
|
||||
{
|
||||
driTextureObject * t = (driTextureObject *) tObj->DriverData;
|
||||
(void) ctx;
|
||||
return (struct gl_texture_image *)CALLOC_STRUCT(intel_texture_image);
|
||||
}
|
||||
|
||||
if ( t != NULL ) {
|
||||
intelFlush( ctx );
|
||||
driDestroyTextureObject( t );
|
||||
|
||||
static struct gl_texture_object *intelNewTextureObject( GLcontext *ctx,
|
||||
GLuint name,
|
||||
GLenum target )
|
||||
{
|
||||
struct intel_texture_object *obj = CALLOC_STRUCT(intel_texture_object);
|
||||
|
||||
_mesa_initialize_texture_object(&obj->base, name, target);
|
||||
|
||||
return &obj->base;
|
||||
}
|
||||
|
||||
|
||||
static void intelFreeTextureImageData( GLcontext *ctx,
|
||||
struct gl_texture_image *texImage )
|
||||
{
|
||||
struct intel_context *intel = intel_context(ctx);
|
||||
struct intel_texture_image *intelImage = intel_texture_image(texImage);
|
||||
|
||||
if (intelImage->mt) {
|
||||
intel_miptree_release(intel, intelImage->mt);
|
||||
intelImage->mt = NULL;
|
||||
}
|
||||
|
||||
/* Free mipmap images and the texture object itself */
|
||||
_mesa_delete_texture_object(ctx, tObj);
|
||||
if (texImage->Data) {
|
||||
free(texImage->Data);
|
||||
texImage->Data = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static const struct gl_texture_format *
|
||||
intelChooseTextureFormat( GLcontext *ctx, GLint internalFormat,
|
||||
GLenum format, GLenum type )
|
||||
void intelInitTextureFuncs(struct dd_function_table * functions)
|
||||
{
|
||||
intelContextPtr intel = INTEL_CONTEXT( ctx );
|
||||
const GLboolean do32bpt = ( intel->intelScreen->cpp == 4 &&
|
||||
intel->intelScreen->tex.size > 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:
|
||||
return &_mesa_texformat_a8;
|
||||
|
||||
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;
|
||||
|
||||
case GL_COMPRESSED_RGB_FXT1_3DFX:
|
||||
return &_mesa_texformat_rgb_fxt1;
|
||||
case GL_COMPRESSED_RGBA_FXT1_3DFX:
|
||||
return &_mesa_texformat_rgba_fxt1;
|
||||
|
||||
case GL_RGB_S3TC:
|
||||
case GL_RGB4_S3TC:
|
||||
case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
|
||||
return &_mesa_texformat_rgb_dxt1;
|
||||
|
||||
case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
|
||||
return &_mesa_texformat_rgba_dxt1;
|
||||
|
||||
case GL_RGBA_S3TC:
|
||||
case GL_RGBA4_S3TC:
|
||||
case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
|
||||
return &_mesa_texformat_rgba_dxt3;
|
||||
|
||||
case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
|
||||
return &_mesa_texformat_rgba_dxt5;
|
||||
|
||||
case GL_DEPTH_COMPONENT:
|
||||
case GL_DEPTH_COMPONENT16:
|
||||
case GL_DEPTH_COMPONENT24:
|
||||
case GL_DEPTH_COMPONENT32:
|
||||
return &_mesa_texformat_depth_component16;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "unexpected texture format %s in %s\n",
|
||||
_mesa_lookup_enum_by_nr(internalFormat),
|
||||
__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 if (image->IsCompressed) {
|
||||
GLuint row_len = image->Width * 2;
|
||||
GLubyte *dst = (GLubyte *)(t->BufAddr + offset);
|
||||
GLubyte *src = (GLubyte *)image->Data;
|
||||
GLuint 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);
|
||||
|
||||
switch (image->InternalFormat) {
|
||||
case GL_COMPRESSED_RGB_FXT1_3DFX:
|
||||
case GL_COMPRESSED_RGBA_FXT1_3DFX:
|
||||
case GL_RGB_S3TC:
|
||||
case GL_RGB4_S3TC:
|
||||
case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
|
||||
case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
|
||||
for (j = 0 ; j < image->Height/4 ; j++, dst += (t->Pitch)) {
|
||||
__memcpy(dst, src, row_len );
|
||||
src += row_len;
|
||||
}
|
||||
break;
|
||||
case GL_RGBA_S3TC:
|
||||
case GL_RGBA4_S3TC:
|
||||
case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
|
||||
case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
|
||||
for (j = 0 ; j < image->Height/4 ; j++, dst += (t->Pitch)) {
|
||||
__memcpy(dst, src, (image->Width*4) );
|
||||
src += image->Width*4;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr,"Internal Compressed format not supported %d\n", image->InternalFormat);
|
||||
break;
|
||||
}
|
||||
}
|
||||
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->tex.offset + 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;
|
||||
functions->CompressedTexImage2D = intelCompressedTexImage2D;
|
||||
functions->CompressedTexSubImage2D = intelCompressedTexSubImage2D;
|
||||
functions->ChooseTextureFormat = intelChooseTextureFormat;
|
||||
functions->TexImage1D = intelTexImage1D;
|
||||
functions->TexImage2D = intelTexImage2D;
|
||||
functions->TexSubImage1D = intelTexSubImage1D;
|
||||
functions->TexSubImage2D = intelTexSubImage2D;
|
||||
functions->NewTextureObject = intelNewTextureObject;
|
||||
functions->NewTextureImage = intelNewTextureImage;
|
||||
functions->DeleteTexture = _mesa_delete_texture_object;
|
||||
functions->FreeTexImageData = intelFreeTextureImageData;
|
||||
functions->TextureMemCpy = _mesa_memcpy;
|
||||
functions->UpdateTexturePalette = 0;
|
||||
functions->IsTextureResident = intelIsTextureResident;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,8 +35,54 @@
|
|||
|
||||
void intelInitTextureFuncs( struct dd_function_table *functions );
|
||||
|
||||
void intelDestroyTexObj( intelContextPtr intel, intelTextureObjectPtr t );
|
||||
int intelUploadTexImages( intelContextPtr intel, intelTextureObjectPtr t,
|
||||
GLuint face );
|
||||
const struct gl_texture_format *
|
||||
intelChooseTextureFormat( GLcontext *ctx, GLint internalFormat,
|
||||
GLenum format, GLenum type );
|
||||
|
||||
void intelTexImage2D(GLcontext *ctx,
|
||||
GLenum target, GLint level,
|
||||
GLint internalFormat,
|
||||
GLint width, GLint height, GLint border,
|
||||
GLenum format, GLenum type, const void *pixels,
|
||||
const struct gl_pixelstore_attrib *packing,
|
||||
struct gl_texture_object *texObj,
|
||||
struct gl_texture_image *texImage);
|
||||
|
||||
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);
|
||||
|
||||
void intelTexImage1D(GLcontext *ctx,
|
||||
GLenum target, GLint level,
|
||||
GLint internalFormat,
|
||||
GLint width, GLint border,
|
||||
GLenum format, GLenum type, const void *pixels,
|
||||
const struct gl_pixelstore_attrib *packing,
|
||||
struct gl_texture_object *texObj,
|
||||
struct gl_texture_image *texImage);
|
||||
|
||||
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);
|
||||
|
||||
GLuint intel_validate_mipmap_tree( struct intel_context *intel,
|
||||
struct intel_texture_object *intelObj );
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
|||
145
src/mesa/drivers/dri/i915/intel_tex_format.c
Normal file
145
src/mesa/drivers/dri/i915/intel_tex_format.c
Normal file
|
|
@ -0,0 +1,145 @@
|
|||
#include "intel_context.h"
|
||||
#include "intel_tex.h"
|
||||
#include "texformat.h"
|
||||
#include "enums.h"
|
||||
|
||||
/* It works out that this function is fine for all the supported
|
||||
* hardware. However, there is still a need to map the formats onto
|
||||
* hardware descriptors.
|
||||
*/
|
||||
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->tex.size > 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:
|
||||
return &_mesa_texformat_a8;
|
||||
|
||||
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;
|
||||
|
||||
case GL_COMPRESSED_RGB_FXT1_3DFX:
|
||||
return &_mesa_texformat_rgb_fxt1;
|
||||
case GL_COMPRESSED_RGBA_FXT1_3DFX:
|
||||
return &_mesa_texformat_rgba_fxt1;
|
||||
|
||||
case GL_RGB_S3TC:
|
||||
case GL_RGB4_S3TC:
|
||||
case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
|
||||
return &_mesa_texformat_rgb_dxt1;
|
||||
|
||||
case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
|
||||
return &_mesa_texformat_rgba_dxt1;
|
||||
|
||||
case GL_RGBA_S3TC:
|
||||
case GL_RGBA4_S3TC:
|
||||
case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
|
||||
return &_mesa_texformat_rgba_dxt3;
|
||||
|
||||
case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
|
||||
return &_mesa_texformat_rgba_dxt5;
|
||||
|
||||
case GL_DEPTH_COMPONENT:
|
||||
case GL_DEPTH_COMPONENT16:
|
||||
case GL_DEPTH_COMPONENT24:
|
||||
case GL_DEPTH_COMPONENT32:
|
||||
return &_mesa_texformat_depth_component16;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "unexpected texture format %s in %s\n",
|
||||
_mesa_lookup_enum_by_nr(internalFormat),
|
||||
__FUNCTION__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return NULL; /* never get here */
|
||||
}
|
||||
315
src/mesa/drivers/dri/i915/intel_tex_image.c
Normal file
315
src/mesa/drivers/dri/i915/intel_tex_image.c
Normal file
|
|
@ -0,0 +1,315 @@
|
|||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "glheader.h"
|
||||
#include "macros.h"
|
||||
#include "mtypes.h"
|
||||
#include "enums.h"
|
||||
#include "colortab.h"
|
||||
#include "convolve.h"
|
||||
#include "context.h"
|
||||
#include "simple_list.h"
|
||||
#include "texcompress.h"
|
||||
#include "texformat.h"
|
||||
#include "texobj.h"
|
||||
#include "texstore.h"
|
||||
|
||||
#include "intel_context.h"
|
||||
#include "intel_mipmap_tree.h"
|
||||
#include "intel_tex.h"
|
||||
#include "intel_ioctl.h"
|
||||
|
||||
|
||||
/* Functions to store texture images. Where possible, mipmap_tree's
|
||||
* will be created or further instantiated with image data, otherwise
|
||||
* images will be stored in malloc'd memory. A validation step is
|
||||
* required to pull those images into a mipmap tree, or otherwise
|
||||
* decide a fallback is required.
|
||||
*/
|
||||
|
||||
|
||||
static int logbase2(int n)
|
||||
{
|
||||
GLint i = 1;
|
||||
GLint log2 = 0;
|
||||
|
||||
while (n > i) {
|
||||
i *= 2;
|
||||
log2++;
|
||||
}
|
||||
|
||||
return log2;
|
||||
}
|
||||
|
||||
|
||||
/* Otherwise, store it in memory if (Border != 0) or (any dimension ==
|
||||
* 1).
|
||||
*
|
||||
* Otherwise, if max_level >= level >= min_level, create tree with
|
||||
* space for textures from min_level down to max_level.
|
||||
*
|
||||
* Otherwise, create tree with space for textures from (level
|
||||
* 0)..(1x1). Consider pruning this tree at a validation if the
|
||||
* saving is worth it.
|
||||
*/
|
||||
static void guess_and_alloc_mipmap_tree( struct intel_context *intel,
|
||||
struct intel_texture_object *intelObj,
|
||||
struct intel_texture_image *intelImage )
|
||||
{
|
||||
GLuint firstLevel;
|
||||
GLuint lastLevel;
|
||||
GLuint width = intelImage->base.Width;
|
||||
GLuint height = intelImage->base.Height;
|
||||
GLuint depth = intelImage->base.Depth;
|
||||
GLuint l2width, l2height, l2depth;
|
||||
GLuint i;
|
||||
|
||||
if (intelImage->base.Border)
|
||||
return;
|
||||
|
||||
if (intelImage->level > intelObj->base.BaseLevel &&
|
||||
(intelImage->base.Width == 1 ||
|
||||
(intelObj->base.Target != GL_TEXTURE_1D &&
|
||||
intelImage->base.Height == 1) ||
|
||||
(intelObj->base.Target == GL_TEXTURE_3D &&
|
||||
intelImage->base.Depth == 1)))
|
||||
return;
|
||||
|
||||
/* If this image disrespects BaseLevel, allocate from level zero.
|
||||
* Usually BaseLevel == 0, so it's unlikely to happen.
|
||||
*/
|
||||
if (intelImage->level < intelObj->base.BaseLevel)
|
||||
firstLevel = 0;
|
||||
else
|
||||
firstLevel = intelObj->base.BaseLevel;
|
||||
|
||||
|
||||
/* Figure out image dimensions at start level.
|
||||
*/
|
||||
for (i = intelImage->level; i > firstLevel; i--) {
|
||||
width <<= 1;
|
||||
if (height != 1) height <<= 1;
|
||||
if (depth != 1) depth <<= 1;
|
||||
}
|
||||
|
||||
/* Guess a reasonable value for lastLevel. This is probably going
|
||||
* to be wrong fairly often and might mean that we have to look at
|
||||
* resizable buffers, or require that buffers implement lazy
|
||||
* pagetable arrangements.
|
||||
*/
|
||||
if ((intelObj->base.MinFilter == GL_NEAREST ||
|
||||
intelObj->base.MinFilter == GL_LINEAR) &&
|
||||
intelImage->level == firstLevel) {
|
||||
lastLevel = firstLevel;
|
||||
}
|
||||
else {
|
||||
l2width = logbase2(width);
|
||||
l2height = logbase2(height);
|
||||
l2depth = logbase2(depth);
|
||||
lastLevel = firstLevel + MAX2(MAX2(l2width,l2height),l2depth);
|
||||
}
|
||||
|
||||
|
||||
intelObj->mt = intel_miptree_create( intel,
|
||||
intelObj->base.Target,
|
||||
intelImage->base.InternalFormat,
|
||||
firstLevel,
|
||||
lastLevel,
|
||||
width,
|
||||
height,
|
||||
depth,
|
||||
intelImage->base.TexFormat->TexelBytes,
|
||||
intelImage->base.IsCompressed );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static GLuint target_to_face( GLenum target )
|
||||
{
|
||||
switch (target) {
|
||||
case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
|
||||
case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
|
||||
case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
|
||||
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
|
||||
case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
|
||||
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
|
||||
return ((GLuint) target -
|
||||
(GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void intelTexImage(GLcontext *ctx,
|
||||
GLint dims,
|
||||
GLenum target, GLint level,
|
||||
GLint internalFormat,
|
||||
GLint width, GLint height, GLint border,
|
||||
GLenum format, GLenum type, const void *pixels,
|
||||
const struct gl_pixelstore_attrib *packing,
|
||||
struct gl_texture_object *texObj,
|
||||
struct gl_texture_image *texImage)
|
||||
{
|
||||
struct intel_context *intel = intel_context(ctx);
|
||||
struct intel_texture_object *intelObj = intel_texture_object(texObj);
|
||||
struct intel_texture_image *intelImage = intel_texture_image(texImage);
|
||||
GLint postConvWidth = width;
|
||||
GLint postConvHeight = height;
|
||||
GLint texelBytes, sizeInBytes;
|
||||
GLuint dstRowStride;
|
||||
|
||||
intelImage->face = target_to_face( target );
|
||||
intelImage->level = level;
|
||||
|
||||
if (ctx->_ImageTransferState & IMAGE_CONVOLUTION_BIT) {
|
||||
_mesa_adjust_image_for_convolution(ctx, dims, &postConvWidth,
|
||||
&postConvHeight);
|
||||
}
|
||||
|
||||
/* choose the texture format */
|
||||
texImage->TexFormat = intelChooseTextureFormat(ctx, internalFormat,
|
||||
format, type);
|
||||
|
||||
assert(texImage->TexFormat);
|
||||
|
||||
if (dims == 1) {
|
||||
texImage->FetchTexelc = texImage->TexFormat->FetchTexel1D;
|
||||
texImage->FetchTexelf = texImage->TexFormat->FetchTexel1Df;
|
||||
}
|
||||
else {
|
||||
texImage->FetchTexelc = texImage->TexFormat->FetchTexel2D;
|
||||
texImage->FetchTexelf = texImage->TexFormat->FetchTexel2Df;
|
||||
}
|
||||
texelBytes = texImage->TexFormat->TexelBytes;
|
||||
|
||||
|
||||
/* Minimum pitch of 32 bytes */
|
||||
if (postConvWidth * texelBytes < 32) {
|
||||
postConvWidth = 32 / texelBytes;
|
||||
texImage->RowStride = postConvWidth;
|
||||
}
|
||||
|
||||
assert(texImage->RowStride == postConvWidth);
|
||||
|
||||
/* Release the reference to a potentially orphaned buffer.
|
||||
* Release any old malloced memory.
|
||||
*/
|
||||
if (intelImage->mt) {
|
||||
intel_miptree_release(intel, intelImage->mt);
|
||||
intelImage->mt = NULL;
|
||||
assert(!texImage->Data);
|
||||
}
|
||||
else if (texImage->Data) {
|
||||
free(texImage->Data);
|
||||
}
|
||||
|
||||
pixels = _mesa_validate_pbo_teximage(ctx, dims, width, height, 1,
|
||||
format, type,
|
||||
pixels, packing, "glTexImage");
|
||||
if (!pixels)
|
||||
return;
|
||||
|
||||
if (!intelObj->mt) {
|
||||
guess_and_alloc_mipmap_tree(intel, intelObj, intelImage);
|
||||
}
|
||||
|
||||
LOCK_HARDWARE(intel);
|
||||
|
||||
if (intelObj->mt &&
|
||||
intel_miptree_match_image(intelObj->mt, &intelImage->base,
|
||||
intelImage->face, intelImage->level)) {
|
||||
|
||||
texImage->Data = intel_miptree_image_map(intel,
|
||||
intelObj->mt,
|
||||
intelImage->face,
|
||||
intelImage->level,
|
||||
&dstRowStride);
|
||||
}
|
||||
else {
|
||||
/* Allocate regular memory and store the image there temporarily. */
|
||||
if (texImage->IsCompressed) {
|
||||
sizeInBytes = texImage->CompressedSize;
|
||||
dstRowStride = _mesa_compressed_row_stride(texImage->InternalFormat,width);
|
||||
}
|
||||
else {
|
||||
sizeInBytes = postConvWidth * postConvHeight * texelBytes;
|
||||
dstRowStride = postConvWidth * texImage->TexFormat->TexelBytes;
|
||||
}
|
||||
|
||||
texImage->Data = malloc(sizeInBytes);
|
||||
}
|
||||
|
||||
/* Copy data. Would like to know when it's ok for us to eg. use
|
||||
* the blitter to copy. Or, use the hardware to do the format
|
||||
* conversion and copy:
|
||||
*/
|
||||
if (!texImage->TexFormat->StoreImage(ctx, dims,
|
||||
texImage->_BaseFormat,
|
||||
texImage->TexFormat,
|
||||
texImage->Data,
|
||||
0, 0, 0, /* dstX/Y/Zoffset */
|
||||
dstRowStride, 0 /* dstImageStride */,
|
||||
width, height, 1,
|
||||
format, type, pixels, packing)) {
|
||||
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage");
|
||||
}
|
||||
|
||||
_mesa_unmap_teximage_pbo(ctx, packing);
|
||||
|
||||
if (intelImage->mt) {
|
||||
intel_miptree_image_unmap(intel, intelImage->mt);
|
||||
texImage->Data = NULL;
|
||||
}
|
||||
|
||||
UNLOCK_HARDWARE(intel);
|
||||
|
||||
#if 0
|
||||
/* GL_SGIS_generate_mipmap -- this can be accelerated now.
|
||||
*/
|
||||
if (level == texObj->BaseLevel &&
|
||||
texObj->GenerateMipmap) {
|
||||
intel_generate_mipmap(ctx, target,
|
||||
&ctx->Texture.Unit[ctx->Texture.CurrentUnit],
|
||||
texObj);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void intelTexImage2D(GLcontext *ctx,
|
||||
GLenum target, GLint level,
|
||||
GLint internalFormat,
|
||||
GLint width, GLint height, GLint border,
|
||||
GLenum format, GLenum type, const void *pixels,
|
||||
const struct gl_pixelstore_attrib *packing,
|
||||
struct gl_texture_object *texObj,
|
||||
struct gl_texture_image *texImage)
|
||||
{
|
||||
intelTexImage( ctx, 2, target, level,
|
||||
internalFormat, width, height, border,
|
||||
format, type, pixels,
|
||||
packing, texObj, texImage );
|
||||
}
|
||||
|
||||
void intelTexImage1D(GLcontext *ctx,
|
||||
GLenum target, GLint level,
|
||||
GLint internalFormat,
|
||||
GLint width, GLint border,
|
||||
GLenum format, GLenum type, const void *pixels,
|
||||
const struct gl_pixelstore_attrib *packing,
|
||||
struct gl_texture_object *texObj,
|
||||
struct gl_texture_image *texImage)
|
||||
{
|
||||
intelTexImage( ctx, 1, target, level,
|
||||
internalFormat, width, 1, border,
|
||||
format, type, pixels,
|
||||
packing, texObj, texImage );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
115
src/mesa/drivers/dri/i915/intel_tex_subimage.c
Normal file
115
src/mesa/drivers/dri/i915/intel_tex_subimage.c
Normal file
|
|
@ -0,0 +1,115 @@
|
|||
|
||||
|
||||
#include "mtypes.h"
|
||||
#include "texobj.h"
|
||||
#include "texstore.h"
|
||||
|
||||
#include "intel_context.h"
|
||||
#include "intel_tex.h"
|
||||
#include "intel_mipmap_tree.h"
|
||||
|
||||
|
||||
static void intelTexSubimage (GLcontext *ctx,
|
||||
GLint dims,
|
||||
GLenum target, GLint level,
|
||||
GLint xoffset, GLint yoffset,
|
||||
GLint width, GLint height,
|
||||
GLenum format, GLenum type, const void *pixels,
|
||||
const struct gl_pixelstore_attrib *packing,
|
||||
struct gl_texture_object *texObj,
|
||||
struct gl_texture_image *texImage)
|
||||
{
|
||||
struct intel_context *intel = intel_context(ctx);
|
||||
struct intel_texture_image *intelImage = intel_texture_image(texImage);
|
||||
GLuint dstImageStride = 0;
|
||||
GLuint dstRowStride;
|
||||
|
||||
pixels = _mesa_validate_pbo_teximage(ctx, dims, width, height, 1, format, type,
|
||||
pixels, packing, "glTexSubImage2D");
|
||||
if (!pixels)
|
||||
return;
|
||||
|
||||
LOCK_HARDWARE(intel);
|
||||
|
||||
/* Map buffer if necessary. Need to lock to prevent other contexts
|
||||
* from uploading the buffer under us.
|
||||
*/
|
||||
if (intelImage->mt)
|
||||
texImage->Data = intel_miptree_image_map(intel,
|
||||
intelImage->mt,
|
||||
intelImage->face,
|
||||
intelImage->level,
|
||||
&dstRowStride );
|
||||
|
||||
|
||||
if (!texImage->TexFormat->StoreImage(ctx, dims, texImage->_BaseFormat,
|
||||
texImage->TexFormat,
|
||||
texImage->Data,
|
||||
xoffset, yoffset, 0,
|
||||
dstRowStride, dstImageStride,
|
||||
width, height, 1,
|
||||
format, type, pixels, packing)) {
|
||||
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage2D");
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* GL_SGIS_generate_mipmap */
|
||||
if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
|
||||
_mesa_generate_mipmap(ctx, target,
|
||||
&ctx->Texture.Unit[ctx->Texture.CurrentUnit],
|
||||
texObj);
|
||||
}
|
||||
#endif
|
||||
|
||||
_mesa_unmap_teximage_pbo(ctx, packing);
|
||||
|
||||
if (intelImage->mt) {
|
||||
intel_miptree_image_unmap(intel, intelImage->mt);
|
||||
texImage->Data = NULL;
|
||||
}
|
||||
|
||||
UNLOCK_HARDWARE(intel);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
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)
|
||||
{
|
||||
|
||||
intelTexSubimage(ctx, 2,
|
||||
target, level, xoffset, yoffset, width,
|
||||
height, format, type, pixels, packing, texObj,
|
||||
texImage);
|
||||
|
||||
}
|
||||
|
||||
|
||||
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)
|
||||
{
|
||||
intelTexSubimage(ctx, 1,
|
||||
target, level, xoffset, 0, width,
|
||||
1, format, type, pixels, packing, texObj,
|
||||
texImage);
|
||||
|
||||
}
|
||||
198
src/mesa/drivers/dri/i915/intel_tex_validate.c
Normal file
198
src/mesa/drivers/dri/i915/intel_tex_validate.c
Normal file
|
|
@ -0,0 +1,198 @@
|
|||
#include "mtypes.h"
|
||||
#include "macros.h"
|
||||
|
||||
#include "intel_context.h"
|
||||
#include "intel_mipmap_tree.h"
|
||||
#include "intel_tex.h"
|
||||
|
||||
|
||||
/**
|
||||
* Compute which mipmap levels that really need to be sent 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.
|
||||
*/
|
||||
static void intel_calculate_first_last_level( struct intel_texture_object *intelObj )
|
||||
{
|
||||
struct gl_texture_object *tObj = &intelObj->base;
|
||||
const struct gl_texture_image * const baseImage =
|
||||
tObj->Image[0][tObj->BaseLevel];
|
||||
|
||||
/* These must be signed values. MinLod and MaxLod can be negative numbers,
|
||||
* and having firstLevel and lastLevel as signed prevents the need for
|
||||
* extra sign checks.
|
||||
*/
|
||||
int firstLevel;
|
||||
int lastLevel;
|
||||
|
||||
/* Yes, this looks overly complicated, but it's all needed.
|
||||
*/
|
||||
switch (tObj->Target) {
|
||||
case GL_TEXTURE_1D:
|
||||
case GL_TEXTURE_2D:
|
||||
case GL_TEXTURE_3D:
|
||||
case GL_TEXTURE_CUBE_MAP:
|
||||
if (tObj->MinFilter == GL_NEAREST || tObj->MinFilter == GL_LINEAR) {
|
||||
/* GL_NEAREST and GL_LINEAR only care about GL_TEXTURE_BASE_LEVEL.
|
||||
*/
|
||||
firstLevel = lastLevel = tObj->BaseLevel;
|
||||
}
|
||||
else {
|
||||
firstLevel = tObj->BaseLevel + (GLint)(tObj->MinLod + 0.5);
|
||||
firstLevel = MAX2(firstLevel, tObj->BaseLevel);
|
||||
lastLevel = tObj->BaseLevel + (GLint)(tObj->MaxLod + 0.5);
|
||||
lastLevel = MAX2(lastLevel, tObj->BaseLevel);
|
||||
lastLevel = MIN2(lastLevel, tObj->BaseLevel + baseImage->MaxLog2);
|
||||
lastLevel = MIN2(lastLevel, tObj->MaxLevel);
|
||||
lastLevel = MAX2(firstLevel, lastLevel); /* need at least one level */
|
||||
}
|
||||
break;
|
||||
case GL_TEXTURE_RECTANGLE_NV:
|
||||
case GL_TEXTURE_4D_SGIS:
|
||||
firstLevel = lastLevel = 0;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
/* save these values */
|
||||
intelObj->firstLevel = firstLevel;
|
||||
intelObj->lastLevel = lastLevel;
|
||||
}
|
||||
|
||||
static void copy_image_data_to_tree( struct intel_context *intel,
|
||||
struct intel_mipmap_tree *mt,
|
||||
struct intel_texture_image *intelImage )
|
||||
{
|
||||
if (intelImage->mt) {
|
||||
/* Copy potentially with the blitter:
|
||||
*/
|
||||
intel_miptree_image_copy(intel,
|
||||
mt,
|
||||
intelImage->face,
|
||||
intelImage->level,
|
||||
intelImage->mt);
|
||||
|
||||
intel_miptree_release(intel, intelImage->mt);
|
||||
}
|
||||
else {
|
||||
assert(intelImage->base.Data != NULL);
|
||||
|
||||
/* More straightforward upload.
|
||||
*/
|
||||
intel_miptree_image_data(intel,
|
||||
mt,
|
||||
intelImage->face,
|
||||
intelImage->level,
|
||||
intelImage->base.Data,
|
||||
intelImage->base.RowStride);
|
||||
|
||||
free(intelImage->base.Data);
|
||||
intelImage->base.Data = NULL;
|
||||
}
|
||||
|
||||
intelImage->mt = intel_miptree_reference(mt);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*/
|
||||
GLuint intel_validate_mipmap_tree( struct intel_context *intel,
|
||||
struct intel_texture_object *intelObj )
|
||||
{
|
||||
GLuint face, i;
|
||||
GLuint nr_faces = 0;
|
||||
struct intel_texture_image *firstImage;
|
||||
|
||||
/* We know/require this is true by now:
|
||||
*/
|
||||
assert(intelObj->base.Complete);
|
||||
|
||||
/* What levels must the tree include at a minimum?
|
||||
*/
|
||||
intel_calculate_first_last_level( intelObj );
|
||||
firstImage = intel_texture_image(intelObj->base.Image[0][intelObj->firstLevel]);
|
||||
|
||||
/* Fallback case:
|
||||
*/
|
||||
if (firstImage->base.Border) {
|
||||
if (intelObj->mt) {
|
||||
intel_miptree_release(intel, intelObj->mt);
|
||||
intelObj->mt = NULL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* If both firstImage and intelObj have a tree which can contain
|
||||
* all active images, favour firstImage.
|
||||
*/
|
||||
if (firstImage->mt &&
|
||||
firstImage->mt != intelObj->mt &&
|
||||
firstImage->mt->first_level <= intelObj->firstLevel &&
|
||||
firstImage->mt->last_level >= intelObj->lastLevel) {
|
||||
|
||||
if (intelObj->mt)
|
||||
intel_miptree_release(intel, intelObj->mt);
|
||||
|
||||
intelObj->mt = intel_miptree_reference(firstImage->mt);
|
||||
}
|
||||
|
||||
/* Check tree can hold all active levels. Check tree matches
|
||||
* target, imageFormat, etc.
|
||||
*/
|
||||
if (intelObj->mt &&
|
||||
((intelObj->mt->first_level > intelObj->firstLevel) ||
|
||||
(intelObj->mt->last_level < intelObj->lastLevel) ||
|
||||
(intelObj->mt->internal_format != firstImage->base.InternalFormat))) {
|
||||
intel_miptree_release(intel, intelObj->mt);
|
||||
intelObj->mt = NULL;
|
||||
}
|
||||
|
||||
|
||||
/* May need to create a new tree:
|
||||
*/
|
||||
if (!intelObj->mt) {
|
||||
assert(!firstImage->mt);
|
||||
intelObj->mt = intel_miptree_create(intel,
|
||||
intelObj->base.Target,
|
||||
firstImage->base.InternalFormat,
|
||||
intelObj->firstLevel,
|
||||
intelObj->lastLevel,
|
||||
firstImage->base.Width,
|
||||
firstImage->base.Height,
|
||||
firstImage->base.Depth,
|
||||
firstImage->base.TexFormat->TexelBytes,
|
||||
firstImage->base.IsCompressed);
|
||||
}
|
||||
|
||||
assert(intelObj->mt);
|
||||
|
||||
assert(firstImage->mt == intelObj->mt ||
|
||||
firstImage->mt == NULL);
|
||||
|
||||
nr_faces = (intelObj->base.Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1;
|
||||
|
||||
for (face = 0; face < nr_faces; face++) {
|
||||
for (i = intelObj->firstLevel; i < intelObj->lastLevel; i++) {
|
||||
struct intel_texture_image *intelImage =
|
||||
intel_texture_image(intelObj->base.Image[face][i]);
|
||||
|
||||
/* Need to import images in main memory or held in other trees.
|
||||
*/
|
||||
if (intelObj->mt != intelImage->mt) {
|
||||
copy_image_data_to_tree(intel,
|
||||
intelObj->mt,
|
||||
intelImage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Loading…
Add table
Reference in a new issue