intel-2D: sna-2.99.902

git-svn-id: svn://kolibrios.org@4251 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
Sergey Semyonov (Serge) 2013-11-18 11:28:53 +00:00
parent d67cc6c3b8
commit de8b1b257a
28 changed files with 16198 additions and 5598 deletions

View File

@ -2239,8 +2239,6 @@ void brw_CMP(struct brw_compile *p,
struct brw_reg src0,
struct brw_reg src1);
void brw_print_reg(struct brw_reg reg);
static inline void brw_math_invert(struct brw_compile *p,
struct brw_reg dst,
struct brw_reg src)

View File

@ -37,19 +37,46 @@
#define must_check __attribute__((warn_unused_result))
#define constant __attribute__((const))
#define pure __attribute__((pure))
#define __packed__ __attribute__((__packed__))
#define tightly_packed __attribute__((__packed__))
#define flatten __attribute__((flatten))
#define page_aligned __attribute__((aligned(4096)))
#else
#define likely(expr) (expr)
#define unlikely(expr) (expr)
#define noinline
#define force_inline
#define force_inline inline
#define fastcall
#define must_check
#define constant
#define pure
#define __packed__
#define tighly_packed
#define flatten
#define page_aligned
#endif
#define HAS_GCC(major, minor) defined(__GNUC__) && (__GNUC__ > (major) || __GNUC__ == (major) && __GNUC_MINOR__ >= (minor))
#if HAS_GCC(4, 5)
#define sse2 __attribute__((target("sse2,fpmath=sse")))
#define sse4_2 __attribute__((target("sse4.2,sse2,fpmath=sse")))
#endif
#if HAS_GCC(4, 7)
#define avx2 __attribute__((target("avx2,sse4.2,sse2,fpmath=sse")))
#endif
#if HAS_GCC(4, 6) && defined(__OPTIMIZE__)
#define fast __attribute__((optimize("Ofast")))
#else
#define fast
#endif
#if HAS_GCC(4, 6) && defined(__OPTIMIZE__)
#define fast_memcpy __attribute__((optimize("Ofast"))) __attribute__((target("inline-all-stringops")))
#elif HAS_GCC(4, 5) && defined(__OPTIMIZE__)
#define fast_memcpy __attribute__((target("inline-all-stringops")))
#else
#define fast_memcpy
#endif
#ifdef HAVE_VALGRIND

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -10,7 +10,6 @@ void gen4_vertex_flush(struct sna *sna);
int gen4_vertex_finish(struct sna *sna);
void gen4_vertex_close(struct sna *sna);
unsigned gen4_choose_composite_emitter(struct sna_composite_op *tmp);
//unsigned gen4_choose_spans_emitter(struct sna_composite_spans_op *tmp);
unsigned gen4_choose_composite_emitter(struct sna *sna, struct sna_composite_op *tmp);
#endif /* GEN4_VERTEX_H */

File diff suppressed because it is too large Load Diff

View File

@ -30,9 +30,6 @@
*
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "sna.h"
#include "sna_reg.h"
@ -54,7 +51,7 @@
#define NO_FILL_ONE 0
#define NO_FILL_CLEAR 0
#define NO_RING_SWITCH 1
#define NO_RING_SWITCH 0
#define PREFER_RENDER 0
#define USE_8_PIXEL_DISPATCH 1
@ -68,6 +65,7 @@
#define GEN6_MAX_SIZE 8192
struct gt_info {
const char *name;
int max_vs_threads;
int max_gs_threads;
int max_wm_threads;
@ -79,6 +77,7 @@ struct gt_info {
};
static const struct gt_info gt1_info = {
.name = "Sandybridge (gen6, gt1)",
.max_vs_threads = 24,
.max_gs_threads = 21,
.max_wm_threads = 40,
@ -86,6 +85,7 @@ static const struct gt_info gt1_info = {
};
static const struct gt_info gt2_info = {
.name = "Sandybridge (gen6, gt2)",
.max_vs_threads = 60,
.max_gs_threads = 60,
.max_wm_threads = 80,
@ -247,18 +247,6 @@ static uint32_t gen6_get_blend(int op,
static uint32_t gen6_get_card_format(PictFormat format)
{
switch (format) {
default:
return -1;
case PICT_a8r8g8b8:
return GEN6_SURFACEFORMAT_B8G8R8A8_UNORM;
case PICT_x8r8g8b8:
return GEN6_SURFACEFORMAT_B8G8R8X8_UNORM;
case PICT_a8:
return GEN6_SURFACEFORMAT_A8_UNORM;
};
/*
switch (format) {
default:
return -1;
@ -285,7 +273,6 @@ static uint32_t gen6_get_card_format(PictFormat format)
case PICT_a4r4g4b4:
return GEN6_SURFACEFORMAT_B4G4R4A4_UNORM;
}
*/
}
static uint32_t gen6_get_dest_format(PictFormat format)
@ -403,7 +390,6 @@ gen6_choose_composite_kernel(int op, bool has_mask, bool is_ca, bool is_affine)
int base;
if (has_mask) {
if (is_ca) {
if (gen6_blend_op[op].src_alpha)
base = GEN6_WM_KERNEL_MASKSA;
@ -411,7 +397,6 @@ gen6_choose_composite_kernel(int op, bool has_mask, bool is_ca, bool is_affine)
base = GEN6_WM_KERNEL_MASKCA;
} else
base = GEN6_WM_KERNEL_MASK;
} else
base = GEN6_WM_KERNEL_NOMASK;
@ -889,6 +874,8 @@ gen6_emit_state(struct sna *sna,
{
bool need_stall = wm_binding_table & 1;
assert(op->dst.bo->exec);
if (gen6_emit_cc(sna, GEN6_BLEND(op->u.gen6.flags)))
need_stall = false;
gen6_emit_sampler(sna, GEN6_SAMPLER(op->u.gen6.flags));
@ -902,7 +889,7 @@ gen6_emit_state(struct sna *sna,
if (kgem_bo_is_dirty(op->src.bo) || kgem_bo_is_dirty(op->mask.bo)) {
gen6_emit_flush(sna);
kgem_clear_dirty(&sna->kgem);
if (op->dst.bo->exec)
assert(op->dst.bo->exec);
kgem_bo_mark_dirty(op->dst.bo);
need_stall = false;
}
@ -1039,15 +1026,12 @@ sampler_fill_init(struct gen6_sampler_state *ss)
static uint32_t
gen6_tiling_bits(uint32_t tiling)
{
return 0;
/*
switch (tiling) {
default: assert(0);
case I915_TILING_NONE: return 0;
case I915_TILING_X: return GEN6_SURFACE_TILED;
case I915_TILING_Y: return GEN6_SURFACE_TILED | GEN6_SURFACE_TILED_Y;
}
*/
}
/**
@ -1068,7 +1052,7 @@ gen6_bind_bo(struct sna *sna,
uint32_t is_scanout = is_dst && bo->scanout;
/* After the first bind, we manage the cache domains within the batch */
offset = kgem_bo_get_binding(bo, format | is_scanout << 31);
offset = kgem_bo_get_binding(bo, format | is_dst << 30 | is_scanout << 31);
if (offset) {
DBG(("[%x] bo(handle=%d), format=%d, reuse %s binding\n",
offset, bo->handle, format,
@ -1084,9 +1068,10 @@ gen6_bind_bo(struct sna *sna,
ss[0] = (GEN6_SURFACE_2D << GEN6_SURFACE_TYPE_SHIFT |
GEN6_SURFACE_BLEND_ENABLED |
format << GEN6_SURFACE_FORMAT_SHIFT);
if (is_dst)
if (is_dst) {
ss[0] |= GEN6_SURFACE_RC_READ_WRITE;
domains = I915_GEM_DOMAIN_RENDER << 16 |I915_GEM_DOMAIN_RENDER;
else
} else
domains = I915_GEM_DOMAIN_SAMPLER << 16;
ss[1] = kgem_add_reloc(&sna->kgem, offset + 1, bo, domains, 0);
ss[2] = ((width - 1) << GEN6_SURFACE_WIDTH_SHIFT |
@ -1095,9 +1080,9 @@ gen6_bind_bo(struct sna *sna,
ss[3] = (gen6_tiling_bits(bo->tiling) |
(bo->pitch - 1) << GEN6_SURFACE_PITCH_SHIFT);
ss[4] = 0;
ss[5] = is_scanout ? 0 : 3 << 16;
ss[5] = (is_scanout || bo->io) ? 0 : 3 << 16;
kgem_bo_set_binding(bo, format | is_scanout << 31, offset);
kgem_bo_set_binding(bo, format | is_dst << 30 | is_scanout << 31, offset);
DBG(("[%x] bind bo(handle=%d, addr=%d), format=%d, width=%d, height=%d, pitch=%d, tiling=%d -> %s\n",
offset, bo->handle, ss[1],
@ -1210,6 +1195,8 @@ inline static int gen6_get_rectangles(struct sna *sna,
{
int rem;
assert(want);
start:
rem = vertex_space(sna);
if (unlikely(rem < op->floats_per_rect)) {
@ -1220,10 +1207,15 @@ start:
goto flush;
}
if (unlikely(sna->render.vertex_offset == 0 &&
!gen6_rectangle_begin(sna, op)))
if (unlikely(sna->render.vertex_offset == 0)) {
if (!gen6_rectangle_begin(sna, op))
goto flush;
else
goto start;
}
assert(rem <= vertex_space(sna));
assert(op->floats_per_rect <= rem);
if (want > 1 && want * op->floats_per_rect > rem)
want = rem / op->floats_per_rect;
@ -1340,7 +1332,6 @@ gen6_align_vertex(struct sna *sna, const struct sna_composite_op *op)
assert((sna->render.vertex_used % op->floats_per_vertex) == 0);
}
fastcall static void
gen6_render_composite_blt(struct sna *sna,
const struct sna_composite_op *op,
@ -1351,7 +1342,6 @@ gen6_render_composite_blt(struct sna *sna,
}
#if 0
fastcall static void
gen6_render_composite_box(struct sna *sna,
const struct sna_composite_op *op,
@ -1462,7 +1452,6 @@ gen6_render_composite_boxes__thread(struct sna *sna,
} while (nbox);
sna_vertex_unlock(&sna->render);
}
#endif
#ifndef MAX
@ -1502,7 +1491,6 @@ gen6_composite_create_blend_state(struct sna_static_stream *stream)
}
#if 0
static uint32_t gen6_bind_video_source(struct sna *sna,
struct kgem_bo *src_bo,
uint32_t src_offset,
@ -1606,21 +1594,24 @@ gen6_render_video(struct sna *sna,
struct sna_video *video,
struct sna_video_frame *frame,
RegionPtr dstRegion,
short src_w, short src_h,
short drw_w, short drw_h,
short dx, short dy,
PixmapPtr pixmap)
{
struct sna_composite_op tmp;
int nbox, pix_xoff, pix_yoff;
int dst_width = dstRegion->extents.x2 - dstRegion->extents.x1;
int dst_height = dstRegion->extents.y2 - dstRegion->extents.y1;
int src_width = frame->src.x2 - frame->src.x1;
int src_height = frame->src.y2 - frame->src.y1;
float src_offset_x, src_offset_y;
float src_scale_x, src_scale_y;
int nbox, pix_xoff, pix_yoff;
struct sna_pixmap *priv;
unsigned filter;
BoxPtr box;
DBG(("%s: src=(%d, %d), dst=(%d, %d), %dx[(%d, %d), (%d, %d)...]\n",
__FUNCTION__, src_w, src_h, drw_w, drw_h,
REGION_NUM_RECTS(dstRegion),
DBG(("%s: src=(%d, %d), dst=(%d, %d), %ldx[(%d, %d), (%d, %d)...]\n",
__FUNCTION__,
src_width, src_height, dst_width, dst_height,
(long)REGION_NUM_RECTS(dstRegion),
REGION_EXTENTS(NULL, dstRegion)->x1,
REGION_EXTENTS(NULL, dstRegion)->y1,
REGION_EXTENTS(NULL, dstRegion)->x2,
@ -1644,7 +1635,7 @@ gen6_render_video(struct sna *sna,
tmp.floats_per_vertex = 3;
tmp.floats_per_rect = 9;
if (src_w == drw_w && src_h == drw_h)
if (src_width == dst_width && src_height == dst_height)
filter = SAMPLER_FILTER_NEAREST;
else
filter = SAMPLER_FILTER_BILINEAR;
@ -1680,9 +1671,11 @@ gen6_render_video(struct sna *sna,
pix_yoff = 0;
#endif
/* Use normalized texture coordinates */
src_scale_x = ((float)src_w / frame->width) / (float)drw_w;
src_scale_y = ((float)src_h / frame->height) / (float)drw_h;
src_scale_x = (float)src_width / dst_width / frame->width;
src_offset_x = (float)frame->src.x1 / frame->width - dstRegion->extents.x1 * src_scale_x;
src_scale_y = (float)src_height / dst_height / frame->height;
src_offset_y = (float)frame->src.y1 / frame->height - dstRegion->extents.y1 * src_scale_y;
box = REGION_RECTS(dstRegion);
nbox = REGION_NUM_RECTS(dstRegion);
@ -1697,16 +1690,16 @@ gen6_render_video(struct sna *sna,
gen6_get_rectangles(sna, &tmp, 1, gen6_emit_video_state);
OUT_VERTEX(r.x2, r.y2);
OUT_VERTEX_F((box->x2 - dx) * src_scale_x);
OUT_VERTEX_F((box->y2 - dy) * src_scale_y);
OUT_VERTEX_F(box->x2 * src_scale_x + src_offset_x);
OUT_VERTEX_F(box->y2 * src_scale_y + src_offset_y);
OUT_VERTEX(r.x1, r.y2);
OUT_VERTEX_F((box->x1 - dx) * src_scale_x);
OUT_VERTEX_F((box->y2 - dy) * src_scale_y);
OUT_VERTEX_F(box->x1 * src_scale_x + src_offset_x);
OUT_VERTEX_F(box->y2 * src_scale_y + src_offset_y);
OUT_VERTEX(r.x1, r.y1);
OUT_VERTEX_F((box->x1 - dx) * src_scale_x);
OUT_VERTEX_F((box->y1 - dy) * src_scale_y);
OUT_VERTEX_F(box->x1 * src_scale_x + src_offset_x);
OUT_VERTEX_F(box->y1 * src_scale_y + src_offset_y);
if (!DAMAGE_IS_ALL(priv->gpu_damage)) {
sna_damage_add_box(&priv->gpu_damage, &r);
@ -1714,7 +1707,6 @@ gen6_render_video(struct sna *sna,
}
box++;
}
priv->clear = false;
gen4_vertex_flush(sna);
return true;
@ -1822,7 +1814,6 @@ inline static void gen6_composite_channel_convert(struct sna_composite_channel *
channel->card_format = gen6_get_card_format(channel->pict_format);
assert(channel->card_format != (unsigned)-1);
}
#endif
static void gen6_render_composite_done(struct sna *sna,
@ -1837,16 +1828,15 @@ static void gen6_render_composite_done(struct sna *sna,
}
// sna_render_composite_redirect_done(sna, op);
}
#if 0
static bool
gen6_composite_set_target(struct sna *sna,
struct sna_composite_op *op,
PicturePtr dst,
int x, int y, int w, int h)
int x, int y, int w, int h,
bool partial)
{
BoxRec box;
@ -1889,6 +1879,22 @@ gen6_composite_set_target(struct sna *sna,
return true;
}
static bool
prefer_blt_composite(struct sna *sna, struct sna_composite_op *tmp)
{
if (untiled_tlb_miss(tmp->dst.bo) ||
untiled_tlb_miss(tmp->src.bo))
return true;
if (kgem_bo_is_render(tmp->dst.bo) ||
kgem_bo_is_render(tmp->src.bo))
return false;
if (!prefer_blt_ring(sna, tmp->dst.bo, 0))
return false;
return prefer_blt_bo(sna, tmp->dst.bo) || prefer_blt_bo(sna, tmp->src.bo);
}
static bool
gen6_render_composite(struct sna *sna,
@ -1908,11 +1914,33 @@ gen6_render_composite(struct sna *sna,
DBG(("%s: %dx%d, current mode=%d\n", __FUNCTION__,
width, height, sna->kgem.ring));
if (mask == NULL &&
try_blt(sna, dst, src, width, height) &&
sna_blt_composite(sna, op,
src, dst,
src_x, src_y,
dst_x, dst_y,
width, height,
tmp, false))
return true;
if (gen6_composite_fallback(sna, src, mask, dst))
return false;
if (need_tiling(sna, width, height))
return sna_tiling_composite(op, src, mask, dst,
src_x, src_y,
msk_x, msk_y,
dst_x, dst_y,
width, height,
tmp);
if (op == PictOpClear)
op = PictOpSrc;
tmp->op = op;
if (!gen6_composite_set_target(sna, tmp, dst,
dst_x, dst_y, width, height))
dst_x, dst_y, width, height,
op > PictOpSrc || dst->pCompositeClip->data))
return false;
switch (gen6_composite_picture(sna, src, &tmp->src,
@ -2000,15 +2028,15 @@ gen6_render_composite(struct sna *sna,
tmp->mask.bo != NULL,
tmp->has_component_alpha,
tmp->is_affine),
gen4_choose_composite_emitter(tmp));
gen4_choose_composite_emitter(sna, tmp));
// tmp->blt = gen6_render_composite_blt;
// tmp->box = gen6_render_composite_box;
// tmp->boxes = gen6_render_composite_boxes__blt;
// if (tmp->emit_boxes) {
// tmp->boxes = gen6_render_composite_boxes;
// tmp->thread_boxes = gen6_render_composite_boxes__thread;
// }
tmp->blt = gen6_render_composite_blt;
tmp->box = gen6_render_composite_box;
tmp->boxes = gen6_render_composite_boxes__blt;
if (tmp->emit_boxes) {
tmp->boxes = gen6_render_composite_boxes;
tmp->thread_boxes = gen6_render_composite_boxes__thread;
}
tmp->done = gen6_render_composite_done;
kgem_set_mode(&sna->kgem, KGEM_RENDER, tmp->dst.bo);
@ -2039,7 +2067,6 @@ cleanup_dst:
return false;
}
#if !NO_COMPOSITE_SPANS
fastcall static void
gen6_render_composite_spans_box(struct sna *sna,
@ -2207,7 +2234,7 @@ gen6_render_composite_spans(struct sna *sna,
tmp->base.op = op;
if (!gen6_composite_set_target(sna, &tmp->base, dst,
dst_x, dst_y, width, height))
dst_x, dst_y, width, height, true))
return false;
switch (gen6_composite_picture(sna, src, &tmp->base.src,
@ -2237,7 +2264,7 @@ gen6_render_composite_spans(struct sna *sna,
SAMPLER_EXTEND_PAD),
gen6_get_blend(tmp->base.op, false, tmp->base.dst.format),
GEN6_WM_KERNEL_OPACITY | !tmp->base.is_affine,
gen4_choose_spans_emitter(tmp));
gen4_choose_spans_emitter(sna, tmp));
tmp->box = gen6_render_composite_spans_box;
tmp->boxes = gen6_render_composite_spans_boxes;
@ -2271,7 +2298,6 @@ cleanup_dst:
}
#endif
static void
gen6_emit_copy_state(struct sna *sna,
const struct sna_composite_op *op)
@ -2304,7 +2330,6 @@ gen6_emit_copy_state(struct sna *sna,
gen6_emit_state(sna, op, offset | dirty);
}
static inline bool prefer_blt_copy(struct sna *sna,
struct kgem_bo *src_bo,
struct kgem_bo *dst_bo,
@ -2326,11 +2351,14 @@ static inline bool prefer_blt_copy(struct sna *sna,
untiled_tlb_miss(dst_bo))
return true;
if (kgem_bo_is_render(dst_bo) ||
kgem_bo_is_render(src_bo))
return false;
if (!prefer_blt_ring(sna, dst_bo, flags))
return false;
return (prefer_blt_bo(sna, src_bo) >= 0 &&
prefer_blt_bo(sna, dst_bo) > 0);
return prefer_blt_bo(sna, src_bo) || prefer_blt_bo(sna, dst_bo);
}
inline static void boxes_extents(const BoxRec *box, int n, BoxRec *extents)
@ -2464,7 +2492,8 @@ fallback_blt:
extents.x1 + dst_dx,
extents.y1 + dst_dy,
extents.x2 - extents.x1,
extents.y2 - extents.y1))
extents.y2 - extents.y1,
n > 1))
goto fallback_tiled;
dst_dx += tmp.dst.x;
@ -2479,14 +2508,14 @@ fallback_blt:
extents = box[0];
for (i = 1; i < n; i++) {
if (extents.x1 < box[i].x1)
if (box[i].x1 < extents.x1)
extents.x1 = box[i].x1;
if (extents.y1 < box[i].y1)
if (box[i].y1 < extents.y1)
extents.y1 = box[i].y1;
if (extents.x2 > box[i].x2)
if (box[i].x2 > extents.x2)
extents.x2 = box[i].x2;
if (extents.y2 > box[i].y2)
if (box[i].y2 > extents.y2)
extents.y2 = box[i].y2;
}
@ -2632,10 +2661,35 @@ gen6_render_copy(struct sna *sna, uint8_t alu,
src->drawable.width, src->drawable.height,
dst->drawable.width, dst->drawable.height));
fallback:
if (prefer_blt_copy(sna, src_bo, dst_bo, 0) &&
sna_blt_compare_depth(&src->drawable, &dst->drawable) &&
sna_blt_copy(sna, alu,
src_bo, dst_bo,
dst->drawable.bitsPerPixel,
op))
return true;
op->base.dst.format = PIXMAN_a8r8g8b8;
if (!(alu == GXcopy || alu == GXclear) || src_bo == dst_bo ||
too_large(src->drawable.width, src->drawable.height) ||
too_large(dst->drawable.width, dst->drawable.height)) {
fallback:
if (!sna_blt_compare_depth(&src->drawable, &dst->drawable))
return false;
return sna_blt_copy(sna, alu, src_bo, dst_bo,
dst->drawable.bitsPerPixel,
op);
}
if (dst->drawable.depth == src->drawable.depth) {
op->base.dst.format = sna_render_format_for_depth(dst->drawable.depth);
op->base.src.pict_format = op->base.dst.format;
} else {
op->base.dst.format = sna_format_for_depth(dst->drawable.depth);
op->base.src.pict_format = sna_format_for_depth(src->drawable.depth);
}
if (!gen6_check_format(op->base.src.pict_format))
goto fallback;
op->base.dst.pixmap = dst;
op->base.dst.width = dst->drawable.width;
@ -2675,119 +2729,7 @@ fallback:
}
#endif
static bool
gen6_blit_tex(struct sna *sna,
uint8_t op, bool scale,
PixmapPtr src, struct kgem_bo *src_bo,
PixmapPtr mask,struct kgem_bo *mask_bo,
PixmapPtr dst, struct kgem_bo *dst_bo,
int32_t src_x, int32_t src_y,
int32_t msk_x, int32_t msk_y,
int32_t dst_x, int32_t dst_y,
int32_t width, int32_t height,
struct sna_composite_op *tmp)
{
DBG(("%s: %dx%d, current mode=%d\n", __FUNCTION__,
width, height, sna->kgem.ring));
tmp->op = PictOpSrc;
tmp->dst.pixmap = dst;
tmp->dst.bo = dst_bo;
tmp->dst.width = dst->drawable.width;
tmp->dst.height = dst->drawable.height;
tmp->dst.format = PICT_x8r8g8b8;
tmp->src.repeat = SAMPLER_EXTEND_NONE;
tmp->src.is_affine = true;
tmp->src.bo = src_bo;
tmp->src.pict_format = PICT_x8r8g8b8;
tmp->src.card_format = gen6_get_card_format(tmp->src.pict_format);
tmp->src.width = src->drawable.width;
tmp->src.height = src->drawable.height;
if ( (tmp->src.width == width) &&
(tmp->src.height == height) )
tmp->src.filter = SAMPLER_FILTER_NEAREST;
else
tmp->src.filter = SAMPLER_FILTER_BILINEAR;
tmp->is_affine = tmp->src.is_affine;
tmp->has_component_alpha = false;
tmp->need_magic_ca_pass = false;
tmp->mask.repeat = SAMPLER_EXTEND_NONE;
tmp->mask.filter = SAMPLER_FILTER_NEAREST;
tmp->mask.is_affine = true;
tmp->mask.bo = mask_bo;
tmp->mask.pict_format = PIXMAN_a8;
tmp->mask.card_format = gen6_get_card_format(tmp->mask.pict_format);
tmp->mask.width = mask->drawable.width;
tmp->mask.height = mask->drawable.height;
if( scale )
{
tmp->src.scale[0] = 1.f/width;
tmp->src.scale[1] = 1.f/height;
}
else
{
tmp->src.scale[0] = 1.f/src->drawable.width;
tmp->src.scale[1] = 1.f/src->drawable.height;
}
// tmp->src.offset[0] = -dst_x;
// tmp->src.offset[1] = -dst_y;
tmp->mask.scale[0] = 1.f/mask->drawable.width;
tmp->mask.scale[1] = 1.f/mask->drawable.height;
// tmp->mask.offset[0] = -dst_x;
// tmp->mask.offset[1] = -dst_y;
tmp->u.gen6.flags =
GEN6_SET_FLAGS(SAMPLER_OFFSET(tmp->src.filter,
tmp->src.repeat,
tmp->mask.filter,
tmp->mask.repeat),
gen6_get_blend(tmp->op,
tmp->has_component_alpha,
tmp->dst.format),
/* gen6_choose_composite_kernel(tmp->op,
tmp->mask.bo != NULL,
tmp->has_component_alpha,
tmp->is_affine),
*/
GEN6_WM_KERNEL_MASK,
gen4_choose_composite_emitter(tmp));
tmp->blt = gen6_render_composite_blt;
// tmp->box = gen6_render_composite_box;
tmp->done = gen6_render_composite_done;
kgem_set_mode(&sna->kgem, KGEM_RENDER, tmp->dst.bo);
if (!kgem_check_bo(&sna->kgem,
tmp->dst.bo, tmp->src.bo, tmp->mask.bo,
NULL)) {
kgem_submit(&sna->kgem);
_kgem_set_mode(&sna->kgem, KGEM_RENDER);
}
gen6_emit_composite_state(sna, tmp);
gen6_align_vertex(sna, tmp);
return true;
}
#if 0
static void
gen6_emit_fill_state(struct sna *sna, const struct sna_composite_op *op)
{
@ -2826,10 +2768,16 @@ static inline bool prefer_blt_fill(struct sna *sna,
if (PREFER_RENDER)
return PREFER_RENDER < 0;
if (kgem_bo_is_render(bo))
return false;
if (untiled_tlb_miss(bo))
return true;
return prefer_blt_ring(sna, bo, 0) || prefer_blt_bo(sna, bo) >= 0;
if (!prefer_blt_ring(sna, bo, 0))
return false;
return prefer_blt_bo(sna, bo);
}
static bool
@ -2910,7 +2858,8 @@ gen6_render_fill_boxes(struct sna *sna,
if (!sna_render_composite_redirect(sna, &tmp,
extents.x1, extents.y1,
extents.x2 - extents.x1,
extents.y2 - extents.y1))
extents.y2 - extents.y1,
n > 1))
return sna_tiling_fill_boxes(sna, op, format, color,
dst, dst_bo, box, n);
}
@ -3385,12 +3334,12 @@ static void gen6_render_fini(struct sna *sna)
static bool is_gt2(struct sna *sna)
{
return DEVICE_ID(sna->PciInfo) & 0x30;
return sna->PciInfo->device_id & 0x30;
}
static bool is_mobile(struct sna *sna)
{
return (DEVICE_ID(sna->PciInfo) & 0xf) == 0x6;
return (sna->PciInfo->device_id & 0xf) == 0x6;
}
static bool gen6_render_setup(struct sna *sna)
@ -3471,38 +3420,166 @@ static bool gen6_render_setup(struct sna *sna)
return state->general_bo != NULL;
}
bool gen6_render_init(struct sna *sna)
const char *gen6_render_init(struct sna *sna, const char *backend)
{
if (!gen6_render_setup(sna))
return false;
return backend;
sna->kgem.context_switch = gen6_render_context_switch;
sna->kgem.retire = gen6_render_retire;
sna->kgem.expire = gen6_render_expire;
// sna->render.composite = gen6_render_composite;
// sna->render.video = gen6_render_video;
#if 0
#if !NO_COMPOSITE
sna->render.composite = gen6_render_composite;
sna->render.prefer_gpu |= PREFER_GPU_RENDER;
#endif
// sna->render.copy_boxes = gen6_render_copy_boxes;
#if !NO_COMPOSITE_SPANS
sna->render.check_composite_spans = gen6_check_composite_spans;
sna->render.composite_spans = gen6_render_composite_spans;
if (is_mobile(sna))
sna->render.prefer_gpu |= PREFER_GPU_SPANS;
#endif
sna->render.video = gen6_render_video;
#if !NO_COPY_BOXES
sna->render.copy_boxes = gen6_render_copy_boxes;
#endif
#if !NO_COPY
sna->render.copy = gen6_render_copy;
#endif
#if !NO_FILL_BOXES
sna->render.fill_boxes = gen6_render_fill_boxes;
#endif
#if !NO_FILL
sna->render.fill = gen6_render_fill;
#endif
#if !NO_FILL_ONE
sna->render.fill_one = gen6_render_fill_one;
#endif
#if !NO_FILL_CLEAR
sna->render.clear = gen6_render_clear;
#endif
#endif
sna->render.caps = HW_BIT_BLIT | HW_TEX_BLIT;
sna->render.blit_tex = gen6_blit_tex;
// sna->render.copy = gen6_render_copy;
// sna->render.fill_boxes = gen6_render_fill_boxes;
// sna->render.fill = gen6_render_fill;
// sna->render.fill_one = gen6_render_fill_one;
// sna->render.clear = gen6_render_clear;
sna->render.flush = gen6_render_flush;
sna->render.reset = gen6_render_reset;
sna->render.fini = gen6_render_fini;
sna->render.max_3d_size = GEN6_MAX_SIZE;
sna->render.max_3d_pitch = 1 << 18;
sna->render.caps = HW_BIT_BLIT | HW_TEX_BLIT;
return true;
return sna->render_state.gen6.info->name;
}
static bool
gen6_blit_tex(struct sna *sna,
uint8_t op, bool scale,
PixmapPtr src, struct kgem_bo *src_bo,
PixmapPtr mask,struct kgem_bo *mask_bo,
PixmapPtr dst, struct kgem_bo *dst_bo,
int32_t src_x, int32_t src_y,
int32_t msk_x, int32_t msk_y,
int32_t dst_x, int32_t dst_y,
int32_t width, int32_t height,
struct sna_composite_op *tmp)
{
DBG(("%s: %dx%d, current mode=%d\n", __FUNCTION__,
width, height, sna->kgem.ring));
tmp->op = PictOpSrc;
tmp->dst.pixmap = dst;
tmp->dst.bo = dst_bo;
tmp->dst.width = dst->drawable.width;
tmp->dst.height = dst->drawable.height;
tmp->dst.format = PICT_x8r8g8b8;
tmp->src.repeat = SAMPLER_EXTEND_NONE;
tmp->src.is_affine = true;
tmp->src.bo = src_bo;
tmp->src.pict_format = PICT_x8r8g8b8;
tmp->src.card_format = gen6_get_card_format(tmp->src.pict_format);
tmp->src.width = src->drawable.width;
tmp->src.height = src->drawable.height;
if ( (tmp->src.width == width) &&
(tmp->src.height == height) )
tmp->src.filter = SAMPLER_FILTER_NEAREST;
else
tmp->src.filter = SAMPLER_FILTER_BILINEAR;
tmp->is_affine = tmp->src.is_affine;
tmp->has_component_alpha = false;
tmp->need_magic_ca_pass = false;
tmp->mask.repeat = SAMPLER_EXTEND_NONE;
tmp->mask.filter = SAMPLER_FILTER_NEAREST;
tmp->mask.is_affine = true;
tmp->mask.bo = mask_bo;
tmp->mask.pict_format = PIXMAN_a8;
tmp->mask.card_format = gen6_get_card_format(tmp->mask.pict_format);
tmp->mask.width = mask->drawable.width;
tmp->mask.height = mask->drawable.height;
if( scale )
{
tmp->src.scale[0] = 1.f/width;
tmp->src.scale[1] = 1.f/height;
}
else
{
tmp->src.scale[0] = 1.f/src->drawable.width;
tmp->src.scale[1] = 1.f/src->drawable.height;
}
// tmp->src.offset[0] = -dst_x;
// tmp->src.offset[1] = -dst_y;
tmp->mask.scale[0] = 1.f/mask->drawable.width;
tmp->mask.scale[1] = 1.f/mask->drawable.height;
// tmp->mask.offset[0] = -dst_x;
// tmp->mask.offset[1] = -dst_y;
tmp->u.gen6.flags =
GEN6_SET_FLAGS(SAMPLER_OFFSET(tmp->src.filter,
tmp->src.repeat,
tmp->mask.filter,
tmp->mask.repeat),
gen6_get_blend(tmp->op,
tmp->has_component_alpha,
tmp->dst.format),
/* gen6_choose_composite_kernel(tmp->op,
tmp->mask.bo != NULL,
tmp->has_component_alpha,
tmp->is_affine),
*/
GEN6_WM_KERNEL_MASK,
gen4_choose_composite_emitter(sna, tmp));
tmp->blt = gen6_render_composite_blt;
// tmp->box = gen6_render_composite_box;
tmp->done = gen6_render_composite_done;
kgem_set_mode(&sna->kgem, KGEM_RENDER, tmp->dst.bo);
if (!kgem_check_bo(&sna->kgem,
tmp->dst.bo, tmp->src.bo, tmp->mask.bo,
NULL)) {
kgem_submit(&sna->kgem);
_kgem_set_mode(&sna->kgem, KGEM_RENDER);
}
gen6_emit_composite_state(sna, tmp);
gen6_align_vertex(sna, tmp);
return true;
}

File diff suppressed because it is too large Load Diff

View File

@ -1224,6 +1224,8 @@ struct gen7_sampler_state {
/* Surface state DW0 */
#define GEN7_SURFACE_RC_READ_WRITE (1 << 8)
#define GEN7_SURFACE_VALIGN_4 (1 << 16)
#define GEN7_SURFACE_HALIGN_8 (1 << 15)
#define GEN7_SURFACE_TILED (1 << 14)
#define GEN7_SURFACE_TILED_Y (1 << 13)
#define GEN7_SURFACE_FORMAT_SHIFT 18

View File

@ -0,0 +1,211 @@
/*
* Copyright 2013 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 NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS 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.
*/
#ifndef _I915_PCIIDS_H
#define _I915_PCIIDS_H
/*
* A pci_device_id struct {
* __u32 vendor, device;
* __u32 subvendor, subdevice;
* __u32 class, class_mask;
* kernel_ulong_t driver_data;
* };
* Don't use C99 here because "class" is reserved and we want to
* give userspace flexibility.
*/
#define INTEL_VGA_DEVICE(id, info) { \
0x8086, id, \
~0, ~0, \
0x030000, 0xff0000, \
(unsigned long) info }
#define INTEL_QUANTA_VGA_DEVICE(info) { \
0x8086, 0x16a, \
0x152d, 0x8990, \
0x030000, 0xff0000, \
(unsigned long) info }
#define INTEL_I830_IDS(info) \
INTEL_VGA_DEVICE(0x3577, info)
#define INTEL_I845G_IDS(info) \
INTEL_VGA_DEVICE(0x2562, info)
#define INTEL_I85X_IDS(info) \
INTEL_VGA_DEVICE(0x3582, info), /* I855_GM */ \
INTEL_VGA_DEVICE(0x358e, info)
#define INTEL_I865G_IDS(info) \
INTEL_VGA_DEVICE(0x2572, info) /* I865_G */
#define INTEL_I915G_IDS(info) \
INTEL_VGA_DEVICE(0x2582, info), /* I915_G */ \
INTEL_VGA_DEVICE(0x258a, info) /* E7221_G */
#define INTEL_I915GM_IDS(info) \
INTEL_VGA_DEVICE(0x2592, info) /* I915_GM */
#define INTEL_I945G_IDS(info) \
INTEL_VGA_DEVICE(0x2772, info) /* I945_G */
#define INTEL_I945GM_IDS(info) \
INTEL_VGA_DEVICE(0x27a2, info), /* I945_GM */ \
INTEL_VGA_DEVICE(0x27ae, info) /* I945_GME */
#define INTEL_I965G_IDS(info) \
INTEL_VGA_DEVICE(0x2972, info), /* I946_GZ */ \
INTEL_VGA_DEVICE(0x2982, info), /* G35_G */ \
INTEL_VGA_DEVICE(0x2992, info), /* I965_Q */ \
INTEL_VGA_DEVICE(0x29a2, info) /* I965_G */
#define INTEL_G33_IDS(info) \
INTEL_VGA_DEVICE(0x29b2, info), /* Q35_G */ \
INTEL_VGA_DEVICE(0x29c2, info), /* G33_G */ \
INTEL_VGA_DEVICE(0x29d2, info) /* Q33_G */
#define INTEL_I965GM_IDS(info) \
INTEL_VGA_DEVICE(0x2a02, info), /* I965_GM */ \
INTEL_VGA_DEVICE(0x2a12, info) /* I965_GME */
#define INTEL_GM45_IDS(info) \
INTEL_VGA_DEVICE(0x2a42, info) /* GM45_G */
#define INTEL_G45_IDS(info) \
INTEL_VGA_DEVICE(0x2e02, info), /* IGD_E_G */ \
INTEL_VGA_DEVICE(0x2e12, info), /* Q45_G */ \
INTEL_VGA_DEVICE(0x2e22, info), /* G45_G */ \
INTEL_VGA_DEVICE(0x2e32, info), /* G41_G */ \
INTEL_VGA_DEVICE(0x2e42, info), /* B43_G */ \
INTEL_VGA_DEVICE(0x2e92, info) /* B43_G.1 */
#define INTEL_PINEVIEW_IDS(info) \
INTEL_VGA_DEVICE(0xa001, info), \
INTEL_VGA_DEVICE(0xa011, info)
#define INTEL_IRONLAKE_D_IDS(info) \
INTEL_VGA_DEVICE(0x0042, info)
#define INTEL_IRONLAKE_M_IDS(info) \
INTEL_VGA_DEVICE(0x0046, info)
#define INTEL_SNB_D_IDS(info) \
INTEL_VGA_DEVICE(0x0102, info), \
INTEL_VGA_DEVICE(0x0112, info), \
INTEL_VGA_DEVICE(0x0122, info), \
INTEL_VGA_DEVICE(0x010A, info)
#define INTEL_SNB_M_IDS(info) \
INTEL_VGA_DEVICE(0x0106, info), \
INTEL_VGA_DEVICE(0x0116, info), \
INTEL_VGA_DEVICE(0x0126, info)
#define INTEL_IVB_M_IDS(info) \
INTEL_VGA_DEVICE(0x0156, info), /* GT1 mobile */ \
INTEL_VGA_DEVICE(0x0166, info) /* GT2 mobile */
#define INTEL_IVB_D_IDS(info) \
INTEL_VGA_DEVICE(0x0152, info), /* GT1 desktop */ \
INTEL_VGA_DEVICE(0x0162, info), /* GT2 desktop */ \
INTEL_VGA_DEVICE(0x015a, info), /* GT1 server */ \
INTEL_VGA_DEVICE(0x016a, info) /* GT2 server */
#define INTEL_IVB_Q_IDS(info) \
INTEL_QUANTA_VGA_DEVICE(info) /* Quanta transcode */
#define INTEL_HSW_D_IDS(info) \
INTEL_VGA_DEVICE(0x0402, info), /* GT1 desktop */ \
INTEL_VGA_DEVICE(0x0412, info), /* GT2 desktop */ \
INTEL_VGA_DEVICE(0x0422, info), /* GT3 desktop */ \
INTEL_VGA_DEVICE(0x040a, info), /* GT1 server */ \
INTEL_VGA_DEVICE(0x041a, info), /* GT2 server */ \
INTEL_VGA_DEVICE(0x042a, info), /* GT3 server */ \
INTEL_VGA_DEVICE(0x040B, info), /* GT1 reserved */ \
INTEL_VGA_DEVICE(0x041B, info), /* GT2 reserved */ \
INTEL_VGA_DEVICE(0x042B, info), /* GT3 reserved */ \
INTEL_VGA_DEVICE(0x040E, info), /* GT1 reserved */ \
INTEL_VGA_DEVICE(0x041E, info), /* GT2 reserved */ \
INTEL_VGA_DEVICE(0x042E, info), /* GT3 reserved */ \
INTEL_VGA_DEVICE(0x0C02, info), /* SDV GT1 desktop */ \
INTEL_VGA_DEVICE(0x0C12, info), /* SDV GT2 desktop */ \
INTEL_VGA_DEVICE(0x0C22, info), /* SDV GT3 desktop */ \
INTEL_VGA_DEVICE(0x0C0A, info), /* SDV GT1 server */ \
INTEL_VGA_DEVICE(0x0C1A, info), /* SDV GT2 server */ \
INTEL_VGA_DEVICE(0x0C2A, info), /* SDV GT3 server */ \
INTEL_VGA_DEVICE(0x0C0B, info), /* SDV GT1 reserved */ \
INTEL_VGA_DEVICE(0x0C1B, info), /* SDV GT2 reserved */ \
INTEL_VGA_DEVICE(0x0C2B, info), /* SDV GT3 reserved */ \
INTEL_VGA_DEVICE(0x0C0E, info), /* SDV GT1 reserved */ \
INTEL_VGA_DEVICE(0x0C1E, info), /* SDV GT2 reserved */ \
INTEL_VGA_DEVICE(0x0C2E, info), /* SDV GT3 reserved */ \
INTEL_VGA_DEVICE(0x0A02, info), /* ULT GT1 desktop */ \
INTEL_VGA_DEVICE(0x0A12, info), /* ULT GT2 desktop */ \
INTEL_VGA_DEVICE(0x0A22, info), /* ULT GT3 desktop */ \
INTEL_VGA_DEVICE(0x0A0A, info), /* ULT GT1 server */ \
INTEL_VGA_DEVICE(0x0A1A, info), /* ULT GT2 server */ \
INTEL_VGA_DEVICE(0x0A2A, info), /* ULT GT3 server */ \
INTEL_VGA_DEVICE(0x0A0B, info), /* ULT GT1 reserved */ \
INTEL_VGA_DEVICE(0x0A1B, info), /* ULT GT2 reserved */ \
INTEL_VGA_DEVICE(0x0A2B, info), /* ULT GT3 reserved */ \
INTEL_VGA_DEVICE(0x0D02, info), /* CRW GT1 desktop */ \
INTEL_VGA_DEVICE(0x0D12, info), /* CRW GT2 desktop */ \
INTEL_VGA_DEVICE(0x0D22, info), /* CRW GT3 desktop */ \
INTEL_VGA_DEVICE(0x0D0A, info), /* CRW GT1 server */ \
INTEL_VGA_DEVICE(0x0D1A, info), /* CRW GT2 server */ \
INTEL_VGA_DEVICE(0x0D2A, info), /* CRW GT3 server */ \
INTEL_VGA_DEVICE(0x0D0B, info), /* CRW GT1 reserved */ \
INTEL_VGA_DEVICE(0x0D1B, info), /* CRW GT2 reserved */ \
INTEL_VGA_DEVICE(0x0D2B, info), /* CRW GT3 reserved */ \
INTEL_VGA_DEVICE(0x0D0E, info), /* CRW GT1 reserved */ \
INTEL_VGA_DEVICE(0x0D1E, info), /* CRW GT2 reserved */ \
INTEL_VGA_DEVICE(0x0D2E, info) /* CRW GT3 reserved */ \
#define INTEL_HSW_M_IDS(info) \
INTEL_VGA_DEVICE(0x0406, info), /* GT1 mobile */ \
INTEL_VGA_DEVICE(0x0416, info), /* GT2 mobile */ \
INTEL_VGA_DEVICE(0x0426, info), /* GT2 mobile */ \
INTEL_VGA_DEVICE(0x0C06, info), /* SDV GT1 mobile */ \
INTEL_VGA_DEVICE(0x0C16, info), /* SDV GT2 mobile */ \
INTEL_VGA_DEVICE(0x0C26, info), /* SDV GT3 mobile */ \
INTEL_VGA_DEVICE(0x0A06, info), /* ULT GT1 mobile */ \
INTEL_VGA_DEVICE(0x0A16, info), /* ULT GT2 mobile */ \
INTEL_VGA_DEVICE(0x0A26, info), /* ULT GT3 mobile */ \
INTEL_VGA_DEVICE(0x0A0E, info), /* ULT GT1 reserved */ \
INTEL_VGA_DEVICE(0x0A1E, info), /* ULT GT2 reserved */ \
INTEL_VGA_DEVICE(0x0A2E, info), /* ULT GT3 reserved */ \
INTEL_VGA_DEVICE(0x0D06, info), /* CRW GT1 mobile */ \
INTEL_VGA_DEVICE(0x0D16, info), /* CRW GT2 mobile */ \
INTEL_VGA_DEVICE(0x0D26, info) /* CRW GT3 mobile */
#define INTEL_VLV_M_IDS(info) \
INTEL_VGA_DEVICE(0x0f30, info), \
INTEL_VGA_DEVICE(0x0f31, info), \
INTEL_VGA_DEVICE(0x0f32, info), \
INTEL_VGA_DEVICE(0x0f33, info), \
INTEL_VGA_DEVICE(0x0157, info)
#define INTEL_VLV_D_IDS(info) \
INTEL_VGA_DEVICE(0x0155, info)
#endif /* _I915_PCIIDS_H */

View File

@ -9,180 +9,52 @@
#define INTEL_VERSION_MINOR PACKAGE_VERSION_MINOR
#define INTEL_VERSION_PATCH PACKAGE_VERSION_PATCHLEVEL
#ifndef PCI_CHIP_I810
#define PCI_CHIP_I810 0x7121
#define PCI_CHIP_I810_DC100 0x7123
#define PCI_CHIP_I810_E 0x7125
#define PCI_CHIP_I815 0x1132
#define PCI_CHIP_I810_BRIDGE 0x7120
#define PCI_CHIP_I810_DC100_BRIDGE 0x7122
#define PCI_CHIP_I810_E_BRIDGE 0x7124
#define PCI_CHIP_I815_BRIDGE 0x1130
#endif
#ifndef PCI_CHIP_I830_M
#define PCI_CHIP_I830_M 0x3577
#define PCI_CHIP_I830_M_BRIDGE 0x3575
#endif
#ifndef PCI_CHIP_845_G
#define PCI_CHIP_845_G 0x2562
#define PCI_CHIP_845_G_BRIDGE 0x2560
#endif
#ifndef PCI_CHIP_I854
#define PCI_CHIP_I854 0x358E
#define PCI_CHIP_I854_BRIDGE 0x358C
#endif
#ifndef PCI_CHIP_I855_GM
#define PCI_CHIP_I855_GM 0x3582
#define PCI_CHIP_I855_GM_BRIDGE 0x3580
#endif
#ifndef PCI_CHIP_I865_G
#define PCI_CHIP_I865_G 0x2572
#define PCI_CHIP_I865_G_BRIDGE 0x2570
#endif
#ifndef PCI_CHIP_I915_G
#define PCI_CHIP_I915_G 0x2582
#define PCI_CHIP_I915_G_BRIDGE 0x2580
#endif
#ifndef PCI_CHIP_I915_GM
#define PCI_CHIP_I915_GM 0x2592
#define PCI_CHIP_I915_GM_BRIDGE 0x2590
#endif
#ifndef PCI_CHIP_E7221_G
#define PCI_CHIP_E7221_G 0x258A
/* Same as I915_G_BRIDGE */
#define PCI_CHIP_E7221_G_BRIDGE 0x2580
#endif
#ifndef PCI_CHIP_I945_G
#define PCI_CHIP_I945_G 0x2772
#define PCI_CHIP_I945_G_BRIDGE 0x2770
#endif
#ifndef PCI_CHIP_I945_GM
#define PCI_CHIP_I945_GM 0x27A2
#define PCI_CHIP_I945_GM_BRIDGE 0x27A0
#endif
#ifndef PCI_CHIP_I945_GME
#define PCI_CHIP_I945_GME 0x27AE
#define PCI_CHIP_I945_GME_BRIDGE 0x27AC
#endif
#ifndef PCI_CHIP_PINEVIEW_M
#define PCI_CHIP_PINEVIEW_M 0xA011
#define PCI_CHIP_PINEVIEW_M_BRIDGE 0xA010
#define PCI_CHIP_PINEVIEW_G 0xA001
#define PCI_CHIP_PINEVIEW_G_BRIDGE 0xA000
#endif
#ifndef PCI_CHIP_G35_G
#define PCI_CHIP_G35_G 0x2982
#define PCI_CHIP_G35_G_BRIDGE 0x2980
#endif
#ifndef PCI_CHIP_I965_Q
#define PCI_CHIP_I965_Q 0x2992
#define PCI_CHIP_I965_Q_BRIDGE 0x2990
#endif
#ifndef PCI_CHIP_I965_G
#define PCI_CHIP_I965_G 0x29A2
#define PCI_CHIP_I965_G_BRIDGE 0x29A0
#endif
#ifndef PCI_CHIP_I946_GZ
#define PCI_CHIP_I946_GZ 0x2972
#define PCI_CHIP_I946_GZ_BRIDGE 0x2970
#endif
#ifndef PCI_CHIP_I965_GM
#define PCI_CHIP_I965_GM 0x2A02
#define PCI_CHIP_I965_GM_BRIDGE 0x2A00
#endif
#ifndef PCI_CHIP_I965_GME
#define PCI_CHIP_I965_GME 0x2A12
#define PCI_CHIP_I965_GME_BRIDGE 0x2A10
#endif
#ifndef PCI_CHIP_G33_G
#define PCI_CHIP_G33_G 0x29C2
#define PCI_CHIP_G33_G_BRIDGE 0x29C0
#endif
#ifndef PCI_CHIP_Q35_G
#define PCI_CHIP_Q35_G 0x29B2
#define PCI_CHIP_Q35_G_BRIDGE 0x29B0
#endif
#ifndef PCI_CHIP_Q33_G
#define PCI_CHIP_G33_G 0x29C2
#define PCI_CHIP_Q33_G 0x29D2
#define PCI_CHIP_Q33_G_BRIDGE 0x29D0
#endif
#ifndef PCI_CHIP_GM45_GM
#define PCI_CHIP_G35_G 0x2982
#define PCI_CHIP_I965_Q 0x2992
#define PCI_CHIP_I965_G 0x29A2
#define PCI_CHIP_I946_GZ 0x2972
#define PCI_CHIP_I965_GM 0x2A02
#define PCI_CHIP_I965_GME 0x2A12
#define PCI_CHIP_GM45_GM 0x2A42
#define PCI_CHIP_GM45_BRIDGE 0x2A40
#endif
#ifndef PCI_CHIP_G45_E_G
#define PCI_CHIP_G45_E_G 0x2E02
#define PCI_CHIP_G45_E_G_BRIDGE 0x2E00
#endif
#ifndef PCI_CHIP_G45_G
#define PCI_CHIP_G45_G 0x2E22
#define PCI_CHIP_G45_G_BRIDGE 0x2E20
#endif
#ifndef PCI_CHIP_Q45_G
#define PCI_CHIP_Q45_G 0x2E12
#define PCI_CHIP_Q45_G_BRIDGE 0x2E10
#endif
#ifndef PCI_CHIP_G41_G
#define PCI_CHIP_G41_G 0x2E32
#define PCI_CHIP_G41_G_BRIDGE 0x2E30
#endif
#ifndef PCI_CHIP_B43_G
#define PCI_CHIP_B43_G 0x2E42
#define PCI_CHIP_B43_G_BRIDGE 0x2E40
#endif
#ifndef PCI_CHIP_B43_G1
#define PCI_CHIP_B43_G1 0x2E92
#define PCI_CHIP_B43_G1_BRIDGE 0x2E90
#endif
#ifndef PCI_CHIP_IRONLAKE_D_G
#define PCI_CHIP_IRONLAKE_D_G 0x0042
#define PCI_CHIP_IRONLAKE_D_G_BRIDGE 0x0040
#endif
#ifndef PCI_CHIP_IRONLAKE_M_G
#define PCI_CHIP_IRONLAKE_M_G 0x0046
#define PCI_CHIP_IRONLAKE_M_G_BRIDGE 0x0044
#endif
#ifndef PCI_CHIP_SANDYBRIDGE_BRIDGE
#define PCI_CHIP_SANDYBRIDGE_BRIDGE 0x0100 /* Desktop */
#define PCI_CHIP_SANDYBRIDGE_GT1 0x0102
#define PCI_CHIP_SANDYBRIDGE_GT2 0x0112
#define PCI_CHIP_SANDYBRIDGE_GT2_PLUS 0x0122
#define PCI_CHIP_SANDYBRIDGE_BRIDGE_M 0x0104 /* Mobile */
#define PCI_CHIP_SANDYBRIDGE_M_GT1 0x0106
#define PCI_CHIP_SANDYBRIDGE_M_GT2 0x0116
#define PCI_CHIP_SANDYBRIDGE_M_GT2_PLUS 0x0126
#define PCI_CHIP_SANDYBRIDGE_BRIDGE_S 0x0108 /* Server */
#define PCI_CHIP_SANDYBRIDGE_S_GT 0x010A
#define PCI_CHIP_IVYBRIDGE_M_GT1 0x0156
@ -194,87 +66,51 @@
#define PCI_CHIP_HASWELL_D_GT1 0x0402
#define PCI_CHIP_HASWELL_D_GT2 0x0412
#define PCI_CHIP_HASWELL_D_GT2_PLUS 0x0422
#define PCI_CHIP_HASWELL_D_GT3 0x0422
#define PCI_CHIP_HASWELL_M_GT1 0x0406
#define PCI_CHIP_HASWELL_M_GT2 0x0416
#define PCI_CHIP_HASWELL_M_GT2_PLUS 0x0426
#define PCI_CHIP_HASWELL_M_GT3 0x0426
#define PCI_CHIP_HASWELL_S_GT1 0x040A
#define PCI_CHIP_HASWELL_S_GT2 0x041A
#define PCI_CHIP_HASWELL_S_GT2_PLUS 0x042A
#define PCI_CHIP_HASWELL_SDV_D_GT1 0x0C02
#define PCI_CHIP_HASWELL_SDV_D_GT2 0x0C12
#define PCI_CHIP_HASWELL_SDV_D_GT2_PLUS 0x0C22
#define PCI_CHIP_HASWELL_SDV_M_GT1 0x0C06
#define PCI_CHIP_HASWELL_SDV_M_GT2 0x0C16
#define PCI_CHIP_HASWELL_SDV_M_GT2_PLUS 0x0C26
#define PCI_CHIP_HASWELL_SDV_S_GT1 0x0C0A
#define PCI_CHIP_HASWELL_SDV_S_GT2 0x0C1A
#define PCI_CHIP_HASWELL_SDV_S_GT2_PLUS 0x0C2A
#define PCI_CHIP_HASWELL_S_GT3 0x042A
#define PCI_CHIP_HASWELL_B_GT1 0x040B
#define PCI_CHIP_HASWELL_B_GT2 0x041B
#define PCI_CHIP_HASWELL_B_GT3 0x042B
#define PCI_CHIP_HASWELL_E_GT1 0x040E
#define PCI_CHIP_HASWELL_E_GT2 0x041E
#define PCI_CHIP_HASWELL_E_GT3 0x042E
#define PCI_CHIP_HASWELL_ULT_D_GT1 0x0A02
#define PCI_CHIP_HASWELL_ULT_D_GT2 0x0A12
#define PCI_CHIP_HASWELL_ULT_D_GT2_PLUS 0x0A22
#define PCI_CHIP_HASWELL_ULT_D_GT3 0x0A22
#define PCI_CHIP_HASWELL_ULT_M_GT1 0x0A06
#define PCI_CHIP_HASWELL_ULT_M_GT2 0x0A16
#define PCI_CHIP_HASWELL_ULT_M_GT2_PLUS 0x0A26
#define PCI_CHIP_HASWELL_ULT_M_GT3 0x0A26
#define PCI_CHIP_HASWELL_ULT_S_GT1 0x0A0A
#define PCI_CHIP_HASWELL_ULT_S_GT2 0x0A1A
#define PCI_CHIP_HASWELL_ULT_S_GT2_PLUS 0x0A2A
#define PCI_CHIP_HASWELL_CRW_D_GT1 0x0D12
#define PCI_CHIP_HASWELL_CRW_D_GT2 0x0D22
#define PCI_CHIP_HASWELL_CRW_D_GT2_PLUS 0x0D32
#define PCI_CHIP_HASWELL_CRW_M_GT1 0x0D16
#define PCI_CHIP_HASWELL_CRW_M_GT2 0x0D26
#define PCI_CHIP_HASWELL_CRW_M_GT2_PLUS 0x0D36
#define PCI_CHIP_HASWELL_CRW_S_GT1 0x0D1A
#define PCI_CHIP_HASWELL_CRW_S_GT2 0x0D2A
#define PCI_CHIP_HASWELL_CRW_S_GT2_PLUS 0x0D3A
#define PCI_CHIP_HASWELL_ULT_S_GT3 0x0A2A
#define PCI_CHIP_HASWELL_ULT_B_GT1 0x0A0B
#define PCI_CHIP_HASWELL_ULT_B_GT2 0x0A1B
#define PCI_CHIP_HASWELL_ULT_B_GT3 0x0A2B
#define PCI_CHIP_HASWELL_ULT_E_GT1 0x0A0E
#define PCI_CHIP_HASWELL_ULT_E_GT2 0x0A1E
#define PCI_CHIP_HASWELL_ULT_E_GT3 0x0A2E
#define PCI_CHIP_VALLEYVIEW_PO 0x0f30
#define PCI_CHIP_VALLEYVIEW_1 0x0f31
#define PCI_CHIP_VALLEYVIEW_2 0x0f32
#define PCI_CHIP_VALLEYVIEW_3 0x0f33
#endif
#define I85X_CAPID 0x44
#define I85X_VARIANT_MASK 0x7
#define I85X_VARIANT_SHIFT 5
#define I855_GME 0x0
#define I855_GM 0x4
#define I852_GME 0x2
#define I852_GM 0x5
#define I810_MEMBASE(p,n) (p)->regions[(n)].base_addr
#define VENDOR_ID(p) (p)->vendor_id
#define DEVICE_ID(p) (p)->device_id
#define SUBVENDOR_ID(p) (p)->subvendor_id
#define SUBSYS_ID(p) (p)->subdevice_id
#define CHIP_REVISION(p) (p)->revision
#define INTEL_INFO(intel) ((intel)->info)
#define IS_GENx(intel, X) (INTEL_INFO(intel)->gen >= 8*(X) && INTEL_INFO(intel)->gen < 8*((X)+1))
#define IS_GEN1(intel) IS_GENx(intel, 1)
#define IS_GEN2(intel) IS_GENx(intel, 2)
#define IS_GEN3(intel) IS_GENx(intel, 3)
#define IS_GEN4(intel) IS_GENx(intel, 4)
#define IS_GEN5(intel) IS_GENx(intel, 5)
#define IS_GEN6(intel) IS_GENx(intel, 6)
#define IS_GEN7(intel) IS_GENx(intel, 7)
#define IS_HSW(intel) (INTEL_INFO(intel)->gen == 075)
/* Some chips have specific errata (or limits) that we need to workaround. */
#define IS_I830(intel) (DEVICE_ID((intel)->PciInfo) == PCI_CHIP_I830_M)
#define IS_845G(intel) (DEVICE_ID((intel)->PciInfo) == PCI_CHIP_845_G)
#define IS_I865G(intel) (DEVICE_ID((intel)->PciInfo) == PCI_CHIP_I865_G)
#define IS_I915G(pI810) (DEVICE_ID(pI810->PciInfo) == PCI_CHIP_I915_G || DEVICE_ID(pI810->PciInfo) == PCI_CHIP_E7221_G)
#define IS_I915GM(pI810) (DEVICE_ID(pI810->PciInfo) == PCI_CHIP_I915_GM)
#define IS_965_Q(pI810) (DEVICE_ID(pI810->PciInfo) == PCI_CHIP_I965_Q)
/* supports Y tiled surfaces (pre-965 Mesa isn't ready yet) */
#define SUPPORTS_YTILING(pI810) (INTEL_INFO(intel)->gen >= 040)
#define HAS_BLT(pI810) (INTEL_INFO(intel)->gen >= 060)
#define PCI_CHIP_HASWELL_CRW_D_GT1 0x0D02
#define PCI_CHIP_HASWELL_CRW_D_GT2 0x0D12
#define PCI_CHIP_HASWELL_CRW_D_GT3 0x0D22
#define PCI_CHIP_HASWELL_CRW_M_GT1 0x0D06
#define PCI_CHIP_HASWELL_CRW_M_GT2 0x0D16
#define PCI_CHIP_HASWELL_CRW_M_GT3 0x0D26
#define PCI_CHIP_HASWELL_CRW_S_GT1 0x0D0A
#define PCI_CHIP_HASWELL_CRW_S_GT2 0x0D1A
#define PCI_CHIP_HASWELL_CRW_S_GT3 0x0D2A
#define PCI_CHIP_HASWELL_CRW_B_GT1 0x0D0B
#define PCI_CHIP_HASWELL_CRW_B_GT2 0x0D1B
#define PCI_CHIP_HASWELL_CRW_B_GT3 0x0D2B
#define PCI_CHIP_HASWELL_CRW_E_GT1 0x0D0E
#define PCI_CHIP_HASWELL_CRW_E_GT2 0x0D1E
#define PCI_CHIP_HASWELL_CRW_E_GT3 0x0D2E
struct intel_device_info {
int gen;

View File

@ -107,6 +107,7 @@
* There are no requirements for a list head, any struct list can be a list
* head.
*/
struct list {
struct list *next, *prev;
};

View File

@ -28,24 +28,34 @@
#ifndef KGEM_H
#define KGEM_H
#define HAS_DEBUG_FULL 1
#include <stdint.h>
#include <stdio.h>
#include <stdbool.h>
#include <stdarg.h>
#include <stdio.h>
#include <i915_drm.h>
#include "compiler.h"
#include "intel_list.h"
#undef DBG
#include <limits.h>
#if !defined(MAXSHORT) || !defined(MINSHORT) || \
!defined(MAXINT) || !defined(MININT)
/*
* Some implementations #define these through <math.h>, so preclude
* #include'ing it later.
*/
#include <math.h>
#undef MAXSHORT
#define MAXSHORT SHRT_MAX
#undef MINSHORT
#define MINSHORT SHRT_MIN
#undef MAXINT
#define MAXINT INT_MAX
#undef MININT
#define MININT INT_MIN
#if HAS_DEBUG_FULL
#define DBG(x) printf x
#else
#define DBG(x)
#endif
struct kgem_bo {
@ -64,6 +74,7 @@ struct kgem_bo {
void *map;
#define IS_CPU_MAP(ptr) ((uintptr_t)(ptr) & 1)
#define IS_GTT_MAP(ptr) (ptr && ((uintptr_t)(ptr) & 1) == 0)
#define MAP(ptr) ((void*)((uintptr_t)(ptr) & ~3))
struct kgem_bo_binding {
struct kgem_bo_binding *next;
@ -90,7 +101,8 @@ struct kgem_bo {
uint32_t pitch : 18; /* max 128k */
uint32_t tiling : 2;
uint32_t reusable : 1;
uint32_t dirty : 1;
uint32_t gpu_dirty : 1;
uint32_t gtt_dirty : 1;
uint32_t domain : 2;
uint32_t needs_flush : 1;
uint32_t snoop : 1;
@ -173,6 +185,7 @@ struct kgem {
uint32_t scanout_busy:1;
uint32_t busy:1;
uint32_t has_create2 :1;
uint32_t has_userptr :1;
uint32_t has_blt :1;
uint32_t has_relaxed_fencing :1;
@ -180,8 +193,9 @@ struct kgem {
uint32_t has_semaphores :1;
uint32_t has_secure_batches :1;
uint32_t has_pinned_batches :1;
uint32_t has_cacheing :1;
uint32_t has_caching :1;
uint32_t has_llc :1;
uint32_t has_wt :1;
uint32_t has_no_reloc :1;
uint32_t has_handle_lut :1;
@ -200,10 +214,23 @@ struct kgem {
void (*retire)(struct kgem *kgem);
void (*expire)(struct kgem *kgem);
uint32_t batch[64*1024-8];
struct drm_i915_gem_exec_object2 exec[256];
struct drm_i915_gem_relocation_entry reloc[4096];
#if 0
void (*memcpy_to_tiled_x)(const void *src, void *dst, int bpp,
int32_t src_stride, int32_t dst_stride,
int16_t src_x, int16_t src_y,
int16_t dst_x, int16_t dst_y,
uint16_t width, uint16_t height);
void (*memcpy_from_tiled_x)(const void *src, void *dst, int bpp,
int32_t src_stride, int32_t dst_stride,
int16_t src_x, int16_t src_y,
int16_t dst_x, int16_t dst_y,
uint16_t width, uint16_t height);
#endif
uint16_t reloc__self[256];
uint32_t batch[64*1024-8] page_aligned;
struct drm_i915_gem_exec_object2 exec[384] page_aligned;
struct drm_i915_gem_relocation_entry reloc[8192] page_aligned;
#ifdef DEBUG_MEMORY
struct {
@ -213,9 +240,11 @@ struct kgem {
#endif
};
#define KGEM_MAX_DEFERRED_VBO 16
#define KGEM_BATCH_RESERVED 1
#define KGEM_RELOC_RESERVED 4
#define KGEM_EXEC_RESERVED 1
#define KGEM_RELOC_RESERVED (KGEM_MAX_DEFERRED_VBO)
#define KGEM_EXEC_RESERVED (1+KGEM_MAX_DEFERRED_VBO)
#ifndef ARRAY_SIZE
#define ARRAY_SIZE(a) (sizeof(a)/sizeof((a)[0]))
@ -233,12 +262,15 @@ struct kgem_bo *kgem_create_map(struct kgem *kgem,
bool read_only);
struct kgem_bo *kgem_create_for_name(struct kgem *kgem, uint32_t name);
struct kgem_bo *kgem_create_for_prime(struct kgem *kgem, int name, uint32_t size);
int kgem_bo_export_to_prime(struct kgem *kgem, struct kgem_bo *bo);
struct kgem_bo *kgem_create_linear(struct kgem *kgem, int size, unsigned flags);
struct kgem_bo *kgem_create_proxy(struct kgem *kgem,
struct kgem_bo *target,
int offset, int length);
void kgem_proxy_bo_attach(struct kgem_bo *bo, struct kgem_bo **ptr);
int kgem_choose_tiling(struct kgem *kgem,
int tiling, int width, int height, int bpp);
@ -248,6 +280,8 @@ unsigned kgem_can_create_2d(struct kgem *kgem, int width, int height, int depth)
#define KGEM_CAN_CREATE_LARGE 0x4
#define KGEM_CAN_CREATE_GTT 0x8
uint32_t kgem_get_unique_id(struct kgem *kgem);
struct kgem_bo *
kgem_replace_bo(struct kgem *kgem,
struct kgem_bo *src,
@ -281,7 +315,6 @@ struct kgem_bo *kgem_create_cpu_2d(struct kgem *kgem,
uint32_t kgem_bo_get_binding(struct kgem_bo *bo, uint32_t format);
void kgem_bo_set_binding(struct kgem_bo *bo, uint32_t format, uint16_t offset);
int kgem_bo_get_swizzling(struct kgem *kgem, struct kgem_bo *bo);
bool kgem_retire(struct kgem *kgem);
@ -304,6 +337,11 @@ static inline bool kgem_is_idle(struct kgem *kgem)
return kgem_ring_is_idle(kgem, kgem->ring);
}
static inline bool __kgem_ring_empty(struct kgem *kgem)
{
return list_is_empty(&kgem->requests[kgem->ring == KGEM_BLT]);
}
void _kgem_submit(struct kgem *kgem);
static inline void kgem_submit(struct kgem *kgem)
{
@ -325,20 +363,7 @@ static inline void kgem_bo_submit(struct kgem *kgem, struct kgem_bo *bo)
_kgem_submit(kgem);
}
void __kgem_flush(struct kgem *kgem, struct kgem_bo *bo);
static inline void kgem_bo_flush(struct kgem *kgem, struct kgem_bo *bo)
{
kgem_bo_submit(kgem, bo);
if (!bo->needs_flush)
return;
/* If the kernel fails to emit the flush, then it will be forced when
* we assume direct access. And as the useual failure is EIO, we do
* not actualy care.
*/
__kgem_flush(kgem, bo);
}
void kgem_scanout_flush(struct kgem *kgem, struct kgem_bo *bo);
static inline struct kgem_bo *kgem_bo_reference(struct kgem_bo *bo)
{
@ -367,6 +392,9 @@ static inline void kgem_set_mode(struct kgem *kgem,
kgem_submit(kgem);
#endif
if (kgem->nreloc && bo->exec == NULL && kgem_ring_is_idle(kgem, kgem->ring))
_kgem_submit(kgem);
if (kgem->mode == mode)
return;
@ -419,6 +447,11 @@ static inline bool kgem_check_batch_with_surfaces(struct kgem *kgem,
static inline uint32_t *kgem_get_batch(struct kgem *kgem)
{
if (kgem->nreloc) {
unsigned mode = kgem->mode;
_kgem_submit(kgem);
_kgem_set_mode(kgem, mode);
}
return kgem->batch + kgem->nbatch;
}
@ -512,6 +545,12 @@ static inline bool __kgem_bo_is_mappable(struct kgem *kgem,
bo->presumed_offset & (kgem_bo_fenced_size(kgem, bo) - 1))
return false;
if (kgem->gen == 021 && bo->tiling == I915_TILING_Y)
return false;
if (kgem->has_llc && bo->tiling == I915_TILING_NONE)
return true;
if (!bo->presumed_offset)
return kgem_bo_size(bo) <= kgem->aperture_mappable / 4;
@ -544,7 +583,7 @@ static inline bool kgem_bo_can_map(struct kgem *kgem, struct kgem_bo *bo)
if (kgem_bo_mapped(kgem, bo))
return true;
if (!bo->tiling && kgem->has_llc)
if (!bo->tiling && (kgem->has_llc || bo->domain == DOMAIN_CPU))
return true;
if (kgem->gen == 021 && bo->tiling == I915_TILING_Y)
@ -553,6 +592,22 @@ static inline bool kgem_bo_can_map(struct kgem *kgem, struct kgem_bo *bo)
return kgem_bo_size(bo) <= kgem->aperture_mappable / 4;
}
static inline bool kgem_bo_can_map__cpu(struct kgem *kgem,
struct kgem_bo *bo,
bool write)
{
if (bo->purged || (bo->scanout && write))
return false;
if (kgem->has_llc)
return true;
if (bo->domain != DOMAIN_CPU)
return false;
return !write || bo->exec == NULL;
}
static inline bool kgem_bo_is_snoop(struct kgem_bo *bo)
{
assert(bo->refcnt);
@ -561,6 +616,8 @@ static inline bool kgem_bo_is_snoop(struct kgem_bo *bo)
return bo->snoop;
}
void kgem_bo_undo(struct kgem *kgem, struct kgem_bo *bo);
bool __kgem_busy(struct kgem *kgem, int handle);
static inline void kgem_bo_mark_busy(struct kgem_bo *bo, int ring)
@ -570,10 +627,12 @@ static inline void kgem_bo_mark_busy(struct kgem_bo *bo, int ring)
inline static void __kgem_bo_clear_busy(struct kgem_bo *bo)
{
bo->needs_flush = false;
list_del(&bo->request);
bo->rq = NULL;
list_del(&bo->request);
bo->domain = DOMAIN_NONE;
bo->needs_flush = false;
bo->gtt_dirty = false;
}
static inline bool kgem_bo_is_busy(struct kgem_bo *bo)
@ -584,8 +643,6 @@ static inline bool kgem_bo_is_busy(struct kgem_bo *bo)
return bo->rq;
}
/*
static inline bool __kgem_bo_is_busy(struct kgem *kgem, struct kgem_bo *bo)
{
DBG(("%s: handle=%d, domain: %d exec? %d, rq? %d\n", __FUNCTION__,
@ -604,7 +661,23 @@ static inline bool __kgem_bo_is_busy(struct kgem *kgem, struct kgem_bo *bo)
return kgem_bo_is_busy(bo);
}
*/
static inline bool kgem_bo_is_render(struct kgem_bo *bo)
{
DBG(("%s: handle=%d, rq? %d [%d]\n", __FUNCTION__,
bo->handle, bo->rq != NULL, (int)RQ_RING(bo->rq)));
assert(bo->refcnt);
return bo->rq && RQ_RING(bo->rq) == I915_EXEC_RENDER;
}
static inline void kgem_bo_mark_unreusable(struct kgem_bo *bo)
{
while (bo->proxy) {
bo->flush = true;
bo = bo->proxy;
}
bo->flush = true;
bo->reusable = false;
}
static inline bool kgem_bo_is_dirty(struct kgem_bo *bo)
{
@ -612,7 +685,7 @@ static inline bool kgem_bo_is_dirty(struct kgem_bo *bo)
return false;
assert(bo->refcnt);
return bo->dirty;
return bo->gpu_dirty;
}
static inline void kgem_bo_unclean(struct kgem *kgem, struct kgem_bo *bo)
@ -632,7 +705,7 @@ static inline void __kgem_bo_mark_dirty(struct kgem_bo *bo)
bo->handle, bo->proxy != NULL));
bo->exec->flags |= LOCAL_EXEC_OBJECT_WRITE;
bo->needs_flush = bo->dirty = true;
bo->needs_flush = bo->gpu_dirty = true;
list_move(&bo->request, &RQ(bo->rq)->buffers);
}
@ -643,7 +716,7 @@ static inline void kgem_bo_mark_dirty(struct kgem_bo *bo)
assert(bo->exec);
assert(bo->rq);
if (bo->dirty)
if (bo->gpu_dirty)
return;
__kgem_bo_mark_dirty(bo);
@ -672,6 +745,9 @@ bool kgem_expire_cache(struct kgem *kgem);
void kgem_purge_cache(struct kgem *kgem);
void kgem_cleanup_cache(struct kgem *kgem);
void kgem_clean_scanout_cache(struct kgem *kgem);
void kgem_clean_large_cache(struct kgem *kgem);
#if HAS_DEBUG_FULL
void __kgem_batch_debug(struct kgem *kgem, uint32_t nbatch);
#else

View File

@ -37,22 +37,6 @@
#include "kgem_debug.h"
#include <kos32sys.h>
/*
void
ErrorF(const char *f, ...)
{
va_list args;
va_start(args, f);
VErrorF(f, args);
va_end(args);
}
*/
#define ErrorF printf
struct drm_i915_gem_relocation_entry *
kgem_debug_get_reloc_entry(struct kgem *kgem, uint32_t offset)
{
@ -388,8 +372,6 @@ decode_2d(struct kgem *kgem, uint32_t offset)
static int (*decode_3d(int gen))(struct kgem*, uint32_t)
{
return kgem_gen6_decode_3d;
/*
if (gen >= 0100) {
} else if (gen >= 070) {
return kgem_gen7_decode_3d;
@ -401,18 +383,12 @@ static int (*decode_3d(int gen))(struct kgem*, uint32_t)
return kgem_gen4_decode_3d;
} else if (gen >= 030) {
return kgem_gen3_decode_3d;
} else if (gen >= 020) {
return kgem_gen2_decode_3d;
}
assert(0);
*/
}
static void (*finish_state(int gen))(struct kgem*)
{
return kgem_gen6_finish_state;
/*
if (gen >= 0100) {
} else if (gen >= 070) {
return kgem_gen7_finish_state;
@ -424,11 +400,8 @@ static void (*finish_state(int gen))(struct kgem*)
return kgem_gen4_finish_state;
} else if (gen >= 030) {
return kgem_gen3_finish_state;
} else if (gen >= 020) {
return kgem_gen2_finish_state;
}
assert(0);
*/
}
void __kgem_batch_debug(struct kgem *kgem, uint32_t nbatch)

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,687 @@
/*
* Copyright © 2007-2011 Intel Corporation
*
* 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, sublicense,
* 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 NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS 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.
*
* Authors:
* Eric Anholt <eric@anholt.net>
* Chris Wilson <chris@chris-wilson.co.uk>
*
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <assert.h>
#include "sna.h"
#include "sna_reg.h"
#include "gen4_render.h"
#include "kgem_debug.h"
static struct state {
struct vertex_buffer {
int handle;
void *base;
const char *ptr;
int pitch;
struct kgem_bo *current;
} vb[33];
struct vertex_elements {
int buffer;
int offset;
bool valid;
uint32_t type;
uint8_t swizzle[4];
} ve[33];
int num_ve;
struct dynamic_state {
struct kgem_bo *current;
void *base, *ptr;
} dynamic_state;
} state;
static void gen4_update_vertex_buffer(struct kgem *kgem, const uint32_t *data)
{
uint32_t reloc = sizeof(uint32_t) * (&data[1] - kgem->batch);
struct kgem_bo *bo = NULL;
void *base, *ptr;
int i;
for (i = 0; i < kgem->nreloc; i++)
if (kgem->reloc[i].offset == reloc)
break;
assert(i < kgem->nreloc);
reloc = kgem->reloc[i].target_handle;
if (reloc == 0) {
base = kgem->batch;
} else {
list_for_each_entry(bo, &kgem->next_request->buffers, request)
if (bo->handle == reloc)
break;
assert(&bo->request != &kgem->next_request->buffers);
base = kgem_bo_map__debug(kgem, bo);
}
ptr = (char *)base + kgem->reloc[i].delta;
i = data[0] >> 27;
state.vb[i].current = bo;
state.vb[i].base = base;
state.vb[i].ptr = ptr;
state.vb[i].pitch = data[0] & 0x7ff;
}
static uint32_t
get_ve_component(uint32_t data, int component)
{
return (data >> (16 + (3 - component) * 4)) & 0x7;
}
static void gen4_update_vertex_elements(struct kgem *kgem, int id, const uint32_t *data)
{
state.ve[id].buffer = data[0] >> 27;
state.ve[id].valid = !!(data[0] & (1 << 26));
state.ve[id].type = (data[0] >> 16) & 0x1ff;
state.ve[id].offset = data[0] & 0x7ff;
state.ve[id].swizzle[0] = get_ve_component(data[1], 0);
state.ve[id].swizzle[1] = get_ve_component(data[1], 1);
state.ve[id].swizzle[2] = get_ve_component(data[1], 2);
state.ve[id].swizzle[3] = get_ve_component(data[1], 3);
}
static void vertices_sint16_out(const struct vertex_elements *ve, const int16_t *v, int max)
{
int c;
ErrorF("(");
for (c = 0; c < max; c++) {
switch (ve->swizzle[c]) {
case 0: ErrorF("#"); break;
case 1: ErrorF("%d", v[c]); break;
case 2: ErrorF("0.0"); break;
case 3: ErrorF("1.0"); break;
case 4: ErrorF("0x1"); break;
case 5: break;
default: ErrorF("?");
}
if (c < 3)
ErrorF(", ");
}
for (; c < 4; c++) {
switch (ve->swizzle[c]) {
case 0: ErrorF("#"); break;
case 1: ErrorF("1.0"); break;
case 2: ErrorF("0.0"); break;
case 3: ErrorF("1.0"); break;
case 4: ErrorF("0x1"); break;
case 5: break;
default: ErrorF("?");
}
if (c < 3)
ErrorF(", ");
}
ErrorF(")");
}
static void vertices_float_out(const struct vertex_elements *ve, const float *f, int max)
{
int c, o;
ErrorF("(");
for (c = o = 0; c < 4 && o < max; c++) {
switch (ve->swizzle[c]) {
case 0: ErrorF("#"); break;
case 1: ErrorF("%f", f[o++]); break;
case 2: ErrorF("0.0"); break;
case 3: ErrorF("1.0"); break;
case 4: ErrorF("0x1"); break;
case 5: break;
default: ErrorF("?");
}
if (c < 3)
ErrorF(", ");
}
for (; c < 4; c++) {
switch (ve->swizzle[c]) {
case 0: ErrorF("#"); break;
case 1: ErrorF("1.0"); break;
case 2: ErrorF("0.0"); break;
case 3: ErrorF("1.0"); break;
case 4: ErrorF("0x1"); break;
case 5: break;
default: ErrorF("?");
}
if (c < 3)
ErrorF(", ");
}
ErrorF(")");
}
static void ve_out(const struct vertex_elements *ve, const void *ptr)
{
switch (ve->type) {
case GEN4_SURFACEFORMAT_R32_FLOAT:
vertices_float_out(ve, ptr, 1);
break;
case GEN4_SURFACEFORMAT_R32G32_FLOAT:
vertices_float_out(ve, ptr, 2);
break;
case GEN4_SURFACEFORMAT_R32G32B32_FLOAT:
vertices_float_out(ve, ptr, 3);
break;
case GEN4_SURFACEFORMAT_R32G32B32A32_FLOAT:
vertices_float_out(ve, ptr, 4);
break;
case GEN4_SURFACEFORMAT_R16_SINT:
vertices_sint16_out(ve, ptr, 1);
break;
case GEN4_SURFACEFORMAT_R16G16_SINT:
vertices_sint16_out(ve, ptr, 2);
break;
case GEN4_SURFACEFORMAT_R16G16B16A16_SINT:
vertices_sint16_out(ve, ptr, 4);
break;
case GEN4_SURFACEFORMAT_R16_SSCALED:
vertices_sint16_out(ve, ptr, 1);
break;
case GEN4_SURFACEFORMAT_R16G16_SSCALED:
vertices_sint16_out(ve, ptr, 2);
break;
case GEN4_SURFACEFORMAT_R16G16B16A16_SSCALED:
vertices_sint16_out(ve, ptr, 4);
break;
}
}
static void indirect_vertex_out(struct kgem *kgem, uint32_t v)
{
int i = 0;
do {
const struct vertex_elements *ve = &state.ve[i];
const struct vertex_buffer *vb = &state.vb[ve->buffer];
const void *ptr = vb->ptr + v * vb->pitch + ve->offset;
if (!ve->valid)
continue;
ve_out(ve, ptr);
while (++i <= state.num_ve && !state.ve[i].valid)
;
if (i <= state.num_ve)
ErrorF(", ");
} while (i <= state.num_ve);
}
static void primitive_out(struct kgem *kgem, uint32_t *data)
{
int n;
assert((data[0] & (1<<15)) == 0); /* XXX index buffers */
for (n = 0; n < data[1]; n++) {
int v = data[2] + n;
ErrorF(" [%d:%d] = ", n, v);
indirect_vertex_out(kgem, v);
ErrorF("\n");
}
}
static void
state_base_out(uint32_t *data, uint32_t offset, unsigned int index,
const char *name)
{
if (data[index] & 1)
kgem_debug_print(data, offset, index,
"%s state base address 0x%08x\n",
name, data[index] & ~1);
else
kgem_debug_print(data, offset, index,
"%s state base not updated\n",
name);
}
static void
state_max_out(uint32_t *data, uint32_t offset, unsigned int index,
const char *name)
{
if (data[index] == 1)
kgem_debug_print(data, offset, index,
"%s state upper bound disabled\n", name);
else if (data[index] & 1)
kgem_debug_print(data, offset, index,
"%s state upper bound 0x%08x\n",
name, data[index] & ~1);
else
kgem_debug_print(data, offset, index,
"%s state upper bound not updated\n",
name);
}
static const char *
get_965_surfacetype(unsigned int surfacetype)
{
switch (surfacetype) {
case 0: return "1D";
case 1: return "2D";
case 2: return "3D";
case 3: return "CUBE";
case 4: return "BUFFER";
case 7: return "NULL";
default: return "unknown";
}
}
static const char *
get_965_depthformat(unsigned int depthformat)
{
switch (depthformat) {
case 0: return "s8_z24float";
case 1: return "z32float";
case 2: return "z24s8";
case 5: return "z16";
default: return "unknown";
}
}
static const char *
get_965_element_component(uint32_t data, int component)
{
uint32_t component_control = (data >> (16 + (3 - component) * 4)) & 0x7;
switch (component_control) {
case 0:
return "nostore";
case 1:
switch (component) {
case 0: return "X";
case 1: return "Y";
case 2: return "Z";
case 3: return "W";
default: return "fail";
}
case 2:
return "0.0";
case 3:
return "1.0";
case 4:
return "0x1";
case 5:
return "VID";
default:
return "fail";
}
}
static const char *
get_965_prim_type(uint32_t data)
{
uint32_t primtype = (data >> 10) & 0x1f;
switch (primtype) {
case 0x01: return "point list";
case 0x02: return "line list";
case 0x03: return "line strip";
case 0x04: return "tri list";
case 0x05: return "tri strip";
case 0x06: return "tri fan";
case 0x07: return "quad list";
case 0x08: return "quad strip";
case 0x09: return "line list adj";
case 0x0a: return "line strip adj";
case 0x0b: return "tri list adj";
case 0x0c: return "tri strip adj";
case 0x0d: return "tri strip reverse";
case 0x0e: return "polygon";
case 0x0f: return "rect list";
case 0x10: return "line loop";
case 0x11: return "point list bf";
case 0x12: return "line strip cont";
case 0x13: return "line strip bf";
case 0x14: return "line strip cont bf";
case 0x15: return "tri fan no stipple";
default: return "fail";
}
}
#if 0
struct reloc {
struct kgem_bo *bo;
void *base;
};
static void *
get_reloc(struct kgem *kgem,
void *base, const uint32_t *reloc,
struct reloc *r)
{
uint32_t delta = *reloc;
memset(r, 0, sizeof(*r));
if (base == 0) {
uint32_t handle = sizeof(uint32_t) * (reloc - kgem->batch);
struct kgem_bo *bo = NULL;
int i;
for (i = 0; i < kgem->nreloc; i++)
if (kgem->reloc[i].offset == handle)
break;
assert(i < kgem->nreloc);
handle = kgem->reloc[i].target_handle;
delta = kgem->reloc[i].delta;
if (handle == 0) {
base = kgem->batch;
} else {
list_for_each_entry(bo, &kgem->next_request->buffers, request)
if (bo->handle == handle)
break;
assert(&bo->request != &kgem->next_request->buffers);
base = kgem_bo_map__debug(kgem, bo);
r->bo = bo;
r->base = base;
}
}
return (char *)base + delta;
}
#endif
int kgem_gen4_decode_3d(struct kgem *kgem, uint32_t offset)
{
static const struct {
uint32_t opcode;
int min_len;
int max_len;
const char *name;
} opcodes[] = {
{ 0x6000, 3, 3, "URB_FENCE" },
{ 0x6001, 2, 2, "CS_URB_FENCE" },
{ 0x6002, 2, 2, "CONSTANT_BUFFER" },
{ 0x6101, 6, 6, "STATE_BASE_ADDRESS" },
{ 0x6102, 2, 2 , "STATE_SIP" },
{ 0x6104, 1, 1, "3DSTATE_PIPELINE_SELECT" },
{ 0x680b, 1, 1, "3DSTATE_VF_STATISTICS" },
{ 0x6904, 1, 1, "3DSTATE_PIPELINE_SELECT" },
{ 0x7800, 7, 7, "3DSTATE_PIPELINED_POINTERS" },
{ 0x7801, 6, 6, "3DSTATE_BINDING_TABLE_POINTERS" },
{ 0x7808, 5, 257, "3DSTATE_VERTEX_BUFFERS" },
{ 0x7809, 3, 256, "3DSTATE_VERTEX_ELEMENTS" },
{ 0x780a, 3, 3, "3DSTATE_INDEX_BUFFER" },
{ 0x780b, 1, 1, "3DSTATE_VF_STATISTICS" },
{ 0x7900, 4, 4, "3DSTATE_DRAWING_RECTANGLE" },
{ 0x7901, 5, 5, "3DSTATE_CONSTANT_COLOR" },
{ 0x7905, 5, 7, "3DSTATE_DEPTH_BUFFER" },
{ 0x7906, 2, 2, "3DSTATE_POLY_STIPPLE_OFFSET" },
{ 0x7907, 33, 33, "3DSTATE_POLY_STIPPLE_PATTERN" },
{ 0x7908, 3, 3, "3DSTATE_LINE_STIPPLE" },
{ 0x7909, 2, 2, "3DSTATE_GLOBAL_DEPTH_OFFSET_CLAMP" },
{ 0x7909, 2, 2, "3DSTATE_CLEAR_PARAMS" },
{ 0x790a, 3, 3, "3DSTATE_AA_LINE_PARAMETERS" },
{ 0x790b, 4, 4, "3DSTATE_GS_SVB_INDEX" },
{ 0x790d, 3, 3, "3DSTATE_MULTISAMPLE" },
{ 0x7910, 2, 2, "3DSTATE_CLEAR_PARAMS" },
{ 0x7b00, 6, 6, "3DPRIMITIVE" },
{ 0x7805, 3, 3, "3DSTATE_URB" },
{ 0x7815, 5, 5, "3DSTATE_CONSTANT_VS_STATE" },
{ 0x7816, 5, 5, "3DSTATE_CONSTANT_GS_STATE" },
{ 0x7817, 5, 5, "3DSTATE_CONSTANT_PS_STATE" },
{ 0x7818, 2, 2, "3DSTATE_SAMPLE_MASK" },
};
uint32_t *data = kgem->batch + offset;
uint32_t op;
unsigned int len;
int i;
const char *desc1 = NULL;
len = (data[0] & 0xff) + 2;
op = (data[0] & 0xffff0000) >> 16;
switch (op) {
case 0x6000:
assert(len == 3);
kgem_debug_print(data, offset, 0, "URB_FENCE: %s%s%s%s%s%s\n",
(data[0] >> 13) & 1 ? "cs " : "",
(data[0] >> 12) & 1 ? "vfe " : "",
(data[0] >> 11) & 1 ? "sf " : "",
(data[0] >> 10) & 1 ? "clip " : "",
(data[0] >> 9) & 1 ? "gs " : "",
(data[0] >> 8) & 1 ? "vs " : "");
kgem_debug_print(data, offset, 1,
"vs fence: %d, gs_fence: %d, clip_fence: %d\n",
data[1] & 0x3ff,
(data[1] >> 10) & 0x3ff,
(data[1] >> 20) & 0x3ff);
kgem_debug_print(data, offset, 2,
"sf fence: %d, vfe_fence: %d, cs_fence: %d\n",
data[2] & 0x3ff,
(data[2] >> 10) & 0x3ff,
(data[2] >> 20) & 0x7ff);
return len;
case 0x6001:
kgem_debug_print(data, offset, 0, "CS_URB_STATE\n");
kgem_debug_print(data, offset, 1, "entry_size: %d [%d bytes], n_entries: %d\n",
(data[1] >> 4) & 0x1f,
(((data[1] >> 4) & 0x1f) + 1) * 64,
data[1] & 0x7);
return len;
case 0x6002:
kgem_debug_print(data, offset, 0, "CONSTANT_BUFFER: %s\n",
(data[0] >> 8) & 1 ? "valid" : "invalid");
kgem_debug_print(data, offset, 1, "offset: 0x%08x, length: %d bytes\n",
data[1] & ~0x3f, ((data[1] & 0x3f) + 1) * 64);
return len;
case 0x6101:
i = 0;
kgem_debug_print(data, offset, i++, "STATE_BASE_ADDRESS\n");
assert(len == 6);
state_base_out(data, offset, i++, "general");
state_base_out(data, offset, i++, "surface");
state_base_out(data, offset, i++, "media");
state_max_out(data, offset, i++, "general");
state_max_out(data, offset, i++, "media");
return len;
case 0x7801:
assert(len == 6);
kgem_debug_print(data, offset, 0,
"3DSTATE_BINDING_TABLE_POINTERS\n");
kgem_debug_print(data, offset, 1, "VS binding table\n");
kgem_debug_print(data, offset, 2, "GS binding table\n");
kgem_debug_print(data, offset, 3, "CLIP binding table\n");
kgem_debug_print(data, offset, 4, "SF binding table\n");
kgem_debug_print(data, offset, 5, "WM binding table\n");
return len;
case 0x7808:
assert((len - 1) % 4 == 0);
kgem_debug_print(data, offset, 0, "3DSTATE_VERTEX_BUFFERS\n");
for (i = 1; i < len;) {
gen4_update_vertex_buffer(kgem, data + i);
kgem_debug_print(data, offset, i, "buffer %d: %s, pitch %db\n",
data[i] >> 27,
data[i] & (1 << 20) ? "random" : "sequential",
data[i] & 0x07ff);
i++;
kgem_debug_print(data, offset, i++, "buffer address\n");
kgem_debug_print(data, offset, i++, "max index\n");
kgem_debug_print(data, offset, i++, "mbz\n");
}
return len;
case 0x7809:
assert((len + 1) % 2 == 0);
kgem_debug_print(data, offset, 0, "3DSTATE_VERTEX_ELEMENTS\n");
memset(state.ve, 0, sizeof(state.ve)); /* XXX? */
for (i = 1; i < len;) {
gen4_update_vertex_elements(kgem, (i - 1)/2, data + i);
kgem_debug_print(data, offset, i, "buffer %d: %svalid, type 0x%04x, "
"src offset 0x%04x bytes\n",
data[i] >> 27,
data[i] & (1 << 26) ? "" : "in",
(data[i] >> 16) & 0x1ff,
data[i] & 0x07ff);
i++;
kgem_debug_print(data, offset, i, "(%s, %s, %s, %s), "
"dst offset 0x%02x bytes\n",
get_965_element_component(data[i], 0),
get_965_element_component(data[i], 1),
get_965_element_component(data[i], 2),
get_965_element_component(data[i], 3),
(data[i] & 0xff) * 4);
i++;
}
state.num_ve = (len - 1) / 2; /* XXX? */
return len;
case 0x780a:
assert(len == 3);
kgem_debug_print(data, offset, 0, "3DSTATE_INDEX_BUFFER\n");
kgem_debug_print(data, offset, 1, "beginning buffer address\n");
kgem_debug_print(data, offset, 2, "ending buffer address\n");
return len;
case 0x7900:
assert(len == 4);
kgem_debug_print(data, offset, 0,
"3DSTATE_DRAWING_RECTANGLE\n");
kgem_debug_print(data, offset, 1, "top left: %d,%d\n",
data[1] & 0xffff,
(data[1] >> 16) & 0xffff);
kgem_debug_print(data, offset, 2, "bottom right: %d,%d\n",
data[2] & 0xffff,
(data[2] >> 16) & 0xffff);
kgem_debug_print(data, offset, 3, "origin: %d,%d\n",
(int)data[3] & 0xffff,
((int)data[3] >> 16) & 0xffff);
return len;
case 0x7905:
assert(len == 7);
kgem_debug_print(data, offset, 0,
"3DSTATE_DEPTH_BUFFER\n");
kgem_debug_print(data, offset, 1, "%s, %s, pitch = %d bytes, %stiled, HiZ %d, Seperate Stencil %d\n",
get_965_surfacetype(data[1] >> 29),
get_965_depthformat((data[1] >> 18) & 0x7),
(data[1] & 0x0001ffff) + 1,
data[1] & (1 << 27) ? "" : "not ",
(data[1] & (1 << 22)) != 0,
(data[1] & (1 << 21)) != 0);
kgem_debug_print(data, offset, 2, "depth offset\n");
kgem_debug_print(data, offset, 3, "%dx%d\n",
((data[3] & 0x0007ffc0) >> 6) + 1,
((data[3] & 0xfff80000) >> 19) + 1);
kgem_debug_print(data, offset, 4, "volume depth\n");
kgem_debug_print(data, offset, 5, "\n");
kgem_debug_print(data, offset, 6, "\n");
return len;
case 0x7a00:
assert(len == 4 || len == 5);
switch ((data[1] >> 14) & 0x3) {
case 0: desc1 = "no write"; break;
case 1: desc1 = "qword write"; break;
case 2: desc1 = "PS_DEPTH_COUNT write"; break;
case 3: desc1 = "TIMESTAMP write"; break;
}
kgem_debug_print(data, offset, 0, "PIPE_CONTROL\n");
kgem_debug_print(data, offset, 1,
"%s, %scs stall, %stlb invalidate, "
"%ssync gfdt, %sdepth stall, %sRC write flush, "
"%sinst flush, %sTC flush\n",
desc1,
data[1] & (1 << 20) ? "" : "no ",
data[1] & (1 << 18) ? "" : "no ",
data[1] & (1 << 17) ? "" : "no ",
data[1] & (1 << 13) ? "" : "no ",
data[1] & (1 << 12) ? "" : "no ",
data[1] & (1 << 11) ? "" : "no ",
data[1] & (1 << 10) ? "" : "no ");
if (len == 5) {
kgem_debug_print(data, offset, 2, "destination address\n");
kgem_debug_print(data, offset, 3, "immediate dword low\n");
kgem_debug_print(data, offset, 4, "immediate dword high\n");
} else {
for (i = 2; i < len; i++) {
kgem_debug_print(data, offset, i, "\n");
}
}
return len;
case 0x7b00:
assert(len == 6);
kgem_debug_print(data, offset, 0,
"3DPRIMITIVE: %s %s\n",
get_965_prim_type(data[0]),
(data[0] & (1 << 15)) ? "random" : "sequential");
kgem_debug_print(data, offset, 1, "vertex count\n");
kgem_debug_print(data, offset, 2, "start vertex\n");
kgem_debug_print(data, offset, 3, "instance count\n");
kgem_debug_print(data, offset, 4, "start instance\n");
kgem_debug_print(data, offset, 5, "index bias\n");
primitive_out(kgem, data);
return len;
}
/* For the rest, just dump the bytes */
for (i = 0; i < ARRAY_SIZE(opcodes); i++)
if (op == opcodes[i].opcode)
break;
assert(i < ARRAY_SIZE(opcodes));
len = 1;
kgem_debug_print(data, offset, 0, "%s\n", opcodes[i].name);
if (opcodes[i].max_len > 1) {
len = (data[0] & 0xff) + 2;
assert(len >= opcodes[i].min_len &&
len <= opcodes[i].max_len);
}
for (i = 1; i < len; i++)
kgem_debug_print(data, offset, i, "dword %d\n", i);
return len;
}
void kgem_gen4_finish_state(struct kgem *kgem)
{
memset(&state, 0, sizeof(state));
}

View File

@ -0,0 +1,662 @@
/*
* Copyright © 2007-2011 Intel Corporation
*
* 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, sublicense,
* 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 NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS 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.
*
* Authors:
* Eric Anholt <eric@anholt.net>
* Chris Wilson <chris@chris-wilson.co.uk>
*
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <assert.h>
#include "sna.h"
#include "sna_reg.h"
#include "gen5_render.h"
#include "kgem_debug.h"
static struct state {
struct vertex_buffer {
int handle;
void *base;
int size;
const char *ptr;
int pitch;
struct kgem_bo *current;
} vb[17];
struct vertex_elements {
int buffer;
int offset;
bool valid;
uint32_t type;
uint8_t swizzle[4];
} ve[17];
int num_ve;
struct dynamic_state {
struct kgem_bo *current;
void *base, *ptr;
} dynamic_state;
} state;
static void gen5_update_vertex_buffer(struct kgem *kgem, const uint32_t *data)
{
struct drm_i915_gem_relocation_entry *reloc;
struct kgem_bo *bo = NULL;
void *base, *ptr;
int i, size;
reloc = kgem_debug_get_reloc_entry(kgem, &data[1] - kgem->batch);
if (reloc->target_handle == -1) {
base = kgem->batch;
size = kgem->nbatch * sizeof(uint32_t);
} else {
bo = kgem_debug_get_bo_for_reloc_entry(kgem, reloc);
base = kgem_bo_map__debug(kgem, bo);
size = kgem_bo_size(bo);
}
ptr = (char *)base + reloc->delta;
i = data[0] >> 27;
state.vb[i].handle = reloc->target_handle;
state.vb[i].current = bo;
state.vb[i].base = base;
state.vb[i].ptr = ptr;
state.vb[i].pitch = data[0] & 0x7ff;
state.vb[i].size = size;
}
static uint32_t
get_ve_component(uint32_t data, int component)
{
return (data >> (16 + (3 - component) * 4)) & 0x7;
}
static void gen5_update_vertex_elements(struct kgem *kgem, int id, const uint32_t *data)
{
state.ve[id].buffer = data[0] >> 27;
state.ve[id].valid = !!(data[0] & (1 << 26));
state.ve[id].type = (data[0] >> 16) & 0x1ff;
state.ve[id].offset = data[0] & 0x7ff;
state.ve[id].swizzle[0] = get_ve_component(data[1], 0);
state.ve[id].swizzle[1] = get_ve_component(data[1], 1);
state.ve[id].swizzle[2] = get_ve_component(data[1], 2);
state.ve[id].swizzle[3] = get_ve_component(data[1], 3);
}
static void vertices_sint16_out(const struct vertex_elements *ve, const int16_t *v, int max)
{
int c, o;
ErrorF("(");
for (c = o = 0; c < 4 && o < max; c++) {
switch (ve->swizzle[c]) {
case 0: ErrorF("#"); break;
case 1: ErrorF("%d", v[o++]); break;
case 2: ErrorF("0.0"); break;
case 3: ErrorF("1.0"); break;
case 4: ErrorF("0x1"); break;
case 5: break;
default: ErrorF("?");
}
if (o < max)
ErrorF(", ");
}
ErrorF(")");
}
static void vertices_float_out(const struct vertex_elements *ve, const float *f, int max)
{
int c, o;
ErrorF("(");
for (c = o = 0; c < 4 && o < max; c++) {
switch (ve->swizzle[c]) {
case 0: ErrorF("#"); break;
case 1: ErrorF("%f", f[o++]); break;
case 2: ErrorF("0.0"); break;
case 3: ErrorF("1.0"); break;
case 4: ErrorF("0x1"); break;
case 5: break;
default: ErrorF("?");
}
if (o < max)
ErrorF(", ");
}
ErrorF(")");
}
static void ve_out(const struct vertex_elements *ve, const void *ptr)
{
switch (ve->type) {
case GEN5_SURFACEFORMAT_R32_FLOAT:
vertices_float_out(ve, ptr, 1);
break;
case GEN5_SURFACEFORMAT_R32G32_FLOAT:
vertices_float_out(ve, ptr, 2);
break;
case GEN5_SURFACEFORMAT_R32G32B32_FLOAT:
vertices_float_out(ve, ptr, 3);
break;
case GEN5_SURFACEFORMAT_R32G32B32A32_FLOAT:
vertices_float_out(ve, ptr, 4);
break;
case GEN5_SURFACEFORMAT_R16_SINT:
vertices_sint16_out(ve, ptr, 1);
break;
case GEN5_SURFACEFORMAT_R16G16_SINT:
vertices_sint16_out(ve, ptr, 2);
break;
case GEN5_SURFACEFORMAT_R16G16B16A16_SINT:
vertices_sint16_out(ve, ptr, 4);
break;
case GEN5_SURFACEFORMAT_R16_SSCALED:
vertices_sint16_out(ve, ptr, 1);
break;
case GEN5_SURFACEFORMAT_R16G16_SSCALED:
vertices_sint16_out(ve, ptr, 2);
break;
case GEN5_SURFACEFORMAT_R16G16B16A16_SSCALED:
vertices_sint16_out(ve, ptr, 4);
break;
}
}
static void indirect_vertex_out(struct kgem *kgem, uint32_t v)
{
int i = 1;
do {
const struct vertex_elements *ve = &state.ve[i];
const struct vertex_buffer *vb = &state.vb[ve->buffer];
const void *ptr = vb->ptr + v * vb->pitch + ve->offset;
if (!ve->valid)
continue;
assert(vb->pitch);
assert(ve->offset + v*vb->pitch < vb->size);
ve_out(ve, ptr);
while (++i <= state.num_ve && !state.ve[i].valid)
;
if (i <= state.num_ve)
ErrorF(", ");
} while (i <= state.num_ve);
}
static void primitive_out(struct kgem *kgem, uint32_t *data)
{
int n;
assert((data[0] & (1<<15)) == 0); /* XXX index buffers */
for (n = 0; n < data[1]; n++) {
int v = data[2] + n;
ErrorF(" [%d:%d] = ", n, v);
indirect_vertex_out(kgem, v);
ErrorF("\n");
}
}
static void
state_base_out(uint32_t *data, uint32_t offset, unsigned int index,
const char *name)
{
if (data[index] & 1)
kgem_debug_print(data, offset, index,
"%s state base address 0x%08x\n",
name, data[index] & ~1);
else
kgem_debug_print(data, offset, index,
"%s state base not updated\n",
name);
}
static void
state_max_out(uint32_t *data, uint32_t offset, unsigned int index,
const char *name)
{
if (data[index] == 1)
kgem_debug_print(data, offset, index,
"%s state upper bound disabled\n", name);
else if (data[index] & 1)
kgem_debug_print(data, offset, index,
"%s state upper bound 0x%08x\n",
name, data[index] & ~1);
else
kgem_debug_print(data, offset, index,
"%s state upper bound not updated\n",
name);
}
static const char *
get_965_surfacetype(unsigned int surfacetype)
{
switch (surfacetype) {
case 0: return "1D";
case 1: return "2D";
case 2: return "3D";
case 3: return "CUBE";
case 4: return "BUFFER";
case 7: return "NULL";
default: return "unknown";
}
}
static const char *
get_965_depthformat(unsigned int depthformat)
{
switch (depthformat) {
case 0: return "s8_z24float";
case 1: return "z32float";
case 2: return "z24s8";
case 5: return "z16";
default: return "unknown";
}
}
static const char *
get_965_element_component(uint32_t data, int component)
{
uint32_t component_control = (data >> (16 + (3 - component) * 4)) & 0x7;
switch (component_control) {
case 0:
return "nostore";
case 1:
switch (component) {
case 0: return "X";
case 1: return "Y";
case 2: return "Z";
case 3: return "W";
default: return "fail";
}
case 2:
return "0.0";
case 3:
return "1.0";
case 4:
return "0x1";
case 5:
return "VID";
default:
return "fail";
}
}
static const char *
get_965_prim_type(uint32_t data)
{
uint32_t primtype = (data >> 10) & 0x1f;
switch (primtype) {
case 0x01: return "point list";
case 0x02: return "line list";
case 0x03: return "line strip";
case 0x04: return "tri list";
case 0x05: return "tri strip";
case 0x06: return "tri fan";
case 0x07: return "quad list";
case 0x08: return "quad strip";
case 0x09: return "line list adj";
case 0x0a: return "line strip adj";
case 0x0b: return "tri list adj";
case 0x0c: return "tri strip adj";
case 0x0d: return "tri strip reverse";
case 0x0e: return "polygon";
case 0x0f: return "rect list";
case 0x10: return "line loop";
case 0x11: return "point list bf";
case 0x12: return "line strip cont";
case 0x13: return "line strip bf";
case 0x14: return "line strip cont bf";
case 0x15: return "tri fan no stipple";
default: return "fail";
}
}
#if 0
struct reloc {
struct kgem_bo *bo;
void *base;
};
static void *
get_reloc(struct kgem *kgem,
void *base, const uint32_t *reloc,
struct reloc *r)
{
uint32_t delta = *reloc;
memset(r, 0, sizeof(*r));
if (base == 0) {
uint32_t handle = sizeof(uint32_t) * (reloc - kgem->batch);
struct kgem_bo *bo = NULL;
int i;
for (i = 0; i < kgem->nreloc; i++)
if (kgem->reloc[i].offset == handle)
break;
assert(i < kgem->nreloc);
handle = kgem->reloc[i].target_handle;
delta = kgem->reloc[i].delta;
if (handle == 0) {
base = kgem->batch;
} else {
list_for_each_entry(bo, &kgem->next_request->buffers, request)
if (bo->handle == handle)
break;
assert(&bo->request != &kgem->next_request->buffers);
base = kgem_bo_map(kgem, bo, PROT_READ);
r->bo = bo;
r->base = base;
}
}
return (char *)base + delta;
}
#endif
int kgem_gen5_decode_3d(struct kgem *kgem, uint32_t offset)
{
static const struct {
uint32_t opcode;
int min_len;
int max_len;
const char *name;
} opcodes[] = {
{ 0x6000, 3, 3, "URB_FENCE" },
{ 0x6001, 2, 2, "CS_URB_FENCE" },
{ 0x6002, 2, 2, "CONSTANT_BUFFER" },
{ 0x6101, 6, 6, "STATE_BASE_ADDRESS" },
{ 0x6102, 2, 2 , "STATE_SIP" },
{ 0x6104, 1, 1, "3DSTATE_PIPELINE_SELECT" },
{ 0x680b, 1, 1, "3DSTATE_VF_STATISTICS" },
{ 0x6904, 1, 1, "3DSTATE_PIPELINE_SELECT" },
{ 0x7800, 7, 7, "3DSTATE_PIPELINED_POINTERS" },
{ 0x7801, 6, 6, "3DSTATE_BINDING_TABLE_POINTERS" },
{ 0x7808, 5, 257, "3DSTATE_VERTEX_BUFFERS" },
{ 0x7809, 3, 256, "3DSTATE_VERTEX_ELEMENTS" },
{ 0x780a, 3, 3, "3DSTATE_INDEX_BUFFER" },
{ 0x780b, 1, 1, "3DSTATE_VF_STATISTICS" },
{ 0x7900, 4, 4, "3DSTATE_DRAWING_RECTANGLE" },
{ 0x7901, 5, 5, "3DSTATE_CONSTANT_COLOR" },
{ 0x7905, 5, 7, "3DSTATE_DEPTH_BUFFER" },
{ 0x7906, 2, 2, "3DSTATE_POLY_STIPPLE_OFFSET" },
{ 0x7907, 33, 33, "3DSTATE_POLY_STIPPLE_PATTERN" },
{ 0x7908, 3, 3, "3DSTATE_LINE_STIPPLE" },
{ 0x7909, 2, 2, "3DSTATE_GLOBAL_DEPTH_OFFSET_CLAMP" },
{ 0x7909, 2, 2, "3DSTATE_CLEAR_PARAMS" },
{ 0x790a, 3, 3, "3DSTATE_AA_LINE_PARAMETERS" },
{ 0x790b, 4, 4, "3DSTATE_GS_SVB_INDEX" },
{ 0x790d, 3, 3, "3DSTATE_MULTISAMPLE" },
{ 0x7910, 2, 2, "3DSTATE_CLEAR_PARAMS" },
{ 0x7b00, 6, 6, "3DPRIMITIVE" },
{ 0x7805, 3, 3, "3DSTATE_URB" },
{ 0x7815, 5, 5, "3DSTATE_CONSTANT_VS_STATE" },
{ 0x7816, 5, 5, "3DSTATE_CONSTANT_GS_STATE" },
{ 0x7817, 5, 5, "3DSTATE_CONSTANT_PS_STATE" },
{ 0x7818, 2, 2, "3DSTATE_SAMPLE_MASK" },
};
uint32_t *data = kgem->batch + offset;
uint32_t op;
unsigned int len;
int i;
const char *desc1 = NULL;
len = (data[0] & 0xff) + 2;
op = (data[0] & 0xffff0000) >> 16;
switch (op) {
case 0x6000:
assert(len == 3);
kgem_debug_print(data, offset, 0, "URB_FENCE: %s%s%s%s%s%s\n",
(data[0] >> 13) & 1 ? "cs " : "",
(data[0] >> 12) & 1 ? "vfe " : "",
(data[0] >> 11) & 1 ? "sf " : "",
(data[0] >> 10) & 1 ? "clip " : "",
(data[0] >> 9) & 1 ? "gs " : "",
(data[0] >> 8) & 1 ? "vs " : "");
kgem_debug_print(data, offset, 1,
"vs fence: %d, gs_fence: %d, clip_fence: %d\n",
data[1] & 0x3ff,
(data[1] >> 10) & 0x3ff,
(data[1] >> 20) & 0x3ff);
kgem_debug_print(data, offset, 2,
"sf fence: %d, vfe_fence: %d, cs_fence: %d\n",
data[2] & 0x3ff,
(data[2] >> 10) & 0x3ff,
(data[2] >> 20) & 0x7ff);
return len;
case 0x6001:
kgem_debug_print(data, offset, 0, "CS_URB_STATE\n");
kgem_debug_print(data, offset, 1, "entry_size: %d [%d bytes], n_entries: %d\n",
(data[1] >> 4) & 0x1f,
(((data[1] >> 4) & 0x1f) + 1) * 64,
data[1] & 0x7);
return len;
case 0x6002:
kgem_debug_print(data, offset, 0, "CONSTANT_BUFFER: %s\n",
(data[0] >> 8) & 1 ? "valid" : "invalid");
kgem_debug_print(data, offset, 1, "offset: 0x%08x, length: %d bytes\n",
data[1] & ~0x3f, ((data[1] & 0x3f) + 1) * 64);
return len;
case 0x6101:
i = 0;
kgem_debug_print(data, offset, i++, "STATE_BASE_ADDRESS\n");
assert(len == 8);
state_base_out(data, offset, i++, "general");
state_base_out(data, offset, i++, "surface");
state_base_out(data, offset, i++, "media");
state_base_out(data, offset, i++, "instruction");
state_max_out(data, offset, i++, "general");
state_max_out(data, offset, i++, "media");
state_max_out(data, offset, i++, "instruction");
return len;
case 0x7801:
assert(len == 6);
kgem_debug_print(data, offset, 0,
"3DSTATE_BINDING_TABLE_POINTERS\n");
kgem_debug_print(data, offset, 1, "VS binding table\n");
kgem_debug_print(data, offset, 2, "GS binding table\n");
kgem_debug_print(data, offset, 3, "CLIP binding table\n");
kgem_debug_print(data, offset, 4, "SF binding table\n");
kgem_debug_print(data, offset, 5, "WM binding table\n");
return len;
case 0x7808:
assert((len - 1) % 4 == 0);
kgem_debug_print(data, offset, 0, "3DSTATE_VERTEX_BUFFERS\n");
for (i = 1; i < len;) {
gen5_update_vertex_buffer(kgem, data + i);
kgem_debug_print(data, offset, i, "buffer %d: %s, pitch %db\n",
data[i] >> 27,
data[i] & (1 << 20) ? "random" : "sequential",
data[i] & 0x07ff);
i++;
kgem_debug_print(data, offset, i++, "buffer address\n");
kgem_debug_print(data, offset, i++, "max index\n");
kgem_debug_print(data, offset, i++, "mbz\n");
}
return len;
case 0x7809:
assert((len + 1) % 2 == 0);
kgem_debug_print(data, offset, 0, "3DSTATE_VERTEX_ELEMENTS\n");
memset(state.ve, 0, sizeof(state.ve)); /* XXX? */
for (i = 1; i < len;) {
gen5_update_vertex_elements(kgem, (i - 1)/2, data + i);
kgem_debug_print(data, offset, i,
"buffer %d: %svalid, type 0x%04x, "
"src offset 0x%04x bytes\n",
data[i] >> 27,
data[i] & (1 << 26) ? "" : "in",
(data[i] >> 16) & 0x1ff,
data[i] & 0x07ff);
i++;
kgem_debug_print(data, offset, i, "(%s, %s, %s, %s)\n",
get_965_element_component(data[i], 0),
get_965_element_component(data[i], 1),
get_965_element_component(data[i], 2),
get_965_element_component(data[i], 3));
i++;
}
state.num_ve = (len - 1) / 2; /* XXX? */
return len;
case 0x780a:
assert(len == 3);
kgem_debug_print(data, offset, 0, "3DSTATE_INDEX_BUFFER\n");
kgem_debug_print(data, offset, 1, "beginning buffer address\n");
kgem_debug_print(data, offset, 2, "ending buffer address\n");
return len;
case 0x7900:
assert(len == 4);
kgem_debug_print(data, offset, 0,
"3DSTATE_DRAWING_RECTANGLE\n");
kgem_debug_print(data, offset, 1, "top left: %d,%d\n",
data[1] & 0xffff,
(data[1] >> 16) & 0xffff);
kgem_debug_print(data, offset, 2, "bottom right: %d,%d\n",
data[2] & 0xffff,
(data[2] >> 16) & 0xffff);
kgem_debug_print(data, offset, 3, "origin: %d,%d\n",
(int)data[3] & 0xffff,
((int)data[3] >> 16) & 0xffff);
return len;
case 0x7905:
assert(len == 7);
kgem_debug_print(data, offset, 0,
"3DSTATE_DEPTH_BUFFER\n");
kgem_debug_print(data, offset, 1, "%s, %s, pitch = %d bytes, %stiled, HiZ %d, Seperate Stencil %d\n",
get_965_surfacetype(data[1] >> 29),
get_965_depthformat((data[1] >> 18) & 0x7),
(data[1] & 0x0001ffff) + 1,
data[1] & (1 << 27) ? "" : "not ",
(data[1] & (1 << 22)) != 0,
(data[1] & (1 << 21)) != 0);
kgem_debug_print(data, offset, 2, "depth offset\n");
kgem_debug_print(data, offset, 3, "%dx%d\n",
((data[3] & 0x0007ffc0) >> 6) + 1,
((data[3] & 0xfff80000) >> 19) + 1);
kgem_debug_print(data, offset, 4, "volume depth\n");
kgem_debug_print(data, offset, 5, "\n");
kgem_debug_print(data, offset, 6, "\n");
return len;
case 0x7a00:
assert(len == 4 || len == 5);
switch ((data[1] >> 14) & 0x3) {
case 0: desc1 = "no write"; break;
case 1: desc1 = "qword write"; break;
case 2: desc1 = "PS_DEPTH_COUNT write"; break;
case 3: desc1 = "TIMESTAMP write"; break;
}
kgem_debug_print(data, offset, 0, "PIPE_CONTROL\n");
kgem_debug_print(data, offset, 1,
"%s, %scs stall, %stlb invalidate, "
"%ssync gfdt, %sdepth stall, %sRC write flush, "
"%sinst flush, %sTC flush\n",
desc1,
data[1] & (1 << 20) ? "" : "no ",
data[1] & (1 << 18) ? "" : "no ",
data[1] & (1 << 17) ? "" : "no ",
data[1] & (1 << 13) ? "" : "no ",
data[1] & (1 << 12) ? "" : "no ",
data[1] & (1 << 11) ? "" : "no ",
data[1] & (1 << 10) ? "" : "no ");
if (len == 5) {
kgem_debug_print(data, offset, 2, "destination address\n");
kgem_debug_print(data, offset, 3, "immediate dword low\n");
kgem_debug_print(data, offset, 4, "immediate dword high\n");
} else {
for (i = 2; i < len; i++) {
kgem_debug_print(data, offset, i, "\n");
}
}
return len;
case 0x7b00:
assert(len == 6);
kgem_debug_print(data, offset, 0,
"3DPRIMITIVE: %s %s\n",
get_965_prim_type(data[0]),
(data[0] & (1 << 15)) ? "random" : "sequential");
kgem_debug_print(data, offset, 1, "vertex count\n");
kgem_debug_print(data, offset, 2, "start vertex\n");
kgem_debug_print(data, offset, 3, "instance count\n");
kgem_debug_print(data, offset, 4, "start instance\n");
kgem_debug_print(data, offset, 5, "index bias\n");
primitive_out(kgem, data);
return len;
}
/* For the rest, just dump the bytes */
for (i = 0; i < ARRAY_SIZE(opcodes); i++)
if (op == opcodes[i].opcode)
break;
assert(i < ARRAY_SIZE(opcodes));
len = 1;
kgem_debug_print(data, offset, 0, "%s\n", opcodes[i].name);
if (opcodes[i].max_len > 1) {
len = (data[0] & 0xff) + 2;
assert(len >= opcodes[i].min_len &&
len <= opcodes[i].max_len);
}
for (i = 1; i < len; i++)
kgem_debug_print(data, offset, i, "dword %d\n", i);
return len;
}
void kgem_gen5_finish_state(struct kgem *kgem)
{
memset(&state, 0, sizeof(state));
}

View File

@ -39,8 +39,6 @@
#include "kgem_debug.h"
#define ErrorF printf
static struct state {
struct vertex_buffer {
int handle;

View File

@ -0,0 +1,715 @@
/*
* Copyright © 2007-2011 Intel Corporation
*
* 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, sublicense,
* 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 NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS 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.
*
* Authors:
* Eric Anholt <eric@anholt.net>
* Chris Wilson <chris"chris-wilson.co.uk>
*
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <assert.h>
#include "sna.h"
#include "sna_reg.h"
#include "gen7_render.h"
#include "kgem_debug.h"
static struct state {
struct vertex_buffer {
int handle;
void *base;
const char *ptr;
int pitch;
struct kgem_bo *current;
} vb[33];
struct vertex_elements {
int buffer;
int offset;
bool valid;
uint32_t type;
uint8_t swizzle[4];
} ve[33];
int num_ve;
struct dynamic_state {
struct kgem_bo *current;
void *base, *ptr;
} dynamic_state;
} state;
static void gen7_update_vertex_buffer(struct kgem *kgem, const uint32_t *data)
{
uint32_t reloc = sizeof(uint32_t) * (&data[1] - kgem->batch);
struct kgem_bo *bo = NULL;
void *base, *ptr;
int i;
for (i = 0; i < kgem->nreloc; i++)
if (kgem->reloc[i].offset == reloc)
break;
assert(i < kgem->nreloc);
reloc = kgem->reloc[i].target_handle;
if (reloc == 0) {
base = kgem->batch;
} else {
list_for_each_entry(bo, &kgem->next_request->buffers, request)
if (bo->handle == reloc)
break;
assert(&bo->request != &kgem->next_request->buffers);
base = kgem_bo_map__debug(kgem, bo);
}
ptr = (char *)base + kgem->reloc[i].delta;
i = data[0] >> 26;
state.vb[i].current = bo;
state.vb[i].base = base;
state.vb[i].ptr = ptr;
state.vb[i].pitch = data[0] & 0x7ff;
}
static void gen7_update_dynamic_buffer(struct kgem *kgem, const uint32_t offset)
{
uint32_t reloc = sizeof(uint32_t) * offset;
struct kgem_bo *bo = NULL;
void *base, *ptr;
int i;
if ((kgem->batch[offset] & 1) == 0)
return;
for (i = 0; i < kgem->nreloc; i++)
if (kgem->reloc[i].offset == reloc)
break;
if(i < kgem->nreloc) {
reloc = kgem->reloc[i].target_handle;
if (reloc == 0) {
base = kgem->batch;
} else {
list_for_each_entry(bo, &kgem->next_request->buffers, request)
if (bo->handle == reloc)
break;
assert(&bo->request != &kgem->next_request->buffers);
base = kgem_bo_map__debug(kgem, bo);
}
ptr = (char *)base + (kgem->reloc[i].delta & ~1);
} else {
bo = NULL;
base = NULL;
ptr = NULL;
}
state.dynamic_state.current = bo;
state.dynamic_state.base = base;
state.dynamic_state.ptr = ptr;
}
static uint32_t
get_ve_component(uint32_t data, int component)
{
return (data >> (16 + (3 - component) * 4)) & 0x7;
}
static void gen7_update_vertex_elements(struct kgem *kgem, int id, const uint32_t *data)
{
state.ve[id].buffer = data[0] >> 26;
state.ve[id].valid = !!(data[0] & (1 << 25));
state.ve[id].type = (data[0] >> 16) & 0x1ff;
state.ve[id].offset = data[0] & 0x7ff;
state.ve[id].swizzle[0] = get_ve_component(data[1], 0);
state.ve[id].swizzle[1] = get_ve_component(data[1], 1);
state.ve[id].swizzle[2] = get_ve_component(data[1], 2);
state.ve[id].swizzle[3] = get_ve_component(data[1], 3);
}
static void gen7_update_sf_state(struct kgem *kgem, uint32_t *data)
{
state.num_ve = 1 + ((data[1] >> 22) & 0x3f);
}
static void vertices_sint16_out(const struct vertex_elements *ve, const int16_t *v, int max)
{
int c;
ErrorF("(");
for (c = 0; c < max; c++) {
switch (ve->swizzle[c]) {
case 0: ErrorF("#"); break;
case 1: ErrorF("%d", v[c]); break;
case 2: ErrorF("0.0"); break;
case 3: ErrorF("1.0"); break;
case 4: ErrorF("0x1"); break;
case 5: break;
default: ErrorF("?");
}
if (c < 3)
ErrorF(", ");
}
for (; c < 4; c++) {
switch (ve->swizzle[c]) {
case 0: ErrorF("#"); break;
case 1: ErrorF("1.0"); break;
case 2: ErrorF("0.0"); break;
case 3: ErrorF("1.0"); break;
case 4: ErrorF("0x1"); break;
case 5: break;
default: ErrorF("?");
}
if (c < 3)
ErrorF(", ");
}
ErrorF(")");
}
static void vertices_float_out(const struct vertex_elements *ve, const float *f, int max)
{
int c, o;
ErrorF("(");
for (c = o = 0; c < 4 && o < max; c++) {
switch (ve->swizzle[c]) {
case 0: ErrorF("#"); break;
case 1: ErrorF("%f", f[o++]); break;
case 2: ErrorF("0.0"); break;
case 3: ErrorF("1.0"); break;
case 4: ErrorF("0x1"); break;
case 5: break;
default: ErrorF("?");
}
if (c < 3)
ErrorF(", ");
}
for (; c < 4; c++) {
switch (ve->swizzle[c]) {
case 0: ErrorF("#"); break;
case 1: ErrorF("1.0"); break;
case 2: ErrorF("0.0"); break;
case 3: ErrorF("1.0"); break;
case 4: ErrorF("0x1"); break;
case 5: break;
default: ErrorF("?");
}
if (c < 3)
ErrorF(", ");
}
ErrorF(")");
}
static void ve_out(const struct vertex_elements *ve, const void *ptr)
{
switch (ve->type) {
case GEN7_SURFACEFORMAT_R32_FLOAT:
vertices_float_out(ve, ptr, 1);
break;
case GEN7_SURFACEFORMAT_R32G32_FLOAT:
vertices_float_out(ve, ptr, 2);
break;
case GEN7_SURFACEFORMAT_R32G32B32_FLOAT:
vertices_float_out(ve, ptr, 3);
break;
case GEN7_SURFACEFORMAT_R32G32B32A32_FLOAT:
vertices_float_out(ve, ptr, 4);
break;
case GEN7_SURFACEFORMAT_R16_SINT:
vertices_sint16_out(ve, ptr, 1);
break;
case GEN7_SURFACEFORMAT_R16G16_SINT:
vertices_sint16_out(ve, ptr, 2);
break;
case GEN7_SURFACEFORMAT_R16G16B16A16_SINT:
vertices_sint16_out(ve, ptr, 4);
break;
case GEN7_SURFACEFORMAT_R16_SSCALED:
vertices_sint16_out(ve, ptr, 1);
break;
case GEN7_SURFACEFORMAT_R16G16_SSCALED:
vertices_sint16_out(ve, ptr, 2);
break;
case GEN7_SURFACEFORMAT_R16G16B16A16_SSCALED:
vertices_sint16_out(ve, ptr, 4);
break;
}
}
static void indirect_vertex_out(struct kgem *kgem, uint32_t v)
{
int i = 1;
do {
const struct vertex_elements *ve = &state.ve[i];
const struct vertex_buffer *vb = &state.vb[ve->buffer];
const void *ptr = vb->ptr + v * vb->pitch + ve->offset;
if (!ve->valid)
continue;
ve_out(ve, ptr);
while (++i <= state.num_ve && !state.ve[i].valid)
;
if (i <= state.num_ve)
ErrorF(", ");
} while (i <= state.num_ve);
}
static void primitive_out(struct kgem *kgem, uint32_t *data)
{
int n;
assert((data[0] & (1<<15)) == 0); /* XXX index buffers */
for (n = 0; n < data[2]; n++) {
int v = data[3] + n;
ErrorF(" [%d:%d] = ", n, v);
indirect_vertex_out(kgem, v);
ErrorF("\n");
}
}
static void finish_state(struct kgem *kgem)
{
memset(&state, 0, sizeof(state));
}
static void
state_base_out(uint32_t *data, uint32_t offset, unsigned int index,
const char *name)
{
if (data[index] & 1)
kgem_debug_print(data, offset, index,
"%s state base address 0x%08x\n",
name, data[index] & ~1);
else
kgem_debug_print(data, offset, index,
"%s state base not updated\n",
name);
}
static void
state_max_out(uint32_t *data, uint32_t offset, unsigned int index,
const char *name)
{
if (data[index] == 1)
kgem_debug_print(data, offset, index,
"%s state upper bound disabled\n", name);
else if (data[index] & 1)
kgem_debug_print(data, offset, index,
"%s state upper bound 0x%08x\n",
name, data[index] & ~1);
else
kgem_debug_print(data, offset, index,
"%s state upper bound not updated\n",
name);
}
static const char *
get_965_surfacetype(unsigned int surfacetype)
{
switch (surfacetype) {
case 0: return "1D";
case 1: return "2D";
case 2: return "3D";
case 3: return "CUBE";
case 4: return "BUFFER";
case 7: return "NULL";
default: return "unknown";
}
}
static const char *
get_965_depthformat(unsigned int depthformat)
{
switch (depthformat) {
case 0: return "s8_z24float";
case 1: return "z32float";
case 2: return "z24s8";
case 5: return "z16";
default: return "unknown";
}
}
static const char *
get_element_component(uint32_t data, int component)
{
uint32_t component_control = (data >> (16 + (3 - component) * 4)) & 0x7;
switch (component_control) {
case 0:
return "nostore";
case 1:
switch (component) {
case 0: return "X";
case 1: return "Y";
case 2: return "Z";
case 3: return "W";
default: return "fail";
}
case 2:
return "0.0";
case 3:
return "1.0";
case 4:
return "0x1";
case 5:
return "VID";
default:
return "fail";
}
}
static const char *
get_prim_type(uint32_t data)
{
uint32_t primtype = data & 0x1f;
switch (primtype) {
case 0x01: return "point list";
case 0x02: return "line list";
case 0x03: return "line strip";
case 0x04: return "tri list";
case 0x05: return "tri strip";
case 0x06: return "tri fan";
case 0x07: return "quad list";
case 0x08: return "quad strip";
case 0x09: return "line list adj";
case 0x0a: return "line strip adj";
case 0x0b: return "tri list adj";
case 0x0c: return "tri strip adj";
case 0x0d: return "tri strip reverse";
case 0x0e: return "polygon";
case 0x0f: return "rect list";
case 0x10: return "line loop";
case 0x11: return "point list bf";
case 0x12: return "line strip cont";
case 0x13: return "line strip bf";
case 0x14: return "line strip cont bf";
case 0x15: return "tri fan no stipple";
default: return "fail";
}
}
struct reloc {
struct kgem_bo *bo;
void *base;
};
static void *
get_reloc(struct kgem *kgem,
void *base, const uint32_t *reloc,
struct reloc *r)
{
uint32_t delta = *reloc;
memset(r, 0, sizeof(*r));
if (base == 0) {
uint32_t handle = sizeof(uint32_t) * (reloc - kgem->batch);
struct kgem_bo *bo = NULL;
int i;
for (i = 0; i < kgem->nreloc; i++)
if (kgem->reloc[i].offset == handle)
break;
assert(i < kgem->nreloc);
handle = kgem->reloc[i].target_handle;
delta = kgem->reloc[i].delta;
if (handle == 0) {
base = kgem->batch;
} else {
list_for_each_entry(bo, &kgem->next_request->buffers, request)
if (bo->handle == handle)
break;
assert(&bo->request != &kgem->next_request->buffers);
base = kgem_bo_map__debug(kgem, bo);
r->bo = bo;
r->base = base;
}
}
return (char *)base + (delta & ~3);
}
static const char *
gen7_filter_to_string(uint32_t filter)
{
switch (filter) {
default:
case GEN7_MAPFILTER_NEAREST: return "nearest";
case GEN7_MAPFILTER_LINEAR: return "linear";
}
}
static const char *
gen7_repeat_to_string(uint32_t repeat)
{
switch (repeat) {
default:
case GEN7_TEXCOORDMODE_CLAMP_BORDER: return "border";
case GEN7_TEXCOORDMODE_WRAP: return "wrap";
case GEN7_TEXCOORDMODE_CLAMP: return "clamp";
case GEN7_TEXCOORDMODE_MIRROR: return "mirror";
}
}
static void
gen7_decode_sampler_state(struct kgem *kgem, const uint32_t *reloc)
{
const struct gen7_sampler_state *ss;
struct reloc r;
const char *min, *mag;
const char *s_wrap, *t_wrap, *r_wrap;
ss = get_reloc(kgem, state.dynamic_state.ptr, reloc, &r);
min = gen7_filter_to_string(ss->ss0.min_filter);
mag = gen7_filter_to_string(ss->ss0.mag_filter);
s_wrap = gen7_repeat_to_string(ss->ss3.s_wrap_mode);
t_wrap = gen7_repeat_to_string(ss->ss3.t_wrap_mode);
r_wrap = gen7_repeat_to_string(ss->ss3.r_wrap_mode);
ErrorF(" Sampler 0:\n");
ErrorF(" filter: min=%s, mag=%s\n", min, mag);
ErrorF(" wrap: s=%s, t=%s, r=%s\n", s_wrap, t_wrap, r_wrap);
ss++;
min = gen7_filter_to_string(ss->ss0.min_filter);
mag = gen7_filter_to_string(ss->ss0.mag_filter);
s_wrap = gen7_repeat_to_string(ss->ss3.s_wrap_mode);
t_wrap = gen7_repeat_to_string(ss->ss3.t_wrap_mode);
r_wrap = gen7_repeat_to_string(ss->ss3.r_wrap_mode);
ErrorF(" Sampler 1:\n");
ErrorF(" filter: min=%s, mag=%s\n", min, mag);
ErrorF(" wrap: s=%s, t=%s, r=%s\n", s_wrap, t_wrap, r_wrap);
}
static const char *
gen7_blend_factor_to_string(uint32_t v)
{
switch (v) {
#define C(x) case GEN7_BLENDFACTOR_##x: return #x;
C(ONE);
C(SRC_COLOR);
C(SRC_ALPHA);
C(DST_ALPHA);
C(DST_COLOR);
C(SRC_ALPHA_SATURATE);
C(CONST_COLOR);
C(CONST_ALPHA);
C(SRC1_COLOR);
C(SRC1_ALPHA);
C(ZERO);
C(INV_SRC_COLOR);
C(INV_SRC_ALPHA);
C(INV_DST_ALPHA);
C(INV_DST_COLOR);
C(INV_CONST_COLOR);
C(INV_CONST_ALPHA);
C(INV_SRC1_COLOR);
C(INV_SRC1_ALPHA);
#undef C
default: return "???";
}
}
static const char *
gen7_blend_function_to_string(uint32_t v)
{
switch (v) {
#define C(x) case GEN7_BLENDFUNCTION_##x: return #x;
C(ADD);
C(SUBTRACT);
C(REVERSE_SUBTRACT);
C(MIN);
C(MAX);
#undef C
default: return "???";
}
}
static void
gen7_decode_blend(struct kgem *kgem, const uint32_t *reloc)
{
const struct gen7_blend_state *blend;
struct reloc r;
const char *dst, *src;
const char *func;
blend = get_reloc(kgem, state.dynamic_state.ptr, reloc, &r);
dst = gen7_blend_factor_to_string(blend->blend0.dest_blend_factor);
src = gen7_blend_factor_to_string(blend->blend0.source_blend_factor);
func = gen7_blend_function_to_string(blend->blend0.blend_func);
ErrorF(" Blend (%s): function %s, src=%s, dst=%s\n",
blend->blend0.blend_enable ? "enabled" : "disabled",
func, src, dst);
}
int kgem_gen7_decode_3d(struct kgem *kgem, uint32_t offset)
{
static const struct {
uint32_t opcode;
int min_len;
int max_len;
const char *name;
} opcodes[] = {
{ 0x6101, 6, 6, "STATE_BASE_ADDRESS" },
{ 0x6102, 2, 2 , "STATE_SIP" },
{ 0x6104, 1, 1, "3DSTATE_PIPELINE_SELECT" },
{ 0x780a, 3, 3, "3DSTATE_INDEX_BUFFER" },
{ 0x7900, 4, 4, "3DSTATE_DRAWING_RECTANGLE" },
};
uint32_t *data = kgem->batch + offset;
uint32_t op;
unsigned int len;
int i;
const char *name;
len = (data[0] & 0xff) + 2;
op = (data[0] & 0xffff0000) >> 16;
switch (op) {
case 0x6101:
i = 0;
kgem_debug_print(data, offset, i++, "STATE_BASE_ADDRESS\n");
assert(len == 10);
state_base_out(data, offset, i++, "general");
state_base_out(data, offset, i++, "surface");
state_base_out(data, offset, i++, "dynamic");
state_base_out(data, offset, i++, "indirect");
state_base_out(data, offset, i++, "instruction");
state_max_out(data, offset, i++, "general");
state_max_out(data, offset, i++, "dynamic");
state_max_out(data, offset, i++, "indirect");
state_max_out(data, offset, i++, "instruction");
gen7_update_dynamic_buffer(kgem, offset + 3);
return len;
case 0x7808:
assert((len - 1) % 4 == 0);
kgem_debug_print(data, offset, 0, "3DSTATE_VERTEX_BUFFERS\n");
for (i = 1; i < len;) {
gen7_update_vertex_buffer(kgem, data + i);
kgem_debug_print(data, offset, i, "buffer %d: %s, pitch %db\n",
data[i] >> 26,
data[i] & (1 << 20) ? "random" : "sequential",
data[i] & 0x07ff);
i++;
kgem_debug_print(data, offset, i++, "buffer address\n");
kgem_debug_print(data, offset, i++, "max index\n");
kgem_debug_print(data, offset, i++, "mbz\n");
}
return len;
case 0x7809:
assert((len + 1) % 2 == 0);
kgem_debug_print(data, offset, 0, "3DSTATE_VERTEX_ELEMENTS\n");
for (i = 1; i < len;) {
gen7_update_vertex_elements(kgem, (i - 1)/2, data + i);
kgem_debug_print(data, offset, i, "buffer %d: %svalid, type 0x%04x, "
"src offset 0x%04x bytes\n",
data[i] >> 26,
data[i] & (1 << 25) ? "" : "in",
(data[i] >> 16) & 0x1ff,
data[i] & 0x07ff);
i++;
kgem_debug_print(data, offset, i, "(%s, %s, %s, %s), "
"dst offset 0x%02x bytes\n",
get_element_component(data[i], 0),
get_element_component(data[i], 1),
get_element_component(data[i], 2),
get_element_component(data[i], 3),
(data[i] & 0xff) * 4);
i++;
}
return len;
case 0x780a:
assert(len == 3);
kgem_debug_print(data, offset, 0, "3DSTATE_INDEX_BUFFER\n");
kgem_debug_print(data, offset, 1, "beginning buffer address\n");
kgem_debug_print(data, offset, 2, "ending buffer address\n");
return len;
case 0x7b00:
assert(len == 7);
kgem_debug_print(data, offset, 0, "3DPRIMITIVE\n");
kgem_debug_print(data, offset, 1, "type %s, %s\n",
get_prim_type(data[1]),
(data[1] & (1 << 15)) ? "random" : "sequential");
kgem_debug_print(data, offset, 2, "vertex count\n");
kgem_debug_print(data, offset, 3, "start vertex\n");
kgem_debug_print(data, offset, 4, "instance count\n");
kgem_debug_print(data, offset, 5, "start instance\n");
kgem_debug_print(data, offset, 6, "index bias\n");
primitive_out(kgem, data);
return len;
}
/* For the rest, just dump the bytes */
name = NULL;
for (i = 0; i < ARRAY_SIZE(opcodes); i++)
if (op == opcodes[i].opcode) {
name = opcodes[i].name;
break;
}
len = (data[0] & 0xff) + 2;
if (name == NULL) {
kgem_debug_print(data, offset, 0, "unknown\n");
} else {
kgem_debug_print(data, offset, 0, "%s\n", opcodes[i].name);
if (opcodes[i].max_len > 1) {
assert(len >= opcodes[i].min_len &&
len <= opcodes[i].max_len);
}
}
for (i = 1; i < len; i++)
kgem_debug_print(data, offset, i, "dword %d\n", i);
return len;
}
void kgem_gen7_finish_state(struct kgem *kgem)
{
finish_state(kgem);
}

View File

@ -1,11 +1,51 @@
/**************************************************************************
Copyright 2001 VA Linux Systems Inc., Fremont, California.
Copyright © 2002 by David Dawes
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
on 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
THE COPYRIGHT HOLDERS AND/OR THEIR 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.
**************************************************************************/
/*
* Authors: Jeff Hartmann <jhartmann@valinux.com>
* Abraham van der Merwe <abraham@2d3d.co.za>
* David Dawes <dawes@xfree86.org>
* Alan Hourihane <alanh@tungstengraphics.com>
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <memory.h>
#include <malloc.h>
#include <kos32sys.h>
#include <pixlib2.h>
#include "i915_pciids.h"
#include "compiler.h"
#include "sna.h"
#include "intel_driver.h"
#define to_surface(x) (surface_t*)((x)->handle)
@ -46,6 +86,8 @@ int kgem_update_fb(struct kgem *kgem, struct sna_fb *fb);
uint32_t kgem_surface_size(struct kgem *kgem,bool relaxed_fencing,
unsigned flags, uint32_t width, uint32_t height,
uint32_t bpp, uint32_t tiling, uint32_t *pitch);
struct kgem_bo *kgem_bo_from_handle(struct kgem *kgem, int handle,
int pitch, int height);
void kgem_close_batches(struct kgem *kgem);
void sna_bo_destroy(struct kgem *kgem, struct kgem_bo *bo);
@ -53,8 +95,6 @@ void sna_bo_destroy(struct kgem *kgem, struct kgem_bo *bo);
const struct intel_device_info *
intel_detect_chipset(struct pci_device *pci);
//struct kgem_bo *create_bo(bitmap_t *bitmap);
static bool sna_solid_cache_init(struct sna *sna);
struct sna *sna_device;
@ -66,7 +106,45 @@ static void no_render_reset(struct sna *sna)
(void)sna;
}
void no_render_init(struct sna *sna)
static void no_render_flush(struct sna *sna)
{
(void)sna;
}
static void
no_render_context_switch(struct kgem *kgem,
int new_mode)
{
if (!kgem->nbatch)
return;
if (kgem_ring_is_idle(kgem, kgem->ring)) {
DBG(("%s: GPU idle, flushing\n", __FUNCTION__));
_kgem_submit(kgem);
}
(void)new_mode;
}
static void
no_render_retire(struct kgem *kgem)
{
(void)kgem;
}
static void
no_render_expire(struct kgem *kgem)
{
(void)kgem;
}
static void
no_render_fini(struct sna *sna)
{
(void)sna;
}
const char *no_render_init(struct sna *sna)
{
struct sna_render *render = &sna->render;
@ -77,28 +155,20 @@ void no_render_init(struct sna *sna)
render->vertices = render->vertex_data;
render->vertex_size = ARRAY_SIZE(render->vertex_data);
// render->composite = no_render_composite;
// render->copy_boxes = no_render_copy_boxes;
// render->copy = no_render_copy;
// render->fill_boxes = no_render_fill_boxes;
// render->fill = no_render_fill;
// render->fill_one = no_render_fill_one;
// render->clear = no_render_clear;
render->reset = no_render_reset;
// render->flush = no_render_flush;
// render->fini = no_render_fini;
render->flush = no_render_flush;
render->fini = no_render_fini;
// sna->kgem.context_switch = no_render_context_switch;
// sna->kgem.retire = no_render_retire;
sna->kgem.context_switch = no_render_context_switch;
sna->kgem.retire = no_render_retire;
sna->kgem.expire = no_render_expire;
if (sna->kgem.gen >= 60)
sna->kgem.mode = KGEM_RENDER;
sna->kgem.ring = KGEM_RENDER;
sna_vertex_init(sna);
}
return "generic";
}
void sna_vertex_init(struct sna *sna)
{
@ -111,47 +181,27 @@ int sna_accel_init(struct sna *sna)
{
const char *backend;
// list_init(&sna->deferred_free);
// list_init(&sna->dirty_pixmaps);
// list_init(&sna->active_pixmaps);
// list_init(&sna->inactive_clock[0]);
// list_init(&sna->inactive_clock[1]);
// sna_accel_install_timers(sna);
backend = "no";
no_render_init(sna);
if (sna->info->gen >= 0100) {
} else if (sna->info->gen >= 070) {
if (gen7_render_init(sna))
backend = "IvyBridge";
} else if (sna->info->gen >= 060) {
if (gen6_render_init(sna))
backend = "SandyBridge";
} else if (sna->info->gen >= 050) {
if (gen5_render_init(sna))
backend = "Ironlake";
} else if (sna->info->gen >= 040) {
if (gen4_render_init(sna))
backend = "Broadwater/Crestline";
} else if (sna->info->gen >= 030) {
if (gen3_render_init(sna))
backend = "gen3";
}
backend = no_render_init(sna);
if (sna->info->gen >= 0100)
(void)backend;
else if (sna->info->gen >= 070)
backend = gen7_render_init(sna, backend);
else if (sna->info->gen >= 060)
backend = gen6_render_init(sna, backend);
else if (sna->info->gen >= 050)
backend = gen5_render_init(sna, backend);
else if (sna->info->gen >= 040)
backend = gen4_render_init(sna, backend);
else if (sna->info->gen >= 030)
backend = gen3_render_init(sna, backend);
DBG(("%s(backend=%s, prefer_gpu=%x)\n",
__FUNCTION__, backend, sna->render.prefer_gpu));
kgem_reset(&sna->kgem);
// if (!sna_solid_cache_init(sna))
// return false;
sna_device = sna;
return kgem_init_fb(&sna->kgem, &sna_fb);
}
@ -186,33 +236,17 @@ int sna_init(uint32_t service)
memset(sna, 0, sizeof(*sna));
sna->PciInfo = &device;
sna->cpu_features = sna_cpu_detect();
sna->PciInfo = &device;
sna->info = intel_detect_chipset(sna->PciInfo);
sna->scrn = service;
kgem_init(&sna->kgem, service, sna->PciInfo, sna->info->gen);
/*
if (!xf86ReturnOptValBool(sna->Options,
OPTION_RELAXED_FENCING,
sna->kgem.has_relaxed_fencing)) {
xf86DrvMsg(scrn->scrnIndex,
sna->kgem.has_relaxed_fencing ? X_CONFIG : X_PROBED,
"Disabling use of relaxed fencing\n");
sna->kgem.has_relaxed_fencing = 0;
}
if (!xf86ReturnOptValBool(sna->Options,
OPTION_VMAP,
sna->kgem.has_vmap)) {
xf86DrvMsg(scrn->scrnIndex,
sna->kgem.has_vmap ? X_CONFIG : X_PROBED,
"Disabling use of vmap\n");
sna->kgem.has_vmap = 0;
}
*/
/* Disable tiling by default */
sna->tiling = SNA_TILING_DISABLE;
sna->tiling = 0;
/* Default fail-safe value of 75 Hz */
// sna->vblank_interval = 1000 * 1000 * 1000 / 75;
@ -490,6 +524,47 @@ err_1:
return -1;
};
int sna_bitmap_from_handle(bitmap_t *bitmap, uint32_t handle)
{
surface_t *sf;
struct kgem_bo *bo;
sf = malloc(sizeof(*sf));
if(sf == NULL)
goto err_1;
__lock_acquire_recursive(__sna_lock);
bo = kgem_bo_from_handle(&sna_device->kgem, handle, bitmap->pitch, bitmap->height);
__lock_release_recursive(__sna_lock);
sf->width = bitmap->width;
sf->height = bitmap->height;
sf->data = NULL;
sf->pitch = bo->pitch;
sf->bo = bo;
sf->bo_size = PAGE_SIZE * bo->size.pages.count;
sf->flags = bitmap->flags;
bitmap->handle = (uint32_t)sf;
return 0;
err_2:
__lock_release_recursive(__sna_lock);
free(sf);
err_1:
return -1;
};
void sna_set_bo_handle(bitmap_t *bitmap, int handle)
{
surface_t *sf = to_surface(bitmap);
struct kgem_bo *bo = sf->bo;
bo->handle = handle;
}
int sna_destroy_bitmap(bitmap_t *bitmap)
{
surface_t *sf = to_surface(bitmap);
@ -686,7 +761,7 @@ int sna_blit_tex(bitmap_t *bitmap, bool scale, int dst_x, int dst_y,
VG_CLEAR(update);
update.handle = mask_bo->handle;
update.bo_map = (__u32)MAP(mask_bo->map);
update.bo_map = (int)kgem_bo_map__cpu(&sna_device->kgem, mask_bo);
drmIoctl(sna_device->kgem.fd, SRV_MASK_UPDATE, &update);
mask_bo->pitch = update.bo_pitch;
@ -756,8 +831,6 @@ int sna_blit_tex(bitmap_t *bitmap, bool scale, int dst_x, int dst_y,
static const struct intel_device_info intel_generic_info = {
.gen = -1,
};
@ -807,99 +880,36 @@ static const struct intel_device_info intel_haswell_info = {
static const struct pci_id_match intel_device_match[] = {
INTEL_I915G_IDS(&intel_i915_info),
INTEL_I915GM_IDS(&intel_i915_info),
INTEL_I945G_IDS(&intel_i945_info),
INTEL_I945GM_IDS(&intel_i945_info),
INTEL_DEVICE_MATCH (PCI_CHIP_I915_G, &intel_i915_info ),
INTEL_DEVICE_MATCH (PCI_CHIP_E7221_G, &intel_i915_info ),
INTEL_DEVICE_MATCH (PCI_CHIP_I915_GM, &intel_i915_info ),
INTEL_DEVICE_MATCH (PCI_CHIP_I945_G, &intel_i945_info ),
INTEL_DEVICE_MATCH (PCI_CHIP_I945_GM, &intel_i945_info ),
INTEL_DEVICE_MATCH (PCI_CHIP_I945_GME, &intel_i945_info ),
INTEL_G33_IDS(&intel_g33_info),
INTEL_PINEVIEW_IDS(&intel_g33_info),
INTEL_DEVICE_MATCH (PCI_CHIP_PINEVIEW_M, &intel_g33_info ),
INTEL_DEVICE_MATCH (PCI_CHIP_PINEVIEW_G, &intel_g33_info ),
INTEL_DEVICE_MATCH (PCI_CHIP_G33_G, &intel_g33_info ),
INTEL_DEVICE_MATCH (PCI_CHIP_Q33_G, &intel_g33_info ),
/* Another marketing win: Q35 is another g33 device not a gen4 part
* like its G35 brethren.
*/
INTEL_DEVICE_MATCH (PCI_CHIP_Q35_G, &intel_g33_info ),
INTEL_I965G_IDS(&intel_i965_info),
INTEL_I965GM_IDS(&intel_i965_info),
INTEL_DEVICE_MATCH (PCI_CHIP_I965_G, &intel_i965_info ),
INTEL_DEVICE_MATCH (PCI_CHIP_G35_G, &intel_i965_info ),
INTEL_DEVICE_MATCH (PCI_CHIP_I965_Q, &intel_i965_info ),
INTEL_DEVICE_MATCH (PCI_CHIP_I946_GZ, &intel_i965_info ),
INTEL_DEVICE_MATCH (PCI_CHIP_I965_GM, &intel_i965_info ),
INTEL_DEVICE_MATCH (PCI_CHIP_I965_GME, &intel_i965_info ),
INTEL_G45_IDS(&intel_g4x_info),
INTEL_GM45_IDS(&intel_g4x_info),
INTEL_DEVICE_MATCH (PCI_CHIP_GM45_GM, &intel_g4x_info ),
INTEL_DEVICE_MATCH (PCI_CHIP_G45_E_G, &intel_g4x_info ),
INTEL_DEVICE_MATCH (PCI_CHIP_G45_G, &intel_g4x_info ),
INTEL_DEVICE_MATCH (PCI_CHIP_Q45_G, &intel_g4x_info ),
INTEL_DEVICE_MATCH (PCI_CHIP_G41_G, &intel_g4x_info ),
INTEL_DEVICE_MATCH (PCI_CHIP_B43_G, &intel_g4x_info ),
INTEL_DEVICE_MATCH (PCI_CHIP_B43_G1, &intel_g4x_info ),
INTEL_IRONLAKE_D_IDS(&intel_ironlake_info),
INTEL_IRONLAKE_M_IDS(&intel_ironlake_info),
INTEL_DEVICE_MATCH (PCI_CHIP_IRONLAKE_D_G, &intel_ironlake_info ),
INTEL_DEVICE_MATCH (PCI_CHIP_IRONLAKE_M_G, &intel_ironlake_info ),
INTEL_SNB_D_IDS(&intel_sandybridge_info),
INTEL_SNB_M_IDS(&intel_sandybridge_info),
INTEL_DEVICE_MATCH (PCI_CHIP_SANDYBRIDGE_GT1, &intel_sandybridge_info ),
INTEL_DEVICE_MATCH (PCI_CHIP_SANDYBRIDGE_GT2, &intel_sandybridge_info ),
INTEL_DEVICE_MATCH (PCI_CHIP_SANDYBRIDGE_GT2_PLUS, &intel_sandybridge_info ),
INTEL_DEVICE_MATCH (PCI_CHIP_SANDYBRIDGE_M_GT1, &intel_sandybridge_info ),
INTEL_DEVICE_MATCH (PCI_CHIP_SANDYBRIDGE_M_GT2, &intel_sandybridge_info ),
INTEL_DEVICE_MATCH (PCI_CHIP_SANDYBRIDGE_M_GT2_PLUS, &intel_sandybridge_info ),
INTEL_DEVICE_MATCH (PCI_CHIP_SANDYBRIDGE_S_GT, &intel_sandybridge_info ),
INTEL_IVB_D_IDS(&intel_ivybridge_info),
INTEL_IVB_M_IDS(&intel_ivybridge_info),
INTEL_DEVICE_MATCH (PCI_CHIP_IVYBRIDGE_M_GT1, &intel_ivybridge_info ),
INTEL_DEVICE_MATCH (PCI_CHIP_IVYBRIDGE_M_GT2, &intel_ivybridge_info ),
INTEL_DEVICE_MATCH (PCI_CHIP_IVYBRIDGE_D_GT1, &intel_ivybridge_info ),
INTEL_DEVICE_MATCH (PCI_CHIP_IVYBRIDGE_D_GT2, &intel_ivybridge_info ),
INTEL_DEVICE_MATCH (PCI_CHIP_IVYBRIDGE_S_GT1, &intel_ivybridge_info ),
INTEL_DEVICE_MATCH (PCI_CHIP_IVYBRIDGE_S_GT2, &intel_ivybridge_info ),
INTEL_HSW_D_IDS(&intel_haswell_info),
INTEL_HSW_M_IDS(&intel_haswell_info),
INTEL_DEVICE_MATCH (PCI_CHIP_HASWELL_D_GT1, &intel_haswell_info ),
INTEL_DEVICE_MATCH (PCI_CHIP_HASWELL_D_GT2, &intel_haswell_info ),
INTEL_DEVICE_MATCH (PCI_CHIP_HASWELL_D_GT2_PLUS, &intel_haswell_info ),
INTEL_DEVICE_MATCH (PCI_CHIP_HASWELL_M_GT1, &intel_haswell_info ),
INTEL_DEVICE_MATCH (PCI_CHIP_HASWELL_M_GT2, &intel_haswell_info ),
INTEL_DEVICE_MATCH (PCI_CHIP_HASWELL_M_GT2_PLUS, &intel_haswell_info ),
INTEL_DEVICE_MATCH (PCI_CHIP_HASWELL_S_GT1, &intel_haswell_info ),
INTEL_DEVICE_MATCH (PCI_CHIP_HASWELL_S_GT2, &intel_haswell_info ),
INTEL_DEVICE_MATCH (PCI_CHIP_HASWELL_S_GT2_PLUS, &intel_haswell_info ),
INTEL_DEVICE_MATCH (PCI_CHIP_HASWELL_SDV_D_GT1, &intel_haswell_info ),
INTEL_DEVICE_MATCH (PCI_CHIP_HASWELL_SDV_D_GT2, &intel_haswell_info ),
INTEL_DEVICE_MATCH (PCI_CHIP_HASWELL_SDV_D_GT2_PLUS, &intel_haswell_info ),
INTEL_DEVICE_MATCH (PCI_CHIP_HASWELL_SDV_M_GT1, &intel_haswell_info ),
INTEL_DEVICE_MATCH (PCI_CHIP_HASWELL_SDV_M_GT2, &intel_haswell_info ),
INTEL_DEVICE_MATCH (PCI_CHIP_HASWELL_SDV_M_GT2_PLUS, &intel_haswell_info ),
INTEL_DEVICE_MATCH (PCI_CHIP_HASWELL_SDV_S_GT1, &intel_haswell_info ),
INTEL_DEVICE_MATCH (PCI_CHIP_HASWELL_SDV_S_GT2, &intel_haswell_info ),
INTEL_DEVICE_MATCH (PCI_CHIP_HASWELL_SDV_S_GT2_PLUS, &intel_haswell_info ),
INTEL_DEVICE_MATCH (PCI_CHIP_HASWELL_ULT_D_GT1, &intel_haswell_info ),
INTEL_DEVICE_MATCH (PCI_CHIP_HASWELL_ULT_D_GT2, &intel_haswell_info ),
INTEL_DEVICE_MATCH (PCI_CHIP_HASWELL_ULT_D_GT2_PLUS, &intel_haswell_info ),
INTEL_DEVICE_MATCH (PCI_CHIP_HASWELL_ULT_M_GT1, &intel_haswell_info ),
INTEL_DEVICE_MATCH (PCI_CHIP_HASWELL_ULT_M_GT2, &intel_haswell_info ),
INTEL_DEVICE_MATCH (PCI_CHIP_HASWELL_ULT_M_GT2_PLUS, &intel_haswell_info ),
INTEL_DEVICE_MATCH (PCI_CHIP_HASWELL_ULT_S_GT1, &intel_haswell_info ),
INTEL_DEVICE_MATCH (PCI_CHIP_HASWELL_ULT_S_GT2, &intel_haswell_info ),
INTEL_DEVICE_MATCH (PCI_CHIP_HASWELL_ULT_S_GT2_PLUS, &intel_haswell_info ),
INTEL_DEVICE_MATCH (PCI_CHIP_HASWELL_CRW_D_GT1, &intel_haswell_info ),
INTEL_DEVICE_MATCH (PCI_CHIP_HASWELL_CRW_D_GT2, &intel_haswell_info ),
INTEL_DEVICE_MATCH (PCI_CHIP_HASWELL_CRW_D_GT2_PLUS, &intel_haswell_info ),
INTEL_DEVICE_MATCH (PCI_CHIP_HASWELL_CRW_M_GT1, &intel_haswell_info ),
INTEL_DEVICE_MATCH (PCI_CHIP_HASWELL_CRW_M_GT2, &intel_haswell_info ),
INTEL_DEVICE_MATCH (PCI_CHIP_HASWELL_CRW_M_GT2_PLUS, &intel_haswell_info ),
INTEL_DEVICE_MATCH (PCI_CHIP_HASWELL_CRW_S_GT1, &intel_haswell_info ),
INTEL_DEVICE_MATCH (PCI_CHIP_HASWELL_CRW_S_GT2, &intel_haswell_info ),
INTEL_DEVICE_MATCH (PCI_CHIP_HASWELL_CRW_S_GT2_PLUS, &intel_haswell_info ),
INTEL_VLV_D_IDS(&intel_valleyview_info),
INTEL_VLV_M_IDS(&intel_valleyview_info),
INTEL_DEVICE_MATCH (PCI_CHIP_VALLEYVIEW_PO, &intel_valleyview_info ),
INTEL_DEVICE_MATCH (PCI_CHIP_VALLEYVIEW_1, &intel_valleyview_info ),
INTEL_DEVICE_MATCH (PCI_CHIP_VALLEYVIEW_2, &intel_valleyview_info ),
INTEL_DEVICE_MATCH (PCI_CHIP_VALLEYVIEW_3, &intel_valleyview_info ),
INTEL_DEVICE_MATCH (PCI_MATCH_ANY, &intel_generic_info ),
INTEL_VGA_DEVICE(PCI_MATCH_ANY, &intel_generic_info),
{ 0, 0, 0 },
};
@ -948,6 +958,20 @@ intel_detect_chipset(struct pci_device *pci)
}
int intel_get_device_id(int fd)
{
struct drm_i915_getparam gp;
int devid = 0;
memset(&gp, 0, sizeof(gp));
gp.param = I915_PARAM_CHIPSET_ID;
gp.value = &devid;
if (drmIoctl(fd, DRM_IOCTL_I915_GETPARAM, &gp))
return 0;
return devid;
}
int drmIoctl(int fd, unsigned long request, void *arg)
{

View File

@ -37,25 +37,82 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#ifndef _SNA_H_
#define _SNA_H_
#include <stdint.h>
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdint.h>
#include "compiler.h"
#include <memory.h>
#include <malloc.h>
#include <errno.h>
#include <kos32sys.h>
#include "intel_driver.h"
#include "pciaccess.h"
#include "compiler.h"
#include <drm.h>
#include <i915_drm.h>
//#define DBG(x)
//#define DBG(x) ErrorF x
#ifdef HAVE_DRI2_H
#include <dri2.h>
#endif
#define assert(x)
#if HAVE_UDEV
#include <libudev.h>
#endif
#if 0
#include <xorg-server.h>
#include <xf86Crtc.h>
#if XF86_CRTC_VERSION >= 5
#define HAS_PIXMAP_SHARING 1
#endif
#include <xf86str.h>
#include <windowstr.h>
#include <glyphstr.h>
#include <picturestr.h>
#include <gcstruct.h>
#include <xvdix.h>
#include <pciaccess.h>
#include <xf86drmMode.h>
#include "../compat-api.h"
#endif
#include <assert.h>
#define ErrorF printf
#if HAS_DEBUG_FULL
#define DBG(x) ErrorF x
#else
#define DBG(x)
#endif
#define DEBUG_NO_BLT 0
#define DEBUG_FLUSH_BATCH 0
#define TEST_ALL 0
#define TEST_ACCEL (TEST_ALL || 0)
#define TEST_BATCH (TEST_ALL || 0)
#define TEST_BLT (TEST_ALL || 0)
#define TEST_COMPOSITE (TEST_ALL || 0)
#define TEST_DAMAGE (TEST_ALL || 0)
#define TEST_GRADIENT (TEST_ALL || 0)
#define TEST_GLYPHS (TEST_ALL || 0)
#define TEST_IO (TEST_ALL || 0)
#define TEST_KGEM (TEST_ALL || 0)
#define TEST_RENDER (TEST_ALL || 0)
int drmIoctl(int fd, unsigned long request, void *arg);
@ -94,12 +151,69 @@ typedef enum {
PIXMAN_x2b10g10r10 = PIXMAN_FORMAT(32,PIXMAN_TYPE_ABGR,0,10,10,10),
PIXMAN_a2b10g10r10 = PIXMAN_FORMAT(32,PIXMAN_TYPE_ABGR,2,10,10,10),
PIXMAN_a8 = PIXMAN_FORMAT(8,PIXMAN_TYPE_A,8,0,0,0)
/* sRGB formats */
PIXMAN_a8r8g8b8_sRGB = PIXMAN_FORMAT(32,PIXMAN_TYPE_ARGB_SRGB,8,8,8,8),
/* 24bpp formats */
PIXMAN_r8g8b8 = PIXMAN_FORMAT(24,PIXMAN_TYPE_ARGB,0,8,8,8),
PIXMAN_b8g8r8 = PIXMAN_FORMAT(24,PIXMAN_TYPE_ABGR,0,8,8,8),
/* 16bpp formats */
PIXMAN_r5g6b5 = PIXMAN_FORMAT(16,PIXMAN_TYPE_ARGB,0,5,6,5),
PIXMAN_b5g6r5 = PIXMAN_FORMAT(16,PIXMAN_TYPE_ABGR,0,5,6,5),
PIXMAN_a1r5g5b5 = PIXMAN_FORMAT(16,PIXMAN_TYPE_ARGB,1,5,5,5),
PIXMAN_x1r5g5b5 = PIXMAN_FORMAT(16,PIXMAN_TYPE_ARGB,0,5,5,5),
PIXMAN_a1b5g5r5 = PIXMAN_FORMAT(16,PIXMAN_TYPE_ABGR,1,5,5,5),
PIXMAN_x1b5g5r5 = PIXMAN_FORMAT(16,PIXMAN_TYPE_ABGR,0,5,5,5),
PIXMAN_a4r4g4b4 = PIXMAN_FORMAT(16,PIXMAN_TYPE_ARGB,4,4,4,4),
PIXMAN_x4r4g4b4 = PIXMAN_FORMAT(16,PIXMAN_TYPE_ARGB,0,4,4,4),
PIXMAN_a4b4g4r4 = PIXMAN_FORMAT(16,PIXMAN_TYPE_ABGR,4,4,4,4),
PIXMAN_x4b4g4r4 = PIXMAN_FORMAT(16,PIXMAN_TYPE_ABGR,0,4,4,4),
/* 8bpp formats */
PIXMAN_a8 = PIXMAN_FORMAT(8,PIXMAN_TYPE_A,8,0,0,0),
PIXMAN_r3g3b2 = PIXMAN_FORMAT(8,PIXMAN_TYPE_ARGB,0,3,3,2),
PIXMAN_b2g3r3 = PIXMAN_FORMAT(8,PIXMAN_TYPE_ABGR,0,3,3,2),
PIXMAN_a2r2g2b2 = PIXMAN_FORMAT(8,PIXMAN_TYPE_ARGB,2,2,2,2),
PIXMAN_a2b2g2r2 = PIXMAN_FORMAT(8,PIXMAN_TYPE_ABGR,2,2,2,2),
PIXMAN_c8 = PIXMAN_FORMAT(8,PIXMAN_TYPE_COLOR,0,0,0,0),
PIXMAN_g8 = PIXMAN_FORMAT(8,PIXMAN_TYPE_GRAY,0,0,0,0),
PIXMAN_x4a4 = PIXMAN_FORMAT(8,PIXMAN_TYPE_A,4,0,0,0),
PIXMAN_x4c4 = PIXMAN_FORMAT(8,PIXMAN_TYPE_COLOR,0,0,0,0),
PIXMAN_x4g4 = PIXMAN_FORMAT(8,PIXMAN_TYPE_GRAY,0,0,0,0),
/* 4bpp formats */
PIXMAN_a4 = PIXMAN_FORMAT(4,PIXMAN_TYPE_A,4,0,0,0),
PIXMAN_r1g2b1 = PIXMAN_FORMAT(4,PIXMAN_TYPE_ARGB,0,1,2,1),
PIXMAN_b1g2r1 = PIXMAN_FORMAT(4,PIXMAN_TYPE_ABGR,0,1,2,1),
PIXMAN_a1r1g1b1 = PIXMAN_FORMAT(4,PIXMAN_TYPE_ARGB,1,1,1,1),
PIXMAN_a1b1g1r1 = PIXMAN_FORMAT(4,PIXMAN_TYPE_ABGR,1,1,1,1),
PIXMAN_c4 = PIXMAN_FORMAT(4,PIXMAN_TYPE_COLOR,0,0,0,0),
PIXMAN_g4 = PIXMAN_FORMAT(4,PIXMAN_TYPE_GRAY,0,0,0,0),
/* 1bpp formats */
PIXMAN_a1 = PIXMAN_FORMAT(1,PIXMAN_TYPE_A,1,0,0,0),
PIXMAN_g1 = PIXMAN_FORMAT(1,PIXMAN_TYPE_GRAY,0,0,0,0),
/* YUV formats */
PIXMAN_yuy2 = PIXMAN_FORMAT(16,PIXMAN_TYPE_YUY2,0,0,0,0),
PIXMAN_yv12 = PIXMAN_FORMAT(12,PIXMAN_TYPE_YV12,0,0,0,0)
} pixman_format_code_t;
typedef enum _PictFormatShort {
PICT_a2r10g10b10 = PIXMAN_a2r10g10b10,
PICT_x2r10g10b10 = PIXMAN_x2r10g10b10,
PICT_a2b10g10r10 = PIXMAN_a2b10g10r10,
PICT_x2b10g10r10 = PIXMAN_x2b10g10r10,
PICT_a8r8g8b8 = PIXMAN_a8r8g8b8,
PICT_x8r8g8b8 = PIXMAN_x8r8g8b8,
PICT_a8b8g8r8 = PIXMAN_a8b8g8r8,
@ -107,10 +221,52 @@ typedef enum _PictFormatShort {
PICT_b8g8r8a8 = PIXMAN_b8g8r8a8,
PICT_b8g8r8x8 = PIXMAN_b8g8r8x8,
/* 24bpp formats */
PICT_r8g8b8 = PIXMAN_r8g8b8,
PICT_b8g8r8 = PIXMAN_b8g8r8,
/* 16bpp formats */
PICT_r5g6b5 = PIXMAN_r5g6b5,
PICT_b5g6r5 = PIXMAN_b5g6r5,
PICT_a1r5g5b5 = PIXMAN_a1r5g5b5,
PICT_x1r5g5b5 = PIXMAN_x1r5g5b5,
PICT_a1b5g5r5 = PIXMAN_a1b5g5r5,
PICT_x1b5g5r5 = PIXMAN_x1b5g5r5,
PICT_a4r4g4b4 = PIXMAN_a4r4g4b4,
PICT_x4r4g4b4 = PIXMAN_x4r4g4b4,
PICT_a4b4g4r4 = PIXMAN_a4b4g4r4,
PICT_x4b4g4r4 = PIXMAN_x4b4g4r4,
/* 8bpp formats */
PICT_a8 = PIXMAN_a8,
PICT_r3g3b2 = PIXMAN_r3g3b2,
PICT_b2g3r3 = PIXMAN_b2g3r3,
PICT_a2r2g2b2 = PIXMAN_a2r2g2b2,
PICT_a2b2g2r2 = PIXMAN_a2b2g2r2,
PICT_c8 = PIXMAN_c8,
PICT_g8 = PIXMAN_g8,
PICT_x4a4 = PIXMAN_x4a4,
PICT_x4c4 = PIXMAN_x4c4,
PICT_x4g4 = PIXMAN_x4g4,
/* 4bpp formats */
PICT_a4 = PIXMAN_a4,
PICT_r1g2b1 = PIXMAN_r1g2b1,
PICT_b1g2r1 = PIXMAN_b1g2r1,
PICT_a1r1g1b1 = PIXMAN_a1r1g1b1,
PICT_a1b1g1r1 = PIXMAN_a1b1g1r1,
PICT_c4 = PIXMAN_c4,
PICT_g4 = PIXMAN_g4,
/* 1bpp formats */
PICT_a1 = PIXMAN_a1,
PICT_g1 = PIXMAN_g1
} PictFormatShort;
#define PIXMAN_FORMAT_A(f) (((f) >> 12) & 0x0f)
@ -266,29 +422,53 @@ typedef unsigned short CARD16;
#define PictOpMaximum 13
#define SNA_CURSOR_X 64
#define SNA_CURSOR_Y SNA_CURSOR_X
struct sna_client {
int is_compositor; /* only 4 bits used */
};
//#define assert(x)
struct sna {
struct kgem kgem;
unsigned scrn;
unsigned flags;
#define SNA_NO_WAIT 0x1
#define SNA_NO_FLIP 0x2
#define SNA_TRIPLE_BUFFER 0x4
#define SNA_TEAR_FREE 0x10
#define SNA_FORCE_SHADOW 0x20
#define SNA_FLUSH_GTT 0x40
#define SNA_IS_HOSTED 0x80
#define SNA_PERFORMANCE 0x100
#define SNA_POWERSAVE 0x200
#define SNA_REPROBE 0x80000000
unsigned cpu_features;
#define MMX 0x1
#define SSE 0x2
#define SSE2 0x4
#define SSE3 0x8
#define SSSE3 0x10
#define SSE4_1 0x20
#define SSE4_2 0x40
#define AVX 0x80
#define AVX2 0x100
struct list flush_pixmaps;
struct list active_pixmaps;
// int vblank_interval;
// struct list deferred_free;
// struct list dirty_pixmaps;
// struct list active_pixmaps;
// struct list inactive_clock[2];
unsigned int tiling;
#define SNA_TILING_DISABLE 0x0
#define SNA_TILING_FB 0x1
#define SNA_TILING_2D 0x2
#define SNA_TILING_ALL (~0)
@ -303,7 +483,6 @@ struct sna {
uint32_t fill_alu;
} blt_state;
union {
// struct gen2_render_state gen2;
struct gen3_render_state gen3;
struct gen4_render_state gen4;
struct gen5_render_state gen5;
@ -318,12 +497,11 @@ struct sna {
/* Driver phase/state information */
// Bool suspended;
struct kgem kgem;
struct sna_render render;
#if DEBUG_MEMORY
struct {
int shadow_pixels_allocs;
int pixmap_allocs;
int cpu_bo_allocs;
size_t shadow_pixels_bytes;
size_t cpu_bo_bytes;
@ -352,4 +530,78 @@ to_sna_from_kgem(struct kgem *kgem)
#ifndef MAX
#define MAX(a,b) ((a) >= (b) ? (a) : (b))
#endif
static inline bool
_sna_transform_point(const PictTransform *transform,
int64_t x, int64_t y, int64_t result[3])
{
int j;
for (j = 0; j < 3; j++)
result[j] = (transform->matrix[j][0] * x +
transform->matrix[j][1] * y +
transform->matrix[j][2]);
return result[2] != 0;
}
static inline void
_sna_get_transformed_coordinates(int x, int y,
const PictTransform *transform,
float *x_out, float *y_out)
{
int64_t result[3];
_sna_transform_point(transform, x, y, result);
*x_out = result[0] / (double)result[2];
*y_out = result[1] / (double)result[2];
}
static inline void
_sna_get_transformed_scaled(int x, int y,
const PictTransform *transform, const float *sf,
float *x_out, float *y_out)
{
*x_out = sf[0] * (transform->matrix[0][0] * x +
transform->matrix[0][1] * y +
transform->matrix[0][2]);
*y_out = sf[1] * (transform->matrix[1][0] * x +
transform->matrix[1][1] * y +
transform->matrix[1][2]);
}
void
sna_get_transformed_coordinates(int x, int y,
const PictTransform *transform,
float *x_out, float *y_out);
void
sna_get_transformed_coordinates_3d(int x, int y,
const PictTransform *transform,
float *x_out, float *y_out, float *z_out);
bool sna_transform_is_affine(const PictTransform *t);
bool sna_transform_is_integer_translation(const PictTransform *t,
int16_t *tx, int16_t *ty);
bool sna_transform_is_translation(const PictTransform *t,
pixman_fixed_t *tx, pixman_fixed_t *ty);
static inline bool
sna_affine_transform_is_rotation(const PictTransform *t)
{
assert(sna_transform_is_affine(t));
return t->matrix[0][1] | t->matrix[1][0];
}
static inline bool
sna_transform_equal(const PictTransform *a, const PictTransform *b)
{
if (a == b)
return true;
if (a == NULL || b == NULL)
return false;
return memcmp(a, b, sizeof(*a)) == 0;
}
#endif /* _SNA_H */

View File

@ -0,0 +1,116 @@
/*
* Copyright (c) 2013 Intel Corporation
*
* 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, sublicense,
* 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 NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS 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.
*
* Authors:
* Chris Wilson <chris@chris-wilson.co.uk>
*
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "sna.h"
#include "sna_cpuid.h"
#define xgetbv(index,eax,edx) \
__asm__ ("xgetbv" : "=a"(eax), "=d"(edx) : "c" (index))
#define has_YMM 0x1
unsigned sna_cpu_detect(void)
{
unsigned max = __get_cpuid_max(BASIC_CPUID, NULL);
unsigned int eax, ebx, ecx, edx;
unsigned features = 0;
unsigned extra = 0;
if (max >= 1) {
__cpuid(1, eax, ebx, ecx, edx);
if (ecx & bit_SSE3)
features |= SSE3;
if (ecx & bit_SSSE3)
features |= SSSE3;
if (ecx & bit_SSE4_1)
features |= SSE4_1;
if (ecx & bit_SSE4_2)
features |= SSE4_2;
if (ecx & bit_OSXSAVE) {
unsigned int bv_eax, bv_ecx;
xgetbv(0, bv_eax, bv_ecx);
if ((bv_eax & 6) == 6)
extra |= has_YMM;
}
if ((extra & has_YMM) && (ecx & bit_AVX))
features |= AVX;
if (edx & bit_MMX)
features |= MMX;
if (edx & bit_SSE)
features |= SSE;
if (edx & bit_SSE2)
features |= SSE2;
}
if (max >= 7) {
__cpuid_count(7, 0, eax, ebx, ecx, edx);
if ((extra & has_YMM) && (ebx & bit_AVX2))
features |= AVX2;
}
return features;
}
char *sna_cpu_features_to_string(unsigned features, char *line)
{
char *ret = line;
#ifdef __x86_64__
line += sprintf (line, "x86-64");
#else
line += sprintf (line, "x86");
#endif
if (features & SSE2)
line += sprintf (line, ", sse2");
if (features & SSE3)
line += sprintf (line, ", sse3");
if (features & SSSE3)
line += sprintf (line, ", ssse3");
if (features & SSE4_1)
line += sprintf (line, ", sse4.1");
if (features & SSE4_2)
line += sprintf (line, ", sse4.2");
if (features & AVX)
line += sprintf (line, ", avx");
if (features & AVX2)
line += sprintf (line, ", avx2");
return ret;
}

View File

@ -0,0 +1,86 @@
/*
* Copyright (c) 2013 Intel Corporation
*
* 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, sublicense,
* 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 NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS 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.
*
* Authors:
* Chris Wilson <chris@chris-wilson.co.uk>
*
*/
/* Small wrapper around compiler specific implementation details of cpuid */
#ifndef SNA_CPUID_H
#define SNA_CPUID_H
#include "compiler.h"
#if HAS_GCC(4, 4) /* for __cpuid_count() */
#include <cpuid.h>
#else
#define __get_cpuid_max(x, y) 0
#define __cpuid(level, a, b, c, d)
#define __cpuid_count(level, count, a, b, c, d)
#endif
#define BASIC_CPUID 0x0
#define EXTENDED_CPUID 0x80000000
#ifndef bit_MMX
#define bit_MMX (1 << 23)
#endif
#ifndef bit_SSE
#define bit_SSE (1 << 25)
#endif
#ifndef bit_SSE2
#define bit_SSE2 (1 << 26)
#endif
#ifndef bit_SSE3
#define bit_SSE3 (1 << 0)
#endif
#ifndef bit_SSSE3
#define bit_SSSE3 (1 << 9)
#endif
#ifndef bit_SSE4_1
#define bit_SSE4_1 (1 << 19)
#endif
#ifndef bit_SSE4_2
#define bit_SSE4_2 (1 << 20)
#endif
#ifndef bit_OSXSAVE
#define bit_OSXSAVE (1 << 27)
#endif
#ifndef bit_AVX
#define bit_AVX (1 << 28)
#endif
#ifndef bit_AVX2
#define bit_AVX2 (1<<5)
#endif
#endif /* SNA_CPUID_H */

View File

@ -30,11 +30,7 @@ struct sna_composite_rectangles {
struct sna_composite_op {
fastcall void (*blt)(struct sna *sna, const struct sna_composite_op *op,
const struct sna_composite_rectangles *r);
fastcall void (*box)(struct sna *sna,
const struct sna_composite_op *op,
const BoxRec *box);
void (*boxes)(struct sna *sna, const struct sna_composite_op *op,
const BoxRec *box, int nbox);
void (*done)(struct sna *sna, const struct sna_composite_op *op);
struct sna_damage **damage;
@ -192,9 +188,6 @@ struct sna_render {
struct sna_video *video,
struct sna_video_frame *frame,
RegionPtr dstRegion,
short src_w, short src_h,
short drw_w, short drw_h,
short dx, short dy,
PixmapPtr pixmap);
bool (*fill_boxes)(struct sna *sna,
@ -358,10 +351,10 @@ struct gen5_render_state {
int ve_id;
uint32_t drawrect_offset;
uint32_t drawrect_limit;
uint32_t last_pipelined_pointers;
uint16_t last_primitive;
int16_t floats_per_vertex;
uint16_t surface_table;
uint16_t last_pipelined_pointers;
bool needs_invariant;
};
@ -505,17 +498,15 @@ bool sna_get_rgba_from_pixel(uint32_t pixel,
uint32_t format);
bool sna_picture_is_solid(PicturePtr picture, uint32_t *color);
void no_render_init(struct sna *sna);
bool gen2_render_init(struct sna *sna);
bool gen3_render_init(struct sna *sna);
bool gen4_render_init(struct sna *sna);
bool gen5_render_init(struct sna *sna);
bool gen6_render_init(struct sna *sna);
bool gen7_render_init(struct sna *sna);
const char *no_render_init(struct sna *sna);
const char *gen2_render_init(struct sna *sna, const char *backend);
const char *gen3_render_init(struct sna *sna, const char *backend);
const char *gen4_render_init(struct sna *sna, const char *backend);
const char *gen5_render_init(struct sna *sna, const char *backend);
const char *gen6_render_init(struct sna *sna, const char *backend);
const char *gen7_render_init(struct sna *sna, const char *backend);
#if 0
bool sna_tiling_composite(uint32_t op,
PicturePtr src,
PicturePtr mask,
@ -683,7 +674,8 @@ inline static void sna_render_composite_redirect_init(struct sna_composite_op *o
bool
sna_render_composite_redirect(struct sna *sna,
struct sna_composite_op *op,
int x, int y, int width, int height);
int x, int y, int width, int height,
bool partial);
void
sna_render_composite_redirect_done(struct sna *sna,
@ -691,8 +683,8 @@ sna_render_composite_redirect_done(struct sna *sna,
bool
sna_composite_mask_is_opaque(PicturePtr mask);
#endif
void sna_vertex_init(struct sna *sna);
static inline void sna_vertex_lock(struct sna_render *r)
@ -726,4 +718,69 @@ static inline bool sna_vertex_wait__locked(struct sna_render *r)
return was_active;
}
#define alphaless(format) PICT_FORMAT(PICT_FORMAT_BPP(format), \
PICT_FORMAT_TYPE(format), \
0, \
PICT_FORMAT_R(format), \
PICT_FORMAT_G(format), \
PICT_FORMAT_B(format))
static bool
gen3_blit_tex(struct sna *sna,
uint8_t op, bool scale,
PixmapPtr src, struct kgem_bo *src_bo,
PixmapPtr mask,struct kgem_bo *mask_bo,
PixmapPtr dst, struct kgem_bo *dst_bo,
int32_t src_x, int32_t src_y,
int32_t msk_x, int32_t msk_y,
int32_t dst_x, int32_t dst_y,
int32_t width, int32_t height,
struct sna_composite_op *tmp);
static bool
gen4_blit_tex(struct sna *sna,
uint8_t op, bool scale,
PixmapPtr src, struct kgem_bo *src_bo,
PixmapPtr mask,struct kgem_bo *mask_bo,
PixmapPtr dst, struct kgem_bo *dst_bo,
int32_t src_x, int32_t src_y,
int32_t msk_x, int32_t msk_y,
int32_t dst_x, int32_t dst_y,
int32_t width, int32_t height,
struct sna_composite_op *tmp);
static bool
gen5_blit_tex(struct sna *sna,
uint8_t op, bool scale,
PixmapPtr src, struct kgem_bo *src_bo,
PixmapPtr mask,struct kgem_bo *mask_bo,
PixmapPtr dst, struct kgem_bo *dst_bo,
int32_t src_x, int32_t src_y,
int32_t msk_x, int32_t msk_y,
int32_t dst_x, int32_t dst_y,
int32_t width, int32_t height,
struct sna_composite_op *tmp);
static bool
gen6_blit_tex(struct sna *sna,
uint8_t op, bool scale,
PixmapPtr src, struct kgem_bo *src_bo,
PixmapPtr mask,struct kgem_bo *mask_bo,
PixmapPtr dst, struct kgem_bo *dst_bo,
int32_t src_x, int32_t src_y,
int32_t msk_x, int32_t msk_y,
int32_t dst_x, int32_t dst_y,
int32_t width, int32_t height,
struct sna_composite_op *tmp);
static bool
gen7_blit_tex(struct sna *sna,
uint8_t op, bool scale,
PixmapPtr src, struct kgem_bo *src_bo,
PixmapPtr mask,struct kgem_bo *mask_bo,
PixmapPtr dst, struct kgem_bo *dst_bo,
int32_t src_x, int32_t src_y,
int32_t msk_x, int32_t msk_y,
int32_t dst_x, int32_t dst_y,
int32_t width, int32_t height,
struct sna_composite_op *tmp);
#endif /* SNA_RENDER_H */

View File

@ -17,7 +17,7 @@ static inline bool need_redirect(struct sna *sna, PixmapPtr dst)
dst->drawable.height > sna->render.max_3d_size);
}
static inline float pack_2s(int16_t x, int16_t y)
static force_inline float pack_2s(int16_t x, int16_t y)
{
union {
struct sna_coordinate p;
@ -28,35 +28,35 @@ static inline float pack_2s(int16_t x, int16_t y)
return u.f;
}
static inline int vertex_space(struct sna *sna)
static force_inline int vertex_space(struct sna *sna)
{
return sna->render.vertex_size - sna->render.vertex_used;
}
static inline void vertex_emit(struct sna *sna, float v)
static force_inline void vertex_emit(struct sna *sna, float v)
{
assert(sna->render.vertex_used < sna->render.vertex_size);
sna->render.vertices[sna->render.vertex_used++] = v;
}
static inline void vertex_emit_2s(struct sna *sna, int16_t x, int16_t y)
static force_inline void vertex_emit_2s(struct sna *sna, int16_t x, int16_t y)
{
vertex_emit(sna, pack_2s(x, y));
}
static inline int batch_space(struct sna *sna)
static force_inline int batch_space(struct sna *sna)
{
assert(sna->kgem.nbatch <= KGEM_BATCH_SIZE(&sna->kgem));
assert(sna->kgem.nbatch + KGEM_BATCH_RESERVED <= sna->kgem.surface);
return sna->kgem.surface - sna->kgem.nbatch - KGEM_BATCH_RESERVED;
}
static inline void batch_emit(struct sna *sna, uint32_t dword)
static force_inline void batch_emit(struct sna *sna, uint32_t dword)
{
assert(sna->kgem.mode != KGEM_NONE);
assert(sna->kgem.nbatch + KGEM_BATCH_RESERVED < sna->kgem.surface);
sna->kgem.batch[sna->kgem.nbatch++] = dword;
}
static inline void batch_emit_float(struct sna *sna, float f)
static force_inline void batch_emit_float(struct sna *sna, float f)
{
union {
uint32_t dw;
@ -67,5 +67,4 @@ static inline void batch_emit_float(struct sna *sna, float f)
}
#endif /* SNA_RENDER_INLINE_H */

View File

@ -0,0 +1,147 @@
/*
* Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. All Rights Reserved.
* Copyright (c) 2005 Jesse Barnes <jbarnes@virtuousgeek.org>
* Copyright © 2010 Intel Corporation
*
* 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, sublicense,
* 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 NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS 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.
*
* Authors:
* Jesse Barns <jbarnes@virtuousgeek.org>
* Chris Wilson <chris@chris-wilson.co.uk>
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "sna.h"
#define pixman_fixed_e ((pixman_fixed_t) 1)
#define pixman_fixed_1 (pixman_int_to_fixed(1))
#define pixman_fixed_1_minus_e (pixman_fixed_1 - pixman_fixed_e)
#define pixman_fixed_to_int(f) ((int) ((f) >> 16))
#define pixman_int_to_fixed(i) ((pixman_fixed_t) ((i) << 16))
#define pixman_fixed_fraction(f) ((f) & pixman_fixed_1_minus_e)
#define IntToxFixed(i) pixman_int_to_fixed(i)
/**
* Returns whether the provided transform is affine.
*
* transform may be null.
*/
bool sna_transform_is_affine(const PictTransform *t)
{
if (t == NULL)
return true;
return t->matrix[2][0] == 0 && t->matrix[2][1] == 0;
}
bool
sna_transform_is_translation(const PictTransform *t,
pixman_fixed_t *tx,
pixman_fixed_t *ty)
{
if (t == NULL) {
*tx = *ty = 0;
return true;
}
if (t->matrix[0][0] != IntToxFixed(1) ||
t->matrix[0][1] != 0 ||
t->matrix[1][0] != 0 ||
t->matrix[1][1] != IntToxFixed(1) ||
t->matrix[2][0] != 0 ||
t->matrix[2][1] != 0 ||
t->matrix[2][2] != IntToxFixed(1))
return false;
*tx = t->matrix[0][2];
*ty = t->matrix[1][2];
return true;
}
bool
sna_transform_is_integer_translation(const PictTransform *t, int16_t *tx, int16_t *ty)
{
if (t == NULL) {
*tx = *ty = 0;
return true;
}
if (t->matrix[0][0] != IntToxFixed(1) ||
t->matrix[0][1] != 0 ||
t->matrix[1][0] != 0 ||
t->matrix[1][1] != IntToxFixed(1) ||
t->matrix[2][0] != 0 ||
t->matrix[2][1] != 0 ||
t->matrix[2][2] != IntToxFixed(1))
return false;
if (pixman_fixed_fraction(t->matrix[0][2]) ||
pixman_fixed_fraction(t->matrix[1][2]))
return false;
*tx = pixman_fixed_to_int(t->matrix[0][2]);
*ty = pixman_fixed_to_int(t->matrix[1][2]);
return true;
}
/**
* Returns the floating-point coordinates transformed by the given transform.
*/
void
sna_get_transformed_coordinates(int x, int y,
const PictTransform *transform,
float *x_out, float *y_out)
{
if (transform == NULL) {
*x_out = x;
*y_out = y;
} else
_sna_get_transformed_coordinates(x, y, transform, x_out, y_out);
}
/**
* Returns the un-normalized floating-point coordinates transformed by the given transform.
*/
void
sna_get_transformed_coordinates_3d(int x, int y,
const PictTransform *transform,
float *x_out, float *y_out, float *w_out)
{
if (transform == NULL) {
*x_out = x;
*y_out = y;
*w_out = 1;
} else {
int64_t result[3];
if (_sna_transform_point(transform, x, y, result)) {
*x_out = result[0] / 65536.;
*y_out = result[1] / 65536.;
*w_out = result[2] / 65536.;
} else {
*x_out = *y_out = 0;
*w_out = 1.;
}
}
}