draw_pt_fetch_shade_pipeline.c revision 2ba6e1fa71be07a2d75abe2d085d485046c0932b
1/************************************************************************** 2 * 3 * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. 4 * All Rights Reserved. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the 8 * "Software"), to deal in the Software without restriction, including 9 * without limitation the rights to use, copy, modify, merge, publish, 10 * distribute, sub license, and/or sell copies of the Software, and to 11 * permit persons to whom the Software is furnished to do so, subject to 12 * the following conditions: 13 * 14 * The above copyright notice and this permission notice (including the 15 * next paragraph) shall be included in all copies or substantial portions 16 * of the Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR 22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 * 26 **************************************************************************/ 27 28#include "pipe/p_util.h" 29#include "draw/draw_context.h" 30#include "draw/draw_private.h" 31#include "draw/draw_vbuf.h" 32#include "draw/draw_vertex.h" 33#include "draw/draw_pt.h" 34 35struct fetch_pipeline_middle_end { 36 struct draw_pt_middle_end base; 37 struct draw_context *draw; 38 39 struct { 40 const ubyte *ptr; 41 unsigned pitch; 42 void (*fetch)( const void *from, float *attrib); 43 void (*emit)( const float *attrib, float **out ); 44 } fetch[PIPE_MAX_ATTRIBS]; 45 46 unsigned nr_fetch; 47 unsigned pipeline_vertex_size; 48 unsigned hw_vertex_size; 49 unsigned prim; 50}; 51 52#if 0 53static void emit_R32_FLOAT( const float *attrib, 54 float **out ) 55{ 56 (*out)[0] = attrib[0]; 57 (*out) += 1; 58} 59 60static void emit_R32G32_FLOAT( const float *attrib, 61 float **out ) 62{ 63 (*out)[0] = attrib[0]; 64 (*out)[1] = attrib[1]; 65 (*out) += 2; 66} 67 68static void emit_R32G32B32_FLOAT( const float *attrib, 69 float **out ) 70{ 71 (*out)[0] = attrib[0]; 72 (*out)[1] = attrib[1]; 73 (*out)[2] = attrib[2]; 74 (*out) += 3; 75} 76#endif 77static void emit_R32G32B32A32_FLOAT( const float *attrib, 78 float **out ) 79{ 80 (*out)[0] = attrib[0]; 81 (*out)[1] = attrib[1]; 82 (*out)[2] = attrib[2]; 83 (*out)[3] = attrib[3]; 84 (*out) += 4; 85} 86 87static void fetch_pipeline_prepare( struct draw_pt_middle_end *middle, 88 unsigned prim ) 89{ 90 struct fetch_pipeline_middle_end *fpme = (struct fetch_pipeline_middle_end *)middle; 91 struct draw_context *draw = fpme->draw; 92 unsigned i, nr = 0; 93 boolean ok; 94 const struct vertex_info *vinfo; 95 96 fpme->prim = prim; 97 98 ok = draw->render->set_primitive(draw->render, prim); 99 if (!ok) { 100 assert(0); 101 return; 102 } 103 /* Must do this after set_primitive() above: 104 */ 105 vinfo = draw->render->get_vertex_info(draw->render); 106 107 /* Need to look at vertex shader inputs (we know it is a 108 * passthrough shader, so these define the outputs too). If we 109 * were running a shader, we'd still be looking at the inputs at 110 * this point. 111 */ 112 for (i = 0; i < draw->vertex_shader->info.num_inputs; i++) { 113 unsigned buf = draw->vertex_element[i].vertex_buffer_index; 114 enum pipe_format format = draw->vertex_element[i].src_format; 115 116 fpme->fetch[nr].ptr = ((const ubyte *) draw->user.vbuffer[buf] + 117 draw->vertex_buffer[buf].buffer_offset + 118 draw->vertex_element[i].src_offset); 119 120 fpme->fetch[nr].pitch = draw->vertex_buffer[buf].pitch; 121 fpme->fetch[nr].fetch = draw_get_fetch_func( format ); 122 123 /* Always do this -- somewhat redundant... 124 */ 125 fpme->fetch[nr].emit = emit_R32G32B32A32_FLOAT; 126 nr++; 127 } 128 129 fpme->nr_fetch = nr; 130 //fpme->pipeline_vertex_size = sizeof(struct vertex_header) + nr * 4 * sizeof(float); 131 fpme->pipeline_vertex_size = (MAX_VERTEX_SIZE + 0x0f) & ~0x0f; 132 fpme->hw_vertex_size = vinfo->size * 4; 133} 134 135 136 137 138static void fetch_pipeline_run( struct draw_pt_middle_end *middle, 139 const unsigned *fetch_elts, 140 unsigned fetch_count, 141 const ushort *draw_elts, 142 unsigned draw_count ) 143{ 144 struct fetch_pipeline_middle_end *fpme = (struct fetch_pipeline_middle_end *)middle; 145 struct draw_context *draw = fpme->draw; 146 struct draw_vertex_shader *shader = draw->vertex_shader; 147 char *pipeline_verts; 148 149 pipeline_verts = MALLOC(fpme->pipeline_vertex_size * 150 fetch_count); 151 152 if (!pipeline_verts) { 153 assert(0); 154 return; 155 } 156 157 158 /* Shade 159 */ 160 shader->prepare(shader, draw); 161 if (shader->run(shader, draw, fetch_elts, fetch_count, pipeline_verts, 162 fpme->pipeline_vertex_size)) { 163 /* Run the pipeline */ 164 draw_pt_run_pipeline( fpme->draw, 165 fpme->prim, 166 pipeline_verts, 167 fpme->pipeline_vertex_size, 168 fetch_count, 169 draw_elts, 170 draw_count ); 171 } else { 172 unsigned i, j; 173 void *hw_verts; 174 float *out; 175 176 /* XXX: need to flush to get prim_vbuf.c to release its allocation?? 177 */ 178 draw_do_flush( draw, DRAW_FLUSH_BACKEND ); 179 180 hw_verts = draw->render->allocate_vertices(draw->render, 181 (ushort)fpme->hw_vertex_size, 182 (ushort)fetch_count); 183 if (!hw_verts) { 184 assert(0); 185 return; 186 } 187 188 out = (float *)hw_verts; 189 for (i = 0; i < fetch_count; i++) { 190 struct vertex_header *header = 191 (struct vertex_header*)(pipeline_verts + (fpme->pipeline_vertex_size * i)); 192 193 for (j = 0; j < fpme->nr_fetch; j++) { 194 float *attrib = header->data[j]; 195 /*debug_printf("emiting [%f, %f, %f, %f]\n", 196 attrib[0], attrib[1], 197 attrib[2], attrib[3]);*/ 198 fpme->fetch[j].emit(attrib, &out); 199 } 200 } 201 /* XXX: Draw arrays path to avoid re-emitting index list again and 202 * again. 203 */ 204 draw->render->draw(draw->render, 205 draw_elts, 206 draw_count); 207 208 draw->render->release_vertices(draw->render, 209 hw_verts, 210 fpme->hw_vertex_size, 211 fetch_count); 212 } 213 214 215 FREE(pipeline_verts); 216} 217 218 219 220static void fetch_pipeline_finish( struct draw_pt_middle_end *middle ) 221{ 222 /* nothing to do */ 223} 224 225static void fetch_pipeline_destroy( struct draw_pt_middle_end *middle ) 226{ 227 FREE(middle); 228} 229 230 231struct draw_pt_middle_end *draw_pt_fetch_pipeline_or_emit( struct draw_context *draw ) 232{ 233 struct fetch_pipeline_middle_end *fetch_pipeline = CALLOC_STRUCT( fetch_pipeline_middle_end ); 234 235 fetch_pipeline->base.prepare = fetch_pipeline_prepare; 236 fetch_pipeline->base.run = fetch_pipeline_run; 237 fetch_pipeline->base.finish = fetch_pipeline_finish; 238 fetch_pipeline->base.destroy = fetch_pipeline_destroy; 239 240 fetch_pipeline->draw = draw; 241 242 return &fetch_pipeline->base; 243} 244