st/mesa: Add a NIR version of the OES_draw_texture built-in shaders.
[mesa.git] / src / mesa / state_tracker / st_cb_drawtex.c
1 /**************************************************************************
2 *
3 * Copyright 2008 VMware, Inc.
4 * All Rights Reserved.
5 *
6 **************************************************************************/
7
8
9 /**
10 * Implementation of glDrawTex() for GL_OES_draw_tex
11 */
12
13
14
15 #include "main/imports.h"
16 #include "main/image.h"
17 #include "main/macros.h"
18 #include "main/teximage.h"
19 #include "main/framebuffer.h"
20 #include "program/program.h"
21 #include "program/prog_print.h"
22
23 #include "st_context.h"
24 #include "st_atom.h"
25 #include "st_cb_bitmap.h"
26 #include "st_cb_drawtex.h"
27 #include "st_nir.h"
28
29 #include "pipe/p_context.h"
30 #include "pipe/p_defines.h"
31 #include "util/u_inlines.h"
32 #include "pipe/p_shader_tokens.h"
33 #include "util/u_draw_quad.h"
34 #include "util/u_simple_shaders.h"
35 #include "util/u_upload_mgr.h"
36
37 #include "cso_cache/cso_context.h"
38
39
40 struct cached_shader
41 {
42 void *handle;
43
44 uint num_attribs;
45 uint semantic_names[2 + MAX_TEXTURE_UNITS];
46 uint semantic_indexes[2 + MAX_TEXTURE_UNITS];
47 };
48
49 #define MAX_SHADERS (2 * MAX_TEXTURE_UNITS)
50
51 /**
52 * Simple linear list cache.
53 * Most of the time there'll only be one cached shader.
54 * XXX This should be per-st_context state.
55 */
56 static struct cached_shader CachedShaders[MAX_SHADERS];
57 static GLuint NumCachedShaders = 0;
58
59 static gl_vert_attrib
60 semantic_to_vert_attrib(unsigned semantic)
61 {
62 switch (semantic) {
63 case TGSI_SEMANTIC_POSITION:
64 return VERT_ATTRIB_POS;
65 case TGSI_SEMANTIC_COLOR:
66 return VERT_ATTRIB_COLOR0;
67 case TGSI_SEMANTIC_GENERIC:
68 case TGSI_SEMANTIC_TEXCOORD:
69 return VERT_ATTRIB_GENERIC0;
70 default:
71 unreachable("unhandled semantic");
72 }
73 }
74
75 static gl_varying_slot
76 semantic_to_varying_slot(unsigned semantic)
77 {
78 switch (semantic) {
79 case TGSI_SEMANTIC_POSITION:
80 return VARYING_SLOT_POS;
81 case TGSI_SEMANTIC_COLOR:
82 return VARYING_SLOT_COL0;
83 case TGSI_SEMANTIC_GENERIC:
84 case TGSI_SEMANTIC_TEXCOORD:
85 return VARYING_SLOT_TEX0;
86 default:
87 unreachable("unhandled semantic");
88 }
89 }
90
91 static void *
92 lookup_shader(struct st_context *st,
93 uint num_attribs,
94 const uint *semantic_names,
95 const uint *semantic_indexes)
96 {
97 struct pipe_context *pipe = st->pipe;
98 struct pipe_screen *screen = pipe->screen;
99 GLuint i, j;
100
101 /* look for existing shader with same attributes */
102 for (i = 0; i < NumCachedShaders; i++) {
103 if (CachedShaders[i].num_attribs == num_attribs) {
104 GLboolean match = GL_TRUE;
105 for (j = 0; j < num_attribs; j++) {
106 if (semantic_names[j] != CachedShaders[i].semantic_names[j] ||
107 semantic_indexes[j] != CachedShaders[i].semantic_indexes[j]) {
108 match = GL_FALSE;
109 break;
110 }
111 }
112 if (match)
113 return CachedShaders[i].handle;
114 }
115 }
116
117 /* not found - create new one now */
118 if (NumCachedShaders >= MAX_SHADERS) {
119 return NULL;
120 }
121
122 CachedShaders[i].num_attribs = num_attribs;
123 for (j = 0; j < num_attribs; j++) {
124 CachedShaders[i].semantic_names[j] = semantic_names[j];
125 CachedShaders[i].semantic_indexes[j] = semantic_indexes[j];
126 }
127
128 enum pipe_shader_ir preferred_ir =
129 screen->get_shader_param(screen, MESA_SHADER_VERTEX,
130 PIPE_SHADER_CAP_PREFERRED_IR);
131
132 if (preferred_ir == PIPE_SHADER_IR_NIR) {
133 unsigned inputs[2 + MAX_TEXTURE_UNITS];
134 unsigned outputs[2 + MAX_TEXTURE_UNITS];
135
136 for (int j = 0; j < num_attribs; j++) {
137 inputs[j] = semantic_to_vert_attrib(semantic_names[j]);
138 outputs[j] = semantic_to_varying_slot(semantic_names[j]);
139 }
140
141 CachedShaders[i].handle =
142 st_nir_make_passthrough_shader(st, "st/drawtex VS",
143 MESA_SHADER_VERTEX,
144 num_attribs, inputs,
145 outputs, NULL, 0);
146 } else {
147 CachedShaders[i].handle =
148 util_make_vertex_passthrough_shader(pipe,
149 num_attribs,
150 semantic_names,
151 semantic_indexes, FALSE);
152 }
153
154 NumCachedShaders++;
155
156 return CachedShaders[i].handle;
157 }
158
159
160 static void
161 st_DrawTex(struct gl_context *ctx, GLfloat x, GLfloat y, GLfloat z,
162 GLfloat width, GLfloat height)
163 {
164 struct st_context *st = ctx->st;
165 struct pipe_context *pipe = st->pipe;
166 struct cso_context *cso = st->cso_context;
167 struct pipe_resource *vbuffer = NULL;
168 GLuint i, numTexCoords, numAttribs;
169 GLboolean emitColor;
170 uint semantic_names[2 + MAX_TEXTURE_UNITS];
171 uint semantic_indexes[2 + MAX_TEXTURE_UNITS];
172 struct pipe_vertex_element velements[2 + MAX_TEXTURE_UNITS];
173 unsigned offset;
174
175 st_flush_bitmap_cache(st);
176 st_invalidate_readpix_cache(st);
177
178 st_validate_state(st, ST_PIPELINE_META);
179
180 /* determine if we need vertex color */
181 if (ctx->FragmentProgram._Current->info.inputs_read & VARYING_BIT_COL0)
182 emitColor = GL_TRUE;
183 else
184 emitColor = GL_FALSE;
185
186 /* determine how many enabled sets of texcoords */
187 numTexCoords = 0;
188 for (i = 0; i < ctx->Const.MaxTextureUnits; i++) {
189 if (ctx->Texture.Unit[i]._Current &&
190 ctx->Texture.Unit[i]._Current->Target == GL_TEXTURE_2D) {
191 numTexCoords++;
192 }
193 }
194
195 /* total number of attributes per vertex */
196 numAttribs = 1 + emitColor + numTexCoords;
197
198 /* load vertex buffer */
199 {
200 #define SET_ATTRIB(VERT, ATTR, X, Y, Z, W) \
201 do { \
202 GLuint k = (((VERT) * numAttribs + (ATTR)) * 4); \
203 assert(k < 4 * 4 * numAttribs); \
204 vbuf[k + 0] = X; \
205 vbuf[k + 1] = Y; \
206 vbuf[k + 2] = Z; \
207 vbuf[k + 3] = W; \
208 } while (0)
209
210 const GLfloat x0 = x, y0 = y, x1 = x + width, y1 = y + height;
211 GLfloat *vbuf = NULL;
212 GLuint tex_attr;
213
214 u_upload_alloc(pipe->stream_uploader, 0,
215 numAttribs * 4 * 4 * sizeof(GLfloat), 4,
216 &offset, &vbuffer, (void **) &vbuf);
217 if (!vbuffer) {
218 return;
219 }
220
221 z = CLAMP(z, 0.0f, 1.0f);
222
223 /* positions (in clip coords) */
224 {
225 const struct gl_framebuffer *fb = ctx->DrawBuffer;
226 const GLfloat fb_width = (GLfloat)_mesa_geometric_width(fb);
227 const GLfloat fb_height = (GLfloat)_mesa_geometric_height(fb);
228
229 const GLfloat clip_x0 = (GLfloat)(x0 / fb_width * 2.0 - 1.0);
230 const GLfloat clip_y0 = (GLfloat)(y0 / fb_height * 2.0 - 1.0);
231 const GLfloat clip_x1 = (GLfloat)(x1 / fb_width * 2.0 - 1.0);
232 const GLfloat clip_y1 = (GLfloat)(y1 / fb_height * 2.0 - 1.0);
233
234 SET_ATTRIB(0, 0, clip_x0, clip_y0, z, 1.0f); /* lower left */
235 SET_ATTRIB(1, 0, clip_x1, clip_y0, z, 1.0f); /* lower right */
236 SET_ATTRIB(2, 0, clip_x1, clip_y1, z, 1.0f); /* upper right */
237 SET_ATTRIB(3, 0, clip_x0, clip_y1, z, 1.0f); /* upper left */
238
239 semantic_names[0] = TGSI_SEMANTIC_POSITION;
240 semantic_indexes[0] = 0;
241 }
242
243 /* colors */
244 if (emitColor) {
245 const GLfloat *c = ctx->Current.Attrib[VERT_ATTRIB_COLOR0];
246 SET_ATTRIB(0, 1, c[0], c[1], c[2], c[3]);
247 SET_ATTRIB(1, 1, c[0], c[1], c[2], c[3]);
248 SET_ATTRIB(2, 1, c[0], c[1], c[2], c[3]);
249 SET_ATTRIB(3, 1, c[0], c[1], c[2], c[3]);
250 semantic_names[1] = TGSI_SEMANTIC_COLOR;
251 semantic_indexes[1] = 0;
252 tex_attr = 2;
253 }
254 else {
255 tex_attr = 1;
256 }
257
258 /* texcoords */
259 for (i = 0; i < ctx->Const.MaxTextureUnits; i++) {
260 if (ctx->Texture.Unit[i]._Current &&
261 ctx->Texture.Unit[i]._Current->Target == GL_TEXTURE_2D) {
262 struct gl_texture_object *obj = ctx->Texture.Unit[i]._Current;
263 const struct gl_texture_image *img = _mesa_base_tex_image(obj);
264 const GLfloat wt = (GLfloat) img->Width;
265 const GLfloat ht = (GLfloat) img->Height;
266 const GLfloat s0 = obj->CropRect[0] / wt;
267 const GLfloat t0 = obj->CropRect[1] / ht;
268 const GLfloat s1 = (obj->CropRect[0] + obj->CropRect[2]) / wt;
269 const GLfloat t1 = (obj->CropRect[1] + obj->CropRect[3]) / ht;
270
271 /*printf("crop texcoords: %g, %g .. %g, %g\n", s0, t0, s1, t1);*/
272 SET_ATTRIB(0, tex_attr, s0, t0, 0.0f, 1.0f); /* lower left */
273 SET_ATTRIB(1, tex_attr, s1, t0, 0.0f, 1.0f); /* lower right */
274 SET_ATTRIB(2, tex_attr, s1, t1, 0.0f, 1.0f); /* upper right */
275 SET_ATTRIB(3, tex_attr, s0, t1, 0.0f, 1.0f); /* upper left */
276
277 semantic_names[tex_attr] = st->needs_texcoord_semantic ?
278 TGSI_SEMANTIC_TEXCOORD : TGSI_SEMANTIC_GENERIC;
279 /* XXX: should this use semantic index i instead of 0 ? */
280 semantic_indexes[tex_attr] = 0;
281
282 tex_attr++;
283 }
284 }
285
286 u_upload_unmap(pipe->stream_uploader);
287
288 #undef SET_ATTRIB
289 }
290
291 cso_save_state(cso, (CSO_BIT_VIEWPORT |
292 CSO_BIT_STREAM_OUTPUTS |
293 CSO_BIT_VERTEX_SHADER |
294 CSO_BIT_TESSCTRL_SHADER |
295 CSO_BIT_TESSEVAL_SHADER |
296 CSO_BIT_GEOMETRY_SHADER |
297 CSO_BIT_VERTEX_ELEMENTS |
298 CSO_BIT_AUX_VERTEX_BUFFER_SLOT));
299
300 {
301 void *vs = lookup_shader(st, numAttribs,
302 semantic_names, semantic_indexes);
303 cso_set_vertex_shader_handle(cso, vs);
304 }
305 cso_set_tessctrl_shader_handle(cso, NULL);
306 cso_set_tesseval_shader_handle(cso, NULL);
307 cso_set_geometry_shader_handle(cso, NULL);
308
309 for (i = 0; i < numAttribs; i++) {
310 velements[i].src_offset = i * 4 * sizeof(float);
311 velements[i].instance_divisor = 0;
312 velements[i].vertex_buffer_index = 0;
313 velements[i].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
314 }
315 cso_set_vertex_elements(cso, numAttribs, velements);
316 cso_set_stream_outputs(cso, 0, NULL, NULL);
317
318 /* viewport state: viewport matching window dims */
319 {
320 const struct gl_framebuffer *fb = ctx->DrawBuffer;
321 const GLboolean invert = (st_fb_orientation(fb) == Y_0_TOP);
322 const GLfloat width = (GLfloat)_mesa_geometric_width(fb);
323 const GLfloat height = (GLfloat)_mesa_geometric_height(fb);
324 struct pipe_viewport_state vp;
325 vp.scale[0] = 0.5f * width;
326 vp.scale[1] = height * (invert ? -0.5f : 0.5f);
327 vp.scale[2] = 1.0f;
328 vp.translate[0] = 0.5f * width;
329 vp.translate[1] = 0.5f * height;
330 vp.translate[2] = 0.0f;
331 cso_set_viewport(cso, &vp);
332 }
333
334 util_draw_vertex_buffer(pipe, cso, vbuffer, 0,
335 offset, /* offset */
336 PIPE_PRIM_TRIANGLE_FAN,
337 4, /* verts */
338 numAttribs); /* attribs/vert */
339
340 pipe_resource_reference(&vbuffer, NULL);
341
342 /* restore state */
343 cso_restore_state(cso);
344 }
345
346
347 void
348 st_init_drawtex_functions(struct dd_function_table *functions)
349 {
350 functions->DrawTex = st_DrawTex;
351 }
352
353
354 /**
355 * Free any cached shaders
356 */
357 void
358 st_destroy_drawtex(struct st_context *st)
359 {
360 GLuint i;
361 for (i = 0; i < NumCachedShaders; i++) {
362 cso_delete_vertex_shader(st->cso_context, CachedShaders[i].handle);
363 }
364 NumCachedShaders = 0;
365 }