diff options
-rw-r--r-- | src/i830.h | 36 | ||||
-rw-r--r-- | src/i830_3d.c | 4 | ||||
-rw-r--r-- | src/i830_batchbuffer.c | 60 | ||||
-rw-r--r-- | src/i830_batchbuffer.h | 51 | ||||
-rw-r--r-- | src/i830_driver.c | 7 | ||||
-rw-r--r-- | src/i830_render.c | 36 | ||||
-rw-r--r-- | src/i830_uxa.c | 31 | ||||
-rw-r--r-- | src/i915_3d.c | 11 | ||||
-rw-r--r-- | src/i915_3d.h | 30 | ||||
-rw-r--r-- | src/i915_reg.h | 27 | ||||
-rw-r--r-- | src/i915_render.c | 991 | ||||
-rw-r--r-- | src/i915_video.c | 33 | ||||
-rw-r--r-- | src/i965_render.c | 22 | ||||
-rw-r--r-- | src/i965_video.c | 18 | ||||
-rw-r--r-- | uxa/uxa-accel.c | 207 | ||||
-rw-r--r-- | uxa/uxa-glyphs.c | 529 | ||||
-rw-r--r-- | uxa/uxa-priv.h | 25 | ||||
-rw-r--r-- | uxa/uxa-render.c | 400 | ||||
-rw-r--r-- | uxa/uxa.h | 20 |
19 files changed, 1708 insertions, 830 deletions
@@ -249,13 +249,13 @@ typedef struct intel_screen_private { long GTTMapSize; drm_intel_bo *front_buffer; dri_bufmgr *bufmgr; - uint8_t *batch_ptr; + uint32_t batch_ptr[4096]; /** Byte offset in batch_ptr for the next dword to be emitted. */ unsigned int batch_used; /** Position in batch_ptr at the start of the current BEGIN_BATCH */ unsigned int batch_emit_start; /** Number of bytes to be emitted in the current BEGIN_BATCH. */ uint32_t batch_emitting; @@ -292,12 +292,13 @@ typedef struct intel_screen_private { uint8_t variant; unsigned int BR[20]; CloseScreenProcPtr CloseScreen; + void (*vertex_flush) (struct intel_screen_private *intel); void (*batch_flush_notify) (ScrnInfoPtr scrn); uxa_driver_t *uxa_driver; Bool need_flush; int accel_pixmap_pitch_alignment; int accel_pixmap_offset_alignment; @@ -339,12 +340,14 @@ typedef struct intel_screen_private { PicturePtr render_source_picture, render_mask_picture, render_dest_picture; CARD32 render_source_solid; CARD32 render_mask_solid; Bool render_source_is_solid; Bool render_mask_is_solid; Bool needs_render_state_emit; + Bool needs_render_vertex_emit; + Bool needs_render_ca_pass; /* i830 render accel state */ uint32_t render_dest_format; uint32_t cblend, ablend, s8_blendctl; /* i915 render accel state */ @@ -354,12 +357,25 @@ typedef struct intel_screen_private { struct { int op; uint32_t dst_format; } i915_render_state; + uint32_t prim_offset; + void (*prim_emit)(PixmapPtr dest, + int srcX, int srcY, + int maskX, int maskY, + int dstX, int dstY, + int w, int h); + int floats_per_vertex; + uint32_t vertex_count; + uint32_t vertex_index; + uint32_t vertex_used; + float vertex_ptr[4*1024]; + dri_bo *vertex_bo; + /* 965 render acceleration state */ struct gen4_render_state *gen4_render_state; enum dri_type directRenderingType; /* DRI enabled this generation. */ Bool directRenderingOpen; @@ -451,40 +467,46 @@ unsigned long i830_get_fence_pitch(intel_screen_private *intel, unsigned long pi uint32_t tiling_mode); void i830_set_gem_max_sizes(ScrnInfoPtr scrn); drm_intel_bo *i830_allocate_framebuffer(ScrnInfoPtr scrn); /* i830_render.c */ -Bool i830_check_composite(int op, PicturePtr source, PicturePtr mask, - PicturePtr dest); +Bool i830_check_composite(int op, + PicturePtr sourcec, PicturePtr mask, PicturePtr dest, + int width, int height); +Bool i830_check_composite_target(PixmapPtr pixmap); Bool i830_check_composite_texture(ScreenPtr screen, PicturePtr picture); Bool i830_prepare_composite(int op, PicturePtr sourcec, PicturePtr mask, PicturePtr dest, PixmapPtr sourcecPixmap, PixmapPtr maskPixmap, PixmapPtr destPixmap); Bool i830_transform_is_affine(PictTransformPtr t); void i830_composite(PixmapPtr dest, int srcX, int srcY, int maskX, int maskY, int dstX, int dstY, int w, int h); void i830_done_composite(PixmapPtr dest); /* i915_render.c */ -Bool i915_check_composite(int op, PicturePtr sourcec, PicturePtr mask, - PicturePtr dest); +Bool i915_check_composite(int op, + PicturePtr sourcec, PicturePtr mask, PicturePtr dest, + int width, int height); +Bool i915_check_composite_target(PixmapPtr pixmap); Bool i915_check_composite_texture(ScreenPtr screen, PicturePtr picture); Bool i915_prepare_composite(int op, PicturePtr sourcec, PicturePtr mask, PicturePtr dest, PixmapPtr sourcecPixmap, PixmapPtr maskPixmap, PixmapPtr destPixmap); void i915_composite(PixmapPtr dest, int srcX, int srcY, int maskX, int maskY, int dstX, int dstY, int w, int h); +void i915_vertex_flush(intel_screen_private *intel); void i915_batch_flush_notify(ScrnInfoPtr scrn); void i830_batch_flush_notify(ScrnInfoPtr scrn); /* i965_render.c */ unsigned int gen4_render_state_size(ScrnInfoPtr scrn); void gen4_render_state_init(ScrnInfoPtr scrn); void gen4_render_state_cleanup(ScrnInfoPtr scrn); -Bool i965_check_composite(int op, PicturePtr sourcec, PicturePtr mask, - PicturePtr dest); +Bool i965_check_composite(int op, + PicturePtr sourcec, PicturePtr mask, PicturePtr dest, + int width, int height); Bool i965_check_composite_texture(ScreenPtr screen, PicturePtr picture); Bool i965_prepare_composite(int op, PicturePtr sourcec, PicturePtr mask, PicturePtr dest, PixmapPtr sourcecPixmap, PixmapPtr maskPixmap, PixmapPtr destPixmap); void i965_composite(PixmapPtr dest, int srcX, int srcY, int maskX, int maskY, int dstX, int dstY, int w, int h); diff --git a/src/i830_3d.c b/src/i830_3d.c index e83cb3f7..a92da055 100644 --- a/src/i830_3d.c +++ b/src/i830_3d.c @@ -35,13 +35,13 @@ #include "i830_reg.h" void I830EmitInvarientState(ScrnInfoPtr scrn) { intel_screen_private *intel = intel_get_screen_private(scrn); - ATOMIC_BATCH(58); + assert(intel->in_batch_atomic); OUT_BATCH(_3DSTATE_MAP_CUBE | MAP_UNIT(0)); OUT_BATCH(_3DSTATE_MAP_CUBE | MAP_UNIT(1)); OUT_BATCH(_3DSTATE_MAP_CUBE | MAP_UNIT(2)); OUT_BATCH(_3DSTATE_MAP_CUBE | MAP_UNIT(3)); @@ -219,9 +219,7 @@ void I830EmitInvarientState(ScrnInfoPtr scrn) OUT_BATCH(_3DSTATE_AA_CMD | AA_LINE_ECAAR_WIDTH_ENABLE | AA_LINE_ECAAR_WIDTH_1_0 | AA_LINE_REGION_WIDTH_ENABLE | AA_LINE_REGION_WIDTH_1_0 | AA_LINE_DISABLE); - - ADVANCE_BATCH(); } diff --git a/src/i830_batchbuffer.c b/src/i830_batchbuffer.c index c23b0b85..69961c6b 100644 --- a/src/i830_batchbuffer.c +++ b/src/i830_batchbuffer.c @@ -36,31 +36,45 @@ #include "xf86.h" #include "i830.h" #include "i915_drm.h" #define DUMP_BATCHBUFFERS NULL /* "/tmp/i915-batchbuffers.dump" */ +static void intel_end_vertex(intel_screen_private *intel) +{ + if (intel->vertex_bo) { + if (intel->vertex_used) + dri_bo_subdata(intel->vertex_bo, 0, intel->vertex_used*4, intel->vertex_ptr); + + dri_bo_unreference(intel->vertex_bo); + intel->vertex_bo = NULL; + } +} + +void intel_next_vertex(intel_screen_private *intel) +{ + intel_end_vertex(intel); + + intel->vertex_bo = + dri_bo_alloc(intel->bufmgr, "vertex", sizeof (intel->vertex_ptr), 4096); + intel->vertex_used = 0; +} + static void intel_next_batch(ScrnInfoPtr scrn) { intel_screen_private *intel = intel_get_screen_private(scrn); - int ret; /* The 865 has issues with larger-than-page-sized batch buffers. */ if (IS_I865G(intel)) intel->batch_bo = dri_bo_alloc(intel->bufmgr, "batch", 4096, 4096); else intel->batch_bo = dri_bo_alloc(intel->bufmgr, "batch", 4096 * 4, 4096); - ret = dri_bo_map(intel->batch_bo, 1); - if (ret != 0) - FatalError("Failed to map batchbuffer: %s\n", strerror(-ret)); - intel->batch_used = 0; - intel->batch_ptr = intel->batch_bo->virtual; /* We don't know when another client has executed, so we have * to reinitialize our 3D state per batch. */ intel->last_3d = LAST_3D_OTHER; } @@ -77,15 +91,12 @@ void intel_batch_init(ScrnInfoPtr scrn) void intel_batch_teardown(ScrnInfoPtr scrn) { intel_screen_private *intel = intel_get_screen_private(scrn); if (intel->batch_ptr != NULL) { - dri_bo_unmap(intel->batch_bo); - intel->batch_ptr = NULL; - dri_bo_unreference(intel->batch_bo); intel->batch_bo = NULL; dri_bo_unreference(intel->last_batch_bo); intel->last_batch_bo = NULL; } @@ -162,37 +173,34 @@ void intel_batch_submit(ScrnInfoPtr scrn) assert (!intel->in_batch_atomic); if (intel->batch_used == 0) return; - /* Emit a padding dword if we aren't going to be quad-word aligned. */ - if ((intel->batch_used & 4) == 0) { - *(uint32_t *) (intel->batch_ptr + intel->batch_used) = MI_NOOP; - intel->batch_used += 4; - } + if (intel->vertex_flush) + intel->vertex_flush(intel); + intel_end_vertex(intel); /* Mark the end of the batchbuffer. */ - *(uint32_t *) (intel->batch_ptr + intel->batch_used) = - MI_BATCH_BUFFER_END; - intel->batch_used += 4; + OUT_BATCH(MI_BATCH_BUFFER_END); + /* Emit a padding dword if we aren't going to be quad-word aligned. */ + if (intel->batch_used & 1) + OUT_BATCH(MI_NOOP); if (DUMP_BATCHBUFFERS) { FILE *file = fopen(DUMP_BATCHBUFFERS, "a"); if (file) { - fwrite (intel->batch_ptr, intel->batch_used, 1, file); + fwrite (intel->batch_ptr, intel->batch_used*4, 1, file); fclose(file); } } - dri_bo_unmap(intel->batch_bo); - intel->batch_ptr = NULL; - - ret = - dri_bo_exec(intel->batch_bo, intel->batch_used, NULL, 0, - 0xffffffff); + ret = dri_bo_subdata(intel->batch_bo, 0, intel->batch_used*4, intel->batch_ptr); + if (ret == 0) + ret = dri_bo_exec(intel->batch_bo, intel->batch_used*4, + NULL, 0, 0xffffffff); if (ret != 0) { static int once; if (!once) { xf86DrvMsg(scrn->scrnIndex, X_ERROR, "Failed to submit batch buffer, expect rendering corruption " @@ -263,9 +271,9 @@ void intel_batch_wait_last(ScrnInfoPtr scrn) { intel_screen_private *intel = intel_get_screen_private(scrn); /* Map it CPU write, which guarantees it's done. This is a completely * non performance path, so we don't need anything better. */ - drm_intel_bo_map(intel->last_batch_bo, TRUE); - drm_intel_bo_unmap(intel->last_batch_bo); + drm_intel_gem_bo_map_gtt(intel->last_batch_bo); + drm_intel_gem_bo_unmap_gtt(intel->last_batch_bo); } diff --git a/src/i830_batchbuffer.h b/src/i830_batchbuffer.h index 2793bc01..b5c729a4 100644 --- a/src/i830_batchbuffer.h +++ b/src/i830_batchbuffer.h @@ -38,13 +38,18 @@ void intel_batch_teardown(ScrnInfoPtr scrn); void intel_batch_emit_flush(ScrnInfoPtr scrn); void intel_batch_submit(ScrnInfoPtr scrn); void intel_batch_wait_last(ScrnInfoPtr scrn); static inline int intel_batch_space(intel_screen_private *intel) { - return (intel->batch_bo->size - BATCH_RESERVED) - (intel->batch_used); + return (intel->batch_bo->size - BATCH_RESERVED) - (4*intel->batch_used); +} + +static inline int intel_vertex_space(intel_screen_private *intel) +{ + return intel->vertex_bo ? intel->vertex_bo->size - (4*intel->vertex_used) : 0; } static inline void intel_batch_require_space(ScrnInfoPtr scrn, intel_screen_private *intel, GLuint sz) { assert(sz < intel->batch_bo->size - 8); @@ -57,13 +62,13 @@ static inline void intel_batch_start_atomic(ScrnInfoPtr scrn, unsigned int sz) intel_screen_private *intel = intel_get_screen_private(scrn); assert(!intel->in_batch_atomic); intel_batch_require_space(scrn, intel, sz * 4); intel->in_batch_atomic = TRUE; - intel->batch_atomic_limit = intel->batch_used + sz * 4; + intel->batch_atomic_limit = intel->batch_used + sz; } static inline void intel_batch_end_atomic(ScrnInfoPtr scrn) { intel_screen_private *intel = intel_get_screen_private(scrn); @@ -71,52 +76,46 @@ static inline void intel_batch_end_atomic(ScrnInfoPtr scrn) assert(intel->batch_used <= intel->batch_atomic_limit); intel->in_batch_atomic = FALSE; } static inline void intel_batch_emit_dword(intel_screen_private *intel, uint32_t dword) { - assert(intel->batch_ptr != NULL); - assert(intel->batch_emitting); - *(uint32_t *) (intel->batch_ptr + intel->batch_used) = dword; - intel->batch_used += 4; + intel->batch_ptr[intel->batch_used++] = dword; } static inline void intel_batch_align(intel_screen_private *intel, uint32_t align) { uint32_t delta; - assert(intel->batch_ptr != NULL); + align /= 4; assert(align); if ((delta = intel->batch_used & (align - 1))) { delta = align - delta; - memset (intel->batch_ptr + intel->batch_used, 0, delta); + memset (intel->batch_ptr + intel->batch_used, 0, 4*delta); intel->batch_used += delta; } } static inline void intel_batch_emit_reloc(intel_screen_private *intel, dri_bo * bo, uint32_t read_domains, uint32_t write_domains, uint32_t delta, int needs_fence) { - assert(intel_batch_space(intel) >= 4); - *(uint32_t *) (intel->batch_ptr + intel->batch_used) = - bo->offset + delta; if (needs_fence) drm_intel_bo_emit_reloc_fence(intel->batch_bo, - intel->batch_used, + intel->batch_used * 4, bo, delta, read_domains, write_domains); else - drm_intel_bo_emit_reloc(intel->batch_bo, intel->batch_used, + drm_intel_bo_emit_reloc(intel->batch_bo, intel->batch_used * 4, bo, delta, read_domains, write_domains); - intel->batch_used += 4; + intel_batch_emit_dword(intel, bo->offset + delta); } static inline void intel_batch_mark_pixmap_domains(intel_screen_private *intel, struct intel_pixmap *priv, uint32_t read_domains, uint32_t write_domain) @@ -141,15 +140,12 @@ static inline void intel_batch_emit_reloc_pixmap(intel_screen_private *intel, PixmapPtr pixmap, uint32_t read_domains, uint32_t write_domain, uint32_t delta, int needs_fence) { struct intel_pixmap *priv = i830_get_pixmap_intel(pixmap); - assert(intel->batch_ptr != NULL); - assert(intel_batch_space(intel) >= 4); - intel_batch_mark_pixmap_domains(intel, priv, read_domains, write_domain); intel_batch_emit_reloc(intel, priv->bo, read_domains, write_domain, delta, needs_fence); } @@ -181,25 +177,13 @@ union intfloat { do { \ if (intel->batch_emitting != 0) \ FatalError("%s: BEGIN_BATCH called without closing " \ "ADVANCE_BATCH\n", __FUNCTION__); \ assert(!intel->in_batch_atomic); \ intel_batch_require_space(scrn, intel, (n) * 4); \ - intel->batch_emitting = (n) * 4; \ - intel->batch_emit_start = intel->batch_used; \ -} while (0) - -/* special-case variant for when we have preallocated space */ -#define ATOMIC_BATCH(n) \ -do { \ - if (intel->batch_emitting != 0) \ - FatalError("%s: ATOMIC_BATCH called without closing " \ - "ADVANCE_BATCH\n", __FUNCTION__); \ - assert(intel->in_batch_atomic); \ - assert(intel->batch_used + (n) * 4 <= intel->batch_atomic_limit); \ - intel->batch_emitting = (n) * 4; \ + intel->batch_emitting = (n); \ intel->batch_emit_start = intel->batch_used; \ } while (0) #define ADVANCE_BATCH() do { \ if (intel->batch_emitting == 0) \ FatalError("%s: ADVANCE_BATCH called with no matching " \ @@ -221,7 +205,14 @@ do { \ /* Note: not actually syncing, just flushing each batch. */ \ intel_batch_submit(scrn); \ } \ intel->batch_emitting = 0; \ } while (0) +void intel_next_vertex(intel_screen_private *intel); +static inline void intel_vertex_emit(intel_screen_private *intel, float v) +{ + intel->vertex_ptr[intel->vertex_used++] = v; +} +#define OUT_VERTEX(v) intel_vertex_emit(intel, v) + #endif /* _INTEL_BATCHBUFFER_H */ diff --git a/src/i830_driver.c b/src/i830_driver.c index db8af063..6ec6f519 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -1224,17 +1224,18 @@ I830ScreenInit(int scrnIndex, ScreenPtr screen, int argc, char **argv) if (!I830AccelInit(screen)) { xf86DrvMsg(scrn->scrnIndex, X_ERROR, "Hardware acceleration initialization failed\n"); return FALSE; } - if (IS_I965G(intel)) + if (IS_I965G(intel)) { intel->batch_flush_notify = i965_batch_flush_notify; - else if (IS_I9XX(intel)) + } else if (IS_I9XX(intel)) { + intel->vertex_flush = i915_vertex_flush; intel->batch_flush_notify = i915_batch_flush_notify; - else + } else intel->batch_flush_notify = i830_batch_flush_notify; miInitializeBackingStore(screen); xf86SetBackingStore(screen); xf86SetSilkenMouse(screen); miDCInitialize(screen, xf86GetPointerScreenFuncs()); diff --git a/src/i830_render.c b/src/i830_render.c index d3bc18e2..cba65eb3 100644 --- a/src/i830_render.c +++ b/src/i830_render.c @@ -299,13 +299,14 @@ static void i830_texture_setup(PicturePtr picture, PixmapPtr pixmap, int unit) tiling_bits |= TM0S1_TILE_WALK; } else tiling_bits = 0; format = i8xx_get_card_format(intel, picture); - ATOMIC_BATCH(10); + assert(intel->in_batch_atomic); + OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_2 | LOAD_TEXTURE_MAP(unit) | 4); OUT_RELOC_PIXMAP(pixmap, I915_GEM_DOMAIN_SAMPLER, 0, 0); OUT_BATCH(((pixmap->drawable.height - 1) << TM0S1_HEIGHT_SHIFT) | ((pixmap->drawable.width - 1) << @@ -333,18 +334,20 @@ static void i830_texture_setup(PicturePtr picture, PixmapPtr pixmap, int unit) TEXBIND_SET3(TEXCOORDSRC_KEEP)); OUT_BATCH(_3DSTATE_MAP_TEX_STREAM_CMD | (unit << 16) | DISABLE_TEX_STREAM_BUMP | ENABLE_TEX_STREAM_COORD_SET | TEX_STREAM_COORD_SET(unit) | ENABLE_TEX_STREAM_MAP_IDX | TEX_STREAM_MAP_IDX(unit)); - ADVANCE_BATCH(); } Bool -i830_check_composite(int op, PicturePtr source_picture, PicturePtr mask_picture, - PicturePtr dest_picture) +i830_check_composite(int op, + PicturePtr source_picture, + PicturePtr mask_picture, + PicturePtr dest_picture, + int width, int height) { ScrnInfoPtr scrn = xf86Screens[dest_picture->pDrawable->pScreen->myNum]; uint32_t tmp1; /* Check for unsupported compositing operations. */ if (op >= sizeof(i830_blend_op) / sizeof(i830_blend_op[0])) { @@ -370,12 +373,29 @@ i830_check_composite(int op, PicturePtr source_picture, PicturePtr mask_picture, if (!i830_get_dest_format(dest_picture, &tmp1)) { intel_debug_fallback(scrn, "Get Color buffer format\n"); return FALSE; } + if (width > 2048 || height > 2048) { + intel_debug_fallback(scrn, "Operation is too large (%d, %d)\n", width, height); + return FALSE; + } + + return TRUE; +} + +Bool +i830_check_composite_target(PixmapPtr pixmap) +{ + if (pixmap->drawable.width > 2048 || pixmap->drawable.height > 2048) + return FALSE; + + if(!intel_check_pitch_3d(pixmap)) + return FALSE; + return TRUE; } Bool i830_check_composite_texture(ScreenPtr screen, PicturePtr picture) { @@ -546,13 +566,13 @@ static void i830_emit_composite_state(ScrnInfoPtr scrn) intel->needs_render_state_emit = FALSE; IntelEmitInvarientState(scrn); intel->last_3d = LAST_3D_RENDER; - ATOMIC_BATCH(21); + assert(intel->in_batch_atomic); if (i830_pixmap_tiled(intel->render_dest)) { tiling_bits = BUF_3D_TILED_SURFACE; if (i830_get_pixmap_intel(intel->render_dest)->tiling == I915_TILING_Y) tiling_bits |= BUF_3D_TILE_WALK_Y; @@ -612,14 +632,12 @@ static void i830_emit_composite_state(ScrnInfoPtr scrn) texcoordfmt |= (TEXCOORDFMT_2D << 2); else texcoordfmt |= (TEXCOORDFMT_3D << 2); } OUT_BATCH(_3DSTATE_VERTEX_FORMAT_2_CMD | texcoordfmt); - ADVANCE_BATCH(); - i830_texture_setup(intel->render_source_picture, intel->render_source, 0); if (intel->render_mask) { i830_texture_setup(intel->render_mask_picture, intel->render_mask, 1); } } @@ -753,14 +771,12 @@ i830_emit_composite_primitive(PixmapPtr dest, per_vertex += 3; /* mask x/y/w */ } } num_floats = 3 * per_vertex; - ATOMIC_BATCH(1 + num_floats); - OUT_BATCH(PRIM3D_INLINE | PRIM3D_RECTLIST | (num_floats - 1)); OUT_BATCH_F(dstX + w); OUT_BATCH_F(dstY + h); OUT_BATCH_F(src_x[2] / intel->scale_units[0][0]); OUT_BATCH_F(src_y[2] / intel->scale_units[0][1]); if (!is_affine_src) { @@ -800,14 +816,12 @@ i830_emit_composite_primitive(PixmapPtr dest, OUT_BATCH_F(mask_x[0] / intel->scale_units[1][0]); OUT_BATCH_F(mask_y[0] / intel->scale_units[1][1]); if (!is_affine_mask) { OUT_BATCH_F(mask_w[0]); } } - - ADVANCE_BATCH(); } /** * Do a single rectangle composite operation. */ void diff --git a/src/i830_uxa.c b/src/i830_uxa.c index d4028959..a2da530c 100644 --- a/src/i830_uxa.c +++ b/src/i830_uxa.c @@ -320,42 +320,47 @@ static void i830_uxa_done_solid(PixmapPtr pixmap) /** * TODO: * - support planemask using FULL_BLT_CMD? */ static Bool -i830_uxa_check_copy(DrawablePtr source, DrawablePtr dest, +i830_uxa_check_copy(PixmapPtr source, PixmapPtr dest, int alu, Pixel planemask) { - ScrnInfoPtr scrn = xf86Screens[dest->pScreen->myNum]; + ScrnInfoPtr scrn = xf86Screens[dest->drawable.pScreen->myNum]; intel_screen_private *intel = intel_get_screen_private(scrn); if (IS_GEN6(intel)) { intel_debug_fallback(scrn, "Sandybridge BLT engine not supported\n"); return FALSE; } - if (!UXA_PM_IS_SOLID(source, planemask)) { + if (!UXA_PM_IS_SOLID(&source->drawable, planemask)) { intel_debug_fallback(scrn, "planemask is not solid"); return FALSE; } - if (source->bitsPerPixel != dest->bitsPerPixel) { + if (source->drawable.bitsPerPixel != dest->drawable.bitsPerPixel) { intel_debug_fallback(scrn, "mixed bpp copies unsupported\n"); return FALSE; } - switch (source->bitsPerPixel) { + 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) @@ -365,17 +370,12 @@ i830_uxa_prepare_copy(PixmapPtr source, PixmapPtr dest, int xdir, drm_intel_bo *bo_table[] = { NULL, /* batch_bo */ i830_get_pixmap_bo(source), i830_get_pixmap_bo(dest), }; - if (!intel_check_pitch_2d(source)) - return FALSE; - if (!intel_check_pitch_2d(dest)) - return FALSE; - if (!i830_get_aperture_space(scrn, bo_table, ARRAY_SIZE(bo_table))) return FALSE; intel->render_source = source; intel->BR[13] = I830CopyROP[alu] << 16; @@ -464,12 +464,16 @@ static void i830_uxa_done_copy(PixmapPtr dest) * * This is shared between i830 through i965. */ 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); } #define xFixedToFloat(val) \ ((float)xFixedToInt(val) + ((float)xFixedFrac(val) / 65536.0)) @@ -1048,12 +1052,17 @@ Bool i830_uxa_init(ScreenPtr screen) memset(intel->uxa_driver, 0, sizeof(*intel->uxa_driver)); intel->bufferOffset = 0; intel->uxa_driver->uxa_major = 1; intel->uxa_driver->uxa_minor = 0; + intel->prim_offset = 0; + intel->vertex_count = 0; + intel->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; @@ -1063,19 +1072,21 @@ Bool i830_uxa_init(ScreenPtr screen) intel->uxa_driver->copy = i830_uxa_copy; intel->uxa_driver->done_copy = i830_uxa_done_copy; /* 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; diff --git a/src/i915_3d.c b/src/i915_3d.c index 517c6851..906043b1 100644 --- a/src/i915_3d.c +++ b/src/i915_3d.c @@ -35,13 +35,13 @@ #include "i915_reg.h" void I915EmitInvarientState(ScrnInfoPtr scrn) { intel_screen_private *intel = intel_get_screen_private(scrn); - ATOMIC_BATCH(24); + assert(intel->in_batch_atomic); OUT_BATCH(_3DSTATE_AA_CMD | AA_LINE_ECAAR_WIDTH_ENABLE | AA_LINE_ECAAR_WIDTH_1_0 | AA_LINE_REGION_WIDTH_ENABLE | AA_LINE_REGION_WIDTH_1_0); @@ -82,14 +82,19 @@ void I915EmitInvarientState(ScrnInfoPtr scrn) OUT_BATCH(_3DSTATE_MODES_4_CMD | ENABLE_LOGIC_OP_FUNC | LOGIC_OP_FUNC(LOGICOP_COPY) | ENABLE_STENCIL_WRITE_MASK | STENCIL_WRITE_MASK(0xff) | ENABLE_STENCIL_TEST_MASK | STENCIL_TEST_MASK(0xff)); - OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(3) | 0); + OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(3) | I1_LOAD_S(4) | I1_LOAD_S(5) | 2); OUT_BATCH(0x00000000); /* Disable texture coordinate wrap-shortest */ + OUT_BATCH((1 << S4_POINT_WIDTH_SHIFT) | + S4_LINE_WIDTH_ONE | + S4_CULLMODE_NONE | + S4_VFMT_XY); + OUT_BATCH(0x00000000); /* Stencil. */ OUT_BATCH(_3DSTATE_SCISSOR_ENABLE_CMD | DISABLE_SCISSOR_RECT); OUT_BATCH(_3DSTATE_SCISSOR_RECT_0_CMD); OUT_BATCH(0); OUT_BATCH(0); @@ -101,9 +106,7 @@ void I915EmitInvarientState(ScrnInfoPtr scrn) OUT_BATCH(_3DSTATE_STIPPLE); OUT_BATCH(0x00000000); OUT_BATCH(_3DSTATE_BACKFACE_STENCIL_OPS | BFO_ENABLE_STENCIL_TWO_SIDE | 0); OUT_BATCH(MI_NOOP); - - ADVANCE_BATCH(); } diff --git a/src/i915_3d.h b/src/i915_3d.h index f85780aa..043a6d56 100644 --- a/src/i915_3d.h +++ b/src/i915_3d.h @@ -415,39 +415,27 @@ do { \ /** * Sets up local state for accumulating a fragment shader buffer. * * \param x maximum number of shader commands that may be used between * a FS_START and FS_END */ -#define FS_LOCALS(x) \ - uint32_t _shader_buf[(x) * 3]; \ - unsigned int _max_shader_commands = x; \ - unsigned int _cur_shader_commands +#define FS_LOCALS() \ + uint32_t _shader_offset #define FS_BEGIN() \ do { \ - _cur_shader_commands = 0; \ + _shader_offset = intel->batch_used++; \ } while (0) #define FS_OUT(_shaderop) \ do { \ - if (_cur_shader_commands >= _max_shader_commands) \ - FatalError("fragment shader command buffer exceeded (%d)\n", \ - _cur_shader_commands); \ - _shader_buf[_cur_shader_commands * 3 + 0] = _shaderop.ui[0]; \ - _shader_buf[_cur_shader_commands * 3 + 1] = _shaderop.ui[1]; \ - _shader_buf[_cur_shader_commands * 3 + 2] = _shaderop.ui[2]; \ - ++_cur_shader_commands; \ + OUT_BATCH(_shaderop.ui[0]); \ + OUT_BATCH(_shaderop.ui[1]); \ + OUT_BATCH(_shaderop.ui[2]); \ } while (0) #define FS_END() \ do { \ - int _i, _pad = (_cur_shader_commands & 0x1) ? 0 : 1; \ - ATOMIC_BATCH(_cur_shader_commands * 3 + 1 + _pad); \ - OUT_BATCH(_3DSTATE_PIXEL_SHADER_PROGRAM | \ - (_cur_shader_commands * 3 - 1)); \ - for (_i = 0; _i < _cur_shader_commands * 3; _i++) \ - OUT_BATCH(_shader_buf[_i]); \ - if (_pad != 0) \ - OUT_BATCH(MI_NOOP); \ - ADVANCE_BATCH(); \ + intel->batch_ptr[_shader_offset] = \ + _3DSTATE_PIXEL_SHADER_PROGRAM | \ + (intel->batch_used - _shader_offset - 2); \ } while (0); diff --git a/src/i915_reg.h b/src/i915_reg.h index a61bc401..746a4131 100644 --- a/src/i915_reg.h +++ b/src/i915_reg.h @@ -29,25 +29,26 @@ #define _I915_REG_H_ #define I915_SET_FIELD( var, mask, value ) (var &= ~(mask), var |= value) #define CMD_3D (0x3<<29) -#define PRIM3D_INLINE (CMD_3D | (0x1f<<24)) -#define PRIM3D_TRILIST (0x0<<18) -#define PRIM3D_TRISTRIP (0x1<<18) -#define PRIM3D_TRISTRIP_RVRSE (0x2<<18) -#define PRIM3D_TRIFAN (0x3<<18) -#define PRIM3D_POLY (0x4<<18) -#define PRIM3D_LINELIST (0x5<<18) -#define PRIM3D_LINESTRIP (0x6<<18) -#define PRIM3D_RECTLIST (0x7<<18) -#define PRIM3D_POINTLIST (0x8<<18) -#define PRIM3D_DIB (0x9<<18) -#define PRIM3D_CLEAR_RECT (0xa<<18) -#define PRIM3D_ZONE_INIT (0xd<<18) +#define PRIM3D (CMD_3D | (0x1f<<24)) +#define PRIM3D_INDIRECT_SEQUENTIAL ((1<<23) | (0<<17)) +#define PRIM3D_TRILIST (PRIM3D | (0x0<<18)) +#define PRIM3D_TRISTRIP (PRIM3D | (0x1<<18)) +#define PRIM3D_TRISTRIP_RVRSE (PRIM3D | (0x2<<18)) +#define PRIM3D_TRIFAN (PRIM3D | (0x3<<18)) +#define PRIM3D_POLY (PRIM3D | (0x4<<18)) +#define PRIM3D_LINELIST (PRIM3D | (0x5<<18)) +#define PRIM3D_LINESTRIP (PRIM3D | (0x6<<18)) +#define PRIM3D_RECTLIST (PRIM3D | (0x7<<18)) +#define PRIM3D_POINTLIST (PRIM3D | (0x8<<18)) +#define PRIM3D_DIB (PRIM3D | (0x9<<18)) +#define PRIM3D_CLEAR_RECT (PRIM3D | (0xa<<18)) +#define PRIM3D_ZONE_INIT (PRIM3D | (0xd<<18)) #define PRIM3D_MASK (0x1f<<18) /* p137 */ #define _3DSTATE_AA_CMD (CMD_3D | (0x06<<24)) #define AA_LINE_ECAAR_WIDTH_ENABLE (1<<16) #define AA_LINE_ECAAR_WIDTH_0_5 0 diff --git a/src/i915_render.c b/src/i915_render.c index 59d92481..3d38397c 100644 --- a/src/i915_render.c +++ b/src/i915_render.c @@ -130,14 +130,16 @@ static uint32_t i915_get_blend_cntl(int op, PicturePtr mask, dblend = BLENDFACT_SRC_COLR; } else if (dblend == BLENDFACT_INV_SRC_ALPHA) { dblend = BLENDFACT_INV_SRC_COLR; } } - return (sblend << S6_CBUF_SRC_BLEND_FACT_SHIFT) | - (dblend << S6_CBUF_DST_BLEND_FACT_SHIFT); + return S6_CBUF_BLEND_ENABLE | S6_COLOR_WRITE_ENABLE | + (BLENDFUNC_ADD << S6_CBUF_BLEND_FUNC_SHIFT) | + (sblend << S6_CBUF_SRC_BLEND_FACT_SHIFT) | + (dblend << S6_CBUF_DST_BLEND_FACT_SHIFT); } #define DSTORG_HORT_BIAS(x) ((x)<<20) #define DSTORG_VERT_BIAS(x) ((x)<<16) static Bool i915_get_dest_format(PicturePtr dest_picture, uint32_t * dst_format) @@ -181,13 +183,14 @@ static Bool i915_get_dest_format(PicturePtr dest_picture, uint32_t * dst_format) } Bool i915_check_composite(int op, PicturePtr source_picture, PicturePtr mask_picture, - PicturePtr dest_picture) + PicturePtr dest_picture, + int width, int height) { ScrnInfoPtr scrn = xf86Screens[dest_picture->pDrawable->pScreen->myNum]; uint32_t tmp1; /* Check for unsupported compositing operations. */ if (op >= sizeof(i915_blend_op) / sizeof(i915_blend_op[0])) { @@ -200,25 +203,42 @@ i915_check_composite(int op, /* Check if it's component alpha that relies on a source alpha * and on the source value. We can only get one of those * into the single source value that we get to blend with. */ if (i915_blend_op[op].src_alpha && (i915_blend_op[op].src_blend != BLENDFACT_ZERO)) { - intel_debug_fallback(scrn, - "Component alpha not supported " - "with source alpha and source " - "value blending.\n"); - return FALSE; + if (op != PictOpOver) { + intel_debug_fallback(scrn, + "Component alpha not supported " + "with source alpha and source " + "value blending.\n"); + return FALSE; + } } } if (!i915_get_dest_format(dest_picture, &tmp1)) { intel_debug_fallback(scrn, "Get Color buffer format\n"); return FALSE; } + if (width > 2048 || height > 2048) + return FALSE; + + return TRUE; +} + +Bool +i915_check_composite_target(PixmapPtr pixmap) +{ + if (pixmap->drawable.width > 2048 || pixmap->drawable.height > 2048) + return FALSE; + + if(!intel_check_pitch_3d(pixmap)) + return FALSE; + return TRUE; } Bool i915_check_composite_texture(ScreenPtr screen, PicturePtr picture) { @@ -285,14 +305,14 @@ static Bool i915_texture_setup(PicturePtr picture, PixmapPtr pixmap, int unit) int w, h, i; uint32_t wrap_mode, tiling_bits; pitch = intel_get_pixmap_pitch(pixmap); w = picture->pDrawable->width; h = picture->pDrawable->height; - intel->scale_units[unit][0] = pixmap->drawable.width; - intel->scale_units[unit][1] = pixmap->drawable.height; + intel->scale_units[unit][0] = 1. / pixmap->drawable.width; + intel->scale_units[unit][1] = 1. / pixmap->drawable.height; for (i = 0; i < sizeof(i915_tex_formats) / sizeof(i915_tex_formats[0]); i++) { if (i915_tex_formats[i].fmt == picture->format) break; } @@ -365,12 +385,386 @@ static Bool i915_texture_setup(PicturePtr picture, PixmapPtr pixmap, int unit) intel->transform[unit] = picture->transform; return TRUE; } +static void +i915_emit_composite_primitive_constant(PixmapPtr dest, + int srcX, int srcY, + int maskX, int maskY, + int dstX, int dstY, + int w, int h) +{ + ScrnInfoPtr scrn = xf86Screens[dest->drawable.pScreen->myNum]; + intel_screen_private *intel = intel_get_screen_private(scrn); + float x, y; + + x = dstX + intel->dst_coord_adjust; + y = dstY + intel->dst_coord_adjust; + + OUT_VERTEX(x + w); + OUT_VERTEX(y + h); + + OUT_VERTEX(x); + OUT_VERTEX(y + h); + + OUT_VERTEX(x); + OUT_VERTEX(y); +} + +static void +i915_emit_composite_primitive_identity_source(PixmapPtr dest, + int srcX, int srcY, + int maskX, int maskY, + int dstX, int dstY, + int w, int h) +{ + ScrnInfoPtr scrn = xf86Screens[dest->drawable.pScreen->myNum]; + intel_screen_private *intel = intel_get_screen_private(scrn); + float dst_x, dst_y, src_x, src_y; + + dst_x = dstX + intel->dst_coord_adjust; + dst_y = dstY + intel->dst_coord_adjust; + src_x = srcX + intel->src_coord_adjust; + src_y = srcY + intel->src_coord_adjust; + + OUT_VERTEX(dst_x + w); + OUT_VERTEX(dst_y + h); + OUT_VERTEX((src_x + w) * intel->scale_units[0][0]); + OUT_VERTEX((src_y + h) * intel->scale_units[0][1]); + + OUT_VERTEX(dst_x); + OUT_VERTEX(dst_y + h); + OUT_VERTEX(src_x * intel->scale_units[0][0]); + OUT_VERTEX((src_y + h) * intel->scale_units[0][1]); + + OUT_VERTEX(dst_x); + OUT_VERTEX(dst_y); + OUT_VERTEX(src_x * intel->scale_units[0][0]); + OUT_VERTEX(src_y * intel->scale_units[0][1]); +} + +static void +i915_emit_composite_primitive_affine_source(PixmapPtr dest, + int srcX, int srcY, + int maskX, int maskY, + int dstX, int dstY, + int w, int h) +{ + ScrnInfoPtr scrn = xf86Screens[dest->drawable.pScreen->myNum]; + intel_screen_private *intel = intel_get_screen_private(scrn); + float x, y, src_x[3], src_y[3]; + + x = srcX + intel->src_coord_adjust; + y = srcY + intel->src_coord_adjust; + + if (!i830_get_transformed_coordinates(x, y, + intel->transform[0], + &src_x[0], + &src_y[0])) + return; + + if (!i830_get_transformed_coordinates(x, y + h, + intel->transform[0], + &src_x[1], + &src_y[1])) + return; + + if (!i830_get_transformed_coordinates(x + w, y + h, + intel->transform[0], + &src_x[2], + &src_y[2])) + return; + + x = dstX + intel->dst_coord_adjust; + y = dstY + intel->dst_coord_adjust; + + OUT_VERTEX(x + w); + OUT_VERTEX(y + h); + OUT_VERTEX(src_x[2] * intel->scale_units[0][0]); + OUT_VERTEX(src_y[2] * intel->scale_units[0][1]); + + OUT_VERTEX(x); + OUT_VERTEX(y + h); + OUT_VERTEX(src_x[1] * intel->scale_units[0][0]); + OUT_VERTEX(src_y[1] * intel->scale_units[0][1]); + + OUT_VERTEX(x); + OUT_VERTEX(y); + OUT_VERTEX(src_x[0] * intel->scale_units[0][0]); + OUT_VERTEX(src_y[0] * intel->scale_units[0][1]); +} + +static void +i915_emit_composite_primitive_constant_identity_mask(PixmapPtr dest, + int srcX, int srcY, + int maskX, int maskY, + int dstX, int dstY, + int w, int h) +{ + ScrnInfoPtr scrn = xf86Screens[dest->drawable.pScreen->myNum]; + intel_screen_private *intel = intel_get_screen_private(scrn); + float x, y, mx, my; + + x = dstX + intel->dst_coord_adjust; + y = dstY + intel->dst_coord_adjust; + mx = maskX + intel->mask_coord_adjust; + my = maskY + intel->mask_coord_adjust; + + OUT_VERTEX(x + w); + OUT_VERTEX(y + h); + OUT_VERTEX((mx + w) * intel->scale_units[0][0]); + OUT_VERTEX((my + h) * intel->scale_units[0][1]); + + OUT_VERTEX(x); + OUT_VERTEX(y + h); + OUT_VERTEX(mx * intel->scale_units[0][0]); + OUT_VERTEX((my + h) * intel->scale_units[0][1]); + + OUT_VERTEX(x); + OUT_VERTEX(y); + OUT_VERTEX(mx * intel->scale_units[0][0]); + OUT_VERTEX(my * intel->scale_units[0][1]); +} + +static void +i915_emit_composite_primitive_identity_source_mask(PixmapPtr dest, + int srcX, int srcY, + int maskX, int maskY, + int dstX, int dstY, + int w, int h) +{ + ScrnInfoPtr scrn = xf86Screens[dest->drawable.pScreen->myNum]; + intel_screen_private *intel = intel_get_screen_private(scrn); + float x, y, sx, sy, mx, my; + + x = dstX + intel->dst_coord_adjust; + y = dstY + intel->dst_coord_adjust; + sx = srcX + intel->src_coord_adjust; + sy = srcY + intel->src_coord_adjust; + mx = maskX + intel->mask_coord_adjust; + my = maskY + intel->mask_coord_adjust; + + OUT_VERTEX(x + w); + OUT_VERTEX(y + h); + OUT_VERTEX((sx + w) * intel->scale_units[0][0]); + OUT_VERTEX((sy + h) * intel->scale_units[0][1]); + OUT_VERTEX((mx + w) * intel->scale_units[1][0]); + OUT_VERTEX((my + h) * intel->scale_units[1][1]); + + OUT_VERTEX(x); + OUT_VERTEX(y + h); + OUT_VERTEX(sx * intel->scale_units[0][0]); + OUT_VERTEX((sy + h) * intel->scale_units[0][1]); + OUT_VERTEX(mx * intel->scale_units[1][0]); + OUT_VERTEX((my + h) * intel->scale_units[1][1]); + + OUT_VERTEX(x); + OUT_VERTEX(y); + OUT_VERTEX(sx * intel->scale_units[0][0]); + OUT_VERTEX(sy * intel->scale_units[0][1]); + OUT_VERTEX(mx * intel->scale_units[1][0]); + OUT_VERTEX(my * intel->scale_units[1][1]); +} + +static void +i915_emit_composite_primitive(PixmapPtr dest, + int srcX, int srcY, + int maskX, int maskY, + int dstX, int dstY, + int w, int h) +{ + ScrnInfoPtr scrn = xf86Screens[dest->drawable.pScreen->myNum]; + intel_screen_private *intel = intel_get_screen_private(scrn); + Bool is_affine_src, is_affine_mask = TRUE; + int per_vertex, num_floats; + int tex_unit = 0; + int src_unit = -1, mask_unit = -1; + float src_x[3], src_y[3], src_w[3], mask_x[3], mask_y[3], mask_w[3]; + + per_vertex = 2; /* dest x/y */ + + if (! intel->render_source_is_solid) { + float x = srcX + intel->src_coord_adjust; + float y = srcY + intel->src_coord_adjust; + + src_unit = tex_unit++; + + is_affine_src = i830_transform_is_affine(intel->transform[src_unit]); + if (is_affine_src) { + if (!i830_get_transformed_coordinates(x, y, + intel-> + transform[src_unit], + &src_x[0], + &src_y[0])) + return; + + if (!i830_get_transformed_coordinates(x, y + h, + intel-> + transform[src_unit], + &src_x[1], + &src_y[1])) + return; + + if (!i830_get_transformed_coordinates(x + w, y + h, + intel-> + transform[src_unit], + &src_x[2], + &src_y[2])) + return; + + per_vertex += 2; /* src x/y */ + } else { + if (!i830_get_transformed_coordinates_3d(x, y, + intel-> + transform[src_unit], + &src_x[0], + &src_y[0], + &src_w[0])) + return; + + if (!i830_get_transformed_coordinates_3d(x, y + h, + intel-> + transform[src_unit], + &src_x[1], + &src_y[1], + &src_w[1])) + return; + + if (!i830_get_transformed_coordinates_3d(x + w, y + h, + intel-> + transform[src_unit], + &src_x[2], + &src_y[2], + &src_w[2])) + return; + + per_vertex += 4; /* src x/y/z/w */ + } + } + + if (intel->render_mask && ! intel->render_mask_is_solid) { + float x = maskX + intel->mask_coord_adjust; + float y = maskY + intel->mask_coord_adjust; + + mask_unit = tex_unit++; + + is_affine_mask = i830_transform_is_affine(intel->transform[mask_unit]); + if (is_affine_mask) { + if (!i830_get_transformed_coordinates(x, y, + intel-> + transform[mask_unit], + &mask_x[0], + &mask_y[0])) + return; + + if (!i830_get_transformed_coordinates(x, y + h, + intel-> + transform[mask_unit], + &mask_x[1], + &mask_y[1])) + return; + + if (!i830_get_transformed_coordinates(x + w, y + h, + intel-> + transform[mask_unit], + &mask_x[2], + &mask_y[2])) + return; + + per_vertex += 2; /* mask x/y */ + } else { + if (!i830_get_transformed_coordinates_3d(x, y, + intel-> + transform[mask_unit], + &mask_x[0], + &mask_y[0], + &mask_w[0])) + return; + + if (!i830_get_transformed_coordinates_3d(x, y + h, + intel-> + transform[mask_unit], + &mask_x[1], + &mask_y[1], + &mask_w[1])) + return; + + if (!i830_get_transformed_coordinates_3d(x + w, y + h, + intel-> + transform[mask_unit], + &mask_x[2], + &mask_y[2], + &mask_w[2])) + return; + + per_vertex += 4; /* mask x/y/z/w */ + } + } + + num_floats = 3 * per_vertex; + + OUT_VERTEX(intel->dst_coord_adjust + dstX + w); + OUT_VERTEX(intel->dst_coord_adjust + dstY + h); + if (! intel->render_source_is_solid) { + OUT_VERTEX(src_x[2] * intel->scale_units[src_unit][0]); + OUT_VERTEX(src_y[2] * intel->scale_units[src_unit][1]); + if (!is_affine_src) { + OUT_VERTEX(0.0); + OUT_VERTEX(src_w[2]); + } + } + if (intel->render_mask && ! intel->render_mask_is_solid) { + OUT_VERTEX(mask_x[2] * intel->scale_units[mask_unit][0]); + OUT_VERTEX(mask_y[2] * intel->scale_units[mask_unit][1]); + if (!is_affine_mask) { + OUT_VERTEX(0.0); + OUT_VERTEX(mask_w[2]); + } + } + + OUT_VERTEX(intel->dst_coord_adjust + dstX); + OUT_VERTEX(intel->dst_coord_adjust + dstY + h); + if (! intel->render_source_is_solid) { + OUT_VERTEX(src_x[1] * intel->scale_units[src_unit][0]); + OUT_VERTEX(src_y[1] * intel->scale_units[src_unit][1]); + if (!is_affine_src) { + OUT_VERTEX(0.0); + OUT_VERTEX(src_w[1]); + } + } + if (intel->render_mask && ! intel->render_mask_is_solid) { + OUT_VERTEX(mask_x[1] * intel->scale_units[mask_unit][0]); + OUT_VERTEX(mask_y[1] * intel->scale_units[mask_unit][1]); + if (!is_affine_mask) { + OUT_VERTEX(0.0); + OUT_VERTEX(mask_w[1]); + } + } + + OUT_VERTEX(intel->dst_coord_adjust + dstX); + OUT_VERTEX(intel->dst_coord_adjust + dstY); + if (! intel->render_source_is_solid) { + OUT_VERTEX(src_x[0] * intel->scale_units[src_unit][0]); + OUT_VERTEX(src_y[0] * intel->scale_units[src_unit][1]); + if (!is_affine_src) { + OUT_VERTEX(0.0); + OUT_VERTEX(src_w[0]); + } + } + if (intel->render_mask && ! intel->render_mask_is_solid) { + OUT_VERTEX(mask_x[0] * intel->scale_units[mask_unit][0]); + OUT_VERTEX(mask_y[0] * intel->scale_units[mask_unit][1]); + if (!is_affine_mask) { + OUT_VERTEX(0.0); + OUT_VERTEX(mask_w[0]); + } + } +} + Bool i915_prepare_composite(int op, PicturePtr source_picture, PicturePtr mask_picture, PicturePtr dest_picture, PixmapPtr source, PixmapPtr mask, PixmapPtr dest) { ScrnInfoPtr scrn = xf86Screens[dest_picture->pDrawable->pScreen->myNum]; @@ -379,12 +773,13 @@ i915_prepare_composite(int op, PicturePtr source_picture, NULL, /* batch_bo */ i830_get_pixmap_bo(dest), source ? i830_get_pixmap_bo(source) : NULL, mask ? i830_get_pixmap_bo(mask) : NULL, }; int tex_unit = 0; + int floats_per_vertex; intel->render_source_picture = source_picture; intel->render_source = source; intel->render_mask_picture = mask_picture; intel->render_mask = mask; intel->render_dest_picture = dest_picture; @@ -420,29 +815,52 @@ i915_prepare_composite(int op, PicturePtr source_picture, if (!i915_get_dest_format(dest_picture, &intel->i915_render_state.dst_format)) return FALSE; if (!i830_get_aperture_space(scrn, bo_table, ARRAY_SIZE(bo_table))) return FALSE; + + intel->needs_render_ca_pass = FALSE; + if (mask_picture != NULL && mask_picture->componentAlpha && + PICT_FORMAT_RGB(mask_picture->format)) { + /* Check if it's component alpha that relies on a source alpha + * and on the source value. We can only get one of those + * into the single source value that we get to blend with. + */ + if (i915_blend_op[op].src_alpha && + (i915_blend_op[op].src_blend != BLENDFACT_ZERO)) { + if (op != PictOpOver) + return FALSE; + + intel->needs_render_ca_pass = TRUE; + } + } + intel->dst_coord_adjust = 0; intel->src_coord_adjust = 0; intel->mask_coord_adjust = 0; intel->transform[0] = NULL; intel->scale_units[0][0] = -1; intel->scale_units[0][1] = -1; intel->transform[1] = NULL; intel->scale_units[1][0] = -1; intel->scale_units[1][1] = -1; + floats_per_vertex = 2; /* dest x/y */ if (! intel->render_source_is_solid) { if (!i915_texture_setup(source_picture, source, tex_unit++)) { intel_debug_fallback(scrn, "fail to setup src texture\n"); return FALSE; } + if (i830_transform_is_affine(source_picture->transform)) + floats_per_vertex += 2; /* src x/y */ + else + floats_per_vertex += 4; /* src x/y/z/w */ + if (source_picture->filter == PictFilterNearest) { #if PIXEL_CENTRE_SAMPLE intel->src_coord_adjust = 0.375; #else intel->dst_coord_adjust = -0.125; #endif @@ -454,12 +872,17 @@ i915_prepare_composite(int op, PicturePtr source_picture, if (!i915_texture_setup(mask_picture, mask, tex_unit++)) { intel_debug_fallback(scrn, "fail to setup mask texture\n"); return FALSE; } + if (i830_transform_is_affine(mask_picture->transform)) + floats_per_vertex += 2; /* mask x/y */ + else + floats_per_vertex += 4; /* mask x/y/z/w */ + if (mask_picture->filter == PictFilterNearest) { #if PIXEL_CENTRE_SAMPLE intel->mask_coord_adjust = 0.375; #else intel->dst_coord_adjust = -0.125; #endif @@ -472,54 +895,179 @@ i915_prepare_composite(int op, PicturePtr source_picture, if((source && i830_uxa_pixmap_is_dirty(source)) || (mask && i830_uxa_pixmap_is_dirty(mask))) intel_batch_emit_flush(scrn); intel->needs_render_state_emit = TRUE; + intel->prim_emit = i915_emit_composite_primitive; + if (!mask) { + if (intel->render_source_is_solid) + intel->prim_emit = i915_emit_composite_primitive_constant; + else if (intel->transform[0] == NULL) + intel->prim_emit = i915_emit_composite_primitive_identity_source; + else if (i830_transform_is_affine(intel->transform[0])) + intel->prim_emit = i915_emit_composite_primitive_affine_source; + } else { + if (intel->transform[0] == NULL) { + if (intel->render_source_is_solid) + intel->prim_emit = i915_emit_composite_primitive_constant_identity_mask; + else if (intel->transform[1] == NULL) + intel->prim_emit = i915_emit_composite_primitive_identity_source_mask; + } + } + + if (floats_per_vertex != intel->floats_per_vertex) { + intel->floats_per_vertex = floats_per_vertex; + intel->needs_render_vertex_emit = TRUE; + } + return TRUE; } +static void +i915_composite_emit_shader(intel_screen_private *intel, CARD8 op) +{ + PicturePtr mask_picture = intel->render_mask_picture; + PixmapPtr mask = intel->render_mask; + int src_reg, mask_reg; + Bool is_solid_src, is_solid_mask; + uint32_t dst_format = intel->i915_render_state.dst_format; + int tex_unit, t; + FS_LOCALS(); + + is_solid_src = intel->render_source_is_solid; + is_solid_mask = intel->render_mask_is_solid; + + FS_BEGIN(); + + /* Declare the registers necessary for our program. */ + t = 0; + if (is_solid_src) { + i915_fs_dcl(FS_T8); + src_reg = FS_T8; + } else { + i915_fs_dcl(FS_T0); + i915_fs_dcl(FS_S0); + t++; + } + if (!mask) { + /* No mask, so load directly to output color */ + if (! is_solid_src) { + if (dst_format == COLR_BUF_8BIT) + src_reg = FS_R0; + else + src_reg = FS_OC; + + if (i830_transform_is_affine(intel->transform[0])) + i915_fs_texld(src_reg, FS_S0, FS_T0); + else + i915_fs_texldp(src_reg, FS_S0, FS_T0); + } + + if (src_reg != FS_OC) { + if (dst_format == COLR_BUF_8BIT) + i915_fs_mov(FS_OC, i915_fs_operand(src_reg, W, W, W, W)); + else + i915_fs_mov(FS_OC, i915_fs_operand_reg(src_reg)); + } + } else { + if (is_solid_mask) { + i915_fs_dcl(FS_T9); + mask_reg = FS_T9; + } else { + i915_fs_dcl(FS_T0 + t); + i915_fs_dcl(FS_S0 + t); + } + + tex_unit = 0; + if (! is_solid_src) { + /* Load the source_picture texel */ + if (i830_transform_is_affine(intel->transform[tex_unit])) + i915_fs_texld(FS_R0, FS_S0, FS_T0); + else + i915_fs_texldp(FS_R0, FS_S0, FS_T0); + + src_reg = FS_R0; + tex_unit++; + } + + if (! is_solid_mask) { + /* Load the mask_picture texel */ + if (i830_transform_is_affine(intel->transform[tex_unit])) + i915_fs_texld(FS_R1, FS_S0 + t, FS_T0 + t); + else + i915_fs_texldp(FS_R1, FS_S0 + t, FS_T0 + t); + + mask_reg = FS_R1; + } + + if (dst_format == COLR_BUF_8BIT) { + i915_fs_mul(FS_OC, + i915_fs_operand(src_reg, W, W, W, W), + i915_fs_operand(mask_reg, W, W, W, W)); + } else { + /* If component alpha is active in the mask and the blend + * operation uses the source alpha, then we know we don't + * need the source value (otherwise we would have hit a + * fallback earlier), so we provide the source alpha (src.A * + * mask.X) as output color. + * Conversely, if CA is set and we don't need the source alpha, + * then we produce the source value (src.X * mask.X) and the + * source alpha is unused. Otherwise, we provide the non-CA + * source value (src.X * mask.A). + */ + if (mask_picture->componentAlpha && + PICT_FORMAT_RGB(mask_picture->format)) { + if (i915_blend_op[op].src_alpha) { + i915_fs_mul(FS_OC, + i915_fs_operand(src_reg, W, W, W, W), + i915_fs_operand_reg(mask_reg)); + } else { + i915_fs_mul(FS_OC, + i915_fs_operand_reg(src_reg), + i915_fs_operand_reg(mask_reg)); + } + } else { + i915_fs_mul(FS_OC, + i915_fs_operand_reg(src_reg), + i915_fs_operand(mask_reg, W, W, W, W)); + } + } + } + + FS_END(); +} + static void i915_emit_composite_setup(ScrnInfoPtr scrn) { intel_screen_private *intel = intel_get_screen_private(scrn); int op = intel->i915_render_state.op; PicturePtr mask_picture = intel->render_mask_picture; PicturePtr dest_picture = intel->render_dest_picture; PixmapPtr mask = intel->render_mask; PixmapPtr dest = intel->render_dest; uint32_t dst_format = intel->i915_render_state.dst_format, dst_pitch; - uint32_t blendctl, tiling_bits; - Bool is_affine_src, is_affine_mask; + uint32_t tiling_bits; Bool is_solid_src, is_solid_mask; int tex_count, t; intel->needs_render_state_emit = FALSE; IntelEmitInvarientState(scrn); intel->last_3d = LAST_3D_RENDER; dst_pitch = intel_get_pixmap_pitch(dest); - is_affine_src = i830_transform_is_affine(intel->transform[0]); - is_affine_mask = i830_transform_is_affine(intel->transform[1]); - is_solid_src = intel->render_source_is_solid; is_solid_mask = intel->render_mask_is_solid; tex_count = 0; tex_count += ! is_solid_src; tex_count += mask && ! is_solid_mask; - t = 15; - if (tex_count) - t += 6 * tex_count + 4; - if (is_solid_src) - t += 2; - if (mask && is_solid_mask) - t += 2; - ATOMIC_BATCH (t); + assert(intel->in_batch_atomic); if (tex_count != 0) { OUT_BATCH(_3DSTATE_MAP_STATE | (3 * tex_count)); OUT_BATCH((1 << tex_count) - 1); for (t = 0; t < tex_count; t++) { OUT_RELOC_PIXMAP(intel->texture[t], I915_GEM_DOMAIN_SAMPLER, 0, 0); @@ -562,379 +1110,142 @@ static void i915_emit_composite_setup(ScrnInfoPtr scrn) OUT_BATCH(_3DSTATE_DST_BUF_VARS_CMD); OUT_BATCH(dst_format); { uint32_t ss2; - OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(2) | - I1_LOAD_S(4) | I1_LOAD_S(5) | I1_LOAD_S(6) | 3); ss2 = ~0; t = 0; if (! is_solid_src) { ss2 &= ~S2_TEXCOORD_FMT(t, TEXCOORDFMT_NOT_PRESENT); ss2 |= S2_TEXCOORD_FMT(t, - is_affine_src ? TEXCOORDFMT_2D : - TEXCOORDFMT_4D); + i830_transform_is_affine(intel->transform[t]) ? + TEXCOORDFMT_2D : TEXCOORDFMT_4D); t++; } if (mask && ! is_solid_mask) { ss2 &= ~S2_TEXCOORD_FMT(t, TEXCOORDFMT_NOT_PRESENT); ss2 |= S2_TEXCOORD_FMT(t, - is_affine_mask ? TEXCOORDFMT_2D : - TEXCOORDFMT_4D); + i830_transform_is_affine(intel->transform[t]) ? + TEXCOORDFMT_2D : TEXCOORDFMT_4D); t++; } - OUT_BATCH(ss2); - OUT_BATCH((1 << S4_POINT_WIDTH_SHIFT) | S4_LINE_WIDTH_ONE | - S4_CULLMODE_NONE | S4_VFMT_XY); - blendctl = - i915_get_blend_cntl(op, mask_picture, dest_picture->format); - OUT_BATCH(0x00000000); /* Disable stencil buffer */ - OUT_BATCH(S6_CBUF_BLEND_ENABLE | S6_COLOR_WRITE_ENABLE | - (BLENDFUNC_ADD << S6_CBUF_BLEND_FUNC_SHIFT) | - blendctl); + + if (intel->needs_render_ca_pass) { + OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(2) | 0); + OUT_BATCH(ss2); + } else { + OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(2) | I1_LOAD_S(6) | 1); + OUT_BATCH(ss2); + OUT_BATCH(i915_get_blend_cntl(op, mask_picture, dest_picture->format)); + } /* draw rect is unconditional */ OUT_BATCH(_3DSTATE_DRAW_RECT_CMD); OUT_BATCH(0x00000000); OUT_BATCH(0x00000000); /* ymin, xmin */ OUT_BATCH(DRAW_YMAX(dest->drawable.height - 1) | DRAW_XMAX(dest->drawable.width - 1)); /* yorig, xorig (relate to color buffer?) */ OUT_BATCH(0x00000000); } - ADVANCE_BATCH(); - - { - FS_LOCALS(20); - int src_reg, mask_reg; - - FS_BEGIN(); - - /* Declare the registers necessary for our program. */ - t = 0; - if (is_solid_src) { - i915_fs_dcl(FS_T8); - src_reg = FS_T8; - } else { - i915_fs_dcl(FS_T0); - i915_fs_dcl(FS_S0); - t++; - } - if (!mask) { - /* No mask, so load directly to output color */ - if (! is_solid_src) { - if (dst_format == COLR_BUF_8BIT) - src_reg = FS_R0; - else - src_reg = FS_OC; - - if (is_affine_src) - i915_fs_texld(src_reg, FS_S0, FS_T0); - else - i915_fs_texldp(src_reg, FS_S0, FS_T0); - } - - if (src_reg != FS_OC) { - if (dst_format == COLR_BUF_8BIT) - i915_fs_mov(FS_OC, i915_fs_operand(src_reg, W, W, W, W)); - else - i915_fs_mov(FS_OC, i915_fs_operand_reg(src_reg)); - } - } else { - if (is_solid_mask) { - i915_fs_dcl(FS_T9); - mask_reg = FS_T9; - } else { - i915_fs_dcl(FS_T0 + t); - i915_fs_dcl(FS_S0 + t); - } - - if (! is_solid_src) { - /* Load the source_picture texel */ - if (is_affine_src) { - i915_fs_texld(FS_R0, FS_S0, FS_T0); - } else { - i915_fs_texldp(FS_R0, FS_S0, FS_T0); - } - - src_reg = FS_R0; - } - - if (! is_solid_mask) { - /* Load the mask_picture texel */ - if (is_affine_mask) { - i915_fs_texld(FS_R1, FS_S0 + t, FS_T0 + t); - } else { - i915_fs_texldp(FS_R1, FS_S0 + t, FS_T0 + t); - } - - mask_reg = FS_R1; - } - - if (dst_format == COLR_BUF_8BIT) { - i915_fs_mul(FS_OC, - i915_fs_operand(src_reg, W, W, W, W), - i915_fs_operand(mask_reg, W, W, W, W)); - } else { - /* If component alpha is active in the mask and the blend - * operation uses the source alpha, then we know we don't - * need the source value (otherwise we would have hit a - * fallback earlier), so we provide the source alpha (src.A * - * mask.X) as output color. - * Conversely, if CA is set and we don't need the source alpha, - * then we produce the source value (src.X * mask.X) and the - * source alpha is unused. Otherwise, we provide the non-CA - * source value (src.X * mask.A). - */ - if (mask_picture->componentAlpha && - PICT_FORMAT_RGB(mask_picture->format)) { - if (i915_blend_op[op].src_alpha) { - i915_fs_mul(FS_OC, - i915_fs_operand(src_reg, W, W, W, W), - i915_fs_operand_reg(mask_reg)); - } else { - i915_fs_mul(FS_OC, - i915_fs_operand_reg(src_reg), - i915_fs_operand_reg(mask_reg)); - } - } else { - i915_fs_mul(FS_OC, - i915_fs_operand_reg(src_reg), - i915_fs_operand(mask_reg, W, W, W, W)); - } - } - } - - FS_END(); - } + if (! intel->needs_render_ca_pass) + i915_composite_emit_shader(intel, op); } -/* Emit the vertices for a single composite rectangle. - * - * This function is no longer shared between i830 and i915 generation code. - */ -static void -i915_emit_composite_primitive(PixmapPtr dest, - int srcX, int srcY, - int maskX, int maskY, - int dstX, int dstY, int w, int h) +void +i915_composite(PixmapPtr dest, int srcX, int srcY, int maskX, int maskY, + int dstX, int dstY, int w, int h) { ScrnInfoPtr scrn = xf86Screens[dest->drawable.pScreen->myNum]; intel_screen_private *intel = intel_get_screen_private(scrn); - Bool is_affine_src, is_affine_mask = TRUE; - int per_vertex, num_floats; - int tex_unit = 0; - int src_unit = -1, mask_unit = -1; - float src_x[3], src_y[3], src_w[3], mask_x[3], mask_y[3], mask_w[3]; - per_vertex = 2; /* dest x/y */ + /* 28 + 16 + 10 + 20 + 32 + 16 */ + intel_batch_start_atomic(scrn, 150); - if (! intel->render_source_is_solid) { - float x = srcX + intel->src_coord_adjust; - float y = srcY + intel->src_coord_adjust; + if (intel->needs_render_state_emit) + i915_emit_composite_setup(scrn); - src_unit = tex_unit++; + if (intel_vertex_space(intel) < 3*4*intel->floats_per_vertex) + intel->needs_render_vertex_emit = TRUE; - is_affine_src = i830_transform_is_affine(intel->transform[src_unit]); - if (is_affine_src) { - if (!i830_get_transformed_coordinates(x, y, - intel-> - transform[src_unit], - &src_x[0], - &src_y[0])) - return; - - if (!i830_get_transformed_coordinates(x, y + h, - intel-> - transform[src_unit], - &src_x[1], - &src_y[1])) - return; + if (intel->needs_render_vertex_emit) { + i915_vertex_flush(intel); - if (!i830_get_transformed_coordinates(x + w, y + h, - intel-> - transform[src_unit], - &src_x[2], - &src_y[2])) - return; + if (intel_vertex_space(intel) < 256) { + intel_next_vertex(intel); - per_vertex += 2; /* src x/y */ + OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | + I1_LOAD_S(0) | I1_LOAD_S(1) | 1); + OUT_RELOC(intel->vertex_bo, I915_GEM_DOMAIN_VERTEX, 0, 0); + OUT_BATCH((intel->floats_per_vertex << S1_VERTEX_WIDTH_SHIFT) | + (intel->floats_per_vertex << S1_VERTEX_PITCH_SHIFT)); + intel->vertex_index = 0; } else { - if (!i830_get_transformed_coordinates_3d(x, y, - intel-> - transform[src_unit], - &src_x[0], - &src_y[0], - &src_w[0])) - return; - - if (!i830_get_transformed_coordinates_3d(x, y + h, - intel-> - transform[src_unit], - &src_x[1], - &src_y[1], - &src_w[1])) - return; - - if (!i830_get_transformed_coordinates_3d(x + w, y + h, - intel-> - transform[src_unit], - &src_x[2], - &src_y[2], - &src_w[2])) - return; - - per_vertex += 4; /* src x/y/z/w */ + OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | + I1_LOAD_S(1) | 0); + OUT_BATCH((intel->floats_per_vertex << S1_VERTEX_WIDTH_SHIFT) | + (intel->floats_per_vertex << S1_VERTEX_PITCH_SHIFT)); + + intel->vertex_index = + (intel->vertex_used + intel->floats_per_vertex - 1) / intel->floats_per_vertex; + intel->vertex_used = intel->vertex_index * intel->floats_per_vertex; } - } - - if (intel->render_mask && ! intel->render_mask_is_solid) { - float x = maskX + intel->mask_coord_adjust; - float y = maskY + intel->mask_coord_adjust; - - mask_unit = tex_unit++; - - is_affine_mask = i830_transform_is_affine(intel->transform[mask_unit]); - if (is_affine_mask) { - if (!i830_get_transformed_coordinates(x, y, - intel-> - transform[mask_unit], - &mask_x[0], - &mask_y[0])) - return; - - if (!i830_get_transformed_coordinates(x, y + h, - intel-> - transform[mask_unit], - &mask_x[1], - &mask_y[1])) - return; - - if (!i830_get_transformed_coordinates(x + w, y + h, - intel-> - transform[mask_unit], - &mask_x[2], - &mask_y[2])) - return; - - per_vertex += 2; /* mask x/y */ - } else { - if (!i830_get_transformed_coordinates_3d(x, y, - intel-> - transform[mask_unit], - &mask_x[0], - &mask_y[0], - &mask_w[0])) - return; - - if (!i830_get_transformed_coordinates_3d(x, y + h, - intel-> - transform[mask_unit], - &mask_x[1], - &mask_y[1], - &mask_w[1])) - return; - - if (!i830_get_transformed_coordinates_3d(x + w, y + h, - intel-> - transform[mask_unit], - &mask_x[2], - &mask_y[2], - &mask_w[2])) - return; - per_vertex += 4; /* mask x/y/z/w */ - } + intel->needs_render_vertex_emit = FALSE; } - num_floats = 3 * per_vertex; - - ATOMIC_BATCH(1 + num_floats); - - OUT_BATCH(PRIM3D_INLINE | PRIM3D_RECTLIST | (num_floats - 1)); - OUT_BATCH_F(intel->dst_coord_adjust + dstX + w); - OUT_BATCH_F(intel->dst_coord_adjust + dstY + h); - if (! intel->render_source_is_solid) { - OUT_BATCH_F(src_x[2] / intel->scale_units[src_unit][0]); - OUT_BATCH_F(src_y[2] / intel->scale_units[src_unit][1]); - if (!is_affine_src) { - OUT_BATCH_F(0.0); - OUT_BATCH_F(src_w[2]); - } - } - if (intel->render_mask && ! intel->render_mask_is_solid) { - OUT_BATCH_F(mask_x[2] / intel->scale_units[mask_unit][0]); - OUT_BATCH_F(mask_y[2] / intel->scale_units[mask_unit][1]); - if (!is_affine_mask) { - OUT_BATCH_F(0.0); - OUT_BATCH_F(mask_w[2]); + if (intel->prim_offset == 0) { + if (intel->needs_render_ca_pass) { + OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(6) | 0); + OUT_BATCH(i915_get_blend_cntl(PictOpOutReverse, + intel->render_mask_picture, + intel->render_dest_picture->format)); + i915_composite_emit_shader(intel, PictOpOutReverse); } - } - OUT_BATCH_F(intel->dst_coord_adjust + dstX); - OUT_BATCH_F(intel->dst_coord_adjust + dstY + h); - if (! intel->render_source_is_solid) { - OUT_BATCH_F(src_x[1] / intel->scale_units[src_unit][0]); - OUT_BATCH_F(src_y[1] / intel->scale_units[src_unit][1]); - if (!is_affine_src) { - OUT_BATCH_F(0.0); - OUT_BATCH_F(src_w[1]); - } - } - if (intel->render_mask && ! intel->render_mask_is_solid) { - OUT_BATCH_F(mask_x[1] / intel->scale_units[mask_unit][0]); - OUT_BATCH_F(mask_y[1] / intel->scale_units[mask_unit][1]); - if (!is_affine_mask) { - OUT_BATCH_F(0.0); - OUT_BATCH_F(mask_w[1]); - } + intel->prim_offset = intel->batch_used; + OUT_BATCH(PRIM3D_RECTLIST | PRIM3D_INDIRECT_SEQUENTIAL); + OUT_BATCH(intel->vertex_index); } + intel->vertex_count += 3; - OUT_BATCH_F(intel->dst_coord_adjust + dstX); - OUT_BATCH_F(intel->dst_coord_adjust + dstY); - if (! intel->render_source_is_solid) { - OUT_BATCH_F(src_x[0] / intel->scale_units[src_unit][0]); - OUT_BATCH_F(src_y[0] / intel->scale_units[src_unit][1]); - if (!is_affine_src) { - OUT_BATCH_F(0.0); - OUT_BATCH_F(src_w[0]); - } - } - if (intel->render_mask && ! intel->render_mask_is_solid) { - OUT_BATCH_F(mask_x[0] / intel->scale_units[mask_unit][0]); - OUT_BATCH_F(mask_y[0] / intel->scale_units[mask_unit][1]); - if (!is_affine_mask) { - OUT_BATCH_F(0.0); - OUT_BATCH_F(mask_w[0]); - } - } + intel->prim_emit(dest, + srcX, srcY, + maskX, maskY, + dstX, dstY, + w, h); - ADVANCE_BATCH(); + intel_batch_end_atomic(scrn); } void -i915_composite(PixmapPtr dest, int srcX, int srcY, int maskX, int maskY, - int dstX, int dstY, int w, int h) +i915_vertex_flush(intel_screen_private *intel) { - ScrnInfoPtr scrn = xf86Screens[dest->drawable.pScreen->myNum]; - intel_screen_private *intel = intel_get_screen_private(scrn); - - /* 28 + 16 + 10 + 20 + 32 + 16 */ - intel_batch_start_atomic(scrn, 150); - - if (intel->needs_render_state_emit) - i915_emit_composite_setup(scrn); - - i915_emit_composite_primitive(dest, srcX, srcY, maskX, maskY, dstX, - dstY, w, h); + if (intel->prim_offset == 0) + return; + + intel->batch_ptr[intel->prim_offset] |= intel->vertex_count; + intel->prim_offset = 0; + + if (intel->needs_render_ca_pass) { + OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(6) | 0); + OUT_BATCH(i915_get_blend_cntl(PictOpAdd, + intel->render_mask_picture, + intel->render_dest_picture->format)); + i915_composite_emit_shader(intel, PictOpAdd); + OUT_BATCH(PRIM3D_RECTLIST | PRIM3D_INDIRECT_SEQUENTIAL | intel->vertex_count); + OUT_BATCH(intel->vertex_index); + } - intel_batch_end_atomic(scrn); + intel->vertex_index += intel->vertex_count; + intel->vertex_count = 0; } -void i915_batch_flush_notify(ScrnInfoPtr scrn) +void +i915_batch_flush_notify(ScrnInfoPtr scrn) { intel_screen_private *intel = intel_get_screen_private(scrn); intel->needs_render_state_emit = TRUE; } diff --git a/src/i915_video.c b/src/i915_video.c index 927047be..bbac610b 100644 --- a/src/i915_video.c +++ b/src/i915_video.c @@ -72,14 +72,12 @@ I915DisplayVideoTextured(ScrnInfoPtr scrn, intel_batch_start_atomic(scrn, 200 + 20 * nbox_this_time); IntelEmitInvarientState(scrn); intel->last_3d = LAST_3D_VIDEO; - ATOMIC_BATCH(20); - /* flush map & render cache */ OUT_BATCH(MI_FLUSH | MI_WRITE_DIRTY_STATE | MI_INVALIDATE_MAP_CACHE); OUT_BATCH(0x00000000); /* draw rect -- just clipping */ @@ -131,18 +129,16 @@ I915DisplayVideoTextured(ScrnInfoPtr scrn, /* front buffer, pitch, offset */ OUT_BATCH(_3DSTATE_BUF_INFO_CMD); OUT_BATCH(BUF_3D_ID_COLOR_BACK | BUF_3D_USE_FENCE | BUF_3D_PITCH(intel_get_pixmap_pitch(pixmap))); OUT_RELOC_PIXMAP(pixmap, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0); - ADVANCE_BATCH(); if (!is_planar_fourcc(id)) { - FS_LOCALS(10); + FS_LOCALS(); - ATOMIC_BATCH(16); OUT_BATCH(_3DSTATE_PIXEL_SHADER_CONSTANTS | 4); OUT_BATCH(0x0000001); /* constant 0 */ /* constant 0: brightness/contrast */ OUT_BATCH_F(adaptor_priv->brightness / 128.0); OUT_BATCH_F(adaptor_priv->contrast / 255.0); OUT_BATCH_F(0.0); @@ -181,29 +177,26 @@ I915DisplayVideoTextured(ScrnInfoPtr scrn, } ms3 |= (height - 1) << MS3_HEIGHT_SHIFT; ms3 |= (width - 1) << MS3_WIDTH_SHIFT; OUT_BATCH(ms3); OUT_BATCH(((video_pitch / 4) - 1) << MS4_PITCH_SHIFT); - ADVANCE_BATCH(); - FS_BEGIN(); i915_fs_dcl(FS_S0); i915_fs_dcl(FS_T0); i915_fs_texld(FS_OC, FS_S0, FS_T0); if (adaptor_priv->brightness != 0) { i915_fs_add(FS_OC, i915_fs_operand_reg(FS_OC), i915_fs_operand(FS_C0, X, X, X, ZERO)); } FS_END(); } else { - FS_LOCALS(16); + FS_LOCALS(); - ATOMIC_BATCH(22 + 11 + 11); /* For the planar formats, we set up three samplers -- * one for each plane, in a Y8 format. Because I * couldn't get the special PLANAR_TO_PACKED * shader setup to work, I did the manual pixel shader: * * y' = y - .0625 @@ -329,13 +322,12 @@ I915DisplayVideoTextured(ScrnInfoPtr scrn, ms3 = MAPSURF_8BIT | MT_8BIT_I8 | MS3_USE_FENCE_REGS; ms3 |= (height / 2 - 1) << MS3_HEIGHT_SHIFT; ms3 |= (width / 2 - 1) << MS3_WIDTH_SHIFT; OUT_BATCH(ms3); OUT_BATCH(((video_pitch / 4) - 1) << MS4_PITCH_SHIFT); - ADVANCE_BATCH(); FS_BEGIN(); /* Declare samplers */ i915_fs_dcl(FS_S0); /* Y */ i915_fs_dcl(FS_S1); /* U */ i915_fs_dcl(FS_S2); /* V */ @@ -386,19 +378,13 @@ I915DisplayVideoTextured(ScrnInfoPtr scrn, i915_fs_operand(FS_C4, X, X, X, ZERO)); } FS_END(); } - { - ATOMIC_BATCH(2); - OUT_BATCH(MI_FLUSH | MI_WRITE_DIRTY_STATE | - MI_INVALIDATE_MAP_CACHE); - OUT_BATCH(0x00000000); - ADVANCE_BATCH(); - } + OUT_BATCH(MI_FLUSH | MI_WRITE_DIRTY_STATE | MI_INVALIDATE_MAP_CACHE); /* Set up the offset for translating from the given region * (in screen coordinates) to the backing pixmap. */ #ifdef COMPOSITE pix_xoff = -pixmap->screen_x + pixmap->drawable.x; @@ -408,37 +394,28 @@ I915DisplayVideoTextured(ScrnInfoPtr scrn, pix_yoff = 0; #endif dxo = dstRegion->extents.x1; dyo = dstRegion->extents.y1; + OUT_BATCH(PRIM3D_RECTLIST | (12 * nbox_this_time - 1)); while (nbox_this_time--) { int box_x1 = pbox->x1; int box_y1 = pbox->y1; int box_x2 = pbox->x2; int box_y2 = pbox->y2; float src_scale_x, src_scale_y; pbox++; src_scale_x = ((float)src_w / width) / drw_w; src_scale_y = ((float)src_h / height) / drw_h; - ATOMIC_BATCH(8 + 12); - OUT_BATCH(MI_NOOP); - OUT_BATCH(MI_NOOP); - OUT_BATCH(MI_NOOP); - OUT_BATCH(MI_NOOP); - OUT_BATCH(MI_NOOP); - OUT_BATCH(MI_NOOP); - OUT_BATCH(MI_NOOP); - /* vertex data - rect list consists of bottom right, * bottom left, and top left vertices. */ - OUT_BATCH(PRIM3D_INLINE | PRIM3D_RECTLIST | (12 - 1)); /* bottom right */ OUT_BATCH_F(box_x2 + pix_xoff); OUT_BATCH_F(box_y2 + pix_yoff); OUT_BATCH_F((box_x2 - dxo) * src_scale_x); OUT_BATCH_F((box_y2 - dyo) * src_scale_y); @@ -451,14 +428,12 @@ I915DisplayVideoTextured(ScrnInfoPtr scrn, /* top left */ OUT_BATCH_F(box_x1 + pix_xoff); OUT_BATCH_F(box_y1 + pix_yoff); OUT_BATCH_F((box_x1 - dxo) * src_scale_x); OUT_BATCH_F((box_y1 - dyo) * src_scale_y); - - ADVANCE_BATCH(); } intel_batch_end_atomic(scrn); } i830_debug_flush(scrn); diff --git a/src/i965_render.c b/src/i965_render.c index 7355ed1d..ed4b4d90 100644 --- a/src/i965_render.c +++ b/src/i965_render.c @@ -193,14 +193,17 @@ static Bool i965_get_dest_format(PicturePtr dest_picture, uint32_t * dst_format) } return TRUE; } Bool -i965_check_composite(int op, PicturePtr source_picture, PicturePtr mask_picture, - PicturePtr dest_picture) +i965_check_composite(int op, + PicturePtr source_picture, + PicturePtr mask_picture, + PicturePtr dest_picture, + int width, int height) { ScrnInfoPtr scrn = xf86Screens[dest_picture->pDrawable->pScreen->myNum]; intel_screen_private *intel = intel_get_screen_private(scrn); uint32_t tmp1; if (IS_GEN6(intel)) { @@ -1178,18 +1181,14 @@ static void i965_emit_composite_state(ScrnInfoPtr scrn) /* URB fence. Erratum (Vol 1a, p32): URB_FENCE must not cross a * cache-line (64 bytes). Start by aligning this sequence of ops to * a cache-line... */ ALIGN_BATCH(64); + assert(intel->in_batch_atomic); { - if (IS_IGDNG(intel)) - ATOMIC_BATCH(14); - else - ATOMIC_BATCH(12); - /* Match Mesa driver setup */ OUT_BATCH(MI_FLUSH | MI_STATE_INSTRUCTION_CACHE_FLUSH | BRW_MI_GLOBAL_SNAPSHOT_RESET); if (IS_G4X(intel) || IS_IGDNG(intel)) OUT_BATCH(NEW_PIPELINE_SELECT | PIPELINE_SELECT_3D); @@ -1226,18 +1225,16 @@ static void i965_emit_composite_state(ScrnInfoPtr scrn) OUT_BATCH(0x10000000 | BASE_ADDRESS_MODIFY); } /* Set system instruction pointer */ OUT_BATCH(BRW_STATE_SIP | 0); OUT_RELOC(render_state->sip_kernel_bo, I915_GEM_DOMAIN_INSTRUCTION, 0, 0); - ADVANCE_BATCH(); } { int pipe_ctrl; - ATOMIC_BATCH(26); /* Pipe control */ if (IS_IGDNG(intel)) pipe_ctrl = BRW_PIPE_CONTROL_NOWRITE; else pipe_ctrl = @@ -1326,13 +1323,12 @@ static void i965_emit_composite_state(ScrnInfoPtr scrn) UF2_SF_FENCE_SHIFT)); /* Constant buffer state */ OUT_BATCH(BRW_CS_URB_STATE | 0); OUT_BATCH(((URB_CS_ENTRY_SIZE - 1) << 4) | (URB_CS_ENTRIES << 0)); - ADVANCE_BATCH(); } { /* * number of extra parameters per vertex */ int nelem = mask ? 2 : 1; @@ -1353,13 +1349,12 @@ static void i965_emit_composite_state(ScrnInfoPtr scrn) } else { src_format = BRW_SURFACEFORMAT_R32G32B32_FLOAT; w_component = BRW_VFCOMPONENT_STORE_SRC; } if (IS_IGDNG(intel)) { - ATOMIC_BATCH(mask ? 9 : 7); /* * The reason to add this extra vertex element in the header is that * IGDNG has different vertex header definition and origin method to * set destination element offset doesn't exist anymore, which means * hardware requires a predefined vertex element layout. * @@ -1383,13 +1378,12 @@ static void i965_emit_composite_state(ScrnInfoPtr scrn) VE1_VFCOMPONENT_1_SHIFT) | (BRW_VFCOMPONENT_STORE_0 << VE1_VFCOMPONENT_2_SHIFT) | (BRW_VFCOMPONENT_STORE_0 << VE1_VFCOMPONENT_3_SHIFT)); } else { - ATOMIC_BATCH(mask ? 7 : 5); /* Set up our vertex elements, sourced from the single vertex buffer. * that will be set up later. */ OUT_BATCH(BRW_3DSTATE_VERTEX_ELEMENTS | ((2 * (1 + nelem)) - 1)); } @@ -1445,14 +1439,12 @@ static void i965_emit_composite_state(ScrnInfoPtr scrn) VE1_VFCOMPONENT_2_SHIFT) | (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_3_SHIFT)); else OUT_BATCH((BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_0_SHIFT) | (BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_1_SHIFT) | (w_component << VE1_VFCOMPONENT_2_SHIFT) | (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_3_SHIFT) | ((4 + 4 + 4) << VE1_DESTINATION_ELEMENT_OFFSET_SHIFT)); /* VUE offset in dwords */ } - - ADVANCE_BATCH(); } } /** * Returns whether the current set of composite state plus vertex buffer is * expected to fit in the aperture. @@ -1832,13 +1824,12 @@ i965_composite(PixmapPtr dest, int srcX, int srcY, int maskX, int maskY, intel_batch_submit(scrn); intel_batch_start_atomic(scrn, 200); if (intel->needs_render_state_emit) i965_emit_composite_state(scrn); - ATOMIC_BATCH(12); OUT_BATCH(MI_FLUSH); /* Set up the pointer to our (single) vertex buffer */ OUT_BATCH(BRW_3DSTATE_VERTEX_BUFFERS | 3); OUT_BATCH((0 << VB0_BUFFER_INDEX_SHIFT) | VB0_VERTEXDATA | (render_state->vertex_size << VB0_BUFFER_PITCH_SHIFT)); @@ -1857,13 +1848,12 @@ i965_composite(PixmapPtr dest, int srcX, int srcY, int maskX, int maskY, 4); OUT_BATCH(3); /* vertex count per instance */ OUT_BATCH(0); /* start vertex offset */ OUT_BATCH(1); /* single instance */ OUT_BATCH(0); /* start instance location */ OUT_BATCH(0); /* index buffer offset, ignored */ - ADVANCE_BATCH(); render_state->vb_offset += i; drm_intel_bo_unreference(vb_bo); intel_batch_end_atomic(scrn); } diff --git a/src/i965_video.c b/src/i965_video.c index 26755565..855f0b5d 100644 --- a/src/i965_video.c +++ b/src/i965_video.c @@ -775,24 +775,18 @@ i965_emit_video_setup(ScrnInfoPtr scrn, drm_intel_bo * bind_bo, int n_src_surf) urb_clip_size = URB_CLIP_ENTRIES * URB_CLIP_ENTRY_SIZE; urb_sf_start = urb_clip_start + urb_clip_size; urb_sf_size = URB_SF_ENTRIES * URB_SF_ENTRY_SIZE; urb_cs_start = urb_sf_start + urb_sf_size; urb_cs_size = URB_CS_ENTRIES * URB_CS_ENTRY_SIZE; - ATOMIC_BATCH(2); OUT_BATCH(MI_FLUSH | MI_STATE_INSTRUCTION_CACHE_FLUSH | BRW_MI_GLOBAL_SNAPSHOT_RESET); OUT_BATCH(MI_NOOP); - ADVANCE_BATCH(); /* brw_debug (scrn, "before base address modify"); */ - if (IS_IGDNG(intel)) - ATOMIC_BATCH(14); - else - ATOMIC_BATCH(12); /* Match Mesa driver setup */ if (IS_G4X(intel) || IS_IGDNG(intel)) OUT_BATCH(NEW_PIPELINE_SELECT | PIPELINE_SELECT_3D); else OUT_BATCH(BRW_PIPELINE_SELECT | PIPELINE_SELECT_3D); @@ -830,26 +824,19 @@ i965_emit_video_setup(ScrnInfoPtr scrn, drm_intel_bo * bind_bo, int n_src_surf) /* Set system instruction pointer */ OUT_BATCH(BRW_STATE_SIP | 0); /* system instruction pointer */ OUT_RELOC(intel->video.gen4_sip_kernel_bo, I915_GEM_DOMAIN_INSTRUCTION, 0, 0); - OUT_BATCH(MI_NOOP); - ADVANCE_BATCH(); - /* brw_debug (scrn, "after base address modify"); */ if (IS_IGDNG(intel)) pipe_ctl = BRW_PIPE_CONTROL_NOWRITE; else pipe_ctl = BRW_PIPE_CONTROL_NOWRITE | BRW_PIPE_CONTROL_IS_FLUSH; - ATOMIC_BATCH(38); - - OUT_BATCH(MI_NOOP); - /* Pipe control */ OUT_BATCH(BRW_PIPE_CONTROL | pipe_ctl | 2); OUT_BATCH(0); /* Destination address */ OUT_BATCH(0); /* Immediate data low DW */ OUT_BATCH(0); /* Immediate data high DW */ @@ -967,15 +954,12 @@ i965_emit_video_setup(ScrnInfoPtr scrn, drm_intel_bo * bind_bo, int n_src_surf) (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_2_SHIFT) | (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_3_SHIFT) | (4 << VE1_DESTINATION_ELEMENT_OFFSET_SHIFT)); } - - OUT_BATCH(MI_NOOP); /* pad to quadword */ - ADVANCE_BATCH(); } void I965DisplayVideoTextured(ScrnInfoPtr scrn, intel_adaptor_private *adaptor_priv, int id, RegionPtr dstRegion, @@ -1216,13 +1200,12 @@ I965DisplayVideoTextured(ScrnInfoPtr scrn, } intel_batch_start_atomic(scrn, 100); i965_emit_video_setup(scrn, bind_bo, n_src_surf); - ATOMIC_BATCH(12); /* Set up the pointer to our vertex buffer */ OUT_BATCH(BRW_3DSTATE_VERTEX_BUFFERS | 3); /* four 32-bit floats per vertex */ OUT_BATCH((0 << VB0_BUFFER_INDEX_SHIFT) | VB0_VERTEXDATA | ((4 * 4) << VB0_BUFFER_PITCH_SHIFT)); OUT_RELOC(vb_bo, I915_GEM_DOMAIN_VERTEX, 0, 0); @@ -1238,13 +1221,12 @@ I965DisplayVideoTextured(ScrnInfoPtr scrn, OUT_BATCH(3); /* vertex count per instance */ OUT_BATCH(0); /* start vertex offset */ OUT_BATCH(1); /* single instance */ OUT_BATCH(0); /* start instance location */ OUT_BATCH(0); /* index buffer offset, ignored */ OUT_BATCH(MI_NOOP); - ADVANCE_BATCH(); intel_batch_end_atomic(scrn); drm_intel_bo_unreference(vb_bo); if (!IS_IGDNG(intel)) diff --git a/uxa/uxa-accel.c b/uxa/uxa-accel.c index cfc2d381..77963f39 100644 --- a/uxa/uxa-accel.c +++ b/uxa/uxa-accel.c @@ -31,39 +31,187 @@ #include <dix-config.h> #endif #include "uxa-priv.h" #include <X11/fonts/fontstruct.h> #include "dixfontstr.h" #include "uxa.h" +#include "mipict.h" + +static CARD32 +format_for_depth(int depth) +{ + switch (depth) { + case 1: return PICT_a1; + case 8: return PICT_a8; + case 15: return PICT_x1r5g5b5; + case 16: return PICT_r5g6b5; + default: + case 24: return PICT_x8r8g8b8; + case 32: return PICT_a8r8g8b8; + } +} static void uxa_fill_spans(DrawablePtr pDrawable, GCPtr pGC, int n, DDXPointPtr ppt, int *pwidth, int fSorted) { - ScreenPtr pScreen = pDrawable->pScreen; - uxa_screen_t *uxa_screen = uxa_get_screen(pScreen); + ScreenPtr screen = pDrawable->pScreen; + uxa_screen_t *uxa_screen = uxa_get_screen(screen); RegionPtr pClip = fbGetCompositeClip(pGC); - PixmapPtr pPixmap = uxa_get_drawable_pixmap(pDrawable); + PixmapPtr dst_pixmap, src_pixmap = NULL; BoxPtr pextent, pbox; int nbox; int extentX1, extentX2, extentY1, extentY2; int fullX1, fullX2, fullY1; int partX1, partX2; int off_x, off_y; + xRenderColor color; + PictFormatPtr format; + PicturePtr dst, src; + int error; - if (uxa_screen->swappedOut || pGC->fillStyle != FillSolid || - !(pPixmap = uxa_get_offscreen_pixmap(pDrawable, &off_x, &off_y)) || - !(*uxa_screen->info->prepare_solid) (pPixmap, + if (uxa_screen->swappedOut) + goto fallback; + + if (pGC->fillStyle != FillSolid) + goto fallback; + + dst_pixmap = uxa_get_offscreen_pixmap(pDrawable, &off_x, &off_y); + if (!dst_pixmap) + goto fallback; + + if (pGC->alu != GXcopy || pGC->planemask != FB_ALLONES) + goto solid; + + format = PictureMatchFormat(screen, + dst_pixmap->drawable.depth, + format_for_depth(dst_pixmap->drawable.depth)); + dst = CreatePicture(0, &dst_pixmap->drawable, format, 0, 0, serverClient, &error); + if (!dst) + goto solid; + + ValidatePicture(dst); + + uxa_get_rgba_from_pixel(pGC->fgPixel, + &color.red, + &color.green, + &color.blue, + &color.alpha, + format_for_depth(dst_pixmap->drawable.depth)); + src = CreateSolidPicture(0, &color, &error); + if (!src) { + FreePicture(dst, 0); + goto solid; + } + + if (!uxa_screen->info->check_composite(PictOpSrc, src, NULL, dst, 0, 0)) { + FreePicture(src, 0); + FreePicture(dst, 0); + goto solid; + } + + if (!uxa_screen->info->check_composite_texture || + !uxa_screen->info->check_composite_texture(screen, src)) { + PicturePtr solid; + int src_off_x, src_off_y; + + solid = uxa_acquire_solid(screen, src->pSourcePict); + FreePicture(src, 0); + + src = solid; + src_pixmap = uxa_get_offscreen_pixmap(src->pDrawable, + &src_off_x, &src_off_y); + if (!src_pixmap) { + FreePicture(src, 0); + FreePicture(dst, 0); + goto solid; + } + } + + if (!uxa_screen->info->prepare_composite(PictOpSrc, src, NULL, dst, src_pixmap, NULL, dst_pixmap)) { + FreePicture(src, 0); + FreePicture(dst, 0); + goto solid; + } + + pextent = REGION_EXTENTS(pGC->screen, pClip); + extentX1 = pextent->x1; + extentY1 = pextent->y1; + extentX2 = pextent->x2; + extentY2 = pextent->y2; + while (n--) { + fullX1 = ppt->x; + fullY1 = ppt->y; + fullX2 = fullX1 + (int)*pwidth; + ppt++; + pwidth++; + + if (fullY1 < extentY1 || extentY2 <= fullY1) + continue; + + if (fullX1 < extentX1) + fullX1 = extentX1; + + if (fullX2 > extentX2) + fullX2 = extentX2; + + if (fullX1 >= fullX2) + continue; + + nbox = REGION_NUM_RECTS(pClip); + if (nbox == 1) { + uxa_screen->info->composite(dst_pixmap, + 0, 0, 0, 0, + fullX1 + off_x, + fullY1 + off_y, + fullX2 - fullX1, 1); + } else { + pbox = REGION_RECTS(pClip); + while (nbox--) { + if (pbox->y2 >= fullY1) + break; + + if (pbox->y1 <= fullY1) { + partX1 = pbox->x1; + if (partX1 < fullX1) + partX1 = fullX1; + + partX2 = pbox->x2; + if (partX2 > fullX2) + partX2 = fullX2; + + if (partX2 > partX1) { + uxa_screen->info->composite(dst_pixmap, + 0, 0, 0, 0, + partX1 + off_x, + fullY1 + off_y, + partX2 - partX1, 1); + } + } + pbox++; + } + } + } + + uxa_screen->info->done_composite(dst_pixmap); + FreePicture(src, 0); + FreePicture(dst, 0); + return; + +solid: + if (uxa_screen->info->check_solid && + !uxa_screen->info->check_solid(pDrawable, pGC->alu, pGC->planemask)) + goto fallback; + + if (!(*uxa_screen->info->prepare_solid) (dst_pixmap, pGC->alu, pGC->planemask, - pGC->fgPixel)) { - uxa_check_fill_spans(pDrawable, pGC, n, ppt, pwidth, fSorted); - return; - } + pGC->fgPixel)) + goto fallback; - pextent = REGION_EXTENTS(pGC->pScreen, pClip); + pextent = REGION_EXTENTS(pGC->screen, pClip); extentX1 = pextent->x1; extentY1 = pextent->y1; extentX2 = pextent->x2; extentY2 = pextent->y2; while (n--) { fullX1 = ppt->x; @@ -83,13 +231,13 @@ uxa_fill_spans(DrawablePtr pDrawable, GCPtr pGC, int n, if (fullX1 >= fullX2) continue; nbox = REGION_NUM_RECTS(pClip); if (nbox == 1) { - (*uxa_screen->info->solid) (pPixmap, + (*uxa_screen->info->solid) (dst_pixmap, fullX1 + off_x, fullY1 + off_y, fullX2 + off_x, fullY1 + 1 + off_y); } else { pbox = REGION_RECTS(pClip); @@ -100,24 +248,29 @@ uxa_fill_spans(DrawablePtr pDrawable, GCPtr pGC, int n, partX1 = fullX1; partX2 = pbox->x2; if (partX2 > fullX2) partX2 = fullX2; if (partX2 > partX1) { (*uxa_screen->info-> - solid) (pPixmap, + solid) (dst_pixmap, partX1 + off_x, fullY1 + off_y, partX2 + off_x, fullY1 + 1 + off_y); } } pbox++; } } } - (*uxa_screen->info->done_solid) (pPixmap); + (*uxa_screen->info->done_solid) (dst_pixmap); + + return; + +fallback: + uxa_check_fill_spans(pDrawable, pGC, n, ppt, pwidth, fSorted); } static Bool uxa_do_put_image(DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y, int w, int h, int format, char *bits, int src_stride) { @@ -430,23 +583,23 @@ uxa_copy_n_to_n(DrawablePtr pSrcDrawable, ScreenPtr screen = pDstDrawable->pScreen; uxa_screen_t *uxa_screen = uxa_get_screen(screen); int src_off_x, src_off_y; int dst_off_x, dst_off_y; PixmapPtr pSrcPixmap, pDstPixmap; - if (uxa_screen->info->check_copy && - !uxa_screen->info->check_copy(pSrcDrawable, pDstDrawable, - pGC ? pGC->alu : GXcopy, - pGC ? pGC->planemask : FB_ALLONES)) - goto fallback; - pSrcPixmap = uxa_get_drawable_pixmap(pSrcDrawable); pDstPixmap = uxa_get_drawable_pixmap(pDstDrawable); if (!pSrcPixmap || !pDstPixmap) goto fallback; + if (uxa_screen->info->check_copy && + !uxa_screen->info->check_copy(pSrcPixmap, pDstPixmap, + pGC ? pGC->alu : GXcopy, + pGC ? pGC->planemask : FB_ALLONES)) + goto fallback; + uxa_get_drawable_deltas(pSrcDrawable, pSrcPixmap, &src_off_x, &src_off_y); uxa_get_drawable_deltas(pDstDrawable, pDstPixmap, &dst_off_x, &dst_off_y); /* Mixed directions must be handled specially if the card is lame */ @@ -965,26 +1118,22 @@ uxa_fill_region_tiled(DrawablePtr pDrawable, */ if (tileWidth == 1 && tileHeight == 1) return uxa_fill_region_solid(pDrawable, pRegion, uxa_get_pixmap_first_pixel(pTile), planemask, alu); + pPixmap = uxa_get_offscreen_pixmap(pDrawable, &xoff, &yoff); + if (!pPixmap || !uxa_pixmap_is_offscreen(pTile)) + goto out; + if (uxa_screen->info->check_copy && - !uxa_screen->info->check_copy(&pTile->drawable, pDrawable, alu, planemask)) + !uxa_screen->info->check_copy(pTile, pPixmap, alu, planemask)) return FALSE; - - pPixmap = uxa_get_drawable_pixmap(pDrawable); - uxa_get_drawable_deltas(pDrawable, pPixmap, &xoff, &yoff); REGION_TRANSLATE(pScreen, pRegion, xoff, yoff); - pPixmap = uxa_get_offscreen_pixmap(pDrawable, &xoff, &yoff); - - if (!pPixmap || !uxa_pixmap_is_offscreen(pTile)) - goto out; - if ((*uxa_screen->info->prepare_copy) (pTile, pPixmap, 1, 1, alu, planemask)) { while (nbox--) { int height = pBox->y2 - pBox->y1; int dstY = pBox->y1; int tileY; diff --git a/uxa/uxa-glyphs.c b/uxa/uxa-glyphs.c index f8bb7f54..93a738ed 100644 --- a/uxa/uxa-glyphs.c +++ b/uxa/uxa-glyphs.c @@ -202,12 +202,14 @@ static Bool uxa_realize_glyph_caches(ScreenPtr pScreen, unsigned int format) (*pScreen->DestroyPixmap) (pPixmap); /* picture holds a refcount */ if (!pPicture) return FALSE; + ValidatePicture(pPicture); + /* And store the picture in all the caches for the format */ for (i = 0; i < UXA_NUM_GLYPH_CACHES; i++) { uxa_glyph_cache_t *cache = &uxa_screen->glyphCaches[i]; int j; @@ -570,47 +572,300 @@ uxa_buffer_glyph(ScreenPtr pScreen, buffer->count++; return UXA_GLYPH_SUCCESS; } -static void uxa_glyphs_to_mask(PicturePtr pMask, uxa_glyph_buffer_t * buffer) +static PicturePtr +uxa_glyphs_acquire_source(ScreenPtr screen, + PicturePtr src, + INT16 x, INT16 y, + const uxa_glyph_buffer_t * buffer, + INT16 * out_x, INT16 * out_y) +{ + uxa_screen_t *uxa_screen = uxa_get_screen(screen); + int x1, y1, x2, y2; + int width, height; + int i; + + if (uxa_screen->info->check_composite_texture && + uxa_screen->info->check_composite_texture(screen, src)) { + if (src->pDrawable) { + *out_x = x + src->pDrawable->x; + *out_y = y + src->pDrawable->y; + } else { + *out_x = x; + *out_y = y; + } + return src; + } + + for (i = 0; i < buffer->count; i++) { + const uxa_composite_rect_t *r = &buffer->rects[i]; + + if (r->xDst < x1) + x1 = r->xDst; + if (r->xDst + r->width > x2) + x2 = r->xDst + r->width; + + if (r->yDst < y1) + y1 = r->yDst; + if (r->yDst + r->height > y2) + y2 = r->yDst + r->height; + } + + width = x2 - x1; + height = y2 - y1; + + if (src->pDrawable) { + PicturePtr dst; + + dst = uxa_acquire_drawable(screen, src, + x, y, + width, height, + out_x, out_y); + if (uxa_screen->info->check_composite_texture && + !uxa_screen->info->check_composite_texture(screen, dst)) { + if (dst != src) + FreePicture(dst, 0); + return 0; + } + + return dst; + } + + *out_x = 0; + *out_y = 0; + return uxa_acquire_pattern(screen, src, + PICT_a8r8g8b8, x, y, width, height); +} + +static int +uxa_glyphs_try_driver_composite(CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + const uxa_glyph_buffer_t * buffer, + INT16 xSrc, INT16 ySrc, + INT16 xDst, INT16 yDst) { - uxa_composite_rects(PictOpAdd, buffer->source, pMask, - buffer->count, buffer->rects); + ScreenPtr screen = pDst->pDrawable->pScreen; + uxa_screen_t *uxa_screen = uxa_get_screen(screen); + PicturePtr localSrc; + int src_off_x = 0, src_off_y = 0, mask_off_x, mask_off_y, dst_off_x, dst_off_y; + PixmapPtr pSrcPix = NULL, pMaskPix, pDstPix; + const uxa_composite_rect_t *rects; + int nrect; + + if (uxa_screen->info->check_composite && + !(*uxa_screen->info->check_composite) (op, pSrc, buffer->source, pDst, 0, 0)) { + return -1; + } + + pDstPix = + uxa_get_offscreen_pixmap(pDst->pDrawable, &dst_off_x, &dst_off_y); + + pMaskPix = + uxa_get_offscreen_pixmap(buffer->source->pDrawable, &mask_off_x, &mask_off_y); + if(!pMaskPix) + return -1; + + localSrc = uxa_glyphs_acquire_source(screen, pSrc, + xSrc, ySrc, + buffer, + &xSrc, &ySrc); + if (!localSrc) + return 0; + + if (localSrc->pDrawable) { + pSrcPix = + uxa_get_offscreen_pixmap(localSrc->pDrawable, &src_off_x, &src_off_y); + if (!pSrcPix) { + if (localSrc != pSrc) + FreePicture(localSrc, 0); + return 0; + } + + xSrc += localSrc->pDrawable->x; + ySrc += localSrc->pDrawable->y; + } + + if (!(*uxa_screen->info->prepare_composite) + (op, localSrc, buffer->source, pDst, pSrcPix, pMaskPix, pDstPix)) { + if (localSrc != pSrc) + FreePicture(localSrc, 0); + return -1; + } + + nrect = buffer->count; + rects = buffer->rects; + do { + INT16 _xDst = rects->xDst + pDst->pDrawable->x; + INT16 _yDst = rects->yDst + pDst->pDrawable->y; + INT16 _xMask = rects->xSrc + buffer->source->pDrawable->x; + INT16 _yMask = rects->ySrc + buffer->source->pDrawable->y; + INT16 _xSrc = xSrc, _ySrc = ySrc; + + RegionRec region; + BoxPtr pbox; + int nbox; + + if (!miComputeCompositeRegion(®ion, + localSrc, buffer->source, pDst, + _xSrc, _ySrc, + _xMask, _yMask, + _xDst, _yDst, + rects->width, rects->height)) + goto next_rect; + + _xSrc += src_off_x - _xDst; + _ySrc += src_off_y - _yDst; + _xMask += mask_off_x - _xDst; + _yMask += mask_off_y - _yDst; + + nbox = REGION_NUM_RECTS(®ion); + pbox = REGION_RECTS(®ion); + while (nbox--) { + (*uxa_screen->info->composite) (pDstPix, + pbox->x1 + _xSrc, + pbox->y1 + _ySrc, + pbox->x1 + _xMask, + pbox->y1 + _yMask, + pbox->x1 + dst_off_x, + pbox->y1 + dst_off_y, + pbox->x2 - pbox->x1, + pbox->y2 - pbox->y1); + pbox++; + } + +next_rect: + REGION_UNINIT(screen, ®ion); - buffer->count = 0; - buffer->source = NULL; + rects++; + } while (--nrect); + (*uxa_screen->info->done_composite) (pDstPix); + + if (localSrc != pSrc) + FreePicture(localSrc, 0); + + return 1; } static void uxa_glyphs_to_dst(CARD8 op, PicturePtr pSrc, PicturePtr pDst, - uxa_glyph_buffer_t * buffer, - INT16 xSrc, INT16 ySrc, INT16 xDst, INT16 yDst) + const uxa_glyph_buffer_t * buffer, + INT16 xSrc, INT16 ySrc, + INT16 xDst, INT16 yDst) { - int i; + if (uxa_glyphs_try_driver_composite(op, pSrc, pDst, buffer, + xSrc, ySrc, + xDst, yDst) != 1) { + int i; - for (i = 0; i < buffer->count; i++) { - uxa_composite_rect_t *rect = &buffer->rects[i]; + for (i = 0; i < buffer->count; i++) { + const uxa_composite_rect_t *rect = &buffer->rects[i]; - CompositePicture(op, - pSrc, - buffer->source, - pDst, - xSrc + rect->xDst - xDst, - ySrc + rect->yDst - yDst, - rect->xSrc, - rect->ySrc, - rect->xDst, - rect->yDst, rect->width, rect->height); - } - - buffer->count = 0; - buffer->source = NULL; + CompositePicture(op, + pSrc, buffer->source, pDst, + xSrc + rect->xDst - xDst, + ySrc + rect->yDst - yDst, + rect->xSrc, rect->ySrc, + rect->xDst, rect->yDst, + rect->width, rect->height); + } + } +} + +static int +uxa_glyphs_try_driver_add_to_mask(PicturePtr pDst, + const uxa_glyph_buffer_t *buffer) +{ + uxa_screen_t *uxa_screen = uxa_get_screen(pDst->pDrawable->pScreen); + int src_off_x, src_off_y, dst_off_x, dst_off_y; + PixmapPtr pSrcPix, pDstPix; + const uxa_composite_rect_t *rects; + int nrect; + + if (uxa_screen->info->check_composite && + !(*uxa_screen->info->check_composite) (PictOpAdd, buffer->source, NULL, pDst, 0, 0)) { + return -1; + } + + pDstPix = + uxa_get_offscreen_pixmap(pDst->pDrawable, &dst_off_x, &dst_off_y); + + pSrcPix = + uxa_get_offscreen_pixmap(buffer->source->pDrawable, &src_off_x, &src_off_y); + if(!pSrcPix) + return -1; + + if (!(*uxa_screen->info->prepare_composite) + (PictOpAdd, buffer->source, NULL, pDst, pSrcPix, NULL, pDstPix)) + return -1; + + rects = buffer->rects; + nrect = buffer->count; + do { + INT16 xDst = rects->xDst + pDst->pDrawable->x; + INT16 yDst = rects->yDst + pDst->pDrawable->y; + INT16 xSrc = rects->xSrc + buffer->source->pDrawable->x; + INT16 ySrc = rects->ySrc + buffer->source->pDrawable->y; + + RegionRec region; + BoxPtr pbox; + int nbox; + + if (!miComputeCompositeRegion(®ion, buffer->source, NULL, pDst, + xSrc, ySrc, 0, 0, xDst, yDst, + rects->width, rects->height)) + goto next_rect; + + xSrc += src_off_x - xDst; + ySrc += src_off_y - yDst; + + nbox = REGION_NUM_RECTS(®ion); + pbox = REGION_RECTS(®ion); + + while (nbox--) { + (*uxa_screen->info->composite) (pDstPix, + pbox->x1 + xSrc, + pbox->y1 + ySrc, + 0, 0, + pbox->x1 + dst_off_x, + pbox->y1 + dst_off_y, + pbox->x2 - pbox->x1, + pbox->y2 - pbox->y1); + pbox++; + } + +next_rect: + REGION_UNINIT(pDst->pDrawable->pScreen, ®ion); + + rects++; + } while (--nrect); + (*uxa_screen->info->done_composite) (pDstPix); + + return 1; +} + +static void uxa_glyphs_to_mask(PicturePtr pDst, const uxa_glyph_buffer_t *buffer) +{ + if (uxa_glyphs_try_driver_add_to_mask(pDst, buffer) != 1) { + int i; + + for (i = 0; i < buffer->count; i++) { + const uxa_composite_rect_t *r = &buffer->rects[i]; + + uxa_check_composite(PictOpAdd, buffer->source, NULL, pDst, + r->xSrc, r->ySrc, + 0, 0, + r->xDst, r->yDst, + r->width, r->height); + } + } } /* Cut and paste from render/glyph.c - probably should export it instead */ static void uxa_glyph_extents(int nlist, GlyphListPtr list, GlyphPtr * glyphs, BoxPtr extents) @@ -851,148 +1106,258 @@ uxa_check_glyphs(CARD8 op, void uxa_glyphs(CARD8 op, PicturePtr pSrc, PicturePtr pDst, PictFormatPtr maskFormat, - INT16 xSrc, - INT16 ySrc, int nlist, GlyphListPtr list, GlyphPtr * glyphs) + INT16 xSrc, INT16 ySrc, + int nlist, GlyphListPtr list, GlyphPtr * glyphs) { - PixmapPtr pMaskPixmap = 0; - PicturePtr pMask; - ScreenPtr pScreen = pDst->pDrawable->pScreen; + ScreenPtr screen = pDst->pDrawable->pScreen; + uxa_screen_t *uxa_screen = uxa_get_screen(screen); + PicturePtr pMask = NULL; int width = 0, height = 0; int x, y; int xDst = list->xOff, yDst = list->yOff; int n; GlyphPtr glyph; int error; BoxRec extents = { 0, 0, 0, 0 }; + Bool have_extents = FALSE; CARD32 component_alpha; uxa_glyph_buffer_t buffer; + PicturePtr localDst = pDst; - if (!uxa_drawable_is_offscreen(pDst->pDrawable)) { + if (!uxa_screen->info->prepare_composite || + uxa_screen->swappedOut || + !uxa_drawable_is_offscreen(pDst->pDrawable) || + pDst->alphaMap || pSrc->alphaMap) { +fallback: uxa_check_glyphs(op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, list, glyphs); return; } - /* If we don't have a mask format but all the glyphs have the same format - * and don't intersect, use the glyph format as mask format for the full - * benefits of the glyph cache. - */ + ValidatePicture(pSrc); + ValidatePicture(pDst); + if (!maskFormat) { - Bool sameFormat = TRUE; - int i; + /* If we don't have a mask format but all the glyphs have the same format, + * require ComponentAlpha and don't intersect, use the glyph format as mask + * format for the full benefits of the glyph cache. + */ + if (NeedsComponent(list[0].format->format)) { + Bool sameFormat = TRUE; + int i; - maskFormat = list[0].format; + maskFormat = list[0].format; - for (i = 0; i < nlist; i++) { - if (maskFormat->format != list[i].format->format) { - sameFormat = FALSE; - break; + for (i = 0; i < nlist; i++) { + if (maskFormat->format != list[i].format->format) { + sameFormat = FALSE; + break; + } } - } - if (!sameFormat || (maskFormat->depth != 1 && - uxa_glyphs_intersect(nlist, list, - glyphs))) { - maskFormat = NULL; + if (!sameFormat || + uxa_glyphs_intersect(nlist, list, glyphs)) + maskFormat = NULL; } } - if (maskFormat) { - GCPtr pGC; - xRectangle rect; + x = y = 0; + if (!maskFormat && + uxa_screen->info->check_composite_target && + !uxa_screen->info->check_composite_target(uxa_get_drawable_pixmap(pDst->pDrawable))) { + int depth = pDst->pDrawable->depth; + PixmapPtr pixmap; + int error; + GCPtr gc; + + pixmap = uxa_get_drawable_pixmap(pDst->pDrawable); + if (uxa_screen->info->check_copy && + !uxa_screen->info->check_copy(pixmap, pixmap, GXcopy, FB_ALLONES)) + goto fallback; uxa_glyph_extents(nlist, list, glyphs, &extents); + /* clip against dst bounds */ + if (extents.x1 < 0) + extents.x1 = 0; + if (extents.y1 < 0) + extents.y1 = 0; + if (extents.x2 > pDst->pDrawable->width) + extents.x2 = pDst->pDrawable->width; + if (extents.y2 > pDst->pDrawable->height) + extents.y2 = pDst->pDrawable->height; + if (extents.x2 <= extents.x1 || extents.y2 <= extents.y1) return; - width = extents.x2 - extents.x1; + width = extents.x2 - extents.x1; height = extents.y2 - extents.y1; + x = -extents.x1; + y = -extents.y1; + have_extents = TRUE; + + xDst += x; + yDst += y; + + pixmap = screen->CreatePixmap(screen, + width, height, depth, + CREATE_PIXMAP_USAGE_SCRATCH); + if (!pixmap) + return; + + gc = GetScratchGC(depth, screen); + if (!gc) { + screen->DestroyPixmap(pixmap); + return; + } + + ValidateGC(&pixmap->drawable, gc); + gc->ops->CopyArea(pDst->pDrawable, &pixmap->drawable, gc, + extents.x1, extents.y1, + width, height, + 0, 0); + FreeScratchGC(gc); + + localDst = CreatePicture(0, &pixmap->drawable, + PictureMatchFormat(screen, depth, pDst->format), + 0, 0, serverClient, &error); + screen->DestroyPixmap(pixmap); + + if (!localDst) + return; + + ValidatePicture(localDst); + } + + if (maskFormat) { + PixmapPtr pixmap; + GCPtr gc; + xRectangle rect; + + if (!have_extents) { + uxa_glyph_extents(nlist, list, glyphs, &extents); + + if (extents.x2 <= extents.x1 || extents.y2 <= extents.y1) + return; + width = extents.x2 - extents.x1; + height = extents.y2 - extents.y1; + x = -extents.x1; + y = -extents.y1; + have_extents = TRUE; + } if (maskFormat->depth == 1) { PictFormatPtr a8Format = - PictureMatchFormat(pScreen, 8, PICT_a8); + PictureMatchFormat(screen, 8, PICT_a8); if (a8Format) maskFormat = a8Format; } - pMaskPixmap = (*pScreen->CreatePixmap) (pScreen, width, height, - maskFormat->depth, - CREATE_PIXMAP_USAGE_SCRATCH); - if (!pMaskPixmap) + pixmap = screen->CreatePixmap(screen, width, height, + maskFormat->depth, + CREATE_PIXMAP_USAGE_SCRATCH); + if (!pixmap) { + if (localDst != pDst) + FreePicture(localDst, 0); return; + } + + gc = GetScratchGC(pixmap->drawable.depth, screen); + ValidateGC(&pixmap->drawable, gc); + rect.x = 0; + rect.y = 0; + rect.width = width; + rect.height = height; + gc->ops->PolyFillRect(&pixmap->drawable, gc, 1, &rect); + FreeScratchGC(gc); + component_alpha = NeedsComponent(maskFormat->format); - pMask = CreatePicture(0, &pMaskPixmap->drawable, + pMask = CreatePicture(0, &pixmap->drawable, maskFormat, CPComponentAlpha, &component_alpha, serverClient, &error); + screen->DestroyPixmap(pixmap); + if (!pMask) { - (*pScreen->DestroyPixmap) (pMaskPixmap); + if (localDst != pDst) + FreePicture(localDst, 0); return; } - pGC = GetScratchGC(pMaskPixmap->drawable.depth, pScreen); - ValidateGC(&pMaskPixmap->drawable, pGC); - rect.x = 0; - rect.y = 0; - rect.width = width; - rect.height = height; - (*pGC->ops->PolyFillRect) (&pMaskPixmap->drawable, pGC, 1, - &rect); - FreeScratchGC(pGC); - x = -extents.x1; - y = -extents.y1; - } else { - pMask = pDst; - x = 0; - y = 0; + + ValidatePicture(pMask); } + buffer.count = 0; buffer.source = NULL; while (nlist--) { x += list->xOff; y += list->yOff; n = list->len; while (n--) { glyph = *glyphs++; if (glyph->info.width > 0 && glyph->info.height > 0 && - uxa_buffer_glyph(pScreen, &buffer, glyph, x, + uxa_buffer_glyph(screen, &buffer, glyph, x, y) == UXA_GLYPH_NEED_FLUSH) { if (maskFormat) uxa_glyphs_to_mask(pMask, &buffer); else - uxa_glyphs_to_dst(op, pSrc, pDst, + uxa_glyphs_to_dst(op, pSrc, localDst, &buffer, xSrc, ySrc, xDst, yDst); - uxa_buffer_glyph(pScreen, &buffer, glyph, x, y); + buffer.count = 0; + buffer.source = NULL; + + uxa_buffer_glyph(screen, &buffer, glyph, x, y); } x += glyph->info.xOff; y += glyph->info.yOff; } list++; } if (buffer.count) { if (maskFormat) uxa_glyphs_to_mask(pMask, &buffer); else - uxa_glyphs_to_dst(op, pSrc, pDst, &buffer, + uxa_glyphs_to_dst(op, pSrc, localDst, &buffer, xSrc, ySrc, xDst, yDst); } if (maskFormat) { - x = extents.x1; - y = extents.y1; + if (localDst == pDst) { + x = extents.x1; + y = extents.y1; + } else + x = y = 0; CompositePicture(op, pSrc, pMask, - pDst, + localDst, xSrc + x - xDst, - ySrc + y - yDst, 0, 0, x, y, width, height); - FreePicture((pointer) pMask, (XID) 0); - (*pScreen->DestroyPixmap) (pMaskPixmap); + ySrc + y - yDst, + 0, 0, + x, y, + width, height); + FreePicture(pMask, 0); + } + + if (localDst != pDst) { + GCPtr gc; + + gc = GetScratchGC(pDst->pDrawable->depth, screen); + if (gc) { + ValidateGC(pDst->pDrawable, gc); + gc->ops->CopyArea(localDst->pDrawable, pDst->pDrawable, gc, + 0, 0, + width, height, + extents.x1, extents.y1); + FreeScratchGC(gc); + } + + FreePicture(localDst, 0); } } diff --git a/uxa/uxa-priv.h b/uxa/uxa-priv.h index a4763b41..bace6798 100644 --- a/uxa/uxa-priv.h +++ b/uxa/uxa-priv.h @@ -431,12 +431,37 @@ uxa_trapezoids(CARD8 op, PicturePtr pSrc, PicturePtr pDst, void uxa_triangles(CARD8 op, PicturePtr pSrc, PicturePtr pDst, PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc, int ntri, xTriangle * tris); +PicturePtr +uxa_acquire_solid(ScreenPtr screen, SourcePict *source); + +PicturePtr +uxa_acquire_drawable(ScreenPtr pScreen, + PicturePtr pSrc, + INT16 x, INT16 y, + CARD16 width, CARD16 height, + INT16 * out_x, INT16 * out_y); + +PicturePtr +uxa_acquire_pattern(ScreenPtr pScreen, + PicturePtr pSrc, + pixman_format_code_t format, + INT16 x, INT16 y, + CARD16 width, CARD16 height); + +Bool +uxa_get_rgba_from_pixel(CARD32 pixel, + CARD16 * red, + CARD16 * green, + CARD16 * blue, + CARD16 * alpha, + CARD32 format); + /* uxa_glyph.c */ void uxa_glyphs_init(ScreenPtr pScreen); void uxa_glyphs_fini(ScreenPtr pScreen); void diff --git a/uxa/uxa-render.c b/uxa/uxa-render.c index 726079a5..ec59871b 100644 --- a/uxa/uxa-render.c +++ b/uxa/uxa-render.c @@ -248,13 +248,13 @@ uxa_get_pixel_from_rgba(CARD32 * pixel, *pixel |= (red >> (16 - rbits)) << rshift; *pixel |= (alpha >> (16 - abits)) << ashift; return TRUE; } -static Bool +Bool uxa_get_rgba_from_pixel(CARD32 pixel, CARD16 * red, CARD16 * green, CARD16 * blue, CARD16 * alpha, CARD32 format) @@ -388,14 +388,12 @@ uxa_try_driver_solid_fill(PicturePtr pSrc, if (!miComputeCompositeRegion(®ion, pSrc, NULL, pDst, xSrc, ySrc, 0, 0, xDst, yDst, width, height)) return 1; - REGION_TRANSLATE(pScreen, ®ion, dst_off_x, dst_off_y); - if (pSrcPix) { if (! uxa_get_color_for_pixmap (pSrcPix, pSrc->format, pDst->format, &pixel)) { REGION_UNINIT(pDst->pDrawable->pScreen, ®ion); return -1; } } else { @@ -429,12 +427,14 @@ uxa_try_driver_solid_fill(PicturePtr pSrc, if (!(*uxa_screen->info->prepare_solid) (pDstPix, GXcopy, FB_ALLONES, pixel)) { REGION_UNINIT(pDst->pDrawable->pScreen, ®ion); return -1; } + REGION_TRANSLATE(pScreen, ®ion, dst_off_x, dst_off_y); + nbox = REGION_NUM_RECTS(®ion); pbox = REGION_RECTS(®ion); while (nbox--) { (*uxa_screen->info->solid) (pDstPix, pbox->x1, pbox->y1, pbox->x2, pbox->y2); @@ -604,13 +604,13 @@ uxa_solid_clear(ScreenPtr screen) return 0; } picture = uxa_screen->solid_clear; return picture; } -static PicturePtr +PicturePtr uxa_acquire_solid(ScreenPtr screen, SourcePict *source) { uxa_screen_t *uxa_screen = uxa_get_screen(screen); PictSolidFill *solid = &source->solidFill; PicturePtr picture; int i; @@ -661,13 +661,13 @@ uxa_acquire_solid(ScreenPtr screen, SourcePict *source) DONE: picture->refcnt++; return picture; } -static PicturePtr +PicturePtr uxa_acquire_pattern(ScreenPtr pScreen, PicturePtr pSrc, pixman_format_code_t format, INT16 x, INT16 y, CARD16 width, CARD16 height) { PicturePtr pDst; @@ -754,13 +754,13 @@ uxa_render_picture(ScreenPtr screen, return 0; } return picture; } -static PicturePtr +PicturePtr uxa_acquire_drawable(ScreenPtr pScreen, PicturePtr pSrc, INT16 x, INT16 y, CARD16 width, CARD16 height, INT16 * out_x, INT16 * out_y) { @@ -785,13 +785,15 @@ uxa_acquire_drawable(ScreenPtr pScreen, *out_x = x + pSrc->pDrawable->x; *out_y = y + pSrc->pDrawable->y; return pSrc; } } - pPixmap = pScreen->CreatePixmap(pScreen, width, height, depth, 0); + pPixmap = pScreen->CreatePixmap(pScreen, + width, height, depth, + CREATE_PIXMAP_USAGE_SCRATCH); if (!pPixmap) return 0; /* Skip the copy if the result remains in memory and not a bo */ if (!uxa_drawable_is_offscreen(&pPixmap->drawable)) { pScreen->DestroyPixmap(pPixmap); @@ -932,13 +934,13 @@ uxa_solid_rects (CARD8 op, xRectangle *rects) { ScreenPtr screen = dst->pDrawable->pScreen; uxa_screen_t *uxa_screen = uxa_get_screen(screen); PixmapPtr dst_pixmap, src_pixmap = NULL; pixman_region16_t region; - pixman_box16_t *boxes; + pixman_box16_t *boxes, *extents; PicturePtr src; int dst_x, dst_y; int num_boxes; if (!pixman_region_not_empty(dst->pCompositeClip)) return; @@ -957,55 +959,64 @@ uxa_solid_rects (CARD8 op, pixman_region_fini(®ion); return; } pixman_region_translate(®ion, dst_x, dst_y); boxes = pixman_region_rectangles(®ion, &num_boxes); + extents = pixman_region_extents (®ion); if (op == PictOpClear) color->red = color->green = color->blue = color->alpha = 0; if (color->alpha >= 0xff00 && op == PictOpOver) op = PictOpSrc; /* Using GEM, the relocation costs outweigh the advantages of the blitter */ if (num_boxes == 1 && (op == PictOpSrc || op == PictOpClear)) { CARD32 pixel; +try_solid: if (uxa_screen->info->check_solid && !uxa_screen->info->check_solid(&dst_pixmap->drawable, GXcopy, FB_ALLONES)) goto err_region; - if (op == PictOpClear) { - pixel = 0; - } else { - if (!uxa_get_pixel_from_rgba(&pixel, - color->red, - color->green, - color->blue, - color->alpha, - dst->format)) - goto err_region; - } + if (!uxa_get_pixel_from_rgba(&pixel, + color->red, + color->green, + color->blue, + color->alpha, + dst->format)) + goto err_region; if (!uxa_screen->info->prepare_solid(dst_pixmap, GXcopy, FB_ALLONES, pixel)) goto err_region; - uxa_screen->info->solid(dst_pixmap, - boxes->x1, boxes->y1, - boxes->x2, boxes->y2); + while (num_boxes--) { + uxa_screen->info->solid(dst_pixmap, + boxes->x1, boxes->y1, + boxes->x2, boxes->y2); + boxes++; + } uxa_screen->info->done_solid(dst_pixmap); } else { int error; src = CreateSolidPicture(0, color, &error); if (!src) goto err_region; - if (!uxa_screen->info->check_composite(op, src, NULL, dst)) + if (!uxa_screen->info->check_composite(op, src, NULL, dst, + extents->x2 - extents->x1, + extents->y2 - extents->y1)) { + if (op == PictOpSrc || op == PictOpClear) { + FreePicture(src, 0); + goto try_solid; + } + goto err_src; + } if (!uxa_screen->info->check_composite_texture || !uxa_screen->info->check_composite_texture(screen, src)) { PicturePtr solid; int src_off_x, src_off_y; @@ -1045,272 +1056,227 @@ err_region: pixman_region_fini(®ion); fallback: uxa_screen->SavedCompositeRects(op, dst, color, num_rects, rects); } static int -uxa_try_driver_composite_rects(CARD8 op, - PicturePtr pSrc, - PicturePtr pDst, - int nrect, uxa_composite_rect_t * rects) -{ - uxa_screen_t *uxa_screen = uxa_get_screen(pDst->pDrawable->pScreen); - int src_off_x, src_off_y, dst_off_x, dst_off_y; - PixmapPtr pSrcPix, pDstPix; - - if (!uxa_screen->info->prepare_composite || uxa_screen->swappedOut) - return -1; - - if (uxa_screen->info->check_composite && - !(*uxa_screen->info->check_composite) (op, pSrc, NULL, pDst)) { - return -1; - } - - pDstPix = - uxa_get_offscreen_pixmap(pDst->pDrawable, &dst_off_x, &dst_off_y); - if (!pDstPix) - return 0; - - pSrcPix = - uxa_get_offscreen_pixmap(pSrc->pDrawable, &src_off_x, &src_off_y); - if (!pSrcPix) - return 0; - - if (!(*uxa_screen->info->prepare_composite) - (op, pSrc, NULL, pDst, pSrcPix, NULL, pDstPix)) - return -1; - - while (nrect--) { - INT16 xDst = rects->xDst + pDst->pDrawable->x; - INT16 yDst = rects->yDst + pDst->pDrawable->y; - INT16 xSrc = rects->xSrc + pSrc->pDrawable->x; - INT16 ySrc = rects->ySrc + pSrc->pDrawable->y; - - RegionRec region; - BoxPtr pbox; - int nbox; - - if (!miComputeCompositeRegion(®ion, pSrc, NULL, pDst, - xSrc, ySrc, 0, 0, xDst, yDst, - rects->width, rects->height)) - goto next_rect; - - REGION_TRANSLATE(pScreen, ®ion, dst_off_x, dst_off_y); - - nbox = REGION_NUM_RECTS(®ion); - pbox = REGION_RECTS(®ion); - - xSrc = xSrc + src_off_x - xDst - dst_off_x; - ySrc = ySrc + src_off_y - yDst - dst_off_y; - - while (nbox--) { - (*uxa_screen->info->composite) (pDstPix, - pbox->x1 + xSrc, - pbox->y1 + ySrc, - 0, 0, - pbox->x1, - pbox->y1, - pbox->x2 - pbox->x1, - pbox->y2 - pbox->y1); - pbox++; - } - -next_rect: - REGION_UNINIT(pDst->pDrawable->pScreen, ®ion); - - rects++; - } - (*uxa_screen->info->done_composite) (pDstPix); - - return 1; -} - -/** - * Copy a number of rectangles from source to destination in a single - * operation. This is specialized for building a glyph mask: we don'y - * have a mask argument because we don't need it for that, and we - * don't have he special-case fallbacks found in uxa_composite() - if the - * driver can support it, we use the driver functionality, otherwise we - * fallback straight to software. - */ -void -uxa_composite_rects(CARD8 op, - PicturePtr pSrc, - PicturePtr pDst, int nrect, uxa_composite_rect_t * rects) -{ - int n; - uxa_composite_rect_t *r; - - /************************************************************/ - - ValidatePicture(pSrc); - ValidatePicture(pDst); - - if (uxa_try_driver_composite_rects(op, pSrc, pDst, nrect, rects) != 1) { - uxa_print_composite_fallback("uxa_composite_rects", - op, pSrc, NULL, pDst); - - n = nrect; - r = rects; - while (n--) { - uxa_check_composite(op, pSrc, NULL, pDst, - r->xSrc, r->ySrc, - 0, 0, - r->xDst, r->yDst, - r->width, r->height); - r++; - } - } - - /************************************************************/ - -} - -static int uxa_try_driver_composite(CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst, INT16 xSrc, INT16 ySrc, INT16 xMask, INT16 yMask, INT16 xDst, INT16 yDst, CARD16 width, CARD16 height) { - uxa_screen_t *uxa_screen = uxa_get_screen(pDst->pDrawable->pScreen); + ScreenPtr screen = pDst->pDrawable->pScreen; + uxa_screen_t *uxa_screen = uxa_get_screen(screen); RegionRec region; BoxPtr pbox; int nbox; + int xDst_copy, yDst_copy; int src_off_x, src_off_y, mask_off_x, mask_off_y, dst_off_x, dst_off_y; PixmapPtr pSrcPix, pMaskPix = NULL, pDstPix; PicturePtr localSrc, localMask = NULL; + PicturePtr localDst = pDst; if (uxa_screen->info->check_composite && - !(*uxa_screen->info->check_composite) (op, pSrc, pMask, pDst)) + !(*uxa_screen->info->check_composite) (op, pSrc, pMask, pDst, width, height)) return -1; + if (uxa_screen->info->check_composite_target && + !uxa_screen->info->check_composite_target(uxa_get_drawable_pixmap(pDst->pDrawable))) { + int depth = pDst->pDrawable->depth; + PixmapPtr pixmap; + int error; + GCPtr gc; + + pixmap = uxa_get_drawable_pixmap(pDst->pDrawable); + if (uxa_screen->info->check_copy && + !uxa_screen->info->check_copy(pixmap, pixmap, GXcopy, FB_ALLONES)) + return -1; + + pixmap = screen->CreatePixmap(screen, + width, height, depth, + CREATE_PIXMAP_USAGE_SCRATCH); + if (!pixmap) + return 0; + + gc = GetScratchGC(depth, screen); + if (!gc) { + screen->DestroyPixmap(pixmap); + return 0; + } + + ValidateGC(&pixmap->drawable, gc); + gc->ops->CopyArea(pDst->pDrawable, &pixmap->drawable, gc, + xDst, yDst, width, height, 0, 0); + FreeScratchGC(gc); + + xDst_copy = xDst; xDst = 0; + yDst_copy = yDst; yDst = 0; + + localDst = CreatePicture(0, &pixmap->drawable, + PictureMatchFormat(screen, depth, pDst->format), + 0, 0, serverClient, &error); + screen->DestroyPixmap(pixmap); + + if (!localDst) + return 0; + + ValidatePicture(localDst); + } + pDstPix = - uxa_get_offscreen_pixmap(pDst->pDrawable, &dst_off_x, &dst_off_y); - if (!pDstPix) + uxa_get_offscreen_pixmap(localDst->pDrawable, &dst_off_x, &dst_off_y); + if (!pDstPix) { + if (localDst != pDst) + FreePicture(localDst, 0); return -1; + } - xDst += pDst->pDrawable->x; - yDst += pDst->pDrawable->y; + xDst += localDst->pDrawable->x; + yDst += localDst->pDrawable->y; - localSrc = uxa_acquire_source(pDst->pDrawable->pScreen, pSrc, + localSrc = uxa_acquire_source(screen, pSrc, xSrc, ySrc, width, height, &xSrc, &ySrc); - if (!localSrc) + if (!localSrc) { + if (localDst != pDst) + FreePicture(localDst, 0); return 0; + } if (pMask) { - localMask = uxa_acquire_mask(pDst->pDrawable->pScreen, pMask, + localMask = uxa_acquire_mask(screen, pMask, xMask, yMask, width, height, &xMask, &yMask); if (!localMask) { if (localSrc != pSrc) FreePicture(localSrc, 0); + if (localDst != pDst) + FreePicture(localDst, 0); return 0; } } - if (!miComputeCompositeRegion(®ion, localSrc, localMask, pDst, + if (!miComputeCompositeRegion(®ion, localSrc, localMask, localDst, xSrc, ySrc, xMask, yMask, xDst, yDst, width, height)) { if (localSrc != pSrc) FreePicture(localSrc, 0); if (localMask && localMask != pMask) FreePicture(localMask, 0); + if (localDst != pDst) + FreePicture(localDst, 0); return 1; } if (localSrc->pDrawable) { pSrcPix = uxa_get_offscreen_pixmap(localSrc->pDrawable, &src_off_x, &src_off_y); if (!pSrcPix) { - REGION_UNINIT(pDst->pDrawable->pScreen, ®ion); + REGION_UNINIT(screen, ®ion); if (localSrc != pSrc) FreePicture(localSrc, 0); if (localMask && localMask != pMask) FreePicture(localMask, 0); + if (localDst != pDst) + FreePicture(localDst, 0); return 0; } } else { pSrcPix = NULL; } if (localMask) { if (localMask->pDrawable) { pMaskPix = uxa_get_offscreen_pixmap(localMask->pDrawable, &mask_off_x, &mask_off_y); if (!pMaskPix) { - REGION_UNINIT(pDst->pDrawable->pScreen, ®ion); + REGION_UNINIT(screen, ®ion); if (localSrc != pSrc) FreePicture(localSrc, 0); if (localMask && localMask != pMask) FreePicture(localMask, 0); + if (localDst != pDst) + FreePicture(localDst, 0); return 0; } } else { pMaskPix = NULL; } } - REGION_TRANSLATE(pScreen, ®ion, dst_off_x, dst_off_y); - if (!(*uxa_screen->info->prepare_composite) - (op, localSrc, localMask, pDst, pSrcPix, pMaskPix, pDstPix)) { - REGION_UNINIT(pDst->pDrawable->pScreen, ®ion); + (op, localSrc, localMask, localDst, pSrcPix, pMaskPix, pDstPix)) { + REGION_UNINIT(screen, ®ion); if (localSrc != pSrc) FreePicture(localSrc, 0); if (localMask && localMask != pMask) FreePicture(localMask, 0); + if (localDst != pDst) + FreePicture(localDst, 0); return -1; } - nbox = REGION_NUM_RECTS(®ion); - pbox = REGION_RECTS(®ion); - if (pMask) { - xMask = xMask + mask_off_x - xDst - dst_off_x; - yMask = yMask + mask_off_y - yDst - dst_off_y; + xMask = xMask + mask_off_x - xDst; + yMask = yMask + mask_off_y - yDst; } - xSrc = xSrc + src_off_x - xDst - dst_off_x; - ySrc = ySrc + src_off_y - yDst - dst_off_y; + xSrc = xSrc + src_off_x - xDst; + ySrc = ySrc + src_off_y - yDst; + nbox = REGION_NUM_RECTS(®ion); + pbox = REGION_RECTS(®ion); while (nbox--) { (*uxa_screen->info->composite) (pDstPix, pbox->x1 + xSrc, pbox->y1 + ySrc, pbox->x1 + xMask, pbox->y1 + yMask, - pbox->x1, - pbox->y1, + pbox->x1 + dst_off_x, + pbox->y1 + dst_off_y, pbox->x2 - pbox->x1, pbox->y2 - pbox->y1); pbox++; } (*uxa_screen->info->done_composite) (pDstPix); - REGION_UNINIT(pDst->pDrawable->pScreen, ®ion); + REGION_UNINIT(screen, ®ion); if (localSrc != pSrc) FreePicture(localSrc, 0); if (localMask && localMask != pMask) FreePicture(localMask, 0); + if (localDst != pDst) { + GCPtr gc; + + gc = GetScratchGC(pDst->pDrawable->depth, screen); + if (gc) { + ValidateGC(pDst->pDrawable, gc); + gc->ops->CopyArea(localDst->pDrawable, pDst->pDrawable, gc, + 0, 0, width, height, xDst_copy, yDst_copy); + FreeScratchGC(gc); + } + + FreePicture(localDst, 0); + } + return 1; } /** * uxa_try_magic_two_pass_composite_helper implements PictOpOver using two passes of * simpler operations PictOpOutReverse and PictOpAdd. Mainly used for component @@ -1362,42 +1328,106 @@ uxa_try_driver_composite(CARD8 op, static int uxa_try_magic_two_pass_composite_helper(CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst, - INT16 xSrc, - INT16 ySrc, - INT16 xMask, - INT16 yMask, - INT16 xDst, - INT16 yDst, CARD16 width, CARD16 height) + INT16 xSrc, INT16 ySrc, + INT16 xMask, INT16 yMask, + INT16 xDst, INT16 yDst, + CARD16 width, CARD16 height) { - uxa_screen_t *uxa_screen = uxa_get_screen(pDst->pDrawable->pScreen); + ScreenPtr screen = pDst->pDrawable->pScreen; + uxa_screen_t *uxa_screen = uxa_get_screen(screen); + PicturePtr localDst = pDst; + int xDst_copy, yDst_copy; assert(op == PictOpOver); if (uxa_screen->info->check_composite && (!(*uxa_screen->info->check_composite) (PictOpOutReverse, pSrc, - pMask, pDst) + pMask, pDst, width, height) || !(*uxa_screen->info->check_composite) (PictOpAdd, pSrc, pMask, - pDst))) { + pDst, width, height))) { return -1; } + if (uxa_screen->info->check_composite_target && + !uxa_screen->info->check_composite_target(uxa_get_drawable_pixmap(pDst->pDrawable))) { + int depth = pDst->pDrawable->depth; + PixmapPtr pixmap; + int error; + GCPtr gc; + + pixmap = uxa_get_drawable_pixmap(pDst->pDrawable); + if (uxa_screen->info->check_copy && + !uxa_screen->info->check_copy(pixmap, pixmap, GXcopy, FB_ALLONES)) + return -1; + + pixmap = screen->CreatePixmap(screen, + width, height, depth, + CREATE_PIXMAP_USAGE_SCRATCH); + if (!pixmap) + return 0; + + gc = GetScratchGC(depth, screen); + if (!gc) { + screen->DestroyPixmap(pixmap); + return 0; + } + + ValidateGC(&pixmap->drawable, gc); + gc->ops->CopyArea(pDst->pDrawable, &pixmap->drawable, gc, + xDst, yDst, width, height, 0, 0); + FreeScratchGC(gc); + + xDst_copy = xDst; xDst = 0; + yDst_copy = yDst; yDst = 0; + + localDst = CreatePicture(0, &pixmap->drawable, + PictureMatchFormat(screen, depth, pDst->format), + 0, 0, serverClient, &error); + screen->DestroyPixmap(pixmap); + + if (!localDst) + return 0; + + ValidatePicture(localDst); + } + /* Now, we think we should be able to accelerate this operation. First, * composite the destination to be the destination times the source alpha * factors. */ - uxa_composite(PictOpOutReverse, pSrc, pMask, pDst, xSrc, ySrc, xMask, - yMask, xDst, yDst, width, height); + uxa_composite(PictOpOutReverse, pSrc, pMask, localDst, + xSrc, ySrc, + xMask, yMask, + xDst, yDst, + width, height); /* Then, add in the source value times the destination alpha factors (1.0). */ - uxa_composite(PictOpAdd, pSrc, pMask, pDst, xSrc, ySrc, xMask, yMask, - xDst, yDst, width, height); + uxa_composite(PictOpAdd, pSrc, pMask, localDst, + xSrc, ySrc, + xMask, yMask, + xDst, yDst, + width, height); + + if (localDst != pDst) { + GCPtr gc; + + gc = GetScratchGC(pDst->pDrawable->depth, screen); + if (gc) { + ValidateGC(pDst->pDrawable, gc); + gc->ops->CopyArea(localDst->pDrawable, pDst->pDrawable, gc, + 0, 0, width, height, xDst_copy, yDst_copy); + FreeScratchGC(gc); + } + + FreePicture(localDst, 0); + } return 1; } static int compatible_formats (CARD8 op, PicturePtr dst, PicturePtr src) @@ -1447,16 +1477,16 @@ drawable_contains (DrawablePtr drawable, int x, int y, int w, int h) void uxa_composite(CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst, - INT16 xSrc, - INT16 ySrc, - INT16 xMask, - INT16 yMask, INT16 xDst, INT16 yDst, CARD16 width, CARD16 height) + INT16 xSrc, INT16 ySrc, + INT16 xMask, INT16 yMask, + INT16 xDst, INT16 yDst, + CARD16 width, CARD16 height) { uxa_screen_t *uxa_screen = uxa_get_screen(pDst->pDrawable->pScreen); int ret = -1; Bool saveSrcRepeat = pSrc->repeat; Bool saveMaskRepeat = pMask ? pMask->repeat : 0; RegionRec region; @@ -1465,15 +1495,17 @@ uxa_composite(CARD8 op, if (uxa_screen->swappedOut) goto fallback; if (!uxa_drawable_is_offscreen(pDst->pDrawable)) goto fallback; + if (pDst->alphaMap || pSrc->alphaMap || (pMask && pMask->alphaMap)) goto fallback; + /* Remove repeat in source if useless */ if (pSrc->pDrawable && pSrc->repeat && pSrc->filter != PictFilterConvolution && transform_is_integer_translation(pSrc->transform, &tx, &ty) && (pSrc->pDrawable->width > 1 || pSrc->pDrawable->height > 1) && drawable_contains(pSrc->pDrawable, xSrc + tx, ySrc + ty, width, height)) pSrc->repeat = 0; @@ -148,15 +148,13 @@ typedef struct _UxaDriver { /** @name copy * @{ */ /** * check_copy() checks whether the driver can blit between the two Pictures */ - Bool(*check_copy) (DrawablePtr pSrcDrawable, - DrawablePtr pDstDrawable, - int alu, Pixel planemask); + Bool(*check_copy) (PixmapPtr pSrc, PixmapPtr pDst, int alu, Pixel planemask); /** * prepare_copy() sets up the driver for doing a copy within video * memory. - * * @param pSrcPixmap source pixmap * @param pDstPixmap destination pixmap @@ -246,12 +244,14 @@ typedef struct _UxaDriver { * accelerated. * * @param op Render operation * @param pSrcPicture source Picture * @param pMaskPicture mask picture * @param pDstPicture destination Picture + * @param width The width of the composite operation + * @param height The height of the composite operation * * The check_composite() call checks if the driver could handle * acceleration of op with the given source, mask, and destination * pictures. This allows drivers to check source and destination * formats, supported operations, transformations, and component * alpha state, and send operations it can't support to software @@ -263,13 +263,25 @@ typedef struct _UxaDriver { * The check_composite() call is recommended if prepare_composite() is * implemented, but is not required. */ Bool(*check_composite) (int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture, - PicturePtr pDstPicture); + PicturePtr pDstPicture, + int width, int height); + + /** + * check_composite_target() checks to see if the destination of the composite + * operation can be used without midification. + * + * @param pixmap Destination Pixmap + * + * The check_composite_target() call is recommended if prepare_composite() is + * implemented, but is not required. + */ + Bool(*check_composite_target) (PixmapPtr pixmap); /** * check_composite_texture() checks to see if a source to the composite * operation can be used without midification. * * @param pScreen Screen |