/** * Copy the back color buffer to the front color buffer. * Used for SwapBuffers(). */ void intelCopyBuffer(const __DRIdrawablePrivate * dPriv, const drm_clip_rect_t * rect) { struct intel_context *intel; const intelScreenPrivate *intelScreen; DBG("%s\n", __FUNCTION__); assert(dPriv); intel = intelScreenContext(dPriv->driScreenPriv->private); if (!intel) return; intelScreen = intel->intelScreen; if (intel->last_swap_fence) { dri_fence_wait(intel->last_swap_fence); dri_fence_unreference(intel->last_swap_fence); intel->last_swap_fence = NULL; } intel->last_swap_fence = intel->first_swap_fence; intel->first_swap_fence = NULL; /* The LOCK_HARDWARE is required for the cliprects. Buffer offsets * should work regardless. */ LOCK_HARDWARE(intel); if (dPriv && dPriv->numClipRects) { struct intel_framebuffer *intel_fb = dPriv->driverPrivate; const struct intel_region *frontRegion = intel_get_rb_region(&intel_fb->Base, BUFFER_FRONT_LEFT); const struct intel_region *backRegion = intel_get_rb_region(&intel_fb->Base, BUFFER_BACK_LEFT); const int nbox = dPriv->numClipRects; const drm_clip_rect_t *pbox = dPriv->pClipRects; const int cpp = frontRegion->cpp; int src_pitch = backRegion->pitch * cpp; int dst_pitch = frontRegion->pitch * cpp; int BR13, CMD; int i; ASSERT(intel_fb); ASSERT(intel_fb->Base.Name == 0); /* Not a user-created FBO */ ASSERT(frontRegion); ASSERT(backRegion); ASSERT(frontRegion->pitch == backRegion->pitch); ASSERT(frontRegion->cpp == backRegion->cpp); if (cpp == 2) { BR13 = (0xCC << 16) | (1 << 24); CMD = XY_SRC_COPY_BLT_CMD; } else { BR13 = (0xCC << 16) | (1 << 24) | (1 << 25); CMD = XY_SRC_COPY_BLT_CMD | XY_BLT_WRITE_ALPHA | XY_BLT_WRITE_RGB; } #ifndef I915 if (backRegion->tiled) { CMD |= XY_SRC_TILED; src_pitch /= 4; } if (frontRegion->tiled) { CMD |= XY_DST_TILED; dst_pitch /= 4; } #endif for (i = 0; i < nbox; i++, pbox++) { drm_clip_rect_t box; if (pbox->x1 >= pbox->x2 || pbox->y1 >= pbox->y2 || pbox->x2 > intelScreen->width || pbox->y2 > intelScreen->height) continue; box = *pbox; if (rect) { if (rect->x1 > box.x1) box.x1 = rect->x1; if (rect->y1 > box.y1) box.y1 = rect->y1; if (rect->x2 < box.x2) box.x2 = rect->x2; if (rect->y2 < box.y2) box.y2 = rect->y2; if (box.x1 >= box.x2 || box.y1 >= box.y2) continue; } assert(box.x1 < box.x2); assert(box.y1 < box.y2); BEGIN_BATCH(8, INTEL_BATCH_NO_CLIPRECTS); OUT_BATCH(CMD); OUT_BATCH(BR13 | dst_pitch); OUT_BATCH((box.y1 << 16) | box.x1); OUT_BATCH((box.y2 << 16) | box.x2); OUT_RELOC(frontRegion->buffer, DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_WRITE, 0); OUT_BATCH((box.y1 << 16) | box.x1); OUT_BATCH(src_pitch); OUT_RELOC(backRegion->buffer, DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_READ, 0); ADVANCE_BATCH(); } if (intel->first_swap_fence) dri_fence_unreference(intel->first_swap_fence); intel_batchbuffer_flush(intel->batch); intel->first_swap_fence = intel->batch->last_fence; if (intel->first_swap_fence) dri_fence_reference(intel->first_swap_fence); } UNLOCK_HARDWARE(intel); }
/** * Copy the back color buffer to the front color buffer. * Used for SwapBuffers(). */ void intelCopyBuffer(const __DRIdrawablePrivate * dPriv, const drm_clip_rect_t * rect) { struct intel_context *intel; const intelScreenPrivate *intelScreen; int ret; DBG("%s\n", __FUNCTION__); assert(dPriv); intel = intelScreenContext(dPriv->driScreenPriv->private); if (!intel) return; intelScreen = intel->intelScreen; if (intel->last_swap_fence) { dri_fence_wait(intel->last_swap_fence); dri_fence_unreference(intel->last_swap_fence); intel->last_swap_fence = NULL; } intel->last_swap_fence = intel->first_swap_fence; intel->first_swap_fence = NULL; /* The LOCK_HARDWARE is required for the cliprects. Buffer offsets * should work regardless. */ LOCK_HARDWARE(intel); if (dPriv && dPriv->numClipRects) { struct intel_framebuffer *intel_fb = dPriv->driverPrivate; struct intel_region *src, *dst; int nbox = dPriv->numClipRects; drm_clip_rect_t *pbox = dPriv->pClipRects; int cpp; int src_pitch, dst_pitch; unsigned short src_x, src_y; int BR13, CMD; int i; src = intel_get_rb_region(&intel_fb->Base, BUFFER_BACK_LEFT); dst = intel_get_rb_region(&intel_fb->Base, BUFFER_FRONT_LEFT); src_pitch = src->pitch * src->cpp; dst_pitch = dst->pitch * dst->cpp; cpp = src->cpp; ASSERT(intel_fb); ASSERT(intel_fb->Base.Name == 0); /* Not a user-created FBO */ ASSERT(src); ASSERT(dst); ASSERT(src->cpp == dst->cpp); if (cpp == 2) { BR13 = (0xCC << 16) | (1 << 24); CMD = XY_SRC_COPY_BLT_CMD; } else { BR13 = (0xCC << 16) | (1 << 24) | (1 << 25); CMD = XY_SRC_COPY_BLT_CMD | XY_BLT_WRITE_ALPHA | XY_BLT_WRITE_RGB; } #ifndef I915 if (src->tiled) { CMD |= XY_SRC_TILED; src_pitch /= 4; } if (dst->tiled) { CMD |= XY_DST_TILED; dst_pitch /= 4; } #endif /* do space/cliprects check before going any further */ intel_batchbuffer_require_space(intel->batch, 8 * 4, REFERENCES_CLIPRECTS); again: ret = dri_bufmgr_check_aperture_space(dst->buffer); ret |= dri_bufmgr_check_aperture_space(src->buffer); if (ret) { intel_batchbuffer_flush(intel->batch); goto again; } for (i = 0; i < nbox; i++, pbox++) { drm_clip_rect_t box = *pbox; if (rect) { if (!intel_intersect_cliprects(&box, &box, rect)) continue; } if (box.x1 >= box.x2 || box.y1 >= box.y2) continue; assert(box.x1 < box.x2); assert(box.y1 < box.y2); src_x = box.x1 - dPriv->x + dPriv->backX; src_y = box.y1 - dPriv->y + dPriv->backY; BEGIN_BATCH(8, REFERENCES_CLIPRECTS); OUT_BATCH(CMD); OUT_BATCH(BR13 | dst_pitch); OUT_BATCH((box.y1 << 16) | box.x1); OUT_BATCH((box.y2 << 16) | box.x2); OUT_RELOC(dst->buffer, DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_WRITE, 0); OUT_BATCH((src_y << 16) | src_x); OUT_BATCH(src_pitch); OUT_RELOC(src->buffer, DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_READ, 0); ADVANCE_BATCH(); } if (intel->first_swap_fence) dri_fence_unreference(intel->first_swap_fence); intel_batchbuffer_flush(intel->batch); intel->first_swap_fence = intel->batch->last_fence; if (intel->first_swap_fence) dri_fence_reference(intel->first_swap_fence); } UNLOCK_HARDWARE(intel); }