1bf215546Sopenharmony_ci/**************************************************************************
2bf215546Sopenharmony_ci *
3bf215546Sopenharmony_ci * Copyright 2008 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 "util/u_memory.h"
29bf215546Sopenharmony_ci#include "util/u_math.h"
30bf215546Sopenharmony_ci#include "util/format/u_format.h"
31bf215546Sopenharmony_ci#include "draw/draw_context.h"
32bf215546Sopenharmony_ci#include "draw/draw_private.h"
33bf215546Sopenharmony_ci#include "draw/draw_pt.h"
34bf215546Sopenharmony_ci#include "translate/translate.h"
35bf215546Sopenharmony_ci#include "translate/translate_cache.h"
36bf215546Sopenharmony_ci
37bf215546Sopenharmony_ci
38bf215546Sopenharmony_cistruct pt_fetch {
39bf215546Sopenharmony_ci   struct draw_context *draw;
40bf215546Sopenharmony_ci
41bf215546Sopenharmony_ci   struct translate *translate;
42bf215546Sopenharmony_ci
43bf215546Sopenharmony_ci   unsigned vertex_size;
44bf215546Sopenharmony_ci
45bf215546Sopenharmony_ci   struct translate_cache *cache;
46bf215546Sopenharmony_ci};
47bf215546Sopenharmony_ci
48bf215546Sopenharmony_ci
49bf215546Sopenharmony_ci/**
50bf215546Sopenharmony_ci * Perform the fetch from API vertex elements & vertex buffers, to a
51bf215546Sopenharmony_ci * contiguous set of float[4] attributes as required for the
52bf215546Sopenharmony_ci * vertex_shader->run_linear() method.
53bf215546Sopenharmony_ci */
54bf215546Sopenharmony_civoid
55bf215546Sopenharmony_cidraw_pt_fetch_prepare(struct pt_fetch *fetch,
56bf215546Sopenharmony_ci                      unsigned vs_input_count,
57bf215546Sopenharmony_ci                      unsigned vertex_size,
58bf215546Sopenharmony_ci                      unsigned instance_id_index)
59bf215546Sopenharmony_ci{
60bf215546Sopenharmony_ci   struct draw_context *draw = fetch->draw;
61bf215546Sopenharmony_ci   unsigned nr_inputs;
62bf215546Sopenharmony_ci   unsigned i, nr = 0, ei = 0;
63bf215546Sopenharmony_ci   unsigned dst_offset = 0;
64bf215546Sopenharmony_ci   unsigned num_extra_inputs = 0;
65bf215546Sopenharmony_ci   struct translate_key key;
66bf215546Sopenharmony_ci
67bf215546Sopenharmony_ci   fetch->vertex_size = vertex_size;
68bf215546Sopenharmony_ci
69bf215546Sopenharmony_ci   /* Leave the clipmask/edgeflags/pad/vertex_id,
70bf215546Sopenharmony_ci    * clip[] and whatever else in the header untouched.
71bf215546Sopenharmony_ci    */
72bf215546Sopenharmony_ci   dst_offset = offsetof(struct vertex_header, data);
73bf215546Sopenharmony_ci
74bf215546Sopenharmony_ci   if (instance_id_index != ~0) {
75bf215546Sopenharmony_ci      num_extra_inputs++;
76bf215546Sopenharmony_ci   }
77bf215546Sopenharmony_ci
78bf215546Sopenharmony_ci   assert(draw->pt.nr_vertex_elements + num_extra_inputs >= vs_input_count);
79bf215546Sopenharmony_ci
80bf215546Sopenharmony_ci   nr_inputs = MIN2(vs_input_count, draw->pt.nr_vertex_elements + num_extra_inputs);
81bf215546Sopenharmony_ci
82bf215546Sopenharmony_ci   for (i = 0; i < nr_inputs; i++) {
83bf215546Sopenharmony_ci      if (i == instance_id_index) {
84bf215546Sopenharmony_ci         key.element[nr].type = TRANSLATE_ELEMENT_INSTANCE_ID;
85bf215546Sopenharmony_ci         key.element[nr].input_format = PIPE_FORMAT_R32_USCALED;
86bf215546Sopenharmony_ci         key.element[nr].output_format = PIPE_FORMAT_R32_USCALED;
87bf215546Sopenharmony_ci         key.element[nr].output_offset = dst_offset;
88bf215546Sopenharmony_ci
89bf215546Sopenharmony_ci         dst_offset += sizeof(uint);
90bf215546Sopenharmony_ci      } else if (util_format_is_pure_sint(draw->pt.vertex_element[i].src_format)) {
91bf215546Sopenharmony_ci         key.element[nr].type = TRANSLATE_ELEMENT_NORMAL;
92bf215546Sopenharmony_ci         key.element[nr].input_format = draw->pt.vertex_element[ei].src_format;
93bf215546Sopenharmony_ci         key.element[nr].input_buffer = draw->pt.vertex_element[ei].vertex_buffer_index;
94bf215546Sopenharmony_ci         key.element[nr].input_offset = draw->pt.vertex_element[ei].src_offset;
95bf215546Sopenharmony_ci         key.element[nr].instance_divisor = draw->pt.vertex_element[ei].instance_divisor;
96bf215546Sopenharmony_ci         key.element[nr].output_format = PIPE_FORMAT_R32G32B32A32_SINT;
97bf215546Sopenharmony_ci         key.element[nr].output_offset = dst_offset;
98bf215546Sopenharmony_ci
99bf215546Sopenharmony_ci         ei++;
100bf215546Sopenharmony_ci         dst_offset += 4 * sizeof(int);
101bf215546Sopenharmony_ci      } else if (util_format_is_pure_uint(draw->pt.vertex_element[i].src_format)) {
102bf215546Sopenharmony_ci         key.element[nr].type = TRANSLATE_ELEMENT_NORMAL;
103bf215546Sopenharmony_ci         key.element[nr].input_format = draw->pt.vertex_element[ei].src_format;
104bf215546Sopenharmony_ci         key.element[nr].input_buffer = draw->pt.vertex_element[ei].vertex_buffer_index;
105bf215546Sopenharmony_ci         key.element[nr].input_offset = draw->pt.vertex_element[ei].src_offset;
106bf215546Sopenharmony_ci         key.element[nr].instance_divisor = draw->pt.vertex_element[ei].instance_divisor;
107bf215546Sopenharmony_ci         key.element[nr].output_format = PIPE_FORMAT_R32G32B32A32_UINT;
108bf215546Sopenharmony_ci         key.element[nr].output_offset = dst_offset;
109bf215546Sopenharmony_ci
110bf215546Sopenharmony_ci         ei++;
111bf215546Sopenharmony_ci         dst_offset += 4 * sizeof(unsigned);
112bf215546Sopenharmony_ci      } else {
113bf215546Sopenharmony_ci         key.element[nr].type = TRANSLATE_ELEMENT_NORMAL;
114bf215546Sopenharmony_ci         key.element[nr].input_format = draw->pt.vertex_element[ei].src_format;
115bf215546Sopenharmony_ci         key.element[nr].input_buffer = draw->pt.vertex_element[ei].vertex_buffer_index;
116bf215546Sopenharmony_ci         key.element[nr].input_offset = draw->pt.vertex_element[ei].src_offset;
117bf215546Sopenharmony_ci         key.element[nr].instance_divisor = draw->pt.vertex_element[ei].instance_divisor;
118bf215546Sopenharmony_ci         key.element[nr].output_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
119bf215546Sopenharmony_ci         key.element[nr].output_offset = dst_offset;
120bf215546Sopenharmony_ci
121bf215546Sopenharmony_ci         ei++;
122bf215546Sopenharmony_ci         dst_offset += 4 * sizeof(float);
123bf215546Sopenharmony_ci      }
124bf215546Sopenharmony_ci
125bf215546Sopenharmony_ci      nr++;
126bf215546Sopenharmony_ci   }
127bf215546Sopenharmony_ci
128bf215546Sopenharmony_ci   assert(dst_offset <= vertex_size);
129bf215546Sopenharmony_ci
130bf215546Sopenharmony_ci   key.nr_elements = nr;
131bf215546Sopenharmony_ci   key.output_stride = vertex_size;
132bf215546Sopenharmony_ci
133bf215546Sopenharmony_ci   if (!fetch->translate ||
134bf215546Sopenharmony_ci       translate_key_compare(&fetch->translate->key, &key) != 0)
135bf215546Sopenharmony_ci   {
136bf215546Sopenharmony_ci      translate_key_sanitize(&key);
137bf215546Sopenharmony_ci      fetch->translate = translate_cache_find(fetch->cache, &key);
138bf215546Sopenharmony_ci   }
139bf215546Sopenharmony_ci}
140bf215546Sopenharmony_ci
141bf215546Sopenharmony_ci
142bf215546Sopenharmony_civoid
143bf215546Sopenharmony_cidraw_pt_fetch_run(struct pt_fetch *fetch,
144bf215546Sopenharmony_ci                  const unsigned *elts,
145bf215546Sopenharmony_ci                  unsigned count,
146bf215546Sopenharmony_ci                  char *verts)
147bf215546Sopenharmony_ci{
148bf215546Sopenharmony_ci   struct draw_context *draw = fetch->draw;
149bf215546Sopenharmony_ci   struct translate *translate = fetch->translate;
150bf215546Sopenharmony_ci   unsigned i;
151bf215546Sopenharmony_ci
152bf215546Sopenharmony_ci   for (i = 0; i < draw->pt.nr_vertex_buffers; i++) {
153bf215546Sopenharmony_ci      translate->set_buffer(translate,
154bf215546Sopenharmony_ci			    i,
155bf215546Sopenharmony_ci			    ((char *)draw->pt.user.vbuffer[i].map +
156bf215546Sopenharmony_ci			     draw->pt.vertex_buffer[i].buffer_offset),
157bf215546Sopenharmony_ci			    draw->pt.vertex_buffer[i].stride,
158bf215546Sopenharmony_ci			    draw->pt.max_index);
159bf215546Sopenharmony_ci   }
160bf215546Sopenharmony_ci
161bf215546Sopenharmony_ci   translate->run_elts( translate,
162bf215546Sopenharmony_ci			elts,
163bf215546Sopenharmony_ci			count,
164bf215546Sopenharmony_ci                        draw->start_instance,
165bf215546Sopenharmony_ci                        draw->instance_id,
166bf215546Sopenharmony_ci			verts );
167bf215546Sopenharmony_ci}
168bf215546Sopenharmony_ci
169bf215546Sopenharmony_ci
170bf215546Sopenharmony_civoid
171bf215546Sopenharmony_cidraw_pt_fetch_run_linear(struct pt_fetch *fetch,
172bf215546Sopenharmony_ci                         unsigned start,
173bf215546Sopenharmony_ci                         unsigned count,
174bf215546Sopenharmony_ci                         char *verts)
175bf215546Sopenharmony_ci{
176bf215546Sopenharmony_ci   struct draw_context *draw = fetch->draw;
177bf215546Sopenharmony_ci   struct translate *translate = fetch->translate;
178bf215546Sopenharmony_ci   unsigned i;
179bf215546Sopenharmony_ci
180bf215546Sopenharmony_ci   for (i = 0; i < draw->pt.nr_vertex_buffers; i++) {
181bf215546Sopenharmony_ci      translate->set_buffer(translate,
182bf215546Sopenharmony_ci			    i,
183bf215546Sopenharmony_ci			    ((char *)draw->pt.user.vbuffer[i].map +
184bf215546Sopenharmony_ci			     draw->pt.vertex_buffer[i].buffer_offset),
185bf215546Sopenharmony_ci			    draw->pt.vertex_buffer[i].stride,
186bf215546Sopenharmony_ci			    draw->pt.max_index);
187bf215546Sopenharmony_ci   }
188bf215546Sopenharmony_ci
189bf215546Sopenharmony_ci   translate->run( translate,
190bf215546Sopenharmony_ci                   start,
191bf215546Sopenharmony_ci                   count,
192bf215546Sopenharmony_ci                   draw->start_instance,
193bf215546Sopenharmony_ci                   draw->instance_id,
194bf215546Sopenharmony_ci                   verts );
195bf215546Sopenharmony_ci}
196bf215546Sopenharmony_ci
197bf215546Sopenharmony_ci
198bf215546Sopenharmony_cistruct pt_fetch *
199bf215546Sopenharmony_cidraw_pt_fetch_create(struct draw_context *draw)
200bf215546Sopenharmony_ci{
201bf215546Sopenharmony_ci   struct pt_fetch *fetch = CALLOC_STRUCT(pt_fetch);
202bf215546Sopenharmony_ci   if (!fetch)
203bf215546Sopenharmony_ci      return NULL;
204bf215546Sopenharmony_ci
205bf215546Sopenharmony_ci   fetch->draw = draw;
206bf215546Sopenharmony_ci   fetch->cache = translate_cache_create();
207bf215546Sopenharmony_ci   if (!fetch->cache) {
208bf215546Sopenharmony_ci      FREE(fetch);
209bf215546Sopenharmony_ci      return NULL;
210bf215546Sopenharmony_ci   }
211bf215546Sopenharmony_ci
212bf215546Sopenharmony_ci   return fetch;
213bf215546Sopenharmony_ci}
214bf215546Sopenharmony_ci
215bf215546Sopenharmony_ci
216bf215546Sopenharmony_civoid
217bf215546Sopenharmony_cidraw_pt_fetch_destroy(struct pt_fetch *fetch)
218bf215546Sopenharmony_ci{
219bf215546Sopenharmony_ci   if (fetch->cache)
220bf215546Sopenharmony_ci      translate_cache_destroy(fetch->cache);
221bf215546Sopenharmony_ci
222bf215546Sopenharmony_ci   FREE(fetch);
223bf215546Sopenharmony_ci}
224