summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2011-11-11 16:13:06 +0000
committerDave Airlie <airlied@redhat.com>2011-12-05 14:36:19 +0000
commitb2596c36c8f73e8bb7a0b1679b491662aeb2f9d9 (patch)
tree0eff8746b4334dbc6e780e7426031a910335a781
parentfd7fcfcc2dffb73ac3159a04ccd164b527c11a8f (diff)
radeon: texture/renderbuffer overhaul.
This could have been split up better, but the driver is just broken now, so bisecting the brokenness is going to be painful no matter what. This adds renderbuffer mapping/unmapping along with texture image allocation. It drops all the old texture upload paths, some of which could possible be reimplemented with the blitter later. It also redoes the span code paths to use its own set of image mapping handlers, along with removing the tiling decode paths for the color buffers, since we now hope to use the blitter for this. Signed-off-by: Dave Airlie <airlied@redhat.com>
-rw-r--r--src/mesa/drivers/dri/r200/r200_blit.c16
-rw-r--r--src/mesa/drivers/dri/r200/r200_blit.h2
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_blit.c16
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_blit.h2
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_common_context.h4
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_fbo.c132
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_mipmap_tree.c30
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_mipmap_tree.h7
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_pixel_read.c2
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_span.c165
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_tex_copy.c2
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_texture.c600
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_texture.h6
13 files changed, 385 insertions, 599 deletions
diff --git a/src/mesa/drivers/dri/r200/r200_blit.c b/src/mesa/drivers/dri/r200/r200_blit.c
index 487bb5b78e1..04ab6d07def 100644
--- a/src/mesa/drivers/dri/r200/r200_blit.c
+++ b/src/mesa/drivers/dri/r200/r200_blit.c
@@ -35,13 +35,13 @@ static inline uint32_t cmdpacket0(struct radeon_screen *rscrn,
if (count)
return CP_PACKET0(reg, count - 1);
return CP_PACKET2;
}
/* common formats supported as both textures and render targets */
-unsigned r200_check_blit(gl_format mesa_format)
+unsigned r200_check_blit(gl_format mesa_format, uint32_t dst_pitch)
{
/* XXX others? BE/LE? */
switch (mesa_format) {
case MESA_FORMAT_ARGB8888:
case MESA_FORMAT_XRGB8888:
case MESA_FORMAT_RGB565:
@@ -55,12 +55,18 @@ unsigned r200_check_blit(gl_format mesa_format)
case MESA_FORMAT_RGBA8888_REV:
break;
default:
return 0;
}
+ /* Rendering to small buffer doesn't work.
+ * Looks like a hw limitation.
+ */
+ if (dst_pitch < 32)
+ return 0;
+
/* ??? */
if (_mesa_get_format_bits(mesa_format, GL_DEPTH_BITS) > 0)
return 0;
return 1;
}
@@ -464,25 +470,19 @@ unsigned r200_blit(struct gl_context *ctx,
unsigned reg_width,
unsigned reg_height,
unsigned flip_y)
{
struct r200_context *r200 = R200_CONTEXT(ctx);
- if (!r200_check_blit(dst_mesaformat))
+ if (!r200_check_blit(dst_mesaformat, dst_pitch))
return GL_FALSE;
/* Make sure that colorbuffer has even width - hw limitation */
if (dst_pitch % 2 > 0)
++dst_pitch;
- /* Rendering to small buffer doesn't work.
- * Looks like a hw limitation.
- */
- if (dst_pitch < 32)
- return GL_FALSE;
-
/* Need to clamp the region size to make sure
* we don't read outside of the source buffer
* or write outside of the destination buffer.
*/
if (reg_width + src_x_offset > src_width)
reg_width = src_width - src_x_offset;
diff --git a/src/mesa/drivers/dri/r200/r200_blit.h b/src/mesa/drivers/dri/r200/r200_blit.h
index 56018b9c0ea..fb5dacbe870 100644
--- a/src/mesa/drivers/dri/r200/r200_blit.h
+++ b/src/mesa/drivers/dri/r200/r200_blit.h
@@ -27,13 +27,13 @@
#ifndef R200_BLIT_H
#define R200_BLIT_H
void r200_blit_init(struct r200_context *r200);
-unsigned r200_check_blit(gl_format mesa_format);
+unsigned r200_check_blit(gl_format mesa_format, uint32_t dst_pitch);
unsigned r200_blit(struct gl_context *ctx,
struct radeon_bo *src_bo,
intptr_t src_offset,
gl_format src_mesaformat,
unsigned src_pitch,
diff --git a/src/mesa/drivers/dri/radeon/radeon_blit.c b/src/mesa/drivers/dri/radeon/radeon_blit.c
index 330e1abdfe5..b84f2fa9f2b 100644
--- a/src/mesa/drivers/dri/radeon/radeon_blit.c
+++ b/src/mesa/drivers/dri/radeon/radeon_blit.c
@@ -35,13 +35,13 @@ static inline uint32_t cmdpacket0(struct radeon_screen *rscrn,
if (count)
return CP_PACKET0(reg, count - 1);
return CP_PACKET2;
}
/* common formats supported as both textures and render targets */
-unsigned r100_check_blit(gl_format mesa_format)
+unsigned r100_check_blit(gl_format mesa_format, uint32_t dst_pitch)
{
/* XXX others? BE/LE? */
switch (mesa_format) {
case MESA_FORMAT_ARGB8888:
case MESA_FORMAT_XRGB8888:
case MESA_FORMAT_RGB565:
@@ -52,12 +52,18 @@ unsigned r100_check_blit(gl_format mesa_format)
case MESA_FORMAT_I8:
break;
default:
return 0;
}
+ /* Rendering to small buffer doesn't work.
+ * Looks like a hw limitation.
+ */
+ if (dst_pitch < 32)
+ return 0;
+
/* ??? */
if (_mesa_get_format_bits(mesa_format, GL_DEPTH_BITS) > 0)
return 0;
return 1;
}
@@ -341,25 +347,19 @@ unsigned r100_blit(struct gl_context *ctx,
unsigned reg_width,
unsigned reg_height,
unsigned flip_y)
{
struct r100_context *r100 = R100_CONTEXT(ctx);
- if (!r100_check_blit(dst_mesaformat))
+ if (!r100_check_blit(dst_mesaformat, dst_pitch))
return GL_FALSE;
/* Make sure that colorbuffer has even width - hw limitation */
if (dst_pitch % 2 > 0)
++dst_pitch;
- /* Rendering to small buffer doesn't work.
- * Looks like a hw limitation.
- */
- if (dst_pitch < 32)
- return GL_FALSE;
-
/* Need to clamp the region size to make sure
* we don't read outside of the source buffer
* or write outside of the destination buffer.
*/
if (reg_width + src_x_offset > src_width)
reg_width = src_width - src_x_offset;
diff --git a/src/mesa/drivers/dri/radeon/radeon_blit.h b/src/mesa/drivers/dri/radeon/radeon_blit.h
index 5e5c73481a6..4fac4afe889 100644
--- a/src/mesa/drivers/dri/radeon/radeon_blit.h
+++ b/src/mesa/drivers/dri/radeon/radeon_blit.h
@@ -27,13 +27,13 @@
#ifndef RADEON_BLIT_H
#define RADEON_BLIT_H
void r100_blit_init(struct r100_context *r100);
-unsigned r100_check_blit(gl_format mesa_format);
+unsigned r100_check_blit(gl_format mesa_format, uint32_t dst_pitch);
unsigned r100_blit(struct gl_context *ctx,
struct radeon_bo *src_bo,
intptr_t src_offset,
gl_format src_mesaformat,
unsigned src_pitch,
diff --git a/src/mesa/drivers/dri/radeon/radeon_common_context.h b/src/mesa/drivers/dri/radeon/radeon_common_context.h
index 6de9f8a37b5..b8c6bf00ebc 100644
--- a/src/mesa/drivers/dri/radeon/radeon_common_context.h
+++ b/src/mesa/drivers/dri/radeon/radeon_common_context.h
@@ -86,12 +86,13 @@ struct radeon_renderbuffer
/* unsigned int offset; */
unsigned int pitch;
struct radeon_bo *map_bo;
GLbitfield map_mode;
int map_x, map_y, map_w, map_h;
+ int map_pitch;
uint32_t draw_offset; /* FBO */
/* boo Xorg 6.8.2 compat */
int has_surface;
GLuint pf_pending; /**< sequence number of pending flip */
@@ -171,12 +172,13 @@ struct _radeon_texture_image {
*
* If mt == 0, the image is stored in normal memory pointed to
* by base.Data.
*/
struct _radeon_mipmap_tree *mt;
struct radeon_bo *bo;
+ GLboolean used_as_render_target;
};
static INLINE radeon_texture_image *get_radeon_texture_image(struct gl_texture_image *image)
{
return (radeon_texture_image*)image;
@@ -478,13 +480,13 @@ struct radeon_context {
void (*pre_emit_atoms)(radeonContextPtr rmesa);
void (*pre_emit_state)(radeonContextPtr rmesa);
void (*fallback)(struct gl_context *ctx, GLuint bit, GLboolean mode);
void (*free_context)(struct gl_context *ctx);
void (*emit_query_finish)(radeonContextPtr radeon);
void (*update_scissor)(struct gl_context *ctx);
- unsigned (*check_blit)(gl_format mesa_format);
+ unsigned (*check_blit)(gl_format mesa_format, uint32_t dst_pitch);
unsigned (*blit)(struct gl_context *ctx,
struct radeon_bo *src_bo,
intptr_t src_offset,
gl_format src_mesaformat,
unsigned src_pitch,
unsigned src_width,
diff --git a/src/mesa/drivers/dri/radeon/radeon_fbo.c b/src/mesa/drivers/dri/radeon/radeon_fbo.c
index 9967fe5139e..5aad67f1a75 100644
--- a/src/mesa/drivers/dri/radeon/radeon_fbo.c
+++ b/src/mesa/drivers/dri/radeon/radeon_fbo.c
@@ -79,77 +79,123 @@ radeon_map_renderbuffer(struct gl_context *ctx,
GLint *out_stride)
{
struct radeon_context *const rmesa = RADEON_CONTEXT(ctx);
struct radeon_renderbuffer *rrb = radeon_renderbuffer(rb);
GLubyte *map;
GLboolean ok;
- int stride, ret;
-
- assert(rrb && rrb->bo);
-
- /* Make a temporary buffer and blit the current contents of the renderbuffer
- * out to it. This gives us linear access to the buffer, instead of having
- * to do detiling in software.
- */
- assert(!rrb->map_bo);
- rrb->map_bo = radeon_bo_open(rmesa->radeonScreen->bom, 0,
- rrb->pitch * h, 4,
- RADEON_GEM_DOMAIN_GTT, 0);
+ int stride, flip_stride;
+ int ret;
+ int src_x, src_y;
+
+ if (!rrb || !rrb->bo) {
+ *out_map = NULL;
+ *out_stride = 0;
+ return;
+ }
+
rrb->map_mode = mode;
rrb->map_x = x;
rrb->map_y = y;
rrb->map_w = w;
rrb->map_h = h;
+ rrb->map_pitch = rrb->pitch;
+
+ ok = rmesa->vtbl.check_blit(rb->Format, rrb->pitch / rrb->cpp);
+ if (ok) {
+ if (rb->Name) {
+ src_x = x;
+ src_y = y;
+ } else {
+ src_x = x;
+ src_y = rrb->base.Height - y - h;
+ }
+
+ /* Make a temporary buffer and blit the current contents of the renderbuffer
+ * out to it. This gives us linear access to the buffer, instead of having
+ * to do detiling in software.
+ */
+
+ rrb->map_pitch = rrb->pitch;
+
+ assert(!rrb->map_bo);
+ rrb->map_bo = radeon_bo_open(rmesa->radeonScreen->bom, 0,
+ rrb->map_pitch * h, 4,
+ RADEON_GEM_DOMAIN_GTT, 0);
+
+ ok = rmesa->vtbl.blit(ctx, rrb->bo, rrb->draw_offset,
+ rb->Format, rrb->pitch / rrb->cpp,
+ rb->Width, rb->Height,
+ src_x, src_y,
+ rrb->map_bo, 0,
+ rb->Format, rrb->map_pitch / rrb->cpp,
+ w, h,
+ 0, 0,
+ w, h,
+ GL_FALSE);
+ assert(ok);
+
+ ret = radeon_bo_map(rrb->map_bo, !!(mode & GL_MAP_WRITE_BIT));
+ assert(!ret);
+
+ map = rrb->map_bo->ptr;
+
+ if (rb->Name) {
+ *out_map = map;
+ *out_stride = rrb->map_pitch;
+ } else {
+ *out_map = map + (h - 1) * rrb->map_pitch;
+ *out_stride = -rrb->map_pitch;
+ }
+ return;
+ }
+
+ /* sw fallback flush stuff */
+ if (radeon_bo_is_referenced_by_cs(rrb->bo, rmesa->cmdbuf.cs)) {
+ radeon_firevertices(rmesa);
+ }
- ok = rmesa->vtbl.check_blit(rb->Format);
- assert(ok);
-
- ok = rmesa->vtbl.blit(ctx, rrb->bo, rrb->draw_offset,
- rb->Format, rrb->pitch / rrb->cpp,
- rb->Width, rb->Height,
- x, y,
- rrb->map_bo, 0,
- rb->Format, rrb->pitch / rrb->cpp,
- w, h,
- 0, 0,
- w, h,
- GL_FALSE);
- assert(ok);
-
- radeon_bo_wait(rrb->map_bo);
- ret = radeon_bo_map(rrb->map_bo, !!(mode & GL_MAP_WRITE_BIT));
+ ret = radeon_bo_map(rrb->bo, !!(mode & GL_MAP_WRITE_BIT));
assert(!ret);
- map = rrb->map_bo->ptr;
- stride = rrb->pitch;
+ map = rrb->bo->ptr;
+ stride = rrb->map_pitch;
if (rb->Name == 0) {
- map += stride * (rb->Height - 1);
- stride = -stride;
+ y = rb->Height - 1 - y;
+ flip_stride = -stride;
+ } else {
+ flip_stride = stride;
+ map += rrb->draw_offset;
}
- map += x * _mesa_get_format_bytes(rb->Format);
+ map += x * rrb->cpp;
map += (int)y * stride;
*out_map = map;
- *out_stride = stride;
+ *out_stride = flip_stride;
}
static void
radeon_unmap_renderbuffer(struct gl_context *ctx,
struct gl_renderbuffer *rb)
{
struct radeon_context *const rmesa = RADEON_CONTEXT(ctx);
struct radeon_renderbuffer *rrb = radeon_renderbuffer(rb);
GLboolean ok;
+ if (!rrb->map_bo) {
+ if (rrb->bo)
+ radeon_bo_unmap(rrb->bo);
+ return;
+ }
+
radeon_bo_unmap(rrb->map_bo);
if (rrb->map_mode & GL_MAP_WRITE_BIT) {
ok = rmesa->vtbl.blit(ctx, rrb->map_bo, 0,
- rb->Format, rrb->pitch / rrb->cpp,
+ rb->Format, rrb->map_pitch / rrb->cpp,
rrb->map_w, rrb->map_h,
0, 0,
rrb->bo, rrb->draw_offset,
rb->Format, rrb->pitch / rrb->cpp,
rb->Width, rb->Height,
rrb->map_x, rrb->map_y,
@@ -624,13 +670,13 @@ radeon_render_texture(struct gl_context * ctx,
(void) fb;
ASSERT(newImage);
radeon_image = (radeon_texture_image *)newImage;
- if (!radeon_image->mt || newImage->Border != 0) {
+ if (!radeon_image->mt) {
/* Fallback on drawing to a texture without a miptree.
*/
_mesa_reference_renderbuffer(&att->Renderbuffer, NULL);
_swrast_render_texture(ctx, fb, att);
return;
}
@@ -678,22 +724,32 @@ radeon_render_texture(struct gl_context * ctx,
}
/* store that offset in the region, along with the correct pitch for
* the image we are rendering to */
rrb->draw_offset = imageOffset;
rrb->pitch = radeon_image->mt->levels[att->TextureLevel].rowstride;
+ radeon_image->used_as_render_target = GL_TRUE;
/* update drawing region, etc */
radeon_draw_buffer(ctx, fb);
}
static void
radeon_finish_render_texture(struct gl_context * ctx,
struct gl_renderbuffer_attachment *att)
{
-
+ struct gl_texture_object *tex_obj = att->Texture;
+ struct gl_texture_image *image =
+ tex_obj->Image[att->CubeMapFace][att->TextureLevel];
+ radeon_texture_image *radeon_image = (radeon_texture_image *)image;
+
+ if (radeon_image)
+ radeon_image->used_as_render_target = GL_FALSE;
+
+ if (ctx->Driver.Flush)
+ ctx->Driver.Flush(ctx); /* +r6/r7 */
}
static void
radeon_validate_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb)
{
radeonContextPtr radeon = RADEON_CONTEXT(ctx);
gl_format mesa_format;
diff --git a/src/mesa/drivers/dri/radeon/radeon_mipmap_tree.c b/src/mesa/drivers/dri/radeon/radeon_mipmap_tree.c
index 05daf1cec43..23af9aca6ce 100644
--- a/src/mesa/drivers/dri/radeon/radeon_mipmap_tree.c
+++ b/src/mesa/drivers/dri/radeon/radeon_mipmap_tree.c
@@ -182,15 +182,15 @@ static void calculate_miptree_layout(radeonContextPtr rmesa, radeon_mipmap_tree
__func__, rmesa, mt, mt->totalsize);
}
/**
* Create a new mipmap tree, calculate its layout and allocate memory.
*/
-static radeon_mipmap_tree* radeon_miptree_create(radeonContextPtr rmesa,
- GLenum target, gl_format mesaFormat, GLuint baseLevel, GLuint numLevels,
- GLuint width0, GLuint height0, GLuint depth0, GLuint tilebits)
+radeon_mipmap_tree* radeon_miptree_create(radeonContextPtr rmesa,
+ GLenum target, gl_format mesaFormat, GLuint baseLevel, GLuint numLevels,
+ GLuint width0, GLuint height0, GLuint depth0, GLuint tilebits)
{
radeon_mipmap_tree *mt = CALLOC_STRUCT(_radeon_mipmap_tree);
radeon_print(RADEON_TEXTURE, RADEON_NORMAL,
"%s(%p) new tree is %p.\n",
__func__, rmesa, mt);
@@ -295,19 +295,16 @@ static void calculate_min_max_lod(struct gl_texture_object *tObj,
/**
* Checks whether the given miptree can hold the given texture image at the
* given face and level.
*/
GLboolean radeon_miptree_matches_image(radeon_mipmap_tree *mt,
- struct gl_texture_image *texImage, GLuint face, GLuint level)
+ struct gl_texture_image *texImage)
{
radeon_mipmap_level *lvl;
-
- if (face >= mt->faces)
- return GL_FALSE;
-
+ GLuint level = texImage->Level;
if (texImage->TexFormat != mt->mesaFormat)
return GL_FALSE;
lvl = &mt->levels[level];
if (!lvl->valid ||
lvl->width != texImage->Width ||
@@ -329,13 +326,13 @@ static GLboolean radeon_miptree_matches_texture(radeon_mipmap_tree *mt, struct g
if (texObj->BaseLevel < mt->baseLevel)
return GL_FALSE;
mtBaseLevel = &mt->levels[texObj->BaseLevel - mt->baseLevel];
firstImage = texObj->Image[0][texObj->BaseLevel];
- numLevels = MIN2(texObj->MaxLevel - texObj->BaseLevel + 1, firstImage->MaxLog2 + 1);
+ numLevels = MIN2(texObj->_MaxLevel - texObj->BaseLevel + 1, firstImage->MaxLog2 + 1);
if (radeon_is_debug_enabled(RADEON_TEXTURE,RADEON_TRACE)) {
fprintf(stderr, "Checking if miptree %p matches texObj %p\n", mt, texObj);
fprintf(stderr, "target %d vs %d\n", mt->target, texObj->Target);
fprintf(stderr, "format %d vs %d\n", mt->mesaFormat, firstImage->TexFormat);
fprintf(stderr, "numLevels %d vs %d\n", mt->numLevels, numLevels);
@@ -369,13 +366,12 @@ static GLboolean radeon_miptree_matches_texture(radeon_mipmap_tree *mt, struct g
*/
void radeon_try_alloc_miptree(radeonContextPtr rmesa, radeonTexObj *t)
{
struct gl_texture_object *texObj = &t->base;
struct gl_texture_image *texImg = texObj->Image[0][texObj->BaseLevel];
GLuint numLevels;
-
assert(!t->mt);
if (!texImg) {
radeon_warning("%s(%p) No image in given texture object(%p).\n",
__func__, rmesa, t);
return;
@@ -541,33 +537,25 @@ static radeon_mipmap_tree * get_biggest_matching_miptree(radeonTexObj *texObj,
* use the mipmap tree that has the most of the correct data.
*/
int radeon_validate_texture_miptree(struct gl_context * ctx, struct gl_texture_object *texObj)
{
radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
radeonTexObj *t = radeon_tex_obj(texObj);
+ radeon_mipmap_tree *dst_miptree;
if (t->validated || t->image_override) {
return GL_TRUE;
}
- if (texObj->Image[0][texObj->BaseLevel]->Border > 0)
- return GL_FALSE;
-
- _mesa_test_texobj_completeness(rmesa->glCtx, texObj);
- if (!texObj->_Complete) {
- return GL_FALSE;
- }
-
calculate_min_max_lod(&t->base, &t->minLod, &t->maxLod);
radeon_print(RADEON_TEXTURE, RADEON_NORMAL,
"%s: Validating texture %p now, minLod = %d, maxLod = %d\n",
__FUNCTION__, texObj ,t->minLod, t->maxLod);
- radeon_mipmap_tree *dst_miptree;
- dst_miptree = get_biggest_matching_miptree(t, t->base.BaseLevel, t->base.MaxLevel);
+ 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",
@@ -588,13 +576,13 @@ int radeon_validate_texture_miptree(struct gl_context * ctx, struct gl_texture_o
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) {
+ 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);
diff --git a/src/mesa/drivers/dri/radeon/radeon_mipmap_tree.h b/src/mesa/drivers/dri/radeon/radeon_mipmap_tree.h
index c0c52f0ff9a..74007ffdebc 100644
--- a/src/mesa/drivers/dri/radeon/radeon_mipmap_tree.h
+++ b/src/mesa/drivers/dri/radeon/radeon_mipmap_tree.h
@@ -81,13 +81,14 @@ struct _radeon_mipmap_tree {
};
void radeon_miptree_reference(radeon_mipmap_tree *mt, radeon_mipmap_tree **ptr);
void radeon_miptree_unreference(radeon_mipmap_tree **ptr);
GLboolean radeon_miptree_matches_image(radeon_mipmap_tree *mt,
- struct gl_texture_image *texImage, GLuint face, GLuint level);
+ struct gl_texture_image *texImage);
+
void radeon_try_alloc_miptree(radeonContextPtr rmesa, radeonTexObj *t);
GLuint radeon_miptree_image_offset(radeon_mipmap_tree *mt,
GLuint face, GLuint level);
uint32_t get_base_teximage_offset(radeonTexObj *texObj);
unsigned get_texture_image_row_stride(radeonContextPtr rmesa, gl_format format, unsigned width, unsigned tiling, unsigned target);
@@ -95,7 +96,11 @@ unsigned get_texture_image_row_stride(radeonContextPtr rmesa, gl_format format,
unsigned get_texture_image_size(
gl_format format,
unsigned rowStride,
unsigned height,
unsigned depth,
unsigned tiling);
+
+radeon_mipmap_tree *radeon_miptree_create(radeonContextPtr rmesa,
+ GLenum target, gl_format mesaFormat, GLuint baseLevel, GLuint numLevels,
+ GLuint width0, GLuint height0, GLuint depth0, GLuint tilebits);
#endif /* __RADEON_MIPMAP_TREE_H_ */
diff --git a/src/mesa/drivers/dri/radeon/radeon_pixel_read.c b/src/mesa/drivers/dri/radeon/radeon_pixel_read.c
index 9f6124034d9..68e3114989d 100644
--- a/src/mesa/drivers/dri/radeon/radeon_pixel_read.c
+++ b/src/mesa/drivers/dri/radeon/radeon_pixel_read.c
@@ -102,13 +102,13 @@ do_blit_readpixels(struct gl_context * ctx,
/* It's not worth if number of pixels to copy is really small */
if (width * height < 100) {
return GL_FALSE;
}
if (dst_format == MESA_FORMAT_NONE ||
- !radeon->vtbl.check_blit(dst_format) || !radeon->vtbl.blit) {
+ !radeon->vtbl.check_blit(dst_format, rrb->pitch / rrb->cpp) || !radeon->vtbl.blit) {
return GL_FALSE;
}
if (ctx->_ImageTransferState || ctx->Color.ColorLogicOpEnabled) {
return GL_FALSE;
}
diff --git a/src/mesa/drivers/dri/radeon/radeon_span.c b/src/mesa/drivers/dri/radeon/radeon_span.c
index ecc3befdbfe..b83d152091c 100644
--- a/src/mesa/drivers/dri/radeon/radeon_span.c
+++ b/src/mesa/drivers/dri/radeon/radeon_span.c
@@ -213,31 +213,31 @@ static GLubyte *radeon_ptr_2byte_8x2(const struct radeon_renderbuffer * rrb,
* Note that all information needed to access pixels in a renderbuffer
* should be obtained through the gl_renderbuffer parameter, not per-context
* information.
*/
#define LOCAL_VARS \
struct radeon_renderbuffer *rrb = (void *) rb; \
- const GLint yScale = ctx->DrawBuffer->Name ? 1 : -1; \
- const GLint yBias = ctx->DrawBuffer->Name ? 0 : rrb->base.Height - 1;\
int minx = 0, miny = 0; \
int maxx = rb->Width; \
int maxy = rb->Height; \
+ void *buf = rb->Data; \
+ int pitch = rb->RowStride * rrb->cpp; \
GLuint p; \
(void)p;
#define LOCAL_DEPTH_VARS \
struct radeon_renderbuffer *rrb = (void *) rb; \
- const GLint yScale = ctx->DrawBuffer->Name ? 1 : -1; \
- const GLint yBias = ctx->DrawBuffer->Name ? 0 : rrb->base.Height - 1;\
int minx = 0, miny = 0; \
+ const GLint yScale = ctx->DrawBuffer->Name ? 1 : -1; \
+ const GLint yBias = ctx->DrawBuffer->Name ? 0 : rrb->base.Height - 1; \
int maxx = rb->Width; \
int maxy = rb->Height;
#define LOCAL_STENCIL_VARS LOCAL_DEPTH_VARS
-#define Y_FLIP(_y) ((_y) * yScale + yBias)
+#define Y_FLIP(_y) (_y)
#define HW_LOCK()
#define HW_UNLOCK()
#define HW_CLIPLOOP()
#define HW_ENDCLIPLOOP()
@@ -246,114 +246,84 @@ static GLubyte *radeon_ptr_2byte_8x2(const struct radeon_renderbuffer * rrb,
*/
/* 16 bit, RGB565 color spanline and pixel functions
*/
#define SPANTMP_PIXEL_FMT GL_RGB
#define SPANTMP_PIXEL_TYPE GL_UNSIGNED_SHORT_5_6_5
-
#define TAG(x) radeon##x##_RGB565
#define TAG2(x,y) radeon##x##_RGB565##y
-#define GET_PTR(X,Y) radeon_ptr_2byte_8x2(rrb, (X), (Y))
#include "spantmp2.h"
#define SPANTMP_PIXEL_FMT GL_RGB
#define SPANTMP_PIXEL_TYPE GL_UNSIGNED_SHORT_5_6_5_REV
-
#define TAG(x) radeon##x##_RGB565_REV
#define TAG2(x,y) radeon##x##_RGB565_REV##y
-#define GET_PTR(X,Y) radeon_ptr_2byte_8x2(rrb, (X), (Y))
#include "spantmp2.h"
/* 16 bit, ARGB1555 color spanline and pixel functions
*/
#define SPANTMP_PIXEL_FMT GL_BGRA
#define SPANTMP_PIXEL_TYPE GL_UNSIGNED_SHORT_1_5_5_5_REV
-
#define TAG(x) radeon##x##_ARGB1555
#define TAG2(x,y) radeon##x##_ARGB1555##y
-#define GET_PTR(X,Y) radeon_ptr_2byte_8x2(rrb, (X), (Y))
#include "spantmp2.h"
#define SPANTMP_PIXEL_FMT GL_BGRA
#define SPANTMP_PIXEL_TYPE GL_UNSIGNED_SHORT_1_5_5_5
-
#define TAG(x) radeon##x##_ARGB1555_REV
#define TAG2(x,y) radeon##x##_ARGB1555_REV##y
-#define GET_PTR(X,Y) radeon_ptr_2byte_8x2(rrb, (X), (Y))
#include "spantmp2.h"
/* 16 bit, RGBA4 color spanline and pixel functions
*/
#define SPANTMP_PIXEL_FMT GL_BGRA
#define SPANTMP_PIXEL_TYPE GL_UNSIGNED_SHORT_4_4_4_4_REV
-
#define TAG(x) radeon##x##_ARGB4444
#define TAG2(x,y) radeon##x##_ARGB4444##y
-#define GET_PTR(X,Y) radeon_ptr_2byte_8x2(rrb, (X), (Y))
#include "spantmp2.h"
#define SPANTMP_PIXEL_FMT GL_BGRA
#define SPANTMP_PIXEL_TYPE GL_UNSIGNED_SHORT_4_4_4_4
-
#define TAG(x) radeon##x##_ARGB4444_REV
#define TAG2(x,y) radeon##x##_ARGB4444_REV##y
-#define GET_PTR(X,Y) radeon_ptr_2byte_8x2(rrb, (X), (Y))
#include "spantmp2.h"
/* 32 bit, xRGB8888 color spanline and pixel functions
*/
#define SPANTMP_PIXEL_FMT GL_BGRA
#define SPANTMP_PIXEL_TYPE GL_UNSIGNED_INT_8_8_8_8_REV
-
#define TAG(x) radeon##x##_xRGB8888
#define TAG2(x,y) radeon##x##_xRGB8888##y
-#define GET_VALUE(_x, _y) ((*(GLuint*)(radeon_ptr_4byte(rrb, _x, _y)) | 0xff000000))
-#define PUT_VALUE(_x, _y, d) { \
- GLuint *_ptr = (GLuint*)radeon_ptr_4byte( rrb, _x, _y ); \
- *_ptr = d; \
-} while (0)
#include "spantmp2.h"
/* 32 bit, ARGB8888 color spanline and pixel functions
*/
#define SPANTMP_PIXEL_FMT GL_BGRA
#define SPANTMP_PIXEL_TYPE GL_UNSIGNED_INT_8_8_8_8_REV
-
#define TAG(x) radeon##x##_ARGB8888
#define TAG2(x,y) radeon##x##_ARGB8888##y
-#define GET_VALUE(_x, _y) (*(GLuint*)(radeon_ptr_4byte(rrb, _x, _y)))
-#define PUT_VALUE(_x, _y, d) { \
- GLuint *_ptr = (GLuint*)radeon_ptr_4byte( rrb, _x, _y ); \
- *_ptr = d; \
-} while (0)
#include "spantmp2.h"
/* 32 bit, BGRx8888 color spanline and pixel functions
*/
#define SPANTMP_PIXEL_FMT GL_BGRA
#define SPANTMP_PIXEL_TYPE GL_UNSIGNED_INT_8_8_8_8
-
#define TAG(x) radeon##x##_BGRx8888
#define TAG2(x,y) radeon##x##_BGRx8888##y
-#define GET_VALUE(_x, _y) ((*(GLuint*)(radeon_ptr_4byte(rrb, _x, _y)) | 0x000000ff))
-#define PUT_VALUE(_x, _y, d) { \
- GLuint *_ptr = (GLuint*)radeon_ptr_4byte( rrb, _x, _y ); \
- *_ptr = d; \
-} while (0)
#include "spantmp2.h"
/* 32 bit, BGRA8888 color spanline and pixel functions
*/
#define SPANTMP_PIXEL_FMT GL_BGRA
#define SPANTMP_PIXEL_TYPE GL_UNSIGNED_INT_8_8_8_8
-
#define TAG(x) radeon##x##_BGRA8888
#define TAG2(x,y) radeon##x##_BGRA8888##y
-#define GET_PTR(X,Y) radeon_ptr_4byte(rrb, (X), (Y))
#include "spantmp2.h"
+#undef Y_FLIP
+#define Y_FLIP(_y) ((_y) * yScale + yBias)
/* ================================================================
* Depth buffer
*/
/* The Radeon family has depth tiling on all the time, so we have to convert
* the x,y coordinates into the memory bus address (mba) in the same
@@ -506,116 +476,111 @@ do { \
} while (0)
#endif
#define TAG(x) radeon##x##_s8_z24
#include "stenciltmp.h"
-
-static void map_unmap_rb(struct gl_renderbuffer *rb, int flag)
+static void
+radeon_renderbuffer_map(struct gl_context *ctx, struct gl_renderbuffer *rb)
{
struct radeon_renderbuffer *rrb = radeon_renderbuffer(rb);
- int r;
+ GLubyte *map;
+ int stride;
- if (rrb == NULL || !rrb->bo)
+ if (!rb || !rrb)
return;
- radeon_print(RADEON_MEMORY, RADEON_TRACE,
- "%s( rb %p, flag %s )\n",
- __func__, rb, flag ? "true":"false");
-
- if (flag) {
- radeon_bo_wait(rrb->bo);
- r = radeon_bo_map(rrb->bo, 1);
- if (r) {
- fprintf(stderr, "(%s) error(%d) mapping buffer.\n",
- __FUNCTION__, r);
- }
+ ctx->Driver.MapRenderbuffer(ctx, rb, 0, 0, rb->Width, rb->Height,
+ GL_MAP_READ_BIT | GL_MAP_WRITE_BIT,
+ &map, &stride);
- radeonSetSpanFunctions(rrb);
- } else {
- radeon_bo_unmap(rrb->bo);
- rb->GetRow = NULL;
- rb->PutRow = NULL;
- }
+ rb->Data = map;
+ rb->RowStride = stride / _mesa_get_format_bytes(rb->Format);
+
+ radeonSetSpanFunctions(rrb);
+}
+
+static void
+radeon_renderbuffer_unmap(struct gl_context *ctx, struct gl_renderbuffer *rb)
+{
+ struct radeon_renderbuffer *rrb = radeon_renderbuffer(rb);
+ if (!rb || !rrb)
+ return;
+
+ ctx->Driver.UnmapRenderbuffer(ctx, rb);
+
+ rb->GetRow = NULL;
+ rb->PutRow = NULL;
+ rb->Data = NULL;
+ rb->RowStride = 0;
}
static void
-radeon_map_unmap_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb,
- GLboolean map)
+radeon_map_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb)
{
GLuint i, j;
radeon_print(RADEON_MEMORY, RADEON_TRACE,
- "%s( %p , fb %p, map %s )\n",
- __func__, ctx, fb, map ? "true":"false");
+ "%s( %p , fb %p )\n",
+ __func__, ctx, fb);
- /* color draw buffers */
- for (j = 0; j < ctx->DrawBuffer->_NumColorDrawBuffers; j++)
- map_unmap_rb(fb->_ColorDrawBuffers[j], map);
+ /* check for render to textures */
+ for (i = 0; i < BUFFER_COUNT; i++)
+ radeon_renderbuffer_map(ctx, fb->Attachment[i].Renderbuffer);
- map_unmap_rb(fb->_ColorReadBuffer, map);
+ radeon_check_front_buffer_rendering(ctx);
+}
- /* check for render to textures */
- for (i = 0; i < BUFFER_COUNT; i++) {
- struct gl_renderbuffer_attachment *att =
- fb->Attachment + i;
- struct gl_texture_object *tex = att->Texture;
- if (tex) {
- /* Render to texture. Note that a mipmapped texture need not
- * be complete for render to texture, so we must restrict to
- * mapping only the attached image.
- */
- radeon_texture_image *image = get_radeon_texture_image(tex->Image[att->CubeMapFace][att->TextureLevel]);
- ASSERT(att->Renderbuffer);
-
- if (map)
- radeon_teximage_map(image, GL_TRUE);
- else
- radeon_teximage_unmap(image);
- }
- }
-
- /* depth buffer (Note wrapper!) */
- if (fb->_DepthBuffer)
- map_unmap_rb(fb->_DepthBuffer->Wrapped, map);
+static void
+radeon_unmap_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb)
+{
+ GLuint i, j;
- if (fb->_StencilBuffer)
- map_unmap_rb(fb->_StencilBuffer->Wrapped, map);
+ radeon_print(RADEON_MEMORY, RADEON_TRACE,
+ "%s( %p , fb %p)\n",
+ __func__, ctx, fb);
+
+ /* check for render to textures */
+ for (i = 0; i < BUFFER_COUNT; i++)
+ radeon_renderbuffer_unmap(ctx, fb->Attachment[i].Renderbuffer);
radeon_check_front_buffer_rendering(ctx);
}
static void radeonSpanRenderStart(struct gl_context * ctx)
{
radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
int i;
radeon_firevertices(rmesa);
- for (i = 0; i < ctx->Const.MaxTextureImageUnits; i++)
- if (ctx->Texture.Unit[i]._ReallyEnabled)
- radeonMapTexture(ctx, ctx->Texture.Unit[i]._Current);
-
- radeon_map_unmap_framebuffer(ctx, ctx->DrawBuffer, GL_TRUE);
+ for (i = 0; i < ctx->Const.MaxTextureImageUnits; i++) {
+ if (ctx->Texture.Unit[i]._ReallyEnabled) {
+ radeon_validate_texture_miptree(ctx, ctx->Texture.Unit[i]._Current);
+ radeon_swrast_map_texture_images(ctx, ctx->Texture.Unit[i]._Current);
+ }
+ }
+
+ radeon_map_framebuffer(ctx, ctx->DrawBuffer);
if (ctx->ReadBuffer != ctx->DrawBuffer)
- radeon_map_unmap_framebuffer(ctx, ctx->ReadBuffer, GL_TRUE);
+ radeon_map_framebuffer(ctx, ctx->ReadBuffer);
}
static void radeonSpanRenderFinish(struct gl_context * ctx)
{
int i;
_swrast_flush(ctx);
for (i = 0; i < ctx->Const.MaxTextureImageUnits; i++)
if (ctx->Texture.Unit[i]._ReallyEnabled)
- radeonUnmapTexture(ctx, ctx->Texture.Unit[i]._Current);
+ radeon_swrast_unmap_texture_images(ctx, ctx->Texture.Unit[i]._Current);
- radeon_map_unmap_framebuffer(ctx, ctx->DrawBuffer, GL_FALSE);
+ radeon_unmap_framebuffer(ctx, ctx->DrawBuffer);
if (ctx->ReadBuffer != ctx->DrawBuffer)
- radeon_map_unmap_framebuffer(ctx, ctx->ReadBuffer, GL_FALSE);
+ radeon_unmap_framebuffer(ctx, ctx->ReadBuffer);
}
void radeonInitSpanFuncs(struct gl_context * ctx)
{
struct swrast_device_driver *swdd =
_swrast_GetDeviceDriverReference(ctx);
diff --git a/src/mesa/drivers/dri/radeon/radeon_tex_copy.c b/src/mesa/drivers/dri/radeon/radeon_tex_copy.c
index bc9015e574d..ca0ac161709 100644
--- a/src/mesa/drivers/dri/radeon/radeon_tex_copy.c
+++ b/src/mesa/drivers/dri/radeon/radeon_tex_copy.c
@@ -98,13 +98,13 @@ do_copy_texsubimage(struct gl_context *ctx,
}
src_mesaformat = rrb->base.Format;
dst_mesaformat = timg->base.Base.TexFormat;
src_bpp = _mesa_get_format_bytes(src_mesaformat);
dst_bpp = _mesa_get_format_bytes(dst_mesaformat);
- if (!radeon->vtbl.check_blit(dst_mesaformat)) {
+ if (!radeon->vtbl.check_blit(dst_mesaformat, rrb->pitch / rrb->cpp)) {
/* depth formats tend to be special */
if (_mesa_get_format_bits(dst_mesaformat, GL_DEPTH_BITS) > 0)
return GL_FALSE;
if (src_bpp != dst_bpp)
return GL_FALSE;
diff --git a/src/mesa/drivers/dri/radeon/radeon_texture.c b/src/mesa/drivers/dri/radeon/radeon_texture.c
index 178ff0925c3..71eff75cc04 100644
--- a/src/mesa/drivers/dri/radeon/radeon_texture.c
+++ b/src/mesa/drivers/dri/radeon/radeon_texture.c
@@ -45,12 +45,19 @@
#include "xmlpool.h" /* for symbolic values of enum-type options */
#include "radeon_common.h"
#include "radeon_mipmap_tree.h"
+static void teximage_assign_miptree(radeonContextPtr rmesa,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage);
+
+static radeon_mipmap_tree *radeon_miptree_create_for_teximage(radeonContextPtr rmesa,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage);
void copy_rows(void* dst, GLuint dststride, const void* src, GLuint srcstride,
GLuint numrows, GLuint rowsize)
{
assert(rowsize <= dststride);
assert(rowsize <= srcstride);
@@ -91,23 +98,49 @@ static void
radeonDeleteTextureImage(struct gl_context *ctx, struct gl_texture_image *img)
{
/* nothing special (yet) for radeon_texture_image */
_mesa_delete_texture_image(ctx, img);
}
+static GLboolean
+radeonAllocTextureImageBuffer(struct gl_context *ctx,
+ struct gl_texture_image *timage,
+ gl_format format, GLsizei width,
+ GLsizei height, GLsizei depth)
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ radeon_texture_image *image = get_radeon_texture_image(timage);
+ struct gl_texture_object *texobj = timage->TexObject;
+ int slices;
+
+ ctx->Driver.FreeTextureImageBuffer(ctx, timage);
+
+ switch (texobj->Target) {
+ case GL_TEXTURE_3D:
+ slices = timage->Depth;
+ break;
+ default:
+ slices = 1;
+ }
+ assert(!image->base.ImageOffsets);
+ image->base.ImageOffsets = malloc(slices * sizeof(GLuint));
+ teximage_assign_miptree(rmesa, texobj, timage);
+
+ return GL_TRUE;
+}
+
/**
* Free memory associated with this texture image.
*/
void radeonFreeTextureImageBuffer(struct gl_context *ctx, struct gl_texture_image *timage)
{
radeon_texture_image* image = get_radeon_texture_image(timage);
if (image->mt) {
radeon_miptree_unreference(&image->mt);
- assert(!image->base.Buffer);
} else {
_swrast_free_texture_image_buffer(ctx, timage);
}
if (image->bo) {
radeon_bo_unref(image->bo);
image->bo = NULL;
@@ -170,97 +203,12 @@ void radeon_teximage_unmap(radeon_texture_image *image)
image->base.Data = 0;
radeon_bo_unmap(image->mt->bo);
}
}
-static void map_override(struct gl_context *ctx, radeonTexObj *t)
-{
- radeon_texture_image *img = get_radeon_texture_image(t->base.Image[0][0]);
-
- radeon_bo_map(t->bo, GL_FALSE);
-
- img->base.Data = t->bo->ptr;
-}
-
-static void unmap_override(struct gl_context *ctx, radeonTexObj *t)
-{
- radeon_texture_image *img = get_radeon_texture_image(t->base.Image[0][0]);
-
- radeon_bo_unmap(t->bo);
-
- img->base.Data = NULL;
-}
-
-/**
- * Map a validated texture for reading during software rendering.
- */
-void radeonMapTexture(struct gl_context *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]));
- }
-}
-
-void radeonUnmapTexture(struct gl_context *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) {
- radeon_texture_image *image =
- get_radeon_texture_image(texObj->Image[face][level]);
- image->base.Data = NULL;
- }
- }
- radeon_bo_unmap(t->mt->bo);
-}
-
-
/**
* Map texture memory/buffer into user space.
* Note: the region of interest parameters are ignored here.
* \param mapOut returns start of mapping of region of interest
* \param rowStrideOut returns row stride in bytes
*/
@@ -283,13 +231,13 @@ radeon_map_texture_image(struct gl_context *ctx,
unsigned int bw, bh;
GLboolean write = (mode & GL_MAP_WRITE_BIT) != 0;
_mesa_get_format_block_size(texImage->TexFormat, &bw, &bh);
assert(y % bh == 0);
y /= bh;
- height /= bh;
+ texel_size /= bw;
if (bo && radeon_bo_is_referenced_by_cs(bo, rmesa->cmdbuf.cs)) {
radeon_print(RADEON_TEXTURE, RADEON_VERBOSE,
"%s for texture that is "
"queued for GPU processing.\n",
__func__);
@@ -299,15 +247,17 @@ radeon_map_texture_image(struct gl_context *ctx,
if (image->bo) {
/* TFP case */
radeon_bo_map(image->bo, write);
*stride = get_texture_image_row_stride(rmesa, texImage->TexFormat, width, 0, texImage->TexObject->Target);
*map = bo->ptr;
} else if (likely(mt)) {
- radeon_bo_map(mt->bo, write);
+ void *base;
radeon_mipmap_level *lvl = &image->mt->levels[texImage->Level];
- void *base = mt->bo->ptr + lvl->faces[image->base.Base.Face].offset;
+
+ radeon_bo_map(mt->bo, write);
+ base = mt->bo->ptr + lvl->faces[image->base.Base.Face].offset;
*stride = lvl->rowstride;
*map = base + (slice * height) * *stride;
} else {
/* texture data is in malloc'd memory */
@@ -591,163 +541,41 @@ gl_format radeonChooseTextureFormat(struct gl_context * ctx,
return MESA_FORMAT_NONE; /* never get here */
}
/** Check if given image is valid within current texture object.
*/
-static int image_matches_texture_obj(struct gl_texture_object *texObj,
- struct gl_texture_image *texImage,
- unsigned level)
-{
- const struct gl_texture_image *baseImage = texObj->Image[0][texObj->BaseLevel];
-
- if (!baseImage)
- return 0;
-
- if (level < texObj->BaseLevel || level > texObj->MaxLevel)
- return 0;
-
- const unsigned levelDiff = level - texObj->BaseLevel;
- const unsigned refWidth = MAX2(baseImage->Width >> levelDiff, 1);
- const unsigned refHeight = MAX2(baseImage->Height >> levelDiff, 1);
- const unsigned refDepth = MAX2(baseImage->Depth >> levelDiff, 1);
-
- return (texImage->Width == refWidth &&
- texImage->Height == refHeight &&
- texImage->Depth == refDepth);
-}
-
static void teximage_assign_miptree(radeonContextPtr rmesa,
- struct gl_texture_object *texObj,
- struct gl_texture_image *texImage,
- unsigned face,
- unsigned level)
+ 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);
- /* Since miptree holds only images for levels <BaseLevel..MaxLevel>
- * don't allocate the miptree if the teximage won't fit.
- */
- if (!image_matches_texture_obj(texObj, texImage, level))
- return;
-
/* Try using current miptree, or create new if there isn't any */
- if (!t->mt || !radeon_miptree_matches_image(t->mt, texImage, face, level)) {
+ if (!t->mt || !radeon_miptree_matches_image(t->mt, texImage)) {
radeon_miptree_unreference(&t->mt);
- radeon_try_alloc_miptree(rmesa, t);
+ t->mt = radeon_miptree_create_for_teximage(rmesa,
+ texObj,
+ texImage);
+
radeon_print(RADEON_TEXTURE, RADEON_NORMAL,
- "%s: texObj %p, texImage %p, face %d, level %d, "
+ "%s: texObj %p, texImage %p, "
"texObj miptree doesn't match, allocated new miptree %p\n",
- __FUNCTION__, texObj, texImage, face, level, t->mt);
+ __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__);
}
-
-/**
- * Update a subregion of the given texture image.
- */
-static void radeon_store_teximage(struct gl_context* 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 texel_size = _mesa_get_format_bytes(texImage->TexFormat);
-
- GLuint dstRowStride;
- GLuint alignedWidth;
- GLint i;
-
- 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->base.Base.Level].rowstride;
- } else if (t->bo) {
- /* TFP case */
- dstRowStride = get_texture_image_row_stride(rmesa, texImage->TexFormat, width, 0, texObj->Target);
- } else {
- dstRowStride = _mesa_format_row_stride(texImage->TexFormat, texImage->Width);
- }
-
- assert(dstRowStride);
-
- /* fill in the ImageOffsets array */
- alignedWidth = dstRowStride / texel_size;
- for (i = 0; i < texImage->Depth; ++i) {
- image->base.ImageOffsets[i] = alignedWidth * texImage->Height * i;
- }
- /* and fill in RowStride (in texels) */
- image->base.RowStride = alignedWidth;
-
- 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, image->base.Data);
- }
- else {
- uint32_t offset;
- offset = dstRowStride / texel_size * yoffset / block_height + xoffset / block_width;
- offset *= texel_size;
- img_start = image->base.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 {
- GLubyte *slices[512];
- GLuint i;
- assert(depth <= 512);
- for (i = 0; i < depth; i++) {
- slices[i] = (GLubyte *) image->base.Data
- + image->base.ImageOffsets[i] * texel_size;
- }
- if (!_mesa_texstore(ctx, dims, texImage->_BaseFormat,
- texImage->TexFormat,
- xoffset, yoffset, zoffset,
- dstRowStride,
- slices,
- width, height, depth,
- format, type, pixels, packing)) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage");
- }
- }
-
- radeon_teximage_unmap(image);
-}
-
/**
* All glTexImage calls go through this function.
*/
static void radeon_teximage(
struct gl_context *ctx, int dims,
GLenum target, GLint level,
@@ -757,78 +585,16 @@ static void radeon_teximage(
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 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);
-
- t->validated = GL_FALSE;
-
- radeonFreeTextureImageBuffer(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);
- image->base.Buffer = _mesa_align_malloc(size, 512);
-
- radeon_print(RADEON_TEXTURE, RADEON_VERBOSE,
- "%s %dd: texObj %p, texImage %p, "
- " no miptree assigned, using local memory %p\n",
- __func__, dims, texObj, texImage, image->base.Buffer);
- }
- }
-
- {
- 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);
- }
- }
-
- image->base.ImageOffsets =
- (GLuint *) malloc(texImage->Depth * sizeof(GLuint));
-
-
- /* 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);
+ _mesa_store_teximage3d(ctx, target, level, internalFormat,
+ width, height, depth, 0,
+ format, type, pixels,
+ packing, texObj, texImage);
}
void radeonTexImage1D(struct gl_context * ctx, GLenum target, GLint level,
GLint internalFormat,
GLint width, GLint border,
GLenum format, GLenum type, const GLvoid * pixels,
@@ -850,23 +616,12 @@ void radeonTexImage2D(struct gl_context * ctx, GLenum target, GLint level,
{
radeon_teximage(ctx, 2, target, level, internalFormat, width, height, 1,
0, format, type, pixels, packing, texObj, texImage, 0);
}
-void radeonCompressedTexImage2D(struct gl_context * ctx, GLenum target,
- GLint level, GLint internalFormat,
- GLint width, GLint height, GLint border,
- GLsizei imageSize, const GLvoid * data,
- struct gl_texture_object *texObj,
- struct gl_texture_image *texImage)
-{
- radeon_teximage(ctx, 2, target, level, internalFormat, width, height, 1,
- imageSize, 0, 0, data, &ctx->Unpack, texObj, texImage, 1);
-}
-
void radeonTexImage3D(struct gl_context * ctx, GLenum target, GLint level,
GLint internalFormat,
GLint width, GLint height, GLint depth,
GLint border,
GLenum format, GLenum type, const GLvoid * pixels,
const struct gl_pixelstore_attrib *packing,
@@ -874,122 +629,12 @@ void radeonTexImage3D(struct gl_context * ctx, GLenum target, GLint level,
struct gl_texture_image *texImage)
{
radeon_teximage(ctx, 3, target, level, internalFormat, width, height, depth,
0, format, type, pixels, packing, texObj, texImage, 0);
}
-/**
- * All glTexSubImage calls go through this function.
- */
-static void radeon_texsubimage(struct gl_context* 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);
-}
-
-void radeonTexSubImage1D(struct gl_context * ctx, GLenum target, GLint level,
- GLint xoffset,
- GLsizei width,
- GLenum format, GLenum type,
- const GLvoid * pixels,
- const struct gl_pixelstore_attrib *packing,
- struct gl_texture_object *texObj,
- struct gl_texture_image *texImage)
-{
- radeon_texsubimage(ctx, 1, target, level, xoffset, 0, 0, width, 1, 1, 0,
- format, type, pixels, packing, texObj, texImage, 0);
-}
-
-void radeonTexSubImage2D(struct gl_context * ctx, GLenum target, GLint level,
- GLint xoffset, GLint yoffset,
- GLsizei width, GLsizei height,
- GLenum format, GLenum type,
- const GLvoid * pixels,
- const struct gl_pixelstore_attrib *packing,
- struct gl_texture_object *texObj,
- struct gl_texture_image *texImage)
-{
- radeon_texsubimage(ctx, 2, target, level, xoffset, yoffset, 0, width, height, 1,
- 0, format, type, pixels, packing, texObj, texImage,
- 0);
-}
-
-void radeonCompressedTexSubImage2D(struct gl_context * ctx, GLenum target,
- GLint level, GLint xoffset,
- GLint yoffset, GLsizei width,
- GLsizei height, GLenum format,
- GLsizei imageSize, const GLvoid * data,
- struct gl_texture_object *texObj,
- struct gl_texture_image *texImage)
-{
- radeon_texsubimage(ctx, 2, target, level, xoffset, yoffset, 0, width, height, 1,
- imageSize, format, 0, data, &ctx->Unpack, texObj, texImage, 1);
-}
-
-
-void radeonTexSubImage3D(struct gl_context * ctx, GLenum target, GLint level,
- GLint xoffset, GLint yoffset, GLint zoffset,
- GLsizei width, GLsizei height, GLsizei depth,
- GLenum format, GLenum type,
- const GLvoid * pixels,
- const struct gl_pixelstore_attrib *packing,
- struct gl_texture_object *texObj,
- struct gl_texture_image *texImage)
-{
- radeon_texsubimage(ctx, 3, target, level, xoffset, yoffset, zoffset, width, height, depth, 0,
- format, type, pixels, packing, texObj, texImage, 0);
-}
-
unsigned radeonIsFormatRenderable(gl_format mesa_format)
{
if (mesa_format == _radeon_texformat_argb8888 || mesa_format == _radeon_texformat_rgb565 ||
mesa_format == _radeon_texformat_argb1555 || mesa_format == _radeon_texformat_argb4444)
return 1;
@@ -1056,14 +701,13 @@ void radeon_image_target_texture_2d(struct gl_context *ctx, GLenum target,
/* 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,
- radeonImage->base.Base.Face, 0))
+ if (!radeon_miptree_matches_image(t->mt, &radeonImage->base.Base))
fprintf(stderr, "miptree doesn't match image\n");
}
#endif
gl_format _radeon_texformat_rgba8888 = MESA_FORMAT_NONE;
gl_format _radeon_texformat_argb8888 = MESA_FORMAT_NONE;
@@ -1098,32 +742,156 @@ radeonInitTextureFormats(void)
void
radeon_init_common_texture_funcs(radeonContextPtr radeon,
struct dd_function_table *functions)
{
functions->NewTextureImage = radeonNewTextureImage;
functions->DeleteTextureImage = radeonDeleteTextureImage;
+ functions->AllocTextureImageBuffer = radeonAllocTextureImageBuffer;
functions->FreeTextureImageBuffer = radeonFreeTextureImageBuffer;
- functions->MapTexture = radeonMapTexture;
- functions->UnmapTexture = radeonUnmapTexture;
functions->MapTextureImage = radeon_map_texture_image;
functions->UnmapTextureImage = radeon_unmap_texture_image;
functions->ChooseTextureFormat = radeonChooseTextureFormat_mesa;
functions->TexImage1D = radeonTexImage1D;
functions->TexImage2D = radeonTexImage2D;
functions->TexImage3D = radeonTexImage3D;
- functions->TexSubImage1D = radeonTexSubImage1D;
- functions->TexSubImage2D = radeonTexSubImage2D;
- functions->TexSubImage3D = radeonTexSubImage3D;
- functions->CompressedTexImage2D = radeonCompressedTexImage2D;
- functions->CompressedTexSubImage2D = radeonCompressedTexSubImage2D;
functions->CopyTexSubImage2D = radeonCopyTexSubImage2D;
functions->Bitmap = _mesa_meta_Bitmap;
#if FEATURE_OES_EGL_image
functions->EGLImageTargetTexture2D = radeon_image_target_texture_2d;
#endif
radeonInitTextureFormats();
}
+
+static void
+radeon_swrast_map_image(radeonContextPtr rmesa,
+ radeon_texture_image *image)
+{
+ GLuint level, face;
+ radeon_mipmap_tree *mt;
+ GLuint texel_size;
+ radeon_mipmap_level *lvl;
+ int rs;
+
+ if (!image || !image->mt)
+ return;
+
+ texel_size = _mesa_get_format_bytes(image->base.Base.TexFormat);
+ level = image->base.Base.Level;
+ face = image->base.Base.Face;
+ mt = image->mt;
+
+ lvl = &image->mt->levels[level];
+
+ rs = lvl->rowstride / texel_size;
+
+ radeon_bo_map(mt->bo, 1);
+
+ image->base.Data = mt->bo->ptr + lvl->faces[face].offset;
+ if (mt->target == GL_TEXTURE_3D) {
+ int i;
+
+ for (i = 0; i < mt->levels[level].depth; i++)
+ image->base.ImageOffsets[i] = rs * lvl->height * i;
+ }
+ image->base.RowStride = rs;
+}
+
+static void
+radeon_swrast_unmap_image(radeonContextPtr rmesa,
+ radeon_texture_image *image)
+{
+ if (image && image->mt) {
+ image->base.Data = NULL;
+ radeon_bo_unmap(image->mt->bo);
+ }
+}
+
+void
+radeon_swrast_map_texture_images(struct gl_context *ctx,
+ struct gl_texture_object *texObj)
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ GLuint nr_faces = (texObj->Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1;
+ int i, face;
+
+ for (i = texObj->BaseLevel; i <= texObj->_MaxLevel; i++) {
+ for (face = 0; face < nr_faces; face++) {
+ radeon_texture_image *image = get_radeon_texture_image(texObj->Image[face][i]);
+ radeon_swrast_map_image(rmesa, image);
+ }
+ }
+}
+
+void
+radeon_swrast_unmap_texture_images(struct gl_context *ctx,
+ struct gl_texture_object *texObj)
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ GLuint nr_faces = (texObj->Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1;
+ int i, face;
+
+ for (i = texObj->BaseLevel; i <= texObj->_MaxLevel; i++) {
+ for (face = 0; face < nr_faces; face++) {
+ radeon_texture_image *image = get_radeon_texture_image(texObj->Image[face][i]);
+ radeon_swrast_unmap_image(rmesa, image);
+ }
+ }
+
+}
+
+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);
+}
diff --git a/src/mesa/drivers/dri/radeon/radeon_texture.h b/src/mesa/drivers/dri/radeon/radeon_texture.h
index 0fa48bd1091..f1af109707f 100644
--- a/src/mesa/drivers/dri/radeon/radeon_texture.h
+++ b/src/mesa/drivers/dri/radeon/radeon_texture.h
@@ -46,16 +46,18 @@ void copy_rows(void* dst, GLuint dststride, const void* src, GLuint srcstride,
GLuint numrows, GLuint rowsize);
struct gl_texture_image *radeonNewTextureImage(struct gl_context *ctx);
void radeonFreeTextureImageBuffer(struct gl_context *ctx, struct gl_texture_image *timage);
void radeon_teximage_map(radeon_texture_image *image, GLboolean write_enable);
void radeon_teximage_unmap(radeon_texture_image *image);
-void radeonMapTexture(struct gl_context *ctx, struct gl_texture_object *texObj);
-void radeonUnmapTexture(struct gl_context *ctx, struct gl_texture_object *texObj);
int radeon_validate_texture_miptree(struct gl_context * ctx, struct gl_texture_object *texObj);
+
+void radeon_swrast_map_texture_images(struct gl_context *ctx, struct gl_texture_object *texObj);
+void radeon_swrast_unmap_texture_images(struct gl_context *ctx, struct gl_texture_object *texObj);
+
gl_format radeonChooseTextureFormat_mesa(struct gl_context * ctx,
GLint internalFormat,
GLenum format,
GLenum type);
gl_format radeonChooseTextureFormat(struct gl_context * ctx,