1/************************************************************************** 2 * 3 * Copyright 2007 VMware, Inc. 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 VMWARE 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 "draw/draw_pipe.h" 29#include "util/u_math.h" 30#include "util/u_memory.h" 31#include "util/u_pack_color.h" 32 33#include "i915_batch.h" 34#include "i915_context.h" 35#include "i915_reg.h" 36#include "i915_state.h" 37 38/** 39 * Primitive emit to hardware. No support for vertex buffers or any 40 * nice fast paths. 41 */ 42struct setup_stage { 43 struct draw_stage stage; /**< This must be first (base class) */ 44 45 struct i915_context *i915; 46}; 47 48/** 49 * Basically a cast wrapper. 50 */ 51static inline struct setup_stage * 52setup_stage(struct draw_stage *stage) 53{ 54 return (struct setup_stage *)stage; 55} 56 57/** 58 * Extract the needed fields from vertex_header and emit i915 dwords. 59 * Recall that the vertices are constructed by the 'draw' module and 60 * have a couple of slots at the beginning (1-dword header, 4-dword 61 * clip pos) that we ignore here. 62 */ 63static inline void 64emit_hw_vertex(struct i915_context *i915, const struct vertex_header *vertex) 65{ 66 const struct vertex_info *vinfo = &i915->current.vertex_info; 67 uint32_t i; 68 uint32_t count = 0; /* for debug/sanity */ 69 70 assert(!i915->dirty); 71 72 for (i = 0; i < vinfo->num_attribs; i++) { 73 const uint32_t j = vinfo->attrib[i].src_index; 74 const float *attrib = vertex->data[j]; 75 switch (vinfo->attrib[i].emit) { 76 case EMIT_1F: 77 OUT_BATCH(fui(attrib[0])); 78 count++; 79 break; 80 case EMIT_2F: 81 OUT_BATCH(fui(attrib[0])); 82 OUT_BATCH(fui(attrib[1])); 83 count += 2; 84 break; 85 case EMIT_3F: 86 OUT_BATCH(fui(attrib[0])); 87 OUT_BATCH(fui(attrib[1])); 88 OUT_BATCH(fui(attrib[2])); 89 count += 3; 90 break; 91 case EMIT_4F: 92 OUT_BATCH(fui(attrib[0])); 93 OUT_BATCH(fui(attrib[1])); 94 OUT_BATCH(fui(attrib[2])); 95 OUT_BATCH(fui(attrib[3])); 96 count += 4; 97 break; 98 case EMIT_4UB: 99 OUT_BATCH( 100 pack_ub4(float_to_ubyte(attrib[0]), float_to_ubyte(attrib[1]), 101 float_to_ubyte(attrib[2]), float_to_ubyte(attrib[3]))); 102 count += 1; 103 break; 104 case EMIT_4UB_BGRA: 105 OUT_BATCH( 106 pack_ub4(float_to_ubyte(attrib[2]), float_to_ubyte(attrib[1]), 107 float_to_ubyte(attrib[0]), float_to_ubyte(attrib[3]))); 108 count += 1; 109 break; 110 default: 111 assert(0); 112 } 113 } 114 assert(count == vinfo->size); 115} 116 117static inline void 118emit_prim(struct draw_stage *stage, struct prim_header *prim, unsigned hwprim, 119 unsigned nr) 120{ 121 struct i915_context *i915 = setup_stage(stage)->i915; 122 unsigned vertex_size; 123 unsigned i; 124 125 if (i915->dirty) 126 i915_update_derived(i915); 127 128 if (i915->hardware_dirty) 129 i915_emit_hardware_state(i915); 130 131 /* need to do this after validation! */ 132 vertex_size = i915->current.vertex_info.size * 4; /* in bytes */ 133 assert(vertex_size >= 12); /* never smaller than 12 bytes */ 134 135 if (!BEGIN_BATCH(1 + nr * vertex_size / 4)) { 136 FLUSH_BATCH(NULL, I915_FLUSH_ASYNC); 137 138 /* Make sure state is re-emitted after a flush: 139 */ 140 i915_emit_hardware_state(i915); 141 142 if (!BEGIN_BATCH(1 + nr * vertex_size / 4)) { 143 assert(0); 144 return; 145 } 146 } 147 148 /* Emit each triangle as a single primitive. I told you this was 149 * simple. 150 */ 151 OUT_BATCH(_3DPRIMITIVE | hwprim | ((4 + vertex_size * nr) / 4 - 2)); 152 153 for (i = 0; i < nr; i++) 154 emit_hw_vertex(i915, prim->v[i]); 155} 156 157static void 158setup_tri(struct draw_stage *stage, struct prim_header *prim) 159{ 160 emit_prim(stage, prim, PRIM3D_TRILIST, 3); 161} 162 163static void 164setup_line(struct draw_stage *stage, struct prim_header *prim) 165{ 166 emit_prim(stage, prim, PRIM3D_LINELIST, 2); 167} 168 169static void 170setup_point(struct draw_stage *stage, struct prim_header *prim) 171{ 172 emit_prim(stage, prim, PRIM3D_POINTLIST, 1); 173} 174 175static void 176setup_flush(struct draw_stage *stage, unsigned flags) 177{ 178} 179 180static void 181reset_stipple_counter(struct draw_stage *stage) 182{ 183} 184 185static void 186render_destroy(struct draw_stage *stage) 187{ 188 FREE(stage); 189} 190 191/** 192 * Create a new primitive setup/render stage. This gets plugged into 193 * the 'draw' module's pipeline. 194 */ 195struct draw_stage * 196i915_draw_render_stage(struct i915_context *i915) 197{ 198 struct setup_stage *setup = CALLOC_STRUCT(setup_stage); 199 200 setup->i915 = i915; 201 setup->stage.draw = i915->draw; 202 setup->stage.point = setup_point; 203 setup->stage.line = setup_line; 204 setup->stage.tri = setup_tri; 205 setup->stage.flush = setup_flush; 206 setup->stage.reset_stipple_counter = reset_stipple_counter; 207 setup->stage.destroy = render_destroy; 208 209 return &setup->stage; 210} 211