mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-06 11:38:05 +02:00
Add another layer on top of the simple 2d regions in intel_regions.[ch]
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.
This commit is contained in:
parent
d4d7fdb43b
commit
3bca9c47f4
6 changed files with 488 additions and 98 deletions
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
218
src/mesa/drivers/dri/i915/intel_mipmap_tree.c
Normal file
218
src/mesa/drivers/dri/i915/intel_mipmap_tree.c
Normal file
|
|
@ -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);
|
||||
|
||||
}
|
||||
156
src/mesa/drivers/dri/i915/intel_mipmap_tree.h
Normal file
156
src/mesa/drivers/dri/i915/intel_mipmap_tree.h
Normal file
|
|
@ -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);
|
||||
dst->cpp,
|
||||
src->pitch, src_offset,
|
||||
dst->pitch, dst_offset,
|
||||
srcx, srcy,
|
||||
dstx, dsty,
|
||||
width, height);
|
||||
|
||||
bmReleaseValidatedBuffers(intel->bm);
|
||||
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;
|
||||
struct bm_buffer_list *list = bmNewBufferList();
|
||||
|
||||
LOCK_HARDWARE(intel);
|
||||
bmAddBuffer(intel->bm, list, dst->buffer, BM_WRITE, NULL, &dst_offset);
|
||||
|
||||
bmClearBufferList(intel->bm);
|
||||
bmAddBuffer(intel->bm, dest->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;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue