diff options
Diffstat (limited to 'src/intel_shadow.c')
-rw-r--r-- | src/intel_shadow.c | 211 |
1 files changed, 211 insertions, 0 deletions
diff --git a/src/intel_shadow.c b/src/intel_shadow.c new file mode 100644 index 00000000..a4b14f90 --- /dev/null +++ b/src/intel_shadow.c @@ -0,0 +1,211 @@ +/************************************************************************** + +Copyright 2010 Intel Corporation +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sub license, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice (including the +next paragraph) shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. +IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "xf86.h" +#include "xaarop.h" +#include "intel.h" +#include "i830_reg.h" + +static dri_bo * +intel_shadow_create_bo(intel_screen_private *intel, + int16_t x1, int16_t y1, + int16_t x2, int16_t y2, + int *pitch) +{ + int w = x2 - x1, h = y2 - y1; + int size = h * w * intel->cpp; + dri_bo *bo; + + bo = drm_intel_bo_alloc(intel->bufmgr, "shadow", size, 0); + if (bo && drm_intel_gem_bo_map_gtt(bo) == 0) { + char *dst = bo->virtual; + char *src = intel->shadow_buffer; + int src_pitch = intel->shadow_stride; + int row_length = w * intel->cpp; + int num_rows = h; + src += y1 * src_pitch + x1 * intel->cpp; + do { + memcpy (dst, src, row_length); + src += src_pitch; + dst += row_length; + } while (--num_rows); + drm_intel_gem_bo_unmap_gtt(bo); + } + + *pitch = w * intel->cpp; + return bo; +} + +void intel_shadow_blt(intel_screen_private *intel) +{ + ScrnInfoPtr scrn = intel->scrn; + unsigned int dst_pitch; + uint32_t blt, br13; + RegionPtr region; + BoxPtr box; + int n; + + dst_pitch = intel->front_pitch; + + blt = XY_SRC_COPY_BLT_CMD; + if (intel->cpp == 4) + blt |= (XY_SRC_COPY_BLT_WRITE_ALPHA | + XY_SRC_COPY_BLT_WRITE_RGB); + + if (IS_I965G(intel)) { + if (intel->front_tiling) { + dst_pitch >>= 2; + blt |= XY_SRC_COPY_BLT_DST_TILED; + } + } + + br13 = ROP_S << 16 | dst_pitch; + switch (intel->cpp) { + default: + case 4: br13 |= 1 << 25; /* RGB8888 */ + case 2: br13 |= 1 << 24; /* RGB565 */ + case 1: break; + } + + region = DamageRegion(intel->shadow_damage); + box = REGION_RECTS(region); + n = REGION_NUM_RECTS(region); + while (n--) { + int pitch; + dri_bo *bo; + int offset; + + if (IS_I8XX(intel)) { + bo = intel->shadow_buffer; + offset = box->x1 | box->y1 << 16; + pitch = intel->shadow_stride; + } else { + bo = intel_shadow_create_bo(intel, + box->x1, box->y1, + box->x2, box->y2, + &pitch); + if (bo == NULL) + return; + + offset = 0; + } + + BEGIN_BATCH(8); + OUT_BATCH(blt); + OUT_BATCH(br13); + OUT_BATCH(box->y1 << 16 | box->x1); + OUT_BATCH(box->y2 << 16 | box->x2); + OUT_RELOC_FENCED(intel->front_buffer, + I915_GEM_DOMAIN_RENDER, + I915_GEM_DOMAIN_RENDER, + 0); + OUT_BATCH(offset); + OUT_BATCH(pitch); + OUT_RELOC(bo, I915_GEM_DOMAIN_RENDER, 0, 0); + + ADVANCE_BATCH(); + + if (bo != intel->shadow_buffer) + drm_intel_bo_unreference(bo); + box++; + } +} + +void intel_shadow_create(struct intel_screen_private *intel) +{ + ScrnInfoPtr scrn = intel->scrn; + ScreenPtr screen = scrn->pScreen; + PixmapPtr pixmap; + int stride; + + pixmap = screen->GetScreenPixmap(screen); + if (IS_I8XX(intel)) { + dri_bo *bo; + int size; + + /* Reduce the incoherency worries for gen2 + * by only allocating a static shadow, at about 2-3x + * performance cost for forcing rendering to uncached memory. + */ + if (intel->shadow_buffer) { + drm_intel_gem_bo_unmap_gtt(intel->shadow_buffer); + drm_intel_bo_unreference(intel->shadow_buffer); + intel->shadow_buffer = NULL; + } + + stride = ALIGN(scrn->virtualX * intel->cpp, 4); + size = stride * scrn->virtualY; + bo = drm_intel_bo_alloc(intel->bufmgr, + "shadow", size, + 0); + if (bo && drm_intel_gem_bo_map_gtt(bo) == 0) { + screen->ModifyPixmapHeader(pixmap, + scrn->virtualX, + scrn->virtualY, + -1, -1, + stride, + bo->virtual); + intel->shadow_buffer = bo; + } + } else { + void *buffer; + + stride = intel->cpp*scrn->virtualX; + buffer = malloc(stride * scrn->virtualY); + + if (buffer && screen->ModifyPixmapHeader(pixmap, + scrn->virtualX, + scrn->virtualY, + -1, -1, + stride, + buffer)) { + if (intel->shadow_buffer) + free(intel->shadow_buffer); + + intel->shadow_buffer = buffer; + } else + stride = intel->shadow_stride; + } + + if (!intel->shadow_damage) { + intel->shadow_damage = DamageCreate(NULL, NULL, + DamageReportNone, + TRUE, + screen, + intel); + DamageRegister(&pixmap->drawable, intel->shadow_damage); + DamageSetReportAfterOp(intel->shadow_damage, TRUE); + } + + scrn->displayWidth = stride / intel->cpp; + intel->shadow_stride = stride; +} + |