summaryrefslogtreecommitdiff
path: root/src/mesa/drivers/dri/intel
diff options
context:
space:
mode:
Diffstat (limited to 'src/mesa/drivers/dri/intel')
-rw-r--r--src/mesa/drivers/dri/intel/intel_buffers.c32
-rw-r--r--src/mesa/drivers/dri/intel/intel_bufmgr_ttm.c192
-rw-r--r--src/mesa/drivers/dri/intel/intel_bufmgr_ttm.h3
-rw-r--r--src/mesa/drivers/dri/intel/intel_context.c24
-rw-r--r--src/mesa/drivers/dri/intel/intel_context.h10
-rw-r--r--src/mesa/drivers/dri/intel/intel_fbo.c64
-rw-r--r--src/mesa/drivers/dri/intel/intel_mipmap_tree.c31
-rw-r--r--src/mesa/drivers/dri/intel/intel_mipmap_tree.h19
-rw-r--r--src/mesa/drivers/dri/intel/intel_pixel_bitmap.c20
-rw-r--r--src/mesa/drivers/dri/intel/intel_screen.c43
-rw-r--r--src/mesa/drivers/dri/intel/intel_tex.c3
-rw-r--r--src/mesa/drivers/dri/intel/intel_tex.h3
-rw-r--r--src/mesa/drivers/dri/intel/intel_tex_image.c82
-rw-r--r--src/mesa/drivers/dri/intel/intel_tex_subimage.c14
14 files changed, 394 insertions, 146 deletions
diff --git a/src/mesa/drivers/dri/intel/intel_buffers.c b/src/mesa/drivers/dri/intel/intel_buffers.c
index 5199f833e2..2a25f079e9 100644
--- a/src/mesa/drivers/dri/intel/intel_buffers.c
+++ b/src/mesa/drivers/dri/intel/intel_buffers.c
@@ -300,6 +300,7 @@ intelWindowMoved(struct intel_context *intel)
default:
intelSetFrontClipRects(intel);
}
+
}
if (!intel->intelScreen->driScrnPriv->dri2.enabled &&
@@ -894,7 +895,7 @@ void
intel_draw_buffer(GLcontext * ctx, struct gl_framebuffer *fb)
{
struct intel_context *intel = intel_context(ctx);
- struct intel_region *colorRegion, *depthRegion = NULL;
+ struct intel_region *colorRegions[MAX_DRAW_BUFFERS], *depthRegion = NULL;
struct intel_renderbuffer *irbDepth = NULL, *irbStencil = NULL;
int front = 0; /* drawing to front color buffer? */
@@ -933,14 +934,24 @@ intel_draw_buffer(GLcontext * ctx, struct gl_framebuffer *fb)
/*
* How many color buffers are we drawing into?
*/
- if (fb->_NumColorDrawBuffers != 1) {
- /* writing to 0 or 2 or 4 color buffers */
- /*_mesa_debug(ctx, "Software rendering\n");*/
+ if (fb->_NumColorDrawBuffers == 0) {
+ /* writing to 0 */
FALLBACK(intel, INTEL_FALLBACK_DRAW_BUFFER, GL_TRUE);
- colorRegion = NULL;
+ colorRegions[0] = NULL;
if (fb->Name != 0)
intelSetRenderbufferClipRects(intel);
+ } else if (fb->_NumColorDrawBuffers > 1) {
+ int i;
+ struct intel_renderbuffer *irb;
+ FALLBACK(intel, INTEL_FALLBACK_DRAW_BUFFER, GL_FALSE);
+
+ if (fb->Name != 0)
+ intelSetRenderbufferClipRects(intel);
+ for (i = 0; i < fb->_NumColorDrawBuffers; i++) {
+ irb = intel_renderbuffer(fb->_ColorDrawBuffers[i]);
+ colorRegions[i] = (irb && irb->region) ? irb->region : NULL;
+ }
}
else {
/* draw to exactly one color buffer */
@@ -958,11 +969,11 @@ intel_draw_buffer(GLcontext * ctx, struct gl_framebuffer *fb)
/* drawing to window system buffer */
if (front) {
intelSetFrontClipRects(intel);
- colorRegion = intel_get_rb_region(fb, BUFFER_FRONT_LEFT);
+ colorRegions[0] = intel_get_rb_region(fb, BUFFER_FRONT_LEFT);
}
else {
intelSetBackClipRects(intel);
- colorRegion = intel_get_rb_region(fb, BUFFER_BACK_LEFT);
+ colorRegions[0]= intel_get_rb_region(fb, BUFFER_BACK_LEFT);
}
}
else {
@@ -970,7 +981,7 @@ intel_draw_buffer(GLcontext * ctx, struct gl_framebuffer *fb)
struct intel_renderbuffer *irb;
intelSetRenderbufferClipRects(intel);
irb = intel_renderbuffer(fb->_ColorDrawBuffers[0]);
- colorRegion = (irb && irb->region) ? irb->region : NULL;
+ colorRegions[0] = (irb && irb->region) ? irb->region : NULL;
}
}
@@ -982,7 +993,7 @@ intel_draw_buffer(GLcontext * ctx, struct gl_framebuffer *fb)
else
ctx->NewState |= _NEW_POLYGON;
- if (!colorRegion) {
+ if (!colorRegions[0]) {
FALLBACK(intel, INTEL_FALLBACK_DRAW_BUFFER, GL_TRUE);
}
else {
@@ -1055,7 +1066,8 @@ intel_draw_buffer(GLcontext * ctx, struct gl_framebuffer *fb)
ctx->NewState |= _NEW_DEPTH;
}
- intel->vtbl.set_draw_region(intel, colorRegion, depthRegion);
+ intel->vtbl.set_draw_region(intel, colorRegions, depthRegion,
+ fb->_NumColorDrawBuffers);
/* update viewport since it depends on window size */
if (ctx->Driver.Viewport) {
diff --git a/src/mesa/drivers/dri/intel/intel_bufmgr_ttm.c b/src/mesa/drivers/dri/intel/intel_bufmgr_ttm.c
index fb65e66555..f164b48963 100644
--- a/src/mesa/drivers/dri/intel/intel_bufmgr_ttm.c
+++ b/src/mesa/drivers/dri/intel/intel_bufmgr_ttm.c
@@ -72,6 +72,28 @@ struct intel_validate_entry {
struct drm_i915_op_arg bo_arg;
};
+struct dri_ttm_bo_bucket_entry {
+ drmBO drm_bo;
+ struct dri_ttm_bo_bucket_entry *next;
+};
+
+struct dri_ttm_bo_bucket {
+ struct dri_ttm_bo_bucket_entry *head;
+ struct dri_ttm_bo_bucket_entry **tail;
+ /**
+ * Limit on the number of entries in this bucket.
+ *
+ * 0 means that this caching at this bucket size is disabled.
+ * -1 means that there is no limit to caching at this size.
+ */
+ int max_entries;
+ int num_entries;
+};
+
+/* Arbitrarily chosen, 16 means that the maximum size we'll cache for reuse
+ * is 1 << 16 pages, or 256MB.
+ */
+#define INTEL_TTM_BO_BUCKETS 16
typedef struct _dri_bufmgr_ttm {
dri_bufmgr bufmgr;
@@ -84,6 +106,9 @@ typedef struct _dri_bufmgr_ttm {
struct intel_validate_entry *validate_array;
int validate_array_size;
int validate_count;
+
+ /** Array of lists of cached drmBOs of power-of-two sizes */
+ struct dri_ttm_bo_bucket cache_bucket[INTEL_TTM_BO_BUCKETS];
} dri_bufmgr_ttm;
/**
@@ -137,6 +162,41 @@ typedef struct _dri_fence_ttm
drmFence drm_fence;
} dri_fence_ttm;
+static int
+logbase2(int n)
+{
+ GLint i = 1;
+ GLint log2 = 0;
+
+ while (n > i) {
+ i *= 2;
+ log2++;
+ }
+
+ return log2;
+}
+
+static struct dri_ttm_bo_bucket *
+dri_ttm_bo_bucket_for_size(dri_bufmgr_ttm *bufmgr_ttm, unsigned long size)
+{
+ int i;
+
+ /* We only do buckets in power of two increments */
+ if ((size & (size - 1)) != 0)
+ return NULL;
+
+ /* We should only see sizes rounded to pages. */
+ assert((size % 4096) == 0);
+
+ /* We always allocate in units of pages */
+ i = ffs(size / 4096) - 1;
+ if (i >= INTEL_TTM_BO_BUCKETS)
+ return NULL;
+
+ return &bufmgr_ttm->cache_bucket[i];
+}
+
+
static void dri_ttm_dump_validation_list(dri_bufmgr_ttm *bufmgr_ttm)
{
int i, j;
@@ -294,8 +354,8 @@ intel_setup_reloc_list(dri_bo *bo)
dri_bo_ttm *bo_ttm = (dri_bo_ttm *)bo;
dri_bufmgr_ttm *bufmgr_ttm = (dri_bufmgr_ttm *)bo->bufmgr;
- bo_ttm->relocs = malloc(sizeof(struct dri_ttm_reloc) *
- bufmgr_ttm->max_relocs);
+ bo_ttm->relocs = calloc(bufmgr_ttm->max_relocs,
+ sizeof(struct dri_ttm_reloc));
bo_ttm->reloc_buf_data = calloc(1, RELOC_BUF_SIZE(bufmgr_ttm->max_relocs));
/* Initialize the relocation list with the header:
@@ -338,6 +398,9 @@ dri_ttm_alloc(dri_bufmgr *bufmgr, const char *name,
int ret;
uint64_t flags;
unsigned int hint;
+ unsigned long alloc_size;
+ struct dri_ttm_bo_bucket *bucket;
+ GLboolean alloc_from_cache = GL_FALSE;
ttm_buf = calloc(1, sizeof(*ttm_buf));
if (!ttm_buf)
@@ -352,13 +415,48 @@ dri_ttm_alloc(dri_bufmgr *bufmgr, const char *name,
/* No hints we want to use. */
hint = 0;
- ret = drmBOCreate(bufmgr_ttm->fd, size, alignment / pageSize,
- NULL, flags, hint, &ttm_buf->drm_bo);
- if (ret != 0) {
- free(ttm_buf);
- return NULL;
+ /* Round the allocated size up to a power of two number of pages. */
+ alloc_size = 1 << logbase2(size);
+ if (alloc_size < pageSize)
+ alloc_size = pageSize;
+ bucket = dri_ttm_bo_bucket_for_size(bufmgr_ttm, alloc_size);
+
+ /* If we don't have caching at this size, don't actually round the
+ * allocation up.
+ */
+ if (bucket == NULL || bucket->max_entries == 0)
+ alloc_size = size;
+
+ /* Get a buffer out of the cache if available */
+ if (bucket != NULL && bucket->num_entries > 0) {
+ struct dri_ttm_bo_bucket_entry *entry = bucket->head;
+ int busy;
+
+ /* Check if the buffer is still in flight. If not, reuse it. */
+ ret = drmBOBusy(bufmgr_ttm->fd, &entry->drm_bo, &busy);
+ alloc_from_cache = (ret == 0 && busy == 0);
+
+ if (alloc_from_cache) {
+ bucket->head = entry->next;
+ if (entry->next == NULL)
+ bucket->tail = &bucket->head;
+ bucket->num_entries--;
+
+ ttm_buf->drm_bo = entry->drm_bo;
+ free(entry);
+ }
}
- ttm_buf->bo.size = ttm_buf->drm_bo.size;
+
+ if (!alloc_from_cache) {
+ ret = drmBOCreate(bufmgr_ttm->fd, alloc_size, alignment / pageSize,
+ NULL, flags, hint, &ttm_buf->drm_bo);
+ if (ret != 0) {
+ free(ttm_buf);
+ return NULL;
+ }
+ }
+
+ ttm_buf->bo.size = size;
ttm_buf->bo.offset = ttm_buf->drm_bo.offset;
ttm_buf->bo.virtual = NULL;
ttm_buf->bo.bufmgr = bufmgr;
@@ -450,6 +548,7 @@ dri_ttm_bo_unreference(dri_bo *buf)
return;
if (--ttm_buf->refcount == 0) {
+ struct dri_ttm_bo_bucket *bucket;
int ret;
assert(ttm_buf->map_count == 0);
@@ -476,11 +575,32 @@ dri_ttm_bo_unreference(dri_bo *buf)
}
}
- ret = drmBOUnreference(bufmgr_ttm->fd, &ttm_buf->drm_bo);
- if (ret != 0) {
- fprintf(stderr, "drmBOUnreference failed (%s): %s\n",
- ttm_buf->name, strerror(-ret));
+ bucket = dri_ttm_bo_bucket_for_size(bufmgr_ttm, ttm_buf->drm_bo.size);
+ /* Put the buffer into our internal cache for reuse if we can. */
+ if (!ttm_buf->shared &&
+ bucket != NULL &&
+ (bucket->max_entries == -1 ||
+ (bucket->max_entries > 0 &&
+ bucket->num_entries < bucket->max_entries)))
+ {
+ struct dri_ttm_bo_bucket_entry *entry;
+
+ entry = calloc(1, sizeof(*entry));
+ entry->drm_bo = ttm_buf->drm_bo;
+
+ entry->next = NULL;
+ *bucket->tail = entry;
+ bucket->tail = &entry->next;
+ bucket->num_entries++;
+ } else {
+ /* Decrement the kernel refcount for the buffer. */
+ ret = drmBOUnreference(bufmgr_ttm->fd, &ttm_buf->drm_bo);
+ if (ret != 0) {
+ fprintf(stderr, "drmBOUnreference failed (%s): %s\n",
+ ttm_buf->name, strerror(-ret));
+ }
}
+
DBG("bo_unreference final: %p (%s)\n", &ttm_buf->bo, ttm_buf->name);
free(buf);
@@ -657,9 +777,34 @@ static void
dri_bufmgr_ttm_destroy(dri_bufmgr *bufmgr)
{
dri_bufmgr_ttm *bufmgr_ttm = (dri_bufmgr_ttm *)bufmgr;
+ int i;
free(bufmgr_ttm->validate_array);
+ /* Free any cached buffer objects we were going to reuse */
+ for (i = 0; i < INTEL_TTM_BO_BUCKETS; i++) {
+ struct dri_ttm_bo_bucket *bucket = &bufmgr_ttm->cache_bucket[i];
+ struct dri_ttm_bo_bucket_entry *entry;
+
+ while ((entry = bucket->head) != NULL) {
+ int ret;
+
+ bucket->head = entry->next;
+ if (entry->next == NULL)
+ bucket->tail = &bucket->head;
+ bucket->num_entries--;
+
+ /* Decrement the kernel refcount for the buffer. */
+ ret = drmBOUnreference(bufmgr_ttm->fd, &entry->drm_bo);
+ if (ret != 0) {
+ fprintf(stderr, "drmBOUnreference failed: %s\n",
+ strerror(-ret));
+ }
+
+ free(entry);
+ }
+ }
+
free(bufmgr);
}
@@ -877,6 +1022,24 @@ dri_ttm_post_submit(dri_bo *batch_buf, dri_fence **last_fence)
}
/**
+ * Enables unlimited caching of buffer objects for reuse.
+ *
+ * This is potentially very memory expensive, as the cache at each bucket
+ * size is only bounded by how many buffers of that size we've managed to have
+ * in flight at once.
+ */
+void
+intel_ttm_enable_bo_reuse(dri_bufmgr *bufmgr)
+{
+ dri_bufmgr_ttm *bufmgr_ttm = (dri_bufmgr_ttm *)bufmgr;
+ int i;
+
+ for (i = 0; i < INTEL_TTM_BO_BUCKETS; i++) {
+ bufmgr_ttm->cache_bucket[i].max_entries = -1;
+ }
+}
+
+/**
* Initializes the TTM buffer manager, which uses the kernel to allocate, map,
* and manage map buffer objections.
*
@@ -890,6 +1053,7 @@ intel_bufmgr_ttm_init(int fd, unsigned int fence_type,
unsigned int fence_type_flush, int batch_size)
{
dri_bufmgr_ttm *bufmgr_ttm;
+ int i;
bufmgr_ttm = calloc(1, sizeof(*bufmgr_ttm));
bufmgr_ttm->fd = fd;
@@ -919,6 +1083,10 @@ intel_bufmgr_ttm_init(int fd, unsigned int fence_type,
bufmgr_ttm->bufmgr.post_submit = dri_ttm_post_submit;
bufmgr_ttm->bufmgr.debug = GL_FALSE;
+ /* Initialize the linked lists for BO reuse cache. */
+ for (i = 0; i < INTEL_TTM_BO_BUCKETS; i++)
+ bufmgr_ttm->cache_bucket[i].tail = &bufmgr_ttm->cache_bucket[i].head;
+
return &bufmgr_ttm->bufmgr;
}
diff --git a/src/mesa/drivers/dri/intel/intel_bufmgr_ttm.h b/src/mesa/drivers/dri/intel/intel_bufmgr_ttm.h
index 0738839cef..d267a168cd 100644
--- a/src/mesa/drivers/dri/intel/intel_bufmgr_ttm.h
+++ b/src/mesa/drivers/dri/intel/intel_bufmgr_ttm.h
@@ -14,4 +14,7 @@ dri_fence *intel_ttm_fence_create_from_arg(dri_bufmgr *bufmgr, const char *name,
dri_bufmgr *intel_bufmgr_ttm_init(int fd, unsigned int fence_type,
unsigned int fence_type_flush, int batch_size);
+void
+intel_ttm_enable_bo_reuse(dri_bufmgr *bufmgr);
+
#endif
diff --git a/src/mesa/drivers/dri/intel/intel_context.c b/src/mesa/drivers/dri/intel/intel_context.c
index d3f0681807..e2388dbb09 100644
--- a/src/mesa/drivers/dri/intel/intel_context.c
+++ b/src/mesa/drivers/dri/intel/intel_context.c
@@ -205,7 +205,6 @@ static const struct dri_extension card_extensions[] = {
{"GL_ARB_texture_rectangle", NULL},
{"GL_NV_texture_rectangle", NULL},
{"GL_EXT_texture_rectangle", NULL},
- {"GL_ARB_point_sprite", NULL},
{"GL_ARB_point_parameters", NULL},
{"GL_ARB_vertex_buffer_object", GL_ARB_vertex_buffer_object_functions},
{"GL_ARB_vertex_program", GL_ARB_vertex_program_functions},
@@ -231,7 +230,6 @@ static const struct dri_extension card_extensions[] = {
{"GL_EXT_texture_env_dot3", NULL},
{"GL_EXT_texture_filter_anisotropic", NULL},
{"GL_EXT_texture_lod_bias", NULL},
- {"GL_EXT_texture_sRGB", NULL},
{"GL_3DFX_texture_compression_FXT1", NULL},
{"GL_APPLE_client_storage", NULL},
{"GL_MESA_pack_invert", NULL},
@@ -248,6 +246,7 @@ static const struct dri_extension brw_extensions[] = {
{ "GL_ARB_shading_language_120", GL_VERSION_2_1_functions},
{ "GL_ARB_shader_objects", GL_ARB_shader_objects_functions},
{ "GL_ARB_vertex_shader", GL_ARB_vertex_shader_functions},
+ { "GL_ARB_point_sprite", NULL},
{ "GL_ARB_fragment_shader", NULL },
{ "GL_ARB_draw_buffers", NULL },
{ "GL_ARB_depth_texture", NULL },
@@ -257,6 +256,7 @@ static const struct dri_extension brw_extensions[] = {
/* ARB extn won't work if not enabled */
{ "GL_SGIX_depth_texture", NULL },
{ "GL_ARB_texture_env_crossbar", NULL },
+ { "GL_EXT_texture_sRGB", NULL},
{ NULL, NULL }
};
@@ -456,6 +456,7 @@ intel_init_bufmgr(struct intel_context *intel)
ttm_supported = GL_FALSE;
if (!ttm_disable && ttm_supported) {
+ int bo_reuse_mode;
intel->bufmgr = intel_bufmgr_ttm_init(intel->driFd,
DRM_FENCE_TYPE_EXE,
DRM_FENCE_TYPE_EXE |
@@ -463,6 +464,15 @@ intel_init_bufmgr(struct intel_context *intel)
BATCH_SZ);
if (intel->bufmgr != NULL)
intel->ttm = GL_TRUE;
+
+ bo_reuse_mode = driQueryOptioni(&intel->optionCache, "bo_reuse");
+ switch (bo_reuse_mode) {
+ case DRI_CONF_BO_REUSE_DISABLED:
+ break;
+ case DRI_CONF_BO_REUSE_ALL:
+ intel_ttm_enable_bo_reuse(intel->bufmgr);
+ break;
+ }
}
/* Otherwise, use the classic buffer manager. */
if (intel->bufmgr == NULL) {
@@ -548,6 +558,9 @@ intelInitContext(struct intel_context *intel,
intel->width = intelScreen->width;
intel->height = intelScreen->height;
+ driParseConfigFiles(&intel->optionCache, &intelScreen->optionCache,
+ intel->driScreen->myNum,
+ IS_965(intelScreen->deviceID) ? "i965" : "i915");
if (intelScreen->deviceID == PCI_CHIP_I865_G)
intel->maxBatchSize = 4096;
else
@@ -556,10 +569,6 @@ intelInitContext(struct intel_context *intel,
if (!intel_init_bufmgr(intel))
return GL_FALSE;
- driParseConfigFiles(&intel->optionCache, &intelScreen->optionCache,
- intel->driScreen->myNum,
- IS_965(intelScreen->deviceID) ? "i965" : "i915");
-
ctx->Const.MaxTextureMaxAnisotropy = 2.0;
/* This doesn't yet catch all non-conformant rendering, but it's a
@@ -855,7 +864,7 @@ intelContendedLock(struct intel_context *intel, GLuint flags)
*/
if (dPriv) {
if (sPriv->dri2.enabled)
- drawable_changed = __driParseEvents(sPriv, dPriv);
+ drawable_changed = __driParseEvents(dPriv->driContextPriv, dPriv);
else
DRI_VALIDATE_DRAWABLE_INFO(sPriv, dPriv);
}
@@ -984,6 +993,7 @@ void LOCK_HARDWARE( struct intel_context *intel )
*/
void UNLOCK_HARDWARE( struct intel_context *intel )
{
+ intel->vtbl.note_unlock( intel );
intel->locked = 0;
DRM_UNLOCK(intel->driFd, intel->driHwLock, intel->hHWContext);
diff --git a/src/mesa/drivers/dri/intel/intel_context.h b/src/mesa/drivers/dri/intel/intel_context.h
index 6c97955b14..1348b0adcf 100644
--- a/src/mesa/drivers/dri/intel/intel_context.h
+++ b/src/mesa/drivers/dri/intel/intel_context.h
@@ -94,8 +94,9 @@ struct intel_context
void (*render_start) (struct intel_context * intel);
void (*render_prevalidate) (struct intel_context * intel);
void (*set_draw_region) (struct intel_context * intel,
- struct intel_region * draw_region,
- struct intel_region * depth_region);
+ struct intel_region * draw_regions[],
+ struct intel_region * depth_region,
+ GLuint num_regions);
GLuint (*flush_cmd) (void);
void (*emit_flush) (struct intel_context *intel, GLuint unused);
@@ -476,6 +477,11 @@ extern void intelInitStateFuncs(struct dd_function_table *functions);
#define BLENDFACT_INV_CONST_ALPHA 0x0f
#define BLENDFACT_MASK 0x0f
+enum {
+ DRI_CONF_BO_REUSE_DISABLED,
+ DRI_CONF_BO_REUSE_ALL
+};
+
extern int intel_translate_shadow_compare_func(GLenum func);
extern int intel_translate_compare_func(GLenum func);
extern int intel_translate_stencil_op(GLenum op);
diff --git a/src/mesa/drivers/dri/intel/intel_fbo.c b/src/mesa/drivers/dri/intel/intel_fbo.c
index 94d499f001..b3f6610546 100644
--- a/src/mesa/drivers/dri/intel/intel_fbo.c
+++ b/src/mesa/drivers/dri/intel/intel_fbo.c
@@ -517,28 +517,10 @@ intel_framebuffer_renderbuffer(GLcontext * ctx,
intel_draw_buffer(ctx, fb);
}
-
-/**
- * When glFramebufferTexture[123]D is called this function sets up the
- * gl_renderbuffer wrapper around the texture image.
- * This will have the region info needed for hardware rendering.
- */
-static struct intel_renderbuffer *
-intel_wrap_texture(GLcontext * ctx, struct gl_texture_image *texImage)
+static GLboolean
+intel_update_wrapper(GLcontext *ctx, struct intel_renderbuffer *irb,
+ struct gl_texture_image *texImage)
{
- const GLuint name = ~0; /* not significant, but distinct for debugging */
- struct intel_renderbuffer *irb;
-
- /* make an intel_renderbuffer to wrap the texture image */
- irb = CALLOC_STRUCT(intel_renderbuffer);
- if (!irb) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glFramebufferTexture");
- return NULL;
- }
-
- _mesa_init_renderbuffer(&irb->Base, name);
- irb->Base.ClassID = INTEL_RB_CLASS;
-
if (texImage->TexFormat == &_mesa_texformat_argb8888) {
irb->Base._ActualFormat = GL_RGBA8;
irb->Base._BaseFormat = GL_RGBA;
@@ -553,12 +535,15 @@ intel_wrap_texture(GLcontext * ctx, struct gl_texture_image *texImage)
irb->Base._ActualFormat = GL_DEPTH_COMPONENT16;
irb->Base._BaseFormat = GL_DEPTH_COMPONENT;
DBG("Render to DEPTH16 texture OK\n");
+ } else if (texImage->TexFormat == &_mesa_texformat_z24_s8) {
+ irb->Base._ActualFormat = GL_DEPTH24_STENCIL8_EXT;
+ irb->Base._BaseFormat = GL_DEPTH_STENCIL_EXT;
+ DBG("Render to DEPTH_STENCIL texture OK\n");
}
else {
DBG("Render to texture BAD FORMAT %d\n",
texImage->TexFormat->MesaFormat);
- _mesa_free(irb);
- return NULL;
+ return GL_FALSE;
}
irb->Base.InternalFormat = irb->Base._ActualFormat;
@@ -577,6 +562,35 @@ intel_wrap_texture(GLcontext * ctx, struct gl_texture_image *texImage)
irb->RenderToTexture = GL_TRUE;
+ return GL_TRUE;
+}
+
+/**
+ * When glFramebufferTexture[123]D is called this function sets up the
+ * gl_renderbuffer wrapper around the texture image.
+ * This will have the region info needed for hardware rendering.
+ */
+static struct intel_renderbuffer *
+intel_wrap_texture(GLcontext * ctx, struct gl_texture_image *texImage)
+{
+ const GLuint name = ~0; /* not significant, but distinct for debugging */
+ struct intel_renderbuffer *irb;
+
+ /* make an intel_renderbuffer to wrap the texture image */
+ irb = CALLOC_STRUCT(intel_renderbuffer);
+ if (!irb) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glFramebufferTexture");
+ return NULL;
+ }
+
+ _mesa_init_renderbuffer(&irb->Base, name);
+ irb->Base.ClassID = INTEL_RB_CLASS;
+
+ if (!intel_update_wrapper(ctx, irb, texImage)) {
+ _mesa_free(irb);
+ return NULL;
+ }
+
return irb;
}
@@ -613,6 +627,10 @@ intel_render_texture(GLcontext * ctx,
_mesa_render_texture(ctx, fb, att);
return;
}
+ } if (!intel_update_wrapper(ctx, irb, newImage)) {
+ _mesa_reference_renderbuffer(&att->Renderbuffer, NULL);
+ _mesa_render_texture(ctx, fb, att);
+ return;
}
DBG("Begin render texture tid %x tex=%u w=%d h=%d refcount=%d\n",
diff --git a/src/mesa/drivers/dri/intel/intel_mipmap_tree.c b/src/mesa/drivers/dri/intel/intel_mipmap_tree.c
index 48dcf07131..55503f45ae 100644
--- a/src/mesa/drivers/dri/intel/intel_mipmap_tree.c
+++ b/src/mesa/drivers/dri/intel/intel_mipmap_tree.c
@@ -110,10 +110,12 @@ intel_miptree_create(struct intel_context *intel,
mt = intel_miptree_create_internal(intel, target, internal_format,
first_level, last_level, width0,
height0, depth0, cpp, compress_byte);
- if (!mt)
+ /*
+ * pitch == 0 indicates the null texture
+ */
+ if (!mt || !mt->pitch)
return NULL;
- assert (mt->pitch);
mt->region = intel_region_alloc(intel,
mt->cpp, mt->pitch, mt->total_height);
@@ -180,7 +182,10 @@ int intel_miptree_pitch_align (struct intel_context *intel,
struct intel_mipmap_tree *mt,
int pitch)
{
+#ifdef I915
GLcontext *ctx = &intel->ctx;
+#endif
+
if (!mt->compressed) {
int pitch_align;
@@ -321,7 +326,7 @@ intel_miptree_set_image_offset(struct intel_mipmap_tree *mt,
assert(img < mt->level[level].nr_images);
- mt->level[level].image_offset[img] = (x + y * mt->pitch);
+ mt->level[level].image_offset[img] = (x + y * mt->pitch) * mt->cpp;
DBG("%s level %d img %d pos %d,%d image_offset %x\n",
__FUNCTION__, level, img, x, y, mt->level[level].image_offset[img]);
@@ -352,7 +357,7 @@ intel_miptree_image_offset(struct intel_mipmap_tree *mt,
{
if (mt->target == GL_TEXTURE_CUBE_MAP_ARB)
return (mt->level[level].level_offset +
- mt->level[level].image_offset[face] * mt->cpp);
+ mt->level[level].image_offset[face]);
else
return mt->level[level].level_offset;
}
@@ -363,6 +368,8 @@ intel_miptree_image_offset(struct intel_mipmap_tree *mt,
* Map a teximage in a mipmap tree.
* \param row_stride returns row stride in bytes
* \param image_stride returns image stride in bytes (for 3D textures).
+ * \param image_offsets pointer to array of pixel offsets from the returned
+ * pointer to each depth image
* \return address of mapping
*/
GLubyte *
@@ -377,12 +384,16 @@ intel_miptree_image_map(struct intel_context * intel,
if (row_stride)
*row_stride = mt->pitch * mt->cpp;
- if (image_offsets) {
- if (mt->target == GL_TEXTURE_CUBE_MAP_ARB)
- memset(image_offsets, 0, mt->level[level].depth * sizeof(GLuint));
- else
- memcpy(image_offsets, mt->level[level].image_offset,
- mt->level[level].depth * sizeof(GLuint));
+ if (mt->target == GL_TEXTURE_3D) {
+ int i;
+
+ for (i = 0; i < mt->level[level].depth; i++)
+ image_offsets[i] = mt->level[level].image_offset[i] / mt->cpp;
+ } else {
+ assert(mt->level[level].depth == 1);
+ assert(mt->target == GL_TEXTURE_CUBE_MAP ||
+ mt->level[level].image_offset[0] == 0);
+ image_offsets[0] = 0;
}
return (intel_region_map(intel, mt->region) +
diff --git a/src/mesa/drivers/dri/intel/intel_mipmap_tree.h b/src/mesa/drivers/dri/intel/intel_mipmap_tree.h
index 3c1a6ffa2a..c9537dbb9a 100644
--- a/src/mesa/drivers/dri/intel/intel_mipmap_tree.h
+++ b/src/mesa/drivers/dri/intel/intel_mipmap_tree.h
@@ -62,18 +62,29 @@
*/
struct intel_mipmap_level
{
+ /**
+ * Byte offset to the base of this level.
+ *
+ * This is used for mipmap levels of 1D/2D/3D textures. However, CUBE
+ * layouts spread images around the whole tree, so the level offset is
+ * always zero in that case.
+ */
GLuint level_offset;
GLuint width;
GLuint height;
+ /** Depth of the mipmap at this level: 1 for 1D/2D/CUBE, n for 3D. */
GLuint depth;
+ /** Number of images at this level: 1 for 1D/2D, 6 for CUBE, depth for 3D */
GLuint nr_images;
- /* Explicitly store the offset of each image for each cube face or
- * depth value. Pretty much have to accept that hardware formats
+ /**
+ * Byte offset from level_offset to the image for each cube face or depth
+ * level.
+ *
+ * Pretty much have to accept that hardware formats
* are going to be so diverse that there is no unified way to
* compute the offsets of depth/cube images within a mipmap level,
- * so have to store them as a lookup table:
- * NOTE level_offset is a byte offset, but the image_offsets are _pixel_ offsets!!!
+ * so have to store them as a lookup table.
*/
GLuint *image_offset;
};
diff --git a/src/mesa/drivers/dri/intel/intel_pixel_bitmap.c b/src/mesa/drivers/dri/intel/intel_pixel_bitmap.c
index 77b6c53cb3..4cb68655f2 100644
--- a/src/mesa/drivers/dri/intel/intel_pixel_bitmap.c
+++ b/src/mesa/drivers/dri/intel/intel_pixel_bitmap.c
@@ -166,11 +166,8 @@ do_blit_bitmap( GLcontext *ctx,
struct intel_context *intel = intel_context(ctx);
struct intel_region *dst = intel_drawbuf_region(intel);
GLfloat tmpColor[4];
-
- union {
- GLuint ui;
- GLubyte ub[4];
- } color;
+ GLubyte ubcolor[4];
+ GLuint color8888, color565;
if (!dst)
return GL_FALSE;
@@ -187,10 +184,13 @@ do_blit_bitmap( GLcontext *ctx,
ADD_3V(tmpColor, tmpColor, ctx->Current.RasterSecondaryColor);
}
- UNCLAMPED_FLOAT_TO_CHAN(color.ub[0], tmpColor[2]);
- UNCLAMPED_FLOAT_TO_CHAN(color.ub[1], tmpColor[1]);
- UNCLAMPED_FLOAT_TO_CHAN(color.ub[2], tmpColor[0]);
- UNCLAMPED_FLOAT_TO_CHAN(color.ub[3], tmpColor[3]);
+ UNCLAMPED_FLOAT_TO_UBYTE(ubcolor[0], tmpColor[0]);
+ UNCLAMPED_FLOAT_TO_UBYTE(ubcolor[1], tmpColor[1]);
+ UNCLAMPED_FLOAT_TO_UBYTE(ubcolor[2], tmpColor[2]);
+ UNCLAMPED_FLOAT_TO_UBYTE(ubcolor[3], tmpColor[3]);
+
+ color8888 = INTEL_PACKCOLOR8888(ubcolor[0], ubcolor[1], ubcolor[2], ubcolor[3]);
+ color565 = INTEL_PACKCOLOR565(ubcolor[0], ubcolor[1], ubcolor[2]);
/* Does zoom apply to bitmaps?
*/
@@ -289,7 +289,7 @@ do_blit_bitmap( GLcontext *ctx,
dst->cpp,
(GLubyte *)stipple,
sz,
- color.ui,
+ (dst->cpp == 2) ? color565 : color8888,
dst->pitch,
dst->buffer,
0,
diff --git a/src/mesa/drivers/dri/intel/intel_screen.c b/src/mesa/drivers/dri/intel/intel_screen.c
index 8b8eeb77aa..3d46073daa 100644
--- a/src/mesa/drivers/dri/intel/intel_screen.c
+++ b/src/mesa/drivers/dri/intel/intel_screen.c
@@ -56,6 +56,15 @@ PUBLIC const char __driConfigOptions[] =
DRI_CONF_SECTION_PERFORMANCE
DRI_CONF_FTHROTTLE_MODE(DRI_CONF_FTHROTTLE_IRQS)
DRI_CONF_VBLANK_MODE(DRI_CONF_VBLANK_DEF_INTERVAL_0)
+ /* Options correspond to DRI_CONF_BO_REUSE_DISABLED,
+ * DRI_CONF_BO_REUSE_ALL
+ */
+ DRI_CONF_OPT_BEGIN_V(bo_reuse, enum, 0, "0:1")
+ DRI_CONF_DESC_BEGIN(en, "Buffer object reuse")
+ DRI_CONF_ENUM(0, "Disable buffer object reuse")
+ DRI_CONF_ENUM(1, "Enable reuse of all sizes of buffer objects")
+ DRI_CONF_DESC_END
+ DRI_CONF_OPT_END
DRI_CONF_SECTION_END
DRI_CONF_SECTION_QUALITY
DRI_CONF_FORCE_S3TC_ENABLE(false)
@@ -66,7 +75,7 @@ PUBLIC const char __driConfigOptions[] =
DRI_CONF_SECTION_END
DRI_CONF_END;
-const GLuint __driNConfigOptions = 5;
+const GLuint __driNConfigOptions = 6;
#ifdef USE_NEW_INTERFACE
static PFNGLXCREATECONTEXTMODES create_context_modes = NULL;
@@ -284,14 +293,17 @@ intelUpdateScreenFromSAREA(intelScreenPrivate * intelScreen,
static void
intelHandleDrawableConfig(__DRIdrawablePrivate *dPriv,
+ __DRIcontextPrivate *pcp,
__DRIDrawableConfigEvent *event)
{
struct intel_framebuffer *intel_fb = dPriv->driverPrivate;
struct intel_region *region = NULL;
struct intel_renderbuffer *rb, *depth_rb, *stencil_rb;
- struct intel_context *intel = dPriv->driContextPriv->driverPrivate;
- int cpp = intel->ctx.Visual.rgbBits / 8;
- GLuint pitch = ((cpp * dPriv->w + 63) & ~63) / cpp;
+ struct intel_context *intel = pcp->driverPrivate;
+ int cpp, pitch;
+
+ cpp = intel->ctx.Visual.rgbBits / 8;
+ pitch = ((cpp * dPriv->w + 63) & ~63) / cpp;
rb = intel_fb->color_rb[1];
if (rb) {
@@ -322,12 +334,13 @@ intelHandleDrawableConfig(__DRIdrawablePrivate *dPriv,
static void
intelHandleBufferAttach(__DRIdrawablePrivate *dPriv,
+ __DRIcontextPrivate *pcp,
__DRIBufferAttachEvent *ba)
{
struct intel_framebuffer *intel_fb = dPriv->driverPrivate;
struct intel_renderbuffer *rb;
struct intel_region *region;
- struct intel_context *intel = dPriv->driContextPriv->driverPrivate;
+ struct intel_context *intel = pcp->driverPrivate;
GLuint tiled;
switch (ba->buffer.attachment) {
@@ -371,22 +384,6 @@ intelHandleBufferAttach(__DRIdrawablePrivate *dPriv,
intel_renderbuffer_set_region(rb, region);
}
-static void
-intelUpdateBuffer(__DRIdrawablePrivate *dPriv, unsigned int *event)
-{
- switch (DRI2_EVENT_TYPE(*event)) {
- case DRI2_EVENT_DRAWABLE_CONFIG:
- /* flush all current regions, allocate new ones, except front buffer */
- intelHandleDrawableConfig(dPriv, (__DRIDrawableConfigEvent *) event);
- break;
-
- case DRI2_EVENT_BUFFER_ATTACH:
- /* attach buffer if different from what we have */
- intelHandleBufferAttach(dPriv, (__DRIBufferAttachEvent *) event);
- break;
- }
-}
-
static const __DRItexOffsetExtension intelTexOffsetExtension = {
{ __DRI_TEX_OFFSET },
intelSetTexOffset,
@@ -671,7 +668,9 @@ static const struct __DriverAPIRec intelAPI = {
.WaitForSBC = NULL,
.SwapBuffersMSC = NULL,
.CopySubBuffer = intelCopySubBuffer,
- .UpdateBuffer = intelUpdateBuffer,
+
+ .HandleDrawableConfig = intelHandleDrawableConfig,
+ .HandleBufferAttach = intelHandleBufferAttach,
};
diff --git a/src/mesa/drivers/dri/intel/intel_tex.c b/src/mesa/drivers/dri/intel/intel_tex.c
index c110df478f..329af0d1b0 100644
--- a/src/mesa/drivers/dri/intel/intel_tex.c
+++ b/src/mesa/drivers/dri/intel/intel_tex.c
@@ -1,5 +1,6 @@
#include "swrast/swrast.h"
#include "texobj.h"
+#include "teximage.h"
#include "mipmap.h"
#include "intel_context.h"
#include "intel_mipmap_tree.h"
@@ -71,7 +72,7 @@ intelFreeTextureImageData(GLcontext * ctx, struct gl_texture_image *texImage)
}
if (texImage->Data) {
- free(texImage->Data);
+ _mesa_free_texmemory(texImage->Data);
texImage->Data = NULL;
}
}
diff --git a/src/mesa/drivers/dri/intel/intel_tex.h b/src/mesa/drivers/dri/intel/intel_tex.h
index 34995f4ebf..3a87137cc9 100644
--- a/src/mesa/drivers/dri/intel/intel_tex.h
+++ b/src/mesa/drivers/dri/intel/intel_tex.h
@@ -138,8 +138,7 @@ void intelGetCompressedTexImage(GLcontext *ctx, GLenum target, GLint level,
void intelSetTexOffset(__DRIcontext *pDRICtx, GLint texname,
unsigned long long offset, GLint depth, GLuint pitch);
void intelSetTexBuffer(__DRIcontext *pDRICtx,
- GLint target, unsigned long handle,
- GLint cpp, GLuint pitch, GLuint height);
+ GLint target, __DRIdrawable *pDraw);
GLuint intel_finalize_mipmap_tree(struct intel_context *intel, GLuint unit);
diff --git a/src/mesa/drivers/dri/intel/intel_tex_image.c b/src/mesa/drivers/dri/intel/intel_tex_image.c
index df08ee1a3b..dd8fbeaa91 100644
--- a/src/mesa/drivers/dri/intel/intel_tex_image.c
+++ b/src/mesa/drivers/dri/intel/intel_tex_image.c
@@ -23,6 +23,7 @@
#include "intel_tex.h"
#include "intel_ioctl.h"
#include "intel_blit.h"
+#include "intel_fbo.h"
#define FILE_DEBUG_FLAG DEBUG_TEXTURE
@@ -359,7 +360,8 @@ intelTexImage(GLcontext * ctx,
assert(!texImage->Data);
}
else if (texImage->Data) {
- _mesa_align_free(texImage->Data);
+ _mesa_free_texmemory(texImage->Data);
+ texImage->Data = NULL;
}
/* If this is the only texture image in the tree, could call
@@ -455,8 +457,6 @@ intelTexImage(GLcontext * ctx,
format, type,
pixels, unpack, "glTexImage");
}
- if (!pixels)
- return;
LOCK_HARDWARE(intel);
@@ -482,7 +482,7 @@ intelTexImage(GLcontext * ctx,
sizeInBytes = depth * dstRowStride * postConvHeight;
}
- texImage->Data = malloc(sizeInBytes);
+ texImage->Data = _mesa_alloc_texmemory(sizeInBytes);
}
DBG("Upload image %dx%dx%d row_len %d "
@@ -493,27 +493,29 @@ intelTexImage(GLcontext * ctx,
* the blitter to copy. Or, use the hardware to do the format
* conversion and copy:
*/
- if (compressed) {
- if (intelImage->mt) {
- struct intel_region *dst = intelImage->mt->region;
- _mesa_copy_rect(texImage->Data, dst->cpp, dst->pitch,
- 0, 0,
- intelImage->mt->level[level].width,
- intelImage->mt->level[level].height/4,
- pixels,
- srcRowStride,
- 0, 0);
- } else
- memcpy(texImage->Data, pixels, imageSize);
- } else if (!texImage->TexFormat->StoreImage(ctx, dims,
- texImage->_BaseFormat,
- texImage->TexFormat,
- texImage->Data, 0, 0, 0, /* dstX/Y/Zoffset */
- dstRowStride,
- texImage->ImageOffsets,
- width, height, depth,
- format, type, pixels, unpack)) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage");
+ if (pixels) {
+ if (compressed) {
+ if (intelImage->mt) {
+ struct intel_region *dst = intelImage->mt->region;
+ _mesa_copy_rect(texImage->Data, dst->cpp, dst->pitch,
+ 0, 0,
+ intelImage->mt->level[level].width,
+ intelImage->mt->level[level].height/4,
+ pixels,
+ srcRowStride,
+ 0, 0);
+ } else
+ memcpy(texImage->Data, pixels, imageSize);
+ } else if (!texImage->TexFormat->StoreImage(ctx, dims,
+ texImage->_BaseFormat,
+ texImage->TexFormat,
+ texImage->Data, 0, 0, 0, /* dstX/Y/Zoffset */
+ dstRowStride,
+ texImage->ImageOffsets,
+ width, height, depth,
+ format, type, pixels, unpack)) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage");
+ }
}
/* GL_SGIS_generate_mipmap */
@@ -694,26 +696,20 @@ intelSetTexOffset(__DRIcontext *pDRICtx, GLint texname,
}
void
-intelSetTexBuffer(__DRIcontext *pDRICtx, GLint target,
- unsigned long handle, GLint cpp, GLuint pitch, GLuint height)
+intelSetTexBuffer(__DRIcontext *pDRICtx, GLint target, __DRIdrawable *pDraw)
{
__DRIcontextPrivate *driContext = pDRICtx->private;
+ __DRIdrawablePrivate *dPriv = pDraw->private;
+ struct intel_framebuffer *intel_fb = dPriv->driverPrivate;
struct intel_context *intel = driContext->driverPrivate;
struct intel_texture_object *intelObj;
struct intel_texture_image *intelImage;
struct intel_mipmap_tree *mt;
- struct intel_region *region;
+ struct intel_renderbuffer *rb;
struct gl_texture_unit *texUnit;
struct gl_texture_object *texObj;
struct gl_texture_image *texImage;
- int level = 0;
-
- /* FIXME: type, format, internalFormat */
- int type = GL_BGRA;
- int format = GL_UNSIGNED_BYTE;
- int internalFormat = (cpp == 3 ? 3 : 4);
- cpp = 4;
- pitch /= 4;
+ int level = 0, type, format, internalFormat;
texUnit = &intel->ctx.Texture.Unit[intel->ctx.Texture.CurrentUnit];
texObj = _mesa_select_tex_object(&intel->ctx, texUnit, target);
@@ -722,12 +718,16 @@ intelSetTexBuffer(__DRIcontext *pDRICtx, GLint target,
if (!intelObj)
return;
- region = intel_region_alloc_for_handle(intel, cpp, pitch, height,
- 0, handle);
+ __driParseEvents(driContext, dPriv);
+
+ rb = intel_fb->color_rb[0];
+ type = GL_BGRA;
+ format = GL_UNSIGNED_BYTE;
+ internalFormat = (rb->region->cpp == 3 ? 3 : 4);
mt = intel_miptree_create_for_region(intel, target,
internalFormat,
- 0, 0, region, 1, 0);
+ 0, 0, rb->region, 1, 0);
if (mt == NULL)
return;
@@ -739,7 +739,7 @@ intelSetTexBuffer(__DRIcontext *pDRICtx, GLint target,
intelObj->mt = mt;
texImage = _mesa_get_tex_image(&intel->ctx, texObj, target, level);
_mesa_init_teximage_fields(&intel->ctx, target, texImage,
- pitch, height, 1,
+ rb->region->pitch, rb->region->height, 1,
0, internalFormat);
intelImage = intel_texture_image(texImage);
@@ -748,7 +748,7 @@ intelSetTexBuffer(__DRIcontext *pDRICtx, GLint target,
texImage->TexFormat = intelChooseTextureFormat(&intel->ctx, internalFormat,
type, format);
_mesa_set_fetch_functions(texImage, 2);
- texImage->RowStride = pitch;
+ texImage->RowStride = rb->region->pitch;
intel_miptree_reference(&intelImage->mt, intelObj->mt);
if (!intel_miptree_match_image(intelObj->mt, &intelImage->base,
diff --git a/src/mesa/drivers/dri/intel/intel_tex_subimage.c b/src/mesa/drivers/dri/intel/intel_tex_subimage.c
index bd27b86bf3..688e3870df 100644
--- a/src/mesa/drivers/dri/intel/intel_tex_subimage.c
+++ b/src/mesa/drivers/dri/intel/intel_tex_subimage.c
@@ -50,8 +50,8 @@ intelTexSubimage(GLcontext * ctx,
{
struct intel_context *intel = intel_context(ctx);
struct intel_texture_image *intelImage = intel_texture_image(texImage);
- GLuint dstRowStride;
-
+ GLuint dstRowStride = 0;
+
DBG("%s target %s level %d offset %d,%d %dx%d\n", __FUNCTION__,
_mesa_lookup_enum_by_nr(target),
level, xoffset, yoffset, width, height);
@@ -76,6 +76,16 @@ intelTexSubimage(GLcontext * ctx,
intelImage->level,
&dstRowStride,
texImage->ImageOffsets);
+ else {
+ if (texImage->IsCompressed) {
+ dstRowStride =
+ _mesa_compressed_row_stride(texImage->TexFormat->MesaFormat, width);
+ assert(dims != 3);
+ }
+ else {
+ dstRowStride = texImage->RowStride * texImage->TexFormat->TexelBytes;
+ }
+ }
assert(dstRowStride);