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_tcoords_ext( priv, \
338 matrix, \
339 xscale, \
340 yscale, \
341 tx1, ty1, tx2, ty2, \
342 texcoords, \
343 stride) \
344 do { \
345 glamor_set_transformed_point(priv, matrix, xscale, yscale, \
346 texcoords, tx1, ty1); \
347 glamor_set_transformed_point(priv, matrix, xscale, yscale, \
348 texcoords + 1 * stride, tx2, ty1); \
349 glamor_set_transformed_point(priv, matrix, xscale, yscale, \
350 texcoords + 2 * stride, tx2, ty2); \
351 glamor_set_transformed_point(priv, matrix, xscale, yscale, \
352 texcoords + 3 * stride, tx1, ty2); \
353 } while (0)
354
355 #define glamor_set_repeat_transformed_normalize_tcoords_ext(pixmap, priv, \
356 repeat_type, \
357 matrix, \
358 xscale, \
359 yscale, \
360 _x1_, _y1_, \
361 _x2_, _y2_, \
362 texcoords, \
363 stride) \
364 do { \
365 if (_X_LIKELY(glamor_pixmap_priv_is_small(priv))) { \
366 glamor_set_transformed_normalize_tcoords_ext(priv, matrix, xscale, \
367 yscale, _x1_, _y1_, \
368 _x2_, _y2_, \
369 texcoords, stride); \
370 } else { \
371 float tx1, ty1, tx2, ty2, tx3, ty3, tx4, ty4; \
372 float ttx1, tty1, ttx2, tty2, ttx3, tty3, ttx4, tty4; \
373 DEBUGF("original coords %d %d %d %d\n", _x1_, _y1_, _x2_, _y2_); \
374 glamor_transform_point(matrix, tx1, ty1, _x1_, _y1_); \
375 glamor_transform_point(matrix, tx2, ty2, _x2_, _y1_); \
376 glamor_transform_point(matrix, tx3, ty3, _x2_, _y2_); \
377 glamor_transform_point(matrix, tx4, ty4, _x1_, _y2_); \
378 DEBUGF("transformed %f %f %f %f %f %f %f %f\n", \
379 tx1, ty1, tx2, ty2, tx3, ty3, tx4, ty4); \
380 glamor_get_repeat_transform_coords(pixmap, priv, repeat_type, \
381 ttx1, tty1, \
382 tx1, ty1); \
383 glamor_get_repeat_transform_coords(pixmap, priv, repeat_type, \
384 ttx2, tty2, \
385 tx2, ty2); \
386 glamor_get_repeat_transform_coords(pixmap, priv, repeat_type, \
387 ttx3, tty3, \
388 tx3, ty3); \
389 glamor_get_repeat_transform_coords(pixmap, priv, repeat_type, \
390 ttx4, tty4, \
391 tx4, ty4); \
392 DEBUGF("repeat transformed %f %f %f %f %f %f %f %f\n", ttx1, tty1, \
393 ttx2, tty2, ttx3, tty3, ttx4, tty4); \
394 _glamor_set_normalize_tpoint(xscale, yscale, ttx1, tty1, \
395 texcoords); \
396 _glamor_set_normalize_tpoint(xscale, yscale, ttx2, tty2, \
397 texcoords + 1 * stride); \
398 _glamor_set_normalize_tpoint(xscale, yscale, ttx3, tty3, \
399 texcoords + 2 * stride); \
400 _glamor_set_normalize_tpoint(xscale, yscale, ttx4, tty4, \
401 texcoords + 3 * stride); \
402 } \
403 } while (0)
404
405 #define glamor_set_repeat_transformed_normalize_tcoords( pixmap, \
406 priv, \
407 repeat_type, \
408 matrix, \
409 xscale, \
410 yscale, \
411 _x1_, _y1_, \
412 _x2_, _y2_, \
413 texcoords) \
414 do { \
415 glamor_set_repeat_transformed_normalize_tcoords_ext( pixmap, \
416 priv, \
417 repeat_type, \
418 matrix, \
419 xscale, \
420 yscale, \
421 _x1_, _y1_, \
422 _x2_, _y2_, \
423 texcoords, \
424 2); \
425 } while (0)
426
427 #define _glamor_set_normalize_tcoords(xscale, yscale, tx1, \
428 ty1, tx2, ty2, \
429 vertices, stride) \
430 do { \
431 /* vertices may be write-only, so we use following \
432 * temporary variable. */ \
433 float _t0_, _t1_, _t2_, _t5_; \
434 (vertices)[0] = _t0_ = t_from_x_coord_x(xscale, tx1); \
435 (vertices)[1 * stride] = _t2_ = t_from_x_coord_x(xscale, tx2); \
436 (vertices)[2 * stride] = _t2_; \
437 (vertices)[3 * stride] = _t0_; \
438 (vertices)[1] = _t1_ = t_from_x_coord_y(yscale, ty1); \
439 (vertices)[2 * stride + 1] = _t5_ = t_from_x_coord_y(yscale, ty2); \
440 (vertices)[1 * stride + 1] = _t1_; \
441 (vertices)[3 * stride + 1] = _t5_; \
442 } while(0)
443
444 #define glamor_set_normalize_tcoords_ext(priv, xscale, yscale, \
445 x1, y1, x2, y2, \
446 vertices, stride) \
447 do { \
448 if (_X_UNLIKELY(glamor_pixmap_priv_is_large(priv))) { \
449 float tx1, tx2, ty1, ty2; \
450 int fbo_x_off, fbo_y_off; \
451 pixmap_priv_get_fbo_off(priv, &fbo_x_off, &fbo_y_off); \
452 tx1 = x1 + fbo_x_off; \
453 tx2 = x2 + fbo_x_off; \
454 ty1 = y1 + fbo_y_off; \
455 ty2 = y2 + fbo_y_off; \
456 _glamor_set_normalize_tcoords(xscale, yscale, tx1, ty1, \
457 tx2, ty2, vertices, \
458 stride); \
459 } else \
460 _glamor_set_normalize_tcoords(xscale, yscale, x1, y1, \
461 x2, y2, vertices, stride); \
462 } while(0)
463
464 #define glamor_set_repeat_normalize_tcoords_ext(pixmap, priv, repeat_type, \
465 xscale, yscale, \
466 _x1_, _y1_, _x2_, _y2_, \
467 vertices, stride) \
468 do { \
469 if (_X_UNLIKELY(glamor_pixmap_priv_is_large(priv))) { \
470 float tx1, tx2, ty1, ty2; \
471 if (repeat_type == RepeatPad) { \
472 tx1 = _x1_ - priv->box.x1; \
473 ty1 = _y1_ - priv->box.y1; \
474 tx2 = tx1 + ((_x2_) - (_x1_)); \
475 ty2 = ty1 + ((_y2_) - (_y1_)); \
476 } else { \
477 glamor_get_repeat_coords(pixmap, priv, repeat_type, \
478 tx1, ty1, tx2, ty2, \
479 _x1_, _y1_, _x2_, _y2_); \
480 } \
481 _glamor_set_normalize_tcoords(xscale, yscale, tx1, ty1, \
482 tx2, ty2, vertices, \
483 stride); \
484 } else \
485 _glamor_set_normalize_tcoords(xscale, yscale, _x1_, _y1_, \
486 _x2_, _y2_, vertices, \
487 stride); \
488 } while(0)
489
490 #define glamor_set_normalize_tcoords_tri_stripe(xscale, yscale, \
491 x1, y1, x2, y2, \
492 vertices) \
493 do { \
494 (vertices)[0] = t_from_x_coord_x(xscale, x1); \
495 (vertices)[2] = t_from_x_coord_x(xscale, x2); \
496 (vertices)[6] = (vertices)[2]; \
497 (vertices)[4] = (vertices)[0]; \
498 (vertices)[1] = t_from_x_coord_y(yscale, y1); \
499 (vertices)[7] = t_from_x_coord_y(yscale, y2); \
500 (vertices)[3] = (vertices)[1]; \
501 (vertices)[5] = (vertices)[7]; \
502 } while(0)
503
504 #define glamor_set_tcoords_tri_strip(x1, y1, x2, y2, vertices) \
505 do { \
506 (vertices)[0] = (x1); \
507 (vertices)[2] = (x2); \
508 (vertices)[6] = (vertices)[2]; \
509 (vertices)[4] = (vertices)[0]; \
510 (vertices)[1] = (y1); \
511 (vertices)[7] = (y2); \
512 (vertices)[3] = (vertices)[1]; \
513 (vertices)[5] = (vertices)[7]; \
514 } while(0)
515
516 #define glamor_set_normalize_vcoords_ext(priv, xscale, yscale, \
517 x1, y1, x2, y2, \
518 vertices, stride) \
519 do { \
520 int fbo_x_off, fbo_y_off; \
521 /* vertices may be write-only, so we use following \
522 * temporary variable. */ \
523 float _t0_, _t1_, _t2_, _t5_; \
524 pixmap_priv_get_fbo_off(priv, &fbo_x_off, &fbo_y_off); \
525 (vertices)[0] = _t0_ = v_from_x_coord_x(xscale, x1 + fbo_x_off); \
526 (vertices)[1 * stride] = _t2_ = v_from_x_coord_x(xscale, \
527 x2 + fbo_x_off); \
528 (vertices)[2 * stride] = _t2_; \
529 (vertices)[3 * stride] = _t0_; \
530 (vertices)[1] = _t1_ = v_from_x_coord_y(yscale, y1 + fbo_y_off); \
531 (vertices)[2 * stride + 1] = _t5_ = \
532 v_from_x_coord_y(yscale, y2 + fbo_y_off); \
533 (vertices)[1 * stride + 1] = _t1_; \
534 (vertices)[3 * stride + 1] = _t5_; \
535 } while(0)
536
537 #define glamor_set_normalize_vcoords_tri_strip(xscale, yscale, \
538 x1, y1, x2, y2, \
539 vertices) \
540 do { \
541 (vertices)[0] = v_from_x_coord_x(xscale, x1); \
542 (vertices)[2] = v_from_x_coord_x(xscale, x2); \
543 (vertices)[6] = (vertices)[2]; \
544 (vertices)[4] = (vertices)[0]; \
545 (vertices)[1] = v_from_x_coord_y(yscale, y1); \
546 (vertices)[7] = v_from_x_coord_y(yscale, y2); \
547 (vertices)[3] = (vertices)[1]; \
548 (vertices)[5] = (vertices)[7]; \
549 } while(0)
550
551 #define glamor_set_normalize_pt(xscale, yscale, x, y, \
552 pt) \
553 do { \
554 (pt)[0] = t_from_x_coord_x(xscale, x); \
555 (pt)[1] = t_from_x_coord_y(yscale, y); \
556 } while(0)
557
558 #define glamor_set_circle_centre(width, height, x, y, \
559 c) \
560 do { \
561 (c)[0] = (float)x; \
562 (c)[1] = (float)y; \
563 } while(0)
564
565 #define ALIGN(i,m) (((i) + (m) - 1) & ~((m) - 1))
566 #define MIN(a,b) ((a) < (b) ? (a) : (b))
567 #define MAX(a,b) ((a) > (b) ? (a) : (b))
568
569 #define glamor_check_fbo_size(_glamor_,_w_, _h_) ((_w_) > 0 && (_h_) > 0 \
570 && (_w_) <= _glamor_->max_fbo_size \
571 && (_h_) <= _glamor_->max_fbo_size)
572
573 /* For 1bpp pixmap, we don't store it as texture. */
574 #define glamor_check_pixmap_fbo_depth(_depth_) ( \
575 _depth_ == 8 \
576 || _depth_ == 15 \
577 || _depth_ == 16 \
578 || _depth_ == 24 \
579 || _depth_ == 30 \
580 || _depth_ == 32)
581
582 #define GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv) (pixmap_priv->gl_fbo == GLAMOR_FBO_NORMAL)
583
584 /**
585 * Borrow from uxa.
586 */
587 static inline CARD32
format_for_depth(int depth)588 format_for_depth(int depth)
589 {
590 switch (depth) {
591 case 1:
592 return PICT_a1;
593 case 4:
594 return PICT_a4;
595 case 8:
596 return PICT_a8;
597 case 15:
598 return PICT_x1r5g5b5;
599 case 16:
600 return PICT_r5g6b5;
601 default:
602 case 24:
603 return PICT_x8r8g8b8;
604 case 30:
605 return PICT_x2r10g10b10;
606 case 32:
607 return PICT_a8r8g8b8;
608 }
609 }
610
611 static inline GLenum
gl_iformat_for_pixmap(PixmapPtr pixmap)612 gl_iformat_for_pixmap(PixmapPtr pixmap)
613 {
614 glamor_screen_private *glamor_priv =
615 glamor_get_screen_private((pixmap)->drawable.pScreen);
616
617 if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP &&
618 ((pixmap)->drawable.depth == 1 || (pixmap)->drawable.depth == 8)) {
619 return glamor_priv->one_channel_format;
620 } else if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP &&
621 (pixmap)->drawable.depth == 30) {
622 return GL_RGB10_A2;
623 } else {
624 return GL_RGBA;
625 }
626 }
627
628 static inline CARD32
format_for_pixmap(PixmapPtr pixmap)629 format_for_pixmap(PixmapPtr pixmap)
630 {
631 return format_for_depth((pixmap)->drawable.depth);
632 }
633
634 #define REVERT_NONE 0
635 #define REVERT_NORMAL 1
636 #define REVERT_UPLOADING_A1 3
637
638 #define SWAP_UPLOADING 2
639 #define SWAP_NONE_UPLOADING 3
640
641 /* borrowed from uxa */
642 static inline Bool
glamor_get_rgba_from_pixel(CARD32 pixel,float * red,float * green,float * blue,float * alpha,CARD32 format)643 glamor_get_rgba_from_pixel(CARD32 pixel,
644 float *red,
645 float *green,
646 float *blue, float *alpha, CARD32 format)
647 {
648 int rbits, bbits, gbits, abits;
649 int rshift, bshift, gshift, ashift;
650
651 rbits = PICT_FORMAT_R(format);
652 gbits = PICT_FORMAT_G(format);
653 bbits = PICT_FORMAT_B(format);
654 abits = PICT_FORMAT_A(format);
655
656 if (PICT_FORMAT_TYPE(format) == PICT_TYPE_A) {
657 rshift = gshift = bshift = ashift = 0;
658 }
659 else if (PICT_FORMAT_TYPE(format) == PICT_TYPE_ARGB) {
660 bshift = 0;
661 gshift = bbits;
662 rshift = gshift + gbits;
663 ashift = rshift + rbits;
664 }
665 else if (PICT_FORMAT_TYPE(format) == PICT_TYPE_ABGR) {
666 rshift = 0;
667 gshift = rbits;
668 bshift = gshift + gbits;
669 ashift = bshift + bbits;
670 }
671 else if (PICT_FORMAT_TYPE(format) == PICT_TYPE_BGRA) {
672 ashift = 0;
673 rshift = abits;
674 if (abits == 0)
675 rshift = PICT_FORMAT_BPP(format) - (rbits + gbits + bbits);
676 gshift = rshift + rbits;
677 bshift = gshift + gbits;
678 }
679 else {
680 return FALSE;
681 }
682 #define COLOR_INT_TO_FLOAT(_fc_, _p_, _s_, _bits_) \
683 *_fc_ = (((_p_) >> (_s_)) & (( 1 << (_bits_)) - 1)) \
684 / (float)((1<<(_bits_)) - 1)
685
686 if (rbits)
687 COLOR_INT_TO_FLOAT(red, pixel, rshift, rbits);
688 else
689 *red = 0;
690
691 if (gbits)
692 COLOR_INT_TO_FLOAT(green, pixel, gshift, gbits);
693 else
694 *green = 0;
695
696 if (bbits)
697 COLOR_INT_TO_FLOAT(blue, pixel, bshift, bbits);
698 else
699 *blue = 0;
700
701 if (abits)
702 COLOR_INT_TO_FLOAT(alpha, pixel, ashift, abits);
703 else
704 *alpha = 1;
705
706 return TRUE;
707 }
708
709 static inline void
glamor_get_rgba_from_color(const xRenderColor * color,float rgba[4])710 glamor_get_rgba_from_color(const xRenderColor *color, float rgba[4])
711 {
712 rgba[0] = color->red / (float)UINT16_MAX;
713 rgba[1] = color->green / (float)UINT16_MAX;
714 rgba[2] = color->blue / (float)UINT16_MAX;
715 rgba[3] = color->alpha / (float)UINT16_MAX;
716 }
717
718 inline static Bool
glamor_is_large_pixmap(PixmapPtr pixmap)719 glamor_is_large_pixmap(PixmapPtr pixmap)
720 {
721 glamor_pixmap_private *priv;
722
723 priv = glamor_get_pixmap_private(pixmap);
724 return (glamor_pixmap_priv_is_large(priv));
725 }
726
727 static inline void
glamor_make_current(glamor_screen_private * glamor_priv)728 glamor_make_current(glamor_screen_private *glamor_priv)
729 {
730 if (lastGLContext != glamor_priv->ctx.ctx) {
731 lastGLContext = glamor_priv->ctx.ctx;
732 glamor_priv->ctx.make_current(&glamor_priv->ctx);
733 }
734 }
735
736 static inline BoxRec
glamor_no_rendering_bounds(void)737 glamor_no_rendering_bounds(void)
738 {
739 BoxRec bounds = {
740 .x1 = 0,
741 .y1 = 0,
742 .x2 = MAXSHORT,
743 .y2 = MAXSHORT,
744 };
745
746 return bounds;
747 }
748
749 static inline BoxRec
glamor_start_rendering_bounds(void)750 glamor_start_rendering_bounds(void)
751 {
752 BoxRec bounds = {
753 .x1 = MAXSHORT,
754 .y1 = MAXSHORT,
755 .x2 = 0,
756 .y2 = 0,
757 };
758
759 return bounds;
760 }
761
762 static inline void
glamor_bounds_union_rect(BoxPtr bounds,xRectangle * rect)763 glamor_bounds_union_rect(BoxPtr bounds, xRectangle *rect)
764 {
765 bounds->x1 = min(bounds->x1, rect->x);
766 bounds->y1 = min(bounds->y1, rect->y);
767 bounds->x2 = min(SHRT_MAX, max(bounds->x2, rect->x + rect->width));
768 bounds->y2 = min(SHRT_MAX, max(bounds->y2, rect->y + rect->height));
769 }
770
771 static inline void
glamor_bounds_union_box(BoxPtr bounds,BoxPtr box)772 glamor_bounds_union_box(BoxPtr bounds, BoxPtr box)
773 {
774 bounds->x1 = min(bounds->x1, box->x1);
775 bounds->y1 = min(bounds->y1, box->y1);
776 bounds->x2 = max(bounds->x2, box->x2);
777 bounds->y2 = max(bounds->y2, box->y2);
778 }
779
780 /**
781 * Helper function for implementing draws with GL_QUADS on GLES2,
782 * where we don't have them.
783 */
784 static inline void
glamor_glDrawArrays_GL_QUADS(glamor_screen_private * glamor_priv,unsigned count)785 glamor_glDrawArrays_GL_QUADS(glamor_screen_private *glamor_priv, unsigned count)
786 {
787 if (glamor_priv->use_quads) {
788 glDrawArrays(GL_QUADS, 0, count * 4);
789 } else {
790 glamor_gldrawarrays_quads_using_indices(glamor_priv, count);
791 }
792 }
793
794
795 #endif
796