/* 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, comp_byte = 0; DBG("%s\n", __FUNCTION__); 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); } assert(!intelObj->mt); if (intelImage->base.IsCompressed) comp_byte = intel_compressed_num_bytes(intelImage->base.TexFormat->MesaFormat); intelObj->mt = intel_miptree_create(intel, intelObj->base.Target, intelImage->base.InternalFormat, firstLevel, lastLevel, width, height, depth, intelImage->base.TexFormat->TexelBytes, comp_byte); DBG("%s - success\n", __FUNCTION__); }
GLuint intel_finalize_mipmap_tree(struct intel_context *intel, GLuint unit) { struct gl_texture_object *tObj = intel->ctx.Texture.Unit[unit]._Current; struct intel_texture_object *intelObj = intel_texture_object(tObj); int comp_byte = 0; int cpp; 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); } return GL_FALSE; } /* If both firstImage and intelObj have a tree which can contain * all active images, favour firstImage. Note that because of the * completeness requirement, we know that the image dimensions * will match. */ 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); intel_miptree_reference(&intelObj->mt, firstImage->mt); } if (firstImage->base.IsCompressed) { comp_byte = intel_compressed_num_bytes(firstImage->base.TexFormat->MesaFormat); cpp = comp_byte; } else cpp = firstImage->base.TexFormat->TexelBytes; /* Check tree can hold all active levels. Check tree matches * target, imageFormat, etc. * * XXX: For some layouts (eg i945?), the test might have to be * first_level == firstLevel, as the tree isn't valid except at the * original start level. Hope to get around this by * programming minLod, maxLod, baseLevel into the hardware and * leaving the tree alone. */ if (intelObj->mt && (intelObj->mt->target != intelObj->base.Target || intelObj->mt->internal_format != firstImage->base.InternalFormat || intelObj->mt->first_level != intelObj->firstLevel || intelObj->mt->last_level != intelObj->lastLevel || intelObj->mt->width0 != firstImage->base.Width || intelObj->mt->height0 != firstImage->base.Height || intelObj->mt->depth0 != firstImage->base.Depth || intelObj->mt->cpp != cpp || intelObj->mt->compressed != firstImage->base.IsCompressed)) { intel_miptree_release(intel, &intelObj->mt); } /* May need to create a new tree: */ if (!intelObj->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, cpp, comp_byte, GL_TRUE); } /* Pull in any images not in the object's tree: */ 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, intelImage); } } } return GL_TRUE; }
GLuint intel_finalize_mipmap_tree( struct intel_context *intel, struct gl_texture_object *tObj ) { struct intel_texture_object *intelObj = intel_texture_object(tObj); GLuint face, i; GLuint nr_faces = 0; struct gl_texture_image *firstImage; GLuint cpp = 0; if( tObj == intel->frame_buffer_texobj ) return GL_FALSE; /* We know/require this is true by now: */ assert(intelObj->base.Complete); /* What levels must the tree include at a minimum? */ if (intelObj->dirty) { intel_calculate_first_last_level( intelObj ); /* intel_miptree_destroy(intel, intelObj->mt); */ /* intelObj->mt = NULL; */ } firstImage = intelObj->base.Image[0][intelObj->firstLevel]; /* Fallback case: */ if (firstImage->Border || ((firstImage->_BaseFormat == GL_DEPTH_COMPONENT) && ((tObj->WrapS == GL_CLAMP_TO_BORDER) || (tObj->WrapT == GL_CLAMP_TO_BORDER)))) { if (intelObj->mt) { intel_miptree_destroy(intel, intelObj->mt); intelObj->mt = NULL; /* Set all images dirty: */ intel_texture_invalidate(intelObj); } return GL_FALSE; } if (firstImage->IsCompressed) { cpp = intel_compressed_num_bytes(firstImage->TexFormat->MesaFormat); } else { cpp = firstImage->TexFormat->TexelBytes; } /* Check tree can hold all active levels. Check tree matches * target, imageFormat, etc. */ if (intelObj->mt && (intelObj->mt->target != intelObj->base.Target || intelObj->mt->internal_format != firstImage->InternalFormat || intelObj->mt->first_level != intelObj->firstLevel || intelObj->mt->last_level != intelObj->lastLevel || intelObj->mt->width0 != firstImage->Width || intelObj->mt->height0 != firstImage->Height || intelObj->mt->depth0 != firstImage->Depth || intelObj->mt->cpp != cpp || intelObj->mt->compressed != firstImage->IsCompressed)) { intel_miptree_destroy(intel, intelObj->mt); intelObj->mt = NULL; /* Set all images dirty: */ intel_texture_invalidate(intelObj); } /* May need to create a new tree: */ if (!intelObj->mt) { intelObj->mt = intel_miptree_create(intel, intelObj->base.Target, firstImage->InternalFormat, intelObj->firstLevel, intelObj->lastLevel, firstImage->Width, firstImage->Height, firstImage->Depth, cpp, firstImage->IsCompressed); /* Tell the buffer manager that we will manage the backing * store, but we still want it to do fencing for us. */ bmBufferSetInvalidateCB(intel, intelObj->mt->region->buffer, intel_texture_invalidate_cb, intelObj, GL_FALSE); } /* Pull in any images not in the object's tree: */ if (intelObj->dirty) { nr_faces = (intelObj->base.Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1; for (face = 0; face < nr_faces; face++) { if (intelObj->dirty_images[face]) { for (i = intelObj->firstLevel; i <= intelObj->lastLevel; i++) { struct gl_texture_image *texImage = intelObj->base.Image[face][i]; /* Need to import images in main memory or held in other trees. */ if (intelObj->dirty_images[face] & (1<<i) && texImage) { if (INTEL_DEBUG & DEBUG_TEXTURE) _mesa_printf("copy data from image %d (%p) into object miptree\n", i, texImage->Data); if (!copy_image_data_to_tree(intel, intelObj, texImage, face, i)) return GL_FALSE; } } } } /* Only clear the dirty flags if everything went ok: */ for (face = 0; face < nr_faces; face++) { intelObj->dirty_images[face] = 0; } intelObj->dirty = 0; } return GL_TRUE; }