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; }
/* Translate a pipe_format into a useful texture format for sampling. * * Some special formats are translated directly using R300_EASY_TX_FORMAT, * but the majority of them is translated in a generic way, automatically * supporting all the formats hw can support. * * R300_EASY_TX_FORMAT swizzles the texture. * Note the signature of R300_EASY_TX_FORMAT: * R300_EASY_TX_FORMAT(B, G, R, A, FORMAT); * * The FORMAT specifies how the texture sampler will treat the texture, and * makes available X, Y, Z, W, ZERO, and ONE for swizzling. */ uint32_t r300_translate_texformat(enum pipe_format format, const unsigned char *swizzle_view, boolean is_r500, boolean dxtc_swizzle) { uint32_t result = 0; const struct util_format_description *desc; unsigned i; boolean uniform = TRUE; const uint32_t sign_bit[4] = { R300_TX_FORMAT_SIGNED_X, R300_TX_FORMAT_SIGNED_Y, R300_TX_FORMAT_SIGNED_Z, R300_TX_FORMAT_SIGNED_W, }; desc = util_format_description(format); /* Colorspace (return non-RGB formats directly). */ switch (desc->colorspace) { /* Depth stencil formats. * Swizzles are added in r300_merge_textures_and_samplers. */ case UTIL_FORMAT_COLORSPACE_ZS: switch (format) { case PIPE_FORMAT_Z16_UNORM: return R300_TX_FORMAT_X16; case PIPE_FORMAT_X8Z24_UNORM: case PIPE_FORMAT_S8_USCALED_Z24_UNORM: if (is_r500) return R500_TX_FORMAT_Y8X24; else return R300_TX_FORMAT_Y16X16; default: return ~0; /* Unsupported. */ } /* YUV formats. */ case UTIL_FORMAT_COLORSPACE_YUV: result |= R300_TX_FORMAT_YUV_TO_RGB; switch (format) { case PIPE_FORMAT_UYVY: return R300_EASY_TX_FORMAT(X, Y, Z, ONE, YVYU422) | result; case PIPE_FORMAT_YUYV: return R300_EASY_TX_FORMAT(X, Y, Z, ONE, VYUY422) | result; default: return ~0; /* Unsupported/unknown. */ } /* Add gamma correction. */ case UTIL_FORMAT_COLORSPACE_SRGB: result |= R300_TX_FORMAT_GAMMA; break; default: switch (format) { /* Same as YUV but without the YUR->RGB conversion. */ case PIPE_FORMAT_R8G8_B8G8_UNORM: return R300_EASY_TX_FORMAT(X, Y, Z, ONE, YVYU422) | result; case PIPE_FORMAT_G8R8_G8B8_UNORM: return R300_EASY_TX_FORMAT(X, Y, Z, ONE, VYUY422) | result; default:; } } result |= r300_get_swizzle_combined(desc->swizzle, swizzle_view, util_format_is_compressed(format) && dxtc_swizzle); /* S3TC formats. */ if (desc->layout == UTIL_FORMAT_LAYOUT_S3TC) { if (!util_format_s3tc_enabled) { return ~0; /* Unsupported. */ } switch (format) { case PIPE_FORMAT_DXT1_RGB: case PIPE_FORMAT_DXT1_RGBA: case PIPE_FORMAT_DXT1_SRGB: case PIPE_FORMAT_DXT1_SRGBA: return R300_TX_FORMAT_DXT1 | result; case PIPE_FORMAT_DXT3_RGBA: case PIPE_FORMAT_DXT3_SRGBA: return R300_TX_FORMAT_DXT3 | result; case PIPE_FORMAT_DXT5_RGBA: case PIPE_FORMAT_DXT5_SRGBA: return R300_TX_FORMAT_DXT5 | result; default: return ~0; /* Unsupported/unknown. */ } } /* Add sign. */ for (i = 0; i < desc->nr_channels; i++) { if (desc->channel[i].type == UTIL_FORMAT_TYPE_SIGNED) { result |= sign_bit[i]; } } /* This is truly a special format. * It stores R8G8 and B is computed using sqrt(1 - R^2 - G^2) * in the sampler unit. Also known as D3DFMT_CxV8U8. */ if (format == PIPE_FORMAT_R8G8Bx_SNORM) { return R300_TX_FORMAT_CxV8U8 | result; } /* RGTC formats. */ if (desc->layout == UTIL_FORMAT_LAYOUT_RGTC) { switch (format) { case PIPE_FORMAT_RGTC1_UNORM: case PIPE_FORMAT_RGTC1_SNORM: return R500_TX_FORMAT_ATI1N | result; case PIPE_FORMAT_RGTC2_UNORM: case PIPE_FORMAT_RGTC2_SNORM: return R400_TX_FORMAT_ATI2N | result; default: return ~0; /* Unsupported/unknown. */ } } /* See whether the components are of the same size. */ for (i = 1; i < desc->nr_channels; i++) { uniform = uniform && desc->channel[0].size == desc->channel[i].size; } /* Non-uniform formats. */ if (!uniform) { switch (desc->nr_channels) { case 3: if (desc->channel[0].size == 5 && desc->channel[1].size == 6 && desc->channel[2].size == 5) { return R300_TX_FORMAT_Z5Y6X5 | result; } if (desc->channel[0].size == 5 && desc->channel[1].size == 5 && desc->channel[2].size == 6) { return R300_TX_FORMAT_Z6Y5X5 | result; } return ~0; /* Unsupported/unknown. */ case 4: if (desc->channel[0].size == 5 && desc->channel[1].size == 5 && desc->channel[2].size == 5 && desc->channel[3].size == 1) { return R300_TX_FORMAT_W1Z5Y5X5 | result; } if (desc->channel[0].size == 10 && desc->channel[1].size == 10 && desc->channel[2].size == 10 && desc->channel[3].size == 2) { return R300_TX_FORMAT_W2Z10Y10X10 | result; } } return ~0; /* Unsupported/unknown. */ } /* And finally, uniform formats. */ switch (desc->channel[0].type) { case UTIL_FORMAT_TYPE_UNSIGNED: case UTIL_FORMAT_TYPE_SIGNED: if (!desc->channel[0].normalized && desc->colorspace != UTIL_FORMAT_COLORSPACE_SRGB) { return ~0; } switch (desc->channel[0].size) { case 4: switch (desc->nr_channels) { case 2: return R300_TX_FORMAT_Y4X4 | result; case 4: return R300_TX_FORMAT_W4Z4Y4X4 | result; } return ~0; case 8: switch (desc->nr_channels) { case 1: return R300_TX_FORMAT_X8 | result; case 2: return R300_TX_FORMAT_Y8X8 | result; case 4: return R300_TX_FORMAT_W8Z8Y8X8 | result; } return ~0; case 16: switch (desc->nr_channels) { case 1: return R300_TX_FORMAT_X16 | result; case 2: return R300_TX_FORMAT_Y16X16 | result; case 4: return R300_TX_FORMAT_W16Z16Y16X16 | result; } } return ~0; case UTIL_FORMAT_TYPE_FLOAT: switch (desc->channel[0].size) { case 16: switch (desc->nr_channels) { case 1: return R300_TX_FORMAT_16F | result; case 2: return R300_TX_FORMAT_16F_16F | result; case 4: return R300_TX_FORMAT_16F_16F_16F_16F | result; } return ~0; case 32: switch (desc->nr_channels) { case 1: return R300_TX_FORMAT_32F | result; case 2: return R300_TX_FORMAT_32F_32F | result; case 4: return R300_TX_FORMAT_32F_32F_32F_32F | result; } } } return ~0; /* Unsupported/unknown. */ }
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; }
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; } }
/* * Note that the _REV formats are the same as the non-REV formats. This is * because the REV and non-REV formats are identical as a byte string, but * differ when accessed as 16-bit or 32-bit words depending on the endianness of * the host. Since the textures are transferred to the R300 as a byte string * (i.e. without any byte-swapping), the R300 sees the REV and non-REV formats * identically. -- paulus */ static const struct tx_table { GLuint format, filter, flag; } tx_table[] = { /* *INDENT-OFF* */ #ifdef MESA_LITTLE_ENDIAN _ASSIGN(RGBA8888, R300_EASY_TX_FORMAT(Y, Z, W, X, W8Z8Y8X8)), _ASSIGN(RGBA8888_REV, R300_EASY_TX_FORMAT(Z, Y, X, W, W8Z8Y8X8)), _ASSIGN(ARGB8888, R300_EASY_TX_FORMAT(X, Y, Z, W, W8Z8Y8X8)), _ASSIGN(ARGB8888_REV, R300_EASY_TX_FORMAT(W, Z, Y, X, W8Z8Y8X8)), #else _ASSIGN(RGBA8888, R300_EASY_TX_FORMAT(Z, Y, X, W, W8Z8Y8X8)), _ASSIGN(RGBA8888_REV, R300_EASY_TX_FORMAT(Y, Z, W, X, W8Z8Y8X8)), _ASSIGN(ARGB8888, R300_EASY_TX_FORMAT(W, Z, Y, X, W8Z8Y8X8)), _ASSIGN(ARGB8888_REV, R300_EASY_TX_FORMAT(X, Y, Z, W, W8Z8Y8X8)), #endif _ASSIGN(XRGB8888, R300_EASY_TX_FORMAT(X, Y, Z, ONE, W8Z8Y8X8)), _ASSIGN(RGB888, R300_EASY_TX_FORMAT(X, Y, Z, ONE, W8Z8Y8X8)), _ASSIGN(RGB565, R300_EASY_TX_FORMAT(X, Y, Z, ONE, Z5Y6X5)), _ASSIGN(RGB565_REV, R300_EASY_TX_FORMAT(X, Y, Z, ONE, Z5Y6X5)), _ASSIGN(ARGB4444, R300_EASY_TX_FORMAT(X, Y, Z, W, W4Z4Y4X4)), _ASSIGN(ARGB4444_REV, R300_EASY_TX_FORMAT(X, Y, Z, W, W4Z4Y4X4)),
/* Translate a pipe_format into a useful texture format for sampling. * * Some special formats are translated directly using R300_EASY_TX_FORMAT, * but the majority of them is translated in a generic way, automatically * supporting all the formats hw can support. * * R300_EASY_TX_FORMAT swizzles the texture. * Note the signature of R300_EASY_TX_FORMAT: * R300_EASY_TX_FORMAT(B, G, R, A, FORMAT); * * The FORMAT specifies how the texture sampler will treat the texture, and * makes available X, Y, Z, W, ZERO, and ONE for swizzling. */ static uint32_t r300_translate_texformat(enum pipe_format format) { uint32_t result = 0; const struct util_format_description *desc; unsigned components = 0, i; boolean uniform = TRUE; const uint32_t swizzle_shift[4] = { R300_TX_FORMAT_R_SHIFT, R300_TX_FORMAT_G_SHIFT, R300_TX_FORMAT_B_SHIFT, R300_TX_FORMAT_A_SHIFT }; const uint32_t swizzle[4] = { R300_TX_FORMAT_X, R300_TX_FORMAT_Y, R300_TX_FORMAT_Z, R300_TX_FORMAT_W }; const uint32_t sign_bit[4] = { R300_TX_FORMAT_SIGNED_X, R300_TX_FORMAT_SIGNED_Y, R300_TX_FORMAT_SIGNED_Z, R300_TX_FORMAT_SIGNED_W, }; desc = util_format_description(format); /* Colorspace (return non-RGB formats directly). */ switch (desc->colorspace) { /* Depth stencil formats. */ case UTIL_FORMAT_COLORSPACE_ZS: switch (format) { case PIPE_FORMAT_Z16_UNORM: return R300_EASY_TX_FORMAT(X, X, X, X, X16); case PIPE_FORMAT_X8Z24_UNORM: case PIPE_FORMAT_S8Z24_UNORM: return R300_EASY_TX_FORMAT(X, X, X, X, W24_FP); default: return ~0; /* Unsupported. */ } /* YUV formats. */ case UTIL_FORMAT_COLORSPACE_YUV: result |= R300_TX_FORMAT_YUV_TO_RGB; switch (format) { case PIPE_FORMAT_UYVY: return R300_EASY_TX_FORMAT(X, Y, Z, ONE, YVYU422) | result; case PIPE_FORMAT_YUYV: return R300_EASY_TX_FORMAT(X, Y, Z, ONE, VYUY422) | result; default: return ~0; /* Unsupported/unknown. */ } /* Add gamma correction. */ case UTIL_FORMAT_COLORSPACE_SRGB: result |= R300_TX_FORMAT_GAMMA; break; default: ; } /* Add swizzle. */ for (i = 0; i < 4; i++) { switch (desc->swizzle[i]) { case UTIL_FORMAT_SWIZZLE_X: case UTIL_FORMAT_SWIZZLE_NONE: result |= swizzle[0] << swizzle_shift[i]; break; case UTIL_FORMAT_SWIZZLE_Y: result |= swizzle[1] << swizzle_shift[i]; break; case UTIL_FORMAT_SWIZZLE_Z: result |= swizzle[2] << swizzle_shift[i]; break; case UTIL_FORMAT_SWIZZLE_W: result |= swizzle[3] << swizzle_shift[i]; break; case UTIL_FORMAT_SWIZZLE_0: result |= R300_TX_FORMAT_ZERO << swizzle_shift[i]; break; case UTIL_FORMAT_SWIZZLE_1: result |= R300_TX_FORMAT_ONE << swizzle_shift[i]; break; default: return ~0; /* Unsupported. */ } } /* Compressed formats. */ if (desc->layout == UTIL_FORMAT_LAYOUT_COMPRESSED) { switch (format) { case PIPE_FORMAT_DXT1_RGB: case PIPE_FORMAT_DXT1_RGBA: case PIPE_FORMAT_DXT1_SRGB: case PIPE_FORMAT_DXT1_SRGBA: return R300_TX_FORMAT_DXT1 | result; case PIPE_FORMAT_DXT3_RGBA: case PIPE_FORMAT_DXT3_SRGBA: return R300_TX_FORMAT_DXT3 | result; case PIPE_FORMAT_DXT5_RGBA: case PIPE_FORMAT_DXT5_SRGBA: return R300_TX_FORMAT_DXT5 | result; default: return ~0; /* Unsupported/unknown. */ } } /* Get the number of components. */ for (i = 0; i < 4; i++) { if (desc->channel[i].type != UTIL_FORMAT_TYPE_VOID) { ++components; } } /* Add sign. */ for (i = 0; i < components; i++) { if (desc->channel[i].type == UTIL_FORMAT_TYPE_SIGNED) { result |= sign_bit[i]; } } /* See whether the components are of the same size. */ for (i = 1; i < components; i++) { uniform = uniform && desc->channel[0].size == desc->channel[i].size; } /* Non-uniform formats. */ if (!uniform) { switch (components) { case 3: if (desc->channel[0].size == 5 && desc->channel[1].size == 6 && desc->channel[2].size == 5) { return R300_TX_FORMAT_Z5Y6X5 | result; } if (desc->channel[0].size == 5 && desc->channel[1].size == 5 && desc->channel[2].size == 6) { return R300_TX_FORMAT_Z6Y5X5 | result; } return ~0; /* Unsupported/unknown. */ case 4: if (desc->channel[0].size == 5 && desc->channel[1].size == 5 && desc->channel[2].size == 5 && desc->channel[3].size == 1) { return R300_TX_FORMAT_W1Z5Y5X5 | result; } if (desc->channel[0].size == 10 && desc->channel[1].size == 10 && desc->channel[2].size == 10 && desc->channel[3].size == 2) { return R300_TX_FORMAT_W2Z10Y10X10 | result; } } return ~0; /* Unsupported/unknown. */ } /* And finally, uniform formats. */ switch (desc->channel[0].type) { case UTIL_FORMAT_TYPE_UNSIGNED: case UTIL_FORMAT_TYPE_SIGNED: if (!desc->channel[0].normalized && desc->colorspace != UTIL_FORMAT_COLORSPACE_SRGB) { return ~0; } switch (desc->channel[0].size) { case 4: switch (components) { case 2: return R300_TX_FORMAT_Y4X4 | result; case 4: return R300_TX_FORMAT_W4Z4Y4X4 | result; } return ~0; case 8: switch (components) { case 1: return R300_TX_FORMAT_X8 | result; case 2: return R300_TX_FORMAT_Y8X8 | result; case 4: return R300_TX_FORMAT_W8Z8Y8X8 | result; } return ~0; case 16: switch (components) { case 1: return R300_TX_FORMAT_X16 | result; case 2: return R300_TX_FORMAT_Y16X16 | result; case 4: return R300_TX_FORMAT_W16Z16Y16X16 | result; } } return ~0; /* XXX Enable float textures here. */ #if 0 case UTIL_FORMAT_TYPE_FLOAT: switch (desc->channel[0].size) { case 16: switch (components) { case 1: return R300_TX_FORMAT_16F | result; case 2: return R300_TX_FORMAT_16F_16F | result; case 4: return R300_TX_FORMAT_16F_16F_16F_16F | result; } return ~0; case 32: switch (components) { case 1: return R300_TX_FORMAT_32F | result; case 2: return R300_TX_FORMAT_32F_32F | result; case 4: return R300_TX_FORMAT_32F_32F_32F_32F | result; } } #endif } return ~0; /* Unsupported/unknown. */ }