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