/** * Wraps Mesa's implementation to ensure that the base level image is mapped. * * This relies on internal details of _mesa_generate_mipmap, in particular * the fact that the memory for recreated texture images is always freed. */ static void radeon_generate_mipmap(GLcontext *ctx, GLenum target, struct gl_texture_object *texObj) { radeonTexObj* t = radeon_tex_obj(texObj); GLuint nr_faces = (t->base.Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1; int i, face; radeon_print(RADEON_TEXTURE, RADEON_VERBOSE, "%s(%p, tex %p) Target type %s.\n", __func__, ctx, texObj, _mesa_lookup_enum_by_nr(target)); _mesa_generate_mipmap(ctx, target, texObj); for (face = 0; face < nr_faces; face++) { for (i = texObj->BaseLevel + 1; i < texObj->MaxLevel; i++) { radeon_texture_image *image; image = get_radeon_texture_image(texObj->Image[face][i]); if (image == NULL) break; image->mtlevel = i; image->mtface = face; radeon_miptree_unreference(&image->mt); } } }
static void radeonDeleteTexture( GLcontext *ctx, struct gl_texture_object *texObj ) { r100ContextPtr rmesa = R100_CONTEXT(ctx); radeonTexObj* t = radeon_tex_obj(texObj); int i; radeon_print(RADEON_TEXTURE, RADEON_NORMAL, "%s( %p (target = %s) )\n", __FUNCTION__, (void *)texObj, _mesa_lookup_enum_by_nr( texObj->Target ) ); if ( rmesa ) { radeon_firevertices(&rmesa->radeon); for ( i = 0 ; i < rmesa->radeon.glCtx->Const.MaxTextureUnits ; i++ ) { if ( t == rmesa->state.texture.unit[i].texobj ) { rmesa->state.texture.unit[i].texobj = NULL; rmesa->hw.tex[i].dirty = GL_FALSE; rmesa->hw.cube[i].dirty = GL_FALSE; } } } radeon_miptree_unreference(&t->mt); /* Free mipmap images and the texture object itself */ _mesa_delete_texture_object(ctx, texObj); }
/** Check if given image is valid within current texture object. */ static void teximage_assign_miptree(radeonContextPtr rmesa, struct gl_texture_object *texObj, struct gl_texture_image *texImage) { radeonTexObj *t = radeon_tex_obj(texObj); radeon_texture_image* image = get_radeon_texture_image(texImage); /* Try using current miptree, or create new if there isn't any */ if (!t->mt || !radeon_miptree_matches_image(t->mt, texImage)) { radeon_miptree_unreference(&t->mt); t->mt = radeon_miptree_create_for_teximage(rmesa, texObj, texImage); radeon_print(RADEON_TEXTURE, RADEON_NORMAL, "%s: texObj %p, texImage %p, " "texObj miptree doesn't match, allocated new miptree %p\n", __FUNCTION__, texObj, texImage, t->mt); } /* Miptree alocation may have failed, * when there was no image for baselevel specified */ if (t->mt) { radeon_miptree_reference(t->mt, &image->mt); } else radeon_print(RADEON_TEXTURE, RADEON_VERBOSE, "%s Failed to allocate miptree.\n", __func__); }
void radeon_image_target_texture_2d(struct gl_context *ctx, GLenum target, struct gl_texture_object *texObj, struct gl_texture_image *texImage, GLeglImageOES image_handle) { radeonContextPtr radeon = RADEON_CONTEXT(ctx); radeonTexObj *t = radeon_tex_obj(texObj); radeon_texture_image *radeonImage = get_radeon_texture_image(texImage); __DRIscreen *screen; __DRIimage *image; screen = radeon->dri.screen; image = screen->dri2.image->lookupEGLImage(screen, image_handle, screen->loaderPrivate); if (image == NULL) return; radeonFreeTextureImageBuffer(ctx, texImage); texImage->Width = image->width; texImage->Height = image->height; texImage->Depth = 1; texImage->_BaseFormat = GL_RGBA; texImage->TexFormat = image->format; radeonImage->base.RowStride = image->pitch; texImage->InternalFormat = image->internal_format; if(t->mt) { radeon_miptree_unreference(&t->mt); t->mt = NULL; } /* NOTE: The following is *very* ugly and will probably break. But I don't know how to deal with it, without creating a whole new function like radeon_miptree_from_bo() so I'm going with the easy but error-prone way. */ radeon_try_alloc_miptree(radeon, t); radeon_miptree_reference(t->mt, &radeonImage->mt); if (t->mt == NULL) { radeon_print(RADEON_TEXTURE, RADEON_VERBOSE, "%s Failed to allocate miptree.\n", __func__); return; } /* Particularly ugly: this is guaranteed to break, if image->bo is not of the required size for a miptree. */ radeon_bo_unref(t->mt->bo); radeon_bo_ref(image->bo); t->mt->bo = image->bo; if (!radeon_miptree_matches_image(t->mt, &radeonImage->base.Base)) fprintf(stderr, "miptree doesn't match image\n"); }
void r200TexUpdateParameters(struct gl_context *ctx, GLuint unit) { struct gl_sampler_object *samp = _mesa_get_samplerobj(ctx, unit); radeonTexObj* t = radeon_tex_obj(ctx->Texture.Unit[unit]._Current); r200SetTexMaxAnisotropy(t , samp->MaxAnisotropy); r200SetTexFilter(t, samp->MinFilter, samp->MagFilter); r200SetTexWrap(t, samp->WrapS, samp->WrapT, samp->WrapR); r200SetTexBorderColor(t, samp->BorderColor.f); }
void radeonCopyTexImage2D(GLcontext *ctx, GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border) { struct gl_texture_unit *texUnit = _mesa_get_current_tex_unit(ctx); struct gl_texture_object *texObj = _mesa_select_tex_object(ctx, texUnit, target); struct gl_texture_image *texImage = _mesa_select_tex_image(ctx, texObj, target, level); int srcx, srcy, dstx, dsty; radeonContextPtr radeon = RADEON_CONTEXT(ctx); radeon_prepare_render(radeon); if (border) goto fail; /* Setup or redefine the texture object, mipmap tree and texture * image. Don't populate yet. */ ctx->Driver.TexImage2D(ctx, target, level, internalFormat, width, height, border, GL_RGBA, GL_UNSIGNED_BYTE, NULL, &ctx->DefaultPacking, texObj, texImage); srcx = x; srcy = y; dstx = 0; dsty = 0; if (!_mesa_clip_copytexsubimage(ctx, &dstx, &dsty, &srcx, &srcy, &width, &height)) { return; } if (!do_copy_texsubimage(ctx, target, level, radeon_tex_obj(texObj), (radeon_texture_image *)texImage, 0, 0, x, y, width, height)) { goto fail; } return; fail: radeon_print(RADEON_FALLBACKS, RADEON_NORMAL, "Falling back to sw for glCopyTexImage2D (internalFormat %s, border %d)\n", _mesa_lookup_enum_by_nr(internalFormat), border); _mesa_meta_CopyTexImage2D(ctx, target, level, internalFormat, x, y, width, height, border); }
/** * All glTexSubImage calls go through this function. */ static void radeon_texsubimage(GLcontext* ctx, int dims, GLenum target, int level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, GLenum format, GLenum type, const GLvoid * pixels, const struct gl_pixelstore_attrib *packing, struct gl_texture_object *texObj, struct gl_texture_image *texImage, int compressed) { radeonContextPtr rmesa = RADEON_CONTEXT(ctx); radeonTexObj* t = radeon_tex_obj(texObj); radeon_texture_image* image = get_radeon_texture_image(texImage); radeon_print(RADEON_TEXTURE, RADEON_NORMAL, "%s %dd: texObj %p, texImage %p, face %d, level %d\n", __func__, dims, texObj, texImage, _mesa_tex_target_to_face(target), level); { struct radeon_bo *bo; bo = !image->mt ? image->bo : image->mt->bo; if (bo && radeon_bo_is_referenced_by_cs(bo, rmesa->cmdbuf.cs)) { radeon_print(RADEON_TEXTURE, RADEON_VERBOSE, "%s Calling texsubimage for texture that is " "queued for GPU processing.\n", __func__); radeon_firevertices(rmesa); } } t->validated = GL_FALSE; if (compressed) { pixels = _mesa_validate_pbo_compressed_teximage( ctx, imageSize, pixels, packing, "glCompressedTexSubImage"); } else { pixels = _mesa_validate_pbo_teximage(ctx, dims, width, height, depth, format, type, pixels, packing, "glTexSubImage"); } if (pixels) { radeon_store_teximage(ctx, dims, xoffset, yoffset, zoffset, width, height, depth, imageSize, format, type, pixels, packing, texObj, texImage, compressed); } _mesa_unmap_teximage_pbo(ctx, packing); }
static radeon_mipmap_tree *radeon_miptree_create_for_teximage(radeonContextPtr rmesa, struct gl_texture_object *texObj, struct gl_texture_image *texImage) { radeonTexObj *t = radeon_tex_obj(texObj); GLuint firstLevel; GLuint lastLevel; int width, height, depth; int i; width = texImage->Width; height = texImage->Height; depth = texImage->Depth; if (texImage->Level > texObj->BaseLevel && (width == 1 || (texObj->Target != GL_TEXTURE_1D && height == 1) || (texObj->Target == GL_TEXTURE_3D && depth == 1))) { /* For this combination, we're at some lower mipmap level and * some important dimension is 1. We can't extrapolate up to a * likely base level width/height/depth for a full mipmap stack * from this info, so just allocate this one level. */ firstLevel = texImage->Level; lastLevel = texImage->Level; } else { if (texImage->Level < texObj->BaseLevel) firstLevel = 0; else firstLevel = texObj->BaseLevel; for (i = texImage->Level; i > firstLevel; i--) { width <<= 1; if (height != 1) height <<= 1; if (depth != 1) depth <<= 1; } if ((texObj->Sampler.MinFilter == GL_NEAREST || texObj->Sampler.MinFilter == GL_LINEAR) && texImage->Level == firstLevel) { lastLevel = firstLevel; } else { lastLevel = firstLevel + _mesa_logbase2(MAX2(MAX2(width, height), depth)); } } return radeon_miptree_create(rmesa, texObj->Target, texImage->TexFormat, firstLevel, lastLevel - firstLevel + 1, width, height, depth, t->tile_bits); }
/** * Ensure all enabled and complete textures are uploaded along with any buffers being used. */ GLboolean r300ValidateBuffers(GLcontext * ctx) { r300ContextPtr rmesa = R300_CONTEXT(ctx); struct radeon_renderbuffer *rrb; int i; int ret; radeon_cs_space_reset_bos(rmesa->radeon.cmdbuf.cs); rrb = radeon_get_colorbuffer(&rmesa->radeon); /* color buffer */ if (rrb && rrb->bo) { radeon_cs_space_add_persistent_bo(rmesa->radeon.cmdbuf.cs, rrb->bo, 0, RADEON_GEM_DOMAIN_VRAM); } /* depth buffer */ rrb = radeon_get_depthbuffer(&rmesa->radeon); if (rrb && rrb->bo) { radeon_cs_space_add_persistent_bo(rmesa->radeon.cmdbuf.cs, rrb->bo, 0, RADEON_GEM_DOMAIN_VRAM); } for (i = 0; i < ctx->Const.MaxTextureImageUnits; ++i) { radeonTexObj *t; if (!ctx->Texture.Unit[i]._ReallyEnabled) continue; if (!r300_validate_texture(ctx, ctx->Texture.Unit[i]._Current)) { _mesa_warning(ctx, "failed to validate texture for unit %d.\n", i); } t = radeon_tex_obj(ctx->Texture.Unit[i]._Current); if (t->image_override && t->bo) radeon_cs_space_add_persistent_bo(rmesa->radeon.cmdbuf.cs, t->bo, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0); else if (t->mt->bo) radeon_cs_space_add_persistent_bo(rmesa->radeon.cmdbuf.cs, t->mt->bo, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0); } ret = radeon_cs_space_check_with_bo(rmesa->radeon.cmdbuf.cs, first_elem(&rmesa->radeon.dma.reserved)->bo, RADEON_GEM_DOMAIN_GTT, 0); if (ret) return GL_FALSE; return GL_TRUE; }
/** * Ensure the given texture is ready for rendering. * * Mostly this means populating the texture object's mipmap tree. */ static GLboolean r300_validate_texture(GLcontext * ctx, struct gl_texture_object *texObj) { r300ContextPtr rmesa = R300_CONTEXT(ctx); radeonTexObj *t = radeon_tex_obj(texObj); if (!radeon_validate_texture_miptree(ctx, texObj)) return GL_FALSE; /* Configure the hardware registers (more precisely, the cached version * of the hardware registers). */ setup_hardware_state(rmesa, t); t->validated = GL_TRUE; return GL_TRUE; }
void r300SetTexOffset(__DRIcontext * pDRICtx, GLint texname, unsigned long long offset, GLint depth, GLuint pitch) { r300ContextPtr rmesa = pDRICtx->driverPrivate; struct gl_texture_object *tObj = _mesa_lookup_texture(rmesa->radeon.glCtx, texname); radeonTexObjPtr t = radeon_tex_obj(tObj); uint32_t pitch_val; if (!tObj) return; t->image_override = GL_TRUE; if (!offset) return; t->bo = NULL; t->override_offset = offset; t->pp_txpitch &= (1 << 13) -1; pitch_val = pitch; switch (depth) { case 32: t->pp_txformat = R300_EASY_TX_FORMAT(X, Y, Z, W, W8Z8Y8X8); t->pp_txfilter |= tx_table[2].filter; pitch_val /= 4; break; case 24: default: t->pp_txformat = R300_EASY_TX_FORMAT(X, Y, Z, ONE, W8Z8Y8X8); t->pp_txfilter |= tx_table[4].filter; pitch_val /= 4; break; case 16: t->pp_txformat = R300_EASY_TX_FORMAT(X, Y, Z, ONE, Z5Y6X5); t->pp_txfilter |= tx_table[5].filter; pitch_val /= 2; break; } pitch_val--; t->pp_txpitch |= pitch_val; }
void radeonUnmapTexture(GLcontext *ctx, struct gl_texture_object *texObj) { radeonTexObj* t = radeon_tex_obj(texObj); int face, level; radeon_print(RADEON_TEXTURE, RADEON_VERBOSE, "%s(%p, tex %p)\n", __func__, ctx, texObj); if (t->image_override && t->bo) unmap_override(ctx, t); /* for r100 3D sw fallbacks don't have mt */ if (!t->mt) return; for(face = 0; face < t->mt->faces; ++face) { for(level = t->minLod; level <= t->maxLod; ++level) texObj->Image[face][level]->Data = 0; } radeon_bo_unmap(t->mt->bo); }
/** * Map a validated texture for reading during software rendering. */ void radeonMapTexture(GLcontext *ctx, struct gl_texture_object *texObj) { radeonTexObj* t = radeon_tex_obj(texObj); int face, level; radeon_print(RADEON_TEXTURE, RADEON_VERBOSE, "%s(%p, tex %p)\n", __func__, ctx, texObj); if (!radeon_validate_texture_miptree(ctx, texObj)) { radeon_error("%s(%p, tex %p) Failed to validate miptree for " "sw fallback.\n", __func__, ctx, texObj); return; } if (t->image_override && t->bo) { radeon_print(RADEON_TEXTURE, RADEON_VERBOSE, "%s(%p, tex %p) Work around for missing miptree in r100.\n", __func__, ctx, texObj); map_override(ctx, t); } /* for r100 3D sw fallbacks don't have mt */ if (!t->mt) { radeon_warning("%s(%p, tex %p) No miptree in texture.\n", __func__, ctx, texObj); return; } radeon_bo_map(t->mt->bo, GL_FALSE); for(face = 0; face < t->mt->faces; ++face) { for(level = t->minLod; level <= t->maxLod; ++level) teximage_set_map_data(get_radeon_texture_image(texObj->Image[face][level])); } }
static void radeonTexParameter( GLcontext *ctx, GLenum target, struct gl_texture_object *texObj, GLenum pname, const GLfloat *params ) { radeonTexObj* t = radeon_tex_obj(texObj); radeon_print(RADEON_TEXTURE, RADEON_VERBOSE, "%s( %s )\n", __FUNCTION__, _mesa_lookup_enum_by_nr( pname ) ); switch ( pname ) { case GL_TEXTURE_MIN_FILTER: case GL_TEXTURE_MAG_FILTER: case GL_TEXTURE_MAX_ANISOTROPY_EXT: radeonSetTexMaxAnisotropy( t, texObj->MaxAnisotropy ); radeonSetTexFilter( t, texObj->MinFilter, texObj->MagFilter ); break; case GL_TEXTURE_WRAP_S: case GL_TEXTURE_WRAP_T: radeonSetTexWrap( t, texObj->WrapS, texObj->WrapT ); break; case GL_TEXTURE_BORDER_COLOR: radeonSetTexBorderColor( t, texObj->BorderColor.f ); break; case GL_TEXTURE_BASE_LEVEL: case GL_TEXTURE_MAX_LEVEL: case GL_TEXTURE_MIN_LOD: case GL_TEXTURE_MAX_LOD: t->validated = GL_FALSE; break; default: return; } }
void radeonCopyTexSubImage2D(GLcontext *ctx, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height) { struct gl_texture_unit *texUnit = _mesa_get_current_tex_unit(ctx); struct gl_texture_object *texObj = _mesa_select_tex_object(ctx, texUnit, target); struct gl_texture_image *texImage = _mesa_select_tex_image(ctx, texObj, target, level); radeonContextPtr radeon = RADEON_CONTEXT(ctx); radeon_prepare_render(radeon); if (!do_copy_texsubimage(ctx, target, level, radeon_tex_obj(texObj), (radeon_texture_image *)texImage, xoffset, yoffset, x, y, width, height)) { radeon_print(RADEON_FALLBACKS, RADEON_NORMAL, "Falling back to sw for glCopyTexSubImage2D\n"); _mesa_meta_CopyTexSubImage2D(ctx, target, level, xoffset, yoffset, x, y, width, height); } }
/** * Validate texture mipmap tree. * If individual images are stored in different mipmap trees * use the mipmap tree that has the most of the correct data. */ int radeon_validate_texture_miptree(struct gl_context * ctx, struct gl_sampler_object *samp, struct gl_texture_object *texObj) { radeonContextPtr rmesa = RADEON_CONTEXT(ctx); radeonTexObj *t = radeon_tex_obj(texObj); radeon_mipmap_tree *dst_miptree; if (samp == &texObj->Sampler && (t->validated || t->image_override)) { return GL_TRUE; } calculate_min_max_lod(samp, &t->base, &t->minLod, &t->maxLod); radeon_print(RADEON_TEXTURE, RADEON_NORMAL, "%s: Validating texture %p now, minLod = %d, maxLod = %d\n", __func__, texObj ,t->minLod, t->maxLod); dst_miptree = get_biggest_matching_miptree(t, t->base.BaseLevel, t->base._MaxLevel); radeon_miptree_unreference(&t->mt); if (!dst_miptree) { radeon_try_alloc_miptree(rmesa, t); radeon_print(RADEON_TEXTURE, RADEON_NORMAL, "%s: No matching miptree found, allocated new one %p\n", __func__, t->mt); } else { radeon_miptree_reference(dst_miptree, &t->mt); radeon_print(RADEON_TEXTURE, RADEON_NORMAL, "%s: Using miptree %p\n", __func__, t->mt); } const unsigned faces = _mesa_num_tex_faces(texObj->Target); unsigned face, level; radeon_texture_image *img; /* Validate only the levels that will actually be used during rendering */ for (face = 0; face < faces; ++face) { for (level = t->minLod; level <= t->maxLod; ++level) { img = get_radeon_texture_image(texObj->Image[face][level]); radeon_print(RADEON_TEXTURE, RADEON_TRACE, "Checking image level %d, face %d, mt %p ... ", level, face, img->mt); if (img->mt != t->mt && !img->used_as_render_target) { radeon_print(RADEON_TEXTURE, RADEON_TRACE, "MIGRATING\n"); struct radeon_bo *src_bo = (img->mt) ? img->mt->bo : img->bo; if (src_bo && radeon_bo_is_referenced_by_cs(src_bo, rmesa->cmdbuf.cs)) { radeon_firevertices(rmesa); } migrate_image_to_miptree(t->mt, img, face, level); } else radeon_print(RADEON_TEXTURE, RADEON_TRACE, "OK\n"); } } t->validated = GL_TRUE; return GL_TRUE; }
void r300SetDepthTexMode(struct gl_texture_object *tObj) { static const GLuint formats[3][3] = { { R300_EASY_TX_FORMAT(X, X, X, ONE, X16), R300_EASY_TX_FORMAT(X, X, X, X, X16), R300_EASY_TX_FORMAT(ZERO, ZERO, ZERO, X, X16), }, { R300_EASY_TX_FORMAT(Y, Y, Y, ONE, X24_Y8), R300_EASY_TX_FORMAT(Y, Y, Y, Y, X24_Y8), R300_EASY_TX_FORMAT(ZERO, ZERO, ZERO, Y, X24_Y8), }, { R300_EASY_TX_FORMAT(X, X, X, ONE, X32), R300_EASY_TX_FORMAT(X, X, X, X, X32), R300_EASY_TX_FORMAT(ZERO, ZERO, ZERO, X, X32), }, }; const GLuint *format; radeonTexObjPtr t; if (!tObj) return; t = radeon_tex_obj(tObj); switch (tObj->Image[0][tObj->BaseLevel]->TexFormat) { case MESA_FORMAT_Z16: format = formats[0]; break; case MESA_FORMAT_S8_Z24: format = formats[1]; break; case MESA_FORMAT_Z32: format = formats[2]; break; default: /* Error...which should have already been caught by higher * levels of Mesa. */ ASSERT(0); return; } switch (tObj->DepthMode) { case GL_LUMINANCE: t->pp_txformat = format[0]; break; case GL_INTENSITY: t->pp_txformat = format[1]; break; case GL_ALPHA: t->pp_txformat = format[2]; break; default: /* Error...which should have already been caught by higher * levels of Mesa. */ ASSERT(0); return; } }
/** * All glTexImage calls go through this function. */ static void radeon_teximage( GLcontext *ctx, int dims, GLenum target, GLint level, GLint internalFormat, GLint width, GLint height, GLint depth, GLsizei imageSize, GLenum format, GLenum type, const GLvoid * pixels, const struct gl_pixelstore_attrib *packing, struct gl_texture_object *texObj, struct gl_texture_image *texImage, int compressed) { radeonContextPtr rmesa = RADEON_CONTEXT(ctx); radeonTexObj* t = radeon_tex_obj(texObj); radeon_texture_image* image = get_radeon_texture_image(texImage); GLint postConvWidth = width; GLint postConvHeight = height; GLuint face = _mesa_tex_target_to_face(target); radeon_print(RADEON_TEXTURE, RADEON_NORMAL, "%s %dd: texObj %p, texImage %p, face %d, level %d\n", __func__, dims, texObj, texImage, face, level); { struct radeon_bo *bo; bo = !image->mt ? image->bo : image->mt->bo; if (bo && radeon_bo_is_referenced_by_cs(bo, rmesa->cmdbuf.cs)) { radeon_print(RADEON_TEXTURE, RADEON_VERBOSE, "%s Calling teximage for texture that is " "queued for GPU processing.\n", __func__); radeon_firevertices(rmesa); } } t->validated = GL_FALSE; if (ctx->_ImageTransferState & IMAGE_CONVOLUTION_BIT) { _mesa_adjust_image_for_convolution(ctx, dims, &postConvWidth, &postConvHeight); } if (!_mesa_is_format_compressed(texImage->TexFormat)) { GLuint texelBytes = _mesa_get_format_bytes(texImage->TexFormat); /* Minimum pitch of 32 bytes */ if (postConvWidth * texelBytes < 32) { postConvWidth = 32 / texelBytes; texImage->RowStride = postConvWidth; } if (!image->mt) { assert(texImage->RowStride == postConvWidth); } } /* Mesa core only clears texImage->Data but not image->mt */ radeonFreeTexImageData(ctx, texImage); if (!t->bo) { teximage_assign_miptree(rmesa, texObj, texImage, face, level); if (!image->mt) { int size = _mesa_format_image_size(texImage->TexFormat, texImage->Width, texImage->Height, texImage->Depth); texImage->Data = _mesa_alloc_texmemory(size); radeon_print(RADEON_TEXTURE, RADEON_VERBOSE, "%s %dd: texObj %p, texImage %p, " " no miptree assigned, using local memory %p\n", __func__, dims, texObj, texImage, texImage->Data); } } /* Upload texture image; note that the spec allows pixels to be NULL */ if (compressed) { pixels = _mesa_validate_pbo_compressed_teximage( ctx, imageSize, pixels, packing, "glCompressedTexImage"); } else { pixels = _mesa_validate_pbo_teximage( ctx, dims, width, height, depth, format, type, pixels, packing, "glTexImage"); } if (pixels) { radeon_store_teximage(ctx, dims, 0, 0, 0, width, height, depth, imageSize, format, type, pixels, packing, texObj, texImage, compressed); } _mesa_unmap_teximage_pbo(ctx, packing); }
/** * Update a subregion of the given texture image. */ static void radeon_store_teximage(GLcontext* ctx, int dims, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, GLenum format, GLenum type, const GLvoid * pixels, const struct gl_pixelstore_attrib *packing, struct gl_texture_object *texObj, struct gl_texture_image *texImage, int compressed) { radeonContextPtr rmesa = RADEON_CONTEXT(ctx); radeonTexObj *t = radeon_tex_obj(texObj); radeon_texture_image* image = get_radeon_texture_image(texImage); GLuint dstRowStride; GLuint *dstImageOffsets; radeon_print(RADEON_TEXTURE, RADEON_TRACE, "%s(%p, tex %p, image %p) compressed %d\n", __func__, ctx, texObj, texImage, compressed); if (image->mt) { dstRowStride = image->mt->levels[image->mtlevel].rowstride; } else if (t->bo) { /* TFP case */ dstRowStride = get_texture_image_row_stride(rmesa, texImage->TexFormat, width, 0); } else { dstRowStride = _mesa_format_row_stride(texImage->TexFormat, texImage->Width); } assert(dstRowStride); if (dims == 3) { unsigned alignedWidth = dstRowStride/_mesa_get_format_bytes(texImage->TexFormat); dstImageOffsets = allocate_image_offsets(ctx, alignedWidth, texImage->Height, texImage->Depth); if (!dstImageOffsets) { radeon_warning("%s Failed to allocate dstImaeOffset.\n", __func__); return; } } else { dstImageOffsets = texImage->ImageOffsets; } radeon_teximage_map(image, GL_TRUE); if (compressed) { uint32_t srcRowStride, bytesPerRow, rows, block_width, block_height; GLubyte *img_start; _mesa_get_format_block_size(texImage->TexFormat, &block_width, &block_height); if (!image->mt) { dstRowStride = _mesa_format_row_stride(texImage->TexFormat, texImage->Width); img_start = _mesa_compressed_image_address(xoffset, yoffset, 0, texImage->TexFormat, texImage->Width, texImage->Data); } else { uint32_t offset; offset = dstRowStride / _mesa_get_format_bytes(texImage->TexFormat) * yoffset / block_height + xoffset / block_width; offset *= _mesa_get_format_bytes(texImage->TexFormat); img_start = texImage->Data + offset; } srcRowStride = _mesa_format_row_stride(texImage->TexFormat, width); bytesPerRow = srcRowStride; rows = (height + block_height - 1) / block_height; copy_rows(img_start, dstRowStride, pixels, srcRowStride, rows, bytesPerRow); } else { if (!_mesa_texstore(ctx, dims, texImage->_BaseFormat, texImage->TexFormat, texImage->Data, xoffset, yoffset, zoffset, dstRowStride, dstImageOffsets, width, height, depth, format, type, pixels, packing)) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage"); } } if (dims == 3) { free(dstImageOffsets); } radeon_teximage_unmap(image); }
void r300SetTexBuffer2(__DRIcontext *pDRICtx, GLint target, GLint glx_texture_format, __DRIdrawable *dPriv) { struct gl_texture_unit *texUnit; struct gl_texture_object *texObj; struct gl_texture_image *texImage; struct radeon_renderbuffer *rb; radeon_texture_image *rImage; radeonContextPtr radeon; r300ContextPtr rmesa; struct radeon_framebuffer *rfb; radeonTexObjPtr t; uint32_t pitch_val; uint32_t internalFormat, type, format; type = GL_BGRA; format = GL_UNSIGNED_BYTE; internalFormat = (glx_texture_format == GLX_TEXTURE_FORMAT_RGB_EXT ? 3 : 4); radeon = pDRICtx->driverPrivate; rmesa = pDRICtx->driverPrivate; rfb = dPriv->driverPrivate; texUnit = &radeon->glCtx->Texture.Unit[radeon->glCtx->Texture.CurrentUnit]; texObj = _mesa_select_tex_object(radeon->glCtx, texUnit, target); texImage = _mesa_get_tex_image(radeon->glCtx, texObj, target, 0); rImage = get_radeon_texture_image(texImage); t = radeon_tex_obj(texObj); if (t == NULL) { return; } radeon_update_renderbuffers(pDRICtx, dPriv); /* back & depth buffer are useless free them right away */ rb = (void*)rfb->base.Attachment[BUFFER_DEPTH].Renderbuffer; if (rb && rb->bo) { radeon_bo_unref(rb->bo); rb->bo = NULL; } rb = (void*)rfb->base.Attachment[BUFFER_BACK_LEFT].Renderbuffer; if (rb && rb->bo) { radeon_bo_unref(rb->bo); rb->bo = NULL; } rb = rfb->color_rb[0]; if (rb->bo == NULL) { /* Failed to BO for the buffer */ return; } _mesa_lock_texture(radeon->glCtx, texObj); if (t->bo) { radeon_bo_unref(t->bo); t->bo = NULL; } if (rImage->bo) { radeon_bo_unref(rImage->bo); rImage->bo = NULL; } radeon_miptree_unreference(&t->mt); radeon_miptree_unreference(&rImage->mt); _mesa_init_teximage_fields(radeon->glCtx, target, texImage, rb->base.Width, rb->base.Height, 1, 0, rb->cpp); texImage->RowStride = rb->pitch / rb->cpp; rImage->bo = rb->bo; radeon_bo_ref(rImage->bo); t->bo = rb->bo; radeon_bo_ref(t->bo); t->tile_bits = 0; t->image_override = GL_TRUE; t->override_offset = 0; t->pp_txpitch &= (1 << 13) -1; pitch_val = rb->pitch; switch (rb->cpp) { case 4: if (glx_texture_format == GLX_TEXTURE_FORMAT_RGB_EXT) t->pp_txformat = R300_EASY_TX_FORMAT(X, Y, Z, ONE, W8Z8Y8X8); else t->pp_txformat = R300_EASY_TX_FORMAT(X, Y, Z, W, W8Z8Y8X8); t->pp_txfilter |= tx_table[2].filter; pitch_val /= 4; break; case 3: default: t->pp_txformat = R300_EASY_TX_FORMAT(X, Y, Z, ONE, W8Z8Y8X8); t->pp_txfilter |= tx_table[4].filter; pitch_val /= 4; break; case 2: t->pp_txformat = R300_EASY_TX_FORMAT(X, Y, Z, ONE, Z5Y6X5); t->pp_txfilter |= tx_table[5].filter; pitch_val /= 2; break; } pitch_val--; t->pp_txsize = (((R300_TX_WIDTHMASK_MASK & ((rb->base.Width - 1) << R300_TX_WIDTHMASK_SHIFT))) | ((R300_TX_HEIGHTMASK_MASK & ((rb->base.Height - 1) << R300_TX_HEIGHTMASK_SHIFT)))); t->pp_txsize |= R300_TX_SIZE_TXPITCH_EN; t->pp_txpitch |= pitch_val; if (rmesa->radeon.radeonScreen->chip_family >= CHIP_FAMILY_RV515) { if (rb->base.Width > 2048) t->pp_txpitch |= R500_TXWIDTH_BIT11; else t->pp_txpitch &= ~R500_TXWIDTH_BIT11; if (rb->base.Height > 2048) t->pp_txpitch |= R500_TXHEIGHT_BIT11; else t->pp_txpitch &= ~R500_TXHEIGHT_BIT11; } t->validated = GL_TRUE; _mesa_unlock_texture(radeon->glCtx, texObj); return; }