1bf215546Sopenharmony_ci/**************************************************************************
2bf215546Sopenharmony_ci *
3bf215546Sopenharmony_ci * Copyright 2007 VMware, Inc.
4bf215546Sopenharmony_ci * All Rights Reserved.
5bf215546Sopenharmony_ci *
6bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
7bf215546Sopenharmony_ci * copy of this software and associated documentation files (the
8bf215546Sopenharmony_ci * "Software"), to deal in the Software without restriction, including
9bf215546Sopenharmony_ci * without limitation the rights to use, copy, modify, merge, publish,
10bf215546Sopenharmony_ci * distribute, sub license, and/or sell copies of the Software, and to
11bf215546Sopenharmony_ci * permit persons to whom the Software is furnished to do so, subject to
12bf215546Sopenharmony_ci * the following conditions:
13bf215546Sopenharmony_ci *
14bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the
15bf215546Sopenharmony_ci * next paragraph) shall be included in all copies or substantial portions
16bf215546Sopenharmony_ci * of the Software.
17bf215546Sopenharmony_ci *
18bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19bf215546Sopenharmony_ci * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20bf215546Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21bf215546Sopenharmony_ci * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
22bf215546Sopenharmony_ci * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23bf215546Sopenharmony_ci * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24bf215546Sopenharmony_ci * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25bf215546Sopenharmony_ci *
26bf215546Sopenharmony_ci **************************************************************************/
27bf215546Sopenharmony_ci
28bf215546Sopenharmony_ci#include "draw/draw_pipe.h"
29bf215546Sopenharmony_ci#include "util/u_math.h"
30bf215546Sopenharmony_ci#include "util/u_memory.h"
31bf215546Sopenharmony_ci#include "util/u_pack_color.h"
32bf215546Sopenharmony_ci
33bf215546Sopenharmony_ci#include "i915_batch.h"
34bf215546Sopenharmony_ci#include "i915_context.h"
35bf215546Sopenharmony_ci#include "i915_reg.h"
36bf215546Sopenharmony_ci#include "i915_state.h"
37bf215546Sopenharmony_ci
38bf215546Sopenharmony_ci/**
39bf215546Sopenharmony_ci * Primitive emit to hardware.  No support for vertex buffers or any
40bf215546Sopenharmony_ci * nice fast paths.
41bf215546Sopenharmony_ci */
42bf215546Sopenharmony_cistruct setup_stage {
43bf215546Sopenharmony_ci   struct draw_stage stage; /**< This must be first (base class) */
44bf215546Sopenharmony_ci
45bf215546Sopenharmony_ci   struct i915_context *i915;
46bf215546Sopenharmony_ci};
47bf215546Sopenharmony_ci
48bf215546Sopenharmony_ci/**
49bf215546Sopenharmony_ci * Basically a cast wrapper.
50bf215546Sopenharmony_ci */
51bf215546Sopenharmony_cistatic inline struct setup_stage *
52bf215546Sopenharmony_cisetup_stage(struct draw_stage *stage)
53bf215546Sopenharmony_ci{
54bf215546Sopenharmony_ci   return (struct setup_stage *)stage;
55bf215546Sopenharmony_ci}
56bf215546Sopenharmony_ci
57bf215546Sopenharmony_ci/**
58bf215546Sopenharmony_ci * Extract the needed fields from vertex_header and emit i915 dwords.
59bf215546Sopenharmony_ci * Recall that the vertices are constructed by the 'draw' module and
60bf215546Sopenharmony_ci * have a couple of slots at the beginning (1-dword header, 4-dword
61bf215546Sopenharmony_ci * clip pos) that we ignore here.
62bf215546Sopenharmony_ci */
63bf215546Sopenharmony_cistatic inline void
64bf215546Sopenharmony_ciemit_hw_vertex(struct i915_context *i915, const struct vertex_header *vertex)
65bf215546Sopenharmony_ci{
66bf215546Sopenharmony_ci   const struct vertex_info *vinfo = &i915->current.vertex_info;
67bf215546Sopenharmony_ci   uint32_t i;
68bf215546Sopenharmony_ci   uint32_t count = 0; /* for debug/sanity */
69bf215546Sopenharmony_ci
70bf215546Sopenharmony_ci   assert(!i915->dirty);
71bf215546Sopenharmony_ci
72bf215546Sopenharmony_ci   for (i = 0; i < vinfo->num_attribs; i++) {
73bf215546Sopenharmony_ci      const uint32_t j = vinfo->attrib[i].src_index;
74bf215546Sopenharmony_ci      const float *attrib = vertex->data[j];
75bf215546Sopenharmony_ci      switch (vinfo->attrib[i].emit) {
76bf215546Sopenharmony_ci      case EMIT_1F:
77bf215546Sopenharmony_ci         OUT_BATCH(fui(attrib[0]));
78bf215546Sopenharmony_ci         count++;
79bf215546Sopenharmony_ci         break;
80bf215546Sopenharmony_ci      case EMIT_2F:
81bf215546Sopenharmony_ci         OUT_BATCH(fui(attrib[0]));
82bf215546Sopenharmony_ci         OUT_BATCH(fui(attrib[1]));
83bf215546Sopenharmony_ci         count += 2;
84bf215546Sopenharmony_ci         break;
85bf215546Sopenharmony_ci      case EMIT_3F:
86bf215546Sopenharmony_ci         OUT_BATCH(fui(attrib[0]));
87bf215546Sopenharmony_ci         OUT_BATCH(fui(attrib[1]));
88bf215546Sopenharmony_ci         OUT_BATCH(fui(attrib[2]));
89bf215546Sopenharmony_ci         count += 3;
90bf215546Sopenharmony_ci         break;
91bf215546Sopenharmony_ci      case EMIT_4F:
92bf215546Sopenharmony_ci         OUT_BATCH(fui(attrib[0]));
93bf215546Sopenharmony_ci         OUT_BATCH(fui(attrib[1]));
94bf215546Sopenharmony_ci         OUT_BATCH(fui(attrib[2]));
95bf215546Sopenharmony_ci         OUT_BATCH(fui(attrib[3]));
96bf215546Sopenharmony_ci         count += 4;
97bf215546Sopenharmony_ci         break;
98bf215546Sopenharmony_ci      case EMIT_4UB:
99bf215546Sopenharmony_ci         OUT_BATCH(
100bf215546Sopenharmony_ci            pack_ub4(float_to_ubyte(attrib[0]), float_to_ubyte(attrib[1]),
101bf215546Sopenharmony_ci                     float_to_ubyte(attrib[2]), float_to_ubyte(attrib[3])));
102bf215546Sopenharmony_ci         count += 1;
103bf215546Sopenharmony_ci         break;
104bf215546Sopenharmony_ci      case EMIT_4UB_BGRA:
105bf215546Sopenharmony_ci         OUT_BATCH(
106bf215546Sopenharmony_ci            pack_ub4(float_to_ubyte(attrib[2]), float_to_ubyte(attrib[1]),
107bf215546Sopenharmony_ci                     float_to_ubyte(attrib[0]), float_to_ubyte(attrib[3])));
108bf215546Sopenharmony_ci         count += 1;
109bf215546Sopenharmony_ci         break;
110bf215546Sopenharmony_ci      default:
111bf215546Sopenharmony_ci         assert(0);
112bf215546Sopenharmony_ci      }
113bf215546Sopenharmony_ci   }
114bf215546Sopenharmony_ci   assert(count == vinfo->size);
115bf215546Sopenharmony_ci}
116bf215546Sopenharmony_ci
117bf215546Sopenharmony_cistatic inline void
118bf215546Sopenharmony_ciemit_prim(struct draw_stage *stage, struct prim_header *prim, unsigned hwprim,
119bf215546Sopenharmony_ci          unsigned nr)
120bf215546Sopenharmony_ci{
121bf215546Sopenharmony_ci   struct i915_context *i915 = setup_stage(stage)->i915;
122bf215546Sopenharmony_ci   unsigned vertex_size;
123bf215546Sopenharmony_ci   unsigned i;
124bf215546Sopenharmony_ci
125bf215546Sopenharmony_ci   if (i915->dirty)
126bf215546Sopenharmony_ci      i915_update_derived(i915);
127bf215546Sopenharmony_ci
128bf215546Sopenharmony_ci   if (i915->hardware_dirty)
129bf215546Sopenharmony_ci      i915_emit_hardware_state(i915);
130bf215546Sopenharmony_ci
131bf215546Sopenharmony_ci   /* need to do this after validation! */
132bf215546Sopenharmony_ci   vertex_size = i915->current.vertex_info.size * 4; /* in bytes */
133bf215546Sopenharmony_ci   assert(vertex_size >= 12); /* never smaller than 12 bytes */
134bf215546Sopenharmony_ci
135bf215546Sopenharmony_ci   if (!BEGIN_BATCH(1 + nr * vertex_size / 4)) {
136bf215546Sopenharmony_ci      FLUSH_BATCH(NULL, I915_FLUSH_ASYNC);
137bf215546Sopenharmony_ci
138bf215546Sopenharmony_ci      /* Make sure state is re-emitted after a flush:
139bf215546Sopenharmony_ci       */
140bf215546Sopenharmony_ci      i915_emit_hardware_state(i915);
141bf215546Sopenharmony_ci
142bf215546Sopenharmony_ci      if (!BEGIN_BATCH(1 + nr * vertex_size / 4)) {
143bf215546Sopenharmony_ci         assert(0);
144bf215546Sopenharmony_ci         return;
145bf215546Sopenharmony_ci      }
146bf215546Sopenharmony_ci   }
147bf215546Sopenharmony_ci
148bf215546Sopenharmony_ci   /* Emit each triangle as a single primitive.  I told you this was
149bf215546Sopenharmony_ci    * simple.
150bf215546Sopenharmony_ci    */
151bf215546Sopenharmony_ci   OUT_BATCH(_3DPRIMITIVE | hwprim | ((4 + vertex_size * nr) / 4 - 2));
152bf215546Sopenharmony_ci
153bf215546Sopenharmony_ci   for (i = 0; i < nr; i++)
154bf215546Sopenharmony_ci      emit_hw_vertex(i915, prim->v[i]);
155bf215546Sopenharmony_ci}
156bf215546Sopenharmony_ci
157bf215546Sopenharmony_cistatic void
158bf215546Sopenharmony_cisetup_tri(struct draw_stage *stage, struct prim_header *prim)
159bf215546Sopenharmony_ci{
160bf215546Sopenharmony_ci   emit_prim(stage, prim, PRIM3D_TRILIST, 3);
161bf215546Sopenharmony_ci}
162bf215546Sopenharmony_ci
163bf215546Sopenharmony_cistatic void
164bf215546Sopenharmony_cisetup_line(struct draw_stage *stage, struct prim_header *prim)
165bf215546Sopenharmony_ci{
166bf215546Sopenharmony_ci   emit_prim(stage, prim, PRIM3D_LINELIST, 2);
167bf215546Sopenharmony_ci}
168bf215546Sopenharmony_ci
169bf215546Sopenharmony_cistatic void
170bf215546Sopenharmony_cisetup_point(struct draw_stage *stage, struct prim_header *prim)
171bf215546Sopenharmony_ci{
172bf215546Sopenharmony_ci   emit_prim(stage, prim, PRIM3D_POINTLIST, 1);
173bf215546Sopenharmony_ci}
174bf215546Sopenharmony_ci
175bf215546Sopenharmony_cistatic void
176bf215546Sopenharmony_cisetup_flush(struct draw_stage *stage, unsigned flags)
177bf215546Sopenharmony_ci{
178bf215546Sopenharmony_ci}
179bf215546Sopenharmony_ci
180bf215546Sopenharmony_cistatic void
181bf215546Sopenharmony_cireset_stipple_counter(struct draw_stage *stage)
182bf215546Sopenharmony_ci{
183bf215546Sopenharmony_ci}
184bf215546Sopenharmony_ci
185bf215546Sopenharmony_cistatic void
186bf215546Sopenharmony_cirender_destroy(struct draw_stage *stage)
187bf215546Sopenharmony_ci{
188bf215546Sopenharmony_ci   FREE(stage);
189bf215546Sopenharmony_ci}
190bf215546Sopenharmony_ci
191bf215546Sopenharmony_ci/**
192bf215546Sopenharmony_ci * Create a new primitive setup/render stage.  This gets plugged into
193bf215546Sopenharmony_ci * the 'draw' module's pipeline.
194bf215546Sopenharmony_ci */
195bf215546Sopenharmony_cistruct draw_stage *
196bf215546Sopenharmony_cii915_draw_render_stage(struct i915_context *i915)
197bf215546Sopenharmony_ci{
198bf215546Sopenharmony_ci   struct setup_stage *setup = CALLOC_STRUCT(setup_stage);
199bf215546Sopenharmony_ci
200bf215546Sopenharmony_ci   setup->i915 = i915;
201bf215546Sopenharmony_ci   setup->stage.draw = i915->draw;
202bf215546Sopenharmony_ci   setup->stage.point = setup_point;
203bf215546Sopenharmony_ci   setup->stage.line = setup_line;
204bf215546Sopenharmony_ci   setup->stage.tri = setup_tri;
205bf215546Sopenharmony_ci   setup->stage.flush = setup_flush;
206bf215546Sopenharmony_ci   setup->stage.reset_stipple_counter = reset_stipple_counter;
207bf215546Sopenharmony_ci   setup->stage.destroy = render_destroy;
208bf215546Sopenharmony_ci
209bf215546Sopenharmony_ci   return &setup->stage;
210bf215546Sopenharmony_ci}
211