1/*
2 * Copyright (C) 2009 Francisco Jerez.
3 * All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining
6 * a copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sublicense, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial
15 * portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20 * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
21 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 *
25 */
26
27#ifndef __NOUVEAU_UTIL_H__
28#define __NOUVEAU_UTIL_H__
29
30#include "main/formats.h"
31#include "main/colormac.h"
32
33static inline unsigned
34pack_rgba_i(gl_format f, uint8_t c[])
35{
36	switch (f) {
37	case MESA_FORMAT_ARGB8888:
38		return PACK_COLOR_8888(c[ACOMP], c[RCOMP], c[GCOMP], c[BCOMP]);
39	case MESA_FORMAT_ARGB8888_REV:
40		return PACK_COLOR_8888(c[BCOMP], c[GCOMP], c[RCOMP], c[ACOMP]);
41	case MESA_FORMAT_XRGB8888:
42		return PACK_COLOR_8888(0, c[RCOMP], c[GCOMP], c[BCOMP]);
43	case MESA_FORMAT_XRGB8888_REV:
44		return PACK_COLOR_8888(c[BCOMP], c[GCOMP], c[RCOMP], 0);
45	case MESA_FORMAT_RGBA8888:
46		return PACK_COLOR_8888(c[RCOMP], c[GCOMP], c[BCOMP], c[ACOMP]);
47	case MESA_FORMAT_RGBA8888_REV:
48		return PACK_COLOR_8888(c[ACOMP], c[BCOMP], c[GCOMP], c[RCOMP]);
49	case MESA_FORMAT_RGB565:
50		return PACK_COLOR_565(c[RCOMP], c[GCOMP], c[BCOMP]);
51	default:
52		assert(0);
53	}
54}
55
56static inline unsigned
57pack_zs_i(gl_format f, uint32_t z, uint8_t s)
58{
59	switch (f) {
60	case MESA_FORMAT_Z24_S8:
61		return (z & 0xffffff00) | (s & 0xff);
62	case MESA_FORMAT_Z24_X8:
63		return (z & 0xffffff00);
64	case MESA_FORMAT_Z16:
65		return (z & 0xffff0000) >> 16;
66	default:
67		assert(0);
68	}
69}
70
71static inline unsigned
72pack_rgba_f(gl_format f, float c[])
73{
74	return pack_rgba_i(f, (uint8_t []) {
75			   FLOAT_TO_UBYTE(c[RCOMP]),
76			   FLOAT_TO_UBYTE(c[GCOMP]),
77			   FLOAT_TO_UBYTE(c[BCOMP]),
78			   FLOAT_TO_UBYTE(c[ACOMP]) });
79}
80
81static inline unsigned
82pack_rgba_clamp_f(gl_format f, float c[])
83{
84	GLubyte bytes[4];
85	_mesa_unclamped_float_rgba_to_ubyte(bytes, c);
86	return pack_rgba_i(f, bytes);
87}
88
89static inline unsigned
90pack_zs_f(gl_format f, float z, uint8_t s)
91{
92	return pack_zs_i(f, FLOAT_TO_UINT(z), s);
93}
94
95/* Integer base-2 logarithm, rounded towards zero. */
96static inline unsigned
97log2i(unsigned i)
98{
99	unsigned r = 0;
100
101	if (i & 0xffff0000) {
102		i >>= 16;
103		r += 16;
104	}
105	if (i & 0x0000ff00) {
106		i >>= 8;
107		r += 8;
108	}
109	if (i & 0x000000f0) {
110		i >>= 4;
111		r += 4;
112	}
113	if (i & 0x0000000c) {
114		i >>= 2;
115		r += 2;
116	}
117	if (i & 0x00000002) {
118		r += 1;
119	}
120	return r;
121}
122
123static inline unsigned
124align(unsigned x, unsigned m)
125{
126	return (x + m - 1) & ~(m - 1);
127}
128
129static inline void
130get_scissors(struct gl_framebuffer *fb, int *x, int *y, int *w, int *h)
131{
132	*w = fb->_Xmax - fb->_Xmin;
133	*h = fb->_Ymax - fb->_Ymin;
134	*x = fb->_Xmin;
135	*y = (fb->Name ? fb->_Ymin :
136	      /* Window system FBO: Flip the Y coordinate. */
137	      fb->Height - fb->_Ymax);
138}
139
140static inline void
141get_viewport_scale(struct gl_context *ctx, float a[16])
142{
143	struct gl_viewport_attrib *vp = &ctx->Viewport;
144	struct gl_framebuffer *fb = ctx->DrawBuffer;
145
146	a[MAT_SX] = (float)vp->Width / 2;
147
148	if (fb->Name)
149		a[MAT_SY] = (float)vp->Height / 2;
150	else
151		/* Window system FBO: Flip the Y coordinate. */
152		a[MAT_SY] = - (float)vp->Height / 2;
153
154	a[MAT_SZ] = fb->_DepthMaxF * (vp->Far - vp->Near) / 2;
155}
156
157static inline void
158get_viewport_translate(struct gl_context *ctx, float a[4])
159{
160	struct gl_viewport_attrib *vp = &ctx->Viewport;
161	struct gl_framebuffer *fb = ctx->DrawBuffer;
162
163	a[0] = (float)vp->Width / 2 + vp->X;
164
165	if (fb->Name)
166		a[1] = (float)vp->Height / 2 + vp->Y;
167	else
168		/* Window system FBO: Flip the Y coordinate. */
169		a[1] = fb->Height - (float)vp->Height / 2 - vp->Y;
170
171	a[2] = fb->_DepthMaxF * (vp->Far + vp->Near) / 2;
172}
173
174static inline GLboolean
175is_color_operand(int op)
176{
177	return op == GL_SRC_COLOR || op == GL_ONE_MINUS_SRC_COLOR;
178}
179
180static inline GLboolean
181is_negative_operand(int op)
182{
183	return op == GL_ONE_MINUS_SRC_COLOR || op == GL_ONE_MINUS_SRC_ALPHA;
184}
185
186static inline GLboolean
187is_texture_source(int s)
188{
189	return s == GL_TEXTURE || (s >= GL_TEXTURE0 && s <= GL_TEXTURE31);
190}
191
192static inline struct gl_texgen *
193get_texgen_coord(struct gl_texture_unit *u, int i)
194{
195	return ((struct gl_texgen *[])
196		{ &u->GenS, &u->GenT, &u->GenR, &u->GenQ }) [i];
197}
198
199static inline float *
200get_texgen_coeff(struct gl_texgen *c)
201{
202	if (c->Mode == GL_OBJECT_LINEAR)
203		return c->ObjectPlane;
204	else if (c->Mode == GL_EYE_LINEAR)
205		return c->EyePlane;
206	else
207		return NULL;
208}
209
210static inline unsigned
211get_format_blocksx(gl_format format,
212		       unsigned x)
213{
214	GLuint blockwidth;
215	GLuint blockheight;
216	_mesa_get_format_block_size(format, &blockwidth, &blockheight);
217	return (x + blockwidth - 1) / blockwidth;
218}
219
220static inline unsigned
221get_format_blocksy(gl_format format,
222		       unsigned y)
223{
224	GLuint blockwidth;
225	GLuint blockheight;
226	_mesa_get_format_block_size(format, &blockwidth, &blockheight);
227	return (y + blockheight - 1) / blockheight;
228}
229
230#endif
231