glamor_utils.h revision 35c4bbdf
1/*
2 * Copyright © 2009 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
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 * IN THE SOFTWARE.
22 *
23 * Authors:
24 *    Zhigang Gong <zhigang.gong@linux.intel.com>
25 *
26 */
27
28#ifndef GLAMOR_PRIV_H
29#error This file can only be included by glamor_priv.h
30#endif
31
32#ifndef __GLAMOR_UTILS_H__
33#define __GLAMOR_UTILS_H__
34
35#include "glamor_prepare.h"
36#include "mipict.h"
37
38#define v_from_x_coord_x(_xscale_, _x_)          ( 2 * (_x_) * (_xscale_) - 1.0)
39#define v_from_x_coord_y(_yscale_, _y_)          (2 * (_y_) * (_yscale_) - 1.0)
40#define t_from_x_coord_x(_xscale_, _x_)          ((_x_) * (_xscale_))
41#define t_from_x_coord_y(_yscale_, _y_)          ((_y_) * (_yscale_))
42
43#define pixmap_priv_get_dest_scale(pixmap, _pixmap_priv_, _pxscale_, _pyscale_) \
44  do {                                                                   \
45    int _w_,_h_;                                                         \
46    PIXMAP_PRIV_GET_ACTUAL_SIZE(pixmap, _pixmap_priv_, _w_, _h_);        \
47    *(_pxscale_) = 1.0 / _w_;                                            \
48    *(_pyscale_) = 1.0 / _h_;                                            \
49   } while(0)
50
51#define pixmap_priv_get_scale(_pixmap_priv_, _pxscale_, _pyscale_)	\
52   do {									\
53    *(_pxscale_) = 1.0 / (_pixmap_priv_)->fbo->width;			\
54    *(_pyscale_) = 1.0 / (_pixmap_priv_)->fbo->height;			\
55  } while(0)
56
57#define PIXMAP_PRIV_GET_ACTUAL_SIZE(pixmap, priv, w, h)          \
58  do {								\
59	if (_X_UNLIKELY(glamor_pixmap_priv_is_large(priv))) {	\
60		w = priv->box.x2 - priv->box.x1;	\
61		h = priv->box.y2 - priv->box.y1;	\
62	} else {						\
63		w = (pixmap)->drawable.width;		\
64		h = (pixmap)->drawable.height;		\
65	}							\
66  } while(0)
67
68#define glamor_pixmap_fbo_fix_wh_ratio(wh, pixmap, priv)         \
69  do {								\
70	int actual_w, actual_h;					\
71	PIXMAP_PRIV_GET_ACTUAL_SIZE(pixmap, priv, actual_w, actual_h);	\
72	wh[0] = (float)priv->fbo->width / actual_w;	\
73	wh[1] = (float)priv->fbo->height / actual_h;	\
74	wh[2] = 1.0 / priv->fbo->width;			\
75	wh[3] = 1.0 / priv->fbo->height;			\
76  } while(0)
77
78#define pixmap_priv_get_fbo_off(_priv_, _xoff_, _yoff_)		\
79   do {								\
80        if (_X_UNLIKELY(_priv_ && glamor_pixmap_priv_is_large(_priv_))) { \
81		*(_xoff_) = - (_priv_)->box.x1;	\
82		*(_yoff_) = - (_priv_)->box.y1;	\
83	} else {						\
84		*(_xoff_) = 0;					\
85		*(_yoff_) = 0;					\
86	}							\
87   } while(0)
88
89#define xFixedToFloat(_val_) ((float)xFixedToInt(_val_)			\
90			      + ((float)xFixedFrac(_val_) / 65536.0))
91
92#define glamor_picture_get_matrixf(_picture_, _matrix_)			\
93  do {									\
94    int _i_;								\
95    if ((_picture_)->transform)						\
96      {									\
97	for(_i_ = 0; _i_ < 3; _i_++)					\
98	  {								\
99	    (_matrix_)[_i_ * 3 + 0] =					\
100	      xFixedToFloat((_picture_)->transform->matrix[_i_][0]);	\
101	    (_matrix_)[_i_ * 3 + 1] =					\
102	      xFixedToFloat((_picture_)->transform->matrix[_i_][1]);	\
103	    (_matrix_)[_i_ * 3 + 2] = \
104	      xFixedToFloat((_picture_)->transform->matrix[_i_][2]);	\
105	  }								\
106      }									\
107  }  while(0)
108
109#define fmod(x, w)		(x - w * floor((float)x/w))
110
111#define fmodulus(x, w, c)	do {c = fmod(x, w);		\
112				    c = c >= 0 ? c : c + w;}	\
113				while(0)
114/* @x: is current coord
115 * @x2: is the right/bottom edge
116 * @w: is current width or height
117 * @odd: is output value, 0 means we are in an even region, 1 means we are in a
118 * odd region.
119 * @c: is output value, equal to x mod w. */
120#define fodd_repeat_mod(x, x2, w, odd, c)	\
121  do {						\
122	float shift;				\
123	fmodulus((x), w, c); 			\
124	shift = fabs((x) - (c));		\
125	shift = floor(fabs(round(shift)) / w);	\
126	odd = (int)shift & 1;			\
127	if (odd && (((x2 % w) == 0) &&		\
128	    round(fabs(x)) == x2))		\
129		odd = 0;			\
130  } while(0)
131
132/* @txy: output value, is the corrected coords.
133 * @xy: input coords to be fixed up.
134 * @cd: xy mod wh, is a input value.
135 * @wh: current width or height.
136 * @bxy1,bxy2: current box edge's x1/x2 or y1/y2
137 *
138 * case 1:
139 *  ----------
140 *  |  *     |
141 *  |        |
142 *  ----------
143 *  tx = (c - x1) mod w
144 *
145 *  case 2:
146 *     ---------
147 *  *  |       |
148 *     |       |
149 *     ---------
150 *   tx = - (c - (x1 mod w))
151 *
152 *   case 3:
153 *
154 *   ----------
155 *   |        |  *
156 *   |        |
157 *   ----------
158 *   tx = ((x2 mod x) - c) + (x2 - x1)
159 **/
160#define __glamor_repeat_reflect_fixup(txy, xy,		\
161				cd, wh, bxy1, bxy2)	\
162  do {							\
163	cd = wh - cd;					\
164	if ( xy >= bxy1 && xy < bxy2) {			\
165		cd = cd - bxy1;				\
166		fmodulus(cd, wh, txy);			\
167	} else	if (xy < bxy1) {			\
168		float bxy1_mod;				\
169		fmodulus(bxy1, wh, bxy1_mod);		\
170		txy = -(cd - bxy1_mod);			\
171	}						\
172	else if (xy >= bxy2)	{			\
173		float bxy2_mod;				\
174		fmodulus(bxy2, wh, bxy2_mod);		\
175		if (bxy2_mod == 0)			\
176			bxy2_mod = wh;			\
177		txy = (bxy2_mod - cd) + bxy2 - bxy1;	\
178	} else {assert(0); txy = 0;}			\
179  } while(0)
180
181#define _glamor_repeat_reflect_fixup(txy, xy, cd, odd,	\
182				     wh, bxy1, bxy2)	\
183  do {							\
184	if (odd) {					\
185		__glamor_repeat_reflect_fixup(txy, xy, 	\
186			cd, wh, bxy1, bxy2);		\
187	} else						\
188		txy = xy - bxy1;			\
189  } while(0)
190
191#define _glamor_get_reflect_transform_coords(pixmap, priv, repeat_type,	\
192					    tx1, ty1, 		\
193				            _x1_, _y1_)		\
194  do {								\
195	int odd_x, odd_y;					\
196	float c, d;						\
197	fodd_repeat_mod(_x1_,priv->box.x2,			\
198		    (pixmap)->drawable.width,		\
199		    odd_x, c);					\
200	fodd_repeat_mod(_y1_,	priv->box.y2,			\
201		    (pixmap)->drawable.height,		\
202		    odd_y, d);					\
203	DEBUGF("c %f d %f oddx %d oddy %d \n",			\
204		c, d, odd_x, odd_y);				\
205	DEBUGF("x2 %d x1 %d fbo->width %d \n", priv->box.x2,	\
206		priv->box.x1, priv->fbo->width);		\
207	DEBUGF("y2 %d y1 %d fbo->height %d \n", priv->box.y2, 	\
208		priv->box.y1, priv->fbo->height);		\
209	_glamor_repeat_reflect_fixup(tx1, _x1_, c, odd_x,	\
210		(pixmap)->drawable.width,		\
211		priv->box.x1, priv->box.x2);			\
212	_glamor_repeat_reflect_fixup(ty1, _y1_, d, odd_y,	\
213		(pixmap)->drawable.height,		\
214		priv->box.y1, priv->box.y2);			\
215   } while(0)
216
217#define _glamor_get_repeat_coords(pixmap, priv, repeat_type, tx1,	\
218				  ty1, tx2, ty2,		\
219				  _x1_, _y1_, _x2_,		\
220				  _y2_, c, d, odd_x, odd_y)	\
221  do {								\
222	if (repeat_type == RepeatReflect) {			\
223		DEBUGF("x1 y1 %d %d\n",				\
224			_x1_, _y1_ );				\
225		DEBUGF("width %d box.x1 %d \n",			\
226		       (pixmap)->drawable.width,	\
227		       priv->box.x1);				\
228		if (odd_x) {					\
229			c = (pixmap)->drawable.width	\
230				- c;				\
231			tx1 = c - priv->box.x1;			\
232			tx2 = tx1 - ((_x2_) - (_x1_));		\
233		} else {					\
234			tx1 = c - priv->box.x1;			\
235			tx2 = tx1 + ((_x2_) - (_x1_));		\
236		}						\
237		if (odd_y){					\
238			d = (pixmap)->drawable.height\
239			    - d;				\
240			ty1 = d - priv->box.y1;			\
241			ty2 = ty1 - ((_y2_) - (_y1_));		\
242		} else {					\
243			ty1 = d - priv->box.y1;			\
244			ty2 = ty1 + ((_y2_) - (_y1_));		\
245		}						\
246	} else { /* RepeatNormal*/				\
247		tx1 = (c - priv->box.x1);  			\
248		ty1 = (d - priv->box.y1);			\
249		tx2 = tx1 + ((_x2_) - (_x1_));			\
250		ty2 = ty1 + ((_y2_) - (_y1_));			\
251	}							\
252   } while(0)
253
254/* _x1_ ... _y2_ may has fractional. */
255#define glamor_get_repeat_transform_coords(pixmap, priv, repeat_type, tx1, \
256					   ty1, _x1_, _y1_)		\
257  do {									\
258	DEBUGF("width %d box.x1 %d x2 %d y1 %d y2 %d\n",		\
259		(pixmap)->drawable.width,			\
260		priv->box.x1, priv->box.x2, priv->box.y1,		\
261		priv->box.y2);						\
262	DEBUGF("x1 %f y1 %f \n", _x1_, _y1_);				\
263	if (repeat_type != RepeatReflect) {				\
264		tx1 = _x1_ - priv->box.x1;				\
265		ty1 = _y1_ - priv->box.y1;				\
266	} else			\
267                _glamor_get_reflect_transform_coords(pixmap, priv, repeat_type, \
268				  tx1, ty1, 				\
269				  _x1_, _y1_);				\
270	DEBUGF("tx1 %f ty1 %f \n", tx1, ty1);				\
271   } while(0)
272
273/* _x1_ ... _y2_ must be integer. */
274#define glamor_get_repeat_coords(pixmap, priv, repeat_type, tx1,		\
275				 ty1, tx2, ty2, _x1_, _y1_, _x2_,	\
276				 _y2_) 					\
277  do {									\
278	int c, d;							\
279	int odd_x = 0, odd_y = 0;					\
280	DEBUGF("width %d box.x1 %d x2 %d y1 %d y2 %d\n",		\
281		(pixmap)->drawable.width,			\
282		priv->box.x1, priv->box.x2,				\
283		priv->box.y1, priv->box.y2);				\
284	modulus((_x1_), (pixmap)->drawable.width, c); 	\
285	modulus((_y1_), (pixmap)->drawable.height, d);	\
286	DEBUGF("c %d d %d \n", c, d);					\
287	if (repeat_type == RepeatReflect) {				\
288		odd_x = abs((_x1_ - c)					\
289                            / ((pixmap)->drawable.width)) & 1;            \
290		odd_y = abs((_y1_ - d)					\
291                            / ((pixmap)->drawable.height)) & 1;           \
292	}								\
293	_glamor_get_repeat_coords(pixmap, priv, repeat_type, tx1, ty1, tx2, ty2, \
294				  _x1_, _y1_, _x2_, _y2_, c, d,		\
295				  odd_x, odd_y);			\
296   } while(0)
297
298#define glamor_transform_point(matrix, tx, ty, x, y)			\
299  do {									\
300    int _i_;								\
301    float _result_[4];							\
302    for (_i_ = 0; _i_ < 3; _i_++) {					\
303      _result_[_i_] = (matrix)[_i_ * 3] * (x) + (matrix)[_i_ * 3 + 1] * (y)	\
304	+ (matrix)[_i_ * 3 + 2];					\
305    }									\
306    tx = _result_[0] / _result_[2];					\
307    ty = _result_[1] / _result_[2];					\
308  } while(0)
309
310#define _glamor_set_normalize_tpoint(xscale, yscale, _tx_, _ty_,	\
311				     texcoord)                          \
312  do {									\
313	(texcoord)[0] = t_from_x_coord_x(xscale, _tx_);			\
314        (texcoord)[1] = t_from_x_coord_y(yscale, _ty_);                 \
315        DEBUGF("normalized point tx %f ty %f \n", (texcoord)[0],	\
316		(texcoord)[1]);						\
317  } while(0)
318
319#define glamor_set_transformed_point(priv, matrix, xscale,              \
320				     yscale, texcoord,			\
321                                     x, y)				\
322  do {									\
323    float tx, ty;							\
324    int fbo_x_off, fbo_y_off;						\
325    pixmap_priv_get_fbo_off(priv, &fbo_x_off, &fbo_y_off);		\
326    glamor_transform_point(matrix, tx, ty, x, y);			\
327    DEBUGF("tx %f ty %f fbooff %d %d \n",				\
328	    tx, ty, fbo_x_off, fbo_y_off);				\
329									\
330    tx += fbo_x_off;							\
331    ty += fbo_y_off;							\
332    (texcoord)[0] = t_from_x_coord_x(xscale, tx);			\
333    (texcoord)[1] = t_from_x_coord_y(yscale, ty);                       \
334    DEBUGF("normalized tx %f ty %f \n", (texcoord)[0], (texcoord)[1]);	\
335  } while(0)
336
337#define glamor_set_transformed_normalize_tri_tcoords(priv,		\
338						     matrix,		\
339						     xscale,		\
340						     yscale,		\
341						     vtx,		\
342						     texcoords)		\
343    do {								\
344	glamor_set_transformed_point(priv, matrix, xscale, yscale,	\
345				     texcoords, (vtx)[0], (vtx)[1]);    \
346	glamor_set_transformed_point(priv, matrix, xscale, yscale,	\
347				     texcoords+2, (vtx)[2], (vtx)[3]);  \
348	glamor_set_transformed_point(priv, matrix, xscale, yscale,	\
349				     texcoords+4, (vtx)[4], (vtx)[5]);  \
350    } while (0)
351
352#define glamor_set_transformed_normalize_tcoords_ext( priv,		\
353						  matrix,		\
354						  xscale,		\
355						  yscale,		\
356                                                  tx1, ty1, tx2, ty2,   \
357                                                  texcoords,		\
358						  stride)		\
359  do {									\
360    glamor_set_transformed_point(priv, matrix, xscale, yscale,		\
361				 texcoords, tx1, ty1);                  \
362    glamor_set_transformed_point(priv, matrix, xscale, yscale,		\
363				 texcoords + 1 * stride, tx2, ty1);     \
364    glamor_set_transformed_point(priv, matrix, xscale, yscale,		\
365				 texcoords + 2 * stride, tx2, ty2);     \
366    glamor_set_transformed_point(priv, matrix, xscale, yscale,		\
367				 texcoords + 3 * stride, tx1, ty2);     \
368  } while (0)
369
370#define glamor_set_transformed_normalize_tcoords( priv,			\
371						  matrix,		\
372						  xscale,		\
373						  yscale,		\
374                                                  tx1, ty1, tx2, ty2,   \
375                                                  texcoords)            \
376  do {									\
377	glamor_set_transformed_normalize_tcoords_ext( priv,		\
378						  matrix,		\
379						  xscale,		\
380						  yscale,		\
381                                                  tx1, ty1, tx2, ty2,   \
382                                                  texcoords,		\
383						  2);			\
384  } while (0)
385
386#define glamor_set_normalize_tri_tcoords(xscale,		\
387					 yscale,		\
388					 vtx,			\
389					 texcoords)		\
390    do {							\
391	_glamor_set_normalize_tpoint(xscale, yscale,		\
392				(vtx)[0], (vtx)[1],		\
393				texcoords);			\
394	_glamor_set_normalize_tpoint(xscale, yscale,		\
395				(vtx)[2], (vtx)[3],		\
396				texcoords+2);			\
397	_glamor_set_normalize_tpoint(xscale, yscale,		\
398				(vtx)[4], (vtx)[5],		\
399				texcoords+4);			\
400    } while (0)
401
402#define glamor_set_repeat_transformed_normalize_tcoords_ext(pixmap, priv, \
403							 repeat_type,	\
404							 matrix,	\
405							 xscale,	\
406							 yscale,	\
407							 _x1_, _y1_,	\
408							 _x2_, _y2_,   	\
409							 texcoords,	\
410							 stride)	\
411  do {									\
412    if (_X_LIKELY(glamor_pixmap_priv_is_small(priv))) {		\
413	glamor_set_transformed_normalize_tcoords_ext(priv, matrix, xscale,	\
414						 yscale, _x1_, _y1_,	\
415						 _x2_, _y2_,	\
416						 texcoords, stride);	\
417    } else {								\
418    float tx1, ty1, tx2, ty2, tx3, ty3, tx4, ty4;			\
419    float ttx1, tty1, ttx2, tty2, ttx3, tty3, ttx4, tty4;		\
420    DEBUGF("original coords %d %d %d %d\n", _x1_, _y1_, _x2_, _y2_);	\
421    glamor_transform_point(matrix, tx1, ty1, _x1_, _y1_);		\
422    glamor_transform_point(matrix, tx2, ty2, _x2_, _y1_);		\
423    glamor_transform_point(matrix, tx3, ty3, _x2_, _y2_);		\
424    glamor_transform_point(matrix, tx4, ty4, _x1_, _y2_);		\
425    DEBUGF("transformed %f %f %f %f %f %f %f %f\n",			\
426	   tx1, ty1, tx2, ty2, tx3, ty3, tx4, ty4);			\
427    glamor_get_repeat_transform_coords(pixmap, priv, repeat_type, \
428				       ttx1, tty1, 			\
429				       tx1, ty1);			\
430    glamor_get_repeat_transform_coords(pixmap, priv, repeat_type, 	\
431				       ttx2, tty2, 			\
432				       tx2, ty2);			\
433    glamor_get_repeat_transform_coords(pixmap, priv, repeat_type, 	\
434				       ttx3, tty3, 			\
435				       tx3, ty3);			\
436    glamor_get_repeat_transform_coords(pixmap, priv, repeat_type, 	\
437				       ttx4, tty4, 			\
438				       tx4, ty4);			\
439    DEBUGF("repeat transformed %f %f %f %f %f %f %f %f\n", ttx1, tty1, 	\
440	    ttx2, tty2,	ttx3, tty3, ttx4, tty4);			\
441    _glamor_set_normalize_tpoint(xscale, yscale, ttx1, tty1,		\
442				 texcoords);			\
443    _glamor_set_normalize_tpoint(xscale, yscale, ttx2, tty2,		\
444				 texcoords + 1 * stride);	\
445    _glamor_set_normalize_tpoint(xscale, yscale, ttx3, tty3,		\
446				 texcoords + 2 * stride);	\
447    _glamor_set_normalize_tpoint(xscale, yscale, ttx4, tty4,		\
448				 texcoords + 3 * stride);	\
449   }									\
450  } while (0)
451
452#define glamor_set_repeat_transformed_normalize_tcoords( pixmap,        \
453                                                         priv,          \
454							 repeat_type,	\
455							 matrix,	\
456							 xscale,	\
457							 yscale,	\
458							 _x1_, _y1_,	\
459							 _x2_, _y2_,   	\
460							 texcoords)	\
461  do {									\
462      glamor_set_repeat_transformed_normalize_tcoords_ext( pixmap,      \
463                                                           priv,	\
464							 repeat_type,	\
465							 matrix,	\
466							 xscale,	\
467							 yscale,	\
468							 _x1_, _y1_,	\
469							 _x2_, _y2_,   	\
470							 texcoords,	\
471							 2);	\
472  } while (0)
473
474#define _glamor_set_normalize_tcoords(xscale, yscale, tx1,		\
475				      ty1, tx2, ty2,			\
476				      vertices, stride)                 \
477  do {									\
478    /* vertices may be write-only, so we use following			\
479     * temporary variable. */ 						\
480    float _t0_, _t1_, _t2_, _t5_;					\
481    (vertices)[0] = _t0_ = t_from_x_coord_x(xscale, tx1);		\
482    (vertices)[1 * stride] = _t2_ = t_from_x_coord_x(xscale, tx2);	\
483    (vertices)[2 * stride] = _t2_;					\
484    (vertices)[3 * stride] = _t0_;					\
485    (vertices)[1] = _t1_ = t_from_x_coord_y(yscale, ty1);               \
486    (vertices)[2 * stride + 1] = _t5_ = t_from_x_coord_y(yscale, ty2);  \
487    (vertices)[1 * stride + 1] = _t1_;					\
488    (vertices)[3 * stride + 1] = _t5_;					\
489  } while(0)
490
491#define glamor_set_normalize_tcoords_ext(priv, xscale, yscale,		\
492				     x1, y1, x2, y2,			\
493                                     vertices, stride)	\
494  do {									\
495     if (_X_UNLIKELY(glamor_pixmap_priv_is_large(priv))) {		\
496	float tx1, tx2, ty1, ty2;					\
497	int fbo_x_off, fbo_y_off;					\
498	pixmap_priv_get_fbo_off(priv, &fbo_x_off, &fbo_y_off);		\
499	tx1 = x1 + fbo_x_off; 						\
500	tx2 = x2 + fbo_x_off;						\
501	ty1 = y1 + fbo_y_off;						\
502	ty2 = y2 + fbo_y_off;						\
503	_glamor_set_normalize_tcoords(xscale, yscale, tx1, ty1,		\
504                                      tx2, ty2, vertices,               \
505				   stride);				\
506     } else								\
507	_glamor_set_normalize_tcoords(xscale, yscale, x1, y1,		\
508                                      x2, y2, vertices, stride);        \
509 } while(0)
510
511#define glamor_set_normalize_tcoords(priv, xscale, yscale,		\
512				     x1, y1, x2, y2,			\
513                                     vertices)		\
514  do {									\
515	glamor_set_normalize_tcoords_ext(priv, xscale, yscale,		\
516				     x1, y1, x2, y2,			\
517                                     vertices, 2);			\
518 } while(0)
519
520#define glamor_set_repeat_normalize_tcoords_ext(pixmap, priv, repeat_type, \
521					    xscale, yscale,		\
522					    _x1_, _y1_, _x2_, _y2_,	\
523	                                    vertices, stride)		\
524  do {									\
525     if (_X_UNLIKELY(glamor_pixmap_priv_is_large(priv))) {		\
526	float tx1, tx2, ty1, ty2;					\
527	if (repeat_type == RepeatPad) {					\
528		tx1 = _x1_ - priv->box.x1;			        \
529		ty1 = _y1_ - priv->box.y1;			        \
530		tx2 = tx1 + ((_x2_) - (_x1_));				\
531		ty2 = ty1 + ((_y2_) - (_y1_));				\
532	} else {							\
533            glamor_get_repeat_coords(pixmap, priv, repeat_type,         \
534				 tx1, ty1, tx2, ty2,			\
535				 _x1_, _y1_, _x2_, _y2_);		\
536	}								\
537	_glamor_set_normalize_tcoords(xscale, yscale, tx1, ty1,		\
538                                      tx2, ty2, vertices,               \
539				   stride);				\
540     } else								\
541	_glamor_set_normalize_tcoords(xscale, yscale, _x1_, _y1_,	\
542                                      _x2_, _y2_, vertices,             \
543				   stride);				\
544 } while(0)
545
546#define glamor_set_repeat_normalize_tcoords(priv, repeat_type,		\
547					    xscale, yscale,		\
548					    _x1_, _y1_, _x2_, _y2_,	\
549	                                    vertices)                   \
550  do {									\
551	glamor_set_repeat_normalize_tcoords_ext(priv, repeat_type,	\
552					    xscale, yscale,		\
553					    _x1_, _y1_, _x2_, _y2_,	\
554	                                    vertices, 2);		\
555 } while(0)
556
557#define glamor_set_normalize_tcoords_tri_stripe(xscale, yscale,		\
558						x1, y1, x2, y2,		\
559						vertices)               \
560    do {								\
561	(vertices)[0] = t_from_x_coord_x(xscale, x1);			\
562	(vertices)[2] = t_from_x_coord_x(xscale, x2);			\
563	(vertices)[6] = (vertices)[2];					\
564	(vertices)[4] = (vertices)[0];					\
565        (vertices)[1] = t_from_x_coord_y(yscale, y1);                   \
566        (vertices)[7] = t_from_x_coord_y(yscale, y2);                   \
567	(vertices)[3] = (vertices)[1];					\
568	(vertices)[5] = (vertices)[7];					\
569    } while(0)
570
571#define glamor_set_tcoords(x1, y1, x2, y2, vertices)            \
572    do {							\
573	(vertices)[0] = (x1);					\
574	(vertices)[2] = (x2);					\
575	(vertices)[4] = (vertices)[2];				\
576	(vertices)[6] = (vertices)[0];				\
577        (vertices)[1] = (y1);                                   \
578        (vertices)[5] = (y2);                                   \
579	(vertices)[3] = (vertices)[1];				\
580	(vertices)[7] = (vertices)[5];				\
581    } while(0)
582
583#define glamor_set_tcoords_ext(x1, y1, x2, y2, vertices, stride)        \
584    do {							\
585	(vertices)[0] = (x1);					\
586	(vertices)[1*stride] = (x2);				\
587	(vertices)[2*stride] = (vertices)[1*stride];		\
588	(vertices)[3*stride] = (vertices)[0];			\
589        (vertices)[1] = (y1);                                   \
590        (vertices)[2*stride + 1] = (y2);			\
591	(vertices)[1*stride + 1] = (vertices)[1];		\
592	(vertices)[3*stride + 1] = (vertices)[2*stride + 1];	\
593    } while(0)
594
595#define glamor_set_normalize_one_vcoord(xscale, yscale, x, y,		\
596					vertices)                       \
597    do {								\
598	(vertices)[0] = v_from_x_coord_x(xscale, x);			\
599        (vertices)[1] = v_from_x_coord_y(yscale, y);                    \
600    } while(0)
601
602#define glamor_set_normalize_tri_vcoords(xscale, yscale, vtx,		\
603					 vertices)                      \
604    do {								\
605	glamor_set_normalize_one_vcoord(xscale, yscale,			\
606					(vtx)[0], (vtx)[1],		\
607					vertices);                      \
608	glamor_set_normalize_one_vcoord(xscale, yscale,			\
609					(vtx)[2], (vtx)[3],		\
610					vertices+2);                    \
611	glamor_set_normalize_one_vcoord(xscale, yscale,			\
612					(vtx)[4], (vtx)[5],		\
613					vertices+4);                    \
614    } while(0)
615
616#define glamor_set_tcoords_tri_strip(x1, y1, x2, y2, vertices)          \
617    do {								\
618	(vertices)[0] = (x1);						\
619	(vertices)[2] = (x2);						\
620	(vertices)[6] = (vertices)[2];					\
621	(vertices)[4] = (vertices)[0];					\
622        (vertices)[1] = (y1);                                           \
623        (vertices)[7] = (y2);                                           \
624	(vertices)[3] = (vertices)[1];					\
625	(vertices)[5] = (vertices)[7];					\
626    } while(0)
627
628#define glamor_set_normalize_vcoords_ext(priv, xscale, yscale,		\
629				     x1, y1, x2, y2,			\
630                                         vertices, stride)              \
631  do {									\
632    int fbo_x_off, fbo_y_off;						\
633    /* vertices may be write-only, so we use following			\
634     * temporary variable. */						\
635    float _t0_, _t1_, _t2_, _t5_;					\
636    pixmap_priv_get_fbo_off(priv, &fbo_x_off, &fbo_y_off);		\
637    (vertices)[0] = _t0_ = v_from_x_coord_x(xscale, x1 + fbo_x_off);	\
638    (vertices)[1 * stride] = _t2_ = v_from_x_coord_x(xscale,		\
639					x2 + fbo_x_off);		\
640    (vertices)[2 * stride] = _t2_;					\
641    (vertices)[3 * stride] = _t0_;					\
642    (vertices)[1] = _t1_ = v_from_x_coord_y(yscale, y1 + fbo_y_off);    \
643    (vertices)[2 * stride + 1] = _t5_ =                                 \
644        v_from_x_coord_y(yscale, y2 + fbo_y_off);                       \
645    (vertices)[1 * stride + 1] = _t1_;					\
646    (vertices)[3 * stride + 1] = _t5_;					\
647  } while(0)
648
649#define glamor_set_normalize_vcoords(priv, xscale, yscale,		\
650				     x1, y1, x2, y2,			\
651                                     vertices)				\
652  do {									\
653	glamor_set_normalize_vcoords_ext(priv, xscale, yscale,		\
654				     x1, y1, x2, y2,			\
655                                     vertices, 2);			\
656  } while(0)
657
658#define glamor_set_const_ext(params, nparam, vertices, nverts, stride)	\
659    do {								\
660	int _i_ = 0, _j_ = 0;						\
661	for(; _i_ < nverts; _i_++) {					\
662	    for(_j_ = 0; _j_ < nparam; _j_++) {				\
663		vertices[stride*_i_ + _j_] = params[_j_];		\
664	    }								\
665	}								\
666    } while(0)
667
668#define glamor_set_normalize_vcoords_tri_strip(xscale, yscale,		\
669					       x1, y1, x2, y2,		\
670					       vertices)		\
671    do {								\
672	(vertices)[0] = v_from_x_coord_x(xscale, x1);			\
673	(vertices)[2] = v_from_x_coord_x(xscale, x2);			\
674	(vertices)[6] = (vertices)[2];					\
675	(vertices)[4] = (vertices)[0];					\
676        (vertices)[1] = v_from_x_coord_y(yscale, y1);                   \
677        (vertices)[7] = v_from_x_coord_y(yscale, y2);                   \
678	(vertices)[3] = (vertices)[1];					\
679	(vertices)[5] = (vertices)[7];					\
680    } while(0)
681
682#define glamor_set_normalize_pt(xscale, yscale, x, y,		\
683                                pt)				\
684    do {							\
685        (pt)[0] = t_from_x_coord_x(xscale, x);			\
686        (pt)[1] = t_from_x_coord_y(yscale, y);                  \
687    } while(0)
688
689#define glamor_set_circle_centre(width, height, x, y,	\
690				 c)		\
691    do {						\
692        (c)[0] = (float)x;				\
693        (c)[1] = (float)y;				\
694    } while(0)
695
696#ifndef ARRAY_SIZE
697#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
698#endif
699
700#define ALIGN(i,m)	(((i) + (m) - 1) & ~((m) - 1))
701#define MIN(a,b)	((a) < (b) ? (a) : (b))
702#define MAX(a,b)	((a) > (b) ? (a) : (b))
703
704#define glamor_check_fbo_size(_glamor_,_w_, _h_)    ((_w_) > 0 && (_h_) > 0 \
705                                                    && (_w_) <= _glamor_->max_fbo_size  \
706                                                    && (_h_) <= _glamor_->max_fbo_size)
707
708/* For 1bpp pixmap, we don't store it as texture. */
709#define glamor_check_pixmap_fbo_depth(_depth_) (			\
710						_depth_ == 8		\
711						|| _depth_ == 15	\
712						|| _depth_ == 16	\
713						|| _depth_ == 24	\
714						|| _depth_ == 30	\
715						|| _depth_ == 32)
716
717#define GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)    (pixmap_priv->gl_fbo == GLAMOR_FBO_NORMAL)
718
719/**
720 * Borrow from uxa.
721 */
722static inline CARD32
723format_for_depth(int depth)
724{
725    switch (depth) {
726    case 1:
727        return PICT_a1;
728    case 4:
729        return PICT_a4;
730    case 8:
731        return PICT_a8;
732    case 15:
733        return PICT_x1r5g5b5;
734    case 16:
735        return PICT_r5g6b5;
736    default:
737    case 24:
738        return PICT_x8r8g8b8;
739#if XORG_VERSION_CURRENT >= 10699900
740    case 30:
741        return PICT_x2r10g10b10;
742#endif
743    case 32:
744        return PICT_a8r8g8b8;
745    }
746}
747
748static inline GLenum
749gl_iformat_for_pixmap(PixmapPtr pixmap)
750{
751    glamor_screen_private *glamor_priv =
752        glamor_get_screen_private((pixmap)->drawable.pScreen);
753
754    if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP &&
755        ((pixmap)->drawable.depth == 1 || (pixmap)->drawable.depth == 8)) {
756        return glamor_priv->one_channel_format;
757    } else {
758        return GL_RGBA;
759    }
760}
761
762static inline CARD32
763format_for_pixmap(PixmapPtr pixmap)
764{
765    return format_for_depth((pixmap)->drawable.depth);
766}
767
768#define REVERT_NONE       		0
769#define REVERT_NORMAL     		1
770#define REVERT_DOWNLOADING_A1		2
771#define REVERT_UPLOADING_A1		3
772#define REVERT_DOWNLOADING_2_10_10_10 	4
773#define REVERT_UPLOADING_2_10_10_10 	5
774#define REVERT_DOWNLOADING_1_5_5_5  	7
775#define REVERT_UPLOADING_1_5_5_5    	8
776#define REVERT_DOWNLOADING_10_10_10_2 	9
777#define REVERT_UPLOADING_10_10_10_2 	10
778
779#define SWAP_NONE_DOWNLOADING  	0
780#define SWAP_DOWNLOADING  	1
781#define SWAP_UPLOADING	  	2
782#define SWAP_NONE_UPLOADING	3
783
784/* borrowed from uxa */
785static inline Bool
786glamor_get_rgba_from_pixel(CARD32 pixel,
787                           float *red,
788                           float *green,
789                           float *blue, float *alpha, CARD32 format)
790{
791    int rbits, bbits, gbits, abits;
792    int rshift, bshift, gshift, ashift;
793
794    rbits = PICT_FORMAT_R(format);
795    gbits = PICT_FORMAT_G(format);
796    bbits = PICT_FORMAT_B(format);
797    abits = PICT_FORMAT_A(format);
798
799    if (PICT_FORMAT_TYPE(format) == PICT_TYPE_A) {
800        rshift = gshift = bshift = ashift = 0;
801    }
802    else if (PICT_FORMAT_TYPE(format) == PICT_TYPE_ARGB) {
803        bshift = 0;
804        gshift = bbits;
805        rshift = gshift + gbits;
806        ashift = rshift + rbits;
807    }
808    else if (PICT_FORMAT_TYPE(format) == PICT_TYPE_ABGR) {
809        rshift = 0;
810        gshift = rbits;
811        bshift = gshift + gbits;
812        ashift = bshift + bbits;
813#if XORG_VERSION_CURRENT >= 10699900
814    }
815    else if (PICT_FORMAT_TYPE(format) == PICT_TYPE_BGRA) {
816        ashift = 0;
817        rshift = abits;
818        if (abits == 0)
819            rshift = PICT_FORMAT_BPP(format) - (rbits + gbits + bbits);
820        gshift = rshift + rbits;
821        bshift = gshift + gbits;
822#endif
823    }
824    else {
825        return FALSE;
826    }
827#define COLOR_INT_TO_FLOAT(_fc_, _p_, _s_, _bits_)	\
828  *_fc_ = (((_p_) >> (_s_)) & (( 1 << (_bits_)) - 1))	\
829    / (float)((1<<(_bits_)) - 1)
830
831    if (rbits)
832        COLOR_INT_TO_FLOAT(red, pixel, rshift, rbits);
833    else
834        *red = 0;
835
836    if (gbits)
837        COLOR_INT_TO_FLOAT(green, pixel, gshift, gbits);
838    else
839        *green = 0;
840
841    if (bbits)
842        COLOR_INT_TO_FLOAT(blue, pixel, bshift, bbits);
843    else
844        *blue = 0;
845
846    if (abits)
847        COLOR_INT_TO_FLOAT(alpha, pixel, ashift, abits);
848    else
849        *alpha = 1;
850
851    return TRUE;
852}
853
854inline static Bool
855glamor_is_large_pixmap(PixmapPtr pixmap)
856{
857    glamor_pixmap_private *priv;
858
859    priv = glamor_get_pixmap_private(pixmap);
860    return (glamor_pixmap_priv_is_large(priv));
861}
862
863static inline void
864_glamor_dump_pixmap_bits(PixmapPtr pixmap, int x, int y, int w, int h)
865{
866    int i, j;
867    unsigned char *p = (pixmap)->devPrivate.ptr;
868    int stride = (pixmap)->devKind;
869
870    p = p + y * stride + x;
871
872    for (i = 0; i < h; i++) {
873        ErrorF("line %3d: ", i);
874        for (j = 0; j < w; j++)
875            ErrorF("%2d ", (p[j / 8] & (1 << (j % 8))) >> (j % 8));
876        p += stride;
877        ErrorF("\n");
878    }
879}
880
881static inline void
882_glamor_dump_pixmap_byte(PixmapPtr pixmap, int x, int y, int w, int h)
883{
884    int i, j;
885    unsigned char *p = (pixmap)->devPrivate.ptr;
886    int stride = (pixmap)->devKind;
887
888    p = p + y * stride + x;
889
890    for (i = 0; i < h; i++) {
891        ErrorF("line %3d: ", i);
892        for (j = 0; j < w; j++)
893            ErrorF("%2x ", p[j]);
894        p += stride;
895        ErrorF("\n");
896    }
897}
898
899static inline void
900_glamor_dump_pixmap_sword(PixmapPtr pixmap, int x, int y, int w, int h)
901{
902    int i, j;
903    unsigned short *p = (pixmap)->devPrivate.ptr;
904    int stride = (pixmap)->devKind / 2;
905
906    p = p + y * stride + x;
907
908    for (i = 0; i < h; i++) {
909        ErrorF("line %3d: ", i);
910        for (j = 0; j < w; j++)
911            ErrorF("%2x ", p[j]);
912        p += stride;
913        ErrorF("\n");
914    }
915}
916
917static inline void
918_glamor_dump_pixmap_word(PixmapPtr pixmap, int x, int y, int w, int h)
919{
920    int i, j;
921    unsigned int *p = (pixmap)->devPrivate.ptr;
922    int stride = (pixmap)->devKind / 4;
923
924    p = p + y * stride + x;
925
926    for (i = 0; i < h; i++) {
927        ErrorF("line %3d: ", i);
928        for (j = 0; j < w; j++)
929            ErrorF("%2x ", p[j]);
930        p += stride;
931        ErrorF("\n");
932    }
933}
934
935static inline void
936glamor_dump_pixmap(PixmapPtr pixmap, int x, int y, int w, int h)
937{
938    w = ((x + w) > (pixmap)->drawable.width) ? ((pixmap)->drawable.width - x) : w;
939    h = ((y + h) > (pixmap)->drawable.height) ? ((pixmap)->drawable.height - y) : h;
940
941    glamor_prepare_access(&(pixmap)->drawable, GLAMOR_ACCESS_RO);
942    switch ((pixmap)->drawable.depth) {
943    case 8:
944        _glamor_dump_pixmap_byte(pixmap, x, y, w, h);
945        break;
946    case 15:
947    case 16:
948        _glamor_dump_pixmap_sword(pixmap, x, y, w, h);
949        break;
950
951    case 24:
952    case 32:
953        _glamor_dump_pixmap_word(pixmap, x, y, w, h);
954        break;
955    case 1:
956        _glamor_dump_pixmap_bits(pixmap, x, y, w, h);
957        break;
958    default:
959        ErrorF("dump depth %d, not implemented.\n", (pixmap)->drawable.depth);
960    }
961    glamor_finish_access(&(pixmap)->drawable);
962}
963
964static inline void
965_glamor_compare_pixmaps(PixmapPtr pixmap1, PixmapPtr pixmap2,
966                        int x, int y, int w, int h,
967                        PictFormatShort short_format, int all, int diffs)
968{
969    int i, j;
970    unsigned char *p1 = pixmap1->devPrivate.ptr;
971    unsigned char *p2 = pixmap2->devPrivate.ptr;
972    int line_need_printed = 0;
973    int test_code = 0xAABBCCDD;
974    int little_endian = 0;
975    unsigned char *p_test;
976    int bpp = pixmap1->drawable.depth == 8 ? 1 : 4;
977    int stride = pixmap1->devKind;
978
979    assert(pixmap1->devKind == pixmap2->devKind);
980
981    ErrorF("stride:%d, width:%d, height:%d\n", stride, w, h);
982
983    p1 = p1 + y * stride + x;
984    p2 = p2 + y * stride + x;
985
986    if (all) {
987        for (i = 0; i < h; i++) {
988            ErrorF("line %3d: ", i);
989
990            for (j = 0; j < stride; j++) {
991                if (j % bpp == 0)
992                    ErrorF("[%d]%2x:%2x ", j / bpp, p1[j], p2[j]);
993                else
994                    ErrorF("%2x:%2x ", p1[j], p2[j]);
995            }
996
997            p1 += stride;
998            p2 += stride;
999            ErrorF("\n");
1000        }
1001    }
1002    else {
1003        if (short_format == PICT_a8r8g8b8) {
1004            p_test = (unsigned char *) &test_code;
1005            little_endian = (*p_test == 0xDD);
1006            bpp = 4;
1007
1008            for (i = 0; i < h; i++) {
1009                line_need_printed = 0;
1010
1011                for (j = 0; j < stride; j++) {
1012                    if (p1[j] != p2[j] &&
1013                        (p1[j] - p2[j] > diffs || p2[j] - p1[j] > diffs)) {
1014                        if (line_need_printed) {
1015                            if (little_endian) {
1016                                switch (j % 4) {
1017                                case 2:
1018                                    ErrorF("[%d]RED:%2x:%2x ", j / bpp, p1[j],
1019                                           p2[j]);
1020                                    break;
1021                                case 1:
1022                                    ErrorF("[%d]GREEN:%2x:%2x ", j / bpp, p1[j],
1023                                           p2[j]);
1024                                    break;
1025                                case 0:
1026                                    ErrorF("[%d]BLUE:%2x:%2x ", j / bpp, p1[j],
1027                                           p2[j]);
1028                                    break;
1029                                case 3:
1030                                    ErrorF("[%d]Alpha:%2x:%2x ", j / bpp, p1[j],
1031                                           p2[j]);
1032                                    break;
1033                                }
1034                            }
1035                            else {
1036                                switch (j % 4) {
1037                                case 1:
1038                                    ErrorF("[%d]RED:%2x:%2x ", j / bpp, p1[j],
1039                                           p2[j]);
1040                                    break;
1041                                case 2:
1042                                    ErrorF("[%d]GREEN:%2x:%2x ", j / bpp, p1[j],
1043                                           p2[j]);
1044                                    break;
1045                                case 3:
1046                                    ErrorF("[%d]BLUE:%2x:%2x ", j / bpp, p1[j],
1047                                           p2[j]);
1048                                    break;
1049                                case 0:
1050                                    ErrorF("[%d]Alpha:%2x:%2x ", j / bpp, p1[j],
1051                                           p2[j]);
1052                                    break;
1053                                }
1054                            }
1055                        }
1056                        else {
1057                            line_need_printed = 1;
1058                            j = -1;
1059                            ErrorF("line %3d: ", i);
1060                            continue;
1061                        }
1062                    }
1063                }
1064
1065                p1 += stride;
1066                p2 += stride;
1067                ErrorF("\n");
1068            }
1069        }                       //more format can be added here.
1070        else {                  // the default format, just print.
1071            for (i = 0; i < h; i++) {
1072                line_need_printed = 0;
1073
1074                for (j = 0; j < stride; j++) {
1075                    if (p1[j] != p2[j]) {
1076                        if (line_need_printed) {
1077                            ErrorF("[%d]%2x:%2x ", j / bpp, p1[j], p2[j]);
1078                        }
1079                        else {
1080                            line_need_printed = 1;
1081                            j = -1;
1082                            ErrorF("line %3d: ", i);
1083                            continue;
1084                        }
1085                    }
1086                }
1087
1088                p1 += stride;
1089                p2 += stride;
1090                ErrorF("\n");
1091            }
1092        }
1093    }
1094}
1095
1096static inline void
1097glamor_compare_pixmaps(PixmapPtr pixmap1, PixmapPtr pixmap2,
1098                       int x, int y, int w, int h, int all, int diffs)
1099{
1100    assert(pixmap1->drawable.depth == pixmap2->drawable.depth);
1101
1102    if (glamor_prepare_access(&pixmap1->drawable, GLAMOR_ACCESS_RO) &&
1103        glamor_prepare_access(&pixmap2->drawable, GLAMOR_ACCESS_RO)) {
1104        _glamor_compare_pixmaps(pixmap1, pixmap2, x, y, w, h, -1, all, diffs);
1105    }
1106    glamor_finish_access(&pixmap1->drawable);
1107    glamor_finish_access(&pixmap2->drawable);
1108}
1109
1110/* This function is used to compare two pictures.
1111   If the picture has no drawable, we use fb functions to generate it. */
1112static inline void
1113glamor_compare_pictures(ScreenPtr screen,
1114                        PicturePtr fst_picture,
1115                        PicturePtr snd_picture,
1116                        int x_source, int y_source,
1117                        int width, int height, int all, int diffs)
1118{
1119    PixmapPtr fst_pixmap;
1120    PixmapPtr snd_pixmap;
1121    int fst_generated, snd_generated;
1122    int error;
1123    int fst_type = -1;
1124    int snd_type = -1;          // -1 represent has drawable.
1125
1126    if (fst_picture->format != snd_picture->format) {
1127        ErrorF("Different picture format can not compare!\n");
1128        return;
1129    }
1130
1131    if (!fst_picture->pDrawable) {
1132        fst_type = fst_picture->pSourcePict->type;
1133    }
1134
1135    if (!snd_picture->pDrawable) {
1136        snd_type = snd_picture->pSourcePict->type;
1137    }
1138
1139    if ((fst_type != -1) && (snd_type != -1) && (fst_type != snd_type)) {
1140        ErrorF("Different picture type will never be same!\n");
1141        return;
1142    }
1143
1144    fst_generated = snd_generated = 0;
1145
1146    if (!fst_picture->pDrawable) {
1147        PicturePtr pixman_pic;
1148        PixmapPtr pixmap = NULL;
1149        PictFormatShort format;
1150
1151        format = fst_picture->format;
1152
1153        pixmap = glamor_create_pixmap(screen,
1154                                      width, height,
1155                                      PIXMAN_FORMAT_DEPTH(format),
1156                                      GLAMOR_CREATE_PIXMAP_CPU);
1157
1158        pixman_pic = CreatePicture(0,
1159                                   &(pixmap)->drawable,
1160                                   PictureMatchFormat(screen,
1161                                                      PIXMAN_FORMAT_DEPTH
1162                                                      (format), format), 0, 0,
1163                                   serverClient, &error);
1164
1165        fbComposite(PictOpSrc, fst_picture, NULL, pixman_pic,
1166                    x_source, y_source, 0, 0, 0, 0, width, height);
1167
1168        glamor_destroy_pixmap(pixmap);
1169
1170        fst_picture = pixman_pic;
1171        fst_generated = 1;
1172    }
1173
1174    if (!snd_picture->pDrawable) {
1175        PicturePtr pixman_pic;
1176        PixmapPtr pixmap = NULL;
1177        PictFormatShort format;
1178
1179        format = snd_picture->format;
1180
1181        pixmap = glamor_create_pixmap(screen,
1182                                      width, height,
1183                                      PIXMAN_FORMAT_DEPTH(format),
1184                                      GLAMOR_CREATE_PIXMAP_CPU);
1185
1186        pixman_pic = CreatePicture(0,
1187                                   &(pixmap)->drawable,
1188                                   PictureMatchFormat(screen,
1189                                                      PIXMAN_FORMAT_DEPTH
1190                                                      (format), format), 0, 0,
1191                                   serverClient, &error);
1192
1193        fbComposite(PictOpSrc, snd_picture, NULL, pixman_pic,
1194                    x_source, y_source, 0, 0, 0, 0, width, height);
1195
1196        glamor_destroy_pixmap(pixmap);
1197
1198        snd_picture = pixman_pic;
1199        snd_generated = 1;
1200    }
1201
1202    fst_pixmap = glamor_get_drawable_pixmap(fst_picture->pDrawable);
1203    snd_pixmap = glamor_get_drawable_pixmap(snd_picture->pDrawable);
1204
1205    if (fst_pixmap->drawable.depth != snd_pixmap->drawable.depth) {
1206        if (fst_generated)
1207            miDestroyPicture(fst_picture);
1208        if (snd_generated)
1209            miDestroyPicture(snd_picture);
1210
1211        ErrorF("Different pixmap depth can not compare!\n");
1212        return;
1213    }
1214
1215    if ((fst_type == SourcePictTypeLinear) ||
1216        (fst_type == SourcePictTypeRadial) ||
1217        (fst_type == SourcePictTypeConical) ||
1218        (snd_type == SourcePictTypeLinear) ||
1219        (snd_type == SourcePictTypeRadial) ||
1220        (snd_type == SourcePictTypeConical)) {
1221        x_source = y_source = 0;
1222    }
1223
1224    if (glamor_prepare_access(&fst_pixmap->drawable, GLAMOR_ACCESS_RO) &&
1225        glamor_prepare_access(&snd_pixmap->drawable, GLAMOR_ACCESS_RO)) {
1226        _glamor_compare_pixmaps(fst_pixmap, snd_pixmap,
1227                                x_source, y_source,
1228                                width, height, fst_picture->format,
1229                                all, diffs);
1230    }
1231    glamor_finish_access(&fst_pixmap->drawable);
1232    glamor_finish_access(&snd_pixmap->drawable);
1233
1234    if (fst_generated)
1235        miDestroyPicture(fst_picture);
1236    if (snd_generated)
1237        miDestroyPicture(snd_picture);
1238
1239    return;
1240}
1241
1242#ifdef __i386__
1243static inline unsigned long
1244__fls(unsigned long x)
1245{
1246 asm("bsr %1,%0":"=r"(x)
1247 :     "rm"(x));
1248    return x;
1249}
1250#else
1251static inline unsigned long
1252__fls(unsigned long x)
1253{
1254    int n;
1255
1256    if (x == 0)
1257        return (0);
1258    n = 0;
1259    if (x <= 0x0000FFFF) {
1260        n = n + 16;
1261        x = x << 16;
1262    }
1263    if (x <= 0x00FFFFFF) {
1264        n = n + 8;
1265        x = x << 8;
1266    }
1267    if (x <= 0x0FFFFFFF) {
1268        n = n + 4;
1269        x = x << 4;
1270    }
1271    if (x <= 0x3FFFFFFF) {
1272        n = n + 2;
1273        x = x << 2;
1274    }
1275    if (x <= 0x7FFFFFFF) {
1276        n = n + 1;
1277    }
1278    return 31 - n;
1279}
1280#endif
1281
1282static inline void
1283glamor_make_current(glamor_screen_private *glamor_priv)
1284{
1285    if (lastGLContext != &glamor_priv->ctx) {
1286        lastGLContext = &glamor_priv->ctx;
1287        glamor_priv->ctx.make_current(&glamor_priv->ctx);
1288    }
1289}
1290
1291/**
1292 * Helper function for implementing draws with GL_QUADS on GLES2,
1293 * where we don't have them.
1294 */
1295static inline void
1296glamor_glDrawArrays_GL_QUADS(glamor_screen_private *glamor_priv, unsigned count)
1297{
1298    if (glamor_priv->use_quads) {
1299        glDrawArrays(GL_QUADS, 0, count * 4);
1300    } else {
1301        glamor_gldrawarrays_quads_using_indices(glamor_priv, count);
1302    }
1303}
1304
1305
1306#endif
1307