xenocara/xserver/glamor/glamor_utils.h

1433 lines
45 KiB
C
Raw Normal View History

/*
* Copyright © 2009 Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*
* Authors:
* Zhigang Gong <zhigang.gong@linux.intel.com>
*
*/
#ifndef GLAMOR_PRIV_H
#error This file can only be included by glamor_priv.h
#endif
#ifndef __GLAMOR_UTILS_H__
#define __GLAMOR_UTILS_H__
#include "glamor_prepare.h"
#define v_from_x_coord_x(_xscale_, _x_) ( 2 * (_x_) * (_xscale_) - 1.0)
#define v_from_x_coord_y(_yscale_, _y_) (-2 * (_y_) * (_yscale_) + 1.0)
#define v_from_x_coord_y_inverted(_yscale_, _y_) (2 * (_y_) * (_yscale_) - 1.0)
#define t_from_x_coord_x(_xscale_, _x_) ((_x_) * (_xscale_))
#define t_from_x_coord_y(_yscale_, _y_) (1.0 - (_y_) * (_yscale_))
#define t_from_x_coord_y_inverted(_yscale_, _y_) ((_y_) * (_yscale_))
#define pixmap_priv_get_dest_scale(_pixmap_priv_, _pxscale_, _pyscale_) \
do { \
int _w_,_h_; \
PIXMAP_PRIV_GET_ACTUAL_SIZE(_pixmap_priv_, _w_, _h_); \
*(_pxscale_) = 1.0 / _w_; \
*(_pyscale_) = 1.0 / _h_; \
} while(0)
#define pixmap_priv_get_scale(_pixmap_priv_, _pxscale_, _pyscale_) \
do { \
*(_pxscale_) = 1.0 / (_pixmap_priv_)->base.fbo->width; \
*(_pyscale_) = 1.0 / (_pixmap_priv_)->base.fbo->height; \
} while(0)
#define GLAMOR_PIXMAP_FBO_NOT_EXACT_SIZE(priv) \
(priv->base.fbo->width != priv->base.pixmap->drawable.width \
|| priv->base.fbo->height != priv->base.pixmap->drawable.height) \
#define PIXMAP_PRIV_GET_ACTUAL_SIZE(priv, w, h) \
do { \
if (_X_UNLIKELY(priv->type == GLAMOR_TEXTURE_LARGE)) { \
w = priv->large.box.x2 - priv->large.box.x1; \
h = priv->large.box.y2 - priv->large.box.y1; \
} else { \
w = priv->base.pixmap->drawable.width; \
h = priv->base.pixmap->drawable.height; \
} \
} while(0)
#define glamor_pixmap_fbo_fix_wh_ratio(wh, priv) \
do { \
int actual_w, actual_h; \
PIXMAP_PRIV_GET_ACTUAL_SIZE(priv, actual_w, actual_h); \
wh[0] = (float)priv->base.fbo->width / actual_w; \
wh[1] = (float)priv->base.fbo->height / actual_h; \
wh[2] = 1.0 / priv->base.fbo->width; \
wh[3] = 1.0 / priv->base.fbo->height; \
} while(0)
#define pixmap_priv_get_fbo_off(_priv_, _xoff_, _yoff_) \
do { \
if (_X_UNLIKELY(_priv_ && (_priv_)->type == GLAMOR_TEXTURE_LARGE)) { \
*(_xoff_) = - (_priv_)->large.box.x1; \
*(_yoff_) = - (_priv_)->large.box.y1; \
} else { \
*(_xoff_) = 0; \
*(_yoff_) = 0; \
} \
} while(0)
#define xFixedToFloat(_val_) ((float)xFixedToInt(_val_) \
+ ((float)xFixedFrac(_val_) / 65536.0))
#define glamor_picture_get_matrixf(_picture_, _matrix_) \
do { \
int _i_; \
if ((_picture_)->transform) \
{ \
for(_i_ = 0; _i_ < 3; _i_++) \
{ \
(_matrix_)[_i_ * 3 + 0] = \
xFixedToFloat((_picture_)->transform->matrix[_i_][0]); \
(_matrix_)[_i_ * 3 + 1] = \
xFixedToFloat((_picture_)->transform->matrix[_i_][1]); \
(_matrix_)[_i_ * 3 + 2] = \
xFixedToFloat((_picture_)->transform->matrix[_i_][2]); \
} \
} \
} while(0)
#define fmod(x, w) (x - w * floor((float)x/w))
#define fmodulus(x, w, c) do {c = fmod(x, w); \
c = c >= 0 ? c : c + w;} \
while(0)
/* @x: is current coord
* @x2: is the right/bottom edge
* @w: is current width or height
* @odd: is output value, 0 means we are in an even region, 1 means we are in a
* odd region.
* @c: is output value, equal to x mod w. */
#define fodd_repeat_mod(x, x2, w, odd, c) \
do { \
float shift; \
fmodulus((x), w, c); \
shift = fabs((x) - (c)); \
shift = floor(fabs(round(shift)) / w); \
odd = (int)shift & 1; \
if (odd && (((x2 % w) == 0) && \
round(fabs(x)) == x2)) \
odd = 0; \
} while(0)
/* @txy: output value, is the corrected coords.
* @xy: input coords to be fixed up.
* @cd: xy mod wh, is a input value.
* @wh: current width or height.
* @bxy1,bxy2: current box edge's x1/x2 or y1/y2
*
* case 1:
* ----------
* | * |
* | |
* ----------
* tx = (c - x1) mod w
*
* case 2:
* ---------
* * | |
* | |
* ---------
* tx = - (c - (x1 mod w))
*
* case 3:
*
* ----------
* | | *
* | |
* ----------
* tx = ((x2 mod x) - c) + (x2 - x1)
**/
#define __glamor_repeat_reflect_fixup(txy, xy, \
cd, wh, bxy1, bxy2) \
do { \
cd = wh - cd; \
if ( xy >= bxy1 && xy < bxy2) { \
cd = cd - bxy1; \
fmodulus(cd, wh, txy); \
} else if (xy < bxy1) { \
float bxy1_mod; \
fmodulus(bxy1, wh, bxy1_mod); \
txy = -(cd - bxy1_mod); \
} \
else if (xy >= bxy2) { \
float bxy2_mod; \
fmodulus(bxy2, wh, bxy2_mod); \
if (bxy2_mod == 0) \
bxy2_mod = wh; \
txy = (bxy2_mod - cd) + bxy2 - bxy1; \
} else {assert(0); txy = 0;} \
} while(0)
#define _glamor_repeat_reflect_fixup(txy, xy, cd, odd, \
wh, bxy1, bxy2) \
do { \
if (odd) { \
__glamor_repeat_reflect_fixup(txy, xy, \
cd, wh, bxy1, bxy2); \
} else \
txy = xy - bxy1; \
} while(0)
#define _glamor_get_reflect_transform_coords(priv, repeat_type, \
tx1, ty1, \
_x1_, _y1_) \
do { \
int odd_x, odd_y; \
float c, d; \
fodd_repeat_mod(_x1_,priv->box.x2, \
priv->base.pixmap->drawable.width, \
odd_x, c); \
fodd_repeat_mod(_y1_, priv->box.y2, \
priv->base.pixmap->drawable.height, \
odd_y, d); \
DEBUGF("c %f d %f oddx %d oddy %d \n", \
c, d, odd_x, odd_y); \
DEBUGF("x2 %d x1 %d fbo->width %d \n", priv->box.x2, \
priv->box.x1, priv->base.fbo->width); \
DEBUGF("y2 %d y1 %d fbo->height %d \n", priv->box.y2, \
priv->box.y1, priv->base.fbo->height); \
_glamor_repeat_reflect_fixup(tx1, _x1_, c, odd_x, \
priv->base.pixmap->drawable.width, \
priv->box.x1, priv->box.x2); \
_glamor_repeat_reflect_fixup(ty1, _y1_, d, odd_y, \
priv->base.pixmap->drawable.height, \
priv->box.y1, priv->box.y2); \
} while(0)
#define _glamor_get_repeat_coords(priv, repeat_type, tx1, \
ty1, tx2, ty2, \
_x1_, _y1_, _x2_, \
_y2_, c, d, odd_x, odd_y) \
do { \
if (repeat_type == RepeatReflect) { \
DEBUGF("x1 y1 %d %d\n", \
_x1_, _y1_ ); \
DEBUGF("width %d box.x1 %d \n", \
(priv)->base.pixmap->drawable.width, \
priv->box.x1); \
if (odd_x) { \
c = (priv)->base.pixmap->drawable.width \
- c; \
tx1 = c - priv->box.x1; \
tx2 = tx1 - ((_x2_) - (_x1_)); \
} else { \
tx1 = c - priv->box.x1; \
tx2 = tx1 + ((_x2_) - (_x1_)); \
} \
if (odd_y){ \
d = (priv)->base.pixmap->drawable.height\
- d; \
ty1 = d - priv->box.y1; \
ty2 = ty1 - ((_y2_) - (_y1_)); \
} else { \
ty1 = d - priv->box.y1; \
ty2 = ty1 + ((_y2_) - (_y1_)); \
} \
} else { /* RepeatNormal*/ \
tx1 = (c - priv->box.x1); \
ty1 = (d - priv->box.y1); \
tx2 = tx1 + ((_x2_) - (_x1_)); \
ty2 = ty1 + ((_y2_) - (_y1_)); \
} \
} while(0)
/* _x1_ ... _y2_ may has fractional. */
#define glamor_get_repeat_transform_coords(priv, repeat_type, tx1, \
ty1, _x1_, _y1_) \
do { \
DEBUGF("width %d box.x1 %d x2 %d y1 %d y2 %d\n", \
(priv)->base.pixmap->drawable.width, \
priv->box.x1, priv->box.x2, priv->box.y1, \
priv->box.y2); \
DEBUGF("x1 %f y1 %f \n", _x1_, _y1_); \
if (repeat_type != RepeatReflect) { \
tx1 = _x1_ - priv->box.x1; \
ty1 = _y1_ - priv->box.y1; \
} else \
_glamor_get_reflect_transform_coords(priv, repeat_type, \
tx1, ty1, \
_x1_, _y1_); \
DEBUGF("tx1 %f ty1 %f \n", tx1, ty1); \
} while(0)
/* _x1_ ... _y2_ must be integer. */
#define glamor_get_repeat_coords(priv, repeat_type, tx1, \
ty1, tx2, ty2, _x1_, _y1_, _x2_, \
_y2_) \
do { \
int c, d; \
int odd_x = 0, odd_y = 0; \
DEBUGF("width %d box.x1 %d x2 %d y1 %d y2 %d\n", \
(priv)->base.pixmap->drawable.width, \
priv->box.x1, priv->box.x2, \
priv->box.y1, priv->box.y2); \
modulus((_x1_), (priv)->base.pixmap->drawable.width, c); \
modulus((_y1_), (priv)->base.pixmap->drawable.height, d); \
DEBUGF("c %d d %d \n", c, d); \
if (repeat_type == RepeatReflect) { \
odd_x = abs((_x1_ - c) \
/ (priv->base.pixmap->drawable.width)) & 1; \
odd_y = abs((_y1_ - d) \
/ (priv->base.pixmap->drawable.height)) & 1; \
} \
_glamor_get_repeat_coords(priv, repeat_type, tx1, ty1, tx2, ty2,\
_x1_, _y1_, _x2_, _y2_, c, d, \
odd_x, odd_y); \
} while(0)
#define glamor_transform_point(matrix, tx, ty, x, y) \
do { \
int _i_; \
float _result_[4]; \
for (_i_ = 0; _i_ < 3; _i_++) { \
_result_[_i_] = (matrix)[_i_ * 3] * (x) + (matrix)[_i_ * 3 + 1] * (y) \
+ (matrix)[_i_ * 3 + 2]; \
} \
tx = _result_[0] / _result_[2]; \
ty = _result_[1] / _result_[2]; \
} while(0)
#define _glamor_set_normalize_tpoint(xscale, yscale, _tx_, _ty_, \
texcoord) \
do { \
(texcoord)[0] = t_from_x_coord_x(xscale, _tx_); \
(texcoord)[1] = t_from_x_coord_y_inverted(yscale, _ty_); \
DEBUGF("normalized point tx %f ty %f \n", (texcoord)[0], \
(texcoord)[1]); \
} while(0)
#define glamor_set_transformed_point(priv, matrix, xscale, \
yscale, texcoord, \
x, y) \
do { \
float tx, ty; \
int fbo_x_off, fbo_y_off; \
pixmap_priv_get_fbo_off(priv, &fbo_x_off, &fbo_y_off); \
glamor_transform_point(matrix, tx, ty, x, y); \
DEBUGF("tx %f ty %f fbooff %d %d \n", \
tx, ty, fbo_x_off, fbo_y_off); \
\
tx += fbo_x_off; \
ty += fbo_y_off; \
(texcoord)[0] = t_from_x_coord_x(xscale, tx); \
(texcoord)[1] = t_from_x_coord_y_inverted(yscale, ty); \
DEBUGF("normalized tx %f ty %f \n", (texcoord)[0], (texcoord)[1]); \
} while(0)
#define glamor_set_transformed_normalize_tri_tcoords(priv, \
matrix, \
xscale, \
yscale, \
vtx, \
texcoords) \
do { \
glamor_set_transformed_point(priv, matrix, xscale, yscale, \
texcoords, (vtx)[0], (vtx)[1]); \
glamor_set_transformed_point(priv, matrix, xscale, yscale, \
texcoords+2, (vtx)[2], (vtx)[3]); \
glamor_set_transformed_point(priv, matrix, xscale, yscale, \
texcoords+4, (vtx)[4], (vtx)[5]); \
} while (0)
#define glamor_set_transformed_normalize_tcoords_ext( priv, \
matrix, \
xscale, \
yscale, \
tx1, ty1, tx2, ty2, \
texcoords, \
stride) \
do { \
glamor_set_transformed_point(priv, matrix, xscale, yscale, \
texcoords, tx1, ty1); \
glamor_set_transformed_point(priv, matrix, xscale, yscale, \
texcoords + 1 * stride, tx2, ty1); \
glamor_set_transformed_point(priv, matrix, xscale, yscale, \
texcoords + 2 * stride, tx2, ty2); \
glamor_set_transformed_point(priv, matrix, xscale, yscale, \
texcoords + 3 * stride, tx1, ty2); \
} while (0)
#define glamor_set_transformed_normalize_tcoords( priv, \
matrix, \
xscale, \
yscale, \
tx1, ty1, tx2, ty2, \
texcoords) \
do { \
glamor_set_transformed_normalize_tcoords_ext( priv, \
matrix, \
xscale, \
yscale, \
tx1, ty1, tx2, ty2, \
texcoords, \
2); \
} while (0)
#define glamor_set_normalize_tri_tcoords(xscale, \
yscale, \
vtx, \
texcoords) \
do { \
_glamor_set_normalize_tpoint(xscale, yscale, \
(vtx)[0], (vtx)[1], \
texcoords); \
_glamor_set_normalize_tpoint(xscale, yscale, \
(vtx)[2], (vtx)[3], \
texcoords+2); \
_glamor_set_normalize_tpoint(xscale, yscale, \
(vtx)[4], (vtx)[5], \
texcoords+4); \
} while (0)
#define glamor_set_repeat_transformed_normalize_tcoords_ext( priv, \
repeat_type, \
matrix, \
xscale, \
yscale, \
_x1_, _y1_, \
_x2_, _y2_, \
texcoords, \
stride) \
do { \
if (_X_LIKELY(priv->type != GLAMOR_TEXTURE_LARGE)) { \
glamor_set_transformed_normalize_tcoords_ext(priv, matrix, xscale, \
yscale, _x1_, _y1_, \
_x2_, _y2_, \
texcoords, stride); \
} else { \
float tx1, ty1, tx2, ty2, tx3, ty3, tx4, ty4; \
float ttx1, tty1, ttx2, tty2, ttx3, tty3, ttx4, tty4; \
DEBUGF("original coords %d %d %d %d\n", _x1_, _y1_, _x2_, _y2_); \
glamor_transform_point(matrix, tx1, ty1, _x1_, _y1_); \
glamor_transform_point(matrix, tx2, ty2, _x2_, _y1_); \
glamor_transform_point(matrix, tx3, ty3, _x2_, _y2_); \
glamor_transform_point(matrix, tx4, ty4, _x1_, _y2_); \
DEBUGF("transformed %f %f %f %f %f %f %f %f\n", \
tx1, ty1, tx2, ty2, tx3, ty3, tx4, ty4); \
glamor_get_repeat_transform_coords((&priv->large), repeat_type, \
ttx1, tty1, \
tx1, ty1); \
glamor_get_repeat_transform_coords((&priv->large), repeat_type, \
ttx2, tty2, \
tx2, ty2); \
glamor_get_repeat_transform_coords((&priv->large), repeat_type, \
ttx3, tty3, \
tx3, ty3); \
glamor_get_repeat_transform_coords((&priv->large), repeat_type, \
ttx4, tty4, \
tx4, ty4); \
DEBUGF("repeat transformed %f %f %f %f %f %f %f %f\n", ttx1, tty1, \
ttx2, tty2, ttx3, tty3, ttx4, tty4); \
_glamor_set_normalize_tpoint(xscale, yscale, ttx1, tty1, \
texcoords); \
_glamor_set_normalize_tpoint(xscale, yscale, ttx2, tty2, \
texcoords + 1 * stride); \
_glamor_set_normalize_tpoint(xscale, yscale, ttx3, tty3, \
texcoords + 2 * stride); \
_glamor_set_normalize_tpoint(xscale, yscale, ttx4, tty4, \
texcoords + 3 * stride); \
} \
} while (0)
#define glamor_set_repeat_transformed_normalize_tcoords( priv, \
repeat_type, \
matrix, \
xscale, \
yscale, \
_x1_, _y1_, \
_x2_, _y2_, \
texcoords) \
do { \
glamor_set_repeat_transformed_normalize_tcoords_ext( priv, \
repeat_type, \
matrix, \
xscale, \
yscale, \
_x1_, _y1_, \
_x2_, _y2_, \
texcoords, \
2); \
} while (0)
#define _glamor_set_normalize_tcoords(xscale, yscale, tx1, \
ty1, tx2, ty2, \
vertices, stride) \
do { \
/* vertices may be write-only, so we use following \
* temporary variable. */ \
float _t0_, _t1_, _t2_, _t5_; \
(vertices)[0] = _t0_ = t_from_x_coord_x(xscale, tx1); \
(vertices)[1 * stride] = _t2_ = t_from_x_coord_x(xscale, tx2); \
(vertices)[2 * stride] = _t2_; \
(vertices)[3 * stride] = _t0_; \
(vertices)[1] = _t1_ = t_from_x_coord_y_inverted(yscale, ty1); \
(vertices)[2 * stride + 1] = _t5_ = t_from_x_coord_y_inverted(yscale, ty2); \
(vertices)[1 * stride + 1] = _t1_; \
(vertices)[3 * stride + 1] = _t5_; \
} while(0)
#define glamor_set_normalize_tcoords_ext(priv, xscale, yscale, \
x1, y1, x2, y2, \
vertices, stride) \
do { \
if (_X_UNLIKELY(priv->type == GLAMOR_TEXTURE_LARGE)) { \
float tx1, tx2, ty1, ty2; \
int fbo_x_off, fbo_y_off; \
pixmap_priv_get_fbo_off(priv, &fbo_x_off, &fbo_y_off); \
tx1 = x1 + fbo_x_off; \
tx2 = x2 + fbo_x_off; \
ty1 = y1 + fbo_y_off; \
ty2 = y2 + fbo_y_off; \
_glamor_set_normalize_tcoords(xscale, yscale, tx1, ty1, \
tx2, ty2, vertices, \
stride); \
} else \
_glamor_set_normalize_tcoords(xscale, yscale, x1, y1, \
x2, y2, vertices, stride); \
} while(0)
#define glamor_set_normalize_tcoords(priv, xscale, yscale, \
x1, y1, x2, y2, \
vertices) \
do { \
glamor_set_normalize_tcoords_ext(priv, xscale, yscale, \
x1, y1, x2, y2, \
vertices, 2); \
} while(0)
#define glamor_set_repeat_normalize_tcoords_ext(priv, repeat_type, \
xscale, yscale, \
_x1_, _y1_, _x2_, _y2_, \
vertices, stride) \
do { \
if (_X_UNLIKELY(priv->type == GLAMOR_TEXTURE_LARGE)) { \
float tx1, tx2, ty1, ty2; \
if (repeat_type == RepeatPad) { \
tx1 = _x1_ - priv->large.box.x1; \
ty1 = _y1_ - priv->large.box.y1; \
tx2 = tx1 + ((_x2_) - (_x1_)); \
ty2 = ty1 + ((_y2_) - (_y1_)); \
} else { \
glamor_get_repeat_coords((&priv->large), repeat_type, \
tx1, ty1, tx2, ty2, \
_x1_, _y1_, _x2_, _y2_); \
} \
_glamor_set_normalize_tcoords(xscale, yscale, tx1, ty1, \
tx2, ty2, vertices, \
stride); \
} else \
_glamor_set_normalize_tcoords(xscale, yscale, _x1_, _y1_, \
_x2_, _y2_, vertices, \
stride); \
} while(0)
#define glamor_set_repeat_normalize_tcoords(priv, repeat_type, \
xscale, yscale, \
_x1_, _y1_, _x2_, _y2_, \
vertices) \
do { \
glamor_set_repeat_normalize_tcoords_ext(priv, repeat_type, \
xscale, yscale, \
_x1_, _y1_, _x2_, _y2_, \
vertices, 2); \
} while(0)
#define glamor_set_normalize_tcoords_tri_stripe(xscale, yscale, \
x1, y1, x2, y2, \
vertices) \
do { \
(vertices)[0] = t_from_x_coord_x(xscale, x1); \
(vertices)[2] = t_from_x_coord_x(xscale, x2); \
(vertices)[6] = (vertices)[2]; \
(vertices)[4] = (vertices)[0]; \
(vertices)[1] = t_from_x_coord_y_inverted(yscale, y1); \
(vertices)[7] = t_from_x_coord_y_inverted(yscale, y2); \
(vertices)[3] = (vertices)[1]; \
(vertices)[5] = (vertices)[7]; \
} while(0)
#define glamor_set_tcoords(x1, y1, x2, y2, vertices) \
do { \
(vertices)[0] = (x1); \
(vertices)[2] = (x2); \
(vertices)[4] = (vertices)[2]; \
(vertices)[6] = (vertices)[0]; \
(vertices)[1] = (y1); \
(vertices)[5] = (y2); \
(vertices)[3] = (vertices)[1]; \
(vertices)[7] = (vertices)[5]; \
} while(0)
#define glamor_set_tcoords_ext(x1, y1, x2, y2, vertices, stride) \
do { \
(vertices)[0] = (x1); \
(vertices)[1*stride] = (x2); \
(vertices)[2*stride] = (vertices)[1*stride]; \
(vertices)[3*stride] = (vertices)[0]; \
(vertices)[1] = (y1); \
(vertices)[2*stride + 1] = (y2); \
(vertices)[1*stride + 1] = (vertices)[1]; \
(vertices)[3*stride + 1] = (vertices)[2*stride + 1]; \
} while(0)
#define glamor_set_normalize_one_vcoord(xscale, yscale, x, y, \
vertices) \
do { \
(vertices)[0] = v_from_x_coord_x(xscale, x); \
(vertices)[1] = v_from_x_coord_y_inverted(yscale, y); \
} while(0)
#define glamor_set_normalize_tri_vcoords(xscale, yscale, vtx, \
vertices) \
do { \
glamor_set_normalize_one_vcoord(xscale, yscale, \
(vtx)[0], (vtx)[1], \
vertices); \
glamor_set_normalize_one_vcoord(xscale, yscale, \
(vtx)[2], (vtx)[3], \
vertices+2); \
glamor_set_normalize_one_vcoord(xscale, yscale, \
(vtx)[4], (vtx)[5], \
vertices+4); \
} while(0)
#define glamor_set_tcoords_tri_strip(x1, y1, x2, y2, vertices) \
do { \
(vertices)[0] = (x1); \
(vertices)[2] = (x2); \
(vertices)[6] = (vertices)[2]; \
(vertices)[4] = (vertices)[0]; \
(vertices)[1] = (y1); \
(vertices)[7] = (y2); \
(vertices)[3] = (vertices)[1]; \
(vertices)[5] = (vertices)[7]; \
} while(0)
#define glamor_set_normalize_vcoords_ext(priv, xscale, yscale, \
x1, y1, x2, y2, \
vertices, stride) \
do { \
int fbo_x_off, fbo_y_off; \
/* vertices may be write-only, so we use following \
* temporary variable. */ \
float _t0_, _t1_, _t2_, _t5_; \
pixmap_priv_get_fbo_off(priv, &fbo_x_off, &fbo_y_off); \
(vertices)[0] = _t0_ = v_from_x_coord_x(xscale, x1 + fbo_x_off); \
(vertices)[1 * stride] = _t2_ = v_from_x_coord_x(xscale, \
x2 + fbo_x_off); \
(vertices)[2 * stride] = _t2_; \
(vertices)[3 * stride] = _t0_; \
(vertices)[1] = _t1_ = v_from_x_coord_y_inverted(yscale, \
y1 + fbo_y_off); \
(vertices)[2 * stride + 1] = _t5_ = \
v_from_x_coord_y_inverted(yscale, \
y2 + fbo_y_off); \
(vertices)[1 * stride + 1] = _t1_; \
(vertices)[3 * stride + 1] = _t5_; \
} while(0)
#define glamor_set_normalize_vcoords(priv, xscale, yscale, \
x1, y1, x2, y2, \
vertices) \
do { \
glamor_set_normalize_vcoords_ext(priv, xscale, yscale, \
x1, y1, x2, y2, \
vertices, 2); \
} while(0)
#define glamor_set_const_ext(params, nparam, vertices, nverts, stride) \
do { \
int _i_ = 0, _j_ = 0; \
for(; _i_ < nverts; _i_++) { \
for(_j_ = 0; _j_ < nparam; _j_++) { \
vertices[stride*_i_ + _j_] = params[_j_]; \
} \
} \
} while(0)
#define glamor_set_normalize_vcoords_tri_strip(xscale, yscale, \
x1, y1, x2, y2, \
vertices) \
do { \
(vertices)[0] = v_from_x_coord_x(xscale, x1); \
(vertices)[2] = v_from_x_coord_x(xscale, x2); \
(vertices)[6] = (vertices)[2]; \
(vertices)[4] = (vertices)[0]; \
(vertices)[1] = v_from_x_coord_y_inverted(yscale, y1); \
(vertices)[7] = v_from_x_coord_y_inverted(yscale, y2); \
(vertices)[3] = (vertices)[1]; \
(vertices)[5] = (vertices)[7]; \
} while(0)
#define glamor_set_normalize_pt(xscale, yscale, x, y, \
pt) \
do { \
(pt)[0] = t_from_x_coord_x(xscale, x); \
(pt)[1] = t_from_x_coord_y_inverted(yscale, y); \
} while(0)
#define glamor_set_circle_centre(width, height, x, y, \
c) \
do { \
(c)[0] = (float)x; \
(c)[1] = (float)y; \
} while(0)
inline static void
glamor_calculate_boxes_bound(BoxPtr bound, BoxPtr boxes, int nbox)
{
int x_min, y_min;
int x_max, y_max;
int i;
x_min = y_min = MAXSHORT;
x_max = y_max = MINSHORT;
for (i = 0; i < nbox; i++) {
if (x_min > boxes[i].x1)
x_min = boxes[i].x1;
if (y_min > boxes[i].y1)
y_min = boxes[i].y1;
if (x_max < boxes[i].x2)
x_max = boxes[i].x2;
if (y_max < boxes[i].y2)
y_max = boxes[i].y2;
}
bound->x1 = x_min;
bound->y1 = y_min;
bound->x2 = x_max;
bound->y2 = y_max;
}
inline static void
glamor_translate_boxes(BoxPtr boxes, int nbox, int dx, int dy)
{
int i;
for (i = 0; i < nbox; i++) {
boxes[i].x1 += dx;
boxes[i].y1 += dy;
boxes[i].x2 += dx;
boxes[i].y2 += dy;
}
}
#ifndef ARRAY_SIZE
#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
#endif
#define ALIGN(i,m) (((i) + (m) - 1) & ~((m) - 1))
#define MIN(a,b) ((a) < (b) ? (a) : (b))
#define MAX(a,b) ((a) > (b) ? (a) : (b))
#define glamor_check_fbo_size(_glamor_,_w_, _h_) ((_w_) > 0 && (_h_) > 0 \
&& (_w_) <= _glamor_->max_fbo_size \
&& (_h_) <= _glamor_->max_fbo_size)
/* For 1bpp pixmap, we don't store it as texture. */
#define glamor_check_pixmap_fbo_depth(_depth_) ( \
_depth_ == 8 \
|| _depth_ == 15 \
|| _depth_ == 16 \
|| _depth_ == 24 \
|| _depth_ == 30 \
|| _depth_ == 32)
#define GLAMOR_PIXMAP_PRIV_IS_PICTURE(pixmap_priv) (pixmap_priv && pixmap_priv->base.is_picture == 1)
#define GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv) (pixmap_priv && pixmap_priv->base.gl_fbo == GLAMOR_FBO_NORMAL)
#define GLAMOR_PIXMAP_PRIV_HAS_FBO_DOWNLOADED(pixmap_priv) (pixmap_priv && (pixmap_priv->base.gl_fbo == GLAMOR_FBO_DOWNLOADED))
/**
* Borrow from uxa.
*/
static inline CARD32
format_for_depth(int depth)
{
switch (depth) {
case 1:
return PICT_a1;
case 4:
return PICT_a4;
case 8:
return PICT_a8;
case 15:
return PICT_x1r5g5b5;
case 16:
return PICT_r5g6b5;
default:
case 24:
return PICT_x8r8g8b8;
#if XORG_VERSION_CURRENT >= 10699900
case 30:
return PICT_x2r10g10b10;
#endif
case 32:
return PICT_a8r8g8b8;
}
}
static inline GLenum
gl_iformat_for_pixmap(PixmapPtr pixmap)
{
glamor_screen_private *glamor_priv =
glamor_get_screen_private(pixmap->drawable.pScreen);
if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP &&
(pixmap->drawable.depth == 1 || pixmap->drawable.depth == 8)) {
return GL_ALPHA;
} else {
return GL_RGBA;
}
}
static inline CARD32
format_for_pixmap(PixmapPtr pixmap)
{
glamor_pixmap_private *pixmap_priv;
PictFormatShort pict_format;
pixmap_priv = glamor_get_pixmap_private(pixmap);
if (GLAMOR_PIXMAP_PRIV_IS_PICTURE(pixmap_priv))
pict_format = pixmap_priv->base.picture->format;
else
pict_format = format_for_depth(pixmap->drawable.depth);
return pict_format;
}
#define REVERT_NONE 0
#define REVERT_NORMAL 1
#define REVERT_DOWNLOADING_A1 2
#define REVERT_UPLOADING_A1 3
#define REVERT_DOWNLOADING_2_10_10_10 4
#define REVERT_UPLOADING_2_10_10_10 5
#define REVERT_DOWNLOADING_1_5_5_5 7
#define REVERT_UPLOADING_1_5_5_5 8
#define REVERT_DOWNLOADING_10_10_10_2 9
#define REVERT_UPLOADING_10_10_10_2 10
#define SWAP_NONE_DOWNLOADING 0
#define SWAP_DOWNLOADING 1
#define SWAP_UPLOADING 2
#define SWAP_NONE_UPLOADING 3
inline static int
cache_format(GLenum format)
{
switch (format) {
case GL_ALPHA:
return 2;
case GL_RGB:
return 1;
case GL_RGBA:
return 0;
default:
return -1;
}
}
/* borrowed from uxa */
static inline Bool
glamor_get_rgba_from_pixel(CARD32 pixel,
float *red,
float *green,
float *blue, float *alpha, CARD32 format)
{
int rbits, bbits, gbits, abits;
int rshift, bshift, gshift, ashift;
rbits = PICT_FORMAT_R(format);
gbits = PICT_FORMAT_G(format);
bbits = PICT_FORMAT_B(format);
abits = PICT_FORMAT_A(format);
if (PICT_FORMAT_TYPE(format) == PICT_TYPE_A) {
rshift = gshift = bshift = ashift = 0;
}
else if (PICT_FORMAT_TYPE(format) == PICT_TYPE_ARGB) {
bshift = 0;
gshift = bbits;
rshift = gshift + gbits;
ashift = rshift + rbits;
}
else if (PICT_FORMAT_TYPE(format) == PICT_TYPE_ABGR) {
rshift = 0;
gshift = rbits;
bshift = gshift + gbits;
ashift = bshift + bbits;
#if XORG_VERSION_CURRENT >= 10699900
}
else if (PICT_FORMAT_TYPE(format) == PICT_TYPE_BGRA) {
ashift = 0;
rshift = abits;
if (abits == 0)
rshift = PICT_FORMAT_BPP(format) - (rbits + gbits + bbits);
gshift = rshift + rbits;
bshift = gshift + gbits;
#endif
}
else {
return FALSE;
}
#define COLOR_INT_TO_FLOAT(_fc_, _p_, _s_, _bits_) \
*_fc_ = (((_p_) >> (_s_)) & (( 1 << (_bits_)) - 1)) \
/ (float)((1<<(_bits_)) - 1)
if (rbits)
COLOR_INT_TO_FLOAT(red, pixel, rshift, rbits);
else
*red = 0;
if (gbits)
COLOR_INT_TO_FLOAT(green, pixel, gshift, gbits);
else
*green = 0;
if (bbits)
COLOR_INT_TO_FLOAT(blue, pixel, bshift, bbits);
else
*blue = 0;
if (abits)
COLOR_INT_TO_FLOAT(alpha, pixel, ashift, abits);
else
*alpha = 1;
return TRUE;
}
inline static Bool
glamor_pict_format_is_compatible(PicturePtr picture)
{
GLenum iformat;
PixmapPtr pixmap = glamor_get_drawable_pixmap(picture->pDrawable);
iformat = gl_iformat_for_pixmap(pixmap);
switch (iformat) {
case GL_RGBA:
return (picture->format == PICT_a8r8g8b8 ||
picture->format == PICT_x8r8g8b8);
case GL_ALPHA:
return (picture->format == PICT_a8);
default:
return FALSE;
}
}
/* return TRUE if we can access this pixmap at DDX driver. */
inline static Bool
glamor_ddx_fallback_check_pixmap(DrawablePtr drawable)
{
PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable);
glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap);
return (!pixmap_priv
|| (pixmap_priv->type == GLAMOR_TEXTURE_DRM
|| pixmap_priv->type == GLAMOR_MEMORY
|| pixmap_priv->type == GLAMOR_DRM_ONLY));
}
inline static Bool
glamor_ddx_fallback_check_gc(GCPtr gc)
{
PixmapPtr pixmap;
if (!gc)
return TRUE;
switch (gc->fillStyle) {
case FillStippled:
case FillOpaqueStippled:
pixmap = gc->stipple;
break;
case FillTiled:
pixmap = gc->tile.pixmap;
break;
default:
pixmap = NULL;
}
return (!pixmap || glamor_ddx_fallback_check_pixmap(&pixmap->drawable));
}
inline static Bool
glamor_is_large_pixmap(PixmapPtr pixmap)
{
glamor_pixmap_private *priv;
priv = glamor_get_pixmap_private(pixmap);
return (priv->type == GLAMOR_TEXTURE_LARGE);
}
inline static Bool
glamor_is_large_picture(PicturePtr picture)
{
PixmapPtr pixmap;
if (picture->pDrawable) {
pixmap = glamor_get_drawable_pixmap(picture->pDrawable);
return glamor_is_large_pixmap(pixmap);
}
return FALSE;
}
inline static Bool
glamor_tex_format_is_readable(GLenum format)
{
return ((format == GL_RGBA || format == GL_RGB || format == GL_ALPHA));
}
static inline void
_glamor_dump_pixmap_bits(PixmapPtr pixmap, int x, int y, int w, int h)
{
int i, j;
unsigned char *p = pixmap->devPrivate.ptr;
int stride = pixmap->devKind;
p = p + y * stride + x;
for (i = 0; i < h; i++) {
ErrorF("line %3d: ", i);
for (j = 0; j < w; j++)
ErrorF("%2d ", (p[j / 8] & (1 << (j % 8))) >> (j % 8));
p += stride;
ErrorF("\n");
}
}
static inline void
_glamor_dump_pixmap_byte(PixmapPtr pixmap, int x, int y, int w, int h)
{
int i, j;
unsigned char *p = pixmap->devPrivate.ptr;
int stride = pixmap->devKind;
p = p + y * stride + x;
for (i = 0; i < h; i++) {
ErrorF("line %3d: ", i);
for (j = 0; j < w; j++)
ErrorF("%2x ", p[j]);
p += stride;
ErrorF("\n");
}
}
static inline void
_glamor_dump_pixmap_sword(PixmapPtr pixmap, int x, int y, int w, int h)
{
int i, j;
unsigned short *p = pixmap->devPrivate.ptr;
int stride = pixmap->devKind / 2;
p = p + y * stride + x;
for (i = 0; i < h; i++) {
ErrorF("line %3d: ", i);
for (j = 0; j < w; j++)
ErrorF("%2x ", p[j]);
p += stride;
ErrorF("\n");
}
}
static inline void
_glamor_dump_pixmap_word(PixmapPtr pixmap, int x, int y, int w, int h)
{
int i, j;
unsigned int *p = pixmap->devPrivate.ptr;
int stride = pixmap->devKind / 4;
p = p + y * stride + x;
for (i = 0; i < h; i++) {
ErrorF("line %3d: ", i);
for (j = 0; j < w; j++)
ErrorF("%2x ", p[j]);
p += stride;
ErrorF("\n");
}
}
static inline void
glamor_dump_pixmap(PixmapPtr pixmap, int x, int y, int w, int h)
{
w = ((x + w) > pixmap->drawable.width) ? (pixmap->drawable.width - x) : w;
h = ((y + h) > pixmap->drawable.height) ? (pixmap->drawable.height - y) : h;
glamor_prepare_access(&pixmap->drawable, GLAMOR_ACCESS_RO);
switch (pixmap->drawable.depth) {
case 8:
_glamor_dump_pixmap_byte(pixmap, x, y, w, h);
break;
case 15:
case 16:
_glamor_dump_pixmap_sword(pixmap, x, y, w, h);
break;
case 24:
case 32:
_glamor_dump_pixmap_word(pixmap, x, y, w, h);
break;
case 1:
_glamor_dump_pixmap_bits(pixmap, x, y, w, h);
break;
default:
ErrorF("dump depth %d, not implemented.\n", pixmap->drawable.depth);
}
glamor_finish_access(&pixmap->drawable);
}
static inline void
_glamor_compare_pixmaps(PixmapPtr pixmap1, PixmapPtr pixmap2,
int x, int y, int w, int h,
PictFormatShort short_format, int all, int diffs)
{
int i, j;
unsigned char *p1 = pixmap1->devPrivate.ptr;
unsigned char *p2 = pixmap2->devPrivate.ptr;
int line_need_printed = 0;
int test_code = 0xAABBCCDD;
int little_endian = 0;
unsigned char *p_test;
int bpp = pixmap1->drawable.depth == 8 ? 1 : 4;
int stride = pixmap1->devKind;
assert(pixmap1->devKind == pixmap2->devKind);
ErrorF("stride:%d, width:%d, height:%d\n", stride, w, h);
p1 = p1 + y * stride + x;
p2 = p2 + y * stride + x;
if (all) {
for (i = 0; i < h; i++) {
ErrorF("line %3d: ", i);
for (j = 0; j < stride; j++) {
if (j % bpp == 0)
ErrorF("[%d]%2x:%2x ", j / bpp, p1[j], p2[j]);
else
ErrorF("%2x:%2x ", p1[j], p2[j]);
}
p1 += stride;
p2 += stride;
ErrorF("\n");
}
}
else {
if (short_format == PICT_a8r8g8b8) {
p_test = (unsigned char *) &test_code;
little_endian = (*p_test == 0xDD);
bpp = 4;
for (i = 0; i < h; i++) {
line_need_printed = 0;
for (j = 0; j < stride; j++) {
if (p1[j] != p2[j] &&
(p1[j] - p2[j] > diffs || p2[j] - p1[j] > diffs)) {
if (line_need_printed) {
if (little_endian) {
switch (j % 4) {
case 2:
ErrorF("[%d]RED:%2x:%2x ", j / bpp, p1[j],
p2[j]);
break;
case 1:
ErrorF("[%d]GREEN:%2x:%2x ", j / bpp, p1[j],
p2[j]);
break;
case 0:
ErrorF("[%d]BLUE:%2x:%2x ", j / bpp, p1[j],
p2[j]);
break;
case 3:
ErrorF("[%d]Alpha:%2x:%2x ", j / bpp, p1[j],
p2[j]);
break;
}
}
else {
switch (j % 4) {
case 1:
ErrorF("[%d]RED:%2x:%2x ", j / bpp, p1[j],
p2[j]);
break;
case 2:
ErrorF("[%d]GREEN:%2x:%2x ", j / bpp, p1[j],
p2[j]);
break;
case 3:
ErrorF("[%d]BLUE:%2x:%2x ", j / bpp, p1[j],
p2[j]);
break;
case 0:
ErrorF("[%d]Alpha:%2x:%2x ", j / bpp, p1[j],
p2[j]);
break;
}
}
}
else {
line_need_printed = 1;
j = -1;
ErrorF("line %3d: ", i);
continue;
}
}
}
p1 += stride;
p2 += stride;
ErrorF("\n");
}
} //more format can be added here.
else { // the default format, just print.
for (i = 0; i < h; i++) {
line_need_printed = 0;
for (j = 0; j < stride; j++) {
if (p1[j] != p2[j]) {
if (line_need_printed) {
ErrorF("[%d]%2x:%2x ", j / bpp, p1[j], p2[j]);
}
else {
line_need_printed = 1;
j = -1;
ErrorF("line %3d: ", i);
continue;
}
}
}
p1 += stride;
p2 += stride;
ErrorF("\n");
}
}
}
}
static inline void
glamor_compare_pixmaps(PixmapPtr pixmap1, PixmapPtr pixmap2,
int x, int y, int w, int h, int all, int diffs)
{
assert(pixmap1->drawable.depth == pixmap2->drawable.depth);
if (glamor_prepare_access(&pixmap1->drawable, GLAMOR_ACCESS_RO) &&
glamor_prepare_access(&pixmap2->drawable, GLAMOR_ACCESS_RO)) {
_glamor_compare_pixmaps(pixmap1, pixmap2, x, y, w, h, -1, all, diffs);
}
glamor_finish_access(&pixmap1->drawable);
glamor_finish_access(&pixmap2->drawable);
}
/* This function is used to compare two pictures.
If the picture has no drawable, we use fb functions to generate it. */
static inline void
glamor_compare_pictures(ScreenPtr screen,
PicturePtr fst_picture,
PicturePtr snd_picture,
int x_source, int y_source,
int width, int height, int all, int diffs)
{
PixmapPtr fst_pixmap;
PixmapPtr snd_pixmap;
int fst_generated, snd_generated;
int error;
int fst_type = -1;
int snd_type = -1; // -1 represent has drawable.
if (fst_picture->format != snd_picture->format) {
ErrorF("Different picture format can not compare!\n");
return;
}
if (!fst_picture->pDrawable) {
fst_type = fst_picture->pSourcePict->type;
}
if (!snd_picture->pDrawable) {
snd_type = snd_picture->pSourcePict->type;
}
if ((fst_type != -1) && (snd_type != -1) && (fst_type != snd_type)) {
ErrorF("Different picture type will never be same!\n");
return;
}
fst_generated = snd_generated = 0;
if (!fst_picture->pDrawable) {
PicturePtr pixman_pic;
PixmapPtr pixmap = NULL;
PictFormatShort format;
format = fst_picture->format;
pixmap = glamor_create_pixmap(screen,
width, height,
PIXMAN_FORMAT_DEPTH(format),
GLAMOR_CREATE_PIXMAP_CPU);
pixman_pic = CreatePicture(0,
&pixmap->drawable,
PictureMatchFormat(screen,
PIXMAN_FORMAT_DEPTH
(format), format), 0, 0,
serverClient, &error);
fbComposite(PictOpSrc, fst_picture, NULL, pixman_pic,
x_source, y_source, 0, 0, 0, 0, width, height);
glamor_destroy_pixmap(pixmap);
fst_picture = pixman_pic;
fst_generated = 1;
}
if (!snd_picture->pDrawable) {
PicturePtr pixman_pic;
PixmapPtr pixmap = NULL;
PictFormatShort format;
format = snd_picture->format;
pixmap = glamor_create_pixmap(screen,
width, height,
PIXMAN_FORMAT_DEPTH(format),
GLAMOR_CREATE_PIXMAP_CPU);
pixman_pic = CreatePicture(0,
&pixmap->drawable,
PictureMatchFormat(screen,
PIXMAN_FORMAT_DEPTH
(format), format), 0, 0,
serverClient, &error);
fbComposite(PictOpSrc, snd_picture, NULL, pixman_pic,
x_source, y_source, 0, 0, 0, 0, width, height);
glamor_destroy_pixmap(pixmap);
snd_picture = pixman_pic;
snd_generated = 1;
}
fst_pixmap = glamor_get_drawable_pixmap(fst_picture->pDrawable);
snd_pixmap = glamor_get_drawable_pixmap(snd_picture->pDrawable);
if (fst_pixmap->drawable.depth != snd_pixmap->drawable.depth) {
if (fst_generated)
glamor_destroy_picture(fst_picture);
if (snd_generated)
glamor_destroy_picture(snd_picture);
ErrorF("Different pixmap depth can not compare!\n");
return;
}
if ((fst_type == SourcePictTypeLinear) ||
(fst_type == SourcePictTypeRadial) ||
(fst_type == SourcePictTypeConical) ||
(snd_type == SourcePictTypeLinear) ||
(snd_type == SourcePictTypeRadial) ||
(snd_type == SourcePictTypeConical)) {
x_source = y_source = 0;
}
if (glamor_prepare_access(&fst_pixmap->drawable, GLAMOR_ACCESS_RO) &&
glamor_prepare_access(&snd_pixmap->drawable, GLAMOR_ACCESS_RO)) {
_glamor_compare_pixmaps(fst_pixmap, snd_pixmap,
x_source, y_source,
width, height, fst_picture->format,
all, diffs);
}
glamor_finish_access(&fst_pixmap->drawable);
glamor_finish_access(&snd_pixmap->drawable);
if (fst_generated)
glamor_destroy_picture(fst_picture);
if (snd_generated)
glamor_destroy_picture(snd_picture);
return;
}
#ifdef __i386__
static inline unsigned long
__fls(unsigned long x)
{
asm("bsr %1,%0":"=r"(x)
: "rm"(x));
return x;
}
#else
static inline unsigned long
__fls(unsigned long x)
{
int n;
if (x == 0)
return (0);
n = 0;
if (x <= 0x0000FFFF) {
n = n + 16;
x = x << 16;
}
if (x <= 0x00FFFFFF) {
n = n + 8;
x = x << 8;
}
if (x <= 0x0FFFFFFF) {
n = n + 4;
x = x << 4;
}
if (x <= 0x3FFFFFFF) {
n = n + 2;
x = x << 2;
}
if (x <= 0x7FFFFFFF) {
n = n + 1;
}
return 31 - n;
}
#endif
static inline void
glamor_make_current(glamor_screen_private *glamor_priv)
{
if (lastGLContext != &glamor_priv->ctx) {
lastGLContext = &glamor_priv->ctx;
glamor_priv->ctx.make_current(&glamor_priv->ctx);
}
}
#endif