which keeps track of a whole, well-defined mipmap tree. These are a fixed layout on intel hardware and managing them is complicated in the face of GL's TexImage function calls where data can arrive in any order, making it difficult to guess a layout ahead of time. Wrapping mipmap trees up in a struct and programming interface like this reduces the burden elsewhere.tags/mesa_20060201
| @@ -10,6 +10,7 @@ | |||
| /* The buffer manager context. Opaque. | |||
| */ | |||
| struct bufmgr; | |||
| struct bm_buffer_list; | |||
| struct bufmgr *bm_fake_intel_Attach( struct intel_context *intel ); | |||
| @@ -23,18 +24,13 @@ void bmInitPool( struct bufmgr *, | |||
| unsigned long high_offset, | |||
| void *virtual_base ); | |||
| #define BM_MEM_SYS 0x1 | |||
| #define BM_MEM_LOCAL 0x1 | |||
| #define BM_MEM_AGP 0x2 | |||
| #define BM_MEM_VRAM 0x4 /* not used */ | |||
| #define BM_WRITE 0x100 /* not used */ | |||
| #define BM_READ 0x200 /* not used */ | |||
| /* Maximum number of buffers to pass to bmValidateBufferList: | |||
| */ | |||
| #define BM_VALIDATE_MAX 32 | |||
| /* Flags for validate. If both NO_UPLOAD and NO_EVICT are specified, | |||
| * ValidateBuffers is essentially a query. | |||
| @@ -76,34 +72,39 @@ void bmUnmapBuffer( struct bufmgr *, | |||
| /* To be called prior to emitting commands to hardware which reference | |||
| * these buffers. | |||
| * | |||
| * ClearBufferList() and AddBuffer() build up a list of buffers to be | |||
| * NewBufferList() and AddBuffer() build up a list of buffers to be | |||
| * validated. The buffer list provides information on where the | |||
| * buffers should be placed and whether their contents need to be | |||
| * preserved on copying. The offset data elements are return values | |||
| * from this function telling the driver exactly where the buffers are | |||
| * currently located. | |||
| * | |||
| * ValidateBuffers() performs the actual validation. | |||
| * ValidateBufferList() performs the actual validation and returns the | |||
| * buffer pools and offsets within the pools. | |||
| * | |||
| * ReleaseValidatedBuffers() must be called to set fences and other | |||
| * FenceBufferList() must be called to set fences and other | |||
| * housekeeping before unlocking after a successful call to | |||
| * ValidateBuffers(). | |||
| * | |||
| * The buffer manager knows how to emit and test fences directly | |||
| * through the drm and without callbacks or whatever into the driver. | |||
| * ValidateBufferList(). The buffer manager knows how to emit and test | |||
| * fences directly through the drm and without callbacks to the | |||
| * driver. | |||
| */ | |||
| void bmClearBufferList( struct bufmgr * ); | |||
| struct bm_buffer_list *bmNewBufferList( void ); | |||
| void bmAddBuffer( struct bufmgr *bm, | |||
| void bmAddBuffer( struct bufmgr *, | |||
| struct bm_buffer_list *list, | |||
| unsigned buffer, | |||
| unsigned flags, | |||
| unsigned *pool_return, | |||
| unsigned *offset_return ); | |||
| int bmValidateBufferList( struct bufmgr *, | |||
| struct bm_buffer_list *, | |||
| unsigned flags ); | |||
| void bmReleaseValidatedBuffers( struct bufmgr * ); | |||
| void bmFenceBufferList( struct bufmgr *, | |||
| struct bm_buffer_list * ); | |||
| void bmFreeBufferList( struct bm_buffer_list * ); | |||
| /* This functionality is used by the buffer manager, not really sure | |||
| @@ -18,8 +18,11 @@ | |||
| struct _mesa_HashTable; | |||
| #define BM_MEM_LOCAL 0x1 | |||
| #define BM_MEM_AGP 0x2 | |||
| /* Maximum number of buffers to pass to bmValidateBufferList: | |||
| */ | |||
| #define BM_LIST_MAX 32 | |||
| /* Wrapper around mm.c's mem_block, which understands that you must | |||
| * wait for fences to expire before memory can be freed. This is | |||
| @@ -53,6 +56,16 @@ struct pool { | |||
| struct block freed; | |||
| }; | |||
| /* List of buffers to validate: | |||
| */ | |||
| struct bm_buffer_list { | |||
| struct buffer *buffer[BM_LIST_MAX]; | |||
| unsigned *offset_return[BM_LIST_MAX]; | |||
| unsigned nr; | |||
| unsigned need_fence; | |||
| }; | |||
| struct bufmgr { | |||
| struct intel_context *intel; | |||
| struct buffer buffer_list; | |||
| @@ -61,14 +74,7 @@ struct bufmgr { | |||
| unsigned buf_nr; /* for generating ids */ | |||
| /* List of buffers to validate: | |||
| */ | |||
| struct buffer *validated[BM_VALIDATE_MAX]; | |||
| unsigned *offset_return[BM_VALIDATE_MAX]; | |||
| unsigned nr_validated; | |||
| unsigned last_fence; | |||
| unsigned in_progress; | |||
| }; | |||
| @@ -194,7 +200,7 @@ static int move_buffers( struct bufmgr *bm, | |||
| int newMemType, | |||
| int flags ) | |||
| { | |||
| struct block *newMem[BM_VALIDATE_MAX]; | |||
| struct block *newMem[BM_LIST_MAX]; | |||
| GLint i; | |||
| memset(newMem, 0, sizeof(newMem)); | |||
| @@ -476,28 +482,34 @@ void bm_fake_SetFixedBufferParams( struct bufmgr *bm | |||
| /* Build the list of buffers to validate: | |||
| */ | |||
| void bmClearBufferList( struct bufmgr *bm ) | |||
| struct bm_buffer_list *bmNewBufferList( void ) | |||
| { | |||
| assert(!bm->in_progress); | |||
| bm->nr_validated = 0; | |||
| struct bm_buffer_list *list = calloc(sizeof(*list), 1); | |||
| return list; | |||
| } | |||
| void bmAddBuffer( struct bufmgr *bm, | |||
| struct bm_buffer_list *list, | |||
| unsigned buffer, | |||
| unsigned flags, | |||
| unsigned *pool_return, | |||
| unsigned *offset_return ) | |||
| { | |||
| assert(bm->nr_validated < BM_VALIDATE_MAX); | |||
| assert(list->nr < BM_LIST_MAX); | |||
| bm->validated[bm->nr_validated] = _mesa_HashLookup(bm->hash, buffer); | |||
| bm->offset_return[bm->nr_validated] = offset_return; | |||
| bm->nr_validated++; | |||
| list->buffer[list->nr] = _mesa_HashLookup(bm->hash, buffer); | |||
| list->offset_return[list->nr] = offset_return; | |||
| list->nr++; | |||
| if (pool_return) | |||
| *pool_return = 0; | |||
| } | |||
| void bmFreeBufferList( struct bm_buffer_list *list ) | |||
| { | |||
| assert(!list->need_fence); | |||
| free(list); | |||
| } | |||
| @@ -510,17 +522,18 @@ void bmAddBuffer( struct bufmgr *bm, | |||
| * buffers are currently located. | |||
| */ | |||
| int bmValidateBufferList( struct bufmgr *bm, | |||
| struct bm_buffer_list *list, | |||
| unsigned flags ) | |||
| { | |||
| unsigned i; | |||
| unsigned total = 0; | |||
| if (bm->nr_validated > BM_VALIDATE_MAX) | |||
| if (list->nr > BM_LIST_MAX) | |||
| return 0; | |||
| for (i = 0; i < bm->nr_validated; i++) { | |||
| assert(!bm->validated[i]->mapped); | |||
| total += bm->validated[i]->size; | |||
| for (i = 0; i < list->nr; i++) { | |||
| assert(!list->buffer[i]->mapped); | |||
| total += list->buffer[i]->size; | |||
| } | |||
| /* Don't need to try allocation in this case: | |||
| @@ -532,13 +545,13 @@ int bmValidateBufferList( struct bufmgr *bm, | |||
| * succeeds. This is a pretty poor strategy but really hard to do | |||
| * better without more infrastucture... Which is coming - hooray! | |||
| */ | |||
| while (!move_buffers(bm, bm->validated, bm->nr_validated, BM_MEM_AGP, flags)) { | |||
| while (!move_buffers(bm, list->buffer, list->nr, BM_MEM_AGP, flags)) { | |||
| if ((flags & BM_NO_EVICT) || | |||
| !evict_lru(bm)) | |||
| return 0; | |||
| } | |||
| bm->in_progress = 1; | |||
| list->need_fence = 1; | |||
| return 1; | |||
| } | |||
| @@ -551,20 +564,21 @@ int bmValidateBufferList( struct bufmgr *bm, | |||
| * The buffer manager knows how to emit and test fences directly | |||
| * through the drm and without callbacks or whatever into the driver. | |||
| */ | |||
| void bmReleaseValidatedBuffers( struct bufmgr *bm ) | |||
| void bmFenceBufferList( struct bufmgr *bm, struct bm_buffer_list *list ) | |||
| { | |||
| unsigned i; | |||
| assert(bm->in_progress); | |||
| bm->in_progress = 0; | |||
| assert(list->need_fence); | |||
| list->need_fence = 0; | |||
| bm->last_fence = bmSetFence( bm ); | |||
| /* Move all buffers to head of resident list and set their fences | |||
| */ | |||
| for (i = 0; i < bm->nr_validated; i++) { | |||
| assert(bm->validated[i]->block->buf == bm->validated[i]); | |||
| move_to_head(&bm->pool.lru, bm->validated[i]->block); | |||
| bm->validated[i]->block->fence = bm->last_fence; | |||
| for (i = 0; i < list->nr; i++) { | |||
| assert(list->buffer[i]->block->buf == list->buffer[i]); | |||
| move_to_head(&bm->pool.lru, list->buffer[i]->block); | |||
| list->buffer[i]->block->fence = bm->last_fence; | |||
| } | |||
| } | |||
| @@ -0,0 +1,218 @@ | |||
| /************************************************************************** | |||
| * | |||
| * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas. | |||
| * All Rights Reserved. | |||
| * | |||
| * Permission is hereby granted, free of charge, to any person obtaining a | |||
| * copy of this software and associated documentation files (the | |||
| * "Software"), to deal in the Software without restriction, including | |||
| * without limitation the rights to use, copy, modify, merge, publish, | |||
| * distribute, sub license, and/or sell copies of the Software, and to | |||
| * permit persons to whom the Software is furnished to do so, subject to | |||
| * the following conditions: | |||
| * | |||
| * The above copyright notice and this permission notice (including the | |||
| * next paragraph) shall be included in all copies or substantial portions | |||
| * of the Software. | |||
| * | |||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | |||
| * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |||
| * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. | |||
| * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR | |||
| * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | |||
| * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | |||
| * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |||
| * | |||
| **************************************************************************/ | |||
| #include "intel_context.h" | |||
| #include "intel_mipmap_tree.h" | |||
| #include "intel_regions.h" | |||
| #include "bufmgr.h" | |||
| static GLenum target_to_target( GLenum target ) | |||
| { | |||
| switch (target) { | |||
| case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB: | |||
| case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB: | |||
| case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB: | |||
| case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB: | |||
| case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB: | |||
| case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB: | |||
| return GL_TEXTURE_CUBE_MAP_ARB; | |||
| default: | |||
| return target; | |||
| } | |||
| } | |||
| struct intel_mipmap_tree *intel_miptree_create( struct intel_context *intel, | |||
| GLenum target, | |||
| GLenum internal_format, | |||
| GLuint first_level, | |||
| GLuint last_level, | |||
| GLuint width0, | |||
| GLuint height0, | |||
| GLuint depth0, | |||
| GLuint cpp, | |||
| GLboolean compressed) | |||
| { | |||
| GLboolean ok; | |||
| struct intel_mipmap_tree *mt = calloc(sizeof(*mt), 1); | |||
| mt->target = target_to_target(target); | |||
| mt->internal_format = internal_format; | |||
| mt->first_level = first_level; | |||
| mt->last_level = last_level; | |||
| mt->width0 = width0; | |||
| mt->height0 = height0; | |||
| mt->depth0 = depth0; | |||
| mt->cpp = cpp; | |||
| mt->compressed = compressed; | |||
| switch (intel->intelScreen->deviceID) { | |||
| case PCI_CHIP_I945_G: | |||
| ok = i945_miptree_layout( mt ); | |||
| break; | |||
| case PCI_CHIP_I915_G: | |||
| case PCI_CHIP_I915_GM: | |||
| ok = i915_miptree_layout( mt ); | |||
| break; | |||
| default: | |||
| ok = 0; | |||
| break; | |||
| } | |||
| if (ok) | |||
| mt->region = intel_region_alloc( intel, | |||
| mt->cpp, | |||
| mt->pitch, | |||
| mt->total_height ); | |||
| if (!mt->region) { | |||
| free(mt); | |||
| return NULL; | |||
| } | |||
| return mt; | |||
| } | |||
| struct intel_mipmap_tree *intel_miptree_reference( struct intel_mipmap_tree *mt ) | |||
| { | |||
| mt->refcount++; | |||
| return mt; | |||
| } | |||
| void intel_miptree_release( struct intel_context *intel, | |||
| struct intel_mipmap_tree *mt ) | |||
| { | |||
| if (--mt->refcount) { | |||
| intel_region_release(intel, mt->region); | |||
| free(mt); | |||
| } | |||
| } | |||
| /* Can the image be pulled into a unified mipmap tree. This mirrors | |||
| * the completeness test in a lot of ways. | |||
| * | |||
| * Not sure whether I want to pass gl_texture_image here. | |||
| */ | |||
| GLboolean intel_miptree_match_image( struct intel_mipmap_tree *mt, | |||
| struct gl_texture_image *image, | |||
| GLuint face, | |||
| GLuint level ) | |||
| { | |||
| /* Images with borders are never pulled into mipmap trees. | |||
| */ | |||
| if (image->Border) | |||
| return GL_FALSE; | |||
| if (image->InternalFormat != mt->internal_format || | |||
| image->IsCompressed != mt->compressed) | |||
| return GL_FALSE; | |||
| /* Test image dimensions against the base level image adjusted for | |||
| * minification. This will also catch images not present in the | |||
| * tree, changed targets, etc. | |||
| */ | |||
| if (image->Width != mt->offset[face][level].width || | |||
| image->Height != mt->offset[face][level].height || | |||
| image->Depth != mt->offset[face][level].depth) | |||
| return GL_FALSE; | |||
| return GL_TRUE; | |||
| } | |||
| GLubyte *intel_miptree_image_map(struct intel_context *intel, | |||
| struct intel_mipmap_tree *mt, | |||
| GLuint face, | |||
| GLuint level, | |||
| GLuint *stride) | |||
| { | |||
| GLubyte *img = intel_region_map(intel, mt->region); | |||
| if (stride) | |||
| *stride = mt->pitch * mt->cpp; | |||
| return img + (mt->offset[face][level].x + | |||
| mt->offset[face][level].y * mt->pitch) * mt->cpp; | |||
| } | |||
| void intel_miptree_image_unmap(struct intel_context *intel, | |||
| struct intel_mipmap_tree *mt) | |||
| { | |||
| intel_region_unmap(intel, mt->region); | |||
| } | |||
| /* Upload data for a particular image. | |||
| * | |||
| * TODO: 3D textures | |||
| */ | |||
| void intel_miptree_image_data(struct intel_context *intel, | |||
| struct intel_mipmap_tree *dst, | |||
| GLuint face, | |||
| GLuint level, | |||
| void *src, GLuint src_pitch ) | |||
| { | |||
| intel_region_data(intel, | |||
| dst->region, | |||
| dst->offset[face][level].x, | |||
| dst->offset[face][level].y, | |||
| src, | |||
| src_pitch, | |||
| 0, 0, /* source x,y */ | |||
| dst->offset[face][level].width, | |||
| dst->offset[face][level].height); | |||
| } | |||
| /* Copy mipmap image between trees | |||
| */ | |||
| void intel_miptree_image_copy( struct intel_context *intel, | |||
| struct intel_mipmap_tree *dst, | |||
| GLuint face, GLuint level, | |||
| struct intel_mipmap_tree *src ) | |||
| { | |||
| assert(src->offset[face][level].width == | |||
| dst->offset[face][level].width); | |||
| assert(src->offset[face][level].height == | |||
| dst->offset[face][level].height); | |||
| intel_region_copy(intel, | |||
| dst->region, | |||
| dst->offset[face][level].x, | |||
| dst->offset[face][level].y, | |||
| src->region, | |||
| src->offset[face][level].x, | |||
| src->offset[face][level].y, | |||
| src->offset[face][level].width, | |||
| src->offset[face][level].height); | |||
| } | |||
| @@ -0,0 +1,156 @@ | |||
| /************************************************************************** | |||
| * | |||
| * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas. | |||
| * All Rights Reserved. | |||
| * | |||
| * Permission is hereby granted, free of charge, to any person obtaining a | |||
| * copy of this software and associated documentation files (the | |||
| * "Software"), to deal in the Software without restriction, including | |||
| * without limitation the rights to use, copy, modify, merge, publish, | |||
| * distribute, sub license, and/or sell copies of the Software, and to | |||
| * permit persons to whom the Software is furnished to do so, subject to | |||
| * the following conditions: | |||
| * | |||
| * The above copyright notice and this permission notice (including the | |||
| * next paragraph) shall be included in all copies or substantial portions | |||
| * of the Software. | |||
| * | |||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | |||
| * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |||
| * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. | |||
| * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR | |||
| * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | |||
| * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | |||
| * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |||
| * | |||
| **************************************************************************/ | |||
| #ifndef INTEL_MIPMAP_TREE_H | |||
| #define INTEL_MIPMAP_TREE_H | |||
| #include "intel_regions.h" | |||
| /* A layer on top of the intel_regions code which adds: | |||
| * | |||
| * - Code to size and layout a region to hold a set of mipmaps. | |||
| * - Query to determine if a new image fits in an existing tree. | |||
| * - More refcounting | |||
| * - maybe able to remove refcounting from intel_region? | |||
| * - ? | |||
| * | |||
| * The fixed mipmap layout of intel hardware where one offset | |||
| * specifies the position of all images in a mipmap hierachy | |||
| * complicates the implementation of GL texture image commands, | |||
| * compared to hardware where each image is specified with an | |||
| * independent offset. | |||
| * | |||
| * In an ideal world, each texture object would be associated with a | |||
| * single bufmgr buffer or 2d intel_region, and all the images within | |||
| * the texture object would slot into the tree as they arrive. The | |||
| * reality can be a little messier, as images can arrive from the user | |||
| * with sizes that don't fit in the existing tree, or in an order | |||
| * where the tree layout cannot be guessed immediately. | |||
| * | |||
| * This structure encodes an idealized mipmap tree. The GL image | |||
| * commands build these where possible, otherwise store the images in | |||
| * temporary system buffers. | |||
| */ | |||
| struct intel_mipmap_offset { | |||
| GLuint x; | |||
| GLuint y; | |||
| GLuint width; | |||
| GLuint height; | |||
| GLuint depth; /* how will this work? */ | |||
| }; | |||
| struct intel_mipmap_tree { | |||
| /* Effectively the key: | |||
| */ | |||
| GLenum target; | |||
| GLenum internal_format; | |||
| GLuint first_level; | |||
| GLuint last_level; | |||
| GLuint width0, height0, depth0; | |||
| GLuint cpp; | |||
| GLboolean compressed; | |||
| /* Derived from the above: | |||
| */ | |||
| GLuint pitch; | |||
| GLuint depth_pitch; /* per-image on i945? */ | |||
| GLuint total_height; | |||
| struct intel_mipmap_offset offset[MAX_FACES][MAX_TEXTURE_LEVELS]; | |||
| /* The data is held here: | |||
| */ | |||
| struct intel_region *region; | |||
| /* These are also refcounted: | |||
| */ | |||
| GLuint refcount; | |||
| }; | |||
| struct intel_mipmap_tree *intel_miptree_create( struct intel_context *intel, | |||
| GLenum target, | |||
| GLenum internal_format, | |||
| GLuint first_level, | |||
| GLuint last_level, | |||
| GLuint width0, | |||
| GLuint height0, | |||
| GLuint depth0, | |||
| GLuint cpp, | |||
| GLboolean compressed); | |||
| struct intel_mipmap_tree *intel_miptree_reference( struct intel_mipmap_tree * ); | |||
| void intel_miptree_release( struct intel_context *intel, | |||
| struct intel_mipmap_tree *mt ); | |||
| /* Check if an image fits an existing mipmap tree layout | |||
| */ | |||
| GLboolean intel_miptree_match_image( struct intel_mipmap_tree *mt, | |||
| struct gl_texture_image *image, | |||
| GLuint face, | |||
| GLuint level ); | |||
| /* Return a pointer to an image within a tree. Return image stride as | |||
| * well. | |||
| */ | |||
| GLubyte *intel_miptree_image_map( struct intel_context *intel, | |||
| struct intel_mipmap_tree *mt, | |||
| GLuint face, | |||
| GLuint level, | |||
| GLuint *stride ); | |||
| void intel_miptree_image_unmap( struct intel_context *intel, | |||
| struct intel_mipmap_tree *mt ); | |||
| /* Upload an image into a tree | |||
| */ | |||
| void intel_miptree_image_data(struct intel_context *intel, | |||
| struct intel_mipmap_tree *dst, | |||
| GLuint face, | |||
| GLuint level, | |||
| void *src, GLuint src_pitch ); | |||
| /* Copy an image between two trees | |||
| */ | |||
| void intel_miptree_image_copy( struct intel_context *intel, | |||
| struct intel_mipmap_tree *dst, | |||
| GLuint face, GLuint level, | |||
| struct intel_mipmap_tree *src ); | |||
| /* i915_mipmap_tree.c: | |||
| */ | |||
| GLboolean i915_miptree_layout( struct intel_mipmap_tree *mt ); | |||
| GLboolean i945_miptree_layout( struct intel_mipmap_tree *mt ); | |||
| #endif | |||
| @@ -106,9 +106,9 @@ static void _mesa_copy_rect( GLubyte *dst, | |||
| GLuint width, | |||
| GLuint height, | |||
| GLubyte *src, | |||
| GLuint src_pitch, | |||
| GLuint src_x, | |||
| GLuint src_y, | |||
| GLuint src_pitch ) | |||
| GLuint src_y ) | |||
| { | |||
| GLuint i; | |||
| @@ -195,24 +195,24 @@ static void _mesa_fill_rect( GLubyte *dst, | |||
| * Currently always memcpy. | |||
| */ | |||
| void intel_region_data(struct intel_context *intel, | |||
| struct intel_region *dest, | |||
| GLuint destx, GLuint desty, | |||
| struct intel_region *dst, | |||
| GLuint dstx, GLuint dsty, | |||
| void *src, GLuint src_pitch, | |||
| GLuint srcx, GLuint srcy, | |||
| GLuint width, GLuint height) | |||
| { | |||
| LOCK_HARDWARE(intel); | |||
| _mesa_copy_rect(intel_region_map(intel, dest), | |||
| dest->cpp, | |||
| dest->pitch, | |||
| destx, desty, | |||
| destx + width, desty + height, | |||
| _mesa_copy_rect(intel_region_map(intel, dst), | |||
| dst->cpp, | |||
| dst->pitch, | |||
| dstx, dsty, | |||
| width, height, | |||
| src, | |||
| srcx, srcy, | |||
| src_pitch); | |||
| src_pitch, | |||
| srcx, srcy); | |||
| intel_region_unmap(intel, dest); | |||
| intel_region_unmap(intel, dst); | |||
| UNLOCK_HARDWARE(intel); | |||
| @@ -222,52 +222,51 @@ void intel_region_data(struct intel_context *intel, | |||
| * push buffers into AGP - will currently do so whenever possible. | |||
| */ | |||
| void intel_region_copy( struct intel_context *intel, | |||
| struct intel_region *dest, | |||
| GLuint destx, GLuint desty, | |||
| struct intel_region *dst, | |||
| GLuint dstx, GLuint dsty, | |||
| struct intel_region *src, | |||
| GLuint srcx, GLuint srcy, | |||
| GLuint width, GLuint height ) | |||
| { | |||
| unsigned dst_offset; | |||
| unsigned src_offset; | |||
| struct bm_buffer_list *list = bmNewBufferList(); | |||
| assert(src->cpp == dest->cpp); | |||
| assert(src->cpp == dst->cpp); | |||
| LOCK_HARDWARE(intel); | |||
| bmClearBufferList(intel->bm); | |||
| bmAddBuffer(intel->bm, dest->buffer, BM_WRITE, NULL, &dst_offset); | |||
| bmAddBuffer(intel->bm, src->buffer, BM_READ, NULL, &src_offset); | |||
| bmAddBuffer(intel->bm, list, dst->buffer, BM_WRITE, NULL, &dst_offset); | |||
| bmAddBuffer(intel->bm, list, src->buffer, BM_READ, NULL, &src_offset); | |||
| /* What I really want to do is query if both buffers are already | |||
| * uploaded: | |||
| */ | |||
| if (bmValidateBufferList(intel->bm, BM_NO_EVICT|BM_NO_UPLOAD)) { | |||
| if (bmValidateBufferList(intel->bm, list, BM_NO_EVICT|BM_NO_UPLOAD)) { | |||
| intelEmitCopyBlitLocked(intel, | |||
| dest->cpp, | |||
| src->pitch, | |||
| src_offset, | |||
| dest->pitch, | |||
| dst_offset, | |||
| srcx, srcy, | |||
| destx, desty, | |||
| width, height); | |||
| bmReleaseValidatedBuffers(intel->bm); | |||
| dst->cpp, | |||
| src->pitch, src_offset, | |||
| dst->pitch, dst_offset, | |||
| srcx, srcy, | |||
| dstx, dsty, | |||
| width, height); | |||
| bmFenceBufferList(intel->bm, list); | |||
| } | |||
| else { | |||
| _mesa_copy_rect(intel_region_map(intel, dest), | |||
| dest->cpp, | |||
| dest->pitch, | |||
| destx, desty, | |||
| _mesa_copy_rect(intel_region_map(intel, dst), | |||
| dst->cpp, | |||
| dst->pitch, | |||
| dstx, dsty, | |||
| width, height, | |||
| intel_region_map(intel, src), | |||
| srcx, srcy, | |||
| src->pitch); | |||
| intel_region_unmap(intel, dest); | |||
| intel_region_unmap(intel, dst); | |||
| intel_region_unmap(intel, src); | |||
| } | |||
| bmFreeBufferList(list); | |||
| UNLOCK_HARDWARE(intel); | |||
| } | |||
| @@ -275,40 +274,40 @@ void intel_region_copy( struct intel_context *intel, | |||
| * push buffers into AGP - will currently do so whenever possible. | |||
| */ | |||
| void intel_region_fill( struct intel_context *intel, | |||
| struct intel_region *dest, | |||
| GLuint destx, GLuint desty, | |||
| struct intel_region *dst, | |||
| GLuint dstx, GLuint dsty, | |||
| GLuint width, GLuint height, | |||
| GLuint color ) | |||
| { | |||
| unsigned dst_offset; | |||
| LOCK_HARDWARE(intel); | |||
| struct bm_buffer_list *list = bmNewBufferList(); | |||
| bmClearBufferList(intel->bm); | |||
| bmAddBuffer(intel->bm, dest->buffer, BM_WRITE, NULL, &dst_offset); | |||
| LOCK_HARDWARE(intel); | |||
| bmAddBuffer(intel->bm, list, dst->buffer, BM_WRITE, NULL, &dst_offset); | |||
| if (bmValidateBufferList(intel->bm, BM_NO_EVICT)) { | |||
| if (bmValidateBufferList(intel->bm, list, BM_NO_EVICT)) { | |||
| intelEmitFillBlitLocked(intel, | |||
| dest->cpp, | |||
| dest->pitch, | |||
| dst->cpp, | |||
| dst->pitch, | |||
| dst_offset, | |||
| destx, desty, | |||
| dstx, dsty, | |||
| width, height, | |||
| color ); | |||
| bmReleaseValidatedBuffers(intel->bm); | |||
| bmFenceBufferList(intel->bm, list); | |||
| } | |||
| else { | |||
| _mesa_fill_rect(intel_region_map(intel, dest), | |||
| dest->cpp, | |||
| dest->pitch, | |||
| destx, desty, | |||
| destx + width, desty + height, | |||
| _mesa_fill_rect(intel_region_map(intel, dst), | |||
| dst->cpp, | |||
| dst->pitch, | |||
| dstx, dsty, | |||
| width, height, | |||
| color); | |||
| intel_region_unmap(intel, dest); | |||
| intel_region_unmap(intel, dst); | |||
| } | |||
| bmFreeBufferList(list); | |||
| UNLOCK_HARDWARE(intel); | |||
| } | |||
| @@ -28,6 +28,9 @@ | |||
| #ifndef INTEL_REGIONS_H | |||
| #define INTEL_REGIONS_H | |||
| #include "mtypes.h" | |||
| struct intel_context; | |||
| /* A layer on top of the bufmgr buffers that adds a few useful things: | |||
| * | |||
| @@ -36,7 +39,6 @@ | |||
| * - Buffer dimensions - pitch and height. | |||
| * - Blitter commands for copying 2D regions between buffers. | |||
| */ | |||
| struct intel_region { | |||
| GLuint buffer; | |||
| GLuint refcount; | |||