static void i915LayoutTextureImages( i915ContextPtr i915, struct gl_texture_object *tObj ) { const struct gl_texture_image *baseImage = tObj->Image[0][tObj->BaseLevel]; i915TextureObjectPtr t = (i915TextureObjectPtr) tObj->DriverData; GLint firstLevel, lastLevel, numLevels; GLint i, total_height, pitch; /* Compute which mipmap levels we really want to send to the hardware. */ driCalculateTextureFirstLastLevel( (driTextureObject *) t ); /* Figure out the amount of memory required to hold all the mipmap * levels. Choose the smallest pitch to accomodate the largest * mipmap: */ firstLevel = t->intel.base.firstLevel; lastLevel = t->intel.base.lastLevel; numLevels = lastLevel - firstLevel + 1; /* All images must be loaded at this pitch. Count the number of * lines required: */ switch (tObj->Target) { case GL_TEXTURE_CUBE_MAP: { const GLuint dim = tObj->Image[0][firstLevel]->Width; GLuint face; pitch = dim * t->intel.texelBytes; pitch *= 2; /* double pitch for cube layouts */ pitch = (pitch + 3) & ~3; total_height = dim * 4; for ( face = 0 ; face < 6 ; face++) { GLuint x = initial_offsets[face][0] * dim; GLuint y = initial_offsets[face][1] * dim; GLuint d = dim; t->intel.base.dirty_images[face] = ~0; assert(tObj->Image[face][firstLevel]->Width == dim); assert(tObj->Image[face][firstLevel]->Height == dim); for (i = 0; i < numLevels; i++) { t->intel.image[face][i].image = tObj->Image[face][firstLevel + i]; if (!t->intel.image[face][i].image) { fprintf(stderr, "no image %d %d\n", face, i); break; /* can't happen */ } t->intel.image[face][i].offset = y * pitch + x * t->intel.texelBytes; t->intel.image[face][i].internalFormat = baseImage->_BaseFormat; d >>= 1; x += step_offsets[face][0] * d; y += step_offsets[face][1] * d; } } break; } case GL_TEXTURE_3D: { GLuint virtual_height; GLuint tmp_numLevels = numLevels; pitch = tObj->Image[0][firstLevel]->Width * t->intel.texelBytes; pitch = (pitch + 3) & ~3; t->intel.base.dirty_images[0] = ~0; /* Calculate the size of a single slice. Hardware demands a * minimum of 8 mipmaps, some of which might ultimately not be * used: */ if (tmp_numLevels < 9) tmp_numLevels = 9; virtual_height = tObj->Image[0][firstLevel]->Height; for ( total_height = i = 0 ; i < tmp_numLevels ; i++ ) { t->intel.image[0][i].image = tObj->Image[0][firstLevel + i]; if (t->intel.image[0][i].image) { t->intel.image[0][i].offset = total_height * pitch; t->intel.image[0][i].internalFormat = baseImage->_BaseFormat; } total_height += MAX2(2, virtual_height); virtual_height >>= 1; } t->intel.depth_pitch = total_height * pitch; /* Multiply slice size by texture depth for total size. It's * remarkable how wasteful of memory all the i8x0 texture * layouts are. */ total_height *= t->intel.image[0][0].image->Depth; break; } default: pitch = tObj->Image[0][firstLevel]->Width * t->intel.texelBytes; pitch = (pitch + 3) & ~3; t->intel.base.dirty_images[0] = ~0; for ( total_height = i = 0 ; i < numLevels ; i++ ) { t->intel.image[0][i].image = tObj->Image[0][firstLevel + i]; if (!t->intel.image[0][i].image) break; t->intel.image[0][i].offset = total_height * pitch; t->intel.image[0][i].internalFormat = baseImage->_BaseFormat; if (t->intel.image[0][i].image->IsCompressed) { if (t->intel.image[0][i].image->Height > 4) total_height += t->intel.image[0][i].image->Height/4; else total_height += 1; } else total_height += MAX2(2, t->intel.image[0][i].image->Height); } break; } t->intel.Pitch = pitch; t->intel.base.totalSize = total_height*pitch; t->intel.max_level = numLevels-1; }
static void i810SetTexImages( i810ContextPtr imesa, struct gl_texture_object *tObj ) { GLuint height, width, pitch, i, textureFormat, log_pitch; i810TextureObjectPtr t = (i810TextureObjectPtr) tObj->DriverData; const struct gl_texture_image *baseImage = tObj->Image[0][tObj->BaseLevel]; GLint numLevels; GLint log2Width, log2Height; /* fprintf(stderr, "%s\n", __FUNCTION__); */ t->texelBytes = 2; switch (baseImage->TexFormat) { case MESA_FORMAT_ARGB1555: textureFormat = MI1_FMT_16BPP | MI1_PF_16BPP_ARGB1555; break; case MESA_FORMAT_ARGB4444: textureFormat = MI1_FMT_16BPP | MI1_PF_16BPP_ARGB4444; break; case MESA_FORMAT_RGB565: textureFormat = MI1_FMT_16BPP | MI1_PF_16BPP_RGB565; break; case MESA_FORMAT_AL88: textureFormat = MI1_FMT_16BPP | MI1_PF_16BPP_AY88; break; case MESA_FORMAT_YCBCR: textureFormat = MI1_FMT_422 | MI1_PF_422_YCRCB_SWAP_Y | MI1_COLOR_CONV_ENABLE; break; case MESA_FORMAT_YCBCR_REV: textureFormat = MI1_FMT_422 | MI1_PF_422_YCRCB | MI1_COLOR_CONV_ENABLE; break; case MESA_FORMAT_CI8: textureFormat = MI1_FMT_8CI | MI1_PF_8CI_ARGB4444; t->texelBytes = 1; break; default: fprintf(stderr, "i810SetTexImages: bad image->Format\n" ); return; } driCalculateTextureFirstLastLevel( (driTextureObject *) t ); numLevels = t->base.lastLevel - t->base.firstLevel + 1; log2Width = tObj->Image[0][t->base.firstLevel]->WidthLog2; log2Height = tObj->Image[0][t->base.firstLevel]->HeightLog2; /* Figure out the amount of memory required to hold all the mipmap * levels. Choose the smallest pitch to accomodate the largest * mipmap: */ width = tObj->Image[0][t->base.firstLevel]->Width * t->texelBytes; for (pitch = 32, log_pitch=2 ; pitch < width ; pitch *= 2 ) log_pitch++; /* All images must be loaded at this pitch. Count the number of * lines required: */ for ( height = i = 0 ; i < numLevels ; i++ ) { t->image[i].image = tObj->Image[0][t->base.firstLevel + i]; t->image[i].offset = height * pitch; t->image[i].internalFormat = baseImage->_BaseFormat; height += t->image[i].image->Height; } t->Pitch = pitch; t->base.totalSize = height*pitch; t->max_level = i-1; t->dirty = I810_UPLOAD_TEX0 | I810_UPLOAD_TEX1; t->Setup[I810_TEXREG_MI1] = (MI1_MAP_0 | textureFormat | log_pitch); t->Setup[I810_TEXREG_MLL] = (GFX_OP_MAP_LOD_LIMITS | MLL_MAP_0 | MLL_UPDATE_MAX_MIP | MLL_UPDATE_MIN_MIP | ((numLevels - 1) << MLL_MIN_MIP_SHIFT)); LOCK_HARDWARE( imesa ); i810UploadTexImagesLocked( imesa, t ); UNLOCK_HARDWARE( imesa ); }
static void i945LayoutTextureImages( i915ContextPtr i915, struct gl_texture_object *tObj ) { const struct gl_texture_image *baseImage = tObj->Image[0][tObj->BaseLevel]; i915TextureObjectPtr t = (i915TextureObjectPtr) tObj->DriverData; GLint firstLevel, lastLevel, numLevels; GLint i, total_height, pitch, sz, max_offset = 0, offset; /* Compute which mipmap levels we really want to send to the hardware. */ driCalculateTextureFirstLastLevel( (driTextureObject *) t ); /* Figure out the amount of memory required to hold all the mipmap * levels. Choose the smallest pitch to accomodate the largest * mipmap: */ firstLevel = t->intel.base.firstLevel; lastLevel = t->intel.base.lastLevel; numLevels = lastLevel - firstLevel + 1; /* All images must be loaded at this pitch. Count the number of * lines required: */ switch (tObj->Target) { case GL_TEXTURE_CUBE_MAP: { const GLuint dim = tObj->Image[0][firstLevel]->Width; GLuint face; /* 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) { pitch = dim * t->intel.texelBytes; pitch *= 2; /* double pitch for cube layouts */ pitch = (pitch + 3) & ~3; } else { pitch = 14 * 8 * t->intel.texelBytes; /* determined by row of * little maps at * bottom */ } 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 = total_height - 4; x = (face - 4) * 8; } else if (dim < 4) { y = total_height - 4; x = face * 8; } t->intel.base.dirty_images[face] = ~0; assert(tObj->Image[face][firstLevel]->Width == dim); assert(tObj->Image[face][firstLevel]->Height == dim); for (i = 0; i < numLevels; i++) { t->intel.image[face][i].image = tObj->Image[face][firstLevel + i]; assert(t->intel.image[face][i].image); t->intel.image[face][i].offset = y * pitch + x * t->intel.texelBytes; t->intel.image[face][i].internalFormat = baseImage->_BaseFormat; d >>= 1; 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 = total_height - 4; x = (face - 4) * 8; break; } case 2: y = 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; } } } max_offset = total_height * pitch; break; } case GL_TEXTURE_3D: { GLuint depth_packing = 0, depth_pack_pitch; GLuint tmp_numLevels = numLevels; pitch = tObj->Image[0][firstLevel]->Width * t->intel.texelBytes; pitch = (pitch + 3) & ~3; depth_pack_pitch = pitch; t->intel.base.dirty_images[0] = ~0; for ( total_height = i = 0 ; i < tmp_numLevels ; i++ ) { t->intel.image[0][i].image = tObj->Image[0][firstLevel + i]; if (!t->intel.image[0][i].image) break; t->intel.image[0][i].offset = total_height * pitch; t->intel.image[0][i].internalFormat = baseImage->_BaseFormat; total_height += MAX2(2, t->intel.image[0][i].image->Height) * MAX2((t->intel.image[0][i].image->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; } } max_offset = total_height * pitch; break; } default: pitch = tObj->Image[0][firstLevel]->Width * t->intel.texelBytes; pitch = (pitch + 3) & ~3; t->intel.base.dirty_images[0] = ~0; max_offset = 0; for ( offset = i = 0 ; i < numLevels ; i++ ) { t->intel.image[0][i].image = tObj->Image[0][firstLevel + i]; if (!t->intel.image[0][i].image) break; t->intel.image[0][i].offset = offset; t->intel.image[0][i].internalFormat = baseImage->_BaseFormat; if (t->intel.image[0][i].image->IsCompressed) sz = MAX2(1, t->intel.image[0][i].image->Height/4) * pitch; else sz = MAX2(2, t->intel.image[0][i].image->Height) * pitch; /* Because the images are packed better, the final offset * might not be the maximal one: */ max_offset = MAX2(max_offset, offset + sz); /* LPT change: step right after second mipmap. */ if (i == 1) offset += pitch / 2; else offset += sz; } break; } t->intel.Pitch = pitch; t->intel.base.totalSize = max_offset; t->intel.max_level = numLevels-1; }
static void r128SetTexImages( r128ContextPtr rmesa, const struct gl_texture_object *tObj ) { r128TexObjPtr t = (r128TexObjPtr) tObj->DriverData; struct gl_texture_image *baseImage = tObj->Image[0][tObj->BaseLevel]; int log2Pitch, log2Height, log2Size, log2MinSize; int totalSize; int i; GLint firstLevel, lastLevel; assert(t); assert(baseImage); if ( R128_DEBUG & DEBUG_VERBOSE_API ) fprintf( stderr, "%s( %p )\n", __FUNCTION__, (void *) tObj ); switch (baseImage->TexFormat->MesaFormat) { case MESA_FORMAT_ARGB8888: case MESA_FORMAT_ARGB8888_REV: t->textureFormat = R128_DATATYPE_ARGB8888; break; case MESA_FORMAT_ARGB4444: case MESA_FORMAT_ARGB4444_REV: t->textureFormat = R128_DATATYPE_ARGB4444; break; case MESA_FORMAT_RGB565: case MESA_FORMAT_RGB565_REV: t->textureFormat = R128_DATATYPE_RGB565; break; case MESA_FORMAT_RGB332: t->textureFormat = R128_DATATYPE_RGB8; break; case MESA_FORMAT_CI8: t->textureFormat = R128_DATATYPE_CI8; break; case MESA_FORMAT_YCBCR: t->textureFormat = R128_DATATYPE_YVYU422; break; case MESA_FORMAT_YCBCR_REV: t->textureFormat = R128_DATATYPE_VYUY422; break; default: _mesa_problem(rmesa->glCtx, "Bad texture format in %s", __FUNCTION__); }; /* Compute which mipmap levels we really want to send to the hardware. */ driCalculateTextureFirstLastLevel( (driTextureObject *) t ); firstLevel = t->base.firstLevel; lastLevel = t->base.lastLevel; log2Pitch = tObj->Image[0][firstLevel]->WidthLog2; log2Height = tObj->Image[0][firstLevel]->HeightLog2; log2Size = MAX2(log2Pitch, log2Height); log2MinSize = log2Size; t->base.dirty_images[0] = 0; totalSize = 0; for ( i = firstLevel; i <= lastLevel; i++ ) { const struct gl_texture_image *texImage; texImage = tObj->Image[0][i]; if ( !texImage || !texImage->Data ) { lastLevel = i - 1; break; } log2MinSize = texImage->MaxLog2; t->image[i - firstLevel].offset = totalSize; t->image[i - firstLevel].width = tObj->Image[0][i]->Width; t->image[i - firstLevel].height = tObj->Image[0][i]->Height; t->base.dirty_images[0] |= (1 << i); totalSize += (tObj->Image[0][i]->Height * tObj->Image[0][i]->Width * tObj->Image[0][i]->TexFormat->TexelBytes); /* Offsets must be 32-byte aligned for host data blits and tiling */ totalSize = (totalSize + 31) & ~31; } t->base.totalSize = totalSize; t->base.firstLevel = firstLevel; t->base.lastLevel = lastLevel; /* Set the texture format */ t->setup.tex_cntl &= ~(0xf << 16); t->setup.tex_cntl |= t->textureFormat; t->setup.tex_combine_cntl = 0x00000000; /* XXX is this right? */ t->setup.tex_size_pitch = ((log2Pitch << R128_TEX_PITCH_SHIFT) | (log2Size << R128_TEX_SIZE_SHIFT) | (log2Height << R128_TEX_HEIGHT_SHIFT) | (log2MinSize << R128_TEX_MIN_SIZE_SHIFT)); for ( i = 0 ; i < R128_MAX_TEXTURE_LEVELS ; i++ ) { t->setup.tex_offset[i] = 0x00000000; } if (firstLevel == lastLevel) t->setup.tex_cntl |= R128_MIP_MAP_DISABLE; else t->setup.tex_cntl &= ~R128_MIP_MAP_DISABLE; /* FYI: r128UploadTexImages( rmesa, t ); used to be called here */ }