Path: blob/21.2-virgl/src/gallium/auxiliary/draw/draw_pt_emit.c
4565 views
/**************************************************************************1*2* Copyright 2008 VMware, Inc.3* All Rights Reserved.4*5* Permission is hereby granted, free of charge, to any person obtaining a6* copy of this software and associated documentation files (the7* "Software"), to deal in the Software without restriction, including8* without limitation the rights to use, copy, modify, merge, publish,9* distribute, sub license, and/or sell copies of the Software, and to10* permit persons to whom the Software is furnished to do so, subject to11* the following conditions:12*13* The above copyright notice and this permission notice (including the14* next paragraph) shall be included in all copies or substantial portions15* of the Software.16*17* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS18* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF19* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.20* IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR21* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,22* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE23* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.24*25**************************************************************************/2627#include "util/u_memory.h"28#include "draw/draw_context.h"29#include "draw/draw_private.h"30#include "draw/draw_vbuf.h"31#include "draw/draw_vertex.h"32#include "draw/draw_pt.h"33#include "translate/translate.h"34#include "translate/translate_cache.h"35#include "util/u_prim.h"3637struct pt_emit {38struct draw_context *draw;3940struct translate *translate;4142struct translate_cache *cache;43unsigned prim;4445const struct vertex_info *vinfo;4647float zero4[4];4849};505152void53draw_pt_emit_prepare(struct pt_emit *emit,54unsigned prim,55unsigned *max_vertices)56{57struct draw_context *draw = emit->draw;58const struct vertex_info *vinfo;59unsigned dst_offset;60struct translate_key hw_key;61unsigned i;6263/* XXX: need to flush to get prim_vbuf.c to release its allocation??64*/65draw_do_flush(draw, DRAW_FLUSH_BACKEND);6667/* XXX: may need to defensively reset this later on as clipping can68* clobber this state in the render backend.69*/70emit->prim = prim;7172draw->render->set_primitive(draw->render, emit->prim);73if (draw->render->set_view_index)74draw->render->set_view_index(draw->render, draw->pt.user.viewid);7576/* Must do this after set_primitive() above:77*/78emit->vinfo = vinfo = draw->render->get_vertex_info(draw->render);7980/* Translate from pipeline vertices to hw vertices.81*/82dst_offset = 0;83for (i = 0; i < vinfo->num_attribs; i++) {84unsigned emit_sz = 0;85unsigned src_buffer = 0;86unsigned output_format;87unsigned src_offset = vinfo->attrib[i].src_index * 4 * sizeof(float);8889output_format = draw_translate_vinfo_format(vinfo->attrib[i].emit);90emit_sz = draw_translate_vinfo_size(vinfo->attrib[i].emit);9192/* doesn't handle EMIT_OMIT */93assert(emit_sz != 0);9495if (vinfo->attrib[i].emit == EMIT_1F_PSIZE) {96src_buffer = 1;97src_offset = 0;98}99else if (vinfo->attrib[i].src_index == DRAW_ATTR_NONEXIST) {100/* elements which don't exist will get assigned zeros */101src_buffer = 2;102src_offset = 0;103}104105hw_key.element[i].type = TRANSLATE_ELEMENT_NORMAL;106hw_key.element[i].input_format = PIPE_FORMAT_R32G32B32A32_FLOAT;107hw_key.element[i].input_buffer = src_buffer;108hw_key.element[i].input_offset = src_offset;109hw_key.element[i].instance_divisor = 0;110hw_key.element[i].output_format = output_format;111hw_key.element[i].output_offset = dst_offset;112113dst_offset += emit_sz;114}115116hw_key.nr_elements = vinfo->num_attribs;117hw_key.output_stride = vinfo->size * 4;118119if (!emit->translate ||120translate_key_compare(&emit->translate->key, &hw_key) != 0) {121translate_key_sanitize(&hw_key);122emit->translate = translate_cache_find(emit->cache, &hw_key);123124emit->translate->set_buffer(emit->translate, 2, &emit->zero4[0], 0, ~0);125}126127if (!vinfo->size)128*max_vertices = 0;129else130*max_vertices = (draw->render->max_vertex_buffer_bytes /131(vinfo->size * 4));132}133134135void136draw_pt_emit(struct pt_emit *emit,137const struct draw_vertex_info *vert_info,138const struct draw_prim_info *prim_info)139{140const float (*vertex_data)[4] = (const float (*)[4])vert_info->verts->data;141unsigned vertex_count = vert_info->count;142unsigned stride = vert_info->stride;143const ushort *elts = prim_info->elts;144struct draw_context *draw = emit->draw;145struct translate *translate = emit->translate;146struct vbuf_render *render = draw->render;147unsigned start, i;148void *hw_verts;149150/* XXX: need to flush to get prim_vbuf.c to release its allocation??151*/152draw_do_flush(draw, DRAW_FLUSH_BACKEND);153154if (vertex_count == 0)155return;156157/* XXX: and work out some way to coordinate the render primitive158* between vbuf.c and here...159*/160render->set_primitive(draw->render, prim_info->prim);161if (draw->render->set_view_index)162draw->render->set_view_index(draw->render, draw->pt.user.viewid);163164assert(vertex_count <= 65535);165render->allocate_vertices(render,166(ushort)translate->key.output_stride,167(ushort)vertex_count);168169hw_verts = render->map_vertices(render);170if (!hw_verts) {171debug_warn_once("map of vertex buffer failed (out of memory?)");172return;173}174175translate->set_buffer(translate,1760,177vertex_data,178stride,179~0);180181translate->set_buffer(translate,1821,183&draw->rasterizer->point_size,1840,185~0);186187/* fetch/translate vertex attribs to fill hw_verts[] */188translate->run(translate,1890,190vertex_count,1910,1920,193hw_verts);194195render->unmap_vertices(render, 0, vertex_count - 1);196197for (start = i = 0;198i < prim_info->primitive_count;199start += prim_info->primitive_lengths[i], i++)200{201render->draw_elements(render,202elts + start,203prim_info->primitive_lengths[i]);204}205206render->release_vertices(render);207}208209210void211draw_pt_emit_linear(struct pt_emit *emit,212const struct draw_vertex_info *vert_info,213const struct draw_prim_info *prim_info)214{215const float (*vertex_data)[4] = (const float (*)[4])vert_info->verts->data;216unsigned stride = vert_info->stride;217unsigned count = vert_info->count;218struct draw_context *draw = emit->draw;219struct translate *translate = emit->translate;220struct vbuf_render *render = draw->render;221void *hw_verts;222unsigned start, i;223224#if 0225debug_printf("Linear emit\n");226#endif227/* XXX: need to flush to get prim_vbuf.c to release its allocation??228*/229draw_do_flush(draw, DRAW_FLUSH_BACKEND);230231/* XXX: and work out some way to coordinate the render primitive232* between vbuf.c and here...233*/234render->set_primitive(draw->render, prim_info->prim);235if (draw->render->set_view_index)236draw->render->set_view_index(draw->render, draw->pt.user.viewid);237238assert(count <= 65535);239if (!render->allocate_vertices(render,240(ushort)translate->key.output_stride,241(ushort)count))242goto fail;243244hw_verts = render->map_vertices(render);245if (!hw_verts)246goto fail;247248translate->set_buffer(translate, 0,249vertex_data, stride, count - 1);250251translate->set_buffer(translate, 1,252&draw->rasterizer->point_size,2530, ~0);254255translate->run(translate,2560,257count,2580,2590,260hw_verts);261262if (0) {263unsigned i;264for (i = 0; i < count; i++) {265debug_printf("\n\n%s vertex %d:\n", __FUNCTION__, i);266draw_dump_emitted_vertex(emit->vinfo,267(const uint8_t *)hw_verts +268translate->key.output_stride * i);269}270}271272render->unmap_vertices(render, 0, count - 1);273274for (start = i = 0;275i < prim_info->primitive_count;276start += prim_info->primitive_lengths[i], i++)277{278render->draw_arrays(render,279start,280prim_info->primitive_lengths[i]);281}282283render->release_vertices(render);284285return;286287fail:288debug_warn_once("allocate or map of vertex buffer failed (out of memory?)");289return;290}291292293struct pt_emit *294draw_pt_emit_create(struct draw_context *draw)295{296struct pt_emit *emit = CALLOC_STRUCT(pt_emit);297if (!emit)298return NULL;299300emit->draw = draw;301emit->cache = translate_cache_create();302if (!emit->cache) {303FREE(emit);304return NULL;305}306307emit->zero4[0] = emit->zero4[1] = emit->zero4[2] = emit->zero4[3] = 0.0f;308309return emit;310}311312313void314draw_pt_emit_destroy(struct pt_emit *emit)315{316if (emit->cache)317translate_cache_destroy(emit->cache);318319FREE(emit);320}321322323