diff options
author | Owain G. Ainsworth <oga@openbsd.org> | 2010-07-18 16:01:48 +0100 |
---|---|---|
committer | Owain G. Ainsworth <oga@openbsd.org> | 2010-07-18 16:01:48 +0100 |
commit | 9290ad77c5eef438ba02fc26334fd85ab3caa009 (patch) | |
tree | a2ac0f1be6786545821e7aa75ecbf4bbc332a1f4 /src/i830_uxa.c | |
parent | 09c5b49b691132d0085c29b74decb45e0d4215e9 (diff) | |
parent | b2f4de3b7fb73bd51b1fd1b2b044862839c9a6ea (diff) |
Merge branch 'bleeding_edge-oga' into 2.9.1-oga
Conflicts:
src/i830_display.c
This has now been commited to cvs, so the branch gets pulled.
Diffstat (limited to 'src/i830_uxa.c')
-rw-r--r-- | src/i830_uxa.c | 663 |
1 files changed, 375 insertions, 288 deletions
diff --git a/src/i830_uxa.c b/src/i830_uxa.c index 78237046..03a01372 100644 --- a/src/i830_uxa.c +++ b/src/i830_uxa.c @@ -36,6 +36,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "i830.h" #include "i810_reg.h" #include "i915_drm.h" +#include "brw_defines.h" #include <string.h> #include <sys/mman.h> #include <errno.h> @@ -78,7 +79,31 @@ const int I830PatternROP[16] = { ROP_1 }; -static int uxa_pixmap_index; +#if HAS_DEVPRIVATEKEYREC +DevPrivateKeyRec uxa_pixmap_index; +#else +int uxa_pixmap_index; +#endif + +static void +ironlake_blt_workaround(ScrnInfoPtr scrn) +{ + intel_screen_private *intel = intel_get_screen_private(scrn); + + /* Ironlake has a limitation that a 3D or Media command can't + * be the first command after a BLT, unless it's + * non-pipelined. Instead of trying to track it and emit a + * command at the right time, we just emit a dummy + * non-pipelined 3D instruction after each blit. + */ + + if (IS_IGDNG(intel)) { + BEGIN_BATCH(2); + OUT_BATCH(CMD_POLY_STIPPLE_OFFSET << 16); + OUT_BATCH(0); + ADVANCE_BATCH(); + } +} Bool i830_get_aperture_space(ScrnInfoPtr scrn, drm_intel_bo ** bo_table, @@ -93,7 +118,7 @@ i830_get_aperture_space(ScrnInfoPtr scrn, drm_intel_bo ** bo_table, bo_table[0] = intel->batch_bo; if (drm_intel_bufmgr_check_aperture_space(bo_table, num_bos) != 0) { - intel_batch_submit(scrn); + intel_batch_submit(scrn, FALSE); bo_table[0] = intel->batch_bo; if (drm_intel_bufmgr_check_aperture_space(bo_table, num_bos) != 0) { @@ -127,14 +152,13 @@ i830_uxa_pixmap_compute_size(PixmapPtr pixmap, { ScrnInfoPtr scrn = xf86Screens[pixmap->drawable.pScreen->myNum]; intel_screen_private *intel = intel_get_screen_private(scrn); - int pitch, pitch_align; - int size; + int pitch, size; if (*tiling != I915_TILING_NONE) { /* First check whether tiling is necessary. */ - pitch_align = intel->accel_pixmap_pitch_alignment; - size = ROUND_TO((w * pixmap->drawable.bitsPerPixel + 7) / 8, - pitch_align) * ALIGN (h, 2); + pitch = (w * pixmap->drawable.bitsPerPixel + 7) / 8; + pitch = ROUND_TO(pitch, intel->accel_pixmap_pitch_alignment); + size = pitch * ALIGN (h, 2); if (!IS_I965G(intel)) { /* Older hardware requires fences to be pot size * aligned with a minimum of 1 MiB, so causes @@ -142,6 +166,12 @@ i830_uxa_pixmap_compute_size(PixmapPtr pixmap, */ if (size < 1024*1024/2) *tiling = I915_TILING_NONE; + + /* Gen 2/3 has a maximum stride for tiling of + * 8192 bytes. + */ + if (pitch > KB(8)) + *tiling = I915_TILING_NONE; } else if (size <= 4096) { /* Disable tiling beneath a page size, we will not see * any benefit from reducing TLB misses and instead @@ -154,29 +184,19 @@ i830_uxa_pixmap_compute_size(PixmapPtr pixmap, pitch = (w * pixmap->drawable.bitsPerPixel + 7) / 8; if (pitch <= 256) *tiling = I915_TILING_NONE; - repeat: - if (*tiling == I915_TILING_NONE) { - pitch_align = intel->accel_pixmap_pitch_alignment; - } else { - pitch_align = 512; - } - *stride = ROUND_TO(pitch, pitch_align); + if (*tiling != I915_TILING_NONE) { + int aligned_h; - if (*tiling == I915_TILING_NONE) { - /* Round the height up so that the GPU's access to a 2x2 aligned - * subspan doesn't address an invalid page offset beyond the - * end of the GTT. - */ - size = *stride * ALIGN(h, 2); - } else { - int aligned_h = h; if (*tiling == I915_TILING_X) aligned_h = ALIGN(h, 8); else aligned_h = ALIGN(h, 32); - *stride = i830_get_fence_pitch(intel, *stride, *tiling); + *stride = i830_get_fence_pitch(intel, + ROUND_TO(pitch, 512), + *tiling); + /* Round the object up to the size of the fence it will live in * if necessary. We could potentially make the kernel allocate * a larger aperture space and just bind the subset of pages in, @@ -184,17 +204,45 @@ i830_uxa_pixmap_compute_size(PixmapPtr pixmap, * with drm_intel_bufmgr_check_aperture(). */ size = i830_get_fence_size(intel, *stride * aligned_h); - assert(size >= *stride * aligned_h); + + if (size > intel->max_tiling_size) + *tiling = I915_TILING_NONE; } - if (*tiling != I915_TILING_NONE && size > intel->max_tiling_size) { - *tiling = I915_TILING_NONE; - goto repeat; + if (*tiling == I915_TILING_NONE) { + /* Round the height up so that the GPU's access to a 2x2 aligned + * subspan doesn't address an invalid page offset beyond the + * end of the GTT. + */ + *stride = ROUND_TO(pitch, intel->accel_pixmap_pitch_alignment); + size = *stride * ALIGN(h, 2); } return size; } +static Bool +i830_uxa_check_solid(DrawablePtr drawable, int alu, Pixel planemask) +{ + ScrnInfoPtr scrn = xf86Screens[drawable->pScreen->myNum]; + + if (!UXA_PM_IS_SOLID(drawable, planemask)) { + intel_debug_fallback(scrn, "planemask is not solid\n"); + return FALSE; + } + + switch (drawable->bitsPerPixel) { + case 8: + case 16: + case 32: + break; + default: + return FALSE; + } + + return TRUE; +} + /** * Sets up hardware state for a series of solid fills. */ @@ -203,32 +251,14 @@ i830_uxa_prepare_solid(PixmapPtr pixmap, int alu, Pixel planemask, Pixel fg) { ScrnInfoPtr scrn = xf86Screens[pixmap->drawable.pScreen->myNum]; intel_screen_private *intel = intel_get_screen_private(scrn); - unsigned long pitch; drm_intel_bo *bo_table[] = { NULL, /* batch_bo */ i830_get_pixmap_bo(pixmap), }; - if (!UXA_PM_IS_SOLID(&pixmap->drawable, planemask)) { - intel_debug_fallback(scrn, "planemask is not solid\n"); - return FALSE; - } - - if (pixmap->drawable.bitsPerPixel == 24) { - intel_debug_fallback(scrn, "solid 24bpp unsupported!\n"); - return FALSE; - } - - if (pixmap->drawable.bitsPerPixel < 8) { - intel_debug_fallback(scrn, "under 8bpp pixmaps unsupported\n"); - return FALSE; - } - if (!intel_check_pitch_2d(pixmap)) return FALSE; - pitch = i830_pixmap_pitch(pixmap); - if (!i830_pixmap_pitch_is_aligned(pixmap)) { intel_debug_fallback(scrn, "pixmap pitch not aligned"); return FALSE; @@ -248,11 +278,10 @@ i830_uxa_prepare_solid(PixmapPtr pixmap, int alu, Pixel planemask, Pixel fg) case 32: /* RGB8888 */ intel->BR[13] |= ((1 << 24) | (1 << 25)); - if (pixmap->drawable.depth == 24) - fg |= 0xff000000; break; } intel->BR[16] = fg; + return TRUE; } @@ -272,6 +301,9 @@ static void i830_uxa_solid(PixmapPtr pixmap, int x1, int y1, int x2, int y2) if (y2 > pixmap->drawable.height) y2 = pixmap->drawable.height; + if (x2 <= x1 || y2 <= y1) + return; + pitch = i830_pixmap_pitch(pixmap); { @@ -299,6 +331,8 @@ static void i830_uxa_solid(PixmapPtr pixmap, int x1, int y1, int x2, int y2) OUT_BATCH(intel->BR[16]); ADVANCE_BATCH(); } + + ironlake_blt_workaround(scrn); } static void i830_uxa_done_solid(PixmapPtr pixmap) @@ -313,39 +347,57 @@ static void i830_uxa_done_solid(PixmapPtr pixmap) * - support planemask using FULL_BLT_CMD? */ static Bool -i830_uxa_prepare_copy(PixmapPtr source, PixmapPtr dest, int xdir, - int ydir, int alu, Pixel planemask) +i830_uxa_check_copy(PixmapPtr source, PixmapPtr dest, + int alu, Pixel planemask) { ScrnInfoPtr scrn = xf86Screens[dest->drawable.pScreen->myNum]; intel_screen_private *intel = intel_get_screen_private(scrn); - drm_intel_bo *bo_table[] = { - NULL, /* batch_bo */ - i830_get_pixmap_bo(source), - i830_get_pixmap_bo(dest), - }; + if (!UXA_PM_IS_SOLID(&source->drawable, planemask)) { intel_debug_fallback(scrn, "planemask is not solid"); return FALSE; } - if (dest->drawable.bitsPerPixel < 8) { - intel_debug_fallback(scrn, "under 8bpp pixmaps unsupported\n"); + if (source->drawable.bitsPerPixel != dest->drawable.bitsPerPixel) { + intel_debug_fallback(scrn, "mixed bpp copies unsupported\n"); return FALSE; } - - if (!i830_get_aperture_space(scrn, bo_table, ARRAY_SIZE(bo_table))) + switch (source->drawable.bitsPerPixel) { + case 8: + case 16: + case 32: + break; + default: return FALSE; + } if (!intel_check_pitch_2d(source)) return FALSE; if (!intel_check_pitch_2d(dest)) return FALSE; + return TRUE; +} + +static Bool +i830_uxa_prepare_copy(PixmapPtr source, PixmapPtr dest, int xdir, + int ydir, int alu, Pixel planemask) +{ + ScrnInfoPtr scrn = xf86Screens[dest->drawable.pScreen->myNum]; + intel_screen_private *intel = intel_get_screen_private(scrn); + drm_intel_bo *bo_table[] = { + NULL, /* batch_bo */ + i830_get_pixmap_bo(source), + i830_get_pixmap_bo(dest), + }; + + if (!i830_get_aperture_space(scrn, bo_table, ARRAY_SIZE(bo_table))) + return FALSE; + intel->render_source = source; intel->BR[13] = I830CopyROP[alu] << 16; - switch (source->drawable.bitsPerPixel) { case 8: break; @@ -356,6 +408,7 @@ i830_uxa_prepare_copy(PixmapPtr source, PixmapPtr dest, int xdir, intel->BR[13] |= ((1 << 25) | (1 << 24)); break; } + return TRUE; } @@ -416,6 +469,7 @@ i830_uxa_copy(PixmapPtr dest, int src_x1, int src_y1, int dst_x1, ADVANCE_BATCH(); } + ironlake_blt_workaround(scrn); } static void i830_uxa_done_copy(PixmapPtr dest) @@ -433,6 +487,10 @@ static void i830_uxa_done_copy(PixmapPtr dest) void i830_done_composite(PixmapPtr dest) { ScrnInfoPtr scrn = xf86Screens[dest->drawable.pScreen->myNum]; + intel_screen_private *intel = intel_get_screen_private(scrn); + + if (intel->vertex_flush) + intel->vertex_flush(intel); i830_debug_flush(scrn); } @@ -518,16 +576,6 @@ Bool i830_transform_is_affine(PictTransformPtr t) return t->matrix[2][0] == 0 && t->matrix[2][1] == 0; } -struct intel_pixmap *i830_get_pixmap_intel(PixmapPtr pixmap) -{ - return dixLookupPrivate(&pixmap->devPrivates, &uxa_pixmap_index); -} - -static void i830_uxa_set_pixmap_intel(PixmapPtr pixmap, struct intel_pixmap *intel) -{ - dixSetPrivate(&pixmap->devPrivates, &uxa_pixmap_index, intel); -} - dri_bo *i830_get_pixmap_bo(PixmapPtr pixmap) { struct intel_pixmap *intel; @@ -547,21 +595,35 @@ void i830_set_pixmap_bo(PixmapPtr pixmap, dri_bo * bo) priv = i830_get_pixmap_intel(pixmap); + if (priv == NULL && bo == NULL) + return; + if (priv != NULL) { + if (priv->bo == bo) + return; + if (list_is_empty(&priv->batch)) { dri_bo_unreference(priv->bo); + } else if (!drm_intel_bo_is_reusable(priv->bo)) { + dri_bo_unreference(priv->bo); + list_del(&priv->batch); + list_del(&priv->flush); } else { list_add(&priv->in_flight, &intel->in_flight); priv = NULL; } + + if (intel->render_current_dest == pixmap) + intel->render_current_dest = NULL; } if (bo != NULL) { + uint32_t tiling; uint32_t swizzle_mode; int ret; if (priv == NULL) { - priv = xcalloc(1, sizeof (struct intel_pixmap)); + priv = calloc(1, sizeof (struct intel_pixmap)); if (priv == NULL) goto BAIL; @@ -574,21 +636,24 @@ void i830_set_pixmap_bo(PixmapPtr pixmap, dri_bo * bo) priv->stride = i830_pixmap_pitch(pixmap); ret = drm_intel_bo_get_tiling(bo, - &priv->tiling, + &tiling, &swizzle_mode); if (ret != 0) { FatalError("Couldn't get tiling on bo %p: %s\n", bo, strerror(-ret)); } + + priv->tiling = tiling; + priv->busy = -1; } else { if (priv != NULL) { - xfree(priv); + free(priv); priv = NULL; } } BAIL: - i830_uxa_set_pixmap_intel(pixmap, priv); + i830_set_pixmap_intel(pixmap, priv); } static Bool i830_uxa_prepare_access(PixmapPtr pixmap, uxa_access_t access) @@ -600,40 +665,30 @@ static Bool i830_uxa_prepare_access(PixmapPtr pixmap, uxa_access_t access) int ret; if (!list_is_empty(&priv->batch) && - (access == UXA_ACCESS_RW || priv->batch_write_domain)) - intel_batch_submit(scrn); - - if (bo) { - if (intel->kernel_exec_fencing) { - if (bo->size > intel->max_gtt_map_size || !intel->have_gem) { - ret = dri_bo_map(bo, access == UXA_ACCESS_RW); - if (ret != 0) { - xf86DrvMsg(scrn->scrnIndex, X_WARNING, - "%s: bo map failed: %s\n", - __FUNCTION__, - strerror(-ret)); - return FALSE; - } - } else { - ret = drm_intel_gem_bo_map_gtt(bo); - if (ret != 0) { - xf86DrvMsg(scrn->scrnIndex, X_WARNING, - "%s: gtt bo map failed: %s\n", - __FUNCTION__, - strerror(-ret)); - return FALSE; - } - } - pixmap->devPrivate.ptr = bo->virtual; - } else { - if (drm_intel_bo_pin(bo, 4096) != 0) - return FALSE; - drm_intel_gem_bo_start_gtt_access(bo, access == - UXA_ACCESS_RW); - pixmap->devPrivate.ptr = intel->FbBase + bo->offset; + (access == UXA_ACCESS_RW || priv->batch_write)) + intel_batch_submit(scrn, FALSE); + + if (bo->size > intel->max_gtt_map_size) { + ret = dri_bo_map(bo, access == UXA_ACCESS_RW); + if (ret != 0) { + xf86DrvMsg(scrn->scrnIndex, X_WARNING, + "%s: bo map failed: %s\n", + __FUNCTION__, + strerror(-ret)); + return FALSE; + } + } else { + ret = drm_intel_gem_bo_map_gtt(bo); + if (ret != 0) { + xf86DrvMsg(scrn->scrnIndex, X_WARNING, + "%s: gtt bo map failed: %s\n", + __FUNCTION__, + strerror(-ret)); + return FALSE; } - } else - i830_wait_ring_idle(scrn); + } + pixmap->devPrivate.ptr = bo->virtual; + priv->busy = 0; return TRUE; } @@ -648,206 +703,207 @@ static void i830_uxa_finish_access(PixmapPtr pixmap) if (bo == intel->front_buffer->bo) intel->need_flush = TRUE; - if (intel->kernel_exec_fencing) { - if (bo->size > intel->max_gtt_map_size) - dri_bo_unmap(bo); - else - drm_intel_gem_bo_unmap_gtt(bo); - pixmap->devPrivate.ptr = NULL; - } + if (bo->size > intel->max_gtt_map_size) + dri_bo_unmap(bo); + else + drm_intel_gem_bo_unmap_gtt(bo); + pixmap->devPrivate.ptr = NULL; } -static Bool i830_bo_put_image(PixmapPtr pixmap, dri_bo *bo, char *src, int src_pitch, int w, int h) +static Bool i830_uxa_pixmap_put_image(PixmapPtr pixmap, + char *src, int src_pitch, + int x, int y, int w, int h) { + struct intel_pixmap *priv = i830_get_pixmap_intel(pixmap); int stride = i830_pixmap_pitch(pixmap); - - /* fill alpha channel */ - if (pixmap->drawable.depth == 24) { - pixman_image_t *src_image, *dst_image; - - src_image = pixman_image_create_bits (PIXMAN_x8r8g8b8, - w, h, - (uint32_t *) src, src_pitch); - - dst_image = pixman_image_create_bits (PIXMAN_a8r8g8b8, - w, h, - (uint32_t *) bo->virtual, stride); - - if (src_image && dst_image) - pixman_image_composite (PictOpSrc, - src_image, NULL, dst_image, - 0, 0, - 0, 0, - 0, 0, - w, h); - - if (src_image) - pixman_image_unref (src_image); - - if (dst_image) - pixman_image_unref (dst_image); - - if (src_image == NULL || dst_image == NULL) - return FALSE; - } else if (src_pitch == stride) { - memcpy (bo->virtual, src, stride * h); - } else { - char *dst = bo->virtual; - int row_length = w * pixmap->drawable.bitsPerPixel/8; + int ret = FALSE; + + if (src_pitch == stride && w == pixmap->drawable.width && priv->tiling == I915_TILING_NONE) { + ret = drm_intel_bo_subdata(priv->bo, y * stride, stride * h, src) == 0; + } else if (drm_intel_gem_bo_map_gtt(priv->bo) == 0) { + char *dst = priv->bo->virtual; + int cpp = pixmap->drawable.bitsPerPixel/8; + int row_length = w * cpp; int num_rows = h; - while (num_rows--) { + if (row_length == src_pitch && src_pitch == stride) + num_rows = 1, row_length *= h; + dst += y * stride + x * cpp; + do { memcpy (dst, src, row_length); src += src_pitch; dst += stride; - } + } while (--num_rows); + drm_intel_gem_bo_unmap_gtt(priv->bo); + ret = TRUE; } - return TRUE; + return ret; } -static Bool -i830_uxa_pixmap_swap_bo_with_image(PixmapPtr pixmap, - char *src, int src_pitch) +static Bool i830_uxa_put_image(PixmapPtr pixmap, + int x, int y, + int w, int h, + char *src, int src_pitch) { - ScrnInfoPtr scrn = xf86Screens[pixmap->drawable.pScreen->myNum]; - intel_screen_private *intel = intel_get_screen_private(scrn); struct intel_pixmap *priv; - dri_bo *bo; - uint32_t tiling = I915_TILING_X; - int stride; - int w = pixmap->drawable.width; - int h = pixmap->drawable.height; - Bool ret; priv = i830_get_pixmap_intel(pixmap); + if (!intel_pixmap_is_busy(priv)) { + /* bo is not busy so can be replaced without a stall, upload in-place. */ + return i830_uxa_pixmap_put_image(pixmap, src, src_pitch, x, y, w, h); + } else { + ScreenPtr screen = pixmap->drawable.pScreen; + + if (x == 0 && y == 0 && + w == pixmap->drawable.width && + h == pixmap->drawable.height) + { + intel_screen_private *intel = intel_get_screen_private(xf86Screens[screen->myNum]); + uint32_t tiling = priv->tiling; + int size, stride; + dri_bo *bo; + + /* Replace busy bo. */ + size = i830_uxa_pixmap_compute_size (pixmap, w, h, + &tiling, &stride); + if (size > intel->max_gtt_map_size) + return FALSE; - if (priv->batch_read_domains || drm_intel_bo_busy(priv->bo)) { - unsigned int size; + bo = drm_intel_bo_alloc(intel->bufmgr, "pixmap", size, 0); + if (bo == NULL) + return FALSE; - size = i830_uxa_pixmap_compute_size (pixmap, w, h, - &tiling, &stride); - if (size > intel->max_gtt_map_size) - return FALSE; + if (tiling != I915_TILING_NONE) + drm_intel_bo_set_tiling(bo, &tiling, stride); - bo = drm_intel_bo_alloc(intel->bufmgr, "pixmap", size, 0); - if (bo == NULL) - return FALSE; + screen->ModifyPixmapHeader(pixmap, + w, h, + 0, 0, + stride, NULL); + i830_set_pixmap_bo(pixmap, bo); + dri_bo_unreference(bo); - if (tiling != I915_TILING_NONE) - drm_intel_bo_set_tiling(bo, &tiling, stride); + return i830_uxa_pixmap_put_image(pixmap, src, src_pitch, 0, 0, w, h); + } + else + { + PixmapPtr scratch; + Bool ret; + + /* Upload to a linear buffer and queue a blit. */ + scratch = (*screen->CreatePixmap)(screen, w, h, + pixmap->drawable.depth, + UXA_CREATE_PIXMAP_FOR_MAP); + if (!scratch) + return FALSE; - dri_bo_unreference(priv->bo); - priv->bo = bo; - priv->tiling = tiling; - priv->batch_read_domains = priv->batch_write_domain = 0; - priv->flush_read_domains = priv->flush_write_domain = 0; - list_del(&priv->batch); - list_del(&priv->flush); - pixmap->drawable.pScreen->ModifyPixmapHeader(pixmap, - w, h, - 0, 0, - stride, NULL); - } else { - bo = priv->bo; - stride = i830_pixmap_pitch(pixmap); - } + ret = i830_uxa_pixmap_put_image(scratch, src, src_pitch, 0, 0, w, h); + if (ret) { + GCPtr gc = GetScratchGC(pixmap->drawable.depth, screen); + if (gc) { + ValidateGC(&pixmap->drawable, gc); - if (drm_intel_gem_bo_map_gtt(bo)) { - xf86DrvMsg(scrn->scrnIndex, X_WARNING, - "%s: bo map failed\n", __FUNCTION__); - return FALSE; + (*gc->ops->CopyArea)(&scratch->drawable, + &pixmap->drawable, + gc, 0, 0, w, h, x, y); + + FreeScratchGC(gc); + } else + ret = FALSE; + } + + (*screen->DestroyPixmap)(scratch); + return ret; + } } +} - ret = i830_bo_put_image(pixmap, bo, src, src_pitch, w, h); +static Bool i830_uxa_pixmap_get_image(PixmapPtr pixmap, + int x, int y, int w, int h, + char *dst, int dst_pitch) +{ + struct intel_pixmap *priv = i830_get_pixmap_intel(pixmap); + int stride = i830_pixmap_pitch(pixmap); - drm_intel_gem_bo_unmap_gtt(bo); + if (dst_pitch == stride && w == pixmap->drawable.width) { + return drm_intel_bo_get_subdata(priv->bo, y * stride, stride * h, dst) == 0; + } else { + char *src; + int cpp; - return ret; + if (drm_intel_bo_map(priv->bo, FALSE)) + return FALSE; + + cpp = pixmap->drawable.bitsPerPixel/8; + src = (char *) priv->bo->virtual + y * stride + x * cpp; + w *= cpp; + do { + memcpy(dst, src, w); + src += stride; + dst += dst_pitch; + } while (--h); + + drm_intel_bo_unmap(priv->bo); + + return TRUE; + } } -static Bool i830_uxa_put_image(PixmapPtr pixmap, +static Bool i830_uxa_get_image(PixmapPtr pixmap, int x, int y, int w, int h, - char *src, int src_pitch) + char *dst, int dst_pitch) { - ScreenPtr screen = pixmap->drawable.pScreen; - ScrnInfoPtr scrn = xf86Screens[screen->myNum]; - PixmapPtr scratch; struct intel_pixmap *priv; - GCPtr gc; + PixmapPtr scratch = NULL; Bool ret; - if (x == 0 && y == 0 && - w == pixmap->drawable.width && - h == pixmap->drawable.height) - { - /* Replace GPU hot bo with new CPU data. */ - return i830_uxa_pixmap_swap_bo_with_image(pixmap, - src, src_pitch); - } + /* The presumption is that we wish to keep the target hot, so + * copy to a new bo and move that to the CPU in preference to + * causing ping-pong of the original. + * + * Also the gpu is much faster at detiling. + */ priv = i830_get_pixmap_intel(pixmap); - if (priv->batch_read_domains || - drm_intel_bo_busy(priv->bo) || - pixmap->drawable.depth == 24) { - dri_bo *bo; - - /* Partial replacement, copy incoming image to a bo and blit. */ - scratch = (*screen->CreatePixmap)(screen, w, h, - pixmap->drawable.depth, - UXA_CREATE_PIXMAP_FOR_MAP); + if (intel_pixmap_is_busy(priv) || priv->tiling != I915_TILING_NONE) { + ScreenPtr screen = pixmap->drawable.pScreen; + GCPtr gc; + + /* Copy to a linear buffer and pull. */ + scratch = screen->CreatePixmap(screen, w, h, + pixmap->drawable.depth, + INTEL_CREATE_PIXMAP_TILING_NONE); if (!scratch) return FALSE; - bo = i830_get_pixmap_bo(scratch); - if (drm_intel_gem_bo_map_gtt(bo)) { - (*screen->DestroyPixmap) (scratch); - xf86DrvMsg(scrn->scrnIndex, X_WARNING, - "%s: bo map failed\n", __FUNCTION__); + gc = GetScratchGC(pixmap->drawable.depth, screen); + if (!gc) { + screen->DestroyPixmap(scratch); return FALSE; } - ret = i830_bo_put_image(scratch, bo, src, src_pitch, w, h); + ValidateGC(&pixmap->drawable, gc); - drm_intel_gem_bo_unmap_gtt(bo); - - if (ret) { - gc = GetScratchGC(pixmap->drawable.depth, screen); - if (gc) { - ValidateGC(&pixmap->drawable, gc); + gc->ops->CopyArea(&pixmap->drawable, + &scratch->drawable, + gc, x, y, w, h, 0, 0); - (*gc->ops->CopyArea)(&scratch->drawable, - &pixmap->drawable, - gc, 0, 0, w, h, x, y); + FreeScratchGC(gc); - FreeScratchGC(gc); - } else - ret = FALSE; - } + intel_batch_submit(xf86Screens[screen->myNum], FALSE); - (*screen->DestroyPixmap)(scratch); - } else { - /* bo is not busy so can be mapped without a stall, upload in-place. */ - if (drm_intel_gem_bo_map_gtt(priv->bo)) { - xf86DrvMsg(scrn->scrnIndex, X_WARNING, - "%s: bo map failed\n", __FUNCTION__); - return FALSE; - } + x = y = 0; + pixmap = scratch; + } - pixman_blt((uint32_t *)src, priv->bo->virtual, - src_pitch / sizeof(uint32_t), - pixmap->devKind / sizeof(uint32_t), - pixmap->drawable.bitsPerPixel, - pixmap->drawable.bitsPerPixel, - 0, 0, - x, y, - w, h); + ret = i830_uxa_pixmap_get_image(pixmap, x, y, w, h, dst, dst_pitch); - drm_intel_gem_bo_unmap_gtt(priv->bo); - ret = TRUE; - } + if (scratch) + scratch->drawable.pScreen->DestroyPixmap(scratch); return ret; + } void i830_uxa_block_handler(ScreenPtr screen) @@ -883,6 +939,9 @@ i830_uxa_create_pixmap(ScreenPtr screen, int w, int h, int depth, if (w > 32767 || h > 32767) return NullPixmap; + if (depth == 1) + return fbCreatePixmap(screen, w, h, depth, usage); + if (usage == CREATE_PIXMAP_USAGE_GLYPH_PICTURE && w <= 32 && h <= 32) return fbCreatePixmap(screen, w, h, depth, usage); @@ -900,7 +959,7 @@ i830_uxa_create_pixmap(ScreenPtr screen, int w, int h, int depth, tiling = I915_TILING_X; if (usage == INTEL_CREATE_PIXMAP_TILING_Y) tiling = I915_TILING_Y; - if (usage == UXA_CREATE_PIXMAP_FOR_MAP) + if (usage == UXA_CREATE_PIXMAP_FOR_MAP || usage == INTEL_CREATE_PIXMAP_TILING_NONE) tiling = I915_TILING_NONE; if (tiling != I915_TILING_NONE) { @@ -911,21 +970,16 @@ i830_uxa_create_pixmap(ScreenPtr screen, int w, int h, int depth, } size = i830_uxa_pixmap_compute_size(pixmap, w, h, &tiling, &stride); - /* Fail very large allocations on 32-bit systems. Large BOs will - * tend to hit SW fallbacks frequently, and also will tend to fail - * to successfully map when doing SW fallbacks because we overcommit - * address space for BO access. - * - * Note that size should fit in 32 bits. We throw out >32767x32767x4, - * and pitch alignment could get us up to 32768x32767x4. + /* Fail very large allocations. Large BOs will tend to hit SW fallbacks + * frequently, and also will tend to fail to successfully map when doing + * SW fallbacks because we overcommit address space for BO access. */ - if (sizeof(unsigned long) == 4 && - size > (unsigned int)(1024 * 1024 * 1024)) { + if (size > intel->max_bo_size || stride >= KB(32)) { fbDestroyPixmap(pixmap); - return NullPixmap; + return fbCreatePixmap(screen, w, h, depth, usage); } - /* Perform a premilinary search for an in-flight bo */ + /* Perform a preliminary search for an in-flight bo */ if (usage != UXA_CREATE_PIXMAP_FOR_MAP) { int aligned_h; @@ -939,50 +993,63 @@ i830_uxa_create_pixmap(ScreenPtr screen, int w, int h, int depth, list_foreach_entry(priv, struct intel_pixmap, &intel->in_flight, in_flight) { - if (priv->tiling == tiling && - priv->stride >= stride && - priv->bo->size >= priv->stride * aligned_h) { - list_del(&priv->in_flight); - screen->ModifyPixmapHeader(pixmap, w, h, 0, 0, priv->stride, NULL); - i830_uxa_set_pixmap_intel(pixmap, priv); - return pixmap; + if (priv->tiling != tiling) + continue; + + if (tiling == I915_TILING_NONE) { + if (priv->bo->size < size) + continue; + + priv->stride = stride; + } else { + if (priv->stride < stride || + priv->bo->size < priv->stride * aligned_h) + continue; + + stride = priv->stride; } + + list_del(&priv->in_flight); + screen->ModifyPixmapHeader(pixmap, w, h, 0, 0, stride, NULL); + i830_set_pixmap_intel(pixmap, priv); + return pixmap; } } - priv = xcalloc(1, sizeof (struct intel_pixmap)); + priv = calloc(1, sizeof (struct intel_pixmap)); if (priv == NULL) { fbDestroyPixmap(pixmap); return NullPixmap; } - if (usage == UXA_CREATE_PIXMAP_FOR_MAP) + if (usage == UXA_CREATE_PIXMAP_FOR_MAP) { + priv->busy = 0; priv->bo = drm_intel_bo_alloc(intel->bufmgr, "pixmap", size, 0); - else + } else { + priv->busy = -1; priv->bo = drm_intel_bo_alloc_for_render(intel->bufmgr, "pixmap", size, 0); + } if (!priv->bo) { - xfree(priv); + free(priv); fbDestroyPixmap(pixmap); if (errno == EFBIG) return fbCreatePixmap(screen, w, h, depth, usage); return NullPixmap; } + if (tiling != I915_TILING_NONE) + drm_intel_bo_set_tiling(priv->bo, &tiling, stride); priv->stride = stride; priv->tiling = tiling; - if (priv->tiling != I915_TILING_NONE) - drm_intel_bo_set_tiling(priv->bo, - &priv->tiling, - stride); screen->ModifyPixmapHeader(pixmap, w, h, 0, 0, stride, NULL); list_init(&priv->batch); list_init(&priv->flush); - i830_uxa_set_pixmap_intel(pixmap, priv); + i830_set_pixmap_intel(pixmap, priv); } return pixmap; @@ -1006,6 +1073,7 @@ void i830_uxa_create_screen_resources(ScreenPtr screen) if (bo != NULL) { PixmapPtr pixmap = screen->GetScreenPixmap(screen); i830_set_pixmap_bo(pixmap, bo); + i830_get_pixmap_intel(pixmap)->busy = 1; } } @@ -1014,7 +1082,11 @@ Bool i830_uxa_init(ScreenPtr screen) ScrnInfoPtr scrn = xf86Screens[screen->myNum]; intel_screen_private *intel = intel_get_screen_private(scrn); +#if HAS_DIXREGISTERPRIVATEKEY + if (!dixRegisterPrivateKey(&uxa_pixmap_index, PRIVATE_PIXMAP, 0)) +#else if (!dixRequestPrivate(&uxa_pixmap_index, 0)) +#endif return FALSE; intel->uxa_driver = uxa_driver_alloc(); @@ -1027,12 +1099,21 @@ Bool i830_uxa_init(ScreenPtr screen) intel->uxa_driver->uxa_major = 1; intel->uxa_driver->uxa_minor = 0; + intel->render_current_dest = NULL; + intel->prim_offset = 0; + intel->vertex_count = 0; + intel->floats_per_vertex = 0; + intel->last_floats_per_vertex = 0; + intel->vertex_bo = NULL; + /* Solid fill */ + intel->uxa_driver->check_solid = i830_uxa_check_solid; intel->uxa_driver->prepare_solid = i830_uxa_prepare_solid; intel->uxa_driver->solid = i830_uxa_solid; intel->uxa_driver->done_solid = i830_uxa_done_solid; /* Copy */ + intel->uxa_driver->check_copy = i830_uxa_check_copy; intel->uxa_driver->prepare_copy = i830_uxa_prepare_copy; intel->uxa_driver->copy = i830_uxa_copy; intel->uxa_driver->done_copy = i830_uxa_done_copy; @@ -1040,17 +1121,22 @@ Bool i830_uxa_init(ScreenPtr screen) /* Composite */ if (!IS_I9XX(intel)) { intel->uxa_driver->check_composite = i830_check_composite; + intel->uxa_driver->check_composite_target = i830_check_composite_target; + intel->uxa_driver->check_composite_texture = i830_check_composite_texture; intel->uxa_driver->prepare_composite = i830_prepare_composite; intel->uxa_driver->composite = i830_composite; intel->uxa_driver->done_composite = i830_done_composite; } else if (IS_I915G(intel) || IS_I915GM(intel) || IS_I945G(intel) || IS_I945GM(intel) || IS_G33CLASS(intel)) { intel->uxa_driver->check_composite = i915_check_composite; + intel->uxa_driver->check_composite_target = i915_check_composite_target; + intel->uxa_driver->check_composite_texture = i915_check_composite_texture; intel->uxa_driver->prepare_composite = i915_prepare_composite; intel->uxa_driver->composite = i915_composite; intel->uxa_driver->done_composite = i830_done_composite; } else { intel->uxa_driver->check_composite = i965_check_composite; + intel->uxa_driver->check_composite_texture = i965_check_composite_texture; intel->uxa_driver->prepare_composite = i965_prepare_composite; intel->uxa_driver->composite = i965_composite; intel->uxa_driver->done_composite = i830_done_composite; @@ -1058,21 +1144,22 @@ Bool i830_uxa_init(ScreenPtr screen) /* PutImage */ intel->uxa_driver->put_image = i830_uxa_put_image; + intel->uxa_driver->get_image = i830_uxa_get_image; intel->uxa_driver->prepare_access = i830_uxa_prepare_access; intel->uxa_driver->finish_access = i830_uxa_finish_access; intel->uxa_driver->pixmap_is_offscreen = i830_uxa_pixmap_is_offscreen; + screen->CreatePixmap = i830_uxa_create_pixmap; + screen->DestroyPixmap = i830_uxa_destroy_pixmap; + if (!uxa_driver_init(screen, intel->uxa_driver)) { xf86DrvMsg(scrn->scrnIndex, X_ERROR, "UXA initialization failed\n"); - xfree(intel->uxa_driver); + free(intel->uxa_driver); return FALSE; } - screen->CreatePixmap = i830_uxa_create_pixmap; - screen->DestroyPixmap = i830_uxa_destroy_pixmap; - uxa_set_fallback_debug(screen, intel->fallback_debug); return TRUE; |