1bf215546Sopenharmony_ci/**********************************************************
2bf215546Sopenharmony_ci * Copyright 2009-2011 VMware, Inc. All rights reserved.
3bf215546Sopenharmony_ci *
4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person
5bf215546Sopenharmony_ci * obtaining a copy of this software and associated documentation
6bf215546Sopenharmony_ci * files (the "Software"), to deal in the Software without
7bf215546Sopenharmony_ci * restriction, including without limitation the rights to use, copy,
8bf215546Sopenharmony_ci * modify, merge, publish, distribute, sublicense, and/or sell copies
9bf215546Sopenharmony_ci * of the Software, and to permit persons to whom the Software is
10bf215546Sopenharmony_ci * furnished to do so, subject to the following conditions:
11bf215546Sopenharmony_ci *
12bf215546Sopenharmony_ci * The above copyright notice and this permission notice shall be
13bf215546Sopenharmony_ci * included in all copies or substantial portions of the Software.
14bf215546Sopenharmony_ci *
15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16bf215546Sopenharmony_ci * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17bf215546Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18bf215546Sopenharmony_ci * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19bf215546Sopenharmony_ci * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20bf215546Sopenharmony_ci * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21bf215546Sopenharmony_ci * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22bf215546Sopenharmony_ci * SOFTWARE.
23bf215546Sopenharmony_ci *
24bf215546Sopenharmony_ci *********************************************************
25bf215546Sopenharmony_ci * Authors:
26bf215546Sopenharmony_ci * Zack Rusin <zackr-at-vmware-dot-com>
27bf215546Sopenharmony_ci */
28bf215546Sopenharmony_ci#include "xa_priv.h"
29bf215546Sopenharmony_ci
30bf215546Sopenharmony_ci#include "pipe/p_format.h"
31bf215546Sopenharmony_ci#include "pipe/p_context.h"
32bf215546Sopenharmony_ci#include "pipe/p_state.h"
33bf215546Sopenharmony_ci#include "pipe/p_shader_tokens.h"
34bf215546Sopenharmony_ci
35bf215546Sopenharmony_ci#include "util/u_memory.h"
36bf215546Sopenharmony_ci
37bf215546Sopenharmony_ci#include "tgsi/tgsi_ureg.h"
38bf215546Sopenharmony_ci
39bf215546Sopenharmony_ci#include "cso_cache/cso_context.h"
40bf215546Sopenharmony_ci#include "cso_cache/cso_hash.h"
41bf215546Sopenharmony_ci
42bf215546Sopenharmony_ci/* Vertex shader:
43bf215546Sopenharmony_ci * IN[0]    = vertex pos
44bf215546Sopenharmony_ci * IN[1]    = src tex coord | solid fill color
45bf215546Sopenharmony_ci * IN[2]    = mask tex coord
46bf215546Sopenharmony_ci * IN[3]    = dst tex coord
47bf215546Sopenharmony_ci * CONST[0] = (2/dst_width, 2/dst_height, 1, 1)
48bf215546Sopenharmony_ci * CONST[1] = (-1, -1, 0, 0)
49bf215546Sopenharmony_ci *
50bf215546Sopenharmony_ci * OUT[0]   = vertex pos
51bf215546Sopenharmony_ci * OUT[1]   = src tex coord
52bf215546Sopenharmony_ci * OUT[2]   = mask tex coord
53bf215546Sopenharmony_ci * OUT[3]   = dst tex coord
54bf215546Sopenharmony_ci */
55bf215546Sopenharmony_ci
56bf215546Sopenharmony_ci/* Fragment shader. Samplers are allocated when needed.
57bf215546Sopenharmony_ci * SAMP[0]  = sampler for first texture (src or mask if src is solid)
58bf215546Sopenharmony_ci * SAMP[1]  = sampler for second texture (mask or none)
59bf215546Sopenharmony_ci * IN[0]    = first texture coordinates if present
60bf215546Sopenharmony_ci * IN[1]    = second texture coordinates if present
61bf215546Sopenharmony_ci * CONST[0] = Solid color (src if src solid or mask if mask solid
62bf215546Sopenharmony_ci *            or src in mask if both solid).
63bf215546Sopenharmony_ci *
64bf215546Sopenharmony_ci * OUT[0] = color
65bf215546Sopenharmony_ci */
66bf215546Sopenharmony_ci
67bf215546Sopenharmony_cistatic void
68bf215546Sopenharmony_ciprint_fs_traits(int fs_traits)
69bf215546Sopenharmony_ci{
70bf215546Sopenharmony_ci    const char *strings[] = {
71bf215546Sopenharmony_ci	"FS_COMPOSITE",		/* = 1 << 0, */
72bf215546Sopenharmony_ci	"FS_MASK",		/* = 1 << 1, */
73bf215546Sopenharmony_ci	"FS_SRC_SRC",	        /* = 1 << 2, */
74bf215546Sopenharmony_ci	"FS_MASK_SRC",	        /* = 1 << 3, */
75bf215546Sopenharmony_ci	"FS_YUV",	        /* = 1 << 4, */
76bf215546Sopenharmony_ci	"FS_SRC_REPEAT_NONE",	/* = 1 << 5, */
77bf215546Sopenharmony_ci	"FS_MASK_REPEAT_NONE",	/* = 1 << 6, */
78bf215546Sopenharmony_ci	"FS_SRC_SWIZZLE_RGB",	/* = 1 << 7, */
79bf215546Sopenharmony_ci	"FS_MASK_SWIZZLE_RGB",	/* = 1 << 8, */
80bf215546Sopenharmony_ci	"FS_SRC_SET_ALPHA",	/* = 1 << 9, */
81bf215546Sopenharmony_ci	"FS_MASK_SET_ALPHA",	/* = 1 << 10, */
82bf215546Sopenharmony_ci	"FS_SRC_LUMINANCE",	/* = 1 << 11, */
83bf215546Sopenharmony_ci	"FS_MASK_LUMINANCE",	/* = 1 << 12, */
84bf215546Sopenharmony_ci	"FS_DST_LUMINANCE",     /* = 1 << 13, */
85bf215546Sopenharmony_ci        "FS_CA",                /* = 1 << 14, */
86bf215546Sopenharmony_ci    };
87bf215546Sopenharmony_ci    int i, k;
88bf215546Sopenharmony_ci
89bf215546Sopenharmony_ci    debug_printf("%s: ", __func__);
90bf215546Sopenharmony_ci
91bf215546Sopenharmony_ci    for (i = 0, k = 1; k < (1 << 16); i++, k <<= 1) {
92bf215546Sopenharmony_ci	if (fs_traits & k)
93bf215546Sopenharmony_ci	    debug_printf("%s, ", strings[i]);
94bf215546Sopenharmony_ci    }
95bf215546Sopenharmony_ci
96bf215546Sopenharmony_ci    debug_printf("\n");
97bf215546Sopenharmony_ci}
98bf215546Sopenharmony_ci
99bf215546Sopenharmony_cistruct xa_shaders {
100bf215546Sopenharmony_ci    struct xa_context *r;
101bf215546Sopenharmony_ci
102bf215546Sopenharmony_ci    struct cso_hash vs_hash;
103bf215546Sopenharmony_ci    struct cso_hash fs_hash;
104bf215546Sopenharmony_ci};
105bf215546Sopenharmony_ci
106bf215546Sopenharmony_cistatic inline void
107bf215546Sopenharmony_cisrc_in_mask(struct ureg_program *ureg,
108bf215546Sopenharmony_ci	    struct ureg_dst dst,
109bf215546Sopenharmony_ci	    struct ureg_src src,
110bf215546Sopenharmony_ci	    struct ureg_src mask,
111bf215546Sopenharmony_ci	    unsigned mask_luminance, boolean component_alpha)
112bf215546Sopenharmony_ci{
113bf215546Sopenharmony_ci    if (mask_luminance)
114bf215546Sopenharmony_ci        if (component_alpha) {
115bf215546Sopenharmony_ci            ureg_MOV(ureg, dst, src);
116bf215546Sopenharmony_ci            ureg_MUL(ureg, ureg_writemask(dst, TGSI_WRITEMASK_W),
117bf215546Sopenharmony_ci                     src, ureg_scalar(mask, TGSI_SWIZZLE_X));
118bf215546Sopenharmony_ci        } else {
119bf215546Sopenharmony_ci            ureg_MUL(ureg, dst, src, ureg_scalar(mask, TGSI_SWIZZLE_X));
120bf215546Sopenharmony_ci        }
121bf215546Sopenharmony_ci    else if (!component_alpha)
122bf215546Sopenharmony_ci        ureg_MUL(ureg, dst, src, ureg_scalar(mask, TGSI_SWIZZLE_W));
123bf215546Sopenharmony_ci    else
124bf215546Sopenharmony_ci        ureg_MUL(ureg, dst, src, mask);
125bf215546Sopenharmony_ci}
126bf215546Sopenharmony_ci
127bf215546Sopenharmony_cistatic struct ureg_src
128bf215546Sopenharmony_civs_normalize_coords(struct ureg_program *ureg,
129bf215546Sopenharmony_ci		    struct ureg_src coords,
130bf215546Sopenharmony_ci		    struct ureg_src const0, struct ureg_src const1)
131bf215546Sopenharmony_ci{
132bf215546Sopenharmony_ci    struct ureg_dst tmp = ureg_DECL_temporary(ureg);
133bf215546Sopenharmony_ci    struct ureg_src ret;
134bf215546Sopenharmony_ci
135bf215546Sopenharmony_ci    ureg_MAD(ureg, tmp, coords, const0, const1);
136bf215546Sopenharmony_ci    ret = ureg_src(tmp);
137bf215546Sopenharmony_ci    ureg_release_temporary(ureg, tmp);
138bf215546Sopenharmony_ci    return ret;
139bf215546Sopenharmony_ci}
140bf215546Sopenharmony_ci
141bf215546Sopenharmony_cistatic void *
142bf215546Sopenharmony_cicreate_vs(struct pipe_context *pipe, unsigned vs_traits)
143bf215546Sopenharmony_ci{
144bf215546Sopenharmony_ci    struct ureg_program *ureg;
145bf215546Sopenharmony_ci    struct ureg_src src;
146bf215546Sopenharmony_ci    struct ureg_dst dst;
147bf215546Sopenharmony_ci    struct ureg_src const0, const1;
148bf215546Sopenharmony_ci    boolean is_composite = (vs_traits & VS_COMPOSITE) != 0;
149bf215546Sopenharmony_ci    boolean has_mask = (vs_traits & VS_MASK) != 0;
150bf215546Sopenharmony_ci    boolean is_yuv = (vs_traits & VS_YUV) != 0;
151bf215546Sopenharmony_ci    boolean is_src_src = (vs_traits & VS_SRC_SRC) != 0;
152bf215546Sopenharmony_ci    boolean is_mask_src = (vs_traits & VS_MASK_SRC) != 0;
153bf215546Sopenharmony_ci    unsigned input_slot = 0;
154bf215546Sopenharmony_ci
155bf215546Sopenharmony_ci    ureg = ureg_create(PIPE_SHADER_VERTEX);
156bf215546Sopenharmony_ci    if (ureg == NULL)
157bf215546Sopenharmony_ci	return NULL;
158bf215546Sopenharmony_ci
159bf215546Sopenharmony_ci    const0 = ureg_DECL_constant(ureg, 0);
160bf215546Sopenharmony_ci    const1 = ureg_DECL_constant(ureg, 1);
161bf215546Sopenharmony_ci
162bf215546Sopenharmony_ci    /* it has to be either a fill or a composite op */
163bf215546Sopenharmony_ci    src = ureg_DECL_vs_input(ureg, input_slot++);
164bf215546Sopenharmony_ci    dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_POSITION, 0);
165bf215546Sopenharmony_ci    src = vs_normalize_coords(ureg, src, const0, const1);
166bf215546Sopenharmony_ci    ureg_MOV(ureg, dst, src);
167bf215546Sopenharmony_ci
168bf215546Sopenharmony_ci    if (is_yuv) {
169bf215546Sopenharmony_ci	src = ureg_DECL_vs_input(ureg, input_slot++);
170bf215546Sopenharmony_ci	dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_GENERIC, 0);
171bf215546Sopenharmony_ci	ureg_MOV(ureg, dst, src);
172bf215546Sopenharmony_ci    }
173bf215546Sopenharmony_ci
174bf215546Sopenharmony_ci    if (is_composite) {
175bf215546Sopenharmony_ci        if (!is_src_src || (has_mask && !is_mask_src)) {
176bf215546Sopenharmony_ci            src = ureg_DECL_vs_input(ureg, input_slot++);
177bf215546Sopenharmony_ci            dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_GENERIC, 0);
178bf215546Sopenharmony_ci            ureg_MOV(ureg, dst, src);
179bf215546Sopenharmony_ci        }
180bf215546Sopenharmony_ci
181bf215546Sopenharmony_ci        if (!is_src_src && (has_mask && !is_mask_src)) {
182bf215546Sopenharmony_ci            src = ureg_DECL_vs_input(ureg, input_slot++);
183bf215546Sopenharmony_ci            dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_GENERIC, 1);
184bf215546Sopenharmony_ci            ureg_MOV(ureg, dst, src);
185bf215546Sopenharmony_ci        }
186bf215546Sopenharmony_ci    }
187bf215546Sopenharmony_ci
188bf215546Sopenharmony_ci    ureg_END(ureg);
189bf215546Sopenharmony_ci
190bf215546Sopenharmony_ci    return ureg_create_shader_and_destroy(ureg, pipe);
191bf215546Sopenharmony_ci}
192bf215546Sopenharmony_ci
193bf215546Sopenharmony_cistatic void *
194bf215546Sopenharmony_cicreate_yuv_shader(struct pipe_context *pipe, struct ureg_program *ureg)
195bf215546Sopenharmony_ci{
196bf215546Sopenharmony_ci    struct ureg_src y_sampler, u_sampler, v_sampler;
197bf215546Sopenharmony_ci    struct ureg_src pos;
198bf215546Sopenharmony_ci    struct ureg_src matrow0, matrow1, matrow2, matrow3;
199bf215546Sopenharmony_ci    struct ureg_dst y, u, v, rgb;
200bf215546Sopenharmony_ci    struct ureg_dst out = ureg_DECL_output(ureg,
201bf215546Sopenharmony_ci					   TGSI_SEMANTIC_COLOR,
202bf215546Sopenharmony_ci					   0);
203bf215546Sopenharmony_ci
204bf215546Sopenharmony_ci    pos = ureg_DECL_fs_input(ureg,
205bf215546Sopenharmony_ci			     TGSI_SEMANTIC_GENERIC, 0,
206bf215546Sopenharmony_ci			     TGSI_INTERPOLATE_PERSPECTIVE);
207bf215546Sopenharmony_ci
208bf215546Sopenharmony_ci    rgb = ureg_DECL_temporary(ureg);
209bf215546Sopenharmony_ci    y = ureg_DECL_temporary(ureg);
210bf215546Sopenharmony_ci    u = ureg_DECL_temporary(ureg);
211bf215546Sopenharmony_ci    v = ureg_DECL_temporary(ureg);
212bf215546Sopenharmony_ci
213bf215546Sopenharmony_ci    y_sampler = ureg_DECL_sampler(ureg, 0);
214bf215546Sopenharmony_ci    u_sampler = ureg_DECL_sampler(ureg, 1);
215bf215546Sopenharmony_ci    v_sampler = ureg_DECL_sampler(ureg, 2);
216bf215546Sopenharmony_ci
217bf215546Sopenharmony_ci    ureg_DECL_sampler_view(ureg, 0, TGSI_TEXTURE_2D,
218bf215546Sopenharmony_ci                           TGSI_RETURN_TYPE_FLOAT, TGSI_RETURN_TYPE_FLOAT,
219bf215546Sopenharmony_ci                           TGSI_RETURN_TYPE_FLOAT, TGSI_RETURN_TYPE_FLOAT);
220bf215546Sopenharmony_ci    ureg_DECL_sampler_view(ureg, 1, TGSI_TEXTURE_2D,
221bf215546Sopenharmony_ci                           TGSI_RETURN_TYPE_FLOAT, TGSI_RETURN_TYPE_FLOAT,
222bf215546Sopenharmony_ci                           TGSI_RETURN_TYPE_FLOAT, TGSI_RETURN_TYPE_FLOAT);
223bf215546Sopenharmony_ci    ureg_DECL_sampler_view(ureg, 2, TGSI_TEXTURE_2D,
224bf215546Sopenharmony_ci                           TGSI_RETURN_TYPE_FLOAT, TGSI_RETURN_TYPE_FLOAT,
225bf215546Sopenharmony_ci                           TGSI_RETURN_TYPE_FLOAT, TGSI_RETURN_TYPE_FLOAT);
226bf215546Sopenharmony_ci
227bf215546Sopenharmony_ci    matrow0 = ureg_DECL_constant(ureg, 0);
228bf215546Sopenharmony_ci    matrow1 = ureg_DECL_constant(ureg, 1);
229bf215546Sopenharmony_ci    matrow2 = ureg_DECL_constant(ureg, 2);
230bf215546Sopenharmony_ci    matrow3 = ureg_DECL_constant(ureg, 3);
231bf215546Sopenharmony_ci
232bf215546Sopenharmony_ci    ureg_TEX(ureg, y, TGSI_TEXTURE_2D, pos, y_sampler);
233bf215546Sopenharmony_ci    ureg_TEX(ureg, u, TGSI_TEXTURE_2D, pos, u_sampler);
234bf215546Sopenharmony_ci    ureg_TEX(ureg, v, TGSI_TEXTURE_2D, pos, v_sampler);
235bf215546Sopenharmony_ci
236bf215546Sopenharmony_ci    ureg_MOV(ureg, rgb, matrow3);
237bf215546Sopenharmony_ci    ureg_MAD(ureg, rgb,
238bf215546Sopenharmony_ci	     ureg_scalar(ureg_src(y), TGSI_SWIZZLE_X), matrow0, ureg_src(rgb));
239bf215546Sopenharmony_ci    ureg_MAD(ureg, rgb,
240bf215546Sopenharmony_ci	     ureg_scalar(ureg_src(u), TGSI_SWIZZLE_X), matrow1, ureg_src(rgb));
241bf215546Sopenharmony_ci    ureg_MAD(ureg, rgb,
242bf215546Sopenharmony_ci	     ureg_scalar(ureg_src(v), TGSI_SWIZZLE_X), matrow2, ureg_src(rgb));
243bf215546Sopenharmony_ci
244bf215546Sopenharmony_ci    ureg_MOV(ureg, out, ureg_src(rgb));
245bf215546Sopenharmony_ci
246bf215546Sopenharmony_ci    ureg_release_temporary(ureg, rgb);
247bf215546Sopenharmony_ci    ureg_release_temporary(ureg, y);
248bf215546Sopenharmony_ci    ureg_release_temporary(ureg, u);
249bf215546Sopenharmony_ci    ureg_release_temporary(ureg, v);
250bf215546Sopenharmony_ci
251bf215546Sopenharmony_ci    ureg_END(ureg);
252bf215546Sopenharmony_ci
253bf215546Sopenharmony_ci    return ureg_create_shader_and_destroy(ureg, pipe);
254bf215546Sopenharmony_ci}
255bf215546Sopenharmony_ci
256bf215546Sopenharmony_cistatic inline void
257bf215546Sopenharmony_cixrender_tex(struct ureg_program *ureg,
258bf215546Sopenharmony_ci	    struct ureg_dst dst,
259bf215546Sopenharmony_ci	    struct ureg_src coords,
260bf215546Sopenharmony_ci	    struct ureg_src sampler,
261bf215546Sopenharmony_ci	    const struct ureg_src *imm0,
262bf215546Sopenharmony_ci	    boolean repeat_none, boolean swizzle, boolean set_alpha)
263bf215546Sopenharmony_ci{
264bf215546Sopenharmony_ci    if (repeat_none) {
265bf215546Sopenharmony_ci	struct ureg_dst tmp0 = ureg_DECL_temporary(ureg);
266bf215546Sopenharmony_ci	struct ureg_dst tmp1 = ureg_DECL_temporary(ureg);
267bf215546Sopenharmony_ci
268bf215546Sopenharmony_ci	ureg_SGT(ureg, tmp1, ureg_swizzle(coords,
269bf215546Sopenharmony_ci					  TGSI_SWIZZLE_X,
270bf215546Sopenharmony_ci					  TGSI_SWIZZLE_Y,
271bf215546Sopenharmony_ci					  TGSI_SWIZZLE_X,
272bf215546Sopenharmony_ci					  TGSI_SWIZZLE_Y), ureg_scalar(*imm0,
273bf215546Sopenharmony_ci								       TGSI_SWIZZLE_X));
274bf215546Sopenharmony_ci	ureg_SLT(ureg, tmp0,
275bf215546Sopenharmony_ci		 ureg_swizzle(coords, TGSI_SWIZZLE_X, TGSI_SWIZZLE_Y,
276bf215546Sopenharmony_ci			      TGSI_SWIZZLE_X, TGSI_SWIZZLE_Y), ureg_scalar(*imm0,
277bf215546Sopenharmony_ci									   TGSI_SWIZZLE_W));
278bf215546Sopenharmony_ci	ureg_MIN(ureg, tmp0, ureg_src(tmp0), ureg_src(tmp1));
279bf215546Sopenharmony_ci	ureg_MIN(ureg, tmp0, ureg_scalar(ureg_src(tmp0), TGSI_SWIZZLE_X),
280bf215546Sopenharmony_ci		 ureg_scalar(ureg_src(tmp0), TGSI_SWIZZLE_Y));
281bf215546Sopenharmony_ci	ureg_TEX(ureg, tmp1, TGSI_TEXTURE_2D, coords, sampler);
282bf215546Sopenharmony_ci	if (swizzle)
283bf215546Sopenharmony_ci	    ureg_MOV(ureg, tmp1, ureg_swizzle(ureg_src(tmp1),
284bf215546Sopenharmony_ci					      TGSI_SWIZZLE_Z,
285bf215546Sopenharmony_ci					      TGSI_SWIZZLE_Y, TGSI_SWIZZLE_X,
286bf215546Sopenharmony_ci					      TGSI_SWIZZLE_W));
287bf215546Sopenharmony_ci	if (set_alpha)
288bf215546Sopenharmony_ci	    ureg_MOV(ureg,
289bf215546Sopenharmony_ci		     ureg_writemask(tmp1, TGSI_WRITEMASK_W),
290bf215546Sopenharmony_ci		     ureg_scalar(*imm0, TGSI_SWIZZLE_W));
291bf215546Sopenharmony_ci	ureg_MUL(ureg, dst, ureg_src(tmp1), ureg_src(tmp0));
292bf215546Sopenharmony_ci	ureg_release_temporary(ureg, tmp0);
293bf215546Sopenharmony_ci	ureg_release_temporary(ureg, tmp1);
294bf215546Sopenharmony_ci    } else {
295bf215546Sopenharmony_ci	if (swizzle) {
296bf215546Sopenharmony_ci	    struct ureg_dst tmp = ureg_DECL_temporary(ureg);
297bf215546Sopenharmony_ci
298bf215546Sopenharmony_ci	    ureg_TEX(ureg, tmp, TGSI_TEXTURE_2D, coords, sampler);
299bf215546Sopenharmony_ci	    ureg_MOV(ureg, dst, ureg_swizzle(ureg_src(tmp),
300bf215546Sopenharmony_ci					     TGSI_SWIZZLE_Z,
301bf215546Sopenharmony_ci					     TGSI_SWIZZLE_Y, TGSI_SWIZZLE_X,
302bf215546Sopenharmony_ci					     TGSI_SWIZZLE_W));
303bf215546Sopenharmony_ci	    ureg_release_temporary(ureg, tmp);
304bf215546Sopenharmony_ci	} else {
305bf215546Sopenharmony_ci	    ureg_TEX(ureg, dst, TGSI_TEXTURE_2D, coords, sampler);
306bf215546Sopenharmony_ci	}
307bf215546Sopenharmony_ci	if (set_alpha)
308bf215546Sopenharmony_ci	    ureg_MOV(ureg,
309bf215546Sopenharmony_ci		     ureg_writemask(dst, TGSI_WRITEMASK_W),
310bf215546Sopenharmony_ci		     ureg_scalar(*imm0, TGSI_SWIZZLE_W));
311bf215546Sopenharmony_ci    }
312bf215546Sopenharmony_ci}
313bf215546Sopenharmony_ci
314bf215546Sopenharmony_cistatic void
315bf215546Sopenharmony_ciread_input(struct ureg_program *ureg,
316bf215546Sopenharmony_ci           struct ureg_dst dst,
317bf215546Sopenharmony_ci           const struct ureg_src *imm0,
318bf215546Sopenharmony_ci           boolean repeat_none, boolean swizzle, boolean set_alpha,
319bf215546Sopenharmony_ci           boolean is_src, unsigned *cur_constant, unsigned *cur_sampler)
320bf215546Sopenharmony_ci{
321bf215546Sopenharmony_ci    struct ureg_src input, sampler;
322bf215546Sopenharmony_ci
323bf215546Sopenharmony_ci    if (is_src) {
324bf215546Sopenharmony_ci        input = ureg_DECL_constant(ureg, (*cur_constant)++);
325bf215546Sopenharmony_ci        ureg_MOV(ureg, dst, input);
326bf215546Sopenharmony_ci    } else {
327bf215546Sopenharmony_ci        sampler = ureg_DECL_sampler(ureg, *cur_sampler);
328bf215546Sopenharmony_ci        ureg_DECL_sampler_view(ureg, *cur_sampler, TGSI_TEXTURE_2D,
329bf215546Sopenharmony_ci                               TGSI_RETURN_TYPE_FLOAT, TGSI_RETURN_TYPE_FLOAT,
330bf215546Sopenharmony_ci                               TGSI_RETURN_TYPE_FLOAT, TGSI_RETURN_TYPE_FLOAT);
331bf215546Sopenharmony_ci        input = ureg_DECL_fs_input(ureg,
332bf215546Sopenharmony_ci                                   TGSI_SEMANTIC_GENERIC, (*cur_sampler)++,
333bf215546Sopenharmony_ci                                   TGSI_INTERPOLATE_PERSPECTIVE);
334bf215546Sopenharmony_ci        xrender_tex(ureg, dst, input, sampler, imm0,
335bf215546Sopenharmony_ci                    repeat_none, swizzle, set_alpha);
336bf215546Sopenharmony_ci    }
337bf215546Sopenharmony_ci}
338bf215546Sopenharmony_ci
339bf215546Sopenharmony_cistatic void *
340bf215546Sopenharmony_cicreate_fs(struct pipe_context *pipe, unsigned fs_traits)
341bf215546Sopenharmony_ci{
342bf215546Sopenharmony_ci    struct ureg_program *ureg;
343bf215546Sopenharmony_ci    struct ureg_dst src, mask;
344bf215546Sopenharmony_ci    struct ureg_dst out;
345bf215546Sopenharmony_ci    struct ureg_src imm0 = { 0 };
346bf215546Sopenharmony_ci    unsigned has_mask = (fs_traits & FS_MASK) != 0;
347bf215546Sopenharmony_ci    unsigned is_yuv = (fs_traits & FS_YUV) != 0;
348bf215546Sopenharmony_ci    unsigned src_repeat_none = (fs_traits & FS_SRC_REPEAT_NONE) != 0;
349bf215546Sopenharmony_ci    unsigned mask_repeat_none = (fs_traits & FS_MASK_REPEAT_NONE) != 0;
350bf215546Sopenharmony_ci    unsigned src_swizzle = (fs_traits & FS_SRC_SWIZZLE_RGB) != 0;
351bf215546Sopenharmony_ci    unsigned mask_swizzle = (fs_traits & FS_MASK_SWIZZLE_RGB) != 0;
352bf215546Sopenharmony_ci    unsigned src_set_alpha = (fs_traits & FS_SRC_SET_ALPHA) != 0;
353bf215546Sopenharmony_ci    unsigned mask_set_alpha = (fs_traits & FS_MASK_SET_ALPHA) != 0;
354bf215546Sopenharmony_ci    unsigned src_luminance = (fs_traits & FS_SRC_LUMINANCE) != 0;
355bf215546Sopenharmony_ci    unsigned mask_luminance = (fs_traits & FS_MASK_LUMINANCE) != 0;
356bf215546Sopenharmony_ci    unsigned dst_luminance = (fs_traits & FS_DST_LUMINANCE) != 0;
357bf215546Sopenharmony_ci    unsigned is_src_src = (fs_traits & FS_SRC_SRC) != 0;
358bf215546Sopenharmony_ci    unsigned is_mask_src = (fs_traits & FS_MASK_SRC) != 0;
359bf215546Sopenharmony_ci    boolean component_alpha = (fs_traits & FS_CA) != 0;
360bf215546Sopenharmony_ci    unsigned cur_sampler = 0;
361bf215546Sopenharmony_ci    unsigned cur_constant = 0;
362bf215546Sopenharmony_ci
363bf215546Sopenharmony_ci#if 0
364bf215546Sopenharmony_ci    print_fs_traits(fs_traits);
365bf215546Sopenharmony_ci#else
366bf215546Sopenharmony_ci    (void)print_fs_traits;
367bf215546Sopenharmony_ci#endif
368bf215546Sopenharmony_ci
369bf215546Sopenharmony_ci    ureg = ureg_create(PIPE_SHADER_FRAGMENT);
370bf215546Sopenharmony_ci    if (ureg == NULL)
371bf215546Sopenharmony_ci	return NULL;
372bf215546Sopenharmony_ci
373bf215546Sopenharmony_ci    if (is_yuv)
374bf215546Sopenharmony_ci       return create_yuv_shader(pipe, ureg);
375bf215546Sopenharmony_ci
376bf215546Sopenharmony_ci    out = ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 0);
377bf215546Sopenharmony_ci
378bf215546Sopenharmony_ci    if (src_repeat_none || mask_repeat_none ||
379bf215546Sopenharmony_ci	src_set_alpha || mask_set_alpha || src_luminance) {
380bf215546Sopenharmony_ci	imm0 = ureg_imm4f(ureg, 0, 0, 0, 1);
381bf215546Sopenharmony_ci    }
382bf215546Sopenharmony_ci
383bf215546Sopenharmony_ci    src = (has_mask || src_luminance || dst_luminance) ?
384bf215546Sopenharmony_ci        ureg_DECL_temporary(ureg) : out;
385bf215546Sopenharmony_ci
386bf215546Sopenharmony_ci    read_input(ureg, src, &imm0, src_repeat_none, src_swizzle,
387bf215546Sopenharmony_ci               src_set_alpha, is_src_src, &cur_constant, &cur_sampler);
388bf215546Sopenharmony_ci
389bf215546Sopenharmony_ci    if (src_luminance) {
390bf215546Sopenharmony_ci	ureg_MOV(ureg, src, ureg_scalar(ureg_src(src), TGSI_SWIZZLE_X));
391bf215546Sopenharmony_ci	ureg_MOV(ureg, ureg_writemask(src, TGSI_WRITEMASK_XYZ),
392bf215546Sopenharmony_ci		 ureg_scalar(imm0, TGSI_SWIZZLE_X));
393bf215546Sopenharmony_ci	if (!has_mask && !dst_luminance)
394bf215546Sopenharmony_ci	    ureg_MOV(ureg, out, ureg_src(src));
395bf215546Sopenharmony_ci    }
396bf215546Sopenharmony_ci
397bf215546Sopenharmony_ci    if (has_mask) {
398bf215546Sopenharmony_ci	mask = ureg_DECL_temporary(ureg);
399bf215546Sopenharmony_ci        read_input(ureg, mask, &imm0, mask_repeat_none,
400bf215546Sopenharmony_ci                   mask_swizzle, mask_set_alpha, is_mask_src, &cur_constant,
401bf215546Sopenharmony_ci                   &cur_sampler);
402bf215546Sopenharmony_ci
403bf215546Sopenharmony_ci	src_in_mask(ureg, (dst_luminance) ? src : out, ureg_src(src),
404bf215546Sopenharmony_ci		    ureg_src(mask), mask_luminance, component_alpha);
405bf215546Sopenharmony_ci
406bf215546Sopenharmony_ci	ureg_release_temporary(ureg, mask);
407bf215546Sopenharmony_ci    }
408bf215546Sopenharmony_ci
409bf215546Sopenharmony_ci    if (dst_luminance) {
410bf215546Sopenharmony_ci	/*
411bf215546Sopenharmony_ci	 * Make sure the alpha channel goes into the output L8 surface.
412bf215546Sopenharmony_ci	 */
413bf215546Sopenharmony_ci	ureg_MOV(ureg, out, ureg_scalar(ureg_src(src), TGSI_SWIZZLE_W));
414bf215546Sopenharmony_ci    }
415bf215546Sopenharmony_ci
416bf215546Sopenharmony_ci    ureg_END(ureg);
417bf215546Sopenharmony_ci
418bf215546Sopenharmony_ci    return ureg_create_shader_and_destroy(ureg, pipe);
419bf215546Sopenharmony_ci}
420bf215546Sopenharmony_ci
421bf215546Sopenharmony_cistruct xa_shaders *
422bf215546Sopenharmony_cixa_shaders_create(struct xa_context *r)
423bf215546Sopenharmony_ci{
424bf215546Sopenharmony_ci    struct xa_shaders *sc = CALLOC_STRUCT(xa_shaders);
425bf215546Sopenharmony_ci
426bf215546Sopenharmony_ci    sc->r = r;
427bf215546Sopenharmony_ci    cso_hash_init(&sc->vs_hash);
428bf215546Sopenharmony_ci    cso_hash_init(&sc->fs_hash);
429bf215546Sopenharmony_ci
430bf215546Sopenharmony_ci    return sc;
431bf215546Sopenharmony_ci}
432bf215546Sopenharmony_ci
433bf215546Sopenharmony_cistatic void
434bf215546Sopenharmony_cicache_destroy(struct pipe_context *pipe,
435bf215546Sopenharmony_ci	      struct cso_hash *hash, unsigned processor)
436bf215546Sopenharmony_ci{
437bf215546Sopenharmony_ci    struct cso_hash_iter iter = cso_hash_first_node(hash);
438bf215546Sopenharmony_ci
439bf215546Sopenharmony_ci    while (!cso_hash_iter_is_null(iter)) {
440bf215546Sopenharmony_ci	void *shader = (void *)cso_hash_iter_data(iter);
441bf215546Sopenharmony_ci
442bf215546Sopenharmony_ci	if (processor == PIPE_SHADER_FRAGMENT) {
443bf215546Sopenharmony_ci	    pipe->delete_fs_state(pipe, shader);
444bf215546Sopenharmony_ci	} else if (processor == PIPE_SHADER_VERTEX) {
445bf215546Sopenharmony_ci	    pipe->delete_vs_state(pipe, shader);
446bf215546Sopenharmony_ci	}
447bf215546Sopenharmony_ci	iter = cso_hash_erase(hash, iter);
448bf215546Sopenharmony_ci    }
449bf215546Sopenharmony_ci    cso_hash_deinit(hash);
450bf215546Sopenharmony_ci}
451bf215546Sopenharmony_ci
452bf215546Sopenharmony_civoid
453bf215546Sopenharmony_cixa_shaders_destroy(struct xa_shaders *sc)
454bf215546Sopenharmony_ci{
455bf215546Sopenharmony_ci    cache_destroy(sc->r->pipe, &sc->vs_hash, PIPE_SHADER_VERTEX);
456bf215546Sopenharmony_ci    cache_destroy(sc->r->pipe, &sc->fs_hash, PIPE_SHADER_FRAGMENT);
457bf215546Sopenharmony_ci
458bf215546Sopenharmony_ci    FREE(sc);
459bf215546Sopenharmony_ci}
460bf215546Sopenharmony_ci
461bf215546Sopenharmony_cistatic inline void *
462bf215546Sopenharmony_cishader_from_cache(struct pipe_context *pipe,
463bf215546Sopenharmony_ci		  unsigned type, struct cso_hash *hash, unsigned key)
464bf215546Sopenharmony_ci{
465bf215546Sopenharmony_ci    void *shader = NULL;
466bf215546Sopenharmony_ci
467bf215546Sopenharmony_ci    struct cso_hash_iter iter = cso_hash_find(hash, key);
468bf215546Sopenharmony_ci
469bf215546Sopenharmony_ci    if (cso_hash_iter_is_null(iter)) {
470bf215546Sopenharmony_ci	if (type == PIPE_SHADER_VERTEX)
471bf215546Sopenharmony_ci	    shader = create_vs(pipe, key);
472bf215546Sopenharmony_ci	else
473bf215546Sopenharmony_ci	    shader = create_fs(pipe, key);
474bf215546Sopenharmony_ci	cso_hash_insert(hash, key, shader);
475bf215546Sopenharmony_ci    } else
476bf215546Sopenharmony_ci	shader = (void *)cso_hash_iter_data(iter);
477bf215546Sopenharmony_ci
478bf215546Sopenharmony_ci    return shader;
479bf215546Sopenharmony_ci}
480bf215546Sopenharmony_ci
481bf215546Sopenharmony_cistruct xa_shader
482bf215546Sopenharmony_cixa_shaders_get(struct xa_shaders *sc, unsigned vs_traits, unsigned fs_traits)
483bf215546Sopenharmony_ci{
484bf215546Sopenharmony_ci    struct xa_shader shader = { NULL, NULL };
485bf215546Sopenharmony_ci    void *vs, *fs;
486bf215546Sopenharmony_ci
487bf215546Sopenharmony_ci    vs = shader_from_cache(sc->r->pipe, PIPE_SHADER_VERTEX,
488bf215546Sopenharmony_ci			   &sc->vs_hash, vs_traits);
489bf215546Sopenharmony_ci    fs = shader_from_cache(sc->r->pipe, PIPE_SHADER_FRAGMENT,
490bf215546Sopenharmony_ci			   &sc->fs_hash, fs_traits);
491bf215546Sopenharmony_ci
492bf215546Sopenharmony_ci    assert(vs && fs);
493bf215546Sopenharmony_ci    if (!vs || !fs)
494bf215546Sopenharmony_ci	return shader;
495bf215546Sopenharmony_ci
496bf215546Sopenharmony_ci    shader.vs = vs;
497bf215546Sopenharmony_ci    shader.fs = fs;
498bf215546Sopenharmony_ci
499bf215546Sopenharmony_ci    return shader;
500bf215546Sopenharmony_ci}
501