Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
3280 Serge 1
/*
2
 * Copyright © 2012 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 "gen4_vertex.h"
36
 
4251 Serge 37
#ifndef sse2
38
#define sse2
39
#endif
40
 
3280 Serge 41
void gen4_vertex_flush(struct sna *sna)
42
{
43
    DBG(("%s[%x] = %d\n", __FUNCTION__,
44
         4*sna->render.vertex_offset,
45
         sna->render.vertex_index - sna->render.vertex_start));
46
 
47
    assert(sna->render.vertex_offset);
48
    assert(sna->render.vertex_index > sna->render.vertex_start);
49
 
50
    sna->kgem.batch[sna->render.vertex_offset] =
51
        sna->render.vertex_index - sna->render.vertex_start;
52
    sna->render.vertex_offset = 0;
53
}
54
 
55
int gen4_vertex_finish(struct sna *sna)
56
{
57
    struct kgem_bo *bo;
58
    unsigned int i;
59
    unsigned hint, size;
60
 
61
    DBG(("%s: used=%d / %d\n", __FUNCTION__,
62
         sna->render.vertex_used, sna->render.vertex_size));
63
    assert(sna->render.vertex_offset == 0);
64
    assert(sna->render.vertex_used);
65
 
66
	sna_vertex_wait__locked(&sna->render);
67
 
68
    /* Note: we only need dword alignment (currently) */
69
 
70
    bo = sna->render.vbo;
71
    if (bo) {
72
        for (i = 0; i < sna->render.nvertex_reloc; i++) {
73
            DBG(("%s: reloc[%d] = %d\n", __FUNCTION__,
74
                 i, sna->render.vertex_reloc[i]));
75
 
76
            sna->kgem.batch[sna->render.vertex_reloc[i]] =
77
                kgem_add_reloc(&sna->kgem,
78
                           sna->render.vertex_reloc[i], bo,
79
                           I915_GEM_DOMAIN_VERTEX << 16,
80
                           0);
81
        }
82
 
83
        assert(!sna->render.active);
84
        sna->render.nvertex_reloc = 0;
85
        sna->render.vertex_used = 0;
86
        sna->render.vertex_index = 0;
87
        sna->render.vbo = NULL;
88
        sna->render.vb_id = 0;
89
 
90
        kgem_bo_destroy(&sna->kgem, bo);
91
    }
92
 
93
    hint = CREATE_GTT_MAP;
94
    if (bo)
95
        hint |= CREATE_CACHED | CREATE_NO_THROTTLE;
96
 
97
    size = 256*1024;
98
    assert(!sna->render.active);
99
    sna->render.vertices = NULL;
100
    sna->render.vbo = kgem_create_linear(&sna->kgem, size, hint);
101
    while (sna->render.vbo == NULL && size > 16*1024) {
102
        size /= 2;
103
        sna->render.vbo = kgem_create_linear(&sna->kgem, size, hint);
104
    }
105
    if (sna->render.vbo == NULL)
106
        sna->render.vbo = kgem_create_linear(&sna->kgem,
107
                             256*1024, CREATE_GTT_MAP);
108
    if (sna->render.vbo)
109
        sna->render.vertices = kgem_bo_map(&sna->kgem, sna->render.vbo);
110
    if (sna->render.vertices == NULL) {
111
        if (sna->render.vbo) {
112
            kgem_bo_destroy(&sna->kgem, sna->render.vbo);
113
            sna->render.vbo = NULL;
114
        }
115
        sna->render.vertices = sna->render.vertex_data;
116
        sna->render.vertex_size = ARRAY_SIZE(sna->render.vertex_data);
117
        return 0;
118
    }
119
 
120
    if (sna->render.vertex_used) {
121
        DBG(("%s: copying initial buffer x %d to handle=%d\n",
122
             __FUNCTION__,
123
             sna->render.vertex_used,
124
             sna->render.vbo->handle));
125
        assert(sizeof(float)*sna->render.vertex_used <=
126
               __kgem_bo_size(sna->render.vbo));
127
        memcpy(sna->render.vertices,
128
               sna->render.vertex_data,
129
               sizeof(float)*sna->render.vertex_used);
130
    }
131
 
132
    size = __kgem_bo_size(sna->render.vbo)/4;
133
    if (size >= UINT16_MAX)
134
        size = UINT16_MAX - 1;
135
 
136
    DBG(("%s: create vbo handle=%d, size=%d\n",
137
         __FUNCTION__, sna->render.vbo->handle, size));
138
 
139
    sna->render.vertex_size = size;
140
    return sna->render.vertex_size - sna->render.vertex_used;
141
}
142
 
143
void gen4_vertex_close(struct sna *sna)
144
{
145
    struct kgem_bo *bo, *free_bo = NULL;
146
    unsigned int i, delta = 0;
147
 
148
    assert(sna->render.vertex_offset == 0);
149
    if (!sna->render.vb_id)
150
        return;
151
 
152
    DBG(("%s: used=%d, vbo active? %d, vb=%x, nreloc=%d\n",
153
         __FUNCTION__, sna->render.vertex_used, sna->render.vbo ? sna->render.vbo->handle : 0,
154
         sna->render.vb_id, sna->render.nvertex_reloc));
155
 
156
    assert(!sna->render.active);
157
 
158
    bo = sna->render.vbo;
159
    if (bo) {
160
        if (sna->render.vertex_size - sna->render.vertex_used < 64) {
161
            DBG(("%s: discarding vbo (full), handle=%d\n", __FUNCTION__, sna->render.vbo->handle));
162
            sna->render.vbo = NULL;
163
            sna->render.vertices = sna->render.vertex_data;
164
            sna->render.vertex_size = ARRAY_SIZE(sna->render.vertex_data);
165
            free_bo = bo;
166
        } else if (IS_CPU_MAP(bo->map) && !sna->kgem.has_llc) {
167
            DBG(("%s: converting CPU map to GTT\n", __FUNCTION__));
168
            sna->render.vertices =
169
                kgem_bo_map__gtt(&sna->kgem, sna->render.vbo);
170
            if (sna->render.vertices == NULL) {
171
                sna->render.vbo = NULL;
172
                sna->render.vertices = sna->render.vertex_data;
173
                sna->render.vertex_size = ARRAY_SIZE(sna->render.vertex_data);
174
                free_bo = bo;
175
            }
176
 
177
        }
178
    } else {
179
        if (sna->kgem.nbatch + sna->render.vertex_used <= sna->kgem.surface) {
180
            DBG(("%s: copy to batch: %d @ %d\n", __FUNCTION__,
181
                 sna->render.vertex_used, sna->kgem.nbatch));
182
            memcpy(sna->kgem.batch + sna->kgem.nbatch,
183
                   sna->render.vertex_data,
184
                   sna->render.vertex_used * 4);
185
            delta = sna->kgem.nbatch * 4;
186
            bo = NULL;
187
            sna->kgem.nbatch += sna->render.vertex_used;
188
        } else {
189
            bo = kgem_create_linear(&sna->kgem,
190
                        4*sna->render.vertex_used,
191
                        CREATE_NO_THROTTLE);
192
            if (bo && !kgem_bo_write(&sna->kgem, bo,
193
                         sna->render.vertex_data,
194
                         4*sna->render.vertex_used)) {
195
                kgem_bo_destroy(&sna->kgem, bo);
196
                bo = NULL;
197
            }
198
            DBG(("%s: new vbo: %d\n", __FUNCTION__,
199
                 sna->render.vertex_used));
200
            free_bo = bo;
201
        }
202
    }
203
 
204
    assert(sna->render.nvertex_reloc);
205
    for (i = 0; i < sna->render.nvertex_reloc; i++) {
206
        DBG(("%s: reloc[%d] = %d\n", __FUNCTION__,
207
             i, sna->render.vertex_reloc[i]));
208
 
209
        sna->kgem.batch[sna->render.vertex_reloc[i]] =
210
            kgem_add_reloc(&sna->kgem,
211
                       sna->render.vertex_reloc[i], bo,
212
                       I915_GEM_DOMAIN_VERTEX << 16,
213
                       delta);
214
    }
215
    sna->render.nvertex_reloc = 0;
216
    sna->render.vb_id = 0;
217
 
218
    if (sna->render.vbo == NULL) {
219
        assert(!sna->render.active);
220
        sna->render.vertex_used = 0;
221
        sna->render.vertex_index = 0;
222
        assert(sna->render.vertices == sna->render.vertex_data);
223
        assert(sna->render.vertex_size == ARRAY_SIZE(sna->render.vertex_data));
224
    }
225
 
226
    if (free_bo)
227
        kgem_bo_destroy(&sna->kgem, free_bo);
228
}
229
 
4251 Serge 230
/* specialised vertex emission routines */
231
 
232
#define OUT_VERTEX(x,y) vertex_emit_2s(sna, x,y) /* XXX assert(!too_large(x, y)); */
233
#define OUT_VERTEX_F(v) vertex_emit(sna, v)
234
 
235
force_inline static float
236
compute_linear(const struct sna_composite_channel *channel,
237
	       int16_t x, int16_t y)
238
{
239
	return ((x+channel->offset[0]) * channel->u.linear.dx +
240
		(y+channel->offset[1]) * channel->u.linear.dy +
241
		channel->u.linear.offset);
242
}
243
 
244
sse2 inline static void
245
emit_texcoord(struct sna *sna,
246
	      const struct sna_composite_channel *channel,
247
	      int16_t x, int16_t y)
248
{
249
	if (channel->is_solid) {
250
		OUT_VERTEX_F(x);
251
		return;
252
	}
253
 
254
	x += channel->offset[0];
255
	y += channel->offset[1];
256
 
257
	if (channel->is_affine) {
258
		float s, t;
259
 
260
		sna_get_transformed_coordinates(x, y,
261
						channel->transform,
262
						&s, &t);
263
		OUT_VERTEX_F(s * channel->scale[0]);
264
		OUT_VERTEX_F(t * channel->scale[1]);
265
	} else {
266
		float s, t, w;
267
 
268
		sna_get_transformed_coordinates_3d(x, y,
269
						   channel->transform,
270
						   &s, &t, &w);
271
		OUT_VERTEX_F(s * channel->scale[0]);
272
		OUT_VERTEX_F(t * channel->scale[1]);
273
		OUT_VERTEX_F(w);
274
	}
275
}
276
 
277
sse2 force_inline static void
278
emit_vertex(struct sna *sna,
279
	    const struct sna_composite_op *op,
280
	    int16_t srcX, int16_t srcY,
281
	    int16_t mskX, int16_t mskY,
282
	    int16_t dstX, int16_t dstY)
283
{
284
	OUT_VERTEX(dstX, dstY);
285
	emit_texcoord(sna, &op->src, srcX, srcY);
286
}
287
 
288
sse2 fastcall static void
289
emit_primitive(struct sna *sna,
290
	       const struct sna_composite_op *op,
291
	       const struct sna_composite_rectangles *r)
292
{
293
	emit_vertex(sna, op,
294
		    r->src.x + r->width,  r->src.y + r->height,
295
		    r->mask.x + r->width, r->mask.y + r->height,
296
		    r->dst.x + r->width, r->dst.y + r->height);
297
	emit_vertex(sna, op,
298
		    r->src.x,  r->src.y + r->height,
299
		    r->mask.x, r->mask.y + r->height,
300
		    r->dst.x,  r->dst.y + r->height);
301
	emit_vertex(sna, op,
302
		    r->src.x,  r->src.y,
303
		    r->mask.x, r->mask.y,
304
		    r->dst.x,  r->dst.y);
305
}
306
 
307
sse2 force_inline static void
308
emit_vertex_mask(struct sna *sna,
309
		 const struct sna_composite_op *op,
310
		 int16_t srcX, int16_t srcY,
311
		 int16_t mskX, int16_t mskY,
312
		 int16_t dstX, int16_t dstY)
313
{
314
	OUT_VERTEX(dstX, dstY);
315
	emit_texcoord(sna, &op->src, srcX, srcY);
316
	emit_texcoord(sna, &op->mask, mskX, mskY);
317
}
318
 
319
sse2 fastcall static void
320
emit_primitive_mask(struct sna *sna,
321
		    const struct sna_composite_op *op,
322
		    const struct sna_composite_rectangles *r)
323
{
324
	emit_vertex_mask(sna, op,
325
			 r->src.x + r->width,  r->src.y + r->height,
326
			 r->mask.x + r->width, r->mask.y + r->height,
327
			 r->dst.x + r->width, r->dst.y + r->height);
328
	emit_vertex_mask(sna, op,
329
			 r->src.x,  r->src.y + r->height,
330
			 r->mask.x, r->mask.y + r->height,
331
			 r->dst.x,  r->dst.y + r->height);
332
	emit_vertex_mask(sna, op,
333
			 r->src.x,  r->src.y,
334
			 r->mask.x, r->mask.y,
335
			 r->dst.x,  r->dst.y);
336
}
337
 
338
sse2 fastcall static void
339
emit_primitive_solid(struct sna *sna,
340
		     const struct sna_composite_op *op,
341
		     const struct sna_composite_rectangles *r)
342
{
343
	float *v;
344
	union {
345
		struct sna_coordinate p;
346
		float f;
347
	} dst;
348
 
349
	assert(op->floats_per_rect == 6);
350
	assert((sna->render.vertex_used % 2) == 0);
351
	v = sna->render.vertices + sna->render.vertex_used;
352
	sna->render.vertex_used += 6;
353
	assert(sna->render.vertex_used <= sna->render.vertex_size);
354
 
355
	dst.p.x = r->dst.x + r->width;
356
	dst.p.y = r->dst.y + r->height;
357
	v[0] = dst.f;
358
	dst.p.x = r->dst.x;
359
	v[2] = dst.f;
360
	dst.p.y = r->dst.y;
361
	v[4] = dst.f;
362
 
363
	v[5] = v[3] = v[1] = .5;
364
}
365
 
366
sse2 fastcall static void
367
emit_boxes_solid(const struct sna_composite_op *op,
368
		 const BoxRec *box, int nbox,
369
		 float *v)
370
{
371
	do {
372
		union {
373
			struct sna_coordinate p;
374
			float f;
375
		} dst;
376
 
377
		dst.p.x = box->x2;
378
		dst.p.y = box->y2;
379
		v[0] = dst.f;
380
		dst.p.x = box->x1;
381
		v[2] = dst.f;
382
		dst.p.y = box->y1;
383
		v[4] = dst.f;
384
 
385
		v[5] = v[3] = v[1] = .5;
386
		box++;
387
		v += 6;
388
	} while (--nbox);
389
}
390
 
391
sse2 fastcall static void
392
emit_primitive_linear(struct sna *sna,
393
		      const struct sna_composite_op *op,
394
		      const struct sna_composite_rectangles *r)
395
{
396
	float *v;
397
	union {
398
		struct sna_coordinate p;
399
		float f;
400
	} dst;
401
 
402
	assert(op->floats_per_rect == 6);
403
	assert((sna->render.vertex_used % 2) == 0);
404
	v = sna->render.vertices + sna->render.vertex_used;
405
	sna->render.vertex_used += 6;
406
	assert(sna->render.vertex_used <= sna->render.vertex_size);
407
 
408
	dst.p.x = r->dst.x + r->width;
409
	dst.p.y = r->dst.y + r->height;
410
	v[0] = dst.f;
411
	dst.p.x = r->dst.x;
412
	v[2] = dst.f;
413
	dst.p.y = r->dst.y;
414
	v[4] = dst.f;
415
 
416
	v[1] = compute_linear(&op->src, r->src.x+r->width, r->src.y+r->height);
417
	v[3] = compute_linear(&op->src, r->src.x, r->src.y+r->height);
418
	v[5] = compute_linear(&op->src, r->src.x, r->src.y);
419
}
420
 
421
sse2 fastcall static void
422
emit_boxes_linear(const struct sna_composite_op *op,
423
		  const BoxRec *box, int nbox,
424
		  float *v)
425
{
426
	union {
427
		struct sna_coordinate p;
428
		float f;
429
	} dst;
430
 
431
	do {
432
		dst.p.x = box->x2;
433
		dst.p.y = box->y2;
434
		v[0] = dst.f;
435
		dst.p.x = box->x1;
436
		v[2] = dst.f;
437
		dst.p.y = box->y1;
438
		v[4] = dst.f;
439
 
440
		v[1] = compute_linear(&op->src, box->x2, box->y2);
441
		v[3] = compute_linear(&op->src, box->x1, box->y2);
442
		v[5] = compute_linear(&op->src, box->x1, box->y1);
443
 
444
		v += 6;
445
		box++;
446
	} while (--nbox);
447
}
448
 
449
sse2 fastcall static void
450
emit_primitive_identity_source(struct sna *sna,
451
			       const struct sna_composite_op *op,
452
			       const struct sna_composite_rectangles *r)
453
{
454
	union {
455
		struct sna_coordinate p;
456
		float f;
457
	} dst;
458
	float *v;
459
 
460
	assert(op->floats_per_rect == 9);
461
	assert((sna->render.vertex_used % 3) == 0);
462
	v = sna->render.vertices + sna->render.vertex_used;
463
	sna->render.vertex_used += 9;
464
 
465
	dst.p.x = r->dst.x + r->width;
466
	dst.p.y = r->dst.y + r->height;
467
	v[0] = dst.f;
468
	dst.p.x = r->dst.x;
469
	v[3] = dst.f;
470
	dst.p.y = r->dst.y;
471
	v[6] = dst.f;
472
 
473
	v[7] = v[4] = (r->src.x + op->src.offset[0]) * op->src.scale[0];
474
	v[1] = v[4] + r->width * op->src.scale[0];
475
 
476
	v[8] = (r->src.y + op->src.offset[1]) * op->src.scale[1];
477
	v[5] = v[2] = v[8] + r->height * op->src.scale[1];
478
}
479
 
480
sse2 fastcall static void
481
emit_boxes_identity_source(const struct sna_composite_op *op,
482
			   const BoxRec *box, int nbox,
483
			   float *v)
484
{
485
	do {
486
		union {
487
			struct sna_coordinate p;
488
			float f;
489
		} dst;
490
 
491
		dst.p.x = box->x2;
492
		dst.p.y = box->y2;
493
		v[0] = dst.f;
494
		dst.p.x = box->x1;
495
		v[3] = dst.f;
496
		dst.p.y = box->y1;
497
		v[6] = dst.f;
498
 
499
		v[7] = v[4] = (box->x1 + op->src.offset[0]) * op->src.scale[0];
500
		v[1] = (box->x2 + op->src.offset[0]) * op->src.scale[0];
501
 
502
		v[8] = (box->y1 + op->src.offset[1]) * op->src.scale[1];
503
		v[2] = v[5] = (box->y2 + op->src.offset[1]) * op->src.scale[1];
504
 
505
		v += 9;
506
		box++;
507
	} while (--nbox);
508
}
509
 
510
sse2 fastcall static void
511
emit_primitive_simple_source(struct sna *sna,
512
			     const struct sna_composite_op *op,
513
			     const struct sna_composite_rectangles *r)
514
{
515
	float *v;
516
	union {
517
		struct sna_coordinate p;
518
		float f;
519
	} dst;
520
 
521
	float xx = op->src.transform->matrix[0][0];
522
	float x0 = op->src.transform->matrix[0][2];
523
	float yy = op->src.transform->matrix[1][1];
524
	float y0 = op->src.transform->matrix[1][2];
525
	float sx = op->src.scale[0];
526
	float sy = op->src.scale[1];
527
	int16_t tx = op->src.offset[0];
528
	int16_t ty = op->src.offset[1];
529
 
530
	assert(op->floats_per_rect == 9);
531
	assert((sna->render.vertex_used % 3) == 0);
532
	v = sna->render.vertices + sna->render.vertex_used;
533
	sna->render.vertex_used += 3*3;
534
 
535
	dst.p.x = r->dst.x + r->width;
536
	dst.p.y = r->dst.y + r->height;
537
	v[0] = dst.f;
538
	v[1] = ((r->src.x + r->width + tx) * xx + x0) * sx;
539
	v[5] = v[2] = ((r->src.y + r->height + ty) * yy + y0) * sy;
540
 
541
	dst.p.x = r->dst.x;
542
	v[3] = dst.f;
543
	v[7] = v[4] = ((r->src.x + tx) * xx + x0) * sx;
544
 
545
	dst.p.y = r->dst.y;
546
	v[6] = dst.f;
547
	v[8] = ((r->src.y + ty) * yy + y0) * sy;
548
}
549
 
550
sse2 fastcall static void
551
emit_boxes_simple_source(const struct sna_composite_op *op,
552
			 const BoxRec *box, int nbox,
553
			 float *v)
554
{
555
	float xx = op->src.transform->matrix[0][0];
556
	float x0 = op->src.transform->matrix[0][2];
557
	float yy = op->src.transform->matrix[1][1];
558
	float y0 = op->src.transform->matrix[1][2];
559
	float sx = op->src.scale[0];
560
	float sy = op->src.scale[1];
561
	int16_t tx = op->src.offset[0];
562
	int16_t ty = op->src.offset[1];
563
 
564
	do {
565
		union {
566
			struct sna_coordinate p;
567
			float f;
568
		} dst;
569
 
570
		dst.p.x = box->x2;
571
		dst.p.y = box->y2;
572
		v[0] = dst.f;
573
		v[1] = ((box->x2 + tx) * xx + x0) * sx;
574
		v[5] = v[2] = ((box->y2 + ty) * yy + y0) * sy;
575
 
576
		dst.p.x = box->x1;
577
		v[3] = dst.f;
578
		v[7] = v[4] = ((box->x1 + tx) * xx + x0) * sx;
579
 
580
		dst.p.y = box->y1;
581
		v[6] = dst.f;
582
		v[8] = ((box->y1 + ty) * yy + y0) * sy;
583
 
584
		v += 9;
585
		box++;
586
	} while (--nbox);
587
}
588
 
589
sse2 fastcall static void
590
emit_primitive_affine_source(struct sna *sna,
591
			     const struct sna_composite_op *op,
592
			     const struct sna_composite_rectangles *r)
593
{
594
	union {
595
		struct sna_coordinate p;
596
		float f;
597
	} dst;
598
	float *v;
599
 
600
	assert(op->floats_per_rect == 9);
601
	assert((sna->render.vertex_used % 3) == 0);
602
	v = sna->render.vertices + sna->render.vertex_used;
603
	sna->render.vertex_used += 9;
604
 
605
	dst.p.x = r->dst.x + r->width;
606
	dst.p.y = r->dst.y + r->height;
607
	v[0] = dst.f;
608
	_sna_get_transformed_scaled(op->src.offset[0] + r->src.x + r->width,
609
				    op->src.offset[1] + r->src.y + r->height,
610
				    op->src.transform, op->src.scale,
611
				    &v[1], &v[2]);
612
 
613
	dst.p.x = r->dst.x;
614
	v[3] = dst.f;
615
	_sna_get_transformed_scaled(op->src.offset[0] + r->src.x,
616
				    op->src.offset[1] + r->src.y + r->height,
617
				    op->src.transform, op->src.scale,
618
				    &v[4], &v[5]);
619
 
620
	dst.p.y = r->dst.y;
621
	v[6] = dst.f;
622
	_sna_get_transformed_scaled(op->src.offset[0] + r->src.x,
623
				    op->src.offset[1] + r->src.y,
624
				    op->src.transform, op->src.scale,
625
				    &v[7], &v[8]);
626
}
627
 
628
sse2 fastcall static void
629
emit_boxes_affine_source(const struct sna_composite_op *op,
630
			 const BoxRec *box, int nbox,
631
			 float *v)
632
{
633
	do {
634
		union {
635
			struct sna_coordinate p;
636
			float f;
637
		} dst;
638
 
639
		dst.p.x = box->x2;
640
		dst.p.y = box->y2;
641
		v[0] = dst.f;
642
		_sna_get_transformed_scaled(op->src.offset[0] + box->x2,
643
					    op->src.offset[1] + box->y2,
644
					    op->src.transform, op->src.scale,
645
					    &v[1], &v[2]);
646
 
647
		dst.p.x = box->x1;
648
		v[3] = dst.f;
649
		_sna_get_transformed_scaled(op->src.offset[0] + box->x1,
650
					    op->src.offset[1] + box->y2,
651
					    op->src.transform, op->src.scale,
652
					    &v[4], &v[5]);
653
 
654
		dst.p.y = box->y1;
655
		v[6] = dst.f;
656
		_sna_get_transformed_scaled(op->src.offset[0] + box->x1,
657
					    op->src.offset[1] + box->y1,
658
					    op->src.transform, op->src.scale,
659
					    &v[7], &v[8]);
660
		box++;
661
		v += 9;
662
	} while (--nbox);
663
}
664
 
665
sse2 fastcall static void
666
emit_primitive_identity_mask(struct sna *sna,
667
			     const struct sna_composite_op *op,
668
			     const struct sna_composite_rectangles *r)
669
{
670
	union {
671
		struct sna_coordinate p;
672
		float f;
673
	} dst;
674
	float msk_x, msk_y;
675
	float w, h;
676
	float *v;
677
 
678
	msk_x = r->mask.x + op->mask.offset[0];
679
	msk_y = r->mask.y + op->mask.offset[1];
680
	w = r->width;
681
	h = r->height;
682
 
683
	DBG(("%s: dst=(%d, %d), mask=(%f, %f) x (%f, %f)\n",
684
	     __FUNCTION__, r->dst.x, r->dst.y, msk_x, msk_y, w, h));
685
 
686
	assert(op->floats_per_rect == 12);
687
	assert((sna->render.vertex_used % 4) == 0);
688
	v = sna->render.vertices + sna->render.vertex_used;
689
	sna->render.vertex_used += 12;
690
 
691
	dst.p.x = r->dst.x + r->width;
692
	dst.p.y = r->dst.y + r->height;
693
	v[0] = dst.f;
694
	v[2] = (msk_x + w) * op->mask.scale[0];
695
	v[7] = v[3] = (msk_y + h) * op->mask.scale[1];
696
 
697
	dst.p.x = r->dst.x;
698
	v[4] = dst.f;
699
	v[10] = v[6] = msk_x * op->mask.scale[0];
700
 
701
	dst.p.y = r->dst.y;
702
	v[8] = dst.f;
703
	v[11] = msk_y * op->mask.scale[1];
704
 
705
	v[9] = v[5] = v[1] = .5;
706
}
707
 
708
sse2 fastcall static void
709
emit_boxes_identity_mask(const struct sna_composite_op *op,
710
			 const BoxRec *box, int nbox,
711
			 float *v)
712
{
713
	float msk_x = op->mask.offset[0];
714
	float msk_y = op->mask.offset[1];
715
 
716
	do {
717
		union {
718
			struct sna_coordinate p;
719
			float f;
720
		} dst;
721
 
722
		dst.p.x = box->x2;
723
		dst.p.y = box->y2;
724
		v[0] = dst.f;
725
		v[2] = (msk_x + box->x2) * op->mask.scale[0];
726
		v[7] = v[3] = (msk_y + box->y2) * op->mask.scale[1];
727
 
728
		dst.p.x = box->x1;
729
		v[4] = dst.f;
730
		v[10] = v[6] = (msk_x + box->x1) * op->mask.scale[0];
731
 
732
		dst.p.y = box->y1;
733
		v[8] = dst.f;
734
		v[11] = (msk_y + box->y1) * op->mask.scale[1];
735
 
736
		v[9] = v[5] = v[1] = .5;
737
		v += 12;
738
		box++;
739
	} while (--nbox);
740
}
741
 
742
sse2 fastcall static void
743
emit_primitive_linear_identity_mask(struct sna *sna,
744
				    const struct sna_composite_op *op,
745
				    const struct sna_composite_rectangles *r)
746
{
747
	union {
748
		struct sna_coordinate p;
749
		float f;
750
	} dst;
751
	float msk_x, msk_y;
752
	float w, h;
753
	float *v;
754
 
755
	msk_x = r->mask.x + op->mask.offset[0];
756
	msk_y = r->mask.y + op->mask.offset[1];
757
	w = r->width;
758
	h = r->height;
759
 
760
	DBG(("%s: dst=(%d, %d), mask=(%f, %f) x (%f, %f)\n",
761
	     __FUNCTION__, r->dst.x, r->dst.y, msk_x, msk_y, w, h));
762
 
763
	assert(op->floats_per_rect == 12);
764
	assert((sna->render.vertex_used % 4) == 0);
765
	v = sna->render.vertices + sna->render.vertex_used;
766
	sna->render.vertex_used += 12;
767
 
768
	dst.p.x = r->dst.x + r->width;
769
	dst.p.y = r->dst.y + r->height;
770
	v[0] = dst.f;
771
	v[2] = (msk_x + w) * op->mask.scale[0];
772
	v[7] = v[3] = (msk_y + h) * op->mask.scale[1];
773
 
774
	dst.p.x = r->dst.x;
775
	v[4] = dst.f;
776
	v[10] = v[6] = msk_x * op->mask.scale[0];
777
 
778
	dst.p.y = r->dst.y;
779
	v[8] = dst.f;
780
	v[11] = msk_y * op->mask.scale[1];
781
 
782
	v[1] = compute_linear(&op->src, r->src.x+r->width, r->src.y+r->height);
783
	v[5] = compute_linear(&op->src, r->src.x, r->src.y+r->height);
784
	v[9] = compute_linear(&op->src, r->src.x, r->src.y);
785
}
786
 
787
sse2 fastcall static void
788
emit_boxes_linear_identity_mask(const struct sna_composite_op *op,
789
				const BoxRec *box, int nbox,
790
				float *v)
791
{
792
	float msk_x = op->mask.offset[0];
793
	float msk_y = op->mask.offset[1];
794
 
795
	do {
796
		union {
797
			struct sna_coordinate p;
798
			float f;
799
		} dst;
800
 
801
		dst.p.x = box->x2;
802
		dst.p.y = box->y2;
803
		v[0] = dst.f;
804
		v[2] = (msk_x + box->x2) * op->mask.scale[0];
805
		v[7] = v[3] = (msk_y + box->y2) * op->mask.scale[1];
806
 
807
		dst.p.x = box->x1;
808
		v[4] = dst.f;
809
		v[10] = v[6] = (msk_x + box->x1) * op->mask.scale[0];
810
 
811
		dst.p.y = box->y1;
812
		v[8] = dst.f;
813
		v[11] = (msk_y + box->y1) * op->mask.scale[1];
814
 
815
		v[1] = compute_linear(&op->src, box->x2, box->y2);
816
		v[5] = compute_linear(&op->src, box->x1, box->y2);
817
		v[9] = compute_linear(&op->src, box->x1, box->y1);
818
 
819
		v += 12;
820
		box++;
821
	} while (--nbox);
822
}
823
 
824
sse2 fastcall static void
3280 Serge 825
emit_primitive_identity_source_mask(struct sna *sna,
826
				    const struct sna_composite_op *op,
827
				    const struct sna_composite_rectangles *r)
828
{
829
	union {
830
		struct sna_coordinate p;
831
		float f;
832
	} dst;
833
	float src_x, src_y;
834
	float msk_x, msk_y;
835
	float w, h;
836
	float *v;
837
 
838
	src_x = r->src.x + op->src.offset[0];
839
	src_y = r->src.y + op->src.offset[1];
840
	msk_x = r->mask.x + op->mask.offset[0];
841
	msk_y = r->mask.y + op->mask.offset[1];
842
	w = r->width;
843
	h = r->height;
844
 
845
	assert(op->floats_per_rect == 15);
846
	assert((sna->render.vertex_used % 5) == 0);
847
	v = sna->render.vertices + sna->render.vertex_used;
848
	sna->render.vertex_used += 15;
849
 
850
	dst.p.x = r->dst.x + r->width;
851
	dst.p.y = r->dst.y + r->height;
852
	v[0] = dst.f;
853
	v[1] = (src_x + w) * op->src.scale[0];
854
	v[2] = (src_y + h) * op->src.scale[1];
855
	v[3] = (msk_x + w) * op->mask.scale[0];
856
	v[4] = (msk_y + h) * op->mask.scale[1];
857
 
858
	dst.p.x = r->dst.x;
859
	v[5] = dst.f;
860
	v[6] = src_x * op->src.scale[0];
861
	v[7] = v[2];
862
	v[8] = msk_x * op->mask.scale[0];
863
	v[9] = v[4];
864
 
865
	dst.p.y = r->dst.y;
866
	v[10] = dst.f;
867
	v[11] = v[6];
868
	v[12] = src_y * op->src.scale[1];
869
	v[13] = v[8];
870
	v[14] = msk_y * op->mask.scale[1];
871
}
872
 
4251 Serge 873
sse2 fastcall static void
874
emit_primitive_simple_source_identity(struct sna *sna,
875
				      const struct sna_composite_op *op,
876
				      const struct sna_composite_rectangles *r)
3280 Serge 877
{
4251 Serge 878
	float *v;
879
	union {
880
		struct sna_coordinate p;
881
		float f;
882
	} dst;
883
 
884
	float xx = op->src.transform->matrix[0][0];
885
	float x0 = op->src.transform->matrix[0][2];
886
	float yy = op->src.transform->matrix[1][1];
887
	float y0 = op->src.transform->matrix[1][2];
888
	float sx = op->src.scale[0];
889
	float sy = op->src.scale[1];
890
	int16_t tx = op->src.offset[0];
891
	int16_t ty = op->src.offset[1];
892
	float msk_x = r->mask.x + op->mask.offset[0];
893
	float msk_y = r->mask.y + op->mask.offset[1];
894
	float w = r->width, h = r->height;
895
 
896
	assert(op->floats_per_rect == 15);
897
	assert((sna->render.vertex_used % 5) == 0);
898
	v = sna->render.vertices + sna->render.vertex_used;
899
	sna->render.vertex_used += 3*5;
900
 
901
	dst.p.x = r->dst.x + r->width;
902
	dst.p.y = r->dst.y + r->height;
903
	v[0] = dst.f;
904
	v[1] = ((r->src.x + r->width + tx) * xx + x0) * sx;
905
	v[2] = ((r->src.y + r->height + ty) * yy + y0) * sy;
906
	v[3] = (msk_x + w) * op->mask.scale[0];
907
	v[4] = (msk_y + h) * op->mask.scale[1];
908
 
909
	dst.p.x = r->dst.x;
910
	v[5] = dst.f;
911
	v[6] = ((r->src.x + tx) * xx + x0) * sx;
912
	v[7] = v[2];
913
	v[8] = msk_x * op->mask.scale[0];
914
	v[9] = v[4];
915
 
916
	dst.p.y = r->dst.y;
917
	v[10] = dst.f;
918
	v[11] = v[6];
919
	v[12] = ((r->src.y + ty) * yy + y0) * sy;
920
	v[13] = v[8];
921
	v[14] = msk_y * op->mask.scale[1];
922
}
923
 
924
sse2 fastcall static void
925
emit_primitive_affine_source_identity(struct sna *sna,
926
				      const struct sna_composite_op *op,
927
				      const struct sna_composite_rectangles *r)
928
{
929
	float *v;
930
	union {
931
		struct sna_coordinate p;
932
		float f;
933
	} dst;
934
	float msk_x = r->mask.x + op->mask.offset[0];
935
	float msk_y = r->mask.y + op->mask.offset[1];
936
	float w = r->width, h = r->height;
937
 
938
	assert(op->floats_per_rect == 15);
939
	assert((sna->render.vertex_used % 5) == 0);
940
	v = sna->render.vertices + sna->render.vertex_used;
941
	sna->render.vertex_used += 3*5;
942
 
943
	dst.p.x = r->dst.x + r->width;
944
	dst.p.y = r->dst.y + r->height;
945
	v[0] = dst.f;
946
	_sna_get_transformed_scaled(op->src.offset[0] + r->src.x + r->width,
947
				    op->src.offset[1] + r->src.y + r->height,
948
				    op->src.transform, op->src.scale,
949
				    &v[1], &v[2]);
950
	v[3] = (msk_x + w) * op->mask.scale[0];
951
	v[4] = (msk_y + h) * op->mask.scale[1];
952
 
953
	dst.p.x = r->dst.x;
954
	v[5] = dst.f;
955
	_sna_get_transformed_scaled(op->src.offset[0] + r->src.x,
956
				    op->src.offset[1] + r->src.y + r->height,
957
				    op->src.transform, op->src.scale,
958
				    &v[6], &v[7]);
959
	v[8] = msk_x * op->mask.scale[0];
960
	v[9] = v[4];
961
 
962
	dst.p.y = r->dst.y;
963
	v[10] = dst.f;
964
	_sna_get_transformed_scaled(op->src.offset[0] + r->src.x,
965
				    op->src.offset[1] + r->src.y,
966
				    op->src.transform, op->src.scale,
967
				    &v[11], &v[12]);
968
	v[13] = v[8];
969
	v[14] = msk_y * op->mask.scale[1];
970
}
971
 
972
/* SSE4_2 */
973
#if defined(sse4_2)
974
 
975
sse4_2 fastcall static void
976
emit_primitive_linear__sse4_2(struct sna *sna,
977
			      const struct sna_composite_op *op,
978
			      const struct sna_composite_rectangles *r)
979
{
980
	float *v;
981
	union {
982
		struct sna_coordinate p;
983
		float f;
984
	} dst;
985
 
986
	assert(op->floats_per_rect == 6);
987
	assert((sna->render.vertex_used % 2) == 0);
988
	v = sna->render.vertices + sna->render.vertex_used;
989
	sna->render.vertex_used += 6;
990
	assert(sna->render.vertex_used <= sna->render.vertex_size);
991
 
992
	dst.p.x = r->dst.x + r->width;
993
	dst.p.y = r->dst.y + r->height;
994
	v[0] = dst.f;
995
	dst.p.x = r->dst.x;
996
	v[2] = dst.f;
997
	dst.p.y = r->dst.y;
998
	v[4] = dst.f;
999
 
1000
	v[1] = compute_linear(&op->src, r->src.x+r->width, r->src.y+r->height);
1001
	v[3] = compute_linear(&op->src, r->src.x, r->src.y+r->height);
1002
	v[5] = compute_linear(&op->src, r->src.x, r->src.y);
1003
}
1004
 
1005
sse4_2 fastcall static void
1006
emit_boxes_linear__sse4_2(const struct sna_composite_op *op,
1007
			  const BoxRec *box, int nbox,
1008
			  float *v)
1009
{
1010
	union {
1011
		struct sna_coordinate p;
1012
		float f;
1013
	} dst;
1014
 
1015
	do {
1016
		dst.p.x = box->x2;
1017
		dst.p.y = box->y2;
1018
		v[0] = dst.f;
1019
		dst.p.x = box->x1;
1020
		v[2] = dst.f;
1021
		dst.p.y = box->y1;
1022
		v[4] = dst.f;
1023
 
1024
		v[1] = compute_linear(&op->src, box->x2, box->y2);
1025
		v[3] = compute_linear(&op->src, box->x1, box->y2);
1026
		v[5] = compute_linear(&op->src, box->x1, box->y1);
1027
 
1028
		v += 6;
1029
		box++;
1030
	} while (--nbox);
1031
}
1032
 
1033
sse4_2 fastcall static void
1034
emit_primitive_identity_source__sse4_2(struct sna *sna,
1035
				       const struct sna_composite_op *op,
1036
				       const struct sna_composite_rectangles *r)
1037
{
1038
	union {
1039
		struct sna_coordinate p;
1040
		float f;
1041
	} dst;
1042
	float *v;
1043
 
1044
	assert(op->floats_per_rect == 9);
1045
	assert((sna->render.vertex_used % 3) == 0);
1046
	v = sna->render.vertices + sna->render.vertex_used;
1047
	sna->render.vertex_used += 9;
1048
 
1049
	dst.p.x = r->dst.x + r->width;
1050
	dst.p.y = r->dst.y + r->height;
1051
	v[0] = dst.f;
1052
	dst.p.x = r->dst.x;
1053
	v[3] = dst.f;
1054
	dst.p.y = r->dst.y;
1055
	v[6] = dst.f;
1056
 
1057
	v[7] = v[4] = (r->src.x + op->src.offset[0]) * op->src.scale[0];
1058
	v[1] = v[4] + r->width * op->src.scale[0];
1059
 
1060
	v[8] = (r->src.y + op->src.offset[1]) * op->src.scale[1];
1061
	v[5] = v[2] = v[8] + r->height * op->src.scale[1];
1062
}
1063
 
1064
sse4_2 fastcall static void
1065
emit_boxes_identity_source__sse4_2(const struct sna_composite_op *op,
1066
				   const BoxRec *box, int nbox,
1067
				   float *v)
1068
{
1069
	do {
1070
		union {
1071
			struct sna_coordinate p;
1072
			float f;
1073
		} dst;
1074
 
1075
		dst.p.x = box->x2;
1076
		dst.p.y = box->y2;
1077
		v[0] = dst.f;
1078
		dst.p.x = box->x1;
1079
		v[3] = dst.f;
1080
		dst.p.y = box->y1;
1081
		v[6] = dst.f;
1082
 
1083
		v[7] = v[4] = (box->x1 + op->src.offset[0]) * op->src.scale[0];
1084
		v[1] = (box->x2 + op->src.offset[0]) * op->src.scale[0];
1085
 
1086
		v[8] = (box->y1 + op->src.offset[1]) * op->src.scale[1];
1087
		v[2] = v[5] = (box->y2 + op->src.offset[1]) * op->src.scale[1];
1088
 
1089
		v += 9;
1090
		box++;
1091
	} while (--nbox);
1092
}
1093
 
1094
sse4_2 fastcall static void
1095
emit_primitive_simple_source__sse4_2(struct sna *sna,
1096
				     const struct sna_composite_op *op,
1097
				     const struct sna_composite_rectangles *r)
1098
{
1099
	float *v;
1100
	union {
1101
		struct sna_coordinate p;
1102
		float f;
1103
	} dst;
1104
 
1105
	float xx = op->src.transform->matrix[0][0];
1106
	float x0 = op->src.transform->matrix[0][2];
1107
	float yy = op->src.transform->matrix[1][1];
1108
	float y0 = op->src.transform->matrix[1][2];
1109
	float sx = op->src.scale[0];
1110
	float sy = op->src.scale[1];
1111
	int16_t tx = op->src.offset[0];
1112
	int16_t ty = op->src.offset[1];
1113
 
1114
	assert(op->floats_per_rect == 9);
1115
	assert((sna->render.vertex_used % 3) == 0);
1116
	v = sna->render.vertices + sna->render.vertex_used;
1117
	sna->render.vertex_used += 3*3;
1118
 
1119
	dst.p.x = r->dst.x + r->width;
1120
	dst.p.y = r->dst.y + r->height;
1121
	v[0] = dst.f;
1122
	v[1] = ((r->src.x + r->width + tx) * xx + x0) * sx;
1123
	v[5] = v[2] = ((r->src.y + r->height + ty) * yy + y0) * sy;
1124
 
1125
	dst.p.x = r->dst.x;
1126
	v[3] = dst.f;
1127
	v[7] = v[4] = ((r->src.x + tx) * xx + x0) * sx;
1128
 
1129
	dst.p.y = r->dst.y;
1130
	v[6] = dst.f;
1131
	v[8] = ((r->src.y + ty) * yy + y0) * sy;
1132
}
1133
 
1134
sse4_2 fastcall static void
1135
emit_boxes_simple_source__sse4_2(const struct sna_composite_op *op,
1136
				 const BoxRec *box, int nbox,
1137
				 float *v)
1138
{
1139
	float xx = op->src.transform->matrix[0][0];
1140
	float x0 = op->src.transform->matrix[0][2];
1141
	float yy = op->src.transform->matrix[1][1];
1142
	float y0 = op->src.transform->matrix[1][2];
1143
	float sx = op->src.scale[0];
1144
	float sy = op->src.scale[1];
1145
	int16_t tx = op->src.offset[0];
1146
	int16_t ty = op->src.offset[1];
1147
 
1148
	do {
1149
		union {
1150
			struct sna_coordinate p;
1151
			float f;
1152
		} dst;
1153
 
1154
		dst.p.x = box->x2;
1155
		dst.p.y = box->y2;
1156
		v[0] = dst.f;
1157
		v[1] = ((box->x2 + tx) * xx + x0) * sx;
1158
		v[5] = v[2] = ((box->y2 + ty) * yy + y0) * sy;
1159
 
1160
		dst.p.x = box->x1;
1161
		v[3] = dst.f;
1162
		v[7] = v[4] = ((box->x1 + tx) * xx + x0) * sx;
1163
 
1164
		dst.p.y = box->y1;
1165
		v[6] = dst.f;
1166
		v[8] = ((box->y1 + ty) * yy + y0) * sy;
1167
 
1168
		v += 9;
1169
		box++;
1170
	} while (--nbox);
1171
}
1172
 
1173
sse4_2 fastcall static void
1174
emit_primitive_identity_mask__sse4_2(struct sna *sna,
1175
				     const struct sna_composite_op *op,
1176
				     const struct sna_composite_rectangles *r)
1177
{
1178
	union {
1179
		struct sna_coordinate p;
1180
		float f;
1181
	} dst;
1182
	float msk_x, msk_y;
1183
	float w, h;
1184
	float *v;
1185
 
1186
	msk_x = r->mask.x + op->mask.offset[0];
1187
	msk_y = r->mask.y + op->mask.offset[1];
1188
	w = r->width;
1189
	h = r->height;
1190
 
1191
	DBG(("%s: dst=(%d, %d), mask=(%f, %f) x (%f, %f)\n",
1192
	     __FUNCTION__, r->dst.x, r->dst.y, msk_x, msk_y, w, h));
1193
 
1194
	assert(op->floats_per_rect == 12);
1195
	assert((sna->render.vertex_used % 4) == 0);
1196
	v = sna->render.vertices + sna->render.vertex_used;
1197
	sna->render.vertex_used += 12;
1198
 
1199
	dst.p.x = r->dst.x + r->width;
1200
	dst.p.y = r->dst.y + r->height;
1201
	v[0] = dst.f;
1202
	v[2] = (msk_x + w) * op->mask.scale[0];
1203
	v[7] = v[3] = (msk_y + h) * op->mask.scale[1];
1204
 
1205
	dst.p.x = r->dst.x;
1206
	v[4] = dst.f;
1207
	v[10] = v[6] = msk_x * op->mask.scale[0];
1208
 
1209
	dst.p.y = r->dst.y;
1210
	v[8] = dst.f;
1211
	v[11] = msk_y * op->mask.scale[1];
1212
 
1213
	v[9] = v[5] = v[1] = .5;
1214
}
1215
 
1216
sse4_2 fastcall static void
1217
emit_boxes_identity_mask__sse4_2(const struct sna_composite_op *op,
1218
				 const BoxRec *box, int nbox,
1219
				 float *v)
1220
{
1221
	float msk_x = op->mask.offset[0];
1222
	float msk_y = op->mask.offset[1];
1223
 
1224
	do {
1225
		union {
1226
			struct sna_coordinate p;
1227
			float f;
1228
		} dst;
1229
 
1230
		dst.p.x = box->x2;
1231
		dst.p.y = box->y2;
1232
		v[0] = dst.f;
1233
		v[2] = (msk_x + box->x2) * op->mask.scale[0];
1234
		v[7] = v[3] = (msk_y + box->y2) * op->mask.scale[1];
1235
 
1236
		dst.p.x = box->x1;
1237
		v[4] = dst.f;
1238
		v[10] = v[6] = (msk_x + box->x1) * op->mask.scale[0];
1239
 
1240
		dst.p.y = box->y1;
1241
		v[8] = dst.f;
1242
		v[11] = (msk_y + box->y1) * op->mask.scale[1];
1243
 
1244
		v[9] = v[5] = v[1] = .5;
1245
		v += 12;
1246
		box++;
1247
	} while (--nbox);
1248
}
1249
 
1250
sse4_2 fastcall static void
1251
emit_primitive_linear_identity_mask__sse4_2(struct sna *sna,
1252
					    const struct sna_composite_op *op,
1253
					    const struct sna_composite_rectangles *r)
1254
{
1255
	union {
1256
		struct sna_coordinate p;
1257
		float f;
1258
	} dst;
1259
	float msk_x, msk_y;
1260
	float w, h;
1261
	float *v;
1262
 
1263
	msk_x = r->mask.x + op->mask.offset[0];
1264
	msk_y = r->mask.y + op->mask.offset[1];
1265
	w = r->width;
1266
	h = r->height;
1267
 
1268
	DBG(("%s: dst=(%d, %d), mask=(%f, %f) x (%f, %f)\n",
1269
	     __FUNCTION__, r->dst.x, r->dst.y, msk_x, msk_y, w, h));
1270
 
1271
	assert(op->floats_per_rect == 12);
1272
	assert((sna->render.vertex_used % 4) == 0);
1273
	v = sna->render.vertices + sna->render.vertex_used;
1274
	sna->render.vertex_used += 12;
1275
 
1276
	dst.p.x = r->dst.x + r->width;
1277
	dst.p.y = r->dst.y + r->height;
1278
	v[0] = dst.f;
1279
	v[2] = (msk_x + w) * op->mask.scale[0];
1280
	v[7] = v[3] = (msk_y + h) * op->mask.scale[1];
1281
 
1282
	dst.p.x = r->dst.x;
1283
	v[4] = dst.f;
1284
	v[10] = v[6] = msk_x * op->mask.scale[0];
1285
 
1286
	dst.p.y = r->dst.y;
1287
	v[8] = dst.f;
1288
	v[11] = msk_y * op->mask.scale[1];
1289
 
1290
	v[1] = compute_linear(&op->src, r->src.x+r->width, r->src.y+r->height);
1291
	v[5] = compute_linear(&op->src, r->src.x, r->src.y+r->height);
1292
	v[9] = compute_linear(&op->src, r->src.x, r->src.y);
1293
}
1294
 
1295
sse4_2 fastcall static void
1296
emit_boxes_linear_identity_mask__sse4_2(const struct sna_composite_op *op,
1297
					const BoxRec *box, int nbox,
1298
					float *v)
1299
{
1300
	float msk_x = op->mask.offset[0];
1301
	float msk_y = op->mask.offset[1];
1302
 
1303
	do {
1304
		union {
1305
			struct sna_coordinate p;
1306
			float f;
1307
		} dst;
1308
 
1309
		dst.p.x = box->x2;
1310
		dst.p.y = box->y2;
1311
		v[0] = dst.f;
1312
		v[2] = (msk_x + box->x2) * op->mask.scale[0];
1313
		v[7] = v[3] = (msk_y + box->y2) * op->mask.scale[1];
1314
 
1315
		dst.p.x = box->x1;
1316
		v[4] = dst.f;
1317
		v[10] = v[6] = (msk_x + box->x1) * op->mask.scale[0];
1318
 
1319
		dst.p.y = box->y1;
1320
		v[8] = dst.f;
1321
		v[11] = (msk_y + box->y1) * op->mask.scale[1];
1322
 
1323
		v[1] = compute_linear(&op->src, box->x2, box->y2);
1324
		v[5] = compute_linear(&op->src, box->x1, box->y2);
1325
		v[9] = compute_linear(&op->src, box->x1, box->y1);
1326
 
1327
		v += 12;
1328
		box++;
1329
	} while (--nbox);
1330
}
1331
 
1332
#endif
1333
 
1334
/* AVX2 */
1335
#if defined(avx2)
1336
 
1337
avx2 fastcall static void
1338
emit_primitive_linear__avx2(struct sna *sna,
1339
			    const struct sna_composite_op *op,
1340
			    const struct sna_composite_rectangles *r)
1341
{
1342
	float *v;
1343
	union {
1344
		struct sna_coordinate p;
1345
		float f;
1346
	} dst;
1347
 
1348
	assert(op->floats_per_rect == 6);
1349
	assert((sna->render.vertex_used % 2) == 0);
1350
	v = sna->render.vertices + sna->render.vertex_used;
1351
	sna->render.vertex_used += 6;
1352
	assert(sna->render.vertex_used <= sna->render.vertex_size);
1353
 
1354
	dst.p.x = r->dst.x + r->width;
1355
	dst.p.y = r->dst.y + r->height;
1356
	v[0] = dst.f;
1357
	dst.p.x = r->dst.x;
1358
	v[2] = dst.f;
1359
	dst.p.y = r->dst.y;
1360
	v[4] = dst.f;
1361
 
1362
	v[1] = compute_linear(&op->src, r->src.x+r->width, r->src.y+r->height);
1363
	v[3] = compute_linear(&op->src, r->src.x, r->src.y+r->height);
1364
	v[5] = compute_linear(&op->src, r->src.x, r->src.y);
1365
}
1366
 
1367
avx2 fastcall static void
1368
emit_boxes_linear__avx2(const struct sna_composite_op *op,
1369
			const BoxRec *box, int nbox,
1370
			float *v)
1371
{
1372
	union {
1373
		struct sna_coordinate p;
1374
		float f;
1375
	} dst;
1376
 
1377
	do {
1378
		dst.p.x = box->x2;
1379
		dst.p.y = box->y2;
1380
		v[0] = dst.f;
1381
		dst.p.x = box->x1;
1382
		v[2] = dst.f;
1383
		dst.p.y = box->y1;
1384
		v[4] = dst.f;
1385
 
1386
		v[1] = compute_linear(&op->src, box->x2, box->y2);
1387
		v[3] = compute_linear(&op->src, box->x1, box->y2);
1388
		v[5] = compute_linear(&op->src, box->x1, box->y1);
1389
 
1390
		v += 6;
1391
		box++;
1392
	} while (--nbox);
1393
}
1394
 
1395
avx2 fastcall static void
1396
emit_primitive_identity_source__avx2(struct sna *sna,
1397
				     const struct sna_composite_op *op,
1398
				     const struct sna_composite_rectangles *r)
1399
{
1400
	union {
1401
		struct sna_coordinate p;
1402
		float f;
1403
	} dst;
1404
	float *v;
1405
 
1406
	assert(op->floats_per_rect == 9);
1407
	assert((sna->render.vertex_used % 3) == 0);
1408
	v = sna->render.vertices + sna->render.vertex_used;
1409
	sna->render.vertex_used += 9;
1410
 
1411
	dst.p.x = r->dst.x + r->width;
1412
	dst.p.y = r->dst.y + r->height;
1413
	v[0] = dst.f;
1414
	dst.p.x = r->dst.x;
1415
	v[3] = dst.f;
1416
	dst.p.y = r->dst.y;
1417
	v[6] = dst.f;
1418
 
1419
	v[7] = v[4] = (r->src.x + op->src.offset[0]) * op->src.scale[0];
1420
	v[1] = v[4] + r->width * op->src.scale[0];
1421
 
1422
	v[8] = (r->src.y + op->src.offset[1]) * op->src.scale[1];
1423
	v[5] = v[2] = v[8] + r->height * op->src.scale[1];
1424
}
1425
 
1426
avx2 fastcall static void
1427
emit_boxes_identity_source__avx2(const struct sna_composite_op *op,
1428
				 const BoxRec *box, int nbox,
1429
				 float *v)
1430
{
1431
	do {
1432
		union {
1433
			struct sna_coordinate p;
1434
			float f;
1435
		} dst;
1436
 
1437
		dst.p.x = box->x2;
1438
		dst.p.y = box->y2;
1439
		v[0] = dst.f;
1440
		dst.p.x = box->x1;
1441
		v[3] = dst.f;
1442
		dst.p.y = box->y1;
1443
		v[6] = dst.f;
1444
 
1445
		v[7] = v[4] = (box->x1 + op->src.offset[0]) * op->src.scale[0];
1446
		v[1] = (box->x2 + op->src.offset[0]) * op->src.scale[0];
1447
 
1448
		v[8] = (box->y1 + op->src.offset[1]) * op->src.scale[1];
1449
		v[2] = v[5] = (box->y2 + op->src.offset[1]) * op->src.scale[1];
1450
 
1451
		v += 9;
1452
		box++;
1453
	} while (--nbox);
1454
}
1455
 
1456
avx2 fastcall static void
1457
emit_primitive_simple_source__avx2(struct sna *sna,
1458
				   const struct sna_composite_op *op,
1459
				   const struct sna_composite_rectangles *r)
1460
{
1461
	float *v;
1462
	union {
1463
		struct sna_coordinate p;
1464
		float f;
1465
	} dst;
1466
 
1467
	float xx = op->src.transform->matrix[0][0];
1468
	float x0 = op->src.transform->matrix[0][2];
1469
	float yy = op->src.transform->matrix[1][1];
1470
	float y0 = op->src.transform->matrix[1][2];
1471
	float sx = op->src.scale[0];
1472
	float sy = op->src.scale[1];
1473
	int16_t tx = op->src.offset[0];
1474
	int16_t ty = op->src.offset[1];
1475
 
1476
	assert(op->floats_per_rect == 9);
1477
	assert((sna->render.vertex_used % 3) == 0);
1478
	v = sna->render.vertices + sna->render.vertex_used;
1479
	sna->render.vertex_used += 3*3;
1480
 
1481
	dst.p.x = r->dst.x + r->width;
1482
	dst.p.y = r->dst.y + r->height;
1483
	v[0] = dst.f;
1484
	v[1] = ((r->src.x + r->width + tx) * xx + x0) * sx;
1485
	v[5] = v[2] = ((r->src.y + r->height + ty) * yy + y0) * sy;
1486
 
1487
	dst.p.x = r->dst.x;
1488
	v[3] = dst.f;
1489
	v[7] = v[4] = ((r->src.x + tx) * xx + x0) * sx;
1490
 
1491
	dst.p.y = r->dst.y;
1492
	v[6] = dst.f;
1493
	v[8] = ((r->src.y + ty) * yy + y0) * sy;
1494
}
1495
 
1496
avx2 fastcall static void
1497
emit_boxes_simple_source__avx2(const struct sna_composite_op *op,
1498
			       const BoxRec *box, int nbox,
1499
			       float *v)
1500
{
1501
	float xx = op->src.transform->matrix[0][0];
1502
	float x0 = op->src.transform->matrix[0][2];
1503
	float yy = op->src.transform->matrix[1][1];
1504
	float y0 = op->src.transform->matrix[1][2];
1505
	float sx = op->src.scale[0];
1506
	float sy = op->src.scale[1];
1507
	int16_t tx = op->src.offset[0];
1508
	int16_t ty = op->src.offset[1];
1509
 
1510
	do {
1511
		union {
1512
			struct sna_coordinate p;
1513
			float f;
1514
		} dst;
1515
 
1516
		dst.p.x = box->x2;
1517
		dst.p.y = box->y2;
1518
		v[0] = dst.f;
1519
		v[1] = ((box->x2 + tx) * xx + x0) * sx;
1520
		v[5] = v[2] = ((box->y2 + ty) * yy + y0) * sy;
1521
 
1522
		dst.p.x = box->x1;
1523
		v[3] = dst.f;
1524
		v[7] = v[4] = ((box->x1 + tx) * xx + x0) * sx;
1525
 
1526
		dst.p.y = box->y1;
1527
		v[6] = dst.f;
1528
		v[8] = ((box->y1 + ty) * yy + y0) * sy;
1529
 
1530
		v += 9;
1531
		box++;
1532
	} while (--nbox);
1533
}
1534
 
1535
avx2 fastcall static void
1536
emit_primitive_identity_mask__avx2(struct sna *sna,
1537
				   const struct sna_composite_op *op,
1538
				   const struct sna_composite_rectangles *r)
1539
{
1540
	union {
1541
		struct sna_coordinate p;
1542
		float f;
1543
	} dst;
1544
	float msk_x, msk_y;
1545
	float w, h;
1546
	float *v;
1547
 
1548
	msk_x = r->mask.x + op->mask.offset[0];
1549
	msk_y = r->mask.y + op->mask.offset[1];
1550
	w = r->width;
1551
	h = r->height;
1552
 
1553
	DBG(("%s: dst=(%d, %d), mask=(%f, %f) x (%f, %f)\n",
1554
	     __FUNCTION__, r->dst.x, r->dst.y, msk_x, msk_y, w, h));
1555
 
1556
	assert(op->floats_per_rect == 12);
1557
	assert((sna->render.vertex_used % 4) == 0);
1558
	v = sna->render.vertices + sna->render.vertex_used;
1559
	sna->render.vertex_used += 12;
1560
 
1561
	dst.p.x = r->dst.x + r->width;
1562
	dst.p.y = r->dst.y + r->height;
1563
	v[0] = dst.f;
1564
	v[2] = (msk_x + w) * op->mask.scale[0];
1565
	v[7] = v[3] = (msk_y + h) * op->mask.scale[1];
1566
 
1567
	dst.p.x = r->dst.x;
1568
	v[4] = dst.f;
1569
	v[10] = v[6] = msk_x * op->mask.scale[0];
1570
 
1571
	dst.p.y = r->dst.y;
1572
	v[8] = dst.f;
1573
	v[11] = msk_y * op->mask.scale[1];
1574
 
1575
	v[9] = v[5] = v[1] = .5;
1576
}
1577
 
1578
avx2 fastcall static void
1579
emit_boxes_identity_mask__avx2(const struct sna_composite_op *op,
1580
			       const BoxRec *box, int nbox,
1581
			       float *v)
1582
{
1583
	float msk_x = op->mask.offset[0];
1584
	float msk_y = op->mask.offset[1];
1585
 
1586
	do {
1587
		union {
1588
			struct sna_coordinate p;
1589
			float f;
1590
		} dst;
1591
 
1592
		dst.p.x = box->x2;
1593
		dst.p.y = box->y2;
1594
		v[0] = dst.f;
1595
		v[2] = (msk_x + box->x2) * op->mask.scale[0];
1596
		v[7] = v[3] = (msk_y + box->y2) * op->mask.scale[1];
1597
 
1598
		dst.p.x = box->x1;
1599
		v[4] = dst.f;
1600
		v[10] = v[6] = (msk_x + box->x1) * op->mask.scale[0];
1601
 
1602
		dst.p.y = box->y1;
1603
		v[8] = dst.f;
1604
		v[11] = (msk_y + box->y1) * op->mask.scale[1];
1605
 
1606
		v[9] = v[5] = v[1] = .5;
1607
		v += 12;
1608
		box++;
1609
	} while (--nbox);
1610
}
1611
 
1612
avx2 fastcall static void
1613
emit_primitive_linear_identity_mask__avx2(struct sna *sna,
1614
					  const struct sna_composite_op *op,
1615
					  const struct sna_composite_rectangles *r)
1616
{
1617
	union {
1618
		struct sna_coordinate p;
1619
		float f;
1620
	} dst;
1621
	float msk_x, msk_y;
1622
	float w, h;
1623
	float *v;
1624
 
1625
	msk_x = r->mask.x + op->mask.offset[0];
1626
	msk_y = r->mask.y + op->mask.offset[1];
1627
	w = r->width;
1628
	h = r->height;
1629
 
1630
	DBG(("%s: dst=(%d, %d), mask=(%f, %f) x (%f, %f)\n",
1631
	     __FUNCTION__, r->dst.x, r->dst.y, msk_x, msk_y, w, h));
1632
 
1633
	assert(op->floats_per_rect == 12);
1634
	assert((sna->render.vertex_used % 4) == 0);
1635
	v = sna->render.vertices + sna->render.vertex_used;
1636
	sna->render.vertex_used += 12;
1637
 
1638
	dst.p.x = r->dst.x + r->width;
1639
	dst.p.y = r->dst.y + r->height;
1640
	v[0] = dst.f;
1641
	v[2] = (msk_x + w) * op->mask.scale[0];
1642
	v[7] = v[3] = (msk_y + h) * op->mask.scale[1];
1643
 
1644
	dst.p.x = r->dst.x;
1645
	v[4] = dst.f;
1646
	v[10] = v[6] = msk_x * op->mask.scale[0];
1647
 
1648
	dst.p.y = r->dst.y;
1649
	v[8] = dst.f;
1650
	v[11] = msk_y * op->mask.scale[1];
1651
 
1652
	v[1] = compute_linear(&op->src, r->src.x+r->width, r->src.y+r->height);
1653
	v[5] = compute_linear(&op->src, r->src.x, r->src.y+r->height);
1654
	v[9] = compute_linear(&op->src, r->src.x, r->src.y);
1655
}
1656
 
1657
avx2 fastcall static void
1658
emit_boxes_linear_identity_mask__avx2(const struct sna_composite_op *op,
1659
				      const BoxRec *box, int nbox,
1660
				      float *v)
1661
{
1662
	float msk_x = op->mask.offset[0];
1663
	float msk_y = op->mask.offset[1];
1664
 
1665
	do {
1666
		union {
1667
			struct sna_coordinate p;
1668
			float f;
1669
		} dst;
1670
 
1671
		dst.p.x = box->x2;
1672
		dst.p.y = box->y2;
1673
		v[0] = dst.f;
1674
		v[2] = (msk_x + box->x2) * op->mask.scale[0];
1675
		v[7] = v[3] = (msk_y + box->y2) * op->mask.scale[1];
1676
 
1677
		dst.p.x = box->x1;
1678
		v[4] = dst.f;
1679
		v[10] = v[6] = (msk_x + box->x1) * op->mask.scale[0];
1680
 
1681
		dst.p.y = box->y1;
1682
		v[8] = dst.f;
1683
		v[11] = (msk_y + box->y1) * op->mask.scale[1];
1684
 
1685
		v[1] = compute_linear(&op->src, box->x2, box->y2);
1686
		v[5] = compute_linear(&op->src, box->x1, box->y2);
1687
		v[9] = compute_linear(&op->src, box->x1, box->y1);
1688
 
1689
		v += 12;
1690
		box++;
1691
	} while (--nbox);
1692
}
1693
 
1694
#endif
1695
 
1696
unsigned gen4_choose_composite_emitter(struct sna *sna, struct sna_composite_op *tmp)
1697
{
3280 Serge 1698
	unsigned vb;
1699
 
1700
	if (tmp->mask.bo) {
1701
		if (tmp->mask.transform == NULL) {
1702
			if (tmp->src.is_solid) {
1703
				DBG(("%s: solid, identity mask\n", __FUNCTION__));
4251 Serge 1704
#if defined(avx2)
1705
				if (sna->cpu_features & AVX2) {
1706
					tmp->prim_emit = emit_primitive_identity_mask__avx2;
1707
				} else
1708
#endif
1709
#if defined(sse4_2)
1710
				if (sna->cpu_features & SSE4_2) {
1711
					tmp->prim_emit = emit_primitive_identity_mask__sse4_2;
1712
				} else
1713
#endif
1714
				{
1715
					tmp->prim_emit = emit_primitive_identity_mask;
1716
				}
1717
				tmp->floats_per_vertex = 4;
1718
				vb = 1 | 2 << 2;
3280 Serge 1719
			} else if (tmp->src.is_linear) {
1720
				DBG(("%s: linear, identity mask\n", __FUNCTION__));
4251 Serge 1721
#if defined(avx2)
1722
				if (sna->cpu_features & AVX2) {
1723
					tmp->prim_emit = emit_primitive_linear_identity_mask__avx2;
1724
				} else
1725
#endif
1726
#if defined(sse4_2)
1727
				if (sna->cpu_features & SSE4_2) {
1728
					tmp->prim_emit = emit_primitive_linear_identity_mask__sse4_2;
1729
				} else
1730
#endif
1731
				{
1732
					tmp->prim_emit = emit_primitive_linear_identity_mask;
1733
				}
1734
				tmp->floats_per_vertex = 4;
1735
				vb = 1 | 2 << 2;
3280 Serge 1736
			} else if (tmp->src.transform == NULL) {
1737
				DBG(("%s: identity source, identity mask\n", __FUNCTION__));
1738
				tmp->prim_emit = emit_primitive_identity_source_mask;
1739
				tmp->floats_per_vertex = 5;
1740
				vb = 2 << 2 | 2;
1741
			} else if (tmp->src.is_affine) {
4251 Serge 1742
				tmp->src.scale[0] /= tmp->src.transform->matrix[2][2];
1743
				tmp->src.scale[1] /= tmp->src.transform->matrix[2][2];
1744
				if (!sna_affine_transform_is_rotation(tmp->src.transform)) {
1745
					DBG(("%s: simple src, identity mask\n", __FUNCTION__));
1746
					tmp->prim_emit = emit_primitive_simple_source_identity;
1747
				} else {
1748
					DBG(("%s: affine src, identity mask\n", __FUNCTION__));
1749
					tmp->prim_emit = emit_primitive_affine_source_identity;
1750
				}
1751
				tmp->floats_per_vertex = 5;
1752
				vb = 2 << 2 | 2;
3280 Serge 1753
			} else {
1754
				DBG(("%s: projective source, identity mask\n", __FUNCTION__));
4251 Serge 1755
				tmp->prim_emit = emit_primitive_mask;
1756
				tmp->floats_per_vertex = 6;
1757
				vb = 2 << 2 | 3;
3280 Serge 1758
			}
1759
		} else {
4251 Serge 1760
			tmp->prim_emit = emit_primitive_mask;
1761
			tmp->floats_per_vertex = 1;
1762
			vb = 0;
1763
			if (tmp->mask.is_solid) {
1764
				tmp->floats_per_vertex += 1;
1765
				vb |= 1 << 2;
1766
			} else if (tmp->mask.is_affine) {
1767
				tmp->floats_per_vertex += 2;
1768
				vb |= 2 << 2;
1769
			}else {
1770
				tmp->floats_per_vertex += 3;
1771
				vb |= 3 << 2;
1772
			}
1773
			if (tmp->src.is_solid) {
1774
				tmp->floats_per_vertex += 1;
1775
				vb |= 1;
1776
			} else if (tmp->src.is_affine) {
1777
				tmp->floats_per_vertex += 2;
1778
				vb |= 2 ;
1779
			}else {
1780
				tmp->floats_per_vertex += 3;
1781
				vb |= 3;
1782
			}
3280 Serge 1783
			DBG(("%s: general mask: floats-per-vertex=%d, vb=%x\n",
1784
			     __FUNCTION__,tmp->floats_per_vertex, vb));
1785
		}
1786
	} else {
4251 Serge 1787
#if 0
1788
		if (tmp->src.is_solid) {
1789
			DBG(("%s: solid, no mask\n", __FUNCTION__));
1790
			tmp->prim_emit = emit_primitive_solid;
1791
			if (tmp->src.is_opaque && tmp->op == PictOpOver)
1792
				tmp->op = PictOpSrc;
1793
			tmp->floats_per_vertex = 2;
1794
			vb = 1;
1795
		} else if (tmp->src.is_linear) {
1796
			DBG(("%s: linear, no mask\n", __FUNCTION__));
1797
#if defined(avx2)
1798
			if (sna->cpu_features & AVX2) {
1799
				tmp->prim_emit = emit_primitive_linear__avx2;
1800
			} else
1801
#endif
1802
#if defined(sse4_2)
1803
			if (sna->cpu_features & SSE4_2) {
1804
				tmp->prim_emit = emit_primitive_linear__sse4_2;
1805
			} else
1806
#endif
1807
			{
1808
				tmp->prim_emit = emit_primitive_linear;
1809
			}
1810
			tmp->floats_per_vertex = 2;
1811
			vb = 1;
1812
		} else if (tmp->src.transform == NULL) {
1813
			DBG(("%s: identity src, no mask\n", __FUNCTION__));
1814
#if defined(avx2)
1815
			if (sna->cpu_features & AVX2) {
1816
				tmp->prim_emit = emit_primitive_identity_source__avx2;
1817
			} else
1818
#endif
1819
#if defined(sse4_2)
1820
			if (sna->cpu_features & SSE4_2) {
1821
				tmp->prim_emit = emit_primitive_identity_source__sse4_2;
1822
			} else
1823
#endif
1824
			{
1825
				tmp->prim_emit = emit_primitive_identity_source;
1826
			}
1827
			tmp->floats_per_vertex = 3;
1828
			vb = 2;
1829
		} else if (tmp->src.is_affine) {
1830
			tmp->src.scale[0] /= tmp->src.transform->matrix[2][2];
1831
			tmp->src.scale[1] /= tmp->src.transform->matrix[2][2];
1832
			if (!sna_affine_transform_is_rotation(tmp->src.transform)) {
1833
				DBG(("%s: simple src, no mask\n", __FUNCTION__));
1834
#if defined(avx2)
1835
				if (sna->cpu_features & AVX2) {
1836
					tmp->prim_emit = emit_primitive_simple_source__avx2;
1837
				} else
1838
#endif
1839
#if defined(sse4_2)
1840
				if (sna->cpu_features & SSE4_2) {
1841
					tmp->prim_emit = emit_primitive_simple_source__sse4_2;
1842
				} else
1843
#endif
1844
				{
1845
					tmp->prim_emit = emit_primitive_simple_source;
1846
				}
1847
			} else {
1848
				DBG(("%s: affine src, no mask\n", __FUNCTION__));
1849
				tmp->prim_emit = emit_primitive_affine_source;
1850
			}
1851
			tmp->floats_per_vertex = 3;
1852
			vb = 2;
1853
		} else {
1854
			DBG(("%s: projective src, no mask\n", __FUNCTION__));
1855
			assert(!tmp->src.is_solid);
1856
			tmp->prim_emit = emit_primitive;
1857
			tmp->floats_per_vertex = 4;
1858
			vb = 3;
1859
		}
1860
#endif
3280 Serge 1861
	}
1862
	tmp->floats_per_rect = 3 * tmp->floats_per_vertex;
1863
 
1864
	return vb;
1865
}
4251 Serge 1866
 
1867