Path: blob/21.2-virgl/src/gallium/drivers/nouveau/nv30/nv30_draw.c
4574 views
/*1* Copyright 2012 Red Hat Inc.2*3* Permission is hereby granted, free of charge, to any person obtaining a4* copy of this software and associated documentation files (the "Software"),5* to deal in the Software without restriction, including without limitation6* the rights to use, copy, modify, merge, publish, distribute, sublicense,7* and/or sell copies of the Software, and to permit persons to whom the8* Software is furnished to do so, subject to the following conditions:9*10* The above copyright notice and this permission notice shall be included in11* all copies or substantial portions of the Software.12*13* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR14* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,15* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL16* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR17* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,18* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR19* OTHER DEALINGS IN THE SOFTWARE.20*21* Authors: Ben Skeggs22*23*/2425#include "draw/draw_context.h"26#include "draw/draw_vertex.h"27#include "draw/draw_pipe.h"28#include "draw/draw_vbuf.h"29#include "draw/draw_private.h"3031#include "nv_object.xml.h"32#include "nv30/nv30-40_3d.xml.h"33#include "nv30/nv30_context.h"34#include "nv30/nv30_format.h"3536struct nv30_render {37struct vbuf_render base;38struct nv30_context *nv30;3940struct pipe_transfer *transfer;41struct pipe_resource *buffer;42unsigned offset;43unsigned length;4445struct vertex_info vertex_info;4647struct nouveau_heap *vertprog;48uint32_t vtxprog[16][4];49uint32_t vtxfmt[16];50uint32_t vtxptr[16];51uint32_t prim;52};5354static inline struct nv30_render *55nv30_render(struct vbuf_render *render)56{57return (struct nv30_render *)render;58}5960static const struct vertex_info *61nv30_render_get_vertex_info(struct vbuf_render *render)62{63return &nv30_render(render)->vertex_info;64}6566static boolean67nv30_render_allocate_vertices(struct vbuf_render *render,68ushort vertex_size, ushort nr_vertices)69{70struct nv30_render *r = nv30_render(render);71struct nv30_context *nv30 = r->nv30;7273r->length = (uint32_t)vertex_size * (uint32_t)nr_vertices;7475if (r->offset + r->length >= render->max_vertex_buffer_bytes) {76pipe_resource_reference(&r->buffer, NULL);77r->buffer = pipe_buffer_create(&nv30->screen->base.base,78PIPE_BIND_VERTEX_BUFFER, PIPE_USAGE_STREAM,79render->max_vertex_buffer_bytes);80if (!r->buffer)81return false;8283r->offset = 0;84}8586return true;87}8889static void *90nv30_render_map_vertices(struct vbuf_render *render)91{92struct nv30_render *r = nv30_render(render);93char *map = pipe_buffer_map_range(94&r->nv30->base.pipe, r->buffer,95r->offset, r->length,96PIPE_MAP_WRITE |97PIPE_MAP_DISCARD_RANGE,98&r->transfer);99assert(map);100return map;101}102103static void104nv30_render_unmap_vertices(struct vbuf_render *render,105ushort min_index, ushort max_index)106{107struct nv30_render *r = nv30_render(render);108pipe_buffer_unmap(&r->nv30->base.pipe, r->transfer);109r->transfer = NULL;110}111112static void113nv30_render_set_primitive(struct vbuf_render *render, enum pipe_prim_type prim)114{115struct nv30_render *r = nv30_render(render);116117r->prim = nv30_prim_gl(prim);118}119120static void121nv30_render_draw_elements(struct vbuf_render *render,122const ushort *indices, uint count)123{124struct nv30_render *r = nv30_render(render);125struct nv30_context *nv30 = r->nv30;126struct nouveau_pushbuf *push = nv30->screen->base.pushbuf;127unsigned i;128129BEGIN_NV04(push, NV30_3D(VTXBUF(0)), r->vertex_info.num_attribs);130for (i = 0; i < r->vertex_info.num_attribs; i++) {131PUSH_RESRC(push, NV30_3D(VTXBUF(i)), BUFCTX_VTXTMP,132nv04_resource(r->buffer), r->offset + r->vtxptr[i],133NOUVEAU_BO_LOW | NOUVEAU_BO_RD, 0, NV30_3D_VTXBUF_DMA1);134}135136if (!nv30_state_validate(nv30, ~0, false))137return;138139BEGIN_NV04(push, NV30_3D(VERTEX_BEGIN_END), 1);140PUSH_DATA (push, r->prim);141142if (count & 1) {143BEGIN_NV04(push, NV30_3D(VB_ELEMENT_U32), 1);144PUSH_DATA (push, *indices++);145}146147count >>= 1;148while (count) {149unsigned npush = MIN2(count, NV04_PFIFO_MAX_PACKET_LEN);150count -= npush;151152BEGIN_NI04(push, NV30_3D(VB_ELEMENT_U16), npush);153while (npush--) {154PUSH_DATA(push, (indices[1] << 16) | indices[0]);155indices += 2;156}157}158159BEGIN_NV04(push, NV30_3D(VERTEX_BEGIN_END), 1);160PUSH_DATA (push, NV30_3D_VERTEX_BEGIN_END_STOP);161PUSH_RESET(push, BUFCTX_VTXTMP);162}163164static void165nv30_render_draw_arrays(struct vbuf_render *render, unsigned start, uint nr)166{167struct nv30_render *r = nv30_render(render);168struct nv30_context *nv30 = r->nv30;169struct nouveau_pushbuf *push = nv30->base.pushbuf;170unsigned fn = nr >> 8, pn = nr & 0xff;171unsigned ps = fn + (pn ? 1 : 0);172unsigned i;173174BEGIN_NV04(push, NV30_3D(VTXBUF(0)), r->vertex_info.num_attribs);175for (i = 0; i < r->vertex_info.num_attribs; i++) {176PUSH_RESRC(push, NV30_3D(VTXBUF(i)), BUFCTX_VTXTMP,177nv04_resource(r->buffer), r->offset + r->vtxptr[i],178NOUVEAU_BO_LOW | NOUVEAU_BO_RD, 0, NV30_3D_VTXBUF_DMA1);179}180181if (!nv30_state_validate(nv30, ~0, false))182return;183184BEGIN_NV04(push, NV30_3D(VERTEX_BEGIN_END), 1);185PUSH_DATA (push, r->prim);186187BEGIN_NI04(push, NV30_3D(VB_VERTEX_BATCH), ps);188while (fn--) {189PUSH_DATA (push, 0xff000000 | start);190start += 256;191}192193if (pn)194PUSH_DATA (push, ((pn - 1) << 24) | start);195196BEGIN_NV04(push, NV30_3D(VERTEX_BEGIN_END), 1);197PUSH_DATA (push, NV30_3D_VERTEX_BEGIN_END_STOP);198PUSH_RESET(push, BUFCTX_VTXTMP);199}200201static void202nv30_render_release_vertices(struct vbuf_render *render)203{204struct nv30_render *r = nv30_render(render);205r->offset += r->length;206}207208static const struct {209unsigned emit;210unsigned vp30;211unsigned vp40;212unsigned ow40;213} vroute [] = {214[TGSI_SEMANTIC_POSITION] = { EMIT_4F, 0, 0, 0x00000000 },215[TGSI_SEMANTIC_COLOR ] = { EMIT_4F, 3, 1, 0x00000001 },216[TGSI_SEMANTIC_BCOLOR ] = { EMIT_4F, 1, 3, 0x00000004 },217[TGSI_SEMANTIC_FOG ] = { EMIT_4F, 5, 5, 0x00000010 },218[TGSI_SEMANTIC_PSIZE ] = { EMIT_1F_PSIZE, 6, 6, 0x00000020 },219[TGSI_SEMANTIC_TEXCOORD] = { EMIT_4F, 8, 7, 0x00004000 },220};221222static bool223vroute_add(struct nv30_render *r, uint attrib, uint sem, uint *idx)224{225struct nv30_screen *screen = r->nv30->screen;226struct nv30_fragprog *fp = r->nv30->fragprog.program;227struct vertex_info *vinfo = &r->vertex_info;228enum pipe_format format;229uint emit = EMIT_OMIT;230uint result = *idx;231232if (sem == TGSI_SEMANTIC_GENERIC) {233uint num_texcoords = (screen->eng3d->oclass < NV40_3D_CLASS) ? 8 : 10;234for (result = 0; result < num_texcoords; result++) {235if (fp->texcoord[result] == *idx + 8) {236sem = TGSI_SEMANTIC_TEXCOORD;237emit = vroute[sem].emit;238break;239}240}241} else {242emit = vroute[sem].emit;243}244245if (emit == EMIT_OMIT)246return false;247248draw_emit_vertex_attr(vinfo, emit, attrib);249format = draw_translate_vinfo_format(emit);250251r->vtxfmt[attrib] = nv30_vtxfmt(&screen->base.base, format)->hw;252r->vtxptr[attrib] = vinfo->size;253vinfo->size += draw_translate_vinfo_size(emit);254255if (screen->eng3d->oclass < NV40_3D_CLASS) {256r->vtxprog[attrib][0] = 0x001f38d8;257r->vtxprog[attrib][1] = 0x0080001b | (attrib << 9);258r->vtxprog[attrib][2] = 0x0836106c;259r->vtxprog[attrib][3] = 0x2000f800 | (result + vroute[sem].vp30) << 2;260} else {261r->vtxprog[attrib][0] = 0x401f9c6c;262r->vtxprog[attrib][1] = 0x0040000d | (attrib << 8);263r->vtxprog[attrib][2] = 0x8106c083;264r->vtxprog[attrib][3] = 0x6041ff80 | (result + vroute[sem].vp40) << 2;265}266267if (result < 8)268*idx = vroute[sem].ow40 << result;269else {270assert(sem == TGSI_SEMANTIC_TEXCOORD);271*idx = 0x00001000 << (result - 8);272}273return true;274}275276static bool277nv30_render_validate(struct nv30_context *nv30)278{279struct nv30_render *r = nv30_render(nv30->draw->render);280struct nv30_rasterizer_stateobj *rast = nv30->rast;281struct pipe_screen *pscreen = &nv30->screen->base.base;282struct nouveau_pushbuf *push = nv30->screen->base.pushbuf;283struct nouveau_object *eng3d = nv30->screen->eng3d;284struct nv30_vertprog *vp = nv30->vertprog.program;285struct vertex_info *vinfo = &r->vertex_info;286unsigned vp_attribs = 0;287unsigned vp_results = 0;288unsigned attrib = 0;289unsigned pntc;290int i;291292if (!r->vertprog) {293struct nouveau_heap *heap = nv30_screen(pscreen)->vp_exec_heap;294if (nouveau_heap_alloc(heap, 16, &r->vertprog, &r->vertprog)) {295while (heap->next && heap->size < 16) {296struct nouveau_heap **evict = heap->next->priv;297nouveau_heap_free(evict);298}299300if (nouveau_heap_alloc(heap, 16, &r->vertprog, &r->vertprog))301return false;302}303}304305vinfo->num_attribs = 0;306vinfo->size = 0;307308/* setup routing for all necessary vp outputs */309for (i = 0; i < vp->info.num_outputs && attrib < 16; i++) {310uint semantic = vp->info.output_semantic_name[i];311uint index = vp->info.output_semantic_index[i];312if (vroute_add(r, attrib, semantic, &index)) {313vp_attribs |= (1 << attrib++);314vp_results |= index;315}316}317318/* setup routing for replaced point coords not written by vp */319if (rast && rast->pipe.point_quad_rasterization)320pntc = rast->pipe.sprite_coord_enable & 0x000002ff;321else322pntc = 0;323324while (pntc && attrib < 16) {325uint index = ffs(pntc) - 1; pntc &= ~(1 << index);326if (vroute_add(r, attrib, TGSI_SEMANTIC_TEXCOORD, &index)) {327vp_attribs |= (1 << attrib++);328vp_results |= index;329}330}331332/* modify vertex format for correct stride, and stub out unused ones */333BEGIN_NV04(push, NV30_3D(VP_UPLOAD_FROM_ID), 1);334PUSH_DATA (push, r->vertprog->start);335r->vtxprog[attrib - 1][3] |= 1;336for (i = 0; i < attrib; i++) {337BEGIN_NV04(push, NV30_3D(VP_UPLOAD_INST(0)), 4);338PUSH_DATAp(push, r->vtxprog[i], 4);339r->vtxfmt[i] |= vinfo->size << 8;340}341for (; i < 16; i++)342r->vtxfmt[i] = NV30_3D_VTXFMT_TYPE_V32_FLOAT;343344BEGIN_NV04(push, NV30_3D(VIEWPORT_TRANSLATE_X), 8);345PUSH_DATAf(push, 0.0);346PUSH_DATAf(push, 0.0);347PUSH_DATAf(push, 0.0);348PUSH_DATAf(push, 0.0);349PUSH_DATAf(push, 1.0);350PUSH_DATAf(push, 1.0);351PUSH_DATAf(push, 1.0);352PUSH_DATAf(push, 1.0);353BEGIN_NV04(push, NV30_3D(DEPTH_RANGE_NEAR), 2);354PUSH_DATAf(push, 0.0);355PUSH_DATAf(push, 1.0);356BEGIN_NV04(push, NV30_3D(VIEWPORT_HORIZ), 2);357PUSH_DATA (push, nv30->framebuffer.width << 16);358PUSH_DATA (push, nv30->framebuffer.height << 16);359360BEGIN_NV04(push, NV30_3D(VTXFMT(0)), 16);361PUSH_DATAp(push, r->vtxfmt, 16);362363BEGIN_NV04(push, NV30_3D(VP_START_FROM_ID), 1);364PUSH_DATA (push, r->vertprog->start);365BEGIN_NV04(push, NV30_3D(ENGINE), 1);366PUSH_DATA (push, 0x00000103);367if (eng3d->oclass >= NV40_3D_CLASS) {368BEGIN_NV04(push, NV40_3D(VP_ATTRIB_EN), 2);369PUSH_DATA (push, vp_attribs);370PUSH_DATA (push, vp_results);371}372373vinfo->size /= 4;374return true;375}376377void378nv30_render_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info,379unsigned drawid_offset,380const struct pipe_draw_start_count_bias *draw_one)381{382struct nv30_context *nv30 = nv30_context(pipe);383struct draw_context *draw = nv30->draw;384struct pipe_transfer *transfer[PIPE_MAX_ATTRIBS] = {NULL};385struct pipe_transfer *transferi = NULL;386int i;387388nv30_render_validate(nv30);389390if (nv30->draw_dirty & NV30_NEW_VIEWPORT)391draw_set_viewport_states(draw, 0, 1, &nv30->viewport);392if (nv30->draw_dirty & NV30_NEW_RASTERIZER)393draw_set_rasterizer_state(draw, &nv30->rast->pipe, NULL);394if (nv30->draw_dirty & NV30_NEW_CLIP)395draw_set_clip_state(draw, &nv30->clip);396if (nv30->draw_dirty & NV30_NEW_ARRAYS) {397draw_set_vertex_buffers(draw, 0, nv30->num_vtxbufs, 0, nv30->vtxbuf);398draw_set_vertex_elements(draw, nv30->vertex->num_elements, nv30->vertex->pipe);399}400if (nv30->draw_dirty & NV30_NEW_FRAGPROG) {401struct nv30_fragprog *fp = nv30->fragprog.program;402if (!fp->draw)403fp->draw = draw_create_fragment_shader(draw, &fp->pipe);404draw_bind_fragment_shader(draw, fp->draw);405}406if (nv30->draw_dirty & NV30_NEW_VERTPROG) {407struct nv30_vertprog *vp = nv30->vertprog.program;408if (!vp->draw)409vp->draw = draw_create_vertex_shader(draw, &vp->pipe);410draw_bind_vertex_shader(draw, vp->draw);411}412if (nv30->draw_dirty & NV30_NEW_VERTCONST) {413if (nv30->vertprog.constbuf) {414void *map = nv04_resource(nv30->vertprog.constbuf)->data;415draw_set_mapped_constant_buffer(draw, PIPE_SHADER_VERTEX, 0,416map, nv30->vertprog.constbuf_nr * 16);417} else {418draw_set_mapped_constant_buffer(draw, PIPE_SHADER_VERTEX, 0, NULL, 0);419}420}421422for (i = 0; i < nv30->num_vtxbufs; i++) {423const void *map = nv30->vtxbuf[i].is_user_buffer ?424nv30->vtxbuf[i].buffer.user : NULL;425if (!map) {426if (nv30->vtxbuf[i].buffer.resource)427map = pipe_buffer_map(pipe, nv30->vtxbuf[i].buffer.resource,428PIPE_MAP_UNSYNCHRONIZED |429PIPE_MAP_READ, &transfer[i]);430}431draw_set_mapped_vertex_buffer(draw, i, map, ~0);432}433434if (info->index_size) {435const void *map = info->has_user_indices ? info->index.user : NULL;436if (!map)437map = pipe_buffer_map(pipe, info->index.resource,438PIPE_MAP_UNSYNCHRONIZED |439PIPE_MAP_READ, &transferi);440draw_set_indexes(draw,441(ubyte *) map,442info->index_size, ~0);443} else {444draw_set_indexes(draw, NULL, 0, 0);445}446447draw_vbo(draw, info, drawid_offset, NULL, draw_one, 1);448draw_flush(draw);449450if (info->index_size && transferi)451pipe_buffer_unmap(pipe, transferi);452for (i = 0; i < nv30->num_vtxbufs; i++)453if (transfer[i])454pipe_buffer_unmap(pipe, transfer[i]);455456nv30->draw_dirty = 0;457nv30_state_release(nv30);458}459460static void461nv30_render_destroy(struct vbuf_render *render)462{463struct nv30_render *r = nv30_render(render);464465if (r->transfer)466pipe_buffer_unmap(&r->nv30->base.pipe, r->transfer);467pipe_resource_reference(&r->buffer, NULL);468nouveau_heap_free(&r->vertprog);469FREE(render);470}471472static struct vbuf_render *473nv30_render_create(struct nv30_context *nv30)474{475struct nv30_render *r = CALLOC_STRUCT(nv30_render);476if (!r)477return NULL;478479r->nv30 = nv30;480r->offset = 1 * 1024 * 1024;481482r->base.max_indices = 16 * 1024;483r->base.max_vertex_buffer_bytes = r->offset;484485r->base.get_vertex_info = nv30_render_get_vertex_info;486r->base.allocate_vertices = nv30_render_allocate_vertices;487r->base.map_vertices = nv30_render_map_vertices;488r->base.unmap_vertices = nv30_render_unmap_vertices;489r->base.set_primitive = nv30_render_set_primitive;490r->base.draw_elements = nv30_render_draw_elements;491r->base.draw_arrays = nv30_render_draw_arrays;492r->base.release_vertices = nv30_render_release_vertices;493r->base.destroy = nv30_render_destroy;494return &r->base;495}496497void498nv30_draw_init(struct pipe_context *pipe)499{500struct nv30_context *nv30 = nv30_context(pipe);501struct vbuf_render *render;502struct draw_context *draw;503struct draw_stage *stage;504505draw = draw_create(pipe);506if (!draw)507return;508509render = nv30_render_create(nv30);510if (!render) {511draw_destroy(draw);512return;513}514515stage = draw_vbuf_stage(draw, render);516if (!stage) {517render->destroy(render);518draw_destroy(draw);519return;520}521522draw_set_render(draw, render);523draw_set_rasterize_stage(draw, stage);524draw_wide_line_threshold(draw, 10000000.f);525draw_wide_point_threshold(draw, 10000000.f);526draw_wide_point_sprites(draw, true);527nv30->draw = draw;528}529530531