static GLboolean intel_alloc_texture_image_buffer(struct gl_context *ctx, struct gl_texture_image *image) { struct intel_context *intel = intel_context(ctx); struct intel_texture_image *intel_image = intel_texture_image(image); struct gl_texture_object *texobj = image->TexObject; struct intel_texture_object *intel_texobj = intel_texture_object(texobj); GLuint slices; assert(image->Border == 0); /* Because the driver uses AllocTextureImageBuffer() internally, it may end * up mismatched with FreeTextureImageBuffer(), but that is safe to call * multiple times. */ ctx->Driver.FreeTextureImageBuffer(ctx, image); /* Allocate the swrast_texture_image::ImageOffsets array now */ switch (texobj->Target) { case GL_TEXTURE_3D: case GL_TEXTURE_2D_ARRAY: slices = image->Depth; break; case GL_TEXTURE_1D_ARRAY: slices = image->Height; break; default: slices = 1; } assert(!intel_image->base.ImageOffsets); intel_image->base.ImageOffsets = malloc(slices * sizeof(GLuint)); _swrast_init_texture_image(image); if (intel_texobj->mt && intel_miptree_match_image(intel_texobj->mt, image)) { intel_miptree_reference(&intel_image->mt, intel_texobj->mt); DBG("%s: alloc obj %p level %d %dx%dx%d using object's miptree %p\n", __FUNCTION__, texobj, image->Level, image->Width, image->Height, image->Depth, intel_texobj->mt); } else { intel_image->mt = intel_miptree_create_for_teximage(intel, intel_texobj, intel_image, false); /* Even if the object currently has a mipmap tree associated * with it, this one is a more likely candidate to represent the * whole object since our level didn't fit what was there * before, and any lower levels would fit into our miptree. */ intel_miptree_reference(&intel_texobj->mt, intel_image->mt); DBG("%s: alloc obj %p level %d %dx%dx%d using new miptree %p\n", __FUNCTION__, texobj, image->Level, image->Width, image->Height, image->Depth, intel_image->mt); } return true; }
/** * ctx->Driver.AllocTextureStorage() handler. * * Compare this to _mesa_alloc_texture_storage, which would call into * intel_alloc_texture_image_buffer() above. */ static GLboolean intel_alloc_texture_storage(struct gl_context *ctx, struct gl_texture_object *texobj, GLsizei levels, GLsizei width, GLsizei height, GLsizei depth) { struct brw_context *brw = brw_context(ctx); struct intel_texture_object *intel_texobj = intel_texture_object(texobj); struct gl_texture_image *first_image = texobj->Image[0][0]; int num_samples = intel_quantize_num_samples(brw->intelScreen, first_image->NumSamples); const int numFaces = _mesa_num_tex_faces(texobj->Target); int face; int level; /* If the object's current miptree doesn't match what we need, make a new * one. */ if (!intel_texobj->mt || !intel_miptree_match_image(intel_texobj->mt, first_image) || intel_texobj->mt->last_level != levels - 1) { intel_miptree_release(&intel_texobj->mt); intel_texobj->mt = intel_miptree_create(brw, texobj->Target, first_image->TexFormat, 0, levels - 1, width, height, depth, false, /* expect_accelerated */ num_samples, INTEL_MIPTREE_TILING_ANY, false); if (intel_texobj->mt == NULL) { return false; } } for (face = 0; face < numFaces; face++) { for (level = 0; level < levels; level++) { struct gl_texture_image *image = texobj->Image[face][level]; struct intel_texture_image *intel_image = intel_texture_image(image); image->NumSamples = num_samples; _swrast_free_texture_image_buffer(ctx, image); if (!_swrast_init_texture_image(image)) return false; intel_miptree_reference(&intel_image->mt, intel_texobj->mt); } } /* The miptree is in a validated state, so no need to check later. */ intel_texobj->needs_validate = false; intel_texobj->validated_first_level = 0; intel_texobj->validated_last_level = levels - 1; intel_texobj->_Format = intel_texobj->mt->format; return true; }
static bool intel_set_texture_storage_for_buffer_object(struct gl_context *ctx, struct gl_texture_object *tex_obj, struct gl_buffer_object *buffer_obj, uint32_t buffer_offset, uint32_t row_stride, bool read_only) { struct brw_context *brw = brw_context(ctx); struct intel_texture_object *intel_texobj = intel_texture_object(tex_obj); struct gl_texture_image *image = tex_obj->Image[0][0]; struct intel_texture_image *intel_image = intel_texture_image(image); struct intel_buffer_object *intel_buffer_obj = intel_buffer_object(buffer_obj); if (!read_only) { /* Renderbuffers have the restriction that the buffer offset and * surface pitch must be a multiple of the element size. If it's * not, we have to fail and fall back to software. */ int cpp = _mesa_get_format_bytes(image->TexFormat); if (buffer_offset % cpp || row_stride % cpp) { perf_debug("Bad PBO alignment; fallback to CPU mapping\n"); return false; } if (!brw->format_supported_as_render_target[image->TexFormat]) { perf_debug("Non-renderable PBO format; fallback to CPU mapping\n"); return false; } } assert(intel_texobj->mt == NULL); drm_intel_bo *bo = intel_bufferobj_buffer(brw, intel_buffer_obj, buffer_offset, row_stride * image->Height); intel_texobj->mt = intel_miptree_create_for_bo(brw, bo, image->TexFormat, buffer_offset, image->Width, image->Height, image->Depth, row_stride, 0); if (!intel_texobj->mt) return false; if (!_swrast_init_texture_image(image)) return false; intel_miptree_reference(&intel_image->mt, intel_texobj->mt); /* The miptree is in a validated state, so no need to check later. */ intel_texobj->needs_validate = false; intel_texobj->validated_first_level = 0; intel_texobj->validated_last_level = 0; intel_texobj->_Format = intel_texobj->mt->format; return true; }
static GLboolean intel_alloc_texture_image_buffer(struct gl_context *ctx, struct gl_texture_image *image) { struct brw_context *brw = brw_context(ctx); struct intel_texture_image *intel_image = intel_texture_image(image); struct gl_texture_object *texobj = image->TexObject; struct intel_texture_object *intel_texobj = intel_texture_object(texobj); assert(image->Border == 0); /* Quantize sample count */ if (image->NumSamples) { image->NumSamples = intel_quantize_num_samples(brw->screen, image->NumSamples); if (!image->NumSamples) return false; } /* Because the driver uses AllocTextureImageBuffer() internally, it may end * up mismatched with FreeTextureImageBuffer(), but that is safe to call * multiple times. */ ctx->Driver.FreeTextureImageBuffer(ctx, image); if (!_swrast_init_texture_image(image)) return false; if (intel_texobj->mt && intel_miptree_match_image(intel_texobj->mt, image)) { intel_miptree_reference(&intel_image->mt, intel_texobj->mt); DBG("%s: alloc obj %p level %d %dx%dx%d using object's miptree %p\n", __func__, texobj, image->Level, image->Width, image->Height, image->Depth, intel_texobj->mt); } else { intel_image->mt = intel_miptree_create_for_teximage(brw, intel_texobj, intel_image, MIPTREE_CREATE_DEFAULT); if (!intel_image->mt) return false; /* Even if the object currently has a mipmap tree associated * with it, this one is a more likely candidate to represent the * whole object since our level didn't fit what was there * before, and any lower levels would fit into our miptree. */ intel_miptree_reference(&intel_texobj->mt, intel_image->mt); DBG("%s: alloc obj %p level %d %dx%dx%d using new miptree %p\n", __func__, texobj, image->Level, image->Width, image->Height, image->Depth, intel_image->mt); } intel_texobj->needs_validate = true; return true; }
/** * Called via ctx->Driver.AllocTextureImageBuffer() */ GLboolean _swrast_alloc_texture_image_buffer(struct gl_context *ctx, struct gl_texture_image *texImage, gl_format format, GLsizei width, GLsizei height, GLsizei depth) { struct swrast_texture_image *swImg = swrast_texture_image(texImage); GLuint bytes = _mesa_format_image_size(format, width, height, depth); GLuint i; /* This _should_ be true (revisit if these ever fail) */ assert(texImage->Width == width); assert(texImage->Height == height); assert(texImage->Depth == depth); assert(!swImg->Buffer); swImg->Buffer = _mesa_align_malloc(bytes, 512); if (!swImg->Buffer) return GL_FALSE; /* RowStride and ImageOffsets[] describe how to address texels in 'Data' */ swImg->RowStride = width; /* Allocate the ImageOffsets array and initialize to typical values. * We allocate the array for 1D/2D textures too in order to avoid special- * case code in the texstore routines. */ swImg->ImageOffsets = (GLuint *) malloc(depth * sizeof(GLuint)); if (!swImg->ImageOffsets) return GL_FALSE; for (i = 0; i < depth; i++) { swImg->ImageOffsets[i] = i * width * height; } _swrast_init_texture_image(texImage, width, height, depth); return GL_TRUE; }