PageRenderTime 3ms CodeModel.GetById 4ms app.highlight 78ms RepoModel.GetById 1ms app.codeStats 0ms

/limare/lib/gp.c

https://gitlab.com/lima-ncc1988/lima-ncc1988
C | 859 lines | 645 code | 167 blank | 47 comment | 101 complexity | f0c7db34defb9a8c421d3cb362b74218 MD5 | raw file
  1/*
  2 * Copyright (c) 2011-2013 Luc Verhaegen <libv@skynet.be>
  3 *
  4 * Permission is hereby granted, free of charge, to any person obtaining a
  5 * copy of this software and associated documentation files (the "Software"),
  6 * to deal in the Software without restriction, including without limitation
  7 * the rights to use, copy, modify, merge, publish, distribute, sub license,
  8 * and/or sell copies of the Software, and to permit persons to whom the
  9 * Software is furnished to do so, subject to the following conditions:
 10 *
 11 * The above copyright notice and this permission notice (including the
 12 * next paragraph) shall be included in all copies or substantial portions
 13 * of the Software.
 14 *
 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 17 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 21 * DEALINGS IN THE SOFTWARE.
 22 */
 23
 24/*
 25 *
 26 * Code to help deal with setting up command streams for GP vs/plbu.
 27 *
 28 */
 29
 30#include <stdlib.h>
 31#include <stdio.h>
 32#include <string.h>
 33#include <errno.h>
 34#include <sys/ioctl.h>
 35
 36#include <GLES2/gl2.h>
 37
 38#include "ioctl_registers.h"
 39#include "limare.h"
 40#include "compiler.h"
 41#include "plb.h"
 42#include "symbols.h"
 43#include "gp.h"
 44#include "jobs.h"
 45#include "vs.h"
 46#include "plbu.h"
 47#include "render_state.h"
 48#include "hfloat.h"
 49#include "from_float.h"
 50#include "texture.h"
 51#include "program.h"
 52
 53int
 54vs_command_queue_create(struct limare_frame *frame, int size)
 55{
 56	size = ALIGN(size, 0x40);
 57
 58	if ((frame->mem_size - frame->mem_used) < size) {
 59		printf("%s: no space for vs queue\n", __func__);
 60		return -1;
 61	}
 62
 63	frame->vs_commands = frame->mem_address + frame->mem_used;
 64	frame->vs_commands_physical = frame->mem_physical + frame->mem_used;
 65	frame->vs_commands_count = 0;
 66	frame->vs_commands_size = size / 8;
 67
 68	frame->mem_used += size;
 69
 70	return 0;
 71}
 72
 73void
 74plbu_viewport_set(struct limare_frame *frame,
 75		  float x, float y, float w, float h)
 76{
 77	struct lima_cmd *cmds = frame->plbu_commands;
 78	int i = frame->plbu_commands_count;
 79
 80	cmds[i].val = from_float(x);
 81	cmds[i].cmd = LIMA_PLBU_CMD_VIEWPORT_X;
 82	i++;
 83
 84	cmds[i].val = from_float(x + w);
 85	cmds[i].cmd = LIMA_PLBU_CMD_VIEWPORT_W;
 86	i++;
 87
 88	cmds[i].val = from_float(y);
 89	cmds[i].cmd = LIMA_PLBU_CMD_VIEWPORT_Y;
 90	i++;
 91
 92	cmds[i].val = from_float(y + h);
 93	cmds[i].cmd = LIMA_PLBU_CMD_VIEWPORT_H;
 94	i++;
 95
 96	frame->plbu_commands_count = i;
 97}
 98
 99void
100plbu_scissor(struct limare_state *state, struct limare_frame *frame)
101{
102	struct lima_cmd *cmds = frame->plbu_commands;
103	int i = frame->plbu_commands_count;
104	int x, y, w, h;
105
106	if (state->scissor) {
107		x = state->scissor_x;
108		y = state->scissor_y;
109		w = state->scissor_w;
110		h = state->scissor_h;
111	} else {
112		x = state->viewport_x;
113		y = state->viewport_y;
114		w = state->viewport_w;
115		h = state->viewport_h;
116	}
117
118	cmds[i].val = (x << 30) | (y + h - 1) << 15 | y;
119	cmds[i].cmd = LIMA_PLBU_CMD_SCISSORS |
120		(x + w  -1) << 13 | (x >> 2);
121
122	frame->plbu_commands_count++;
123}
124
125int
126plbu_command_queue_create(struct limare_state *state,
127			  struct limare_frame *frame, int size, int heap_size)
128{
129	struct plb_info *plb = state->plb;
130	struct lima_cmd *cmds;
131	int i = 0;
132
133	size = ALIGN(size, 0x40);
134	heap_size = ALIGN(heap_size, 0x40);
135
136	if ((frame->mem_size - frame->mem_used) < (size + heap_size)) {
137		printf("%s: no space for plbu queue and tile heap\n", __func__);
138		return -1;
139	}
140
141	frame->tile_heap_offset = frame->mem_used;
142	frame->tile_heap_size = heap_size;
143	frame->mem_used += heap_size;
144
145	frame->plbu_commands = frame->mem_address + frame->mem_used;
146	frame->plbu_commands_physical = frame->mem_physical + frame->mem_used;
147	frame->plbu_commands_count = 0;
148	frame->plbu_commands_size = size / 8;
149	frame->mem_used += size;
150
151	cmds = frame->plbu_commands;
152
153	cmds[i].val = 0x0000200;
154	cmds[i].cmd = LIMA_PLBU_CMD_PRIMITIVE_SETUP;
155	i++;
156
157	cmds[i].val = plb->shift_w | (plb->shift_h << 16);
158	if (state->type == LIMARE_TYPE_M400)
159		cmds[i].val |= plb->shift_max << 28;
160	cmds[i].cmd = LIMA_PLBU_CMD_BLOCK_STEP;
161	i++;
162
163	cmds[i].val = ((plb->tiled_w - 1) << 24) | ((plb->tiled_h - 1) << 8);
164	cmds[i].cmd = LIMA_PLBU_CMD_TILED_DIMENSIONS;
165	i++;
166
167	cmds[i].val = plb->block_w;
168	cmds[i].cmd = LIMA_PLBU_CMD_PLBU_BLOCK_STRIDE;
169	i++;
170
171	cmds[i].val = frame->mem_physical + frame->plb_plbu_offset;
172	if (state->type == LIMARE_TYPE_M200)
173		cmds[i].cmd = LIMA_M200_PLBU_CMD_PLBU_ARRAY_ADDRESS;
174	else if (state->type == LIMARE_TYPE_M400) {
175		cmds[i].cmd = LIMA_M400_PLBU_CMD_PLBU_ARRAY_ADDRESS;
176		cmds[i].cmd |= plb->block_w * plb->block_h - 1;
177	}
178	i++;
179
180	frame->plbu_commands_count = i;
181
182	plbu_viewport_set(frame, 0.0, 0.0, state->width, state->height);
183
184	i = frame->plbu_commands_count;
185
186	cmds[i].val = frame->mem_physical + frame->tile_heap_offset;
187	cmds[i].cmd = LIMA_PLBU_CMD_TILE_HEAP_START;
188
189	i++;
190
191	cmds[i].val = frame->mem_physical + frame->tile_heap_offset +
192		frame->tile_heap_size;
193	cmds[i].cmd = LIMA_PLBU_CMD_TILE_HEAP_END;
194	i++;
195
196	frame->plbu_commands_count = i;
197
198	return 0;
199}
200
201int
202vs_info_setup(struct limare_state *state, struct limare_frame *frame,
203	      struct draw_info *draw)
204{
205	struct vs_info *info = draw->vs;
206	int i;
207
208	if (state->type == LIMARE_TYPE_M200) {
209		if ((frame->mem_size - frame->mem_used) <
210		    sizeof(struct gp_common)) {
211			printf("%s: no space for vs common\n", __func__);
212			return -1;
213		}
214
215		/* lima200 has a common area for attributes and varyings. */
216		info->common = frame->mem_address + frame->mem_used;
217		info->common_offset = frame->mem_used;
218		info->common_size = sizeof(struct gp_common);
219		frame->mem_used += ALIGN(info->common_size, 0x40);
220
221		/* initialize common */
222		for (i = 0; i < 0x10; i++) {
223			info->common->attributes[i].physical = 0;
224			info->common->attributes[i].size = 0x3F;
225		}
226		for (i = 0; i < 0x10; i++) {
227			info->common->varyings[i].physical = 0;
228			info->common->varyings[i].size = 0x3F;
229		}
230	} else if (state->type == LIMARE_TYPE_M400) {
231		if ((frame->mem_size - frame->mem_used) <
232		    (0x20 * sizeof(struct gp_common_entry))) {
233			printf("%s: no space for vs attribute/varying area\n",
234			       __func__);
235			return -1;
236		}
237
238		info->attribute_area = frame->mem_address + frame->mem_used;
239		info->attribute_area_size = 0x10 * sizeof(struct gp_common_entry);
240		info->attribute_area_offset = frame->mem_used;
241		frame->mem_used += ALIGN(info->attribute_area_size, 0x40);
242
243		info->varying_area = frame->mem_address + frame->mem_used;
244		info->varying_area_size = 0x10 * sizeof(struct gp_common_entry);
245		info->varying_area_offset = frame->mem_used;
246		frame->mem_used += ALIGN(info->varying_area_size, 0x40);
247	}
248
249	return 0;
250}
251
252int
253vs_info_attach_uniforms(struct limare_frame *frame, struct draw_info *draw,
254			struct symbol **uniforms, int count, int size)
255{
256	struct vs_info *info = draw->vs;
257	void *address;
258	int i;
259
260	if ((frame->mem_size - frame->mem_used) <
261	    ALIGN(4 * size, 0x40)) {
262		printf("%s: no space for uniforms\n", __func__);
263		return -1;
264	}
265
266	info->uniform_offset = frame->mem_used;
267	info->uniform_size = size;
268	frame->mem_used += ALIGN(4 * size, 0x40);
269
270	address = frame->mem_address + info->uniform_offset;
271
272	for (i = 0; i < count; i++) {
273		struct symbol *symbol = uniforms[i];
274
275		if (symbol->src_stride == symbol->dst_stride)
276			memcpy(address + symbol->component_size * symbol->offset,
277			       symbol->data, symbol->size);
278		else {
279			void *symbol_address = address +
280				symbol->component_size * symbol->offset;
281			int j;
282
283			for (j = 0; (j * symbol->src_stride) < symbol->size; j++)
284				memcpy(symbol_address + (j * symbol->dst_stride),
285				       symbol->data + (j * symbol->src_stride),
286				       symbol->src_stride);
287		}
288	}
289
290	return 0;
291}
292
293int
294vs_info_attach_attribute(struct limare_frame *frame, struct draw_info *draw,
295			 struct symbol *attribute)
296{
297	struct vs_info *info = draw->vs;
298
299	if (info->attribute_count == 0x10) {
300		printf("%s: No more attributes\n", __func__);
301		return -1;
302	}
303
304	info->attributes[attribute->offset / 4] = attribute;
305	info->attribute_count++;
306
307	return 0;
308}
309
310int
311vs_info_attach_varyings(struct limare_program *program,
312			struct limare_frame *frame, struct draw_info *draw)
313{
314	struct vs_info *info = draw->vs;
315
316	info->varying_size = ALIGN(program->varying_map_size *
317				   draw->attributes_vertex_count, 0x40);
318	if (info->varying_size > (frame->mem_size - frame->mem_used)) {
319		printf("%s: No more space\n", __func__);
320		return -2;
321	}
322
323	info->varying_offset = frame->mem_used;
324	frame->mem_used += info->varying_size;
325
326	info->gl_Position_size =
327		ALIGN(16 * draw->attributes_vertex_count, 0x40);
328	if (info->gl_Position_size > (frame->mem_size - frame->mem_used)) {
329		printf("%s: No more space\n", __func__);
330		return -2;
331	}
332
333	info->gl_Position_offset = frame->mem_used;
334	frame->mem_used += info->gl_Position_size;
335
336	return 0;
337}
338
339void
340vs_commands_draw_add(struct limare_state *state, struct limare_frame *frame,
341		     struct limare_program *program, struct draw_info *draw)
342{
343	struct vs_info *vs = draw->vs;
344	struct plbu_info *plbu = draw->plbu;
345	struct lima_cmd *cmds = frame->vs_commands;
346	int i = frame->vs_commands_count;
347
348	if (!plbu->indices_mem_physical) {
349		cmds[i].val = LIMA_VS_CMD_ARRAYS_SEMAPHORE_BEGIN_1;
350		cmds[i].cmd = LIMA_VS_CMD_ARRAYS_SEMAPHORE;
351		i++;
352
353		cmds[i].val = LIMA_VS_CMD_ARRAYS_SEMAPHORE_BEGIN_2;
354		cmds[i].cmd = LIMA_VS_CMD_ARRAYS_SEMAPHORE;
355		i++;
356	}
357
358	cmds[i].val = program->mem_physical + program->vertex_mem_offset;
359	cmds[i].cmd = LIMA_VS_CMD_SHADER_ADDRESS |
360		((program->vertex_shader_size / 16) << 16);
361	i++;
362
363	cmds[i].val = (program->vertex_attribute_prefetch - 1) << 20;
364	cmds[i].val |= ((ALIGN(program->vertex_shader_size, 16) / 16) - 1)
365		<< 10;
366	cmds[i].cmd = LIMA_VS_CMD_SHADER_INFO;
367	i++;
368
369	cmds[i].val = (program->varying_map_count << 8) |
370		((vs->attribute_count - 1) << 24);
371	cmds[i].cmd = LIMA_VS_CMD_VARYING_ATTRIBUTE_COUNT;
372	i++;
373
374	cmds[i].val = frame->mem_physical + vs->uniform_offset;
375	cmds[i].cmd = LIMA_VS_CMD_UNIFORMS_ADDRESS |
376		(ALIGN(vs->uniform_size, 4) << 14);
377	i++;
378
379	if (state->type == LIMARE_TYPE_M200) {
380		cmds[i].val = frame->mem_physical + vs->common_offset;
381		cmds[i].cmd = LIMA_VS_CMD_COMMON_ADDRESS |
382			(vs->common_size << 14);
383		i++;
384	} else if (state->type == LIMARE_TYPE_M400) {
385		cmds[i].val = frame->mem_physical + vs->attribute_area_offset;
386		cmds[i].cmd = LIMA_VS_CMD_ATTRIBUTES_ADDRESS |
387			(vs->attribute_count << 17);
388		i++;
389
390		cmds[i].val = frame->mem_physical + vs->varying_area_offset;
391		cmds[i].cmd = LIMA_VS_CMD_VARYINGS_ADDRESS |
392			((program->varying_map_count + 1) << 17);
393		i++;
394	}
395
396	cmds[i].val = 0x00000003; /* always 3 */
397	cmds[i].cmd = 0x10000041;
398	i++;
399
400	cmds[i].val = draw->attributes_vertex_count << 24;
401	if (plbu->indices_mem_physical)
402		cmds[i].val |= 0x01;
403	cmds[i].cmd = LIMA_VS_CMD_DRAW | draw->attributes_vertex_count >> 8;
404	i++;
405
406	cmds[i].val = 0x00000000;
407	cmds[i].cmd = 0x60000000;
408	i++;
409
410	if (plbu->indices_mem_physical)
411		cmds[i].val = LIMA_VS_CMD_ARRAYS_SEMAPHORE_NEXT;
412	else
413		cmds[i].val = LIMA_VS_CMD_ARRAYS_SEMAPHORE_END;
414	cmds[i].cmd = LIMA_VS_CMD_ARRAYS_SEMAPHORE;
415	i++;
416
417	/* update our size so we can set the gp job properly */
418	frame->vs_commands_count = i;
419}
420
421void
422vs_info_finalize(struct limare_state *state, struct limare_frame *frame,
423		 struct limare_program *program,
424		 struct draw_info *draw, struct vs_info *info)
425{
426	int i;
427
428	if (state->type == LIMARE_TYPE_M200) {
429		for (i = 0; i < info->attribute_count; i++) {
430			struct symbol *symbol = info->attributes[i];
431
432			info->common->attributes[i].physical =
433				symbol->mem_physical;
434			info->common->attributes[i].size =
435				(symbol->entry_stride << 11) |
436				(symbol->component_type << 2) |
437				(symbol->component_count - 1);
438		}
439
440		for (i = 0; i < program->varying_map_count; i++) {
441			info->common->varyings[i].physical =
442				frame->mem_physical +
443				info->varying_offset +
444				program->varying_map[i].offset;
445			info->common->varyings[i].size =
446				(program->varying_map_size << 11) |
447				(program->varying_map[i].entries - 1);
448
449			if (program->varying_map[i].entry_size == 2)
450				info->common->varyings[i].size |= 0x0C;
451		}
452
453		if (program->gl_Position) {
454			info->common->varyings[i].physical =
455				frame->mem_physical + info->gl_Position_offset;
456			info->common->varyings[i].size = 0x8020;
457		}
458
459	} else if (state->type == LIMARE_TYPE_M400) {
460		for (i = 0; i < info->attribute_count; i++) {
461			struct symbol *symbol = info->attributes[i];
462
463
464			info->attribute_area[i].physical =
465				symbol->mem_physical +
466				(symbol->entry_stride * draw->vertex_start);
467			info->attribute_area[i].size =
468				(symbol->entry_stride << 11) |
469				(symbol->component_type << 2) |
470				(symbol->component_count - 1);
471		}
472
473		for (i = 0; i < program->varying_map_count; i++) {
474			info->varying_area[i].physical =
475				frame->mem_physical +
476				info->varying_offset +
477				program->varying_map[i].offset;
478			info->varying_area[i].size =
479				(program->varying_map_size << 11) |
480				(program->varying_map[i].entries - 1);
481
482			if (program->varying_map[i].entry_size == 2)
483				info->varying_area[i].size |= 0x0C;
484		}
485
486		if (program->gl_Position) {
487			info->varying_area[i].physical =
488				frame->mem_physical + info->gl_Position_offset;
489			info->varying_area[i].size = 0x8020;
490		}
491	}
492}
493
494void
495plbu_commands_draw_add(struct limare_state *state, struct limare_frame *frame,
496		       struct draw_info *draw)
497{
498	struct plbu_info *plbu = draw->plbu;
499	struct vs_info *vs = draw->vs;
500	struct lima_cmd *cmds = frame->plbu_commands;
501	int i = frame->plbu_commands_count;
502
503	/*
504	 *
505	 */
506	if (!plbu->indices_mem_physical) {
507		cmds[i].val = LIMA_PLBU_CMD_ARRAYS_SEMAPHORE_BEGIN;
508		cmds[i].cmd = LIMA_PLBU_CMD_ARRAYS_SEMAPHORE;
509		i++;
510	}
511
512	cmds[i].val = LIMA_PLBU_CMD_PRIMITIVE_GLES2 | 0x0000200;
513	if (plbu->indices_mem_physical) {
514		if (plbu->indices_type == GL_UNSIGNED_SHORT)
515			cmds[i].val |= LIMA_PLBU_CMD_PRIMITIVE_INDEX_SHORT;
516		else
517			cmds[i].val |= LIMA_PLBU_CMD_PRIMITIVE_INDEX_BYTE;
518	}
519	if (state->culling) {
520		if (state->cull_front_cw) {
521			if (state->cull_front)
522				cmds[i].val |= LIMA_PLBU_CMD_PRIMITIVE_CULL_CW;
523			if (state->cull_back)
524				cmds[i].val |= LIMA_PLBU_CMD_PRIMITIVE_CULL_CCW;
525		} else {
526			if (state->cull_front)
527				cmds[i].val |= LIMA_PLBU_CMD_PRIMITIVE_CULL_CCW;
528			if (state->cull_back)
529				cmds[i].val |= LIMA_PLBU_CMD_PRIMITIVE_CULL_CW;
530		}
531	}
532
533	cmds[i].cmd = LIMA_PLBU_CMD_PRIMITIVE_SETUP;
534	i++;
535
536	cmds[i].val = frame->mem_physical + plbu->render_state_offset;
537	cmds[i].cmd = LIMA_PLBU_CMD_RSW_VERTEX_ARRAY;
538	cmds[i].cmd |= (frame->mem_physical + vs->gl_Position_offset) >> 4;
539	i++;
540
541	frame->plbu_commands_count = i;
542
543	/* original mali driver also flushes depth in this case. */
544	if (state->viewport_dirty && state->scissor_dirty)
545		state->depth_dirty = 1;
546
547	if (state->viewport_dirty) {
548		plbu_viewport_set(frame, state->viewport_x, state->viewport_y,
549				  state->viewport_w, state->viewport_h);
550		state->viewport_dirty = 0;
551	}
552
553	if (state->scissor_dirty) {
554		plbu_scissor(state, frame);
555		state->scissor_dirty = 0;
556	}
557
558	i = frame->plbu_commands_count;
559	if (state->depth_dirty) {
560		cmds[i].val = 0x00000000;
561		cmds[i].cmd = 0x1000010a;
562		i++;
563
564		cmds[i].val = from_float(state->depth_near);
565		cmds[i].cmd = LIMA_PLBU_CMD_DEPTH_RANGE_NEAR;
566		i++;
567
568		cmds[i].val = from_float(state->depth_far);
569		cmds[i].cmd = LIMA_PLBU_CMD_DEPTH_RANGE_FAR;
570		i++;
571
572		state->depth_dirty = 0;
573	}
574
575	if (plbu->indices_mem_physical) {
576		cmds[i].val = frame->mem_physical + vs->gl_Position_offset;
577		cmds[i].cmd = LIMA_PLBU_CMD_INDEXED_DEST;
578		i++;
579
580		cmds[i].val = plbu->indices_mem_physical;
581		cmds[i].cmd = LIMA_PLBU_CMD_INDICES;
582		i++;
583	} else {
584		cmds[i].val = (draw->vertex_count << 24) | draw->vertex_start;
585		cmds[i].cmd = LIMA_PLBU_CMD_DRAW | LIMA_PLBU_CMD_DRAW_ARRAYS |
586			((draw->draw_mode & 0x1F) << 16) |
587			(draw->vertex_count >> 8);
588		i++;
589	}
590
591	cmds[i].val = LIMA_PLBU_CMD_ARRAYS_SEMAPHORE_END;
592	cmds[i].cmd = LIMA_PLBU_CMD_ARRAYS_SEMAPHORE;
593	i++;
594
595	if (plbu->indices_mem_physical) {
596		cmds[i].val = (draw->vertex_count << 24) | draw->vertex_start;
597		cmds[i].cmd = LIMA_PLBU_CMD_DRAW | LIMA_PLBU_CMD_DRAW_ELEMENTS |
598			((draw->draw_mode & 0x1F) << 16) | (draw->vertex_count >> 8);
599		i++;
600	}
601
602	/* update our size so we can set the gp job properly */
603	frame->plbu_commands_count = i;
604}
605
606void
607plbu_commands_depth_buffer_clear_draw_add(struct limare_state *state,
608					  struct limare_frame *frame,
609					  struct draw_info *draw, unsigned int
610					  varying_vertices_physical)
611{
612	struct plbu_info *plbu = draw->plbu;
613	struct lima_cmd *cmds = frame->plbu_commands;
614	int i;
615
616	plbu_viewport_set(frame, 0.0, 0.0, 4096.0, 4096.0);
617	state->viewport_dirty = 1;
618
619	if (state->scissor_dirty) {
620		plbu_scissor(state, frame);
621		state->scissor_dirty = 0;
622	}
623
624	i = frame->plbu_commands_count;
625	cmds[i].val = frame->mem_physical + plbu->render_state_offset;
626	cmds[i].cmd = LIMA_PLBU_CMD_RSW_VERTEX_ARRAY;
627	cmds[i].cmd |= varying_vertices_physical >> 4;
628	i++;
629
630	cmds[i].val = 0x00000200;
631	cmds[i].cmd = LIMA_PLBU_CMD_PRIMITIVE_SETUP;
632	i++;
633
634	cmds[i].val = from_float(state->depth_near);
635	cmds[i].cmd = LIMA_PLBU_CMD_DEPTH_RANGE_NEAR;
636	i++;
637
638	cmds[i].val = from_float(state->depth_far);
639	cmds[i].cmd = LIMA_PLBU_CMD_DEPTH_RANGE_FAR;
640	i++;
641
642	cmds[i].val = 0x00000000;
643	cmds[i].cmd = 0x1000010a;
644	i++;
645
646	state->depth_dirty = 1;
647
648	cmds[i].val = plbu->indices_mem_physical;
649	cmds[i].cmd = LIMA_PLBU_CMD_INDICES;
650	i++;
651
652	cmds[i].val = varying_vertices_physical;
653	cmds[i].cmd = LIMA_PLBU_CMD_INDEXED_DEST;
654	i++;
655
656	cmds[i].val = (draw->vertex_count << 24) | draw->vertex_start;
657	cmds[i].cmd = LIMA_PLBU_CMD_DRAW | LIMA_PLBU_CMD_DRAW_ELEMENTS |
658		((draw->draw_mode & 0x1F) << 16) | (draw->vertex_count >> 8);
659	i++;
660
661	/* update our size so we can set the gp job properly */
662	frame->plbu_commands_count = i;
663}
664
665
666void
667plbu_commands_finish(struct limare_frame *frame)
668{
669	struct lima_cmd *cmds = frame->plbu_commands;
670	int i = frame->plbu_commands_count;
671
672#if 0
673	cmds[i].val = 0x00000000;
674	cmds[i].cmd = 0xd0000000;
675	i++;
676
677	cmds[i].val = 0x00000000;
678	cmds[i].cmd = 0xd0000000;
679	i++;
680#endif
681
682	cmds[i].val = 0;
683	cmds[i].cmd = LIMA_PLBU_CMD_END;
684	i++;
685
686	/* update our size so we can set the gp job properly */
687	frame->plbu_commands_count = i;
688}
689
690int
691plbu_info_attach_uniforms(struct limare_frame *frame, struct draw_info *draw,
692			  struct symbol **uniforms, int count, int size)
693{
694	struct plbu_info *info = draw->plbu;
695	void *address;
696	unsigned int *array;
697	int i;
698
699	if (!count)
700		return 0;
701
702	/* if we have only samplers, we can shortcut this. */
703	for (i = 0; i < count; i++) {
704		struct symbol *symbol = uniforms[i];
705
706		if (symbol->value_type != SYMBOL_SAMPLER)
707			break;
708	}
709
710	if (i == count)
711		return 0;
712
713	if ((frame->mem_size - frame->mem_used) < (0x40 + ALIGN(size, 0x40))) {
714		printf("%s: no space for plbu uniforms\n", __func__);
715		return -1;
716	}
717
718	info->uniform_array_offset = frame->mem_used;
719	info->uniform_array_size = 4;
720	frame->mem_used += 0x40;
721
722	array = frame->mem_address + info->uniform_array_offset;
723
724	info->uniform_offset = frame->mem_used;
725	info->uniform_size = size;
726	frame->mem_used += ALIGN(4 * size, 0x40);
727
728	address = frame->mem_address + info->uniform_offset;
729	array[0] = frame->mem_physical + info->uniform_offset;
730
731	for (i = 0; i < count; i++) {
732		struct symbol *symbol = uniforms[i];
733
734		/*
735		 * For samplers, there is place reserved, but the actual
736		 * uniform never is written, and the value is actually plainly
737		 * ignored.
738		 */
739		if (symbol->value_type == SYMBOL_SAMPLER)
740			continue;
741
742		memcpy(address +
743		       symbol->component_size * symbol->offset,
744		       symbol->data, symbol->size);
745	}
746
747	return 0;
748}
749
750void
751plbu_info_attach_indices(struct draw_info *draw, int indices_type,
752			 unsigned int mem_physical)
753{
754	struct plbu_info *plbu = draw->plbu;
755
756	plbu->indices_type = indices_type;
757
758	plbu->indices_mem_physical = mem_physical;
759}
760
761int
762plbu_info_attach_textures(struct limare_state *state,
763			  struct limare_frame *frame,
764			  struct draw_info *draw)
765{
766	struct limare_program *program = state->program_current;
767	unsigned int *list;
768	int i;
769
770	/* first a quick pass to see whether we need any textures */
771	for (i = 0; i < program->fragment_uniform_count; i++) {
772		struct symbol *symbol = program->fragment_uniforms[i];
773
774		if (symbol->value_type == SYMBOL_SAMPLER)
775			break;
776	}
777
778	if (i == program->fragment_uniform_count)
779		return 0;
780
781	/* create descriptor list */
782	draw->texture_descriptor_list_offset = frame->mem_used;
783	list = frame->mem_address + frame->mem_used;
784	frame->mem_used += 0x40;
785
786	for (i = 0; i < program->fragment_uniform_count; i++) {
787		struct symbol *symbol = program->fragment_uniforms[i];
788		struct limare_texture *texture;
789		int handle, j;
790
791		if (symbol->value_type != SYMBOL_SAMPLER)
792			continue;
793
794		handle = symbol->data_handle;
795
796		/* first, check sanity of the offset */
797		if (symbol->offset >= LIMARE_DRAW_TEXTURE_COUNT) {
798			printf("%s: Error: sampler %s has wrong offset %d.\n",
799			       __func__, symbol->name, symbol->offset);
800			return -1;
801		}
802
803		/* find the matching texture */
804		for (j = 0; j < LIMARE_TEXTURE_COUNT; j++) {
805			if (!state->textures[j])
806				continue;
807
808			texture = state->textures[j];
809
810			if (handle == texture->handle)
811				break;
812		}
813
814		if (j == LIMARE_TEXTURE_COUNT) {
815			printf("%s: Error: symbol %s texture handle not "
816			       "found\n", __func__, symbol->name);
817			return -1;
818		}
819
820		draw->texture_handles[symbol->offset] = handle;
821		list[symbol->offset] = texture->descriptor_physical;
822
823		if ((symbol->offset + 1) > draw->texture_descriptor_count)
824			draw->texture_descriptor_count = symbol->offset + 1;
825	}
826
827	return 0;
828}
829
830struct draw_info *
831draw_create_new(struct limare_state *state, struct limare_frame *frame,
832		int draw_mode, int attributes_vertex_count, int vertex_start,
833		int vertex_count)
834{
835	struct draw_info *draw = calloc(1, sizeof(struct draw_info));
836
837	if (!draw)
838		return NULL;
839
840	draw->draw_mode = draw_mode;
841
842	draw->attributes_vertex_count = attributes_vertex_count;
843
844	draw->vertex_start = vertex_start;
845	draw->vertex_count = vertex_count;
846
847	if (vs_info_setup(state, frame, draw)) {
848		free(draw);
849		return NULL;
850	}
851
852	return draw;
853}
854
855void
856draw_info_destroy(struct draw_info *draw)
857{
858	free(draw);
859}