diff options
Diffstat (limited to 'src/mesa/drivers/dri/intel')
-rw-r--r-- | src/mesa/drivers/dri/intel/intel_buffers.c | 32 | ||||
-rw-r--r-- | src/mesa/drivers/dri/intel/intel_bufmgr_ttm.c | 192 | ||||
-rw-r--r-- | src/mesa/drivers/dri/intel/intel_bufmgr_ttm.h | 3 | ||||
-rw-r--r-- | src/mesa/drivers/dri/intel/intel_context.c | 24 | ||||
-rw-r--r-- | src/mesa/drivers/dri/intel/intel_context.h | 10 | ||||
-rw-r--r-- | src/mesa/drivers/dri/intel/intel_fbo.c | 64 | ||||
-rw-r--r-- | src/mesa/drivers/dri/intel/intel_mipmap_tree.c | 31 | ||||
-rw-r--r-- | src/mesa/drivers/dri/intel/intel_mipmap_tree.h | 19 | ||||
-rw-r--r-- | src/mesa/drivers/dri/intel/intel_pixel_bitmap.c | 20 | ||||
-rw-r--r-- | src/mesa/drivers/dri/intel/intel_screen.c | 43 | ||||
-rw-r--r-- | src/mesa/drivers/dri/intel/intel_tex.c | 3 | ||||
-rw-r--r-- | src/mesa/drivers/dri/intel/intel_tex.h | 3 | ||||
-rw-r--r-- | src/mesa/drivers/dri/intel/intel_tex_image.c | 82 | ||||
-rw-r--r-- | src/mesa/drivers/dri/intel/intel_tex_subimage.c | 14 |
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); |