diff options
-rw-r--r-- | src/gallium/state_trackers/nine/basetexture9.c | 221 |
1 files changed, 125 insertions, 96 deletions
diff --git a/src/gallium/state_trackers/nine/basetexture9.c b/src/gallium/state_trackers/nine/basetexture9.c index 9b7976c3862..330827aec37 100644 --- a/src/gallium/state_trackers/nine/basetexture9.c +++ b/src/gallium/state_trackers/nine/basetexture9.c @@ -163,7 +163,8 @@ NineBaseTexture9_UploadSelf( struct NineBaseTexture9 *This ) { HRESULT hr; unsigned last_level = This->base.info.last_level; - unsigned l; + unsigned l, min_level_dirty = This->managed.lod; + BOOL update_lod; DBG("This=%p dirty=%i type=%s\n", This, This->managed.dirty, nine_D3DRTYPE_to_str(This->base.type)); @@ -173,7 +174,14 @@ NineBaseTexture9_UploadSelf( struct NineBaseTexture9 *This ) if (This->base.usage & D3DUSAGE_AUTOGENMIPMAP) last_level = 0; /* TODO: What if level 0 is not resident ? */ - if (This->managed.lod_resident != This->managed.lod) { + update_lod = This->managed.lod_resident != This->managed.lod; + if (!update_lod && !This->managed.dirty) + return D3D_OK; + + /* Allocate a new resource with the correct number of levels, + * Mark states for update, and tell the nine surfaces/volumes + * their new resource. */ + if (update_lod) { struct pipe_resource *res; DBG("updating LOD from %u to %u ...\n", This->managed.lod_resident, This->managed.lod); @@ -192,148 +200,169 @@ NineBaseTexture9_UploadSelf( struct NineBaseTexture9 *This ) state->changed.group |= NINE_STATE_TEXTURE; } + /* Allocate a new resource */ hr = NineBaseTexture9_CreatePipeResource(This, This->managed.lod_resident != -1); if (FAILED(hr)) return hr; res = This->base.resource; - if (This->managed.lod_resident == -1) /* no levels were resident */ + if (This->managed.lod_resident == -1) {/* no levels were resident */ + This->managed.dirty = FALSE; /* We are going to upload everything. */ This->managed.lod_resident = This->base.info.last_level + 1; + } + + if (This->base.type == D3DRTYPE_TEXTURE) { + struct NineTexture9 *tex = NineTexture9(This); + + /* last content (if apply) has been copied to the new resource. + * Note: We cannot render to surfaces of managed textures. + * Note2: the level argument passed is to get the level offset + * right when the texture is uploaded (the texture first level + * corresponds to This->managed.lod). + * Note3: We don't care about the value passed for the surfaces + * before This->managed.lod, negative with this implementation. */ + for (l = 0; l <= This->base.info.last_level; ++l) + NineSurface9_SetResource(tex->surfaces[l], res, l - This->managed.lod); + } else + if (This->base.type == D3DRTYPE_CUBETEXTURE) { + struct NineCubeTexture9 *tex = NineCubeTexture9(This); + unsigned z; + + for (l = 0; l <= This->base.info.last_level; ++l) { + for (z = 0; z < 6; ++z) + NineSurface9_SetResource(tex->surfaces[l * 6 + z], + res, l - This->managed.lod); + } + } else + if (This->base.type == D3DRTYPE_VOLUMETEXTURE) { + struct NineVolumeTexture9 *tex = NineVolumeTexture9(This); + + for (l = 0; l <= This->base.info.last_level; ++l) + NineVolume9_SetResource(tex->volumes[l], res, l - This->managed.lod); + } else { + assert(!"invalid texture type"); + } + + /* We are going to fully upload the new levels, + * no need to update dirty parts of the texture for these */ + min_level_dirty = MAX2(This->managed.lod, This->managed.lod_resident); + } + + /* Update dirty parts of the texture */ + if (This->managed.dirty) { + if (This->base.type == D3DRTYPE_TEXTURE) { + struct NineTexture9 *tex = NineTexture9(This); + struct pipe_box box; + box.z = 0; + box.depth = 1; + + DBG("TEXTURE: dirty rect=(%u,%u) (%ux%u)\n", + tex->dirty_rect.x, tex->dirty_rect.y, + tex->dirty_rect.width, tex->dirty_rect.height); + + /* Note: for l < min_level_dirty, the resource is + * either non-existing (and thus will be entirely re-uploaded + * if the lod changes) or going to have a full upload */ + if (tex->dirty_rect.width) { + for (l = min_level_dirty; l <= last_level; ++l) { + u_box_minify_2d(&box, &tex->dirty_rect, l); + NineSurface9_UploadSelf(tex->surfaces[l], &box); + } + memset(&tex->dirty_rect, 0, sizeof(tex->dirty_rect)); + tex->dirty_rect.depth = 1; + } + } else + if (This->base.type == D3DRTYPE_CUBETEXTURE) { + struct NineCubeTexture9 *tex = NineCubeTexture9(This); + unsigned z; + struct pipe_box box; + box.z = 0; + box.depth = 1; + + for (z = 0; z < 6; ++z) { + DBG("FACE[%u]: dirty rect=(%u,%u) (%ux%u)\n", z, + tex->dirty_rect[z].x, tex->dirty_rect[z].y, + tex->dirty_rect[z].width, tex->dirty_rect[z].height); + + if (tex->dirty_rect[z].width) { + for (l = min_level_dirty; l <= last_level; ++l) { + u_box_minify_2d(&box, &tex->dirty_rect[z], l); + NineSurface9_UploadSelf(tex->surfaces[l * 6 + z], &box); + } + memset(&tex->dirty_rect[z], 0, sizeof(tex->dirty_rect[z])); + tex->dirty_rect[z].depth = 1; + } + } + } else + if (This->base.type == D3DRTYPE_VOLUMETEXTURE) { + struct NineVolumeTexture9 *tex = NineVolumeTexture9(This); + struct pipe_box box; + + DBG("VOLUME: dirty_box=(%u,%u,%u) (%ux%ux%u)\n", + tex->dirty_box.x, tex->dirty_box.y, tex->dirty_box.y, + tex->dirty_box.width, tex->dirty_box.height, tex->dirty_box.depth); + + if (tex->dirty_box.width) { + for (l = 0; l <= last_level; ++l) { + u_box_minify_2d(&box, &tex->dirty_box, l); + NineVolume9_AddDirtyRegion(tex->volumes[l], &tex->dirty_box); + } + memset(&tex->dirty_box, 0, sizeof(tex->dirty_box)); + } + for (l = min_level_dirty; l <= last_level; ++l) + NineVolume9_UploadSelf(tex->volumes[l]); + } else { + assert(!"invalid texture type"); + } + This->managed.dirty = FALSE; + } + /* Upload the new levels */ + if (update_lod) { if (This->base.type == D3DRTYPE_TEXTURE) { struct NineTexture9 *tex = NineTexture9(This); struct pipe_box box; - /* Mark uninitialized levels as dirty. */ box.x = box.y = box.z = 0; box.depth = 1; for (l = This->managed.lod; l < This->managed.lod_resident; ++l) { box.width = u_minify(This->base.info.width0, l); box.height = u_minify(This->base.info.height0, l); - NineSurface9_AddDirtyRect(tex->surfaces[l], &box); + NineSurface9_UploadSelf(tex->surfaces[l], &box); } - for (l = 0; l < This->managed.lod; ++l) - NineSurface9_SetResource(tex->surfaces[l], NULL, -1); - for (; l <= This->base.info.last_level; ++l) - NineSurface9_SetResource(tex->surfaces[l], res, l - This->managed.lod); } else if (This->base.type == D3DRTYPE_CUBETEXTURE) { struct NineCubeTexture9 *tex = NineCubeTexture9(This); struct pipe_box box; unsigned z; - /* Mark uninitialized levels as dirty. */ box.x = box.y = box.z = 0; box.depth = 1; for (l = This->managed.lod; l < This->managed.lod_resident; ++l) { box.width = u_minify(This->base.info.width0, l); box.height = u_minify(This->base.info.height0, l); for (z = 0; z < 6; ++z) - NineSurface9_AddDirtyRect(tex->surfaces[l * 6 + z], &box); - } - for (l = 0; l < This->managed.lod; ++l) { - for (z = 0; z < 6; ++z) - NineSurface9_SetResource(tex->surfaces[l * 6 + z], - NULL, -1); - } - for (; l <= This->base.info.last_level; ++l) { - for (z = 0; z < 6; ++z) - NineSurface9_SetResource(tex->surfaces[l * 6 + z], - res, l - This->managed.lod); + NineSurface9_UploadSelf(tex->surfaces[l * 6 + z], &box); } } else if (This->base.type == D3DRTYPE_VOLUMETEXTURE) { struct NineVolumeTexture9 *tex = NineVolumeTexture9(This); struct pipe_box box; - /* Mark uninitialized levels as dirty. */ box.x = box.y = box.z = 0; for (l = This->managed.lod; l < This->managed.lod_resident; ++l) { box.width = u_minify(This->base.info.width0, l); box.height = u_minify(This->base.info.height0, l); box.depth = u_minify(This->base.info.depth0, l); NineVolume9_AddDirtyRegion(tex->volumes[l], &box); + NineVolume9_UploadSelf(tex->volumes[l]); } - for (l = 0; l < This->managed.lod; ++l) - NineVolume9_SetResource(tex->volumes[l], NULL, -1); - for (; l <= This->base.info.last_level; ++l) - NineVolume9_SetResource(tex->volumes[l], res, l - This->managed.lod); } else { assert(!"invalid texture type"); } - if (This->managed.lod < This->managed.lod_resident) - This->managed.dirty = TRUE; This->managed.lod_resident = This->managed.lod; } - if (!This->managed.dirty) - return D3D_OK; - - if (This->base.type == D3DRTYPE_TEXTURE) { - struct NineTexture9 *tex = NineTexture9(This); - struct pipe_box box; - box.z = 0; - box.depth = 1; - - DBG("TEXTURE: dirty rect=(%u,%u) (%ux%u)\n", - tex->dirty_rect.x, tex->dirty_rect.y, - tex->dirty_rect.width, tex->dirty_rect.height); - - /* Note: for l < This->managed.lod, the resource is - * non-existing, and thus will be entirely re-uploaded - * if This->managed.lod changes */ - if (tex->dirty_rect.width) { - for (l = This->managed.lod; l <= last_level; ++l) { - u_box_minify_2d(&box, &tex->dirty_rect, l); - NineSurface9_UploadSelf(tex->surfaces[l], &box); - } - memset(&tex->dirty_rect, 0, sizeof(tex->dirty_rect)); - tex->dirty_rect.depth = 1; - } - } else - if (This->base.type == D3DRTYPE_CUBETEXTURE) { - struct NineCubeTexture9 *tex = NineCubeTexture9(This); - unsigned z; - struct pipe_box box; - box.z = 0; - box.depth = 1; - - for (z = 0; z < 6; ++z) { - DBG("FACE[%u]: dirty rect=(%u,%u) (%ux%u)\n", z, - tex->dirty_rect[z].x, tex->dirty_rect[z].y, - tex->dirty_rect[z].width, tex->dirty_rect[z].height); - - if (tex->dirty_rect[z].width) { - for (l = This->managed.lod; l <= last_level; ++l) { - u_box_minify_2d(&box, &tex->dirty_rect[z], l); - NineSurface9_UploadSelf(tex->surfaces[l * 6 + z], &box); - } - memset(&tex->dirty_rect[z], 0, sizeof(tex->dirty_rect[z])); - tex->dirty_rect[z].depth = 1; - } - } - } else - if (This->base.type == D3DRTYPE_VOLUMETEXTURE) { - struct NineVolumeTexture9 *tex = NineVolumeTexture9(This); - struct pipe_box box; - - DBG("VOLUME: dirty_box=(%u,%u,%u) (%ux%ux%u)\n", - tex->dirty_box.x, tex->dirty_box.y, tex->dirty_box.y, - tex->dirty_box.width, tex->dirty_box.height, tex->dirty_box.depth); - - if (tex->dirty_box.width) { - for (l = 0; l <= last_level; ++l) { - u_box_minify_2d(&box, &tex->dirty_box, l); - NineVolume9_AddDirtyRegion(tex->volumes[l], &tex->dirty_box); - } - memset(&tex->dirty_box, 0, sizeof(tex->dirty_box)); - } - for (l = This->managed.lod; l <= last_level; ++l) - NineVolume9_UploadSelf(tex->volumes[l]); - } else { - assert(!"invalid texture type"); - } - This->managed.dirty = FALSE; if (This->base.usage & D3DUSAGE_AUTOGENMIPMAP) This->dirty_mip = TRUE; |