Subversion Repositories Kolibri OS

Rev

Rev 3769 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
3299 Serge 1
/*
2
 * Copyright © 2010-2011 Intel Corporation
3
 *
4
 * Permission is hereby granted, free of charge, to any person obtaining a
5
 * copy of this software and associated documentation files (the "Software"),
6
 * to deal in the Software without restriction, including without limitation
7
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8
 * and/or sell copies of the Software, and to permit persons to whom the
9
 * Software is furnished to do so, subject to the following conditions:
10
 *
11
 * The above copyright notice and this permission notice (including the next
12
 * paragraph) shall be included in all copies or substantial portions of the
13
 * Software.
14
 *
15
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
 * SOFTWARE.
22
 *
23
 * Authors:
24
 *    Chris Wilson 
25
 *
26
 */
27
 
28
#ifdef HAVE_CONFIG_H
29
#include "config.h"
30
#endif
31
 
32
#include "sna.h"
33
#include "sna_render.h"
34
#include "sna_render_inline.h"
35
#include "sna_reg.h"
36
//#include "sna_video.h"
37
 
38
#include "gen3_render.h"
39
 
40
#define NO_COMPOSITE 0
41
#define NO_COMPOSITE_SPANS 0
42
#define NO_COPY 0
43
#define NO_COPY_BOXES 0
44
#define NO_FILL 0
45
#define NO_FILL_ONE 0
46
#define NO_FILL_BOXES 0
47
 
48
#define PREFER_BLT_FILL 1
49
 
50
enum {
51
	SHADER_NONE = 0,
52
	SHADER_ZERO,
53
	SHADER_BLACK,
54
	SHADER_WHITE,
55
	SHADER_CONSTANT,
56
	SHADER_LINEAR,
57
	SHADER_RADIAL,
58
	SHADER_TEXTURE,
59
	SHADER_OPACITY,
60
};
61
 
62
#define MAX_3D_SIZE 2048
63
#define MAX_3D_PITCH 8192
64
 
65
#define OUT_BATCH(v) batch_emit(sna, v)
66
#define OUT_BATCH_F(v) batch_emit_float(sna, v)
67
#define OUT_VERTEX(v) vertex_emit(sna, v)
68
 
69
enum gen3_radial_mode {
70
	RADIAL_ONE,
71
	RADIAL_TWO
72
};
73
 
74
static const struct blendinfo {
75
	bool dst_alpha;
76
	bool src_alpha;
77
	uint32_t src_blend;
78
	uint32_t dst_blend;
79
} gen3_blend_op[] = {
80
	/* Clear */	{0, 0, BLENDFACT_ZERO, BLENDFACT_ZERO},
81
	/* Src */	{0, 0, BLENDFACT_ONE, BLENDFACT_ZERO},
82
	/* Dst */	{0, 0, BLENDFACT_ZERO, BLENDFACT_ONE},
83
	/* Over */	{0, 1, BLENDFACT_ONE, BLENDFACT_INV_SRC_ALPHA},
84
	/* OverReverse */ {1, 0, BLENDFACT_INV_DST_ALPHA, BLENDFACT_ONE},
85
	/* In */	{1, 0, BLENDFACT_DST_ALPHA, BLENDFACT_ZERO},
86
	/* InReverse */ {0, 1, BLENDFACT_ZERO, BLENDFACT_SRC_ALPHA},
87
	/* Out */	{1, 0, BLENDFACT_INV_DST_ALPHA, BLENDFACT_ZERO},
88
	/* OutReverse */ {0, 1, BLENDFACT_ZERO, BLENDFACT_INV_SRC_ALPHA},
89
	/* Atop */	{1, 1, BLENDFACT_DST_ALPHA, BLENDFACT_INV_SRC_ALPHA},
90
	/* AtopReverse */ {1, 1, BLENDFACT_INV_DST_ALPHA, BLENDFACT_SRC_ALPHA},
91
	/* Xor */	{1, 1, BLENDFACT_INV_DST_ALPHA, BLENDFACT_INV_SRC_ALPHA},
92
	/* Add */	{0, 0, BLENDFACT_ONE, BLENDFACT_ONE},
93
};
94
 
95
#define S6_COLOR_WRITE_ONLY \
96
	(S6_COLOR_WRITE_ENABLE | \
97
	 BLENDFUNC_ADD << S6_CBUF_BLEND_FUNC_SHIFT | \
98
	 BLENDFACT_ONE << S6_CBUF_SRC_BLEND_FACT_SHIFT | \
99
	 BLENDFACT_ZERO << S6_CBUF_DST_BLEND_FACT_SHIFT)
100
 
101
static const struct formatinfo {
102
	unsigned int fmt, xfmt;
103
	uint32_t card_fmt;
104
	bool rb_reversed;
105
} gen3_tex_formats[] = {
106
	{PICT_a8, 0, MAPSURF_8BIT | MT_8BIT_A8, false},
107
	{PICT_a8r8g8b8, 0, MAPSURF_32BIT | MT_32BIT_ARGB8888, false},
108
	{PICT_x8r8g8b8, 0, MAPSURF_32BIT | MT_32BIT_XRGB8888, false},
109
	{PICT_a8b8g8r8, 0, MAPSURF_32BIT | MT_32BIT_ABGR8888, false},
110
	{PICT_x8b8g8r8, 0, MAPSURF_32BIT | MT_32BIT_XBGR8888, false}
111
};
112
 
113
#define xFixedToDouble(f) pixman_fixed_to_double(f)
114
 
115
static inline bool too_large(int width, int height)
116
{
117
	return width > MAX_3D_SIZE || height > MAX_3D_SIZE;
118
}
119
 
120
static inline uint32_t gen3_buf_tiling(uint32_t tiling)
121
{
122
	uint32_t v = 0;
123
	switch (tiling) {
124
	case I915_TILING_Y: v |= BUF_3D_TILE_WALK_Y;
125
	case I915_TILING_X: v |= BUF_3D_TILED_SURFACE;
126
	case I915_TILING_NONE: break;
127
	}
128
	return v;
129
}
130
static uint32_t gen3_get_blend_cntl(int op,
131
				    bool has_component_alpha,
132
				    uint32_t dst_format)
133
{
134
	uint32_t sblend;
135
	uint32_t dblend;
136
 
4245 Serge 137
    sblend = BLENDFACT_ONE;
138
    dblend = BLENDFACT_INV_SRC_ALPHA;
3299 Serge 139
 
140
#if 0
141
	if (op <= PictOpSrc) /* for clear and src disable blending */
142
		return S6_COLOR_WRITE_ONLY;
143
 
144
	/* If there's no dst alpha channel, adjust the blend op so that we'll
145
	 * treat it as always 1.
146
	 */
147
	if (gen3_blend_op[op].dst_alpha) {
148
		if (PICT_FORMAT_A(dst_format) == 0) {
149
			if (sblend == BLENDFACT_DST_ALPHA)
150
				sblend = BLENDFACT_ONE;
151
			else if (sblend == BLENDFACT_INV_DST_ALPHA)
152
				sblend = BLENDFACT_ZERO;
153
		}
154
 
155
		/* gen3 engine reads 8bit color buffer into green channel
156
		 * in cases like color buffer blending etc., and also writes
157
		 * back green channel.  So with dst_alpha blend we should use
158
		 * color factor. See spec on "8-bit rendering".
159
		 */
160
		if (dst_format == PICT_a8) {
161
			if (sblend == BLENDFACT_DST_ALPHA)
162
				sblend = BLENDFACT_DST_COLR;
163
			else if (sblend == BLENDFACT_INV_DST_ALPHA)
164
				sblend = BLENDFACT_INV_DST_COLR;
165
		}
166
	}
167
 
168
	/* If the source alpha is being used, then we should only be in a case
169
	 * where the source blend factor is 0, and the source blend value is the
170
	 * mask channels multiplied by the source picture's alpha.
171
	 */
172
	if (has_component_alpha && gen3_blend_op[op].src_alpha) {
173
		if (dblend == BLENDFACT_SRC_ALPHA)
174
			dblend = BLENDFACT_SRC_COLR;
175
		else if (dblend == BLENDFACT_INV_SRC_ALPHA)
176
			dblend = BLENDFACT_INV_SRC_COLR;
177
	}
178
#endif
179
 
180
	return (S6_CBUF_BLEND_ENABLE | S6_COLOR_WRITE_ENABLE |
181
		BLENDFUNC_ADD << S6_CBUF_BLEND_FUNC_SHIFT |
182
		sblend << S6_CBUF_SRC_BLEND_FACT_SHIFT |
183
		dblend << S6_CBUF_DST_BLEND_FACT_SHIFT);
184
}
185
static bool gen3_dst_rb_reversed(uint32_t format)
186
{
187
	switch (format) {
188
	case PICT_a8r8g8b8:
189
	case PICT_x8r8g8b8:
190
	case PICT_a8:
191
		return false;
192
	default:
193
		return true;
194
	}
195
}
196
 
197
#define DSTORG_HORT_BIAS(x)             ((x)<<20)
198
#define DSTORG_VERT_BIAS(x)             ((x)<<16)
199
 
200
static uint32_t gen3_get_dst_format(uint32_t format)
201
{
202
#define BIAS (DSTORG_HORT_BIAS(0x8) | DSTORG_VERT_BIAS(0x8))
203
	switch (format) {
204
	default:
205
	case PICT_a8r8g8b8:
206
	case PICT_x8r8g8b8:
207
	case PICT_a8b8g8r8:
208
	case PICT_x8b8g8r8:
209
		return BIAS | COLR_BUF_ARGB8888;
210
	case PICT_a8:
211
		return BIAS | COLR_BUF_8BIT;
212
	}
213
#undef BIAS
214
}
215
 
216
 
217
 
218
fastcall static void
219
gen3_emit_composite_primitive_identity_source_mask(struct sna *sna,
220
						   const struct sna_composite_op *op,
221
						   const struct sna_composite_rectangles *r)
222
{
223
	float dst_x, dst_y;
224
	float src_x, src_y;
225
	float msk_x, msk_y;
226
	float w, h;
227
	float *v;
228
 
229
	dst_x = r->dst.x + op->dst.x;
230
	dst_y = r->dst.y + op->dst.y;
231
	src_x = r->src.x + op->src.offset[0];
232
	src_y = r->src.y + op->src.offset[1];
233
	msk_x = r->mask.x + op->mask.offset[0];
234
	msk_y = r->mask.y + op->mask.offset[1];
235
	w = r->width;
236
	h = r->height;
237
 
238
	v = sna->render.vertices + sna->render.vertex_used;
239
	sna->render.vertex_used += 18;
240
 
241
	v[0] = dst_x + w;
242
	v[1] = dst_y + h;
243
	v[2] = (src_x + w) * op->src.scale[0];
244
	v[3] = (src_y + h) * op->src.scale[1];
245
	v[4] = (msk_x + w) * op->mask.scale[0];
246
	v[5] = (msk_y + h) * op->mask.scale[1];
247
 
248
	v[6] = dst_x;
249
	v[7] = v[1];
250
	v[8] = src_x * op->src.scale[0];
251
	v[9] = v[3];
252
	v[10] = msk_x * op->mask.scale[0];
253
	v[11] =v[5];
254
 
255
	v[12] = v[6];
256
	v[13] = dst_y;
257
	v[14] = v[8];
258
	v[15] = src_y * op->src.scale[1];
259
	v[16] = v[10];
260
	v[17] = msk_y * op->mask.scale[1];
261
}
262
 
263
 
264
 
265
 
266
 
267
 
268
 
269
 
270
 
271
 
272
 
273
 
274
 
275
 
276
 
277
 
278
 
279
 
280
 
281
 
282
 
283
 
284
 
285
 
286
 
287
 
288
 
289
 
290
 
291
 
292
 
293
 
294
 
295
 
296
 
297
 
298
 
299
 
300
 
301
 
302
 
303
 
304
 
305
 
306
 
307
 
308
 
309
 
310
 
311
 
312
 
313
 
314
 
315
 
316
 
317
 
318
 
319
 
320
 
321
 
322
 
323
 
324
 
325
static inline void
326
gen3_2d_perspective(struct sna *sna, int in, int out)
327
{
328
	gen3_fs_rcp(out, 0, gen3_fs_operand(in, W, W, W, W));
329
	gen3_fs_mul(out,
330
		    gen3_fs_operand(in, X, Y, ZERO, ONE),
331
		    gen3_fs_operand_reg(out));
332
}
333
 
334
static inline void
335
gen3_linear_coord(struct sna *sna,
336
		  const struct sna_composite_channel *channel,
337
		  int in, int out)
338
{
339
	int c = channel->u.gen3.constants;
340
 
341
	if (!channel->is_affine) {
342
		gen3_2d_perspective(sna, in, FS_U0);
343
		in = FS_U0;
344
	}
345
 
346
	gen3_fs_mov(out, gen3_fs_operand_zero());
347
	gen3_fs_dp3(out, MASK_X,
348
		    gen3_fs_operand(in, X, Y, ONE, ZERO),
349
		    gen3_fs_operand_reg(c));
350
}
351
 
352
static void
353
gen3_radial_coord(struct sna *sna,
354
		  const struct sna_composite_channel *channel,
355
		  int in, int out)
356
{
357
	int c = channel->u.gen3.constants;
358
 
359
	if (!channel->is_affine) {
360
		gen3_2d_perspective(sna, in, FS_U0);
361
		in = FS_U0;
362
	}
363
 
364
	switch (channel->u.gen3.mode) {
365
	case RADIAL_ONE:
366
		/*
367
		   pdx = (x - c1x) / dr, pdy = (y - c1y) / dr;
368
		   r? = pdx*pdx + pdy*pdy
369
		   t = r?/sqrt(r?) - r1/dr;
370
		   */
371
		gen3_fs_mad(FS_U0, MASK_X | MASK_Y,
372
			    gen3_fs_operand(in, X, Y, ZERO, ZERO),
373
			    gen3_fs_operand(c, Z, Z, ZERO, ZERO),
374
			    gen3_fs_operand(c, NEG_X, NEG_Y, ZERO, ZERO));
375
		gen3_fs_dp2add(FS_U0, MASK_X,
376
			       gen3_fs_operand(FS_U0, X, Y, ZERO, ZERO),
377
			       gen3_fs_operand(FS_U0, X, Y, ZERO, ZERO),
378
			       gen3_fs_operand_zero());
379
		gen3_fs_rsq(out, MASK_X, gen3_fs_operand(FS_U0, X, X, X, X));
380
		gen3_fs_mad(out, 0,
381
			    gen3_fs_operand(FS_U0, X, ZERO, ZERO, ZERO),
382
			    gen3_fs_operand(out, X, ZERO, ZERO, ZERO),
383
			    gen3_fs_operand(c, W, ZERO, ZERO, ZERO));
384
		break;
385
 
386
	case RADIAL_TWO:
387
		/*
388
		   pdx = x - c1x, pdy = y - c1y;
389
		   A = dx? + dy? - dr?
390
		   B = -2*(pdx*dx + pdy*dy + r1*dr);
391
		   C = pdx? + pdy? - r1?;
392
		   det = B*B - 4*A*C;
393
		   t = (-B + sqrt (det)) / (2 * A)
394
		   */
395
 
396
		/* u0.x = pdx, u0.y = pdy, u[0].z = r1; */
397
		gen3_fs_add(FS_U0,
398
			    gen3_fs_operand(in, X, Y, ZERO, ZERO),
399
			    gen3_fs_operand(c, X, Y, Z, ZERO));
400
		/* u0.x = pdx, u0.y = pdy, u[0].z = r1, u[0].w = B; */
401
		gen3_fs_dp3(FS_U0, MASK_W,
402
			    gen3_fs_operand(FS_U0, X, Y, ONE, ZERO),
403
			    gen3_fs_operand(c+1, X, Y, Z, ZERO));
404
		/* u1.x = pdx? + pdy? - r1?; [C] */
405
		gen3_fs_dp3(FS_U1, MASK_X,
406
			    gen3_fs_operand(FS_U0, X, Y, Z, ZERO),
407
			    gen3_fs_operand(FS_U0, X, Y, NEG_Z, ZERO));
408
		/* u1.x = C, u1.y = B, u1.z=-4*A; */
409
		gen3_fs_mov_masked(FS_U1, MASK_Y, gen3_fs_operand(FS_U0, W, W, W, W));
410
		gen3_fs_mov_masked(FS_U1, MASK_Z, gen3_fs_operand(c, W, W, W, W));
411
		/* u1.x = B? - 4*A*C */
412
		gen3_fs_dp2add(FS_U1, MASK_X,
413
			       gen3_fs_operand(FS_U1, X, Y, ZERO, ZERO),
414
			       gen3_fs_operand(FS_U1, Z, Y, ZERO, ZERO),
415
			       gen3_fs_operand_zero());
416
		/* out.x = -B + sqrt (B? - 4*A*C), */
417
		gen3_fs_rsq(out, MASK_X, gen3_fs_operand(FS_U1, X, X, X, X));
418
		gen3_fs_mad(out, MASK_X,
419
			    gen3_fs_operand(out, X, ZERO, ZERO, ZERO),
420
			    gen3_fs_operand(FS_U1, X, ZERO, ZERO, ZERO),
421
			    gen3_fs_operand(FS_U0, NEG_W, ZERO, ZERO, ZERO));
422
		/* out.x = (-B + sqrt (B? - 4*A*C)) / (2 * A), */
423
		gen3_fs_mul(out,
424
			    gen3_fs_operand(out, X, ZERO, ZERO, ZERO),
425
			    gen3_fs_operand(c+1, W, ZERO, ZERO, ZERO));
426
		break;
427
	}
428
}
429
 
430
static void
431
gen3_composite_emit_shader(struct sna *sna,
432
			   const struct sna_composite_op *op,
433
			   uint8_t blend)
434
{
435
	bool dst_is_alpha = PIXMAN_FORMAT_RGB(op->dst.format) == 0;
436
	const struct sna_composite_channel *src, *mask;
437
	struct gen3_render_state *state = &sna->render_state.gen3;
438
	uint32_t shader_offset, id;
439
	int src_reg, mask_reg;
440
	int t, length;
441
 
442
	src = &op->src;
443
	mask = &op->mask;
444
	if (mask->u.gen3.type == SHADER_NONE)
445
		mask = NULL;
446
 
447
	id = (src->u.gen3.type |
448
	      src->is_affine << 4 |
449
	      src->alpha_fixup << 5 |
450
	      src->rb_reversed << 6);
451
	if (mask) {
452
		id |= (mask->u.gen3.type << 8 |
453
		       mask->is_affine << 12 |
454
		       gen3_blend_op[blend].src_alpha << 13 |
455
		       op->has_component_alpha << 14 |
456
		       mask->alpha_fixup << 15 |
457
		       mask->rb_reversed << 16);
458
	}
459
	id |= dst_is_alpha << 24;
460
	id |= op->rb_reversed << 25;
461
 
462
	if (id == state->last_shader)
463
		return;
464
 
465
	state->last_shader = id;
466
 
467
	shader_offset = sna->kgem.nbatch++;
468
	t = 0;
469
	switch (src->u.gen3.type) {
470
	case SHADER_NONE:
471
	case SHADER_OPACITY:
472
		assert(0);
473
	case SHADER_ZERO:
474
	case SHADER_BLACK:
475
	case SHADER_WHITE:
476
		break;
477
	case SHADER_CONSTANT:
478
		gen3_fs_dcl(FS_T8);
479
		src_reg = FS_T8;
480
		break;
481
	case SHADER_TEXTURE:
482
	case SHADER_RADIAL:
483
	case SHADER_LINEAR:
484
		gen3_fs_dcl(FS_S0);
485
		gen3_fs_dcl(FS_T0);
486
		t++;
487
		break;
488
	}
489
 
490
	if (mask == NULL) {
491
		switch (src->u.gen3.type) {
492
		case SHADER_ZERO:
493
			gen3_fs_mov(FS_OC, gen3_fs_operand_zero());
494
			goto done;
495
		case SHADER_BLACK:
496
			if (dst_is_alpha)
497
				gen3_fs_mov(FS_OC, gen3_fs_operand_one());
498
			else
499
				gen3_fs_mov(FS_OC, gen3_fs_operand(FS_R0, ZERO, ZERO, ZERO, ONE));
500
			goto done;
501
		case SHADER_WHITE:
502
			gen3_fs_mov(FS_OC, gen3_fs_operand_one());
503
			goto done;
504
		}
505
		if (src->alpha_fixup && dst_is_alpha) {
506
			gen3_fs_mov(FS_OC, gen3_fs_operand_one());
507
			goto done;
508
		}
509
		/* No mask, so load directly to output color */
510
		if (src->u.gen3.type != SHADER_CONSTANT) {
511
			if (dst_is_alpha || src->rb_reversed ^ op->rb_reversed)
512
				src_reg = FS_R0;
513
			else
514
				src_reg = FS_OC;
515
		}
516
		switch (src->u.gen3.type) {
517
		case SHADER_LINEAR:
518
			gen3_linear_coord(sna, src, FS_T0, FS_R0);
519
			gen3_fs_texld(src_reg, FS_S0, FS_R0);
520
			break;
521
 
522
		case SHADER_RADIAL:
523
			gen3_radial_coord(sna, src, FS_T0, FS_R0);
524
			gen3_fs_texld(src_reg, FS_S0, FS_R0);
525
			break;
526
 
527
		case SHADER_TEXTURE:
528
			if (src->is_affine)
529
				gen3_fs_texld(src_reg, FS_S0, FS_T0);
530
			else
531
				gen3_fs_texldp(src_reg, FS_S0, FS_T0);
532
			break;
533
 
534
		case SHADER_NONE:
535
		case SHADER_WHITE:
536
		case SHADER_BLACK:
537
		case SHADER_ZERO:
538
			assert(0);
539
		case SHADER_CONSTANT:
540
			break;
541
		}
542
 
543
		if (src_reg != FS_OC) {
544
			if (src->alpha_fixup)
545
				gen3_fs_mov(FS_OC,
546
					    src->rb_reversed ^ op->rb_reversed ?
547
					    gen3_fs_operand(src_reg, Z, Y, X, ONE) :
548
					    gen3_fs_operand(src_reg, X, Y, Z, ONE));
549
			else if (dst_is_alpha)
550
				gen3_fs_mov(FS_OC, gen3_fs_operand(src_reg, W, W, W, W));
551
			else if (src->rb_reversed ^ op->rb_reversed)
552
				gen3_fs_mov(FS_OC, gen3_fs_operand(src_reg, Z, Y, X, W));
553
			else
554
				gen3_fs_mov(FS_OC, gen3_fs_operand_reg(src_reg));
555
		} else if (src->alpha_fixup)
556
			gen3_fs_mov_masked(FS_OC, MASK_W, gen3_fs_operand_one());
557
	} else {
558
		int out_reg = FS_OC;
559
		if (op->rb_reversed)
560
			out_reg = FS_U0;
561
 
562
		switch (mask->u.gen3.type) {
563
		case SHADER_CONSTANT:
564
			gen3_fs_dcl(FS_T9);
565
			mask_reg = FS_T9;
566
			break;
567
		case SHADER_TEXTURE:
568
		case SHADER_LINEAR:
569
		case SHADER_RADIAL:
570
			gen3_fs_dcl(FS_S0 + t);
571
			/* fall through */
572
		case SHADER_OPACITY:
573
			gen3_fs_dcl(FS_T0 + t);
574
			break;
575
		case SHADER_ZERO:
576
		case SHADER_BLACK:
577
			assert(0);
578
		case SHADER_NONE:
579
		case SHADER_WHITE:
580
			break;
581
		}
582
 
583
		t = 0;
584
		switch (src->u.gen3.type) {
585
		case SHADER_LINEAR:
586
			gen3_linear_coord(sna, src, FS_T0, FS_R0);
587
			gen3_fs_texld(FS_R0, FS_S0, FS_R0);
588
			src_reg = FS_R0;
589
			t++;
590
			break;
591
 
592
		case SHADER_RADIAL:
593
			gen3_radial_coord(sna, src, FS_T0, FS_R0);
594
			gen3_fs_texld(FS_R0, FS_S0, FS_R0);
595
			src_reg = FS_R0;
596
			t++;
597
			break;
598
 
599
		case SHADER_TEXTURE:
600
			if (src->is_affine)
601
				gen3_fs_texld(FS_R0, FS_S0, FS_T0);
602
			else
603
				gen3_fs_texldp(FS_R0, FS_S0, FS_T0);
604
			src_reg = FS_R0;
605
			t++;
606
			break;
607
 
608
		case SHADER_CONSTANT:
609
		case SHADER_NONE:
610
		case SHADER_ZERO:
611
		case SHADER_BLACK:
612
		case SHADER_WHITE:
613
			break;
614
		}
615
		if (src->alpha_fixup)
616
			gen3_fs_mov_masked(src_reg, MASK_W, gen3_fs_operand_one());
617
		if (src->rb_reversed)
618
			gen3_fs_mov(src_reg, gen3_fs_operand(src_reg, Z, Y, X, W));
619
 
620
		switch (mask->u.gen3.type) {
621
		case SHADER_LINEAR:
622
			gen3_linear_coord(sna, mask, FS_T0 + t, FS_R1);
623
			gen3_fs_texld(FS_R1, FS_S0 + t, FS_R1);
624
			mask_reg = FS_R1;
625
			break;
626
 
627
		case SHADER_RADIAL:
628
			gen3_radial_coord(sna, mask, FS_T0 + t, FS_R1);
629
			gen3_fs_texld(FS_R1, FS_S0 + t, FS_R1);
630
			mask_reg = FS_R1;
631
			break;
632
 
633
		case SHADER_TEXTURE:
634
			if (mask->is_affine)
635
				gen3_fs_texld(FS_R1, FS_S0 + t, FS_T0 + t);
636
			else
637
				gen3_fs_texldp(FS_R1, FS_S0 + t, FS_T0 + t);
638
			mask_reg = FS_R1;
639
			break;
640
 
641
		case SHADER_OPACITY:
642
			switch (src->u.gen3.type) {
643
			case SHADER_BLACK:
644
			case SHADER_WHITE:
645
				if (dst_is_alpha || src->u.gen3.type == SHADER_WHITE) {
646
					gen3_fs_mov(out_reg,
647
						    gen3_fs_operand(FS_T0 + t, X, X, X, X));
648
				} else {
649
					gen3_fs_mov(out_reg,
650
						    gen3_fs_operand(FS_T0 + t, ZERO, ZERO, ZERO, X));
651
				}
652
				break;
653
			default:
654
				if (dst_is_alpha) {
655
					gen3_fs_mul(out_reg,
656
						    gen3_fs_operand(src_reg, W, W, W, W),
657
						    gen3_fs_operand(FS_T0 + t, X, X, X, X));
658
				} else {
659
					gen3_fs_mul(out_reg,
660
						    gen3_fs_operand(src_reg, X, Y, Z, W),
661
						    gen3_fs_operand(FS_T0 + t, X, X, X, X));
662
				}
663
			}
664
			goto mask_done;
665
 
666
		case SHADER_CONSTANT:
667
		case SHADER_ZERO:
668
		case SHADER_BLACK:
669
		case SHADER_WHITE:
670
		case SHADER_NONE:
671
			break;
672
		}
673
		if (mask->alpha_fixup)
674
			gen3_fs_mov_masked(mask_reg, MASK_W, gen3_fs_operand_one());
675
		if (mask->rb_reversed)
676
			gen3_fs_mov(mask_reg, gen3_fs_operand(mask_reg, Z, Y, X, W));
677
 
678
		if (dst_is_alpha) {
679
			switch (src->u.gen3.type) {
680
			case SHADER_BLACK:
681
			case SHADER_WHITE:
682
				gen3_fs_mov(out_reg,
683
					    gen3_fs_operand(mask_reg, W, W, W, W));
684
				break;
685
			default:
686
				gen3_fs_mul(out_reg,
687
					    gen3_fs_operand(src_reg, W, W, W, W),
688
					    gen3_fs_operand(mask_reg, W, W, W, W));
689
				break;
690
			}
691
		} else {
692
			/* If component alpha is active in the mask and the blend
693
			 * operation uses the source alpha, then we know we don't
694
			 * need the source value (otherwise we would have hit a
695
			 * fallback earlier), so we provide the source alpha (src.A *
696
			 * mask.X) as output color.
697
			 * Conversely, if CA is set and we don't need the source alpha,
698
			 * then we produce the source value (src.X * mask.X) and the
699
			 * source alpha is unused.  Otherwise, we provide the non-CA
700
			 * source value (src.X * mask.A).
701
			 */
702
			if (op->has_component_alpha) {
703
				switch (src->u.gen3.type) {
704
				case SHADER_BLACK:
705
					if (gen3_blend_op[blend].src_alpha)
706
						gen3_fs_mov(out_reg,
707
							    gen3_fs_operand_reg(mask_reg));
708
					else
709
						gen3_fs_mov(out_reg,
710
							    gen3_fs_operand(mask_reg, ZERO, ZERO, ZERO, W));
711
					break;
712
				case SHADER_WHITE:
713
					gen3_fs_mov(out_reg,
714
						    gen3_fs_operand_reg(mask_reg));
715
					break;
716
				default:
717
					if (gen3_blend_op[blend].src_alpha)
718
						gen3_fs_mul(out_reg,
719
							    gen3_fs_operand(src_reg, W, W, W, W),
720
							    gen3_fs_operand_reg(mask_reg));
721
					else
722
						gen3_fs_mul(out_reg,
723
							    gen3_fs_operand_reg(src_reg),
724
							    gen3_fs_operand_reg(mask_reg));
725
					break;
726
				}
727
			} else {
728
				switch (src->u.gen3.type) {
729
				case SHADER_WHITE:
730
					gen3_fs_mov(out_reg,
731
						    gen3_fs_operand(mask_reg, W, W, W, W));
732
					break;
733
				case SHADER_BLACK:
734
					gen3_fs_mov(out_reg,
735
						    gen3_fs_operand(mask_reg, ZERO, ZERO, ZERO, W));
736
					break;
737
				default:
738
					gen3_fs_mul(out_reg,
739
						    gen3_fs_operand_reg(src_reg),
740
						    gen3_fs_operand(mask_reg, W, W, W, W));
741
					break;
742
				}
743
			}
744
		}
745
mask_done:
746
		if (op->rb_reversed)
747
			gen3_fs_mov(FS_OC, gen3_fs_operand(FS_U0, Z, Y, X, W));
748
	}
749
 
750
done:
751
	length = sna->kgem.nbatch - shader_offset;
752
	sna->kgem.batch[shader_offset] =
753
		_3DSTATE_PIXEL_SHADER_PROGRAM | (length - 2);
754
}
755
 
756
static uint32_t gen3_ms_tiling(uint32_t tiling)
757
{
758
	uint32_t v = 0;
759
	switch (tiling) {
760
	case I915_TILING_Y: v |= MS3_TILE_WALK;
761
	case I915_TILING_X: v |= MS3_TILED_SURFACE;
762
	case I915_TILING_NONE: break;
763
	}
764
	return v;
765
}
766
 
767
static void gen3_emit_invariant(struct sna *sna)
768
{
769
	/* Disable independent alpha blend */
770
	OUT_BATCH(_3DSTATE_INDEPENDENT_ALPHA_BLEND_CMD | IAB_MODIFY_ENABLE |
771
		  IAB_MODIFY_FUNC | BLENDFUNC_ADD << IAB_FUNC_SHIFT |
772
		  IAB_MODIFY_SRC_FACTOR | BLENDFACT_ONE << IAB_SRC_FACTOR_SHIFT |
773
		  IAB_MODIFY_DST_FACTOR | BLENDFACT_ZERO << IAB_DST_FACTOR_SHIFT);
774
 
775
	OUT_BATCH(_3DSTATE_COORD_SET_BINDINGS |
776
		  CSB_TCB(0, 0) |
777
		  CSB_TCB(1, 1) |
778
		  CSB_TCB(2, 2) |
779
		  CSB_TCB(3, 3) |
780
		  CSB_TCB(4, 4) |
781
		  CSB_TCB(5, 5) |
782
		  CSB_TCB(6, 6) |
783
		  CSB_TCB(7, 7));
784
 
785
	OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(3) | I1_LOAD_S(4) | I1_LOAD_S(5) | I1_LOAD_S(6) | 3);
786
	OUT_BATCH(0); /* Disable texture coordinate wrap-shortest */
787
	OUT_BATCH((1 << S4_POINT_WIDTH_SHIFT) |
788
		  S4_LINE_WIDTH_ONE |
789
		  S4_CULLMODE_NONE |
790
		  S4_VFMT_XY);
791
	OUT_BATCH(0); /* Disable fog/stencil. *Enable* write mask. */
792
	OUT_BATCH(S6_COLOR_WRITE_ONLY); /* Disable blending, depth */
793
 
794
	OUT_BATCH(_3DSTATE_SCISSOR_ENABLE_CMD | DISABLE_SCISSOR_RECT);
795
	OUT_BATCH(_3DSTATE_DEPTH_SUBRECT_DISABLE);
796
 
797
	OUT_BATCH(_3DSTATE_LOAD_INDIRECT);
798
	OUT_BATCH(0x00000000);
799
 
800
	OUT_BATCH(_3DSTATE_STIPPLE);
801
	OUT_BATCH(0x00000000);
802
 
803
	sna->render_state.gen3.need_invariant = false;
804
}
805
 
806
#define MAX_OBJECTS 3 /* worst case: dst + src + mask  */
807
 
808
static void
809
gen3_get_batch(struct sna *sna, const struct sna_composite_op *op)
810
{
811
	kgem_set_mode(&sna->kgem, KGEM_RENDER, op->dst.bo);
812
 
813
	if (!kgem_check_batch(&sna->kgem, 200)) {
814
		DBG(("%s: flushing batch: size %d > %d\n",
815
		     __FUNCTION__, 200,
816
		     sna->kgem.surface-sna->kgem.nbatch));
817
		kgem_submit(&sna->kgem);
818
		_kgem_set_mode(&sna->kgem, KGEM_RENDER);
819
	}
820
 
821
	if (!kgem_check_reloc(&sna->kgem, MAX_OBJECTS)) {
822
		DBG(("%s: flushing batch: reloc %d >= %d\n",
823
		     __FUNCTION__,
824
		     sna->kgem.nreloc,
825
		     (int)KGEM_RELOC_SIZE(&sna->kgem) - MAX_OBJECTS));
826
		kgem_submit(&sna->kgem);
827
		_kgem_set_mode(&sna->kgem, KGEM_RENDER);
828
	}
829
 
830
	if (!kgem_check_exec(&sna->kgem, MAX_OBJECTS)) {
831
		DBG(("%s: flushing batch: exec %d >= %d\n",
832
		     __FUNCTION__,
833
		     sna->kgem.nexec,
834
		     (int)KGEM_EXEC_SIZE(&sna->kgem) - MAX_OBJECTS - 1));
835
		kgem_submit(&sna->kgem);
836
		_kgem_set_mode(&sna->kgem, KGEM_RENDER);
837
	}
838
 
839
	if (sna->render_state.gen3.need_invariant)
840
		gen3_emit_invariant(sna);
841
#undef MAX_OBJECTS
842
}
843
 
844
static void gen3_emit_target(struct sna *sna,
845
			     struct kgem_bo *bo,
846
			     int width,
847
			     int height,
848
			     int format)
849
{
850
	struct gen3_render_state *state = &sna->render_state.gen3;
851
 
852
	assert(!too_large(width, height));
853
 
854
	/* BUF_INFO is an implicit flush, so skip if the target is unchanged. */
855
	assert(bo->unique_id != 0);
856
	if (bo->unique_id != state->current_dst) {
857
		uint32_t v;
858
 
859
		DBG(("%s: setting new target id=%d, handle=%d\n",
860
		     __FUNCTION__, bo->unique_id, bo->handle));
861
 
862
		OUT_BATCH(_3DSTATE_BUF_INFO_CMD);
863
		OUT_BATCH(BUF_3D_ID_COLOR_BACK |
864
			  gen3_buf_tiling(bo->tiling) |
865
			  bo->pitch);
866
		OUT_BATCH(kgem_add_reloc(&sna->kgem, sna->kgem.nbatch,
867
					 bo,
868
					 I915_GEM_DOMAIN_RENDER << 16 |
869
					 I915_GEM_DOMAIN_RENDER,
870
					 0));
871
 
872
		OUT_BATCH(_3DSTATE_DST_BUF_VARS_CMD);
873
		OUT_BATCH(gen3_get_dst_format(format));
874
 
875
		v = DRAW_YMAX(height - 1) | DRAW_XMAX(width - 1);
876
		if (v != state->last_drawrect_limit) {
877
			OUT_BATCH(_3DSTATE_DRAW_RECT_CMD);
878
			OUT_BATCH(0); /* XXX dither origin? */
879
			OUT_BATCH(0);
880
			OUT_BATCH(v);
881
			OUT_BATCH(0);
882
			state->last_drawrect_limit = v;
883
		}
884
 
885
		state->current_dst = bo->unique_id;
886
	}
887
	kgem_bo_mark_dirty(bo);
888
}
889
 
890
static void gen3_emit_composite_state(struct sna *sna,
891
				      const struct sna_composite_op *op)
892
{
893
	struct gen3_render_state *state = &sna->render_state.gen3;
894
	uint32_t map[4];
895
	uint32_t sampler[4];
896
	struct kgem_bo *bo[2];
897
	unsigned int tex_count, n;
898
	uint32_t ss2;
899
 
900
	gen3_get_batch(sna, op);
901
 
902
	if (kgem_bo_is_dirty(op->src.bo) || kgem_bo_is_dirty(op->mask.bo)) {
903
		if (op->src.bo == op->dst.bo || op->mask.bo == op->dst.bo)
904
			OUT_BATCH(MI_FLUSH | MI_INVALIDATE_MAP_CACHE);
905
		else
906
			OUT_BATCH(_3DSTATE_MODES_5_CMD |
907
				  PIPELINE_FLUSH_RENDER_CACHE |
908
				  PIPELINE_FLUSH_TEXTURE_CACHE);
909
		kgem_clear_dirty(&sna->kgem);
910
	}
911
 
912
	gen3_emit_target(sna,
913
			 op->dst.bo,
914
			 op->dst.width,
915
			 op->dst.height,
916
			 op->dst.format);
917
 
918
	ss2 = ~0;
919
	tex_count = 0;
920
	switch (op->src.u.gen3.type) {
921
	case SHADER_OPACITY:
922
	case SHADER_NONE:
923
		assert(0);
924
	case SHADER_ZERO:
925
	case SHADER_BLACK:
926
	case SHADER_WHITE:
927
		break;
928
	case SHADER_CONSTANT:
929
		if (op->src.u.gen3.mode != state->last_diffuse) {
930
			OUT_BATCH(_3DSTATE_DFLT_DIFFUSE_CMD);
931
			OUT_BATCH(op->src.u.gen3.mode);
932
			state->last_diffuse = op->src.u.gen3.mode;
933
		}
934
		break;
935
	case SHADER_LINEAR:
936
	case SHADER_RADIAL:
937
	case SHADER_TEXTURE:
938
		ss2 &= ~S2_TEXCOORD_FMT(tex_count, TEXCOORDFMT_NOT_PRESENT);
939
		ss2 |= S2_TEXCOORD_FMT(tex_count,
940
				       op->src.is_affine ? TEXCOORDFMT_2D : TEXCOORDFMT_4D);
941
		map[tex_count * 2 + 0] =
942
			op->src.card_format |
943
			gen3_ms_tiling(op->src.bo->tiling) |
944
			(op->src.height - 1) << MS3_HEIGHT_SHIFT |
945
			(op->src.width - 1) << MS3_WIDTH_SHIFT;
946
		map[tex_count * 2 + 1] =
947
			(op->src.bo->pitch / 4 - 1) << MS4_PITCH_SHIFT;
948
 
949
		sampler[tex_count * 2 + 0] = op->src.filter;
950
		sampler[tex_count * 2 + 1] =
951
			op->src.repeat |
952
			tex_count << SS3_TEXTUREMAP_INDEX_SHIFT;
953
		bo[tex_count] = op->src.bo;
954
		tex_count++;
955
		break;
956
	}
957
	switch (op->mask.u.gen3.type) {
958
	case SHADER_NONE:
959
	case SHADER_ZERO:
960
	case SHADER_BLACK:
961
	case SHADER_WHITE:
962
		break;
963
	case SHADER_CONSTANT:
964
		if (op->mask.u.gen3.mode != state->last_specular) {
965
			OUT_BATCH(_3DSTATE_DFLT_SPEC_CMD);
966
			OUT_BATCH(op->mask.u.gen3.mode);
967
			state->last_specular = op->mask.u.gen3.mode;
968
		}
969
		break;
970
	case SHADER_LINEAR:
971
	case SHADER_RADIAL:
972
	case SHADER_TEXTURE:
973
		ss2 &= ~S2_TEXCOORD_FMT(tex_count, TEXCOORDFMT_NOT_PRESENT);
974
		ss2 |= S2_TEXCOORD_FMT(tex_count,
975
				       op->mask.is_affine ? TEXCOORDFMT_2D : TEXCOORDFMT_4D);
976
		map[tex_count * 2 + 0] =
977
			op->mask.card_format |
978
			gen3_ms_tiling(op->mask.bo->tiling) |
979
			(op->mask.height - 1) << MS3_HEIGHT_SHIFT |
980
			(op->mask.width - 1) << MS3_WIDTH_SHIFT;
981
		map[tex_count * 2 + 1] =
982
			(op->mask.bo->pitch / 4 - 1) << MS4_PITCH_SHIFT;
983
 
984
		sampler[tex_count * 2 + 0] = op->mask.filter;
985
		sampler[tex_count * 2 + 1] =
986
			op->mask.repeat |
987
			tex_count << SS3_TEXTUREMAP_INDEX_SHIFT;
988
		bo[tex_count] = op->mask.bo;
989
		tex_count++;
990
		break;
991
	case SHADER_OPACITY:
992
		ss2 &= ~S2_TEXCOORD_FMT(tex_count, TEXCOORDFMT_NOT_PRESENT);
993
		ss2 |= S2_TEXCOORD_FMT(tex_count, TEXCOORDFMT_1D);
994
		break;
995
	}
996
 
997
	{
998
		uint32_t blend_offset = sna->kgem.nbatch;
999
 
1000
		OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(2) | I1_LOAD_S(6) | 1);
1001
		OUT_BATCH(ss2);
1002
		OUT_BATCH(gen3_get_blend_cntl(op->op,
1003
					      op->has_component_alpha,
1004
					      op->dst.format));
1005
 
1006
		if (memcmp(sna->kgem.batch + state->last_blend + 1,
1007
			   sna->kgem.batch + blend_offset + 1,
1008
			   2 * 4) == 0)
1009
			sna->kgem.nbatch = blend_offset;
1010
		else
1011
			state->last_blend = blend_offset;
1012
	}
1013
 
1014
	if (op->u.gen3.num_constants) {
1015
		int count = op->u.gen3.num_constants;
1016
		if (state->last_constants) {
1017
			int last = sna->kgem.batch[state->last_constants+1];
1018
			if (last == (1 << (count >> 2)) - 1 &&
1019
			    memcmp(&sna->kgem.batch[state->last_constants+2],
1020
				   op->u.gen3.constants,
1021
				   count * sizeof(uint32_t)) == 0)
1022
				count = 0;
1023
		}
1024
		if (count) {
1025
			state->last_constants = sna->kgem.nbatch;
1026
			OUT_BATCH(_3DSTATE_PIXEL_SHADER_CONSTANTS | count);
1027
			OUT_BATCH((1 << (count >> 2)) - 1);
1028
 
1029
			memcpy(sna->kgem.batch + sna->kgem.nbatch,
1030
			       op->u.gen3.constants,
1031
			       count * sizeof(uint32_t));
1032
			sna->kgem.nbatch += count;
1033
		}
1034
	}
1035
 
1036
	if (tex_count != 0) {
1037
		uint32_t rewind;
1038
 
1039
		n = 0;
1040
		if (tex_count == state->tex_count) {
1041
			for (; n < tex_count; n++) {
1042
				if (map[2*n+0] != state->tex_map[2*n+0] ||
1043
				    map[2*n+1] != state->tex_map[2*n+1] ||
1044
				    state->tex_handle[n] != bo[n]->handle ||
1045
				    state->tex_delta[n] != bo[n]->delta)
1046
					break;
1047
			}
1048
		}
1049
		if (n < tex_count) {
1050
			OUT_BATCH(_3DSTATE_MAP_STATE | (3 * tex_count));
1051
			OUT_BATCH((1 << tex_count) - 1);
1052
			for (n = 0; n < tex_count; n++) {
1053
				OUT_BATCH(kgem_add_reloc(&sna->kgem,
1054
							 sna->kgem.nbatch,
1055
							 bo[n],
1056
							 I915_GEM_DOMAIN_SAMPLER<< 16,
1057
							 0));
1058
				OUT_BATCH(map[2*n + 0]);
1059
				OUT_BATCH(map[2*n + 1]);
1060
 
1061
				state->tex_map[2*n+0] = map[2*n+0];
1062
				state->tex_map[2*n+1] = map[2*n+1];
1063
				state->tex_handle[n] = bo[n]->handle;
1064
				state->tex_delta[n] = bo[n]->delta;
1065
			}
1066
			state->tex_count = n;
1067
		}
1068
 
1069
		rewind = sna->kgem.nbatch;
1070
		OUT_BATCH(_3DSTATE_SAMPLER_STATE | (3 * tex_count));
1071
		OUT_BATCH((1 << tex_count) - 1);
1072
		for (n = 0; n < tex_count; n++) {
1073
			OUT_BATCH(sampler[2*n + 0]);
1074
			OUT_BATCH(sampler[2*n + 1]);
1075
			OUT_BATCH(0);
1076
		}
1077
		if (state->last_sampler &&
1078
		    memcmp(&sna->kgem.batch[state->last_sampler+1],
1079
			   &sna->kgem.batch[rewind + 1],
1080
			   (3*tex_count + 1)*sizeof(uint32_t)) == 0)
1081
			sna->kgem.nbatch = rewind;
1082
		else
1083
			state->last_sampler = rewind;
1084
	}
1085
 
1086
	gen3_composite_emit_shader(sna, op, op->op);
1087
}
1088
 
1089
static bool gen3_magic_ca_pass(struct sna *sna,
1090
			       const struct sna_composite_op *op)
1091
{
1092
	if (!op->need_magic_ca_pass)
1093
		return false;
1094
 
1095
	DBG(("%s(%d)\n", __FUNCTION__,
1096
	     sna->render.vertex_index - sna->render.vertex_start));
1097
 
1098
	OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(6) | 0);
1099
	OUT_BATCH(gen3_get_blend_cntl(PictOpAdd, true, op->dst.format));
1100
	gen3_composite_emit_shader(sna, op, PictOpAdd);
1101
 
1102
	OUT_BATCH(PRIM3D_RECTLIST | PRIM3D_INDIRECT_SEQUENTIAL |
1103
		  (sna->render.vertex_index - sna->render.vertex_start));
1104
	OUT_BATCH(sna->render.vertex_start);
1105
 
1106
	sna->render_state.gen3.last_blend = 0;
1107
	return true;
1108
}
1109
 
1110
static void gen3_vertex_flush(struct sna *sna)
1111
{
1112
	assert(sna->render.vertex_offset);
1113
 
1114
	DBG(("%s[%x] = %d\n", __FUNCTION__,
1115
	     4*sna->render.vertex_offset,
1116
	     sna->render.vertex_index - sna->render.vertex_start));
1117
 
1118
	sna->kgem.batch[sna->render.vertex_offset] =
1119
		PRIM3D_RECTLIST | PRIM3D_INDIRECT_SEQUENTIAL |
1120
		(sna->render.vertex_index - sna->render.vertex_start);
1121
	sna->kgem.batch[sna->render.vertex_offset + 1] =
1122
		sna->render.vertex_start;
1123
 
1124
	sna->render.vertex_offset = 0;
1125
}
1126
 
1127
static int gen3_vertex_finish(struct sna *sna)
1128
{
1129
	struct kgem_bo *bo;
1130
 
1131
	DBG(("%s: used=%d/%d, vbo active? %d\n",
1132
	     __FUNCTION__, sna->render.vertex_used, sna->render.vertex_size,
1133
	     sna->render.vbo ? sna->render.vbo->handle : 0));
1134
	assert(sna->render.vertex_offset == 0);
1135
	assert(sna->render.vertex_used);
1136
	assert(sna->render.vertex_used <= sna->render.vertex_size);
1137
 
1138
	sna_vertex_wait__locked(&sna->render);
1139
 
1140
	bo = sna->render.vbo;
1141
	if (bo) {
1142
		DBG(("%s: reloc = %d\n", __FUNCTION__,
1143
		     sna->render.vertex_reloc[0]));
1144
 
1145
		if (sna->render.vertex_reloc[0]) {
1146
			sna->kgem.batch[sna->render.vertex_reloc[0]] =
1147
				kgem_add_reloc(&sna->kgem, sna->render.vertex_reloc[0],
1148
					       bo, I915_GEM_DOMAIN_VERTEX << 16, 0);
1149
 
1150
			sna->render.vertex_reloc[0] = 0;
1151
		}
1152
		sna->render.vertex_used = 0;
1153
		sna->render.vertex_index = 0;
1154
		sna->render.vbo = NULL;
1155
 
1156
		kgem_bo_destroy(&sna->kgem, bo);
1157
	}
1158
 
1159
	sna->render.vertices = NULL;
1160
	sna->render.vbo = kgem_create_linear(&sna->kgem,
1161
					     256*1024, CREATE_GTT_MAP);
1162
	if (sna->render.vbo)
1163
		sna->render.vertices = kgem_bo_map(&sna->kgem, sna->render.vbo);
1164
	if (sna->render.vertices == NULL) {
1165
		if (sna->render.vbo)
1166
			kgem_bo_destroy(&sna->kgem, sna->render.vbo);
1167
		sna->render.vbo = NULL;
1168
		return 0;
1169
	}
1170
	assert(sna->render.vbo->snoop == false);
1171
 
1172
	if (sna->render.vertex_used) {
1173
		memcpy(sna->render.vertices,
1174
		       sna->render.vertex_data,
1175
		       sizeof(float)*sna->render.vertex_used);
1176
	}
1177
	sna->render.vertex_size = 64 * 1024 - 1;
1178
	return sna->render.vertex_size - sna->render.vertex_used;
1179
}
1180
 
1181
static void gen3_vertex_close(struct sna *sna)
1182
{
1183
	struct kgem_bo *bo, *free_bo = NULL;
1184
	unsigned int delta = 0;
1185
 
1186
	assert(sna->render.vertex_offset == 0);
1187
	if (sna->render.vertex_reloc[0] == 0)
1188
		return;
1189
 
1190
	DBG(("%s: used=%d/%d, vbo active? %d\n",
1191
	     __FUNCTION__, sna->render.vertex_used, sna->render.vertex_size,
1192
	     sna->render.vbo ? sna->render.vbo->handle : 0));
1193
 
1194
	bo = sna->render.vbo;
1195
	if (bo) {
1196
		if (sna->render.vertex_size - sna->render.vertex_used < 64) {
1197
			DBG(("%s: discarding full vbo\n", __FUNCTION__));
1198
			sna->render.vbo = NULL;
1199
			sna->render.vertices = sna->render.vertex_data;
1200
			sna->render.vertex_size = ARRAY_SIZE(sna->render.vertex_data);
1201
			free_bo = bo;
1202
		} else if (IS_CPU_MAP(bo->map)) {
1203
			DBG(("%s: converting CPU map to GTT\n", __FUNCTION__));
1204
			sna->render.vertices = kgem_bo_map__gtt(&sna->kgem, bo);
1205
			if (sna->render.vertices == NULL) {
1206
				DBG(("%s: discarding non-mappable vertices\n",__FUNCTION__));
1207
				sna->render.vbo = NULL;
1208
				sna->render.vertices = sna->render.vertex_data;
1209
				sna->render.vertex_size = ARRAY_SIZE(sna->render.vertex_data);
1210
				free_bo = bo;
1211
			}
1212
		}
1213
	} else {
1214
		if (sna->kgem.nbatch + sna->render.vertex_used <= sna->kgem.surface) {
1215
			DBG(("%s: copy to batch: %d @ %d\n", __FUNCTION__,
1216
			     sna->render.vertex_used, sna->kgem.nbatch));
1217
			memcpy(sna->kgem.batch + sna->kgem.nbatch,
1218
			       sna->render.vertex_data,
1219
			       sna->render.vertex_used * 4);
1220
			delta = sna->kgem.nbatch * 4;
1221
			bo = NULL;
1222
			sna->kgem.nbatch += sna->render.vertex_used;
1223
		} else {
1224
			DBG(("%s: new vbo: %d\n", __FUNCTION__,
1225
			     sna->render.vertex_used));
1226
			bo = kgem_create_linear(&sna->kgem,
1227
						4*sna->render.vertex_used,
1228
						CREATE_NO_THROTTLE);
1229
			if (bo) {
1230
				assert(bo->snoop == false);
1231
				kgem_bo_write(&sna->kgem, bo,
1232
					      sna->render.vertex_data,
1233
					      4*sna->render.vertex_used);
1234
			}
1235
			free_bo = bo;
1236
		}
1237
	}
1238
 
1239
	DBG(("%s: reloc = %d\n", __FUNCTION__, sna->render.vertex_reloc[0]));
1240
	sna->kgem.batch[sna->render.vertex_reloc[0]] =
1241
		kgem_add_reloc(&sna->kgem, sna->render.vertex_reloc[0],
1242
			       bo, I915_GEM_DOMAIN_VERTEX << 16, delta);
1243
	sna->render.vertex_reloc[0] = 0;
1244
 
1245
	if (sna->render.vbo == NULL) {
1246
		DBG(("%s: resetting vbo\n", __FUNCTION__));
1247
		sna->render.vertex_used = 0;
1248
		sna->render.vertex_index = 0;
1249
		assert(sna->render.vertices == sna->render.vertex_data);
1250
		assert(sna->render.vertex_size == ARRAY_SIZE(sna->render.vertex_data));
1251
	}
1252
 
1253
	if (free_bo)
1254
		kgem_bo_destroy(&sna->kgem, free_bo);
1255
}
1256
 
1257
static bool gen3_rectangle_begin(struct sna *sna,
1258
				 const struct sna_composite_op *op)
1259
{
1260
	struct gen3_render_state *state = &sna->render_state.gen3;
1261
	int ndwords, i1_cmd = 0, i1_len = 0;
1262
 
1263
	if (sna_vertex_wait__locked(&sna->render) && sna->render.vertex_offset)
1264
		return true;
1265
 
1266
	ndwords = 2;
1267
	if (op->need_magic_ca_pass)
1268
		ndwords += 100;
1269
	if (sna->render.vertex_reloc[0] == 0)
1270
		i1_len++, i1_cmd |= I1_LOAD_S(0), ndwords++;
1271
	if (state->floats_per_vertex != op->floats_per_vertex)
1272
		i1_len++, i1_cmd |= I1_LOAD_S(1), ndwords++;
1273
 
1274
	if (!kgem_check_batch(&sna->kgem, ndwords+1))
1275
		return false;
1276
 
1277
	if (i1_cmd) {
1278
		OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | i1_cmd | (i1_len - 1));
1279
		if (sna->render.vertex_reloc[0] == 0)
1280
			sna->render.vertex_reloc[0] = sna->kgem.nbatch++;
1281
		if (state->floats_per_vertex != op->floats_per_vertex) {
1282
			state->floats_per_vertex = op->floats_per_vertex;
1283
			OUT_BATCH(state->floats_per_vertex << S1_VERTEX_WIDTH_SHIFT |
1284
				  state->floats_per_vertex << S1_VERTEX_PITCH_SHIFT);
1285
		}
1286
	}
1287
 
1288
	if (sna->kgem.nbatch == 2 + state->last_vertex_offset &&
1289
	    !op->need_magic_ca_pass) {
1290
		sna->render.vertex_offset = state->last_vertex_offset;
1291
	} else {
1292
		sna->render.vertex_offset = sna->kgem.nbatch;
1293
		OUT_BATCH(MI_NOOP); /* to be filled later */
1294
		OUT_BATCH(MI_NOOP);
1295
		sna->render.vertex_start = sna->render.vertex_index;
1296
		state->last_vertex_offset = sna->render.vertex_offset;
1297
	}
1298
 
1299
	return true;
1300
}
1301
 
1302
static int gen3_get_rectangles__flush(struct sna *sna,
1303
				      const struct sna_composite_op *op)
1304
{
1305
	/* Preventing discarding new vbo after lock contention */
1306
	if (sna_vertex_wait__locked(&sna->render)) {
1307
		int rem = vertex_space(sna);
1308
		if (rem > op->floats_per_rect)
1309
			return rem;
1310
	}
1311
 
1312
	if (!kgem_check_batch(&sna->kgem, op->need_magic_ca_pass ? 105: 5))
1313
		return 0;
1314
	if (!kgem_check_reloc_and_exec(&sna->kgem, 1))
1315
		return 0;
1316
 
1317
	if (sna->render.vertex_offset) {
1318
		gen3_vertex_flush(sna);
1319
		if (gen3_magic_ca_pass(sna, op)) {
1320
			OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(6) | 0);
1321
			OUT_BATCH(gen3_get_blend_cntl(op->op,
1322
						      op->has_component_alpha,
1323
						      op->dst.format));
1324
			gen3_composite_emit_shader(sna, op, op->op);
1325
		}
1326
	}
1327
 
1328
	return gen3_vertex_finish(sna);
1329
}
1330
 
1331
inline static int gen3_get_rectangles(struct sna *sna,
1332
				      const struct sna_composite_op *op,
1333
				      int want)
1334
{
1335
	int rem;
1336
 
1337
	DBG(("%s: want=%d, rem=%d\n",
1338
	     __FUNCTION__, want*op->floats_per_rect, vertex_space(sna)));
1339
 
1340
	assert(want);
1341
	assert(sna->render.vertex_index * op->floats_per_vertex == sna->render.vertex_used);
1342
 
1343
start:
1344
	rem = vertex_space(sna);
1345
	if (unlikely(op->floats_per_rect > rem)) {
1346
		DBG(("flushing vbo for %s: %d < %d\n",
1347
		     __FUNCTION__, rem, op->floats_per_rect));
1348
		rem = gen3_get_rectangles__flush(sna, op);
1349
		if (unlikely(rem == 0))
1350
			goto flush;
1351
	}
1352
 
1353
	if (unlikely(sna->render.vertex_offset == 0)) {
1354
		if (!gen3_rectangle_begin(sna, op))
1355
			goto flush;
1356
		else
1357
			goto start;
1358
	}
1359
 
1360
	assert(op->floats_per_rect >= vertex_space(sna));
1361
	assert(rem <= vertex_space(sna));
1362
	if (want > 1 && want * op->floats_per_rect > rem)
1363
		want = rem / op->floats_per_rect;
1364
	sna->render.vertex_index += 3*want;
1365
 
1366
	assert(want);
1367
	assert(sna->render.vertex_index * op->floats_per_vertex <= sna->render.vertex_size);
1368
	return want;
1369
 
1370
flush:
1371
	DBG(("%s: flushing batch\n", __FUNCTION__));
1372
	if (sna->render.vertex_offset) {
1373
		gen3_vertex_flush(sna);
1374
		gen3_magic_ca_pass(sna, op);
1375
	}
1376
	sna_vertex_wait__locked(&sna->render);
1377
	_kgem_submit(&sna->kgem);
1378
	gen3_emit_composite_state(sna, op);
1379
	assert(sna->render.vertex_offset == 0);
1380
	assert(sna->render.vertex_reloc[0] == 0);
1381
	goto start;
1382
}
1383
 
1384
fastcall static void
1385
gen3_render_composite_blt(struct sna *sna,
1386
			  const struct sna_composite_op *op,
1387
			  const struct sna_composite_rectangles *r)
1388
{
1389
	DBG(("%s: src=(%d, %d)+(%d, %d), mask=(%d, %d)+(%d, %d), dst=(%d, %d)+(%d, %d), size=(%d, %d)\n", __FUNCTION__,
1390
	     r->src.x, r->src.y, op->src.offset[0], op->src.offset[1],
1391
	     r->mask.x, r->mask.y, op->mask.offset[0], op->mask.offset[1],
1392
	     r->dst.x, r->dst.y, op->dst.x, op->dst.y,
1393
	     r->width, r->height));
1394
 
1395
	gen3_get_rectangles(sna, op, 1);
1396
 
1397
	op->prim_emit(sna, op, r);
1398
}
1399
 
1400
static void
1401
gen3_render_composite_done(struct sna *sna,
1402
			   const struct sna_composite_op *op)
1403
{
1404
	DBG(("%s()\n", __FUNCTION__));
1405
 
1406
	if (sna->render.vertex_offset) {
1407
		gen3_vertex_flush(sna);
1408
		gen3_magic_ca_pass(sna, op);
1409
	}
1410
 
1411
}
1412
 
1413
static void
1414
discard_vbo(struct sna *sna)
1415
{
1416
	kgem_bo_destroy(&sna->kgem, sna->render.vbo);
1417
	sna->render.vbo = NULL;
1418
	sna->render.vertices = sna->render.vertex_data;
1419
	sna->render.vertex_size = ARRAY_SIZE(sna->render.vertex_data);
1420
	sna->render.vertex_used = 0;
1421
	sna->render.vertex_index = 0;
1422
}
1423
 
1424
static void
1425
gen3_render_reset(struct sna *sna)
1426
{
1427
	struct gen3_render_state *state = &sna->render_state.gen3;
1428
 
1429
	state->need_invariant = true;
1430
	state->current_dst = 0;
1431
	state->tex_count = 0;
1432
	state->last_drawrect_limit = ~0U;
1433
	state->last_target = 0;
1434
	state->last_blend = 0;
1435
	state->last_constants = 0;
1436
	state->last_sampler = 0;
1437
	state->last_shader = 0x7fffffff;
1438
	state->last_diffuse = 0xcc00ffee;
1439
	state->last_specular = 0xcc00ffee;
1440
 
1441
	state->floats_per_vertex = 0;
1442
	state->last_floats_per_vertex = 0;
1443
	state->last_vertex_offset = 0;
1444
 
1445
	if (sna->render.vbo != NULL &&
1446
	    !kgem_bo_is_mappable(&sna->kgem, sna->render.vbo)) {
1447
		DBG(("%s: discarding vbo as next access will stall: %d\n",
1448
		     __FUNCTION__, sna->render.vbo->presumed_offset));
1449
		discard_vbo(sna);
1450
	}
1451
 
1452
	sna->render.vertex_reloc[0] = 0;
1453
	sna->render.vertex_offset = 0;
1454
}
1455
 
1456
static void
1457
gen3_render_retire(struct kgem *kgem)
1458
{
1459
	struct sna *sna;
1460
 
1461
	sna = container_of(kgem, struct sna, kgem);
1462
	if (sna->render.vertex_reloc[0] == 0 &&
1463
	    sna->render.vbo && !kgem_bo_is_busy(sna->render.vbo)) {
1464
		DBG(("%s: resetting idle vbo\n", __FUNCTION__));
1465
		sna->render.vertex_used = 0;
1466
		sna->render.vertex_index = 0;
1467
	}
1468
}
1469
 
1470
static void
1471
gen3_render_expire(struct kgem *kgem)
1472
{
1473
	struct sna *sna;
1474
 
1475
	sna = container_of(kgem, struct sna, kgem);
1476
	if (sna->render.vbo && !sna->render.vertex_used) {
1477
		DBG(("%s: discarding vbo\n", __FUNCTION__));
1478
		discard_vbo(sna);
1479
	}
1480
}
1481
 
1482
static bool gen3_composite_channel_set_format(struct sna_composite_channel *channel,
1483
					      CARD32 format)
1484
{
1485
	unsigned int i;
1486
 
1487
	for (i = 0; i < ARRAY_SIZE(gen3_tex_formats); i++) {
1488
		if (gen3_tex_formats[i].fmt == format) {
1489
			channel->card_format = gen3_tex_formats[i].card_fmt;
1490
			channel->rb_reversed = gen3_tex_formats[i].rb_reversed;
1491
			return true;
1492
		}
1493
	}
1494
	return false;
1495
}
1496
 
1497
 
1498
 
1499
 
1500
 
1501
 
1502
 
1503
 
1504
 
1505
 
1506
 
1507
 
1508
 
1509
 
1510
 
1511
 
1512
 
1513
 
1514
 
1515
 
1516
 
1517
 
1518
 
1519
 
1520
 
1521
 
1522
 
1523
 
1524
 
1525
 
1526
 
1527
 
1528
 
1529
 
1530
 
1531
 
1532
 
1533
 
1534
 
1535
 
1536
 
1537
 
1538
 
1539
 
1540
 
1541
 
1542
 
1543
 
1544
 
1545
 
1546
 
1547
 
1548
 
1549
 
1550
 
1551
 
1552
 
1553
 
1554
 
1555
static void
1556
gen3_align_vertex(struct sna *sna,
1557
		  const struct sna_composite_op *op)
1558
{
1559
	if (op->floats_per_vertex != sna->render_state.gen3.last_floats_per_vertex) {
1560
		if (sna->render.vertex_size - sna->render.vertex_used < 2*op->floats_per_rect)
1561
			gen3_vertex_finish(sna);
1562
 
1563
		DBG(("aligning vertex: was %d, now %d floats per vertex, %d->%d\n",
1564
		     sna->render_state.gen3.last_floats_per_vertex,
1565
		     op->floats_per_vertex,
1566
		     sna->render.vertex_index,
1567
		     (sna->render.vertex_used + op->floats_per_vertex - 1) / op->floats_per_vertex));
1568
		sna->render.vertex_index = (sna->render.vertex_used + op->floats_per_vertex - 1) / op->floats_per_vertex;
1569
		sna->render.vertex_used = sna->render.vertex_index * op->floats_per_vertex;
1570
		assert(sna->render.vertex_used < sna->render.vertex_size - op->floats_per_rect);
1571
		sna->render_state.gen3.last_floats_per_vertex = op->floats_per_vertex;
1572
	}
1573
}
1574
 
1575
 
1576
 
1577
 
1578
 
1579
 
1580
 
1581
 
1582
 
1583
 
1584
 
1585
 
1586
 
1587
 
1588
 
1589
 
1590
 
1591
 
1592
 
1593
 
1594
 
1595
 
1596
 
1597
 
1598
 
1599
 
1600
 
1601
 
1602
 
1603
 
1604
 
1605
 
1606
 
1607
 
1608
 
1609
 
1610
 
1611
 
1612
 
1613
 
1614
 
1615
 
1616
 
1617
 
1618
 
1619
 
1620
 
1621
 
1622
 
1623
 
1624
 
1625
 
1626
 
1627
 
1628
 
1629
 
1630
 
1631
 
1632
 
1633
 
1634
 
1635
 
1636
 
1637
 
1638
 
1639
 
1640
 
1641
 
1642
 
1643
 
1644
 
1645
 
1646
 
1647
 
1648
 
1649
 
1650
 
1651
 
1652
 
1653
 
1654
 
1655
 
1656
 
1657
 
1658
 
1659
 
1660
 
1661
 
1662
 
1663
 
1664
 
1665
 
1666
 
1667
 
1668
 
1669
 
1670
 
1671
 
1672
 
1673
 
1674
 
1675
 
1676
 
1677
 
1678
 
1679
 
1680
 
1681
 
1682
 
1683
 
1684
 
1685
 
1686
 
1687
 
1688
 
1689
 
1690
 
1691
 
1692
 
1693
 
1694
 
1695
 
1696
 
1697
 
1698
 
1699
 
1700
 
1701
 
1702
 
1703
 
1704
 
1705
 
1706
 
1707
 
1708
 
1709
 
1710
 
1711
 
1712
 
1713
static inline bool is_constant_ps(uint32_t type)
1714
{
1715
	switch (type) {
1716
	case SHADER_NONE: /* be warned! */
1717
	case SHADER_ZERO:
1718
	case SHADER_BLACK:
1719
	case SHADER_WHITE:
1720
	case SHADER_CONSTANT:
1721
		return true;
1722
	default:
1723
		return false;
1724
	}
1725
}
1726
 
1727
 
1728
 
1729
 
1730
 
1731
 
1732
 
1733
 
1734
 
1735
 
1736
 
1737
 
1738
 
1739
 
1740
 
1741
 
1742
 
1743
 
1744
 
1745
 
1746
 
1747
 
1748
 
1749
 
1750
 
1751
 
1752
 
1753
 
1754
 
1755
 
1756
 
1757
 
1758
 
1759
 
1760
 
1761
 
1762
 
1763
 
1764
 
1765
 
1766
 
1767
 
1768
 
1769
 
1770
 
1771
 
1772
 
1773
 
1774
 
1775
 
1776
 
1777
 
1778
 
1779
 
1780
 
1781
 
1782
 
1783
 
1784
 
1785
 
1786
 
1787
 
1788
 
1789
 
1790
 
1791
 
1792
 
1793
 
1794
 
1795
 
1796
 
1797
 
1798
 
1799
 
1800
 
1801
 
1802
 
1803
 
1804
 
1805
 
1806
 
1807
 
1808
 
1809
 
1810
 
1811
 
1812
 
1813
 
1814
 
1815
 
1816
 
1817
 
1818
 
1819
 
1820
 
1821
 
1822
 
1823
 
1824
 
1825
 
1826
 
1827
 
1828
 
1829
 
1830
 
1831
 
1832
 
1833
 
1834
 
1835
static bool
1836
gen3_blit_tex(struct sna *sna,
3769 Serge 1837
              uint8_t op, bool scale,
3299 Serge 1838
		      PixmapPtr src, struct kgem_bo *src_bo,
1839
		      PixmapPtr mask,struct kgem_bo *mask_bo,
4245 Serge 1840
		      PixmapPtr dst, struct kgem_bo *dst_bo,
3299 Serge 1841
              int32_t src_x, int32_t src_y,
1842
              int32_t msk_x, int32_t msk_y,
1843
              int32_t dst_x, int32_t dst_y,
1844
              int32_t width, int32_t height,
1845
              struct sna_composite_op *tmp)
1846
{
1847
 
1848
    DBG(("%s: %dx%d, current mode=%d\n", __FUNCTION__,
1849
         width, height, sna->kgem.ring));
1850
 
1851
    tmp->op = PictOpSrc;
1852
 
1853
    tmp->dst.pixmap = dst;
1854
    tmp->dst.bo     = dst_bo;
1855
    tmp->dst.width  = dst->drawable.width;
1856
    tmp->dst.height = dst->drawable.height;
1857
    tmp->dst.format = PICT_x8r8g8b8;
1858
 
1859
	tmp->rb_reversed = gen3_dst_rb_reversed(tmp->dst.format);
1860
 
1861
	tmp->u.gen3.num_constants = 0;
1862
	tmp->src.u.gen3.type = SHADER_TEXTURE;
1863
	tmp->src.is_affine = true;
1864
 
1865
 
1866
	tmp->src.repeat = RepeatNone;
1867
	tmp->src.filter = PictFilterNearest;
1868
 
1869
    tmp->src.bo = src_bo;
1870
	tmp->src.pict_format = PICT_x8r8g8b8;
4245 Serge 1871
 
3299 Serge 1872
	gen3_composite_channel_set_format(&tmp->src, tmp->src.pict_format);
4245 Serge 1873
 
3299 Serge 1874
    tmp->src.width  = src->drawable.width;
1875
    tmp->src.height = src->drawable.height;
1876
 
1877
	tmp->mask.u.gen3.type = SHADER_TEXTURE;
1878
	tmp->mask.is_affine = true;
1879
	tmp->need_magic_ca_pass = false;
1880
	tmp->has_component_alpha = false;
1881
 
1882
 
1883
 	tmp->mask.repeat = RepeatNone;
1884
	tmp->mask.filter = PictFilterNearest;
1885
    tmp->mask.is_affine = true;
1886
 
1887
    tmp->mask.bo = mask_bo;
1888
    tmp->mask.pict_format = PIXMAN_a8;
1889
	gen3_composite_channel_set_format(&tmp->mask, tmp->mask.pict_format);
1890
    tmp->mask.width  = mask->drawable.width;
1891
    tmp->mask.height = mask->drawable.height;
1892
 
3769 Serge 1893
    if( scale )
1894
    {
1895
        tmp->src.scale[0] = 1.f/width;
1896
        tmp->src.scale[1] = 1.f/height;
1897
    }
1898
    else
1899
    {
1900
        tmp->src.scale[0] = 1.f/src->drawable.width;
1901
        tmp->src.scale[1] = 1.f/src->drawable.height;
1902
    }
3299 Serge 1903
 
1904
    tmp->mask.scale[0] = 1.f/mask->drawable.width;
1905
    tmp->mask.scale[1] = 1.f/mask->drawable.height;
1906
 
1907
	tmp->prim_emit = gen3_emit_composite_primitive_identity_source_mask;
1908
 
1909
 
1910
	tmp->floats_per_vertex = 2;
1911
	if (!is_constant_ps(tmp->src.u.gen3.type))
1912
		tmp->floats_per_vertex += tmp->src.is_affine ? 2 : 4;
1913
	if (!is_constant_ps(tmp->mask.u.gen3.type))
1914
		tmp->floats_per_vertex += tmp->mask.is_affine ? 2 : 4;
4245 Serge 1915
//	DBG(("%s: floats_per_vertex = 2 + %d + %d = %d [specialised emitter? %d]\n", __FUNCTION__,
1916
//	     !is_constant_ps(tmp->src.u.gen3.type) ? tmp->src.is_affine ? 2 : 4 : 0,
1917
//	     !is_constant_ps(tmp->mask.u.gen3.type) ? tmp->mask.is_affine ? 2 : 4 : 0,
1918
//	     tmp->floats_per_vertex,
1919
//	     tmp->prim_emit != gen3_emit_composite_primitive));
3299 Serge 1920
	tmp->floats_per_rect = 3 * tmp->floats_per_vertex;
1921
 
1922
	tmp->blt   = gen3_render_composite_blt;
1923
 
1924
	tmp->done  = gen3_render_composite_done;
1925
 
1926
	if (!kgem_check_bo(&sna->kgem,
1927
			   tmp->dst.bo, tmp->src.bo, tmp->mask.bo,
1928
			   NULL)) {
1929
		kgem_submit(&sna->kgem);
1930
	}
1931
 
1932
	gen3_emit_composite_state(sna, tmp);
1933
	gen3_align_vertex(sna, tmp);
1934
	return true;
1935
}
1936
 
1937
static void gen3_render_flush(struct sna *sna)
1938
{
1939
	gen3_vertex_close(sna);
1940
 
1941
	assert(sna->render.vertex_reloc[0] == 0);
1942
	assert(sna->render.vertex_offset == 0);
1943
}
1944
 
1945
static void
1946
gen3_render_fini(struct sna *sna)
1947
{
1948
}
1949
 
1950
bool gen3_render_init(struct sna *sna)
1951
{
1952
	struct sna_render *render = &sna->render;
1953
 
1954
 
1955
//	render->video = gen3_render_video;
1956
 
3769 Serge 1957
    render->blit_tex = gen3_blit_tex;
3299 Serge 1958
 
1959
	render->reset = gen3_render_reset;
1960
	render->flush = gen3_render_flush;
1961
	render->fini = gen3_render_fini;
1962
 
1963
	render->max_3d_size = MAX_3D_SIZE;
1964
	render->max_3d_pitch = MAX_3D_PITCH;
1965
 
3769 Serge 1966
    render->caps = HW_BIT_BLIT | HW_TEX_BLIT;
1967
 
3299 Serge 1968
	sna->kgem.retire = gen3_render_retire;
1969
	sna->kgem.expire = gen3_render_expire;
1970
	return true;
1971
}