Bool i915_check_composite_texture(ScreenPtr screen, PicturePtr picture) { if (picture->repeatType > RepeatReflect) { ScrnInfoPtr scrn = xf86Screens[screen->myNum]; intel_debug_fallback(scrn, "Unsupported picture repeat %d\n", picture->repeatType); return FALSE; } if (picture->filter != PictFilterNearest && picture->filter != PictFilterBilinear) { ScrnInfoPtr scrn = xf86Screens[screen->myNum]; intel_debug_fallback(scrn, "Unsupported filter 0x%x\n", picture->filter); return FALSE; } if (picture->pSourcePict) { SourcePict *source = picture->pSourcePict; if (source->type == SourcePictTypeSolidFill) return TRUE; } if (picture->pDrawable) { int w, h, i; w = picture->pDrawable->width; h = picture->pDrawable->height; if ((w > 2048) || (h > 2048)) { ScrnInfoPtr scrn = xf86Screens[screen->myNum]; intel_debug_fallback(scrn, "Picture w/h too large (%dx%d)\n", w, h); return FALSE; } for (i = 0; i < sizeof(i915_tex_formats) / sizeof(i915_tex_formats[0]); i++) { if (i915_tex_formats[i].fmt == picture->format) break; } if (i == sizeof(i915_tex_formats) / sizeof(i915_tex_formats[0])) { ScrnInfoPtr scrn = xf86Screens[screen->myNum]; intel_debug_fallback(scrn, "Unsupported picture format " "0x%x\n", (int)picture->format); return FALSE; } return TRUE; } return FALSE; }
static Bool i830_get_dest_format(PicturePtr dest_picture, uint32_t * dst_format) { ScrnInfoPtr scrn; switch (dest_picture->format) { case PICT_a8r8g8b8: case PICT_x8r8g8b8: *dst_format = COLR_BUF_ARGB8888; break; case PICT_r5g6b5: *dst_format = COLR_BUF_RGB565; break; case PICT_a1r5g5b5: case PICT_x1r5g5b5: *dst_format = COLR_BUF_ARGB1555; break; case PICT_a8: *dst_format = COLR_BUF_8BIT; break; case PICT_a4r4g4b4: case PICT_x4r4g4b4: *dst_format = COLR_BUF_ARGB4444; break; default: scrn = xf86Screens[dest_picture->pDrawable->pScreen->myNum]; intel_debug_fallback(scrn, "Unsupported dest format 0x%x\n", (int)dest_picture->format); return FALSE; } *dst_format |= DSTORG_HORT_BIAS(0x8) | DSTORG_VERT_BIAS(0x8); return TRUE; }
Bool i915_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(i915_blend_op) / sizeof(i915_blend_op[0])) { intel_debug_fallback(scrn, "Unsupported Composite op 0x%x\n", op); return 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) { 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 i830_check_composite_texture(ScreenPtr screen, PicturePtr picture) { ScrnInfoPtr scrn = xf86Screens[screen->myNum]; intel_screen_private *intel = intel_get_screen_private(scrn); if (picture->repeatType > RepeatReflect) { intel_debug_fallback(scrn, "Unsupported picture repeat %d\n", picture->repeatType); return FALSE; } if (picture->filter != PictFilterNearest && picture->filter != PictFilterBilinear) { intel_debug_fallback(scrn, "Unsupported filter 0x%x\n", picture->filter); return FALSE; } if (picture->pDrawable) { int w, h; w = picture->pDrawable->width; h = picture->pDrawable->height; if ((w > 2048) || (h > 2048)) { intel_debug_fallback(scrn, "Picture w/h too large (%dx%d)\n", w, h); return FALSE; } /* XXX we can use the xrgb32 types if there the picture covers the clip */ if (!i8xx_get_card_format(intel, picture)) { intel_debug_fallback(scrn, "Unsupported picture format " "0x%x\n", (int)picture->format); return FALSE; } return TRUE; } return FALSE; }
Bool i830_check_composite(int op, PicturePtr source_picture, PicturePtr mask_picture, PicturePtr dest_picture, int width, int height) { ScrnInfoPtr scrn = xf86ScreenToScrn(dest_picture->pDrawable->pScreen); uint32_t tmp1; /* Check for unsupported compositing operations. */ if (op >= sizeof(i830_blend_op) / sizeof(i830_blend_op[0])) { intel_debug_fallback(scrn, "Unsupported Composite op 0x%x\n", op); return 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 (i830_blend_op[op].src_alpha && (i830_blend_op[op].src_blend != BLENDFACTOR_ZERO)) { intel_debug_fallback(scrn, "Component alpha not " "supported with source alpha and " "source value blending.\n"); return FALSE; } } 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 intel_get_aperture_space(ScrnInfoPtr scrn, drm_intel_bo ** bo_table, int num_bos) { intel_screen_private *intel = intel_get_screen_private(scrn); if (intel->batch_bo == NULL) { intel_debug_fallback(scrn, "VT inactive\n"); return FALSE; } bo_table[0] = intel->batch_bo; if (drm_intel_bufmgr_check_aperture_space(bo_table, num_bos) != 0) { intel_batch_submit(scrn); bo_table[0] = intel->batch_bo; if (drm_intel_bufmgr_check_aperture_space(bo_table, num_bos) != 0) { intel_debug_fallback(scrn, "Couldn't get aperture " "space for BOs\n"); return FALSE; } } return TRUE; }
static Bool i830_get_blend_cntl(ScrnInfoPtr scrn, int op, PicturePtr mask, uint32_t dst_format, uint32_t * blendctl) { uint32_t sblend, dblend; sblend = i830_blend_op[op].src_blend; dblend = i830_blend_op[op].dst_blend; /* If there's no dst alpha channel, adjust the blend op so that we'll treat * it as always 1. */ if (PICT_FORMAT_A(dst_format) == 0 && i830_blend_op[op].dst_alpha) { if (sblend == BLENDFACTOR_DST_ALPHA) sblend = BLENDFACTOR_ONE; else if (sblend == BLENDFACTOR_INV_DST_ALPHA) sblend = BLENDFACTOR_ZERO; } /* For blending purposes, COLR_BUF_8BIT values show up in the green * channel. So we can't use the alpha channel. */ if (dst_format == PICT_a8 && ((sblend == BLENDFACTOR_DST_ALPHA || sblend == BLENDFACTOR_INV_DST_ALPHA))) { intel_debug_fallback(scrn, "Can't do dst alpha blending with " "PICT_a8 dest.\n"); return FALSE; } /* If the source alpha is being used, then we should only be in a case * where the source blend factor is 0, and the source blend value is the * mask channels multiplied by the source picture's alpha. */ if (mask && mask->componentAlpha && PICT_FORMAT_RGB(mask->format) && i830_blend_op[op].src_alpha) { if (dblend == BLENDFACTOR_SRC_ALPHA) { dblend = BLENDFACTOR_SRC_COLR; } else if (dblend == BLENDFACTOR_INV_SRC_ALPHA) { dblend = BLENDFACTOR_INV_SRC_COLR; } } *blendctl = (sblend << S8_SRC_BLEND_FACTOR_SHIFT) | (dblend << S8_DST_BLEND_FACTOR_SHIFT); return TRUE; }
static Bool intel_uxa_check_solid(DrawablePtr drawable, int alu, Pixel planemask) { ScrnInfoPtr scrn = xf86Screens[drawable->pScreen->myNum]; if (!UXA_PM_IS_SOLID(drawable, planemask)) { intel_debug_fallback(scrn, "planemask is not solid\n"); return FALSE; } switch (drawable->bitsPerPixel) { case 8: case 16: case 32: break; default: return FALSE; } return TRUE; }
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]; intel_screen_private *intel = intel_get_screen_private(scrn); drm_intel_bo *bo_table[] = { NULL, /* batch_bo */ intel_get_pixmap_bo(dest), source ? intel_get_pixmap_bo(source) : NULL, mask ? intel_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; intel->render_dest = dest; intel->render_source_is_solid = FALSE; if (source_picture->pSourcePict) { SourcePict *source = source_picture->pSourcePict; if (source->type == SourcePictTypeSolidFill) { intel->render_source_is_solid = TRUE; intel->render_source_solid = source->solidFill.color; } } if (!intel->render_source_is_solid && !intel_check_pitch_3d(source)) return FALSE; intel->render_mask_is_solid = FALSE; if (mask) { if (mask_picture->pSourcePict) { SourcePict *source = mask_picture->pSourcePict; if (source->type == SourcePictTypeSolidFill) { intel->render_mask_is_solid = TRUE; intel->render_mask_solid = source->solidFill.color; } } if (!intel->render_mask_is_solid && !intel_check_pitch_3d(mask)) return FALSE; } if (!intel_check_pitch_3d(dest)) return FALSE; if (!i915_get_dest_format(dest_picture, &intel->i915_render_state.dst_format)) return FALSE; if (!intel_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->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 (intel_transform_is_affine(source_picture->transform)) floats_per_vertex += 2; /* src x/y */ else floats_per_vertex += 4; /* src x/y/z/w */ } if (mask != NULL) { if (! intel->render_mask_is_solid) { if (!i915_texture_setup(mask_picture, mask, tex_unit++)) { intel_debug_fallback(scrn, "fail to setup mask texture\n"); return FALSE; } if (intel_transform_is_affine(mask_picture->transform)) floats_per_vertex += 2; /* mask x/y */ else floats_per_vertex += 4; /* mask x/y/z/w */ } } intel->i915_render_state.op = op; /* BUF_INFO is an implicit flush */ if (dest != intel->render_current_dest) intel_batch_do_flush(scrn); else if((source && intel_pixmap_is_dirty(source)) || (mask && intel_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 (intel_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 Bool i915_texture_setup(PicturePtr picture, PixmapPtr pixmap, int unit) { ScrnInfoPtr scrn = xf86Screens[picture->pDrawable->pScreen->myNum]; intel_screen_private *intel = intel_get_screen_private(scrn); uint32_t format, pitch, filter; uint32_t wrap_mode, tiling_bits; int i; pitch = intel_pixmap_pitch(pixmap); 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; } if (i == sizeof(i915_tex_formats) / sizeof(i915_tex_formats[0])) { intel_debug_fallback(scrn, "unknown texture format\n"); return FALSE; } format = i915_tex_formats[i].card_fmt; switch (picture->repeatType) { case RepeatNone: wrap_mode = TEXCOORDMODE_CLAMP_BORDER; break; case RepeatNormal: wrap_mode = TEXCOORDMODE_WRAP; break; case RepeatPad: wrap_mode = TEXCOORDMODE_CLAMP_EDGE; break; case RepeatReflect: wrap_mode = TEXCOORDMODE_MIRROR; break; default: FatalError("Unknown repeat type %d\n", picture->repeatType); } switch (picture->filter) { case PictFilterNearest: filter = (FILTER_NEAREST << SS2_MAG_FILTER_SHIFT) | (FILTER_NEAREST << SS2_MIN_FILTER_SHIFT); break; case PictFilterBilinear: filter = (FILTER_LINEAR << SS2_MAG_FILTER_SHIFT) | (FILTER_LINEAR << SS2_MIN_FILTER_SHIFT); break; default: filter = 0; intel_debug_fallback(scrn, "Bad filter 0x%x\n", picture->filter); return FALSE; } /* offset filled in at emit time */ if (intel_pixmap_tiled(pixmap)) { tiling_bits = MS3_TILED_SURFACE; if (intel_get_pixmap_private(pixmap)->tiling == I915_TILING_Y) tiling_bits |= MS3_TILE_WALK; } else tiling_bits = 0; intel->texture[unit] = pixmap; intel->mapstate[unit * 3 + 0] = 0; intel->mapstate[unit * 3 + 1] = format | tiling_bits | ((pixmap->drawable.height - 1) << MS3_HEIGHT_SHIFT) | ((pixmap->drawable.width - 1) << MS3_WIDTH_SHIFT); intel->mapstate[unit * 3 + 2] = ((pitch / 4) - 1) << MS4_PITCH_SHIFT; intel->samplerstate[unit * 3 + 0] = (MIPFILTER_NONE << SS2_MIP_FILTER_SHIFT); intel->samplerstate[unit * 3 + 0] |= filter; intel->samplerstate[unit * 3 + 1] = SS3_NORMALIZED_COORDS; intel->samplerstate[unit * 3 + 1] |= wrap_mode << SS3_TCX_ADDR_MODE_SHIFT; intel->samplerstate[unit * 3 + 1] |= wrap_mode << SS3_TCY_ADDR_MODE_SHIFT; intel->samplerstate[unit * 3 + 1] |= unit << SS3_TEXTUREMAP_INDEX_SHIFT; intel->samplerstate[unit * 3 + 2] = 0x00000000; /* border color */ intel->transform[unit] = picture->transform; return TRUE; }
Bool i830_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]; intel_screen_private *intel = intel_get_screen_private(scrn); drm_intel_bo *bo_table[] = { NULL, /* batch_bo */ intel_get_pixmap_bo(source), mask ? intel_get_pixmap_bo(mask) : NULL, intel_get_pixmap_bo(dest), }; 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; intel->render_dest = dest; if (!intel_check_pitch_3d(source)) return FALSE; if (mask) { if (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 (i830_blend_op[op].src_alpha && (i830_blend_op[op].src_blend != BLENDFACTOR_ZERO)) { intel_debug_fallback(scrn, "Component alpha not " "supported with source alpha and " "source value blending.\n"); return FALSE; } } if (!intel_check_pitch_3d(mask)) return FALSE; } if (!intel_check_pitch_3d(dest)) return FALSE; if (!i830_get_dest_format(dest_picture, &intel->render_dest_format)) return FALSE; if (!intel_get_aperture_space(scrn, bo_table, ARRAY_SIZE(bo_table))) return FALSE; if (mask) { intel->transform[1] = NULL; intel->scale_units[1][0] = -1; intel->scale_units[1][1] = -1; } { uint32_t cblend, ablend, blendctl; /* 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). * * The PICT_FORMAT_RGB(pict) == 0 fixups are not needed on 855+'s a8 * pictures, but we need to implement it for 830/845 and there's no * harm done in leaving it in. */ cblend = TB0C_LAST_STAGE | TB0C_RESULT_SCALE_1X | TB0C_OP_MODULE | TB0C_OUTPUT_WRITE_CURRENT; ablend = TB0A_RESULT_SCALE_1X | TB0A_OP_MODULE | TB0A_OUTPUT_WRITE_CURRENT; /* Get the source picture's channels into TBx_ARG1 */ if ((mask_picture != NULL && mask_picture->componentAlpha && PICT_FORMAT_RGB(mask_picture->format) && i830_blend_op[op].src_alpha) || dest_picture->format == PICT_a8) { /* Producing source alpha value, so the first set of channels * is src.A instead of src.X. We also do this if the destination * is a8, in which case src.G is what's written, and the other * channels are ignored. */ ablend |= TB0A_ARG1_SEL_TEXEL0; cblend |= TB0C_ARG1_SEL_TEXEL0 | TB0C_ARG1_REPLICATE_ALPHA; } else { if (PICT_FORMAT_RGB(source_picture->format) != 0) cblend |= TB0C_ARG1_SEL_TEXEL0; else cblend |= TB0C_ARG1_SEL_ONE | TB0C_ARG1_INVERT; /* 0.0 */ ablend |= TB0A_ARG1_SEL_TEXEL0; } if (mask) { cblend |= TB0C_ARG2_SEL_TEXEL1; if (dest_picture->format == PICT_a8 || ! mask_picture->componentAlpha || ! PICT_FORMAT_RGB(mask_picture->format)) cblend |= TB0C_ARG2_REPLICATE_ALPHA; ablend |= TB0A_ARG2_SEL_TEXEL1; } else { cblend |= TB0C_ARG2_SEL_ONE; ablend |= TB0A_ARG2_SEL_ONE; } if (!i830_get_blend_cntl (scrn, op, mask_picture, dest_picture->format, &blendctl)) { return FALSE; } intel->cblend = cblend; intel->ablend = ablend; intel->s8_blendctl = blendctl; } if(intel_pixmap_is_dirty(source) || (mask && intel_pixmap_is_dirty(mask))) intel_batch_emit_flush(scrn); intel->needs_render_state_emit = TRUE; return TRUE; }