#include "r300_context.h"
#include "r300_state.h"
#include "r300_ioctl.h"
-#include "radeon_ioctl.h"
-#include "r300_mipmap_tree.h"
+#include "radeon_mipmap_tree.h"
#include "r300_tex.h"
#include "r300_reg.h"
-#include "radeon_buffer.h"
#define VALID_FORMAT(f) ( ((f) <= MESA_FORMAT_RGBA_DXT5 \
|| ((f) >= MESA_FORMAT_RGBA_FLOAT32 && \
_ASSIGN(INTENSITY_FLOAT16, R300_EASY_TX_FORMAT(X, X, X, X, FL_I16)),
_ASSIGN(Z16, R300_EASY_TX_FORMAT(X, X, X, X, X16)),
_ASSIGN(Z24_S8, R300_EASY_TX_FORMAT(X, X, X, X, X24_Y8)),
+ _ASSIGN(S8_Z24, R300_EASY_TX_FORMAT(Y, Y, Y, Y, X24_Y8)),
_ASSIGN(Z32, R300_EASY_TX_FORMAT(X, X, X, X, X32)),
+ /* EXT_texture_sRGB */
+ _ASSIGN(SRGBA8, R300_EASY_TX_FORMAT(Y, Z, W, X, W8Z8Y8X8) | R300_TX_FORMAT_GAMMA),
+ _ASSIGN(SLA8, R300_EASY_TX_FORMAT(X, X, X, Y, Y8X8) | R300_TX_FORMAT_GAMMA),
+ _ASSIGN(SL8, R300_EASY_TX_FORMAT(X, X, X, ONE, X8) | R300_TX_FORMAT_GAMMA),
/* *INDENT-ON* */
};
},
};
const GLuint *format;
- r300TexObjPtr t;
+ radeonTexObjPtr t;
if (!tObj)
return;
- t = r300_tex_obj(tObj);
+ t = radeon_tex_obj(tObj);
switch (tObj->Image[0][tObj->BaseLevel]->TexFormat->MesaFormat) {
case MESA_FORMAT_Z16:
switch (tObj->DepthMode) {
case GL_LUMINANCE:
- t->format = format[0];
+ t->pp_txformat = format[0];
break;
case GL_INTENSITY:
- t->format = format[1];
+ t->pp_txformat = format[1];
break;
case GL_ALPHA:
- t->format = format[2];
+ t->pp_txformat = format[2];
break;
default:
/* Error...which should have already been caught by higher
* \param rmesa Context pointer
* \param t the r300 texture object
*/
-static void setup_hardware_state(r300ContextPtr rmesa, r300TexObj *t)
+static void setup_hardware_state(r300ContextPtr rmesa, radeonTexObj *t)
{
- const struct gl_texture_image *firstImage =
- t->base.Image[0][t->mt->firstLevel];
+ const struct gl_texture_image *firstImage;
+ int firstlevel = t->mt ? t->mt->firstLevel : 0;
+
+ firstImage = t->base.Image[0][firstlevel];
if (!t->image_override
&& VALID_FORMAT(firstImage->TexFormat->MesaFormat)) {
if (firstImage->TexFormat->BaseFormat == GL_DEPTH_COMPONENT) {
r300SetDepthTexMode(&t->base);
} else {
- t->format = tx_table[firstImage->TexFormat->MesaFormat].format;
+ t->pp_txformat = tx_table[firstImage->TexFormat->MesaFormat].format;
}
- t->filter |= tx_table[firstImage->TexFormat->MesaFormat].filter;
+ t->pp_txfilter |= tx_table[firstImage->TexFormat->MesaFormat].filter;
} else if (!t->image_override) {
_mesa_problem(NULL, "unexpected texture format in %s",
__FUNCTION__);
return;
}
+ if (t->image_override && t->bo)
+ return;
+
+ t->pp_txsize = (((firstImage->Width - 1) << R300_TX_WIDTHMASK_SHIFT)
+ | ((firstImage->Height - 1) << R300_TX_HEIGHTMASK_SHIFT)
+ | ((firstImage->DepthLog2) << R300_TX_DEPTHMASK_SHIFT)
+ | ((t->mt->lastLevel - t->mt->firstLevel) << R300_TX_MAX_MIP_LEVEL_SHIFT));
+
t->tile_bits = 0;
if (t->base.Target == GL_TEXTURE_CUBE_MAP)
- t->format |= R300_TX_FORMAT_CUBIC_MAP;
+ t->pp_txformat |= R300_TX_FORMAT_CUBIC_MAP;
if (t->base.Target == GL_TEXTURE_3D)
- t->format |= R300_TX_FORMAT_3D;
+ t->pp_txformat |= R300_TX_FORMAT_3D;
- t->size = (((firstImage->Width - 1) << R300_TX_WIDTHMASK_SHIFT)
- | ((firstImage->Height - 1) << R300_TX_HEIGHTMASK_SHIFT))
- | ((t->mt->lastLevel - t->mt->firstLevel) << R300_TX_MAX_MIP_LEVEL_SHIFT);
if (t->base.Target == GL_TEXTURE_RECTANGLE_NV) {
unsigned int align = (64 / t->mt->bpp) - 1;
- t->size |= R300_TX_SIZE_TXPITCH_EN;
+ t->pp_txsize |= R300_TX_SIZE_TXPITCH_EN;
if (!t->image_override)
- t->pitch_reg = ((firstImage->Width + align) & ~align) - 1;
+ t->pp_txpitch = ((firstImage->Width + align) & ~align) - 1;
}
if (rmesa->radeon.radeonScreen->chip_family >= CHIP_FAMILY_RV515) {
if (firstImage->Width > 2048)
- t->pitch_reg |= R500_TXWIDTH_BIT11;
+ t->pp_txpitch |= R500_TXWIDTH_BIT11;
if (firstImage->Height > 2048)
- t->pitch_reg |= R500_TXHEIGHT_BIT11;
- }
-}
-
-
-static void copy_rows(void* dst, GLuint dststride, const void* src, GLuint srcstride,
- GLuint numrows, GLuint rowsize)
-{
- assert(rowsize <= dststride);
- assert(rowsize <= srcstride);
-
- if (rowsize == srcstride && rowsize == dststride) {
- memcpy(dst, src, numrows*rowsize);
- } else {
- GLuint i;
- for(i = 0; i < numrows; ++i) {
- memcpy(dst, src, rowsize);
- dst += dststride;
- src += srcstride;
- }
- }
-}
-
-
-/**
- * Ensure that the given image is stored in the given miptree from now on.
- */
-static void migrate_image_to_miptree(r300_mipmap_tree *mt, r300_texture_image *image, int face, int level)
-{
- r300_mipmap_level *dstlvl = &mt->levels[level - mt->firstLevel];
- unsigned char *dest;
-
- assert(image->mt != mt);
- assert(dstlvl->width == image->base.Width);
- assert(dstlvl->height == image->base.Height);
- assert(dstlvl->depth == image->base.Depth);
-
- radeon_bo_map(mt->bo, GL_TRUE);
- dest = mt->bo->ptr + dstlvl->faces[face].offset;
-
- if (image->mt) {
- /* Format etc. should match, so we really just need a memcpy().
- * In fact, that memcpy() could be done by the hardware in many
- * cases, provided that we have a proper memory manager.
- */
- r300_mipmap_level *srclvl = &image->mt->levels[image->mtlevel];
-
- assert(srclvl->size == dstlvl->size);
- assert(srclvl->rowstride == dstlvl->rowstride);
-
- radeon_bo_map(image->mt->bo, GL_FALSE);
- memcpy(dest,
- image->mt->bo->ptr + srclvl->faces[face].offset,
- dstlvl->size);
- radeon_bo_unmap(image->mt->bo);
-
- r300_miptree_unreference(image->mt);
- } else {
- uint srcrowstride = image->base.Width * image->base.TexFormat->TexelBytes;
-
- if (mt->tilebits)
- WARN_ONCE("%s: tiling not supported yet", __FUNCTION__);
-
- copy_rows(dest, dstlvl->rowstride, image->base.Data, srcrowstride,
- image->base.Height * image->base.Depth, srcrowstride);
-
- _mesa_free_texmemory(image->base.Data);
- image->base.Data = 0;
+ t->pp_txpitch |= R500_TXHEIGHT_BIT11;
}
-
- radeon_bo_unmap(mt->bo);
-
- image->mt = mt;
- image->mtface = face;
- image->mtlevel = level;
- r300_miptree_reference(image->mt);
}
-
/**
* Ensure the given texture is ready for rendering.
*
static GLboolean r300_validate_texture(GLcontext * ctx, struct gl_texture_object *texObj)
{
r300ContextPtr rmesa = R300_CONTEXT(ctx);
- r300TexObj *t = r300_tex_obj(texObj);
- r300_texture_image *baseimage = get_r300_texture_image(texObj->Image[0][texObj->BaseLevel]);
- int face, level;
-
- if (t->validated || t->image_override)
- return GL_TRUE;
+ radeonTexObj *t = radeon_tex_obj(texObj);
- if (RADEON_DEBUG & DEBUG_TEXTURE)
- fprintf(stderr, "%s: Validating texture %p now\n", __FUNCTION__, texObj);
-
- if (baseimage->base.Border > 0)
+ if (!radeon_validate_texture_miptree(ctx, texObj))
return GL_FALSE;
- /* Ensure a matching miptree exists.
- *
- * Differing mipmap trees can result when the app uses TexImage to
- * change texture dimensions.
- *
- * Prefer to use base image's miptree if it
- * exists, since that most likely contains more valid data (remember
- * that the base level is usually significantly larger than the rest
- * of the miptree, so cubemaps are the only possible exception).
- */
- if (baseimage->mt &&
- baseimage->mt != t->mt &&
- r300_miptree_matches_texture(baseimage->mt, &t->base)) {
- r300_miptree_unreference(t->mt);
- t->mt = baseimage->mt;
- r300_miptree_reference(t->mt);
- } else if (t->mt && !r300_miptree_matches_texture(t->mt, &t->base)) {
- r300_miptree_unreference(t->mt);
- t->mt = 0;
- }
-
- if (!t->mt) {
- if (RADEON_DEBUG & DEBUG_TEXTURE)
- fprintf(stderr, " Allocate new miptree\n");
- r300_try_alloc_miptree(rmesa, t, &baseimage->base, 0, texObj->BaseLevel);
- if (!t->mt) {
- _mesa_problem(ctx, "r300_validate_texture failed to alloc miptree");
- return GL_FALSE;
- }
- }
-
- /* Ensure all images are stored in the single main miptree */
- for(face = 0; face < t->mt->faces; ++face) {
- for(level = t->mt->firstLevel; level <= t->mt->lastLevel; ++level) {
- r300_texture_image *image = get_r300_texture_image(texObj->Image[face][level]);
- if (RADEON_DEBUG & DEBUG_TEXTURE)
- fprintf(stderr, " face %i, level %i... ", face, level);
- if (t->mt == image->mt) {
- if (RADEON_DEBUG & DEBUG_TEXTURE)
- fprintf(stderr, "OK\n");
- continue;
- }
-
- if (RADEON_DEBUG & DEBUG_TEXTURE)
- fprintf(stderr, "migrating\n");
- migrate_image_to_miptree(t->mt, image, face, level);
- }
- }
-
/* Configure the hardware registers (more precisely, the cached version
* of the hardware registers). */
setup_hardware_state(rmesa, t);
return GL_TRUE;
}
-
/**
- * Ensure all enabled and complete textures are uploaded.
+ * Ensure all enabled and complete textures are uploaded along with any buffers being used.
*/
-void r300ValidateTextures(GLcontext * ctx)
+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;
"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, rmesa->radeon.dma.current, RADEON_GEM_DOMAIN_GTT, 0);
+ if (ret)
+ return GL_FALSE;
+ return GL_TRUE;
}
void r300SetTexOffset(__DRIcontext * pDRICtx, GLint texname,
r300ContextPtr rmesa = pDRICtx->driverPrivate;
struct gl_texture_object *tObj =
_mesa_lookup_texture(rmesa->radeon.glCtx, texname);
- r300TexObjPtr t = r300_tex_obj(tObj);
+ radeonTexObjPtr t = radeon_tex_obj(tObj);
uint32_t pitch_val;
if (!tObj)
if (!offset)
return;
- t->bo = NULL;
+
+ t->bo = NULL;
t->override_offset = offset;
- t->pitch_reg &= (1 << 13) -1;
+ t->pp_txpitch &= (1 << 13) -1;
pitch_val = pitch;
switch (depth) {
case 32:
- t->format = R300_EASY_TX_FORMAT(X, Y, Z, W, W8Z8Y8X8);
- t->filter |= tx_table[2].filter;
+ 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->format = R300_EASY_TX_FORMAT(X, Y, Z, ONE, W8Z8Y8X8);
- t->filter |= tx_table[4].filter;
+ 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->format = R300_EASY_TX_FORMAT(X, Y, Z, ONE, Z5Y6X5);
- t->filter |= tx_table[5].filter;
+ 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->pitch_reg |= pitch_val;
+ t->pp_txpitch |= pitch_val;
}
-void r300SetTexBuffer(__DRIcontext *pDRICtx, GLint target, __DRIdrawable *dPriv)
+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 gl_texture_image *texImage;
struct radeon_renderbuffer *rb;
- r300_texture_image *rImage;
+ radeon_texture_image *rImage;
radeonContextPtr radeon;
r300ContextPtr rmesa;
- GLframebuffer *fb;
- r300TexObjPtr t;
+ struct radeon_framebuffer *rfb;
+ radeonTexObjPtr t;
uint32_t pitch_val;
+ uint32_t internalFormat, type, format;
- target = GL_TEXTURE_RECTANGLE_ARB;
+ type = GL_BGRA;
+ format = GL_UNSIGNED_BYTE;
+ internalFormat = (glx_texture_format == GLX_TEXTURE_FORMAT_RGB_EXT ? 3 : 4);
radeon = pDRICtx->driverPrivate;
rmesa = pDRICtx->driverPrivate;
- fb = dPriv->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_r300_texture_image(texImage);
- t = r300_tex_obj(texObj);
+ 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*)fb->Attachment[BUFFER_DEPTH].Renderbuffer;
- if (rb && rb->bo) {
- radeon_bo_unref(rb->bo);
+ 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*)fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer;
- if (rb && rb->bo) {
- radeon_bo_unref(rb->bo);
- rb->bo = NULL;
- }
- rb = (void*)fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer;
- if (rb->bo == NULL) {
- /* Failed to BO for the buffer */
- return;
- }
-
- _mesa_lock_texture(radeon->glCtx, texObj);
- if (t->bo) {
- t->bo = NULL;
- }
- if (t->mt) {
- t->mt = NULL;
- }
- if (rImage->mt) {
- r300_miptree_unreference(rImage->mt);
- rImage->mt = NULL;
- }
- fprintf(stderr,"settexbuf %dx%d@%d\n", rb->width, rb->height, rb->cpp);
- _mesa_init_teximage_fields(radeon->glCtx, target, texImage,
- rb->width, rb->height, 1, 0, rb->cpp);
- texImage->TexFormat = &_mesa_texformat_rgba8888_rev;
- rImage->bo = rb->bo;
-
- t->bo = rb->bo;
- t->tile_bits = 0;
+ }
+ 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;
+ }
+ if (t->mt) {
+ radeon_miptree_unreference(t->mt);
+ t->mt = NULL;
+ }
+ if (rImage->mt) {
+ radeon_miptree_unreference(rImage->mt);
+ rImage->mt = NULL;
+ }
+ _mesa_init_teximage_fields(radeon->glCtx, target, texImage,
+ rb->base.Width, rb->base.Height, 1, 0, rb->cpp);
+ texImage->RowStride = rb->pitch / rb->cpp;
+ texImage->TexFormat = radeonChooseTextureFormat(radeon->glCtx,
+ internalFormat,
+ type, format, 0);
+ 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->pitch_reg &= (1 << 13) -1;
+ t->pp_txpitch &= (1 << 13) -1;
pitch_val = rb->pitch;
switch (rb->cpp) {
case 4:
- t->format = R300_EASY_TX_FORMAT(X, Y, Z, W, W8Z8Y8X8);
- t->filter |= tx_table[2].filter;
+ 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->format = R300_EASY_TX_FORMAT(X, Y, Z, ONE, W8Z8Y8X8);
- t->filter |= tx_table[4].filter;
+ 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->format = R300_EASY_TX_FORMAT(X, Y, Z, ONE, Z5Y6X5);
- t->filter |= tx_table[5].filter;
+ 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->size = ((rb->width - 1) << R300_TX_WIDTHMASK_SHIFT) |
- ((rb->height - 1) << R300_TX_HEIGHTMASK_SHIFT);
- t->size |= R300_TX_SIZE_TXPITCH_EN;
- t->pitch_reg |= pitch_val;
+ t->pp_txsize = ((rb->base.Width - 1) << R300_TX_WIDTHMASK_SHIFT) |
+ ((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;
+ if (rb->base.Height > 2048)
+ t->pp_txpitch |= R500_TXHEIGHT_BIT11;
+ }
t->validated = GL_TRUE;
- _mesa_unlock_texture(radeon->glCtx, texObj);
- return;
+ _mesa_unlock_texture(radeon->glCtx, texObj);
+ return;
+}
+
+void r300SetTexBuffer(__DRIcontext *pDRICtx, GLint target, __DRIdrawable *dPriv)
+{
+ r300SetTexBuffer2(pDRICtx, target, GLX_TEXTURE_FORMAT_RGBA_EXT, dPriv);
}